📄 if_elc.c
字号:
do_protocol_with_type (eh->ether_type, m, &sc->es_ac, len);#else /* copy data from the ring buffer to mbuf a long-word at a time */ m = bcopy_to_mbufs (pData, len, 0, (struct ifnet *) &sc->es_if, 2); if (m == NULL) { sc->es_if.if_ierrors++; /* bump error statistic */ goto doneGet; } do_protocol (eh, m, &sc->es_ac, len);#endifdoneGet: sc->next = pH->next; sc->uppByteCnt = pH->uppByteCnt; } /* update BOUND Register */ if (sc->next <= SMC8013WC_PSTART) sysOutByte (ELC_BOUND (sc->elcAddr), SMC8013WC_PSTOP - 1); else sysOutByte (ELC_BOUND (sc->elcAddr), sc->next - 1); sc->flags &= ~RXING; /* go back if we received an interrupt and a new packet */ if (sc->next != sc->current) goto unlucky; }#ifdef BSD43_DRIVER/********************************************************************************* elcoutput - ethernet output routine** Encapsulate a packet of type family for the local net.* Use trailer local net encapsulation if enough data in first* packet leaves a multiple of 512 bytes of data in remainder.* If destination is this address or broadcast, send packet to* loop device to kludge around the fact that 3com interfaces can't* talk to themselves.** RETURNS: ?*/LOCAL int elcoutput ( struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst ) { return (ether_output (ifp, m0, dst, (FUNCPTR)elcPut, &elc_softc [ifp->if_unit].es_ac)); }#endif/********************************************************************************* elcPut - copy a packet to the interface.** Copy from mbuf chain to transmitter buffer in shared memory.**/#ifdef BSD43_DRIVERLOCAL void elcPut ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc [unit];#elseLOCAL void elcPut ( ELC_SOFTC *sc ) {#endif FAST struct mbuf *m; FAST int len; UINT transmitPage = sc->transmitPage[sc->transmitCnt & 1]; UCHAR *pBuf = (UCHAR *)(sc->memAddr + (transmitPage << 8));#ifdef BSD43_DRIVER int s = splnet (); if (sc->es_if.if_snd.ifq_head != NULL)#else while (sc->es_if.if_snd.ifq_head != NULL)#endif { semTake (&elcSyncSem, sysClkRateGet()); IF_DEQUEUE (&sc->es_if.if_snd, m); copy_from_mbufs (pBuf, m, len); len = max (ETHERSMALL, len); cacheDrvFlush (&cacheDmaFuncs, pBuf, len); /* call output hook if any */ if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&sc->es_if, pBuf, len))#ifdef BSD43_DRIVER goto donePut;#else continue;#endif /* kick Transmitter */ sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00); sysOutByte (ELC_TSTART (sc->elcAddr), transmitPage); sysOutByte (ELC_TCNTH (sc->elcAddr), len >> 8); sysOutByte (ELC_TCNTL (sc->elcAddr), len & 0xff); sysOutByte (ELC_CMD (sc->elcAddr), CMD_TXP); sc->transmitCnt++; sysOutByte (ELC_INTMASK (sc->elcAddr), IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE);#ifndef BSD43_DRIVER sc->es_if.if_opackets++;#endif }#ifdef BSD43_DRIVERdonePut: splx (s);#endif }/********************************************************************************* elcReset - reset the chip** Reset the chip.**/LOCAL void elcReset ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc [unit]; int s = splnet (); /* mask interrupt */ sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00); bicInit (unit); elcInit (unit); /* unmask interrupt */ sysOutByte (ELC_INTMASK (sc->elcAddr), IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE); sc->elcStat.reset++; splx (s); }/********************************************************************************* elcioctl - ioctl for interface** RETURNS: ?*/LOCAL int elcioctl ( FAST struct ifnet *ifp, int cmd, caddr_t data ) { int error = 0; int s; s = splimp(); switch (cmd) { case SIOCSIFADDR: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas (ifp, &IA_SIN (data)->sin_addr); break; case SIOCSIFFLAGS: /* Handled outside module - nothing more to do. */ break; default: error = EINVAL; } splx (s); return (error); }/********************************************************************************* bicInit - initialize SMC83c584 BIC (Bus Interface Controller)** RETURNS: N/A** NOMANUAL*/LOCAL void bicInit ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc[unit]; IRQ_TABLE *p = &irqTable[sc->intLevel]; char laar = (sc->memAddr & 0xf80000) >> 19; char msr = (sc->memAddr & 0x07e000) >> 13; char iar = (sc->bicAddr & 0xe000) >> 8 | (sc->bicAddr & 0x03e0) >> 5; char irr; char icr; char eeromIrr; /* get IRQ level bits */ if (p->ir2 == 0xff) p = &irqTable[3]; /* default is IRQ3 */ irr = p->ir01 << 5; icr = p->ir2 << 2; /* Reset and Recall */ sysOutByte (BIC_MSR (sc->bicAddr), MSR_RST); sysOutByte (BIC_MSR (sc->bicAddr), 0); taskDelay (sysClkRateGet () >> 2); sysOutByte (BIC_ICR (sc->bicAddr), ICR_RLA | ICR_RX7); while (sysInByte (BIC_ICR (sc->bicAddr)) & (ICR_RLA | ICR_RX7)) ; /* get values set by EEROM */ eeromIrr = sysInByte (BIC_IRR (sc->bicAddr)); /* Memory Select Reg: Enable, 0x??000. */ sysOutByte (BIC_MSR (sc->bicAddr), MSR_MEN | msr); /* Interface Config Reg: 16Kbytes, 16Bit. */ sysOutByte (BIC_ICR (sc->bicAddr), ICR_BIT16 | icr); /* IO Address Reg: 0x??0 */ sysOutByte (BIC_IAR (sc->bicAddr), iar); /* BIOS ROM Address Reg: Disable */ sysOutByte (BIC_BIO (sc->bicAddr), 0x00); /* Interrupt Request Reg: Enable, IRQ? */ if (sc->config == 1) sysOutByte (BIC_IRR (sc->bicAddr), IRR_IEN | irr | IRR_OUT1); else if (sc->config == 2) sysOutByte (BIC_IRR (sc->bicAddr), IRR_IEN | irr | IRR_OUT1 | IRR_OUT2); else sysOutByte (BIC_IRR (sc->bicAddr), IRR_IEN | irr | IRR_OUT1 | (eeromIrr & 0x0e)); /* LA Address Reg: 16Bit-memory, 16Bit-lan, 0x??000 */ sysOutByte (BIC_LAAR (sc->bicAddr), LAAR_M16EN | LAAR_L16EN | laar); }/********************************************************************************* elcInit - initialize SMC83c690 ELC (Ethernet LAN Controller)** RETURNS: N/A** NOMANUAL*/LOCAL void elcInit ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc[unit]; /* 1. program Command Register for page 0 */ sysOutByte (ELC_CMD (sc->elcAddr), CMD_CMD5 | CMD_STP); while ((sysInByte (ELC_INTSTAT (sc->elcAddr)) & ISTAT_RST) != ISTAT_RST) ; /* 2. initialize Data Configuration Register */ sysOutByte (ELC_DCON (sc->elcAddr), DCON_BSIZE1 | DCON_BUS16 | 0x08); /* 3. clear Remote Byte Count Register */ sysOutByte (ELC_RBCR0 (sc->elcAddr), 0x00); sysOutByte (ELC_RBCR1 (sc->elcAddr), 0x00); /* 4. initialize Receive Configuration Register */ sysOutByte (ELC_RCON (sc->elcAddr), 0x04); /* 5. place the ELC in LOOPBACK mode 1 or 2 */ sysOutByte (ELC_TCON (sc->elcAddr), TCON_LB1); /* 6. initialize Receive Buffer Ring */ sysOutByte (ELC_RSTART (sc->elcAddr), SMC8013WC_PSTART); sysOutByte (ELC_RSTOP (sc->elcAddr), SMC8013WC_PSTOP); sysOutByte (ELC_BOUND (sc->elcAddr), SMC8013WC_PSTART); /* 7. clear Interrupt Status Register */ sysOutByte (ELC_INTSTAT (sc->elcAddr), 0xff); /* 8. initialize Interrupt Mask Register */ sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00); /* 9. program Command Register for page 1 */ sysOutByte (ELC_CMD (sc->elcAddr), CMD_PS0 | CMD_STP); sysOutByte (ELC_STA0 (sc->elcAddr), sysInByte (BIC_LAR0 (sc->bicAddr))); sysOutByte (ELC_STA1 (sc->elcAddr), sysInByte (BIC_LAR1 (sc->bicAddr))); sysOutByte (ELC_STA2 (sc->elcAddr), sysInByte (BIC_LAR2 (sc->bicAddr))); sysOutByte (ELC_STA3 (sc->elcAddr), sysInByte (BIC_LAR3 (sc->bicAddr))); sysOutByte (ELC_STA4 (sc->elcAddr), sysInByte (BIC_LAR4 (sc->bicAddr))); sysOutByte (ELC_STA5 (sc->elcAddr), sysInByte (BIC_LAR5 (sc->bicAddr))); sysOutByte (ELC_MAR0 (sc->elcAddr), 0); sysOutByte (ELC_MAR1 (sc->elcAddr), 0); sysOutByte (ELC_MAR2 (sc->elcAddr), 0); sysOutByte (ELC_MAR3 (sc->elcAddr), 0); sysOutByte (ELC_MAR4 (sc->elcAddr), 0); sysOutByte (ELC_MAR5 (sc->elcAddr), 0); sysOutByte (ELC_MAR6 (sc->elcAddr), 0); sysOutByte (ELC_MAR7 (sc->elcAddr), 0); sc->next = SMC8013WC_PSTART + 1; sysOutByte (ELC_CURR (sc->elcAddr), sc->next); sysOutByte (ELC_CMD (sc->elcAddr), CMD_PS1 | CMD_STP); sysOutByte (ELC_ENH (sc->elcAddr), 0x00); /* 0 wait states */ sysOutByte (ELC_BLOCK (sc->elcAddr), 0x00); /* 0x00xxxx */ /* 10. put the ELC in START mode */ sysOutByte (ELC_CMD (sc->elcAddr), CMD_STA); /* 11. initialize Transmit Configuration Register */ sysOutByte (ELC_TCON (sc->elcAddr), 0x00); }/********************************************************************************* elcGetAddr - get hardwired ethernet address.** Read the ethernet address off the board, one byte at a time.**/LOCAL void elcGetAddr ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc[unit]; UCHAR *pAddr = (UCHAR *)sc->es_enaddr; *pAddr++ = sysInByte (BIC_LAR0 (sc->bicAddr)); *pAddr++ = sysInByte (BIC_LAR1 (sc->bicAddr)); *pAddr++ = sysInByte (BIC_LAR2 (sc->bicAddr)); *pAddr++ = sysInByte (BIC_LAR3 (sc->bicAddr)); *pAddr++ = sysInByte (BIC_LAR4 (sc->bicAddr)); *pAddr = sysInByte (BIC_LAR5 (sc->bicAddr)); }/********************************************************************************* elcGetCurr - get current page** RETURNS: current page that ELC is working on** NOMANUAL*/LOCAL UCHAR elcGetCurr ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc[unit]; UCHAR curr; /* get CURR register */ sysOutByte (ELC_CMD (sc->elcAddr), CMD_PS0); curr = sysInByte (ELC_CURR (sc->elcAddr)); sysOutByte (ELC_CMD (sc->elcAddr), 0); return (curr); }/********************************************************************************* elcShow - display statistics for the SMC 8013WC `elc' network interface** This routine displays statistics about the `elc' 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 elcShow ( int unit, /* interface unit */ BOOL zap /* 1 = zero totals */ ) { FAST ELC_SOFTC *sc = &elc_softc[unit]; FAST int ix; static char *e_message [] = { "collisions", "crcs", "aligns", "missed", "over-runs", "disabled", "deferring", "under-run", "aborts", "out-of-window", "heart-beats", "bad-packet", "short-packet", "t-no-error", "r-no-error", "t-error", "r-error", "over-write", "wrapped", "interrupts", "reset", "stray-int"}; for (ix = 0; ix < NELEMENTS(e_message); ix++) { printf (" %-30.30s %4d\n", e_message [ix], sc->elcStat.stat [ix]); if (zap) sc->elcStat.stat [ix] = 0; } printf (" %-30.30s 0x%2x\n", "flags", sc->flags); }/********************************************************************************* elcdetach - detach the card from the bus.** Dettach the card from the bus for reset.** RETURNS: N/A** NOMANUAL*/void elcdetach ( int unit ) { FAST ELC_SOFTC *sc = &elc_softc[unit]; if (elcAttached) { sysOutByte (ELC_INTMASK (sc->elcAddr), 0x00); sysOutByte (ELC_CMD (sc->elcAddr), CMD_CMD5 | CMD_STP); while ((sysInByte (ELC_INTSTAT (sc->elcAddr)) & ISTAT_RST) != ISTAT_RST) ; sysOutByte (ELC_RCON (sc->elcAddr), 0x00); sysOutByte (ELC_TCON (sc->elcAddr), TCON_LB1); sysIntDisablePIC (sc->intLevel); sysOutByte (BIC_MSR (sc->bicAddr), MSR_RST); taskDelay (sysClkRateGet () >> 1); sysOutByte (BIC_MSR (sc->bicAddr), 0x00); taskDelay (sysClkRateGet () >> 1); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -