#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
-
-#include "etherif.h"
-#include "ethermii.h"
+#include "../port/etherif.h"
+#include "../port/ethermii.h"
enum { /* registers */
Idr0 = 0x00, /* MAC address */
Tbianar = 0x68, /* TBI Auto-Negotiation Advertisment */
Tbilpar = 0x6A, /* TBI Auto-Negotiation Link Partner */
Phystatus = 0x6C, /* PHY Status */
+ Pmch = 0x6F, /* power management */
+ Ldps = 0x82, /* link down power saving */
Rms = 0xDA, /* Receive Packet Maximum Size */
Cplusc = 0xE0, /* C+ Command */
Macv15 = 0x38800000, /* RTL8100E */
// Macv19 = 0x3c000000, /* dup Macv12a: RTL8111c-gr */
Macv25 = 0x28000000, /* RTL8168D */
+ Macv26 = 0x48000000, /* RTL8111/8168B */
+ Macv27 = 0x2c800000, /* RTL8111e */
+ Macv28 = 0x2c000000, /* RTL8111/8168B */
+ Macv29 = 0x40800000, /* RTL8101/8102E */
+ Macv30 = 0x24000000, /* RTL8101E? (untested) */
+ Macv39 = 0x44800000, /* RTL8106E */
+ Macv40 = 0x4c000000, /* RTL8168G */
+ Macv42 = 0x50800000, /* RTL8168GU */
+ Macv44 = 0x5c800000, /* RTL8411B */
+ Macv45 = 0x54000000, /* RTL8111HN */
+
Ifg0 = 0x01000000, /* Interframe Gap 0 */
Ifg1 = 0x02000000, /* Interframe Gap 1 */
};
};
enum { /* Cplusc */
+ Txenb = 0x0001, /* enable C+ transmit mode */
+ Rxenb = 0x0002, /* enable C+ receive mode */
Mulrw = 0x0008, /* PCI Multiple R/W Enable */
Dac = 0x0010, /* PCI Dual Address Cycle Enable */
Rxchksum = 0x0020, /* Receive Checksum Offload Enable */
Rxvlan = 0x0040, /* Receive VLAN De-tagging Enable */
+ Macstatdis = 0x0080, /* Disable Mac Statistics */
Endian = 0x0200, /* Endian Mode */
};
Mtu = ETHERMAXTU,
Mps = ROUNDUP(ETHERMAXTU+4, 128),
-// Mps = Mtu + 8 + 14, /* if(mtu>ETHERMAXTU) */
};
typedef struct Dtcc Dtcc;
typedef struct Ctlr Ctlr;
typedef struct Ctlr {
+ Lock;
+
int port;
Pcidev* pcidev;
Ctlr* next;
int active;
QLock alock; /* attach */
- Lock ilock; /* init */
int init; /* */
+ Rendez reset;
int pciv; /* */
int macv; /* MAC version */
Mii* mii;
- Lock tlock; /* transmit */
D* td; /* descriptor ring */
Block** tb; /* transmit buffers */
int ntd;
int tdh; /* head - producer index (host) */
int tdt; /* tail - consumer index (NIC) */
- int ntdfree;
int ntq;
-// int rbsz; /* receive buffer size */
-
- Lock rlock; /* receive */
D* rd; /* descriptor ring */
Block** rb; /* receive buffers */
int nrd;
int rdh; /* head - producer index (NIC) */
int rdt; /* tail - consumer index (host) */
- int nrdfree;
+ int nrq;
int tcr; /* transmit configuration register */
int rcr; /* receive configuration register */
uint udpf;
uint ipf;
uint fovf;
- uint ierrs;
uint rer;
uint rdu;
uint punlc;
+ uint serr;
uint fovw;
uint mcast;
uint frag; /* partial packets; rb was too small */
ctlr->mii->miw = rtl8169miimiw;
ctlr->mii->ctlr = ctlr;
+ /*
+ * PHY wakeup
+ */
+ switch(ctlr->macv){
+ case Macv25:
+ case Macv28:
+ case Macv29:
+ case Macv30:
+ csr8w(ctlr, Pmch, csr8r(ctlr, Pmch) | 0x80);
+ break;
+ }
+ rtl8169miimiw(ctlr->mii, 1, 0x1f, 0);
+ rtl8169miimiw(ctlr->mii, 1, 0x0e, 0);
+
/*
* 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 */
+ csr8w(ctlr, Ldps, 1); /* magic */
rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
}
ctlr->mii = nil;
return -1;
}
- print("oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
+ print("rtl8169: oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
+ miireset(ctlr->mii);
+
+ microdelay(100);
+
miiane(ctlr->mii, ~0, ~0, ~0);
return 0;
edev = arg;
ctlr = edev->ctlr;
- ilock(&ctlr->ilock);
-
+ ilock(ctlr);
if(on)
ctlr->rcr |= Aap;
else
ctlr->rcr &= ~Aap;
csr32w(ctlr, Rcr, ctlr->rcr);
- iunlock(&ctlr->ilock);
+ iunlock(ctlr);
}
enum {
edev = ether;
ctlr = edev->ctlr;
- ilock(&ctlr->ilock);
+ ilock(ctlr);
ctlr->mchash |= 1ULL << (ethercrcbe(eaddr, Eaddrlen) >> 26);
csr32w(ctlr, Mar0+4, ctlr->mchash>>32);
}
- iunlock(&ctlr->ilock);
+ iunlock(ctlr);
}
static long
Dtcc *dtcc;
int i, l, r, timeo;
+ p = smalloc(READSTR);
+
ctlr = edev->ctlr;
qlock(&ctlr->slock);
- p = nil;
if(waserror()){
qunlock(&ctlr->slock);
free(p);
if(n == 0){
qunlock(&ctlr->slock);
poperror();
+ free(p);
return 0;
}
- if((p = malloc(READSTR)) == nil)
- error(Enomem);
-
l = snprint(p, READSTR, "TxOk: %llud\n", dtcc->txok);
l += snprint(p+l, READSTR-l, "RxOk: %llud\n", dtcc->rxok);
l += snprint(p+l, READSTR-l, "TxEr: %llud\n", dtcc->txer);
l += snprint(p+l, READSTR-l, "TxAbt: %ud\n", dtcc->txabt);
l += snprint(p+l, READSTR-l, "TxUndrn: %ud\n", dtcc->txundrn);
+ l += snprint(p+l, READSTR-l, "serr: %ud\n", ctlr->serr);
+ l += snprint(p+l, READSTR-l, "fovw: %ud\n", ctlr->fovw);
+
l += snprint(p+l, READSTR-l, "txdu: %ud\n", ctlr->txdu);
l += snprint(p+l, READSTR-l, "tcpf: %ud\n", ctlr->tcpf);
l += snprint(p+l, READSTR-l, "udpf: %ud\n", ctlr->udpf);
l += snprint(p+l, READSTR-l, "ipf: %ud\n", ctlr->ipf);
l += snprint(p+l, READSTR-l, "fovf: %ud\n", ctlr->fovf);
- l += snprint(p+l, READSTR-l, "ierrs: %ud\n", ctlr->ierrs);
l += snprint(p+l, READSTR-l, "rer: %ud\n", ctlr->rer);
l += snprint(p+l, READSTR-l, "rdu: %ud\n", ctlr->rdu);
l += snprint(p+l, READSTR-l, "punlc: %ud\n", ctlr->punlc);
- l += snprint(p+l, READSTR-l, "fovw: %ud\n", ctlr->fovw);
l += snprint(p+l, READSTR-l, "tcr: %#8.8ux\n", ctlr->tcr);
l += snprint(p+l, READSTR-l, "rcr: %#8.8ux\n", ctlr->rcr);
l += snprint(p+l, READSTR-l, "multicast: %ud\n", ctlr->mcast);
if(ctlr->mii != nil && ctlr->mii->curphy != nil){
- l += snprint(p+l, READSTR, "phy: ");
+ l += snprint(p+l, READSTR-l, "phy: ");
for(i = 0; i < NMiiPhyr; i++){
if(i && ((i & 0x07) == 0))
l += snprint(p+l, READSTR-l, "\n ");
rtl8169replenish(Ctlr* ctlr)
{
D *d;
- int rdt;
+ int x;
Block *bp;
- rdt = ctlr->rdt;
- while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){
- d = &ctlr->rd[rdt];
- if(ctlr->rb[rdt] == nil){
- /*
- * Simple allocation for now.
- * This better be aligned on 8.
- */
- bp = iallocb(Mps);
- if(bp == nil){
- iprint("no available buffers\n");
- break;
- }
- ctlr->rb[rdt] = bp;
- d->addrlo = PCIWADDR(bp->rp);
- d->addrhi = 0;
- coherence();
- }else
- iprint("i8169: rx overrun\n");
- d->control |= Own|Mps;
- rdt = NEXT(rdt, ctlr->nrd);
- ctlr->nrdfree++;
+ x = ctlr->rdt;
+ while(NEXT(x, ctlr->nrd) != ctlr->rdh){
+ bp = iallocb(Mps);
+ if(bp == nil){
+ iprint("rtl8169: no available buffers\n");
+ break;
+ }
+ ctlr->rb[x] = bp;
+ ctlr->nrq++;
+ d = &ctlr->rd[x];
+ d->addrlo = PCIWADDR(bp->rp);
+ d->addrhi = 0;
+ coherence();
+ d->control = (d->control & Eor) | Own | BALLOC(bp);
+ x = NEXT(x, ctlr->nrd);
+ ctlr->rdt = x;
}
- ctlr->rdt = rdt;
}
static int
u32int r;
Block *bp;
Ctlr *ctlr;
- u8int cplusc;
+ u16int cplusc;
ctlr = edev->ctlr;
- ilock(&ctlr->ilock);
+ ilock(ctlr);
- rtl8169halt(ctlr);
+ rtl8169reset(ctlr);
- /*
- * MAC Address is not settable on some (all?) chips.
- * Must put chip into config register write enable mode.
- */
- csr8w(ctlr, Cr9346, Eem1|Eem0);
-
- /*
- * Transmitter.
- */
memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
- ctlr->tdh = ctlr->tdt = 0;
+ ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
ctlr->td[ctlr->ntd-1].control = Eor;
+ for(i = 0; i < ctlr->ntd; i++)
+ if(bp = ctlr->tb[i]){
+ ctlr->tb[i] = nil;
+ freeb(bp);
+ }
- /*
- * Receiver.
- * Need to do something here about the multicast filter.
- */
memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd);
- ctlr->nrdfree = ctlr->rdh = ctlr->rdt = 0;
+ ctlr->rdh = ctlr->rdt = ctlr->nrq = 0;
ctlr->rd[ctlr->nrd-1].control = Eor;
-
for(i = 0; i < ctlr->nrd; i++)
- if((bp = ctlr->rb[i]) != nil){
+ if(bp = ctlr->rb[i]){
ctlr->rb[i] = nil;
freeb(bp);
}
+
rtl8169replenish(ctlr);
- ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm;
- /*
- * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst
- * settings in Tcr/Rcr; the (1<<14) is magic.
- */
- cplusc = csr16r(ctlr, Cplusc) & ~(1<<14);
- cplusc |= /*Rxchksum|*/Mulrw;
+ cplusc = csr16r(ctlr, Cplusc);
+ cplusc &= ~(Endian|Rxchksum);
+ cplusc |= Txenb|Mulrw;
switch(ctlr->macv){
- default:
- panic("ether8169: unknown macv %#08ux for vid %#ux did %#ux",
- ctlr->macv, ctlr->pcidev->vid, ctlr->pcidev->did);
- case Macv01:
- 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 Macv07:
- case Macv07a:
- case Macv11:
- case Macv12:
- case Macv12a:
- case Macv14:
- case Macv15:
- case Macv25:
+ case Macv40:
+ case Macv44:
+ cplusc |= Macstatdis;
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);
- csr32w(ctlr, Mar0, 0);
- csr32w(ctlr, Mar0+4, 0);
- ctlr->mchash = 0;
- case Rtl8169sc:
- case Rtl8168b:
+ cplusc |= Rxenb;
break;
}
+ csr16w(ctlr, Cplusc, cplusc);
- /*
- * Interrupts.
- * Disable Tdu|Tok for now, the transmit routine will tidy.
- * Tdu means the NIC ran out of descriptors to send, so it
- * doesn't really need to ever be on.
- */
- csr32w(ctlr, Timerint, 0);
- ctlr->imr = Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok;
- csr16w(ctlr, Imr, ctlr->imr);
-
- /*
- * Clear missed-packet counter;
- * clear early transmit threshold value;
- * set the descriptor ring base addresses;
- * set the maximum receive packet size;
- * no early-receive interrupts.
- *
- * note: the maximum rx size is a filter. the size of the buffer
- * in the descriptor ring is still honored. we will toss >Mtu
- * packets because they've been fragmented into multiple
- * rx buffers.
- */
- csr32w(ctlr, Mpc, 0);
- csr8w(ctlr, Etx, 0x3f); /* magic */
csr32w(ctlr, Tnpds+4, 0);
csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td));
csr32w(ctlr, Rdsar+4, 0);
csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
- csr16w(ctlr, Rms, 16383); /* was Mps; see above comment */
- r = csr16r(ctlr, Mulint) & 0xF000; /* no early rx interrupts */
- csr16w(ctlr, Mulint, r);
- csr16w(ctlr, Cplusc, cplusc);
- csr16w(ctlr, Coal, 0);
- /*
- * Set configuration.
- */
- switch(ctlr->pciv){
- case Rtl8169sc:
- csr8w(ctlr, Cr, Te|Re);
- csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
- csr32w(ctlr, Rcr, ctlr->rcr);
+ csr8w(ctlr, Cr, Te|Re);
+
+ csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
+ ctlr->tcr = csr32r(ctlr, Tcr);
+ switch(ctlr->macv){
+ case Macv42:
+ case Macv45:
+ ctlr->rcr = Rxfth256|Mrxdmaunlimited|Ab|Am|Apm;
break;
- case Rtl8168b:
- case Rtl8169c:
- csr16w(ctlr, Cplusc, 0x2000); /* magic */
- csr8w(ctlr, Cr, Te|Re);
- csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
- csr32w(ctlr, Rcr, ctlr->rcr);
+ default:
+ ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm;
break;
}
- ctlr->tcr = csr32r(ctlr, Tcr);
- csr8w(ctlr, Cr9346, 0);
+ ctlr->mchash = 0;
+ csr32w(ctlr, Mar0, 0);
+ csr32w(ctlr, Mar0+4, 0);
+ csr32w(ctlr, Rcr, ctlr->rcr);
+
+ /* maximum packet sizes, unlimited */
+ csr8w(ctlr, Etx, 0x3f);
+ csr16w(ctlr, Rms, 0x3fff);
+
+ csr16w(ctlr, Coal, 0);
+
+ /* no early rx interrupts */
+ r = csr16r(ctlr, Mulint) & 0xF000;
+ csr16w(ctlr, Mulint, r);
+
+ ctlr->imr = Serr|Fovw|Punlc|Rdu|Ter|Rer|Rok|Tdu;
+ csr16w(ctlr, Imr, ctlr->imr);
- iunlock(&ctlr->ilock);
+ csr32w(ctlr, Mpc, 0);
-// rtl8169mii(ctlr);
+ iunlock(ctlr);
return 0;
}
+static void
+rtl8169reseter(void *arg)
+{
+ Ether *edev;
+ Ctlr *ctlr;
+
+ edev = arg;
+
+ for(;;){
+ rtl8169init(edev);
+
+ ctlr = edev->ctlr;
+ qunlock(&ctlr->alock);
+
+ while(waserror())
+ ;
+ sleep(&ctlr->reset, return0, nil);
+ poperror();
+
+ qlock(&ctlr->alock);
+ }
+}
+
static void
rtl8169attach(Ether* edev)
{
ctlr = edev->ctlr;
qlock(&ctlr->alock);
- if(ctlr->init == 0){
- /*
- * Handle allocation/init errors here.
- */
- ctlr->td = mallocalign(sizeof(D)*Ntd, 256, 0, 0);
- ctlr->tb = malloc(Ntd*sizeof(Block*));
+ if(!ctlr->init){
ctlr->ntd = Ntd;
- ctlr->rd = mallocalign(sizeof(D)*Nrd, 256, 0, 0);
- ctlr->rb = malloc(Nrd*sizeof(Block*));
ctlr->nrd = Nrd;
+ ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
+ ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
+ ctlr->td = mallocalign(sizeof(D)*ctlr->ntd, 256, 0, 0);
+ ctlr->rd = mallocalign(sizeof(D)*ctlr->nrd, 256, 0, 0);
ctlr->dtcc = mallocalign(sizeof(Dtcc), 64, 0, 0);
- rtl8169init(edev);
+ if(ctlr->rb == nil || ctlr->rb == nil ||
+ ctlr->rd == nil || ctlr->rd == nil || ctlr->dtcc == nil){
+ free(ctlr->tb);
+ ctlr->tb = nil;
+ free(ctlr->rb);
+ ctlr->rb = nil;
+ free(ctlr->td);
+ ctlr->td = nil;
+ free(ctlr->rd);
+ ctlr->rd = nil;
+ free(ctlr->dtcc);
+ ctlr->dtcc = nil;
+ qunlock(&ctlr->alock);
+ error(Enomem);
+ }
ctlr->init = 1;
+ kproc("rtl8169", rtl8169reseter, edev);
+
+ /* rtl8169reseter() does qunlock(&ctlr->alock) when complete */
+ qlock(&ctlr->alock);
}
qunlock(&ctlr->alock);
ctlr = edev->ctlr;
+ r = csr8r(ctlr, Phystatus);
/*
* Maybe the link changed - do we care very much?
* Could stall transmits if no link, maybe?
*/
- if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){
- edev->link = 0;
- return;
- }
- edev->link = 1;
+ edev->link = (r & Linksts) != 0;
limit = 256*1024;
if(r & Speed10){
D *d;
Block *bp;
Ctlr *ctlr;
- int control, x;
+ int x;
ctlr = edev->ctlr;
- ilock(&ctlr->tlock);
+ if(!canlock(ctlr))
+ return;
for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
d = &ctlr->td[x];
- if((control = d->control) & Own)
+ if(d->control & Own)
break;
- /*
- * Check errors and log here.
- */
- USED(control);
-
/*
* Free it up.
* Need to clean the descriptor here? Not really.
*/
freeb(ctlr->tb[x]);
ctlr->tb[x] = nil;
- d->control &= Eor;
-
ctlr->ntq--;
}
ctlr->tdh = x;
d = &ctlr->td[x];
d->addrlo = PCIWADDR(bp->rp);
d->addrhi = 0;
- ctlr->tb[x] = bp;
coherence();
- d->control |= Own | Fs | Ls | BLEN(bp);
+ d->control = (d->control & Eor) | Own | Fs | Ls | BLEN(bp);
- x = NEXT(x, ctlr->ntd);
+ ctlr->tb[x] = bp;
ctlr->ntq++;
+
+ x = NEXT(x, ctlr->ntd);
}
- if(x != ctlr->tdt){
+ if(x != ctlr->tdt)
ctlr->tdt = x;
- csr8w(ctlr, Tppoll, Npq);
- }
else if(ctlr->ntq >= (ctlr->ntd-1))
ctlr->txdu++;
- iunlock(&ctlr->tlock);
+ if(ctlr->ntq > 0){
+ coherence();
+ csr8w(ctlr, Tppoll, Npq);
+ }
+ unlock(ctlr);
}
static void
rtl8169receive(Ether* edev)
{
D *d;
- int rdh;
Block *bp;
Ctlr *ctlr;
u32int control;
+ int x;
ctlr = edev->ctlr;
+ if(ctlr->nrq < ctlr->nrd/2)
+ rtl8169replenish(ctlr);
- rdh = ctlr->rdh;
- for(;;){
- d = &ctlr->rd[rdh];
-
- if(d->control & Own)
+ for(x = ctlr->rdh; x != ctlr->rdt;){
+ d = &ctlr->rd[x];
+ if((control = d->control) & Own)
break;
- control = d->control;
+ bp = ctlr->rb[x];
+ ctlr->rb[x] = nil;
+ ctlr->nrq--;
+
+ x = NEXT(x, ctlr->nrd);
+ ctlr->rdh = x;
+
+ if(ctlr->nrq < ctlr->nrd/2)
+ rtl8169replenish(ctlr);
+
if((control & (Fs|Ls|Res)) == (Fs|Ls)){
- bp = ctlr->rb[rdh];
bp->wp = bp->rp + (control & RxflMASK) - 4;
if(control & Fovf)
bp->flag |= Bipck;
break;
}
- etheriq(edev, bp, 1);
+ etheriq(edev, bp);
}else{
if(!(control & Res))
ctlr->frag++;
- /* iprint("i8169: control %#.8ux\n", control); */
- freeb(ctlr->rb[rdh]);
+ freeb(bp);
}
- ctlr->rb[rdh] = nil;
- d->control &= Eor;
- ctlr->nrdfree--;
- rdh = NEXT(rdh, ctlr->nrd);
-
- if(ctlr->nrdfree < ctlr->nrd/2)
- rtl8169replenish(ctlr);
}
- ctlr->rdh = rdh;
+}
+
+static void
+rtl8169restart(Ctlr *ctlr)
+{
+ ctlr->imr = 0;
+ rtl8169halt(ctlr);
+ wakeup(&ctlr->reset);
}
static void
csr16w(ctlr, Isr, isr);
if((isr & ctlr->imr) == 0)
break;
- if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
- rtl8169receive(edev);
- if(!(isr & (Punlc|Rok)))
- ctlr->ierrs++;
- if(isr & Rer)
- ctlr->rer++;
- if(isr & Rdu)
- ctlr->rdu++;
- if(isr & Punlc)
- ctlr->punlc++;
- if(isr & Fovw)
- ctlr->fovw++;
- isr &= ~(Fovw|Rdu|Rer|Rok);
+
+ if(isr & Serr)
+ ctlr->serr++;
+ if(isr & Fovw)
+ ctlr->fovw++;
+ if(isr & Rer)
+ ctlr->rer++;
+ if(isr & Rdu)
+ ctlr->rdu++;
+ if(isr & Punlc)
+ ctlr->punlc++;
+
+ if(isr & (Serr|Fovw)){
+ rtl8169restart(ctlr);
+ break;
}
- if(isr & (Tdu|Ter|Tok)){
+ if(isr & (Punlc|Rdu|Rer|Rok))
+ rtl8169receive(edev);
+
+ if(isr & (Tdu|Ter|Tok))
rtl8169transmit(edev);
- isr &= ~(Tdu|Ter|Tok);
- }
- if(isr & Punlc){
+ if(isr & Punlc)
rtl8169link(edev);
- isr &= ~Punlc;
- }
-
- /*
- * 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",
- csr16r(ctlr, Imr), isr);
}
}
case Macv14:
case Macv15:
case Macv25:
+ case Macv26:
+ case Macv27:
+ case Macv28:
+ case Macv29:
+ case Macv30:
+ case Macv39:
+ case Macv40:
+ case Macv42:
+ case Macv44:
+ case Macv45:
break;
}
return 0;
continue;
}
ctlr = malloc(sizeof(Ctlr));
+ if(ctlr == nil){
+ print("rtl8169: can't allocate memory\n");
+ iofree(port);
+ continue;
+ }
ctlr->port = port;
ctlr->pcidev = p;
ctlr->pciv = i;
ctlr->pcie = pcie;
+ pcienable(p);
if(vetmacv(ctlr, &macv) == -1){
+ pcidisable(p);
iofree(port);
free(ctlr);
print("rtl8169: unknown mac %.4ux %.8ux\n", p->did, macv);
continue;
}
- 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)){
+ pcidisable(p);
iofree(port);
free(ctlr);
+ print("rtl8169: reset failed\n");
continue;
}
edev->attach = rtl8169attach;
edev->transmit = rtl8169transmit;
- edev->interrupt = rtl8169interrupt;
edev->ifstat = rtl8169ifstat;
edev->arg = edev;
edev->promiscuous = rtl8169promiscuous;
edev->multicast = rtl8169multicast;
-// edev->shutdown = rtl8169shutdown;
rtl8169link(edev);
+ intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
+
return 0;
}