M carrera/l.s => carrera/l.s +1 -0
@@ 103,6 103,7 @@ TEXT splhi(SB), $0
TEXT splx(SB), $0
MOVW R31, 12(R(MACH)) /* save PC in m->splpc */
+ /* fall though */
TEXT splxpc(SB), $0 /* for iunlock */
MOVW M(STATUS), R2
A mpc/clock.c => mpc/clock.c +152 -0
@@ 0,0 1,152 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.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 */
+long clkvv;
+ulong clkhigh;
+
+void
+addclock0link(void (*clock)(void))
+{
+ Clock0link *lp;
+
+ if((lp = malloc(sizeof(Clock0link))) == 0){
+ print("addclock0link: too many links\n");
+ return;
+ }
+ ilock(&clock0lock);
+ lp->clock = clock;
+ lp->link = clock0link;
+ clock0link = lp;
+ iunlock(&clock0lock);
+}
+
+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 = 4, /* system clock cycles per time base cycle */
+};
+
+static ulong clkreload;
+
+void
+clockinit(void)
+{
+ long x, est;
+
+ est = m->cpuhz/1000; /* initial estimate */
+ m->delayloop = est;
+ do {
+ x = gettbl();
+ delay(10);
+ x = gettbl() - x;
+ } while(x < 0);
+
+ /*
+ * fix count
+ */
+ m->delayloop = (m->delayloop*10*est)/(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 = (clkvv = -getdec());
+ if(v > clkreload)
+ clkhigh++;
+ if(v > clkreload/2){
+ if(v > clkreload)
+ m->ticks += v/clkreload;
+ v = 0;
+ }
+ putdec(clkreload-v);
+
+ m->ticks++;
+ if(m->ticks%MS2TK(1000) == 0)
+ m->bcsr[4] ^= DisableLamp;
+
+ if(up)
+ up->pc = ur->pc;
+
+ checkalarms();
+ if(m->machno == 0) {
+ if(kproftick != nil)
+ (*kproftick)(ur->pc);
+ lock(&clock0lock);
+ for(lp = clock0link; lp; lp = lp->link)
+ lp->clock();
+ unlock(&clock0lock);
+ }
+
+ if(up && up->state == Running){
+// if(up->type == Interp && tready())
+// ur->cr |= 1<<(31-31);
+ if(nrdy > 0)
+ sched();
+ }
+}
+
+void
+clockcheck(void)
+{
+ /* called by ../port/taslock.c: reset watchdog here, if it's enabled */
+}
+
+void
+clkprint(void)
+{
+ print("clkr=%ld clkvv=%ld clkhigh=%lud\n", clkreload, clkvv, clkhigh);
+ print("\n");
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ if(hz)
+ *hz = HZ;
+ return m->ticks;
+}
A mpc/cpm.c => mpc/cpm.c +563 -0
@@ 0,0 1,563 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ BDSIZE= 1024, /* IO memory reserved for buffer descriptors */
+ CPMSIZE= 1024, /* IO memory reserved for other uses */
+};
+
+static Map bdmapv[BDSIZE/sizeof(BD)];
+static RMap bdmap = {"buffer descriptors"};
+
+static Map cpmmapv[CPMSIZE/sizeof(ulong)];
+static RMap cpmmap = {"CPM memory"};
+
+static Lock cpmlock;
+
+static struct {
+ Lock;
+ ulong avail;
+} brgens;
+
+static struct {
+ Lock;
+ ulong clash; /* disable bits for mutually-exclusive options */
+ ulong active; /* disable bit for current owner, or 0 */
+ void (*stop)(void*);
+ void* arg;
+} scc2owner;
+
+static void i2cspireloc(void);
+
+/*
+ * initialise the communications processor module
+ * and associated device registers
+ */
+void
+cpminit(void)
+{
+ IMM *io;
+
+ io = m->iomem;
+ io->rccr = 0;
+ io->rmds = 0;
+ io->lccr &= ~1; /* disable LCD */
+ io->sdcr = 1;
+ io->pcint = 0; /* disable all port C interrupts */
+ io->pcso = 0;
+ io->pcdir =0;
+ io->pcpar = 0;
+ io->papar = 0;
+ io->padir = 0;
+ io->pbpar = 0;
+ io->pbdir = 0;
+ io->tgcr = 0x2222; /* reset timers, low-power stop */
+ eieio();
+
+ for(io->cpcr = 0x8001; io->cpcr & 1;) /* reset all CPM channels */
+ eieio();
+
+ mapinit(&bdmap, bdmapv, sizeof(bdmapv));
+ mapfree(&bdmap, DPBASE, BDSIZE);
+ mapinit(&cpmmap, cpmmapv, sizeof(cpmmapv));
+ mapfree(&cpmmap, DPBASE+BDSIZE, CPMSIZE);
+
+ if(m->cputype == 0x50 && (getimmr() & 0xFFFF) <= 0x2001)
+ brgens.avail = 0x3;
+ else
+ brgens.avail = 0xF;
+
+ scc2owner.clash = DisableEther|DisableIR|DisableRS232b;
+
+ i2cspireloc();
+}
+
+/*
+ * issue a request to a CPM device
+ */
+void
+cpmop(int op, int cno, int param)
+{
+ IMM *io;
+
+ ilock(&cpmlock);
+ io = m->iomem;
+ while(io->cpcr & 1)
+ eieio();
+ io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
+ eieio();
+ while(io->cpcr & 1)
+ eieio();
+ iunlock(&cpmlock);
+}
+
+/*
+ * lock the shared IO memory and return a reference to it
+ */
+IMM*
+ioplock(void)
+{
+ ilock(&cpmlock);
+ return m->iomem;
+}
+
+/*
+ * release the lock on the shared IO memory
+ */
+void
+iopunlock(void)
+{
+ eieio();
+ iunlock(&cpmlock);
+}
+
+/*
+ * connect SCCx clocks in NSMI mode (x=1 for USB)
+ */
+void
+sccnmsi(int x, int rcs, int tcs)
+{
+ IMM *io;
+ ulong v;
+ int sh;
+
+ sh = (x-1)*8; /* each SCCx field in sicr is 8 bits */
+ v = (((rcs&7)<<3) | (tcs&7)) << sh;
+ io = ioplock();
+ io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
+ iopunlock();
+}
+
+/*
+ * request or grab (if force!=0) the use of SCC2
+ * for the mode (uart, ether, etc) defined by the enable bits.
+ * the `stop' function is invoked with the given argument
+ * when the device is lost to another driver.
+ */
+int
+scc2claim(int force, ulong enable, void (*stop)(void*), void *arg)
+{
+ ulong clash;
+
+ clash = scc2owner.clash & ~enable;
+ ilock(&scc2owner);
+ if(~m->bcsr[1] & clash){
+ if(!force){
+ iunlock(&scc2owner);
+ return 0;
+ }
+ /* notify current owner */
+ if(scc2owner.stop)
+ scc2owner.stop(scc2owner.arg);
+ m->bcsr[1] |= clash;
+ }
+ scc2owner.stop = stop;
+ scc2owner.arg = arg;
+ scc2owner.active = enable;
+ m->bcsr[1] &= ~enable; /* the bits are active low */
+ iunlock(&scc2owner);
+ /* beware: someone else can claim it during the `successful' return */
+ return 1;
+}
+
+/*
+ * if SCC2 is currently enabled, shut it down
+ */
+void
+scc2stop(void *a)
+{
+ SCC *scc;
+
+ scc = a;
+ if(scc->gsmrl & (3<<4)){
+ cpmop(GracefulStopTx, SCC2ID, 0);
+ cpmop(CloseRxBD, SCC2ID, 0);
+ delay(1);
+ scc->gsmrl &= ~(3<<4); /* disable current use */
+ m->bcsr[1] |= scc2owner.clash;
+ }
+}
+
+/*
+ * yield up control of SCC2
+ */
+void
+scc2free(void)
+{
+ ilock(&scc2owner);
+ m->bcsr[1] |= scc2owner.active;
+ scc2owner.active = 0;
+ iunlock(&scc2owner);
+}
+
+/*
+ * allocate a buffer descriptor
+ */
+BD *
+bdalloc(int n)
+{
+ ulong a;
+
+ a = rmapalloc(&bdmap, 0, n*sizeof(BD), sizeof(BD));
+ if(a == 0)
+ panic("bdalloc");
+ return KADDR(a);
+}
+
+/*
+ * free a buffer descriptor
+ */
+void
+bdfree(BD *b, int n)
+{
+ if(b){
+ eieio();
+ mapfree(&bdmap, PADDR(b), n*sizeof(BD));
+ }
+}
+
+/*
+ * allocate memory from the shared IO memory space
+ */
+void *
+cpmalloc(int n, int align)
+{
+ ulong a;
+
+ a = rmapalloc(&cpmmap, 0, n, align);
+ if(a == 0)
+ panic("cpmalloc");
+ return KADDR(a);
+}
+
+/*
+ * free previously allocated shared memory
+ */
+void
+cpmfree(void *p, int n)
+{
+ if(p != nil && n > 0){
+ eieio();
+ mapfree(&cpmmap, PADDR(p), n);
+ }
+}
+
+/*
+ * allocate a baud rate generator, returning its index
+ * (or -1 if none is available)
+ */
+int
+brgalloc(void)
+{
+ int n;
+
+ lock(&brgens);
+ for(n=0; brgens.avail!=0; n++)
+ if(brgens.avail & (1<<n)){
+ brgens.avail &= ~(1<<n);
+ unlock(&brgens);
+ return n;
+ }
+ unlock(&brgens);
+ return -1;
+}
+
+/*
+ * free a previously allocated baud rate generator
+ */
+void
+brgfree(int n)
+{
+ if(n >= 0){
+ if(n > 3 || brgens.avail & (1<<n))
+ panic("brgfree");
+ lock(&brgens);
+ brgens.avail |= 1 << n;
+ unlock(&brgens);
+ }
+}
+
+/*
+ * return a value suitable for loading into a baud rate
+ * generator to produce the given rate if the generator
+ * is prescaled by the given amount (typically 16).
+ * the value must be or'd with BaudEnable to start the generator.
+ */
+ulong
+baudgen(int rate, int scale)
+{
+ int d;
+
+ rate *= scale;
+ d = (2*m->cpuhz+rate)/(2*rate) - 1;
+ if(d < 0)
+ d = 0;
+ if(d >= (1<<12))
+ return ((d+15)>>(4-1))|1; /* divider too big: enable prescale by 16 */
+ return d<<1;
+}
+
+/*
+ * initialise receive and transmit buffer rings.
+ */
+int
+ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
+{
+ int i, x;
+
+ /* the ring entries must be aligned on sizeof(BD) boundaries */
+ r->nrdre = nrdre;
+ if(r->rdr == nil)
+ r->rdr = bdalloc(nrdre);
+ if(r->rrb == nil)
+ r->rrb = malloc(nrdre*bufsize);
+ dcflush(r->rrb, nrdre*bufsize);
+ if(r->rdr == nil || r->rrb == nil)
+ return -1;
+ x = PADDR(r->rrb);
+ for(i = 0; i < nrdre; i++){
+ r->rdr[i].length = 0;
+ r->rdr[i].addr = x;
+ r->rdr[i].status = BDEmpty|BDInt;
+ x += bufsize;
+ }
+ r->rdr[i-1].status |= BDWrap;
+ r->rdrx = 0;
+
+ r->ntdre = ntdre;
+ if(r->tdr == nil)
+ r->tdr = bdalloc(ntdre);
+ if(r->txb == nil)
+ r->txb = malloc(ntdre*sizeof(Block*));
+ if(r->tdr == nil || r->txb == nil)
+ return -1;
+ for(i = 0; i < ntdre; i++){
+ r->txb[i] = nil;
+ r->tdr[i].addr = 0;
+ r->tdr[i].length = 0;
+ r->tdr[i].status = 0;
+ }
+ r->tdr[i-1].status |= BDWrap;
+ r->tdrh = 0;
+ r->tdri = 0;
+ r->ntq = 0;
+ return 0;
+}
+
+/*
+ * Allocate a new parameter block for I2C or SPI,
+ * and plant a pointer to it for the microcode,
+ * returning the kernel address.
+ * See motorola errata and microcode package:
+ * the design botch is that the parameters for the SCC2 ethernet overlap the
+ * SPI/I2C parameter space; this compensates by relocating the latter.
+ * This routine may be used iff i2cspireloc is used (and it is, above).
+ */
+void*
+cpmparam(ulong olda, int nb)
+{
+ void *p;
+
+ if(olda < INTMEM)
+ olda += INTMEM;
+ if(olda != SPIP && olda != I2CP)
+ return KADDR(olda);
+ p = cpmalloc(nb, 32); /* ``RPBASE must be multiple of 32'' */
+ if(p == nil)
+ return p;
+ *(ushort*)KADDR(olda+0x2C) = PADDR(p); /* set RPBASE */
+ eieio();
+ return p;
+}
+
+/*
+ * I2C/SPI microcode package from Motorola
+ * (to relocate I2C/SPI parameters), which was distributed
+ * on their web site in S-record format.
+ *
+ * May 1998
+ */
+
+/*S00600004844521B*/
+static ulong ubase1 = 0x2000;
+static ulong ucode1[] = {
+ /* #02202000 */ 0x7FFFEFD9,
+ /* #02202004 */ 0x3FFD0000,
+ /* #02202008 */ 0x7FFB49F7,
+ /* #0220200C */ 0x7FF90000,
+ /* #02202010 */ 0x5FEFADF7,
+ /* #02202014 */ 0x5F89ADF7,
+ /* #02202018 */ 0x5FEFAFF7,
+ /* #0220201C */ 0x5F89AFF7,
+ /* #02202020 */ 0x3A9CFBC8,
+ /* #02202024 */ 0xE7C0EDF0,
+ /* #02202028 */ 0x77C1E1BB,
+ /* #0220202C */ 0xF4DC7F1D,
+ /* #02202030 */ 0xABAD932F,
+ /* #02202034 */ 0x4E08FDCF,
+ /* #02202038 */ 0x6E0FAFF8,
+ /* #0220203C */ 0x7CCF76CF,
+ /* #02202040 */ 0xFD1FF9CF,
+ /* #02202044 */ 0xABF88DC6,
+ /* #02202048 */ 0xAB5679F7,
+ /* #0220204C */ 0xB0937383,
+ /* #02202050 */ 0xDFCE79F7,
+ /* #02202054 */ 0xB091E6BB,
+ /* #02202058 */ 0xE5BBE74F,
+ /* #0220205C */ 0xB3FA6F0F,
+ /* #02202060 */ 0x6FFB76CE,
+ /* #02202064 */ 0xEE0DF9CF,
+ /* #02202068 */ 0x2BFBEFEF,
+ /* #0220206C */ 0xCFEEF9CF,
+ /* #02202070 */ 0x76CEAD24,
+ /* #02202074 */ 0x90B2DF9A,
+ /* #02202078 */ 0x7FDDD0BF,
+ /* #0220207C */ 0x4BF847FD,
+ /* #02202080 */ 0x7CCF76CE,
+ /* #02202084 */ 0xCFEF7E1F,
+ /* #02202088 */ 0x7F1D7DFD,
+ /* #0220208C */ 0xF0B6EF71,
+ /* #02202090 */ 0x7FC177C1,
+ /* #02202094 */ 0xFBC86079,
+ /* #02202098 */ 0xE722FBC8,
+ /* #0220209C */ 0x5FFFDFFF,
+ /* #022020A0 */ 0x5FB2FFFB,
+ /* #022020A4 */ 0xFBC8F3C8,
+ /* #022020A8 */ 0x94A67F01,
+ /* #022020AC */ 0x7F1D5F39,
+ /* #022020B0 */ 0xAFE85F5E,
+ /* #022020B4 */ 0xFFDFDF96,
+ /* #022020B8 */ 0xCB9FAF7D,
+ /* #022020BC */ 0x5FC1AFED,
+ /* #022020C0 */ 0x8C1C5FC1,
+ /* #022020C4 */ 0xAFDD5FC3,
+ /* #022020C8 */ 0xDF9A7EFD,
+ /* #022020CC */ 0xB0B25FB2,
+ /* #022020D0 */ 0xFFFEABAD,
+ /* #022020D4 */ 0x5FB2FFFE,
+ /* #022020D8 */ 0x5FCE600B,
+ /* #022020DC */ 0xE6BB600B,
+ /* #022020E0 */ 0x5FCEDFC6,
+ /* #022020E4 */ 0x27FBEFDF,
+ /* #022020E8 */ 0x5FC8CFDE,
+ /* #022020EC */ 0x3A9CE7C0,
+ /* #022020F0 */ 0xEDF0F3C8,
+ /* #022020F4 */ 0x7F0154CD,
+ /* #022020F8 */ 0x7F1D2D3D,
+ /* #022020FC */ 0x363A7570,
+ /* #02202100 */ 0x7E0AF1CE,
+ /* #02202104 */ 0x37EF2E68,
+ /* #02202108 */ 0x7FEE10EC,
+ /* #0220210C */ 0xADF8EFDE,
+ /* #02202110 */ 0xCFEAE52F,
+ /* #02202114 */ 0x7D0FE12B,
+ /* #02202118 */ 0xF1CE5F65,
+ /* #0220211C */ 0x7E0A4DF8,
+ /* #02202120 */ 0xCFEA5F72,
+ /* #02202124 */ 0x7D0BEFEE,
+ /* #02202128 */ 0xCFEA5F74,
+ /* #0220212C */ 0xE522EFDE,
+ /* #02202130 */ 0x5F74CFDA,
+ /* #02202134 */ 0x0B627385,
+ /* #02202138 */ 0xDF627E0A,
+ /* #0220213C */ 0x30D8145B,
+ /* #02202140 */ 0xBFFFF3C8,
+ /* #02202144 */ 0x5FFFDFFF,
+ /* #02202148 */ 0xA7F85F5E,
+ /* #0220214C */ 0xBFFE7F7D,
+ /* #02202150 */ 0x10D31450,
+ /* #02202154 */ 0x5F36BFFF,
+ /* #02202158 */ 0xAF785F5E,
+ /* #0220215C */ 0xBFFDA7F8,
+ /* #02202160 */ 0x5F36BFFE,
+ /* #02202164 */ 0x77FD30C0,
+ /* #02202168 */ 0x4E08FDCF,
+ /* #0220216C */ 0xE5FF6E0F,
+ /* #02202170 */ 0xAFF87E1F,
+ /* #02202174 */ 0x7E0FFD1F,
+ /* #02202178 */ 0xF1CF5F1B,
+ /* #0220217C */ 0xABF80D5E,
+ /* #02202180 */ 0x5F5EFFEF,
+ /* #02202184 */ 0x79F730A2,
+ /* #02202188 */ 0xAFDD5F34,
+ /* #0220218C */ 0x47F85F34,
+ /* #02202190 */ 0xAFED7FDD,
+ /* #02202194 */ 0x50B24978,
+ /* #02202198 */ 0x47FD7F1D,
+ /* #0220219C */ 0x7DFD70AD,
+ /* #022021A0 */ 0xEF717EC1,
+ /* #022021A4 */ 0x6BA47F01,
+ /* #022021A8 */ 0x2D267EFD,
+ /* #022021AC */ 0x30DE5F5E,
+ /* #022021B0 */ 0xFFFD5F5E,
+ /* #022021B4 */ 0xFFEF5F5E,
+ /* #022021B8 */ 0xFFDF0CA0,
+ /* #022021BC */ 0xAFED0A9E,
+ /* #022021C0 */ 0xAFDD0C3A,
+ /* #022021C4 */ 0x5F3AAFBD,
+ /* #022021C8 */ 0x7FBDB082,
+ /* #022021CC */ 0x5F8247F8,
+};
+
+/*S00600004844521B*/
+static ulong ubase2 = 0x2F00;
+static ulong ucode2[] = {
+ /* #02202F00 */ 0x3E303430,
+ /* #02202F04 */ 0x34343737,
+ /* #02202F08 */ 0xABF7BF9B,
+ /* #02202F0C */ 0x994B4FBD,
+ /* #02202F10 */ 0xBD599493,
+ /* #02202F14 */ 0x349FFF37,
+ /* #02202F18 */ 0xFB9B177D,
+ /* #02202F1C */ 0xD9936956,
+ /* #02202F20 */ 0xBBFDD697,
+ /* #02202F24 */ 0xBDD2FD11,
+ /* #02202F28 */ 0x31DB9BB3,
+ /* #02202F2C */ 0x63139637,
+ /* #02202F30 */ 0x93733693,
+ /* #02202F34 */ 0x193137F7,
+ /* #02202F38 */ 0x331737AF,
+ /* #02202F3C */ 0x7BB9B999,
+ /* #02202F40 */ 0xBB197957,
+ /* #02202F44 */ 0x7FDFD3D5,
+ /* #02202F48 */ 0x73B773F7,
+ /* #02202F4C */ 0x37933B99,
+ /* #02202F50 */ 0x1D115316,
+ /* #02202F54 */ 0x99315315,
+ /* #02202F58 */ 0x31694BF4,
+ /* #02202F5C */ 0xFBDBD359,
+ /* #02202F60 */ 0x31497353,
+ /* #02202F64 */ 0x76956D69,
+ /* #02202F68 */ 0x7B9D9693,
+ /* #02202F6C */ 0x13131979,
+ /* #02202F70 */ 0x79376935,
+};
+
+/*
+ * compensate for chip design botch by installing
+ * microcode to relocate I2C and SPI parameters away
+ * from the ethernet parameters
+ */
+static void
+i2cspireloc(void)
+{
+ IMM *io;
+ static int done;
+
+ if(done)
+ return;
+ io = m->iomem;
+ io->rccr &= ~3;
+ memmove((uchar*)m->iomem+ubase1, ucode1, sizeof(ucode1));
+ memmove((uchar*)m->iomem+ubase2, ucode2, sizeof(ucode2));
+ io->rctr1 = 0x802a; /* relocate SPI */
+ io->rctr2 = 0x8028; /* relocate SPI */
+ io->rctr3 = 0x802e; /* relocate I2C */
+ io->rctr4 = 0x802c; /* relocate I2C */
+ io->rccr |= 1;
+ done = 1;
+}
A mpc/dat.h => mpc/dat.h +217 -0
@@ 0,0 1,217 @@
+typedef struct Conf Conf;
+typedef struct FPsave FPsave;
+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 Notsave Notsave;
+typedef struct PMMU PMMU;
+typedef struct Map Map;
+typedef struct PCArch PCArch;
+typedef struct Proc Proc;
+typedef struct RMap RMap;
+typedef struct Ureg Ureg;
+
+#define MACHP(n) (n==0? &mach0 : *(Mach**)0)
+
+/*
+ * parameters for sysproc.c
+ */
+#define AOUT_MAGIC (Q_MAGIC)
+
+
+struct Lock
+{
+ ulong key;
+ ulong pc;
+ ulong sr;
+ Proc *p;
+ ushort isilock;
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+/*
+ * things saved in the Proc structure during a notify
+ */
+struct Notsave
+{
+ ulong UNUSED;
+};
+
+/*
+ * MMU stuff in proc
+ */
+#define NCOLOR 1
+struct PMMU
+{
+ ulong UNUSED;
+};
+
+/*
+ * FPsave.status
+ */
+enum
+{
+ FPinit,
+ FPactive,
+ FPinactive,
+};
+
+/*
+ * This structure must agree with fpsave and fprestore asm routines
+ */
+struct FPsave
+{
+ double fpreg[32];
+ union {
+ double fpscrd;
+ struct {
+ ulong pad;
+ ulong fpscr;
+ };
+ };
+ int fpistate; /* emulated fp */
+ ulong emreg[32][3]; /* emulated fp */
+};
+
+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 upages; /* user page pool */
+ ulong nimage; /* number of page cache image headers */
+ ulong nswap; /* number of swap pages */
+ int nswppo; /* max # of pageouts per segment pass */
+ ulong base0; /* base of bank 0 */
+ ulong base1; /* base of bank 1 */
+ ulong copymode; /* 0 is copy on write, 1 is copy on reference */
+ ulong ialloc; /* max interrupt time allocation in bytes */
+ ulong interps; /* number of interpreter processes */
+ ulong pipeqsize; /* size in bytes of pipe queues */
+};
+
+#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 */
+
+ ulong fairness; /* for runproc */
+
+ int tlbfault;
+ int tlbpurge;
+ int pfault;
+ int cs;
+ int syscall;
+ int load;
+ int intr;
+ vlong fastclock; /* last sampled value */
+ int flushmmu; /* make current proc flush it's mmu state */
+
+ /* MUST BE LAST */
+ int stack[1];
+};
+extern Mach mach0;
+
+/*
+ * Fake kmap
+ */
+typedef void KMap;
+#define VA(k) ((ulong)(k))
+#define kmap(p) (KMap*)((p)->pa)
+#define kunmap(k)
+
+/*
+ * routines for things outside the PowerPC model
+ */
+struct PCArch
+{
+ char* id;
+ int (*ident)(void); /* this should be in the model */
+ void (*reset)(void); /* this should be in the model */
+ int (*serialpower)(int); /* 1 == on, 0 == off */
+ int (*modempower)(int); /* 1 == on, 0 == off */
+
+ void (*intrinit)(void);
+ int (*intrenable)(int, int, Irqctl*);
+
+ void (*clockenable)(void);
+};
+
+/*
+ * a parsed .ini line
+ */
+#define ISAOPTLEN 16
+#define NISAOPT 8
+
+struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+ ulong mem;
+ int dma;
+ ulong size;
+ ulong freq;
+ uchar bus;
+
+ int nopt;
+ char opt[NISAOPT][ISAOPTLEN];
+};
+
+struct Map {
+ int size;
+ ulong addr;
+};
+
+struct RMap {
+ char* name;
+ Map* map;
+ Map* mapend;
+
+ Lock;
+};
+
+struct
+{
+ Lock;
+ short machs;
+ short exiting;
+ short ispanic;
+}active;
+
+extern register Mach *m;
+extern register Proc *up;
+
A mpc/devether.c => mpc/devether.c +447 -0
@@ 0,0 1,447 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+#include "etherif.h"
+
+static Ether *etherxx[MaxEther];
+
+void ethermediumlink(void);
+
+Chan*
+etherattach(char* spec)
+{
+ ulong ctlrno;
+ char *p;
+ Chan *chan;
+
+ ctlrno = 0;
+ if(spec && *spec){
+ ctlrno = strtoul(spec, &p, 0);
+ if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
+ error(Ebadarg);
+ }
+ if(etherxx[ctlrno] == 0)
+ error(Enodev);
+
+ chan = devattach('l', spec);
+ chan->dev = ctlrno;
+ if(etherxx[ctlrno]->attach)
+ etherxx[ctlrno]->attach(etherxx[ctlrno]);
+ return chan;
+}
+
+static void
+etherdetach(void)
+{
+ Ether **ether;
+
+ ether = etherxx;
+ while(*ether){
+ if((*ether)->detach)
+ (*ether)->detach(*ether);
+ ether++;
+ }
+}
+
+static int
+etherwalk(Chan* chan, char* name)
+{
+ return netifwalk(etherxx[chan->dev], chan, name);
+}
+
+static void
+etherstat(Chan* chan, char* dp)
+{
+ netifstat(etherxx[chan->dev], chan, dp);
+}
+
+static Chan*
+etheropen(Chan* chan, int omode)
+{
+ return netifopen(etherxx[chan->dev], chan, omode);
+}
+
+static void
+ethercreate(Chan*, char*, int, ulong)
+{
+}
+
+static void
+etherclose(Chan* chan)
+{
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ netifclose(ether, chan);
+ if(ether->closed)
+ ether->closed(ether);
+}
+
+static long
+etherread(Chan* chan, void* buf, long n, vlong offset)
+{
+ Ether *ether;
+
+ ether = etherxx[chan->dev];
+ if((chan->qid.path & CHDIR) == 0 && ether->ifstat){
+ /*
+ * With some controllers it is necessary to reach
+ * into the chip to extract statistics.
+ */
+ if(NETTYPE(chan->qid.path) == Nifstatqid)
+ return ether->ifstat(ether, buf, n, offset);
+ else if(NETTYPE(chan->qid.path) == Nstatqid)
+ ether->ifstat(ether, buf, 0, offset);
+ }
+
+ return netifread(ether, chan, buf, n, offset);
+}
+
+static Block*
+etherbread(Chan* chan, long n, ulong offset)
+{
+ return netifbread(etherxx[chan->dev], chan, n, offset);
+}
+
+static void
+etherremove(Chan*)
+{
+}
+
+static void
+etherwstat(Chan* chan, char* dp)
+{
+ netifwstat(etherxx[chan->dev], chan, dp);
+}
+
+static void
+etherrtrace(Netfile* f, Etherpkt* pkt, int len)
+{
+ int i, n;
+ Block *bp;
+
+ if(qwindow(f->in) <= 0)
+ return;
+ if(len > 64)
+ n = 64;
+ else
+ n = len;
+ bp = iallocb(n);
+ if(bp == 0)
+ return;
+ memmove(bp->wp, pkt->d, n);
+ i = TK2MS(MACHP(0)->ticks);
+ bp->wp[58] = len>>8;
+ bp->wp[59] = len;
+ bp->wp[60] = i>>24;
+ bp->wp[61] = i>>16;
+ bp->wp[62] = i>>8;
+ bp->wp[63] = i;
+ bp->wp += 64;
+ qpass(f->in, bp);
+}
+
+Block*
+etheriq(Ether* ether, Block* bp, int freebp)
+{
+ Etherpkt *pkt;
+ ushort type;
+ int len;
+ Netfile **ep, *f, **fp, *fx;
+ Block *xbp;
+
+ ether->inpackets++;
+
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ type = (pkt->type[0]<<8)|pkt->type[1];
+ fx = 0;
+ ep = ðer->f[Ntypes];
+
+ /* check for valid multcast addresses */
+ if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
+ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
+ if(freebp){
+ freeb(bp);
+ bp = 0;
+ }
+ return bp;
+ }
+ }
+
+ /*
+ * Multiplex the packet to all the connections which want it.
+ * If the packet is not to be used subsequently (freebp != 0),
+ * attempt to simply pass it into one of the connections, thereby
+ * saving a copy of the data (usual case hopefully).
+ */
+ for(fp = ether->f; fp < ep; fp++){
+ if((f = *fp) && (f->type == type || f->type < 0)){
+ if(f->type > -2){
+ if(freebp && fx == 0)
+ fx = f;
+ else if(xbp = iallocb(len)){
+ memmove(xbp->wp, pkt, len);
+ xbp->wp += len;
+ qpass(f->in, xbp);
+ }
+ else
+ ether->soverflows++;
+ }
+ else
+ etherrtrace(f, pkt, len);
+ }
+ }
+
+ if(fx){
+ qpass(fx->in, bp);
+ return 0;
+ }
+ if(freebp){
+ freeb(bp);
+ return 0;
+ }
+
+ return bp;
+}
+
+static int
+etheroq(Ether* ether, Block* bp)
+{
+ int len, loopback, s;
+ Etherpkt *pkt;
+
+ ether->outpackets++;
+
+ /*
+ * Check if the packet has to be placed back onto the input queue,
+ * i.e. if it's a loopback or broadcast packet or the interface is
+ * in promiscuous mode.
+ * If it's a loopback packet indicate to etheriq that the data isn't
+ * needed and return, etheriq will pass-on or free the block.
+ */
+ pkt = (Etherpkt*)bp->rp;
+ len = BLEN(bp);
+ loopback = (memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0);
+ if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
+ s = splhi();
+ etheriq(ether, bp, loopback);
+ splx(s);
+ }
+
+ if(!loopback){
+ qbwrite(ether->oq, bp);
+ ether->transmit(ether);
+ }
+
+ return len;
+}
+
+static long
+etherwrite(Chan* chan, void* buf, long n, vlong)
+{
+ Ether *ether;
+ Block *bp;
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid)
+ return netifwrite(ether, chan, buf, n);
+
+ if(n > ETHERMAXTU)
+ error(Etoobig);
+// if(n < ETHERMINTU)
+// error(Etoosmall);
+
+ bp = allocb(n);
+ if(waserror()){
+ freeb(bp);
+ nexterror();
+ }
+ memmove(bp->rp, buf, n);
+ memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
+ poperror();
+ bp->wp += n;
+
+ return etheroq(ether, bp);
+}
+
+static long
+etherbwrite(Chan* chan, Block* bp, ulong)
+{
+ Ether *ether;
+ long n;
+
+ n = BLEN(bp);
+
+ ether = etherxx[chan->dev];
+ if(NETTYPE(chan->qid.path) != Ndataqid){
+ n = netifwrite(ether, chan, bp->rp, n);
+ freeb(bp);
+ return n;
+ }
+
+ if(n > ETHERMAXTU){
+ freeb(bp);
+ error(Ebadarg);
+ }
+
+ return etheroq(ether, bp);
+}
+
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+static void
+etherreset(void)
+{
+ Ether *ether;
+ int i, n, ctlrno;
+ char name[NAMELEN], buf[128];
+
+ //ethermediumlink();
+ for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
+ if(ether == 0)
+ ether = malloc(sizeof(Ether));
+ memset(ether, 0, sizeof(Ether));
+ ether->ctlrno = ctlrno;
+ ether->tbdf = BUSUNKNOWN;
+ ether->mbps = 10;
+ if(isaconfig("ether", ctlrno, ether) == 0)
+ continue;
+ for(n = 0; cards[n].type; n++){
+ if(cistrcmp(cards[n].type, ether->type))
+ continue;
+ for(i = 0; i < ether->nopt; i++){
+ if(strncmp(ether->opt[i], "ea=", 3))
+ continue;
+ if(parseether(ether->ea, ðer->opt[i][3]) == -1)
+ memset(ether->ea, 0, Eaddrlen);
+ }
+ if(cards[n].reset(ether))
+ break;
+
+ intrenable(ether->irq, ether->interrupt, ether, ether->tbdf);
+
+ i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
+ ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
+ if(ether->mem)
+ i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
+ if(ether->size)
+ i += sprint(buf+i, " size 0x%luX", ether->size);
+ i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ sprint(buf+i, "\n");
+ print(buf);
+
+ snprint(name, sizeof(name), "ether%d", ctlrno);
+ if(ether->mbps == 100){
+ netifinit(ether, name, Ntypes, 256*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(256*1024, 1, 0, 0);
+ }
+ else{
+ netifinit(ether, name, Ntypes, 32*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(64*1024, 1, 0, 0);
+ }
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ etherxx[ctlrno] = ether;
+ ether = 0;
+ break;
+ }
+ }
+ if(ether)
+ free(ether);
+}
+
+#define POLY 0xedb88320
+
+/* really slow 32 bit crc for ethers */
+ulong
+ethercrc(uchar *p, int len)
+{
+ int i, j;
+ ulong crc, b;
+
+ crc = 0xffffffff;
+ for(i = 0; i < len; i++){
+ b = *p++;
+ for(j = 0; j < 8; j++){
+ crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
+ b >>= 1;
+ }
+ }
+ return crc;
+}
+
+Dev etherdevtab = {
+ 'l',
+ "ether",
+
+ etherreset,
+ devinit,
+ etherattach,
+ /*etherdetach,*/
+ devclone,
+ etherwalk,
+ etherstat,
+ etheropen,
+ ethercreate,
+ etherclose,
+ etherread,
+ etherbread,
+ etherwrite,
+ etherbwrite,
+ etherremove,
+ etherwstat,
+};
A mpc/devrtc.c => mpc/devrtc.c +180 -0
@@ 0,0 1,180 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#include "io.h"
+
+/*
+ * MPC8xx real time clock
+ * FADS board option switch
+ * interrupt statistics
+ */
+
+enum{
+ Qrtc = 1,
+ Qswitch,
+ Qintstat,
+
+ /* sccr */
+ RTDIV= 1<<24,
+ RTSEL= 1<<23,
+
+ /* rtcsc */
+ RTE= 1<<0,
+ R38K= 1<<4,
+};
+
+static QLock rtclock; /* mutex on clock operations */
+
+static Dirtab rtcdir[]={
+ "rtc", {Qrtc, 0}, 12, 0666,
+ "switch", {Qswitch, 0}, 0, 0444,
+ "intstat", {Qintstat, 0}, 0, 0444,
+};
+#define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0]))
+
+static void
+rtcreset(void)
+{
+ IMM *io;
+ int n;
+
+ io = m->iomem;
+ io->rtcsck = KEEP_ALIVE_KEY;
+ n = (RTClevel<<8)|RTE;
+ if(m->oscclk == 5)
+ n |= R38K;
+ io->rtcsc = n;
+ io->rtcsck = ~KEEP_ALIVE_KEY;
+print("sccr=#%8.8lux plprcr=#%8.8lux\n", io->sccr, io->plprcr);
+}
+
+static Chan*
+rtcattach(char *spec)
+{
+ return devattach('r', spec);
+}
+
+static int
+rtcwalk(Chan *c, char *name)
+{
+ return devwalk(c, name, rtcdir, NRTC, devgen);
+}
+
+static void
+rtcstat(Chan *c, char *dp)
+{
+ devstat(c, dp, rtcdir, NRTC, devgen);
+}
+
+static Chan*
+rtcopen(Chan *c, int omode)
+{
+ omode = openmode(omode);
+ switch(c->qid.path){
+ case Qrtc:
+ if(strcmp(up->user, eve)!=0 && omode!=OREAD)
+ error(Eperm);
+ break;
+ case Qswitch:
+ case Qintstat:
+ if(omode!=OREAD)
+ error(Eperm);
+ break;
+ }
+ return devopen(c, omode, rtcdir, NRTC, devgen);
+}
+
+static void
+rtcclose(Chan*)
+{
+}
+
+static long
+rtcread(Chan *c, void *buf, long n, vlong offset)
+{
+ ulong t;
+ char *b;
+
+ if(c->qid.path & CHDIR)
+ return devdirread(c, buf, n, rtcdir, NRTC, devgen);
+
+ switch(c->qid.path){
+ case Qrtc:
+ t = m->iomem->rtc;
+ n = readnum(offset, buf, n, t, 12);
+ return n;
+ case Qswitch:
+ return readnum(offset, buf, n, (m->bcsr[2]>>19)&0xF, 12);
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+static long
+rtcwrite(Chan *c, void *buf, long n, vlong offset)
+{
+ ulong secs;
+ char *cp, *ep;
+ IMM *io;
+
+ switch(c->qid.path){
+ case Qrtc:
+ if(offset!=0)
+ error(Ebadarg);
+ /*
+ * read the time
+ */
+ cp = ep = buf;
+ ep += n;
+ while(cp < ep){
+ if(*cp>='0' && *cp<='9')
+ break;
+ cp++;
+ }
+ secs = strtoul(cp, 0, 0);
+ /*
+ * set it
+ */
+ io = ioplock();
+ io->rtck = KEEP_ALIVE_KEY;
+ io->rtc = secs;
+ io->rtck = ~KEEP_ALIVE_KEY;
+ iopunlock();
+ return n;
+ case Qswitch:
+ return 0;
+ }
+ error(Egreg);
+ return 0; /* not reached */
+}
+
+long
+rtctime(void)
+{
+ return m->iomem->rtc;
+}
+
+Dev rtcdevtab = {
+ 'r',
+ "rtc",
+
+ rtcreset,
+ devinit,
+ rtcattach,
+ devclone,
+ rtcwalk,
+ rtcstat,
+ rtcopen,
+ devcreate,
+ rtcclose,
+ rtcread,
+ devbread,
+ rtcwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
A mpc/etherif.h => mpc/etherif.h +28 -0
@@ 0,0 1,28 @@
+enum {
+ MaxEther = 24,
+ Ntypes = 8,
+};
+
+typedef struct Ether Ether;
+struct Ether {
+ ISAConf; /* hardware info */
+ int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
+ int mbps; /* Mbps */
+ uchar ea[Eaddrlen];
+
+ void (*attach)(Ether*); /* filled in by reset routine */
+ void (*closed)(Ether*);
+ void (*detach)(Ether*);
+ void (*transmit)(Ether*);
+ void (*interrupt)(Ureg*, void*);
+ long (*ifstat)(Ether*, void*, long, ulong);
+ void *ctlr;
+
+ Queue* oq;
+
+ Netif;
+};
+
+extern Block* etheriq(Ether*, Block*, int);
+extern void addethercard(char*, int(*)(Ether*));
A mpc/fns.h => mpc/fns.h +91 -0
@@ 0,0 1,91 @@
+#include "../port/portfns.h"
+
+void archinit(void);
+int brgalloc(void);
+void brgfree(int);
+ulong baudgen(int, int);
+int cistrcmp(char*, char*);
+int cistrncmp(char*, char*, int);
+void clockcheck(void);
+void clockinit(void);
+void clockintr(Ureg*);
+void clrfptrap(void);
+#define coherence() // not need on signle processor machines
+void cpminit(void);
+int cpuidentify(void);
+void cpuidprint(void);
+void dcflush(void*, ulong);
+void delay(int);
+ulong draminit(ulong*);
+void dtlbmiss(void);
+void dumpregs(Ureg*);
+void eieio(void);
+void evenaddr(ulong);
+void faultpower(Ureg*);
+void firmware(int);
+void fpinit(void);
+int fpipower(Ureg*);
+void fpoff(void);
+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);
+int iprint(char*, ...);
+void intr(Ureg*);
+void intrenable(int, void (*)(Ureg*, void*), void*, int);
+int intrstats(char*, int);
+void intrvec(void);
+void itlbmiss(void);
+int isaconfig(char*, int, ISAConf*);
+void kbdinit(void);
+void kbdreset(void);
+void links(void);
+void mapfree(RMap*, ulong, int);
+void mapinit(RMap*, Map*, int);
+void mathinit(void);
+void mmuinit(void);
+ulong* mmuwalk(ulong*, ulong, int);
+#define procrestore(p)
+void procsave(Proc*);
+void procsetup(Proc*);
+void putdec(ulong);
+void putmsr(ulong);
+ulong rmapalloc(RMap*, ulong, int, int);
+void screeninit(void);
+void setpanic(void);
+int screenprint(char*, ...); /* debugging */
+#define screenputs(x, y) // no screen
+ulong sdraminit(ulong*);
+int segflush(void*, ulong);
+void spireset(void);
+long spioutin(void*, long, void*);
+int tas(void*);
+void trapinit(void);
+void trapvec(void);
+void uartinstall(void);
+void uartwait(void); /* debugging */
+void wbflush(void);
+
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+ulong getcallerpc(void*);
+
+// identity map between kernel physical and virtual addresses
+#define KADDR(a) ((void*)(a))
+#define PADDR(a) ((ulong)(a))
+
+/* IBM bit field order */
+#define IBIT(b) ((ulong)1<<(31-(b)))
+#define SIBIT(n) ((ushort)1<<(15-(n)))
+
+/* compatibility with inf2.1 */
+#define bpenumenv(n) ((char*)0)
A mpc/io.h => mpc/io.h +556 -0
@@ 0,0 1,556 @@
+typedef struct BD BD;
+typedef struct Ring Ring;
+typedef struct GTimer GTimer;
+
+enum
+{
+ /* interrupt vectors (SIU and CPM) */
+ VectorPIC= 0, /* level 0 to level 7, assigned by software */
+ /* vector assignments are determined by the assignments here */
+ PITlevel= 2,
+ CPIClevel= 4,
+ PCMCIAlevel= 6,
+ RTClevel= 7,
+ VectorIRQ= VectorPIC+8, /* IRQ0 to IRQ7 */
+ VectorCPIC= VectorIRQ+8, /* 32 CPM interrupts: 0 (error) to 0x1F (PC15) */
+};
+
+/*
+ * these are defined to keep the interface compatible with other
+ * architectures, but only BUSUNKNOWN is currently used
+ */
+#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
+#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
+#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
+#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
+#define BUSTYPE(tbdf) ((tbdf)>>24)
+#define BUSBDF(tbdf) ((tbdf)&0x00FFFF00)
+#define BUSUNKNOWN (-1)
+
+/*
+ * Buffer Descriptors and IO Rings
+ */
+
+struct BD {
+ ushort status;
+ ushort length;
+ ulong addr;
+};
+
+BD* bdalloc(int);
+void bdfree(BD*, int);
+
+enum {
+ /* Rx BDs, bits common to all protocols */
+ BDEmpty= 1<<15,
+ BDWrap= 1<<13,
+ BDInt= 1<<12,
+ BDLast= 1<<11,
+ BDFirst= 1<<10,
+
+ /* Tx BDs */
+ BDReady= 1<<15,
+ /* BDWrap, BDInt, BDLast */
+};
+
+
+struct Ring {
+ BD* rdr; /* receive descriptor ring */
+ void* rrb; /* receive ring buffers */
+ int rdrx; /* index into rdr */
+ int nrdre; /* length of rdr */
+
+ BD* tdr; /* transmit descriptor ring */
+ Block** txb; /* corresponding transmit ring buffers */
+ int tdrh; /* host index into tdr */
+ int tdri; /* interface index into tdr */
+ int ntdre; /* length of tdr */
+ int ntq; /* pending transmit requests */
+};
+
+#define NEXT(x, l) (((x)+1)%(l))
+#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
+#define HOWMANY(x, y) (((x)+((y)-1))/(y))
+#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
+
+int ioringinit(Ring*, int, int, int);
+
+/*
+ * CPM
+ */
+enum {
+ /* commands */
+ InitRxTx = 0,
+ InitRx = 1,
+ InitTx = 2,
+ EnterHunt= 3,
+ StopTx= 4,
+ GracefulStopTx = 5,
+ InitIDMA = 5,
+ RestartTx = 6,
+ CloseRxBD = 7,
+ SetGroupAddr = 8,
+ SetTimer = 8,
+ GCITimeout = 9,
+ GCIAbort = 10,
+ StopIDMA = 11,
+ StartDSP = 12,
+ ArmIDMA = 13,
+ InitDSP = 13,
+ USBCmd = 15,
+
+ /* channel IDs */
+ SCC1ID= 0,
+ USBID= 0,
+ I2CID= 1,
+ IDMA1ID= 1,
+ SCC2ID= 4,
+ SPIID= 5,
+ IDMA2ID= 5,
+ TIMERID= 5,
+ SCC3ID= 8,
+ SMC1ID= 9,
+ DSP1ID=9,
+ SCC4ID= 12,
+ SMC2ID= 13,
+ DSP2ID= 13,
+
+ /* bgcr */
+ BaudEnable = 1<<16,
+
+ /* sicr */
+ CLK1 = 4, /* SCC1,2 */
+ CLK2 = 5,
+ CLK3 = 6,
+ CLK4 = 7,
+ CLK5 = CLK1, /* SCC3,4 */
+ CLK6 = CLK2,
+ CLK7 = CLK3,
+ CLK8 = CLK4,
+};
+
+void cpmop(int, int, int);
+void* cpmalloc(int, int);
+void cpmfree(void*, int);
+void* cpmparam(ulong, int);
+IMM* ioplock(void);
+void iopunlock(void);
+void sccnmsi(int, int, int);
+int scc2claim(int, ulong, void(*)(void*), void*);
+void scc2stop(void*);
+
+/*
+ * CPM timers
+ */
+enum {
+ /* timer modes */
+ CaptureRise= 1<<6,
+ CaptureFall= 2<<6,
+ CaptureEdge= 3<<6,
+ TimerToggle= 1<<5, /* toggle TOUTx* pin */
+ TimerORI= 1<<4, /* Output Reference Interrupt */
+ TimerRestart= 1<<3,
+ TimerSclk= 1<<1,
+ TimerSclk16= 2<<1,
+ TimerTIN= 3<<1, /* clock by falling edge of TINx */
+ TimerGate= 1<<0, /* TGATE1* controls timer */
+
+ /* timer events */
+ TimerREF= 1<<1,
+ TimerCAP= 1<<0
+};
+
+struct GTimer{
+ int x;
+ int inuse;
+ int event;
+ ushort* tmr;
+ ushort* trr;
+ ushort* tcr;
+ ushort* tcn;
+ ushort* ter;
+ void* arg;
+ void (*interrupt)(Ureg*, void*, GTimer*);
+};
+GTimer* gtimer(ushort, ushort, void (*)(Ureg*,void*,GTimer*), void*);
+void gtimerset(GTimer*, ushort, int);
+void gtimerstart(GTimer*);
+void gtimerstop(GTimer*);
+void gtimerfree(GTimer*);
+
+enum {
+ /* BCSR1 bits */
+ DisableFlash= IBIT(0),
+ DisableDRAM= IBIT(1),
+ DisableEther= IBIT(2),
+ DisableIR= IBIT(3),
+ DisableRS232a= IBIT(7),
+ DisablePCMCIA= IBIT(8),
+ PCCVCCMask= IBIT(9)|IBIT(15),
+ PCCVPPMask= IBIT(10)|IBIT(11),
+ DisableRS232b= IBIT(13),
+ EnableSDRAM= IBIT(14),
+
+ PCCVCC0V= IBIT(15)|IBIT(9),
+ PCCVCC5V= IBIT(9), /* active low */
+ PCCVCC3V= IBIT(15), /* active low */
+ PCCVPP0V= IBIT(10)|IBIT(11), /* active low */
+ PCCVPP5V= IBIT(10), /* active low */
+ PCCVPP12V= IBIT(11), /* active low */
+ PCCVPPHiZ= IBIT(10)|IBIT(11),
+
+ /* BCSR4 bits */
+ DisableTPDuplex= IBIT(1),
+ DisableLamp= IBIT(3),
+ DisableUSB= IBIT(4),
+ USBFullSpeed= IBIT(5),
+ DisableUSBVcc= IBIT(6),
+ DisableVideoLamp= IBIT(8),
+ EnableVideoClock= IBIT(9),
+ EnableVideoPort= IBIT(10),
+ DisableModem= IBIT(11),
+};
+
+/*
+ * everything in this file follows a hardware/firmware layout in the 8xx manuals:
+ * mind the data types, offsets and alignment
+ */
+
+/*
+ * basic IO controller parameters (SMC and SCC)
+ */
+typedef struct IOCparam IOCparam;
+struct IOCparam {
+ ushort rbase;
+ ushort tbase;
+ uchar rfcr;
+ uchar tfcr;
+ ushort mrblr;
+ ulong rstate;
+ ulong rxidp;
+ ushort rbptr;
+ ushort rxibc;
+ ulong rxtemp;
+ ulong tstate;
+ ulong txidp;
+ ushort tbptr;
+ ushort txibc;
+ ulong txtemp;
+};
+
+typedef struct SCCparam SCCparam;
+struct SCCparam {
+ IOCparam;
+ ulong rcrc;
+ ulong tcrc;
+};
+
+typedef struct SCC SCC;
+struct SCC {
+ ulong gsmrl;
+ ulong gsmrh;
+ ushort psmr;
+ uchar rsvscc0[2];
+ ushort todr;
+ ushort dsr;
+ ushort scce;
+ uchar rsvscc1[2];
+ ushort sccm;
+ uchar rsvscc3;
+ uchar sccs;
+ ushort irmode;
+ ushort irsip;
+};
+
+typedef struct SMC SMC;
+struct SMC {
+ uchar pad1[2];
+ ushort smcmr;
+ uchar pad2[2];
+ uchar smce;
+ uchar pad3[3];
+ uchar smcm;
+ uchar pad4[5];
+};
+
+typedef struct SPI SPI;
+struct SPI {
+ ushort spmode;
+ uchar res1[4];
+ uchar spie;
+ uchar res2[3];
+ uchar spim;
+ uchar res3[2];
+ uchar spcom;
+ uchar res4[10];
+};
+
+typedef struct USB USB;
+struct USB {
+ uchar usmod;
+ uchar usadr;
+ uchar uscom;
+ uchar rsvu1;
+ ushort usep[4];
+ uchar rsvu2[4];
+ ushort usber;
+ uchar rsvu3[2];
+ ushort usbmr;
+ uchar rsvu4;
+ uchar usbs;
+ uchar rsvu5[8];
+};
+
+typedef struct IMM IMM;
+struct IMM {
+ struct { /* general SIU */
+ ulong siumcr;
+ ulong sypcr;
+ uchar rsv0[0xE-0x8];
+ ushort swsr;
+ ulong sipend;
+ ulong simask;
+ ulong siel;
+ uchar sivec;
+ uchar padv[3];
+ ulong tesr;
+ uchar rsv1[0x30-0x24];
+ ulong sdcr;
+ uchar rsv2[0x80-0x34];
+ };
+ struct { /* PCMCIA */
+ struct {
+ ulong base;
+ ulong option;
+ } pcmr[8];
+ uchar rsv3[0xe0-0xc0];
+ ulong pgcra;
+ ulong pgcrb;
+ ulong pscr;
+ uchar rsv4[0xf0-0xec];
+ ulong pipr;
+ uchar rsv5[4];
+ ulong per;
+ uchar rsv6[4];
+ };
+ struct { /* MEMC */
+ struct {
+ ulong base;
+ ulong option;
+ } memc[8];
+ uchar rsv7a[0x24];
+ ulong mar;
+ ulong mcr;
+ uchar rsv7b[4];
+ ulong mamr;
+ ulong mbmr;
+ ushort mstat;
+ ushort mptpr;
+ ulong mdr;
+ uchar rsv7c[0x80];
+ };
+ struct { /* system integration timers */
+ ushort tbscr;
+ uchar rsv8a[2];
+ ulong tbrefu;
+ ulong tbrefl;
+ uchar rsv8b[0x14];
+ ushort rtcsc;
+ uchar rsv8c[2];
+ ulong rtc;
+ ulong rtsec;
+ ulong rtcal;
+ uchar rsv8d[0x10];
+ ushort piscr;
+ ushort rsv8e;
+ ulong pitc;
+ ulong pitr;
+ uchar rsv8f[0x34];
+ };
+ struct { /* 280: clocks and resets */
+ ulong sccr;
+ ulong plprcr;
+ ulong rsr;
+ uchar rsv9[0x300-0x28c];
+ };
+ struct { /* 300: system integration timers keys */
+ ulong tbscrk;
+ ulong tbrefuk;
+ ulong tbreflk;
+ ulong tbk;
+ uchar rsv10a[0x10];
+ ulong rtcsck;
+ ulong rtck;
+ ulong rtseck;
+ ulong rtcalk;
+ uchar rsv10b[0x10];
+ ulong piscrk;
+ ulong pitck;
+ uchar rsv10c[0x38];
+ };
+ struct { /* 380: clocks and resets keys */
+ ulong sccrk;
+ ulong plprcrk;
+ ulong rsrk;
+ uchar rsv11[0x800-0x38C];
+ };
+ struct { /* 800: video controller */
+ ushort vccr;
+ ushort pad11a;
+ uchar vsr;
+ uchar pad11b;
+ uchar vcmr;
+ uchar pad11c;
+ ulong vbcb;
+ ulong pad11d;
+ ulong vfcr0;
+ ulong vfaa0;
+ ulong vfba0;
+ ulong vfcr1;
+ ulong vfaa1;
+ ulong vfba1;
+ uchar rsv11a[0x840-0x828];
+ };
+ struct { /* 840: LCD */
+ ulong lccr;
+ ulong lchcr;
+ ulong lcvcr;
+ ulong rsv11b;
+ ulong lcfaa;
+ ulong lcfba;
+ uchar lcsr;
+ uchar rsv11c[0x860-0x859];
+ };
+ struct { /* 860: I2C */
+ uchar i2mod;
+ uchar rsv12a[3];
+ uchar i2add;
+ uchar rsv12b[3];
+ uchar i2brg;
+ uchar rsv12c[3];
+ uchar i2com;
+ uchar rsv12d[3];
+ uchar i2cer;
+ uchar rsv12e[3];
+ uchar i2cmr;
+ uchar rsv12[0x900-0x875];
+ };
+ struct { /* 900: DMA */
+ uchar rsv13[4];
+ ulong sdar;
+ uchar sdsr;
+ uchar pad1[3];
+ uchar sdmr;
+ uchar pad2[3];
+ uchar idsr1;
+ uchar pad3[3];
+ uchar idmr1;
+ uchar pad4[3];
+ uchar idsr2;
+ uchar pad5[3];
+ uchar idmr2;
+ uchar pad6[0x930-0x91D];
+ };
+ struct { /* CPM interrupt control */
+ ushort civr;
+ uchar pad7[0x940-0x932];
+ ulong cicr;
+ ulong cipr;
+ ulong cimr;
+ ulong cisr;
+ };
+ struct { /* input/output port */
+ ushort padir;
+ ushort papar;
+ ushort paodr;
+ ushort padat;
+ uchar pad8[8];
+ ushort pcdir;
+ ushort pcpar;
+ ushort pcso;
+ ushort pcdat;
+ ushort pcint;
+ uchar pad9[6];
+ ushort pddir;
+ ushort pdpar;
+ ushort rsv14a;
+ ushort pddat;
+ uchar rsv14[0x980-0x978];
+ };
+ struct { /* CPM timers */
+ ushort tgcr;
+ uchar rsv15a[0x990-0x982];
+ ushort tmr1;
+ ushort tmr2;
+ ushort trr1;
+ ushort trr2;
+ ushort tcr1;
+ ushort tcr2;
+ ushort tcn1;
+ ushort tcn2;
+ ushort tmr3;
+ ushort tmr4;
+ ushort trr3;
+ ushort trr4;
+ ushort tcr3;
+ ushort tcr4;
+ ushort tcn3;
+ ushort tcn4;
+ ushort ter1;
+ ushort ter2;
+ ushort ter3;
+ ushort ter4;
+ uchar rsv15[0x9C0-0x9B8];
+ };
+ struct { /* CPM */
+ ushort cpcr;
+ uchar res0[2];
+ ushort rccr;
+ uchar res1;
+ uchar rmds;
+ uchar res2a[4];
+ ushort rctr1;
+ ushort rctr2;
+ ushort rctr3;
+ ushort rctr4;
+ uchar res2[2];
+ ushort rter;
+ uchar res3[2];
+ ushort rtmr;
+ uchar rsv16[0x9F0-0x9DC];
+ };
+ union { /* BRG */
+ struct {
+ ulong brgc1;
+ ulong brgc2;
+ ulong brgc3;
+ ulong brgc4;
+ };
+ ulong brgc[4];
+ };
+ uchar skip0[0xAB2-0xA00]; /* USB, SCC, SMC, SPI: address using IOREGS in fns.h */
+ struct { /* PIP */
+ ushort pipc; /* not 823 */
+ ushort ptpr; /* not 823 */
+ ulong pbdir;
+ ulong pbpar;
+ uchar pad10[2];
+ ushort pbodr;
+ ulong pbdat;
+ uchar pad11[0xAE0-0xAC8];
+ };
+ struct { /* SI */
+ ulong simode;
+ uchar sigmr;
+ uchar pad12;
+ uchar sistr;
+ uchar sicmr;
+ uchar pad13[4];
+ ulong sicr;
+ ulong sirp;
+ uchar pad14[0xB00-0xAF4];
+ };
+ uchar vcram[256];
+ uchar siram[512];
+ ushort lcdmap[256];
+};
A mpc/l.s => mpc/l.s +663 -0
@@ 0,0 1,663 @@
+#include "mem.h"
+
+/*
+ * common ppc special purpose registers
+ */
+#define DSISR 18
+#define DAR 19 /* Data Address Register */
+#define DEC 22 /* Decrementer */
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define SPRG0 272 /* Supervisor Private Registers */
+#define SPRG1 273
+#define SPRG2 274
+#define SPRG3 275
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define TBRL 268
+#define TBWU 285 /* Time base Upper/Lower (Writing) */
+#define TBWL 284
+#define PVR 287 /* Processor Version */
+
+/*
+ * mpc8xx-specific special purpose registers of interest here
+ */
+#define EIE 80
+#define EID 81
+#define NRI 82
+#define IMMR 638
+#define IC_CST 560
+#define IC_ADR 561
+#define IC_DAT 562
+#define DC_CST 568
+#define DC_ADR 569
+#define DC_DAT 570
+#define MI_CTR 784
+#define MI_AP 786
+#define MI_EPN 787
+#define MI_TWC 789
+#define MI_RPN 790
+#define MI_DBCAM 816
+#define MI_DBRAM0 817
+#define MI_DBRAM1 818
+#define MD_CTR 792
+#define M_CASID 793
+#define MD_AP 794
+#define MD_EPN 795
+#define M_TWB 796
+#define MD_TWC 797
+#define MD_RPN 798
+#define M_TW 799
+#define MD_DBCAM 824
+#define MD_DBRAM0 825
+#define MD_DBRAM1 826
+
+/* use of SPRG registers in save/restore */
+#define SAVER0 SPRG0
+#define SAVER1 SPRG1
+#define SAVELR SPRG2
+#define SAVEXX SPRG3
+
+/* special instruction definitions */
+#define BDNZ BC 16,0,
+#define BDNE BC 0,2,
+#define TLBIA WORD $(31<<26)
+#define MFTB(tbr,d) WORD $((31<<26)|((d)<<21)|((tbr&0x1f)<<16)|(((tbr>>5)&0x1f)<<11)|(371<<1))
+
+/* on some models mtmsr doesn't synchronise enough (eg, 603e) */
+#define MSRSYNC SYNC; ISYNC
+
+#define UREGSPACE (UREGSIZE+8)
+
+ TEXT start(SB), $-4
+
+ /* turn off interrupts but enable traps */
+ MOVW MSR, R3
+ MOVW $~(MSR_EE|MSR_FP), R4
+ AND R4, R3
+ OR $(MSR_IP|MSR_ME), R3
+ ISYNC
+ MOVW R3, MSR
+ MSRSYNC
+
+ MOVW $0, R0 /* except during trap handling, R0 is zero from now on */
+ MOVW $setSB(SB), R2
+
+/*
+ * reset the caches and disable them for now
+ */
+ MOVW SPR(IC_CST), R4 /* read and clear */
+ MOVW $(5<<25), R4
+ MOVW R4, SPR(IC_CST) /* unlock all */
+ ISYNC
+ MOVW $(6<<25), R4
+ MOVW R4, SPR(IC_CST) /* invalidate all */
+ ISYNC
+ MOVW $(2<<25), R4
+ MOVW R4, SPR(IC_CST) /* disable i-cache */
+ ISYNC
+
+ SYNC
+ MOVW SPR(DC_CST), R4 /* read and clear */
+ MOVW $(10<<24), R4
+ SYNC
+ MOVW R4, SPR(DC_CST) /* unlock all */
+ ISYNC
+ MOVW $(12<<24), R4
+ SYNC
+ MOVW R4, SPR(DC_CST) /* invalidate all */
+ ISYNC
+ MOVW $(4<<24), R4
+ SYNC
+ MOVW R4, SPR(DC_CST) /* disable d-cache */
+ ISYNC
+
+ MOVW $7, R4
+ MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
+ ISYNC
+
+/*
+ * set other system configuration values
+ */
+ MOVW $INTMEM, R4
+ MOVW R4, SPR(IMMR) /* set internal memory base */
+
+ MOVW $mach0(SB), R(MACH)
+ ADD $(MACHSIZE-8), R(MACH), R1
+ SUB $4, R(MACH), R3
+ ADD $4, R1, R4
+clrmach:
+ MOVWU R0, 4(R3)
+ CMP R3, R4
+ BNE clrmach
+
+ MOVW R0, R(USER)
+ MOVW R0, 0(R(MACH))
+
+ MOVW $edata(SB), R3
+ MOVW $end(SB), R4
+ ADD $4, R4
+ SUB $4, R3
+clrbss:
+ MOVWU R0, 4(R3)
+ CMP R3, R4
+ BNE clrbss
+
+ BL main(SB)
+ BR 0(PC)
+
+TEXT kernelmmu(SB), $0
+ TLBIA
+ ISYNC
+
+ MOVW $0, R4
+ MOVW R4, SPR(M_CASID) /* set supervisor space */
+ MOVW $(0<<29), R4 /* allow i-cache when IR=0 */
+ MOVW R4, SPR(MI_CTR) /* i-mmu control */
+ ISYNC
+ MOVW $((1<<29)|(1<<28)), R4 /* cache inhibit when DR=0, write-through */
+ SYNC
+ MOVW R4, SPR(MD_CTR) /* d-mmu control */
+ ISYNC
+ TLBIA
+
+ /* map various things 1:1 */
+ MOVW $tlbtab-KZERO(SB), R4
+ MOVW $tlbtabe-KZERO(SB), R5
+ SUB R4, R5
+ MOVW $(3*4), R6
+ DIVW R6, R5
+ SUB $4, R4
+ MOVW R5, CTR
+ltlb:
+ MOVWU 4(R4), R5
+ MOVW R5, SPR(MD_EPN)
+ MOVW R5, SPR(MI_EPN)
+ MOVWU 4(R4), R5
+ MOVW R5, SPR(MI_TWC)
+ MOVW R5, SPR(MD_TWC)
+ MOVWU 4(R4), R5
+ MOVW R5, SPR(MD_RPN)
+ MOVW R5, SPR(MI_RPN)
+ BDNZ ltlb
+
+ MOVW $(1<<25), R4
+ MOVW R4, SPR(IC_CST) /* enable i-cache */
+ ISYNC
+
+ MOVW $(1<<24), R4
+ SYNC
+ MOVW R4, SPR(DC_CST) /* force write through mode */
+ MOVW $(1<<25), R4
+ SYNC
+ MOVW R4, SPR(DC_CST) /* enable d-cache */
+ ISYNC
+
+ /* enable MMU and set kernel PC to virtual space */
+ MOVW $((0<<29)|(1<<28)), R4 /* cache when DR=0, write-through */
+ SYNC
+ MOVW R4, SPR(MD_CTR) /* d-mmu control */
+ MOVW LR, R3
+ OR $KZERO, R3
+ MOVW R3, SPR(SRR0)
+ MOVW MSR, R4
+ OR $(MSR_ME|MSR_IR|MSR_DR), R4 /* had ME|FPE|FE0|FE1 */
+ MOVW R4, SPR(SRR1)
+ RFI /* resume in kernel mode in caller */
+
+TEXT splhi(SB), $0
+ MOVW MSR, R3
+ RLWNM $0, R3, $~MSR_EE, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ MOVW LR, R31
+ MOVW R31, 4(R(MACH)) /* save PC in m->splpc */
+ RETURN
+
+TEXT splx(SB), $0
+ /* fall though */
+
+TEXT splxpc(SB), $0
+ MOVW MSR, R4
+ RLWMI $0, R3, $MSR_EE, R4
+ RLWNMCC $0, R3, $MSR_EE, R5
+ BNE splx0
+ MOVW LR, R31
+ MOVW R31, 4(R(MACH)) /* save PC in m->splpc */
+splx0:
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT spllo(SB), $0
+ MFTB(TBRL, 3)
+ MOVW R3, spltbl(SB)
+ MOVW MSR, R3
+ OR $MSR_EE, R3, R4
+ SYNC
+ MOVW R4, MSR
+ MSRSYNC
+ RETURN
+
+TEXT spldone(SB), $0
+ RETURN
+
+TEXT islo(SB), $0
+ MOVW MSR, R3
+ RLWNM $0, R3, $MSR_EE, R3
+ RETURN
+
+TEXT setlabel(SB), $-4
+ MOVW LR, R31
+ MOVW R1, 0(R3)
+ MOVW R31, 4(R3)
+ MOVW $0, R3
+ RETURN
+
+TEXT gotolabel(SB), $-4
+ MOVW 4(R3), R31
+ MOVW R31, LR
+ MOVW 0(R3), R1
+ MOVW $1, R3
+ RETURN
+
+/*
+ * enter with stack set and mapped.
+ * on return, SB (R2) has been set, and R3 has the Ureg*,
+ * the MMU has been re-enabled, kernel text and PC are in KSEG,
+ * R(MACH) has been set, and R0 contains 0.
+ *
+ * this can be simplified in the Inferno regime
+ */
+TEXT saveureg(SB), $-4
+/*
+ * save state
+ */
+ MOVMW R2, 48(R1) /* r2:r31 */
+ MOVW $setSB(SB), R2
+ MOVW SPR(SAVER1), R4
+ MOVW R4, 44(R1)
+ MOVW SPR(SAVER0), R5
+ MOVW R5, 40(R1)
+ MOVW CTR, R6
+ MOVW R6, 36(R1)
+ MOVW XER, R4
+ MOVW R4, 32(R1)
+ MOVW CR, R5
+ MOVW R5, 28(R1)
+ MOVW SPR(SAVELR), R6 /* LR */
+ MOVW R6, 24(R1)
+ /* pad at 20(R1) */
+ /* old PC(16) and status(12) saved earlier */
+ MOVW SPR(SAVEXX), R0
+ MOVW R0, 8(R1) /* cause/vector */
+ ADD $8, R1, R3 /* Ureg* */
+ STWCCC R3, (R1) /* break any pending reservations */
+ MOVW $0, R0 /* compiler/linker expect R0 to be zero */
+
+ MOVW MSR, R5
+ OR $(MSR_IR|MSR_DR), R5 /* enable MMU */
+ MOVW R5, SPR(SRR1)
+ MOVW LR, R31
+ OR $KZERO, R31 /* return PC in KSEG0 */
+ MOVW R31, SPR(SRR0)
+ SYNC
+ ISYNC
+ RFI /* returns to trap handler */
+
+TEXT icflush(SB), $-4 /* icflush(virtaddr, count) */
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+icf0: ICBI (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ icf0
+ ISYNC
+ RETURN
+
+TEXT dcflush(SB), $-4 /* dcflush(virtaddr, count) */
+ SYNC
+ MOVW n+4(FP), R4
+ RLWNM $0, R3, $~(CACHELINESZ-1), R5
+ CMP R4, $0
+ BLE dcf1
+ SUB R5, R3
+ ADD R3, R4
+ ADD $(CACHELINESZ-1), R4
+ SRAW $CACHELINELOG, R4
+ MOVW R4, CTR
+dcf0: DCBF (R5)
+ ADD $CACHELINESZ, R5
+ BDNZ dcf0
+ SYNC
+ ISYNC
+dcf1:
+ RETURN
+
+TEXT tas(SB), $0
+ SYNC
+ MOVW R3, R4
+ MOVW $0xdeaddead,R5
+tas1:
+ DCBF (R4) /* fix for 603x bug */
+ LWAR (R4), R3
+ CMP R3, $0
+ BNE tas0
+ STWCCC R5, (R4)
+ BNE tas1
+tas0:
+ SYNC
+ ISYNC
+ RETURN
+
+TEXT gettbl(SB), $0
+ MFTB(TBRL, 3)
+ RETURN
+
+TEXT gettbu(SB), $0
+ MOVW SPR(TBRU), R3
+ RETURN
+
+TEXT getpvr(SB), $0
+ MOVW SPR(PVR), R3
+ RETURN
+
+TEXT getimmr(SB), $0
+ MOVW SPR(IMMR), R3
+ RETURN
+
+TEXT getdec(SB), $0
+ MOVW SPR(DEC), R3
+ RETURN
+
+TEXT putdec(SB), $0
+ MOVW R3, SPR(DEC)
+ RETURN
+
+TEXT getcallerpc(SB), $-4
+ MOVW 0(R1), R3
+ RETURN
+
+TEXT getdar(SB), $0
+ MOVW SPR(DAR), R3
+ RETURN
+
+TEXT getdsisr(SB), $0
+ MOVW SPR(DSISR), R3
+ RETURN
+
+TEXT getdepn(SB), $0
+ MOVW SPR(MD_EPN), R3
+ RETURN
+
+TEXT getmsr(SB), $0
+ MOVW MSR, R3
+ RETURN
+
+TEXT putmsr(SB), $0
+ SYNC
+ MOVW R3, MSR
+ MSRSYNC
+ RETURN
+
+TEXT eieio(SB), $0
+ EIEIO
+ RETURN
+
+TEXT gotopc(SB), $0
+ MOVW R3, CTR
+ MOVW LR, R31 /* for trace back */
+ BR (CTR)
+
+TEXT firmware(SB), $0
+ MOVW MSR, R3
+ MOVW $(MSR_EE|MSR_ME), R4
+ ANDN R4, R3
+ OR $(MSR_IP), R3
+ ISYNC
+ MOVW R3, MSR /* turn off interrupts and machine checks */
+ MSRSYNC
+ MOVW $(MSR_RI|MSR_IR|MSR_DR|MSR_ME), R4
+ ANDN R4, R3
+ MOVW R3, SPR(SRR1)
+ MOVW $(0xFF00<<16), R4
+ MOVW R4, SPR(IMMR)
+ MOVW $(0x0800<<16), R4
+ MOVW R4, SPR(SRR0) /* force bad address */
+ MOVW R0, SPR(149) /* ensure checkstop on machine check */
+ MOVW R0, R1
+ MOVW R0, R2
+ EIEIO
+ ISYNC
+ RFI
+
+/*
+ * byte swapping of arrays of long and short;
+ * could possibly be avoided with more changes to drivers
+ */
+TEXT swabl(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ SRAW $2, R5, R5
+ MOVW R5, CTR
+ SUB $4, R4
+ SUB $4, R3
+swabl1:
+ ADD $4, R3
+ MOVWU 4(R4), R7
+ MOVWBR R7, (R3)
+ BDNZ swabl1
+ RETURN
+
+TEXT swabs(SB), $0
+ MOVW v+4(FP), R4
+ MOVW n+8(FP), R5
+ SRAW $1, R5, R5
+ MOVW R5, CTR
+ SUB $2, R4
+ SUB $2, R3
+swabs1:
+ ADD $2, R3
+ MOVHZU 2(R4), R7
+ MOVHBR R7, (R3)
+ BDNZ swabs1
+ RETURN
+
+TEXT legetl(SB), $0
+ MOVWBR (R3), R3
+ RETURN
+
+TEXT lesetl(SB), $0
+ MOVW v+4(FP), R4
+ MOVWBR R4, (R3)
+ RETURN
+
+TEXT legets(SB), $0
+ MOVHBR (R3), R3
+ RETURN
+
+TEXT lesets(SB), $0
+ MOVW v+4(FP), R4
+ MOVHBR R4, (R3)
+ RETURN
+
+/*
+ * ITLB miss
+ * avoid references that might need the right SB value;
+ * IR and DR are off.
+ */
+TEXT itlbmiss(SB), $-4
+ MOVW R1, SPR(M_TW)
+ MOVW SPR(SRR0), R1 /* instruction miss address */
+ MOVW R1, SPR(MD_EPN)
+ MOVW SPR(M_TWB), R1 /* level one pointer */
+ MOVW (R1), R1
+ MOVW R1, SPR(MI_TWC) /* save level one attributes */
+ MOVW R1, SPR(MD_TWC) /* save base and attributes */
+ MOVW SPR(MD_TWC), R1 /* level two pointer */
+ MOVW (R1), R1 /* level two entry */
+ MOVW R1, SPR(MI_RPN) /* write TLB */
+ MOVW SPR(M_TW), R1
+ RFI
+
+/*
+ * DTLB miss
+ * avoid references that might need the right SB value;
+ * IR and DR are off.
+ */
+TEXT dtlbmiss(SB), $-4
+ MOVW R1, SPR(M_TW)
+ MOVW SPR(M_TWB), R1 /* level one pointer */
+ MOVW (R1), R1 /* level one entry */
+ MOVW R1, SPR(MD_TWC) /* save base and attributes */
+ MOVW SPR(MD_TWC), R1 /* level two pointer */
+ MOVW (R1), R1 /* level two entry */
+ MOVW R1, SPR(MD_RPN) /* write TLB */
+ MOVW SPR(M_TW), R1
+ RFI
+
+/*
+ * traps force memory mapping off.
+ * this code goes to too much effort (for the Inferno environment) to restore it.
+ */
+TEXT trapvec(SB), $-4
+traps:
+ MOVW LR, R0
+
+pagefault:
+
+/*
+ * map data virtually and make space to save
+ */
+ MOVW R0, SPR(SAVEXX) /* vector */
+ MOVW R1, SPR(SAVER1)
+ SYNC
+ ISYNC
+ MOVW MSR, R0
+ OR $(MSR_DR|MSR_ME), R0 /* make data space usable */
+ SYNC
+ MOVW R0, MSR
+ MSRSYNC
+ SUB $UREGSPACE, R1
+
+ MOVW SPR(SRR0), R0 /* save SRR0/SRR1 now, since DLTB might be missing stack page */
+ MOVW R0, LR
+ MOVW SPR(SRR1), R0
+ MOVW R0, 12(R1) /* save status: could take DLTB miss here */
+ MOVW LR, R0
+ MOVW R0, 16(R1) /* old PC */
+ BL saveureg(SB)
+ BL trap(SB)
+ BR restoreureg
+
+TEXT intrvec(SB), $-4
+ MOVW LR, R0
+
+/*
+ * map data virtually and make space to save
+ */
+ MOVW R0, SPR(SAVEXX) /* vector */
+ MOVW R1, SPR(SAVER1)
+ SYNC
+ ISYNC
+ MOVW MSR, R0
+ OR $MSR_DR, R0 /* make data space usable */
+ SYNC
+ MOVW R0, MSR
+ MSRSYNC
+ SUB $UREGSPACE, R1
+
+ MFTB(TBRL, 0)
+ MOVW R0, intrtbl(SB)
+
+ MOVW SPR(SRR0), R0
+ MOVW R0, LR
+ MOVW SPR(SRR1), R0
+ MOVW R0, 12(R1)
+ MOVW LR, R0
+ MOVW R0, 16(R1)
+ BL saveureg(SB)
+
+ MFTB(TBRL, 5)
+ MOVW R5, isavetbl(SB)
+
+ BL intr(SB)
+
+/*
+ * restore state from Ureg and return from trap/interrupt
+ */
+restoreureg:
+ MOVMW 48(R1), R2 /* r2:r31 */
+ /* defer R1 */
+ MOVW 40(R1), R0
+ MOVW R0, SPR(SAVER0)
+ MOVW 36(R1), R0
+ MOVW R0, CTR
+ MOVW 32(R1), R0
+ MOVW R0, XER
+ MOVW 28(R1), R0
+ MOVW R0, CR /* CR */
+ MOVW 24(R1), R0
+ MOVW R0, SPR(SAVELR) /* LR */
+ /* pad, skip */
+ MOVW 16(R1), R0
+ MOVW R0, SPR(SRR0) /* old PC */
+ MOVW 12(R1), R0
+ MOVW R0, SPR(SRR1) /* old MSR */
+ /* cause, skip */
+ MOVW 44(R1), R1 /* old SP */
+ MOVW SPR(SAVELR), R0
+ MOVW R0, LR
+ MOVW SPR(SAVER0), R0
+ RFI
+
+TEXT powerdownled(SB), $0
+
+ MOVW $0x10002200,R11
+ MOVW $0,R7
+ MOVW R7,0(R11)
+ RETURN
+
+TEXT powerupled(SB), $0
+
+ MOVW $0x10002200,R11
+ MOVW $2,R7
+ MOVW R7,0(R11)
+ RETURN
+
+TEXT reset(SB), $-4
+ MOVW $0,R4
+ MOVW 0(R4), R5
+loop:
+ BR loop
+
+
+GLOBL mach0+0(SB), $MACHSIZE
+GLOBL spltbl+0(SB), $4
+GLOBL intrtbl+0(SB), $4
+GLOBL isavetbl+0(SB), $4
+
+/*
+ * 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|DRAMMEM|TLBVALID, DRAMMEM|PTEWRITE|PTELPS|PTESH|PTEVALID, PTE8MB|PTEWT|PTEVALID) /* DRAM, 8M */
+/* TLBE(KZERO|BCSRMEM|TLBVALID, BCSRMEM|PTEWRITE|PTESH|PTECI|PTEVALID, PTE4K|PTEWT|PTEVALID) /* Board CSR, 4K */
+/* TLBE(KZERO|INTMEM|TLBVALID, INTMEM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE4K|PTEWT|PTEVALID) /* IMMR, 16K */
+/* TLBE(KZERO|FLASHMEM|TLBVALID, FLASHMEM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE8MB|PTEWT|PTEVALID) /* Flash, 8M */
+/* TLBE(KZERO|SDRAMMEM|TLBVALID, SDRAMMEM|PTEWRITE|PTELPS|PTESH|PTEVALID, PTE8MB|PTEWT|PTEVALID) /* SDRAM, 8M */
+/* TLBE(KZERO|PCMCIAMEM|TLBVALID, PCMCIAMEM|PTEWRITE|PTELPS|PTESH|PTECI|PTEVALID, PTE8MB|PTEWT|PTEVALID) /* PCMCIA, 8M */
+TEXT tlbtabe(SB), $-4
+ RETURN
A mpc/main.c => mpc/main.c +190 -0
@@ 0,0 1,190 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+#include "pool.h"
+
+#define MAXCONF 1000
+
+char *confname[MAXCONF];
+char *confval[MAXCONF];
+int nconf;
+
+Conf conf;
+
+void
+main(void)
+{
+ machinit();
+}
+
+void
+machinit(void)
+{
+ IMM *io;
+ int mf, osc;
+
+ memset(m, 0, sizeof(*m));
+ m->delayloop = 20000;
+ m->cputype = getpvr()>>16;
+ m->iomem = KADDR(INTMEM);
+
+ io = m->iomem;
+ osc = 5;
+ mf = io->plprcr >> 20;
+ m->oscclk = osc;
+ m->speed = osc*(mf+1);
+}
+
+void
+exit(int ispanic)
+{
+ int ms, once;
+
+ lock(&active);
+ if(ispanic)
+ active.ispanic = ispanic;
+ else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
+ active.ispanic = 0;
+ once = active.machs & (1<<m->machno);
+ active.machs &= ~(1<<m->machno);
+ active.exiting = 1;
+ unlock(&active);
+
+ if(once)
+ print("cpu%d: exiting\n", m->machno);
+ spllo();
+ for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
+ delay(TK2MS(2));
+ if(active.machs == 0 && consactive() == 0)
+ break;
+ }
+
+ if(active.ispanic && m->machno == 0){
+ if(cpuserver)
+ delay(10000);
+ else
+ for(;;);
+ }
+ else
+ delay(1000);
+
+// arch->reset();
+}
+
+/*
+ * set up floating point for a new process
+ */
+void
+procsetup(Proc *p)
+{
+ USED(p);
+}
+
+/*
+ * Save the mach dependent part of the process state.
+ */
+void
+procsave(Proc *p)
+{
+ USED(p);
+}
+
+// print without using interrupts
+int
+iprint(char *fmt, ...)
+{
+ char buf[PRINTSIZE];
+ int n;
+ va_list arg;
+
+ va_start(arg, fmt);
+ n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+ va_end(arg);
+
+ print("%s", buf);
+
+ return n;
+}
+
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q, *r;
+ int n;
+
+ sprint(cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(strncmp(confname[n], cc, NAMELEN))
+ continue;
+ isa->nopt = 0;
+ p = confval[n];
+ while(*p){
+ while(*p == ' ' || *p == '\t')
+ p++;
+ if(*p == '\0')
+ break;
+ if(strncmp(p, "type=", 5) == 0){
+ p += 5;
+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+ if(*p == '\0' || *p == ' ' || *p == '\t')
+ break;
+ *q = *p++;
+ }
+ *q = '\0';
+ }
+ else if(strncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "freq=", 5) == 0)
+ isa->freq = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "dma=", 4) == 0)
+ isa->dma = strtoul(p+4, &p, 0);
+ else if(isa->nopt < NISAOPT){
+ r = isa->opt[isa->nopt];
+ while(*p && *p != ' ' && *p != '\t'){
+ *r++ = *p++;
+ if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
+ break;
+ }
+ *r = '\0';
+ isa->nopt++;
+ }
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+int
+cistrcmp(char *a, char *b)
+{
+ int ac, bc;
+
+ for(;;){
+ ac = *a++;
+ bc = *b++;
+
+ if(ac >= 'A' && ac <= 'Z')
+ ac = 'a' + (ac - 'A');
+ if(bc >= 'A' && bc <= 'Z')
+ bc = 'a' + (bc - 'A');
+ ac -= bc;
+ if(ac)
+ return ac;
+ if(bc == 0)
+ break;
+ }
+ return 0;
+}
A mpc/mem.h => mpc/mem.h +156 -0
@@ 0,0 1,156 @@
+/*
+ * 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
+#define KSTACK 4096 /* Size of kernel stack */
+
+/*
+ * Time
+ */
+#define HZ 100 /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define TK2MS(t) ((t)*MS2HZ) /* ticks to milliseconds */
+#define MS2TK(t) ((t)/MS2HZ) /* milliseconds to ticks */
+
+/* Bit encodings for Machine State Register (MSR) */
+#define MSR_POW (1<<18) /* Enable Power Management */
+#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+#define MSR_ILE (1<<16) /* Interrupt Little-Endian enable */
+#define MSR_EE (1<<15) /* External Interrupt enable */
+#define MSR_PR (1<<14) /* Supervisor/User privelege */
+#define MSR_FP (1<<13) /* Floating Point enable */
+#define MSR_ME (1<<12) /* Machine Check enable */
+#define MSR_SE (1<<10) /* Single Step */
+#define MSR_BE (1<<9) /* Branch Trace */
+#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* Instruction MMU enable */
+#define MSR_DR (1<<4) /* Data MMU enable */
+#define MSR_RI (1<<1) /* Recoverable Exception */
+#define MSR_LE (1<<0) /* Little-Endian enable */
+
+/*
+ * Traps
+ */
+
+/*
+ * Magic registers
+ */
+
+#define MACH 30 /* R30 is m-> */
+#define USER 29 /* R29 is up-> */
+
+/*
+ * Fundamental addresses
+ */
+#define MACHADDR ((long)&mach0)
+
+#define UREGSIZE ((8+32)*4)
+
+/*
+ * virtual MMU
+ */
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+#define PPN(x) ((x)&~(BY2PG-1))
+
+/*
+ * 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
+
+/*
+ * physical MMU - bogus at the momement
+ */
+#define PTEUNCACHED (1<<4)
+#define PTERONLY (0<<1)
+#define PTEKERNEL (0<<2)
+#define PTEUSER (1<<2)
+#define PTESIZE (1<<7)
+
+/* TLB and MxEPN flag */
+#define TLBVALID (1<<9)
+
+#define TLBSETS 32 /* number of tlb sets */
+
+/*
+ * Address spaces
+ *
+ * User is at 0-2GB
+ * Kernel is at 2GB-4GB
+ */
+#define UZERO 0 /* base of user address space */
+#define UTZERO (UZERO+BY2PG) /* first address in user text */
+#define KZERO 0x80000000 /* base of kernel address space */
+#define KTZERO 0xff000000 /* first address in kernel text */
+#define USTKTOP (KZERO-BY2PG) /* byte just beyond user stack */
+#define USTKSIZE (16*1024*1024) /* size of user stack */
+#define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */
+#define TSTKSIZ 100
+
+/*
+ * atlas board registers
+ */
+#define INTMEM 0x80000000
+#define NIMMEM 0x80100000
+#define FLASH0MEM 0x80200000
+#define FLASH1MEM 0x80400000
+#define SDRAMMEM 0x03000000
+#define DRAMMEM 0xff000000 // to 0xffffffff: 16 Meg
+
+#define SIRAM (INTMEM+0xC00)
+#define LCDCOLR (INTMEM+0xE00)
+#define DPRAM (INTMEM+0x2000)
+#define DPLEN1 0x200
+#define DPLEN2 0x400
+#define DPLEN3 0x800
+#define DPBASE (DPRAM+DPLEN1)
+
+#define SCC1P (INTMEM+0x3C00)
+#define I2CP (INTMEM+0x3C80)
+#define MISCP (INTMEM+0x3CB0)
+#define IDMA1P (INTMEM+0x3CC0)
+#define SCC2P (INTMEM+0x3D00)
+#define SPIP (INTMEM+0x3D80)
+#define TIMERP (INTMEM+0x3DB0)
+#define SMC1P (INTMEM+0x3E80)
+#define DSP1P (INTMEM+0x3EC0)
+#define SMC2P (INTMEM+0x3F80)
+#define DSP2P (INTMEM+0x3FC0)
+
+#define KEEP_ALIVE_KEY 0x55ccaa33 /* clock and rtc register key */
+
+#define getpgcolor(a) 0
A mpc/mmu.c => mpc/mmu.c +68 -0
@@ 0,0 1,68 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+
+static void
+taskswitch(ulong pdb, ulong stack)
+{
+ USED(pdb, stack);
+}
+
+void
+mmuinit(void)
+{
+}
+
+void
+flushmmu(void)
+{
+}
+
+static void
+mmuptefree(Proc* proc)
+{
+ USED(proc);
+}
+
+void
+mmuswitch(Proc* proc)
+{
+ USED(proc);
+}
+
+void
+mmurelease(Proc* proc)
+{
+ USED(proc);
+}
+
+static Page*
+mmupdballoc(void)
+{
+}
+
+void
+putmmu(ulong va, ulong pa, Page*)
+{
+ USED(va, pa);
+}
+
+static Lock mmukmaplock;
+
+int
+mmukmapsync(ulong va)
+{
+ USED(va);
+ return 0;
+}
+
+ulong
+mmukmap(ulong pa, ulong va, int size)
+{
+ USED(pa, va, size);
+ return 0;
+}
A mpc/rmap.c => mpc/rmap.c +106 -0
@@ 0,0 1,106 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+void
+mapinit(RMap *rmap, Map *map, int size)
+{
+ lock(rmap);
+ rmap->map = map;
+ rmap->mapend = map+(size/sizeof(Map));
+ unlock(rmap);
+}
+
+void
+mapfree(RMap* rmap, ulong addr, int size)
+{
+ Map *mp;
+ ulong t;
+
+ if(size <= 0)
+ return;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
+ ;
+
+ if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
+ (mp-1)->size += size;
+ if(addr+size == mp->addr){
+ (mp-1)->size += mp->size;
+ while(mp->size){
+ mp++;
+ (mp-1)->addr = mp->addr;
+ (mp-1)->size = mp->size;
+ }
+ }
+ }
+ else{
+ if(addr+size == mp->addr && mp->size){
+ mp->addr -= size;
+ mp->size += size;
+ }
+ else do{
+ if(mp >= rmap->mapend){
+ print("mapfree: %s: losing 0x%uX, %d\n",
+ rmap->name, addr, size);
+ break;
+ }
+ t = mp->addr;
+ mp->addr = addr;
+ addr = t;
+ t = mp->size;
+ mp->size = size;
+ mp++;
+ }while(size = t);
+ }
+ unlock(rmap);
+}
+
+ulong
+rmapalloc(RMap* rmap, ulong addr, int size, int align)
+{
+ Map *mp;
+ ulong maddr, oaddr;
+
+ lock(rmap);
+ for(mp = rmap->map; mp->size; mp++){
+ maddr = mp->addr;
+
+ if(addr){
+ if(maddr > addr)
+ break;
+ if(maddr+mp->size < addr)
+ continue;
+ if(addr+size > maddr+mp->size)
+ break;
+ maddr = addr;
+ }
+
+ if(align > 0)
+ maddr = ((maddr+align-1)/align)*align;
+ if(mp->addr+mp->size-maddr < size)
+ continue;
+
+ oaddr = mp->addr;
+ mp->addr = maddr+size;
+ mp->size -= maddr-oaddr+size;
+ if(mp->size == 0){
+ do{
+ mp++;
+ (mp-1)->addr = mp->addr;
+ }while((mp-1)->size = mp->size);
+ }
+
+ unlock(rmap);
+ if(oaddr != maddr)
+ mapfree(rmap, oaddr, maddr-oaddr);
+
+ return maddr;
+ }
+ unlock(rmap);
+
+ return 0;
+}
A mpc/segment.h => mpc/segment.h +8 -0
@@ 0,0 1,8 @@
+/*
+ * Attach segment types
+ */
+static Physseg physseg[10] = {
+ { SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 },
+ { SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
+};
A mpc/trap.c => mpc/trap.c +133 -0
@@ 0,0 1,133 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+/* Give enough context in the ureg to produce a kernel stack for
+ * a sleeping process
+ */
+void
+setkernur(Ureg* ureg, Proc* p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+}
+
+/* This routine must save the values of registers the user is not permitted to write
+ * from devproc and then restore the saved values before returning
+ */
+void
+setregisters(Ureg* ureg, char* pureg, char* uva, int n)
+{
+ USED(ureg, pureg, uva, n);
+ panic("not done");
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+ USED(ureg);
+ panic("not done");
+}
+
+void
+dumpstack(void)
+{
+ panic("not done");
+}
+
+ulong
+userpc(void)
+{
+ Ureg *ureg;
+
+ ureg = (Ureg*)up->dbgreg;
+ return ureg->pc;
+}
+
+ulong
+dbgpc(Proc *p)
+{
+ Ureg *ureg;
+
+ ureg = p->dbgreg;
+ if(ureg == 0)
+ return 0;
+
+ return ureg->pc;
+}
+
+static void
+linkproc(void)
+{
+ spllo();
+ up->kpfun(up->kparg);
+}
+
+void
+kprocchild(Proc* p, void (*func)(void*), void* arg)
+{
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK;
+
+ p->kpfun = func;
+ p->kparg = arg;
+}
+
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+ USED(p, ureg);
+}
+
+/*
+ * called in sysfile.c
+ */
+void
+evenaddr(ulong addr)
+{
+ if(addr & 3){
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+long
+execregs(ulong entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize);
+ *--sp = nargs;
+
+ ureg = up->dbgreg;
+ ureg->usp = (ulong)sp;
+ ureg->pc = entry;
+ return USTKTOP-BY2WD; /* address of user-level clock */
+}
+
+void
+trap(Ureg *ur)
+{
+ USED(ur);
+}
+
+/*
+ * called directly by l.s:/intrvec
+ */
+void
+intr(Ureg *ur)
+{
+ USED(ur);
+}
+
+void
+intrenable(int v, void (*r)(Ureg*, void*), void *arg, int)
+{
+ USED(v, r, arg);
+}