M pc/ether2114x.c => pc/ether2114x.c +106 -13
@@ 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)
{
@@ 1180,6 1243,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
* and point p at a fake info leaf with compact 21140 entries.
@@ 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
M pc/sdmylex.c => pc/sdmylex.c +63 -26
@@ 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
M port/dev.c => port/dev.c +24 -14
@@ 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;
}
M port/devsrv.c => port/devsrv.c +1 -0
@@ 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);
M port/latin1.h => port/latin1.h +1 -1
@@ 61,7 61,7 @@
"T", "-u", L"Ŧ⊨",
"V", "=", L"⇐",
"Y", "R", L"Ʀ",
- "Z", "-Z", L"Ƶℤ",
+ "Z", "-ACSZ", L"Ƶℤ",
"^", "ACEGHIJOSUWYaceghijosuwy", L"ÂĈÊĜĤÎĴÔŜÛŴŶâĉêĝĥîĵôŝûŵŷ",
"_\"", "AUau", L"ǞǕǟǖ",
"_,", "Oo", L"Ǭǭ",
M port/portfns.h => port/portfns.h +1 -0
@@ 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*);