Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/xl/if_xl.c
Show First 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | |||||
static void xl_reset(struct xl_softc *); | static void xl_reset(struct xl_softc *); | ||||
static int xl_list_rx_init(struct xl_softc *); | static int xl_list_rx_init(struct xl_softc *); | ||||
static int xl_list_tx_init(struct xl_softc *); | static int xl_list_tx_init(struct xl_softc *); | ||||
static int xl_list_tx_init_90xB(struct xl_softc *); | static int xl_list_tx_init_90xB(struct xl_softc *); | ||||
static void xl_wait(struct xl_softc *); | static void xl_wait(struct xl_softc *); | ||||
static void xl_mediacheck(struct xl_softc *); | static void xl_mediacheck(struct xl_softc *); | ||||
static void xl_choose_media(struct xl_softc *sc, int *media); | static void xl_choose_media(struct xl_softc *sc, int *media); | ||||
static void xl_choose_xcvr(struct xl_softc *, int); | static void xl_choose_xcvr(struct xl_softc *, int); | ||||
static void xl_dma_map_addr(void *, bus_dma_segment_t *, int, int); | |||||
#ifdef notdef | #ifdef notdef | ||||
static void xl_testpacket(struct xl_softc *); | static void xl_testpacket(struct xl_softc *); | ||||
#endif | #endif | ||||
static int xl_miibus_readreg(device_t, int, int); | static int xl_miibus_readreg(device_t, int, int); | ||||
static int xl_miibus_writereg(device_t, int, int, int); | static int xl_miibus_writereg(device_t, int, int, int); | ||||
static void xl_miibus_statchg(device_t); | static void xl_miibus_statchg(device_t); | ||||
static void xl_miibus_mediainit(device_t); | static void xl_miibus_mediainit(device_t); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
static devclass_t xl_devclass; | static devclass_t xl_devclass; | ||||
DRIVER_MODULE_ORDERED(xl, pci, xl_driver, xl_devclass, NULL, NULL, | DRIVER_MODULE_ORDERED(xl, pci, xl_driver, xl_devclass, NULL, NULL, | ||||
SI_ORDER_ANY); | SI_ORDER_ANY); | ||||
DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, NULL, NULL); | DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, NULL, NULL); | ||||
static void | |||||
xl_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) | |||||
{ | |||||
u_int32_t *paddr; | |||||
paddr = arg; | |||||
*paddr = segs->ds_addr; | |||||
} | |||||
/* | /* | ||||
* Murphy's law says that it's possible the chip can wedge and | * Murphy's law says that it's possible the chip can wedge and | ||||
* the 'command in progress' bit may never clear. Hence, we wait | * the 'command in progress' bit may never clear. Hence, we wait | ||||
* only a finite amount of time to avoid getting caught in an | * only a finite amount of time to avoid getting caught in an | ||||
* infinite loop. Normally this delay routine would be a macro, | * infinite loop. Normally this delay routine would be a macro, | ||||
* but it isn't called during normal operation so we can afford | * but it isn't called during normal operation so we can afford | ||||
* to make it a function. Suppress warning when card gone. | * to make it a function. Suppress warning when card gone. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 707 Lines • ▼ Show 20 Lines | |||||
* Attach the interface. Allocate softc structures, do ifmedia | * Attach the interface. Allocate softc structures, do ifmedia | ||||
* setup and ethernet/BPF attach. | * setup and ethernet/BPF attach. | ||||
*/ | */ | ||||
static int | static int | ||||
xl_attach(device_t dev) | xl_attach(device_t dev) | ||||
{ | { | ||||
u_char eaddr[ETHER_ADDR_LEN]; | u_char eaddr[ETHER_ADDR_LEN]; | ||||
u_int16_t sinfo2, xcvr[2]; | u_int16_t sinfo2, xcvr[2]; | ||||
struct bus_dmamem_args args; | |||||
struct xl_softc *sc; | struct xl_softc *sc; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int media, pmcap; | int media, pmcap; | ||||
int error = 0, phy, rid, res, unit; | int error = 0, phy, rid, res, unit; | ||||
uint16_t did; | uint16_t did; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->xl_dev = dev; | sc->xl_dev = dev; | ||||
▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | if (xl_read_eeprom(sc, (caddr_t)&eaddr, XL_EE_OEM_ADR0, 3, 1)) { | ||||
error = ENXIO; | error = ENXIO; | ||||
goto fail; | goto fail; | ||||
} | } | ||||
callout_init_mtx(&sc->xl_tick_callout, &sc->xl_mtx, 0); | callout_init_mtx(&sc->xl_tick_callout, &sc->xl_mtx, 0); | ||||
TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc); | TASK_INIT(&sc->xl_task, 0, xl_rxeof_task, sc); | ||||
/* | /* | ||||
* Now allocate a tag for the DMA descriptor lists and a chunk | * Now allocate a chunk of DMA-able memory for the DMA | ||||
* of DMA-able memory based on the tag. Also obtain the DMA | * descriptor lists. All of our lists are allocated as a | ||||
* addresses of the RX and TX ring, which we'll need later. | * contiguous block of memory. | ||||
* All of our lists are allocated as a contiguous block | |||||
* of memory. | |||||
*/ | */ | ||||
error = bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, | bus_dma_mem_args_init(&args); | ||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, | args.dma_alignment = 8; | ||||
XL_RX_LIST_SZ, 1, XL_RX_LIST_SZ, 0, NULL, NULL, | args.dma_lowaddr = BUS_SPACE_MAXADDR_32BIT; | ||||
&sc->xl_ldata.xl_rx_tag); | error = bus_dma_mem_alloc(bus_get_dma_tag(dev), XL_RX_LIST_SZ, 0, &args, | ||||
&sc->xl_ldata.xl_rx_ring); | |||||
if (error) { | if (error) { | ||||
device_printf(dev, "failed to allocate rx dma tag\n"); | device_printf(dev, "failed to allocate rx ring\n"); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
sc->xl_ldata.xl_rx_list = sc->xl_ldata.xl_rx_ring.dma_vaddr; | |||||
error = bus_dmamem_alloc(sc->xl_ldata.xl_rx_tag, | error = bus_dma_mem_alloc(bus_get_dma_tag(dev), XL_TX_LIST_SZ, 0, &args, | ||||
(void **)&sc->xl_ldata.xl_rx_list, BUS_DMA_NOWAIT | | &sc->xl_ldata.xl_tx_ring); | ||||
BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->xl_ldata.xl_rx_dmamap); | |||||
if (error) { | if (error) { | ||||
device_printf(dev, "no memory for rx list buffers!\n"); | device_printf(dev, "failed to allocate tx ring\n"); | ||||
bus_dma_tag_destroy(sc->xl_ldata.xl_rx_tag); | |||||
sc->xl_ldata.xl_rx_tag = NULL; | |||||
goto fail; | goto fail; | ||||
} | } | ||||
sc->xl_ldata.xl_tx_list = sc->xl_ldata.xl_tx_ring.dma_vaddr; | |||||
error = bus_dmamap_load(sc->xl_ldata.xl_rx_tag, | |||||
sc->xl_ldata.xl_rx_dmamap, sc->xl_ldata.xl_rx_list, | |||||
XL_RX_LIST_SZ, xl_dma_map_addr, | |||||
&sc->xl_ldata.xl_rx_dmaaddr, BUS_DMA_NOWAIT); | |||||
if (error) { | |||||
device_printf(dev, "cannot get dma address of the rx ring!\n"); | |||||
bus_dmamem_free(sc->xl_ldata.xl_rx_tag, sc->xl_ldata.xl_rx_list, | |||||
sc->xl_ldata.xl_rx_dmamap); | |||||
bus_dma_tag_destroy(sc->xl_ldata.xl_rx_tag); | |||||
sc->xl_ldata.xl_rx_tag = NULL; | |||||
goto fail; | |||||
} | |||||
error = bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, | |||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, | |||||
XL_TX_LIST_SZ, 1, XL_TX_LIST_SZ, 0, NULL, NULL, | |||||
&sc->xl_ldata.xl_tx_tag); | |||||
if (error) { | |||||
device_printf(dev, "failed to allocate tx dma tag\n"); | |||||
goto fail; | |||||
} | |||||
error = bus_dmamem_alloc(sc->xl_ldata.xl_tx_tag, | |||||
(void **)&sc->xl_ldata.xl_tx_list, BUS_DMA_NOWAIT | | |||||
BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->xl_ldata.xl_tx_dmamap); | |||||
if (error) { | |||||
device_printf(dev, "no memory for list buffers!\n"); | |||||
bus_dma_tag_destroy(sc->xl_ldata.xl_tx_tag); | |||||
sc->xl_ldata.xl_tx_tag = NULL; | |||||
goto fail; | |||||
} | |||||
error = bus_dmamap_load(sc->xl_ldata.xl_tx_tag, | |||||
sc->xl_ldata.xl_tx_dmamap, sc->xl_ldata.xl_tx_list, | |||||
XL_TX_LIST_SZ, xl_dma_map_addr, | |||||
&sc->xl_ldata.xl_tx_dmaaddr, BUS_DMA_NOWAIT); | |||||
if (error) { | |||||
device_printf(dev, "cannot get dma address of the tx ring!\n"); | |||||
bus_dmamem_free(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_list, | |||||
sc->xl_ldata.xl_tx_dmamap); | |||||
bus_dma_tag_destroy(sc->xl_ldata.xl_tx_tag); | |||||
sc->xl_ldata.xl_tx_tag = NULL; | |||||
goto fail; | |||||
} | |||||
/* | /* | ||||
* Allocate a DMA tag for the mapping of mbufs. | * Allocate a DMA tag for the mapping of mbufs. | ||||
*/ | */ | ||||
error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, | error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, | ||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, | BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, | ||||
MCLBYTES * XL_MAXFRAGS, XL_MAXFRAGS, MCLBYTES, 0, NULL, | MCLBYTES * XL_MAXFRAGS, XL_MAXFRAGS, MCLBYTES, 0, NULL, | ||||
NULL, &sc->xl_mtag); | NULL, &sc->xl_mtag); | ||||
if (error) { | if (error) { | ||||
▲ Show 20 Lines • Show All 300 Lines • ▼ Show 20 Lines | #endif | ||||
if (ifp) | if (ifp) | ||||
if_free(ifp); | if_free(ifp); | ||||
if (sc->xl_mtag) { | if (sc->xl_mtag) { | ||||
bus_dmamap_destroy(sc->xl_mtag, sc->xl_tmpmap); | bus_dmamap_destroy(sc->xl_mtag, sc->xl_tmpmap); | ||||
bus_dma_tag_destroy(sc->xl_mtag); | bus_dma_tag_destroy(sc->xl_mtag); | ||||
} | } | ||||
if (sc->xl_ldata.xl_rx_tag) { | bus_dma_mem_free(&sc->xl_ldata.xl_rx_ring); | ||||
bus_dmamap_unload(sc->xl_ldata.xl_rx_tag, | bus_dma_mem_free(&sc->xl_ldata.xl_tx_ring); | ||||
sc->xl_ldata.xl_rx_dmamap); | |||||
bus_dmamem_free(sc->xl_ldata.xl_rx_tag, sc->xl_ldata.xl_rx_list, | |||||
sc->xl_ldata.xl_rx_dmamap); | |||||
bus_dma_tag_destroy(sc->xl_ldata.xl_rx_tag); | |||||
} | |||||
if (sc->xl_ldata.xl_tx_tag) { | |||||
bus_dmamap_unload(sc->xl_ldata.xl_tx_tag, | |||||
sc->xl_ldata.xl_tx_dmamap); | |||||
bus_dmamem_free(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_list, | |||||
sc->xl_ldata.xl_tx_dmamap); | |||||
bus_dma_tag_destroy(sc->xl_ldata.xl_tx_tag); | |||||
} | |||||
mtx_destroy(&sc->xl_mtx); | mtx_destroy(&sc->xl_mtx); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Initialize the transmit descriptors. | * Initialize the transmit descriptors. | ||||
Show All 10 Lines | xl_list_tx_init(struct xl_softc *sc) | ||||
cd = &sc->xl_cdata; | cd = &sc->xl_cdata; | ||||
ld = &sc->xl_ldata; | ld = &sc->xl_ldata; | ||||
for (i = 0; i < XL_TX_LIST_CNT; i++) { | 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_ptr = &ld->xl_tx_list[i]; | ||||
error = bus_dmamap_create(sc->xl_mtag, 0, | error = bus_dmamap_create(sc->xl_mtag, 0, | ||||
&cd->xl_tx_chain[i].xl_map); | &cd->xl_tx_chain[i].xl_map); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
cd->xl_tx_chain[i].xl_phys = ld->xl_tx_dmaaddr + | cd->xl_tx_chain[i].xl_phys = ld->xl_tx_ring.dma_baddr + | ||||
i * sizeof(struct xl_list); | i * sizeof(struct xl_list); | ||||
if (i == (XL_TX_LIST_CNT - 1)) | if (i == (XL_TX_LIST_CNT - 1)) | ||||
cd->xl_tx_chain[i].xl_next = NULL; | cd->xl_tx_chain[i].xl_next = NULL; | ||||
else | else | ||||
cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1]; | cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1]; | ||||
} | } | ||||
cd->xl_tx_free = &cd->xl_tx_chain[0]; | cd->xl_tx_free = &cd->xl_tx_chain[0]; | ||||
cd->xl_tx_tail = cd->xl_tx_head = NULL; | cd->xl_tx_tail = cd->xl_tx_head = NULL; | ||||
bus_dmamap_sync(ld->xl_tx_tag, ld->xl_tx_dmamap, BUS_DMASYNC_PREWRITE); | bus_dma_mem_sync(&ld->xl_tx_ring, BUS_DMASYNC_PREWRITE); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Initialize the transmit descriptors. | * Initialize the transmit descriptors. | ||||
*/ | */ | ||||
static int | static int | ||||
xl_list_tx_init_90xB(struct xl_softc *sc) | xl_list_tx_init_90xB(struct xl_softc *sc) | ||||
{ | { | ||||
struct xl_chain_data *cd; | struct xl_chain_data *cd; | ||||
struct xl_list_data *ld; | struct xl_list_data *ld; | ||||
int error, i; | int error, i; | ||||
XL_LOCK_ASSERT(sc); | XL_LOCK_ASSERT(sc); | ||||
cd = &sc->xl_cdata; | cd = &sc->xl_cdata; | ||||
ld = &sc->xl_ldata; | ld = &sc->xl_ldata; | ||||
for (i = 0; i < XL_TX_LIST_CNT; i++) { | 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_ptr = &ld->xl_tx_list[i]; | ||||
error = bus_dmamap_create(sc->xl_mtag, 0, | error = bus_dmamap_create(sc->xl_mtag, 0, | ||||
&cd->xl_tx_chain[i].xl_map); | &cd->xl_tx_chain[i].xl_map); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
cd->xl_tx_chain[i].xl_phys = ld->xl_tx_dmaaddr + | cd->xl_tx_chain[i].xl_phys = ld->xl_tx_ring.dma_baddr + | ||||
i * sizeof(struct xl_list); | i * sizeof(struct xl_list); | ||||
if (i == (XL_TX_LIST_CNT - 1)) | if (i == (XL_TX_LIST_CNT - 1)) | ||||
cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[0]; | cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[0]; | ||||
else | else | ||||
cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1]; | cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1]; | ||||
if (i == 0) | if (i == 0) | ||||
cd->xl_tx_chain[i].xl_prev = | cd->xl_tx_chain[i].xl_prev = | ||||
&cd->xl_tx_chain[XL_TX_LIST_CNT - 1]; | &cd->xl_tx_chain[XL_TX_LIST_CNT - 1]; | ||||
else | else | ||||
cd->xl_tx_chain[i].xl_prev = | cd->xl_tx_chain[i].xl_prev = | ||||
&cd->xl_tx_chain[i - 1]; | &cd->xl_tx_chain[i - 1]; | ||||
} | } | ||||
bzero(ld->xl_tx_list, XL_TX_LIST_SZ); | bzero(ld->xl_tx_list, XL_TX_LIST_SZ); | ||||
ld->xl_tx_list[0].xl_status = htole32(XL_TXSTAT_EMPTY); | ld->xl_tx_list[0].xl_status = htole32(XL_TXSTAT_EMPTY); | ||||
cd->xl_tx_prod = 1; | cd->xl_tx_prod = 1; | ||||
cd->xl_tx_cons = 1; | cd->xl_tx_cons = 1; | ||||
cd->xl_tx_cnt = 0; | cd->xl_tx_cnt = 0; | ||||
bus_dmamap_sync(ld->xl_tx_tag, ld->xl_tx_dmamap, BUS_DMASYNC_PREWRITE); | bus_dma_mem_sync(&ld->xl_tx_ring, BUS_DMASYNC_PREWRITE); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Initialize the RX descriptors and allocate mbufs for them. Note that | * Initialize the RX descriptors and allocate mbufs for them. Note that | ||||
* we arrange the descriptors in a closed ring, so that the last descriptor | * we arrange the descriptors in a closed ring, so that the last descriptor | ||||
* points back to the first. | * points back to the first. | ||||
*/ | */ | ||||
Show All 18 Lines | if (error) | ||||
return (error); | return (error); | ||||
error = xl_newbuf(sc, &cd->xl_rx_chain[i]); | error = xl_newbuf(sc, &cd->xl_rx_chain[i]); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if (i == (XL_RX_LIST_CNT - 1)) | if (i == (XL_RX_LIST_CNT - 1)) | ||||
next = 0; | next = 0; | ||||
else | else | ||||
next = i + 1; | next = i + 1; | ||||
nextptr = ld->xl_rx_dmaaddr + | nextptr = ld->xl_rx_ring.dma_baddr + | ||||
next * sizeof(struct xl_list_onefrag); | next * sizeof(struct xl_list_onefrag); | ||||
cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[next]; | cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[next]; | ||||
ld->xl_rx_list[i].xl_next = htole32(nextptr); | ld->xl_rx_list[i].xl_next = htole32(nextptr); | ||||
} | } | ||||
bus_dmamap_sync(ld->xl_rx_tag, ld->xl_rx_dmamap, BUS_DMASYNC_PREWRITE); | bus_dma_mem_sync(&ld->xl_rx_ring, BUS_DMASYNC_PREWRITE); | ||||
cd->xl_rx_head = &cd->xl_rx_chain[0]; | cd->xl_rx_head = &cd->xl_rx_chain[0]; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Initialize an RX descriptor and attach an MBUF cluster. | * Initialize an RX descriptor and attach an MBUF cluster. | ||||
* If we fail to do so, we need to leave the old mbuf and | * If we fail to do so, we need to leave the old mbuf and | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | xl_rxeof(struct xl_softc *sc) | ||||
struct ifnet *ifp = sc->xl_ifp; | struct ifnet *ifp = sc->xl_ifp; | ||||
struct xl_chain_onefrag *cur_rx; | struct xl_chain_onefrag *cur_rx; | ||||
int total_len; | int total_len; | ||||
int rx_npkts = 0; | int rx_npkts = 0; | ||||
u_int32_t rxstat; | u_int32_t rxstat; | ||||
XL_LOCK_ASSERT(sc); | XL_LOCK_ASSERT(sc); | ||||
again: | again: | ||||
bus_dmamap_sync(sc->xl_ldata.xl_rx_tag, sc->xl_ldata.xl_rx_dmamap, | bus_dma_mem_sync(&sc->xl_ldata.xl_rx_ring, BUS_DMASYNC_POSTREAD); | ||||
BUS_DMASYNC_POSTREAD); | |||||
while ((rxstat = le32toh(sc->xl_cdata.xl_rx_head->xl_ptr->xl_status))) { | while ((rxstat = le32toh(sc->xl_cdata.xl_rx_head->xl_ptr->xl_status))) { | ||||
#ifdef DEVICE_POLLING | #ifdef DEVICE_POLLING | ||||
if (ifp->if_capenable & IFCAP_POLLING) { | if (ifp->if_capenable & IFCAP_POLLING) { | ||||
if (sc->rxcycles <= 0) | if (sc->rxcycles <= 0) | ||||
break; | break; | ||||
sc->rxcycles--; | sc->rxcycles--; | ||||
} | } | ||||
#endif | #endif | ||||
Show All 15 Lines | #endif | ||||
* If an error occurs, update stats, clear the | * If an error occurs, update stats, clear the | ||||
* status word and leave the mbuf cluster in place: | * status word and leave the mbuf cluster in place: | ||||
* it should simply get re-used next time this descriptor | * it should simply get re-used next time this descriptor | ||||
* comes up in the ring. | * comes up in the ring. | ||||
*/ | */ | ||||
if (rxstat & XL_RXSTAT_UP_ERROR) { | if (rxstat & XL_RXSTAT_UP_ERROR) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | ||||
cur_rx->xl_ptr->xl_status = 0; | cur_rx->xl_ptr->xl_status = 0; | ||||
bus_dmamap_sync(sc->xl_ldata.xl_rx_tag, | bus_dma_mem_sync(&sc->xl_ldata.xl_rx_ring, | ||||
sc->xl_ldata.xl_rx_dmamap, BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREWRITE); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* If the error bit was not set, the upload complete | * If the error bit was not set, the upload complete | ||||
* bit should be set which means we have a valid packet. | * bit should be set which means we have a valid packet. | ||||
* If not, something truly strange has happened. | * If not, something truly strange has happened. | ||||
*/ | */ | ||||
if (!(rxstat & XL_RXSTAT_UP_CMPLT)) { | if (!(rxstat & XL_RXSTAT_UP_CMPLT)) { | ||||
device_printf(sc->xl_dev, | device_printf(sc->xl_dev, | ||||
"bad receive status -- packet dropped\n"); | "bad receive status -- packet dropped\n"); | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | ||||
cur_rx->xl_ptr->xl_status = 0; | cur_rx->xl_ptr->xl_status = 0; | ||||
bus_dmamap_sync(sc->xl_ldata.xl_rx_tag, | bus_dma_mem_sync(&sc->xl_ldata.xl_rx_ring, | ||||
sc->xl_ldata.xl_rx_dmamap, BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREWRITE); | ||||
continue; | continue; | ||||
} | } | ||||
/* No errors; receive the packet. */ | /* No errors; receive the packet. */ | ||||
bus_dmamap_sync(sc->xl_mtag, cur_rx->xl_map, | bus_dmamap_sync(sc->xl_mtag, cur_rx->xl_map, | ||||
BUS_DMASYNC_POSTREAD); | BUS_DMASYNC_POSTREAD); | ||||
m = cur_rx->xl_mbuf; | m = cur_rx->xl_mbuf; | ||||
/* | /* | ||||
* Try to conjure up a new mbuf cluster. If that | * Try to conjure up a new mbuf cluster. If that | ||||
* fails, it means we have an out of memory condition and | * fails, it means we have an out of memory condition and | ||||
* should leave the buffer in place and continue. This will | * should leave the buffer in place and continue. This will | ||||
* result in a lost packet, but there's little else we | * result in a lost packet, but there's little else we | ||||
* can do in this situation. | * can do in this situation. | ||||
*/ | */ | ||||
if (xl_newbuf(sc, cur_rx)) { | if (xl_newbuf(sc, cur_rx)) { | ||||
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); | ||||
cur_rx->xl_ptr->xl_status = 0; | cur_rx->xl_ptr->xl_status = 0; | ||||
bus_dmamap_sync(sc->xl_ldata.xl_rx_tag, | bus_dma_mem_sync(&sc->xl_ldata.xl_rx_ring, | ||||
sc->xl_ldata.xl_rx_dmamap, BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREWRITE); | ||||
continue; | continue; | ||||
} | } | ||||
bus_dmamap_sync(sc->xl_ldata.xl_rx_tag, | bus_dma_mem_sync(&sc->xl_ldata.xl_rx_ring, | ||||
sc->xl_ldata.xl_rx_dmamap, BUS_DMASYNC_PREWRITE); | BUS_DMASYNC_PREWRITE); | ||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); | ||||
m->m_pkthdr.rcvif = ifp; | m->m_pkthdr.rcvif = ifp; | ||||
m->m_pkthdr.len = m->m_len = total_len; | m->m_pkthdr.len = m->m_len = total_len; | ||||
if (ifp->if_capenable & IFCAP_RXCSUM) { | if (ifp->if_capenable & IFCAP_RXCSUM) { | ||||
/* Do IP checksum checking. */ | /* Do IP checksum checking. */ | ||||
if (rxstat & XL_RXSTAT_IPCKOK) | if (rxstat & XL_RXSTAT_IPCKOK) | ||||
Show All 34 Lines | #endif | ||||
* you need to reload the ring pointer. Here we have to | * you need to reload the ring pointer. Here we have to | ||||
* fake it. I'm mad at myself for not being clever enough | * fake it. I'm mad at myself for not being clever enough | ||||
* to avoid the use of a goto here. | * to avoid the use of a goto here. | ||||
*/ | */ | ||||
if (CSR_READ_4(sc, XL_UPLIST_PTR) == 0 || | if (CSR_READ_4(sc, XL_UPLIST_PTR) == 0 || | ||||
CSR_READ_4(sc, XL_UPLIST_STATUS) & XL_PKTSTAT_UP_STALLED) { | CSR_READ_4(sc, XL_UPLIST_STATUS) & XL_PKTSTAT_UP_STALLED) { | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); | ||||
xl_wait(sc); | xl_wait(sc); | ||||
CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->xl_ldata.xl_rx_dmaaddr); | CSR_WRITE_4(sc, XL_UPLIST_PTR, | ||||
sc->xl_ldata.xl_rx_ring.dma_baddr); | |||||
sc->xl_cdata.xl_rx_head = &sc->xl_cdata.xl_rx_chain[0]; | sc->xl_cdata.xl_rx_head = &sc->xl_cdata.xl_rx_chain[0]; | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); | ||||
goto again; | goto again; | ||||
} | } | ||||
return (rx_npkts); | return (rx_npkts); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
xl_txeof_90xB(struct xl_softc *sc) | xl_txeof_90xB(struct xl_softc *sc) | ||||
{ | { | ||||
struct xl_chain *cur_tx = NULL; | struct xl_chain *cur_tx = NULL; | ||||
struct ifnet *ifp = sc->xl_ifp; | struct ifnet *ifp = sc->xl_ifp; | ||||
int idx; | int idx; | ||||
XL_LOCK_ASSERT(sc); | XL_LOCK_ASSERT(sc); | ||||
bus_dmamap_sync(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_dmamap, | bus_dma_mem_sync(&sc->xl_ldata.xl_tx_ring, BUS_DMASYNC_POSTREAD); | ||||
BUS_DMASYNC_POSTREAD); | |||||
idx = sc->xl_cdata.xl_tx_cons; | idx = sc->xl_cdata.xl_tx_cons; | ||||
while (idx != sc->xl_cdata.xl_tx_prod) { | while (idx != sc->xl_cdata.xl_tx_prod) { | ||||
cur_tx = &sc->xl_cdata.xl_tx_chain[idx]; | cur_tx = &sc->xl_cdata.xl_tx_chain[idx]; | ||||
if (!(le32toh(cur_tx->xl_ptr->xl_status) & | if (!(le32toh(cur_tx->xl_ptr->xl_status) & | ||||
XL_TXSTAT_DL_COMPLETE)) | XL_TXSTAT_DL_COMPLETE)) | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 483 Lines • ▼ Show 20 Lines | sc->xl_cdata.xl_tx_tail->xl_ptr->xl_next = | ||||
htole32(start_tx->xl_phys); | htole32(start_tx->xl_phys); | ||||
sc->xl_cdata.xl_tx_tail->xl_ptr->xl_status &= | sc->xl_cdata.xl_tx_tail->xl_ptr->xl_status &= | ||||
htole32(~XL_TXSTAT_DL_INTR); | htole32(~XL_TXSTAT_DL_INTR); | ||||
sc->xl_cdata.xl_tx_tail = cur_tx; | sc->xl_cdata.xl_tx_tail = cur_tx; | ||||
} else { | } else { | ||||
sc->xl_cdata.xl_tx_head = start_tx; | sc->xl_cdata.xl_tx_head = start_tx; | ||||
sc->xl_cdata.xl_tx_tail = cur_tx; | sc->xl_cdata.xl_tx_tail = cur_tx; | ||||
} | } | ||||
bus_dmamap_sync(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_dmamap, | bus_dma_mem_sync(&sc->xl_ldata.xl_tx_ring, BUS_DMASYNC_PREWRITE); | ||||
BUS_DMASYNC_PREWRITE); | |||||
if (!CSR_READ_4(sc, XL_DOWNLIST_PTR)) | if (!CSR_READ_4(sc, XL_DOWNLIST_PTR)) | ||||
CSR_WRITE_4(sc, XL_DOWNLIST_PTR, start_tx->xl_phys); | CSR_WRITE_4(sc, XL_DOWNLIST_PTR, start_tx->xl_phys); | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL); | ||||
XL_SEL_WIN(7); | XL_SEL_WIN(7); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | xl_start_90xB_locked(struct ifnet *ifp) | ||||
* get an interrupt once for the whole chain rather than | * get an interrupt once for the whole chain rather than | ||||
* once for each packet. | * once for each packet. | ||||
*/ | */ | ||||
cur_tx->xl_ptr->xl_status |= htole32(XL_TXSTAT_DL_INTR); | cur_tx->xl_ptr->xl_status |= htole32(XL_TXSTAT_DL_INTR); | ||||
/* Start transmission */ | /* Start transmission */ | ||||
sc->xl_cdata.xl_tx_prod = idx; | sc->xl_cdata.xl_tx_prod = idx; | ||||
start_tx->xl_prev->xl_ptr->xl_next = htole32(start_tx->xl_phys); | start_tx->xl_prev->xl_ptr->xl_next = htole32(start_tx->xl_phys); | ||||
bus_dmamap_sync(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_dmamap, | bus_dma_mem_sync(&sc->xl_ldata.xl_tx_ring, BUS_DMASYNC_PREWRITE); | ||||
BUS_DMASYNC_PREWRITE); | |||||
/* | /* | ||||
* Set a timeout in case the chip goes out to lunch. | * Set a timeout in case the chip goes out to lunch. | ||||
*/ | */ | ||||
sc->xl_wdog_timer = 5; | sc->xl_wdog_timer = 5; | ||||
} | } | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | #endif | ||||
* we're finished. We also have to wait for the | * we're finished. We also have to wait for the | ||||
* stall command to complete before proceeding. | * stall command to complete before proceeding. | ||||
* Note that we have to do this after any RX resets | * Note that we have to do this after any RX resets | ||||
* have completed since the uplist register is cleared | * have completed since the uplist register is cleared | ||||
* by a reset. | * by a reset. | ||||
*/ | */ | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL); | ||||
xl_wait(sc); | xl_wait(sc); | ||||
CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->xl_ldata.xl_rx_dmaaddr); | CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->xl_ldata.xl_rx_ring.dma_baddr); | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL); | ||||
xl_wait(sc); | xl_wait(sc); | ||||
if (sc->xl_type == XL_TYPE_905B) { | if (sc->xl_type == XL_TYPE_905B) { | ||||
/* Set polling interval */ | /* Set polling interval */ | ||||
CSR_WRITE_1(sc, XL_DOWN_POLL, 64); | CSR_WRITE_1(sc, XL_DOWN_POLL, 64); | ||||
/* Load the address of the TX list */ | /* Load the address of the TX list */ | ||||
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL); | CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL); | ||||
▲ Show 20 Lines • Show All 498 Lines • Show Last 20 Lines |