diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/pci/if_xl.c | 363 | ||||
-rw-r--r-- | sys/pci/if_xlreg.h | 19 |
2 files changed, 309 insertions, 73 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index a5f50a2..36ff5a2 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998 + * Copyright (c) 1997, 1998, 1999 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -202,12 +202,16 @@ static int xl_newbuf __P((struct xl_softc *, static void xl_stats_update __P((void *)); static int xl_encap __P((struct xl_softc *, struct xl_chain *, struct mbuf * )); +static int xl_encap_90xB __P((struct xl_softc *, struct xl_chain *, + struct mbuf * )); static void xl_rxeof __P((struct xl_softc *)); static void xl_txeof __P((struct xl_softc *)); +static void xl_txeof_90xB __P((struct xl_softc *)); static void xl_txeoc __P((struct xl_softc *)); static void xl_intr __P((void *)); static void xl_start __P((struct ifnet *)); +static void xl_start_90xB __P((struct ifnet *)); static int xl_ioctl __P((struct ifnet *, u_long, caddr_t)); static void xl_init __P((void *)); static void xl_stop __P((struct xl_softc *)); @@ -232,6 +236,7 @@ static void xl_setmulti_hash __P((struct xl_softc *)); static void xl_reset __P((struct xl_softc *)); static int xl_list_rx_init __P((struct xl_softc *)); static int xl_list_tx_init __P((struct xl_softc *)); +static int xl_list_tx_init_90xB __P((struct xl_softc *)); static void xl_wait __P((struct xl_softc *)); static void xl_mediacheck __P((struct xl_softc *)); #ifdef notdef @@ -1147,14 +1152,12 @@ static void xl_mediacheck(sc) static int xl_attach(dev) device_t dev; { - int s, i; + int s; u_char eaddr[ETHER_ADDR_LEN]; u_int32_t command; struct xl_softc *sc; struct ifnet *ifp; int media = IFM_ETHER|IFM_100_TX|IFM_FDX; - unsigned int round; - caddr_t roundptr; int unit, error = 0, rid; s = splimp(); @@ -1285,9 +1288,10 @@ static int xl_attach(dev) callout_handle_init(&sc->xl_stat_ch); bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - sc->xl_ldata_ptr = malloc(sizeof(struct xl_list_data) + 8, - M_DEVBUF, M_NOWAIT); - if (sc->xl_ldata_ptr == NULL) { + sc->xl_ldata = contigmalloc(sizeof(struct xl_list_data), M_DEVBUF, + M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0); + + if (sc->xl_ldata == NULL) { printf("xl%d: no memory for list buffers!\n", unit); bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq); @@ -1296,19 +1300,19 @@ static int xl_attach(dev) goto fail; } - sc->xl_ldata = (struct xl_list_data *)sc->xl_ldata_ptr; - round = (uintptr_t)sc->xl_ldata_ptr & 0xF; - roundptr = sc->xl_ldata_ptr; - for (i = 0; i < 8; i++) { - if (round % 8) { - round++; - roundptr++; - } else - break; - } - sc->xl_ldata = (struct xl_list_data *)roundptr; bzero(sc->xl_ldata, sizeof(struct xl_list_data)); + /* + * Figure out the card type. 3c905B adapters have the + * 'supportsNoTxLength' bit set in the capabilities + * word in the EEPROM. + */ + xl_read_eeprom(sc, (caddr_t)&sc->xl_caps, XL_EE_CAPS, 1, 0); + if (sc->xl_caps & XL_CAPS_NO_TXLENGTH) + sc->xl_type = XL_TYPE_905B; + else + sc->xl_type = XL_TYPE_90X; + ifp = &sc->arpcom.ac_if; ifp->if_softc = sc; ifp->if_unit = unit; @@ -1317,24 +1321,16 @@ static int xl_attach(dev) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = xl_ioctl; ifp->if_output = ether_output; - ifp->if_start = xl_start; + if (sc->xl_type == XL_TYPE_905B) + ifp->if_start = xl_start_90xB; + else + ifp->if_start = xl_start; ifp->if_watchdog = xl_watchdog; ifp->if_init = xl_init; ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = XL_TX_LIST_CNT - 1; /* - * Figure out the card type. 3c905B adapters have the - * 'supportsNoTxLength' bit set in the capabilities - * word in the EEPROM. - */ - xl_read_eeprom(sc, (caddr_t)&sc->xl_caps, XL_EE_CAPS, 1, 0); - if (sc->xl_caps & XL_CAPS_NO_TXLENGTH) - sc->xl_type = XL_TYPE_905B; - else - sc->xl_type = XL_TYPE_90X; - - /* * Now we have to see what sort of media we have. * This includes probing for an MII interace and a * possible PHY. @@ -1362,7 +1358,8 @@ static int xl_attach(dev) bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq); bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res); - free(sc->xl_ldata_ptr, M_DEVBUF); + contigfree(sc->xl_ldata, + sizeof(struct xl_list_data), M_DEVBUF); error = ENXIO; goto fail; } @@ -1491,6 +1488,7 @@ static int xl_detach(dev) sc = device_get_softc(dev); ifp = &sc->arpcom.ac_if; + xl_reset(sc); xl_stop(sc); if_detach(ifp); @@ -1505,7 +1503,7 @@ static int xl_detach(dev) bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res); ifmedia_removeall(&sc->ifmedia); - free(sc->xl_ldata_ptr, M_DEVBUF); + contigfree(sc->xl_ldata, sizeof(struct xl_list_data), M_DEVBUF); splx(s); @@ -1539,6 +1537,44 @@ static int xl_list_tx_init(sc) } /* + * Initialize the transmit descriptors. + */ +static int xl_list_tx_init_90xB(sc) + struct xl_softc *sc; +{ + struct xl_chain_data *cd; + struct xl_list_data *ld; + int i; + + cd = &sc->xl_cdata; + ld = sc->xl_ldata; + for (i = 0; i < XL_TX_LIST_CNT; i++) { + cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i]; + cd->xl_tx_chain[i].xl_phys = vtophys(&ld->xl_tx_list[i]); + if (i == (XL_TX_LIST_CNT - 1)) + cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[0]; + else + cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1]; + if (i == 0) + cd->xl_tx_chain[i].xl_prev = + &cd->xl_tx_chain[XL_TX_LIST_CNT - 1]; + else + cd->xl_tx_chain[i].xl_prev = + &cd->xl_tx_chain[i - 1]; + } + + bzero((char *)ld->xl_tx_list, + sizeof(struct xl_list) * XL_TX_LIST_CNT); + ld->xl_tx_list[0].xl_status = XL_TXSTAT_EMPTY; + + cd->xl_tx_prod = 1; + cd->xl_tx_cons = 1; + cd->xl_tx_cnt = 0; + + return(0); +} + +/* * Initialize the RX descriptors and allocate mbufs for them. Note that * we arrange the descriptors in a closed ring, so that the last descriptor * points back to the first. @@ -1561,11 +1597,11 @@ static int xl_list_rx_init(sc) if (i == (XL_RX_LIST_CNT - 1)) { cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[0]; ld->xl_rx_list[i].xl_next = - vtophys(&ld->xl_rx_list[0]); + vtophys(&ld->xl_rx_list[0]); } else { cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[i + 1]; ld->xl_rx_list[i].xl_next = - vtophys(&ld->xl_rx_list[i + 1]); + vtophys(&ld->xl_rx_list[i + 1]); } } @@ -1585,26 +1621,28 @@ static int xl_newbuf(sc, c) MGETHDR(m_new, M_DONTWAIT, MT_DATA); if (m_new == NULL) { - printf("xl%d: no memory for rx list -- packet dropped!\n", - sc->xl_unit); + printf("xl%d: no memory for rx list -- " + "packet dropped!\n", sc->xl_unit); return(ENOBUFS); } MCLGET(m_new, M_DONTWAIT); if (!(m_new->m_flags & M_EXT)) { - printf("xl%d: no memory for rx list -- packet dropped!\n", - sc->xl_unit); + printf("xl%d: no memory for rx list -- " + "packet dropped!\n", sc->xl_unit); m_freem(m_new); return(ENOBUFS); } + m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + /* Force longword alignment for packet payload. */ - m_new->m_data += 2; + m_adj(m_new, ETHER_ALIGN); c->xl_mbuf = m_new; - c->xl_ptr->xl_status = 0; c->xl_ptr->xl_frag.xl_addr = vtophys(mtod(m_new, caddr_t)); c->xl_ptr->xl_frag.xl_len = MCLBYTES | XL_LAST_FRAG; + c->xl_ptr->xl_status = 0; return(0); } @@ -1649,8 +1687,8 @@ again: * If not, something truly strange has happened. */ if (!(rxstat & XL_RXSTAT_UP_CMPLT)) { - printf("xl%d: bad receive status -- packet dropped", - sc->xl_unit); + printf("xl%d: bad receive status -- " + "packet dropped", sc->xl_unit); ifp->if_ierrors++; cur_rx->xl_ptr->xl_status = 0; continue; @@ -1771,11 +1809,10 @@ static void xl_txeof(sc) */ while(sc->xl_cdata.xl_tx_head != NULL) { cur_tx = sc->xl_cdata.xl_tx_head; - if ((sc->xl_type == XL_TYPE_905B && - !(cur_tx->xl_ptr->xl_status & XL_TXSTAT_DL_COMPLETE)) || - CSR_READ_4(sc, XL_DOWNLIST_PTR)) { + + if (CSR_READ_4(sc, XL_DOWNLIST_PTR)) break; - } + sc->xl_cdata.xl_tx_head = cur_tx->xl_next; m_freem(cur_tx->xl_mbuf); cur_tx->xl_mbuf = NULL; @@ -1800,6 +1837,43 @@ static void xl_txeof(sc) return; } +static void xl_txeof_90xB(sc) + struct xl_softc *sc; +{ + struct xl_chain *cur_tx = NULL; + struct ifnet *ifp; + int idx; + + ifp = &sc->arpcom.ac_if; + + idx = sc->xl_cdata.xl_tx_cons; + while(idx != sc->xl_cdata.xl_tx_prod) { + + cur_tx = &sc->xl_cdata.xl_tx_chain[idx]; + + if (!(cur_tx->xl_ptr->xl_status & XL_TXSTAT_DL_COMPLETE)) + break; + + if (cur_tx->xl_mbuf != NULL) { + m_freem(cur_tx->xl_mbuf); + cur_tx->xl_mbuf = NULL; + } + + ifp->if_opackets++; + + sc->xl_cdata.xl_tx_cnt--; + XL_INC(idx, XL_TX_LIST_CNT); + ifp->if_timer = 0; + } + + sc->xl_cdata.xl_tx_cons = idx; + + if (cur_tx != NULL) + ifp->if_flags &= ~IFF_OACTIVE; + + return; +} + /* * TX 'end of channel' interrupt handler. Actually, we should * only get a 'TX complete' interrupt if there's a transmit error, @@ -1818,9 +1892,21 @@ static void xl_txeoc(sc) sc->xl_unit, txstat); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET); xl_wait(sc); - if (sc->xl_cdata.xl_tx_head != NULL) - CSR_WRITE_4(sc, XL_DOWNLIST_PTR, + if (sc->xl_type == XL_TYPE_905B) { + if (sc->xl_cdata.xl_tx_cnt) { + int i; + struct xl_chain *c; + i = sc->xl_cdata.xl_tx_cons; + c = &sc->xl_cdata.xl_tx_chain[i]; + CSR_WRITE_4(sc, XL_DOWNLIST_PTR, + c->xl_phys); + CSR_WRITE_1(sc, XL_DOWN_POLL, 64); + } + } else { + if (sc->xl_cdata.xl_tx_head != NULL) + CSR_WRITE_4(sc, XL_DOWNLIST_PTR, vtophys(sc->xl_cdata.xl_tx_head->xl_ptr)); + } /* * Remember to set this for the * first generation 3c90X chips. @@ -1865,14 +1951,7 @@ static void xl_intr(arg) sc = arg; ifp = &sc->arpcom.ac_if; - /* Disable interrupts. */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB); - - for (;;) { - status = CSR_READ_2(sc, XL_STATUS); - - if ((status & XL_INTRS) == 0) - break; + while((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS) { CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|(status & XL_INTRS)); @@ -1880,8 +1959,12 @@ static void xl_intr(arg) if (status & XL_STAT_UP_COMPLETE) xl_rxeof(sc); - if (status & XL_STAT_DOWN_COMPLETE) - xl_txeof(sc); + if (status & XL_STAT_DOWN_COMPLETE) { + if (sc->xl_type == XL_TYPE_905B) + xl_txeof_90xB(sc); + else + xl_txeof(sc); + } if (status & XL_STAT_TX_COMPLETE) { ifp->if_oerrors++; @@ -1900,13 +1983,8 @@ static void xl_intr(arg) } } - /* Re-enable interrupts. */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS); - - XL_SEL_WIN(7); - if (ifp->if_snd.ifq_head != NULL) - xl_start(ifp); + (*ifp->if_start)(ifp); return; } @@ -2166,6 +2244,120 @@ static void xl_start(ifp) return; } +static int xl_encap_90xB(sc, c, m_head) + struct xl_softc *sc; + struct xl_chain *c; + struct mbuf *m_head; +{ + int frag = 0; + struct xl_frag *f = NULL; + struct mbuf *m; + struct xl_list *d; + + /* + * Start packing the mbufs in this chain into + * the fragment pointers. Stop when we run out + * of fragments or hit the end of the mbuf chain. + */ + d = c->xl_ptr; + d->xl_status = 0; + d->xl_next = 0; + + for (m = m_head, frag = 0; m != NULL; m = m->m_next) { + if (m->m_len != 0) { + if (frag == XL_MAXFRAGS) + break; + f = &d->xl_frag[frag]; + f->xl_addr = vtophys(mtod(m, vm_offset_t)); + f->xl_len = m->m_len; + frag++; + } + } + + c->xl_mbuf = m_head; + c->xl_ptr->xl_frag[frag - 1].xl_len |= XL_LAST_FRAG; + c->xl_ptr->xl_status = XL_TXSTAT_RND_DEFEAT; + + return(0); +} + +static void xl_start_90xB(ifp) + struct ifnet *ifp; +{ + struct xl_softc *sc; + struct mbuf *m_head = NULL; + struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx; + int idx; + + sc = ifp->if_softc; + + if (ifp->if_flags & IFF_OACTIVE) + return; + + idx = sc->xl_cdata.xl_tx_prod; + start_tx = &sc->xl_cdata.xl_tx_chain[idx]; + + while (sc->xl_cdata.xl_tx_chain[idx].xl_mbuf == NULL) { + + if ((XL_TX_LIST_CNT - sc->xl_cdata.xl_tx_cnt) < 3) { + ifp->if_flags |= IFF_OACTIVE; + break; + } + + IF_DEQUEUE(&ifp->if_snd, m_head); + if (m_head == NULL) + break; + + cur_tx = &sc->xl_cdata.xl_tx_chain[idx]; + + /* Pack the data into the descriptor. */ + xl_encap_90xB(sc, cur_tx, m_head); + + /* Chain it together. */ + if (prev != NULL) + prev->xl_ptr->xl_next = cur_tx->xl_phys; + prev = cur_tx; + +#if NBPF > 0 + /* + * If there's a BPF listener, bounce a copy of this frame + * to him. + */ + if (ifp->if_bpf) + bpf_mtap(ifp, cur_tx->xl_mbuf); +#endif + + XL_INC(idx, XL_TX_LIST_CNT); + sc->xl_cdata.xl_tx_cnt++; + } + + /* + * If there are no packets queued, bail. + */ + if (cur_tx == NULL) + return; + + /* + * Place the request for the upload interrupt + * in the last descriptor in the chain. This way, if + * we're chaining several packets at once, we'll only + * get an interupt once for the whole chain rather than + * once for each packet. + */ + cur_tx->xl_ptr->xl_status |= XL_TXSTAT_DL_INTR; + + /* Start transmission */ + sc->xl_cdata.xl_tx_prod = idx; + start_tx->xl_prev->xl_ptr->xl_next = start_tx->xl_phys; + + /* + * Set a timeout in case the chip goes out to lunch. + */ + ifp->if_timer = 5; + + return; +} + static void xl_init(xsc) void *xsc; { @@ -2197,7 +2389,6 @@ static void xl_init(xsc) /* Clear the station mask. */ for (i = 0; i < 3; i++) CSR_WRITE_2(sc, XL_W2_STATION_MASK_LO + (i * 2), 0); - #ifdef notdef /* Reset TX and RX. */ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET); @@ -2205,7 +2396,6 @@ static void xl_init(xsc) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET); xl_wait(sc); #endif - /* Init circular RX list. */ if (xl_list_rx_init(sc) == ENOBUFS) { printf("xl%d: initialization failed: no " @@ -2215,7 +2405,10 @@ static void xl_init(xsc) } /* Init TX descriptors. */ - xl_list_tx_init(sc); + if (sc->xl_type == XL_TYPE_905B) + xl_list_tx_init_90xB(sc); + else + xl_list_tx_init(sc); /* * Set the TX freethresh value. @@ -2240,7 +2433,7 @@ static void xl_init(xsc) */ if (sc->xl_type == XL_TYPE_905B) { CSR_WRITE_2(sc, XL_COMMAND, - XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4)); + XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4)); } /* Set RX filter bits. */ @@ -2292,6 +2485,20 @@ static void xl_init(xsc) xl_wait(sc); CSR_WRITE_4(sc, XL_UPLIST_PTR, vtophys(&sc->xl_ldata->xl_rx_list[0])); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); + xl_wait(sc); + + + if (sc->xl_type == XL_TYPE_905B) { + /* Set polling interval */ + CSR_WRITE_1(sc, XL_DOWN_POLL, 64); + /* Load the address of the TX list */ + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL); + xl_wait(sc); + CSR_WRITE_4(sc, XL_DOWNLIST_PTR, + vtophys(&sc->xl_ldata->xl_tx_list[0])); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL); + xl_wait(sc); + } /* * If the coax transceiver is on, make sure to enable @@ -2324,12 +2531,21 @@ static void xl_init(xsc) CSR_WRITE_2(sc, XL_DMACTL, XL_DMACTL_UP_RX_EARLY); /* Enable receiver and transmitter. */ - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE); + xl_wait(sc); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE); + xl_wait(sc); if (mii != NULL) mii_mediachg(mii); + XL_SEL_WIN(7); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); + xl_wait(sc); + CSR_WRITE_4(sc, XL_UPLIST_PTR, vtophys(&sc->xl_ldata->xl_rx_list[0])); + CSR_WRITE_1(sc, XL_UP_POLL, 8); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); + xl_wait(sc); /* Select window 7 for normal operations. */ XL_SEL_WIN(7); @@ -2530,7 +2746,7 @@ static void xl_watchdog(ifp) xl_init(sc); if (ifp->if_snd.ifq_head != NULL) - xl_start(ifp); + (*ifp->if_start)(ifp); return; } @@ -2556,13 +2772,17 @@ static void xl_stop(sc) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_DISABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); DELAY(800); -#ifdef notdef + +#ifdef foo CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET); xl_wait(sc); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET); xl_wait(sc); #endif + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|XL_STAT_INTLATCH); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|0); + CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0); /* Stop the stats updater. */ untimeout(xl_stats_update, sc, sc->xl_stat_ch); @@ -2606,6 +2826,7 @@ static void xl_shutdown(dev) sc = device_get_softc(dev); + xl_reset(sc); xl_stop(sc); return; diff --git a/sys/pci/if_xlreg.h b/sys/pci/if_xlreg.h index 9497e39..c504ccc 100644 --- a/sys/pci/if_xlreg.h +++ b/sys/pci/if_xlreg.h @@ -92,9 +92,11 @@ #define XL_TX_FREE 0x1C #define XL_DMACTL 0x20 #define XL_DOWNLIST_PTR 0x24 +#define XL_DOWN_POLL 0x2D /* 3c90xB only */ #define XL_TX_FREETHRESH 0x2F #define XL_UPLIST_PTR 0x38 #define XL_UPLIST_STATUS 0x30 +#define XL_UP_POLL 0x3D /* 3c90xB only */ #define XL_PKTSTAT_UP_STALLED 0x00002000 #define XL_PKTSTAT_UP_ERROR 0x00004000 @@ -440,6 +442,8 @@ struct xl_list_onefrag { #define XL_RX_LIST_CNT 128 #define XL_TX_LIST_CNT 256 #define XL_MIN_FRAMELEN 60 +#define ETHER_ALIGN 2 +#define XL_INC(x, y) (x) = (x + 1) % y struct xl_list_data { struct xl_list_onefrag xl_rx_list[XL_RX_LIST_CNT]; @@ -451,6 +455,8 @@ struct xl_chain { struct xl_list *xl_ptr; struct mbuf *xl_mbuf; struct xl_chain *xl_next; + struct xl_chain *xl_prev; + u_int32_t xl_phys; }; struct xl_chain_onefrag { @@ -465,9 +471,15 @@ struct xl_chain_data { struct xl_chain_onefrag *xl_rx_head; + /* 3c90x "boomerang" queuing stuff */ struct xl_chain *xl_tx_head; struct xl_chain *xl_tx_tail; struct xl_chain *xl_tx_free; + + /* 3c90xB "cyclone/hurricane/tornado" stuff */ + int xl_tx_prod; + int xl_tx_cons; + int xl_tx_cnt; }; #define XL_RXSTAT_LENMASK 0x00001FFF @@ -495,11 +507,12 @@ struct xl_chain_data { #define XL_TXSTAT_IPCKSUM 0x02000000 /* 3c905B only */ #define XL_TXSTAT_TCPCKSUM 0x04000000 /* 3c905B only */ #define XL_TXSTAT_UDPCKSUM 0x08000000 /* 3c905B only */ +#define XL_TXSTAT_RND_DEFEAT 0x10000000 /* 3c905B only */ +#define XL_TXSTAT_EMPTY 0x20000000 /* 3c905B only */ #define XL_TXSTAT_DL_INTR 0x80000000 #define XL_CAPABILITY_BM 0x20 - struct xl_type { u_int16_t xl_vid; u_int16_t xl_did; @@ -528,6 +541,9 @@ struct xl_mii_frame { * take advantage of, namely the multicast hash filter. With older * chips, you only have the option of turning on reception of all * multicast frames, which is kind of lame. + * + * We also use this to decide on a transmit strategy. For the 3c90xB + * cards, we can use polled descriptor mode, which reduces CPU overhead. */ #define XL_TYPE_905B 1 #define XL_TYPE_90X 2 @@ -549,7 +565,6 @@ struct xl_softc { u_int16_t xl_caps; u_int8_t xl_stats_no_timeout; u_int16_t xl_tx_thresh; - caddr_t xl_ldata_ptr; struct xl_list_data *xl_ldata; struct xl_chain_data xl_cdata; struct callout_handle xl_stat_ch; |