diff options
-rw-r--r-- | sys/dev/pci/if_vic.c | 999 | ||||
-rw-r--r-- | sys/dev/pci/if_vicreg.h | 80 | ||||
-rw-r--r-- | sys/dev/pci/if_vicvar.h | 108 |
3 files changed, 595 insertions, 592 deletions
diff --git a/sys/dev/pci/if_vic.c b/sys/dev/pci/if_vic.c index f3eab35f9c8..18719bab8ff 100644 --- a/sys/dev/pci/if_vic.c +++ b/sys/dev/pci/if_vic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vic.c,v 1.9 2006/05/31 06:46:12 brad Exp $ */ +/* $OpenBSD: if_vic.c,v 1.10 2006/10/31 06:04:15 dlg Exp $ */ /* * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> @@ -23,11 +23,11 @@ #include "bpfilter.h" #include <sys/param.h> +#include <sys/systm.h> #include <sys/sockio.h> #include <sys/mbuf.h> #include <sys/kernel.h> #include <sys/socket.h> -#include <sys/systm.h> #include <sys/malloc.h> #include <sys/timeout.h> #include <sys/device.h> @@ -54,43 +54,134 @@ #include <dev/pci/pcidevs.h> #include <dev/pci/if_vicreg.h> -#include <dev/pci/if_vicvar.h> - -int vic_match(struct device *, void *, void *); -void vic_attach(struct device *, struct device *, void *); -void vic_link_state(struct vic_softc *); -void vic_shutdown(void *); -int vic_intr(void *); -void vic_rx_proc(struct vic_softc *); -void vic_tx_proc(struct vic_softc *); -void vic_iff(struct vic_softc *, u_int); -void vic_getlladdr(struct vic_softc *); -void vic_setlladdr(struct vic_softc *); -int vic_media_change(struct ifnet *); -void vic_media_status(struct ifnet *, struct ifmediareq *); -void vic_start(struct ifnet *); -int vic_tx_start(struct vic_softc *, struct mbuf *); -void vic_watchdog(struct ifnet *); -int vic_ioctl(struct ifnet *, u_long, caddr_t); -void vic_init(struct ifnet *); -void vic_stop(struct ifnet *); -void vic_printb(unsigned short, char *); -void vic_timer(void *); -void vic_poll(void *); /* XXX poll */ -struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t); -int vic_alloc_data(struct vic_softc *); -void vic_reset_data(struct vic_softc *); -void vic_free_data(struct vic_softc *); +#ifdef VIC_DEBUG +int vic_debug = 0; +#define DPRINTF(x...) do { if (vic_debug) printf(x); } while (0) +#else +#define DPRINTF(x...) +#endif -struct cfattach vic_ca = { - sizeof(struct vic_softc), vic_match, vic_attach +#define VIC_PCI_BAR PCI_MAPREG_START /* Base Address Register */ + +#define VIC_NBUF 100 +#define VIC_NBUF_MAX 128 +#define VIC_MAX_SCATTER 1 /* 8? */ +#define VIC_QUEUE_SIZE VIC_NBUF_MAX +#define VIC_QUEUE2_SIZE 1 +#define VIC_INC(_x, _y) (_x) = ((_x) + 1) % (_y) +#define VIC_INC_POS(_x, _y) (_x) = (++(_x)) % (_y) ? (_x) : 1 +#define VIC_TX_TIMEOUT 5 +#define VIC_TIMER_DELAY 2 +#define VIC_TIMER_MS(_ms) (_ms * hz / 1000) + +#define VIC_TXURN_WARN(_sc) ((_sc)->sc_txpending >= ((_sc)->sc_ntxbuf - 5)) +#define VIC_TXURN(_sc) ((_sc)->sc_txpending >= (_sc)->sc_ntxbuf) +#define VIC_OFF_TXDESC(_n) \ + (sizeof(struct vic_data) + \ + ((sc->sc_nrxbuf + VIC_QUEUE2_SIZE) * sizeof(struct vic_rxdesc)) + \ + ((_n) * sizeof(struct vic_txdesc))) + +struct vic_rxbuf { + bus_dmamap_t rxb_dmamap; + struct mbuf *rxb_m; +}; + +struct vic_txbuf { + bus_dmamap_t txb_dmamap; + struct mbuf *txb_m; +}; + +struct vic_softc { + struct device sc_dev; + + pci_chipset_tag_t sc_pc; + pcitag_t sc_tag; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_size_t sc_ios; + bus_dma_tag_t sc_dmat; + + void *sc_ih; + + struct arpcom sc_ac; + struct ifmedia sc_media; + + u_int32_t sc_nrxbuf; + u_int32_t sc_ntxbuf; + u_int32_t sc_cap; + u_int32_t sc_feature; + u_int8_t sc_lladdr[ETHER_ADDR_LEN]; + + bus_dmamap_t sc_dma_map; + bus_dma_segment_t sc_dma_seg; + size_t sc_dma_size; + caddr_t sc_dma_kva; +#define VIC_DMA_DVA(_sc) ((_sc)->sc_dma_map->dm_segs[0].ds_addr) +#define VIC_DMA_KVA(_sc) ((void *)(_sc)->sc_dma_kva) + + struct vic_data *sc_data; + + struct vic_rxbuf *sc_rxbuf; + struct vic_rxdesc *sc_rxq; + struct vic_rxdesc *sc_rxq2; + + struct vic_txbuf *sc_txbuf; + struct vic_txdesc *sc_txq; + volatile u_int sc_txpending; }; struct cfdriver vic_cd = { 0, "vic", DV_IFNET }; +int vic_match(struct device *, void *, void *); +void vic_attach(struct device *, struct device *, void *); + +struct cfattach vic_ca = { + sizeof(struct vic_softc), vic_match, vic_attach +}; + +int vic_intr(void *); +void vic_shutdown(void *); + +int vic_map_pci(struct vic_softc *, struct pci_attach_args *); +int vic_query(struct vic_softc *); +int vic_alloc_data(struct vic_softc *); +int vic_init_data(struct vic_softc *sc); + +u_int32_t vic_read(struct vic_softc *, bus_size_t); +void vic_write(struct vic_softc *, bus_size_t, u_int32_t); + +u_int32_t vic_read_cmd(struct vic_softc *, u_int32_t); + +int vic_alloc_dmamem(struct vic_softc *); +void vic_free_dmamem(struct vic_softc *); + +void vic_link_state(struct vic_softc *); +void vic_rx_proc(struct vic_softc *); +void vic_tx_proc(struct vic_softc *); +void vic_iff(struct vic_softc *, u_int); +void vic_getlladdr(struct vic_softc *); +void vic_setlladdr(struct vic_softc *); +int vic_media_change(struct ifnet *); +void vic_media_status(struct ifnet *, struct ifmediareq *); +void vic_start(struct ifnet *); +int vic_encap(struct vic_softc *, struct mbuf *); +void vic_watchdog(struct ifnet *); +int vic_ioctl(struct ifnet *, u_long, caddr_t); +void vic_init(struct ifnet *); +void vic_stop(struct ifnet *); +void vic_timer(void *); + +#define DEVNAME(_s) ((_s)->sc_dev.dv_xname) + +struct mbuf *vic_alloc_mbuf(struct vic_softc *, bus_dmamap_t); +int vic_alloc_data(struct vic_softc *); +void vic_reset_data(struct vic_softc *); +void vic_free_data(struct vic_softc *); + const struct pci_matchid vic_devices[] = { { PCI_VENDOR_VMWARE, PCI_PRODUCT_VMWARE_NET } }; @@ -107,82 +198,30 @@ vic_match(struct device *parent, void *match, void *aux) void vic_attach(struct device *parent, struct device *self, void *aux) { - struct vic_softc *sc = (struct vic_softc *)self; - struct pci_attach_args *pa = aux; - pci_chipset_tag_t pc = pa->pa_pc; - pci_intr_handle_t ih; - const char *intrstr = NULL; - bus_size_t size; - struct ifnet *ifp; - - /* Enable I/O mapping */ - if (pci_mapreg_map(pa, VIC_BAR0, PCI_MAPREG_TYPE_IO, 0, - &sc->sc_st, &sc->sc_sh, NULL, &size, 0)) { - printf(": I/O mapping of register space failed\n"); - return; - } + struct vic_softc *sc = (struct vic_softc *)self; + struct pci_attach_args *pa = aux; + struct ifnet *ifp; - /* Map and enable the interrupt line */ - if (pci_intr_map(pa, &ih)) { - printf(": interrupt mapping failed\n"); - goto fail_1; + if (vic_map_pci(sc, pa) != 0) { + /* error printed by vic_map_pci */ + return; } - intrstr = pci_intr_string(pc, ih); - - sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, vic_intr, sc, - sc->sc_dev.dv_xname); - if (sc->sc_ih == NULL) { - printf(": couldn't establish interrupt"); - if (intrstr != NULL) - printf(" at %s", intrstr); - printf("\n"); - goto fail_1; + if (vic_query(sc) != 0) { + /* error printed by vic_query */ + return; } - printf(": %s\n", intrstr); - - sc->sc_dmat = pa->pa_dmat; - - sc->sc_ver_major = VIC_READ(VIC_VERSION_MAJOR); - sc->sc_ver_minor = VIC_READ(VIC_VERSION_MINOR); - - printf("%s: vmxnet %X", sc->sc_dev.dv_xname, - sc->sc_ver_major & ~VIC_VERSION_MAJOR_M); - - /* Check for a supported version */ - if (((sc->sc_ver_major & VIC_VERSION_MAJOR_M) != - (VIC_MAGIC & VIC_VERSION_MAJOR_M)) || - VIC_MAGIC > sc->sc_ver_major || - VIC_MAGIC < sc->sc_ver_minor) { - printf(" unsupported device\n"); - goto fail_2; + if (vic_alloc_data(sc) != 0) { + /* error printed by vic_alloc */ + return; } - VIC_WRITE(VIC_CMD, VIC_CMD_NUM_Rx_BUF); - sc->sc_nrxbuf = VIC_READ(VIC_CMD); - if (sc->sc_nrxbuf > VIC_NBUF_MAX || sc->sc_nrxbuf == 0) - sc->sc_nrxbuf = VIC_NBUF; - - VIC_WRITE(VIC_CMD, VIC_CMD_NUM_Tx_BUF); - sc->sc_ntxbuf = VIC_READ(VIC_CMD); - if (sc->sc_ntxbuf > VIC_NBUF_MAX || sc->sc_ntxbuf == 0) - sc->sc_ntxbuf = VIC_NBUF; - - VIC_WRITE(VIC_CMD, VIC_CMD_FEATURE); - sc->sc_feature = VIC_READ(VIC_CMD); - - VIC_WRITE(VIC_CMD, VIC_CMD_HWCAP); - sc->sc_cap = VIC_READ(VIC_CMD); - if (sc->sc_cap) { - printf(", "); - vic_printb(sc->sc_cap, VIC_CMD_HWCAP_BITS); + if (vic_init_data(sc) != 0) { + /* error printed by vic_alloc */ + return; } - printf("\n"); - - vic_getlladdr(sc); - bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); ifp = &sc->sc_ac.ac_if; @@ -192,7 +231,7 @@ vic_attach(struct device *parent, struct device *self, void *aux) ifp->if_start = vic_start; ifp->if_watchdog = vic_watchdog; ifp->if_hardmtu = VIC_JUMBO_MTU; - strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); + strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); @@ -207,14 +246,6 @@ vic_attach(struct device *parent, struct device *self, void *aux) IFCAP_CSUM_UDPv4; #endif - /* Allocate Rx and Tx queues */ - if (vic_alloc_data(sc) != 0) { - printf(": could not allocate queues\n"); - goto fail_2; - } - - printf(", address %s\n", ether_sprintf(sc->sc_lladdr)); - /* Initialise pseudo media types */ ifmedia_init(&sc->sc_media, 0, vic_media_change, vic_media_status); ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); @@ -224,20 +255,233 @@ vic_attach(struct device *parent, struct device *self, void *aux) if_attach(ifp); ether_ifattach(ifp); - sc->sc_sdhook = shutdownhook_establish(vic_shutdown, sc); + return; +} + +int +vic_map_pci(struct vic_softc *sc, struct pci_attach_args *pa) +{ + pcireg_t memtype; + pci_intr_handle_t ih; + const char *intrstr; + + sc->sc_pc = pa->pa_pc; + sc->sc_tag = pa->pa_tag; + sc->sc_dmat = pa->pa_dmat; - /* Initialize timeout for link state update. */ - timeout_set(&sc->sc_timer, vic_timer, sc); + memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, VIC_PCI_BAR); + if (pci_mapreg_map(pa, VIC_PCI_BAR, memtype, 0, &sc->sc_iot, + &sc->sc_ioh, NULL, &sc->sc_ios, 0) != 0) { + printf(": unable to map system interface register\n"); + return(1); + } + + if (pci_intr_map(pa, &ih) != 0) { + printf(": unable to map interrupt\n"); + goto unmap; + } + intrstr = pci_intr_string(pa->pa_pc, ih); + sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, + vic_intr, sc, DEVNAME(sc)); + if (sc->sc_ih == NULL) { + printf(": unable to map interrupt%s%s\n", + intrstr == NULL ? "" : " at ", + intrstr == NULL ? "" : intrstr); + goto unmap; + } + printf(": %s\n", intrstr); + + return (0); + +unmap: + bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); + sc->sc_ios = 0; + return (1); +} - /* XXX poll */ - timeout_set(&sc->sc_poll, vic_poll, sc); - return; +int +vic_query(struct vic_softc *sc) +{ + u_int32_t major, minor; -fail_2: - pci_intr_disestablish(pc, sc->sc_ih); + major = vic_read(sc, VIC_VERSION_MAJOR); + minor = vic_read(sc, VIC_VERSION_MINOR); -fail_1: - bus_space_unmap(sc->sc_st, sc->sc_sh, size); + /* Check for a supported version */ + if ((major & VIC_VERSION_MAJOR_M) != + (VIC_MAGIC & VIC_VERSION_MAJOR_M)) { + printf("%s: magic mismatch\n", DEVNAME(sc)); + return (1); + } + + if (VIC_MAGIC > major || VIC_MAGIC < minor) { + printf("%s: unsupported version (%X)\n", DEVNAME(sc), + major & ~VIC_VERSION_MAJOR_M); + return (1); + } + + sc->sc_nrxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Rx_BUF); + if (sc->sc_nrxbuf > VIC_NBUF_MAX || sc->sc_nrxbuf == 0) + sc->sc_nrxbuf = VIC_NBUF; + + sc->sc_ntxbuf = vic_read_cmd(sc, VIC_CMD_NUM_Tx_BUF); + if (sc->sc_ntxbuf > VIC_NBUF_MAX || sc->sc_ntxbuf == 0) + sc->sc_ntxbuf = VIC_NBUF; + + sc->sc_feature = vic_read_cmd(sc, VIC_CMD_FEATURE); + sc->sc_cap = vic_read_cmd(sc, VIC_CMD_HWCAP); + + vic_getlladdr(sc); + + printf("%s: VMXnet %04X, address %s\n", DEVNAME(sc), + major & ~VIC_VERSION_MAJOR_M, ether_sprintf(sc->sc_lladdr)); + + return (0); +} + +int +vic_alloc_data(struct vic_softc *sc) +{ + sc->sc_rxbuf = malloc(sizeof(struct vic_rxbuf) * sc->sc_nrxbuf, + M_NOWAIT, M_DEVBUF); + if (sc->sc_rxbuf == NULL) { + printf("%s: unable to allocate rxbuf\n", DEVNAME(sc)); + goto err; + } + + sc->sc_txbuf = malloc(sizeof(struct vic_txbuf) * sc->sc_ntxbuf, + M_NOWAIT, M_DEVBUF); + if (sc->sc_txbuf == NULL) { + printf("%s: unable to allocate txbuf\n", DEVNAME(sc)); + goto freerx; + } + + sc->sc_dma_size = sizeof(struct vic_data) + + (sc->sc_nrxbuf + VIC_QUEUE2_SIZE) * sizeof(struct vic_rxdesc) + + sc->sc_ntxbuf * sizeof(struct vic_txdesc); + + if (vic_alloc_dmamem(sc) != 0) { + printf("%s: unable to allocate dma region\n", DEVNAME(sc)); + goto freetx; + } + + return (0); +freetx: + free(sc->sc_txbuf, M_DEVBUF); +freerx: + free(sc->sc_rxbuf, M_DEVBUF); +err: + return (1); +} + +int +vic_init_data(struct vic_softc *sc) +{ + u_int8_t *kva = VIC_DMA_KVA(sc); + u_int offset; + + struct vic_rxbuf *rxb; + struct vic_rxdesc *rxd; + struct vic_txbuf *txb; + + int i; + + /* set up basic vic data */ + sc->sc_data = VIC_DMA_KVA(sc); + + sc->sc_data->vd_magic = VIC_MAGIC; + sc->sc_data->vd_length = sc->sc_dma_size; + + offset = sizeof(struct vic_data); + + /* set up the rx ring */ + sc->sc_rxq = (struct vic_rxdesc *)&kva[offset]; + + sc->sc_data->vd_rx_offset = offset; + sc->sc_data->vd_rx_length = sc->sc_nrxbuf; + + for (i = 0; i < sc->sc_nrxbuf; i++) { + rxb = &sc->sc_rxbuf[i]; + rxd = &sc->sc_rxq[i]; + + if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, + MCLBYTES, 0, BUS_DMA_NOWAIT, &rxb->rxb_dmamap) != 0) { + printf("%s: unable to create dmamap for rxb %d\n", + DEVNAME(sc), i); + goto freerxbs; + } + + rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap); + if (rxb->rxb_m == NULL) { + /* error already printed */ + bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); + goto freerxbs; + } + + bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0, + rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD); + + rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr; + rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len; /* XXX? */ + rxd->rx_length = 0; + rxd->rx_owner = VIC_OWNER_NIC; + + offset += sizeof(struct vic_rxdesc); + } + + /* set up the dummy rx ring 2 with an unusable entry */ + sc->sc_rxq2 = (struct vic_rxdesc *)&kva[offset]; + + sc->sc_data->vd_rx_offset2 = offset; + sc->sc_data->vd_rx_length2 = VIC_QUEUE2_SIZE; + + for (i = 0; i < VIC_QUEUE2_SIZE; i++) { + rxd = &sc->sc_rxq2[i]; + + rxd->rx_physaddr = 0; + rxd->rx_buflength = 0; + rxd->rx_length = 0; + rxd->rx_owner = VIC_OWNER_DRIVER; + + offset += sizeof(struct vic_rxdesc); + } + + /* set up the tx ring */ + sc->sc_txq = (struct vic_txdesc *)&kva[offset]; + + sc->sc_data->vd_tx_offset = offset; + sc->sc_data->vd_tx_length = sc->sc_ntxbuf; + + for (i = 0; i < sc->sc_ntxbuf; i++) { + txb = &sc->sc_txbuf[i]; + if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1 /* XXX 6 */, + MCLBYTES, 0, BUS_DMA_NOWAIT, &txb->txb_dmamap) != 0) { + printf("%s: unable to create dmamap for tx %d\n", + DEVNAME(sc), i); + goto freetxbs; + } + txb->txb_m = NULL; + } + + return (0); + +freetxbs: + while (i--) { + txb = &sc->sc_txbuf[i]; + bus_dmamap_destroy(sc->sc_dmat, txb->txb_dmamap); + } + + i = sc->sc_nrxbuf; +freerxbs: + while (i--) { + rxb = &sc->sc_rxbuf[i]; + bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0, + rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap); + bus_dmamap_destroy(sc->sc_dmat, rxb->rxb_dmamap); + } + + return (1); } void @@ -247,7 +491,7 @@ vic_link_state(struct vic_softc *sc) u_int32_t status; int link_state = LINK_STATE_DOWN; - status = VIC_READ(VIC_STATUS); + status = vic_read(sc, VIC_STATUS); if (status & VIC_STATUS_CONNECTED) link_state = LINK_STATE_UP; if (ifp->if_link_state != link_state) { @@ -268,14 +512,8 @@ int vic_intr(void *arg) { struct vic_softc *sc = (struct vic_softc *)arg; - struct ifnet *ifp = &sc->sc_ac.ac_if; - VIC_WRITE(VIC_CMD, VIC_CMD_INTR_ACK); - -#ifdef VIC_DEBUG - if (ifp->if_flags & IFF_DEBUG) - printf("%s: %s\n", sc->sc_dev.dv_xname, __func__); -#endif + vic_write(sc, VIC_CMD, VIC_CMD_INTR_ACK); vic_rx_proc(sc); vic_tx_proc(sc); @@ -286,18 +524,17 @@ vic_intr(void *arg) void vic_rx_proc(struct vic_softc *sc) { - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct vic_rxdesc *desc; - struct vic_rxbuf *rxb; - struct mbuf *m; - int len, idx; + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct vic_rxdesc *rxd; + struct vic_rxbuf *rxb; + struct mbuf *m; + int len, idx; - for (;;) { - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, - sizeof(struct vic_data), - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - idx = letoh32(sc->sc_data->vd_rx_nextidx); + for (;;) { + idx = sc->sc_data->vd_rx_nextidx; if (idx >= sc->sc_data->vd_rx_length) { ifp->if_ierrors++; if (ifp->if_flags & IFF_DEBUG) @@ -306,46 +543,43 @@ vic_rx_proc(struct vic_softc *sc) break; } - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, - VIC_OFF_RXDESC(idx), sizeof(struct vic_rxdesc), - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - desc = &sc->sc_rxq[idx]; - - if (desc->rx_owner != VIC_OWNER_DRIVER) + rxd = &sc->sc_rxq[idx]; + if (rxd->rx_owner != VIC_OWNER_DRIVER) break; - len = letoh32(desc->rx_length); + rxb = &sc->sc_rxbuf[idx]; + + len = rxd->rx_length; if (len < ETHER_MIN_LEN) { ifp->if_iqdrops++; goto nextp; } - if ((rxb = (struct vic_rxbuf *)desc->rx_priv) == NULL || - rxb->rxb_m == NULL) { + if (rxb->rxb_m == NULL) { ifp->if_ierrors++; - if (ifp->if_flags & IFF_DEBUG) - printf("%s: receive buffer error\n", - sc->sc_dev.dv_xname); + printf("%s: rxb %d has no mbuf\n", DEVNAME(sc), idx); break; } - bus_dmamap_sync(sc->sc_dmat, rxb->rxb_map, 0, - rxb->rxb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, rxb->rxb_map); + bus_dmamap_sync(sc->sc_dmat, rxb->rxb_dmamap, 0, + rxb->rxb_m->m_pkthdr.len, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->sc_dmat, rxb->rxb_dmamap); + m = rxb->rxb_m; rxb->rxb_m = NULL; m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = m->m_len = len; /* Get new mbuf for the Rx queue */ - if ((rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_map)) == NULL) { + rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_dmamap); + if (rxb->rxb_m == NULL) { ifp->if_ierrors++; - if (ifp->if_flags & IFF_DEBUG) - printf("%s: receive buffer failed\n", - sc->sc_dev.dv_xname); + printf("%s: mbuf alloc failed\n", DEVNAME(sc)); break; } - desc->rx_physaddr = rxb->rxb_map->dm_segs->ds_addr; + rxd->rx_physaddr = rxb->rxb_dmamap->dm_segs[0].ds_addr; + rxd->rx_buflength = rxb->rxb_m->m_pkthdr.len; + rxd->rx_length = 0; ifp->if_ipackets++; @@ -356,26 +590,28 @@ vic_rx_proc(struct vic_softc *sc) ether_input_mbuf(ifp, m); - nextp: - desc->rx_owner = VIC_OWNER_NIC; +nextp: + rxd->rx_owner = VIC_OWNER_NIC; VIC_INC(sc->sc_data->vd_rx_nextidx, sc->sc_data->vd_rx_length); } + + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } void vic_tx_proc(struct vic_softc *sc) { - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct vic_txdesc *desc; - struct vic_txbuf *txb; - int idx; + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct vic_txdesc *txd; + struct vic_txbuf *txb; + int idx; - for (; sc->sc_txpending;) { - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, - sizeof(struct vic_data), - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - idx = letoh32(sc->sc_data->vd_tx_curidx); + while (sc->sc_txpending > 0) { + idx = sc->sc_data->vd_tx_curidx; if (idx >= sc->sc_data->vd_tx_length) { ifp->if_oerrors++; if (ifp->if_flags & IFF_DEBUG) @@ -384,31 +620,26 @@ vic_tx_proc(struct vic_softc *sc) break; } - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, - VIC_OFF_TXDESC(idx), sizeof(struct vic_rxdesc), - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - desc = &sc->sc_txq[idx]; - - if (desc->tx_owner != VIC_OWNER_DRIVER) + txd = &sc->sc_txq[idx]; + if (txd->tx_owner != VIC_OWNER_DRIVER) break; - if ((txb = (struct vic_txbuf *)desc->tx_priv) == NULL || - txb->txb_m == NULL) { + txb = &sc->sc_txbuf[idx]; + + if (txb->txb_m == NULL) { ifp->if_oerrors++; if (ifp->if_flags & IFF_DEBUG) printf("%s: transmit buffer error\n", - sc->sc_dev.dv_xname); + DEVNAME(sc)); break; } - bus_dmamap_sync(sc->sc_dmat, txb->txb_map, 0, - txb->txb_map->dm_mapsize, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->sc_dmat, txb->txb_map); - if (txb->txb_m != NULL) { - m_freem(txb->txb_m); - txb->txb_m = NULL; - ifp->if_flags &= ~IFF_OACTIVE; - } + /* XXX bus dma sync */ + bus_dmamap_unload(sc->sc_dmat, txb->txb_dmamap); + + m_freem(txb->txb_m); + txb->txb_m = NULL; + ifp->if_flags &= ~IFF_OACTIVE; sc->sc_txpending--; sc->sc_data->vd_tx_stopped = 0; @@ -416,8 +647,8 @@ vic_tx_proc(struct vic_softc *sc) VIC_INC(sc->sc_data->vd_tx_curidx, sc->sc_data->vd_tx_length); } - sc->sc_txtimeout = 0; - ifp->if_flags &= ~IFF_OACTIVE; + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); if (!IFQ_IS_EMPTY(&ifp->if_snd)) vic_start(ifp); @@ -431,23 +662,27 @@ vic_iff(struct vic_softc *sc, u_int flags) sizeof(sc->sc_data->vd_mcastfil)); sc->sc_data->vd_iff = flags; +/* bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, sizeof(struct vic_data), BUS_DMASYNC_POSTWRITE); +*/ - VIC_WRITE(VIC_CMD, VIC_CMD_MCASTFIL); - VIC_WRITE(VIC_CMD, VIC_CMD_IFF); + vic_write(sc, VIC_CMD, VIC_CMD_MCASTFIL); + vic_write(sc, VIC_CMD, VIC_CMD_IFF); } void vic_getlladdr(struct vic_softc *sc) { u_int32_t reg; - int i; /* Get MAC address */ - reg = sc->sc_cap & VIC_CMD_HWCAP_VPROM ? VIC_VPROM : VIC_LLADDR; - for (i = 0; i < ETHER_ADDR_LEN; i++) - sc->sc_lladdr[i] = VIC_READ8(reg + i); + reg = (sc->sc_cap & VIC_CMD_HWCAP_VPROM) ? VIC_VPROM : VIC_LLADDR; + + bus_space_barrier(sc->sc_iot, sc->sc_ioh, reg, ETHER_ADDR_LEN, + BUS_SPACE_BARRIER_READ); + bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, reg, sc->sc_lladdr, + ETHER_ADDR_LEN); /* Update the MAC address register */ if (reg == VIC_VPROM) @@ -457,10 +692,10 @@ vic_getlladdr(struct vic_softc *sc) void vic_setlladdr(struct vic_softc *sc) { - int i; - - for (i = 0; i < ETHER_ADDR_LEN; i++) - VIC_WRITE8(VIC_LLADDR + i, sc->sc_lladdr[i]); + bus_space_barrier(sc->sc_iot, sc->sc_ioh, VIC_LLADDR, ETHER_ADDR_LEN, + BUS_SPACE_BARRIER_READ); + bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, VIC_LLADDR, + sc->sc_lladdr, ETHER_ADDR_LEN); } int @@ -488,74 +723,59 @@ vic_media_status(struct ifnet *ifp, struct ifmediareq *imr) void vic_start(struct ifnet *ifp) { - struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; - struct mbuf *m; - int error; + struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; + struct mbuf *m; if (ifp->if_flags & IFF_OACTIVE) return; - for (;; error = 0) { + for (;;) { IFQ_POLL(&ifp->if_snd, m); if (m == NULL) break; -#if NBPFILTER > 0 - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); -#endif - - if ((error = vic_tx_start(sc, m)) != 0) - ifp->if_oerrors++; + if (vic_encap(sc, m) != 0) { + printf("%s: encap err\n", DEVNAME(sc)); + break; + } } } int -vic_tx_start(struct vic_softc *sc, struct mbuf *m) +vic_encap(struct vic_softc *sc, struct mbuf *m) { - struct ifnet *ifp = &sc->sc_ac.ac_if; - struct vic_txbuf *txb; - struct vic_txdesc *desc; - struct mbuf *m0 = NULL; - int idx; + struct ifnet *ifp = &sc->sc_ac.ac_if; + struct vic_txbuf *txb; + struct vic_txdesc *txd; + struct mbuf *m0 = NULL; + int idx; - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, - sizeof(struct vic_data), + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - idx = letoh32(sc->sc_data->vd_tx_nextidx); + idx = sc->sc_data->vd_tx_nextidx; if (idx >= sc->sc_data->vd_tx_length) { ifp->if_oerrors++; if (ifp->if_flags & IFF_DEBUG) - printf("%s: transmit index error\n", - sc->sc_dev.dv_xname); + printf("%s: transmit index error\n", DEVNAME(sc)); return (EINVAL); } - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, - VIC_OFF_TXDESC(idx), sizeof(struct vic_txdesc), - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - - desc = &sc->sc_txq[idx]; - txb = (struct vic_txbuf *)desc->tx_priv; + txd = &sc->sc_txq[idx]; + txb = &sc->sc_txbuf[idx]; if (VIC_TXURN(sc)) { ifp->if_flags |= IFF_OACTIVE; return (ENOBUFS); - } else if (txb == NULL) { - ifp->if_oerrors++; - if (ifp->if_flags & IFF_DEBUG) - printf("%s: transmit buffer error\n", - sc->sc_dev.dv_xname); - return (ENOBUFS); } else if (txb->txb_m != NULL) { sc->sc_data->vd_tx_stopped = 1; ifp->if_oerrors++; return (ENOMEM); } - if (bus_dmamap_load_mbuf(sc->sc_dmat, txb->txb_map, + if (bus_dmamap_load_mbuf(sc->sc_dmat, txb->txb_dmamap, m, BUS_DMA_NOWAIT) != 0) { + /* XXX this is bollocks */ MGETHDR(m0, M_DONTWAIT, MT_DATA); if (m0 == NULL) return (ENOBUFS); @@ -568,13 +788,19 @@ vic_tx_start(struct vic_softc *sc, struct mbuf *m) } m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; - if (bus_dmamap_load_mbuf(sc->sc_dmat, txb->txb_map, + if (bus_dmamap_load_mbuf(sc->sc_dmat, txb->txb_dmamap, m0, BUS_DMA_NOWAIT) != 0) { m_freem(m0); return (ENOBUFS); } } +#if NBPFILTER > 0 + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); +#endif + + /* m0 means this has to be done here, more bollocks */ IFQ_DEQUEUE(&ifp->if_snd, m); if (m0 != NULL) { m_freem(m); @@ -582,37 +808,39 @@ vic_tx_start(struct vic_softc *sc, struct mbuf *m) m0 = NULL; } - desc->tx_flags = VIC_TX_FLAGS_KEEP; - desc->tx_sa.sa_length = 1; - desc->tx_sa.sa_sg[0].sg_length = htole16(m->m_len); - desc->tx_sa.sa_sg[0].sg_addr_low = txb->txb_map->dm_segs->ds_addr; - desc->tx_owner = VIC_OWNER_NIC; + /* XXX nsegs are cool */ + txd->tx_flags = VIC_TX_FLAGS_KEEP; + txd->tx_sa.sa_length = 1; + txd->tx_sa.sa_sg[0].sg_length = m->m_len; + txd->tx_sa.sa_sg[0].sg_addr_low = txb->txb_dmamap->dm_segs[0].ds_addr; + txd->tx_owner = VIC_OWNER_NIC; + + /* XXX bus dma sync */ if (VIC_TXURN_WARN(sc)) { if (ifp->if_flags & IFF_DEBUG) printf("%s: running out of tx descriptors\n", - sc->sc_dev.dv_xname); - desc->tx_flags |= VIC_TX_FLAGS_TXURN; + DEVNAME(sc)); + txd->tx_flags |= VIC_TX_FLAGS_TXURN; } ifp->if_opackets++; - sc->sc_txpending++; - sc->sc_txtimeout = VIC_TX_TIMEOUT; - ifp->if_timer = 1; VIC_INC(sc->sc_data->vd_tx_nextidx, sc->sc_data->vd_tx_length); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + return (0); } void vic_watchdog(struct ifnet *ifp) { +#if 0 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; - ifp->if_timer = 0; - if (sc->sc_txpending && sc->sc_txtimeout > 0) { if (--sc->sc_txtimeout == 0) { printf("%s: device timeout\n", sc->sc_dev.dv_xname); @@ -621,11 +849,11 @@ vic_watchdog(struct ifnet *ifp) ifp->if_oerrors++; return; } - ifp->if_timer = 1; } if (!IFQ_IS_EMPTY(&ifp->if_snd)) vic_start(ifp); +#endif } int @@ -704,43 +932,27 @@ vic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) void vic_init(struct ifnet *ifp) { - struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; - int s; + struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; + int s; - s = splnet(); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_map, 0, sc->sc_dma_size, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - timeout_add(&sc->sc_timer, hz * VIC_TIMER_DELAY); - - vic_reset_data(sc); - -#ifdef notyet - VIC_WRITE(VIC_CMD, VIC_CMD_INTR_ENABLE); -#endif + s = splnet(); - VIC_WRITE(VIC_DATA_ADDR, sc->sc_physaddr); - VIC_WRITE(VIC_DATA_LENGTH, htole32(sc->sc_size)); + vic_write(sc, VIC_DATA_ADDR, VIC_DMA_DVA(sc)); + vic_write(sc, VIC_DATA_LENGTH, sc->sc_dma_size); if (ifp->if_flags & IFF_PROMISC) vic_iff(sc, VIC_CMD_IFF_PROMISC); else vic_iff(sc, VIC_CMD_IFF_BROADCAST | VIC_CMD_IFF_MULTICAST); -#ifdef VIC_DEBUG - if (ifp->if_flags & IFF_DEBUG) - printf("%s: physaddr 0x%08x length 0x%08x\n", - sc->sc_dev.dv_xname, sc->sc_physaddr, sc->sc_size); -#endif - sc->sc_data->vd_tx_stopped = sc->sc_data->vd_tx_queued = 0; ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - /* XXX poll */ - if (ifp->if_flags & IFF_LINK0) { - sc->sc_polling = 1; - timeout_add(&sc->sc_poll, VIC_TIMER_MS(100)); - } else - sc->sc_polling = 0; + vic_write(sc, VIC_CMD, VIC_CMD_INTR_ENABLE); splx(s); } @@ -748,57 +960,27 @@ vic_init(struct ifnet *ifp) void vic_stop(struct ifnet *ifp) { +#if 0 struct vic_softc *sc = (struct vic_softc *)ifp->if_softc; int s; s = splnet(); sc->sc_txtimeout = 0; - ifp->if_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); #ifdef notyet - VIC_WRITE(VIC_CMD, VIC_CMD_INTR_DISABLE); + vic_write(sc, VIC_CMD, VIC_CMD_INTR_DISABLE); #endif - VIC_WRITE(VIC_DATA_ADDR, 0); + vic_write(sc, VIC_DATA_ADDR, 0); vic_iff(sc, 0); sc->sc_data->vd_tx_stopped = 1; timeout_del(&sc->sc_timer); - /* XXX poll */ - if (sc->sc_polling) { - sc->sc_polling = 0; - timeout_del(&sc->sc_poll); - } - splx(s); -} - -void -vic_printb(unsigned short v, char *bits) -{ - int i, any = 0; - char c; - - /* - * Used to print capability bits on startup - */ - bits++; - if (bits) { - while ((i = *bits++)) { - if (v & (1 << (i-1))) { - if (any) - printf(" "); - any = 1; - for (; (c = *bits) > 32; bits++) - printf("%c", c); - } else - for (; *bits > 32; bits++) - ; - } - } +#endif } struct mbuf * @@ -809,14 +991,16 @@ vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map) MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) return (NULL); + MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(m); return (NULL); } + m->m_len = m->m_pkthdr.len = MCLBYTES; + if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT) != 0) { - printf("%s: could not load mbuf DMA map", - sc->sc_dev.dv_xname); + printf("%s: could not load mbuf DMA map", DEVNAME(sc)); m_freem(m); return (NULL); } @@ -824,118 +1008,11 @@ vic_alloc_mbuf(struct vic_softc *sc, bus_dmamap_t map) return (m); } -int -vic_alloc_data(struct vic_softc *sc) -{ - struct vic_rxbuf *rxb; - struct vic_txbuf *txb; - u_int32_t offset; - int i, error; - - sc->sc_size = sizeof(struct vic_data) + - (sc->sc_nrxbuf + VIC_QUEUE2_SIZE) * sizeof(struct vic_rxdesc) + - sc->sc_ntxbuf * sizeof(struct vic_txdesc); - - if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_size, 1, - sc->sc_size, 0, BUS_DMA_NOWAIT, &sc->sc_map)) != 0) { - printf("%s: could not create DMA material\n", - sc->sc_dev.dv_xname); - goto fail; - } - - if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_size, PAGE_SIZE, 0, - &sc->sc_seg, 1, &sc->sc_nsegs, BUS_DMA_NOWAIT)) != 0) { - printf("%s: could not allocate DMA memory\n", - sc->sc_dev.dv_xname); - goto fail; - } - - if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, - sc->sc_nsegs, sc->sc_size, (caddr_t *)&sc->sc_data, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { - printf("%s: could not map DMA memory\n", - sc->sc_dev.dv_xname); - goto fail; - } - - if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_map, - sc->sc_data, sc->sc_size, NULL, BUS_DMA_NOWAIT)) != 0) { - printf("%s: could not load DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - bzero(sc->sc_data, sc->sc_size); - sc->sc_physaddr = sc->sc_map->dm_segs->ds_addr; - sc->sc_data->vd_magic = VIC_MAGIC; - sc->sc_data->vd_length = htole32(sc->sc_size); - offset = (u_int32_t)sc->sc_data + sizeof(struct vic_data); - -#ifdef VIC_DEBUG - printf("%s: (rxbuf %d * %d) (txbuf %d * %d) (size %d)\n", - sc->sc_dev.dv_xname, - sc->sc_nrxbuf, sizeof(struct vic_rxdesc), - sc->sc_ntxbuf, sizeof(struct vic_txdesc), - sc->sc_size); -#endif - - /* Setup the Rx queue */ - sc->sc_rxq = (struct vic_rxdesc *)offset; - sc->sc_data->vd_rx_offset = htole32(offset); - sc->sc_data->vd_rx_length = htole32(sc->sc_nrxbuf); - offset += sc->sc_nrxbuf + sizeof(struct vic_rxdesc); - for (i = 0; i < sc->sc_nrxbuf; i++) { - rxb = &sc->sc_rxbuf[i]; - if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, - VIC_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT, - &rxb->rxb_map)) != 0) { - printf("%s: could not create rx DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - - /* Preallocate the Rx mbuf */ - if ((rxb->rxb_m = vic_alloc_mbuf(sc, rxb->rxb_map)) == NULL) { - error = ENOMEM; - goto fail; - } - sc->sc_rxq[i].rx_physaddr = rxb->rxb_map->dm_segs->ds_addr; - } - - /* Setup Rx queue 2 (unused gap) */ - sc->sc_rxq2 = (struct vic_rxdesc *)offset; - sc->sc_data->vd_rx_offset = htole32(offset); - sc->sc_data->vd_rx_length = htole32(1); - sc->sc_rxq2[0].rx_owner = VIC_OWNER_DRIVER; - offset += sizeof(struct vic_rxdesc); - - /* Setup the Tx queue */ - sc->sc_txq = (struct vic_txdesc *)offset; - sc->sc_data->vd_tx_offset = htole32(offset); - sc->sc_data->vd_tx_length = htole32(sc->sc_ntxbuf); - offset += sc->sc_ntxbuf + sizeof(struct vic_txdesc); - for (i = 0; i < sc->sc_ntxbuf; i++) { - txb = &sc->sc_txbuf[i]; - if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, - VIC_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT, - &txb->txb_map)) != 0) { - printf("%s: could not create tx DMA map\n", - sc->sc_dev.dv_xname); - goto fail; - } - } - - return (0); - - fail: - vic_free_data(sc); - - return (error); -} - void vic_reset_data(struct vic_softc *sc) { + +#if 0 struct vic_rxbuf *rxb; struct vic_txbuf *txb; int i; @@ -972,11 +1049,14 @@ vic_reset_data(struct vic_softc *sc) bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, sc->sc_map->dm_mapsize, BUS_DMASYNC_PREWRITE); +#endif } void vic_free_data(struct vic_softc *sc) { +#if 0 + bus_dmamap_t map; int i; @@ -1008,53 +1088,86 @@ vic_free_data(struct vic_softc *sc) } bus_dmamap_destroy(sc->sc_dmat, map); } - - bus_dmamap_sync(sc->sc_dmat, sc->sc_map, 0, - sc->sc_map->dm_mapsize, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, sc->sc_map); - bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_data, sc->sc_size); - bus_dmamem_free(sc->sc_dmat, &sc->sc_seg, sc->sc_nsegs); +#endif } void vic_timer(void *arg) { - struct vic_softc *sc = (struct vic_softc *)arg; - struct ifnet *ifp = &sc->sc_ac.ac_if; - -#ifdef VIC_DEBUG - if (ifp->if_flags & IFF_DEBUG) { - if (sc->sc_polling) - printf("%s: %s (polling #%u)\n", - ifp->if_xname, __func__, sc->sc_polling); - else - printf("%s: %s\n", - ifp->if_xname, __func__); - } -#endif + struct vic_softc *sc = (struct vic_softc *)arg; +// struct ifnet *ifp = &sc->sc_ac.ac_if; /* Update link state (if changed) */ vic_link_state(sc); /* Re-schedule another timeout. */ - timeout_add(&sc->sc_timer, hz * VIC_TIMER_DELAY); +// timeout_add(&sc->sc_timer, hz * VIC_TIMER_DELAY); +} + +u_int32_t +vic_read(struct vic_softc *sc, bus_size_t r) +{ + bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, + BUS_SPACE_BARRIER_READ); + return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r)); } - /* XXX poll */ void -vic_poll(void *arg) +vic_write(struct vic_softc *sc, bus_size_t r, u_int32_t v) { - struct vic_softc *sc = (struct vic_softc *)arg; - int s; + bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); + bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, + BUS_SPACE_BARRIER_WRITE); +} - s = splnet(); +u_int32_t +vic_read_cmd(struct vic_softc *sc, u_int32_t cmd) +{ + vic_write(sc, VIC_CMD, cmd); + return (vic_read(sc, VIC_CMD)); +} - vic_rx_proc(sc); - vic_tx_proc(sc); +int +vic_alloc_dmamem(struct vic_softc *sc) +{ + int nsegs; - VIC_INC_POS(sc->sc_polling, UINT_MAX); + if (bus_dmamap_create(sc->sc_dmat, sc->sc_dma_size, 1, + sc->sc_dma_size, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, + &sc->sc_dma_map) != 0) + goto err; - timeout_add(&sc->sc_poll, VIC_TIMER_MS(100)); + if (bus_dmamem_alloc(sc->sc_dmat, sc->sc_dma_size, 16, 0, + &sc->sc_dma_seg, 1, &nsegs, BUS_DMA_NOWAIT) != 0) + goto destroy; - splx(s); + if (bus_dmamem_map(sc->sc_dmat, &sc->sc_dma_seg, nsegs, + sc->sc_dma_size, &sc->sc_dma_kva, BUS_DMA_NOWAIT) != 0) + goto free; + + if (bus_dmamap_load(sc->sc_dmat, sc->sc_dma_map, sc->sc_dma_kva, + sc->sc_dma_size, NULL, BUS_DMA_NOWAIT) != 0) + goto unmap; + + bzero(sc->sc_dma_kva, sc->sc_dma_size); + + return (0); + +unmap: + bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size); +free: + bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1); +destroy: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map); +err: + return (1); +} + +void +vic_free_dmamem(struct vic_softc *sc) +{ + bus_dmamap_unload(sc->sc_dmat, sc->sc_dma_map); + bus_dmamem_unmap(sc->sc_dmat, sc->sc_dma_kva, sc->sc_dma_size); + bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_seg, 1); + bus_dmamap_destroy(sc->sc_dmat, sc->sc_dma_map); } diff --git a/sys/dev/pci/if_vicreg.h b/sys/dev/pci/if_vicreg.h index 4cb676899cc..e8973c4a661 100644 --- a/sys/dev/pci/if_vicreg.h +++ b/sys/dev/pci/if_vicreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vicreg.h,v 1.2 2006/05/28 00:20:21 brad Exp $ */ +/* $OpenBSD: if_vicreg.h,v 1.3 2006/10/31 06:04:15 dlg Exp $ */ /* * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> @@ -31,44 +31,42 @@ /* Command register */ #define VIC_CMD 0x000c /* Command register */ -#define VIC_CMD_INTR_ACK 0x00000001 /* Acknowledge interrupt */ -#define VIC_CMD_MCASTFIL 0x00000002 /* Multicast address filter */ -#define VIC_CMD_MCASTFIL_LENGTH 2 -#define VIC_CMD_IFF 0x00000004 /* Interface flags */ -#define VIC_CMD_IFF_PROMISC 0x0001 /* Promiscous enabled */ -#define VIC_CMD_IFF_BROADCAST 0x0002 /* Broadcast enabled */ -#define VIC_CMD_IFF_MULTICAST 0x0004 /* Multicast enabled */ -#define VIC_CMD_RESERVED_8 0x00000008 -#define VIC_CMD_RESERVED_10 0x00000010 -#define VIC_CMD_INTR_DISABLE 0x00000020 /* Enable interrupts */ -#define VIC_CMD_INTR_ENABLE 0x00000040 /* Disable interrupts */ -#define VIC_CMD_RESERVED_80 0x00000080 -#define VIC_CMD_Tx_DONE 0x00000100 /* Tx done register */ -#define VIC_CMD_NUM_Rx_BUF 0x00000200 /* Number of Rx buffers */ -#define VIC_CMD_NUM_Tx_BUF 0x00000400 /* Number of Tx buffers */ -#define VIC_CMD_NUM_PINNED_BUF 0x00000800 /* Number of pinned buffers */ -#define VIC_CMD_HWCAP 0x00001000 /* Capability register */ -#define VIC_CMD_HWCAP_SG 0x0001 /* Scatter-gather transmits */ -#define VIC_CMD_HWCAP_CSUM_IPv4 0x0002 /* Hardware checksum of TCP/UDP */ -#define VIC_CMD_HWCAP_CSUM_ALL 0x0004 /* Hardware checksum support */ -#define VIC_CMD_HWCAP_CSUM \ +#define VIC_CMD_INTR_ACK 0x0001 /* Acknowledge interrupt */ +#define VIC_CMD_MCASTFIL 0x0002 /* Multicast address filter */ +#define VIC_CMD_MCASTFIL_LENGTH 2 +#define VIC_CMD_IFF 0x0004 /* Interface flags */ +#define VIC_CMD_IFF_PROMISC 0x0001 /* Promiscous enabled */ +#define VIC_CMD_IFF_BROADCAST 0x0002 /* Broadcast enabled */ +#define VIC_CMD_IFF_MULTICAST 0x0004 /* Multicast enabled */ +#define VIC_CMD_INTR_DISABLE 0x0020 /* Enable interrupts */ +#define VIC_CMD_INTR_ENABLE 0x0040 /* Disable interrupts */ +#define VIC_CMD_Tx_DONE 0x0100 /* Tx done register */ +#define VIC_CMD_NUM_Rx_BUF 0x0200 /* Number of Rx buffers */ +#define VIC_CMD_NUM_Tx_BUF 0x0400 /* Number of Tx buffers */ +#define VIC_CMD_NUM_PINNED_BUF 0x0800 /* Number of pinned buffers */ +#define VIC_CMD_HWCAP 0x1000 /* Capability register */ +#define VIC_CMD_HWCAP_SG (1<<0) /* Scatter-gather transmits */ +#define VIC_CMD_HWCAP_CSUM_IPv4 (1<<1) /* TCP/UDP cksum */ +#define VIC_CMD_HWCAP_CSUM_ALL (1<<3) /* Hardware cksum */ +#define VIC_CMD_HWCAP_CSUM \ (VIC_CMD_HWCAP_CSUM_IPv4 | VIC_CMD_HWCAP_CSUM_ALL) -#define VIC_CMD_HWCAP_DMA_HIGH 0x0008 /* High DMA mapping possible */ -#define VIC_CMD_HWCAP_TOE 0x0010 /* TCP offload engine available */ -#define VIC_CMD_HWCAP_TSO 0x0020 /* TCP segmentation offload */ -#define VIC_CMD_HWCAP_TSO_SW 0x0040 /* Software TCP segmentation */ -#define VIC_CMD_HWCAP_VPROM 0x0080 /* Virtual PROM available */ -#define VIC_CMD_HWCAP_VLAN_Tx 0x0100 /* Hardware VLAN MTU Rx */ -#define VIC_CMD_HWCAP_VLAN_Rx 0x0200 /* Hardware VLAN MTU Tx */ -#define VIC_CMD_HWCAP_VLAN_SW 0x0400 /* Software VLAN MTU */ -#define VIC_CMD_HWCAP_VLAN \ - (VIC_CMD_HWCAP_VLAN_Tx | VIC_CMD_HWCAP_VLAN_Rx | VIC_CMD_HWCAP_VLAN_SW) -#define VIC_CMD_HWCAP_BITS \ - "\20\01SG\02CSUM4\03CSUM\04HDMA\05TOE" \ - "\06TSO\07TSOSW\10VPROM\13VLANTx\14VLANRx\15VLANSW" -#define VIC_CMD_FEATURE 0x00002000 /* Additional feature register */ -#define VIC_CMD_FEATURE_0_Tx 0x0001 -#define VIC_CMD_FEATURE_TSO 0x0002 +#define VIC_CMD_HWCAP_DMA_HIGH (1<<4) /* High DMA mapping */ +#define VIC_CMD_HWCAP_TOE (1<<5) /* TCP offload engine */ +#define VIC_CMD_HWCAP_TSO (1<<6) /* TCP segmentation offload */ +#define VIC_CMD_HWCAP_TSO_SW (1<<7) /* Software TCP segmentation */ +#define VIC_CMD_HWCAP_VPROM (1<<8) /* Virtual PROM available */ +#define VIC_CMD_HWCAP_VLAN_Tx (1<<9) /* Hardware VLAN MTU Rx */ +#define VIC_CMD_HWCAP_VLAN_Rx (1<<10) /* Hardware VLAN MTU Tx */ +#define VIC_CMD_HWCAP_VLAN_SW (1<<11) /* Software VLAN MTU */ +#define VIC_CMD_HWCAP_VLAN \ + (VIC_CMD_HWCAP_VLAN_Tx | VIC_CMD_HWCAP_VLAN_Rx | \ + VIC_CMD_HWCAP_VLAN_SW) +#define VIC_CMD_HWCAP_BITS \ + "\20\01SG\02CSUM4\03CSUM\04HDMA\05TOE\06TSO" \ + "\07TSOSW\10VPROM\13VLANTx\14VLANRx\15VLANSW" +#define VIC_CMD_FEATURE 0x2000 /* Additional feature register */ +#define VIC_CMD_FEATURE_0_Tx (1<<0) +#define VIC_CMD_FEATURE_TSO (1<<1) #define VIC_LLADDR 0x0010 /* MAC address register */ #define VIC_VERSION_MINOR 0x0018 /* Minor version register */ @@ -77,8 +75,8 @@ /* Status register */ #define VIC_STATUS 0x0020 -#define VIC_STATUS_CONNECTED 0x00000001 -#define VIC_STATUS_ENABLED 0x00000002 +#define VIC_STATUS_CONNECTED (1<<0) +#define VIC_STATUS_ENABLED (1<<1) #define VIC_TOE_ADDR 0x0024 /* TCP offload address */ @@ -105,7 +103,7 @@ struct vic_sgarray { u_int16_t sa_addr_type; u_int16_t sa_length; struct vic_sg sa_sg[VIC_SG_MAX]; -}; +} __packed; struct vic_rxdesc { u_int64_t rx_physaddr; diff --git a/sys/dev/pci/if_vicvar.h b/sys/dev/pci/if_vicvar.h deleted file mode 100644 index b884bb52a54..00000000000 --- a/sys/dev/pci/if_vicvar.h +++ /dev/null @@ -1,108 +0,0 @@ -/* $OpenBSD: if_vicvar.h,v 1.4 2006/03/04 03:33:06 brad Exp $ */ - -/* - * Copyright (c) 2006 Reyk Floeter <reyk@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _DEV_IC_VICVAR_H -#define _DEV_IC_VICVAR_H - -#define VIC_DEBUG 1 - -#define VIC_BAR0 0x10 /* Base Address Register */ - -#define VIC_NBUF 100 -#define VIC_NBUF_MAX 128 -#define VIC_MAX_SCATTER 1 /* 8? */ -#define VIC_QUEUE_SIZE VIC_NBUF_MAX -#define VIC_QUEUE2_SIZE 1 -#define VIC_INC(_x, _y) (_x) = ((_x) + 1) % (_y) -#define VIC_INC_POS(_x, _y) (_x) = (++(_x)) % (_y) ? (_x) : 1 -#define VIC_TX_TIMEOUT 5 -#define VIC_TIMER_DELAY 2 -#define VIC_TIMER_MS(_ms) (_ms * hz / 1000) - -#define VIC_TXURN_WARN(_sc) ((_sc)->sc_txpending >= ((_sc)->sc_ntxbuf - 5)) -#define VIC_TXURN(_sc) ((_sc)->sc_txpending >= (_sc)->sc_ntxbuf) -#define VIC_OFF_RXDESC(_n) \ - (sizeof(struct vic_data) + ((_n) * sizeof(struct vic_rxdesc))) -#define VIC_OFF_TXDESC(_n) \ - (sizeof(struct vic_data) + \ - ((sc->sc_nrxbuf + VIC_QUEUE2_SIZE) * sizeof(struct vic_rxdesc)) + \ - ((_n) * sizeof(struct vic_txdesc))) - -#define VIC_WRITE(_reg, _val) \ - bus_space_write_4(sc->sc_st, sc->sc_sh, (_reg), (_val)) -#define VIC_READ(_reg) \ - bus_space_read_4(sc->sc_st, sc->sc_sh, (_reg)) -#define VIC_WRITE8(_reg, _val) \ - bus_space_write_1(sc->sc_st, sc->sc_sh, (_reg), (_val)) -#define VIC_READ8(_reg) \ - bus_space_read_1(sc->sc_st, sc->sc_sh, (_reg)) - -struct vic_rxbuf { - bus_dmamap_t rxb_map; - struct mbuf *rxb_m; -}; - -struct vic_txbuf { - bus_dmamap_t txb_map; - struct mbuf *txb_m; -}; - -struct vic_softc { - struct device sc_dev; - void *sc_ih; - void *sc_sdhook; - - struct arpcom sc_ac; - struct ifmedia sc_media; - struct timeout sc_timer; - - struct timeout sc_poll; /* XXX poll */ - u_int sc_polling; - - int (*sc_enable)(struct vic_softc *); - void (*sc_disable)(struct vic_softc *); - void (*sc_power)(struct vic_softc *, int); - - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - bus_dma_tag_t sc_dmat; - - u_int32_t sc_ver_major, sc_ver_minor; - u_int32_t sc_cap, sc_feature; - - u_int8_t sc_lladdr[ETHER_ADDR_LEN]; - - u_int32_t sc_nrxbuf, sc_ntxbuf; - - struct vic_rxdesc *sc_rxq, *sc_rxq2; - struct vic_rxbuf sc_rxbuf[VIC_QUEUE_SIZE]; - - struct vic_txdesc *sc_txq; - struct vic_txbuf sc_txbuf[VIC_QUEUE_SIZE]; - int sc_txpending; - int sc_txtimeout; - - struct vic_data *sc_data; - bus_addr_t sc_physaddr; - bus_dmamap_t sc_map; - bus_dma_segment_t sc_seg; - int sc_nsegs; - int sc_size; -}; - -#endif /* _DEV_IC_VICVAR_H */ |