📄 etherdp83820.c
字号:
if(csr32r(ctlr, Mear) & Mdio) data |= (1<<i); csr32w(ctlr, Mear, Mdc|r); csr32w(ctlr, Mear, r); } csr32w(ctlr, Mear, mear); return data;}static 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 intdp83820miimir(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); data = mdior(ctlr, 18); if(data & 0x10000) return -1; return data & 0xFFFF;}static intdp83820miimiw(Mii* mii, int pa, int ra, int data){ Ctlr *ctlr; ctlr = mii->ctlr; /* * MII Management Interface Write. * * Preamble; * ST+OP+PA+RA+LT + 16 data bits; * Z. */ mdiow(ctlr, 0xFFFFFFFF, 32); data &= 0xFFFF; data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16); mdiow(ctlr, data, 32); return data & 0xFFFF; /* TODO: what's the caller expect here? */}/* * return free Block+buffer ready for input of up to MTU bytes. * desc->bp is also set to the return value. */static Block *dp83820rballoc(Desc* desc){ Block *bp; if(desc->bp == nil){ ilock(&dp83820rblock); if((bp = dp83820rbpool) == nil){ iunlock(&dp83820rblock); desc->bp = nil; desc->cmdsts = Own; iprint("dp83820rballoc: out of buffers\n"); return nil; } dp83820rbpool = bp->next; bp->next = nil; iunlock(&dp83820rblock); desc->bufptr = PCIWADDR(bp->rp); desc->bp = bp; } else{ bp = desc->bp; BLKRESET(bp); } coherence(); desc->cmdsts = Intr|Rbsz; return bp;}/* should be called via freeb() */static voiddp83820rbfree(Block *bp){ BLKRESET(bp); ilock(&dp83820rblock); bp->next = dp83820rbpool; dp83820rbpool = bp; iunlock(&dp83820rblock);}static voiddp83820halt(Ctlr* ctlr){ int i, timeo; ilock(&ctlr->ilock); csr32w(ctlr, Imr, 0); csr32w(ctlr, Ier, 0); csr32w(ctlr, Cr, Rxd|Txd); for(timeo = 0; timeo < 1000; timeo++){ if(!(csr32r(ctlr, Cr) & (Rxe|Txe))) break; microdelay(1); } csr32w(ctlr, Mibc, Frz); iunlock(&ctlr->ilock); if(ctlr->rd != nil){ for(i = 0; i < ctlr->nrd; i++){ if(ctlr->rd[i].bp == nil) continue; freeb(ctlr->rd[i].bp); ctlr->rd[i].bp = nil; } } if(ctlr->td != nil){ for(i = 0; i < ctlr->ntd; i++){ if(ctlr->td[i].bp == nil) continue; freeb(ctlr->td[i].bp); ctlr->td[i].bp = nil; } }}static voiddp83820cfg(Ctlr* ctlr){ int cfg; /* * Don't know how to deal with a TBI yet. */ if(ctlr->mii == nil) { iprint("83820: got tbi, not phy\n"); return; } /* * The polarity of these bits is at the mercy * of the board designer. * The correct answer for all speed and duplex questions * should be to query the phy. */ cfg = csr32r(ctlr, Cfg); if(!(cfg & Dupsts)){ ctlr->rxcfg |= Rxfd; ctlr->txcfg |= Csi|Hbi; iprint("83820: full duplex, "); } else{ ctlr->rxcfg &= ~Rxfd; ctlr->txcfg &= ~(Csi|Hbi); iprint("83820: half duplex, "); } csr32w(ctlr, Rxcfg, ctlr->rxcfg); csr32w(ctlr, Txcfg, ctlr->txcfg); switch(cfg & (Spdsts1000|Spdsts100)){ case Spdsts1000: /* 100Mbps */ default: /* 10Mbps */ ctlr->cfg &= ~Mode1000; if ((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000) iprint("100Mb/s\n"); else iprint("10Mb/s\n"); break; case Spdsts100: /* 1Gbps */ ctlr->cfg |= Mode1000; iprint("1Gb/s\n"); break; } csr32w(ctlr, Cfg, ctlr->cfg);}static voiddp83820init(Ether* edev){ int i; Ctlr *ctlr; Desc *desc; uchar *alloc; ctlr = edev->ctlr; dp83820halt(ctlr); /* * Receiver */ alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8); ctlr->rd = (Desc*)alloc; alloc += ctlr->nrd*sizeof(Desc); memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc)); ctlr->rdx = 0; for(i = 0; i < ctlr->nrd; i++){ desc = &ctlr->rd[i]; desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]); if(dp83820rballoc(desc) == nil) { print("dp83820init: out of buffers\n"); continue; } } csr32w(ctlr, Rxdphi, 0); csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd)); for(i = 0; i < Eaddrlen; i += 2){ csr32w(ctlr, Rfcr, i); csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]); } /* for now, accept all multicast packets */ csr32w(ctlr, Rfcr, Rfen|Aab|Apm|Aam); ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT); ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok; /* * Transmitter. */ ctlr->td = (Desc*)alloc; memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc)); ctlr->tdh = ctlr->tdt = ctlr->ntq = 0; for(i = 0; i < ctlr->ntd; i++){ desc = &ctlr->td[i]; desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]); } csr32w(ctlr, Txdphi, 0); csr32w(ctlr, Txdp, PCIWADDR(ctlr->td)); ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT); ctlr->imr |= Txurn|Txidle|Txdesc|Txok; ilock(&ctlr->ilock); dp83820cfg(ctlr); csr32w(ctlr, Mibc, Aclr); ctlr->imr |= Mib; csr32w(ctlr, Imr, ctlr->imr); /* try coalescing adjacent interrupts; use hold-off interval of 100µs */ csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT)); csr32w(ctlr, Ier, Ien); csr32w(ctlr, Cr, Rxe|Txe); iunlock(&ctlr->ilock);}/* multicast already on, don't need to do anything */static voidmulticast(void*, uchar*, int){}static voiddp83820attach(Ether* edev){ Block *bp; Ctlr *ctlr; ctlr = edev->ctlr; qlock(&ctlr->alock); if(ctlr->alloc != nil){ qunlock(&ctlr->alock); return; } if(waserror()){err: if(ctlr->mii != nil){ free(ctlr->mii); ctlr->mii = nil; } if(ctlr->alloc != nil){ free(ctlr->alloc); ctlr->alloc = nil; } qunlock(&ctlr->alock); nexterror(); } if(!(ctlr->cfg & Tbien)){ if((ctlr->mii = malloc(sizeof(Mii))) == nil) error(Enomem); ctlr->mii->ctlr = ctlr; ctlr->mii->mir = dp83820miimir; ctlr->mii->miw = dp83820miimiw; if(mii(ctlr->mii, ~0) == 0) error("no PHY"); ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien; ctlr->imr |= Phy; } /* allocate all Descs */ ctlr->nrd = Nrd; ctlr->nrb = Nrb; ctlr->ntd = Ntd; ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0); if(ctlr->alloc == nil) error(Enomem); /* * allocate receive Blocks+buffers, add all to receive Block+buffer pool */ for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ if((bp = iallocb(Rbsz)) == nil) { print( "dp83820attach: iallocb failed with %d rcv bufs allocated\n", ctlr->nrb); error(Enomem); }#ifdef FS bp->flags |= Mbrcvbuf;#endif bp->free = dp83820rbfree; /* to be called via freeb() */ dp83820rbfree(bp); } /* attaches a receive Block+buffer to each receive Desc */ dp83820init(edev); qunlock(&ctlr->alock); poperror();}static voiddp83820transmit(Ether* edev){ Block *bp; Ctlr *ctlr; Desc *desc; int cmdsts, r, x; ctlr = edev->ctlr; ilock(&ctlr->tlock); bp = nil; for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){ desc = &ctlr->td[x]; if((cmdsts = desc->cmdsts) & Own) break; if(!(cmdsts & Ok)){ if(cmdsts & Ec) ctlr->ec++; if(cmdsts & Owc) ctlr->owc++; if(cmdsts & Ed) ctlr->ed++; if(cmdsts & Crs) ctlr->crs++; if(cmdsts & Tfu) ctlr->tfu++; if(cmdsts & Txa) ctlr->txa++;#ifndef FS edev->oerrs++;#endif } desc->bp->next = bp; /* chain transmitted Blocks together */ bp = desc->bp; desc->bp = nil; /* unlink them from Descs */ ctlr->ntq--; } /* free Blocks+buffers comprising the packets just sent */ ctlr->tdh = x; if(bp != nil) freeblist(bp); x = ctlr->tdt; while(ctlr->ntq < (ctlr->ntd-1)){ bp = etheroq(edev); /* get head of transmit q */ if(bp == nil) break; desc = &ctlr->td[x]; desc->bufptr = PCIWADDR(bp->rp); desc->bp = bp; /* attach to Desc */ ctlr->ntq++; coherence(); desc->cmdsts = Own|Intr|BLEN(bp); /* fire! */ x = NEXT(x, ctlr->ntd); } if (ctlr->ntq >= ctlr->ntd-1) iprint("83820: xmit q full, Ntd=%d\n", Ntd); if(x != ctlr->tdt){ ctlr->tdt = x; r = csr32r(ctlr, Cr); csr32w(ctlr, Cr, Txe|r); } iunlock(&ctlr->tlock);}static voiddp83820interrupt(Ureg*, void* arg){ Block *bp; Ctlr *ctlr; Desc *desc; Ether *edev; int cmdsts, i, isr, r, x, rcvd = 0; edev = arg; ctlr = edev->ctlr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -