#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "init.h"
#include "pool.h"
Mach *m;
Proc *up;
Conf conf;
int noprint;
void
main(void)
{
mmuinvalidate();
/* zero out bss */
memset(edata, 0, end-edata);
/* point to Mach structure */
m = (Mach*)MACHADDR;
memset(m, 0, sizeof(Mach));
m->ticks = 1;
active.machs = 1;
rs232power(1);
quotefmtinstall();
iprint("\nPlan 9 bitsy kernel\n");
confinit();
xinit();
mmuinit();
machinit();
trapinit();
sa1110_uartsetup(1);
dmainit();
screeninit();
printinit(); /* from here on, print works, before this we need iprint */
clockinit();
procinit0();
initseg();
links();
chandevreset();
pageinit();
swapinit();
userinit();
powerinit();
schedinit();
}
/* need to do better */
void
reboot(void*, void*, ulong)
{
exit(0);
}
/*
* exit kernel either on a panic or user request
*/
void
exit(int ispanic)
{
void (*f)(void);
USED(ispanic);
delay(1000);
iprint("it's a wonderful day to die\n");
cacheflush();
mmuinvalidate();
mmudisable();
f = nil;
(*f)();
}
static uchar *sp;
/*
* starting place for first process
*/
void
init0(void)
{
up->nerrlab = 0;
spllo();
/*
* These are o.k. because rootinit is null.
* Then early kproc's will have a root and dot.
*/
up->slash = namec("#/", Atodir, 0, 0);
pathclose(up->slash->path);
up->slash->path = newpath("/");
up->dot = cclone(up->slash);
chandevinit();
if(!waserror()){
ksetenv("terminal", "bitsy", 0);
ksetenv("cputype", "arm", 0);
if(cpuserver)
ksetenv("service", "cpu", 0);
else
ksetenv("service", "terminal", 0);
poperror();
}
kproc("alarm", alarmkproc, 0);
kproc("power", powerkproc, 0);
touser(sp);
}
/*
* pass boot arguments to /boot
*/
static uchar *
pusharg(char *p)
{
int n;
n = strlen(p)+1;
sp -= n;
memmove(sp, p, n);
return sp;
}
static void
bootargs(ulong base)
{
int i, ac;
uchar *av[32];
uchar *bootpath;
uchar **lsp;
/*
* the sizeof(Sargs) is to make the validaddr check in
* trap.c's syscall() work even when we have less than the
* max number of args.
*/
sp = (uchar*)base + BY2PG - sizeof(Sargs);
bootpath = pusharg("/boot/boot");
ac = 0;
av[ac++] = pusharg("boot");
/* 4 byte word align stack */
sp = (uchar*)((ulong)sp & ~3);
/* build argc, argv on stack */
sp -= (ac+1)*sizeof(sp);
lsp = (uchar**)sp;
for(i = 0; i < ac; i++)
*lsp++ = av[i] + ((USTKTOP - BY2PG) - base);
*lsp = 0;
/* push argv onto stack */
sp -= BY2WD;
lsp = (uchar**)sp;
*lsp = sp + BY2WD + ((USTKTOP - BY2PG) - base);
/* push pointer to "/boot" */
sp -= BY2WD;
lsp = (uchar**)sp;
*lsp = bootpath + ((USTKTOP - BY2PG) - base);
/* leave space for where the initcode's caller's return PC would normally reside */
sp -= BY2WD;
/* relocate stack to user's virtual addresses */
sp += (USTKTOP - BY2PG) - base;
}
/*
* create the first process
*/
void
userinit(void)
{
Proc *p;
Segment *s;
KMap *k;
Page *pg;
/* no processes yet */
up = nil;
p = newproc();
p->pgrp = newpgrp();
p->egrp = smalloc(sizeof(Egrp));
p->egrp->ref = 1;
p->fgrp = dupfgrp(nil);
p->rgrp = newrgrp();
p->procmode = 0640;
kstrdup(&eve, "");
kstrdup(&p->text, "*init*");
kstrdup(&p->user, eve);
/*
* Kernel Stack
*/
p->sched.pc = (ulong)init0;
p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Sargs)+BY2WD);
/*
* User Stack
*/
s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
p->seg[SSEG] = s;
pg = newpage(1, 0, USTKTOP-BY2PG);
segpage(s, pg);
k = kmap(pg);
bootargs(VA(k));
kunmap(k);
/*
* Text
*/
s = newseg(SG_TEXT, UTZERO, 1);
p->seg[TSEG] = s;
pg = newpage(1, 0, UTZERO);
memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
segpage(s, pg);
k = kmap(s->map[0]->pages[0]);
memmove((ulong*)VA(k), initcode, sizeof initcode);
kunmap(k);
ready(p);
}
/*
* set mach dependent process state for a new process
*/
void
procsetup(Proc *p)
{
p->fpstate = FPinit;
}
/*
* Save the mach dependent part of the process state.
*/
void
procsave(Proc *p)
{
USED(p);
}
/* place holder */
/*
* dummy since rdb is not included
*/
void
rdb(void)
{
}
/*
* probe the last location in a meg of memory, make sure it's not
* reflected into something else we've already found.
*/
int
probemem(ulong addr)
{
int i;
ulong *p;
ulong a;
addr += OneMeg - sizeof(ulong);
p = (ulong*)addr;
*p = addr;
for(i=0; i<nelem(conf.mem); i++){
for(a = conf.mem[i].base+OneMeg-sizeof(ulong); a < conf.mem[i].limit; a += OneMeg){
p = (ulong*)a;
*p = 0;
}
}
p = (ulong*)addr;
if(*p != addr)
return -1;
return 0;
}
/*
* we assume that the kernel is at the beginning of one of the
* contiguous chunks of memory.
*/
void
confinit(void)
{
int i, j;
ulong addr;
ulong ktop;
/* find first two contiguous sections of available memory */
addr = PHYSDRAM0;
for(i=0; i<nelem(conf.mem); i++){
conf.mem[i].base = addr;
conf.mem[i].limit = addr;
}
for(j=0; j<nelem(conf.mem); j++){
conf.mem[j].base = addr;
conf.mem[j].limit = addr;
for(i = 0; i < 512; i++){
if(probemem(addr) == 0)
break;
addr += OneMeg;
}
for(; i < 512; i++){
if(probemem(addr) < 0)
break;
addr += OneMeg;
conf.mem[j].limit = addr;
}
}
conf.npage = 0;
for(i=0; i<nelem(conf.mem); i++){
/* take kernel out of allocatable space */
ktop = PGROUND((ulong)end);
if(ktop >= conf.mem[i].base && ktop <= conf.mem[i].limit)
conf.mem[i].base = ktop;
/* zero memory */
memset((void*)conf.mem[i].base, 0, conf.mem[i].limit - conf.mem[i].base);
conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
conf.npage += conf.mem[i].npage;
}
if(conf.npage > 16*MB/BY2PG){
conf.upages = (conf.npage*60)/100;
imagmem->minarena = 4*1024*1024;
}else
conf.upages = (conf.npage*40)/100;
conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
/* only one processor */
conf.nmach = 1;
/* set up other configuration parameters */
conf.nproc = 100;
conf.nswap = conf.npage*3;
conf.nswppo = 4096;
conf.nimage = 200;
conf.monitor = 1;
conf.copymode = 0; /* copy on write */
}
GPIOregs *gpioregs;
ulong *egpioreg = (ulong*)EGPIOREGS;
PPCregs *ppcregs;
MemConfRegs *memconfregs;
PowerRegs *powerregs;
ResetRegs *resetregs;
/*
* configure the machine
*/
void
machinit(void)
{
/* set direction of SA1110 io pins and select alternate functions for some */
gpioregs = mapspecial(GPIOREGS, sizeof(GPIOregs));
gpioregs->direction =
GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
|GPIO_CLK_SET0_o|GPIO_CLK_SET1_o
|GPIO_L3_SDA_io|GPIO_L3_MODE_o|GPIO_L3_SCLK_o
|GPIO_COM_RTS_o;
gpioregs->rising = 0;
gpioregs->falling = 0;
gpioregs->altfunc |=
GPIO_LDD8_o|GPIO_LDD9_o|GPIO_LDD10_o|GPIO_LDD11_o
|GPIO_LDD12_o|GPIO_LDD13_o|GPIO_LDD14_o|GPIO_LDD15_o
|GPIO_SSP_CLK_i;
/* map in special H3650 io pins */
egpioreg = mapspecial(EGPIOREGS, sizeof(ulong));
/* map in peripheral pin controller (ssp will need it) */
ppcregs = mapspecial(PPCREGS, sizeof(PPCregs));
/* SA1110 power management */
powerregs = mapspecial(POWERREGS, sizeof(PowerRegs));
/* memory configuraton */
memconfregs = mapspecial(MEMCONFREGS, sizeof(MemConfRegs));
/* reset controller */
resetregs = mapspecial(RESETREGS, sizeof(ResetRegs));
}
/*
* manage egpio bits
*/
static ulong egpiosticky;
void
egpiobits(ulong bits, int on)
{
if(on)
egpiosticky |= bits;
else
egpiosticky &= ~bits;
*egpioreg = egpiosticky;
}
void
rs232power(int on)
{
egpiobits(EGPIO_rs232_power, on);
delay(50);
}
void
audioamppower(int on)
{
egpiobits(EGPIO_audio_power, on);
delay(50);
}
void
audioicpower(int on)
{
egpiobits(EGPIO_audio_ic_power, on);
delay(50);
}
void
irpower(int on)
{
egpiobits(EGPIO_ir_power, on);
delay(50);
}
void
lcdpower(int on)
{
egpiobits(EGPIO_lcd_3v|EGPIO_lcd_ic_power|EGPIO_lcd_5v|EGPIO_lcd_9v, on);
delay(50);
}
void
flashprogpower(int on)
{
egpiobits(EGPIO_prog_flash, on);
}
/* here on hardware reset */
void
resettrap(void)
{
}
/*
* for drivers that used to run on x86's
*/
void
outb(ulong a, uchar v)
{
*(uchar*)a = v;
}
void
outs(ulong a, ushort v)
{
*(ushort*)a = v;
}
void
outss(ulong a, void *p, int n)
{
ushort *sp = p;
while(n-- > 0)
*(ushort*)a = *sp++;
}
void
outl(ulong a, ulong v)
{
*(ulong*)a = v;
}
uchar
inb(ulong a)
{
return *(uchar*)a;
}
ushort
ins(ulong a)
{
return *(ushort*)a;
}
void
inss(ulong a, void *p, int n)
{
ushort *sp = p;
while(n-- > 0)
*sp++ = *(ushort*)a;
}
ulong
inl(ulong a)
{
return *(ulong*)a;
}
char*
getconf(char*)
{
return nil;
}
long
_xdec(long *p)
{
int s;
long v;
s = splhi();
v = --*p;
splx(s);
return v;
}
void
_xinc(long *p)
{
int s;
s = splhi();
++*p;
splx(s);
}
int
cmpswap(long *addr, long old, long new)
{
int r, s;
s = splhi();
if(r = (*addr==old))
*addr = new;
splx(s);
return r;
}
|