diff options
Diffstat (limited to 'os/rpcg')
| -rw-r--r-- | os/rpcg/NOTICE | 4 | ||||
| -rw-r--r-- | os/rpcg/archrpcg.c | 428 | ||||
| -rw-r--r-- | os/rpcg/archrpcg.h | 48 | ||||
| -rw-r--r-- | os/rpcg/clock.c | 145 | ||||
| -rw-r--r-- | os/rpcg/dat.h | 162 | ||||
| -rw-r--r-- | os/rpcg/fns.h | 119 | ||||
| -rw-r--r-- | os/rpcg/io.h | 1 | ||||
| -rw-r--r-- | os/rpcg/main.c | 392 | ||||
| -rw-r--r-- | os/rpcg/mem.h | 157 | ||||
| -rw-r--r-- | os/rpcg/mkfile | 108 | ||||
| -rw-r--r-- | os/rpcg/mmu.c | 20 | ||||
| -rw-r--r-- | os/rpcg/rpcg | 122 | ||||
| -rw-r--r-- | os/rpcg/tlb.s | 24 |
13 files changed, 1730 insertions, 0 deletions
diff --git a/os/rpcg/NOTICE b/os/rpcg/NOTICE new file mode 100644 index 00000000..0e031173 --- /dev/null +++ b/os/rpcg/NOTICE @@ -0,0 +1,4 @@ +Inferno® Copyright © 1996-1999 Lucent Technologies Inc. All rights reserved. +PowerPC support Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net). All rights reserved. +MPC8xx Inferno PowerPC port Copyright © 1998-2003 Vita Nuova Holdings Limited. All rights reserved. +RPCG Inferno PowerPC port Copyright © 2002-2003 Vita Nuova Holdings Limited. All rights reserved. diff --git a/os/rpcg/archrpcg.c b/os/rpcg/archrpcg.c new file mode 100644 index 00000000..8da2cab1 --- /dev/null +++ b/os/rpcg/archrpcg.c @@ -0,0 +1,428 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +#include "../port/netif.h" +#include "../mpc/etherif.h" +#include "../port/flashif.h" +#include "archrpcg.h" + +/* + * board-specific support for the 850/823 RPCG board + */ + +enum { + /* sccr */ + COM3= IBIT(1)|IBIT(2), /* clock output disabled */ + TBS = IBIT(6), /* =0, time base is OSCCLK/{4,16}; =1, time base is GCLK2/16 */ + RTSEL = IBIT(8), /* =0, select main oscillator (OSCM); =1, select external crystal (EXTCLK) */ + RTDIV = IBIT(7), /* =0, divide by 4; =1, divide by 512 */ + CRQEN = IBIT(9), /* =1, switch to high frequency when CPM active */ + PRQEN = IBIT(10), /* =1, switch to high frequency when interrupt pending */ + EDBF2 = IBIT(14), /* =1, CLKOUT is GCLK2/2 */ + + /* plprcr */ + CSRC = IBIT(21), /* =0, clock is DFNH; =1, clock is DFNL */ +}; + +/* + * called early in main.c, after machinit: + * using board and architecture specific registers, initialise + * 8xx registers that need it and complete initialisation of the Mach structure. + */ +void +archinit(void) +{ + IMM *io; + int mf, i; + + m->bcsr = KADDR(PHYSBCSR); + m->bcsr[0] &= ~EnableEnet; + io = m->iomem; /* run by reset code: no need to lock */ + m->clockgen = 8000000; /* crystal frequency */ + m->oscclk = m->clockgen/MHz; + io->plprcrk = KEEP_ALIVE_KEY; + io->plprcr &= ~CSRC; /* general system clock is DFNH */ + mf = (io->plprcr >> 20)+1; /* use timing set by bootstrap */ + m->cpuhz = m->clockgen*mf; + m->speed = m->cpuhz/MHz; + io->plprcrk = ~KEEP_ALIVE_KEY; + io->sccrk = KEEP_ALIVE_KEY; + io->sccr |= COM3 | TBS | CRQEN | PRQEN; + io->sccrk = ~KEEP_ALIVE_KEY; + if(0){ + /* reset PCMCIA in case monitor hasn't */ + io->pgcr[1] = 1<<7; /* OP2 high to disable PCMCIA */ + io->per = 0; + io->pscr = ~0; + for(i=0; i<8; i++) + io->pcmr[i].base = io->pcmr[i].option = 0; + } +} + +static ulong +banksize(int x, ulong *pa) +{ + IMM *io; + + io = m->iomem; + if((io->memc[x].base & 1) == 0) + return 0; /* bank not valid */ + *pa = io->memc[x].base & ~0x7FFF; + return -(io->memc[x].option&~0x7FFF); +} + +/* + * initialise the kernel's memory configuration: + * there are two banks (base0, npage0) and (base1, npage1). + * initialise any other values in conf that are board-specific. + */ +void +archconfinit(void) +{ + ulong nbytes, pa, ktop; + + conf.nscc = 2; + conf.nocts2 = 1; /* TO DO: check this */ + + conf.npage0 = 0; + nbytes = banksize(DRAM1CS, &pa); + if(nbytes){ + conf.npage0 = nbytes/BY2PG; + conf.base0 = pa; + } + + conf.npage1 = 0; + + /* the following assumes the kernel text and/or data is in bank 0 */ + ktop = PGROUND((ulong)end); + ktop = PADDR(ktop) - conf.base0; + conf.npage0 -= ktop/BY2PG; + conf.base0 += ktop; + + /* check for NVRAM */ + if(m->bcsr[0] & NVRAMBattGood){ + conf.nvramsize = banksize(NVRAMCS, &pa); + conf.nvrambase = KADDR(pa); + } +} + +void +cpuidprint(void) +{ + ulong v; + int i; + + print("PVR: "); + switch(m->cputype){ + case 0x01: print("MPC601"); break; + case 0x03: print("MPC603"); break; + case 0x04: print("MPC604"); break; + case 0x06: print("MPC603e"); break; + case 0x07: print("MPC603e-v7"); break; + case 0x50: print("MPC8xx"); break; + default: print("PowerPC version #%x", m->cputype); break; + } + print(", revision #%lux\n", getpvr()&0xffff); + print("IMMR: "); + v = getimmr() & 0xFFFF; + switch(v>>8){ + case 0x00: print("MPC860/821"); break; + case 0x20: print("MPC823"); break; + case 0x21: print("MPC823A"); break; + default: print("Type #%lux", v>>8); break; + } + print(", mask #%lux\n", v&0xFF); + print("plprcr=%8.8lux sccr=%8.8lux bcsr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr, m->bcsr[0]); + print("%lud MHz system\n", m->cpuhz/MHz); + print("%lud pages\n", (conf.npage0-conf.base0)/BY2PG); + print("%ludK NVRAM\n", conf.nvramsize/1024); + print("\n"); + for(i=0; i<nelem(m->iomem->pcmr); i++) + print("%d: %8.8lux %8.8lux\n", i, m->iomem->memc[i].base, m->iomem->memc[i].option); +} + +/* + * provide value for #r/switch (devrtc.c) + */ +int +archoptionsw(void) +{ + return (m->bcsr[0]&DipSwitchMask)>>4; +} + +/* + * invoked by clock.c:/^clockintr + */ +static void +twinkle(void) +{ + if(m->ticks%MS2TK(1000) == 0) + m->bcsr[0] ^= LedOff; +} + +void (*archclocktick)(void) = twinkle; + +/* + * invoked by ../port/taslock.c:/^ilock: + * reset watchdog timer here, if there is one and it is enabled + * (qboot currently disables it on the FADS board) + */ +void +clockcheck(void) +{ +} + +/* + * for devflash.c:/^flashreset + * retrieve flash type, virtual base and length and return 0; + * return -1 on error (no flash) + */ +int +archflashreset(int bank, Flash *f) +{ + if(bank != 0) + return -1; + f->type = "AMD29F0x0"; +// f->type = "cfi16"; + f->addr = KADDR(PHYSFLASH); + f->size = 4*1024*1024; + f->width = 4; + f->interleave = 1; + return 0; +} + +int +archether(int ctlrno, Ether *ether) +{ + if(isaconfig("ether", ctlrno, ether) == 0) + return -1; + return 1; +} + +/* + * enable the clocks for the given SCC ether and reveal them to the caller. + * do anything else required to prepare the transceiver (eg, set full-duplex, reset loopback). + */ +int +archetherenable(int cpmid, int *rcs, int *tcs, int mbps, int fullduplex) +{ + IMM *io; + + if(cpmid != CPscc2) + return -1; + USED(mbps); + USED(fullduplex); + io = ioplock(); + m->bcsr[0] = (m->bcsr[0] & ~(EnableXcrLB|DisableColTest)) | EnableEnet; + eieio(); + io->papar |= SIBIT(6)|SIBIT(4); /* enable CLK2 and CLK4 */ + io->padir &= ~(SIBIT(6)|SIBIT(4)); + iopunlock(); + *rcs = CLK4; + *tcs = CLK2; + return 0; +} + +/* + * do anything extra required to enable the UART on the given CPM port + */ +void +archenableuart(int id, int irda) +{ + USED(id, irda); +} + +/* + * do anything extra required to disable the UART on the given CPM port + */ +void +archdisableuart(int id) +{ + USED(id); +} + +/* + * enable the external USB transceiver + * speed is 12MHz if highspeed is non-zero; 1.5MHz if zero + * master is non-zero if the node is acting as USB Host and should provide power + */ +void +archenableusb(int highspeed, int master) +{ + ioplock(); + if(master) + m->bcsr[0] |= EnableUSBPwr; + else + m->bcsr[0] &= ~EnableUSBPwr; + m->bcsr[0] &= ~DisableUSB; + if(highspeed) + m->bcsr[0] |= HighSpdUSB; + else + m->bcsr[0] &= ~HighSpdUSB; + iopunlock(); +} + +/* + * shut down the USB transceiver + */ +void +archdisableusb(void) +{ + ioplock(); + m->bcsr[0] |= DisableUSB; + m->bcsr[0] &= ~EnableUSBPwr; + iopunlock(); +} + +/* + * set the external infrared transceiver to the given speed + */ +void +archsetirxcvr(int highspeed) +{ + USED(highspeed); +} + +/* + * force hardware reset/reboot + */ +void +archreboot(void) +{ + IMM *io; + + io = m->iomem; + io->plprcrk = KEEP_ALIVE_KEY; + io->plprcr |= 1<<7; /* checkstop reset enable */ + io->plprcrk = ~KEEP_ALIVE_KEY; + eieio(); + io->sdcr = 1; + eieio(); + io->lccr = 0; /* switch LCD off */ + eieio(); + firmware(0); +} + +/* + * board-specific PCMCIA support: assumes slot B on 82xFADS + */ +int +pcmslotavail(int slotno) +{ + return slotno == 1; +} + +void +pcmenable(void) +{ + ioplock(); + m->bcsr[0] = m->bcsr[0] & ~(VPPMask|VCCMask); /* power off */ + eieio(); + m->bcsr[0] |= VCC5V | VPPVCC; /* apply Vcc */ + eieio(); + m->iomem->pgcr[1] = 0; /* OP2 low to enable PCMCIA */ + iopunlock(); +iprint("B=%8.8lux\n", m->bcsr[0]); +} + +int +pcmpowered(int) +{ + ulong r; + + r = m->bcsr[0]&VCCMask; + if(r == VCC5V) + return 5; + if(r == VCC3V) + return 3; + return 0; +} + +void +pcmsetvcc(int, int v) +{ + if(v == 5) + v = VCC5V; + else if(v == 3) + v = VCC3V; + else + v = VCC0V; + ioplock(); + m->bcsr[0] = (m->bcsr[0] & ~VCCMask) | v; + iopunlock(); +} + +void +pcmsetvpp(int, int v) +{ + if(v == 5 || v == 3) + v = VPPVCC; + else if(v == 12) + v = VPP12V; + else if(v == 0) + v = VPP0V; + else + v = VPPHiZ; + ioplock(); + m->bcsr[0] = (m->bcsr[0] & ~VPPMask) | v; + iopunlock(); +} + +void +pcmpower(int slotno, int on) +{ + if(!on){ + pcmsetvcc(slotno, 0); /* turn off card power */ + pcmsetvpp(slotno, -1); /* turn off programming voltage (Hi-Z) */ + }else + pcmsetvcc(slotno, 5); +} + +/* + * enable/disable the LCD panel's backlight + */ +void +archbacklight(int on) +{ + USED(on); +} + +/* + * set parameters to describe the screen + */ +int +archlcdmode(Mode *m) +{ + m->x = 640; + m->y = 480; + m->d = 3; + m->lcd.freq = 25000000; + m->lcd.ac = 0; + m->lcd.vpw = 1; + m->lcd.wbf = 33; + m->lcd.wbl = 228; + m->lcd.flags = IsColour | IsTFT | OELow | VsyncLow | ClockLow; + return -1; /* there isn't a screen */ +} + +/* + * there isn't a keyboard port + */ +void +archkbdinit(void) +{ +} + +void +archflashwp(Flash*, int) +{ +} diff --git a/os/rpcg/archrpcg.h b/os/rpcg/archrpcg.h new file mode 100644 index 00000000..400dc2f4 --- /dev/null +++ b/os/rpcg/archrpcg.h @@ -0,0 +1,48 @@ +/* + * values for RPXLite AW + */ +enum { + /* CS assignment */ + BOOTCS = 0, + DRAM1CS = 1, + DRAM2CS = 2, + BCSRCS = 3, + NVRAMCS = 4, + /* expansion header on CS5 */ + PCMCIA0CS= 6, /* even bytes(!); CS6 to header if OP2 high */ + PCMCIA1CS= 7, /* odd bytes(!); CS7 to header if OP2 high */ +}; + +/* + * BCSR bits (there's only one register) + */ +enum { + EnableEnet = IBIT(0), + EnableXcrLB= IBIT(1), + DisableColTest= IBIT(2), + DisableFullDplx=IBIT(3), + LedOff= IBIT(4), + DisableUSB= IBIT(5), + HighSpdUSB= IBIT(6), + EnableUSBPwr= IBIT(7), + /* 8,9,10 unused */ + VCCMask= IBIT(12)|IBIT(13), + VPPMask= IBIT(14)|IBIT(15), + VCC0V= 0, + VCC5V= IBIT(13), + VCC3V= IBIT(12), + VPP0V= 0, + VPPVCC= IBIT(14), + VPP12V= IBIT(15), + VPPHiZ= IBIT(14)|IBIT(15), + /* 16-23 NYI */ + DipSwitchMask= IBIT(24)|IBIT(25)|IBIT(26)|IBIT(27), + DipSwitch0= IBIT(24), + DipSwitch1= IBIT(25), + DipSwitch2= IBIT(26), + DipSwitch3= IBIT(27), + /* bit 28 RESERVED */ + FlashComplete= IBIT(29), + NVRAMBattGood= IBIT(30), + RTCBattGood= IBIT(31), +}; diff --git a/os/rpcg/clock.c b/os/rpcg/clock.c new file mode 100644 index 00000000..05f79891 --- /dev/null +++ b/os/rpcg/clock.c @@ -0,0 +1,145 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" + +#include <isa.h> +#include <interp.h> + +typedef struct Clock0link Clock0link; +typedef struct Clock0link { + void (*clock)(void); + Clock0link* link; +} Clock0link; + +static Clock0link *clock0link; +static Lock clock0lock; +ulong clkrelinq; +void (*kproftick)(ulong); /* set by devkprof.c when active */ +void (*archclocktick)(void); /* set by arch*.c when desired */ + +Timer* +addclock0link(void (*clock)(void), int) +{ + Clock0link *lp; + + if((lp = malloc(sizeof(Clock0link))) == 0){ + print("addclock0link: too many links\n"); + return nil; + } + ilock(&clock0lock); + lp->clock = clock; + lp->link = clock0link; + clock0link = lp; + iunlock(&clock0lock); + return nil; +} + +void +delay(int l) +{ + ulong i, j; + + j = m->delayloop; + while(l-- > 0) + for(i=0; i < j; i++) + ; +} + +void +microdelay(int l) +{ + ulong i; + + l *= m->delayloop; + l /= 1000; + if(l <= 0) + l = 1; + for(i = 0; i < l; i++) + ; +} + +enum { + Timebase = 2, /* system clock cycles per time base cycle */ +}; + +static ulong clkreload; + +void +clockinit(void) +{ + long x; + + m->delayloop = m->cpuhz/1000; /* initial estimate */ + do { + x = gettbl(); + delay(10); + x = gettbl() - x; + } while(x < 0); + + /* + * fix count + */ + m->delayloop = ((vlong)m->delayloop*(10*m->clockgen/1000))/(x*Timebase); + if(m->delayloop == 0) + m->delayloop = 1; + + clkreload = (m->clockgen/Timebase)/HZ-1; + putdec(clkreload); +} + +void +clockintr(Ureg *ur) +{ + Clock0link *lp; + long v; + + v = -getdec(); + if(v > clkreload/2){ + if(v > clkreload) + m->ticks += v/clkreload; + v = 0; + } + putdec(clkreload-v); + + /* watchdog */ + if(m->iomem->sypcr & (1<<2)){ + m->iomem->swsr = 0x556c; + m->iomem->swsr = 0xaa39; + } + + m->ticks++; + if(archclocktick != nil) + archclocktick(); + + if(up) + up->pc = ur->pc; + + checkalarms(); + if(m->machno == 0) { + if(kproftick != nil) + (*kproftick)(ur->pc); + if(canlock(&clock0lock)){ + for(lp = clock0link; lp; lp = lp->link) + lp->clock(); + unlock(&clock0lock); + } + } + + if(up && up->state == Running){ + if(cflag && up->type == Interp && tready(nil)) + ur->cr |= 1; /* set flag in condition register for ../../libinterp/comp-power.c:/^schedcheck */ + } + /* other preemption checks are done by trap.c */ +} + +uvlong +fastticks(uvlong *hz) +{ + if(hz) + *hz = HZ; + return m->ticks; +} diff --git a/os/rpcg/dat.h b/os/rpcg/dat.h new file mode 100644 index 00000000..19d7c560 --- /dev/null +++ b/os/rpcg/dat.h @@ -0,0 +1,162 @@ +typedef struct Conf Conf; +typedef struct FPU FPU; +typedef struct FPenv FPenv; +typedef struct IMM IMM; +typedef struct Irqctl Irqctl; +typedef struct ISAConf ISAConf; +typedef struct Label Label; +typedef struct Lock Lock; +typedef struct Mach Mach; +typedef struct Map Map; +typedef struct Power Power; +typedef struct RMap RMap; +typedef struct Ureg Ureg; + +typedef ulong Instr; + +#define MACHP(n) (n==0? &mach0 : *(Mach**)0) + +struct Lock +{ + ulong key; + ulong pc; + ulong sr; + int pri; +}; + +struct Label +{ + ulong sp; + ulong pc; +}; + +/* + * Proc.fpstate + */ +enum +{ + FPINIT, + FPACTIVE, + FPINACTIVE, +}; + +/* + * This structure must agree with FPsave and FPrestore asm routines + */ +struct FPenv +{ + union { + double fpscrd; + struct { + ulong pad; + ulong fpscr; + }; + }; + int fpistate; /* emulated fp */ + ulong emreg[32][3]; /* emulated fp */ +}; +/* + * This structure must agree with fpsave and fprestore asm routines + */ +struct FPU +{ + double fpreg[32]; + FPenv env; +}; + +struct Conf +{ + ulong nmach; /* processors */ + ulong nproc; /* processes */ + ulong npage0; /* total physical pages of memory */ + ulong npage1; /* total physical pages of memory */ + ulong npage; /* total physical pages of memory */ + ulong base0; /* base of bank 0 */ + ulong base1; /* base of bank 1 */ + ulong ialloc; /* max interrupt time allocation in bytes */ + + int nscc; /* number of SCCs implemented */ + ulong smcuarts; /* bits for SMCs to define as eiaN */ + ulong sccuarts; /* bits for SCCs to define as eiaN */ + int nocts2; /* CTS2 and CD2 aren't connected */ + uchar* nvrambase; /* virtual address of nvram */ + ulong nvramsize; /* size in bytes */ +}; + +#include "../port/portdat.h" + +/* + * machine dependent definitions not used by ../port/dat.h + */ + +struct Mach +{ + /* OFFSETS OF THE FOLLOWING KNOWN BY l.s */ + int machno; /* physical id of processor (unused) */ + ulong splpc; /* pc of last caller to splhi (unused) */ + int mmask; /* 1<<m->machno (unused) */ + + /* ordering from here on irrelevant */ + ulong ticks; /* of the clock since boot time */ + Proc *proc; /* current process on this processor */ + Label sched; /* scheduler wakeup */ + Lock alarmlock; /* access to alarm list */ + void *alarm; /* alarms bound to this clock */ + int nrdy; + int speed; /* general system clock in MHz */ + long oscclk; /* oscillator frequency (MHz) */ + long cpuhz; /* general system clock (cycles) */ + long clockgen; /* clock generator frequency (cycles) */ + int cputype; + ulong delayloop; + ulong* bcsr; + IMM* iomem; /* MPC8xx internal i/o control memory */ + + /* MUST BE LAST */ + int stack[1]; +}; +extern Mach mach0; + + +/* + * a parsed .ini line + */ +#define NISAOPT 8 + +struct ISAConf { + char* type; + ulong port; + ulong irq; + ulong mem; + int dma; + ulong size; + ulong freq; + uchar bus; + + int nopt; + char* opt[NISAOPT]; +}; + +struct Map { + int size; + ulong addr; +}; + +struct RMap { + char* name; + Map* map; + Map* mapend; + + Lock; +}; + +struct Power { + Dev* dev; + int (*powerdown)(Power*); + int (*powerup)(Power*); + int state; + void* arg; +}; + +extern register Mach *m; +extern register Proc *up; diff --git a/os/rpcg/fns.h b/os/rpcg/fns.h new file mode 100644 index 00000000..d776078d --- /dev/null +++ b/os/rpcg/fns.h @@ -0,0 +1,119 @@ +#include "../port/portfns.h" + +void addpower(Power*); +void archbacklight(int); +void archconfinit(void); +void archdisableuart(int); +void archdisableusb(void); +void archdisablevideo(void); +void archenableuart(int, int); +void archenableusb(int, int); +void archenablevideo(void); +void archkbdinit(void); +void archresetvideo(void); +int archetherenable(int, int*, int*, int, int); +void archinit(void); +int archoptionsw(void); +void archreboot(void); +void archsetirxcvr(int); +uchar* archvideobuffer(long); +ulong baudgen(int, int); +int brgalloc(void); +void brgfree(int); +int cistrcmp(char*, char*); +int cistrncmp(char*, char*, int); +void clockcheck(void); +void clockinit(void); +void clockintr(Ureg*); +void clrfptrap(void); +#define coherence() /* nothing needed for uniprocessor */ +void cpminit(void); +void cpuidprint(void); +void dcflush(void*, ulong); +void dcinval(void*, ulong); +void delay(int); +void dtlbmiss(void); +void dumplongs(char*, ulong*, int); +void dumpregs(Ureg*); +void eieio(void); +void faultpower(Ureg*); +void firmware(int); +void fpinit(void); +int fpipower(Ureg*); +void fpoff(void); +void fprestore(FPU*); +void fpsave(FPU*); +ulong fpstatus(void); +char* getconf(char*); +ulong getdar(void); +ulong getdec(void); +ulong getdepn(void); +ulong getdsisr(void); +ulong getimmr(void); +ulong getmsr(void); +ulong getpvr(void); +ulong gettbl(void); +ulong gettbu(void); +void gotopc(ulong); +void icflush(void*, ulong); +void idle(void); +#define idlehands() /* nothing to do in the runproc */ +void intr(Ureg*); +void intrenable(int, void (*)(Ureg*, void*), void*, int, char*); +void intrdisable(int, void (*)(Ureg*, void*), void*, int, char*); +int intrstats(char*, int); +void intrvec(void); +int isaconfig(char*, int, ISAConf*); +int isvalid_va(void*); +void itlbmiss(void); +void kbdinit(void); +void kbdreset(void); +void lcdpanel(int); +void links(void); +void mapfree(RMap*, ulong, int); +void mapinit(RMap*, Map*, int); +void mathinit(void); +void mmuinit(void); +ulong* mmuwalk(ulong*, ulong, int); +void pcmenable(void); +void pcmintrenable(int, void (*)(Ureg*, void*), void*); +int pcmpin(int slot, int type); +void pcmpower(int, int); +int pcmpowered(int); +void pcmsetvcc(int, int); +void pcmsetvpp(int, int); +int pcmslotavail(int); +void procsave(Proc*); +void procsetup(Proc*); +void putdec(ulong); +void putmsr(ulong); +void puttwb(ulong); +ulong rmapalloc(RMap*, ulong, int, int); +void screeninit(void); +int screenprint(char*, ...); /* debugging */ +void screenputs(char*, int); +int segflush(void*, ulong); +void setpanic(void); +long spioutin(void*, long, void*); +void spireset(void); +ulong _tas(ulong*); +void trapinit(void); +void trapvec(void); +void uartinstall(void); +void uartspecial(int, int, Queue**, Queue**, int (*)(Queue*, int)); +void uartwait(void); /* debugging */ +void videoreset(void); +void videotest(void); +void wbflush(void); + +#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1])) +ulong getcallerpc(void*); + +#define KADDR(a) ((void*)((ulong)(a)|KZERO)) +#define PADDR(a) ((((ulong)(a)&KSEGM)!=KSEG0)?(ulong)(a):((ulong)(a)&~KZERO)) + +/* IBM bit field order */ +#define IBIT(b) ((ulong)1<<(31-(b))) +#define SIBIT(n) ((ushort)1<<(15-(n))) + +/* compatibility with inf2.1 */ diff --git a/os/rpcg/io.h b/os/rpcg/io.h new file mode 100644 index 00000000..30312c68 --- /dev/null +++ b/os/rpcg/io.h @@ -0,0 +1 @@ +#include "../mpc/800io.h" diff --git a/os/rpcg/main.c b/os/rpcg/main.c new file mode 100644 index 00000000..5251e074 --- /dev/null +++ b/os/rpcg/main.c @@ -0,0 +1,392 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "ureg.h" +#include "version.h" + +/* where b.com or qboot leaves configuration info */ +#define BOOTARGS ((char*)CONFADDR) +#define BOOTARGSLEN 1024 +#define MAXCONF 32 + +extern ulong kerndate; +extern int cflag; +int remotedebug; + +extern int main_pool_pcnt; +extern int heap_pool_pcnt; +extern int image_pool_pcnt; + +char bootargs[BOOTARGSLEN+1]; +char bootdisk[KNAMELEN]; +char *confname[MAXCONF]; +char *confval[MAXCONF]; +int nconf; + +extern void addconf(char *, char *); + +/* + * arguments passed to initcode and /boot + */ +char argbuf[128]; + +static void +options(void) +{ + long i, n; + char *cp, *line[MAXCONF], *p, *q; + + /* + * parse configuration args from bootstrap + */ + memmove(bootargs, BOOTARGS, BOOTARGSLEN); /* where b.com leaves its config */ + cp = bootargs; + cp[BOOTARGSLEN-1] = 0; + + /* + * Strip out '\r', change '\t' -> ' '. + */ + p = cp; + for(q = cp; *q; q++){ + if(*q == '\r') + continue; + if(*q == '\t') + *q = ' '; + *p++ = *q; + } + *p = 0; + + n = getfields(cp, line, MAXCONF, 1, "\n"); + for(i = 0; i < n; i++){ + if(*line[i] == '#') + continue; + cp = strchr(line[i], '='); + if(cp == 0) + continue; + *cp++ = 0; + confname[nconf] = line[i]; + confval[nconf] = cp; + nconf++; + } +} + +void +doc(char *m) +{ + USED(m); + print("%s...\n", m); uartwait(); +} + +static void +poolsizeinit(void) +{ + ulong nb; + + nb = conf.npage*BY2PG; + poolsize(mainmem, (nb*main_pool_pcnt)/100, 0); + poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0); + poolsize(imagmem, (nb*image_pool_pcnt)/100, 1); +} + +static void +serialconsole(void) +{ + char *p; + int port, baud; + + p = getconf("console"); + if(p == nil) + p = "0"; + if(p != nil && !remotedebug){ + port = strtol(p, nil, 0); + baud = 9600; + p = getconf("baud"); + if(p != nil){ + baud = strtol(p, nil, 0); + if(baud < 9600) + baud = 9600; + } + uartspecial(port, baud, &kbdq, &printq, kbdcr2nl); + } +} + +void +main(void) +{ + machinit(); + options(); + archinit(); + quotefmtinstall(); + confinit(); + cpminit(); + xinit(); + poolsizeinit(); + trapinit(); + mmuinit(); + printinit(); + uartinstall(); + serialconsole(); + doc("screeninit"); + screeninit(); + doc("kbdinit"); + kbdinit(); + doc("clockinit"); + clockinit(); + doc("procinit"); + procinit(); + cpuidprint(); + doc("links"); + links(); + doc("chandevreset"); + chandevreset(); + + eve = strdup("inferno"); + + print("\nInferno %s\n", VERSION); + print("Vita Nuova\n"); + print("conf %s (%lud) jit %d\n\n",conffile, kerndate, cflag); + + doc("userinit"); + userinit(); + doc("schedinit"); + schedinit(); +} + +void +machinit(void) +{ + int n; + + n = m->machno; + memset(m, 0, sizeof(Mach)); + m->machno = n; + m->mmask = 1<<m->machno; + m->iomem = KADDR(getimmr() & ~0xFFFF); + m->cputype = getpvr()>>16; + m->delayloop = 20000; /* initial estimate only; set by clockinit */ + m->speed = 50; /* initial estimate only; set by archinit */ +} + +void +init0(void) +{ + Osenv *o; + int i; + char buf[2*KNAMELEN]; + + up->nerrlab = 0; + + spllo(); + + if(waserror()) + panic("init0"); + /* + * These are o.k. because rootinit is null. + * Then early kproc's will have a root and dot. + */ + o = up->env; + o->pgrp->slash = namec("#/", Atodir, 0, 0); + cnameclose(o->pgrp->slash->name); + o->pgrp->slash->name = newcname("/"); + o->pgrp->dot = cclone(o->pgrp->slash); + + chandevinit(); + + if(!waserror()){ + ksetenv("cputype", "power", 0); + snprint(buf, sizeof(buf), "power %s", conffile); + ksetenv("terminal", buf, 0); + poperror(); + } + for(i = 0; i < nconf; i++) + if(confname[i][0] != '*'){ + if(!waserror()){ + ksetenv(confname[i], confval[i], 0); + poperror(); + } + } + + poperror(); + disinit("/osinit.dis"); +} + +void +userinit(void) +{ + Proc *p; + Osenv *o; + + p = newproc(); + o = p->env; + + o->fgrp = newfgrp(nil); + + o->pgrp = newpgrp(); + o->egrp = newegrp(); + kstrdup(&o->user, eve); + + strcpy(p->text, "interp"); + + /* + * Kernel Stack + */ + p->sched.pc = (ulong)init0; + p->sched.sp = (ulong)p->kstack+KSTACK; + + ready(p); +} + +Conf conf; + +void +addconf(char *name, char *val) +{ + if(nconf >= MAXCONF) + return; + confname[nconf] = name; + confval[nconf] = val; + nconf++; +} + +char* +getconf(char *name) +{ + int i; + + for(i = 0; i < nconf; i++) + if(cistrcmp(confname[i], name) == 0) + return confval[i]; + return 0; +} + +void +confinit(void) +{ + char *p; + int pcnt; + + if(p = getconf("*kernelpercent")) + pcnt = 100 - strtol(p, 0, 0); + else + pcnt = 0; + + conf.nscc = 4; + conf.smcuarts = 1<<0; /* SMC1 (usual console) */ + conf.sccuarts = 0; /* SCC2 not available by default (it's Ether) */ + + archconfinit(); + + conf.npage = conf.npage0 + conf.npage1; + if(pcnt < 10) + pcnt = 70; + conf.ialloc = (((conf.npage*(100-pcnt))/100)/2)*BY2PG; + + conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5; + conf.nmach = MAXMACH; +} + +void +exit(int ispanic) +{ + up = 0; + spllo(); + print("cpu %d exiting\n", m->machno); + + /* Shutdown running devices */ + chandevshutdown(); + + delay(1000); + splhi(); + if(ispanic) + for(;;); + archreboot(); +} + +void +reboot(void) +{ + exit(0); +} + +void +halt(void) +{ + print("cpu halted\n"); + microdelay(1000); + for(;;) + ; +} + +int +isaconfig(char *class, int ctlrno, ISAConf *isa) +{ + char cc[KNAMELEN], *p; + int i; + + snprint(cc, sizeof cc, "%s%d", class, ctlrno); + p = getconf(cc); + if(p == nil) + return 0; + + isa->nopt = tokenize(p, isa->opt, NISAOPT); + for(i = 0; i < isa->nopt; i++){ + p = isa->opt[i]; + if(cistrncmp(p, "type=", 5) == 0) + isa->type = p + 5; + else if(cistrncmp(p, "port=", 5) == 0) + isa->port = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "irq=", 4) == 0) + isa->irq = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "mem=", 4) == 0) + isa->mem = strtoul(p+4, &p, 0); + else if(cistrncmp(p, "size=", 5) == 0) + isa->size = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "freq=", 5) == 0) + isa->freq = strtoul(p+5, &p, 0); + else if(cistrncmp(p, "dma=", 4) == 0) + isa->dma = strtoul(p+4, &p, 0); + } + return 1; +} + +/* + * Save the mach dependent part of the process state. + */ +void +procsave(Proc*) +{ +} + +void +uartputs(char *s, int n) +{ +// screenputs(buf, n); + putstrn(s, n); + uartwait(); +} + +/* stubs */ +void +setfsr(ulong) +{ +} + +ulong +getfsr() +{ + return 0; +} + +void +setfcr(ulong) +{ +} + +ulong +getfcr() +{ + return 0; +} diff --git a/os/rpcg/mem.h b/os/rpcg/mem.h new file mode 100644 index 00000000..160569cc --- /dev/null +++ b/os/rpcg/mem.h @@ -0,0 +1,157 @@ +/* + * Memory and machine-specific definitions. Used in C and assembler. + */ + +/* + * Sizes + */ + +#define BI2BY 8 /* bits per byte */ +#define BI2WD 32 /* bits per word */ +#define BY2WD 4 /* bytes per word */ +#define BY2V 8 /* bytes per double word */ +#define BY2PG 4096 /* bytes per page */ +#define WD2PG (BY2PG/BY2WD) /* words per page */ +#define PGSHIFT 12 /* log(BY2PG) */ +#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1)) +#define PGROUND(s) ROUND(s, BY2PG) +#define CACHELINELOG 4 +#define CACHELINESZ (1<<CACHELINELOG) + +#define MAXMACH 1 /* max # cpus system can run */ +#define MACHSIZE BY2PG + +/* + * Time + */ +#define HZ 100 /* clock frequency */ +#define MS2HZ (1000/HZ) /* millisec per clock tick */ +#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ +#define MS2TK(t) ((t)/MS2HZ) /* milliseconds to ticks */ +#define MHz 1000000 + +/* + * MSR bits + */ + +#define POW 0x40000 /* enable power mgmt */ +#define TGPR 0x20000 /* GPR0-3 remapped; 603/603e specific */ +#define ILE 0x10000 /* interrupts little endian */ +#define EE 0x08000 /* enable external/decrementer interrupts */ +#define PR 0x04000 /* =1, user mode */ +#define FPE 0x02000 /* enable floating point */ +#define ME 0x01000 /* enable machine check exceptions */ +#define FE0 0x00800 +#define SE 0x00400 /* single-step trace */ +#define BE 0x00200 /* branch trace */ +#define FE1 0x00100 +#define MSR_IP 0x00040 /* =0, vector to nnnnn; =1, vector to FFFnnnnn */ +#define IR 0x00020 /* enable instruction address translation */ +#define DR 0x00010 /* enable data address translation */ +#define RI 0x00002 /* exception is recoverable */ +#define LE 0x00001 /* little endian mode */ + +#define KMSR (ME|FE0|FE1|FPE) +#define UMSR (KMSR|PR|EE|IR|DR) + +/* + * Magic registers + */ + +#define MACH 30 /* R30 is m-> */ +#define USER 29 /* R29 is up-> */ +#define IOMEMR 28 /* R28 will be iomem-> */ + +/* + * Fundamental addresses + */ + +#define UREGSIZE ((8+32)*4) + +/* + * MMU + */ + +/* L1 table entry and Mx_TWC flags */ +#define PTEVALID (1<<0) +#define PTEWT (1<<1) /* write through */ +#define PTE4K (0<<2) +#define PTE512K (1<<2) +#define PTE8MB (3<<2) +#define PTEG (1<<4) /* guarded */ + +/* L2 table entry and Mx_RPN flags (also PTEVALID) */ +#define PTECI (1<<1) /* cache inhibit */ +#define PTESH (1<<2) /* page is shared; ASID ignored */ +#define PTELPS (1<<3) /* large page size */ +#define PTEWRITE 0x9F0 + +/* TLB and MxEPN flag */ +#define TLBVALID (1<<9) + +/* + * Address spaces + */ + +#define KUSEG 0x00000000 +#define KSEG0 0x20000000 +#define KSEGM 0xE0000000 /* mask to check which seg */ + +#define KZERO KSEG0 /* base of kernel address space */ +#define KTZERO (KZERO+0x3000) /* first address in kernel text */ +#define KSTACK 8192 /* Size of kernel stack */ + +#define CONFADDR (KZERO|0x200000) /* where qboot leaves configuration info */ + +/* + * Exception codes (trap vectors) + */ +#define CRESET 0x01 +#define CMCHECK 0x02 +#define CDSI 0x03 +#define CISI 0x04 +#define CEI 0x05 +#define CALIGN 0x06 +#define CPROG 0x07 +#define CFPU 0x08 +#define CDEC 0x09 +#define CSYSCALL 0x0C +#define CTRACE 0x0D +#define CFPA 0x0E +/* rest are power-implementation dependent (8xx) */ +#define CEMU 0x10 +#define CIMISS 0x11 +#define CDMISS 0x12 +#define CITLBE 0x13 +#define CDTLBE 0x14 +#define CDBREAK 0x1C +#define CIBREAK 0x1D +#define CPBREAK 0x1E +#define CDPORT 0x1F + +/* + * MPC8xx physical addresses + */ + +/* those encouraged by rpx lite */ +#define PHYSDRAM 0x00000000 +#define PHYSNVRAM 0xFA000000 +#define PHYSIMM 0xFA200000 +#define PHYSBCSR 0xFA400000 +#define PHYSFLASH 0xFE000000 + +/* remaining ones are our choice */ +#define PHYSPCMCIA 0x04000000 +#define PCMCIALEN (8*MB) /* chosen to allow mapping by single TLB entry */ +#define ISAIO (KZERO|PHYSPCMCIA) /* for inb.s */ + +/* + * MPC8xx dual-ported CPM memory physical addresses + */ +#define PHYSDPRAM (PHYSIMM+0x2000) +#define DPLEN1 0x200 +#define DPLEN2 0x400 +#define DPLEN3 0x800 +#define DPBASE (PHYSDPRAM+DPLEN1) + +#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */ diff --git a/os/rpcg/mkfile b/os/rpcg/mkfile new file mode 100644 index 00000000..d0ac4390 --- /dev/null +++ b/os/rpcg/mkfile @@ -0,0 +1,108 @@ +SYSTARG=Inferno +OBJTYPE=power +<../../mkconfig + +#Configurable parameters + +CONF=rpcg #default configuration +CONFLIST=rpcg +KZERO=0x20003020 + +SYSTARG=$OSTARG +OBJTYPE=power +INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed +#INSTALLDIR=/$OBJTYPE + +#end configurable parameters + +<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system + +<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $ETHERS, $VGAS, $PORT, $MISC, $LIBS, $OTHERS + +OBJ=\ + l.$O\ + tlb.$O\ + nofp.$O\ + clock.$O\ + cpm.$O\ + faultpower.$O\ + fpi.$O\ + fpimem.$O\ + fpipower.$O\ + kbd.$O\ + main.$O\ + mmu.$O\ + rmap.$O\ + trap.$O\ + $CONF.root.$O\ + $IP\ + $DEVS\ + $ETHERS\ + $LINKS\ + $VGAS\ + $PORT\ + $MISC\ + $OTHERS\ + +LIBNAMES=${LIBS:%=lib%.a} + +HFILES=\ + mem.h\ + dat.h\ + fns.h\ + io.h\ + ../mpc/800io.h\ + ../mpc/screen.h\ + +CFLAGS=-wFV -I. -I../mpc -I../port -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp +KERNDATE=`{$NDATE} + +#default:V: i$CONF.sq +default:V: i$CONF + +i$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES + $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c + $LD -o $target -T$KZERO -l $OBJ $CONF.$O $LIBFILES + $KSIZE $target + +i$CONF.sq: i$CONF + sqz -w i$CONF >$target + +install:V: i$CONF # i$CONF.sq + cp i$CONF $INSTALLDIR/i$CONF + #cp i$CONF.sq $INSTALLDIR/i$CONF.sq + +uninstall:V: + rm -f $ROOT/$OBJDIR/bin/i$CONF + rm -f $ROOT/$OBJDIR/bin/i$CONF.sq + +<../port/portmkfile + +../init/$INIT.dis: ../init/$INIT.b + cd ../init; mk $INIT.dis + +clock.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h +devether.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h +faultpower.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h +main.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h +trap.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h + +devether.$O $ETHERS: ../mpc/etherif.h ../port/netif.h + +#$VGAS: screen.h vga.h +$IP devip.$O: ../ip/ip.h + +%.$O: ../mpc/%.c + $CC $CFLAGS -I. -I../mpc ../mpc/$stem.c + +%.$O: ../mpc/%.s + $AS -I. -I../mpc ../mpc/$stem.s + +clock.$O: clock.c + $CC $CFLAGS -I. clock.c + +devboot.$O: devboot.c + $CC $CFLAGS devboot.c + +devuart.$O: ../mpc/devuart.c + $CC $CFLAGS ../mpc/devuart.c diff --git a/os/rpcg/mmu.c b/os/rpcg/mmu.c new file mode 100644 index 00000000..c9cd758b --- /dev/null +++ b/os/rpcg/mmu.c @@ -0,0 +1,20 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +void +mmuinit(void) +{ + /* the l.s initial TLB settings do all that's required */ +} + +int +segflush(void *a, ulong n) +{ + /* flush dcache then invalidate icache */ + dcflush(a, n); + icflush(a, n); + return 0; +} diff --git a/os/rpcg/rpcg b/os/rpcg/rpcg new file mode 100644 index 00000000..c5c90ece --- /dev/null +++ b/os/rpcg/rpcg @@ -0,0 +1,122 @@ +# rpcg RPXLite +dev + root + cons archrpcg + env + mnt + pipe + prog + rtc + srv + dup + ssl + cap + + + ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum iprouter plan9 nullmedium pktmedium + ether netif netaux + uart + flash +# usb +# pcmcia cis +# ata inb + + ftl +# kfs chk kcon console dat dentry fcall fs fswren iobuf kfs sub uid +# kprof + +# vid i2c + i2c i2c + +ip + il + tcp + udp + ipifc + icmp + icmp6 + ipmux + +lib + interp + tk + draw + memlayer + memdraw + keyring + sec + mp + math + kern + +link + etherscc + ethermedium + flashamd29f0x0 +# flashcfi16 +# pppmedium ppp compress + +mod + sys +# draw +# tk + math + keyring + +port + alarm + alloc + allocb + chan + dev + dial + dis + discall + exception + exportfs + inferno + latin1 + nocache + nodynld + parse + pgrp + print + proc + qio + qlock + random + sysfile + taslock + xalloc + +code + int cflag = 0; + int consoleprint = 1; + int panicreset = 0; + int kernel_pool_pcnt = 10; + int main_pool_pcnt = 40; + int heap_pool_pcnt = 20; + int image_pool_pcnt = 40; + void screenputs(char*, int){} + void screeninit(void){} /* disabled until we've got one */ + +init + rpcginit + +root + /chan + /dev + /dis + /env + /fd / + /n + /net + /nvfs / + /prog + /icons + /osinit.dis + /dis/lib/auth.dis + /dis/lib/ssl.dis + /n/local / + /n/remote / + /nvfs/default /usr/inferno/keyring/default diff --git a/os/rpcg/tlb.s b/os/rpcg/tlb.s new file mode 100644 index 00000000..7005afbe --- /dev/null +++ b/os/rpcg/tlb.s @@ -0,0 +1,24 @@ +#include "mem.h" + +#define MB (1024*1024) + +/* + * TLB prototype entries, loaded once-for-all at startup, + * remaining unchanged thereafter. + * Limit the table to at most 8 entries to ensure + * it works on the 823 (other 8xx processors allow up to 32 TLB entries). + */ +#define TLBE(epn,rpn,twc) WORD $(epn); WORD $(twc); WORD $(rpn) + +TEXT tlbtab(SB), $-4 + + /* epn, rpn, twc */ + TLBE(KZERO|PHYSDRAM|TLBVALID, PHYSDRAM|PTEWRITE|PTELPS|PTESH|PTEVALID, PTE8MB|/*PTEWT|*/PTEVALID) /* DRAM, 8M */ + TLBE(KZERO|(PHYSDRAM+8*MB)|TLBVALID, (PHYSDRAM+8*MB)|PTEWRITE|PTELPS|PTESH|PTEVALID, PTE8MB|PTEVALID) /* DRAM, 8M */ + TLBE(KZERO|PHYSBCSR|TLBVALID, PHYSBCSR|PTEWRITE|PTESH|PTECI|PTEVALID, PTE4K|PTEWT|PTEVALID) /* Board CSR, 4K */ + TLBE(KZERO|PHYSIMM|TLBVALID, PHYSIMM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE4K|PTEWT|PTEVALID) /* IMMR, 16K */ + TLBE(KZERO|PHYSFLASH|TLBVALID, PHYSFLASH|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE8MB|PTEWT|PTEVALID) /* Flash, 8M */ + TLBE(KZERO|PHYSPCMCIA|TLBVALID, PHYSPCMCIA|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE8MB|PTEWT|PTEG|PTEVALID) /* PCMCIA, 8M */ + TLBE(KZERO|PHYSNVRAM|TLBVALID, PHYSNVRAM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE512K|PTEWT|PTEG|PTEVALID) /* NVRAM, 512K */ +TEXT tlbtabe(SB), $-4 + RETURN |
