diff options
author | mdodd <mdodd@FreeBSD.org> | 2002-03-29 11:22:22 +0000 |
---|---|---|
committer | mdodd <mdodd@FreeBSD.org> | 2002-03-29 11:22:22 +0000 |
commit | 84c21f1d8ff69f47f8e2bef01392d5b39cf9ce02 (patch) | |
tree | acee2dafe452f857b35aa52d9223075e812b1e18 /sys | |
parent | fdbdd2f5af8ced636e98ffa82c0898512b04bfba (diff) | |
download | FreeBSD-src-84c21f1d8ff69f47f8e2bef01392d5b39cf9ce02.zip FreeBSD-src-84c21f1d8ff69f47f8e2bef01392d5b39cf9ce02.tar.gz |
- Merge the pdq driver (if_fpa and if_fea) from NetBSD.
Among other things this gets us ifmedia support.
- Update fddi_ifattach() to take an additional argument.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pdq/if_fea.c | 180 | ||||
-rw-r--r-- | sys/dev/pdq/if_fpa.c | 172 | ||||
-rw-r--r-- | sys/dev/pdq/pdq.c | 504 | ||||
-rw-r--r-- | sys/dev/pdq/pdq_freebsd.h | 271 | ||||
-rw-r--r-- | sys/dev/pdq/pdq_ifsubr.c | 670 | ||||
-rw-r--r-- | sys/dev/pdq/pdqreg.h | 168 | ||||
-rw-r--r-- | sys/dev/pdq/pdqvar.h | 247 | ||||
-rw-r--r-- | sys/net/fddi.h | 4 | ||||
-rw-r--r-- | sys/net/if_fddisubr.c | 13 |
9 files changed, 1707 insertions, 522 deletions
diff --git a/sys/dev/pdq/if_fea.c b/sys/dev/pdq/if_fea.c index ee4fba3..3348550 100644 --- a/sys/dev/pdq/if_fea.c +++ b/sys/dev/pdq/if_fea.c @@ -35,25 +35,32 @@ #include <sys/kernel.h> #include <sys/socket.h> -#include <net/if.h> -#include <net/if_arp.h> - #include <sys/module.h> #include <sys/bus.h> + #include <machine/bus.h> #include <machine/resource.h> #include <sys/rman.h> + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/if_media.h> +#include <net/fddi.h> + #include <dev/eisa/eisaconf.h> -#include <dev/pdq/pdqvar.h> + +#include <dev/pdq/pdq_freebsd.h> #include <dev/pdq/pdqreg.h> static void pdq_eisa_subprobe (pdq_bus_t, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *); static void pdq_eisa_devinit (pdq_softc_t *); static const char * pdq_eisa_match (eisa_id_t); + static int pdq_eisa_probe (device_t); static int pdq_eisa_attach (device_t); -void pdq_eisa_intr (void *); +static int pdq_eisa_detach (device_t); static int pdq_eisa_shutdown (device_t); +static void pdq_eisa_ifintr (void *); #define DEFEA_IRQS 0x0000FBA9U @@ -91,18 +98,18 @@ pdq_eisa_devinit (sc) /* * Do the standard initialization for the DEFEA registers. */ - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_FUNCTION_CTRL, 0x23); - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CMP_1_1, (sc->sc_iobase >> 8) & 0xF0); - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CMP_0_1, (sc->sc_iobase >> 8) & 0xF0); - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_SLOT_CTRL, 0x01); - data = PDQ_OS_IORD_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_FUNCTION_CTRL, 0x23); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CMP_1_1, (sc->io_bsh >> 8) & 0xF0); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CMP_0_1, (sc->io_bsh >> 8) & 0xF0); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_SLOT_CTRL, 0x01); + data = PDQ_OS_IORD_8(sc->io_bst, sc->io_bsh, PDQ_EISA_BURST_HOLDOFF); #if defined(PDQ_IOMAPPED) - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF, data & ~1); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_BURST_HOLDOFF, data & ~1); #else - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_BURST_HOLDOFF, data | 1); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_BURST_HOLDOFF, data | 1); #endif - data = PDQ_OS_IORD_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CONFIG_STAT_0); - PDQ_OS_IOWR_8(sc->sc_bc, sc->sc_iobase, PDQ_EISA_IO_CONFIG_STAT_0, data | DEFEA_INTRENABLE); + data = PDQ_OS_IORD_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CONFIG_STAT_0); + PDQ_OS_IOWR_8(sc->io_bst, sc->io_bsh, PDQ_EISA_IO_CONFIG_STAT_0, data | DEFEA_INTRENABLE); return; } @@ -144,7 +151,7 @@ pdq_eisa_probe (dev) device_set_desc(dev, desc); iobase = eisa_get_slot(dev) * EISA_SLOT_SIZE; - pdq_eisa_subprobe(PDQ_BUS_EISA, iobase, &maddr, &msize, &irq); + pdq_eisa_subprobe(SYS_RES_IOPORT, iobase, &maddr, &msize, &irq); eisa_add_iospace(dev, iobase, 0x200, RESVADDR_NONE); eisa_add_mspace(dev, maddr, msize, RESVADDR_NONE); @@ -153,99 +160,119 @@ pdq_eisa_probe (dev) return (0); } -void -pdq_eisa_intr(xdev) - void *xdev; +static void +pdq_eisa_ifintr(arg) + void * arg; { - device_t dev = (device_t) xdev; - pdq_softc_t *sc = device_get_softc(dev); + device_t dev; + pdq_softc_t * sc; + + dev = (device_t)arg; + sc = device_get_softc(dev); + + PDQ_LOCK(sc); (void) pdq_interrupt(sc->sc_pdq); + PDQ_LOCK(sc); return; } static int pdq_eisa_attach (dev) - device_t dev; + device_t dev; { - pdq_softc_t *sc = device_get_softc(dev); - struct resource *io = 0; - struct resource *irq = 0; - struct resource *mspace = 0; - int rid; - void *ih; - u_int32_t m_addr, m_size; - - rid = 0; - io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, 1, RF_ACTIVE); - - if (!io) { - device_printf(dev, "No I/O space?!\n"); - goto bad; - } + pdq_softc_t * sc; + struct ifnet * ifp; + int error; - rid = 0; - mspace = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0, ~0, 1, RF_ACTIVE); + sc = device_get_softc(dev); + ifp = &sc->arpcom.ac_if; - if (!mspace) { - device_printf(dev, "No memory space?!\n"); + sc->dev = dev; + + sc->io_rid = 0; + sc->io_type = SYS_RES_IOPORT; + sc->io = bus_alloc_resource(dev, sc->io_type, &sc->io_rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->io) { + device_printf(dev, "Unable to allocate I/O space resource.\n"); + error = ENXIO; goto bad; } - - rid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, - 0, ~0, 1, RF_ACTIVE); - - if (!irq) { - device_printf(dev, "No, irq?!\n"); + sc->io_bsh = rman_get_bushandle(sc->io); + sc->io_bst = rman_get_bustag(sc->io); + + sc->mem_rid = 0; + sc->mem_type = SYS_RES_MEMORY; + sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->mem) { + device_printf(dev, "Unable to allocate memory resource.\n"); + error = ENXIO; + goto bad; + } + sc->mem_bsh = rman_get_bushandle(sc->mem); + sc->mem_bst = rman_get_bustag(sc->mem); + + sc->irq_rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, + 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); + if (!sc->irq) { + device_printf(dev, "Unable to allocate interrupt resource.\n"); + error = ENXIO; goto bad; } - m_addr = rman_get_start(mspace); - m_size = rman_get_size(mspace); - - sc->sc_iobase = (pdq_bus_ioport_t) rman_get_start(io); - sc->sc_membase = (pdq_bus_memaddr_t) pmap_mapdev(m_addr, m_size); - sc->sc_if.if_name = "fea"; - sc->sc_if.if_unit = device_get_unit(dev); + ifp->if_name = "fea"; + ifp->if_unit = device_get_unit(dev); pdq_eisa_devinit(sc); - sc->sc_pdq = pdq_initialize(PDQ_BUS_EISA, sc->sc_membase, - sc->sc_if.if_name, sc->sc_if.if_unit, - (void *) sc, PDQ_DEFEA); + sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh, + ifp->if_name, ifp->if_unit, + (void *)sc, PDQ_DEFEA); if (sc->sc_pdq == NULL) { - device_printf(dev, "initialization failed\n"); + device_printf(dev, "Initialization failed.\n"); + error = ENXIO; goto bad; } - if (bus_setup_intr(dev, irq, INTR_TYPE_NET, pdq_eisa_intr, dev, &ih)) { + error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, + pdq_eisa_ifintr, dev, &sc->irq_ih); + if (error) { + device_printf(dev, "Failed to setup interrupt handler.\n"); + error = ENXIO; goto bad; } - bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6); - pdq_ifattach(sc, NULL); + bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, + (caddr_t) sc->arpcom.ac_enaddr, FDDI_ADDR_LEN); + pdq_ifattach(sc); return (0); - bad: - if (io) - bus_release_resource(dev, SYS_RES_IOPORT, 0, io); - if (irq) - bus_release_resource(dev, SYS_RES_IRQ, 0, irq); - if (mspace) - bus_release_resource(dev, SYS_RES_MEMORY, 0, mspace); - - return (-1); + pdq_free(dev); + return (error); +} + +static int +pdq_eisa_detach (dev) + device_t dev; +{ + pdq_softc_t * sc; + + sc = device_get_softc(dev); + pdq_ifdetach(sc); + + return (0); } static int pdq_eisa_shutdown(dev) device_t dev; { - pdq_softc_t *sc = device_get_softc(dev); + pdq_softc_t * sc; + sc = device_get_softc(dev); pdq_hwreset(sc->sc_pdq); return (0); @@ -254,6 +281,7 @@ pdq_eisa_shutdown(dev) static device_method_t pdq_eisa_methods[] = { DEVMETHOD(device_probe, pdq_eisa_probe), DEVMETHOD(device_attach, pdq_eisa_attach), + DEVMETHOD(device_attach, pdq_eisa_detach), DEVMETHOD(device_shutdown, pdq_eisa_shutdown), { 0, 0 } @@ -265,6 +293,6 @@ static driver_t pdq_eisa_driver = { sizeof(pdq_softc_t), }; -static devclass_t pdq_devclass; - -DRIVER_MODULE(pdq, eisa, pdq_eisa_driver, pdq_devclass, 0, 0); +DRIVER_MODULE(if_fea, eisa, pdq_eisa_driver, pdq_devclass, 0, 0); +/* MODULE_DEPEND(if_fea, eisa, 1, 1, 1); */ +MODULE_DEPEND(if_fea, fddi, 1, 1, 1); diff --git a/sys/dev/pdq/if_fpa.c b/sys/dev/pdq/if_fpa.c index 9eb3f50..c01b8ad 100644 --- a/sys/dev/pdq/if_fpa.c +++ b/sys/dev/pdq/if_fpa.c @@ -32,22 +32,29 @@ */ #include <sys/param.h> +#include <sys/systm.h> #include <sys/kernel.h> #include <sys/socket.h> -#include <net/if.h> +#include <sys/module.h> +#include <sys/bus.h> -#include <net/ethernet.h> -#include <net/if_arp.h> -#include <dev/pdq/pdqvar.h> -#include <dev/pdq/pdqreg.h> +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> #include <machine/bus.h> #include <machine/resource.h> -#include <sys/bus.h> -#include <sys/rman.h> -#include <pci/pcivar.h> -#include <pci/pcireg.h> +#include <sys/rman.h> +#include <net/if.h> +#include <net/if_arp.h> +#include <net/if_media.h> +#include <net/fddi.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +#include <dev/pdq/pdq_freebsd.h> +#include <dev/pdq/pdqreg.h> #define DEC_VENDORID 0x1011 #define DEFPA_CHIPID 0x000F @@ -58,13 +65,26 @@ #define PCI_CBMA 0x10 /* Configuration Base Memory Address */ #define PCI_CBIO 0x14 /* Configuration Base I/O Address */ +static int pdq_pci_probe (device_t); +static int pdq_pci_attach (device_t); +static int pdq_pci_detach (device_t); +static void pdq_pci_shutdown (device_t); +static void pdq_pci_ifintr (void *); + static void pdq_pci_ifintr(void *arg) { + device_t dev; pdq_softc_t *sc; - sc = device_get_softc(arg); + dev = (device_t)arg; + sc = device_get_softc(dev); + + PDQ_LOCK(sc); (void) pdq_interrupt(sc->sc_pdq); + PDQ_UNLOCK(sc); + + return; } /* @@ -76,61 +96,112 @@ pdq_pci_probe(device_t dev) if (pci_get_vendor(dev) == DEC_VENDORID && pci_get_device(dev) == DEFPA_CHIPID) { device_set_desc(dev, "Digital DEFPA PCI FDDI Controller"); - return 0; + return (0); } - return ENXIO; + + return (ENXIO); } static int pdq_pci_attach(device_t dev) { pdq_softc_t *sc; - int data; - struct resource *memres, *irqres; - int rid; - void *ih; + struct ifnet *ifp; + u_int32_t command; + int error; - memres = NULL; - irqres = NULL; sc = device_get_softc(dev); + ifp = &sc->arpcom.ac_if; + + sc->dev = dev; - data = pci_read_config(dev, PCIR_LATTIMER, 1); - if (data < DEFPA_LATENCY) { - data = DEFPA_LATENCY; - pci_write_config(dev, PCIR_LATTIMER, data, 1); + /* + * Map control/status registers. + */ + pci_enable_busmaster(dev); + pci_enable_io(dev, SYS_RES_IOPORT); + pci_enable_io(dev, SYS_RES_MEMORY); + command = pci_read_config(dev, PCIR_COMMAND, 4); + + if (!(command & PCIM_CMD_PORTEN)) { + device_printf(dev, "Failed to enable PCI I/O ports.\n"); + error = ENXIO; + goto bad; } - rid = PCI_CBMA; - memres = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE); - if (!memres) + if (!(command & PCIM_CMD_MEMEN)) { + device_printf(dev, "Failed to enable PCI memory mapping.\n"); + error = ENXIO; goto bad; + } + + command = pci_read_config(dev, PCIR_LATTIMER, 1); + if (command < DEFPA_LATENCY) { + command = DEFPA_LATENCY; + pci_write_config(dev, PCIR_LATTIMER, command, 1); + } - sc->sc_if.if_name = "fpa"; - sc->sc_if.if_unit = device_get_unit(dev); - sc->sc_membase = (pdq_bus_memaddr_t) rman_get_virtual(memres); - sc->sc_pdq = pdq_initialize(PDQ_BUS_PCI, sc->sc_membase, - sc->sc_if.if_name, sc->sc_if.if_unit, - (void *) sc, PDQ_DEFPA); - if (sc->sc_pdq == NULL) + sc->mem_rid = PCI_CBMA; + sc->mem_type = SYS_RES_MEMORY; + sc->mem = bus_alloc_resource(dev, sc->mem_type, &sc->mem_rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->mem) { + device_printf(dev, "Unable to allocate I/O space resource.\n"); + error = ENXIO; goto bad; - bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr, 6); - pdq_ifattach(sc, NULL); - rid = 0; - irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - if (!irqres) + } + sc->mem_bsh = rman_get_bushandle(sc->mem); + sc->mem_bst = rman_get_bustag(sc->mem); + + sc->irq_rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, + 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); + if (!sc->irq) { + device_printf(dev, "Unable to allocate interrupt resource.\n"); + error = ENXIO; goto bad; - if (bus_setup_intr(dev, irqres, INTR_TYPE_NET, pdq_pci_ifintr, - (void *)dev, &ih)) + } + + ifp->if_name = "fpa"; + ifp->if_unit = device_get_unit(dev); + + sc->sc_pdq = pdq_initialize(sc->mem_bst, sc->mem_bsh, + ifp->if_name, ifp->if_unit, + (void *)sc, PDQ_DEFPA); + if (sc->sc_pdq == NULL) { + device_printf(dev, "Initialization failed.\n"); + error = ENXIO; goto bad; - return 0; + } + error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET, + pdq_pci_ifintr, dev, &sc->irq_ih); + if (error) { + device_printf(dev, "Failed to setup interrupt handler.\n"); + error = ENXIO; + goto bad; + } + + bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, + (caddr_t) sc->arpcom.ac_enaddr, FDDI_ADDR_LEN); + pdq_ifattach(sc); + + return (0); bad: - if (memres) - bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, memres); - if (irqres) - bus_release_resource(dev, SYS_RES_IRQ, 0, irqres); - return ENXIO; + pdq_free(dev); + return (error); +} + +static int +pdq_pci_detach (dev) + device_t dev; +{ + pdq_softc_t *sc; + + sc = device_get_softc(dev); + pdq_ifdetach(sc); + + return (0); } static void @@ -140,19 +211,26 @@ pdq_pci_shutdown(device_t dev) sc = device_get_softc(dev); pdq_hwreset(sc->sc_pdq); + + return; } static device_method_t pdq_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pdq_pci_probe), DEVMETHOD(device_attach, pdq_pci_attach), + DEVMETHOD(device_detach, pdq_pci_detach), DEVMETHOD(device_shutdown, pdq_pci_shutdown), + { 0, 0 } }; + static driver_t pdq_pci_driver = { "fpa", pdq_pci_methods, sizeof(pdq_softc_t), }; -static devclass_t pdq_devclass; + DRIVER_MODULE(if_fpa, pci, pdq_pci_driver, pdq_devclass, 0, 0); +/* MODULE_DEPEND(if_fpa, pci, 1, 1, 1); */ +MODULE_DEPEND(if_fpa, fddi, 1, 1, 1); diff --git a/sys/dev/pdq/pdq.c b/sys/dev/pdq/pdq.c index 055bdc2..fd9aa00 100644 --- a/sys/dev/pdq/pdq.c +++ b/sys/dev/pdq/pdq.c @@ -1,3 +1,5 @@ +/* $NetBSD: pdq.c,v 1.33 2001/11/13 13:14:43 lukem Exp $ */ + /*- * Copyright (c) 1995,1996 Matt Thomas <matt@3am-software.com> * All rights reserved. @@ -8,7 +10,7 @@ * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission + * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -21,6 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * Id: pdq.c,v 1.32 1997/06/05 01:56:35 thomas Exp * $FreeBSD$ * */ @@ -28,7 +31,7 @@ /* * DEC PDQ FDDI Controller O/S independent code * - * This module should work any PDQ based board. Note that changes for + * This module should work any on PDQ based board. Note that changes for * MIPS and Alpha architectures (or any other architecture which requires * a flushing of memory or write buffers and/or has incoherent caches) * have yet to be made. @@ -37,10 +40,18 @@ * flushing of the write buffers. */ +#ifdef __NetBSD__ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: pdq.c,v 1.33 2001/11/13 13:14:43 lukem Exp $"); +#endif + #define PDQ_HWSUPPORT /* for pdq.h */ #if defined(__FreeBSD__) -#include <dev/pdq/pdqvar.h> +/* + * What a botch having to specific includes for FreeBSD! + */ +#include <dev/pdq/pdq_freebsd.h> #include <dev/pdq/pdqreg.h> #else #include "pdqvar.h" @@ -76,6 +87,7 @@ static const char * const pdq_entities[] = { }; static const char * const pdq_station_events[] = { + "Unknown Event #0", "Trace Received" }; @@ -218,6 +230,8 @@ pdq_print_fddi_chars( pdq_pmd_types[rsp->status_chars_get.pmd_type[1] / 100][rsp->status_chars_get.pmd_type[1] % 100]); printf("\n"); + + pdq_os_update_status(pdq, rsp); } static void @@ -261,6 +275,7 @@ pdq_init_pci_csrs( static void pdq_flush_databuf_queue( + pdq_t *pdq, pdq_databuf_queue_t *q) { PDQ_OS_DATABUF_T *pdu; @@ -268,7 +283,7 @@ pdq_flush_databuf_queue( PDQ_OS_DATABUF_DEQUEUE(q, pdu); if (pdu == NULL) return; - PDQ_OS_DATABUF_FREE(pdu); + PDQ_OS_DATABUF_FREE(pdq, pdu); } } @@ -409,7 +424,6 @@ static const struct { sizeof(pdq_response_addr_filter_get_t), "Addr Filter Get" }, -#if 0 { sizeof(pdq_cmd_generic_t), /* 9 - PDQC_ERROR_LOG_CLEAR */ sizeof(pdq_response_generic_t), "Error Log Clear" @@ -443,7 +457,7 @@ static const struct { sizeof(pdq_response_generic_t), "SMT MIB Set", }, -#endif + { 0, 0, "Bogus CMD" }, }; static void @@ -453,6 +467,7 @@ pdq_queue_commands( const pdq_csrs_t * const csrs = &pdq->pdq_csrs; pdq_command_info_t * const ci = &pdq->pdq_command_info; pdq_descriptor_block_t * const dbp = pdq->pdq_dbp; + pdq_txdesc_t * const txd = &dbp->pdqdb_command_requests[ci->ci_request_producer]; pdq_cmd_code_t op; pdq_uint32_t cmdlen, rsplen, mask; @@ -487,23 +502,19 @@ pdq_queue_commands( * Obtain and fill in the descriptor for the command (descriptor is * pre-initialized) */ - dbp->pdqdb_command_requests[ci->ci_request_producer].txd_seg_len = cmdlen; - PDQ_ADVANCE(ci->ci_request_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests)); - - /* - * Obtain and fill in the descriptor for the response (descriptor is - * pre-initialized) - */ - dbp->pdqdb_command_responses[ci->ci_response_producer].rxd_seg_len_hi = cmdlen / 16; - PDQ_ADVANCE(ci->ci_response_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses)); + txd->txd_seg_len = cmdlen; /* * Clear the command area, set the opcode, and the command from the pending * mask. */ - PDQ_OS_MEMZERO(ci->ci_bufstart, cmdlen); - *(pdq_cmd_code_t *) ci->ci_bufstart = op; + ci->ci_queued_commands[ci->ci_request_producer] = op; +#if defined(PDQVERBOSE) + ((pdq_response_generic_t *) ci->ci_response_bufstart)->generic_op = PDQC_BOGUS_CMD; +#endif + PDQ_OS_MEMZERO(ci->ci_request_bufstart, cmdlen); + *(pdq_cmd_code_t *) ci->ci_request_bufstart = op; ci->ci_pending_commands &= ~mask; /* @@ -511,7 +522,7 @@ pdq_queue_commands( */ switch (op) { case PDQC_FILTER_SET: { - pdq_cmd_filter_set_t *filter_set = (pdq_cmd_filter_set_t *) ci->ci_bufstart; + pdq_cmd_filter_set_t *filter_set = (pdq_cmd_filter_set_t *) ci->ci_request_bufstart; unsigned idx = 0; filter_set->filter_set_items[idx].item_code = PDQI_IND_GROUP_PROM; filter_set->filter_set_items[idx].filter_state = (pdq->pdq_flags & PDQ_PROMISC ? PDQ_FILTER_PASS : PDQ_FILTER_BLOCK); @@ -529,7 +540,7 @@ pdq_queue_commands( break; } case PDQC_ADDR_FILTER_SET: { - pdq_cmd_addr_filter_set_t *addr_filter_set = (pdq_cmd_addr_filter_set_t *) ci->ci_bufstart; + pdq_cmd_addr_filter_set_t *addr_filter_set = (pdq_cmd_addr_filter_set_t *) ci->ci_request_bufstart; pdq_lanaddr_t *addr = addr_filter_set->addr_filter_set_addresses; addr->lanaddr_bytes[0] = 0xFF; addr->lanaddr_bytes[1] = 0xFF; @@ -541,10 +552,36 @@ pdq_queue_commands( pdq_os_addr_fill(pdq, addr, 61); break; } + case PDQC_SNMP_SET: { + pdq_cmd_snmp_set_t *snmp_set = (pdq_cmd_snmp_set_t *) ci->ci_request_bufstart; + unsigned idx = 0; + snmp_set->snmp_set_items[idx].item_code = PDQSNMP_FULL_DUPLEX_ENABLE; + snmp_set->snmp_set_items[idx].item_value = (pdq->pdq_flags & PDQ_WANT_FDX ? 1 : 2); + snmp_set->snmp_set_items[idx].item_port = 0; + idx++; + snmp_set->snmp_set_items[idx].item_code = PDQSNMP_EOL; + break; + } default: { /* to make gcc happy */ break; } } + + + /* + * Sync the command request buffer and descriptor, then advance + * the request producer index. + */ + PDQ_OS_CMDRQST_PRESYNC(pdq, txd->txd_seg_len); + PDQ_OS_DESC_PRESYNC(pdq, txd, sizeof(pdq_txdesc_t)); + PDQ_ADVANCE(ci->ci_request_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests)); + + /* + * Sync the command response buffer and advance the response + * producer index (descriptor is already pre-initialized) + */ + PDQ_OS_CMDRSP_PRESYNC(pdq, PDQ_SIZE_COMMAND_RESPONSE); + PDQ_ADVANCE(ci->ci_response_producer, 1, PDQ_RING_MASK(dbp->pdqdb_command_responses)); /* * At this point the command is done. All that needs to be done is to * produce it to the PDQ. @@ -578,15 +615,21 @@ pdq_process_command_responses( PDQ_ASSERT(cbp->pdqcb_command_request != ci->ci_request_completion); - rspgen = (const pdq_response_generic_t *) ci->ci_bufstart; + PDQ_OS_CMDRSP_POSTSYNC(pdq, PDQ_SIZE_COMMAND_RESPONSE); + rspgen = (const pdq_response_generic_t *) ci->ci_response_bufstart; + PDQ_ASSERT(rspgen->generic_op == ci->ci_queued_commands[ci->ci_request_completion]); PDQ_ASSERT(rspgen->generic_status == PDQR_SUCCESS); - PDQ_PRINTF(("PDQ Process Command Response: %s completed (status=%d)\n", + PDQ_PRINTF(("PDQ Process Command Response: %s completed (status=%d [0x%x])\n", pdq_cmd_info[rspgen->generic_op].cmd_name, - rspgen->generic_status)); + rspgen->generic_status, rspgen->generic_status)); if (rspgen->generic_op == PDQC_STATUS_CHARS_GET && (pdq->pdq_flags & PDQ_PRINTCHARS)) { pdq->pdq_flags &= ~PDQ_PRINTCHARS; pdq_print_fddi_chars(pdq, (const pdq_response_status_chars_get_t *) rspgen); + } else if (rspgen->generic_op == PDQC_DEC_EXT_MIB_GET) { + pdq->pdq_flags &= ~PDQ_IS_FDX; + if (((const pdq_response_dec_ext_mib_get_t *)rspgen)->dec_ext_mib_get.fdx_operational) + pdq->pdq_flags |= PDQ_IS_FDX; } PDQ_ADVANCE(ci->ci_request_completion, 1, PDQ_RING_MASK(dbp->pdqdb_command_requests)); @@ -617,19 +660,40 @@ pdq_process_unsolicited_events( pdq_unsolicited_info_t *ui = &pdq->pdq_unsolicited_info; volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp; pdq_descriptor_block_t *dbp = pdq->pdq_dbp; - const pdq_unsolicited_event_t *event; - pdq_rxdesc_t *rxd; /* * Process each unsolicited event (if any). */ while (cbp->pdqcb_unsolicited_event != ui->ui_completion) { - rxd = &dbp->pdqdb_unsolicited_events[ui->ui_completion]; + const pdq_unsolicited_event_t *event; event = &ui->ui_events[ui->ui_completion & (PDQ_NUM_UNSOLICITED_EVENTS-1)]; + PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, event); switch (event->event_type) { case PDQ_UNSOLICITED_EVENT: { + int bad_event = 0; + switch (event->event_entity) { + case PDQ_ENTITY_STATION: { + bad_event = event->event_code.value >= PDQ_STATION_EVENT_MAX; + break; + } + case PDQ_ENTITY_LINK: { + bad_event = event->event_code.value >= PDQ_LINK_EVENT_MAX; + break; + } + case PDQ_ENTITY_PHY_PORT: { + bad_event = event->event_code.value >= PDQ_PHY_EVENT_MAX; + break; + } + default: { + bad_event = 1; + break; + } + } + if (bad_event) { + break; + } printf(PDQ_OS_PREFIX "Unsolicited Event: %s: %s", PDQ_OS_PREFIX_ARGS, pdq_entities[event->event_entity], @@ -643,6 +707,7 @@ pdq_process_unsolicited_events( break; } } + PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, event); PDQ_ADVANCE(ui->ui_completion, 1, PDQ_RING_MASK(dbp->pdqdb_unsolicited_events)); ui->ui_free++; } @@ -679,11 +744,13 @@ pdq_process_received_data( fpdu = lpdu = buffers[completion]; PDQ_ASSERT(fpdu != NULL); - + PDQ_OS_RXPDU_POSTSYNC(pdq, fpdu, 0, sizeof(u_int32_t)); dataptr = PDQ_OS_DATABUF_PTR(fpdu); status = *(pdq_rxstatus_t *) dataptr; - if ((status.rxs_status & 0x200000) == 0) { - datalen = status.rxs_status & 0x1FFF; + if (status.rxs_rcc_badpdu == 0) { + datalen = status.rxs_len; + PDQ_OS_RXPDU_POSTSYNC(pdq, fpdu, sizeof(u_int32_t), + PDQ_RX_FC_OFFSET + 1 - sizeof(u_int32_t)); fc = dataptr[PDQ_RX_FC_OFFSET]; switch (fc & (PDQ_FDDIFC_C|PDQ_FDDIFC_L|PDQ_FDDIFC_F)) { case PDQ_FDDI_LLC_ASYNC: @@ -710,19 +777,19 @@ pdq_process_received_data( * Update the lengths of the data buffers now that we know * the real length. */ - pdulen = datalen - 4 /* CRC */; - segcnt = (pdulen + PDQ_RX_FC_OFFSET + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE; - PDQ_OS_DATABUF_ALLOC(npdu); + pdulen = datalen + (PDQ_RX_FC_OFFSET - PDQ_OS_HDR_OFFSET) - 4 /* CRC */; + segcnt = (pdulen + PDQ_OS_HDR_OFFSET + PDQ_OS_DATABUF_SIZE - 1) / PDQ_OS_DATABUF_SIZE; + PDQ_OS_DATABUF_ALLOC(pdq, npdu); if (npdu == NULL) { PDQ_PRINTF(("discard: no databuf #0\n")); goto discard_frame; } buffers[completion] = npdu; for (idx = 1; idx < segcnt; idx++) { - PDQ_OS_DATABUF_ALLOC(npdu); + PDQ_OS_DATABUF_ALLOC(pdq, npdu); if (npdu == NULL) { PDQ_OS_DATABUF_NEXT_SET(lpdu, NULL); - PDQ_OS_DATABUF_FREE(fpdu); + PDQ_OS_DATABUF_FREE(pdq, fpdu); goto discard_frame; } PDQ_OS_DATABUF_NEXT_SET(lpdu, buffers[(completion + idx) & ring_mask]); @@ -735,13 +802,17 @@ pdq_process_received_data( buffers[(completion + idx) & ring_mask]; buffers[(completion + idx) & ring_mask] = NULL; } - PDQ_OS_DATABUF_ADJ(fpdu, PDQ_RX_FC_OFFSET); + PDQ_OS_DATABUF_ADJ(fpdu, PDQ_OS_HDR_OFFSET); if (segcnt == 1) { PDQ_OS_DATABUF_LEN_SET(fpdu, pdulen); } else { - PDQ_OS_DATABUF_LEN_SET(lpdu, pdulen + PDQ_RX_FC_OFFSET - (segcnt - 1) * PDQ_OS_DATABUF_SIZE); + PDQ_OS_DATABUF_LEN_SET(lpdu, pdulen + PDQ_OS_HDR_OFFSET - (segcnt - 1) * PDQ_OS_DATABUF_SIZE); } - pdq_os_receive_pdu(pdq, fpdu, pdulen); + /* + * Do not pass to protocol if packet was received promiscuously + */ + pdq_os_receive_pdu(pdq, fpdu, pdulen, + status.rxs_rcc_dd < PDQ_RXS_RCC_DD_CAM_MATCH); rx->rx_free += PDQ_RX_SEGCNT; PDQ_ADVANCE(producer, PDQ_RX_SEGCNT, ring_mask); PDQ_ADVANCE(completion, PDQ_RX_SEGCNT, ring_mask); @@ -754,21 +825,21 @@ pdq_process_received_data( goto discard_frame; if (status.rxs_rcc_reason != 0) { /* hardware fault */ - } - if (status.rxs_rcc_badcrc) { - printf(PDQ_OS_PREFIX " MAC CRC error (source=%x-%x-%x-%x-%x-%x)\n", - PDQ_OS_PREFIX_ARGS, - dataptr[PDQ_RX_FC_OFFSET+1], - dataptr[PDQ_RX_FC_OFFSET+2], - dataptr[PDQ_RX_FC_OFFSET+3], - dataptr[PDQ_RX_FC_OFFSET+4], - dataptr[PDQ_RX_FC_OFFSET+5], - dataptr[PDQ_RX_FC_OFFSET+6]); - /* rx->rx_badcrc++; */ - } else if (status.rxs_fsc == 0 || status.rxs_fsb_e == 1) { - /* rx->rx_frame_status_errors++; */ - } else { - /* hardware fault */ + if (status.rxs_rcc_badcrc) { + printf(PDQ_OS_PREFIX " MAC CRC error (source=%x-%x-%x-%x-%x-%x)\n", + PDQ_OS_PREFIX_ARGS, + dataptr[PDQ_RX_FC_OFFSET+1], + dataptr[PDQ_RX_FC_OFFSET+2], + dataptr[PDQ_RX_FC_OFFSET+3], + dataptr[PDQ_RX_FC_OFFSET+4], + dataptr[PDQ_RX_FC_OFFSET+5], + dataptr[PDQ_RX_FC_OFFSET+6]); + /* rx->rx_badcrc++; */ + } else if (status.rxs_fsc == 0 || status.rxs_fsb_e == 1) { + /* rx->rx_frame_status_errors++; */ + } else { + /* hardware fault */ + } } } discard_frame: @@ -787,7 +858,9 @@ pdq_process_received_data( } rxd->rxd_pa_hi = 0; rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16; - rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(pdq, PDQ_OS_DATABUF_PTR(buffers[rx->rx_producer])); + rxd->rxd_pa_lo = PDQ_OS_DATABUF_BUSPA(pdq, buffers[rx->rx_producer]); + PDQ_OS_RXPDU_PRESYNC(pdq, buffers[rx->rx_producer], 0, PDQ_OS_DATABUF_SIZE); + PDQ_OS_DESC_PRESYNC(pdq, rxd, sizeof(*rxd)); PDQ_ADVANCE(rx->rx_producer, 1, ring_mask); PDQ_ADVANCE(producer, 1, ring_mask); PDQ_ADVANCE(completion, 1, ring_mask); @@ -804,7 +877,7 @@ pdq_process_received_data( */ for (idx = 0; idx < PDQ_RX_SEGCNT; idx++) { if ((pdu = buffers[(rx->rx_producer + idx) & ring_mask]) == NULL) { - PDQ_OS_DATABUF_ALLOC(pdu); + PDQ_OS_DATABUF_ALLOC(pdq, pdu); if (pdu == NULL) break; buffers[(rx->rx_producer + idx) & ring_mask] = pdu; @@ -817,7 +890,9 @@ pdq_process_received_data( } rxd->rxd_pa_hi = 0; rxd->rxd_seg_len_hi = PDQ_OS_DATABUF_SIZE / 16; - rxd->rxd_pa_lo = PDQ_OS_VA_TO_PA(pdq, PDQ_OS_DATABUF_PTR(pdu)); + rxd->rxd_pa_lo = PDQ_OS_DATABUF_BUSPA(pdq, pdu); + PDQ_OS_RXPDU_PRESYNC(pdq, pdu, 0, PDQ_OS_DATABUF_SIZE); + PDQ_OS_DESC_PRESYNC(pdq, rxd, sizeof(*rxd)); } if (idx < PDQ_RX_SEGCNT) { /* @@ -832,24 +907,65 @@ pdq_process_received_data( } } +static void pdq_process_transmitted_data(pdq_t *pdq); + pdq_boolean_t pdq_queue_transmit_data( pdq_t *pdq, PDQ_OS_DATABUF_T *pdu) { - pdq_tx_info_t *tx = &pdq->pdq_tx_info; - pdq_descriptor_block_t *dbp = pdq->pdq_dbp; + pdq_tx_info_t * const tx = &pdq->pdq_tx_info; + pdq_descriptor_block_t * const dbp = pdq->pdq_dbp; pdq_uint32_t producer = tx->tx_producer; pdq_txdesc_t *eop = NULL; PDQ_OS_DATABUF_T *pdu0; pdq_uint32_t freecnt; +#if defined(PDQ_BUS_DMA) + bus_dmamap_t map; +#endif - if (tx->tx_free < 1) + again: + if (PDQ_RX_FC_OFFSET == PDQ_OS_HDR_OFFSET) { + freecnt = tx->tx_free - 1; + } else { + freecnt = tx->tx_free; + } + /* + * Need 2 or more descriptors to be able to send. + */ + if (freecnt == 0) { + pdq->pdq_intrmask |= PDQ_HOST_INT_TX_ENABLE; + PDQ_CSR_WRITE(&pdq->pdq_csrs, csr_host_int_enable, pdq->pdq_intrmask); return PDQ_FALSE; + } - dbp->pdqdb_transmits[producer] = tx->tx_hdrdesc; - PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits)); + if (PDQ_RX_FC_OFFSET == PDQ_OS_HDR_OFFSET) { + dbp->pdqdb_transmits[producer] = tx->tx_hdrdesc; + PDQ_OS_DESC_PRESYNC(pdq, &dbp->pdqdb_transmits[producer], sizeof(pdq_txdesc_t)); + PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits)); + } +#if defined(PDQ_BUS_DMA) + map = M_GETCTX(pdu, bus_dmamap_t); + if (freecnt >= map->dm_nsegs) { + int idx; + for (idx = 0; idx < map->dm_nsegs; idx++) { + /* + * Initialize the transmit descriptor + */ + eop = &dbp->pdqdb_transmits[producer]; + eop->txd_seg_len = map->dm_segs[idx].ds_len; + eop->txd_pa_lo = map->dm_segs[idx].ds_addr; + eop->txd_sop = eop->txd_eop = eop->txd_pa_hi = 0; + PDQ_OS_DESC_PRESYNC(pdq, eop, sizeof(pdq_txdesc_t)); + freecnt--; + PDQ_ADVANCE(producer, 1, PDQ_RING_MASK(dbp->pdqdb_transmits)); + } + pdu0 = NULL; + } else { + pdu0 = pdu; + } +#else for (freecnt = tx->tx_free - 1, pdu0 = pdu; pdu0 != NULL && freecnt > 0;) { pdq_uint32_t fraglen, datalen = PDQ_OS_DATABUF_LEN(pdu0); const pdq_uint8_t *dataptr = PDQ_OS_DATABUF_PTR(pdu0); @@ -868,9 +984,9 @@ pdq_queue_transmit_data( */ eop = &dbp->pdqdb_transmits[producer]; eop->txd_seg_len = seglen; - eop->txd_pa_lo = PDQ_OS_VA_TO_PA(pdq, dataptr); + eop->txd_pa_lo = PDQ_OS_VA_TO_BUSPA(pdq, dataptr); eop->txd_sop = eop->txd_eop = eop->txd_pa_hi = 0; - + PDQ_OS_DESC_PRESYNC(pdq, eop, sizeof(pdq_txdesc_t)); datalen -= seglen; dataptr += seglen; fraglen = PDQ_OS_PAGESIZE; @@ -879,20 +995,37 @@ pdq_queue_transmit_data( } pdu0 = PDQ_OS_DATABUF_NEXT(pdu0); } +#endif /* defined(PDQ_BUS_DMA) */ if (pdu0 != NULL) { + unsigned completion = tx->tx_completion; PDQ_ASSERT(freecnt == 0); + PDQ_OS_CONSUMER_POSTSYNC(pdq); + pdq_process_transmitted_data(pdq); + if (completion != tx->tx_completion) { + producer = tx->tx_producer; + eop = NULL; + goto again; + } /* * If we still have data to process then the ring was too full * to store the PDU. Return FALSE so the caller will requeue * the PDU for later. */ + pdq->pdq_intrmask |= PDQ_HOST_INT_TX_ENABLE; + PDQ_CSR_WRITE(&pdq->pdq_csrs, csr_host_int_enable, pdq->pdq_intrmask); return PDQ_FALSE; } /* * Everything went fine. Finish it up. */ tx->tx_descriptor_count[tx->tx_producer] = tx->tx_free - freecnt; + if (PDQ_RX_FC_OFFSET != PDQ_OS_HDR_OFFSET) { + dbp->pdqdb_transmits[tx->tx_producer].txd_sop = 1; + PDQ_OS_DESC_PRESYNC(pdq, &dbp->pdqdb_transmits[tx->tx_producer], + sizeof(pdq_txdesc_t)); + } eop->txd_eop = 1; + PDQ_OS_DESC_PRESYNC(pdq, eop, sizeof(pdq_txdesc_t)); PDQ_OS_DATABUF_ENQUEUE(&tx->tx_txq, pdu); tx->tx_producer = producer; tx->tx_free = freecnt; @@ -908,6 +1041,7 @@ pdq_process_transmitted_data( volatile const pdq_consumer_block_t *cbp = pdq->pdq_cbp; pdq_descriptor_block_t *dbp = pdq->pdq_dbp; pdq_uint32_t completion = tx->tx_completion; + int reclaimed = 0; while (completion != cbp->pdqcb_transmits) { PDQ_OS_DATABUF_T *pdu; @@ -917,14 +1051,17 @@ pdq_process_transmitted_data( PDQ_OS_DATABUF_DEQUEUE(&tx->tx_txq, pdu); pdq_os_transmit_done(pdq, pdu); tx->tx_free += descriptor_count; - + reclaimed = 1; PDQ_ADVANCE(completion, descriptor_count, PDQ_RING_MASK(dbp->pdqdb_transmits)); } if (tx->tx_completion != completion) { tx->tx_completion = completion; + pdq->pdq_intrmask &= ~PDQ_HOST_INT_TX_ENABLE; + PDQ_CSR_WRITE(&pdq->pdq_csrs, csr_host_int_enable, pdq->pdq_intrmask); pdq_os_restart_transmitter(pdq); } - PDQ_DO_TYPE2_PRODUCER(pdq); + if (reclaimed) + PDQ_DO_TYPE2_PRODUCER(pdq); } void @@ -943,11 +1080,12 @@ pdq_flush_transmitter( * Don't call transmit done since the packet never made it * out on the wire. */ - PDQ_OS_DATABUF_FREE(pdu); + PDQ_OS_DATABUF_FREE(pdq, pdu); } tx->tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits); - tx->tx_completion = cbp->pdqcb_transmits = tx->tx_producer; + cbp->pdqcb_transmits = tx->tx_completion = tx->tx_producer; + PDQ_OS_CONSUMER_PRESYNC(pdq); PDQ_DO_TYPE2_PRODUCER(pdq); } @@ -964,17 +1102,17 @@ pdq_hwreset( if (state == PDQS_DMA_UNAVAILABLE) return; PDQ_CSR_WRITE(csrs, csr_port_data_a, - (state == PDQS_HALTED) ? 0 : PDQ_PRESET_SKIP_SELFTEST); + (state == PDQS_HALTED && pdq->pdq_type != PDQ_DEFTA) ? 0 : PDQ_PRESET_SKIP_SELFTEST); PDQ_CSR_WRITE(csrs, csr_port_reset, 1); PDQ_OS_USEC_DELAY(100); PDQ_CSR_WRITE(csrs, csr_port_reset, 0); - for (cnt = 45000;;cnt--) { + for (cnt = 100000;;cnt--) { PDQ_OS_USEC_DELAY(1000); state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status)); if (state == PDQS_DMA_UNAVAILABLE || cnt == 0) break; } - PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 45000 - cnt)); + PDQ_PRINTF(("PDQ Reset spun %d cycles\n", 100000 - cnt)); PDQ_OS_USEC_DELAY(10000); state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status)); PDQ_ASSERT(state == PDQS_DMA_UNAVAILABLE); @@ -1050,12 +1188,12 @@ pdq_stop( /* * Flush all the databuf queues. */ - pdq_flush_databuf_queue(&pdq->pdq_tx_info.tx_txq); - pdq->pdq_flags &= ~PDQ_TXOK; + pdq_flush_databuf_queue(pdq, &pdq->pdq_tx_info.tx_txq); + pdq->pdq_flags &= ~(PDQ_TXOK|PDQ_IS_ONRING|PDQ_IS_FDX); buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_rx_info.rx_buffers; for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_receives); idx++) { if (buffers[idx] != NULL) { - PDQ_OS_DATABUF_FREE(buffers[idx]); + PDQ_OS_DATABUF_FREE(pdq, buffers[idx]); buffers[idx] = NULL; } } @@ -1063,7 +1201,7 @@ pdq_stop( buffers = (PDQ_OS_DATABUF_T **) pdq->pdq_host_smt_info.rx_buffers; for (idx = 0; idx < PDQ_RING_SIZE(pdq->pdq_dbp->pdqdb_host_smt); idx++) { if (buffers[idx] != NULL) { - PDQ_OS_DATABUF_FREE(buffers[idx]); + PDQ_OS_DATABUF_FREE(pdq, buffers[idx]); buffers[idx] = NULL; } } @@ -1078,6 +1216,7 @@ pdq_stop( pdq->pdq_cbp->pdqcb_unsolicited_event = 0; pdq->pdq_cbp->pdqcb_command_response = 0; pdq->pdq_cbp->pdqcb_command_request = 0; + PDQ_OS_CONSUMER_PRESYNC(pdq); /* * Reset the producer and completion indexes to 0. @@ -1119,20 +1258,30 @@ pdq_stop( */ pdq_process_unsolicited_events(pdq); - if (pdq->pdq_type == PDQ_DEFEA && pdq->pdq_chip_rev == PDQ_CHIP_REV_E) + if ((pdq->pdq_type == PDQ_DEFEA && pdq->pdq_chip_rev == PDQ_CHIP_REV_E) + || pdq->pdq_type == PDQ_DEFTA) PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_16LW); else PDQ_CSR_WRITE(csrs, csr_port_data_b, PDQ_DMA_BURST_8LW); PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_SUB_CMD_DMA_BURST_SIZE_SET); pdq_do_port_control(csrs, PDQ_PCTL_SUB_CMD); + /* + * Make sure there isn't stale information in the caches before + * tell the adapter about the blocks it's going to use. + */ + PDQ_OS_CONSUMER_PRESYNC(pdq); + PDQ_CSR_WRITE(csrs, csr_port_data_b, 0); - PDQ_CSR_WRITE(csrs, csr_port_data_a, PDQ_OS_VA_TO_PA(pdq, pdq->pdq_cbp)); + PDQ_CSR_WRITE(csrs, csr_port_data_a, pdq->pdq_pa_consumer_block); pdq_do_port_control(csrs, PDQ_PCTL_CONSUMER_BLOCK); PDQ_CSR_WRITE(csrs, csr_port_data_b, 0); - PDQ_CSR_WRITE(csrs, csr_port_data_a, - PDQ_OS_VA_TO_PA(pdq, pdq->pdq_dbp) | PDQ_DMA_INIT_LW_BSWAP_DATA); +#if !defined(BYTE_ORDER) || BYTE_ORDER == LITTLE_ENDIAN + PDQ_CSR_WRITE(csrs, csr_port_data_a, pdq->pdq_pa_descriptor_block | PDQ_DMA_INIT_LW_BSWAP_DATA); +#else + PDQ_CSR_WRITE(csrs, csr_port_data_a, pdq->pdq_pa_descriptor_block | PDQ_DMA_INIT_LW_BSWAP_DATA | PDQ_DMA_INIT_LW_BSWAP_LITERAL); +#endif pdq_do_port_control(csrs, PDQ_PCTL_DMA_INIT); for (cnt = 0; cnt < 1000; cnt++) { @@ -1152,9 +1301,11 @@ pdq_stop( PDQ_ASSERT(state == PDQS_DMA_AVAILABLE); PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF); - PDQ_CSR_WRITE(csrs, csr_host_int_enable, 0) /* PDQ_HOST_INT_STATE_CHANGE + pdq->pdq_intrmask = 0; + /* PDQ_HOST_INT_STATE_CHANGE |PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE |PDQ_HOST_INT_UNSOL_ENABLE */; + PDQ_CSR_WRITE(csrs, csr_host_int_enable, pdq->pdq_intrmask); /* * Any other command but START should be valid. @@ -1169,6 +1320,7 @@ pdq_stop( * Now wait (up to 100ms) for the command(s) to finish. */ for (cnt = 0; cnt < 1000; cnt++) { + PDQ_OS_CONSUMER_POSTSYNC(pdq); pdq_process_command_responses(pdq); if (pdq->pdq_command_info.ci_response_producer == pdq->pdq_command_info.ci_response_completion) break; @@ -1201,9 +1353,11 @@ pdq_run( * ones will get through. */ PDQ_CSR_WRITE(csrs, csr_host_int_type_0, 0xFF); - PDQ_CSR_WRITE(csrs, csr_host_int_enable, PDQ_HOST_INT_STATE_CHANGE|PDQ_HOST_INT_XMT_DATA_FLUSH - |PDQ_HOST_INT_FATAL_ERROR|PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE - |PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_TX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE); + pdq->pdq_intrmask = PDQ_HOST_INT_STATE_CHANGE + |PDQ_HOST_INT_XMT_DATA_FLUSH|PDQ_HOST_INT_FATAL_ERROR + |PDQ_HOST_INT_CMD_RSP_ENABLE|PDQ_HOST_INT_UNSOL_ENABLE + |PDQ_HOST_INT_RX_ENABLE|PDQ_HOST_INT_HOST_SMT_ENABLE; + PDQ_CSR_WRITE(csrs, csr_host_int_enable, pdq->pdq_intrmask); /* * Set the MAC and address filters and start up the PDQ. */ @@ -1223,7 +1377,9 @@ pdq_run( | (pdq->pdq_host_smt_info.rx_completion << 8)); } pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET) - | PDQ_BITMASK(PDQC_ADDR_FILTER_SET) | PDQ_BITMASK(PDQC_START); + | PDQ_BITMASK(PDQC_ADDR_FILTER_SET) + | PDQ_BITMASK(PDQC_SNMP_SET) + | PDQ_BITMASK(PDQC_START); if (pdq->pdq_flags & PDQ_PRINTCHARS) pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET); pdq_queue_commands(pdq); @@ -1232,7 +1388,8 @@ pdq_run( case PDQS_LINK_UNAVAILABLE: case PDQS_LINK_AVAILABLE: { pdq->pdq_command_info.ci_pending_commands = PDQ_BITMASK(PDQC_FILTER_SET) - | PDQ_BITMASK(PDQC_ADDR_FILTER_SET); + | PDQ_BITMASK(PDQC_ADDR_FILTER_SET) + | PDQ_BITMASK(PDQC_SNMP_SET); if (pdq->pdq_flags & PDQ_PRINTCHARS) pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_STATUS_CHARS_GET); if (pdq->pdq_flags & PDQ_PASS_SMT) { @@ -1270,6 +1427,7 @@ pdq_interrupt( while ((data = PDQ_CSR_READ(csrs, csr_port_status)) & PDQ_PSTS_INTR_PENDING) { progress = 1; PDQ_PRINTF(("PDQ Interrupt: Status = 0x%08x\n", data)); + PDQ_OS_CONSUMER_POSTSYNC(pdq); if (data & PDQ_PSTS_RCV_DATA_PENDING) { pdq_process_received_data(pdq, &pdq->pdq_rx_info, pdq->pdq_dbp->pdqdb_receives, @@ -1284,7 +1442,7 @@ pdq_interrupt( PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt)); PDQ_DO_HOST_SMT_PRODUCER(pdq); } - if (data & PDQ_PSTS_XMT_DATA_PENDING) + /* if (data & PDQ_PSTS_XMT_DATA_PENDING) */ pdq_process_transmitted_data(pdq); if (data & PDQ_PSTS_UNSOL_PENDING) pdq_process_unsolicited_events(pdq); @@ -1296,9 +1454,13 @@ pdq_interrupt( pdq_state_t state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(csrs, csr_port_status)); printf(PDQ_OS_PREFIX "%s", PDQ_OS_PREFIX_ARGS, pdq_adapter_states[state]); if (state == PDQS_LINK_UNAVAILABLE) { - pdq->pdq_flags &= ~PDQ_TXOK; + pdq->pdq_flags &= ~(PDQ_TXOK|PDQ_IS_ONRING|PDQ_IS_FDX); } else if (state == PDQS_LINK_AVAILABLE) { - pdq->pdq_flags |= PDQ_TXOK; + if (pdq->pdq_flags & PDQ_WANT_FDX) { + pdq->pdq_command_info.ci_pending_commands |= PDQ_BITMASK(PDQC_DEC_EXT_MIB_GET); + pdq_queue_commands(pdq); + } + pdq->pdq_flags |= PDQ_TXOK|PDQ_IS_ONRING; pdq_os_restart_transmitter(pdq); } else if (state == PDQS_HALTED) { pdq_response_error_log_get_t log_entry; @@ -1310,7 +1472,28 @@ pdq_interrupt( PDQ_CSR_READ(&pdq->pdq_pci_csrs, csr_pfi_status), data & PDQ_HOST_INT_FATAL_ERROR)); } - pdq_read_error_log(pdq, &log_entry); + PDQ_OS_MEMZERO(&log_entry, sizeof(log_entry)); + if (pdq_read_error_log(pdq, &log_entry)) { + PDQ_PRINTF((" Error log Entry:\n")); + PDQ_PRINTF((" CMD Status = %d (0x%x)\n", + log_entry.error_log_get_status, + log_entry.error_log_get_status)); + PDQ_PRINTF((" Event Status = %d (0x%x)\n", + log_entry.error_log_get_event_status, + log_entry.error_log_get_event_status)); + PDQ_PRINTF((" Caller Id = %d (0x%x)\n", + log_entry.error_log_get_caller_id, + log_entry.error_log_get_caller_id)); + PDQ_PRINTF((" Write Count = %d (0x%x)\n", + log_entry.error_log_get_write_count, + log_entry.error_log_get_write_count)); + PDQ_PRINTF((" FRU Implication Mask = %d (0x%x)\n", + log_entry.error_log_get_fru_implication_mask, + log_entry.error_log_get_fru_implication_mask)); + PDQ_PRINTF((" Test ID = %d (0x%x)\n", + log_entry.error_log_get_test_id, + log_entry.error_log_get_test_id)); + } pdq_stop(pdq); if (pdq->pdq_flags & PDQ_RUNNING) pdq_run(pdq); @@ -1350,8 +1533,11 @@ pdq_initialize( { pdq_t *pdq; pdq_state_t state; + pdq_descriptor_block_t *dbp; +#if !defined(PDQ_BUS_DMA) const pdq_uint32_t contig_bytes = (sizeof(pdq_descriptor_block_t) * 2) - PDQ_OS_PAGESIZE; pdq_uint8_t *p; +#endif int idx; PDQ_ASSERT(sizeof(pdq_descriptor_block_t) == 8192); @@ -1387,32 +1573,46 @@ pdq_initialize( * buffers (though on machines with 8KB pages we will to allocate * them separately since there will be nothing left overs.) */ +#if defined(PDQ_OS_MEMALLOC_CONTIG) p = (pdq_uint8_t *) PDQ_OS_MEMALLOC_CONTIG(contig_bytes); + +if (p == NULL) + printf("%s() - PDQ_OS_MEMALLOC_CONTIG() failed!\n", __FUNCTION__); + if (p != NULL) { - pdq_physaddr_t physaddr = PDQ_OS_VA_TO_PA(pdq, p); + pdq_physaddr_t physaddr = PDQ_OS_VA_TO_BUSPA(pdq, p); /* * Assert that we really got contiguous memory. This isn't really * needed on systems that actually have physical contiguous allocation * routines, but on those systems that don't ... */ for (idx = PDQ_OS_PAGESIZE; idx < 0x2000; idx += PDQ_OS_PAGESIZE) { - if (PDQ_OS_VA_TO_PA(pdq, p + idx) - physaddr != idx) + if (PDQ_OS_VA_TO_BUSPA(pdq, p + idx) - physaddr != idx) goto cleanup_and_return; } - physaddr &= 0x1FFF; - if (physaddr) { + if (physaddr & 0x1FFF) { pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) p; - pdq->pdq_dbp = (pdq_descriptor_block_t *) &p[0x2000 - physaddr]; + pdq->pdq_unsolicited_info.ui_pa_bufstart = physaddr; + pdq->pdq_dbp = (pdq_descriptor_block_t *) &p[0x2000 - (physaddr & 0x1FFF)]; + pdq->pdq_pa_descriptor_block = physaddr & ~0x1FFFUL; } else { pdq->pdq_dbp = (pdq_descriptor_block_t *) p; + pdq->pdq_pa_descriptor_block = physaddr; pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) &p[0x2000]; + pdq->pdq_unsolicited_info.ui_pa_bufstart = physaddr + 0x2000; } } + pdq->pdq_cbp = (volatile pdq_consumer_block_t *) &pdq->pdq_dbp->pdqdb_consumer; + pdq->pdq_pa_consumer_block = PDQ_DB_BUSPA(pdq, pdq->pdq_cbp); if (contig_bytes == sizeof(pdq_descriptor_block_t)) { pdq->pdq_unsolicited_info.ui_events = (pdq_unsolicited_event_t *) PDQ_OS_MEMALLOC( PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t)); } +#else + if (pdq_os_memalloc_contig(pdq)) + goto cleanup_and_return; +#endif /* * Make sure everything got allocated. If not, free what did @@ -1420,27 +1620,24 @@ pdq_initialize( */ if (pdq->pdq_dbp == NULL || pdq->pdq_unsolicited_info.ui_events == NULL) { cleanup_and_return: +#ifdef PDQ_OS_MEMFREE_CONTIG if (p /* pdq->pdq_dbp */ != NULL) PDQ_OS_MEMFREE_CONTIG(p /* pdq->pdq_dbp */, contig_bytes); if (contig_bytes == sizeof(pdq_descriptor_block_t) && pdq->pdq_unsolicited_info.ui_events != NULL) PDQ_OS_MEMFREE(pdq->pdq_unsolicited_info.ui_events, PDQ_NUM_UNSOLICITED_EVENTS * sizeof(pdq_unsolicited_event_t)); +#endif PDQ_OS_MEMFREE(pdq, sizeof(pdq_t)); return NULL; } - - pdq->pdq_cbp = (volatile pdq_consumer_block_t *) &pdq->pdq_dbp->pdqdb_consumer; - pdq->pdq_command_info.ci_bufstart = (pdq_uint8_t *) pdq->pdq_dbp->pdqdb_command_pool; - pdq->pdq_rx_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_receive_buffers; - - pdq->pdq_host_smt_info.rx_buffers = (void *) pdq->pdq_dbp->pdqdb_host_smt_buffers; - - PDQ_PRINTF(("\nPDQ Descriptor Block = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp)); - PDQ_PRINTF((" Recieve Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_receives)); - PDQ_PRINTF((" Transmit Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_transmits)); - PDQ_PRINTF((" Host SMT Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_host_smt)); - PDQ_PRINTF((" Command Response Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_command_responses)); - PDQ_PRINTF((" Command Request Queue = " PDQ_OS_PTR_FMT "\n", pdq->pdq_dbp->pdqdb_command_requests)); + dbp = pdq->pdq_dbp; + + PDQ_PRINTF(("\nPDQ Descriptor Block = " PDQ_OS_PTR_FMT " (PA = 0x%x)\n", dbp, pdq->pdq_pa_descriptor_block)); + PDQ_PRINTF((" Receive Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_receives)); + PDQ_PRINTF((" Transmit Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_transmits)); + PDQ_PRINTF((" Host SMT Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_host_smt)); + PDQ_PRINTF((" Command Response Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_command_responses)); + PDQ_PRINTF((" Command Request Queue = " PDQ_OS_PTR_FMT "\n", dbp->pdqdb_command_requests)); PDQ_PRINTF(("PDQ Consumer Block = " PDQ_OS_PTR_FMT "\n", pdq->pdq_cbp)); /* @@ -1449,7 +1646,7 @@ pdq_initialize( * block, command pool, and buffer pointers for the receive * host_smt rings. */ - PDQ_OS_MEMZERO(pdq->pdq_dbp, sizeof(*pdq->pdq_dbp)); + PDQ_OS_MEMZERO(dbp, sizeof(*dbp)); /* * Initialize the CSR references. @@ -1459,61 +1656,81 @@ pdq_initialize( if (pdq->pdq_type == PDQ_DEFPA) pdq_init_pci_csrs(&pdq->pdq_pci_csrs, bus, csr_base, 1); - PDQ_PRINTF(("PDQ CSRs: BASE = " PDQ_OS_PTR_FMT "\n", pdq->pdq_csrs.csr_base)); - PDQ_PRINTF((" Port Reset = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF(("PDQ CSRs: BASE = " PDQ_OS_CSR_FMT "\n", pdq->pdq_csrs.csr_base)); + PDQ_PRINTF((" Port Reset = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_port_reset, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_reset))); - PDQ_PRINTF((" Host Data = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Host Data = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_host_data, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_data))); - PDQ_PRINTF((" Port Control = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Port Control = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_port_control, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_control))); - PDQ_PRINTF((" Port Data A = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Port Data A = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_port_data_a, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_a))); - PDQ_PRINTF((" Port Data B = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Port Data B = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_port_data_b, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_data_b))); - PDQ_PRINTF((" Port Status = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Port Status = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_port_status, PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status))); - PDQ_PRINTF((" Host Int Type 0 = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Host Int Type 0 = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_host_int_type_0, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_type_0))); - PDQ_PRINTF((" Host Int Enable = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Host Int Enable = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_host_int_enable, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_int_enable))); - PDQ_PRINTF((" Type 2 Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Type 2 Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_type_2_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_type_2_producer))); - PDQ_PRINTF((" Command Response Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Command Response Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_cmd_response_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_response_producer))); - PDQ_PRINTF((" Command Request Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Command Request Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_cmd_request_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_cmd_request_producer))); - PDQ_PRINTF((" Host SMT Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Host SMT Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_host_smt_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_host_smt_producer))); - PDQ_PRINTF((" Unsolicited Producer = " PDQ_OS_PTR_FMT " [0x%08x]\n", + PDQ_PRINTF((" Unsolicited Producer = " PDQ_OS_CSR_FMT " [0x%08x]\n", pdq->pdq_csrs.csr_unsolicited_producer, PDQ_CSR_READ(&pdq->pdq_csrs, csr_unsolicited_producer))); /* * Initialize the command information block */ - pdq->pdq_command_info.ci_pa_bufstart = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_command_info.ci_bufstart); - for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_command_requests)/sizeof(pdq->pdq_dbp->pdqdb_command_requests[0]); idx++) { - pdq_txdesc_t *txd = &pdq->pdq_dbp->pdqdb_command_requests[idx]; - - txd->txd_pa_lo = pdq->pdq_command_info.ci_pa_bufstart; + pdq->pdq_command_info.ci_request_bufstart = dbp->pdqdb_cmd_request_buf; + pdq->pdq_command_info.ci_pa_request_bufstart = PDQ_DB_BUSPA(pdq, pdq->pdq_command_info.ci_request_bufstart); + pdq->pdq_command_info.ci_pa_request_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_command_requests); + PDQ_PRINTF(("PDQ Command Request Buffer = " PDQ_OS_PTR_FMT " (PA=0x%x)\n", + pdq->pdq_command_info.ci_request_bufstart, + pdq->pdq_command_info.ci_pa_request_bufstart)); + for (idx = 0; idx < sizeof(dbp->pdqdb_command_requests)/sizeof(dbp->pdqdb_command_requests[0]); idx++) { + pdq_txdesc_t *txd = &dbp->pdqdb_command_requests[idx]; + + txd->txd_pa_lo = pdq->pdq_command_info.ci_pa_request_bufstart; txd->txd_eop = txd->txd_sop = 1; txd->txd_pa_hi = 0; } - for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_command_responses)/sizeof(pdq->pdq_dbp->pdqdb_command_responses[0]); idx++) { - pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_command_responses[idx]; - - rxd->rxd_pa_lo = pdq->pdq_command_info.ci_pa_bufstart; + PDQ_OS_DESC_PRESYNC(pdq, dbp->pdqdb_command_requests, + sizeof(dbp->pdqdb_command_requests)); + + pdq->pdq_command_info.ci_response_bufstart = dbp->pdqdb_cmd_response_buf; + pdq->pdq_command_info.ci_pa_response_bufstart = PDQ_DB_BUSPA(pdq, pdq->pdq_command_info.ci_response_bufstart); + pdq->pdq_command_info.ci_pa_response_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_command_responses); + PDQ_PRINTF(("PDQ Command Response Buffer = " PDQ_OS_PTR_FMT " (PA=0x%x)\n", + pdq->pdq_command_info.ci_response_bufstart, + pdq->pdq_command_info.ci_pa_response_bufstart)); + for (idx = 0; idx < sizeof(dbp->pdqdb_command_responses)/sizeof(dbp->pdqdb_command_responses[0]); idx++) { + pdq_rxdesc_t *rxd = &dbp->pdqdb_command_responses[idx]; + + rxd->rxd_pa_lo = pdq->pdq_command_info.ci_pa_response_bufstart; rxd->rxd_sop = 1; rxd->rxd_seg_cnt = 0; rxd->rxd_seg_len_lo = 0; + rxd->rxd_seg_len_hi = PDQ_SIZE_COMMAND_RESPONSE / 16; } + PDQ_OS_DESC_PRESYNC(pdq, dbp->pdqdb_command_responses, + sizeof(dbp->pdqdb_command_responses)); /* * Initialize the unsolicited event information block */ pdq->pdq_unsolicited_info.ui_free = PDQ_NUM_UNSOLICITED_EVENTS; - pdq->pdq_unsolicited_info.ui_pa_bufstart = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_unsolicited_info.ui_events); - for (idx = 0; idx < sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events)/sizeof(pdq->pdq_dbp->pdqdb_unsolicited_events[0]); idx++) { - pdq_rxdesc_t *rxd = &pdq->pdq_dbp->pdqdb_unsolicited_events[idx]; + pdq->pdq_unsolicited_info.ui_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_unsolicited_events); + PDQ_PRINTF(("PDQ Unsolicit Event Buffer = " PDQ_OS_PTR_FMT " (PA=0x%x)\n", + pdq->pdq_unsolicited_info.ui_events, + pdq->pdq_unsolicited_info.ui_pa_bufstart)); + for (idx = 0; idx < sizeof(dbp->pdqdb_unsolicited_events)/sizeof(dbp->pdqdb_unsolicited_events[0]); idx++) { + pdq_rxdesc_t *rxd = &dbp->pdqdb_unsolicited_events[idx]; pdq_unsolicited_event_t *event = &pdq->pdq_unsolicited_info.ui_events[idx & (PDQ_NUM_UNSOLICITED_EVENTS-1)]; rxd->rxd_sop = 1; @@ -1522,26 +1739,35 @@ pdq_initialize( rxd->rxd_pa_lo = pdq->pdq_unsolicited_info.ui_pa_bufstart + (const pdq_uint8_t *) event - (const pdq_uint8_t *) pdq->pdq_unsolicited_info.ui_events; rxd->rxd_pa_hi = 0; + PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, event); } + PDQ_OS_DESC_PRESYNC(pdq, dbp->pdqdb_unsolicited_events, + sizeof(dbp->pdqdb_unsolicited_events)); + /* * Initialize the receive information blocks (normal and SMT). */ - pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_receives); + pdq->pdq_rx_info.rx_buffers = pdq->pdq_receive_buffers; + pdq->pdq_rx_info.rx_free = PDQ_RING_MASK(dbp->pdqdb_receives); pdq->pdq_rx_info.rx_target = pdq->pdq_rx_info.rx_free - PDQ_RX_SEGCNT * 8; + pdq->pdq_rx_info.rx_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_receives); - pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_host_smt); + pdq->pdq_host_smt_info.rx_buffers = pdq->pdq_host_smt_buffers; + pdq->pdq_host_smt_info.rx_free = PDQ_RING_MASK(dbp->pdqdb_host_smt); pdq->pdq_host_smt_info.rx_target = pdq->pdq_host_smt_info.rx_free - PDQ_RX_SEGCNT * 3; + pdq->pdq_host_smt_info.rx_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_host_smt); /* * Initialize the transmit information block. */ - pdq->pdq_tx_hdr[0] = PDQ_FDDI_PH0; - pdq->pdq_tx_hdr[1] = PDQ_FDDI_PH1; - pdq->pdq_tx_hdr[2] = PDQ_FDDI_PH2; - pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(pdq->pdq_dbp->pdqdb_transmits); - pdq->pdq_tx_info.tx_hdrdesc.txd_seg_len = sizeof(pdq->pdq_tx_hdr); + dbp->pdqdb_tx_hdr[0] = PDQ_FDDI_PH0; + dbp->pdqdb_tx_hdr[1] = PDQ_FDDI_PH1; + dbp->pdqdb_tx_hdr[2] = PDQ_FDDI_PH2; + pdq->pdq_tx_info.tx_free = PDQ_RING_MASK(dbp->pdqdb_transmits); + pdq->pdq_tx_info.tx_hdrdesc.txd_seg_len = 3; pdq->pdq_tx_info.tx_hdrdesc.txd_sop = 1; - pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_OS_VA_TO_PA(pdq, pdq->pdq_tx_hdr); + pdq->pdq_tx_info.tx_hdrdesc.txd_pa_lo = PDQ_DB_BUSPA(pdq, dbp->pdqdb_tx_hdr); + pdq->pdq_tx_info.tx_pa_descriptors = PDQ_DB_BUSPA(pdq, dbp->pdqdb_transmits); state = PDQ_PSTS_ADAPTER_STATE(PDQ_CSR_READ(&pdq->pdq_csrs, csr_port_status)); PDQ_PRINTF(("PDQ Adapter State = %s\n", pdq_adapter_states[state])); diff --git a/sys/dev/pdq/pdq_freebsd.h b/sys/dev/pdq/pdq_freebsd.h new file mode 100644 index 0000000..fd556b9 --- /dev/null +++ b/sys/dev/pdq/pdq_freebsd.h @@ -0,0 +1,271 @@ +/* $NetBSD: pdqvar.h,v 1.27 2000/05/03 19:17:54 thorpej Exp $ */ + +/*- + * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Id: pdqvar.h,v 1.21 1997/03/21 21:16:04 thomas Exp + * $FreeBSD$ + * + */ + +/* + * DEC PDQ FDDI Controller; PDQ O/S dependent definitions + * + * Written by Matt Thomas + * + */ + +#if defined(PDQ_HWSUPPORT) +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/malloc.h> +#include <sys/socket.h> +#include <sys/sockio.h> + +#include <sys/module.h> +#include <sys/bus.h> + +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/if_dl.h> +#include <net/if_media.h> +#include <net/fddi.h> + +#include <net/bpf.h> + +#include <vm/vm.h> /* for vtophys */ +#include <vm/pmap.h> /* for vtophys */ +#include <machine/clock.h> /* for DELAY */ + +#endif /* PDQ_HWSUPPORT */ + +typedef struct _pdq_t pdq_t; +typedef struct _pdq_csrs_t pdq_csrs_t; +typedef struct _pdq_pci_csrs_t pdq_pci_csrs_t; +typedef struct _pdq_lanaddr_t pdq_lanaddr_t; +typedef unsigned int pdq_uint32_t; +typedef unsigned short pdq_uint16_t; +typedef unsigned char pdq_uint8_t; +typedef enum _pdq_boolean_t pdq_boolean_t; +typedef enum _pdq_type_t pdq_type_t; +typedef enum _pdq_state_t pdq_state_t; +typedef struct mbuf PDQ_OS_DATABUF_T; + +typedef bus_space_tag_t pdq_bus_t; +typedef bus_space_handle_t pdq_bus_memaddr_t; +typedef pdq_bus_memaddr_t pdq_bus_memoffset_t; + +extern devclass_t pdq_devclass; + +enum _pdq_type_t { + PDQ_DEFPA, /* PCI-bus */ + PDQ_DEFEA, /* EISA-bus */ + PDQ_DEFTA, /* TurboChannel */ + PDQ_DEFAA, /* FutureBus+ */ + PDQ_DEFQA /* Q-bus */ +}; + +#define sc_ifmedia ifmedia +#define sc_if arpcom.ac_if +#define sc_bpf sc_if.if_bpf +#define IFQ_DEQUEUE IF_DEQUEUE +#define IFQ_IS_EMPTY(q) ((q)->ifq_len == 0) + +typedef struct _pdq_os_ctx_t { + struct arpcom arpcom; + struct ifmedia ifmedia; + device_t dev; + int debug; + + pdq_t * sc_pdq; + int sc_flags; +#define PDQIF_DOWNCALL 0x0001 /* active calling from if to pdq */ + + struct resource * io; + int io_rid; + int io_type; + bus_space_handle_t io_bsh; + bus_space_tag_t io_bst; + + struct resource * mem; + int mem_rid; + int mem_type; + bus_space_handle_t mem_bsh; + bus_space_tag_t mem_bst; + + struct resource * irq; + int irq_rid; + void * irq_ih; + + struct mtx mtx; +} pdq_softc_t; + +#define PDQ_LOCK(_sc) mtx_lock(&(_sc)->mtx) +#define PDQ_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) + +#define PDQ_OS_HDR_OFFSET PDQ_RX_FC_OFFSET + +#define PDQ_OS_PAGESIZE PAGE_SIZE +#define PDQ_OS_TX_TRANSMIT 5 + +#define PDQ_OS_IORD_32(bt, bh, off) bus_space_read_4(bt, bh, off) +#define PDQ_OS_IOWR_32(bt, bh, off, data) bus_space_write_4(bt, bh, off, data) +#define PDQ_OS_IORD_8(bt, bh, off) bus_space_read_1(bt, bh, off) +#define PDQ_OS_IOWR_8(bt, bh, off, data) bus_space_write_1(bt, bh, off, data) + +#define PDQ_CSR_OFFSET(base, offset) (0 + (offset)*sizeof(pdq_uint32_t)) +#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_IOWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data) +#define PDQ_CSR_READ(csr, name) PDQ_OS_IORD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name) + +#define PDQ_OS_DATABUF_FREE(pdq, b) (m_freem(b)) + +#if defined(PDQ_OSSUPPORT) +#define PDQ_OS_TX_TIMEOUT 5 /* seconds */ + +#define PDQ_OS_IFP_TO_SOFTC(ifp) ((pdq_softc_t *) (ifp)->if_softc) +#define PDQ_BPF_MTAP(sc, m) bpf_mtap(&(sc)->arpcom.ac_if, m) + +#endif /* PDQ_OSSUPPORT */ + +#if defined(PDQ_HWSUPPORT) + +#define PDQ_OS_PREFIX "%s%d: " +#define PDQ_OS_PREFIX_ARGS pdq->pdq_os_name, pdq->pdq_unit + +#define PDQ_OS_PTR_FMT "%p" +#define PDQ_OS_CSR_FMT "0x%x" + +#define PDQ_OS_USEC_DELAY(n) DELAY(n) +#define PDQ_OS_VA_TO_BUSPA(pdq, p) vtophys(p) + +#define PDQ_OS_MEMALLOC(n) malloc(n, M_DEVBUF, M_NOWAIT) +#define PDQ_OS_MEMFREE(p, n) free((void *) p, M_DEVBUF) +#define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n)) +#define PDQ_OS_MEMALLOC_CONTIG(n) contigmalloc(n, M_DEVBUF, M_NOWAIT, 0x800000, ~0, PAGE_SIZE, 0) +#define PDQ_OS_MEMFREE_CONTIG(p, n) contigfree(p, n, M_DEVBUF) + +#define PDQ_OS_DATABUF_SIZE (MCLBYTES) +#define PDQ_OS_DATABUF_NEXT(b) ((b)->m_next) +#define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->m_next = (b1)) +#define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->m_nextpkt) +#define PDQ_OS_DATABUF_NEXTPKT_SET(b, b1) ((b)->m_nextpkt = (b1)) +#define PDQ_OS_DATABUF_LEN(b) ((b)->m_len) +#define PDQ_OS_DATABUF_LEN_SET(b, n) ((b)->m_len = (n)) +/* #define PDQ_OS_DATABUF_LEN_ADJ(b, n) ((b)->m_len += (n)) */ +#define PDQ_OS_DATABUF_PTR(b) (mtod((b), pdq_uint8_t *)) +#define PDQ_OS_DATABUF_ADJ(b, n) ((b)->m_data += (n), (b)->m_len -= (n)) + +#define PDQ_OS_DATABUF_ALLOC(pdq, b) do { \ + PDQ_OS_DATABUF_T *x_m0; \ + MGETHDR(x_m0, M_DONTWAIT, MT_DATA); \ + if (x_m0 != NULL) { \ + MCLGET(x_m0, M_DONTWAIT); \ + if ((x_m0->m_flags & M_EXT) == 0) { \ + m_free(x_m0); \ + (b) = NULL; \ + } else { \ + (b) = x_m0; \ + x_m0->m_len = PDQ_OS_DATABUF_SIZE; \ + } \ + } else { \ + (b) = NULL; \ + } \ +} while (0) + +#define PDQ_OS_DATABUF_RESET(b) ((b)->m_data = (b)->m_ext.ext_buf, (b)->m_len = MCLBYTES) + +#define PDQ_OS_DATABUF_ENQUEUE(q, b) do { \ + PDQ_OS_DATABUF_NEXTPKT_SET(b, NULL); \ + if ((q)->q_tail == NULL) \ + (q)->q_head = (b); \ + else \ + PDQ_OS_DATABUF_NEXTPKT_SET(((PDQ_OS_DATABUF_T *)(q)->q_tail), b); \ + (q)->q_tail = (b); \ +} while (0) + +#define PDQ_OS_DATABUF_DEQUEUE(q, b) do { \ + if (((b) = (PDQ_OS_DATABUF_T *) (q)->q_head) != NULL) { \ + if (((q)->q_head = PDQ_OS_DATABUF_NEXTPKT(b)) == NULL) \ + (q)->q_tail = NULL; \ + PDQ_OS_DATABUF_NEXTPKT_SET(b, NULL); \ + } \ +} while (0) + +#define PDQ_OS_DATABUF_BUSPA(pdq, b) PDQ_OS_VA_TO_BUSPA(pdq, PDQ_OS_DATABUF_PTR(b)) + +#define PDQ_OS_CONSUMER_PRESYNC(pdq) do { } while(0) +#define PDQ_OS_CONSUMER_POSTSYNC(pdq) do { } while(0) +#define PDQ_OS_DESC_PRESYNC(pdq, d, s) do { } while(0) +#define PDQ_OS_DESC_POSTSYNC(pdq, d, s) do { } while(0) +#define PDQ_OS_CMDRQST_PRESYNC(pdq, s) do { } while(0) +#define PDQ_OS_CMDRQST_POSTSYNC(pdq, s) do { } while(0) +#define PDQ_OS_CMDRSP_PRESYNC(pdq, s) do { } while(0) +#define PDQ_OS_CMDRSP_POSTSYNC(pdq, s) do { } while(0) +#define PDQ_OS_RXPDU_PRESYNC(pdq, b, o, l) do { } while(0) +#define PDQ_OS_RXPDU_POSTSYNC(pdq, b, o, l) do { } while(0) +#define PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, e) do { } while(0) +#define PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, e) do { } while(0) + +#endif /* PDQ_HWSUPPORT */ + +/* + * OS dependent functions provided by pdq_ifsubr.c to pdq.c + */ +void pdq_os_addr_fill (pdq_t *pdq, pdq_lanaddr_t *addrs, size_t numaddrs); +void pdq_os_receive_pdu (pdq_t *, PDQ_OS_DATABUF_T *, size_t, int); +void pdq_os_restart_transmitter (pdq_t *pdq); +void pdq_os_transmit_done (pdq_t *, PDQ_OS_DATABUF_T *); +void pdq_os_update_status (pdq_t *, const void *); + +/* + * Driver interfaces functions provided by pdq.c to pdq_ifsubr.c + */ +pdq_boolean_t pdq_queue_transmit_data (pdq_t *pdq, PDQ_OS_DATABUF_T *pdu); +void pdq_run (pdq_t *pdq); +pdq_state_t pdq_stop (pdq_t *pdq); + +/* + * OS dependent functions provided by + * pdq_ifsubr.c or pdq.c to the bus front ends + */ +void pdq_ifattach (pdq_softc_t *); +void pdq_ifdetach (pdq_softc_t *); +void pdq_free (device_t); +int pdq_interrupt (pdq_t *pdq); +void pdq_hwreset (pdq_t *pdq); +pdq_t * pdq_initialize (pdq_bus_t bus, pdq_bus_memaddr_t csr_va, + const char *name, int unit, + void *ctx, pdq_type_t type); +/* + * Misc prototypes. + */ +void pdq_flush_transmitter(pdq_t *pdq); diff --git a/sys/dev/pdq/pdq_ifsubr.c b/sys/dev/pdq/pdq_ifsubr.c index ad8e02a..5a9a4a1 100644 --- a/sys/dev/pdq/pdq_ifsubr.c +++ b/sys/dev/pdq/pdq_ifsubr.c @@ -1,3 +1,5 @@ +/* $NetBSD: pdq_ifsubr.c,v 1.38 2001/12/21 23:21:47 matt Exp $ */ + /*- * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com> * All rights reserved. @@ -8,7 +10,7 @@ * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission + * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -21,8 +23,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * $NetBSD: pdq_ifsubr.c,v 1.12 1997/06/05 01:56:35 thomas Exp$ * $FreeBSD$ - * */ /* @@ -32,65 +34,45 @@ * (ie. it provides an ifnet interface to the rest of the system) */ +#ifdef __NetBSD__ +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: pdq_ifsubr.c,v 1.38 2001/12/21 23:21:47 matt Exp $"); +#endif -#include "opt_inet.h" +#define PDQ_OSSUPPORT #include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/malloc.h> #include <sys/socket.h> #include <sys/sockio.h> -#if defined(__bsdi__) || defined(__NetBSD__) -#include <sys/device.h> -#endif + +#include <sys/module.h> +#include <sys/bus.h> + +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> #include <net/if.h> +#include <net/if_arp.h> #include <net/if_dl.h> +#include <net/if_media.h> +#include <net/fddi.h> #include <net/bpf.h> -#if defined(__FreeBSD__) -#ifdef INET -#include <netinet/in.h> -#include <netinet/if_ether.h> -#endif -#include <netinet/if_fddi.h> -#else -#include <net/if_fddi.h> -#endif - -#if defined(__bsdi__) -#include <i386/isa/isavar.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#if defined(__FreeBSD__) -#include <dev/pdq/pdqvar.h> +#include <dev/pdq/pdq_freebsd.h> #include <dev/pdq/pdqreg.h> -#else -#include "pdqvar.h" -#include "pdqreg.h" -#endif -#if defined(__bsdi__) && _BSDI_VERSION < 199506 /* XXX */ -static void -arp_ifinit( - struct arpcom *ac, - struct ifaddr *ifa) -{ - sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr; - arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr); -#if _BSDI_VERSION >= 199401 - ifa->ifa_rtrequest = arp_rtrequest; - ifa->ifa_flags |= RTF_CLONING; -#endif -} -#endif +devclass_t pdq_devclass; - -void +static void pdq_ifinit( pdq_softc_t *sc) { @@ -101,11 +83,6 @@ pdq_ifinit( } else { sc->sc_pdq->pdq_flags &= ~PDQ_PROMISC; } - if (sc->sc_if.if_flags & IFF_ALLMULTI) { - sc->sc_pdq->pdq_flags |= PDQ_ALLMULTI; - } else { - sc->sc_pdq->pdq_flags &= ~PDQ_ALLMULTI; - } if (sc->sc_if.if_flags & IFF_LINK1) { sc->sc_pdq->pdq_flags |= PDQ_PASS_SMT; } else { @@ -120,7 +97,7 @@ pdq_ifinit( } } -void +static void pdq_ifwatchdog( struct ifnet *ifp) { @@ -131,15 +108,20 @@ pdq_ifwatchdog( ifp->if_flags &= ~IFF_OACTIVE; ifp->if_timer = 0; - IF_DRAIN(&ifp->if_snd); + for (;;) { + struct mbuf *m; + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) + return; + PDQ_OS_DATABUF_FREE(PDQ_OS_IFP_TO_SOFTC(ifp)->sc_pdq, m); + } } -ifnet_ret_t +static void pdq_ifstart( struct ifnet *ifp) { - pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if)); - struct ifqueue *ifq = &ifp->if_snd; + pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp); struct mbuf *m; int tx = 0; @@ -153,41 +135,95 @@ pdq_ifstart( sc->sc_if.if_flags |= IFF_OACTIVE; return; } + sc->sc_flags |= PDQIF_DOWNCALL; for (;; tx = 1) { - IF_DEQUEUE(ifq, m); + IF_DEQUEUE(&ifp->if_snd, m); if (m == NULL) break; +#if defined(PDQ_BUS_DMA) && !defined(PDQ_BUS_DMA_NOTX) + if ((m->m_flags & M_HASTXDMAMAP) == 0) { + bus_dmamap_t map; + if (PDQ_OS_HDR_OFFSET != PDQ_RX_FC_OFFSET) { + m->m_data[0] = PDQ_FDDI_PH0; + m->m_data[1] = PDQ_FDDI_PH1; + m->m_data[2] = PDQ_FDDI_PH2; + } + if (!bus_dmamap_create(sc->sc_dmatag, m->m_pkthdr.len, 255, + m->m_pkthdr.len, 0, BUS_DMA_NOWAIT, &map)) { + if (!bus_dmamap_load_mbuf(sc->sc_dmatag, map, m, + BUS_DMA_WRITE|BUS_DMA_NOWAIT)) { + bus_dmamap_sync(sc->sc_dmatag, map, 0, m->m_pkthdr.len, + BUS_DMASYNC_PREWRITE); + M_SETCTX(m, map); + m->m_flags |= M_HASTXDMAMAP; + } + } + if ((m->m_flags & M_HASTXDMAMAP) == 0) + break; + } +#else + if (PDQ_OS_HDR_OFFSET != PDQ_RX_FC_OFFSET) { + m->m_data[0] = PDQ_FDDI_PH0; + m->m_data[1] = PDQ_FDDI_PH1; + m->m_data[2] = PDQ_FDDI_PH2; + } +#endif - if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) { - ifp->if_flags |= IFF_OACTIVE; - IF_PREPEND(ifq, m); + if (pdq_queue_transmit_data(sc->sc_pdq, m) == PDQ_FALSE) break; - } + } + if (m != NULL) { + ifp->if_flags |= IFF_OACTIVE; + IF_PREPEND(&ifp->if_snd, m); } if (tx) PDQ_DO_TYPE2_PRODUCER(sc->sc_pdq); + sc->sc_flags &= ~PDQIF_DOWNCALL; } void pdq_os_receive_pdu( pdq_t *pdq, struct mbuf *m, - size_t pktlen) + size_t pktlen, + int drop) { - pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx; - struct fddi_header *fh = mtod(m, struct fddi_header *); + pdq_softc_t *sc = pdq->pdq_os_ctx; + struct fddi_header *fh; sc->sc_if.if_ipackets++; +#if defined(PDQ_BUS_DMA) + { + /* + * Even though the first mbuf start at the first fddi header octet, + * the dmamap starts PDQ_OS_HDR_OFFSET octets earlier. Any additional + * mbufs will start normally. + */ + int offset = PDQ_OS_HDR_OFFSET; + struct mbuf *m0; + for (m0 = m; m0 != NULL; m0 = m0->m_next, offset = 0) { + pdq_os_databuf_sync(sc, m0, offset, m0->m_len, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->sc_dmatag, M_GETCTX(m0, bus_dmamap_t)); + bus_dmamap_destroy(sc->sc_dmatag, M_GETCTX(m0, bus_dmamap_t)); + m0->m_flags &= ~M_HASRXDMAMAP; + M_SETCTX(m0, NULL); + } + } +#endif + m->m_pkthdr.len = pktlen; +#if NBPFILTER > 0 if (sc->sc_bpf != NULL) PDQ_BPF_MTAP(sc, m); - if ((fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) { - m_freem(m); +#endif + fh = mtod(m, struct fddi_header *); + if (drop || (fh->fddi_fc & (FDDIFC_L|FDDIFC_F)) != FDDIFC_LLC_ASYNC) { + sc->sc_if.if_iqdrops++; + sc->sc_if.if_ierrors++; + PDQ_OS_DATABUF_FREE(pdq, m); return; } - m->m_data += sizeof(struct fddi_header); - m->m_len -= sizeof(struct fddi_header); - m->m_pkthdr.len = pktlen - sizeof(struct fddi_header); + m_adj(m, FDDI_HDR_LEN); m->m_pkthdr.rcvif = &sc->sc_if; fddi_input(&sc->sc_if, fh, m); } @@ -196,11 +232,12 @@ void pdq_os_restart_transmitter( pdq_t *pdq) { - pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx; + pdq_softc_t *sc = pdq->pdq_os_ctx; sc->sc_if.if_flags &= ~IFF_OACTIVE; - if (sc->sc_if.if_snd.ifq_head != NULL) { + if (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0) { sc->sc_if.if_timer = PDQ_OS_TX_TIMEOUT; - pdq_ifstart(&sc->sc_if); + if ((sc->sc_flags & PDQIF_DOWNCALL) == 0) + pdq_ifstart(&sc->sc_if); } else { sc->sc_if.if_timer = 0; } @@ -211,10 +248,12 @@ pdq_os_transmit_done( pdq_t *pdq, struct mbuf *m) { - pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx; + pdq_softc_t *sc = pdq->pdq_os_ctx; +#if NBPFILTER > 0 if (sc->sc_bpf != NULL) PDQ_BPF_MTAP(sc, m); - m_freem(m); +#endif + PDQ_OS_DATABUF_FREE(pdq, m); sc->sc_if.if_opackets++; } @@ -224,9 +263,23 @@ pdq_os_addr_fill( pdq_lanaddr_t *addr, size_t num_addrs) { - pdq_softc_t *sc = (pdq_softc_t *) pdq->pdq_os_ctx; + pdq_softc_t *sc = pdq->pdq_os_ctx; + struct ifnet *ifp; struct ifmultiaddr *ifma; + ifp = &sc->arpcom.ac_if; + + /* + * ADDR_FILTER_SET is always issued before FILTER_SET so + * we can play with PDQ_ALLMULTI and not worry about + * queueing a FILTER_SET ourselves. + */ + + pdq->pdq_flags &= ~PDQ_ALLMULTI; +#if defined(IFF_ALLMULTI) + sc->sc_if.if_flags &= ~IFF_ALLMULTI; +#endif + for (ifma = TAILQ_FIRST(&sc->sc_if.if_multiaddrs); ifma && num_addrs > 0; ifma = TAILQ_NEXT(ifma, ifma_link)) { char *mcaddr; @@ -239,66 +292,95 @@ pdq_os_addr_fill( addr++; num_addrs--; } + /* + * If not all the address fit into the CAM, turn on all-multicast mode. + */ + if (ifma != NULL) { + pdq->pdq_flags |= PDQ_ALLMULTI; +#if defined(IFF_ALLMULTI) + sc->sc_if.if_flags |= IFF_ALLMULTI; +#endif + } } -int +#if defined(IFM_FDDI) +static int +pdq_ifmedia_change( + struct ifnet *ifp) +{ + pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp); + + if (sc->sc_ifmedia.ifm_media & IFM_FDX) { + if ((sc->sc_pdq->pdq_flags & PDQ_WANT_FDX) == 0) { + sc->sc_pdq->pdq_flags |= PDQ_WANT_FDX; + if (sc->sc_pdq->pdq_flags & PDQ_RUNNING) + pdq_run(sc->sc_pdq); + } + } else if (sc->sc_pdq->pdq_flags & PDQ_WANT_FDX) { + sc->sc_pdq->pdq_flags &= ~PDQ_WANT_FDX; + if (sc->sc_pdq->pdq_flags & PDQ_RUNNING) + pdq_run(sc->sc_pdq); + } + + return 0; +} + +static void +pdq_ifmedia_status( + struct ifnet *ifp, + struct ifmediareq *ifmr) +{ + pdq_softc_t * const sc = PDQ_OS_IFP_TO_SOFTC(ifp); + + ifmr->ifm_status = IFM_AVALID; + if (sc->sc_pdq->pdq_flags & PDQ_IS_ONRING) + ifmr->ifm_status |= IFM_ACTIVE; + + ifmr->ifm_active = (ifmr->ifm_current & ~IFM_FDX); + if (sc->sc_pdq->pdq_flags & PDQ_IS_FDX) + ifmr->ifm_active |= IFM_FDX; +} + +void +pdq_os_update_status( + pdq_t *pdq, + const void *arg) +{ + pdq_softc_t * const sc = pdq->pdq_os_ctx; + const pdq_response_status_chars_get_t *rsp = arg; + int media = 0; + + switch (rsp->status_chars_get.pmd_type[0]) { + case PDQ_PMD_TYPE_ANSI_MUTLI_MODE: media = IFM_FDDI_MMF; break; + case PDQ_PMD_TYPE_ANSI_SINGLE_MODE_TYPE_1: media = IFM_FDDI_SMF; break; + case PDQ_PMD_TYPE_ANSI_SIGNLE_MODE_TYPE_2: media = IFM_FDDI_SMF; break; + case PDQ_PMD_TYPE_UNSHIELDED_TWISTED_PAIR: media = IFM_FDDI_UTP; break; + default: media |= IFM_MANUAL; + } + + if (rsp->status_chars_get.station_type == PDQ_STATION_TYPE_DAS) + media |= IFM_FDDI_DA; + + sc->sc_ifmedia.ifm_media = media | IFM_FDDI; +} +#endif /* defined(IFM_FDDI) */ + +static int pdq_ifioctl( struct ifnet *ifp, - ioctl_cmd_t cmd, + u_long cmd, caddr_t data) { - pdq_softc_t *sc = (pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if)); - int s, error = 0; + pdq_softc_t *sc = PDQ_OS_IFP_TO_SOFTC(ifp); + int error = 0; - s = splimp(); + PDQ_LOCK(sc); switch (cmd) { + case SIOCSIFMTU: + case SIOCGIFADDR: case SIOCSIFADDR: { - struct ifaddr *ifa = (struct ifaddr *)data; - - ifp->if_flags |= IFF_UP; - switch(ifa->ifa_addr->sa_family) { -#if defined(INET) - case AF_INET: { - pdq_ifinit(sc); - arp_ifinit(&sc->sc_ac.ac_if, ifa); - break; - } -#endif /* INET */ - -#if defined(NS) - /* This magic copied from if_is.c; I don't use XNS, - * so I have no way of telling if this actually - * works or not. - */ - case AF_NS: { - struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); - if (ns_nullhost(*ina)) { - ina->x_host = *(union ns_host *)(sc->sc_ac.ac_enaddr); - } else { - ifp->if_flags &= ~IFF_RUNNING; - bcopy((caddr_t)ina->x_host.c_host, - (caddr_t)sc->sc_ac.ac_enaddr, - sizeof sc->sc_ac.ac_enaddr); - } - - pdq_ifinit(sc); - break; - } -#endif /* NS */ - - default: { - pdq_ifinit(sc); - break; - } - } - break; - } - case SIOCGIFADDR: { - struct ifreq *ifr = (struct ifreq *)data; - bcopy((caddr_t) sc->sc_ac.ac_enaddr, - (caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data, - 6); + error = fddi_ioctl(ifp, cmd, data); break; } @@ -308,32 +390,22 @@ pdq_ifioctl( } case SIOCADDMULTI: - case SIOCDELMULTI: - /* - * Update multicast listeners - */ - if (sc->sc_if.if_flags & IFF_RUNNING) - pdq_run(sc->sc_pdq); + case SIOCDELMULTI: { + if (sc->sc_if.if_flags & IFF_RUNNING) { + pdq_run(sc->sc_pdq); error = 0; - break; + } + break; + } -#if defined(SIOCSIFMTU) -#if !defined(ifr_mtu) -#define ifr_mtu ifr_metric -#endif - case SIOCSIFMTU: { +#if defined(IFM_FDDI) && defined(SIOCSIFMEDIA) + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: { struct ifreq *ifr = (struct ifreq *)data; - /* - * Set the interface MTU. - */ - if (ifr->ifr_mtu > FDDIMTU) { - error = EINVAL; - break; - } - ifp->if_mtu = ifr->ifr_mtu; + error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd); break; } -#endif /* SIOCSIFMTU */ +#endif default: { error = EINVAL; @@ -341,7 +413,7 @@ pdq_ifioctl( } } - splx(s); + PDQ_UNLOCK(sc); return error; } @@ -350,12 +422,15 @@ pdq_ifioctl( #endif void -pdq_ifattach( - pdq_softc_t *sc, - ifnet_ret_t (*ifwatchdog)(int unit)) +pdq_ifattach(pdq_softc_t *sc) { struct ifnet *ifp = &sc->sc_if; + mtx_init(&sc->mtx, device_get_nameunit(sc->dev), MTX_DEF | MTX_RECURSE); + + ifp->if_softc = sc; + ifp->if_init = (if_init_f_t *)pdq_ifinit; + ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; #if (defined(__FreeBSD__) && BSD >= 199506) || defined(__NetBSD__) @@ -365,13 +440,296 @@ pdq_ifattach( #endif ifp->if_ioctl = pdq_ifioctl; +#if !defined(__NetBSD__) && !defined(__FreeBSD__) ifp->if_output = fddi_output; +#endif ifp->if_start = pdq_ifstart; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; -#warning "Implement fddi_resolvemulti!" -/* ifp->if_resolvemulti = ether_resolvemulti; XXX */ + +#if defined(IFM_FDDI) + { + const int media = sc->sc_ifmedia.ifm_media; + ifmedia_init(&sc->sc_ifmedia, IFM_FDX, + pdq_ifmedia_change, pdq_ifmedia_status); + ifmedia_add(&sc->sc_ifmedia, media, 0, 0); + ifmedia_set(&sc->sc_ifmedia, media); + } +#endif if_attach(ifp); - fddi_ifattach(ifp); - PDQ_BPFATTACH(sc, DLT_FDDI, sizeof(struct fddi_header)); +#if defined(__NetBSD__) + fddi_ifattach(ifp, (caddr_t)&sc->sc_pdq->pdq_hwaddr); +#else + fddi_ifattach(ifp, FDDI_BPF_SUPPORTED); +#endif +} + +void +pdq_ifdetach (pdq_softc_t *sc) +{ + struct ifnet *ifp; + + ifp = &sc->arpcom.ac_if; + + fddi_ifdetach(ifp, FDDI_BPF_SUPPORTED); + pdq_stop(sc->sc_pdq); + pdq_free(sc->dev); + + return; +} + +void +pdq_free (device_t dev) +{ + pdq_softc_t *sc; + + sc = device_get_softc(dev); + + if (sc->io) + bus_release_resource(dev, sc->io_type, sc->io_rid, sc->io); + if (sc->mem) + bus_release_resource(dev, sc->mem_type, sc->mem_rid, sc->mem); + if (sc->irq_ih) + bus_teardown_intr(dev, sc->irq, sc->irq_ih); + if (sc->irq) + bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq); + + /* + * Destroy the mutex. + */ + if (mtx_initialized(&sc->mtx) != 0) { + mtx_destroy(&sc->mtx); + } + + return; +} + +#if defined(PDQ_BUS_DMA) +int +pdq_os_memalloc_contig( + pdq_t *pdq) +{ + pdq_softc_t * const sc = pdq->pdq_os_ctx; + bus_dma_segment_t db_segs[1], ui_segs[1], cb_segs[1]; + int db_nsegs = 0, ui_nsegs = 0; + int steps = 0; + int not_ok; + + not_ok = bus_dmamem_alloc(sc->sc_dmatag, + sizeof(*pdq->pdq_dbp), sizeof(*pdq->pdq_dbp), + sizeof(*pdq->pdq_dbp), db_segs, 1, &db_nsegs, + BUS_DMA_NOWAIT); + if (!not_ok) { + steps = 1; + not_ok = bus_dmamem_map(sc->sc_dmatag, db_segs, db_nsegs, + sizeof(*pdq->pdq_dbp), (caddr_t *) &pdq->pdq_dbp, + BUS_DMA_NOWAIT); + } + if (!not_ok) { + steps = 2; + not_ok = bus_dmamap_create(sc->sc_dmatag, db_segs[0].ds_len, 1, + 0x2000, 0, BUS_DMA_NOWAIT, &sc->sc_dbmap); + } + if (!not_ok) { + steps = 3; + not_ok = bus_dmamap_load(sc->sc_dmatag, sc->sc_dbmap, + pdq->pdq_dbp, sizeof(*pdq->pdq_dbp), + NULL, BUS_DMA_NOWAIT); + } + if (!not_ok) { + steps = 4; + pdq->pdq_pa_descriptor_block = sc->sc_dbmap->dm_segs[0].ds_addr; + not_ok = bus_dmamem_alloc(sc->sc_dmatag, + PDQ_OS_PAGESIZE, PDQ_OS_PAGESIZE, PDQ_OS_PAGESIZE, + ui_segs, 1, &ui_nsegs, BUS_DMA_NOWAIT); + } + if (!not_ok) { + steps = 5; + not_ok = bus_dmamem_map(sc->sc_dmatag, ui_segs, ui_nsegs, + PDQ_OS_PAGESIZE, + (caddr_t *) &pdq->pdq_unsolicited_info.ui_events, + BUS_DMA_NOWAIT); + } + if (!not_ok) { + steps = 6; + not_ok = bus_dmamap_create(sc->sc_dmatag, ui_segs[0].ds_len, 1, + PDQ_OS_PAGESIZE, 0, BUS_DMA_NOWAIT, + &sc->sc_uimap); + } + if (!not_ok) { + steps = 7; + not_ok = bus_dmamap_load(sc->sc_dmatag, sc->sc_uimap, + pdq->pdq_unsolicited_info.ui_events, + PDQ_OS_PAGESIZE, NULL, BUS_DMA_NOWAIT); + } + if (!not_ok) { + steps = 8; + pdq->pdq_unsolicited_info.ui_pa_bufstart = sc->sc_uimap->dm_segs[0].ds_addr; + cb_segs[0] = db_segs[0]; + cb_segs[0].ds_addr += offsetof(pdq_descriptor_block_t, pdqdb_consumer); + cb_segs[0].ds_len = sizeof(pdq_consumer_block_t); + not_ok = bus_dmamem_map(sc->sc_dmatag, cb_segs, 1, + sizeof(*pdq->pdq_cbp), (caddr_t *) &pdq->pdq_cbp, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT); + } + if (!not_ok) { + steps = 9; + not_ok = bus_dmamap_create(sc->sc_dmatag, cb_segs[0].ds_len, 1, + 0x2000, 0, BUS_DMA_NOWAIT, &sc->sc_cbmap); + } + if (!not_ok) { + steps = 10; + not_ok = bus_dmamap_load(sc->sc_dmatag, sc->sc_cbmap, + (caddr_t) pdq->pdq_cbp, sizeof(*pdq->pdq_cbp), + NULL, BUS_DMA_NOWAIT); + } + if (!not_ok) { + pdq->pdq_pa_consumer_block = sc->sc_cbmap->dm_segs[0].ds_addr; + return not_ok; + } + + switch (steps) { + case 11: { + bus_dmamap_unload(sc->sc_dmatag, sc->sc_cbmap); + /* FALL THROUGH */ + } + case 10: { + bus_dmamap_destroy(sc->sc_dmatag, sc->sc_cbmap); + /* FALL THROUGH */ + } + case 9: { + bus_dmamem_unmap(sc->sc_dmatag, + (caddr_t) pdq->pdq_cbp, sizeof(*pdq->pdq_cbp)); + /* FALL THROUGH */ + } + case 8: { + bus_dmamap_unload(sc->sc_dmatag, sc->sc_uimap); + /* FALL THROUGH */ + } + case 7: { + bus_dmamap_destroy(sc->sc_dmatag, sc->sc_uimap); + /* FALL THROUGH */ + } + case 6: { + bus_dmamem_unmap(sc->sc_dmatag, + (caddr_t) pdq->pdq_unsolicited_info.ui_events, + PDQ_OS_PAGESIZE); + /* FALL THROUGH */ + } + case 5: { + bus_dmamem_free(sc->sc_dmatag, ui_segs, ui_nsegs); + /* FALL THROUGH */ + } + case 4: { + bus_dmamap_unload(sc->sc_dmatag, sc->sc_dbmap); + /* FALL THROUGH */ + } + case 3: { + bus_dmamap_destroy(sc->sc_dmatag, sc->sc_dbmap); + /* FALL THROUGH */ + } + case 2: { + bus_dmamem_unmap(sc->sc_dmatag, + (caddr_t) pdq->pdq_dbp, + sizeof(*pdq->pdq_dbp)); + /* FALL THROUGH */ + } + case 1: { + bus_dmamem_free(sc->sc_dmatag, db_segs, db_nsegs); + /* FALL THROUGH */ + } + } + + return not_ok; +} + +extern void +pdq_os_descriptor_block_sync( + pdq_os_ctx_t *sc, + size_t offset, + size_t length, + int ops) +{ + bus_dmamap_sync(sc->sc_dmatag, sc->sc_dbmap, offset, length, ops); } + +extern void +pdq_os_consumer_block_sync( + pdq_os_ctx_t *sc, + int ops) +{ + bus_dmamap_sync(sc->sc_dmatag, sc->sc_cbmap, 0, sizeof(pdq_consumer_block_t), ops); +} + +extern void +pdq_os_unsolicited_event_sync( + pdq_os_ctx_t *sc, + size_t offset, + size_t length, + int ops) +{ + bus_dmamap_sync(sc->sc_dmatag, sc->sc_uimap, offset, length, ops); +} + +extern void +pdq_os_databuf_sync( + pdq_os_ctx_t *sc, + struct mbuf *m, + size_t offset, + size_t length, + int ops) +{ + bus_dmamap_sync(sc->sc_dmatag, M_GETCTX(m, bus_dmamap_t), offset, length, ops); +} + +extern void +pdq_os_databuf_free( + pdq_os_ctx_t *sc, + struct mbuf *m) +{ + if (m->m_flags & (M_HASRXDMAMAP|M_HASTXDMAMAP)) { + bus_dmamap_t map = M_GETCTX(m, bus_dmamap_t); + bus_dmamap_unload(sc->sc_dmatag, map); + bus_dmamap_destroy(sc->sc_dmatag, map); + m->m_flags &= ~(M_HASRXDMAMAP|M_HASTXDMAMAP); + } + m_freem(m); +} + +extern struct mbuf * +pdq_os_databuf_alloc( + pdq_os_ctx_t *sc) +{ + struct mbuf *m; + bus_dmamap_t map; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == NULL) { + printf("%s: can't alloc small buf\n", sc->sc_dev.dv_xname); + return NULL; + } + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + printf("%s: can't alloc cluster\n", sc->sc_dev.dv_xname); + m_free(m); + return NULL; + } + m->m_pkthdr.len = m->m_len = PDQ_OS_DATABUF_SIZE; + + if (bus_dmamap_create(sc->sc_dmatag, PDQ_OS_DATABUF_SIZE, + 1, PDQ_OS_DATABUF_SIZE, 0, BUS_DMA_NOWAIT, &map)) { + printf("%s: can't create dmamap\n", sc->sc_dev.dv_xname); + m_free(m); + return NULL; + } + if (bus_dmamap_load_mbuf(sc->sc_dmatag, map, m, + BUS_DMA_READ|BUS_DMA_NOWAIT)) { + printf("%s: can't load dmamap\n", sc->sc_dev.dv_xname); + bus_dmamap_destroy(sc->sc_dmatag, map); + m_free(m); + return NULL; + } + m->m_flags |= M_HASRXDMAMAP; + M_SETCTX(m, map); + return m; +} +#endif diff --git a/sys/dev/pdq/pdqreg.h b/sys/dev/pdq/pdqreg.h index 26ddab1..9578195 100644 --- a/sys/dev/pdq/pdqreg.h +++ b/sys/dev/pdq/pdqreg.h @@ -1,3 +1,5 @@ +/* $NetBSD: pdqreg.h,v 1.14 2001/06/13 10:46:03 wiz Exp $ */ + /*- * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com> * All rights reserved. @@ -8,7 +10,7 @@ * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products - * derived from this software withough specific prior written permission + * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -21,6 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * Id: pdqreg.h,v 1.11 1997/03/21 21:16:04 thomas Exp * $FreeBSD$ * */ @@ -33,6 +36,11 @@ #ifndef _PDQREG_H #define _PDQREG_H +#if !defined(KERNEL) && !defined(_KERNEL) +#include <stddef.h> +#elif !defined(offsetof) +#define offsetof(t, m) ((char *) (&((t *)0L)->m) - (char *) 0L) +#endif #if defined(PDQTEST) && !defined(PDQ_NDEBUG) #include <assert.h> #define PDQ_ASSERT assert @@ -303,19 +311,36 @@ typedef struct { typedef union { pdq_uint32_t rxs_status; - pdq_uint32_t PDQ_BITFIELD12(rxs_len : 13, - rxs_rcc_ss : 2, - rxs_rcc_dd : 2, - rxs_rcc_reason : 3, - rxs_rcc_badcrc : 1, - rxs_rcc_badpdu : 1, - rxs_fsb__reserved : 2, - rxs_fsb_c : 1, - rxs_fsb_a : 1, - rxs_fsb_e : 1, - rxs_fsc : 3, - rxs__reserved : 2); + struct { + pdq_uint32_t PDQ_BITFIELD12(st_len : 13, + st_rcc_ss : 2, + st_rcc_dd : 2, + st_rcc_reason : 3, + st_rcc_badcrc : 1, + st_rcc_badpdu : 1, + st_fsb__reserved : 2, + st_fsb_c : 1, + st_fsb_a : 1, + st_fsb_e : 1, + st_fsc : 3, + st__reserved : 2); + } rxs_st; } pdq_rxstatus_t; +#define rxs_len rxs_st.st_len +#define rxs_rcc_ss rxs_st.st_rcc_ss +#define rxs_rcc_dd rxs_st.st_rcc_dd +#define rxs_rcc_reason rxs_st.st_rcc_reason +#define rxs_rcc_badcrc rxs_st.st_rcc_badcrc +#define rxs_rcc_badpdu rxs_st.st_rcc_badpdu +#define rxs_fsb_c rxs_st.st_fsb_c +#define rxs_fsb_a rxs_st.st_fsb_a +#define rxs_fsb_e rxs_st.st_fsb_e +#define rxs_fsc rxs_st.st_fsc + +#define PDQ_RXS_RCC_DD_NO_MATCH 0x00 +#define PDQ_RXS_RCC_DD_PROMISC_MATCH 0x01 +#define PDQ_RXS_RCC_DD_CAM_MATCH 0x02 +#define PDQ_RXS_RCC_DD_MLA_MATCH 0x03 typedef struct { pdq_uint32_t PDQ_BITFIELD5(txd_pa_hi : 16, @@ -337,27 +362,52 @@ typedef struct { * The rest of the descriptor block is unused. * As such we could use it for other things. */ - pdq_consumer_block_t pdqdb_consumer; /* 64; 0x1380..0x13BF */ - void *pdqdb_receive_buffers[256]; /* 1024/2048; 0x13C0..0x17BF 0x13C0..0x1BBF */ - void *pdqdb_host_smt_buffers[64]; /* 256/ 512; 0x17C0..0x18BF 0x1BC0..0x1DBF */ + pdq_uint32_t pdqdb__filler1[16]; /* 64; 0x1380..0x13BF */ + pdq_consumer_block_t pdqdb_consumer; /* 64; 0x13C0..0x13FF */ /* * The maximum command size is 512 so as long as thes * command is at least that long all will be fine. */ -#if defined(__alpha) || defined(__alpha__) - pdq_uint32_t pdqdb_command_pool[144]; -#else - pdq_uint32_t pdqdb_command_pool[464]; -#endif + pdq_uint32_t pdqdb__filler2[64]; /* 256; 0x1400..0x14FF */ + pdq_uint8_t pdqdb_cmd_request_buf[1024]; /* 1024; 0x1500..0x18FF */ + pdq_uint8_t pdqdb_cmd_response_buf[1024]; /* 1024; 0x1900..0x1CFF */ + pdq_uint32_t pdqdb__filler3[128]; /* 512; 0x1D00..0x1EFF */ + pdq_uint8_t pdqdb_tx_hdr[4]; /* 4; 0x1F00..0x1F03 */ + pdq_uint32_t pdqdb__filler4[63]; /* 252; 0x1F04..0x1FFF */ } pdq_descriptor_block_t; +#define PDQ_SIZE_COMMAND_RESPONSE 512 + +typedef enum { + PDQC_START=0, + PDQC_FILTER_SET=1, + PDQC_FILTER_GET=2, + PDQC_CHARS_SET=3, + PDQC_STATUS_CHARS_GET=4, + PDQC_COUNTERS_GET=5, + PDQC_COUNTERS_SET=6, + PDQC_ADDR_FILTER_SET=7, + PDQC_ADDR_FILTER_GET=8, + PDQC_ERROR_LOG_CLEAR=9, + PDQC_ERROR_LOG_GET=10, + PDQC_FDDI_MIB_GET=11, + PDQC_DEC_EXT_MIB_GET=12, + PDQC_DEV_SPECIFIC_GET=13, + PDQC_SNMP_SET=14, + PDQC_SMT_MIB_GET=16, + PDQC_SMT_MIB_SET=17, + PDQC_BOGUS_CMD=18 +} pdq_cmd_code_t; + typedef struct { /* * These value manage the available space in command/response * buffer area. */ - pdq_physaddr_t ci_pa_bufstart; - pdq_uint8_t *ci_bufstart; + pdq_physaddr_t ci_pa_request_bufstart; + pdq_uint8_t *ci_request_bufstart; + pdq_physaddr_t ci_pa_response_bufstart; + pdq_uint8_t *ci_response_bufstart; /* * Bitmask of commands to sent to the PDQ */ @@ -370,6 +420,13 @@ typedef struct { pdq_uint32_t ci_response_producer; pdq_uint32_t ci_request_completion; pdq_uint32_t ci_response_completion; + /* + * + */ + pdq_physaddr_t ci_pa_request_descriptors; + pdq_physaddr_t ci_pa_response_descriptors; + + pdq_cmd_code_t ci_queued_commands[16]; } pdq_command_info_t; #define PDQ_SIZE_UNSOLICITED_EVENT 512 @@ -379,6 +436,7 @@ typedef struct _pdq_unsolicited_event_t pdq_unsolicited_event_t; typedef struct { pdq_physaddr_t ui_pa_bufstart; + pdq_physaddr_t ui_pa_descriptors; pdq_unsolicited_event_t *ui_events; pdq_uint32_t ui_free; @@ -409,6 +467,7 @@ typedef struct { typedef struct { void *rx_buffers; + pdq_physaddr_t rx_pa_descriptors; pdq_uint32_t rx_target; pdq_uint32_t rx_free; @@ -420,12 +479,14 @@ typedef struct { pdq_databuf_queue_t tx_txq; pdq_txdesc_t tx_hdrdesc; pdq_uint8_t tx_descriptor_count[256]; + pdq_physaddr_t tx_pa_descriptors; pdq_uint32_t tx_free; pdq_uint32_t tx_producer; pdq_uint32_t tx_completion; } pdq_tx_info_t; +typedef struct _pdq_os_ctx_t pdq_os_ctx_t; struct _pdq_t { pdq_csrs_t pdq_csrs; pdq_pci_csrs_t pdq_pci_csrs; @@ -435,6 +496,7 @@ struct _pdq_t { pdq_fwrev_t pdq_fwrev; pdq_descriptor_block_t *pdq_dbp; volatile pdq_consumer_block_t *pdq_cbp; + pdq_uint32_t pdq_intrmask; pdq_uint32_t pdq_flags; #define PDQ_PROMISC 0x0001 #define PDQ_ALLMULTI 0x0002 @@ -442,36 +504,27 @@ struct _pdq_t { #define PDQ_RUNNING 0x0008 #define PDQ_PRINTCHARS 0x0010 #define PDQ_TXOK 0x0020 +#define PDQ_WANT_FDX 0x0040 +#define PDQ_IS_FDX 0x0080 +#define PDQ_IS_ONRING 0x0100 const char *pdq_os_name; - void *pdq_os_ctx; + pdq_os_ctx_t *pdq_os_ctx; pdq_uint32_t pdq_unit; pdq_command_info_t pdq_command_info; pdq_unsolicited_info_t pdq_unsolicited_info; pdq_tx_info_t pdq_tx_info; pdq_rx_info_t pdq_rx_info; pdq_rx_info_t pdq_host_smt_info; - pdq_uint8_t pdq_tx_hdr[3]; + void *pdq_receive_buffers[256]; + void *pdq_host_smt_buffers[64]; + pdq_physaddr_t pdq_pa_consumer_block; + pdq_physaddr_t pdq_pa_descriptor_block; }; -typedef enum { - PDQC_START=0, - PDQC_FILTER_SET=1, - PDQC_FILTER_GET=2, - PDQC_CHARS_SET=3, - PDQC_STATUS_CHARS_GET=4, - PDQC_COUNTERS_GET=5, - PDQC_COUNTERS_SET=6, - PDQC_ADDR_FILTER_SET=7, - PDQC_ADDR_FILTER_GET=8, - PDQC_ERROR_LOG_CLEAR=9, - PDQC_ERROR_LOG_GET=10, - PDQC_FDDI_MIB_GET=11, - PDQC_DEC_EXT_MIB_GET=12, - PDQC_DEV_SPECIFIC_GET=13, - PDQC_SNMP_SET=14, - PDQC_SMT_MIB_GET=16, - PDQC_SMT_MIB_SET=17 -} pdq_cmd_code_t; +#define PDQ_DB_BUSPA(pdq, m) \ + ((pdq)->pdq_pa_descriptor_block + \ + ((u_int8_t *) (m) - (u_int8_t *) (pdq)->pdq_dbp)) + typedef enum { PDQR_SUCCESS=0, @@ -556,6 +609,11 @@ typedef enum { PDQI_FULL_DUPLEX_ENABLE=44 } pdq_item_code_t; +typedef enum { + PDQSNMP_EOL=0, + PDQSNMP_FULL_DUPLEX_ENABLE=0x2F11 +} pdq_snmp_item_code_t; + enum _pdq_boolean_t { PDQ_FALSE=0, PDQ_TRUE=1 @@ -956,6 +1014,16 @@ typedef struct { #define PDQ_SIZE_RESPONSE_DEC_EXT_MIB_GET 0x50 +typedef struct { + pdq_cmd_code_t snmp_set_op; + struct { + pdq_item_code_t item_code; + pdq_uint32_t item_value; + pdq_port_type_t item_port; + } snmp_set_items[7]; + pdq_item_code_t snmp_set_eol_item_code; +} pdq_cmd_snmp_set_t; + typedef enum { PDQ_CALLER_ID_NONE=0, PDQ_CALLER_ID_SELFTEST=1, @@ -994,11 +1062,13 @@ typedef enum { typedef enum { PDQ_ENTITY_STATION=0, PDQ_ENTITY_LINK=1, - PDQ_ENTITY_PHY_PORT=2 + PDQ_ENTITY_PHY_PORT=2, + PDQ_ENTITY_MAX=3 } pdq_entity_t; typedef enum { - PDQ_STATION_EVENT_TRACE_RECEIVED=1 + PDQ_STATION_EVENT_TRACE_RECEIVED=1, + PDQ_STATION_EVENT_MAX=2 } pdq_station_event_t; typedef enum { @@ -1022,7 +1092,8 @@ typedef enum { PDQ_LINK_EVENT_RING_PURGE_ERROR=15, PDQ_LINK_EVENT_FCI_STRIP_ERROR=16, PDQ_LINK_EVENT_TRACE_INITIATED=17, - PDQ_LINK_EVENT_DIRECTED_BEACON_RECEIVED=18 + PDQ_LINK_EVENT_DIRECTED_BEACON_RECEIVED=18, + PDQ_LINK_EVENT_MAX=19 } pdq_link_event_t; typedef enum { @@ -1036,7 +1107,8 @@ typedef enum { typedef enum { PDQ_PHY_EVENT_LEM_ERROR_MONITOR_REJECT=0, PDQ_PHY_EVENT_ELASTICITY_BUFFER_ERROR=1, - PDQ_PHY_EVENT_LINK_CONFIDENCE_TEST_REJECT=2 + PDQ_PHY_EVENT_LINK_CONFIDENCE_TEST_REJECT=2, + PDQ_PHY_EVENT_MAX=3 } pdq_phy_event_t; typedef enum { diff --git a/sys/dev/pdq/pdqvar.h b/sys/dev/pdq/pdqvar.h index 5828047..dc25da5 100644 --- a/sys/dev/pdq/pdqvar.h +++ b/sys/dev/pdq/pdqvar.h @@ -1,3 +1,5 @@ +/* $NetBSD: pdqvar.h,v 1.27 2000/05/03 19:17:54 thorpej Exp $ */ + /*- * Copyright (c) 1995, 1996 Matt Thomas <matt@3am-software.com> * All rights reserved. @@ -21,6 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * Id: pdqvar.h,v 1.21 1997/03/21 21:16:04 thomas Exp * $FreeBSD$ * */ @@ -62,13 +65,10 @@ enum _pdq_type_t { #include <sys/param.h> #include <sys/systm.h> -#include <sys/lock.h> #ifndef M_MCAST #include <sys/mbuf.h> #endif /* M_CAST */ #include <sys/malloc.h> -#include <sys/mutex.h> - #include <vm/vm.h> #include <vm/vm_kern.h> @@ -87,31 +87,31 @@ enum _pdq_type_t { #endif #define PDQ_OS_USEC_DELAY(n) DELAY(n) #define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n)) -#if defined(__NetBSD__) && defined(__alpha__) -#define PDQ_OS_VA_TO_PA(pdq, p) (vtophys((vm_offset_t)p) | (pdq->pdq_type == PDQ_DEFTA ? 0 : 0x40000000)) -#elif defined(__FreeBSD__) && defined(__alpha__) -#define PDQ_OS_VA_TO_PA(pdq, p) (vtophys((vm_offset_t)p) | (pdq->pdq_type == PDQ_DEFTA ? 0 : alpha_XXX_dmamap_or)) -#else -#define PDQ_OS_VA_TO_PA(pdq, p) vtophys(p) +#if defined(__NetBSD__) && !defined(PDQ_NO_BUS_DMA) +#define PDQ_BUS_DMA +#endif +#if !defined(PDQ_BUS_DMA) +#define PDQ_OS_VA_TO_BUSPA(pdq, p) vtophys(p) #endif #define PDQ_OS_MEMALLOC(n) malloc(n, M_DEVBUF, M_NOWAIT) #define PDQ_OS_MEMFREE(p, n) free((void *) p, M_DEVBUF) #ifdef __FreeBSD__ #define PDQ_OS_MEMALLOC_CONTIG(n) vm_page_alloc_contig(n, 0, 0xffffffff, PAGE_SIZE) -#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vm_offset_t) p, n) +#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vaddr_t) p, n) #else -#define PDQ_OS_MEMALLOC_CONTIG(n) kmem_alloc(kernel_map, round_page(n)) -#define PDQ_OS_MEMFREE_CONTIG(p, n) kmem_free(kernel_map, (vm_offset_t) p, n) +#if !defined(PDQ_BUS_DMA) +#define PDQ_OS_MEMALLOC_CONTIG(n) uvm_km_alloc(kernel_map, round_page(n)) +#define PDQ_OS_MEMFREE_CONTIG(p, n) uvm_km_free(kernel_map, (vaddr_t) p, n) +#endif #endif /* __FreeBSD__ */ #if defined(__FreeBSD__) #include <vm/pmap.h> #include <vm/vm_extern.h> -#include <machine/bus.h> #include <machine/cpufunc.h> #include <machine/clock.h> -typedef void ifnet_ret_t; -typedef u_long ioctl_cmd_t; +#define ifnet_ret_t void +typedef int ioctl_cmd_t; typedef enum { PDQ_BUS_EISA, PDQ_BUS_PCI } pdq_bus_t; typedef u_int16_t pdq_bus_ioport_t; typedef volatile pdq_uint32_t *pdq_bus_memaddr_t; @@ -121,10 +121,14 @@ typedef pdq_bus_memaddr_t pdq_bus_memoffset_t; #define PDQ_BPFATTACH(sc, t, s) bpfattach(&(sc)->sc_if, t, s) #endif +#define pdq_os_update_status(a, b) ((void) 0) #elif defined(__bsdi__) +#if !defined(PDQ_HWSUPPORT) && (_BSDI_VERSION >= 199701) +#include <net/if_media.h> +#endif #include <machine/inline.h> -typedef int ifnet_ret_t; +#define ifnet_ret_t int typedef int ioctl_cmd_t; typedef enum { PDQ_BUS_EISA, PDQ_BUS_PCI } pdq_bus_t; typedef u_int16_t pdq_bus_ioport_t; @@ -133,36 +137,100 @@ typedef pdq_bus_memaddr_t pdq_bus_memoffset_t; #elif defined(__NetBSD__) +#if !defined(PDQ_HWSUPPORT) +#include <net/if_media.h> +#endif #include <machine/bus.h> #include <machine/intr.h> +#define PDQ_OS_HDR_OFFSET (PDQ_RX_FC_OFFSET-3) #define PDQ_OS_PTR_FMT "%p" -typedef void ifnet_ret_t; +#define PDQ_OS_CSR_FMT "0x%lx" +#define ifnet_ret_t void typedef u_long ioctl_cmd_t; -typedef bus_chipset_tag_t pdq_bus_t; -typedef bus_io_handle_t pdq_bus_ioport_t; -#if defined(PDQ_IOMAPPED) -typedef bus_io_handle_t pdq_bus_memaddr_t; -#else -typedef bus_mem_handle_t pdq_bus_memaddr_t; -#endif -typedef pdq_uint32_t pdq_bus_memoffset_t; +typedef bus_space_tag_t pdq_bus_t; +typedef bus_space_handle_t pdq_bus_ioport_t; +typedef bus_space_handle_t pdq_bus_memaddr_t; +typedef bus_addr_t pdq_bus_memoffset_t; +#define PDQ_OS_SPL_RAISE() splnet() #define PDQ_OS_IOMEM -#define PDQ_OS_IORD_32(t, base, offset) bus_io_read_4 (t, base, offset) -#define PDQ_OS_IOWR_32(t, base, offset, data) bus_io_write_4 (t, base, offset, data) -#define PDQ_OS_IORD_8(t, base, offset) bus_io_read_1 (t, base, offset) -#define PDQ_OS_IOWR_8(t, base, offset, data) bus_io_write_1 (t, base, offset, data) -#define PDQ_OS_MEMRD_32(t, base, offset) bus_mem_read_4(t, base, offset) -#define PDQ_OS_MEMWR_32(t, base, offset, data) bus_mem_write_4(t, base, offset, data) +#define PDQ_OS_IORD_32(t, base, offset) bus_space_read_4 (t, base, offset) +#define PDQ_OS_IOWR_32(t, base, offset, data) bus_space_write_4 (t, base, offset, data) +#define PDQ_OS_IORD_8(t, base, offset) bus_space_read_1 (t, base, offset) +#define PDQ_OS_IOWR_8(t, base, offset, data) bus_space_write_1 (t, base, offset, data) #define PDQ_CSR_OFFSET(base, offset) (0 + (offset)*sizeof(pdq_uint32_t)) -#if defined(PDQ_IOMAPPED) +#ifdef PDQ_BUS_DMA +#define PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, event) \ + pdq_os_unsolicited_event_sync((pdq)->pdq_os_ctx, \ + (u_int8_t *) (event) - \ + (u_int8_t *) (pdq)->pdq_unsolicited_info.ui_events, \ + sizeof(*event), BUS_DMASYNC_PREREAD) +#define PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, event) \ + pdq_os_unsolicited_event_sync((pdq)->pdq_os_ctx, \ + (u_int8_t *) (event) - \ + (u_int8_t *) (pdq)->pdq_unsolicited_info.ui_events, \ + sizeof(*event), BUS_DMASYNC_POSTREAD) +#define PDQ_OS_DESCBLOCK_SYNC(pdq, what, length, why) \ + pdq_os_descriptor_block_sync((pdq)->pdq_os_ctx, \ + (u_int8_t *) (what) - (u_int8_t *) (pdq)->pdq_dbp, \ + (length), (why)) +#define PDQ_OS_CONSUMER_PRESYNC(pdq) \ + pdq_os_consumer_block_sync((pdq)->pdq_os_ctx, \ + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define PDQ_OS_CONSUMER_POSTSYNC(pdq) \ + pdq_os_consumer_block_sync((pdq)->pdq_os_ctx, \ + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define PDQ_OS_DESC_PRESYNC(pdq, d, s) \ + PDQ_OS_DESCBLOCK_SYNC((pdq), (d), (s), BUS_DMASYNC_PREWRITE) +#define PDQ_OS_DESC_POSTSYNC(pdq, d, s) \ + PDQ_OS_DESCBLOCK_SYNC((pdq), (d), (s), BUS_DMASYNC_POSTWRITE) +#define PDQ_OS_CMDRQST_PRESYNC(pdq, s) \ + PDQ_OS_DESCBLOCK_SYNC((pdq), \ + (pdq)->pdq_command_info.ci_request_bufstart, \ + (s), BUS_DMASYNC_PREWRITE) +#define PDQ_OS_CMDRSP_PRESYNC(pdq, s) \ + PDQ_OS_DESCBLOCK_SYNC((pdq), \ + (pdq)->pdq_command_info.ci_response_bufstart, \ + (s), BUS_DMASYNC_PREREAD) +#define PDQ_OS_CMDRQST_POSTSYNC(pdq, s) \ + PDQ_OS_DESCBLOCK_SYNC((pdq), \ + (pdq)->pdq_command_info.ci_request_bufstart, \ + (s), BUS_DMASYNC_POSTWRITE) +#define PDQ_OS_CMDRSP_POSTSYNC(pdq, s) \ + PDQ_OS_DESCBLOCK_SYNC((pdq), \ + (pdq)->pdq_command_info.ci_response_bufstart, \ + (s), BUS_DMASYNC_POSTREAD) +#define PDQ_OS_RXPDU_PRESYNC(pdq, b, o, l) \ + pdq_os_databuf_sync((pdq)->pdq_os_ctx, (b), (o), (l), \ + BUS_DMASYNC_PREREAD) +#define PDQ_OS_RXPDU_POSTSYNC(pdq, b, o, l) \ + pdq_os_databuf_sync((pdq)->pdq_os_ctx, (b), (o), (l), \ + BUS_DMASYNC_POSTREAD) +#define PDQ_OS_DATABUF_ALLOC(pdq, b) ((void)((b) = pdq_os_databuf_alloc((pdq)->pdq_os_ctx))) +#define PDQ_OS_DATABUF_FREE(pdq, b) pdq_os_databuf_free((pdq)->pdq_os_ctx, (b)) +#define PDQ_OS_DATABUF_BUSPA(pdq, b) (M_GETCTX((b), bus_dmamap_t)->dm_segs[0].ds_addr + 0) +struct _pdq_os_ctx_t; +extern void pdq_os_descriptor_block_sync(struct _pdq_os_ctx_t *osctx, size_t offset, + size_t length, int ops); +extern void pdq_os_consumer_block_sync(struct _pdq_os_ctx_t *osctx, int ops); +extern void pdq_os_unsolicited_event_sync(struct _pdq_os_ctx_t *osctx, size_t offset, + size_t length, int ops); +extern struct mbuf *pdq_os_databuf_alloc(struct _pdq_os_ctx_t *osctx); +extern void pdq_os_databuf_sync(struct _pdq_os_ctx_t *osctx, struct mbuf *b, + size_t offset, size_t length, int ops); +extern void pdq_os_databuf_free(struct _pdq_os_ctx_t *osctx, struct mbuf *m); +#define M_HASTXDMAMAP M_LINK1 +#define M_HASRXDMAMAP M_LINK2 +#endif + #define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_IOWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data) #define PDQ_CSR_READ(csr, name) PDQ_OS_IORD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name) -#else -#define PDQ_CSR_WRITE(csr, name, data) PDQ_OS_MEMWR_32((csr)->csr_bus, (csr)->csr_base, (csr)->name, data) -#define PDQ_CSR_READ(csr, name) PDQ_OS_MEMRD_32((csr)->csr_bus, (csr)->csr_base, (csr)->name) -#endif +#define PDQ_OS_IFP_TO_SOFTC(ifp) ((pdq_softc_t *) (ifp)->if_softc) +#define PDQ_ARP_IFINIT(sc, ifa) arp_ifinit(&(sc)->sc_if, (ifa)) +#define PDQ_FDDICOM(sc) (&(sc)->sc_ec) +#define PDQ_LANADDR(sc) LLADDR((sc)->sc_if.if_sadl) +#define PDQ_LANADDR_SIZE(sc) ((sc)->sc_if.if_sadl->sdl_alen) #endif #if !defined(PDQ_BPF_MTAP) @@ -173,17 +241,42 @@ typedef pdq_uint32_t pdq_bus_memoffset_t; #define PDQ_BPFATTACH(sc, t, s) bpfattach(&(sc)->sc_bpf, &(sc)->sc_if, t, s) #endif +#if !defined(PDQ_OS_SPL_RAISE) +#define PDQ_OS_SPL_RAISE() splimp() +#endif + +#if !defined(PDQ_OS_SPL_LOWER) +#define PDQ_OS_SPL_LOWER(s) splx(s) +#endif + +#if !defined(PDQ_FDDICOM) +#define PDQ_FDDICOM(sc) (&(sc)->sc_ac) +#endif + +#if !defined(PDQ_ARP_IFINIT) +#define PDQ_ARP_IFINIT(sc, ifa) arp_ifinit(&(sc)->sc_ac, (ifa)) +#endif + #if !defined(PDQ_OS_PTR_FMT) #define PDQ_OS_PTR_FMT "0x%x" #endif +#if !defined(PDQ_OS_CSR_FMT) +#define PDQ_OS_CSR_FMT "0x%x" +#endif + +#if !defined(PDQ_LANADDR) +#define PDQ_LANADDR(sc) ((sc)->sc_ac.ac_enaddr) +#define PDQ_LANADDR_SIZE(sc) (sizeof((sc)->sc_ac.ac_enaddr)) +#endif + #if !defined(PDQ_OS_IOMEM) #define PDQ_OS_IORD_32(t, base, offset) inl((base) + (offset)) #define PDQ_OS_IOWR_32(t, base, offset, data) outl((base) + (offset), data) #define PDQ_OS_IORD_8(t, base, offset) inb((base) + (offset)) #define PDQ_OS_IOWR_8(t, base, offset, data) outb((base) + (offset), data) -#define PDQ_OS_MEMRD_32(t, base, offset) readl((base) + (offset)) -#define PDQ_OS_MEMWR_32(t, base, offset, data) writel((base) + (offset), data) +#define PDQ_OS_MEMRD_32(t, base, offset) (0 + *((base) + (offset))) +#define PDQ_OS_MEMWR_32(t, base, offset, data) do *((base) + (offset)) = (data); while (0) #endif #ifndef PDQ_CSR_OFFSET #define PDQ_CSR_OFFSET(base, offset) (0 + (base) + (offset)) @@ -194,38 +287,60 @@ typedef pdq_uint32_t pdq_bus_memoffset_t; #define PDQ_CSR_READ(csr, name) PDQ_OS_MEMRD_32((csr)->csr_bus, (csr)->name, 0) #endif +#ifndef PDQ_OS_IFP_TO_SOFTC +#define PDQ_OS_IFP_TO_SOFTC(ifp) ((pdq_softc_t *) ((caddr_t) ifp - offsetof(pdq_softc_t, sc_ac.ac_if))) +#endif + + #if !defined(PDQ_HWSUPPORT) -typedef struct { +typedef struct _pdq_os_ctx_t { #if defined(__bsdi__) struct device sc_dev; /* base device */ struct isadev sc_id; /* ISA device */ struct intrhand sc_ih; /* interrupt vectoring */ struct atshutdown sc_ats; /* shutdown routine */ + struct arpcom sc_ac; +#define sc_if sc_ac.ac_if #elif defined(__NetBSD__) struct device sc_dev; /* base device */ void *sc_ih; /* interrupt vectoring */ void *sc_ats; /* shutdown hook */ + struct ethercom sc_ec; + bus_dma_tag_t sc_dmatag; +#define sc_if sc_ec.ec_if #elif defined(__FreeBSD__) struct kern_devconf *sc_kdc; /* freebsd cruft */ -#endif struct arpcom sc_ac; #define sc_if sc_ac.ac_if +#endif +#if defined(IFM_FDDI) + struct ifmedia sc_ifmedia; +#endif pdq_t *sc_pdq; #if defined(__alpha__) || defined(__i386__) pdq_bus_ioport_t sc_iobase; #endif -#ifdef PDQ_IOMAPPED +#if defined(PDQ_IOMAPPED) && !defined(__NetBSD__) #define sc_membase sc_iobase #else pdq_bus_memaddr_t sc_membase; #endif - pdq_bus_t sc_bc; + pdq_bus_t sc_iotag; + pdq_bus_t sc_csrtag; #if !defined(__bsdi__) || _BSDI_VERSION >= 199401 #define sc_bpf sc_if.if_bpf #else caddr_t sc_bpf; #endif +#if defined(PDQ_BUS_DMA) +#if !defined(__NetBSD__) + bus_dma_tag_t sc_dmatag; +#endif + bus_dmamap_t sc_dbmap; /* DMA map for descriptor block */ + bus_dmamap_t sc_uimap; /* DMA map for unsolicited events */ + bus_dmamap_t sc_cbmap; /* DMA map for consumer block */ +#endif } pdq_softc_t; @@ -251,7 +366,7 @@ extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifwatchdog)(int unit)); #define PDQ_OS_PAGESIZE PAGESIZE #define PDQ_OS_USEC_DELAY(n) drv_usecwait(n) #define PDQ_OS_MEMZERO(p, n) bzero((caddr_t)(p), (n)) -#define PDQ_OS_VA_TO_PA(pdq, p) vtop((caddr_t)p, NULL) +#define PDQ_OS_VA_TO_BUSPA(pdq, p) vtop((caddr_t)p, NULL) #define PDQ_OS_MEMALLOC(n) kmem_zalloc(n, KM_NOSLEEP) #define PDQ_OS_MEMFREE(p, n) kmem_free((caddr_t) p, n) #define PDQ_OS_MEMALLOC_CONTIG(n) kmem_zalloc_physreq(n, decfddiphysreq_db, KM_NOSLEEP) @@ -260,7 +375,7 @@ extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifwatchdog)(int unit)); extern physreq_t *decfddiphysreq_db; extern physreq_t *decfddiphysreq_mblk; -#define PDQ_OS_DATABUF_ALLOC(b) ((void) (((b) = allocb_physreq(PDQ_OS_DATABUF_SIZE, BPRI_MED, decfddiphysreq_mblk)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE))) +#define PDQ_OS_DATABUF_ALLOC(pdq, b) ((void) (((b) = allocb_physreq(PDQ_OS_DATABUF_SIZE, BPRI_MED, decfddiphysreq_mblk)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE))) #define PDQ_OS_IORD_8(port) inb(port) #define PDQ_OS_IOWR_8(port, data) outb(port, data) @@ -269,7 +384,9 @@ extern physreq_t *decfddiphysreq_mblk; #ifdef PDQ_USE_MBUFS #define PDQ_OS_DATABUF_SIZE (MCLBYTES) -#define PDQ_OS_DATABUF_FREE(b) (m_freem(b)) +#ifndef PDQ_OS_DATABUF_FREE +#define PDQ_OS_DATABUF_FREE(pdq, b) (m_freem(b)) +#endif #define PDQ_OS_DATABUF_NEXT(b) ((b)->m_next) #define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->m_next = (b1)) #define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->m_nextpkt) @@ -281,7 +398,8 @@ extern physreq_t *decfddiphysreq_mblk; #define PDQ_OS_DATABUF_ADJ(b, n) ((b)->m_data += (n), (b)->m_len -= (n)) typedef struct mbuf PDQ_OS_DATABUF_T; -#define PDQ_OS_DATABUF_ALLOC(b) do { \ +#ifndef PDQ_OS_DATABUF_ALLOC +#define PDQ_OS_DATABUF_ALLOC(pdq, b) do { \ PDQ_OS_DATABUF_T *x_m0; \ MGETHDR(x_m0, M_DONTWAIT, MT_DATA); \ if (x_m0 != NULL) { \ @@ -297,12 +415,13 @@ typedef struct mbuf PDQ_OS_DATABUF_T; (b) = NULL; \ } \ } while (0) +#endif #define PDQ_OS_DATABUF_RESET(b) ((b)->m_data = (b)->m_ext.ext_buf, (b)->m_len = MCLBYTES) #endif /* PDQ_USE_MBUFS */ #ifdef PDQ_USE_STREAMS #define PDQ_OS_DATABUF_SIZE (2048) -#define PDQ_OS_DATABUF_FREE(b) (freemsg(b)) +#define PDQ_OS_DATABUF_FREE(pdq, b) (freemsg(b)) #define PDQ_OS_DATABUF_NEXT(b) ((b)->b_cont) #define PDQ_OS_DATABUF_NEXT_SET(b, b1) ((b)->b_cont = (b1)) #define PDQ_OS_DATABUF_NEXTPKT(b) ((b)->b_next) @@ -315,7 +434,7 @@ typedef struct mbuf PDQ_OS_DATABUF_T; typedef mblk_t PDQ_OS_DATABUF_T; #ifndef PDQ_OS_DATABUF_ALLOC -#define PDQ_OS_DATABUF_ALLOC(b) ((void) (((b) = allocb(PDQ_OS_DATABUF_SIZE, BPRI_MED)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE))) +#define PDQ_OS_DATABUF_ALLOC(pdq, b) ((void) (((b) = allocb(PDQ_OS_DATABUF_SIZE, BPRI_MED)) && ((b)->b_wptr = (b)->b_rptr + PDQ_OS_DATABUF_SIZE))) #endif /* PDQ_OS_DATABUF_ALLOC */ #endif /* PDQ_USE_STREAMS */ @@ -338,11 +457,39 @@ typedef mblk_t PDQ_OS_DATABUF_T; } \ } while (0) +#if !defined(PDQ_OS_CONSUMER_PRESYNC) +#define PDQ_OS_CONSUMER_PRESYNC(pdq) do { } while(0) +#define PDQ_OS_CONSUMER_POSTSYNC(pdq) do { } while(0) +#define PDQ_OS_DESC_PRESYNC(pdq, d, s) do { } while(0) +#define PDQ_OS_DESC_POSTSYNC(pdq, d, s) do { } while(0) +#define PDQ_OS_CMDRQST_PRESYNC(pdq, s) do { } while(0) +#define PDQ_OS_CMDRQST_POSTSYNC(pdq, s) do { } while(0) +#define PDQ_OS_CMDRSP_PRESYNC(pdq, s) do { } while(0) +#define PDQ_OS_CMDRSP_POSTSYNC(pdq, s) do { } while(0) +#define PDQ_OS_RXPDU_PRESYNC(pdq, b, o, l) do { } while(0) +#define PDQ_OS_RXPDU_POSTSYNC(pdq, b, o, l) do { } while(0) +#define PDQ_OS_UNSOL_EVENT_PRESYNC(pdq, e) do { } while(0) +#define PDQ_OS_UNSOL_EVENT_POSTSYNC(pdq, e) do { } while(0) +#endif + +#ifndef PDQ_OS_DATABUF_BUSPA +#define PDQ_OS_DATABUF_BUSPA(pdq, b) PDQ_OS_VA_TO_BUSPA(pdq, PDQ_OS_DATABUF_PTR(b)) +#endif + +#ifndef PDQ_OS_HDR_OFFSET +#define PDQ_OS_HDR_OFFSET PDQ_RX_FC_OFFSET +#endif + extern void pdq_os_addr_fill(pdq_t *pdq, pdq_lanaddr_t *addrs, size_t numaddrs); -extern void pdq_os_receive_pdu(pdq_t *, PDQ_OS_DATABUF_T *pdu, size_t pdulen); +extern void pdq_os_receive_pdu(pdq_t *, PDQ_OS_DATABUF_T *pdu, size_t pdulen, int drop); extern void pdq_os_restart_transmitter(pdq_t *pdq); extern void pdq_os_transmit_done(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu); - +#if !defined(pdq_os_update_status) +extern void pdq_os_update_status(pdq_t *pdq, const void *rsp); +#endif +#if !defined(PDQ_OS_MEMALLOC_CONTIG) +extern int pdq_os_memalloc_contig(pdq_t *pdq); +#endif extern pdq_boolean_t pdq_queue_transmit_data(pdq_t *pdq, PDQ_OS_DATABUF_T *pdu); extern void pdq_flush_transmitter(pdq_t *pdq); diff --git a/sys/net/fddi.h b/sys/net/fddi.h index 7d69ce7..82c1a13 100644 --- a/sys/net/fddi.h +++ b/sys/net/fddi.h @@ -97,11 +97,9 @@ struct fddi_header { #define FDDI_BPF_UNSUPPORTED 0 #define FDDI_BPF_SUPPORTED 1 -void fddi_ifattach(struct ifnet *); +void fddi_ifattach(struct ifnet *, int); void fddi_ifdetach(struct ifnet *, int); void fddi_input(struct ifnet *, struct fddi_header *, struct mbuf *); -int fddi_output(struct ifnet *, struct mbuf *, struct sockaddr *, - struct rtentry *); int fddi_ioctl(struct ifnet *, int, caddr_t); #endif /* _KERNEL */ diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index 642e625..126cf92 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -94,8 +94,11 @@ extern u_char aarp_org_code[ 3 ]; static u_char fddibroadcastaddr[FDDI_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -static int fddi_resolvemulti(struct ifnet *, struct sockaddr **, +static int fddi_resolvemulti(struct ifnet *, struct sockaddr **, struct sockaddr *); +static int fddi_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); + #define IFP2AC(IFP) ((struct arpcom *)IFP) #define senderr(e) { error = (e); goto bad; } @@ -107,7 +110,7 @@ static int fddi_resolvemulti(struct ifnet *, struct sockaddr **, * packet leaves a multiple of 512 bytes of data in remainder. * Assumes that ifp is actually pointer to arpcom structure. */ -int +static int fddi_output(ifp, m, dst, rt0) struct ifnet *ifp; struct mbuf *m; @@ -519,8 +522,9 @@ dropanyway: * Perform common duties while attaching to interface list */ void -fddi_ifattach(ifp) +fddi_ifattach(ifp, bpf) struct ifnet *ifp; + int bpf; { struct ifaddr *ifa; struct sockaddr_dl *sdl; @@ -551,6 +555,9 @@ fddi_ifattach(ifp) sdl->sdl_alen = ifp->if_addrlen; bcopy(IFP2AC(ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); + if (bpf) + bpfattach(ifp, DLT_FDDI, FDDI_HDR_LEN); + return; } |