1/* 2 */ 3 4#include <sys/cdefs.h> 5__FBSDID("$FreeBSD$"); 6 7#include <sys/param.h> 8#include <sys/systm.h> 9#include <sys/kernel.h> 10#include <sys/module.h> 11#include <sys/conf.h> 12#include <sys/fcntl.h> 13#include <sys/bio.h> 14#include <sys/cdio.h> 15#include <sys/bus.h> 16 17#include <sys/mutex.h> 18 19#include <machine/bus.h> 20#include <machine/resource.h> 21#include <sys/rman.h> 22 23#include <isa/isavar.h> 24 25#include <dev/scd/scdreg.h> 26#include <dev/scd/scdvar.h> 27 28static int scd_isa_probe (device_t); 29static int scd_isa_attach (device_t); 30static int scd_isa_detach (device_t); 31 32static int scd_alloc_resources (device_t); 33static void scd_release_resources (device_t); 34 35static int 36scd_isa_probe (device_t dev) 37{ 38 struct scd_softc * sc; 39 int error; 40 41 /* No pnp support */ 42 if (isa_get_vendorid(dev)) 43 return (ENXIO); 44 45 /* IO port must be configured. */ 46 if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) 47 return (ENXIO); 48 49 sc = device_get_softc(dev); 50 sc->dev = dev; 51 sc->port_rid = 0; 52 sc->port_type = SYS_RES_IOPORT; 53 error = scd_alloc_resources(dev); 54 if (error) 55 goto fail; 56 57 error = scd_probe(sc); 58 if (error) { 59 device_printf(dev, "Probe failed.\n"); 60 goto fail; 61 } 62 63 device_set_desc(dev, sc->data.name); 64 65fail: 66 scd_release_resources(dev); 67 return (error); 68} 69 70static int 71scd_isa_attach (device_t dev) 72{ 73 struct scd_softc * sc; 74 int error; 75 76 sc = device_get_softc(dev); 77 error = 0; 78 79 sc->dev = dev; 80 sc->port_rid = 0; 81 sc->port_type = SYS_RES_IOPORT; 82 error = scd_alloc_resources(dev); 83 if (error) 84 goto fail; 85 86 error = scd_probe(sc); 87 if (error) { 88 device_printf(dev, "Re-Probe failed.\n"); 89 goto fail; 90 } 91 92 error = scd_attach(sc); 93 if (error) { 94 device_printf(dev, "Attach failed.\n"); 95 goto fail; 96 } 97 98 return (0); 99fail: 100 scd_release_resources(dev); 101 return (error); 102} 103 104static int 105scd_isa_detach (device_t dev) 106{ 107 struct scd_softc * sc; 108 int error; 109 110 sc = device_get_softc(dev); 111 error = 0; 112 113 destroy_dev(sc->scd_dev_t); 114 115 scd_release_resources(dev); 116 117 return (error); 118} 119 120static int 121scd_alloc_resources (device_t dev) 122{ 123 struct scd_softc * sc; 124 int error; 125 126 sc = device_get_softc(dev); 127 error = 0; 128 129 if (sc->port_type) { 130 sc->port = bus_alloc_resource_any(dev, sc->port_type, 131 &sc->port_rid, RF_ACTIVE); 132 if (sc->port == NULL) { 133 device_printf(dev, "Unable to allocate PORT resource.\n"); 134 error = ENOMEM; 135 goto bad; 136 } 137 sc->port_bst = rman_get_bustag(sc->port); 138 sc->port_bsh = rman_get_bushandle(sc->port); 139 } 140 141 mtx_init(&sc->mtx, device_get_nameunit(dev), 142 "Interrupt lock", MTX_DEF | MTX_RECURSE); 143 144bad: 145 return (error); 146} 147 148void 149scd_release_resources (device_t dev) 150{ 151 struct scd_softc * sc; 152 153 sc = device_get_softc(dev); 154 155 if (sc->port) { 156 bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port); 157 sc->port_bst = 0; 158 sc->port_bsh = 0; 159 } 160 161 if (mtx_initialized(&sc->mtx) != 0) 162 mtx_destroy(&sc->mtx); 163 164 return; 165} 166 167static device_method_t scd_isa_methods[] = { 168 DEVMETHOD(device_probe, scd_isa_probe), 169 DEVMETHOD(device_attach, scd_isa_attach), 170 DEVMETHOD(device_detach, scd_isa_detach), 171 172 { 0, 0 } 173}; 174 175static driver_t scd_isa_driver = { 176 "scd", 177 scd_isa_methods, 178 sizeof(struct scd_softc) 179}; 180 181static devclass_t scd_devclass; 182 183DRIVER_MODULE(scd, isa, scd_isa_driver, scd_devclass, NULL, 0); 184