M mpc/clock.c => mpc/clock.c +48 -0
@@ 67,6 67,41 @@ enum {
static ulong clkreload;
+#ifdef XXX
+ulong
+millisec(void)
+{
+ ulong tbu, tbl, x;
+ vlong t;
+
+ do {
+ tbu = gettbu();
+ tbl = gettbl();
+ } while (gettbu() != tbu);
+ t = (((vlong)tbu)<<32) + tbl;
+
+ t <<= 4;
+ t /= m->oscclk * 1000;
+
+ x = t;
+ if((long)(ledtime-x) < 0)
+ powerdownled();
+
+ return (ulong)t;
+}
+
+#endif
+ulong
+millisec(void)
+{
+ ulong tbl, x;
+
+ tbl = gettbl();
+ x = tbl/((m->oscclk * 1000)/16);
+
+ return x;
+}
+
void
delayloopinit(void)
{
@@ 118,6 153,13 @@ clockintr(Ureg *ur)
m->iomem->swsr = 0xaa39;
m->ticks++;
+
+ if((m->iomem->pddat & SIBIT(15)) == 0) {
+ print("button pressed\n");
+ delay(200);
+ reset();
+ }
+
if(m->proc)
m->proc->pc = ur->pc;
@@ 134,6 176,12 @@ clockintr(Ureg *ur)
unlock(&clock0lock);
}
+ if(m->flushmmu){
+ if(up)
+ flushmmu();
+ m->flushmmu = 0;
+ }
+
if(up == 0 || up->state != Running)
return;
A mpc/cmmu.c => mpc/cmmu.c +391 -0
@@ 0,0 1,391 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+/*
+ * tlb entry 0 is used only by mmuswitch() to set the current tlb pid.
+ */
+
+/*
+ * Kmap entries start at tlb index 1 and work their way up until
+ * kmapinval() removes them. They then restart at 1. As long as there
+ * are few kmap entries they will not pass TLBROFF (the WIRED tlb entry
+ * limit) and interfere with user tlb entries.
+ */
+
+/*
+ * All invalidations of the tlb are via indexed entries. The virtual
+ * address used is always 'KZERO | (x<<(PGSHIFT+1) | currentpid' where
+ * 'x' is the index into the tlb. This ensures that the current pid doesn't
+ * change and that no two invalidated entries have matching virtual
+ * addresses just in case SGI/MIPS ever makes a chip that cares (as
+ * they keep threatening). These entries should never be used in
+ * lookups since accesses to KZERO addresses don't go through the tlb.
+ */
+
+#define TLBINVAL(x, pid) puttlbx(x, KZERO|((x)<<(PGSHIFT+1))|(pid), 0, 0, PGSZ4K)
+
+void
+tlbinit(void)
+{
+ int i;
+
+ for(i=0; i<NTLB; i++)
+ TLBINVAL(i, 0);
+}
+
+Lock kmaplock;
+KMap kpte[KPTESIZE];
+KMap* kmapfree;
+
+void
+kmapinit(void)
+{
+ KMap *k, *klast;
+
+ kmapfree = kpte;
+ klast = &kpte[KPTESIZE-1];
+ for(k=kpte; k<klast; k++)
+ k->next = k+1;
+ k->next = 0;
+
+ m->ktlbnext = TLBROFF;
+}
+
+/*
+ * Arrange that the KMap'd virtual address will hit the same
+ * primary cache line as pg->va by making bits 14...12 of the
+ * tag the same as virtual address. These bits are the index
+ * into the primary cache and are checked whenever accessing
+ * the secondary cache through the primary. Violation causes
+ * a VCE trap.
+ */
+KMap *
+kmap(Page *pg)
+{
+ int s;
+ KMap *k;
+ ulong pte;
+ ulong x, virt;
+
+ s = splhi();
+ lock(&kmaplock);
+
+ if(kmapfree == 0) {
+ unlock(&kmaplock);
+ kmapinval(); /* try and free some */
+ lock(&kmaplock);
+ if(kmapfree == 0)
+ panic("out of kmap");
+ }
+
+ k = kmapfree;
+ kmapfree = k->next;
+
+ k->pg = pg;
+ /* One for the allocation,
+ * One for kactive
+ */
+ k->ref = 2;
+ k->konmach[m->machno] = m->kactive;
+ m->kactive = k;
+
+ virt = pg->va;
+ /* bits 14..12 form the secondary-cache virtual index */
+ virt &= PIDX;
+ virt |= KMAPADDR | ((k-kpte)<<KMAPSHIFT);
+
+ k->virt = virt;
+ pte = PPN(pg->pa)|PTECOHERXCLW|PTEGLOBL|PTEWRITE|PTEVALID;
+ if(virt & BY2PG) {
+ k->phys0 = PTEGLOBL|PTECOHERXCLW;
+ k->phys1 = pte;
+ }
+ else {
+ k->phys0 = pte;
+ k->phys1 = PTEGLOBL|PTECOHERXCLW;
+ }
+
+ x = m->ktlbnext;
+ k->tlbi[m->machno] = x;
+ puttlbx(x, (virt&~BY2PG)|TLBPID(tlbvirt()), k->phys0, k->phys1, PGSZ4K);
+ if(++x >= NTLB)
+ m->ktlbnext = TLBROFF;
+ else
+ m->ktlbnext = x;
+
+ unlock(&kmaplock);
+
+ splx(s);
+ return k;
+}
+
+void
+kunmap(KMap *k)
+{
+ int s;
+
+ s = splhi();
+ if(decref(k) == 0) {
+ k->virt = 0;
+ k->phys0 = 0;
+ k->phys1 = 0;
+ k->pg = 0;
+
+ lock(&kmaplock);
+ k->next = kmapfree;
+ kmapfree = k;
+ unlock(&kmaplock);
+ }
+ splx(s);
+}
+
+void
+kfault(Ureg *ur)
+{
+ int mno;
+ KMap *k, *f;
+ ulong x, index, virt, addr;
+
+ mno = m->machno;
+ addr = ur->badvaddr;
+ index = (addr & ~KMAPADDR) >> KMAPSHIFT;
+
+ if(index >= KPTESIZE)
+ panic("kmapfault: %lux", addr);
+
+ k = &kpte[index];
+ if(k->virt == 0 || k->ref < 1)
+ panic("kmapfault: unmapped %lux", addr);
+
+ for(f = m->kactive; f; f = f->konmach[mno])
+ if(f == k)
+ break;
+
+ if(f == 0) {
+ incref(k);
+ k->konmach[mno] = m->kactive;
+ m->kactive = k;
+ }
+
+ x = m->ktlbnext;
+ virt = (k->virt&~BY2PG)|TLBPID(tlbvirt());
+ puttlbx(x, virt, k->phys0, k->phys1, PGSZ4K);
+ k->tlbi[mno] = x;
+
+ if(++x >= NTLB)
+ m->ktlbnext = TLBROFF;
+ else
+ m->ktlbnext = x;
+}
+
+void
+kmapinval()
+{
+ int mno, curpid;
+ KMap *k, *next;
+
+ if(m->kactive == 0)
+ return;
+
+ curpid = PTEPID(TLBPID(tlbvirt()));
+ mno = m->machno;
+ for(k = m->kactive; k; k = next) {
+ next = k->konmach[mno];
+ TLBINVAL(k->tlbi[mno], curpid);
+ kunmap(k);
+ }
+ m->kactive = 0;
+}
+
+void
+mmuswitch(Proc *p)
+{
+ int tp;
+
+ if(p->newtlb) {
+ memset(p->pidonmach, 0, sizeof p->pidonmach);
+ p->newtlb = 0;
+ }
+ tp = p->pidonmach[m->machno];
+ if(tp == 0)
+ tp = newtlbpid(p);
+
+ puttlbx(0, KZERO|PTEPID(tp), 0, 0, PGSZ4K);
+}
+
+void
+mmurelease(Proc *p)
+{
+ memset(p->pidonmach, 0, sizeof p->pidonmach);
+}
+
+/*
+ * Process must be splhi
+ */
+int
+newtlbpid(Proc *p)
+{
+ int i, s;
+ Proc **h;
+
+ i = m->lastpid;
+ h = m->pidproc;
+ for(s = 0; s < NTLBPID; s++) {
+ i++;
+ if(i >= NTLBPID)
+ i = 1;
+ if(h[i] == 0)
+ break;
+ }
+
+ if(h[i])
+ purgetlb(i);
+ if(h[i] != 0)
+ panic("newtlb");
+
+ m->pidproc[i] = p;
+ p->pidonmach[m->machno] = i;
+ m->lastpid = i;
+
+ return i;
+}
+
+void
+putmmu(ulong tlbvirt, ulong tlbphys, Page *pg)
+{
+ int s;
+ short tp;
+ char *ctl;
+ Softtlb *entry;
+
+ s = splhi();
+ tp = up->pidonmach[m->machno];
+ if(tp == 0)
+ tp = newtlbpid(up);
+
+ /*
+ * Fix up EISA memory address which are greater
+ * than 32 bits physical: 0x100000000
+ */
+ if((tlbphys&0xffff0000) == PPN(Eisamphys)) {
+ tlbphys &= ~PPN(Eisamphys);
+ tlbphys |= 0x04000000;
+ }
+ tlbvirt |= PTEPID(tp);
+ if((tlbphys & PTEALGMASK) != PTEUNCACHED) {
+ tlbphys &= ~PTEALGMASK;
+ tlbphys |= PTECOHERXCLW;
+ }
+
+ entry = putstlb(tlbvirt, tlbphys);
+ puttlb(entry->virt, entry->phys0, entry->phys1);
+
+ ctl = &pg->cachectl[m->machno];
+ switch(*ctl) {
+ case PG_TXTFLUSH:
+ icflush((void*)pg->va, BY2PG);
+ *ctl = PG_NOFLUSH;
+ break;
+ case PG_DATFLUSH:
+ dcflush((void*)pg->va, BY2PG);
+ *ctl = PG_NOFLUSH;
+ break;
+ case PG_NEWCOL:
+ cleancache(); /* Too expensive */
+ *ctl = PG_NOFLUSH;
+ break;
+ }
+ splx(s);
+}
+
+void
+purgetlb(int pid)
+{
+ int i, mno;
+ Proc *sp, **pidproc;
+ Softtlb *entry, *etab;
+
+ m->tlbpurge++;
+
+ /*
+ * find all pid entries that are no longer used by processes
+ */
+ mno = m->machno;
+ pidproc = m->pidproc;
+ for(i=1; i<NTLBPID; i++) {
+ sp = pidproc[i];
+ if(sp && sp->pidonmach[mno] != i)
+ pidproc[i] = 0;
+ }
+
+ /*
+ * shoot down the one we want
+ */
+ sp = pidproc[pid];
+ if(sp != 0)
+ sp->pidonmach[mno] = 0;
+ pidproc[pid] = 0;
+
+ /*
+ * clean out all dead pids from the stlb;
+ */
+ entry = m->stb;
+ for(etab = &entry[STLBSIZE]; entry < etab; entry++)
+ if(pidproc[TLBPID(entry->virt)] == 0)
+ entry->virt = 0;
+
+ /*
+ * clean up the hardware
+ */
+ for(i=TLBROFF; i<NTLB; i++)
+ if(pidproc[TLBPID(gettlbvirt(i))] == 0)
+ TLBINVAL(i, pid);
+}
+
+void
+flushmmu(void)
+{
+ int s;
+
+ s = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(s);
+}
+
+void
+clearmmucache(void)
+{
+}
+
+Softtlb*
+putstlb(ulong tlbvirt, ulong tlbphys)
+{
+ int k;
+ Softtlb *entry;
+
+ k = tlbvirt & BY2PG;
+ tlbvirt &= ~BY2PG;
+
+ entry = &m->stb[(tlbvirt ^ (tlbvirt>>13)) & (STLBSIZE-1)];
+ if(entry->virt != tlbvirt) {
+ entry->virt = tlbvirt;
+ entry->phys0 = 0;
+ entry->phys1 = 0;
+ }
+
+ if(k)
+ entry->phys1 = tlbphys;
+ else
+ entry->phys0 = tlbphys;
+
+ if(entry->phys0 == 0 && entry->phys1 == 0)
+ entry->virt = 0;
+
+ return entry;
+}
A mpc/conf.c => mpc/conf.c +74 -0
@@ 0,0 1,74 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "init.h"
+
+char*
+getconf(char *name)
+{
+ char **p;
+ int n;
+
+ n = strlen(name);
+
+ for(p = conf; *p; p++) {
+ if(strncmp(*p, name, n) == 0 && (*p)[n] == '=')
+ return *p+n+1;
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q, *r;
+
+ strcpy(cc, class);
+ p = cc + strlen(cc);
+ *p++ = ctlrno + '0';
+ *p = 0;
+
+ p = getconf(cc);
+ if(p == 0)
+ return 0;
+
+ 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(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;
+}
M mpc/cpm.c => mpc/cpm.c +152 -149
@@ 365,11 365,11 @@ cpmparam(ulong olda, int nb)
if(olda < INTMEM)
olda += INTMEM;
if(olda != SPIP && olda != I2CP)
- return KADDR(olda);
+ return (void*)(olda);
p = cpmalloc(nb, 32); /* ``RPBASE must be multiple of 32'' */
if(p == nil)
return p;
- *(ushort*)KADDR(olda+0x2C) = PADDR(p); /* set RPBASE */
+ *(ushort*)(olda+0x2C) = PADDR(p); /* set RPBASE */
eieio();
return p;
}
@@ 382,159 382,161 @@ cpmparam(ulong olda, int nb)
* 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,
+/*S30902202000*/ 0x7FFFEFD9,
+/*S30902202004*/ 0x3FFD0000,
+/*S30902202008*/ 0x7FFB49F7,
+/*S3090220200C*/ 0x7FF90000,
+/*S30902202010*/ 0x5FEFADF7,
+/*S30902202014*/ 0x5F88ADF7,
+/*S30902202018*/ 0x5FEFAFF7,
+/*S3090220201C*/ 0x5F88AFF7,
+/*S30902202020*/ 0x3A9CFBC8,
+/*S30902202024*/ 0x77CAE1BB,
+/*S30902202028*/ 0xF4DE7FAD,
+/*S3090220202C*/ 0xABAE9330,
+/*S30902202030*/ 0x4E08FDCF,
+/*S30902202034*/ 0x6E0FAFF8,
+/*S30902202038*/ 0x7CCF76CF,
+/*S3090220203C*/ 0xFDAFF9CF,
+/*S30902202040*/ 0xABF88DC8,
+/*S30902202044*/ 0xAB5879F7,
+/*S30902202048*/ 0xB0926A27,
+/*S3090220204C*/ 0xDFD079F7,
+/*S30902202050*/ 0xB090E6BB,
+/*S30902202054*/ 0xE5BBE74F,
+/*S30902202058*/ 0xAA616F0F,
+/*S3090220205C*/ 0x6FFB76CE,
+/*S30902202060*/ 0xEE0CF9CF,
+/*S30902202064*/ 0x2BFBEFEF,
+/*S30902202068*/ 0xCFEEF9CF,
+/*S3090220206C*/ 0x76CEAD23,
+/*S30902202070*/ 0x90B3DF99,
+/*S30902202074*/ 0x7FDDD0C1,
+/*S30902202078*/ 0x4BF847FD,
+/*S3090220207C*/ 0x7CCF76CE,
+/*S30902202080*/ 0xCFEF77CA,
+/*S30902202084*/ 0x7EAF7FAD,
+/*S30902202088*/ 0x7DFDF0B7,
+/*S3090220208C*/ 0xEF7A7FCA,
+/*S30902202090*/ 0x77CAFBC8,
+/*S30902202094*/ 0x6079E722,
+/*S30902202098*/ 0xFBC85FFF,
+/*S3090220209C*/ 0xDFFF5FB3,
+/*S309022020A0*/ 0xFFFBFBC8,
+/*S309022020A4*/ 0xF3C894A5,
+/*S309022020A8*/ 0xE7C9EDF9,
+/*S309022020AC*/ 0x7F9A7FAD,
+/*S309022020B0*/ 0x5F36AFE8,
+/*S309022020B4*/ 0x5F5BFFDF,
+/*S309022020B8*/ 0xDF95CB9E,
+/*S309022020BC*/ 0xAF7D5FC3,
+/*S309022020C0*/ 0xAFED8C1B,
+/*S309022020C4*/ 0x5FC3AFDD,
+/*S309022020C8*/ 0x5FC5DF99,
+/*S309022020CC*/ 0x7EFDB0B3,
+/*S309022020D0*/ 0x5FB3FFFE,
+/*S309022020D4*/ 0xABAE5FB3,
+/*S309022020D8*/ 0xFFFE5FD0,
+/*S309022020DC*/ 0x600BE6BB,
+/*S309022020E0*/ 0x600B5FD0,
+/*S309022020E4*/ 0xDFC827FB,
+/*S309022020E8*/ 0xEFDF5FCA,
+/*S309022020EC*/ 0xCFDE3A9C,
+/*S309022020F0*/ 0xE7C9EDF9,
+/*S309022020F4*/ 0xF3C87F9E,
+/*S309022020F8*/ 0x54CA7FED,
+/*S309022020FC*/ 0x2D3A3637,
+/*S30902202100*/ 0x756F7E9A,
+/*S30902202104*/ 0xF1CE37EF,
+/*S30902202108*/ 0x2E677FEE,
+/*S3090220210C*/ 0x10EBADF8,
+/*S30902202110*/ 0xEFDECFEA,
+/*S30902202114*/ 0xE52F7D9F,
+/*S30902202118*/ 0xE12BF1CE,
+/*S3090220211C*/ 0x5F647E9A,
+/*S30902202120*/ 0x4DF8CFEA,
+/*S30902202124*/ 0x5F717D9B,
+/*S30902202128*/ 0xEFEECFEA,
+/*S3090220212C*/ 0x5F73E522,
+/*S30902202130*/ 0xEFDE5F73,
+/*S30902202134*/ 0xCFDA0B61,
+/*S30902202138*/ 0x6A29DF61,
+/*S3090220213C*/ 0xE7C9EDF9,
+/*S30902202140*/ 0x7E9A30D5,
+/*S30902202144*/ 0x1458BFFF,
+/*S30902202148*/ 0xF3C85FFF,
+/*S3090220214C*/ 0xDFFFA7F8,
+/*S30902202150*/ 0x5F5BBFFE,
+/*S30902202154*/ 0x7F7D10D0,
+/*S30902202158*/ 0x144D5F33,
+/*S3090220215C*/ 0xBFFFAF78,
+/*S30902202160*/ 0x5F5BBFFD,
+/*S30902202164*/ 0xA7F85F33,
+/*S30902202168*/ 0xBFFE77FD,
+/*S3090220216C*/ 0x30BD4E08,
+/*S30902202170*/ 0xFDCFE5FF,
+/*S30902202174*/ 0x6E0FAFF8,
+/*S30902202178*/ 0x7EEF7E9F,
+/*S3090220217C*/ 0xFDEFF1CF,
+/*S30902202180*/ 0x5F17ABF8,
+/*S30902202184*/ 0x0D5B5F5B,
+/*S30902202188*/ 0xFFEF79F7,
+/*S3090220218C*/ 0x309EAFDD,
+/*S30902202190*/ 0x5F3147F8,
+/*S30902202194*/ 0x5F31AFED,
+/*S30902202198*/ 0x7FDD50AF,
+/*S3090220219C*/ 0x497847FD,
+/*S309022021A0*/ 0x7F9E7FED,
+/*S309022021A4*/ 0x7DFD70A9,
+/*S309022021A8*/ 0xEF7E7ECE,
+/*S309022021AC*/ 0x6BA07F9E,
+/*S309022021B0*/ 0x2D227EFD,
+/*S309022021B4*/ 0x30DB5F5B,
+/*S309022021B8*/ 0xFFFD5F5B,
+/*S309022021BC*/ 0xFFEF5F5B,
+/*S309022021C0*/ 0xFFDF0C9C,
+/*S309022021C4*/ 0xAFED0A9A,
+/*S309022021C8*/ 0xAFDD0C37,
+/*S309022021CC*/ 0x5F37AFBD,
+/*S309022021D0*/ 0x7FBDB081,
+/*S309022021D4*/ 0x5F8147F8,
};
-/*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,
+/*S30902202F00*/ 0x3E303430,
+/*S30902202F04*/ 0x34343737,
+/*S30902202F08*/ 0xABBF9B99,
+/*S30902202F0C*/ 0x4B4FBDBD,
+/*S30902202F10*/ 0x59949334,
+/*S30902202F14*/ 0x9FFF37FB,
+/*S30902202F18*/ 0x9B177DD9,
+/*S30902202F1C*/ 0x936956BB,
+/*S30902202F20*/ 0xFBDD697B,
+/*S30902202F24*/ 0xDD2FD113,
+/*S30902202F28*/ 0x1DB9F7BB,
+/*S30902202F2C*/ 0x36313963,
+/*S30902202F30*/ 0x79373369,
+/*S30902202F34*/ 0x3193137F,
+/*S30902202F38*/ 0x7331737A,
+/*S30902202F3C*/ 0xF7BB9B99,
+/*S30902202F40*/ 0x9BB19795,
+/*S30902202F44*/ 0x77FDFD3D,
+/*S30902202F48*/ 0x573B773F,
+/*S30902202F4C*/ 0x737933F7,
+/*S30902202F50*/ 0xB991D115,
+/*S30902202F54*/ 0x31699315,
+/*S30902202F58*/ 0x31531694,
+/*S30902202F5C*/ 0xBF4FBDBD,
+/*S30902202F60*/ 0x35931497,
+/*S30902202F64*/ 0x35376956,
+/*S30902202F68*/ 0xBD697B9D,
+/*S30902202F6C*/ 0x96931313,
+/*S30902202F70*/ 0x19797937,
+/*S30902202F74*/ 0x69350000,
};
/*
@@ 554,6 556,7 @@ i2cspireloc(void)
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 */
A mpc/cpm2.c => mpc/cpm2.c +819 -0
@@ 0,0 1,819 @@
+#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 */ 0){
+ 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 (void*)(olda);
+ p = cpmalloc(nb, 32); /* ``RPBASE must be multiple of 32'' */
+ if(p == nil)
+ return p;
+ *(ushort*)(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
+ */
+
+static ulong ubase1 = 0x2000;
+
+/*S00600004844521B*/
+static ulong ucode1[] = {
+/*S30902202000*/ 0x3FFF0000,
+/*S30902202004*/ 0x3FFD0000,
+/*S30902202008*/ 0x3FFB0000,
+/*S3090220200C*/ 0x3FF90000,
+/*S30902202010*/ 0x5F13EFF8,
+/*S30902202014*/ 0x5EB5EFF8,
+/*S30902202018*/ 0x5F88ADF7,
+/*S3090220201C*/ 0x5FEFADF7,
+/*S30902202020*/ 0x3A9CFBC8,
+/*S30902202024*/ 0x77CAE1BB,
+/*S30902202028*/ 0xF4DE7FAD,
+/*S3090220202C*/ 0xABAE9330,
+/*S30902202030*/ 0x4E08FDCF,
+/*S30902202034*/ 0x6E0FAFF8,
+/*S30902202038*/ 0x7CCF76CF,
+/*S3090220203C*/ 0xFDAFF9CF,
+/*S30902202040*/ 0xABF88DC8,
+/*S30902202044*/ 0xAB5879F7,
+/*S30902202048*/ 0xB0925D8D,
+/*S3090220204C*/ 0xDFD079F7,
+/*S30902202050*/ 0xB090E6BB,
+/*S30902202054*/ 0xE5BBE74F,
+/*S30902202058*/ 0x9E046F0F,
+/*S3090220205C*/ 0x6FFB76CE,
+/*S30902202060*/ 0xEE0CF9CF,
+/*S30902202064*/ 0x2BFBEFEF,
+/*S30902202068*/ 0xCFEEF9CF,
+/*S3090220206C*/ 0x76CEAD23,
+/*S30902202070*/ 0x90B3DF99,
+/*S30902202074*/ 0x7FDDD0C1,
+/*S30902202078*/ 0x4BF847FD,
+/*S3090220207C*/ 0x7CCF76CE,
+/*S30902202080*/ 0xCFEF77CA,
+/*S30902202084*/ 0x7EAF7FAD,
+/*S30902202088*/ 0x7DFDF0B7,
+/*S3090220208C*/ 0xEF7A7FCA,
+/*S30902202090*/ 0x77CAFBC8,
+/*S30902202094*/ 0x6079E722,
+/*S30902202098*/ 0xFBC85FFF,
+/*S3090220209C*/ 0xDFFF5FB3,
+/*S309022020A0*/ 0xFFFBFBC8,
+/*S309022020A4*/ 0xF3C894A5,
+/*S309022020A8*/ 0xE7C9EDF9,
+/*S309022020AC*/ 0x7F9A7FAD,
+/*S309022020B0*/ 0x5F36AFE8,
+/*S309022020B4*/ 0x5F5BFFDF,
+/*S309022020B8*/ 0xDF95CB9E,
+/*S309022020BC*/ 0xAF7D5FC3,
+/*S309022020C0*/ 0xAFED8C1B,
+/*S309022020C4*/ 0x5FC3AFDD,
+/*S309022020C8*/ 0x5FC5DF99,
+/*S309022020CC*/ 0x7EFDB0B3,
+/*S309022020D0*/ 0x5FB3FFFE,
+/*S309022020D4*/ 0xABAE5FB3,
+/*S309022020D8*/ 0xFFFE5FD0,
+/*S309022020DC*/ 0x600BE6BB,
+/*S309022020E0*/ 0x600B5FD0,
+/*S309022020E4*/ 0xDFC827FB,
+/*S309022020E8*/ 0xEFDF5FCA,
+/*S309022020EC*/ 0xCFDE3A9C,
+/*S309022020F0*/ 0xE7C9EDF9,
+/*S309022020F4*/ 0xF3C87F9E,
+/*S309022020F8*/ 0x54CA7FED,
+/*S309022020FC*/ 0x2D3A3637,
+/*S30902202100*/ 0x756F7E9A,
+/*S30902202104*/ 0xF1CE37EF,
+/*S30902202108*/ 0x2E677FEE,
+/*S3090220210C*/ 0x10EBADF8,
+/*S30902202110*/ 0xEFDECFEA,
+/*S30902202114*/ 0xE52F7D9F,
+/*S30902202118*/ 0xE12BF1CE,
+/*S3090220211C*/ 0x5F647E9A,
+/*S30902202120*/ 0x4DF8CFEA,
+/*S30902202124*/ 0x5F717D9B,
+/*S30902202128*/ 0xEFEECFEA,
+/*S3090220212C*/ 0x5F73E522,
+/*S30902202130*/ 0xEFDE5F73,
+/*S30902202134*/ 0xCFDA0B61,
+/*S30902202138*/ 0x5D8FDF61,
+/*S3090220213C*/ 0xE7C9EDF9,
+/*S30902202140*/ 0x7E9A30D5,
+/*S30902202144*/ 0x1458BFFF,
+/*S30902202148*/ 0xF3C85FFF,
+/*S3090220214C*/ 0xDFFFA7F8,
+/*S30902202150*/ 0x5F5BBFFE,
+/*S30902202154*/ 0x7F7D10D0,
+/*S30902202158*/ 0x144D5F33,
+/*S3090220215C*/ 0xBFFFAF78,
+/*S30902202160*/ 0x5F5BBFFD,
+/*S30902202164*/ 0xA7F85F33,
+/*S30902202168*/ 0xBFFE77FD,
+/*S3090220216C*/ 0x30BD4E08,
+/*S30902202170*/ 0xFDCFE5FF,
+/*S30902202174*/ 0x6E0FAFF8,
+/*S30902202178*/ 0x7EEF7E9F,
+/*S3090220217C*/ 0xFDEFF1CF,
+/*S30902202180*/ 0x5F17ABF8,
+/*S30902202184*/ 0x0D5B5F5B,
+/*S30902202188*/ 0xFFEF79F7,
+/*S3090220218C*/ 0x309EAFDD,
+/*S30902202190*/ 0x5F3147F8,
+/*S30902202194*/ 0x5F31AFED,
+/*S30902202198*/ 0x7FDD50AF,
+/*S3090220219C*/ 0x497847FD,
+/*S309022021A0*/ 0x7F9E7FED,
+/*S309022021A4*/ 0x7DFD70A9,
+/*S309022021A8*/ 0xEF7E7ECE,
+/*S309022021AC*/ 0x6BA07F9E,
+/*S309022021B0*/ 0x2D227EFD,
+/*S309022021B4*/ 0x30DB5F5B,
+/*S309022021B8*/ 0xFFFD5F5B,
+/*S309022021BC*/ 0xFFEF5F5B,
+/*S309022021C0*/ 0xFFDF0C9C,
+/*S309022021C4*/ 0xAFED0A9A,
+/*S309022021C8*/ 0xAFDD0C37,
+/*S309022021CC*/ 0x5F37AFBD,
+/*S309022021D0*/ 0x7FBDB081,
+/*S309022021D4*/ 0x5F8147F8,
+/*S309022021D8*/ 0x3A11E710,
+/*S309022021DC*/ 0xEDF0CCDD,
+/*S309022021E0*/ 0xF3186D0A,
+/*S309022021E4*/ 0x7F0E5F06,
+/*S309022021E8*/ 0x7FEDBB38,
+/*S309022021EC*/ 0x3AFE7468,
+/*S309022021F0*/ 0x7FEDF4FC,
+/*S309022021F4*/ 0x8FFBB951,
+/*S309022021F8*/ 0xB85F77FD,
+/*S309022021FC*/ 0xB0DF5DDD,
+/*S30902202200*/ 0xDEFE7FED,
+/*S30902202204*/ 0x90E1E74D,
+/*S30902202208*/ 0x6F0DCBF7,
+/*S3090220220C*/ 0xE7DECFED,
+/*S30902202210*/ 0xCB74CFED,
+/*S30902202214*/ 0xCFEDDF6D,
+/*S30902202218*/ 0x91714F74,
+/*S3090220221C*/ 0x5DD2DEEF,
+/*S30902202220*/ 0x9E04E7DF,
+/*S30902202224*/ 0xEFBB6FFB,
+/*S30902202228*/ 0xE7EF7F0E,
+/*S3090220222C*/ 0x9E097FED,
+/*S30902202230*/ 0xEBDBEFFA,
+/*S30902202234*/ 0xEB54AFFB,
+/*S30902202238*/ 0x7FEA90D7,
+/*S3090220223C*/ 0x7E0CF0C3,
+/*S30902202240*/ 0xBFFFF318,
+/*S30902202244*/ 0x5FFFDFFF,
+/*S30902202248*/ 0xAC59EFEA,
+/*S3090220224C*/ 0x7FCE1EE5,
+/*S30902202250*/ 0xE2FF5EE1,
+/*S30902202254*/ 0xAFFBE2FF,
+/*S30902202258*/ 0x5EE3AFFB,
+/*S3090220225C*/ 0xF9CC7D0F,
+/*S30902202260*/ 0xAEF8770F,
+/*S30902202264*/ 0x7D0FB0C6,
+/*S30902202268*/ 0xEFFBBFFF,
+/*S3090220226C*/ 0xCFEF5EDE,
+/*S30902202270*/ 0x7D0FBFFF,
+/*S30902202274*/ 0x5EDE4CF8,
+/*S30902202278*/ 0x7FDDD0BF,
+/*S3090220227C*/ 0x49F847FD,
+/*S30902202280*/ 0x7EFDF0BB,
+/*S30902202284*/ 0x7FEDFFFD,
+/*S30902202288*/ 0x7DFDF0B7,
+/*S3090220228C*/ 0xEF7E7E1E,
+/*S30902202290*/ 0x5EDE7F0E,
+/*S30902202294*/ 0x3A11E710,
+/*S30902202298*/ 0xEDF0CCAB,
+/*S3090220229C*/ 0xFB18AD2E,
+/*S309022022A0*/ 0x1EA9BBB8,
+/*S309022022A4*/ 0x74283B7E,
+/*S309022022A8*/ 0x73C2E4BB,
+/*S309022022AC*/ 0x2ADA4FB8,
+/*S309022022B0*/ 0xDC21E4BB,
+/*S309022022B4*/ 0xB2A1FFBF,
+/*S309022022B8*/ 0x5E2C43F8,
+/*S309022022BC*/ 0xFC87E1BB,
+/*S309022022C0*/ 0xE74FFD91,
+/*S309022022C4*/ 0x6F0F4FE8,
+/*S309022022C8*/ 0xC7BA32E2,
+/*S309022022CC*/ 0xF396EFEB,
+/*S309022022D0*/ 0x600B4F78,
+/*S309022022D4*/ 0xE5BB760B,
+/*S309022022D8*/ 0x53ACAEF8,
+/*S309022022DC*/ 0x4EF88B0E,
+/*S309022022E0*/ 0xCFEF9E09,
+/*S309022022E4*/ 0xABF8751F,
+/*S309022022E8*/ 0xEFEF5BAC,
+/*S309022022EC*/ 0x741F4FE8,
+/*S309022022F0*/ 0x751E760D,
+/*S309022022F4*/ 0x7FDBF081,
+/*S309022022F8*/ 0x741CAFCE,
+/*S309022022FC*/ 0xEFCC7FCE,
+/*S30902202300*/ 0x751E70AC,
+/*S30902202304*/ 0x741CE7BB,
+/*S30902202308*/ 0x3372CFED,
+/*S3090220230C*/ 0xAFDBEFEB,
+/*S30902202310*/ 0xE5BB760B,
+/*S30902202314*/ 0x53F2AEF8,
+/*S30902202318*/ 0xAFE8E7EB,
+/*S3090220231C*/ 0x4BF8771E,
+/*S30902202320*/ 0x7E247FED,
+/*S30902202324*/ 0x4FCBE2CC,
+/*S30902202328*/ 0x7FBC30A9,
+/*S3090220232C*/ 0x7B0F7A0F,
+/*S30902202330*/ 0x34D577FD,
+/*S30902202334*/ 0x308B5DB7,
+/*S30902202338*/ 0xDE553E5F,
+/*S3090220233C*/ 0xAF78741F,
+/*S30902202340*/ 0x741F30F0,
+/*S30902202344*/ 0xCFEF5E2C,
+/*S30902202348*/ 0x741F3EAC,
+/*S3090220234C*/ 0xAFB8771E,
+/*S30902202350*/ 0x5E677FED,
+/*S30902202354*/ 0x0BD3E2CC,
+/*S30902202358*/ 0x741CCFEC,
+/*S3090220235C*/ 0xE5CA53CD,
+/*S30902202360*/ 0x6FCB4F74,
+/*S30902202364*/ 0x5DADDE4B,
+/*S30902202368*/ 0x2AB63D38,
+/*S3090220236C*/ 0x4BB3DE30,
+/*S30902202370*/ 0x751F741C,
+/*S30902202374*/ 0x6C42EFFA,
+/*S30902202378*/ 0xEFEA7FCE,
+/*S3090220237C*/ 0x6FFC30BE,
+/*S30902202380*/ 0xEFEC3FCA,
+/*S30902202384*/ 0x30B3DE2E,
+/*S30902202388*/ 0xADF85D9E,
+/*S3090220238C*/ 0xAF7DAEFD,
+/*S30902202390*/ 0x5D9EDE2E,
+/*S30902202394*/ 0x5D9EAFDD,
+/*S30902202398*/ 0x761F10AC,
+/*S3090220239C*/ 0x1DA07EFD,
+/*S309022023A0*/ 0x30ADFFFE,
+/*S309022023A4*/ 0x4908FB18,
+/*S309022023A8*/ 0x5FFFDFFF,
+/*S309022023AC*/ 0xAFBB709B,
+/*S309022023B0*/ 0x4EF85E67,
+/*S309022023B4*/ 0xADF814AD,
+/*S309022023B8*/ 0x7A0F70AD,
+/*S309022023BC*/ 0xCFEF50AD,
+/*S309022023C0*/ 0x7A0FDE30,
+/*S309022023C4*/ 0x5DA0AFED,
+/*S309022023C8*/ 0x3C12780F,
+/*S309022023CC*/ 0xEFEF780F,
+/*S309022023D0*/ 0xEFEF790F,
+/*S309022023D4*/ 0xA7F85E0F,
+/*S309022023D8*/ 0xFFEF790F,
+/*S309022023DC*/ 0xEFEF790F,
+/*S309022023E0*/ 0x14ADDE2E,
+/*S309022023E4*/ 0x5D9EADFD,
+/*S309022023E8*/ 0x5E2DFFFB,
+/*S309022023EC*/ 0xE79ADDFD,
+/*S309022023F0*/ 0xEFF96079,
+/*S309022023F4*/ 0x607AE79A,
+/*S309022023F8*/ 0xDDFCEFF9,
+/*S309022023FC*/ 0x60795DFF,
+/*S30902202400*/ 0x607ACFEF,
+/*S30902202404*/ 0xEFEFEFDF,
+/*S30902202408*/ 0xEFBFEF7F,
+/*S3090220240C*/ 0xEEFFEDFF,
+/*S30902202410*/ 0xEBFFE7FF,
+/*S30902202414*/ 0xAFEFAFDF,
+/*S30902202418*/ 0xAFBFAF7F,
+/*S3090220241C*/ 0xAEFFADFF,
+/*S30902202420*/ 0xABFFA7FF,
+/*S30902202424*/ 0x6FEF6FDF,
+/*S30902202428*/ 0x6FBF6F7F,
+/*S3090220242C*/ 0x6EFF6DFF,
+/*S30902202430*/ 0x6BFF67FF,
+/*S30902202434*/ 0x2FEF2FDF,
+/*S30902202438*/ 0x2FBF2F7F,
+/*S3090220243C*/ 0x2EFF2DFF,
+/*S30902202440*/ 0x2BFF27FF,
+/*S30902202444*/ 0x4E08FD1F,
+/*S30902202448*/ 0xE5FF6E0F,
+/*S3090220244C*/ 0xAFF87EEF,
+/*S30902202450*/ 0x7E0FFDEF,
+/*S30902202454*/ 0xF11F6079,
+/*S30902202458*/ 0xABF8F542,
+/*S3090220245C*/ 0x7E0AF11C,
+/*S30902202460*/ 0x37CFAE3A,
+/*S30902202464*/ 0x7FEC90BE,
+/*S30902202468*/ 0xADF8EFDC,
+/*S3090220246C*/ 0xCFEAE52F,
+/*S30902202470*/ 0x7D0FE12B,
+/*S30902202474*/ 0xF11C6079,
+/*S30902202478*/ 0x7E0A4DF8,
+/*S3090220247C*/ 0xCFEA5DC4,
+/*S30902202480*/ 0x7D0BEFEC,
+/*S30902202484*/ 0xCFEA5DC6,
+/*S30902202488*/ 0xE522EFDC,
+/*S3090220248C*/ 0x5DC6CFDA,
+/*S30902202490*/ 0x4E08FD1F,
+/*S30902202494*/ 0x6E0FAFF8,
+/*S30902202498*/ 0x7C1F761F,
+/*S3090220249C*/ 0xFDEFF91F,
+/*S309022024A0*/ 0x6079ABF8,
+/*S309022024A4*/ 0x761CEE24,
+/*S309022024A8*/ 0xF91F2BFB,
+/*S309022024AC*/ 0xEFEFCFEC,
+/*S309022024B0*/ 0xF91F6079,
+/*S309022024B4*/ 0x761C27FB,
+/*S309022024B8*/ 0xEFDF5DA7,
+/*S309022024BC*/ 0xCFDC7FDD,
+/*S309022024C0*/ 0xD09C4BF8,
+/*S309022024C4*/ 0x47FD7C1F,
+/*S309022024C8*/ 0x761CCFCF,
+/*S309022024CC*/ 0x7EEF7FED,
+/*S309022024D0*/ 0x7DFDF093,
+/*S309022024D4*/ 0xEF7E7F1E,
+/*S309022024D8*/ 0x771EFB18,
+/*S309022024DC*/ 0x6079E722,
+/*S309022024E0*/ 0xE6BBE5BB,
+/*S309022024E4*/ 0xAE0AE5BB,
+/*S309022024E8*/ 0x600BAE85,
+/*S309022024EC*/ 0xE2BBE2BB,
+/*S309022024F0*/ 0xE2BBE2BB,
+/*S309022024F4*/ 0xAF02E2BB,
+/*S309022024F8*/ 0xE2BB2FF9,
+/*S309022024FC*/ 0x6079E2BB,
+};
+
+static ulong ubase2 = 0x2F00;
+static ulong ucode2[] = {
+/*S30902202F00*/ 0x30303030,
+/*S30902202F04*/ 0x3E3E3434,
+/*S30902202F08*/ 0xABBF9B99,
+/*S30902202F0C*/ 0x4B4FBDBD,
+/*S30902202F10*/ 0x59949334,
+/*S30902202F14*/ 0x9FFF37FB,
+/*S30902202F18*/ 0x9B177DD9,
+/*S30902202F1C*/ 0x936956BB,
+/*S30902202F20*/ 0xFBDD697B,
+/*S30902202F24*/ 0xDD2FD113,
+/*S30902202F28*/ 0x1DB9F7BB,
+/*S30902202F2C*/ 0x36313963,
+/*S30902202F30*/ 0x79373369,
+/*S30902202F34*/ 0x3193137F,
+/*S30902202F38*/ 0x7331737A,
+/*S30902202F3C*/ 0xF7BB9B99,
+/*S30902202F40*/ 0x9BB19795,
+/*S30902202F44*/ 0x77FDFD3D,
+/*S30902202F48*/ 0x573B773F,
+/*S30902202F4C*/ 0x737933F7,
+/*S30902202F50*/ 0xB991D115,
+/*S30902202F54*/ 0x31699315,
+/*S30902202F58*/ 0x31531694,
+/*S30902202F5C*/ 0xBF4FBDBD,
+/*S30902202F60*/ 0x35931497,
+/*S30902202F64*/ 0x35376956,
+/*S30902202F68*/ 0xBD697B9D,
+/*S30902202F6C*/ 0x96931313,
+/*S30902202F70*/ 0x19797937,
+/*S30902202F74*/ 0x6935AF78,
+/*S30902202F78*/ 0xB9B3BAA3,
+/*S30902202F7C*/ 0xB8788683,
+/*S30902202F80*/ 0x368F78F7,
+/*S30902202F84*/ 0x87778733,
+/*S30902202F88*/ 0x3FFFFB3B,
+/*S30902202F8C*/ 0x8E8F78B8,
+/*S30902202F90*/ 0x1D118E13,
+/*S30902202F94*/ 0xF3FF3F8B,
+/*S30902202F98*/ 0x6BD8E173,
+/*S30902202F9C*/ 0xD1366856,
+/*S30902202FA0*/ 0x68D1687B,
+/*S30902202FA4*/ 0x3DAF78B8,
+/*S30902202FA8*/ 0x3A3A3F87,
+/*S30902202FAC*/ 0x8F81378F,
+/*S30902202FB0*/ 0xF876F887,
+/*S30902202FB4*/ 0x77FD8778,
+/*S30902202FB8*/ 0x737DE8D6,
+/*S30902202FBC*/ 0xBBF8BFFF,
+/*S30902202FC0*/ 0xD8DF87F7,
+/*S30902202FC4*/ 0xFD876F7B,
+/*S30902202FC8*/ 0x8BFFF8BD,
+/*S30902202FCC*/ 0x8683387D,
+/*S30902202FD0*/ 0xB873D87B,
+/*S30902202FD4*/ 0x3B8FD7F8,
+/*S30902202FD8*/ 0xF7338883,
+/*S30902202FDC*/ 0xBB8EE1F8,
+/*S30902202FE0*/ 0xEF837377,
+/*S30902202FE4*/ 0x3337B836,
+/*S30902202FE8*/ 0x817D11F8,
+/*S30902202FEC*/ 0x7378B878,
+/*S30902202FF0*/ 0xD3368B7D,
+/*S30902202FF4*/ 0xED731B7D,
+/*S30902202FF8*/ 0x833731F3,
+/*S30902202FFC*/ 0xF22F3F23,
+/*S30902202E00*/ 0x27EEEEEE,
+/*S30902202E04*/ 0xEEEEEEEE,
+/*S30902202E08*/ 0xEEEEEEEE,
+/*S30902202E0C*/ 0xEEEEEEEE,
+/*S30902202E10*/ 0xEE4BF4FB,
+/*S30902202E14*/ 0xDBD259BB,
+/*S30902202E18*/ 0x1979577F,
+/*S30902202E1C*/ 0xDFD2D573,
+/*S30902202E20*/ 0xB773F737,
+/*S30902202E24*/ 0x4B4FBDBD,
+/*S30902202E28*/ 0x25B9B177,
+/*S30902202E2C*/ 0xD2D17376,
+/*S30902202E30*/ 0x956BBFDD,
+/*S30902202E34*/ 0x697BDD2F,
+/*S30902202E38*/ 0xFF9F79FF,
+/*S30902202E3C*/ 0xFF9FF22F,
+};
+
+/*
+ * 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 = 0x8080; /* relocate SPI */
+ io->rctr2 = 0x808a; /* relocate SPI */
+ io->rctr3 = 0x8028; /* relocate I2C */
+ io->rctr4 = 0x802a; /* relocate I2C */
+ io->rccr |= 3;
+ done = 1;
+}
M mpc/dat.h => mpc/dat.h +21 -8
@@ 13,10 13,9 @@ typedef struct Map Map;
typedef struct PCArch PCArch;
typedef struct Proc Proc;
typedef struct RMap RMap;
+typedef struct Softtlb Softtlb;
typedef struct Ureg Ureg;
-#define MACHP(n) (n==0? &mach0 : *(Mach**)0)
-
/*
* parameters for sysproc.c
*/
@@ 52,7 51,7 @@ struct Notsave
#define NCOLOR 1
struct PMMU
{
- ulong UNUSED;
+ int pidonmach[MAXMACH];
};
/*
@@ 111,13 110,23 @@ 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 */
+ ulong splpc; /* pc of last caller to splhi */
int mmask; /* 1<<m->machno (unused) */
- Proc *proc; /* current process on this processor */
+ Proc *proc; /* current process on this processor */
+ Softtlb *stb; /* software tlb cache */
+ ulong tlbfault; /* # of tlb faults */
+ ulong dar; /* # of tlb faults */
+ ulong dsisr; /* # of tlb faults */
+ ulong epn;
+ ulong cmp1;
/* ordering from here on irrelevant */
ulong ticks; /* of the clock since boot time */
Label sched; /* scheduler wakeup */
+ QLock stlblk; /* lock for allocating stlb entries on this mach */
+ int lastpid; /* last pid allocated on this machine */
+ int purgepid; /* last pid purged on this machine */
+ Proc* pidproc[NTLBPID]; /* proc that owns tlbpid on this mach */
Lock alarmlock; /* access to alarm list */
void *alarm; /* alarms bound to this clock */
int nrdy;
@@ 132,7 141,6 @@ struct Mach
ulong fairness; /* for runproc */
- int tlbfault;
int tlbpurge;
int pfault;
int cs;
@@ 146,14 154,19 @@ struct Mach
/* MUST BE LAST */
int stack[1];
};
-extern Mach mach0;
+
+struct Softtlb
+{
+ ulong virt;
+ ulong phys;
+};
/*
* Fake kmap
*/
typedef void KMap;
#define VA(k) ((ulong)(k))
-#define kmap(p) (KMap*)((p)->pa)
+#define kmap(p) (KMap*)(((p)->pa)|KZERO)
#define kunmap(k)
/*
M mpc/devether.c => mpc/devether.c +1 -0
@@ 349,6 349,7 @@ etherreset(void)
ether->mbps = 10;
if(isaconfig("ether", ctlrno, ether) == 0)
continue;
+print("etherreset ether%d\n", ctlrno);
for(n = 0; cards[n].type; n++){
if(cistrcmp(cards[n].type, ether->type))
continue;
M mpc/devrtc.c => mpc/devrtc.c +17 -1
@@ 11,6 11,7 @@ enum{
Qrtc = 1,
Qnvram,
Qnvram2,
+ Qled,
/* sccr */
RTDIV= 1<<24,
@@ 29,11 30,11 @@ enum{
static QLock rtclock; /* mutex on clock operations */
static Lock nvrtlock;
-
static Dirtab rtcdir[]={
"rtc", {Qrtc, 0}, 12, 0666,
"nvram", {Qnvram, 0}, Nvsize, 0664,
"nvram2", {Qnvram2, 0}, Nvsize, 0664,
+ "led", {Qled, 0}, 0, 0664,
};
#define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0]))
@@ 77,6 78,7 @@ rtcopen(Chan *c, int omode)
omode = openmode(omode);
switch(c->qid.path){
case Qrtc:
+ case Qled:
if(strcmp(up->user, eve)!=0 && omode!=OREAD)
error(Eperm);
break;
@@ 108,6 110,7 @@ rtcread(Chan *c, void *buf, long n, vlong offset)
n = readnum(offset, buf, n, t, 12);
return n;
case Qnvram:
+ return 0;
if(offset >= Nvsize)
return 0;
t = offset;
@@ 118,6 121,7 @@ rtcread(Chan *c, void *buf, long n, vlong offset)
iunlock(&nvrtlock);
return n;
case Qnvram2:
+ return 0;
if(offset >= Nvsize2)
return 0;
t = offset;
@@ 127,6 131,8 @@ rtcread(Chan *c, void *buf, long n, vlong offset)
memmove(buf, (uchar*)(NVRAMMEM + Nvoff2 + t), n);
iunlock(&nvrtlock);
return n;
+ case Qled:
+ return 0;
}
error(Egreg);
return 0; /* not reached */
@@ 165,6 171,7 @@ rtcwrite(Chan *c, void *buf, long n, vlong offset)
iopunlock();
return n;
case Qnvram:
+ return 0;
if(offset >= Nvsize)
return 0;
t = offset;
@@ 175,6 182,7 @@ rtcwrite(Chan *c, void *buf, long n, vlong offset)
iunlock(&nvrtlock);
return n;
case Qnvram2:
+ return 0;
if(offset >= Nvsize2)
return 0;
t = offset;
@@ 184,6 192,14 @@ rtcwrite(Chan *c, void *buf, long n, vlong offset)
memmove((uchar*)(NVRAMMEM + Nvoff2 + offset), buf, n);
iunlock(&nvrtlock);
return n;
+ case Qled:
+ if(strncmp(buf, "on", 2) == 0)
+ powerupled();
+ else if(strncmp(buf, "off", 3) == 0)
+ powerdownled();
+ else
+ error("unknown command");
+ return n;
}
error(Egreg);
return 0; /* not reached */
M mpc/devsac.c => mpc/devsac.c +19 -8
@@ 6,13 6,6 @@
#include "io.h"
#include "../port/error.h"
-/*
- * Rather than reading /adm/users, which is a lot of work for
- * a toy program, we assume all groups have the form
- * NNN:user:user:
- * meaning that each user is the leader of his own group.
- */
-
enum
{
OPERM = 0x3, /* mask of all permission types in open mode */
@@ 85,7 78,8 @@ enum
Powner = 64,
};
-static uchar *data = SACMEM;
+static char *sacfs = "fs.sac";
+static uchar *data;
static int blocksize;
static Sac root;
static Cache cache[CacheSize];
@@ 104,9 98,26 @@ sacinit(void)
{
SacHeader *hdr;
uchar *p;
+ char *s;
int i;
print("sacinit\n");
+ s = getconf("flash");
+ if(s == nil) {
+ print("devsac: no flash file system\n");
+ return;
+ }
+
+ p = (uchar*)strtoul(s, 0, 0);
+ if(p == 0) {
+ print("devsac: bad address for flash file system\n");
+ return;
+ }
+ data = tarlookup(p, sacfs, &i);
+ if(data == 0) {
+ print("devsac: could not find file: %s\n", sacfs);
+ return;
+ }
hdr = (SacHeader*)data;
if(getl(hdr->magic) != Magic) {
print("devsac: bad magic\n");
M mpc/devuart.c => mpc/devuart.c +13 -8
@@ 279,19 279,24 @@ smcsetup(Uart *up)
up->brgc = brgalloc();
if(up->brgc < 0)
error(Eio);
-// m->bcsr[1] &= ~DisableRS232a; /* enable rs232-1 */
io = ioplock();
- io->pbpar |= IBIT(23)|IBIT(24)|IBIT(25); /* enable SMC1 TX/RX/SYN */
- io->pbdir &= ~(IBIT(23)|IBIT(24)|IBIT(25));
+ /* step 1 */
+ io->papar |= SIBIT(8)|SIBIT(9);
+ io->padir &= ~(SIBIT(8)|SIBIT(9));
+ io->paodr &= ~(SIBIT(8)|SIBIT(9));
+
io->brgc[up->brgc] = baudgen(up->baud, 16) | BaudEnable;
- io->simode = (io->simode & ~0xF000) | (up->brgc<<12); /* SMC1 to NMSI mode, set Tx/Rx clock */
+
+ /* step 3: route clock to SMC2 */
+ io->simode = (io->simode & ~0xF0000000) | (up->brgc<<28);
+
iopunlock();
- up->param = KADDR(SMC1P);
+ up->param = KADDR(SMC2P);
uartsetbuf(up);
- cpmop(InitRxTx, SMC1ID, 0);
+ cpmop(InitRxTx, SMC2ID, 0);
/* SMC protocol parameters */
p = (Uartsmc*)up->param;
@@ 300,12 305,12 @@ smcsetup(Uart *up)
p->brkln = 0;
p->brkec = 0;
p->brkcr = 1;
- smc = IOREGS(0xA80, SMC);
+ smc = IOREGS(0xA90, SMC);
smc->smce = 0xff; /* clear events */
smc->smcm = BSY|RXB|TXB; /* enable all possible interrupts */
up->smc = smc;
smc->smcmr = ((1+8+1-1)<<11)|(2<<4); /* 8-bit, 1 stop, no parity; UART mode */
- intrenable(VectorCPIC+4, smcuintr, up, BUSUNKNOWN);
+ intrenable(VectorCPIC+3, smcuintr, up, BUSUNKNOWN);
smc->smcmr |= 3; /* enable rx/tx */
}
A mpc/devusb.c => mpc/devusb.c +628 -0
@@ 0,0 1,628 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct USBparam USBparam;
+struct USBparam {
+ ushort epptr[4]; /**/
+ ulong rstate;
+ ulong rptr;
+ ushort frame_n; /**/
+ ushort rbcnt;
+ ulong rtemp;
+};
+
+typedef struct EPparam EPparam;
+struct EPparam {
+ ushort rbase;
+ ushort tbase;
+ uchar rfcr;
+ uchar tfcr;
+ ushort mrblr;
+ ushort rbptr;
+ ushort tbptr;
+
+ ulong tstate;
+ ulong tptr;
+ ushort tcrc;
+ ushort tbcnt;
+ ulong res[2];
+};
+
+enum {
+ Nrdre = 8, /* receive descriptor ring entries */
+ Ntdre = 8, /* transmit descriptor ring entries */
+
+ Rbsize = 8+3, /* ring buffer size (+3 for PID+CRC16) */
+ Bufsize = (Rbsize+7)&~7, /* aligned */
+
+ Nendpt = 4,
+};
+
+#define MkPID(x) (((~x&0xF)<<4)|(x&0xF))
+enum {
+ TokIN = MkPID(9),
+ TokOUT = MkPID(1),
+ TokSOF = MkPID(5),
+ TokSETUP = MkPID(0xD),
+ TokDATA0 = MkPID(3),
+ TokDATA1 = MkPID(0xB),
+ TokACK = MkPID(2),
+ TokNAK = MkPID(0xA),
+ TokPRE = MkPID(0xC),
+};
+
+enum {
+ BDData0= 1<<7,
+ BDData1= 1<<6, /* DATA1 if set, DATA0 otherwise */
+ BDrxerr= 0x3F, /* various error flags */
+
+ BDtxcrc= 1<<10,
+ BDcnf= 1<<9, /* transmit confirmation */
+ /* BDData0, BDData1 */
+ BDNak= 1<<4, /* nak received */
+ BDStall= 1<<3, /* stall received */
+ BDTmo= 1<<2, /* timeout */
+ BDUrun= 1<<1, /* underrun */
+
+ /* usmod */
+ EN= 1<<0, /* enable USB */
+ HOST= 1<<1, /* host mode */
+ TEST= 1<<2, /* test mode */
+ RESUME= 1<<6, /* generate resume condition */
+ LSS= 1<<7, /* low-speed signalling */
+
+ /* usber */
+ Freset= 1<<9,
+ Fidle= 1<<8,
+ Ftxe3= 1<<7,
+ Ftxe2= 1<<6,
+ Ftxe1= 1<<5,
+ Ftxe0= 1<<4,
+ Ftxe= Ftxe0|Ftxe1|Ftxe2|Ftxe3,
+ Fsof= 1<<3,
+ Fbsy= 1<<2,
+ Ftxb= 1<<1,
+ Frxb= 1<<0,
+
+ /* uscom */
+ FifoFill= 1<<7,
+ FifoFlush= 1<<6,
+
+ /* USB commands (or'd with USBCmd) */
+ StopTxEndPt = 1<<4,
+ RestartTxEndPt = 2<<4,
+
+ SOFmask= (1<<11)-1,
+};
+
+#define USBABITS (SIBIT(14)|SIBIT(15))
+#define USBRXCBIT (SIBIT(10)|SIBIT(11))
+#define USBTXCBIT (SIBIT(6)|SIBIT(7))
+
+/*
+ * software structures
+ */
+typedef struct Ctlr Ctlr;
+typedef struct Endpt Endpt;
+
+struct Endpt {
+ int x; /* index in Ctlr.pts */
+ int dev; /* remote device (host endpt only) */
+ int endpt; /* remote endpt (host endpt only) */
+ uchar addr[2]; /* crc5<<11 | endpt<<7 | dev */
+ int rtog; /* DATA0 or DATA1 */
+ int xtog; /* DATA0 or DATA1 */
+ int rxintr;
+ Rendez ir;
+ EPparam* ep;
+ Ring;
+
+ Queue* oq;
+ Queue* iq;
+ Ctlr* ctlr;
+};
+
+struct Ctlr {
+ Lock;
+ int init;
+ USB* usb;
+ USBparam *usbp;
+ Endpt pts[4];
+};
+
+static Ctlr usbctlr[1];
+
+static void dumpusb(Block*, char*);
+static void interrupt(Ureg*, void*);
+static void setupep(int, EPparam*);
+static void usbtest(void);
+
+/*
+ * test driver for USB, host mode
+ */
+void
+usbreset(void)
+{
+ IMM *io;
+ USB *usb;
+ USBparam *usbp;
+ EPparam *ep;
+ int brg, i;
+
+ brg = brgalloc();
+ if(brg < 0){
+ print("usb: no baud rate generator is free\n");
+ return;
+ }
+
+ io = m->iomem;
+ usb = (USB*)((ulong)m->iomem+0xA00);
+ usbp = (USBparam*)KADDR(SCC1P);
+
+ /* select port pins */
+ io->padir &= ~USBABITS;
+ io->papar |= USBABITS;
+ io->pcpar = (io->pcpar & ~USBRXCBIT) | USBTXCBIT;
+ io->pcdir = (io->pcdir & ~USBRXCBIT) | USBTXCBIT;
+ io->pcso |= USBRXCBIT;
+ eieio();
+
+ ep = cpmalloc(Nendpt*sizeof(*ep), 32);
+ if(ep == nil){
+ print("can't allocate USB\n");
+ return;
+ }
+print("ep=#%.8ux\n", PADDR(ep));
+
+ usbp->frame_n = 0;
+ usbp->rstate = 0;
+ for(i=0; i<Nendpt; i++){
+ usb->uscom = FifoFlush|i;
+ usb->usep[i] = 0;
+ usbp->epptr[i] = PADDR(ep+i) & 0xffff;
+ ep[i].rbase = 0;
+ ep[i].tbase = 0;
+ ep[i].rfcr = 0x10;
+ ep[i].tfcr = 0x10;
+ ep[i].mrblr = Bufsize;
+ ep[i].rbptr = 0;
+ ep[i].tbptr = 0;
+ ep[i].tstate = 0;
+ ep[i].tptr = 0;
+ }
+
+ usbctlr->usb = usb;
+ usbctlr->usbp = usbp;
+
+ usb->usmod = 0;
+ if(1)
+ usb->usmod = HOST;
+ if(0)
+ usb->usmod |= LSS;
+ if(1)
+ usb->usmod |= TEST|HOST;
+
+ /* set up baud rate generator for appropriate speed */
+ if(usb->usmod & LSS){
+ print("USB: low speed\n");
+ io->brgc[brg] = baudgen(1000000, 1) | BaudEnable;
+ }else
+ io->brgc[brg] = BaudEnable;
+ eieio();
+ io->sicr = (io->sicr & ~(7<<3)) | (brg<<3); /* set R1CS */
+ eieio();
+
+ usb->usep[0] = (0<<12) | (2<<8) | (1<<5); /* EPN=0, TM=bulk, multi frame */
+ setupep(0, ep);
+ if(usb->usmod & TEST){
+ print("USB: loop back mode\n");
+ usb->usep[1] = (1<<12) | (0<<8); /* EPN=1, TM=control*/
+ setupep(1, ep+1);
+ }
+
+ m->bcsr[4] &= ~(DisableUSB|DisableUSBVcc);
+ if(usb->usmod & LSS)
+ m->bcsr[4] &= ~USBFullSpeed;
+ else
+ m->bcsr[4] |= USBFullSpeed;
+ if(usb->usmod & HOST && !(usb->usmod & TEST))
+ usb->usadr = 0x7f; /* unused in host mode, but just in case */
+ else
+ usb->usadr = 0;
+ usb->usber = ~0; /* clear events */
+ intrenable(CPICvec+0x1E, interrupt, usbctlr, BUSUNKNOWN);
+ usb->usbmr = ~0 & ~Fidle; /* enable all events except idle */
+ eieio();
+ delay(12);
+ usb->usmod |= EN;
+}
+
+static void
+setupep(int n, EPparam *ep)
+{
+ Endpt *e;
+
+ e = &usbctlr->pts[n];
+ e->x = n;
+ e->ctlr = usbctlr;
+ e->xtog = TokDATA0;
+ if(e->oq == nil)
+ e->oq = qopen(8*1024, 1, 0, 0);
+ if(e->iq == nil)
+ e->iq = qopen(8*1024, 1, 0, 0);
+ e->ep = ep;
+ if(ioringinit(e, Nrdre, Ntdre, Bufsize) < 0)
+ panic("usbreset");
+ ep->rbase = PADDR(e->rdr);
+ ep->rbptr = ep->rbase;
+ ep->tbase = PADDR(e->tdr);
+ ep->tbptr = ep->tbase;
+ eieio();
+}
+
+static void
+epprod(Ctlr *ctlr, int epn)
+{
+ ctlr->usb->uscom = FifoFill | (epn&3);
+ eieio();
+}
+
+static void
+txstart(Endpt *r)
+{
+ int len, flags;
+ Block *b;
+ BD *dre, *rdy;
+
+ if(r->ctlr->init)
+ return;
+ rdy = nil;
+ while(r->ntq < Ntdre-1){
+ b = qget(r->oq);
+ if(b == 0)
+ break;
+
+ dre = &r->tdr[r->tdrh];
+ if(dre->status & BDReady)
+ panic("txstart");
+print("Tx%d: ", r->x); dumpusb(b, "TX");
+
+ /*
+ * Give ownership of the descriptor to the chip, increment the
+ * software ring descriptor pointer and tell the chip to poll.
+ */
+ flags = 0;
+ switch(b->rp[0]){
+ case TokDATA1:
+ flags = BDData1|BDData0;
+ case TokDATA0:
+ flags |= BDtxcrc|BDcnf|BDReady;
+ flags |= BDData0;
+ /*b->rp++; /* skip DATAn */
+ }
+ len = BLEN(b);
+ dcflush(b->rp, len);
+ if(r->txb[r->tdrh] != nil)
+ panic("usb: txstart");
+ r->txb[r->tdrh] = b;
+ dre->addr = PADDR(b->rp);
+ dre->length = len;
+ eieio();
+ dre->status = (dre->status & BDWrap) | BDInt|BDLast | flags;
+ if(rdy){
+ rdy->status |= BDReady;
+ rdy = nil;
+ }
+ if((flags & BDReady) == 0)
+ rdy = dre;
+ eieio();
+ r->ntq++;
+ r->tdrh = NEXT(r->tdrh, Ntdre);
+ }
+ if(rdy)
+ rdy->status |= BDReady;
+ eieio();
+}
+
+static void
+transmit(Endpt *r)
+{
+ ilock(r->ctlr);
+ txstart(r);
+ iunlock(r->ctlr);
+}
+
+static void
+endptintr(Endpt *r, int events)
+{
+ int len, status;
+ BD *dre;
+ Block *b;
+
+ if(events & Frxb || 1){
+ dre = &r->rdr[r->rdrx];
+ while(((status = dre->status) & BDEmpty) == 0){
+ if(status & BDrxerr || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+ print("usb rx%d: %4.4ux %d ", r->x, status, dre->length);
+ {uchar *p;int i; p=KADDR(dre->addr); for(i=0;i<14&&i<dre->length; i++)print(" %.2ux", p[i]);print("\n");}
+ }
+ else{
+ /*
+ * We have a packet. Read it into the next
+ * free ring buffer, if any.
+ */
+ len = dre->length-2; /* discard CRC */
+ if(len >= 0 && (b = iallocb(len)) != 0){
+ memmove(b->wp, KADDR(dre->addr), len);
+ dcflush(KADDR(dre->addr), len);
+ b->wp += len;
+ // usbiq(ctlr, b);
+ print("rx%d: ", r->x); dumpusb(b, "RX");
+ freeb(b);
+ }
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ dre->length = 0;
+ dre->status = (dre->status & BDWrap) | BDEmpty | BDInt;
+ eieio();
+
+ r->rdrx = NEXT(r->rdrx, Nrdre);
+ dre = &r->rdr[r->rdrx];
+ r->rxintr = 1;
+ wakeup(&r->ir);
+ }
+ }
+
+ /*
+ * Transmitter interrupt: handle anything queued for a free descriptor.
+ */
+ if(events & (Ftxb|Ftxe0|Ftxe1)){
+ lock(r->ctlr);
+ while(r->ntq){
+ dre = &r->tdr[r->tdri];
+ if(dre->status & BDReady)
+ break;
+ print("usbtx%d=#%.4x %8.8lux\n", r->x, dre->status, dre->addr);
+ /* TO DO: error counting */
+ b = r->txb[r->tdri];
+ if(b == nil)
+ panic("usb/interrupt: bufp");
+ r->txb[r->tdri] = nil;
+ freeb(b);
+ r->ntq--;
+ r->tdri = NEXT(r->tdri, Ntdre);
+ }
+ txstart(r);
+ unlock(r->ctlr);
+ if(r->ntq)
+ epprod(r->ctlr, r->x);
+ }
+}
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ int events;
+ Ctlr *ctlr;
+ USB *usb;
+
+ ctlr = arg;
+ usb = ctlr->usb;
+ events = usb->usber;
+ eieio();
+ usb->usber = events;
+ print("USB#%x\n", events);
+
+ if(events & Fsof)
+ print("SOF #%ux\n", ctlr->usbp->frame_n&SOFmask);
+ endptintr(&ctlr->pts[0], events);
+ if(usb->usmod & TEST)
+ endptintr(&ctlr->pts[1], events);
+ if(events & Ftxe0)
+ cpmop(USBCmd|RestartTxEndPt, USBID, 0<<1);
+ if(events & Ftxe1)
+ cpmop(USBCmd|RestartTxEndPt, USBID, 1<<1);
+}
+
+void
+usbinit(void)
+{
+ usbreset();
+usbtest();
+}
+
+static void
+dumpusb(Block *b, char *msg)
+{
+ int i;
+
+ print("%s: %8.8lux [%d]: ", msg, (ulong)b->rp, BLEN(b));
+ for(i=0; i<BLEN(b) && i < 16; i++)
+ print(" %.2x", b->rp[i]);
+ print("\n");
+}
+
+/*
+ * could generate a table, but since the result can be precomputed
+ * per connection, it doesn't seem worthwhile.
+ */
+static ulong
+crc5(ushort v)
+{
+ int i;
+ ulong x, poly;
+
+ x = 0x1F;
+ poly = 0x14;
+ for(i=0; i<11; i++, v>>= 1){
+ if((x^v) & 1)
+ x = ((x>>1)&0x0F)^poly;
+ else
+ x = ((x>>1)&0x0F);
+ }
+ return ~x&0x1F;
+}
+
+static void
+setaddr(Endpt *e, int dev, int endpt)
+{
+ ushort v;
+
+ e->dev = dev;
+ e->endpt = endpt;
+ v = (e->endpt<<7) | e->dev;
+ v |= crc5(v) << 11;
+ e->addr[0] = v;
+ e->addr[1] = v>>8;
+}
+
+/*
+ * Token packets (watch bit/byte order; it's LSB on the wire):
+ *
+ * 4 bit PID, 4 bit check
+ * TokIN, etc.
+ * 7 bit device, 4 bit end point
+ * 5 bit CRC5
+ */
+static void
+sendtoken(Endpt *e, int pid)
+{
+ Block *b;
+
+ b = allocb(3);
+ b->wp[0] = pid;
+ b->wp[1] = e->addr[0];
+ b->wp[2] = e->addr[1];
+ b->wp += 3;
+ if(pid == TokDATA0 || pid == TokDATA1)
+ e->xtog ^= TokDATA1^TokDATA0;
+ else
+ e->xtog = TokDATA0;
+ qbwrite(e->oq, b);
+ /* wait for reply? */
+// transmit(e);
+}
+
+static void
+sendSOF(Endpt *e, int frame)
+{
+ Block *b;
+
+ b = allocb(3);
+ b->wp[0] = TokSOF;
+ frame &= SOFmask;
+ frame |= crc5(frame) << 11;
+ b->wp[1] = frame;
+ b->wp[2] = frame>>8;
+ b->wp += 3;
+ qbwrite(e->oq, b);
+ transmit(e);
+}
+
+static void
+sendack(Endpt *e, int pid)
+{
+ Block *b;
+
+ b = allocb(1);
+ b->wp[0] = pid;
+ b->wp += 1;
+ qbwrite(e->oq, b);
+ /* wait for reply? */
+ transmit(e);
+}
+
+static void
+senddata(Endpt *e, void *buf, long n)
+{
+ Block *b;
+
+ b = allocb(n+4);
+ b->wp += 3; /* skip 3 bytes for word alignment of data */
+ b->rp = b->wp;
+ b->wp[0] = e->xtog;
+ memmove(b->wp+1, buf, n);
+ b->wp += n+1;
+ e->xtog ^= TokDATA1^TokDATA0;
+ qbwrite(e->oq, b);
+ /* wait for reply? */
+ transmit(e);
+ epprod(e->ctlr, e->x);
+}
+
+static int
+usbinput(void *a)
+{
+ return ((Endpt*)a)->rxintr;
+}
+
+static void
+usbtest(void)
+{
+ Ctlr *ctlr;
+ Endpt *e, *e1;
+ uchar msg[8];
+ int epn, testing, i;
+
+ ctlr = usbctlr;
+ epn = 0;
+ testing = ctlr->usb->usmod & TEST;
+ if(testing)
+ epn = 1;
+ e = &ctlr->pts[0];
+ e1 = &ctlr->pts[1];
+ if((ctlr->usb->usmod & LSS) == 0)
+ sendSOF(e, 0);
+ memset(msg, 0, 8);
+ msg[0] = 0;
+ msg[1] = 8; /* set configuration */
+ msg[2] = 1;
+ setaddr(e, 0, epn);
+ sendtoken(e, TokSETUP);
+ senddata(e, msg, 8);
+ if(testing){
+ for(i=0; i<8; i++)
+ msg[i] = 0x40+i;
+ senddata(e1, msg, 8);
+ tsleep(&up->sleep, return0, 0, 3);
+ }
+ if(1){
+ e->rxintr = 0;
+ sendtoken(e, TokIN);
+ transmit(e);
+ epprod(ctlr, 0);
+ tsleep(&e->ir, usbinput, e, 1000);
+ if(!usbinput(e))
+ print("RX: none\n");
+ }
+ sendtoken(e, TokSETUP);
+ msg[0] = 0x23;
+ msg[1] = 3; /* set feature */
+ msg[2] = 8; /* port power */
+ msg[3] = 0;
+ msg[4] = 1; /* port 1 */
+ senddata(e, msg, 8);
+ if(testing){
+ for(i=0; i<8; i++)
+ msg[i] = 0x60+i;
+ senddata(e1, msg, 8);
+ tsleep(&up->sleep, return0, 0, 3);
+ }
+ if(1){
+ e->rxintr = 0;
+ sendtoken(e, TokIN);
+ transmit(e);
+ epprod(ctlr, 0);
+ tsleep(&e->ir, usbinput, e, 1000);
+ if(!usbinput(e))
+ print("RX: none\n");
+ }
+}
M mpc/ether589.c => mpc/ether589.c +18 -46
@@ 111,11 111,8 @@ configASIC(Ether* ether, int port, int xcvr)
static int
reset(Ether* ether)
{
- int i, slot;
+ int slot;
int port;
- enum { WantAny, Want10BT, Want10B2 };
- int want;
- char *p;
if(ether->irq == 0)
ether->irq = 10;
@@ 123,56 120,31 @@ reset(Ether* ether)
ether->port = 0x240;
port = ether->port;
- if(ioalloc(port, 0x10, 0, "3C589") < 0)
+ if((slot = pcmspecial(ether->type, ether)) < 0)
return -1;
- if((slot = pcmspecial(ether->type, ether)) < 0){
- iofree(port);
+ /* try configuring as a 10BaseT */
+ if(configASIC(ether, port, xcvr10BaseT) < 0){
+ pcmspecialclose(slot);
return -1;
}
-
- /*
- * Allow user to specify desired media in plan9.ini
- */
- want = WantAny;
- for(i = 0; i < ether->nopt; i++){
- if(cistrncmp(ether->opt[i], "media=", 6) != 0)
- continue;
- p = ether->opt[i]+6;
- if(cistrcmp(p, "10base2") == 0)
- want = Want10B2;
- else if(cistrcmp(p, "10baseT") == 0)
- want = Want10BT;
- }
-
- /* try configuring as a 10BaseT */
- if(want==WantAny || want==Want10BT){
- if(configASIC(ether, port, xcvr10BaseT) < 0){
- pcmspecialclose(slot);
- iofree(port);
- return -1;
- }
- delay(100);
- COMMAND(port, SelectRegisterWindow, Wdiagnostic);
- if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
- COMMAND(port, SelectRegisterWindow, Wop);
- print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, ether->type);
- return 0;
- }
+ delay(100);
+ COMMAND(port, SelectRegisterWindow, Wdiagnostic);
+ if(ins(port+MediaStatus) & linkBeatDetect){
+ COMMAND(port, SelectRegisterWindow, Wop);
+ print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, ether->type);
+ return 0;
}
/* try configuring as a 10base2 */
- if(want==WantAny || want==Want10B2){
- COMMAND(port, GlobalReset, 0);
- if(configASIC(ether, port, xcvr10Base2) < 0){
- pcmspecialclose(slot);
- iofree(port);
- return -1;
- }
- print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, ether->type);
- return 0;
+ COMMAND(port, GlobalReset, 0);
+ if(configASIC(ether, port, xcvr10Base2) < 0){
+ pcmspecialclose(slot);
+ return -1;
}
- return -1; /* not reached */
+ print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, ether->type);
+
+ return 0;
}
void
M mpc/etherif.h => mpc/etherif.h +1 -1
@@ 1,5 1,5 @@
enum {
- MaxEther = 24,
+ MaxEther = 4,
Ntypes = 8,
};
M mpc/etherscc.c => mpc/etherscc.c +88 -45
@@ 137,10 137,10 @@ attach(Ether *ether)
static void
closed(Ether *ether)
{
- Ctlr *ctlr;
-
- ctlr = ether->ctlr;
if(0){
+ Ctlr *ctlr;
+
+ ctlr = ether->ctlr;
if(ether->port == 2)
scc2stop(ctlr->scc);
ilock(ctlr);
@@ 268,15 268,14 @@ interrupt(Ureg*, void *arg)
ctlr->overrun++;
if(events & TXE)
ether->oerrs++;
- if(0 || events & TXE)
- print("ETHER.SCC#%d: scce = 0x%uX\n", ether->ctlrno, events);
}
+
/*
* Receiver interrupt: run round the descriptor ring logging
* errors and passing valid receive data up to the higher levels
* until we encounter a descriptor still owned by the chip.
*/
- if(events & (RXF|RXB) || 1){
+ if(events & (RXF|RXB)){
dre = &ctlr->rdr[ctlr->rdrx];
while(((status = dre->status) & BDEmpty) == 0){
if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
@@ 288,7 287,7 @@ interrupt(Ureg*, void *arg)
ether->crcs++;
if(status & RxeOV)
ether->overflows++;
- //print("eth rx: %ux\n", status);
+ print("eth rx: %ux\n", status);
}
else{
/*
@@ 320,7 319,7 @@ interrupt(Ureg*, void *arg)
/*
* Transmitter interrupt: handle anything queued for a free descriptor.
*/
- if(events & TXB){
+ if(events & (TXB|TXE)){
lock(ctlr);
while(ctlr->ntq){
dre = &ctlr->tdr[ctlr->tdri];
@@ 348,11 347,13 @@ interrupt(Ureg*, void *arg)
ctlr->ntq--;
ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
}
+
+ if(events & TXE)
+ cpmop(RestartTx, ctlr->sccid, 0);
+
txstart(ether);
unlock(ctlr);
}
- if(events & TXE)
- cpmop(RestartTx, ctlr->sccid, 0);
}
static long
@@ 391,52 392,84 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
static void
sccsetup(Ctlr *ctlr, SCC *scc, uchar *ea)
{
- int i, rcs, tcs;
+ int i;
Etherparam *p;
IMM *io;
io = ioplock();
- p = (Etherparam*)KADDR(SCC1P);
-
- if(ctlr->port != 1)
- panic("only do SCC1 at the momment");
-
- // step 1: enable TXD RXD ports
- io->papar |= SIBIT(14)|SIBIT(15);
- io->padir &= ~(SIBIT(14)|SIBIT(15));
- io->paodr &= ~SIBIT(14);
-
- // step 2: enable CLSN and RENA ports
- io->pcpar &= ~(SIBIT(11)|SIBIT(10));
- io->pcdir &= ~(SIBIT(11)|SIBIT(10));
- io->pcso |= SIBIT(11)|SIBIT(10);
- eieio();
-
- // setp 3
- io->pcpar &= ~SIBIT(15); /* disble TENA pin */
- // step 4: enable clocks
- io->papar |= SIBIT(6)|SIBIT(4); /* enable CLK2 and CLK4 */
- io->padir &= ~(SIBIT(6)|SIBIT(4));
- eieio();
-
- // step 5/6: route clocks
- io->sicr = (7<<3) | (5);
- eieio();
+ switch(ctlr->port) {
+ default:
+ iopunlock();
+ return;
+ case 2:
+ p = (Etherparam*)(SCC2P);
+
+ // step 1: enable TXD RXD ports
+ io->papar |= SIBIT(12)|SIBIT(13);
+ io->padir &= ~(SIBIT(12)|SIBIT(13));
+ io->paodr &= ~(SIBIT(12)|SIBIT(13));
+
+ // step 2: enable CLSN and RENA ports
+ io->pcpar &= ~(SIBIT(8)|SIBIT(9));
+ io->pcdir &= ~(SIBIT(8)|SIBIT(9));
+ io->pcso |= SIBIT(8)|SIBIT(9);
+
+ // setp 3: disble TENA pin */
+ io->pcpar &= ~SIBIT(14);
+ io->pcdir &= ~SIBIT(14);
+
+ // step 4: enable clocks CLK3 and CLK4
+ io->papar |= SIBIT(6)|SIBIT(7);
+ io->padir &= ~(SIBIT(6)|SIBIT(7));
+
+ // step 5/6: route clocks
+ iopunlock();
+ sccnmsi(2, CLK1, CLK2); /* connect the clocks */
+ io = ioplock();
+ break;
+
+ case 3:
+ p = (Etherparam*)KADDR(SCC3P);
+
+ // step 1: enable TXD RXD ports
+ io->pbpar |= IBIT(24)|IBIT(25);
+ io->pbdir |= IBIT(24)|IBIT(25);
+ io->pbodr &= ~(IBIT(24)|IBIT(25));
+
+ // step 2: enable CLSN and RENA ports
+ io->pcpar &= ~(SIBIT(4)|SIBIT(5));
+ io->pcdir &= ~(SIBIT(4)|SIBIT(5));
+ io->pcso |= SIBIT(4)|SIBIT(5);
+ eieio();
+
+ // setp 3
+ io->pcpar &= ~SIBIT(13);
+ io->pcdir &= ~SIBIT(13);
+
+ // step 4: enable clocks
+ io->papar |= SIBIT(4)|SIBIT(5);
+ io->padir &= ~(SIBIT(4)|SIBIT(5));
+ eieio();
+
+ // step 5/6: route clocks
+ iopunlock();
+ sccnmsi(3, CLK3, CLK4);
+ io = ioplock();
+ break;
+ }
// step 7: set dma priority
io->sdcr = 1;
-
+
iopunlock();
-// sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
-
// step 8:
p->rbase = PADDR(ctlr->rdr);
p->tbase = PADDR(ctlr->tdr);
// step 9:
- cpmop(InitRxTx, SCC1ID, 0);
+ cpmop(InitRxTx, sccid[ctlr->port], 0);
// step 10
p->rfcr = 0x18; // manuals say 0x10
@@ 514,9 547,17 @@ sccsetup(Ctlr *ctlr, SCC *scc, uchar *ea)
// step 33:
scc->psmr = 0x080A; /* 32-bit CRC, non-promiscuous */
- // step 34
- io->pcpar |= SIBIT(15); /* enable TENA pin (RTS2) */
- io->pcdir &= ~SIBIT(15);
+ // step 34: enable TENA
+ switch(ctlr->port) {
+ case 2:
+ io->pcpar |= SIBIT(14);
+ io->pcdir &= ~SIBIT(14);
+ break;
+ case 3:
+ io->pcpar |= SIBIT(13);
+ io->pcdir &= ~SIBIT(13);
+ break;
+ }
// step 35: done at attach time
}
@@ 528,6 569,8 @@ reset(Ether* ether)
Ctlr *ctlr;
SCC *scc;
+print("etherscc: reset\n");
+
if(m->speed < 24){
print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type);
return -1;
@@ 583,5 626,5 @@ void
etherscclink(void)
{
addethercard("SCC", reset);
-// addethercard("SCC2", reset);
+// addethercard("SCC3", reset);
}
M mpc/fns.h => mpc/fns.h +7 -8
@@ 18,6 18,7 @@ void dcflush(void*, ulong);
void delay(int);
ulong draminit(ulong*);
void dtlbmiss(void);
+void dtlberror(void);
void dumpregs(Ureg*);
void delayloopinit(void);
void eieio(void);
@@ 43,10 44,6 @@ void gotopc(ulong);
void icflush(void*, ulong);
void idle(void);
#define idlehands() /* nothing to do in the runproc */
-void iofree(int);
-void ioinit(void);
-int iounused(int, int);
-int ioalloc(int, int, int, char*);
int inb(int);
void insb(int, void*, int);
ushort ins(int);
@@ 84,6 81,7 @@ void procsave(Proc*);
void procsetup(Proc*);
void putdec(ulong);
void putmsr(ulong);
+void putcasid(ulong);
ulong rmapalloc(RMap*, ulong, int, int);
void screeninit(void);
void setpanic(void);
@@ 94,19 92,20 @@ int segflush(void*, ulong);
void spireset(void);
long spioutin(void*, long, void*);
int tas(void*);
+uchar* tarlookup(uchar *addr, char *file, int *dlen);
void touser(void*);
void trapinit(void);
void trapvec(void);
+void tlbflush(ulong);
+void tlbflushall(void);
void uartinstall(void);
void uartwait(void); /* debugging */
int unsac(uchar *dst, uchar *src, int n, int nsrc);
void wbflush(void);
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
-
-// identity map between kernel physical and virtual addresses
-#define KADDR(a) ((void*)(a))
-#define PADDR(a) ((ulong)(a))
+#define KADDR(a) ((void*)((ulong)(a)|KZERO))
+#define PADDR(a) ((ulong)(a)&~KZERO)
/* IBM bit field order */
#define IBIT(b) ((ulong)1<<(31-(b)))
M mpc/l.s => mpc/l.s +471 -216
@@ 4,8 4,8 @@
* common ppc special purpose registers
*/
#define DSISR 18
-#define DAR 19 /* Data Address Register */
-#define DEC 22 /* Decrementer */
+#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 */
@@ 51,6 51,27 @@
#define MD_DBRAM0 825
#define MD_DBRAM1 826
+/*
+ * mpc8xx specific debug-level SPRs
+ */
+#define CMPA 144
+#define CMPB 145
+#define CMPC 146
+#define CMPD 147
+#define ICR 148
+#define DER 149
+#define COUNTA 150
+#define COUNTB 151
+#define CMPE 152
+#define CMPF 153
+#define CMPG 154
+#define CMPH 155
+#define LCTRL1 156
+#define LCTRL2 157
+#define ICTRL 158
+#define BAR 159
+#define DPDR 630
+
/* use of SPRG registers in save/restore */
#define SAVER0 SPRG0
#define SAVER1 SPRG1
@@ 66,21 87,46 @@
/* on some models mtmsr doesn't synchronise enough (eg, 603e) */
#define MSRSYNC SYNC; ISYNC
+/*
+ * The following code assume that the MPC8xx processor has been
+ * configured to a certain extent. In particular, we assume the following
+ * following registers have been set up.
+ *
+ * SIU
+ * SIUMCR
+ * SYPCR
+ *
+ */
+
#define UREGSPACE (UREGSIZE+8)
TEXT start(SB), $-4
- /* turn off interrupts but enable traps */
+ /*
+ * setup MSR
+ * turn off interrupts
+ * use 0x000 as exception prefix
+ * enable machine check
+ */
MOVW MSR, R3
- MOVW $~(MSR_EE|MSR_FP), R4
- AND R4, R3
- OR $(MSR_IP|MSR_ME), R3
+ MOVW $(MSR_EE|MSR_IP), R4
+ ANDN R4, R3
+ OR $(MSR_ME), R3
ISYNC
MOVW R3, MSR
MSRSYNC
- MOVW $0, R0 /* except during trap handling, R0 is zero from now on */
+ /* set internal memory base */
+ MOVW $INTMEM, R4
+ MOVW R4, SPR(IMMR)
+
+ /* except during trap handling, R0 is zero from now on */
+ MOVW $0, R0
+
+ /* setup SB for pre mmu */
MOVW $setSB(SB), R2
+ MOVW $KZERO, R3
+ ANDN R3, R2
/*
* reset the caches and disable them for now
@@ 112,113 158,130 @@
ISYNC
MOVW $7, R4
- MOVW R4, SPR(158) /* cancel `show cycle' for normal instruction execution */
+ MOVW R4, SPR(ICTRL) /* cancel `show cycle' for normal instruction execution */
+ ISYNC
+ MOVW R4, SPR(DER)
+ ISYNC
+ BL mmuinit0(SB)
+
+ /* running with MMU on!! */
+
+ /* set R2 to it correct value */
+ MOVW $setSB(SB), R2
+
+ /* enable i-cache */
+ MOVW $(1<<25), R4
+ MOVW R4, SPR(IC_CST)
+ ISYNC
+
+ /* enable d-cache */
+ MOVW $(2<<24), R4
+ MOVW R4, SPR(DC_CST)
ISYNC
+
/*
* set other system configuration values
*/
- MOVW $INTMEM, R4
- MOVW R4, SPR(IMMR) /* set internal memory base */
- MOVW $mach0(SB), R(MACH)
+
+/*
+ * setup mach
+ */
+ MOVW $MACHADDR, R(MACH)
ADD $(MACHSIZE-8), R(MACH), R1 /* set stack */
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))
+ /* zero bss */
MOVW $edata(SB), R3
MOVW $end(SB), R4
- ADD $4, R4
+ SUBCC R3, R4
+ BLE skipz
+ SRAW $2, R4
+ MOVW R4, CTR
SUB $4, R3
-clrbss:
+zero:
MOVWU R0, 4(R3)
- CMP R3, R4
- BNE clrbss
+ BDNZ zero
+skipz:
/* off to main */
BL main(SB)
BR 0(PC)
-
-TEXT kernelmmu(SB), $0
+/*
+ * on return from this function we will be running in virtual mode.
+ * We setup two TLB entries:
+ * 1) map the first 8Mb of RAM to KZERO
+ * 2) map the region that contains the IMMR
+ */
+TEXT mmuinit0(SB), $0
+ /* reset all the tlbs */
+ TLBIA
/* dont use CASID yet - set to zero for now */
MOVW $0, R4
MOVW R4, SPR(M_CASID)
- /* set Ks = 0 Kp = 1 for all acess groups */
+ /* set Ks = 0 Kp = 1 for all access groups */
MOVW $0x55555555, R4
MOVW R4, SPR(MI_AP)
MOVW R4, SPR(MD_AP)
/*
* set:
- * PowerPC mode
- * Page protection mode - no 1K pages
- * ~CI when MMU is disbaled
- * WT when DMMU is disbaled - this will change
- * disable protected TLB for the momment
- * ignore user/supervisor state when looking for TLB
- * set first tlb entry to 28 - first lockable entry
+ * GPM = 0: PowerPC mode
+ * PPM = 0: Page protection mode - no 1K pages
+ * CIDEF = 0: cache enable when MMU disabled
+ * WTDEF = 0: write back when MMU is disbaled
+ * RSV2 = 0: no reserved entries
+ * TWAM = 0: don't use table walk assit
+ * PPCS = 0: not used in PowerPC mode
+ * INDX = 0: start at first entry
*/
- MOVW $((31<<8)), R4
- MOVW R4, SPR(MI_CTR) /* i-mmu control */
- ISYNC
- MOVW $((31<<8)), R4
- MOVW R4, SPR(MD_CTR) /* d-mmu control */
- ISYNC
-
- /* map various things 1:1 */
- MOVW $tlbtab(SB), R4
- MOVW $tlbtabe(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
-
- /* lock kernel entries in tlb - also reset tlb index*/
- MOVW $(MMURSV4), R4
+ MOVW $0, R4
MOVW R4, SPR(MI_CTR) /* i-mmu control */
- ISYNC
- MOVW $(MMURSV4), R4
+ MOVW $0, R4
MOVW R4, SPR(MD_CTR) /* d-mmu control */
- ISYNC
-
- /* enable i-cache */
- MOVW $(1<<25), R4
- MOVW R4, SPR(IC_CST)
- ISYNC
- /* enable d-cache */
- MOVW $(1<<25), R4
- MOVW R4, SPR(DC_CST)
- ISYNC
+ /*
+ * map 8Mb of ram at 0 -> KZERO, cached, writeback, shared
+ */
+ MOVW $(KZERO|MMUEV), R4
+ MOVW R4, SPR(MD_EPN)
+ MOVW R4, SPR(MI_EPN)
+ MOVW $(MMUPS8M|MMUV), R4 /* |MMUWT */
+ MOVW R4, SPR(MD_TWC)
+ MOVW R4, SPR(MI_TWC)
+ MOVW $(0|MMUPP|MMUSPS|MMUSH|MMUV), R4
+ MOVW R4, SPR(MD_RPN)
+ MOVW R4, SPR(MI_RPN)
- /* enable MMU */
+ /*
+ * map 8mb IO at INTMEM->INTMEM, cache inhibit, shared
+ */
+ MOVW $(INTMEM|MMUEV), R4
+ MOVW R4, SPR(MD_EPN)
+ MOVW $(MMUPS8M|MMUWT|MMUV), R4
+ MOVW R4, SPR(MD_TWC)
+ MOVW $(INTMEM|MMUPP|MMUSPS|MMUSH|MMUCI|MMUV), R4
+ MOVW R4, SPR(MD_RPN)
+
+ /* enable MMU */
+ MOVW LR, R3
+ OR $KZERO, R3
+ MOVW R3, SPR(SRR0)
MOVW MSR, R4
OR $(MSR_IR|MSR_DR), R4
- MOVW R4, MSR
- ISYNC
+ MOVW R4, SPR(SRR1)
+ RFI /* resume in kernel mode in caller */
RETURN
@@ 282,57 345,12 @@ TEXT gotolabel(SB), $-4
TEXT touser(SB), $-4
MOVW $(UTZERO+32), R5 /* header appears in text */
- MOVW $(MSR_EE|MSR_PR|MSR_ME|MSR_IP|MSR_IR|MSR_DR|MSR_RI), R4
+ MOVW $(MSR_EE|MSR_PR|MSR_ME|MSR_IR|MSR_DR|MSR_RI), R4
MOVW R4, SPR(SRR1)
MOVW R3, R1
MOVW R5, SPR(SRR0)
RFI
-/*
- * 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 $mach0(SB), R(MACH)
- MOVW 12(R(MACH)), R(USER)
- 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
@@ 349,7 367,6 @@ icf0: ICBI (R5)
RETURN
TEXT dcflush(SB), $-4 /* dcflush(virtaddr, count) */
- SYNC
MOVW n+4(FP), R4
RLWNM $0, R3, $~(CACHELINESZ-1), R5
CMP R4, $0
@@ 362,15 379,13 @@ TEXT dcflush(SB), $-4 /* dcflush(virtaddr, count) */
dcf0: DCBF (R5)
ADD $CACHELINESZ, R5
BDNZ dcf0
- SYNC
- ISYNC
dcf1:
RETURN
TEXT tas(SB), $0
SYNC
MOVW R3, R4
- MOVW $0xdeaddead,R5
+ MOVW $0xdead,R5
tas1:
DCBF (R4) /* fix for 603x bug */
LWAR (R4), R3
@@ 423,6 438,14 @@ TEXT getmsr(SB), $0
MOVW MSR, R3
RETURN
+TEXT putder(SB), $0
+ MOVW R3, SPR(DER)
+ RETURN
+
+TEXT getder(SB), $0
+ MOVW SPR(DER), R3
+ RETURN
+
TEXT putmsr(SB), $0
SYNC
MOVW R3, MSR
@@ 433,55 456,38 @@ TEXT eieio(SB), $0
EIEIO
RETURN
-TEXT _flushmmu(SB), $0
+TEXT tlbflushall(SB), $0
TLBIA
RETURN
-TEXT _putmmu(SB), $0
- MOVW MSR, R7
- MOVW $~(MSR_DR|MSR_IR), R8
- AND R7, R8
- MOVW R8, MSR
- OR $MMUEV, R3
- MOVW R3, SPR(MD_EPN)
- MOVW R3, SPR(MI_EPN)
- MOVW $(MMUWT|MMUV), R5
- MOVW R5, SPR(MI_TWC)
- MOVW R5, SPR(MD_TWC)
- MOVW 4(FP), R6
- MOVW R6, SPR(MD_RPN)
- MOVW R6, SPR(MI_RPN)
- MOVW SPR(MD_CTR), R3
- MOVW R7, MSR
+TEXT tlbflush(SB), $0
+ TLBIE R3
RETURN
+TEXT putcasid(SB), $-4
+ MOVW LR, R4
+ MOVW MSR, R5
+ BL nommu(SB)
+ MOVW R3, SPR(M_CASID)
+ MOVW R4, SPR(SRR0)
+ MOVW R5, SPR(SRR1)
+ RFI
+
+TEXT nommu(SB), $-4
+ MOVW LR, R6
+ RLWNM $0, R6, $~KZERO, R6
+ MOVW $(MSR_DR|MSR_IR), R8
+ MOVW R5, R7
+ ANDN R8, R7
+ MOVW R6, SPR(SRR0)
+ MOVW R7, SPR(SRR1)
+ RFI
+
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
@@ 532,79 538,244 @@ TEXT lesets(SB), $0
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
+ MOVW R1, SPR(SAVER1)
+ MOVW R2, SPR(M_TW)
/*
- * DTLB miss
- * avoid references that might need the right SB value;
- * IR and DR are off.
- */
+ to enable hardware break points
+ MOVW MSR, R1
+ OR $(MSR_RI), R1
+ MOVW R1, MSR
+ ISYNC
+*/
+
+ /* m->tlbfault++ */
+ MOVW $(MACHADDR&~KZERO), R1 /* m-> */
+ MOVW 20(R1), R2
+ ADD $1, R2
+ MOVW R2, 20(R1)
+
+ MOVW CR, R2
+ MOVW SPR(MI_EPN), R1
+ MOVW R1, CR
+ BC 4,0,itlblookup
+ /*
+ * map ram
+ */
+ MOVW R2, CR
+ MOVW $(MMUPS8M|MMUV), R2
+ MOVW R2, SPR(MI_TWC)
+ RLWNM $0, R1, $0x7f800000, R1
+ OR $(MMUPP|MMUSPS|MMUSH|MMUV), R1
+ MOVW R1, SPR(MI_RPN)
+ MOVW SPR(M_TW), R2
+ MOVW SPR(SAVER1), R1
+ RFI
+
+itlblookup:
+ MOVW R0, SPR(SAVER0)
+ MOVW R3, SPR(SAVEXX)
+
+ /*
+ * R1 = 20 bits of addr | 8 bits of junk | 4 bits of asid
+ * calulate ((x>>9)^(x>>21)^(x<<11)) & (0xfff<<3)
+ * note (x>>21)^(x<<11) = rotate left 11
+ */
+ RLWNM $(32-9), R1, $(0xfff<<3), R3
+ RLWNM $11, R1, $(0xfff<<3), R1
+ XOR R1, R3, R1
+ MOVW $(MACHADDR&~KZERO), R3 /* m-> */
+ MOVW 16(R3), R3 /* m->stb */
+ RLWNM $0, R3, $~KZERO, R3 /* PADDR(m->stb) */
+ ADD R1, R3
+ MOVW 4(R3), R0
+ MOVW 0(R3), R3
+ MOVW SPR(MI_EPN), R1
+ RLWNM $20, R1, $0xffffff, R1
+ RLWNM $12, R1, $~0, R1
+ CMP R3, R1
+ BNE itlbtrap
+ MOVW R2, CR
+ MOVW $(MMUV), R1
+ MOVW R1, SPR(MI_TWC)
+ MOVW R0, SPR(MI_RPN)
+ MOVW SPR(SAVEXX), R3
+ MOVW SPR(M_TW), R2
+ MOVW SPR(SAVER1), R1
+ MOVW SPR(SAVER0), R0
+ RFI
+itlbtrap:
+ MOVW R2, CR
+
+ MOVW $(MACHADDR&~KZERO), R2 /* m-> */
+ MOVW R1, 32(R2)
+ MOVW R3, 36(R2)
+
+ MOVW SPR(SAVEXX), R3
+ MOVW SPR(M_TW), R2
+ MOVW LR, R0
+ MOVW R0, SPR(SAVELR)
+ MOVW $0x1100, R0
+ BR traps
+
+
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
+
+ MOVW R1, SPR(SAVER1)
+ MOVW R2, SPR(M_TW)
+/*
+ to enable hardware break points
+ MOVW MSR, R1
+ OR $(MSR_RI), R1
+ MOVW R1, MSR
+ ISYNC
+*/
+
+ /* m->tlbfault++ */
+ MOVW $(MACHADDR&~KZERO), R1 /* m-> */
+ MOVW 20(R1), R2
+ ADD $1, R2
+ MOVW R2, 20(R1)
+
+ MOVW CR, R2
+ MOVW SPR(MD_EPN), R1
+ MOVW R1, CR
+ BC 4,0,dtlblookup
+ BC 12,1,dtlbio
+ /*
+ * map ram
+ */
+ MOVW R2, CR
+ MOVW $(MMUPS8M|MMUV), R2
+ MOVW R2, SPR(MD_TWC)
+ RLWNM $0, R1, $0x7f800000, R1
+ OR $(MMUPP|MMUSPS|MMUSH|MMUV), R1
+ MOVW R1, SPR(MD_RPN)
+ MOVW SPR(M_TW), R2
+ MOVW SPR(SAVER1), R1
+ RFI
+dtlbio:
+ /*
+ * map io
+ */
+ MOVW R2, CR
+ MOVW $(MMUPS8M|MMUWT|MMUV), R2
+ MOVW R2, SPR(MD_TWC)
+ RLWNM $0, R1, $0xff800000, R1
+ OR $(MMUPP|MMUSPS|MMUSH|MMUCI|MMUV), R1
+ MOVW R1, SPR(MD_RPN)
+ MOVW SPR(M_TW), R2
+ MOVW SPR(SAVER1), R1
RFI
+dtlblookup:
+ MOVW R0, SPR(SAVER0)
+ MOVW R3, SPR(SAVEXX)
+
+ /*
+ * R1 = 20 bits of addr | 8 bits of junk | 4 bits of asid
+ * calulate ((x>>9)^(x>>21)^(x<<11)) & (0xfff<<3)
+ * note (x>>21)^(x<<11) = rotate left 11
+ */
+ RLWNM $(32-9), R1, $(0xfff<<3), R3
+ RLWNM $11, R1, $(0xfff<<3), R1
+ XOR R1, R3, R1
+ MOVW $(MACHADDR&~KZERO), R3 /* m-> */
+ MOVW 16(R3), R3 /* m->stb */
+ RLWNM $0, R3, $~KZERO, R3 /* PADDR(m->stb) */
+ ADD R1,R3,R3
+ MOVW 4(R3), R0
+ MOVW 0(R3), R3
+ MOVW SPR(MD_EPN), R1
+ RLWNM $20, R1, $0xffffff, R1
+ RLWNM $12, R1, $~0, R1
+ CMP R3, R1
+ BNE dtlbtrap
+ MOVW $(MMUV), R1
+ MOVW R1, SPR(MD_TWC)
+ MOVW R0, SPR(MD_RPN)
+ MOVW R2, CR
+ MOVW SPR(SAVEXX), R3
+ MOVW SPR(M_TW), R2
+ MOVW SPR(SAVER1), R1
+ MOVW SPR(SAVER0), R0
+ RFI
+dtlbtrap:
+ MOVW R2, CR
+
+ MOVW $(MACHADDR&~KZERO), R2 /* m-> */
+ MOVW R1, 32(R2)
+ MOVW R3, 36(R2)
+
+ MOVW SPR(MD_EPN), R1
+ MOVW $(MACHADDR&~KZERO), R3 /* m-> */
+ MOVW R1, 24(R3) /* save dar */
+ MOVW SPR(SAVEXX), R3
+ MOVW SPR(M_TW), R2
+ MOVW LR, R0
+ MOVW R0, SPR(SAVELR)
+ MOVW $0x1200, R0
+ BR traps
+
+TEXT dtlberror(SB), $-4
+ MOVW R0, SPR(SAVER0)
+ MOVW R1, SPR(SAVER1)
+ MOVW LR, R0
+ MOVW R0, SPR(SAVELR)
+ MOVW $(MACHADDR&~KZERO), R1 /* m-> */
+ MOVW SPR(DAR), R0
+ MOVW R0, 24(R1) /* save dar */
+ MOVW SPR(DSISR), R0
+ MOVW R0, 28(R1) /* save dsisr */
+ MOVW $0x1400, R0
+ BR traps
/*
* traps force memory mapping off.
+ * the following code has been executed at the exception
+ * vector location
+ * MOVW R0, SPR(SAVER0)
+ * MOVW LR, R0
+ * MOVW R0, SPR(SAVELR)
+ * bl trapvec(SB)
*/
TEXT trapvec(SB), $-4
-traps:
MOVW LR, R0
-
- MOVW R0, SPR(SAVEXX) /* vector */
MOVW R1, SPR(SAVER1)
- MOVW CR, R1
- MOVW MSR, R0
- OR $(MSR_DR|MSR_IR), R0 /* make data space usable */
- MOVW R0, MSR
- MOVW SPR(SRR0), R0 /* save SRR0/SRR1 now, since DLTB might be missing stack page */
- MOVW R0, LR
+traps:
+ MOVW R0, SPR(SAVEXX) /* vector */
+
+/*
+ to enable hardware break points
+ MOVW MSR, R1
+ OR $(MSR_RI), R1
+ MOVW R1, MSR
+ ISYNC
+*/
+
+ /* did we come from user space */
MOVW SPR(SRR1), R0
- ANDCC $MSR_PR, R0
- BEQ ktrap
+ MOVW CR, R1
+ MOVW R0, CR
+ BC 4,17,ktrap
/* switch to kernel stack */
MOVW R1, CR
- MOVW R2, R0
- MOVW $setSB(SB), R2
- MOVW $mach0(SB), R1 /* m-> */
- MOVW R0, R2
- MOVW 12(R1), R1 /* m->proc */
- MOVW 8(R1), R1 /* m->proc->kstack */
+ MOVW $(MACHADDR&~KZERO), R1 /* PADDR(m->) */
+ MOVW 12(R1), R1 /* m->proc */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc) */
+ MOVW 8(R1), R1 /* m->proc->kstack */
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc->kstack) */
ADD $(KSTACK-UREGSIZE), R1
- BR trap1
+ BL saveureg(SB)
+ BL trap(SB)
+ BR restoreureg
ktrap:
MOVW R1, CR
MOVW SPR(SAVER1), R1
+ RLWNM $0, R1, $~KZERO, R1 /* PADDR(m->proc->kstack) */
SUB $UREGSPACE, R1
-trap1:
- 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
@@ 612,6 783,8 @@ trap1:
TEXT intrvec(SB), $-4
MOVW LR, R0
+ BR 0(PC)
+
/*
* map data virtually and make space to save
*/
@@ 641,6 814,54 @@ TEXT intrvec(SB), $-4
MOVW R5, isavetbl(SB)
BL intr(SB)
+/*
+ * 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.
+ *
+ */
+TEXT saveureg(SB), $-4
+/*
+ * save state
+ */
+ MOVMW R2, 48(R1) /* r2:r31 */
+ MOVW $setSB(SB), R2
+ MOVW $(MACHADDR&~KZERO), R(MACH)
+ MOVW 12(R(MACH)), R(USER)
+ MOVW $MACHADDR, R(MACH)
+ 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) */
+ MOVW SPR(SRR0), R0
+ MOVW R0, 16(R1) /* old PC */
+ MOVW SPR(SRR1), R0
+ MOVW R0, 12(R1) /* old status */
+ MOVW SPR(SAVEXX), R0
+ MOVW R0, 8(R1) /* cause/vector */
+ ADD $8, R1, R3 /* Ureg* */
+ OR $KZERO, R3 /* fix 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|MSR_RI), R5 /* enable MMU */
+ MOVW R5, SPR(SRR1)
+ MOVW LR, R31
+ OR $KZERO, R31 /* return PC in KSEG0 */
+ MOVW R31, SPR(SRR0)
+ OR $KZERO, R1 /* fix stack pointer */
+ RFI /* returns to trap handler */
/*
* restore state from Ureg and return from trap/interrupt
@@ 660,7 881,7 @@ restoreureg:
MOVW 28(R1), R0
MOVW R0, CR /* CR */
MOVW 24(R1), R0
- MOVW R0, SPR(SAVELR) /* LR */
+ MOVW R0, LR
/* pad, skip */
MOVW 16(R1), R0
MOVW R0, SPR(SRR0) /* old PC */
@@ 668,13 889,47 @@ restoreureg:
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 flash(SB), $-4
+flash0:
+ BL powerupled(SB);
+ MOVW $0x100000, R5
+ MOVW R5, CTR
+delay0:
+ BDNZ delay0
+ BL powerdownled(SB);
+ MOVW $0x100000, R5
+ MOVW R5, CTR
+delay1:
+ BDNZ delay1
+ BR flash0
+
+TEXT powerupled(SB), $0
+
+ MOVW $INTMEM,R11
+ MOVH 0x970(R11), R7
+ MOVW $0x100,R8
+ OR R8,R7
+ MOVH R7,0x970(R11)
+ MOVH 0x976(R11), R7
+ ANDN R8,R7
+ MOVH R7,0x976(R11)
+ RETURN
+
+TEXT powerdownled(SB), $0
+
+ MOVW $INTMEM,R11
+ MOVH 0x970(R11), R7
+ MOVW $0x100,R8
+ OR R8,R7
+ MOVH R7,0x970(R11)
+ MOVH 0x976(R11), R7
+ OR R8,R7
+ MOVH R7,0x976(R11)
+ RETURN
-GLOBL mach0+0(SB), $MACHSIZE
GLOBL spltbl+0(SB), $4
GLOBL intrtbl+0(SB), $4
GLOBL isavetbl+0(SB), $4
M mpc/main.c => mpc/main.c +97 -173
@@ 7,11 7,7 @@
#include "init.h"
#include "pool.h"
-#define MAXCONF 32
-
-char *confname[MAXCONF];
-char *confval[MAXCONF];
-int nconf;
+static char **confenv = (char**)(CONFPARSED);
int predawn = 1;
@@ 23,13 19,17 @@ struct Bootargs
uchar chksum;
};
-Conf conf;
+/*
+ * software tlb simulation
+ */
+Softtlb stlb[MAXMACH][STLBSIZE];
-static void options(void);
+Conf conf;
void
main(void)
{
+ powerdownled();
machinit();
clockinit();
confinit();
@@ 38,19 38,11 @@ main(void)
printinit();
cpminit();
uartinstall();
+print("hello world from kernel %ux %ux %ux\n", m->iomem->pddat, m->iomem->pddir, m->iomem->pdpar);
mmuinit();
-
-// turn on pcmcia
-*(uchar*)(NVRAMMEM+0x100001) |= 0x60;
-
-print("m->delayloop = %ld\n", m->delayloop);
- delayloopinit();
-print("m->delayloop = %ld\n", m->delayloop);
-
pageinit();
procinit0();
initseg();
- options();
links();
chandevreset();
swapinit();
@@ 69,6 61,7 @@ machinit(void)
m->delayloop = 20000;
m->cputype = getpvr()>>16;
m->iomem = KADDR(INTMEM);
+ m->stb = &stlb[0][0];
io = m->iomem;
osc = 50;
@@ 78,24 71,39 @@ machinit(void)
m->cpuhz = m->speed*MHz; /* general system clock (cycles) */
m->clockgen = osc*MHz; /* clock generator frequency (cycles) */
- *(ushort*)&(io->memc[4].base) = 0x8060;
-// *(ushort*)&(io->memc[7].option) = 0xffe0;
- *(ushort*)&(io->memc[7].base) = 0xff00;
+ active.machs = 1;
+ active.exiting = 0;
+ /* enable check stop reset */
+ io->plprcrk = KEEP_ALIVE_KEY; // unlock
+ io->plprcr |= IBIT(24); // enable checkstop reset
+ putmsr(getmsr() | MSR_RI | MSR_ME);
+// putmsr(getmsr() & ~MSR_ME);
}
-
-void
-bootargs(ulong base)
+char*
+getconf(char *name)
{
-print("bootargs = %ulx\n", base);
- USED(base);
+ char **p, *q;
+ int n;
+
+ n = strlen(name);
+
+ for(p = confenv; *p; p++) {
+ q = *p;
+ if(strncmp(q, name, n) == 0 && q[n] == '=')
+ return q+n+1;
+ }
+ return 0;
}
void
init0(void)
{
- int i;
+ char **p, *q, name[NAMELEN];
+ int n;
+
+print("init0\n");
up->nerrlab = 0;
@@ 116,9 124,18 @@ init0(void)
ksetenv("service", "cpu");
else
ksetenv("service", "terminal");
- for(i = 0; i < nconf; i++)
- if(confname[i] && confname[i][0] != '*')
- ksetenv(confname[i], confval[i]);
+
+ for(p = confenv; *p; p++) {
+ q = strchr(p[0], '=');
+ if(q == 0)
+ continue;
+ n = q-p[0];
+ if(n >= NAMELEN)
+ n = NAMELEN-1;
+ memmove(name, p[0], n);
+ name[n] = 0;
+ ksetenv(name, q+1);
+ }
poperror();
}
kproc("alarm", alarmkproc, 0);
@@ 162,9 179,6 @@ userinit(void)
p->seg[SSEG] = s;
pg = newpage(1, 0, USTKTOP-BY2PG);
segpage(s, pg);
- k = kmap(pg);
- bootargs(VA(k));
- kunmap(k);
/*
* Text
@@ 256,21 270,23 @@ confinit(void)
{
int nbytes;
ulong pa;
+ char **p;
+
+ /* fix up confenv */
+ for(p = confenv; *p; p++)
+ *p = KADDR(*p);
conf.nmach = 1; /* processors */
conf.nproc = 60; /* processes */
// hard wire for now
- pa = 0xffd00000; // leave 1 Meg for kernel
- nbytes = 2*1024*1024; // leave room at the top as well
+ pa = 0x200000; // leave 2 Meg for kernel
+ nbytes = 8*1024*1024; // leave room at the top as well
conf.npage0 = nbytes/BY2PG;
conf.base0 = pa;
- pa = 0xfff04000;
- nbytes = 1024*1024 - 0x4000;
-
- conf.npage1 = nbytes/BY2PG;
+ conf.npage1 = 0;
conf.base1 = pa;
conf.npage = conf.npage0 + conf.npage1;
@@ 279,8 295,8 @@ confinit(void)
conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
/* set up other configuration parameters */
- conf.nswap = 0; // conf.npage*3;
- conf.nswppo = 0; // 4096;
+ conf.nswap = 0;
+ conf.nswppo = 0;
conf.nimage = 20;
conf.copymode = 0; /* copy on write */
@@ 307,112 323,58 @@ getcfields(char* lp, char** fields, int n, char* sep)
return i;
}
-static char BOOTARGS[] =
- "ether0=type=SCC port=1 ea=000086353a6b\r\n"
- "ether1=type=589E port=0x300\r\n";
-
-static void
-options(void)
-{
- long i, n;
- char *cp, *p, *q;
- char *line[MAXCONF];
- Bootargs *ba;
-
- /*
- * parse configuration args from dos file plan9.ini
- */
- ba = (Bootargs*)(NVRAMMEM+ 4*1024);
- if(ba->chksum == nvcsum(ba->args, sizeof(ba->args))) {
- cp = smalloc(strlen(ba->args)+1);
- memmove(cp, ba->args, strlen(ba->args)+1);
- } else
- cp = BOOTARGS;
-print("bootargs = %s\n", cp);
-
- /*
- * 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 = getcfields(cp, line, MAXCONF, "\n");
- for(i = 0; i < n; i++){
- if(*line[i] == '#')
- continue;
- cp = strchr(line[i], '=');
- if(cp == 0)
- continue;
- *cp++ = 0;
- if(cp - line[i] >= NAMELEN+1)
- *(line[i]+NAMELEN-1) = 0;
- confname[nconf] = line[i];
- confval[nconf] = cp;
- nconf++;
- }
-}
-
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';
+
+ p = getconf(cc);
+ if(p == 0)
+ return 0;
+print("%s=%s\n", cc, p);
+ isa->nopt = 0;
+ 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++;
}
- 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++;
+ *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;
}
- while(*p && *p != ' ' && *p != '\t')
- p++;
+ *r = '\0';
+ isa->nopt++;
}
- return 1;
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
}
- return 0;
+ return 1;
}
int
@@ 437,41 399,3 @@ cistrcmp(char *a, char *b)
return 0;
}
-int
-cistrncmp(char *a, char *b, int n)
-{
- unsigned ac, bc;
-
- while(n > 0){
- ac = *a++;
- bc = *b++;
- n--;
-
- 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;
-}
-
-/* dummy - not used */
-
-void
-iofree(int)
-{
-}
-
-int
-ioalloc(int, int, int, char*)
-{
- return 1;
-}
-
M mpc/mem.h => mpc/mem.h +25 -17
@@ 83,12 83,6 @@
#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
@@ 100,10 94,17 @@
#define PPN(x) ((x)&~(BY2PG-1))
/*
+ * Fundamental addresses
+ */
+#define MACHADDR (KTZERO-MAXMACH*MACHSIZE)
+#define MACHP(n) ((Mach *)(MACHADDR+(n)*MACHSIZE))
+
+#define UREGSIZE ((8+32)*4)
+
+/*
* MMU
*/
-#ifdef notdef
/* L1 table entry and Mx_TWC flags */
#define PTEWT (1<<1) /* write through */
#define PTE4K (0<<2)
@@ 119,11 120,18 @@
#define PTEKERNEL (0<<2)
#define PTEUSER (1<<2)
#define PTESIZE (1<<7)
-#endif
+
+#define NTLBPID 16
+#define TLBPID(n) ((n)&(NTLBPID-1))
+
+/* soft tlb */
+#define STLBLOG 12
+#define STLBSIZE (1<<STLBLOG)
+
/*
* portable MMU bits for fault.c - though still machine specific
*/
-#define PTEVALID (MMUPP|MMUSH|MMUV)
+#define PTEVALID (MMUPP|MMUV)
#define PTEWRITE (2<<10)
#define PTERONLY (3<<10)
#define PTEUNCACHED (1<<4)
@@ 167,26 175,26 @@
#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 0xffc00000 /* first address in kernel text */
+#define KTZERO 0x80010000 /* 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
+#define CONFPARSED (KZERO+0x2000)
-#define INTMEM 0x80000000
-#define ISAMEM 0x80100000
-#define FLASHMEM 0xff000000
+#define INTMEM 0xff000000
+#define ISAMEM 0xfe000000
+#define FLASHMEM 0xff200000
#define SACMEM FLASHMEM + 0x80000
-#define NVRAMMEM 0x80600000
-#define DRAMMEM 0xff800000 /* to 0xffffffff: 8 Meg */
+#define NVRAMMEM 0xfc000000
+#define DRAMMEM 0x80000000
#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 DPBASE (DPRAM+DPLEN3)
#define SCC1P (INTMEM+0x3C00)
#define I2CP (INTMEM+0x3C80)
A mpc/memspeed.c => mpc/memspeed.c +53 -0
@@ 0,0 1,53 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+char d0[1000008], d1[1000008];
+
+static void test(int size, int align);
+
+
+void
+memspeed()
+{
+ int j;
+
+ spllo();
+
+ memmove(d0, d1, sizeof(d0));
+
+ for(j = 0; j<8; j++)
+ test(12, j);
+ for(j = 0; j<8; j++)
+ test(100, j);
+ for(j = 0; j<8; j++)
+ test(400, j);
+ for(j = 0; j<8; j++)
+ test(1000, j);
+ for(j = 0; j<8; j++)
+ test(10000, j);
+ for(j = 0; j<8; j++)
+ test(100000, j);
+ for(j = 0; j<8; j++)
+ test(1000000, j);
+}
+
+static void
+test(int size, int align)
+{
+ int n;
+ int t;
+
+ t = -TK2MS(m->ticks);
+ n = 10000000/size;
+ while(n) {
+ memmove(d0+align, d1, size);
+ n--;
+ }
+ t += TK2MS(m->ticks);
+ print("size = %d align = %d KB/s %d %d\n", size, align, 10000000/t, t);
+}
+
M mpc/mmu.c => mpc/mmu.c +122 -15
@@ 5,46 5,154 @@
#include "fns.h"
#include "io.h"
+#define TLBINVLAID KZERO
void
mmuinit(void)
{
+ int i;
+
print("mmuinit\n");
- kernelmmu();
+ for(i=0; i<STLBSIZE; i++)
+ m->stb[i].virt = TLBINVLAID;
}
void
flushmmu(void)
{
-// print("flushmmu()\n");
- _flushmmu();
+ int x;
+
+if(0)print("flushmmu(%d)\n", up->pid);
+ x = splhi();
+ up->newtlb = 1;
+ mmuswitch(up);
+ splx(x);
+}
+
+/*
+ * called with splhi
+ */
+void
+mmuswitch(Proc *p)
+{
+ int tp;
+
+if(0)print("mmuswitch()\n");
+ if(p->newtlb) {
+ memset(p->pidonmach, 0, sizeof p->pidonmach);
+ p->newtlb = 0;
+ }
+ tp = p->pidonmach[m->machno];
+ putcasid(tp);
}
void
-mmuswitch(Proc*)
+mmurelease(Proc* p)
{
- flushmmu();
+if(0)print("mmurelease(%d)\n", p->pid);
+ memset(p->pidonmach, 0, sizeof p->pidonmach);
}
void
-mmurelease(Proc* proc)
+purgetlb(int pid)
{
- USED(proc);
+ int i, mno;
+ Proc *sp, **pidproc;
+ Softtlb *entry, *etab;
+
+if(0)print("purgetlb: pid = %d\n", pid);
+ m->tlbpurge++;
+ /*
+ * find all pid entries that are no longer used by processes
+ */
+ mno = m->machno;
+ pidproc = m->pidproc;
+ for(i=1; i<NTLBPID; i++) {
+ sp = pidproc[i];
+ if(sp && sp->pidonmach[mno] != i)
+ pidproc[i] = 0;
+ }
+
+ /*
+ * shoot down the one we want
+ */
+ sp = pidproc[pid];
+ if(sp != 0)
+ sp->pidonmach[mno] = 0;
+ pidproc[pid] = 0;
+
+ /*
+ * clean out all dead pids from the stlb;
+ */
+ entry = m->stb;
+ for(etab = &entry[STLBSIZE]; entry < etab; entry++)
+ if(pidproc[TLBPID(entry->virt)] == 0)
+ entry->virt = TLBINVLAID;
+
+ /*
+ * clean up the hardware
+ */
+ tlbflushall();
}
+int
+newtlbpid(Proc *p)
+{
+ int i, s;
+ Proc **h;
+
+ i = m->lastpid;
+ h = m->pidproc;
+ for(s = 0; s < NTLBPID; s++) {
+ i++;
+ if(i >= NTLBPID)
+ i = 1;
+ if(h[i] == 0)
+ break;
+ }
+
+ if(h[i]) {
+ i = m->purgepid+1;
+ if(i >= NTLBPID)
+ i = 1;
+ m->purgepid = i;
+ purgetlb(i);
+ }
+
+ if(h[i] != 0)
+ panic("newtlb");
+
+ m->pidproc[i] = p;
+ p->pidonmach[m->machno] = i;
+ m->lastpid = i;
+if(0)print("newtlbpid: pid=%d = tlbpid = %d\n", p->pid, i);
+ return i;
+}
void
putmmu(ulong va, ulong pa, Page *pg)
{
- int x, r;
char *ctl;
+ int tp;
+ ulong h;
-//if((va&0x8000000) == 0)
-//print("putmmu va=%ux pa=%ux\n", va, pa);
- x = splhi();
- r = _putmmu(va, pa);
+ qlock(&m->stlblk);
+
+ tp = up->pidonmach[m->machno];
+ if(tp == 0) {
+ tp = newtlbpid(up);
+ putcasid(tp);
+ }
+
+ h = ((va>>12)^(va>>24)^(tp<<8)) & 0xfff;
+ m->stb[h].virt = va|tp;
+ m->stb[h].phys = pa;
+ tlbflush(va);
+
+ qunlock(&m->stlblk);
ctl = &pg->cachectl[m->machno];
+if(0)print("putmmu tp=%d h=%d va=%ux pa=%ux ctl=%x\n", tp, h,va, pa, *ctl);
switch(*ctl) {
default:
panic("putmmu: %d\n", *ctl);
@@ 52,14 160,13 @@ putmmu(ulong va, ulong pa, Page *pg)
case PG_NOFLUSH:
break;
case PG_TXTFLUSH:
+ dcflush((void*)pg->va, BY2PG);
icflush((void*)pg->va, BY2PG);
*ctl = PG_NOFLUSH;
break;
case PG_NEWCOL:
- dcflush((void*)pg->va, BY2PG);
+print("PG_NEWCOL!!\n");
*ctl = PG_NOFLUSH;
break;
}
-
- splx(x);
}
A mpc/ms.c => mpc/ms.c +82 -0
@@ 0,0 1,82 @@
+#include <u.h>
+#include <libc.h>
+
+char d0[1000008], d1[1000008];
+
+void test(int size, int align);
+
+memtest(char *pp, int n)
+{
+ static int seed = 0;
+ ulong *p, *ep;
+ ulong x;
+
+if(seed % 100 == 0)
+print("memtest seed = %d\n", seed);
+
+ p = (ulong*)pp;
+ ep = (ulong*)(pp+n);
+
+ x = seed;
+ while(p < ep) {
+ *p++ = x;
+ x *= 1103515245;
+ }
+
+ x = seed;
+ p = (ulong*)pp;
+ ep = (ulong*)(pp+n);
+ while(p < ep) {
+ if(*p++ != x) {
+ print("error %ux!!\n", ((char*)p) - pp);
+ return;
+ }
+ x *= 1103515245;
+ }
+ seed++;
+}
+
+void
+main()
+{
+ int j;
+
+ memmove(d0, d1, sizeof(d0));
+
+ for(j=0; j<10; j++) {
+ memtest(d0, sizeof(d0));
+ }
+
+ for(j = 0; j<8; j++)
+ test(12, j);
+ for(j = 0; j<8; j++)
+ test(100, j);
+ for(j = 0; j<8; j++)
+ test(400, j);
+ for(j = 0; j<8; j++)
+ test(1000, j);
+ for(j = 0; j<8; j++)
+ test(10000, j);
+ for(j = 0; j<8; j++)
+ test(100000, j);
+ for(j = 0; j<8; j++)
+ test(1000000, j);
+
+ exits(0);
+}
+
+void
+test(int size, int align)
+{
+ int n;
+ int t;
+
+ t = -times(0);
+ n = 10000000/size;
+ while(n) {
+ memmove(d0+align, d1, size);
+ n--;
+ }
+ t += times(0);
+ print("size = %d align = %d KB/s %d %d\n", size, align, 10000000/t, t);
+}
M mpc/nocache.c => mpc/nocache.c +0 -1
@@ 15,7 15,6 @@ cinit(void)
void
copen(Chan *c)
{
-print("copen called!\n");
USED(c);
}
M mpc/sh.c => mpc/sh.c +1 -1
@@ 57,7 57,7 @@ main(int argc, char *argv[])
open("#c/cons", OWRITE);
open("#c/cons", OWRITE);
- print("hello world\n");
+ print("hello world from sh\n");
if(argc>1 && strcmp(argv[1], "-t")==0)
tflag++;
A mpc/spi.c => mpc/spi.c +521 -0
@@ 0,0 1,521 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+typedef struct SPIparam SPIparam;
+struct SPIparam {
+ ushort rbase;
+ ushort tbase;
+ uchar rfcr;
+ uchar tfcr;
+ ushort mrblr;
+ ulong rstate;
+ ulong rptr;
+ ushort rbptr;
+ ushort rcnt;
+ ulong rtmp;
+ ulong tstate;
+ ulong tptr;
+ ushort tbptr;
+ ushort tcnt;
+ ulong ttmp;
+};
+
+enum {
+ Nrdre = 2, /* receive descriptor ring entries */
+ Ntdre = 2, /* transmit descriptor ring entries */
+
+ Rbsize = 8, /* ring buffer size (+3 for PID+CRC16) */
+ Bufsize = (Rbsize+7)&~7, /* aligned */
+};
+
+enum {
+ /* spi-specific BD flags */
+ BDContin= 1<<9, /* continuous mode */
+ BDrxov= 1<<1, /* overrun */
+ BDtxun= 1<<1, /* underflow */
+ BDme= 1<<0, /* multimaster error */
+ BDrxerr= BDrxov|BDme,
+ BDtxerr= BDtxun|BDme,
+
+ /* spmod */
+ MLoop= 1<<14, /* loopback mode */
+ MClockInv= 1<<13, /* inactive state of SPICLK is high */
+ MClockPhs= 1<<12, /* SPCLK starts toggling at beginning of transfer */
+ MDiv16= 1<<11, /* use BRGCLK/16 as input to SPI baud rate */
+ MRev= 1<<10, /* normal operation */
+ MMaster= 1<<9,
+ MSlave= 0<<9,
+ MEnable= 1<<8,
+ /* LEN, PS fields */
+
+ /* spie */
+ MME = 1<<5,
+ TXE = 1<<4,
+ RES = 1<<3,
+ BSY = 1<<2,
+ TXB = 1<<1,
+ RXB = 1<<0,
+};
+
+/*
+ * software structures
+ */
+typedef struct Ctlr Ctlr;
+
+struct Ctlr {
+ QLock;
+ int init;
+ SPI* spi;
+ SPIparam* sp;
+
+ int rxintr;
+ Rendez ir;
+ Ring;
+};
+
+static Ctlr spictlr[1];
+
+static void interrupt(Ureg*, void*);
+
+/*
+ * test driver for SPI, host mode
+ */
+void
+spireset(void)
+{
+ IMM *io;
+ SPI *spi;
+ SPIparam *sp;
+ Ctlr *ctlr;
+
+ io = m->iomem;
+ sp = (SPIparam*)cpmparam(SPIP, sizeof(*sp));
+ memset(sp, 0, sizeof(*sp));
+ if(sp == nil){
+ print("SPI: can't allocate new parameter memory\n");
+ return;
+ }
+
+ spi = (SPI*)((ulong)m->iomem+0xAA0);
+ ctlr = spictlr;
+
+ /* step 1: select port pins */
+ io->pbdir |= IBIT(30)|IBIT(29)|IBIT(28);
+ io->pbpar |= IBIT(30)|IBIT(29)|IBIT(28); /* SPICLK, SPIMOSI, SPIMISO */
+
+ /* step 2: set CS pin - also disables SPISEL */
+ io->pbpar &= ~(IBIT(31));
+ io->pbdir |= IBIT(31);
+ io->pbodr &= ~(IBIT(31));
+ io->pbdat &= ~(IBIT(31));
+
+ ctlr->spi = spi;
+ ctlr->sp = sp;
+
+ if(ioringinit(ctlr, Nrdre, Ntdre, Bufsize)<0)
+ panic("spireset: ioringinit");
+
+ /* step 3: configure rbase and tbase */
+ sp->rbase = PADDR(ctlr->rdr);
+ sp->tbase = PADDR(ctlr->tdr);
+
+ /* step 4: do not issue InitRxTx command - due to microcode bug */
+
+ /* step 5: */
+ io->sdcr = 1;
+
+ /* step 6: */
+ sp->rfcr = 0x10;
+ sp->tfcr = 0x10;
+
+ /* step 7: */
+ sp->mrblr = Bufsize;
+
+ /* step 7.5: init other params because of bug in microcode */
+ sp->rstate = 0;
+ sp->rbptr = sp->rbase;
+ sp->rcnt = 0;
+ sp->tstate = 0;
+ sp->tbptr = sp->tbase;
+ sp->tcnt = 0;
+
+ /* step 8-9: done by ioringinit */
+
+ /* step 10: clear events */
+ spi->spie = ~0;
+
+ /* step 11-12: enable interrupts */
+ intrenable(VectorCPIC+0x05, interrupt, spictlr, BUSUNKNOWN);
+ spi->spim = ~0;
+
+ /* step 13: enable in master mode, 8 bit chacters, slow clock */
+ spi->spmode = MMaster|MRev|MDiv16|MEnable|(0x7<<4)|0xf;
+print("spi->spmode = %ux\n", spi->spmode);
+}
+
+static void
+interrupt(Ureg*, void *arg)
+{
+ int events;
+ Ctlr *ctlr;
+ SPI *spi;
+
+ ctlr = arg;
+ spi = ctlr->spi;
+ events = spi->spie;
+ spi->spie = events;
+ print("SPI#%x\n", events);
+}
+
+void
+spdump(SPIparam *sp)
+{
+ print("rbase = %ux\n", sp->rbase);
+ print("tbase = %ux\n", sp->tbase);
+ print("rfcr = %ux\n", sp->rfcr);
+ print("tfcr = %ux\n", sp->tfcr);
+ print("mrblr = %ux\n", sp->mrblr);
+ print("rstate = %lux\n", sp->rstate);
+ print("rptr = %lux\n", sp->rptr);
+ print("rbptr = %ux\n", sp->rbptr);
+ print("rcnt = %ux\n", sp->rcnt);
+ print("rtmp = %ux\n", sp->rtmp);
+ print("tstate = %lux\n", sp->tstate);
+ print("tptr = %lux\n", sp->tptr);
+ print("tbptr = %ux\n", sp->tbptr);
+ print("tcnt = %ux\n", sp->tcnt);
+ print("ttmp = %ux\n", sp->ttmp);
+}
+
+void
+spitest(void)
+{
+ BD *dre;
+ Block *b;
+ int len;
+ Ctlr *ctlr;
+ ulong status;
+
+ ctlr = spictlr;
+
+ dre = &ctlr->tdr[ctlr->tdrh];
+ if(dre->status & BDReady)
+ panic("spitest: txstart");
+
+print("dre->status %ux %ux\n", dre[0].status, dre[1].status);
+ b = allocb(4);
+ b->wp[0] = 0xc0;
+ b->wp[1] = 0x00;
+ b->wp[2] = 0x00;
+ b->wp[3] = 0x00;
+ b->wp += 4;
+ len = BLEN(b);
+print("len = %d\n", len);
+ dcflush(b->rp, len);
+ if(ctlr->txb[ctlr->tdrh] != nil)
+ panic("scc/ether: txstart");
+ ctlr->txb[ctlr->tdrh] = b;
+ dre->addr = PADDR(b->rp);
+print("addr = %lux\n", PADDR(b->rp));
+ dre->length = len;
+ dre->status = (dre->status & BDWrap) | BDReady|BDInt|BDLast;
+ eieio();
+spdump(ctlr->sp);
+m->iomem->pbdat |= IBIT(31);
+microdelay(1);
+ ctlr->spi->spcom = 1<<7; /* transmit now */
+print("cpcom = %ux\n", &ctlr->spi->spcom);
+spdump(ctlr->sp);
+ eieio();
+ ctlr->ntq++;
+ ctlr->tdrh = NEXT(ctlr->tdrh, Ntdre);
+print("going into loop %ux %ux\n", dre->status, ctlr->spi->spcom);
+ while(dre->status&BDReady) {
+print("ctrl->spi->spim = %ux %ux\n", ctlr->spi->spie, dre->status);
+spdump(ctlr->sp);
+ delay(10000);
+ }
+delay(100);
+ dre = &ctlr->rdr[ctlr->rdrx];
+ status = dre->status;
+ len = dre->length;
+print("%d status = %ux len=%d\n", ctlr->rdrx, status, len);
+ b = iallocb(len);
+ memmove(b->wp, KADDR(dre->addr), len);
+ b->wp += len;
+print("%ux %ux %ux %ux\n", b->rp[0], b->rp[1], b->rp[2], b->rp[3]);
+ dcflush(KADDR(dre->addr), len);
+ dre->status = (status & BDWrap) | BDEmpty | BDInt;
+ ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
+m->iomem->pbdat &= ~(IBIT(31));
+microdelay(1);
+}
+
+
+void
+spiinit(void)
+{
+ spireset();
+ spitest();
+}
+
+#ifdef XXX
+
+static void
+epprod(Ctlr *ctlr, int epn)
+{
+ ctlr->spi->uscom = FifoFill | (epn&3);
+ eieio();
+}
+
+static void
+txstart(Endpt *r)
+{
+ int len, flags;
+ Block *b;
+ BD *dre, *rdy;
+
+ if(r->ctlr->init)
+ return;
+ rdy = nil;
+ while(r->ntq < Ntdre-1){
+ b = qget(r->oq);
+ if(b == 0)
+ break;
+
+ dre = &r->tdr[r->tdrh];
+ if(dre->status & BDReady)
+ panic("txstart");
+dumpspi(b, "TX");
+
+ /*
+ * Give ownership of the descriptor to the chip, increment the
+ * software ring descriptor pointer and tell the chip to poll.
+ */
+ flags = 0;
+ switch(b->rp[0]){
+ case TokDATA1:
+ flags = BDData1|BDData0;
+ case TokDATA0:
+ flags |= BDtxcrc|BDcnf|BDReady;
+ flags |= BDData0;
+ b->rp++; /* skip DATAn */
+ }
+ len = BLEN(b);
+ dcflush(b->rp, len);
+ if(r->txb[r->tdrh] != nil)
+ panic("spi: txstart");
+ r->txb[r->tdrh] = b;
+ dre->addr = PADDR(b->rp);
+ dre->length = len;
+ eieio();
+ dre->status = (dre->status & BDWrap) | BDInt|BDLast | flags;
+ if(rdy){
+ rdy->status |= BDReady;
+ rdy = nil;
+ }
+ if((flags & BDReady) == 0)
+ rdy = dre;
+ eieio();
+ r->ntq++;
+ r->tdrh = NEXT(r->tdrh, Ntdre);
+ }
+ if(rdy)
+ rdy->status |= BDReady;
+ eieio();
+}
+
+static void
+transmit(Endpt *r)
+{
+ ilock(r->ctlr);
+ txstart(r);
+ iunlock(r->ctlr);
+}
+
+static void
+endptintr(Endpt *r, int events)
+{
+ int len, status;
+ BD *dre;
+ Block *b;
+
+ if(events & Frxb || 1){
+ dre = &r->rdr[r->rdrx];
+ while(((status = dre->status) & BDEmpty) == 0){
+ if(status & BDrxerr || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
+ print("spi rx: %4.4ux %d ", status, dre->length);
+ {uchar *p;int i; p=KADDR(dre->addr); for(i=0;i<14&&i<dre->length; i++)print(" %.2ux", p[i]);print("\n");}
+ }
+ else{
+ /*
+ * We have a packet. Read it into the next
+ * free ring buffer, if any.
+ */
+ len = dre->length-2; /* discard CRC */
+ if(len >= 0 && (b = iallocb(len)) != 0){
+ memmove(b->wp, KADDR(dre->addr), len);
+ dcflush(KADDR(dre->addr), len);
+ b->wp += len;
+ // spiiq(ctlr, b);
+ dumpspi(b, "RX");
+ freeb(b);
+ }
+ }
+
+ /*
+ * Finished with this descriptor, reinitialise it,
+ * give it back to the chip, then on to the next...
+ */
+ dre->length = 0;
+ dre->status = (dre->status & BDWrap) | BDEmpty | BDInt;
+ eieio();
+
+ r->rdrx = NEXT(r->rdrx, Nrdre);
+ dre = &r->rdr[r->rdrx];
+ r->rxintr = 1;
+ wakeup(&r->ir);
+ }
+ }
+
+ /*
+ * Transmitter interrupt: handle anything queued for a free descriptor.
+ */
+ if(events & (Ftxb|Ftxe0|Ftxe1)){
+ lock(r->ctlr);
+ while(r->ntq){
+ dre = &r->tdr[r->tdri];
+ if(dre->status & BDReady)
+ break;
+ print("spitx=#%.4x %8.8lux\n", dre->status, dre->addr);
+ /* TO DO: error counting */
+ b = r->txb[r->tdri];
+ if(b == nil)
+ panic("spi/interrupt: bufp");
+ r->txb[r->tdri] = nil;
+ freeb(b);
+ r->ntq--;
+ r->tdri = NEXT(r->tdri, Ntdre);
+ }
+ txstart(r);
+ unlock(r->ctlr);
+ if(r->ntq)
+ epprod(r->ctlr, r->x);
+ }
+}
+
+
+static void
+dumpspi(Block *b, char *msg)
+{
+ int i;
+
+ print("%s: %8.8lux [%d]: ", msg, (ulong)b->rp, BLEN(b));
+ for(i=0; i<BLEN(b) && i < 16; i++)
+ print(" %.2x", b->rp[i]);
+ print("\n");
+}
+
+static void
+setaddr(Endpt *e, int dev, int endpt)
+{
+ ushort v;
+
+ e->dev = dev;
+ e->endpt = endpt;
+ v = (e->endpt<<7) | e->dev;
+ v |= crc5(v) << 11;
+ e->addr[0] = v;
+ e->addr[1] = v>>8;
+}
+
+static int
+spiinput(void *a)
+{
+ return ((Ctlr*)a)->rxintr;
+}
+
+static void
+spitest(void)
+{
+ Ctlr *ctlr;
+ Endpt *e, *e1;
+ uchar msg[8];
+ int epn, testing, i;
+
+ ctlr = spictlr;
+ epn = 0;
+ testing = ctlr->spi->usmod & TEST;
+ if(testing)
+ epn = 1;
+ e = &ctlr->pts[0];
+ e1 = &ctlr->pts[1];
+ memset(msg, 0, 8);
+ msg[0] = 0;
+ msg[1] = 8; /* set configuration */
+ msg[2] = 1;
+ setaddr(e, 0, epn);
+ sendtoken(e, TokSETUP);
+ senddata(e, msg, 8);
+ if(!testing){
+ for(i=0; i<8; i++)
+ msg[i] = 0x40+i;
+ senddata(e1, msg, 8);
+ e->rxintr = 0;
+ sendtoken(e, TokIN);
+ transmit(e);
+ epprod(ctlr, 0);
+ tsleep(&e->ir, spiinput, e, 1000);
+ if(!spiinput(e))
+ print("RX: none\n");
+ }
+ sendtoken(e, TokSETUP);
+ msg[0] = 0x23;
+ msg[1] = 3; /* set feature */
+ msg[2] = 8; /* port power */
+ msg[3] = 0;
+ msg[4] = 1; /* port 1 */
+ senddata(e, msg, 8);
+ if(!testing){
+ for(i=0; i<8; i++)
+ msg[i] = 0x60+i;
+ senddata(e1, msg, 8);
+ e->rxintr = 0;
+ sendtoken(e, TokIN);
+ transmit(e);
+ epprod(ctlr, 0);
+ tsleep(&e->ir, spiinput, e, 1000);
+ if(!spiinput(e))
+ print("RX: none\n");
+ }
+}
+
+static void
+setupep(int n, EPparam *ep)
+{
+ Endpt *e;
+
+ e = &usbctlr->pts[n];
+ e->x = n;
+ e->ctlr = usbctlr;
+ e->xtog = TokDATA0;
+ if(e->oq == nil)
+ e->oq = qopen(8*1024, 1, 0, 0);
+ if(e->iq == nil)
+ e->iq = qopen(8*1024, 1, 0, 0);
+ e->ep = ep;
+ if(ioringinit(e, Nrdre, Ntdre, Bufsize) < 0)
+ panic("usbreset");
+ ep->rbase = PADDR(e->rdr);
+ ep->rbptr = ep->rbase;
+ ep->tbase = PADDR(e->tdr);
+ ep->tbptr = ep->tbase;
+ eieio();
+}
+
+
+#endif
A mpc/tar.c => mpc/tar.c +86 -0
@@ 0,0 1,86 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+typedef union Hblock Hblock;
+
+#define TBLOCK 512
+#define NAMSIZ 100
+union Hblock
+{
+ char dummy[TBLOCK];
+ struct header
+ {
+ char name[NAMSIZ];
+ char mode[8];
+ char uid[8];
+ char gid[8];
+ char size[12];
+ char mtime[12];
+ char chksum[8];
+ char linkflag;
+ char linkname[NAMSIZ];
+ } dbuf;
+};
+
+static int getdir(Hblock *hb, Dir *sp);
+static int checksum(Hblock *hb);
+
+uchar*
+tarlookup(uchar *addr, char *file, int *dlen)
+{
+ Hblock *hp;
+ Dir dir;
+
+print("tarlookup: %x\n", addr);
+ hp = (Hblock*)addr;
+ while(getdir(hp, &dir) != 0) {
+print("name = %s\n", hp->dbuf.name);
+ if(strcmp(file, hp->dbuf.name) == 0) {
+ *dlen = dir.length;
+ return (uchar*)(hp+1);
+ }
+ hp += (dir.length+TBLOCK-1)/TBLOCK + 1;
+ }
+ return 0;
+}
+
+static int
+getdir(Hblock *hp, Dir *sp)
+{
+ int chksum;
+
+ if (hp->dbuf.name[0] == '\0')
+ return 0;
+ sp->mode = strtol(hp->dbuf.mode, 0, 8);
+ strncpy(sp->uid, "adm", sizeof(sp->uid));
+ strncpy(sp->gid, "adm", sizeof(sp->gid));
+ sp->length = strtol(hp->dbuf.size, 0, 8);
+ sp->mtime = strtol(hp->dbuf.mtime, 0, 8);
+ chksum = strtol(hp->dbuf.chksum, 0, 8);
+ if (chksum != checksum(hp)) {
+ print("directory checksum error\n");
+ return 0;
+ }
+ return 1;
+}
+
+static int
+checksum(Hblock *hp)
+{
+ int i;
+ char *cp;
+
+ i = 0;
+ for (cp = hp->dummy; cp < &hp->dummy[TBLOCK]; cp++) {
+ if(cp < hp->dbuf.chksum || cp >= &hp->dbuf.chksum[sizeof(hp->dbuf.chksum)])
+ i += *cp & 0xff;
+ else
+ i += ' ' & 0xff;
+ }
+ return(i);
+}
M mpc/trap.c => mpc/trap.c +36 -24
@@ 35,6 35,7 @@ void faultpower(Ureg *ur, ulong addr, int read);
void kernfault(Ureg*, int);
void syscall(Ureg* ureg);
void noted(Ureg*, ulong);
+void reset(void);
char *excname[] =
{
@@ 119,7 120,7 @@ sethvec(int v, void (*r)(void))
{
ulong *vp, pa, o;
- vp = (ulong*)(0xfff00000+v);
+ vp = KADDR(v);
vp[0] = 0x7c1043a6; /* MOVW R0, SPR(SPRG0) */
vp[1] = 0x7c0802a6; /* MOVW LR, R0 */
vp[2] = 0x7c1243a6; /* MOVW R0, SPR(SPRG2) */
@@ 151,11 152,14 @@ trap(Ureg *ur)
{
int ecode;
static struct {int callsched;} c = {1};
+ int user = (ur->srr1 & MSR_PR) != 0;
+ char buf[ERRLEN];
m->intrts = fastticks(nil);
ecode = (ur->cause >> 8) & 0xff;
- if(ecode < 0 || ecode >= 0x1F)
- ecode = 0x1F;
+
+if(ur->status & MSR_RI == 0)
+print("double fault?: ecode = %d\n", ecode);
switch(ecode){
case CEI:
intr(ur);
@@ 164,21 168,24 @@ trap(Ureg *ur)
case CDEC:
clockintr(ur);
break;
-
case CIMISS:
+ faultpower(ur, ur->pc, 1);
+ break;
case CITLBE:
faultpower(ur, ur->pc, 1);
break;
case CDMISS:
- faultpower(ur, getdepn(), 1);
+if(0) print("CDMISS: %lux %lux\n", m->epn, m->cmp1);
+ faultpower(ur, m->dar, 1);
break;
case CDTLBE:
- faultpower(ur, getdar(), !(getdsisr() & (1<<25)));
+ faultpower(ur, m->dar, !(m->dsisr & (1<<25)));
break;
case CEMU:
- print("pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc);
- goto Default;
+ print("CEMU: pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc);
+ sprint(buf, "sys: trap: illegal op addr=0x%lux", ur->pc);
+ postnote(up, 1, buf, NDebug);
break;
case CSYSCALL:
@@ 196,14 203,20 @@ trap(Ureg *ur)
Default:
default:
+ spllo();
+ print("ecode = %d\n", ecode);
+ if(ecode < 0 || ecode >= 0x1F)
+ ecode = 0x1F;
print("kernel %s pc=0x%lux\n", excname[ecode], ur->pc);
dumpregs(ur);
dumpstack();
- spllo();
- exit(1);
+ delay(100);
+ reset();
}
splhi();
+ if(user)
+ notify(ur);
}
void
@@ 211,9 224,8 @@ faultpower(Ureg *ureg, ulong addr, int read)
{
int user, insyscall, n;
char buf[ERRLEN];
-
user = (ureg->srr1 & MSR_PR) != 0;
-//print("fault: pid=%d pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", up->pid, ureg->pc, addr, read, user, &ureg);
+if(0)print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg);
insyscall = up->insyscall;
up->insyscall = 1;
spllo();
@@ 223,7 235,8 @@ faultpower(Ureg *ureg, ulong addr, int read)
dumpregs(ureg);
panic("fault: 0x%lux\n", addr);
}
-print("sys: trap: fault %s addr=0x%lux\n", read? "read" : "write", addr);
+print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg);
+dumpregs(ureg);
sprint(buf, "sys: trap: fault %s addr=0x%lux",
read? "read" : "write", addr);
postnote(up, 1, buf, NDebug);
@@ 269,12 282,13 @@ trapinit(void)
/*
* set all exceptions to trap
*/
- for(i = 0x0; i < 0x3000; i += 0x100)
+ for(i = 0x0; i < 0x2000; i += 0x100)
sethvec(i, trapvec);
//sethvec(CEI<<8, intrvec);
- //sethvec2(CIMISS<<8, itlbmiss);
- //sethvec2(CDMISS<<8, dtlbmiss);
+ sethvec2(CIMISS<<8, itlbmiss);
+ sethvec2(CDMISS<<8, dtlbmiss);
+ sethvec2(CDTLBE<<8, dtlberror);
}
void
@@ 315,9 329,6 @@ intrenable(int v, void (*r)(Ureg*, void*), void *arg, int)
iunlock(&veclock);
}
-/*
- * called directly by l.s:/intrvec
- */
void
intr(Ureg *ur)
{
@@ 497,8 508,12 @@ reset(void)
io = m->iomem;
io->plprcrk = KEEP_ALIVE_KEY; // unlock
io->plprcr |= IBIT(24); // enable checkstop reset
- putmsr(getmsr() & ~MSR_ME);
+ putmsr(getmsr() & ~(MSR_ME|MSR_RI));
+predawn = 1;
+print("reset = %ulx\n", getmsr());
+ delay(1000);
// cause checkstop -> causes reset
+ *(uchar*)(0xdeadbeef) = 0;
*(ulong*)(0) = 0;
}
@@ 616,7 631,7 @@ syscall(Ureg* ureg)
up->dbgreg = ureg;
scallnr = ureg->r3;
-//print("scall %s\n", sysctab[scallnr]);
+//print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
up->scallnr = scallnr;
spllo();
@@ 676,8 691,6 @@ notify(Ureg* ur)
ulong s, sp;
Note *n;
-//print("***notify %ld\n", up->pid);
-
if(up->procctl)
procctl(up);
if(up->nnote == 0)
@@ 753,7 766,6 @@ noted(Ureg* ureg, ulong arg0)
Ureg *nureg;
ulong oureg, sp;
-//print("***noted\n");
qlock(&up->debug);
if(arg0!=NRSTR && !up->notified) {
qunlock(&up->debug);
M port/devdraw.c => port/devdraw.c +4 -4
@@ 360,7 360,7 @@ addflush(Rectangle r)
/*
* absorb if:
* total area is small
- * waste is less than ½ total area
+ * waste is less than half total area
* rectangles touch
*/
if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
@@ 981,7 981,7 @@ drawclose(Chan *c)
/* all screens are freed, so now we can free images */
dp = cl->dimage;
for(i=0; i<NHASH; i++){
- while(d = *dp){ /* assign = */
+ while((d = *dp) != nil){
*dp = d->next;
drawfreedimage(d);
}
@@ 1288,7 1288,7 @@ drawmesg(Client *client, void *av, int n)
fmt = nil;
if(waserror()){
if(fmt) printmesg(fmt, a, 1);
- // iprint("error: %s\n", up->error);
+ /* iprint("error: %s\n", up->error); */
nexterror();
}
while((n-=m) > 0){
@@ 1297,7 1297,7 @@ drawmesg(Client *client, void *av, int n)
switch(*a){
default:
error("bad draw command");
- /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbαα[4] */
+ /* new allocate: 'b' id[4] screenid[4] refresh[1] chan[4] repl[1] R[4*4] clipR[4*4] rrggbbaa[4] */
case 'b':
printmesg(fmt="LLbLbRRL", a, 0);
m = 1+4+4+1+4+1+4*4+4*4+4;
M port/devmouse.c => port/devmouse.c +1 -0
@@ 142,6 142,7 @@ mouseopen(Chan *c, int omode)
unlock(&mouse);
break;
case Qmousein:
+ error("disabled");
lock(&mouse);
if(mouse.inopen){
unlock(&mouse);
M port/devpipe.c => port/devpipe.c +15 -1
@@ 113,6 113,8 @@ static int
pipegen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
{
int id;
+ int len;
+ Pipe *p;
if(i == DEVDOTDOT){
devdir(c, c->qid, "#|", 0, eve, CHDIR|0555, dp);
@@ 125,7 127,19 @@ pipegen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
if(tab==0 || i>=ntab)
return -1;
tab += i;
- devdir(c, (Qid){NETQID(id, tab->qid.path),0}, tab->name, tab->length, eve, tab->perm, dp);
+ p = c->aux;
+ switch(tab->qid.path){
+ case Qdata0:
+ len = qlen(p->q[0]);
+ break;
+ case Qdata1:
+ len = qlen(p->q[1]);
+ break;
+ default:
+ len = tab->length;
+ break;
+ }
+ devdir(c, (Qid){NETQID(id, tab->qid.path),0}, tab->name, len, eve, tab->perm, dp);
return 1;
}