1104445Smdodd/* 2104445Smdodd */ 3104445Smdodd 4119418Sobrien#include <sys/cdefs.h> 5119418Sobrien__FBSDID("$FreeBSD$"); 6119418Sobrien 7104445Smdodd#include <sys/param.h> 8104445Smdodd#include <sys/systm.h> 9104445Smdodd#include <sys/kernel.h> 10104445Smdodd#include <sys/module.h> 11104445Smdodd#include <sys/conf.h> 12104445Smdodd#include <sys/fcntl.h> 13104445Smdodd#include <sys/bio.h> 14104445Smdodd#include <sys/cdio.h> 15104445Smdodd#include <sys/bus.h> 16104445Smdodd 17104547Sbde#include <sys/lock.h> 18104445Smdodd#include <sys/mutex.h> 19104445Smdodd 20104445Smdodd#include <machine/bus.h> 21104445Smdodd#include <machine/resource.h> 22104445Smdodd#include <sys/rman.h> 23104445Smdodd 24104445Smdodd#include <isa/isavar.h> 25104445Smdodd 26104445Smdodd#include <dev/mcd/mcdreg.h> 27104445Smdodd#include <dev/mcd/mcdvar.h> 28104445Smdodd 29104445Smdoddstatic int mcd_isa_probe (device_t); 30104445Smdoddstatic int mcd_isa_attach (device_t); 31104445Smdoddstatic int mcd_isa_detach (device_t); 32104445Smdodd 33104445Smdoddstatic int mcd_alloc_resources (device_t); 34104445Smdoddstatic void mcd_release_resources (device_t); 35104445Smdodd 36104445Smdoddstatic int 37104445Smdoddmcd_isa_probe (device_t dev) 38104445Smdodd{ 39104445Smdodd struct mcd_softc * sc; 40104445Smdodd int error; 41104445Smdodd 42104445Smdodd /* No pnp support */ 43104445Smdodd if (isa_get_vendorid(dev)) 44104445Smdodd return (ENXIO); 45104445Smdodd 46104445Smdodd /* IO port must be configured. */ 47104445Smdodd if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) 48104445Smdodd return (ENXIO); 49104445Smdodd 50104445Smdodd sc = device_get_softc(dev); 51104445Smdodd sc->dev = dev; 52104445Smdodd sc->port_rid = 0; 53104445Smdodd sc->port_type = SYS_RES_IOPORT; 54104445Smdodd error = mcd_alloc_resources(dev); 55104445Smdodd if (error) 56104445Smdodd goto fail; 57104445Smdodd 58104445Smdodd error = mcd_probe(sc); 59104445Smdodd if (error) { 60104445Smdodd device_printf(dev, "Probe failed.\n"); 61104445Smdodd goto fail; 62104445Smdodd } 63104445Smdodd 64104445Smdodd device_set_desc(dev, sc->data.name); 65104445Smdodd 66104445Smdoddfail: 67104445Smdodd mcd_release_resources(dev); 68104445Smdodd return (error); 69104445Smdodd} 70104445Smdodd 71104445Smdoddstatic int 72104445Smdoddmcd_isa_attach (device_t dev) 73104445Smdodd{ 74104445Smdodd struct mcd_softc * sc; 75104445Smdodd int error; 76104445Smdodd 77104445Smdodd sc = device_get_softc(dev); 78104445Smdodd error = 0; 79104445Smdodd 80104445Smdodd sc->dev = dev; 81104445Smdodd sc->port_rid = 0; 82104445Smdodd sc->port_type = SYS_RES_IOPORT; 83104445Smdodd error = mcd_alloc_resources(dev); 84104445Smdodd if (error) 85104445Smdodd goto fail; 86104445Smdodd 87104445Smdodd error = mcd_probe(sc); 88104445Smdodd if (error) { 89104445Smdodd device_printf(dev, "Re-Probe failed.\n"); 90104445Smdodd goto fail; 91104445Smdodd } 92104445Smdodd 93104445Smdodd error = mcd_attach(sc); 94104445Smdodd if (error) { 95104445Smdodd device_printf(dev, "Attach failed.\n"); 96104445Smdodd goto fail; 97104445Smdodd } 98104445Smdodd 99104445Smdodd return (0); 100104445Smdoddfail: 101104445Smdodd mcd_release_resources(dev); 102104445Smdodd return (error); 103104445Smdodd} 104104445Smdodd 105104445Smdoddstatic int 106104445Smdoddmcd_isa_detach (device_t dev) 107104445Smdodd{ 108104445Smdodd struct mcd_softc * sc; 109104445Smdodd int error; 110104445Smdodd 111104445Smdodd sc = device_get_softc(dev); 112104445Smdodd error = 0; 113104445Smdodd 114104545Smdodd destroy_dev(sc->mcd_dev_t); 115104445Smdodd 116104445Smdodd mcd_release_resources(dev); 117104445Smdodd 118104445Smdodd return (error); 119104445Smdodd} 120104445Smdodd 121104445Smdoddstatic int 122104445Smdoddmcd_alloc_resources (device_t dev) 123104445Smdodd{ 124104445Smdodd struct mcd_softc * sc; 125104445Smdodd int error; 126104445Smdodd 127104445Smdodd sc = device_get_softc(dev); 128104445Smdodd error = 0; 129104445Smdodd 130104445Smdodd if (sc->port_type) { 131127135Snjl sc->port = bus_alloc_resource_any(dev, sc->port_type, 132127135Snjl &sc->port_rid, RF_ACTIVE); 133104445Smdodd if (sc->port == NULL) { 134104445Smdodd device_printf(dev, "Unable to allocate PORT resource.\n"); 135104445Smdodd error = ENOMEM; 136104445Smdodd goto bad; 137104445Smdodd } 138104445Smdodd sc->port_bst = rman_get_bustag(sc->port); 139104445Smdodd sc->port_bsh = rman_get_bushandle(sc->port); 140104445Smdodd } 141104445Smdodd 142104445Smdodd if (sc->irq_type) { 143127135Snjl sc->irq = bus_alloc_resource_any(dev, sc->irq_type, 144127135Snjl &sc->irq_rid, RF_ACTIVE); 145104445Smdodd if (sc->irq == NULL) { 146104445Smdodd device_printf(dev, "Unable to allocate IRQ resource.\n"); 147104445Smdodd error = ENOMEM; 148104445Smdodd goto bad; 149104445Smdodd } 150104445Smdodd } 151104445Smdodd 152104445Smdodd if (sc->drq_type) { 153127135Snjl sc->drq = bus_alloc_resource_any(dev, sc->drq_type, 154127135Snjl &sc->drq_rid, RF_ACTIVE); 155104445Smdodd if (sc->drq == NULL) { 156104445Smdodd device_printf(dev, "Unable to allocate DRQ resource.\n"); 157104445Smdodd error = ENOMEM; 158104445Smdodd goto bad; 159104445Smdodd } 160104445Smdodd } 161104445Smdodd 162104445Smdodd mtx_init(&sc->mtx, device_get_nameunit(dev), 163104445Smdodd "Interrupt lock", MTX_DEF | MTX_RECURSE); 164104445Smdodd 165104445Smdoddbad: 166104445Smdodd return (error); 167104445Smdodd} 168104445Smdodd 169105215Sphkstatic void 170104445Smdoddmcd_release_resources (device_t dev) 171104445Smdodd{ 172104445Smdodd struct mcd_softc * sc; 173104445Smdodd 174104445Smdodd sc = device_get_softc(dev); 175104445Smdodd 176104445Smdodd if (sc->irq_ih) 177104445Smdodd bus_teardown_intr(dev, sc->irq, sc->irq_ih); 178104445Smdodd if (sc->port) { 179104445Smdodd bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port); 180104445Smdodd sc->port_bst = 0; 181104445Smdodd sc->port_bsh = 0; 182104445Smdodd } 183104445Smdodd if (sc->irq) 184104445Smdodd bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq); 185104445Smdodd if (sc->drq) 186104445Smdodd bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq); 187104445Smdodd 188104445Smdodd if (mtx_initialized(&sc->mtx) != 0) 189104445Smdodd mtx_destroy(&sc->mtx); 190104445Smdodd 191104445Smdodd return; 192104445Smdodd} 193104445Smdodd 194104445Smdoddstatic device_method_t mcd_isa_methods[] = { 195104445Smdodd DEVMETHOD(device_probe, mcd_isa_probe), 196104445Smdodd DEVMETHOD(device_attach, mcd_isa_attach), 197104445Smdodd DEVMETHOD(device_detach, mcd_isa_detach), 198104445Smdodd 199104445Smdodd { 0, 0 } 200104445Smdodd}; 201104445Smdodd 202104445Smdoddstatic driver_t mcd_isa_driver = { 203104445Smdodd "mcd", 204104445Smdodd mcd_isa_methods, 205104445Smdodd sizeof(struct mcd_softc) 206104445Smdodd}; 207104445Smdodd 208104445Smdoddstatic devclass_t mcd_devclass; 209104445Smdodd 210104445SmdoddDRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0); 211