📄 etherfcc.c
字号:
else fccthisto[xmtd]++; if(xmtd) fccrthisto[rcvd]++; else fccrhisto[rcvd]++;#endif}static longifstat(Ether* ether, void* a, long n, ulong offset){ char *p; int len, i, r; Ctlr *ctlr; MiiPhy *phy; if(n == 0) return 0; ctlr = ether->ctlr; p = malloc(2*READSTR); len = snprint(p, 2*READSTR, "interrupts: %lud\n", ctlr->interrupts); len += snprint(p+len, 2*READSTR-len, "carrierlost: %lud\n", ctlr->carrierlost); len += snprint(p+len, 2*READSTR-len, "heartbeat: %lud\n", ctlr->heartbeat); len += snprint(p+len, 2*READSTR-len, "retrylimit: %lud\n", ctlr->retrylim); len += snprint(p+len, 2*READSTR-len, "retrycount: %lud\n", ctlr->retrycount); len += snprint(p+len, 2*READSTR-len, "latecollisions: %lud\n", ctlr->latecoll); len += snprint(p+len, 2*READSTR-len, "rxoverruns: %lud\n", ctlr->overrun); len += snprint(p+len, 2*READSTR-len, "txunderruns: %lud\n", ctlr->underrun); len += snprint(p+len, 2*READSTR-len, "framesdeferred: %lud\n", ctlr->deferred); miistatus(ctlr->mii); phy = ctlr->mii->curphy; len += snprint(p+len, 2*READSTR-len, "phy: link=%d, tfc=%d, rfc=%d, speed=%d, fd=%d\n", phy->link, phy->tfc, phy->rfc, phy->speed, phy->fd);#ifdef DBG if(ctlr->mii != nil && ctlr->mii->curphy != nil){ len += snprint(p+len, 2*READSTR, "phy: "); for(i = 0; i < NMiiPhyr; i++){ if(i && ((i & 0x07) == 0)) len += snprint(p+len, 2*READSTR-len, "\n "); r = miimir(ctlr->mii, i); len += snprint(p+len, 2*READSTR-len, " %4.4uX", r); } snprint(p+len, 2*READSTR-len, "\n"); }#endif snprint(p+len, 2*READSTR-len, "\n"); n = readstr(offset, a, n, p); free(p); return n;}/* * This follows the MPC8260 user guide: section28.9's initialisation sequence. */static intfccsetup(Ctlr *ctlr, FCC *fcc, uchar *ea){ int i; Etherparam *p; MiiPhy *phy; /* Turn Ethernet off */ fcc->gfmr &= ~(ENR | ENT); ioplock(); switch(ctlr->port) { default: iopunlock(); return -1; case 0: /* Step 1 (Section 28.9), write the parallel ports */ ctlr->pmdio = 0x01000000; ctlr->pmdck = 0x08000000; imm->port[0].pdir &= ~A1dir0; imm->port[0].pdir |= A1dir1; imm->port[0].psor &= ~A1psor0; imm->port[0].psor |= A1psor1; imm->port[0].ppar |= (A1dir0 | A1dir1); /* Step 2, Port C clocks */ imm->port[2].psor &= ~0x00000c00; imm->port[2].pdir &= ~0x00000c00; imm->port[2].ppar |= 0x00000c00; imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck); imm->port[3].podr |= ctlr->pmdio; imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck); imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck); eieio(); /* Step 3, Serial Interface clock routing */ imm->cmxfcr &= ~0xff000000; /* Clock mask */ imm->cmxfcr |= 0x37000000; /* Clock route */ break; case 1: /* Step 1 (Section 28.9), write the parallel ports */ ctlr->pmdio = 0x00400000; ctlr->pmdck = 0x00200000; imm->port[1].pdir &= ~B2dir0; imm->port[1].pdir |= B2dir1; imm->port[1].psor &= ~B2psor0; imm->port[1].psor |= B2psor1; imm->port[1].ppar |= (B2dir0 | B2dir1); /* Step 2, Port C clocks */ imm->port[2].psor &= ~0x00003000; imm->port[2].pdir &= ~0x00003000; imm->port[2].ppar |= 0x00003000; imm->port[2].pdat |= (ctlr->pmdio | ctlr->pmdck); imm->port[2].podr |= ctlr->pmdio; imm->port[2].pdir |= (ctlr->pmdio | ctlr->pmdck); imm->port[2].ppar &= ~(ctlr->pmdio | ctlr->pmdck); eieio(); /* Step 3, Serial Interface clock routing */ imm->cmxfcr &= ~0x00ff0000; imm->cmxfcr |= 0x00250000; break; case 2: /* Step 1 (Section 28.9), write the parallel ports */ imm->port[1].pdir &= ~B3dir0; imm->port[1].pdir |= B3dir1; imm->port[1].psor &= ~B3psor0; imm->port[1].psor |= B3psor1; imm->port[1].ppar |= (B3dir0 | B3dir1); /* Step 2, Port C clocks */ imm->port[2].psor &= ~0x0000c000; imm->port[2].pdir &= ~0x0000c000; imm->port[2].ppar |= 0x0000c000; imm->port[3].pdat |= (ctlr->pmdio | ctlr->pmdck); imm->port[3].podr |= ctlr->pmdio; imm->port[3].pdir |= (ctlr->pmdio | ctlr->pmdck); imm->port[3].ppar &= ~(ctlr->pmdio | ctlr->pmdck); eieio(); /* Step 3, Serial Interface clock routing */ imm->cmxfcr &= ~0x0000ff00; imm->cmxfcr |= 0x00003700; break; } iopunlock(); p = (Etherparam*)(m->immr->prmfcc + ctlr->port); memset(p, 0, sizeof(Etherparam)); /* Step 4 */ fcc->gfmr |= ENET; /* Step 5 */ fcc->fpsmr = CRCE | FDE | LPB; /* full duplex operation */ ctlr->duplex = ~0; /* Step 6 */ fcc->fdsr = 0xd555; /* Step 7, initialize parameter ram */ p->rbase = PADDR(ctlr->rdr); p->tbase = PADDR(ctlr->tdr); p->rstate = (GBL | EB) << 24; p->tstate = (GBL | EB) << 24; p->cmask = 0xdebb20e3; p->cpres = 0xffffffff; p->retlim = 15; /* retry limit */ p->mrblr = (Rbsize+0x1f)&~0x1f; /* multiple of 32 */ p->mflr = Rbsize; p->minflr = ETHERMINTU; p->maxd1 = (Rbsize+7) & ~7; p->maxd2 = (Rbsize+7) & ~7; for(i=0; i<Eaddrlen; i+=2) p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* Step 7, initialize parameter ram, configuration-dependent values */ p->riptr = m->immr->fccextra[ctlr->port].ri - (uchar*)IMMR; p->tiptr = m->immr->fccextra[ctlr->port].ti - (uchar*)IMMR; p->padptr = m->immr->fccextra[ctlr->port].pad - (uchar*)IMMR; memset(m->immr->fccextra[ctlr->port].pad, 0x88, 0x20); /* Step 8, clear out events */ fcc->fcce = ~0; /* Step 9, Interrupt enable */ fcc->fccm = TXE | RXF | TXB; /* Step 10, Configure interrupt priority (not done here) */ /* Step 11, Clear out current events */ /* Step 12, Enable interrupts to the CP interrupt controller */ /* Step 13, Issue the Init Tx and Rx command, specifying 0xc for ethernet*/ cpmop(InitRxTx, fccid[ctlr->port], 0xc); /* Step 14, Link management */ if((ctlr->mii = malloc(sizeof(Mii))) == nil) return -1; ctlr->mii->mir = fccmiimir; ctlr->mii->miw = fccmiimiw; ctlr->mii->ctlr = ctlr; if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ free(ctlr->mii); ctlr->mii = nil; return -1; } miiane(ctlr->mii, ~0, ~0, ~0);#ifdef DBG print("oui=%X, phyno=%d, ", phy->oui, phy->phyno); print("anar=%ux, ", phy->anar); print("fc=%ux, ", phy->fc); print("mscr=%ux, ", phy->mscr); print("link=%ux, ", phy->link); print("speed=%ux, ", phy->speed); print("fd=%ux, ", phy->fd); print("rfc=%ux, ", phy->rfc); print("tfc=%ux\n", phy->tfc);#endif /* Step 15, Enable ethernet: done at attach time */ return 0;}static intreset(Ether* ether){ uchar ea[Eaddrlen]; Ctlr *ctlr; FCC *fcc; Block *b; int i; if(m->cpuhz < 24000000){ print("%s ether: system speed must be >= 24MHz for ether use\n", ether->type); return -1; } if(ether->port > 3){ print("%s ether: no FCC port %ld\n", ether->type, ether->port); return -1; } ether->irq = fccirq[ether->port]; ether->tbdf = BusPPC; fcc = imm->fcc + ether->port; ctlr = malloc(sizeof(*ctlr)); ether->ctlr = ctlr; memset(ctlr, 0, sizeof(*ctlr)); ctlr->fcc = fcc; ctlr->port = ether->port; ctlr->fccid = fccid[ether->port]; /* Ioringinit will allocate the buffer descriptors in normal memory * and NOT in Dual-Ported Ram, as prescribed by the MPC8260 * PowerQUICC II manual (Section 28.6). When they are allocated * in DPram and the Dcache is enabled, the processor will hang */ if(ioringinit(ctlr, Nrdre, Ntdre, 0) < 0) panic("etherfcc init"); for(i = 0; i < Nrdre; i++){ b = iallocb(Bufsize); b->rp = (uchar*)(((ulong)b->rp + CACHELINESZ-1) & ~(CACHELINESZ-1)); b->wp = b->rp; ctlr->rcvbufs[i] = b; ctlr->rdr[i].addr = PADDR(b->wp); } fccsetup(ctlr, fcc, ether->ea); ether->mbps = 100; /* TO DO: could be 10mbps */ ether->attach = attach; ether->transmit = transmit; ether->interrupt = interrupt; ether->ifstat = ifstat; ether->arg = ether; ether->promiscuous = promiscuous; ether->multicast = multicast; /* * Until we know where to find it, insist that the plan9.ini * entry holds the Ethernet address. */ memset(ea, 0, Eaddrlen); if(memcmp(ea, ether->ea, Eaddrlen) == 0){ print("no ether address"); return -1; } return 0;}voidetherfcclink(void){ addethercard("fcc", reset);}static voidnanodelay(void){ static int count; int i; for(i = 0; i < 500; i++) count++; return;}staticvoid miiwriteloop(Ctlr *ctlr, Port *port, int cnt, ulong cmd){ int i; for(i = 0; i < cnt; i++){ port->pdat &= ~ctlr->pmdck; if(cmd & BIT(i)) port->pdat |= ctlr->pmdio; else port->pdat &= ~ctlr->pmdio; nanodelay(); port->pdat |= ctlr->pmdck; nanodelay(); }}static intfccmiimiw(Mii *mii, int pa, int ra, int data){ int x; Port *port; ulong cmd; Ctlr *ctlr; /* * MII Management Interface Write. */ ctlr = mii->ctlr; port = imm->port + 3; cmd = MDIwrite | (pa<<(5+2+16))| (ra<<(2+16)) | (data & 0xffff); x = splhi(); port->pdir |= (ctlr->pmdio|ctlr->pmdck); nanodelay(); miiwriteloop(ctlr, port, 32, ~0); miiwriteloop(ctlr, port, 32, cmd); port->pdir |= (ctlr->pmdio|ctlr->pmdck); nanodelay(); miiwriteloop(ctlr, port, 32, ~0); splx(x); return 1;}static intfccmiimir(Mii *mii, int pa, int ra){ int data, i, x; Port *port; ulong cmd; Ctlr *ctlr; ctlr = mii->ctlr; port = imm->port + 3; cmd = MDIread | pa<<(5+2+16) | ra<<(2+16); x = splhi(); port->pdir |= (ctlr->pmdio|ctlr->pmdck); nanodelay(); miiwriteloop(ctlr, port, 32, ~0); /* Clock out the first 14 MS bits of the command */ miiwriteloop(ctlr, port, 14, cmd); /* Turn-around */ port->pdat &= ~ctlr->pmdck; port->pdir &= ~ctlr->pmdio; nanodelay(); /* For read, clock in 18 bits, use 16 */ data = 0; for(i=0; i<18; i++){ data <<= 1; if(port->pdat & ctlr->pmdio) data |= 1; port->pdat |= ctlr->pmdck; nanodelay(); port->pdat &= ~ctlr->pmdck; nanodelay(); } port->pdir |= (ctlr->pmdio|ctlr->pmdck); nanodelay(); miiwriteloop(ctlr, port, 32, ~0); splx(x); return data & 0xffff;}static voidfccltimer(Ureg*, Timer *t){ Ether *ether; Ctlr *ctlr; MiiPhy *phy; ulong gfmr; ether = t->ta; ctlr = ether->ctlr; if(ctlr->mii == nil || ctlr->mii->curphy == nil) return; phy = ctlr->mii->curphy; if(miistatus(ctlr->mii) < 0){ print("miistatus failed\n"); return; } if(phy->link == 0){ print("link lost\n"); return; } ether->mbps = phy->speed; if(phy->fd != ctlr->duplex) print("set duplex\n"); ilock(ctlr); gfmr = ctlr->fcc->gfmr; if(phy->fd != ctlr->duplex){ ctlr->fcc->gfmr &= ~(ENR|ENT); if(phy->fd) ctlr->fcc->fpsmr |= FDE | LPB; /* full duplex operation */ else ctlr->fcc->fpsmr &= ~(FDE | LPB); /* half duplex operation */ ctlr->duplex = phy->fd; } ctlr->fcc->gfmr = gfmr; iunlock(ctlr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -