Lines Matching +full:double +full:- +full:buffering
1 /*-
2 * SPDX-License-Identifier: BSD-4-Clause
19 * 4. Neither the name of the author nor the names of any co-contributors
41 * The Level 1 chip is used on some D-Link, SMC and Addtron NICs.
42 * It's a 64-bit PCI part that supports TCP/IP checksum offload,
47 * of double buffer DMA where the packet data is copied to a
48 * pre-allocated DMA buffer who's physical address has been loaded
52 * for double buffering. This may be true in Windows NT and the like,
57 * Also, the VLAN tagging is done using a 16-entry table which allows
63 * - Jeff James at Intel, for arranging to have the LXT1001 manual
65 * - Beny Chen at D-Link, for actually sending it to me
66 * - Brad Short and Keith Alexis at SMC, for sending me sample
68 * - Paul Saab at Y!, for not killing me (though it remains to be seen
225 device_printf(sc->lge_dev, "EEPROM read timed out\n"); in lge_eeprom_getword()
269 * If we have a non-PCS PHY, pretend that the internal in lge_miibus_readreg()
273 if (sc->lge_pcs == 0 && phy == 0) in lge_miibus_readreg()
283 device_printf(sc->lge_dev, "PHY read timed out\n"); in lge_miibus_readreg()
306 device_printf(sc->lge_dev, "PHY write timed out\n"); in lge_miibus_writereg()
320 mii = device_get_softc(sc->lge_miibus); in lge_miibus_statchg()
323 switch (IFM_SUBTYPE(mii->mii_media_active)) { in lge_miibus_statchg()
344 if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { in lge_miibus_statchg()
362 hashes[1] |= (1 << (h - 32)); in lge_hash_maddr()
372 ifp = sc->lge_ifp; in lge_setmulti()
410 device_printf(sc->lge_dev, "reset never completed\n"); in lge_reset()
429 while(t->lge_name != NULL) { in lge_probe()
430 if ((pci_get_vendor(dev) == t->lge_vid) && in lge_probe()
431 (pci_get_device(dev) == t->lge_did)) { in lge_probe()
432 device_set_desc(dev, t->lge_name); in lge_probe()
454 sc->lge_dev = dev; in lge_attach()
456 mtx_init(&sc->lge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, in lge_attach()
458 callout_init_mtx(&sc->lge_stat_callout, &sc->lge_mtx, 0); in lge_attach()
466 sc->lge_res = bus_alloc_resource_any(dev, LGE_RES, &rid, RF_ACTIVE); in lge_attach()
468 if (sc->lge_res == NULL) { in lge_attach()
474 sc->lge_btag = rman_get_bustag(sc->lge_res); in lge_attach()
475 sc->lge_bhandle = rman_get_bushandle(sc->lge_res); in lge_attach()
479 sc->lge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, in lge_attach()
482 if (sc->lge_irq == NULL) { in lge_attach()
498 sc->lge_ldata = contigmalloc(sizeof(struct lge_list_data), M_DEVBUF, in lge_attach()
501 if (sc->lge_ldata == NULL) { in lge_attach()
514 ifp = sc->lge_ifp = if_alloc(IFT_ETHER); in lge_attach()
521 if_setsendqlen(ifp, LGE_TX_LIST_CNT - 1); in lge_attach()
526 sc->lge_pcs = 1; in lge_attach()
528 sc->lge_pcs = 0; in lge_attach()
533 error = mii_attach(dev, &sc->lge_miibus, ifp, lge_ifmedia_upd, in lge_attach()
545 error = bus_setup_intr(dev, sc->lge_irq, INTR_TYPE_NET | INTR_MPSAFE, in lge_attach()
546 NULL, lge_intr, sc, &sc->lge_intrhand); in lge_attach()
557 if (sc->lge_ldata) in lge_attach()
558 free(sc->lge_ldata, M_DEVBUF); in lge_attach()
561 if (sc->lge_irq) in lge_attach()
562 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lge_irq); in lge_attach()
563 if (sc->lge_res) in lge_attach()
564 bus_release_resource(dev, LGE_RES, LGE_RID, sc->lge_res); in lge_attach()
565 mtx_destroy(&sc->lge_mtx); in lge_attach()
576 ifp = sc->lge_ifp; in lge_detach()
582 callout_drain(&sc->lge_stat_callout); in lge_detach()
587 bus_teardown_intr(dev, sc->lge_irq, sc->lge_intrhand); in lge_detach()
588 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->lge_irq); in lge_detach()
589 bus_release_resource(dev, LGE_RES, LGE_RID, sc->lge_res); in lge_detach()
591 free(sc->lge_ldata, M_DEVBUF); in lge_detach()
594 mtx_destroy(&sc->lge_mtx); in lge_detach()
609 cd = &sc->lge_cdata; in lge_list_tx_init()
610 ld = sc->lge_ldata; in lge_list_tx_init()
612 ld->lge_tx_list[i].lge_mbuf = NULL; in lge_list_tx_init()
613 ld->lge_tx_list[i].lge_ctl = 0; in lge_list_tx_init()
616 cd->lge_tx_prod = cd->lge_tx_cons = 0; in lge_list_tx_init()
634 ld = sc->lge_ldata; in lge_list_rx_init()
635 cd = &sc->lge_cdata; in lge_list_rx_init()
637 cd->lge_rx_prod = cd->lge_rx_cons = 0; in lge_list_rx_init()
644 if (lge_newbuf(sc, &ld->lge_rx_list[i], NULL) == ENOBUFS) in lge_list_rx_init()
666 device_printf(sc->lge_dev, "no memory for rx list " in lge_newbuf()
667 "-- packet dropped!\n"); in lge_newbuf()
675 device_printf(sc->lge_dev, "jumbo allocation failed " in lge_newbuf()
676 "-- packet dropped!\n"); in lge_newbuf()
682 m_new->m_len = m_new->m_pkthdr.len = LGE_JUMBO_FRAMELEN; in lge_newbuf()
687 m_new->m_len = m_new->m_pkthdr.len = LGE_JUMBO_FRAMELEN; in lge_newbuf()
688 m_new->m_data = m_new->m_ext.ext_buf; in lge_newbuf()
698 c->lge_mbuf = m_new; in lge_newbuf()
699 c->lge_fragptr_hi = 0; in lge_newbuf()
700 c->lge_fragptr_lo = vtophys(mtod(m_new, caddr_t)); in lge_newbuf()
701 c->lge_fraglen = m_new->m_len; in lge_newbuf()
702 c->lge_ctl = m_new->m_len | LGE_RXCTL_WANTINTR | LGE_FRAGCNT(1); in lge_newbuf()
703 c->lge_sts = 0; in lge_newbuf()
710 * DWORD, which lets us specify a 64-bit address if in lge_newbuf()
711 * desired. We only use a 32-bit address for now. in lge_newbuf()
717 LGE_INC(sc->lge_cdata.lge_rx_prod, LGE_RX_LIST_CNT); in lge_newbuf()
730 sc->lge_cdata.lge_jumbo_buf = contigmalloc(LGE_JMEM, M_DEVBUF, in lge_alloc_jumbo_mem()
733 if (sc->lge_cdata.lge_jumbo_buf == NULL) { in lge_alloc_jumbo_mem()
734 device_printf(sc->lge_dev, "no memory for jumbo buffers!\n"); in lge_alloc_jumbo_mem()
738 SLIST_INIT(&sc->lge_jfree_listhead); in lge_alloc_jumbo_mem()
739 SLIST_INIT(&sc->lge_jinuse_listhead); in lge_alloc_jumbo_mem()
745 ptr = sc->lge_cdata.lge_jumbo_buf; in lge_alloc_jumbo_mem()
747 sc->lge_cdata.lge_jslots[i] = ptr; in lge_alloc_jumbo_mem()
752 device_printf(sc->lge_dev, "no memory for jumbo " in lge_alloc_jumbo_mem()
756 entry->slot = i; in lge_alloc_jumbo_mem()
757 SLIST_INSERT_HEAD(&sc->lge_jfree_listhead, in lge_alloc_jumbo_mem()
769 if (sc->lge_cdata.lge_jumbo_buf == NULL) in lge_free_jumbo_mem()
772 while ((entry = SLIST_FIRST(&sc->lge_jinuse_listhead))) { in lge_free_jumbo_mem()
773 device_printf(sc->lge_dev, in lge_free_jumbo_mem()
775 SLIST_REMOVE_HEAD(&sc->lge_jinuse_listhead, jpool_entries); in lge_free_jumbo_mem()
776 SLIST_INSERT_HEAD(&sc->lge_jfree_listhead, entry, in lge_free_jumbo_mem()
779 while (!SLIST_EMPTY(&sc->lge_jfree_listhead)) { in lge_free_jumbo_mem()
780 entry = SLIST_FIRST(&sc->lge_jfree_listhead); in lge_free_jumbo_mem()
781 SLIST_REMOVE_HEAD(&sc->lge_jfree_listhead, jpool_entries); in lge_free_jumbo_mem()
785 free(sc->lge_cdata.lge_jumbo_buf, M_DEVBUF); in lge_free_jumbo_mem()
798 entry = SLIST_FIRST(&sc->lge_jfree_listhead); in lge_jalloc()
802 device_printf(sc->lge_dev, "no free jumbo buffers\n"); in lge_jalloc()
807 SLIST_REMOVE_HEAD(&sc->lge_jfree_listhead, jpool_entries); in lge_jalloc()
808 SLIST_INSERT_HEAD(&sc->lge_jinuse_listhead, entry, jpool_entries); in lge_jalloc()
809 return(sc->lge_cdata.lge_jslots[entry->slot]); in lge_jalloc()
823 sc = m->m_ext.ext_arg1; in lge_jfree()
829 i = ((vm_offset_t)m->m_ext.ext_buf in lge_jfree()
830 - (vm_offset_t)sc->lge_cdata.lge_jumbo_buf) / LGE_JLEN; in lge_jfree()
835 entry = SLIST_FIRST(&sc->lge_jinuse_listhead); in lge_jfree()
838 entry->slot = i; in lge_jfree()
839 SLIST_REMOVE_HEAD(&sc->lge_jinuse_listhead, jpool_entries); in lge_jfree()
840 SLIST_INSERT_HEAD(&sc->lge_jfree_listhead, entry, jpool_entries); in lge_jfree()
856 ifp = sc->lge_ifp; in lge_rxeof()
860 i = sc->lge_cdata.lge_rx_cons; in lge_rxeof()
866 cur_rx = &sc->lge_ldata->lge_rx_list[i]; in lge_rxeof()
867 rxctl = cur_rx->lge_ctl; in lge_rxeof()
868 rxsts = cur_rx->lge_sts; in lge_rxeof()
869 m = cur_rx->lge_mbuf; in lge_rxeof()
870 cur_rx->lge_mbuf = NULL; in lge_rxeof()
873 c--; in lge_rxeof()
878 * it should simply get re-used next time this descriptor in lge_rxeof()
892 device_printf(sc->lge_dev, "no receive buffers " in lge_rxeof()
893 "available -- packet dropped!\n"); in lge_rxeof()
899 m->m_pkthdr.rcvif = ifp; in lge_rxeof()
900 m->m_pkthdr.len = m->m_len = total_len; in lge_rxeof()
907 m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; in lge_rxeof()
909 m->m_pkthdr.csum_flags |= CSUM_IP_VALID; in lge_rxeof()
914 m->m_pkthdr.csum_flags |= in lge_rxeof()
916 m->m_pkthdr.csum_data = 0xffff; in lge_rxeof()
924 sc->lge_cdata.lge_rx_cons = i; in lge_rxeof()
934 ifp = sc->lge_ifp; in lge_rxeoc()
952 ifp = sc->lge_ifp; in lge_txeof()
955 sc->lge_timer = 0; in lge_txeof()
961 idx = sc->lge_cdata.lge_tx_cons; in lge_txeof()
964 while (idx != sc->lge_cdata.lge_tx_prod && txdone) { in lge_txeof()
965 cur_tx = &sc->lge_ldata->lge_tx_list[idx]; in lge_txeof()
968 if (cur_tx->lge_mbuf != NULL) { in lge_txeof()
969 m_freem(cur_tx->lge_mbuf); in lge_txeof()
970 cur_tx->lge_mbuf = NULL; in lge_txeof()
972 cur_tx->lge_ctl = 0; in lge_txeof()
974 txdone--; in lge_txeof()
976 sc->lge_timer = 0; in lge_txeof()
979 sc->lge_cdata.lge_tx_cons = idx; in lge_txeof()
995 ifp = sc->lge_ifp; in lge_tick()
1003 if (!sc->lge_link) { in lge_tick()
1004 mii = device_get_softc(sc->lge_miibus); in lge_tick()
1006 if (mii->mii_media_status & IFM_ACTIVE && in lge_tick()
1007 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { in lge_tick()
1008 sc->lge_link++; in lge_tick()
1010 (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX|| in lge_tick()
1011 IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T)) in lge_tick()
1012 device_printf(sc->lge_dev, "gigabit link up\n"); in lge_tick()
1018 if (sc->lge_timer != 0 && --sc->lge_timer == 0) in lge_tick()
1020 callout_reset(&sc->lge_stat_callout, hz, lge_tick, sc); in lge_tick()
1033 ifp = sc->lge_ifp; in lge_intr()
1064 sc->lge_link = 0; in lge_intr()
1065 callout_stop(&sc->lge_stat_callout); in lge_intr()
1070 /* Re-enable interrupts. */ in lge_intr()
1098 cur_tx = &sc->lge_ldata->lge_tx_list[*txidx]; in lge_encap()
1101 for (m = m_head; m != NULL; m = m->m_next) { in lge_encap()
1102 if (m->m_len != 0) { in lge_encap()
1103 tot_len += m->m_len; in lge_encap()
1104 f = &cur_tx->lge_frags[frag]; in lge_encap()
1105 f->lge_fraglen = m->m_len; in lge_encap()
1106 f->lge_fragptr_lo = vtophys(mtod(m, vm_offset_t)); in lge_encap()
1107 f->lge_fragptr_hi = 0; in lge_encap()
1115 cur_tx->lge_mbuf = m_head; in lge_encap()
1116 cur_tx->lge_ctl = LGE_TXCTL_WANTINTR|LGE_FRAGCNT(frag)|tot_len; in lge_encap()
1152 if (!sc->lge_link) in lge_start_locked()
1155 idx = sc->lge_cdata.lge_tx_prod; in lge_start_locked()
1160 while(sc->lge_ldata->lge_tx_list[idx].lge_mbuf == NULL) { in lge_start_locked()
1181 sc->lge_cdata.lge_tx_prod = idx; in lge_start_locked()
1186 sc->lge_timer = 5; in lge_start_locked()
1204 if_t ifp = sc->lge_ifp; in lge_init_locked()
1217 CSR_WRITE_4(sc, LGE_PAR0, *(u_int32_t *)(&if_getlladdr(sc->lge_ifp)[0])); in lge_init_locked()
1218 CSR_WRITE_4(sc, LGE_PAR1, *(u_int32_t *)(&if_getlladdr(sc->lge_ifp)[4])); in lge_init_locked()
1222 device_printf(sc->lge_dev, "initialization failed: no " in lge_init_locked()
1321 callout_reset(&sc->lge_stat_callout, hz, lge_tick, sc); in lge_init_locked()
1352 mii = device_get_softc(sc->lge_miibus); in lge_ifmedia_upd_locked()
1353 sc->lge_link = 0; in lge_ifmedia_upd_locked()
1354 LIST_FOREACH(miisc, &mii->mii_phys, mii_list) in lge_ifmedia_upd_locked()
1371 mii = device_get_softc(sc->lge_miibus); in lge_ifmedia_sts()
1373 ifmr->ifm_active = mii->mii_media_active; in lge_ifmedia_sts()
1374 ifmr->ifm_status = mii->mii_media_status; in lge_ifmedia_sts()
1391 if (ifr->ifr_mtu > LGE_JUMBO_MTU) in lge_ioctl()
1394 if_setmtu(ifp, ifr->ifr_mtu); in lge_ioctl()
1402 !(sc->lge_if_flags & IFF_PROMISC)) { in lge_ioctl()
1408 sc->lge_if_flags & IFF_PROMISC) { in lge_ioctl()
1419 sc->lge_if_flags = if_getflags(ifp); in lge_ioctl()
1432 mii = device_get_softc(sc->lge_miibus); in lge_ioctl()
1433 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); in lge_ioctl()
1449 ifp = sc->lge_ifp; in lge_watchdog()
1474 ifp = sc->lge_ifp; in lge_stop()
1475 sc->lge_timer = 0; in lge_stop()
1476 callout_stop(&sc->lge_stat_callout); in lge_stop()
1481 sc->lge_link = 0; in lge_stop()
1487 if (sc->lge_ldata->lge_rx_list[i].lge_mbuf != NULL) { in lge_stop()
1488 m_freem(sc->lge_ldata->lge_rx_list[i].lge_mbuf); in lge_stop()
1489 sc->lge_ldata->lge_rx_list[i].lge_mbuf = NULL; in lge_stop()
1492 bzero((char *)&sc->lge_ldata->lge_rx_list, in lge_stop()
1493 sizeof(sc->lge_ldata->lge_rx_list)); in lge_stop()
1499 if (sc->lge_ldata->lge_tx_list[i].lge_mbuf != NULL) { in lge_stop()
1500 m_freem(sc->lge_ldata->lge_tx_list[i].lge_mbuf); in lge_stop()
1501 sc->lge_ldata->lge_tx_list[i].lge_mbuf = NULL; in lge_stop()
1505 bzero((char *)&sc->lge_ldata->lge_tx_list, in lge_stop()
1506 sizeof(sc->lge_ldata->lge_tx_list)); in lge_stop()