📄 if_esmc.c
字号:
pData = ((unsigned char *) eh) + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER check_trailer (eh, pData, &len, &off, &sc->es_if); /* copy data from the ring buffer to mbuf a long-word at a time */ m = bcopy_to_mbufs (pData, len, off, (struct ifnet *)&sc->es_if, 2); if (m == NULL) { sc->es_if.if_ierrors++; /* bump error statistic */ continue; } do_protocol_with_type (eh->ether_type, m, &sc->es_ac, len);#else /* copy data from the ring buffer to mbuf */ m = bcopy_to_mbufs (pData, len, off, (struct ifnet *)&sc->es_if, 2); if (m == NULL) { sc->es_if.if_ierrors++; /* bump error statistic */ continue; } do_protocol (eh, m, &sc->es_ac, len);#endif if (len & 0x01) /* buffer length */ bufLen = len + 1; else bufLen = len + 2; sc->pOut = sc->packetAddr[sc->indexOut] + bufLen; sc->packetLen[sc->indexOut] = 0; /* mark it empty */ sc->indexOut = (sc->indexOut + 1) % sc->nIndex; /* increment */ } sc->flags &= ~ESMC_RXING; }/********************************************************************************* esmcPut - copy a packet to the interface.** Copy from mbuf chain to transmitter buffer in shared memory.** RETURNS: N/A*/#ifdef BSD43_DRIVERLOCAL void esmcPut ( int unit ) { FAST ESMC_SOFTC *sc = &esmc_softc [unit];#elseLOCAL void esmcPut ( ESMC_SOFTC *sc ) {#endif FAST int ioaddr = sc->ioAddr; FAST struct mbuf *m; int timeout = ESMC_ALLOC_TIMEOUT; int len; int pages; u_char mask; u_char packetNo; int s = splnet (); if (sc->es_if.if_snd.ifq_head != NULL) { IF_DEQUEUE (&sc->es_if.if_snd, m); copy_from_mbufs (sc->pBuft, m, len); len = max (ETHERSMALL, len); /* call output hook if any */ if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&sc->es_if, sc->pBuft, len)) { goto donePut; }#ifndef BSD43_DRIVER sc->es_if.if_opackets++; /* bump statistic. */#endif /* allocate transmit memory and transmit */ pages = len / 256; ESMC_SWITCH_BANK (2); mask = sysInByte (ioaddr + ESMC_INT_MASK); /* save mask */ sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_ALLOC | pages); /* alloc mem */ while (((sysInByte (ioaddr + ESMC_INT_STAT) & ESMC_INT_ALLOC) == 0) && (--timeout)) ; if (timeout == 0) /* take sem & wait */ { sysOutByte (ioaddr + ESMC_INT_MASK, mask | ESMC_INT_ALLOC); if (semTake (&sc->esmcSyncSem, sysClkRateGet () >> 2) == ERROR) { sc->allocTimeout++; goto donePut; } } if ((packetNo = sysInByte (ioaddr + ESMC_ARR)) & 0x80) /* check it */ { sc->allocFailed++; goto donePut; }#ifdef ESMC_DEBUG { int ix; int iy; printf ("pages=0x%x, packetNo=0x%x, len=%d\n", pages, packetNo, len); for (iy = 0; iy < 8; iy++) { for (ix = 0; ix < 16; ix++) printf ("%2.2x ", (u_char)sc->pBuft[iy * 16 + ix]); printf ("\n"); } }#endif /* ESMC_DEBUG */ sysOutByte (ioaddr + ESMC_INT_MASK, 0); /* lock INT */ sysOutByte (ioaddr + ESMC_PNR, packetNo); /* set the tx packet */ sysOutWord (ioaddr + ESMC_PTR, ESMC_PTR_AUTOINC); /* set the pointer */#if ESMC_USE_LONG sysOutLong (ioaddr + ESMC_DATA_1, (len + 6) << 16); /* status, count */ sysOutLongString (ioaddr + ESMC_DATA_1, (long *)sc->pBuft, len >> 2); if (len & 0x02) sysOutWord (ioaddr + ESMC_DATA_1, *(short *)&sc->pBuft[len & ~0x03]);#else sysOutWord (ioaddr + ESMC_DATA_1, 0); /* status */ sysOutWord (ioaddr + ESMC_DATA_1, (len + 6)); /* byte count */ sysOutWordString (ioaddr + ESMC_DATA_1, (short *)sc->pBuft, len >> 1);#endif /* ESMC_USE_LONG */ if (len & 0x01) /* odd byte count */ { sysOutByte (ioaddr + ESMC_DATA_1, sc->pBuft[len - 1]); sysOutByte (ioaddr + ESMC_DATA_1, 0x20); } else /* even byte count */ sysOutWord (ioaddr + ESMC_DATA_1, 0); sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_ENQUEUE); /* send it */ sysOutByte (ioaddr + ESMC_INT_MASK, mask | ESMC_INT_TX | ESMC_INT_TX_EMPTY); }donePut: splx (s); }/********************************************************************************* esmcChipInit - initialize SMC91c9x chip** RETURNS: N/A*/LOCAL STATUS esmcChipInit ( int unit ) { FAST ESMC_SOFTC *sc = &esmc_softc[unit]; FAST int ioaddr = sc->ioAddr; int memSize; int ix; u_short bank; u_short config; u_short addr; u_short memInfo; u_short memConfig; char revision; char * pRevision; sysOutWord (ioaddr + ESMC_BANK_SELECT, 0x00); bank = sysInWord (ioaddr + ESMC_BANK_SELECT); if ((bank & 0xff00) != 0x3300) {#ifdef ESMC_DEBUG printf ("esmc: error - bank select 0x%x\n", bank & 0xff00);#endif return (ERROR); } ESMC_SWITCH_BANK (1); addr = sysInWord (ioaddr + ESMC_BASE); if (ioaddr != ((addr >> 3) & 0x3e0)) {#ifdef ESMC_DEBUG printf ("esmc: error - ioaddr=0x%x\n", (addr >> 3) & 0x3e0);#endif return (ERROR); } ESMC_SWITCH_BANK (3); revision = sysInByte (ioaddr + ESMC_REVISION); if ((pRevision = pName[(revision >> 4) & 0x0f]) == NULL) {#ifdef ESMC_DEBUG printf ("esmc: error - revision=0x%x\n", (revision >> 4) & 0x0f);#endif return (ERROR); } ESMC_SWITCH_BANK (0); memInfo = sysInWord (ioaddr + ESMC_MIR); memConfig = sysInWord (ioaddr + ESMC_MCR); memSize = (memConfig >> 9) & 0x07; memSize *= (memInfo & 0xff) * 256; esmcChipReset (unit); /* reset the chip */ ESMC_SWITCH_BANK (1); config = sysInWord (ioaddr + ESMC_CONFIG); if (sc->config == ATTACHMENT_DEFAULT) /* EEPROM */ { if (config & ESMC_CFG_AUI_SELECT) /* EEPROM - AUI */ sc->config = ATTACHMENT_AUI; else /* EEPROM - RJ45 */ { sc->config = ATTACHMENT_RJ45; sysOutByte (ioaddr + ESMC_CONFIG, config); } } else if (sc->config == ATTACHMENT_AUI) /* AUI */ sysOutByte (ioaddr + ESMC_CONFIG, config | ESMC_CFG_AUI_SELECT); else if (sc->config == ATTACHMENT_RJ45) /* RJ45 */ sysOutByte (ioaddr + ESMC_CONFIG, config & ~ESMC_CFG_AUI_SELECT); for (ix = 0; ix < 6; ix++) /* ethernet addres */ sc->es_enaddr[ix] = sysInByte (ioaddr + ESMC_ADDR_0 + ix); ESMC_SWITCH_BANK (0); sysOutWord (ioaddr + ESMC_MCR, 0x0006); /* 1532 bytes */ sysOutWord (ioaddr + ESMC_TCR, ESMC_TCR_PAD | ESMC_TCR_TXEN); /* TXenable */ sysOutWord (ioaddr + ESMC_RCR, ESMC_RCR_RXEN); /* RX enable */ ESMC_SWITCH_BANK (2); /* int enable */ sysOutByte (ioaddr + ESMC_INT_MASK, ESMC_INT_RX_OVRN | ESMC_INT_RCV); #if ESMC_DEBUG printf ("ESMC: %s(rev=%d) at %#3x IRQ=%d IF=%s MEM=%d ", pRevision, revision & 0x0f, ioaddr, sc->intLevel, (sc->config == 1)? "TP" : "AUI", memSize); printf ("("); for (ix = 0; ix < 5; ix++) printf ("%2.2x:", (u_char)sc->es_enaddr[ix]); printf ("%2.2x)\n", (u_char)sc->es_enaddr[ix]);#endif /* ESMC_DEBUG */ return (OK); }/********************************************************************************* esmcChipReset - reset SMC91c9x chip** RETURNS: N/A*/LOCAL void esmcChipReset ( int unit ) { FAST ESMC_SOFTC *sc = &esmc_softc[unit]; FAST int ioaddr = sc->ioAddr; ESMC_SWITCH_BANK (2); sysOutByte (ioaddr + ESMC_INT_MASK, 0); /* lock INT */ ESMC_SWITCH_BANK (0); sysOutWord (ioaddr + ESMC_RCR, ESMC_RCR_EPH_RST); /* software reset */ taskDelay (sysClkRateGet () >> 3); sysOutWord (ioaddr + ESMC_RCR, 0x0000); /* RX disable */ sysOutWord (ioaddr + ESMC_TCR, 0x0000); /* TX disable */ ESMC_SWITCH_BANK (1); sysOutWord (ioaddr + ESMC_CONTROL, /* TX auto release */ sysInWord (ioaddr + ESMC_CONTROL) | ESMC_CTL_AUTO_RELEASE); ESMC_SWITCH_BANK (2); sysOutWord (ioaddr + ESMC_MMU, ESMC_MMU_RESET); /* MMU reset */ taskDelay (sysClkRateGet () >> 3); }#if ESMC_SHOW/********************************************************************************* esmcShow - display statistics for the `esmc' network interface** This routine displays statistics about the `esmc' Ethernet network interface.* It has two parameters:* .iP <unit>* interface unit; should be 0.* .iP <zap>* if 1, all collected statistics are cleared to zero.* .LP** RETURNS: N/A*/void esmcShow ( int unit, /* interface unit */ BOOL zap /* zero totals */ ) { FAST ESMC_SOFTC *sc = &esmc_softc[unit]; FAST int ioaddr = sc->ioAddr; FAST u_int * pUint = &sc->interrupt; FAST int ix; u_short bank; u_char mask; static char *pMessage [] = { "interrupt", "interrupt rcv", "interrupt tx", "interrupt txempty", "interrupt alloc", "interrupt overrun", "interrupt eph", "interrupt ercv", "lost carr", "alloc timeout", "alloc failed", }; printf ("esmc: ioAddr=0x%x intLevel=0x%x\n", sc->ioAddr, sc->intLevel); for (ix = 0; ix < NELEMENTS(pMessage); ix++) { printf (" %-30.30s %4d\n", pMessage[ix], pUint[ix]); if (zap) pUint[ix] = 0; } printf (" %-30.30s 0x%2x\n", "flags", sc->flags); bank = sysInWord (ioaddr + ESMC_BANK_SELECT); ESMC_SWITCH_BANK (2); mask = sysInByte (ioaddr + ESMC_INT_MASK); sysOutByte (ioaddr + ESMC_INT_MASK, 0); /* lock INT */ ESMC_SWITCH_BANK (0); printf ("bank0-TCR: 0x%x\n", sysInWord (ioaddr + ESMC_TCR)); printf ("bank0-EPH: 0x%x\n", sysInWord (ioaddr + ESMC_EPH)); printf ("bank0-RCR: 0x%x\n", sysInWord (ioaddr + ESMC_RCR)); printf ("bank0-COUNTER: 0x%x\n", sysInWord (ioaddr + ESMC_COUNTER)); printf ("bank0-MIR: 0x%x\n", sysInWord (ioaddr + ESMC_MIR)); printf ("bank0-MCR: 0x%x\n", sysInWord (ioaddr + ESMC_MCR)); ESMC_SWITCH_BANK (1); printf ("bank1-CONFIG: 0x%x\n", sysInWord (ioaddr + ESMC_CONFIG)); printf ("bank1-CONTROL: 0x%x\n", sysInWord (ioaddr + ESMC_CONTROL)); ESMC_SWITCH_BANK (2); printf ("bank2-MMU: 0x%x\n", sysInWord (ioaddr + ESMC_MMU)); printf ("bank2-PNR: 0x%x\n", sysInByte (ioaddr + ESMC_PNR)); printf ("bank2-ARR: 0x%x\n", sysInByte (ioaddr + ESMC_ARR)); printf ("bank2-FIFO: 0x%x\n", sysInWord (ioaddr + ESMC_FIFO)); printf ("bank2-PTR: 0x%x\n", sysInWord (ioaddr + ESMC_PTR)); printf ("bank2-INT_STAT: 0x%x\n", sysInByte (ioaddr + ESMC_INT_STAT)); printf ("bank2-INT_MASK: 0x%x\n", mask); ESMC_SWITCH_BANK (3); printf ("bank3-MGMT: 0x%x\n", sysInWord (ioaddr + ESMC_MGMT)); printf ("bank3-REVISION: 0x%x\n", sysInWord (ioaddr + ESMC_REVISION)); printf ("bank3-ERCV: 0x%x\n", sysInWord (ioaddr + ESMC_ERCV)); ESMC_SWITCH_BANK (bank); sysOutByte (ioaddr + ESMC_INT_MASK, mask); /* unlock INT */ }#endif /* ESMC_SHOW */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -