@@ 183,11 183,16 @@ enum { /* CbTransmit count */
CbEOF = 0x8000,
};
+typedef struct Ctlr Ctlr;
typedef struct Ctlr {
Lock slock; /* attach */
int state;
int port;
+ Pcidev* pcidev;
+ Ctlr* next;
+ int active;
+
int eepromsz; /* address size in bits */
ushort* eeprom;
@@ 219,6 224,9 @@ typedef struct Ctlr {
ulong dump[17];
} Ctlr;
+static Ctlr* ctlrhead;
+static Ctlr* ctlrtail;
+
static uchar configdata[24] = {
0x16, /* byte count */
0x08, /* Rx/Tx FIFO limit */
@@ 882,34 890,12 @@ reread:
return data;
}
-typedef struct Adapter {
- int port;
- int irq;
- int tbdf;
-} Adapter;
-static Block* adapter;
-
-static void
-i82557adapter(Block** bpp, int port, int irq, int tbdf)
-{
- Block *bp;
- Adapter *ap;
-
- bp = allocb(sizeof(Adapter));
- ap = (Adapter*)bp->rp;
- ap->port = port;
- ap->irq = irq;
- ap->tbdf = tbdf;
-
- bp->next = *bpp;
- *bpp = bp;
-}
-
static void
i82557pci(void)
{
- Pcidev *p;
int port;
+ Pcidev *p;
+ Ctlr *ctlr;
p = nil;
while(p = pcimatch(p, 0x8086, 0x1229)){
@@ 919,11 905,21 @@ i82557pci(void)
* bar[2] is for the flash ROM (1MB).
*/
port = p->mem[1].bar & ~0x01;
- if(ioalloc(port, p->mem[1].size, 0, "i82557pci") < 0){
- print("i82557pci: port 0x%uX in use\n", port);
+ if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
+ print("i82557: port 0x%uX in use\n", port);
continue;
}
- i82557adapter(&adapter, port, p->intl, p->tbdf);
+
+ ctlr = malloc(sizeof(Ctlr));
+ ctlr->port = port;
+ ctlr->pcidev = p;
+
+ if(ctlrhead != nil)
+ ctlrtail->next = ctlr;
+ else
+ ctlrhead = ctlr;
+ ctlrtail = ctlr;
+
pcisetbme(p);
}
}
@@ 970,51 966,41 @@ scanphy(Ctlr* ctlr)
static int
reset(Ether* ether)
{
- int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, port, x;
+ int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, x;
unsigned short sum;
- Block *bp, **bpp;
- Adapter *ap;
uchar ea[Eaddrlen];
Ctlr *ctlr;
- static int scandone;
- if(scandone == 0){
+ if(ctlrhead == nil)
i82557pci();
- scandone = 1;
- }
/*
- * Any adapter matches if no port is supplied,
+ * Any adapter matches if no ether->port is supplied,
* otherwise the ports must match.
*/
- port = 0;
- bpp = &adapter;
- for(bp = *bpp; bp; bp = bp->next){
- ap = (Adapter*)bp->rp;
- if(ether->port == 0 || ether->port == ap->port){
- port = ap->port;
- ether->irq = ap->irq;
- ether->tbdf = ap->tbdf;
- *bpp = bp->next;
- freeb(bp);
+ for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
+ if(ctlr->active)
+ continue;
+ if(ether->port == 0 || ether->port == ctlr->port){
+ ctlr->active = 1;
break;
}
- bpp = &bp->next;
}
- if(port == 0)
+ if(ctlr == nil)
return -1;
/*
- * Allocate a controller structure and start to initialise it.
+ * Initialise the Ctlr structure.
* Perform a software reset after which should ensure busmastering
* is still enabled. The EtherExpress PRO/100B appears to leave
* the PCI configuration alone (see the 'To do' list above) so punt
* for now.
* Load the RUB and CUB registers for linear addressing (0).
*/
- ether->ctlr = malloc(sizeof(Ctlr));
- ctlr = ether->ctlr;
- ctlr->port = port;
+ ether->ctlr = ctlr;
+ ether->port = ctlr->port;
+ ether->irq = ctlr->pcidev->intl;
+ ether->tbdf = ctlr->pcidev->tbdf;
ilock(&ctlr->rlock);
csr32w(ctlr, Port, 0);
@@ 1053,16 1039,29 @@ reset(Ether* ether)
* to set any PHY specific options and determine the speed.
* Unfortunately, sometimes the EEPROM is blank except for
* the ether address and checksum; in this case look at the
- * controller type and if 0 scan for the first PHY and try to
- * use that.
+ * controller type and if it's am 82558 or 82559 it has an
+ * embedded PHY so scan for that.
* If no PHY, assume 82503 (serial) operation.
*/
if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))
phyaddr = ctlr->eeprom[6] & 0x00FF;
- else if(!(ctlr->eeprom[5] & 0xFF00))
- phyaddr = scanphy(ctlr);
else
+ switch(ctlr->pcidev->rid){
+ case 0x01: /* 82557 A-step */
+ case 0x02: /* 82557 B-step */
+ case 0x03: /* 82557 C-step */
+ default:
phyaddr = -1;
+ break;
+ case 0x04: /* 82558 A-step */
+ case 0x05: /* 82558 B-step */
+ case 0x06: /* 82559 A-step */
+ case 0x07: /* 82559 B-step */
+ case 0x08: /* 82559 C-step */
+ case 0x09: /* 82559ER A-step */
+ phyaddr = scanphy(ctlr);
+ break;
+ }
if(phyaddr >= 0){
/*
* Resolve the highest common ability of the two
@@ 1234,7 1233,6 @@ reset(Ether* ether)
/*
* Linkage to the generic ethernet driver.
*/
- ether->port = port;
ether->attach = attach;
ether->transmit = transmit;
ether->interrupt = interrupt;