summaryrefslogtreecommitdiffstats
path: root/sys/dev/pdq/if_fpa.c
diff options
context:
space:
mode:
authormdodd <mdodd@FreeBSD.org>2002-03-29 11:22:22 +0000
committermdodd <mdodd@FreeBSD.org>2002-03-29 11:22:22 +0000
commit84c21f1d8ff69f47f8e2bef01392d5b39cf9ce02 (patch)
treeacee2dafe452f857b35aa52d9223075e812b1e18 /sys/dev/pdq/if_fpa.c
parentfdbdd2f5af8ced636e98ffa82c0898512b04bfba (diff)
downloadFreeBSD-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/dev/pdq/if_fpa.c')
-rw-r--r--sys/dev/pdq/if_fpa.c172
1 files changed, 125 insertions, 47 deletions
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);
OpenPOWER on IntegriCloud