|
@@ -17,7 +17,6 @@
|
|
|
#include "fns.h"
|
|
|
#include "io.h"
|
|
|
|
|
|
-
|
|
|
typedef struct QLock { int r; } QLock;
|
|
|
#define qlock(i) while(0)
|
|
|
#define qunlock(i) while(0)
|
|
@@ -106,6 +105,16 @@ enum { /* Tcr */
|
|
|
Ifg2 = 0x00080000, /* Interframe Gap 2 */
|
|
|
HwveridSHIFT = 23, /* Hardware Version ID */
|
|
|
HwveridMASK = 0x7C800000,
|
|
|
+ Macv01 = 0x00000000, /* RTL8169 */
|
|
|
+ Macv02 = 0x00800000, /* RTL8169S/8110S */
|
|
|
+ Macv03 = 0x04000000, /* RTL8169S/8110S */
|
|
|
+ Macv04 = 0x10000000, /* RTL8169SB/8110SB */
|
|
|
+ Macv05 = 0x18000000, /* RTL8169SC/8110SC */
|
|
|
+ Macv11 = 0x30000000, /* RTL8168B/8111B */
|
|
|
+ Macv12 = 0x38000000, /* RTL8169B/8111B */
|
|
|
+ Macv13 = 0x34000000, /* RTL8101E */
|
|
|
+ Macv14 = 0x30800000, /* RTL8100E */
|
|
|
+ Macv15 = 0x38800000, /* RTL8100E */
|
|
|
Ifg0 = 0x01000000, /* Interframe Gap 0 */
|
|
|
Ifg1 = 0x02000000, /* Interframe Gap 1 */
|
|
|
};
|
|
@@ -234,18 +243,30 @@ struct Dtcc {
|
|
|
u16int txundrn;
|
|
|
};
|
|
|
|
|
|
+enum { /* Variants */
|
|
|
+ Rtl8100e = (0x8136<<16)|0x10EC, /* RTL810[01]E ? */
|
|
|
+ Rtl8169sc = (0x8167<<16)|0x10EC, /* RTL8169SC */
|
|
|
+ Rtl8168b = (0x8168<<16)|0x10EC, /* RTL8168B */
|
|
|
+ Rtl8169 = (0x8169<<16)|0x10EC, /* RTL8169 */
|
|
|
+};
|
|
|
+
|
|
|
typedef struct Ctlr Ctlr;
|
|
|
typedef struct Ctlr {
|
|
|
int port;
|
|
|
Pcidev* pcidev;
|
|
|
Ctlr* next;
|
|
|
int active;
|
|
|
- uint id;
|
|
|
+
|
|
|
+ void* nic;
|
|
|
|
|
|
QLock alock; /* attach */
|
|
|
Lock ilock; /* init */
|
|
|
int init; /* */
|
|
|
|
|
|
+ int pciv; /* */
|
|
|
+ int macv; /* MAC version */
|
|
|
+ int phyv; /* PHY version */
|
|
|
+
|
|
|
Mii* mii;
|
|
|
|
|
|
Lock tlock; /* transmit */
|
|
@@ -285,8 +306,8 @@ typedef struct Ctlr {
|
|
|
uint fovw;
|
|
|
} Ctlr;
|
|
|
|
|
|
-static Ctlr* ctlrhead;
|
|
|
-static Ctlr* ctlrtail;
|
|
|
+static Ctlr* rtl8169ctlrhead;
|
|
|
+static Ctlr* rtl8169ctlrtail;
|
|
|
|
|
|
#define csr8r(c, r) (inb((c)->port+(r)))
|
|
|
#define csr16r(c, r) (ins((c)->port+(r)))
|
|
@@ -358,36 +379,59 @@ rtl8169mii(Ctlr* ctlr)
|
|
|
ctlr->mii->mir = rtl8169miimir;
|
|
|
ctlr->mii->miw = rtl8169miimiw;
|
|
|
ctlr->mii->ctlr = ctlr;
|
|
|
- rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
|
|
|
|
|
|
- if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
|
|
|
+ /*
|
|
|
+ * Get rev number out of Phyidr2 so can config properly.
|
|
|
+ * There's probably more special stuff for Macv0[234] needed here.
|
|
|
+ */
|
|
|
+ ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F;
|
|
|
+ if(ctlr->macv == Macv02){
|
|
|
+ csr8w(ctlr, 0x82, 1); /* magic */
|
|
|
+ rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
|
|
|
+ }
|
|
|
+
|
|
|
+ if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
|
|
|
free(ctlr->mii);
|
|
|
ctlr->mii = nil;
|
|
|
return -1;
|
|
|
}
|
|
|
- print("oui %X phyno %d\n", phy->oui, phy->phyno);
|
|
|
+ print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
|
|
|
+ phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
|
|
|
|
|
|
miiane(ctlr->mii, ~0, ~0, ~0);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+rtl8169halt(Ctlr* ctlr)
|
|
|
+{
|
|
|
+ csr8w(ctlr, Cr, 0);
|
|
|
+ csr16w(ctlr, Imr, 0);
|
|
|
+ csr16w(ctlr, Isr, ~0);
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
rtl8169reset(Ctlr* ctlr)
|
|
|
{
|
|
|
+ u32int r;
|
|
|
int timeo;
|
|
|
|
|
|
/*
|
|
|
* Soft reset the controller.
|
|
|
*/
|
|
|
csr8w(ctlr, Cr, Rst);
|
|
|
- for(timeo = 0; timeo < 1000; timeo++){
|
|
|
- if(!(csr8r(ctlr, Cr) & Rst))
|
|
|
- return 0;
|
|
|
+ for(r = timeo = 0; timeo < 1000; timeo++){
|
|
|
+ r = csr8r(ctlr, Cr);
|
|
|
+ if(!(r & Rst))
|
|
|
+ break;
|
|
|
delay(1);
|
|
|
}
|
|
|
+ rtl8169halt(ctlr);
|
|
|
|
|
|
- return -1;
|
|
|
+ if(r & Rst)
|
|
|
+ return -1;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -396,14 +440,6 @@ rtl8169detach(Ether* edev)
|
|
|
rtl8169reset(edev->ctlr);
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-rtl8169halt(Ctlr* ctlr)
|
|
|
-{
|
|
|
- csr8w(ctlr, Cr, 0);
|
|
|
- csr16w(ctlr, Imr, 0);
|
|
|
- csr16w(ctlr, Isr, ~0);
|
|
|
-}
|
|
|
-
|
|
|
static void
|
|
|
rtl8169replenish(Ctlr* ctlr)
|
|
|
{
|
|
@@ -418,7 +454,7 @@ rtl8169replenish(Ctlr* ctlr)
|
|
|
/*
|
|
|
* simple allocation for now
|
|
|
*/
|
|
|
- bp = malloc(Mps);
|
|
|
+ bp = mallocalign(Mps, 8, 0, 0);
|
|
|
ctlr->rb[rdt] = bp;
|
|
|
d->addrlo = PCIWADDR(bp);
|
|
|
d->addrhi = 0;
|
|
@@ -431,23 +467,18 @@ rtl8169replenish(Ctlr* ctlr)
|
|
|
ctlr->rdt = rdt;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
+static int
|
|
|
rtl8169init(Ether* edev)
|
|
|
{
|
|
|
- uint r;
|
|
|
+ u32int r;
|
|
|
Ctlr *ctlr;
|
|
|
+ u8int cplusc;
|
|
|
|
|
|
ctlr = edev->ctlr;
|
|
|
ilock(&ctlr->ilock);
|
|
|
|
|
|
rtl8169halt(ctlr);
|
|
|
|
|
|
- /*
|
|
|
- * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst settings
|
|
|
- * in Tcr/Rcr.
|
|
|
- */
|
|
|
- csr16w(ctlr, Cplusc, (1<<14)|Rxchksum|Mulrw); /* magic (1<<14) */
|
|
|
-
|
|
|
/*
|
|
|
* MAC Address.
|
|
|
* Must put chip into config register write enable mode.
|
|
@@ -458,46 +489,96 @@ rtl8169init(Ether* edev)
|
|
|
r = (edev->ea[5]<<8)|edev->ea[4];
|
|
|
csr32w(ctlr, Idr0+4, r);
|
|
|
|
|
|
- /*
|
|
|
- * Enable receiver/transmitter.
|
|
|
- * Need to do this first or some of the settings below
|
|
|
- * won't take.
|
|
|
- */
|
|
|
- csr8w(ctlr, Cr, Te|Re);
|
|
|
-
|
|
|
/*
|
|
|
* Transmitter.
|
|
|
- * Mtps is in units of 128.
|
|
|
*/
|
|
|
memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
|
|
|
ctlr->tdh = ctlr->tdt = 0;
|
|
|
ctlr->td[ctlr->ntd-1].control = Eor;
|
|
|
- ctlr->mtps = HOWMANY(Mps, 128);
|
|
|
|
|
|
/*
|
|
|
* Receiver.
|
|
|
+ * Need to do something here about the multicast filter.
|
|
|
*/
|
|
|
memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
|
|
|
ctlr->rdh = ctlr->rdt = 0;
|
|
|
ctlr->rd[ctlr->nrd-1].control = Eor;
|
|
|
-
|
|
|
- //for(i = 0; i < ctlr->nrd; i++){
|
|
|
- // if((bp = ctlr->rb[i]) != nil){
|
|
|
- // ctlr->rb[i] = nil;
|
|
|
- // freeb(bp);
|
|
|
- // }
|
|
|
- //}
|
|
|
rtl8169replenish(ctlr);
|
|
|
- ctlr->rcr = Rxfth256|Mrxdmaunlimited|Ab|Apm;
|
|
|
+ ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Mtps is in units of 128 except for the RTL8169
|
|
|
+ * where is is 32. If using jumbo frames should be
|
|
|
+ * set to 0x3F.
|
|
|
+ * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
|
|
|
+ * settings in Tcr/Rcr; the (1<<14) is magic.
|
|
|
+ */
|
|
|
+ ctlr->mtps = HOWMANY(Mps, 128);
|
|
|
+ cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
|
|
|
+ cplusc |= Rxchksum|Mulrw;
|
|
|
+ switch(ctlr->macv){
|
|
|
+ default:
|
|
|
+ return -1;
|
|
|
+ case Macv01:
|
|
|
+ ctlr->mtps = HOWMANY(Mps, 32);
|
|
|
+ break;
|
|
|
+ case Macv02:
|
|
|
+ case Macv03:
|
|
|
+ cplusc |= (1<<14); /* magic */
|
|
|
+ break;
|
|
|
+ case Macv05:
|
|
|
+ /*
|
|
|
+ * This is interpreted from clearly bogus code
|
|
|
+ * in the manufacturer-supplied driver, it could
|
|
|
+ * be wrong. Untested.
|
|
|
+ */
|
|
|
+ r = csr8r(ctlr, Config2) & 0x07;
|
|
|
+ if(r == 0x01) /* 66MHz PCI */
|
|
|
+ csr32w(ctlr, 0x7C, 0x0007FFFF); /* magic */
|
|
|
+ else
|
|
|
+ csr32w(ctlr, 0x7C, 0x0007FF00); /* magic */
|
|
|
+ pciclrmwi(ctlr->pcidev);
|
|
|
+ break;
|
|
|
+ case Macv13:
|
|
|
+ /*
|
|
|
+ * This is interpreted from clearly bogus code
|
|
|
+ * in the manufacturer-supplied driver, it could
|
|
|
+ * be wrong. Untested.
|
|
|
+ */
|
|
|
+ pcicfgw8(ctlr->pcidev, 0x68, 0x00); /* magic */
|
|
|
+ pcicfgw8(ctlr->pcidev, 0x69, 0x08); /* magic */
|
|
|
+ break;
|
|
|
+ case Macv04:
|
|
|
+ case Macv11:
|
|
|
+ case Macv12:
|
|
|
+ case Macv14:
|
|
|
+ case Macv15:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Enable receiver/transmitter.
|
|
|
+ * Need to do this first or some of the settings below
|
|
|
+ * won't take.
|
|
|
+ */
|
|
|
+ switch(ctlr->pciv){
|
|
|
+ default:
|
|
|
+ csr8w(ctlr, Cr, Te|Re);
|
|
|
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
|
|
|
+ csr32w(ctlr, Rcr, ctlr->rcr);
|
|
|
+ case Rtl8169sc:
|
|
|
+ case Rtl8168b:
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* Interrupts.
|
|
|
* Disable Tdu|Tok for now, the transmit routine will tidy.
|
|
|
- * Tdu means the NIC ran out of descritors to send, so it
|
|
|
+ * Tdu means the NIC ran out of descriptors to send, so it
|
|
|
* doesn't really need to ever be on.
|
|
|
*/
|
|
|
csr32w(ctlr, Timerint, 0);
|
|
|
- csr16w(ctlr, Imr, Serr|Timeout/*|Tdu*/|Fovw|Punlc|Rdu|Ter/*|Tok*/|Rer|Rok);
|
|
|
+ csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok);
|
|
|
|
|
|
/*
|
|
|
* Clear missed-packet counter;
|
|
@@ -513,20 +594,40 @@ rtl8169init(Ether* edev)
|
|
|
csr32w(ctlr, Rdsar+4, 0);
|
|
|
csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
|
|
|
csr16w(ctlr, Rms, Mps);
|
|
|
- csr16w(ctlr, Mulint, 0);
|
|
|
+ r = csr16r(ctlr, Mulint) & 0xF000;
|
|
|
+ csr16w(ctlr, Mulint, r);
|
|
|
+ csr16w(ctlr, Cplusc, cplusc);
|
|
|
|
|
|
/*
|
|
|
* Set configuration.
|
|
|
*/
|
|
|
- csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
|
|
|
- csr32w(ctlr, Rcr, ctlr->rcr);
|
|
|
- csr16w(ctlr, 0xE2, 0); /* magic */
|
|
|
+ switch(ctlr->pciv){
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ case Rtl8169sc:
|
|
|
+ csr16w(ctlr, 0xE2, 0); /* magic */
|
|
|
+ csr8w(ctlr, Cr, Te|Re);
|
|
|
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
|
|
|
+ csr32w(ctlr, Rcr, ctlr->rcr);
|
|
|
+ break;
|
|
|
+ case Rtl8168b:
|
|
|
+ csr16w(ctlr, 0xE2, 0); /* magic */
|
|
|
+ csr16w(ctlr, Cplusc, 0x2000); /* magic */
|
|
|
+ csr8w(ctlr, Cr, Te|Re);
|
|
|
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
|
|
|
+ csr32w(ctlr, Rcr, ctlr->rcr);
|
|
|
+ csr16w(ctlr, Rms, 0x0800);
|
|
|
+ csr8w(ctlr, Mtps, 0x3F);
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
csr8w(ctlr, Cr9346, 0);
|
|
|
|
|
|
iunlock(&ctlr->ilock);
|
|
|
|
|
|
- //rtl8169mii(ctlr);
|
|
|
+// rtl8169mii(ctlr);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -663,7 +764,7 @@ rtl8169receive(Ether* edev)
|
|
|
else{
|
|
|
/*
|
|
|
* Error stuff here.
|
|
|
- print("control %8.8uX\n", control);
|
|
|
+ print("control %#8.8ux\n", control);
|
|
|
*/
|
|
|
}
|
|
|
d->control &= Eor;
|
|
@@ -686,7 +787,7 @@ rtl8169interrupt(Ureg*, void* arg)
|
|
|
edev = arg;
|
|
|
ctlr = edev->ctlr;
|
|
|
|
|
|
- while((isr = csr16r(ctlr, Isr)) != 0){
|
|
|
+ while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
|
|
|
csr16w(ctlr, Isr, isr);
|
|
|
if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
|
|
|
rtl8169receive(edev);
|
|
@@ -709,7 +810,7 @@ rtl8169interrupt(Ureg*, void* arg)
|
|
|
}
|
|
|
|
|
|
if(isr & Punlc){
|
|
|
- //rtl8169link(edev);
|
|
|
+// rtl8169link(edev);
|
|
|
isr &= ~Punlc;
|
|
|
}
|
|
|
|
|
@@ -717,104 +818,103 @@ rtl8169interrupt(Ureg*, void* arg)
|
|
|
* Some of the reserved bits get set sometimes...
|
|
|
*/
|
|
|
if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok))
|
|
|
- panic("rtl8169interrupt: imr %4.4uX isr %4.4uX\n",
|
|
|
+ panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n",
|
|
|
csr16r(ctlr, Imr), isr);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static Ctlr*
|
|
|
-rtl8169match(Ether* edev, int id)
|
|
|
+static void
|
|
|
+rtl8169pci(void)
|
|
|
{
|
|
|
Pcidev *p;
|
|
|
Ctlr *ctlr;
|
|
|
- int port;
|
|
|
+ int i, port;
|
|
|
+ u32int bar;
|
|
|
|
|
|
- /*
|
|
|
- * Any adapter matches if no edev->port is supplied,
|
|
|
- * otherwise the ports must match.
|
|
|
- */
|
|
|
- for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
|
|
|
- if(ctlr->active)
|
|
|
+ p = nil;
|
|
|
+ while(p = pcimatch(p, 0, 0)){
|
|
|
+ if(p->ccrb != 0x02 || p->ccru != 0)
|
|
|
continue;
|
|
|
- p = ctlr->pcidev;
|
|
|
- if(((p->did<<16)|p->vid) != id)
|
|
|
- continue;
|
|
|
- port = p->mem[0].bar & ~0x01;
|
|
|
- if(edev->port != 0 && edev->port != port)
|
|
|
+
|
|
|
+ switch(i = ((p->did<<16)|p->vid)){
|
|
|
+ default:
|
|
|
continue;
|
|
|
+ case Rtl8100e: /* RTL810[01]E ? */
|
|
|
+ case Rtl8169sc: /* RTL8169SC */
|
|
|
+ case Rtl8168b: /* RTL8168B */
|
|
|
+ case Rtl8169: /* RTL8169 */
|
|
|
+ break;
|
|
|
+ case (0xC107<<16)|0x1259: /* Corega CG-LAPCIGT */
|
|
|
+ i = Rtl8169;
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
+ bar = p->mem[0].bar;
|
|
|
+ port = bar & ~0x01;
|
|
|
+ if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
|
|
|
+ print("rtl8169: port %#ux in use\n", port);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ctlr = malloc(sizeof(Ctlr));
|
|
|
ctlr->port = port;
|
|
|
- if(rtl8169reset(ctlr))
|
|
|
+ ctlr->pcidev = p;
|
|
|
+ ctlr->pciv = i;
|
|
|
+
|
|
|
+ if(pcigetpms(p) > 0){
|
|
|
+ pcisetpms(p, 0);
|
|
|
+
|
|
|
+ for(i = 0; i < 6; i++)
|
|
|
+ pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
|
|
|
+ pcicfgw8(p, PciINTL, p->intl);
|
|
|
+ pcicfgw8(p, PciLTR, p->ltr);
|
|
|
+ pcicfgw8(p, PciCLS, p->cls);
|
|
|
+ pcicfgw16(p, PciPCR, p->pcr);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(rtl8169reset(ctlr)){
|
|
|
+ iofree(port);
|
|
|
+ free(ctlr);
|
|
|
continue;
|
|
|
+ }
|
|
|
|
|
|
- csr8w(ctlr, 0x82, 1); /* magic */
|
|
|
+ /*
|
|
|
+ * Extract the chip hardware version,
|
|
|
+ * needed to configure each properly.
|
|
|
+ */
|
|
|
+ ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK;
|
|
|
|
|
|
rtl8169mii(ctlr);
|
|
|
|
|
|
pcisetbme(p);
|
|
|
- ctlr->active = 1;
|
|
|
- return ctlr;
|
|
|
+
|
|
|
+ if(rtl8169ctlrhead != nil)
|
|
|
+ rtl8169ctlrtail->next = ctlr;
|
|
|
+ else
|
|
|
+ rtl8169ctlrhead = ctlr;
|
|
|
+ rtl8169ctlrtail = ctlr;
|
|
|
}
|
|
|
- return nil;
|
|
|
}
|
|
|
|
|
|
-static struct {
|
|
|
- char* name;
|
|
|
- int id;
|
|
|
-} rtl8169pci[] = {
|
|
|
- { "rtl8169", (0x8169<<16)|0x10EC, }, /* generic */
|
|
|
- { "CG-LAPCIGT", (0xC107<<16)|0x1259, }, /* Corega CG-LAPCIGT */
|
|
|
- { nil },
|
|
|
-};
|
|
|
-
|
|
|
int
|
|
|
rtl8169pnp(Ether* edev)
|
|
|
{
|
|
|
- Pcidev *p;
|
|
|
+ u32int r;
|
|
|
Ctlr *ctlr;
|
|
|
- int i, id;
|
|
|
- uchar ea[Eaddrlen];
|
|
|
|
|
|
- /*
|
|
|
- * Make a list of all ethernet controllers
|
|
|
- * if not already done.
|
|
|
- */
|
|
|
- if(ctlrhead == nil){
|
|
|
- p = nil;
|
|
|
- while(p = pcimatch(p, 0, 0)){
|
|
|
- if(p->ccrb != 0x02 || p->ccru != 0)
|
|
|
- continue;
|
|
|
- ctlr = malloc(sizeof(Ctlr));
|
|
|
- ctlr->pcidev = p;
|
|
|
- ctlr->id = (p->did<<16)|p->vid;
|
|
|
-
|
|
|
- if(ctlrhead != nil)
|
|
|
- ctlrtail->next = ctlr;
|
|
|
- else
|
|
|
- ctlrhead = ctlr;
|
|
|
- ctlrtail = ctlr;
|
|
|
- }
|
|
|
- }
|
|
|
+ if(rtl8169ctlrhead == nil)
|
|
|
+ rtl8169pci();
|
|
|
|
|
|
/*
|
|
|
- * Is it an RTL8169 under a different name?
|
|
|
- * Normally a search is made through all the found controllers
|
|
|
- * for one which matches any of the known vid+did pairs.
|
|
|
- * If a vid+did pair is specified a search is made for that
|
|
|
- * specific controller only.
|
|
|
+ * Any adapter matches if no edev->port is supplied,
|
|
|
+ * otherwise the ports must match.
|
|
|
*/
|
|
|
- id = 0;
|
|
|
- for(i = 0; i < edev->nopt; i++){
|
|
|
- if(cistrncmp(edev->opt[i], "id=", 3) == 0)
|
|
|
- id = strtol(&edev->opt[i][3], nil, 0);
|
|
|
- }
|
|
|
-
|
|
|
- ctlr = nil;
|
|
|
- if(id != 0)
|
|
|
- ctlr = rtl8169match(edev, id);
|
|
|
- else for(i = 0; rtl8169pci[i].name; i++){
|
|
|
- if((ctlr = rtl8169match(edev, rtl8169pci[i].id)) != nil)
|
|
|
+ for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){
|
|
|
+ if(ctlr->active)
|
|
|
+ continue;
|
|
|
+ if(edev->port == 0 || edev->port == ctlr->port){
|
|
|
+ ctlr->active = 1;
|
|
|
break;
|
|
|
+ }
|
|
|
}
|
|
|
if(ctlr == nil)
|
|
|
return -1;
|
|
@@ -823,23 +923,33 @@ rtl8169pnp(Ether* edev)
|
|
|
edev->port = ctlr->port;
|
|
|
edev->irq = ctlr->pcidev->intl;
|
|
|
edev->tbdf = ctlr->pcidev->tbdf;
|
|
|
+// edev->mbps = 100;
|
|
|
|
|
|
/*
|
|
|
+ * Pull the MAC address out of the chip.
|
|
|
*/
|
|
|
- memset(ea, 0, Eaddrlen);
|
|
|
- i = csr32r(ctlr, Idr0);
|
|
|
- edev->ea[0] = i;
|
|
|
- edev->ea[1] = i>>8;
|
|
|
- edev->ea[2] = i>>16;
|
|
|
- edev->ea[3] = i>>24;
|
|
|
- i = csr32r(ctlr, Idr0+4);
|
|
|
- edev->ea[4] = i;
|
|
|
- edev->ea[5] = i>>8;
|
|
|
+ r = csr32r(ctlr, Idr0);
|
|
|
+ edev->ea[0] = r;
|
|
|
+ edev->ea[1] = r>>8;
|
|
|
+ edev->ea[2] = r>>16;
|
|
|
+ edev->ea[3] = r>>24;
|
|
|
+ r = csr32r(ctlr, Idr0+4);
|
|
|
+ edev->ea[4] = r;
|
|
|
+ edev->ea[5] = r>>8;
|
|
|
|
|
|
+ /*
|
|
|
+ * Linkage to the generic ethernet driver.
|
|
|
+ */
|
|
|
edev->attach = rtl8169attach;
|
|
|
edev->transmit = rtl8169transmit;
|
|
|
edev->interrupt = rtl8169interrupt;
|
|
|
edev->detach = rtl8169detach;
|
|
|
+// edev->ifstat = rtl8169ifstat;
|
|
|
+// edev->ctl = nil;
|
|
|
+//
|
|
|
+// edev->arg = edev;
|
|
|
+// edev->promiscuous = rtl8169promiscuous;
|
|
|
+// edev->multicast = rtl8169multicast;
|
|
|
|
|
|
return 0;
|
|
|
}
|