diff options
Diffstat (limited to 'sys/dev/scd/scd_isa.c')
-rw-r--r-- | sys/dev/scd/scd_isa.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/sys/dev/scd/scd_isa.c b/sys/dev/scd/scd_isa.c new file mode 100644 index 0000000..3df26f2 --- /dev/null +++ b/sys/dev/scd/scd_isa.c @@ -0,0 +1,183 @@ +/* + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <sys/bio.h> +#include <sys/cdio.h> +#include <sys/disklabel.h> +#include <sys/bus.h> + +#include <sys/mutex.h> + +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> + +#include <isa/isavar.h> + +#include <dev/scd/scdreg.h> +#include <dev/scd/scdvar.h> + +static int scd_isa_probe (device_t); +static int scd_isa_attach (device_t); +static int scd_isa_detach (device_t); + +static int scd_alloc_resources (device_t); +static void scd_release_resources (device_t); + +static int +scd_isa_probe (device_t dev) +{ + struct scd_softc * sc; + int error; + + /* No pnp support */ + if (isa_get_vendorid(dev)) + return (ENXIO); + + /* IO port must be configured. */ + if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) + return (ENXIO); + + sc = device_get_softc(dev); + sc->dev = dev; + sc->port_rid = 0; + sc->port_type = SYS_RES_IOPORT; + error = scd_alloc_resources(dev); + if (error) + goto fail; + + error = scd_probe(sc); + if (error) { + device_printf(dev, "Probe failed.\n"); + goto fail; + } + + device_set_desc(dev, sc->data.name); + +fail: + scd_release_resources(dev); + return (error); +} + +static int +scd_isa_attach (device_t dev) +{ + struct scd_softc * sc; + int error; + + sc = device_get_softc(dev); + error = 0; + + sc->dev = dev; + sc->port_rid = 0; + sc->port_type = SYS_RES_IOPORT; + error = scd_alloc_resources(dev); + if (error) + goto fail; + + error = scd_probe(sc); + if (error) { + device_printf(dev, "Re-Probe failed.\n"); + goto fail; + } + + error = scd_attach(sc); + if (error) { + device_printf(dev, "Attach failed.\n"); + goto fail; + } + + return (0); +fail: + scd_release_resources(dev); + return (error); +} + +static int +scd_isa_detach (device_t dev) +{ + struct scd_softc * sc; + int error; + + sc = device_get_softc(dev); + error = 0; + + destroy_dev(sc->scd_dev_t); + + scd_release_resources(dev); + + return (error); +} + +static int +scd_alloc_resources (device_t dev) +{ + struct scd_softc * sc; + int error; + + sc = device_get_softc(dev); + error = 0; + + if (sc->port_type) { + sc->port = bus_alloc_resource(dev, sc->port_type, &sc->port_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->port == NULL) { + device_printf(dev, "Unable to allocate PORT resource.\n"); + error = ENOMEM; + goto bad; + } + sc->port_bst = rman_get_bustag(sc->port); + sc->port_bsh = rman_get_bushandle(sc->port); + } + + mtx_init(&sc->mtx, device_get_nameunit(dev), + "Interrupt lock", MTX_DEF | MTX_RECURSE); + +bad: + return (error); +} + +void +scd_release_resources (device_t dev) +{ + struct scd_softc * sc; + + sc = device_get_softc(dev); + + if (sc->port) { + bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port); + sc->port_bst = 0; + sc->port_bsh = 0; + } + + if (mtx_initialized(&sc->mtx) != 0) + mtx_destroy(&sc->mtx); + + return; +} + +static device_method_t scd_isa_methods[] = { + DEVMETHOD(device_probe, scd_isa_probe), + DEVMETHOD(device_attach, scd_isa_attach), + DEVMETHOD(device_detach, scd_isa_detach), + + { 0, 0 } +}; + +static driver_t scd_isa_driver = { + "scd", + scd_isa_methods, + sizeof(struct scd_softc) +}; + +static devclass_t scd_devclass; + +DRIVER_MODULE(scd, isa, scd_isa_driver, scd_devclass, NULL, 0); |