From 9fe2b517e9769fa149754efe5fddee414ea24bf5 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 16 May 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-05-16 --- mpc/clock.c | 48 +++ mpc/cmmu.c | 391 +++++++++++++++++++++++ mpc/conf.c | 74 +++++ mpc/cpm.c | 301 +++++++++--------- mpc/cpm2.c | 819 ++++++++++++++++++++++++++++++++++++++++++++++++ mpc/dat.h | 29 +- mpc/devether.c | 1 + mpc/devrtc.c | 18 +- mpc/devsac.c | 27 +- mpc/devuart.c | 21 +- mpc/devusb.c | 628 +++++++++++++++++++++++++++++++++++++ mpc/ether589.c | 64 ++-- mpc/etherif.h | 2 +- mpc/etherscc.c | 133 +++++--- mpc/fns.h | 15 +- mpc/l.s | 687 +++++++++++++++++++++++++++------------- mpc/main.c | 270 ++++++---------- mpc/mem.h | 42 ++- mpc/memspeed.c | 53 ++++ mpc/mmu.c | 137 +++++++- mpc/ms.c | 82 +++++ mpc/nocache.c | 1 - mpc/sh.c | 2 +- mpc/spi.c | 521 ++++++++++++++++++++++++++++++ mpc/tar.c | 86 +++++ mpc/trap.c | 60 ++-- port/devdraw.c | 8 +- port/devmouse.c | 1 + port/devpipe.c | 16 +- 29 files changed, 3811 insertions(+), 726 deletions(-) create mode 100644 mpc/cmmu.c create mode 100644 mpc/conf.c create mode 100644 mpc/cpm2.c create mode 100644 mpc/devusb.c create mode 100644 mpc/memspeed.c create mode 100644 mpc/ms.c create mode 100644 mpc/spi.c create mode 100644 mpc/tar.c diff --git a/mpc/clock.c b/mpc/clock.c index 7d7264956a0032b6c94216e8032c2d787d3bd275..0abdba1e93e7ef7d7396c18ac86d49e707d76660 100644 --- a/mpc/clock.c +++ b/mpc/clock.c @@ -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; diff --git a/mpc/cmmu.c b/mpc/cmmu.c new file mode 100644 index 0000000000000000000000000000000000000000..38171bfe0d64268df48bf22c439a4e57f02cb22c --- /dev/null +++ b/mpc/cmmu.c @@ -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; inext = 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)<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; ipidonmach[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; inewtlb = 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; +} diff --git a/mpc/conf.c b/mpc/conf.c new file mode 100644 index 0000000000000000000000000000000000000000..318913d83777bcb6b6417e5bc92cf52f99b5f57a --- /dev/null +++ b/mpc/conf.c @@ -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; +} diff --git a/mpc/cpm.c b/mpc/cpm.c index 12d3468fc0c1eb6548cca452266700d965b525b1..b9a476225b500b6693f7bbfc9293e8d54cfb35fb 100644 --- a/mpc/cpm.c +++ b/mpc/cpm.c @@ -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 */ diff --git a/mpc/cpm2.c b/mpc/cpm2.c new file mode 100644 index 0000000000000000000000000000000000000000..e56e57a5bca171170bfc6ad5c5900195fcb537df --- /dev/null +++ b/mpc/cpm2.c @@ -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<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<= 0){ + if(n > 3 || brgens.avail & (1<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; +} diff --git a/mpc/dat.h b/mpc/dat.h index 8512b4616dce1d8e4ddea76eb2298b6d298e13de..a6e1a22aa104d3c7f165ceb9a798a3e7414066d1 100644 --- a/mpc/dat.h +++ b/mpc/dat.h @@ -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<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) /* diff --git a/mpc/devether.c b/mpc/devether.c index 22bfea833b61cf42c474052771866455cc43ec22..4334bf9559d6f64b3d8e5797b164e9193357a0b6 100644 --- a/mpc/devether.c +++ b/mpc/devether.c @@ -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; diff --git a/mpc/devrtc.c b/mpc/devrtc.c index 718de8eb44ae2a2da16457fab6426cb22898070a..d83a4fc2680471a3ab62361d65c27ac98d281d90 100644 --- a/mpc/devrtc.c +++ b/mpc/devrtc.c @@ -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 */ diff --git a/mpc/devsac.c b/mpc/devsac.c index 4ab4e59760583a3978fc7365a16040d632599fd8..3ee3e104e9f7abb950d6079d3cfd59bfd51c2d95 100644 --- a/mpc/devsac.c +++ b/mpc/devsac.c @@ -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"); diff --git a/mpc/devuart.c b/mpc/devuart.c index c1450cbb4cc9738f41f7779bd7a21346f50dff62..b61ce5dfc911b625c66be0af1caa746d5551fd7d 100644 --- a/mpc/devuart.c +++ b/mpc/devuart.c @@ -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 */ } diff --git a/mpc/devusb.c b/mpc/devusb.c new file mode 100644 index 0000000000000000000000000000000000000000..ab9a982a3f2f2ee960bedbc450e247db13838e74 --- /dev/null +++ b/mpc/devusb.c @@ -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; iuscom = 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&&ilength; 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; irp[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"); + } +} diff --git a/mpc/ether589.c b/mpc/ether589.c index fb90a0df3247b4d7661ca594fcd6ced5b9295d87..d8931e2ddcc712827f6f61b23e1604100f822889 100644 --- a/mpc/ether589.c +++ b/mpc/ether589.c @@ -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 diff --git a/mpc/etherif.h b/mpc/etherif.h index 096c9d483bef5d5f458482d1d95b8c60b0a48d1f..6e43bf628ee3d246456443cf5e19a5d61fa47cb3 100644 --- a/mpc/etherif.h +++ b/mpc/etherif.h @@ -1,5 +1,5 @@ enum { - MaxEther = 24, + MaxEther = 4, Ntypes = 8, }; diff --git a/mpc/etherscc.c b/mpc/etherscc.c index 83492b466311d32b360d09e8c124d8da0c71f95a..6cf157c9ff130740452433df4155edf257e31d34 100644 --- a/mpc/etherscc.c +++ b/mpc/etherscc.c @@ -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); } diff --git a/mpc/fns.h b/mpc/fns.h index 56d8a3b790a3521fc6370f031632f4d09918196a..6000cc8a82ab70fafe9d8dbb8223dd2bbad67d0a 100644 --- a/mpc/fns.h +++ b/mpc/fns.h @@ -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))) diff --git a/mpc/l.s b/mpc/l.s index 06b987ec5a0dd276b0a7f616cf38c0b09f9eb8fc..af9b57c46956bdc89f44f58a26848e4bb29fe438 100644 --- a/mpc/l.s +++ b/mpc/l.s @@ -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 diff --git a/mpc/main.c b/mpc/main.c index 42f82992c617cdf8e4520f8a19e598b0a21590e8..5ea0c6c849a8ad40579085ded639aee5f10d535c 100644 --- a/mpc/main.c +++ b/mpc/main.c @@ -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; -} - diff --git a/mpc/mem.h b/mpc/mem.h index 27df46b398bbe2448df7c69f789f6f2be2966405..83c00d6160495b148c2d8486286b51945843f44d 100644 --- a/mpc/mem.h +++ b/mpc/mem.h @@ -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 @@ -99,11 +93,18 @@ #define SSEGMAPSIZE 16 #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<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); +} + diff --git a/mpc/mmu.c b/mpc/mmu.c index c35eddf77aca7b745c1a66fe2d576e1620516f95..04250808715eff8f780e32876cc5270a2c874276 100644 --- a/mpc/mmu.c +++ b/mpc/mmu.c @@ -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; istb[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; ipidonmach[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); } diff --git a/mpc/ms.c b/mpc/ms.c new file mode 100644 index 0000000000000000000000000000000000000000..2b369925be81b731db3d9bcc522a8f3872629b9d --- /dev/null +++ b/mpc/ms.c @@ -0,0 +1,82 @@ +#include +#include + +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); +} diff --git a/mpc/nocache.c b/mpc/nocache.c index 5b6f7c84d71608f7a73c1109e14e6101fbcd1f09..ce11c8cc79f3b885525faecb690185c1951c0494 100644 --- a/mpc/nocache.c +++ b/mpc/nocache.c @@ -15,7 +15,6 @@ cinit(void) void copen(Chan *c) { -print("copen called!\n"); USED(c); } diff --git a/mpc/sh.c b/mpc/sh.c index 36de6460a74e51f929c95121db96ea82b06d939e..8f18d06900ae7d0125c6d23076c8e5da8249e682 100644 --- a/mpc/sh.c +++ b/mpc/sh.c @@ -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++; diff --git a/mpc/spi.c b/mpc/spi.c new file mode 100644 index 0000000000000000000000000000000000000000..2bc6d2394084362766f1c0d3f1499f1169a96f29 --- /dev/null +++ b/mpc/spi.c @@ -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&&ilength; 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; irp[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 diff --git a/mpc/tar.c b/mpc/tar.c new file mode 100644 index 0000000000000000000000000000000000000000..7e9efdc1945b0382ae71874d02abd57cd1eee59e --- /dev/null +++ b/mpc/tar.c @@ -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); +} diff --git a/mpc/trap.c b/mpc/trap.c index 19a1819220c8391b8dc55c884609a5aafecfab6b..464b73280327bac0527dd017da5a92a56c5bba55 100644 --- a/mpc/trap.c +++ b/mpc/trap.c @@ -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); diff --git a/port/devdraw.c b/port/devdraw.c index 3335d7ccd3af0c1927f5c88f63cfc50f512fbee3..794171a10dd90e173d04f196a6a4e48023727d40 100644 --- a/port/devdraw.c +++ b/port/devdraw.c @@ -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*2dimage; for(i=0; inext; 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; diff --git a/port/devmouse.c b/port/devmouse.c index ecba107a9d8a0cef8c857c494ca0dc975fac33d5..30330e744947f4c56ac5fa0b5dd62b2fdcdee845 100644 --- a/port/devmouse.c +++ b/port/devmouse.c @@ -142,6 +142,7 @@ mouseopen(Chan *c, int omode) unlock(&mouse); break; case Qmousein: + error("disabled"); lock(&mouse); if(mouse.inopen){ unlock(&mouse); diff --git a/port/devpipe.c b/port/devpipe.c index 65814362d05bb463bd0bb97cfa5d391cd0cf419c..c5f29e117a6fb0d0a5a6df22bfa59c9ccb82c167 100644 --- a/port/devpipe.c +++ b/port/devpipe.c @@ -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; }