📄 ether83815.mii.c
字号:
static voidtransmit(Ether* ether){ Ctlr *ctlr; ctlr = ether->ctlr; ilock(&ctlr->tlock); txstart(ether); iunlock(&ctlr->tlock);}// TODO: finish this; set speed toostatic voidtxrxcfg(Ctlr *ctlr, int txdrth){ ulong rx, tx; rx = csr32r(ctlr, Rrxcfg); tx = csr32r(ctlr, Rtxcfg); if(ctlr->fd){ rx |= Atx; tx |= Csi | Hbi; }else{ rx &= ~Atx; tx &= ~(Csi | Hbi); } tx &= ~(Mxdma|Drth|Flth); tx |= Mxdma64 | Flth128 | txdrth; csr32w(ctlr, Rtxcfg, tx); rx &= ~(Mxdma|Rdrth); rx |= Mxdma64 | Rdrth64; csr32w(ctlr, Rrxcfg, rx);}static voidinterrupt(Ureg*, void* arg){ Ctlr *ctlr; Ether *ether; int len, status, cmdsts, iter = 0; Des *des; Block *bp; ether = arg; ctlr = ether->ctlr; while((status = csr32r(ctlr, Risr)) != 0){ if (iter++ >= 100) print("ns83815: interrupt: >= 100 iterations\n"); status &= ~(Pme|Mib); if(status & Hiberr){ if(status & Rxsovr) ctlr->rxsover++; if(status & Sserr) ctlr->sserr++; if(status & Dperr) ctlr->dperr++; if(status & Rmabt) ctlr->rmabt++; if(status & Rtabt) ctlr->rtabt++; status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt); } /* * Received packets. */ if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){ des = &ctlr->rdr[ctlr->rdrx]; while((cmdsts = des->cmdsts) & Own){ if((cmdsts&Ok) == 0){ if(cmdsts & Rxa) ctlr->rxa++; if(cmdsts & Rxo) ctlr->rxo++; if(cmdsts & Long) ctlr->rlong++; if(cmdsts & Runt) ctlr->runt++; if(cmdsts & Ise) ctlr->ise++; if(cmdsts & Crce) ctlr->crce++; if(cmdsts & Fae) ctlr->fae++; if(cmdsts & Lbp) ctlr->lbp++; if(cmdsts & Col) ctlr->col++; } else if(bp = iallocb(Rbsz)){ len = (cmdsts&Size)-4; if (len <= 0) { print( "ns83815: interrupt: packet len %d <= 0\n", len); freeb(des->bp); /* toss it */ } else { SETWPCNT(des->bp, len); ETHERIQ(ether, des->bp, 1); } /* replace just-queued/freed packet */ des->bp = bp; des->addr = PADDR(bp->rp);// debug(// "ns83815: interrupt: packet into input q, new des->addr %lux\n",// des->addr); coherence(); } else { print( "ns83815: interrupt: iallocb for input buffer failed\n"); /* * prevent accidents & ignore this * packet. it will be overwritten. */ des->bp->next = 0; } des->cmdsts = Rbsz; coherence(); ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr); des = &ctlr->rdr[ctlr->rdrx]; } status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn); } /* * Check the transmit side: * check for Transmit Underflow and Adjust * the threshold upwards; * free any transmitted buffers and try to * top-up the ring. */ if(status & Txurn){ ctlr->txurn++; ilock(&ctlr->lock); /* change threshold */ iunlock(&ctlr->lock); status &= ~(Txurn); } ilock(&ctlr->tlock); while(ctlr->ntq > 0){ des = &ctlr->tdr[ctlr->tdri]; cmdsts = des->cmdsts; if(cmdsts & Own) break; if((cmdsts & Ok) == 0){ if(cmdsts & Txa) ctlr->txa++; if(cmdsts & Tfu) ctlr->tfu++; if(cmdsts & Td) ctlr->td++; if(cmdsts & Ed) ctlr->ed++; if(cmdsts & Owc) ctlr->owc++; if(cmdsts & Ec) ctlr->ec++;#ifndef FS ether->oerrs++;#endif }// debug("ns83815: interrupt: done output for des->addr %lux\n",// des->addr); if (des->bp == nil) panic("83815 interrupt: nil des->bp"); freeb(des->bp); des->bp = nil; des->cmdsts = 0; ctlr->ntq--; ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr); } txstart(ether); iunlock(&ctlr->tlock); if((status & Phy) && ctlr->mii != nil){ ctlr->mii->mir(ctlr->mii, 1, Bmsr); print("phy: cfg %8.8lux bmsr %4.4ux\n", csr32r(ctlr, Rcfg), ctlr->mii->mir(ctlr->mii, 1, Bmsr)); /* TODO: set speed too; can't do it yet */ txrxcfg(ctlr, Drth512); /* set duplicity */ status &= ~Phy; } status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok); /* * Anything left not catered for? */ if(status) print("#l%d: status %8.8ux\n", ether->ctlrno, status); }}static voidctlrinit(Ether* ether){ Ctlr *ctlr; Des *des, *last; ctlr = ether->ctlr; /* * Allocate and initialise the receive ring; * allocate and initialise the transmit ring; * unmask interrupts and start the transmit side */ ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des)); if(ctlr->rdr == nil) { print("ns83815: ctlrinit: iallocb of rcv. descs. failed\n"); return; } last = nil; for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ des->bp = iallocb(Rbsz); if (des->bp == nil) { print("ns83815: ctlrinit: iallocb(%d) failed\n", Rbsz); return; } des->cmdsts = Rbsz; des->addr = PADDR(des->bp->rp); if(last != nil) last->next = PADDR(des); last = des; } ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr); ctlr->rdrx = 0; csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr)); ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0); last = nil; for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){ des->cmdsts = 0; des->bp = nil; des->addr = ~0; if(last != nil) last->next = PADDR(des); last = des; } ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr); ctlr->tdrh = 0; ctlr->tdri = 0; csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr)); txrxcfg(ctlr, Drth512);// TODO: finish this// MII csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr| Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */ csr32r(ctlr, Risr); /* clear status */ csr32w(ctlr, Rier, Ie); debug("ns83815: ctlrinit: set Ie, done\n");}/* * EEPROM */static voideeclk(Ctlr *ctlr, int clk){ csr32w(ctlr, Rmear, Eesel | clk); microdelay(2);}static voideeidle(Ctlr *ctlr){ int i; eeclk(ctlr, 0); eeclk(ctlr, Eeclk); for(i=0; i<25; i++){ eeclk(ctlr, 0); eeclk(ctlr, Eeclk); } eeclk(ctlr, 0); csr32w(ctlr, Rmear, 0); microdelay(2);}static inteegetw(Ctlr *ctlr, int a){ int d, i, w; eeidle(ctlr); eeclk(ctlr, 0); eeclk(ctlr, Eeclk); d = 0x180 | a; // read EEPROM at address `a' for(i=0x400; i; i>>=1){ if(d & i) csr32w(ctlr, Rmear, Eesel|Eedi); else csr32w(ctlr, Rmear, Eesel); eeclk(ctlr, Eeclk); eeclk(ctlr, 0); microdelay(2); } w = 0; for(i=0x8000; i; i >>= 1){ eeclk(ctlr, Eeclk); if(csr32r(ctlr, Rmear) & Eedo) w |= i; microdelay(2); eeclk(ctlr, 0); } eeidle(ctlr); return w;}static voidsoftreset(Ctlr* ctlr, int resetphys){ int i, w; /* * Soft-reset the controller */ csr32w(ctlr, Rcr, Rst); for(i=0;; i++){ if(i > 100) panic("ns83815: soft reset did not complete"); microdelay(250); if((csr32r(ctlr, Rcr) & Rst) == 0) break; delay(1); } csr32w(ctlr, Rccsr, Pmests); csr32w(ctlr, Rccsr, 0); csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);// MII// TODO: finish this if(resetphys){ /* * Soft-reset the PHY */ csr32w(ctlr, Rbmcr, Reset); for(i=0;; i++){ if(i > 100) panic("ns83815: PHY soft reset time out"); if((csr32r(ctlr, Rbmcr) & Reset) == 0) break; delay(1); } } /* * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration) */ csr16w(ctlr, 0xCC, 0x0001); /* PGSEL */ csr16w(ctlr, 0xE4, 0x189C); /* PMCCSR */ csr16w(ctlr, 0xFC, 0x0000); /* TSTDAT */ csr16w(ctlr, 0xF4, 0x5040); /* DSPCFG */ csr16w(ctlr, 0xF8, 0x008C); /* SDCFG */ /* * Auto negotiate */ w = csr16r(ctlr, Rbmsr); /* clear latched bits */ debug("anar: %4.4ux\n", csr16r(ctlr, Ranar)); csr16w(ctlr, Rbmcr, Anena); if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){ csr16w(ctlr, Rbmcr, Anena|Anrestart); /* TODO: this times out on the SiS900. why? */// TODO: finish this for(i=0;; i++){ if(i > 6000){ print("ns83815: speed auto neg. timed out\n"); break; } if((w = csr16r(ctlr, Rbmsr)) & Ancomp) break; delay(1); } debug("%d ms\n", i); w &= 0xFFFF; debug("bmsr: %4.4ux\n", w); USED(w); } debug("anar: %4.4ux\n", csr16r(ctlr, Ranar)); debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar)); debug("aner: %4.4ux\n", csr16r(ctlr, Raner)); debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts)); debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));}/* * MII/PHY */// TODO: finish thisstatic intmdior(Ctlr* ctlr, int n){ int data, i, mear, r;// mear = csr32r(ctlr, Mear);// r = ~(Mdc|Mddir) & mear; data = 0; for(i = n-1; i >= 0; i--){// if(csr32r(ctlr, Mear) & Mdio) data |= (1<<i);// csr32w(ctlr, Mear, Mdc|r);// csr32w(ctlr, Mear, r); }// csr32w(ctlr, Mear, mear); return data;}// TODO: finish thisstatic voidmdiow(Ctlr* ctlr, int bits, int n){ int i, mear, r;// mear = csr32r(ctlr, Mear);// r = Mddir|(~Mdc & mear); for(i = n-1; i >= 0; i--){// if(bits & (1<<i))// r |= Mdio;// else// r &= ~Mdio;// csr32w(ctlr, Mear, r);// csr32w(ctlr, Mear, Mdc|r); }// csr32w(ctlr, Mear, mear);}static intns83815miimir(Mii* mii, int pa, int ra){ int data; Ctlr *ctlr; ctlr = mii->ctlr; /* * MII Management Interface Read. * * Preamble; * ST+OP+PA+RA; * LT + 16 data bits. */ mdiow(ctlr, 0xFFFFFFFF, 32); mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -