📄 if_wlp.c
字号:
voidwlpinit(sc) struct wlp_softc *sc;{ int s; s = splimp(); if (sc->sc_gone) goto done;#if 0 if (sc->sc_iftype == IFTYPE_REDWING) { /* * Fix for ASIC Problem ??? */ IOWrite1(0x0C, P12_SERIAL_CLOCK); IOWrite1(0x0C, 0x00); }#endif /* * (1) Disable Receive (2) Reset the 82593 */ IOWrite1(0x00, P0_RCV_DISABLE); IOWrite1(0x00, P0_RESET); DELAY(200); if (sc->sc_ifconfig(sc)) { printf("wlp%d: Configuration failed.\n", sc->sc_unit); goto done; } if (sc->sc_iftype == IFTYPE_REDWING) { /* * (1) Reset the Receive DMA Counter (Port 0x02 and 0x03) * (2) Reset the Transmit DMA Counter (Port 0x04 and 0x05) * (3) Reset the Interrupt Control Port (Port 0x07) * (4) Enable Collision Avoidance and set IFS (Port 0x08) * (5) Reset the Page Control Port (Port 0x09) * (6) Reset the status information */ RW_ResetRXDMA(); sc->sc_rxnext = 0; RW_ResetTXDMA(); IOWrite1(0x07, 0x00); IOWrite1(0x08, IORead1(0x08) | P8_CA_ENABLE | (P8_IFS_TIME & IFS_TIME));#if 0 IOWrite1(0x09, 0x00);#endif } else if (sc->sc_iftype == IFTYPE_WAVELAN) {#ifdef WAVELAN_ROAMING sc->sc_rs.rs_disabletx = 0;#endif sc->sc_nwidprom = 0; /* NWID Promisc Mode */ /* * (1) Reset the RX DMA */ WLP_ResetRXDMA(); sc->sc_rxnext = 0; } /* * (1) Switch to Port 1 * (2) Reset/Setup the Ring Buffer Management * (3) Enable interrupts * (4) Switch to Port 0 * (5) Enable packet reception */ IOWrite1(0x00, P0_SWITCH_TO_P1); IOWrite1(0x00, P1_RST_RING_MGMT); IOWrite1(0x00, P1_ENABLE_INT); IOWrite1(0x00, P1_SWITCH_TO_P0); IOWrite1(0x00, P0_RCV_ENABLE); sc->sc_ac.ac_if.if_flags |= IFF_RUNNING; sc->sc_ac.ac_if.if_flags &= ~IFF_OACTIVE;#ifdef WAVELAN_ROAMING sc->sc_rs.rs_activetx = 0;#endif /* * Try to start output */ wlpstart(&sc->sc_ac.ac_if);done: splx(s);}/* * ====================================================================== * PACKET TRANSMISSION ROUTINES * ====================================================================== */voidwlpwatchdog(ifp) struct ifnet *ifp;{ struct wlp_softc *sc = (struct wlp_softc *) ifp->if_softc; ifp->if_oerrors++; if (sc->sc_gone) return; printf("wlp%d: watchdog resetting interface\n", ifp->if_unit); wlpinit(sc); /* calls wlpstart() */}static voidwlpstart(ifp) struct ifnet *ifp;{ struct wlp_softc *sc = ifp->if_softc; struct mbuf *m; int s; s = splimp(); /* * If the card has been removed, quit. */ if (sc->sc_gone) goto done; /* * If no resources have been allocated for this interface, quit. */ if ((ifp->if_flags & IFF_RUNNING) == 0 || (ifp->if_flags & IFF_OACTIVE)) goto done;#ifdef WAVELAN_ROAMING if(sc->sc_rs.rs_activetx) goto done;#endif#ifdef MONARCH_DSRIFQ DSRIFQ_DEQUEUE(ifp, m); if(0 == m) goto done;#else /* * Determine if there's anything to send. */ m = ifp->if_snd.ifq_head; if (!m) goto done; IF_DEQUEUE(&ifp->if_snd, m);#endif /* MONARCH_DSRIFQ */ wlptransmit(sc, m); m_freem(m);done: splx(s);}/* * This routine is called from wlpstart() and from the * roaming code - jgb 02/13/99 */voidwlptransmit(sc, m) struct wlp_softc *sc; struct mbuf *m;{ struct ifnet *ifp = &sc->sc_ac.ac_if; struct mbuf *m0; u_int16_t len; u_int16_t totlen;#ifdef WAVELAN_ROAMING if(sc->sc_rs.rs_activetx) {#ifdef notdef printf("wlptransmit: returning... (activetx set)\n");#endif return; }#endif /* * Determine the packet's length */ for (m0 = m, totlen = 0; m0; m0 = m0->m_next) totlen += m0->m_len; /* * If the packet is too long, discard it. */ if (totlen > ETHER_MAX_LEN) { ++ifp->if_oerrors; goto done; }#ifdef WLP_STATS sc->sc_txcnt++;#endif ifp->if_opackets++; ifp->if_obytes += totlen; ifp->if_flags |= IFF_OACTIVE; ifp->if_timer = 2; /* 2 seconds */#ifdef WAVELAN_ROAMING sc->sc_rs.rs_activetx = 1;#endif if (sc->sc_iftype == IFTYPE_REDWING) { len = 2; for (m0 = m; m0; m0 = m0->m_next) { MEMWrite(mtod(m0, caddr_t), RW_RXWINDOW + len, m0->m_len); len += m0->m_len; } if (len < ETHER_MIN_LEN + 2) { int i; for (i = len; i <= (ETHER_MIN_LEN + 2); i++) MEMWrite1(RW_RXWINDOW + i, 0x00); len = (ETHER_MIN_LEN + 2); } MEMWrite1(RW_RXWINDOW + len, P0_NOP); MEMWrite1(RW_RXWINDOW + len + 1, P0_NOP); len -= 2; MEMWrite1(RW_RXWINDOW, len & 0xFF); /* Insert "Byte Count" */ MEMWrite1(RW_RXWINDOW + 1, (len >> 8) & 0xFF); /* * (1) Update the interface flags * (2) Reset the TX DMA counter * (3) Give the Card a Collision Avoidance Seed */ RW_ResetTXDMA();#if 0 IOWrite1(0x0A, time.tv_usec & P10_CASEED);#endif } else if (sc->sc_iftype == IFTYPE_WAVELAN) { /* * Pointer at the beginning of the Transmit Buffer */ WLP_PointTXBUF(WLP_TXBASE); if (totlen < ETHER_MIN_LEN) totlen = ETHER_MIN_LEN; IOWrite1(0x04, (totlen & 0xFF)); IOWrite1(0x04, ((totlen >> 8) & 0xFF)); for (m0 = m, len = 0; m0; m0 = m0->m_next) { IOWrite(0x04, mtod(m0, caddr_t), m0->m_len); len += m0->m_len; } for (; len < ETHER_MIN_LEN; len++) IOWrite1(0x04, 0x00); IOWrite1(0x04, P0_NOP); IOWrite1(0x04, P0_NOP); /* * (1) Reset the TX DMA counter */ WLP_ResetTXDMA(); } /* * (1) Issue the transmit command */ IOWrite1(0x00, P0_TRANSMIT);#if NBPFILTER > 0 if (ifp->if_bpf) { bpf_mtap(ifp, m); }#endifdone: ;}/* * ====================================================================== * INTERRUPT SERVICE ROUTINE * ====================================================================== */voidwlpintr(unit) int unit;{ struct wlp_softc *sc = &wlp_softc[unit]; struct ifnet *ifp = &(sc->sc_ac.ac_if); u_int8_t status;#ifdef WLP_STATS sc->sc_irqcnt++;#endif /* * If the card has been removed, quit. */ if (sc->sc_gone) { printf("wlp%d: Interrupt received but card is missing\n", sc->sc_unit); return; }#if 0 /* * Disable INTs */ IOWrite1(0x00, P0_SWITCH_TO_P1); IOWrite1(0x00, P1_DISABLE_INT); IOWrite1(0x00, P1_SWITCH_TO_P0);#endif while (1) { if (sc->sc_iftype == IFTYPE_REDWING) { /* * (1) Check for Timer IRQ from Alliston * (2) Check for Carrier Sense IRQ from Alliston * (3) Check for IRQs from the 82593 */ status = IORead1(0x07); if (status & P7_TIRQ) { /* Timer IRQ */ printf("\tTimer IRQ received\n"); IOWrite1(0x07, status | P7_TIRQ); DELAY(100); continue; } if (status & P7_CIRQ) { /* Carrier Sense IRQ */ printf("\tCarrier Sense IRQ received\n"); IOWrite1(0x07, status | P7_CIRQ); DELAY(100); continue; } } IOWrite1(0x00, P0_NOP); /* Reset Register Pointer */ status = IORead1(0x00); if ((status & P0_S0_INT) == 0) /* 82593 IRQ */ goto done; switch (status & P0_S0_EVENT) { case END_OF_FRAME: { u_int32_t RFP = 0; /* Receive Frame Pointer */ u_int16_t BlockLength = 0; u_int16_t First = 0; u_int16_t Current; u_int16_t Next; u_int8_t RxPage; if (status != (P0_S0_INT | P0_S0_RCV | P0_S0_CHNL | END_OF_FRAME)) { printf("wlp%d: invalid END_OF_FRAME status\n", sc->sc_unit); } if (sc->sc_iftype == IFTYPE_REDWING) { /* * Figure out where the next frame is... */ IOWrite1(0x00, P0_NOP | P0_STATUS2); RFP = IORead1(0x00); RFP += (IORead1(0x00) << 8); /* * Take all of the frames out of the * receive buffer that were received * as of the time this interrupt was * generated. */ if (RFP == sc->sc_rxnext) goto rx_done; /* * (1) Map the correct page into memory. * (2) Figure out how many bytes we have to process. */ RxPage = ((((RFP & 0x3C00) >> 10) - 3) & 0x0F); IOWrite1(0x09, (IORead1(0x09) & P9_TXBUF) | RxPage); if (RFP > sc->sc_rxnext) { BlockLength = RFP - sc->sc_rxnext; } else { BlockLength = RW_RXBUFSIZE - sc->sc_rxnext + RFP; } First = ((sc->sc_rxnext - (RxPage << 10)) & 0xFFF); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { /* * Figure out where the next frame is... */ RFP = IORead1(0x02); RFP |= ((IORead1(0x03) & P3_RPLH) << 8); if (RFP == sc->sc_rxnext) goto rx_done; /* * Take all of the frames out of the * receive buffer that were received * as of the time this interrupt was * generated. */ if (RFP > sc->sc_rxnext) { BlockLength = RFP - sc->sc_rxnext; } else { BlockLength = WLP_RXBUFSIZE - sc->sc_rxnext + RFP; } First = sc->sc_rxnext; } Current = 0;#define WORKING 1#define ERROR 2#define READY 3 do { int rx_status = 0; int sigstat = 0; u_int32_t len = 0; u_int16_t RxFrameStatus = WORKING; u_int16_t EBYTES = (sc->sc_iftype == IFTYPE_REDWING ? 2 : 5); Next = BlockLength; while (RxFrameStatus == WORKING) { if (sc->sc_iftype == IFTYPE_REDWING) { rx_status = MEMRead1(First + Next - 4); rx_status += (MEMRead1(First + Next - 3) << 8); len = MEMRead1(First + Next - 2); len += (MEMRead1(First + Next - 1) << 8); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_PointRXBUF(First + Next - 7); rx_status = IORead1(0x04); rx_status += (IORead1(0x04) << 8); len = IORead1(0x04); len += (IORead1(0x04) << 8); sigstat = ((IORead1(0x04) & 0x3F) << SIGL_SHIFT); sigstat += ((IORead1(0x04) & 0x3F) << SILL_SHIFT); sigstat += ((IORead1(0x04) & 0x0F) << SIGQ_SHIFT); } /* * I don't check ETHER_MIN_LEN because * of BEACONS */ if ((rx_status & RX_STAT_BITS) != (RX_RCV_OK | 0x10) || (len - EBYTES > ETHER_MAX_LEN)) { RxFrameStatus = ERROR; ifp->if_ierrors++;#ifdef WLP_STATS if (rx_status & RX_RCLD) sc->sc_rcvcld++; if (rx_status & RX_IA_MCH) sc->sc_iamch++; if (rx_status & RX_SRT_FRM) sc->sc_srtfrm++; if (rx_status & RX_OVRRUN) sc->sc_overrun++; if (rx_status & RX_ALG_ERR) sc->sc_algerr++; if (rx_status & RX_CRC_ERR) sc->sc_crcerr++; if (rx_status & RX_LEN_ERR) sc->sc_lenerr++;#endif } else if (((Next - (len + EBYTES)) & RXBUF_MAX_ADDR) == Current) { RxFrameStatus = READY; } else { Next = (Next - (len + EBYTES)) & RXBUF_MAX_ADDR; } /* * Sanity Check */ if (Next < Current) { goto rx_fatal_error; } } /* while( WORKING ) */#ifdef WLP_STATS sc->sc_rxcnt++;#endif if (RxFrameStatus == READY) { ifp->if_ipackets++; ifp->if_ibytes += (Next - (Current + EBYTES + 2));#ifdef WLP_STATS sc->sc_rxok++;#endif if (sc->sc_iftype == IFTYPE_REDWING) { wlpread(sc, Next - (Current + 4), 0, First + Current); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_PointRXBUF((First + Current) & RXBUF_MAX_ADDR); wlpread(sc, (Next - (Current + 7)) & RXBUF_MAX_ADDR, sigstat, 0); } } else { /* RxFrameStatus == ERROR */ } Current = Next; } while (Current != BlockLength);#undef WORKING#undef READY#undef ERROR goto rx_done; rx_fatal_error: printf("wlp%d: receive error\n", ifp->if_unit); ifp->if_ierrors++; IOWrite1(0x00, P0_RCV_DISABLE); IOWrite1(0x00, P0_SWITCH_TO_P1); IOWrite1(0x00, P1_RST_RING_MGMT); IOWrite1(0x00, P1_SWITCH_TO_P0); if (sc->sc_iftype == IFTYPE_REDWING) { RW_ResetRXDMA(); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_ResetRXDMA(); } sc->sc_rxnext = 0; RFP = 0; IOWrite1(0x00, P0_RCV_ENABLE); rx_done: sc->sc_rxnext = RFP; } break; case TRANSMIT_DONE: case TRANSMIT_NOCRC_DONE: case RETRANSMIT_DONE: { u_int16_t tx_status; ifp->if_timer = 0; /* stop the watchdog * timer */ tx_status = IORead1(0x00); tx_status |= (IORead1(0x00) << 8); if ((tx_status & TX_STAT_BITS) == TX_OK) {#ifdef WLP_STATS sc->sc_txok++;#endif goto tx_done; } /* ERROR: Unsuccessful Transmission */ if (tx_status & (TX_FRTL | TX_COLL | TX_UND_RUN | TX_LST_CTS)) ifp->if_oerrors++;#ifdef WLP_STATS if (tx_status & TX_FRTL) sc->sc_frtl++; if (tx_status & TX_MAX_COL) sc->sc_maxcol++; if (tx_status & TX_UND_RUN) sc->sc_undrun++; if (tx_status & TX_LST_CTS) sc->sc_lostcts++; if (tx_status & TX_LST_CRS) sc->sc_lostcrs++; if (tx_status & TX_LTCOL) sc->sc_ltcol++; if (tx_status & TX_COLL) sc->sc_col++;#endif tx_done:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -