#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "init.h"
void
main(void)
{
active.exiting = 0;
active.machs = 1;
machinit();
confinit();
lockinit();
printinit();
tlbinit();
vecinit();
procinit0();
pgrpinit();
chaninit();
clockinit();
alarminit();
io2init();
chandevreset();
streaminit();
pageinit();
userinit();
launchinit();
schedinit();
}
void
machinit(void)
{
int n;
n = m->machno;
memset(m, 0, sizeof(Mach));
m->machno = n;
m->mmask = 1<<m->machno;
}
void
tlbinit(void)
{
int i;
for(i=0; i<NTLB; i++)
puttlbx(i, KZERO | PTEPID(i), 0);
}
void
vecinit(void)
{
ulong *p, *q;
int size;
p = (ulong*)EXCEPTION;
q = (ulong*)vector80;
for(size=0; size<4; size++)
*p++ = *q++;
p = (ulong*)UTLBMISS;
q = (ulong*)vector80;
for(size=0; size<4; size++)
*p++ = *q++;
}
/*
* We have to program both the IO2 board to generate interrupts
* and the SBCC on CPU 0 to accept them.
*/
void
io2init(void)
{
long i;
/*
* reset VME bus (MODEREG is on the IO2)
*/
MODEREG->resetforce = (1<<1);
for(i=0; i<1000000; i++)
;
MODEREG->resetforce = 0;
MODEREG->masterslave = (SLAVE<<4) | MASTER;
/*
* all VME interrupts to the error routine
*/
for(i=0; i<256; i++)
setvmevec(i, novme);
/*
* tell IO2 to sent all interrupts to CPU 0's SBCC
*/
for(i=0; i<8; i++)
INTVECREG->i[i].vec = 0<<8;
/*
* Tell CPU 0's SBCC to map all interrupts from the IO2 to MIPS level 5
*
* Since there are 6 MIPS hardware interrupts and the SBCC can generate
* only 5, one hardware interrupt can't be generated by the SBCC. SBCC
* interrupt 4 maps to MIPS interrupt 5, SBCC interrupt 0 maps to MIPS
* interrupt 0. I don't know which interrupt is missing. -- presotto
*/
SBCCREG->flevel = 0x10;
/*
* Tell CPU 0's SBCC to enable all interrupts from the IO2.
*
* The SBCC 16 bit registers are read/written as ulong, but only
* bits 23-16 and 7-0 are meaningful.
*/
SBCCREG->fintenable |= 0xff; /* allow all interrupts on the IO2 */
SBCCREG->idintenable |= 0x800000; /* allow interrupts from the IO2 */
/*
* enable all interrupts on the IO2
*/
*IO2SETMASK = 0xff;
}
void
launchinit(void)
{
int i;
for(i=1; i<conf.nmach; i++)
launch(i);
for(i=0; i<1000000; i++)
if(active.machs == (1<<conf.nmach) - 1){
print("all launched\n");
return;
}
print("launch: active = %x\n", active.machs);
}
void
init0(void)
{
m->proc = u->p;
u->p->state = Running;
u->p->mach = m;
spllo();
chandevinit();
u->slash = (*devtab[0].attach)(0);
u->dot = clone(u->slash, 0);
touser();
}
FPsave initfp;
void
userinit(void)
{
Proc *p;
Seg *s;
User *up;
p = newproc();
p->pgrp = newpgrp();
strcpy(p->text, "*init*");
strcpy(p->pgrp->user, "bootes");
savefpregs(&initfp);
p->fpstate = FPinit;
/*
* Kernel Stack
*/
p->sched.pc = (ulong)init0;
p->sched.sp = USERADDR+BY2PG-20;
p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF));
/*
* User
*/
up = (User*)(p->upage->pa|KZERO);
up->p = p;
/*
* User Stack
*/
s = &p->seg[SSEG];
s->proc = p;
s->o = neworig(USTKTOP-BY2PG, 1, OWRPERM, 0);
s->minva = USTKTOP-BY2PG;
s->maxva = USTKTOP;
/*
* Text
*/
s = &p->seg[TSEG];
s->proc = p;
s->o = neworig(UTZERO, 1, 0, 0);
s->o->pte[0].page = newpage(0, 0, UTZERO);
memcpy((ulong*)(s->o->pte[0].page->pa|KZERO), initcode, sizeof initcode);
s->minva = 0x1000;
s->maxva = 0x2000;
ready(p);
}
void
lights(int v)
{
*LED = ~v;
}
typedef struct Beef Beef;
struct Beef
{
long deadbeef;
long sum;
long cpuid;
long virid;
long erno;
void (*launch)(void);
void (*rend)(void);
long junk1[4];
long isize;
long dsize;
long nonbss;
long junk2[18];
};
void
launch(int n)
{
Beef *p;
long i;
p = (Beef*) 0xb0000500 + n;
p->launch = newstart;
p->sum -= (long)newstart;
for(i=0; i<3000000; i++)
if(p->launch == 0)
break;
}
void
online(void)
{
machinit();
lock(&active);
active.machs |= 1<<m->machno;
unlock(&active);
tlbinit();
clockinit();
schedinit();
}
void
exit(void)
{
int i;
u = 0;
lock(&active);
active.machs &= ~(1<<m->machno);
active.exiting = 1;
unlock(&active);
spllo();
print("cpu %d exiting\n", m->machno);
while(active.machs || consactive())
for(i=0; i<1000; i++)
;
splhi();
for(i=0; i<2000000; i++)
;
duartreset();
firmware();
}
/*
* Insert new into list after where
*/
void
insert(List **head, List *where, List *new)
{
if(where == 0){
new->next = *head;
*head = new;
}else{
new->next = where->next;
where->next = new;
}
}
/*
* Insert new into list at end
*/
void
append(List **head, List *new)
{
List *where;
where = *head;
if(where == 0)
*head = new;
else{
while(where->next)
where = where->next;
where->next = new;
}
new->next = 0;
}
/*
* Delete old from list
*/
void
delete0(List **head, List *old)
{
List *l;
l = *head;
if(l == old){
*head = old->next;
return;
}
while(l->next != old)
l = l->next;
l->next = old->next;
}
/*
* Delete old from list. where->next is known to be old.
*/
void
delete(List **head, List *where, List *old)
{
if(where == 0){
*head = old->next;
return;
}
where->next = old->next;
}
Conf conf;
void
confinit(void)
{
long x, i, j, *l;
conf.nmach = 4;
if(conf.nmach > MAXMACH)
panic("confinit");
conf.nproc = 193;
conf.npgrp = 100;
x = 0x12345678;
for(i=4; i<128; i+=4){
l = (long*)(KSEG1|(i*1024L*1024L));
*l = x;
wbflush();
*(ulong*)KSEG1 = *(ulong*)KSEG1; /* clear latches */
if(*l != x)
break;
x += 0x3141526;
}
conf.npage = i*1024/4;
conf.npte = 4*conf.npage;
conf.nmod = 2000;
conf.nalarm = 10000;
conf.norig = 500;
conf.nchan = 500;
conf.nenv = 400;
conf.nenvchar = 20000;
conf.npgenv = 400;
conf.nmtab = 100;
conf.nmount = 500;
conf.nmntdev = 30;
conf.nmntbuf = 60;
conf.nmnthdr = 60;
conf.nstream = 512;
conf.nqueue = 5 * conf.nstream;
conf.nblock = 16 * conf.nstream;
conf.nsrv = 32;
}