Ultrix-3.1/sys/sys/main.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
/*
* SCCSID: @(#)main.c 3.1 4/8/87
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/filsys.h>
#include <sys/mount.h>
#include <sys/map.h>
#include <sys/proc.h>
#include <sys/inode.h>
#include <sys/seg.h>
#include <sys/conf.h>
#include <sys/buf.h>
#include <sys/devmaj.h>
/*
* Initialization code.
* Called from cold start routine as
* soon as a stack and segmentation
* have been established.
* Functions:
* clear and free user core
* turn on clock
* hand craft 0th process
* call all initialization routines
* fork - process 0 to schedule
* - process 1 execute bootstrap
*
* loop at low address in user mode -- /etc/init
* cannot be executed.
*/
int io_csr[]; /* I/O device CSR address, see c.c */
char io_bae[]; /* I/O device BAE address offsets, see c.c */
int stksize = sizeof(u.u_stack); /* size of stack, used in mch.s */
int *inEMT = &u.u_inemt;
extern long cdlimit; /* initialized in c.c */
main()
{
startup();
/*
* set up system process
*/
proc[0].p_addr = ka6->r[0];
proc[0].p_size = USIZE;
proc[0].p_stat = SRUN;
proc[0].p_flag |= SLOAD|SSYS;
proc[0].p_nice = NZERO;
u.u_procp = &proc[0];
u.u_cmask = CMASK;
u.u_limit = cdlimit;
/*
* Initialize devices and
* set up 'known' i-nodes
*/
#ifdef UCB_IHASH
ihinit();
#endif
/* clkstart(); */
cinit();
binit();
/*
* clkstart() was moved to here, because
* if there is no clock on the system `panic no clock'
* is called. This is incorrect because panic calls update
* which will not work due to the buffers not having
* been initialized yet.
* Fred Canter 1/1/82
*/
#ifdef UCB_NET
netinit();
#endif UCB_NET
clkstart();
/*
* Iinit needs to be after clkstart.
* rl driver calls timeout and clock
* must have been started, otherwise
* a system hang occurs.
* Bill Burns - 3/15/84
*/
iinit();
rootdir = iget(rootdev, (ino_t)ROOTINO);
rootdir->i_flag &= ~ILOCK;
u.u_cdir = iget(rootdev, (ino_t)ROOTINO);
u.u_cdir->i_flag &= ~ILOCK;
u.u_rdir = NULL;
/*
* call ipc init routines
* Ohms 3/21/85
* call file lock init routine: George 5/31/85
* maus and msg init routines moved to machdep.c: George 6/13/85
*/
seminit();
flckinit();
/*
* make init process
* enter scheduling loop
* with system process
*/
if(newproc()) {
expand(USIZE + (int)btoc(szicode));
estabur((unsigned)0, btoc(szicode), (unsigned)0, 0, RO);
copyout((caddr_t)icode, (caddr_t)0, szicode);
/*
* Return goes to loc. 0 of user init
* code just copied out.
*/
return;
}
sched();
}
/*
* iinit is called once (from main)
* very early in initialization.
* It reads the root's super block
* and initializes the current date
* from the last modified date.
*
* panic: iinit -- cannot read the super
* block. Usually because of an IO error.
*/
int nuda; /* (c.c) number of MSCP controllers */
int nts; /* (tds.c) number of TS11 controllers */
int ntk; /* (tds.c) number of TMSCP controllers */
long boottime;
static
iinit()
{
register struct buf *cp, *bp;
register struct filsys *fp;
int cn, dn, md;
/*
* If RA disks configured, call raopen()
* to force UDA/RQDX1/KLESI init, see errlog.c (case EL_ON:).
* Flag equal to -1 says init controller,
* do get unit status for drive.
* Depends on SA register never actually
* containing -1 (don't think this can happen).
*/
if(bdevsw[RA_BMAJ].d_tab == 0)
goto ii_tk; /* RA disk driver not configured */
for(cn=0; cn<nuda; cn++) {
md = *((int *)io_csr[RA_RMAJ] + cn);
md += 2; /* SA register addr */
if(fuiword((caddr_t)md) != -1)
for(dn=0; dn<8; dn++) {
md = (cn << 6) | (dn << 3);
(*bdevsw[RA_BMAJ].d_open)(((RA_BMAJ<<8)|md), -1);
}
}
ii_tk:
if(bdevsw[TK_BMAJ].d_tab == 0)
goto ii_mnt; /* TK tape driver not configured */
for(cn=0; cn<ntk; cn++) {
md = *((int *)io_csr[TK_RMAJ] + cn);
md += 2; /* SA register addr */
if(fuiword((caddr_t)md) != -1)
(*bdevsw[TK_BMAJ].d_open)(((TK_BMAJ<<8)|cn), -1);
}
/*
* Open the swap device,
* just in case it is not on the same device
* as the root, i.e., ML11.
* Required because swap I/O does not call open
* before calling strategy, that's double plus ungood !
*
* Fred Canter 7/28/83 (should have been long ago but I forgot)
*/
ii_mnt:
(*bdevsw[major(swapdev)].d_open)(swapdev, 1);
(*bdevsw[major(rootdev)].d_open)(rootdev, 1);
bp = bread(rootdev, SUPERB);
if(u.u_error)
panic("iinit");
mount[0].m_bufp = bp;
mount[0].m_inodp = (struct inode *) 1;
bp->b_flags |= B_MOUNT;
mount[0].m_dev = rootdev;
fp = mapin(bp);
fp->s_flock = 0;
fp->s_ilock = 0;
fp->s_ronly = 0;
fp->s_lasti = 1;
fp->s_nbehind = 0;
boottime = time = fp->s_time;
brelse(bp);
mapout(bp);
for(cn=0; cn<4; cn++) { /* Call user device open routines */
if(bdevsw[U1_BMAJ+cn].d_tab) /* device is configured */
(*bdevsw[U1_BMAJ+cn].d_open)(((U1_BMAJ+cn)<<8), -1);
}
}
/*
* This is the set of buffers proper, whose heads
* were declared in buf.h. There can exist buffer
* headers not pointing here that are used purely
* as arguments to the I/O routines to describe
* I/O to be done-- e.g. swbuf for
* swapping.
*/
memaddr bpaddr; /* physical click-address of buffers */
/*
* Initialize the buffer I/O system by freeing
* all buffers and setting all device buffer lists to empty.
*/
static
binit()
{
register struct buf *bp;
register struct buf *dp;
register int i;
struct bdevsw *bdp;
long paddr;
int j, k;
bfreelist.b_forw = bfreelist.b_back =
bfreelist.av_forw = bfreelist.av_back = &bfreelist;
paddr = ((long) bpaddr) << 6;
for (i=0; i<nbuf; i++) {
bp = &buf[i];
bp->b_dev = NODEV;
bp->b_un.b_addr = loint(paddr);
bp->b_xmem = hiint(paddr);
paddr += BSIZE;
bp->b_back = &bfreelist;
bp->b_forw = bfreelist.b_forw;
bfreelist.b_forw->b_back = bp;
bfreelist.b_forw = bp;
bp->b_flags = B_BUSY;
brelse(bp);
}
for (i=0, bdp = bdevsw; bdp->d_open; bdp++, i++) {
dp = bdp->d_tab;
/*
* If any massbus devices (hp, hm, hs, ml, ht) are in the
* configuration table (bdevsw[]), check the controller
* type. Set it to RH70 if the bus address extension
* register is present.
* Also set a bit in the block device configuration word
* (el_bdcw) for device present in bdevsw[].
*
* NOTE: dp points to an array of device tables for drivers
* that support multiple controllers (RA, TK, & TS).
* Added 1/20/86 -- Fred Canter (to fix multi cntlr support)
*/
if(io_bae[i]) /* see c.c */
if((fuiword((caddr_t)(io_csr[i+RK_RMAJ]+io_bae[i])) < 0)
|| (dp == 0))
io_bae[i] = 0;
if(dp) {
if(i == TK_BMAJ)
k = ntk;
else if(i == TS_BMAJ)
k = nts;
else if(i == RA_BMAJ)
k = nuda;
else
k = 1;
for(j=0; j<k; j++) {
dp->b_forw = dp;
dp->b_back = dp;
dp++;
}
el_bdcw |= (1 << i);
}
nblkdev++;
}
/*
* Set up first 10 unibus map registers, if map present.
* 0->(cfree, uda, hp_bads, hk_bads, TS (cmdpkt, chrbuf, mesbuf))
* 1 thru 9 -> buffers
*/
mapinit();
/*
* so that io_info can be put in data space after mb_end
* see bio.c for more info.
*/
{
extern struct {
int nbufr;
long nread, nreada, ncache;
long nwrite, bufcount[1];
} io_info;
io_info.nbufr = nbuf;
}
}