summaryrefslogtreecommitdiffstats
path: root/sys/dev/cm/if_cm_isa.c
diff options
context:
space:
mode:
authorfjoe <fjoe@FreeBSD.org>2006-06-11 22:25:01 +0000
committerfjoe <fjoe@FreeBSD.org>2006-06-11 22:25:01 +0000
commit999666b44159735052ba7b95c5c2d5dd18a97ce1 (patch)
treec9d2fbebd6f056420ca95f8fa1572fd66237dc1b /sys/dev/cm/if_cm_isa.c
parent0d8c7ef30e7c962c5912eae1146cc053f222e7f4 (diff)
downloadFreeBSD-src-999666b44159735052ba7b95c5c2d5dd18a97ce1.zip
FreeBSD-src-999666b44159735052ba7b95c5c2d5dd18a97ce1.tar.gz
Make cm(4) driver MPSAFE.
Diffstat (limited to 'sys/dev/cm/if_cm_isa.c')
-rw-r--r--sys/dev/cm/if_cm_isa.c77
1 files changed, 53 insertions, 24 deletions
diff --git a/sys/dev/cm/if_cm_isa.c b/sys/dev/cm/if_cm_isa.c
index 0eb070c..e8cf14a 100644
--- a/sys/dev/cm/if_cm_isa.c
+++ b/sys/dev/cm/if_cm_isa.c
@@ -48,10 +48,13 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
#include <net/if.h>
#include <net/if_arc.h>
+#include <dev/cm/smc90cx6reg.h>
#include <dev/cm/smc90cx6var.h>
static int cm_isa_probe (device_t);
@@ -62,20 +65,35 @@ cm_isa_probe(dev)
device_t dev;
{
struct cm_softc *sc = device_get_softc(dev);
- int error;
+ int rid;
- bzero(sc, sizeof(struct cm_softc));
+ rid = 0;
+ sc->port_res = bus_alloc_resource(
+ dev, SYS_RES_IOPORT, &rid, 0ul, ~0ul, CM_IO_PORTS, RF_ACTIVE);
+ if (sc->port_res == NULL)
+ return (ENOENT);
- error = cm_probe(dev);
- if (error == 0)
- goto end;
+ if (GETREG(CMSTAT) == 0xff) {
+ cm_release_resources(dev);
+ return (ENXIO);
+ }
-end:
- if (error == 0)
- error = cm_alloc_irq(dev, 0);
+ rid = 0;
+ sc->mem_res = bus_alloc_resource(
+ dev, SYS_RES_MEMORY, &rid, 0ul, ~0ul, CM_MEM_SIZE, RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ cm_release_resources(dev);
+ return (ENOENT);
+ }
- cm_release_resources(dev);
- return (error);
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ cm_release_resources(dev);
+ return (ENOENT);
+ }
+
+ return (0);
}
static int
@@ -85,18 +103,25 @@ cm_isa_attach(dev)
struct cm_softc *sc = device_get_softc(dev);
int error;
- cm_alloc_port(dev, sc->port_rid, sc->port_used);
- cm_alloc_memory(dev, sc->mem_rid, sc->mem_used);
- cm_alloc_irq(dev, sc->irq_rid);
+ /* init mtx and setup interrupt */
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev),
+ MTX_NETWORK_LOCK, MTX_DEF);
+ error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
+ cmintr, sc, &sc->irq_handle);
+ if (error)
+ goto err;
- error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
- cmintr, sc, &sc->irq_handle);
- if (error) {
- cm_release_resources(dev);
- return (error);
- }
+ /* attach */
+ error = cm_attach(dev);
+ if (error)
+ goto err;
+
+ return 0;
- return cm_attach(dev);
+err:
+ mtx_destroy(&sc->sc_mtx);
+ cm_release_resources(dev);
+ return (error);
}
static int
@@ -104,19 +129,23 @@ cm_isa_detach(device_t dev)
{
struct cm_softc *sc = device_get_softc(dev);
struct ifnet *ifp = sc->sc_ifp;
- int s;
- cm_stop(sc);
+ /* stop and detach */
+ CM_LOCK(sc);
+ cm_stop_locked(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ CM_UNLOCK(sc);
- s = splimp();
+ callout_drain(&sc->sc_recon_ch);
arc_ifdetach(ifp);
- splx(s);
+ /* teardown interrupt, destroy mtx and release resources */
bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+ mtx_destroy(&sc->sc_mtx);
if_free(ifp);
cm_release_resources(dev);
+ bus_generic_detach(dev);
return (0);
}
OpenPOWER on IntegriCloud