📄 if_wlp.c
字号:
ifp->if_collisions += (tx_status & TX_NUMCOL);#ifdef WLP_STATS sc->sc_numcol += (tx_status & TX_NUMCOL); if (tx_status & TX_HRT_BET) sc->sc_hrtbet++; if (tx_status & TX_DEF) sc->sc_txdef++; if ((status & P0_S0_EVENT) == RETRANSMIT_DONE) sc->sc_rexmit++;#endif IOWrite1(0x00, P0_INT_ACK | P0_NOP);#ifdef WAVELAN_ROAMING if (sc->sc_rs.rs_disabletx == 0) ifp->if_flags &= ~IFF_OACTIVE; sc->sc_rs.rs_activetx = 0;#else ifp->if_flags &= ~IFF_OACTIVE;#endif wlpstart(&sc->sc_ac.ac_if); /* Restart Transmission */ continue; /* Don't re-ack the INT */ } break; case DUMP_DONE: { char tmpbuf[128]; /* * Dump the 72 bytes returned when in * Enhanced mode. */ printf("\nIntel 82593 Dump\n"); if (sc->sc_iftype == IFTYPE_REDWING) { dump_bytes(sc->sc_maddr, 72); /* * (1) Reset the Receive DMA Counter (Port 0x02 and 0x03) * (2) Reset the Page Control Port (Port 0x09) */ RW_ResetRXDMA(); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_PointRXBUF(0x00); IORead(0x04, tmpbuf, 72); dump_bytes(tmpbuf, 72); WLP_ResetRXDMA(); } IOWrite1(0x00, P0_RCV_ENABLE); } break; case RCV_ABORT: case STOP_REG_HIT: {#ifdef WLP_STATS sc->sc_stopreg++;#endif /* * Disable receive AND make sure that it got * disabled. */ IOWrite1(0x00, P0_RCV_DISABLE); DELAY(500); IOWrite1(0x00, P0_NOP | P0_STATUS3); if ((IORead1(0x00) & P0_S3_RCV_STATE) != 0x00) { printf("wlp%d: Could not disable receive\n", sc->sc_unit); /* * If this was a RCV ABORT and we * could not disable receive, we are * in trouble. Now we must reset the * card. */ if ((status & P0_S0_EVENT) == RCV_ABORT) wlpinit(sc); /* * If this was a STOP REG HIT, we are * probably going to get a RCV ABORT * interrupt right after this. just * break out of the switch so that * the status register can be * re-check for interrupts. */ break; } /* * Reset the Ring Management on the 82593 */ 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; IOWrite1(0x00, P0_RCV_ENABLE); } break; case MC_SETUP_DONE: break; case TDR_DONE: case DIAGNOSE_PASSED: case EXECUTION_ABORT: case DIAGNOSE_FAILED: case IA_SETUP_DONE: case CONFIGURE_DONE: printf("wlp%d received %s (IRQ %x)\n", sc->sc_unit, I82593_IRQ[status & P0_S0_EVENT], status & P0_S0_EVENT); break; default: printf("wlp%d received unknown interrupt.\n", sc->sc_unit); } IOWrite1(0x00, P0_INT_ACK | P0_NOP); }done: /* * Enable INTs */#if 0 IOWrite1(0x00, P0_SWITCH_TO_P1); IOWrite1(0x00, P1_ENABLE_INT); IOWrite1(0x00, P1_SWITCH_TO_P0);#endif}/* * ====================================================================== * PACKET RECEPTION ROUTINE * ====================================================================== */static voidwlpread(sc, len, sigstat, rxaddr) struct wlp_softc *sc; u_int32_t len; u_int32_t sigstat; u_int32_t rxaddr;{ struct ifnet *ifp = &(sc->sc_ac.ac_if); struct ether_header *eh = 0; struct mbuf *top = 0; if (len > ETHER_MAX_LEN) panic("wlpread: sc 0x%x len %d sigstat %x rxaddr %x\n", sc, len, sigstat, rxaddr); MGETHDR(top, M_DONTWAIT, MT_HEADER); if (!top) goto bad; top->m_pkthdr.rcvif = &sc->sc_ac.ac_if; top->m_pkthdr.len = len; if ((len + sizeof(sigstat)) > MINCLSIZE) { MCLGET(top, M_DONTWAIT); if((top->m_flags & M_EXT) == 0) goto bad; if (sc->sc_iftype == IFTYPE_REDWING) { MEMRead(top->m_data, rxaddr, len); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { IORead(0x04, top->m_data, len); } top->m_len = len; } else { u_int32_t tocopy; tocopy = min(len, MHLEN); if (sc->sc_iftype == IFTYPE_REDWING) { MEMRead(top->m_data, rxaddr, tocopy); rxaddr += tocopy; } else if (sc->sc_iftype == IFTYPE_WAVELAN) { IORead(0x04, top->m_data, tocopy); } top->m_len = tocopy; len -= tocopy; while (len > 0) { register struct mbuf *m = 0; MGET(m, M_DONTWAIT, MT_DATA); if (!m) goto bad; tocopy = min(len, MLEN); if (sc->sc_iftype == IFTYPE_REDWING) { MEMRead(m->m_data, rxaddr, tocopy); rxaddr += tocopy; } else if (sc->sc_iftype == IFTYPE_WAVELAN) { IORead(0x04, m->m_data, tocopy); } m->m_len = tocopy; len -= tocopy; m_cat(top, m); } } eh = mtod(top, struct ether_header *);#if NBPFILTER > 0#ifdef MONARCH_ADHOC /* * Append the three sigstat values to the packet when * tapping off. */ if (ifp->if_bpf) { struct bpf_pktstat bps; bps.bs_sigstat = sigstat; bpf_mtap_withstat(ifp, top, &bps); }#else if (ifp->if_bpf) bpf_mtap(ifp, top);#endif /* MONARCH_ADHOC */#endif /* NBPFILTER > 0 */ if (ifp->if_flags & IFF_PROMISC) {#define ETHER_MULTICAST(x) ((x)[0] & 1)#define ETHER_ADDR_MATCH(x,y) (! bcmp((x), (y), ETHER_ADDR_LEN)) if (ETHER_MULTICAST(eh->ether_dhost) == 0 && ETHER_ADDR_MATCH(eh->ether_dhost, sc->sc_ac.ac_enaddr) == 0) { goto bad; } } m_adj(top, sizeof(struct ether_header));#ifdef WAVELAN_ROAMING /* * Don't pass BEACON packets up the protocol stack. */ if (ntohs(eh->ether_type) < 1500 && bcmp(ether_wavelan_snaphdr, mtod(top, caddr_t), sizeof(ether_wavelan_snaphdr)) == 0) { if (sc->sc_rs.rs_roam_enable == ROAM_ON) { m_adj(top, sizeof(ether_wavelan_snaphdr)); wavelan_input(eh, top, sigstat); } m_freem(top); return; }#endif sc->sc_sigstat = sigstat; ether_input(ifp, eh, top); return;bad: if (top) m_freem(top); return;}intwlpioctl(ifp, cmd, data) struct ifnet *ifp; int cmd; caddr_t data;{ register struct ifaddr *ifa = (struct ifaddr *) data; struct wlp_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; s = splimp(); if (sc->sc_gone) { error = ENXIO; goto done; } /* * ============================================================ * Common ioctl()'s * ============================================================ */ switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; /* netifs are BUSY when UP */ switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: wlpinit(sc); /* before arpwhohas */ arp_ifinit((struct arpcom *) ifp, ifa); break;#endif#ifdef INET6 case AF_INET6: wlpinit(sc); ndp6_ifinit(ifp, ifa); break;#endif default: wlpinit(sc); break; } break; case SIOCGIFADDR: { struct sockaddr *sa; sa = (struct sockaddr *) & ifr->ifr_data; bcopy((caddr_t) sc->sc_ac.ac_enaddr, (caddr_t) sa->sa_data, ETHER_ADDR_LEN); } break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { ifp->if_flags &= ~IFF_RUNNING; wlpstop(sc); } else { /* reinitialize card on any parameter change */ wlpinit(sc); } break; case SIOCSIFMTU: /* * Set the interface MTU. */ if (ifr->ifr_mtu > ETHERMTU) { error = EINVAL; } else { ifp->if_mtu = ifr->ifr_mtu; } break; case SIOCADDMULTI: case SIOCDELMULTI: if (cmd == SIOCADDMULTI) error = ether_addmulti(ifr, &sc->sc_ac); else error = ether_delmulti(ifr, &sc->sc_ac); if (error == ENETRESET) { wlpsetrcr(sc); error = 0; } break; case SIOCGIFSTATS: get_ifstats(sc, ifr); break; default: if (sc->sc_iftype == IFTYPE_WAVELAN) error = wavelan_ioctl(ifp, cmd, data); else error = EINVAL; }done: splx(s); return (error);}static voidwlpstop(sc) struct wlp_softc *sc;{ /* Already at splimp() */ if (sc->sc_gone) return; IOWrite1(0x00, P0_RCV_DISABLE);}voidwlpsetrcr(sc) struct wlp_softc *sc;{ struct ether_multi *enm; u_int16_t offset = 2; if (sc->sc_iftype == IFTYPE_REDWING) { } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_PointTXBUF(WLP_TXBASE + 0x02); } for (enm = sc->sc_ac.ac_multiaddrs; enm; enm = enm->enm_next) { u_int32_t lo; u_int32_t hi; lo = (enm->enm_addrlo[3] << 16) + (enm->enm_addrlo[4] << 8) + enm->enm_addrlo[5]; hi = (enm->enm_addrhi[3] << 16) + (enm->enm_addrhi[4] << 8) + enm->enm_addrhi[5]; while (lo <= hi) { if (sc->sc_iftype == IFTYPE_REDWING) { MEMWrite(enm->enm_addrlo, RW_RXWINDOW + offset, 3); offset += 3; MEMWrite1(RW_RXWINDOW + offset, ((lo >> 16) & 0xFF)); offset++; MEMWrite1(RW_RXWINDOW + offset, ((lo >> 8) & 0xFF)); offset++; MEMWrite1(RW_RXWINDOW + offset, (lo & 0xFF)); offset++; } else if (sc->sc_iftype == IFTYPE_WAVELAN) { IOWrite(0x04, enm->enm_addrlo, 3); offset += 3; IOWrite1(0x04, ((lo >> 16) & 0xFF)); offset++; IOWrite1(0x04, ((lo >> 8) & 0xFF)); offset++; IOWrite1(0x04, (lo & 0xFF)); offset++; } lo++; } } /* for loop */ if (offset == 2) goto done; offset -= 2; if (sc->sc_iftype == IFTYPE_REDWING) { MEMWrite1(RW_RXWINDOW, (offset & 0xFF)); MEMWrite1(RW_RXWINDOW + 1, (offset >> 8) & 0xFF); /* * (1) Reset the Page Control Port (Port 9) * (2) Reset the Transmit DMA Counters (Port 4 and 5) * (3) Issue the MC-SETUP command */#if 0 IOWrite1(0x09, (IORead1(0x09) & P9_RXBUF));#endif RW_ResetTXDMA(); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_PointTXBUF(WLP_TXBASE); IOWrite1(0x04, (offset & 0xFF)); /* Fill-in the length */ IOWrite1(0x04, (offset >> 8) & 0xFF); WLP_ResetTXDMA(); } /* * (1) Issue the MC-SETUP command */ IOWrite1(0x00, P0_MC_SETUP);done: return;}/* * ====================================================================== * UTILITY ROUTINES * ====================================================================== */#if 0static voidwlpdump(sc) struct wlp_softc *sc;{ /* * (1) Reset the 82593's internel status register pointer. * (2) Disable packet reception * (3) Reset the Receive DMA * (4) Issue the DUMP command */ IOWrite1(0x00, P0_NOP); IOWrite1(0x00, P0_RCV_DISABLE); if (sc->sc_iftype == IFTYPE_REDWING) { RW_ResetRXDMA(); } else if (sc->sc_iftype == IFTYPE_WAVELAN) { WLP_ResetRXDMA(); } IOWrite1(0x00, P0_DUMP);}#endifstatic voidget_ifstats(sc, ifr) struct wlp_softc *sc; struct ifreq *ifr;{ struct ifstats *ifs = (struct ifstats *) ifr; ifs->ifs_iftype = sc->sc_iftype; ifs->ifs_unit = sc->sc_unit; ifs->ifs_iobase = sc->sc_iobase; ifs->ifs_iosize = sc->sc_iosize; ifs->ifs_maddr = (int) sc->sc_maddr; ifs->ifs_msize = sc->sc_msize;#ifdef WLP_STATS ifs->ifs_istats.txcnt = sc->sc_txcnt; ifs->ifs_istats.numcol = sc->sc_numcol; ifs->ifs_istats.frtl = sc->sc_frtl; ifs->ifs_istats.txdef = sc->sc_txdef; ifs->ifs_istats.undrun = sc->sc_undrun; ifs->ifs_istats.lostcts = sc->sc_lostcts; ifs->ifs_istats.lostcrs = sc->sc_lostcrs; ifs->ifs_istats.txok = sc->sc_txok; ifs->ifs_istats.col = sc->sc_col; ifs->ifs_istats.rxcnt = sc->sc_rxcnt; ifs->ifs_istats.srtfrm = sc->sc_srtfrm; ifs->ifs_istats.nosfd = sc->sc_nosfd; ifs->ifs_istats.nadmch = sc->sc_nadmch; ifs->ifs_istats.iamch = sc->sc_iamch; ifs->ifs_istats.rcvcld = sc->sc_rcvcld; ifs->ifs_istats.rxok = sc->sc_rxok; ifs->ifs_istats.lenerr = sc->sc_lenerr; ifs->ifs_istats.crcerr = sc->sc_crcerr; ifs->ifs_istats.algerr = sc->sc_algerr; ifs->ifs_istats.overrun = sc->sc_overrun; ifs->ifs_istats.stopreg = sc->sc_stopreg; ifs->ifs_istats.rexmit = sc->sc_rexmit; ifs->ifs_istats.irqcnt = sc->sc_irqcnt;#endif ifs->ifs_wstats.nwid = ((sc->sc_nwid[0] << 8) | sc->sc_nwid[1]); wavelan_stats(sc, ifs);}static voiddump_bytes(tbuf, cnt) caddr_t tbuf; u_int32_t cnt;{ int i; cnt = cnt / 8; for (i = 0; i < cnt; i++) printf("byte %3d | %2x %2x %2x %2x %2x %2x %2x %2x\n", (i << 3), (u_char) tbuf[(i << 3) + 0], (u_char) tbuf[(i << 3) + 1], (u_char) tbuf[(i << 3) + 2], (u_char) tbuf[(i << 3) + 3], (u_char) tbuf[(i << 3) + 4], (u_char) tbuf[(i << 3) + 5], (u_char) tbuf[(i << 3) + 6], (u_char) tbuf[(i << 3) + 7]); printf("\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -