From dce0b3ea5e6472bf9439edd32b33623e28cf6e91 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 18 Jul 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-07-18 --- pc/ether2114x.c | 119 ++++++++++++++++++++++++++++++++++++++++++------ pc/sdmylex.c | 89 +++++++++++++++++++++++++----------- port/dev.c | 38 ++++++++++------ port/devsrv.c | 1 + port/latin1.h | 2 +- port/portfns.h | 1 + 6 files changed, 196 insertions(+), 54 deletions(-) diff --git a/pc/ether2114x.c b/pc/ether2114x.c index 979befc8968be017a3fe445132d09945b31219ab..561fab85efdda01ac35406a72bf5014966287e00 100644 --- a/pc/ether2114x.c +++ b/pc/ether2114x.c @@ -19,7 +19,7 @@ #include "etherif.h" -#define DEBUG 0 +#define DEBUG (1) #define debug if(DEBUG)print enum { @@ -27,6 +27,8 @@ enum { Ntde = 64, }; +#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4) + enum { /* CRS0 - Bus Mode */ Swr = 0x00000001, /* Software Reset */ Bar = 0x00000002, /* Bus Arbitration */ @@ -181,12 +183,20 @@ enum { /* PHY registers */ Aner = 6, /* Auto-Negotiation Expansion */ }; +enum { /* Variants */ + Tulip0 = (0x0009<<16)|0x1011, + Tulip3 = (0x0019<<16)|0x1011, + Pnic = (0x0002<<16)|0x11AD, + Pnic2 = (0xC115<<16)|0x11AD, +}; + typedef struct Ctlr Ctlr; typedef struct Ctlr { int port; Pcidev* pcidev; Ctlr* next; int active; + int id; /* (pcidev->did<<16)|pcidev->vid */ uchar srom[128]; uchar* sromea; /* MAC address */ @@ -455,7 +465,7 @@ interrupt(Ureg*, void* arg) if(des->status & De) ctlr->de++; } - else if(bp = iallocb(sizeof(Etherpkt)+4)){ + else if(bp = iallocb(Rbsz)){ len = ((des->status & Fl)>>16)-4; des->bp->wp = des->bp->rp+len; etheriq(ether, des->bp, 1); @@ -464,7 +474,7 @@ interrupt(Ureg*, void* arg) } des->control &= Er; - des->control |= ROUNDUP(sizeof(Etherpkt)+4, 4); + des->control |= Rbsz; coherence(); des->status = Own; @@ -566,9 +576,9 @@ ctlrinit(Ether* ether) */ ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des)); for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = allocb(ROUNDUP(sizeof(Etherpkt)+4, 4)); + des->bp = allocb(Rbsz); des->status = Own; - des->control = ROUNDUP(sizeof(Etherpkt)+4, 4); + des->control = Rbsz; des->addr = PADDR(des->bp->rp); } ctlr->rdr[ctlr->nrdr-1].control |= Er; @@ -581,7 +591,12 @@ ctlrinit(Ether* ether) ctlr->tdri = 0; csr32w(ctlr, 4, PADDR(ctlr->tdr)); + /* + * Clear any bits in the Status Register (CSR5) as + * the PNIC has a different reset value from a true 2114x. + */ ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti; + csr32w(ctlr, 5, ctlr->mask); csr32w(ctlr, 7, ctlr->mask); ctlr->csr6 |= St; csr32w(ctlr, 6, ctlr->csr6); @@ -652,7 +667,20 @@ miimdo(Ctlr* ctlr, int bits, int n) static int miir(Ctlr* ctlr, int phyad, int regad) { - int data; + int data, i; + + if(ctlr->id == Pnic){ + i = 1000; + csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18)); + do{ + microdelay(1); + data = csr32r(ctlr, 20); + }while((data & 0x80000000) && --i); + + if(i == 0) + return -1; + return data & 0xFFFF; + } /* * Preamble; @@ -690,6 +718,17 @@ sromr(Ctlr* ctlr, int r) { int i, op, data; + if(ctlr->id == Pnic){ + i = 1000; + csr32w(ctlr, 19, 0x600|r); + do{ + microdelay(1); + data = csr32r(ctlr, 19); + }while((data & 0x80000000) && --i); + + return csr32r(ctlr, 9) & 0xFFFF; + } + /* * This sequence for reading a 16-bit register 'r' * in the EEPROM is taken straight from Section @@ -760,7 +799,7 @@ type5block(Ctlr* ctlr, uchar* block) * sequence. */ len = *block++; - if(ctlr->pcidev->did == 0x0009){ + if(ctlr->id != Tulip3){ for(i = 0; i < len; i++){ csr32w(ctlr, 12, *block); block++; @@ -1139,6 +1178,30 @@ static uchar* leaf21140[] = { nil, }; +/* + * Copied to ctlr->srom at offset 20. + */ +static uchar leafpnic[] = { + 0x00, 0x00, 0x00, 0x00, /* MAC address */ + 0x00, 0x00, + 0x00, /* controller 0 device number */ + 0x1E, 0x00, /* controller 0 info leaf offset */ + 0x00, /* reserved */ + 0x00, 0x08, /* selected connection type */ + 0x00, /* general purpose control */ + 0x01, /* block count */ + + 0x8C, /* format indicator and count */ + 0x01, /* block type */ + 0x00, /* PHY number */ + 0x00, /* GPR sequence length */ + 0x00, /* reset sequence length */ + 0x00, 0x78, /* media capabilities */ + 0xE0, 0x01, /* Nway advertisment */ + 0x00, 0x50, /* FDX bitmap */ + 0x00, 0x18, /* TTM bitmap */ +}; + static int srom(Ctlr* ctlr) { @@ -1179,6 +1242,19 @@ srom(Ctlr* ctlr) } } + /* + * Fake up the SROM for the PNIC. + * It looks like a 21140 with a PHY. + * The MAC address is byte-swapped in the orginal SROM data. + */ + if(ctlr->id == Pnic){ + memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic)); + for(i = 0; i < Eaddrlen; i += 2){ + ctlr->srom[20+i] = ctlr->srom[i+1]; + ctlr->srom[20+i+1] = ctlr->srom[i]; + } + } + /* * Next, try to find the info leaf in the SROM for media detection. * If it's a non-conforming card try to match the vendor ethernet code @@ -1212,7 +1288,7 @@ srom(Ctlr* ctlr) ctlr->leaf = p; ctlr->sct = *p++; ctlr->sct |= *p++<<8; - if(ctlr->pcidev->did == 0x0009){ + if(ctlr->id != Tulip3){ csr32w(ctlr, 12, Gpc|*p++); delay(200); } @@ -1227,7 +1303,7 @@ srom(Ctlr* ctlr) * The RAMIX PMC665 has a badly-coded SROM, * hence the test for 21143 and type 3. */ - if((*p & 0x80) || (ctlr->pcidev->did == 0x0019 && *(p+1) == 3)){ + if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){ *p |= 0x80; if(*(p+1) == 1 || *(p+1) == 3) phy = 1; @@ -1278,12 +1354,14 @@ dec2114xpci(void) int x; p = nil; - while(p = pcimatch(p, 0x1011, 0)){ - switch(p->did){ + while(p = pcimatch(p, 0, 0)){ + if(p->ccrb != 0x02 || p->ccru != 0) + continue; + switch((p->did<<16)|p->vid){ default: continue; - case 0x0019: /* 21143 */ + case Tulip3: /* 21143 */ /* * Exit sleep mode. */ @@ -1292,7 +1370,9 @@ dec2114xpci(void) pcicfgw32(p, 0x40, x); /*FALLTHROUGH*/ - case 0x0009: /* 21140 */ + case Pnic: /* PNIC */ + case Pnic2: /* PNIC-II */ + case Tulip0: /* 21140 */ break; } @@ -1303,6 +1383,7 @@ dec2114xpci(void) ctlr = malloc(sizeof(Ctlr)); ctlr->port = p->mem[0].bar & ~0x01; ctlr->pcidev = p; + ctlr->id = (p->did<<16)|p->vid; if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){ print("dec2114x: port 0x%uX in use\n", ctlr->port); @@ -1323,6 +1404,18 @@ dec2114xpci(void) break; } + switch(ctlr->id){ + default: + break; + + case Pnic: /* PNIC */ + /* + * Turn off the jabber timer. + */ + csr32w(ctlr, 15, 0x00000001); + break; + } + if(ctlrhead != nil) ctlrtail->next = ctlr; else diff --git a/pc/sdmylex.c b/pc/sdmylex.c index dcc759a0a218b595021e635d886681558ae49a2e..44a5ad10cdbc84f54a47551af39b14deda9f4740 100644 --- a/pc/sdmylex.c +++ b/pc/sdmylex.c @@ -4,7 +4,6 @@ * 24-bit mode works for Adaptec AHA-154xx series too. * * To do: - * tidy the PCI probe and do EISA; * allocate more Ccb's as needed, up to NMbox-1; * add nmbox and nccb to Ctlr struct for the above; * 64-bit LUN/explicit wide support necessary? @@ -54,7 +53,7 @@ enum { /* Rstatus */ enum { /* Rcpr */ Cinitialise = 0x01, /* Initialise Mailbox */ Cstart = 0x02, /* Start Mailbox Command */ - Cinquiry = 0x04, /* Adapter Anquiry */ + Cinquiry = 0x04, /* Adapter Inquiry */ Ceombri = 0x05, /* Enable OMBR Interrupt */ Cinquire = 0x0B, /* Inquire Configuration */ Cextbios = 0x28, /* AHA-1542: extended BIOS info. */ @@ -224,7 +223,7 @@ enum { NCcb = NMbox-1, /* number of Ccb's */ }; -#define PADDR24(a, n) (PADDR(a)+n <= (1<<24)) +#define PADDR24(a, n) ((PADDR(a)+(n)) <= (1<<24)) static void ccbfree(Ctlr* ctlr, Ccb* ccb) @@ -253,7 +252,7 @@ ccballoc(Ctlr* ctlr) for(;;){ lock(&ctlr->ccblock); - if(ccb = ctlr->ccb){ + if((ccb = ctlr->ccb) != nil){ if(ctlr->bus == 24) ctlr->ccb = ((Ccb24*)ccb)->ccb; else @@ -303,7 +302,7 @@ mylex24rio(SDreq* r) * from the last completed Ccb, return it immediately. */ lock(&ctlr->cachelock); - if(ccb = ctlr->cache[target]){ + if((ccb = ctlr->cache[target]) != nil){ ctlr->cache[target] = nil; if(r->cmd[0] == 0x03 && ccb->sdstat == SDcheck && lun == ((ccb->cs[1]>>5) & 0x07)){ @@ -410,9 +409,21 @@ mylex24rio(SDreq* r) */ while(waserror()) ; - sleep(ccb, done24, ccb); + tsleep(ccb, done24, ccb, 30*1000); poperror(); + if(!done24(ccb)){ + print("%s: %d/%d: sd24rio timeout\n", + ctlr->sdev->name, target, r->lun); + if(ccb->data != nil){ + free(data); + ccb->data = nil; + } + ccbfree(ctlr, (Ccb*)ccb); + + return SDtimeout; + } + /* * Save the status and patch up the number of * bytes actually transferred. @@ -434,7 +445,7 @@ mylex24rio(SDreq* r) /* * Tidy things up if a staging area was used for the data, */ - if(ccb->data){ + if(ccb->data != nil){ if(sdstat == SDok && btstat == 0 && !r->write) memmove(ccb->data, data, n); free(data); @@ -545,10 +556,10 @@ mylex32rio(SDreq* r) * from the last completed Ccb, return it immediately. */ lock(&ctlr->cachelock); - if(ccb = ctlr->cache[target]){ + if((ccb = ctlr->cache[target]) != nil){ ctlr->cache[target] = nil; if(r->cmd[0] == 0x03 - && ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){ + && ccb->sdstat == SDcheck && lun == (ccb->luntag & 0x07)){ unlock(&ctlr->cachelock); if(r->dlen){ n = 8+ccb->sense[7]; @@ -572,11 +583,11 @@ mylex32rio(SDreq* r) n = r->dlen; if(n == 0) - ccb->datadir |= CCBdataout|CCBdatain; + ccb->datadir = CCBdataout|CCBdatain; else if(!r->write) - ccb->datadir |= CCBdatain; + ccb->datadir = CCBdatain; else - ccb->datadir |= CCBdataout; + ccb->datadir = CCBdataout; ccb->cdblen = r->clen; @@ -631,9 +642,17 @@ mylex32rio(SDreq* r) */ while(waserror()) ; - sleep(ccb, done32, ccb); + tsleep(ccb, done32, ccb, 30*1000); poperror(); + if(!done32(ccb)){ + print("%s: %d/%d: sd32rio timeout\n", + ctlr->sdev->name, target, r->lun); + ccbfree(ctlr, (Ccb*)ccb); + + return SDtimeout; + } + /* * Save the status and patch up the number of * bytes actually transferred. @@ -972,6 +991,8 @@ buggery: outb(0x0A, 0x00); break; default: + if(ctlr->bus == 24) + goto buggery; break; } @@ -1021,7 +1042,8 @@ mylexpnp(void) { Pcidev *p; Ctlr *ctlr; - int cfg, i, x; + ISAConf isa; + int cfg, ctlrno, i, x; SDev *sdev, *head, *tail; p = nil; @@ -1040,17 +1062,33 @@ mylexpnp(void) tail = sdev; } - if(strncmp(KADDR(0xFFFD9), "EISA", 4)) - return head; - for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){ - x = 0; - for(i = 0; i < 4; i++) - x |= inb(cfg+CfgEISA+i)<<(i*8); - if(x != 0x0142B30A && x != 0x0242B30A) - continue; + if(strncmp(KADDR(0xFFFD9), "EISA", 4) == 0){ + for(cfg = 0x1000; cfg < MaxEISA*0x1000; cfg += 0x1000){ + x = 0; + for(i = 0; i < 4; i++) + x |= inb(cfg+CfgEISA+i)<<(i*8); + if(x != 0x0142B30A && x != 0x0242B30A) + continue; + + x = inb(cfg+0xC8C); + if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil) + continue; + + if(head != nil) + tail->next = sdev; + else + head = sdev; + tail = sdev; + } + } - x = inb(cfg+0xC8C); - if((sdev = mylexprobe(mylexport[x & 0x07], -1)) == nil) + for(ctlrno = 0; ctlrno < 4; ctlrno++){ + memset(&isa, 0, sizeof(isa)); + if(!isaconfig("scsi", ctlrno, &isa)) + continue; + if(strcmp(isa.type, "aha1542")) + continue; + if((sdev = mylexprobe(isa.port, -1)) == nil) continue; if(head != nil) @@ -1104,9 +1142,8 @@ mylex24enable(Ctlr* ctlr) cmd[2] = p>>16; cmd[3] = p>>8; cmd[4] = p; - len = 5; - return issue(ctlr, cmd, len, 0, 0); + return issue(ctlr, cmd, 5, 0, 0); } static int diff --git a/port/dev.c b/port/dev.c index 78019c300e050579c919b639d464079f1a6ea332..8978bff3f1eb3c8cff04fb83beb7fe6f259b35e2 100644 --- a/port/dev.c +++ b/port/dev.c @@ -209,13 +209,33 @@ devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen) return m; } +/* + * error(Eperm) if open permission not granted for up->user. + */ +void +devpermcheck(char *fileuid, ulong perm, int omode) +{ + ulong t; + static int access[] = { 0400, 0200, 0600, 0100 }; + + if(strcmp(up->user, fileuid) == 0) + perm <<= 0; + else + if(strcmp(up->user, eve) == 0) + perm <<= 3; + else + perm <<= 6; + + t = access[omode&3]; + if((t&perm) != t) + error(Eperm); +} + Chan* devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen) { int i; Dir dir; - ulong t, mode; - static int access[] = { 0400, 0200, 0600, 0100 }; for(i=0;; i++) { switch((*gen)(c, tab, ntab, i, &dir)){ @@ -225,18 +245,8 @@ devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen) break; case 1: if(c->qid.path == dir.qid.path) { - if(strcmp(up->user, dir.uid) == 0) - mode = dir.mode; - else - if(strcmp(up->user, eve) == 0) - mode = dir.mode<<3; - else - mode = dir.mode<<6; - - t = access[omode&3]; - if((t & mode) == t) - goto Return; - error(Eperm); + devpermcheck(dir.uid, dir.mode, omode); + goto Return; } break; } diff --git a/port/devsrv.c b/port/devsrv.c index dc8db5288634e9534d58b97a8e1d8bcc470d3391..9f4e657daee8d8661e7cf0150105a4847a650708 100644 --- a/port/devsrv.c +++ b/port/devsrv.c @@ -122,6 +122,7 @@ srvopen(Chan *c, int omode) error("srv file already exists"); if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR) error(Eperm); + devpermcheck(sp->owner, sp->perm, omode); cclose(c); incref(sp->chan); diff --git a/port/latin1.h b/port/latin1.h index 04e535b01f671a1ddbeb727f7e9e095f3af03aba..2ecfaecfcf5de03b6609a11affcc55b89e3a6c4c 100644 --- a/port/latin1.h +++ b/port/latin1.h @@ -61,7 +61,7 @@ "T", "-u", L"Ŧ⊨", "V", "=", L"⇐", "Y", "R", L"Ʀ", - "Z", "-Z", L"Ƶℤ", + "Z", "-ACSZ", L"Ƶℤ", "^", "ACEGHIJOSUWYaceghijosuwy", L"ÂĈÊĜĤÎĴÔŜÛŴŶâĉêĝĥîĵôŝûŵŷ", "_\"", "AUau", L"ǞǕǟǖ", "_,", "Oo", L"Ǭǭ", diff --git a/port/portfns.h b/port/portfns.h index 4a512183e12ac4708acd4dd8244d507d88275a88..a19151cc5cd68fe9451a7972848c5ba62c5a52a5 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -74,6 +74,7 @@ Devgen devgen; void devinit(void); int devno(int, int); Chan* devopen(Chan*, int, Dirtab*, int, Devgen*); +void devpermcheck(char*, ulong, int); void devremove(Chan*); void devreset(void); void devstat(Chan*, char*, Dirtab*, int, Devgen*);