mcd_isa.c revision 105215
1/* 2 * $FreeBSD: head/sys/dev/mcd/mcd_isa.c 105215 2002-10-16 08:48:39Z phk $ 3 */ 4 5#include <sys/param.h> 6#include <sys/systm.h> 7#include <sys/kernel.h> 8#include <sys/module.h> 9#include <sys/conf.h> 10#include <sys/fcntl.h> 11#include <sys/bio.h> 12#include <sys/cdio.h> 13#include <sys/disklabel.h> 14#include <sys/bus.h> 15 16#include <sys/lock.h> 17#include <sys/mutex.h> 18 19#include <machine/bus_pio.h> 20#include <machine/bus.h> 21#include <machine/resource.h> 22#include <sys/rman.h> 23 24#include <isa/isavar.h> 25 26#include <dev/mcd/mcdreg.h> 27#include <dev/mcd/mcdvar.h> 28 29static int mcd_isa_probe (device_t); 30static int mcd_isa_attach (device_t); 31static int mcd_isa_detach (device_t); 32 33static int mcd_alloc_resources (device_t); 34static void mcd_release_resources (device_t); 35 36static int 37mcd_isa_probe (device_t dev) 38{ 39 struct mcd_softc * sc; 40 int error; 41 42 /* No pnp support */ 43 if (isa_get_vendorid(dev)) 44 return (ENXIO); 45 46 /* IO port must be configured. */ 47 if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) 48 return (ENXIO); 49 50 sc = device_get_softc(dev); 51 sc->dev = dev; 52 sc->port_rid = 0; 53 sc->port_type = SYS_RES_IOPORT; 54 error = mcd_alloc_resources(dev); 55 if (error) 56 goto fail; 57 58 error = mcd_probe(sc); 59 if (error) { 60 device_printf(dev, "Probe failed.\n"); 61 goto fail; 62 } 63 64 device_set_desc(dev, sc->data.name); 65 66fail: 67 mcd_release_resources(dev); 68 return (error); 69} 70 71static int 72mcd_isa_attach (device_t dev) 73{ 74 struct mcd_softc * sc; 75 int error; 76 77 sc = device_get_softc(dev); 78 error = 0; 79 80 sc->dev = dev; 81 sc->port_rid = 0; 82 sc->port_type = SYS_RES_IOPORT; 83 error = mcd_alloc_resources(dev); 84 if (error) 85 goto fail; 86 87 error = mcd_probe(sc); 88 if (error) { 89 device_printf(dev, "Re-Probe failed.\n"); 90 goto fail; 91 } 92 93 error = mcd_attach(sc); 94 if (error) { 95 device_printf(dev, "Attach failed.\n"); 96 goto fail; 97 } 98 99 return (0); 100fail: 101 mcd_release_resources(dev); 102 return (error); 103} 104 105static int 106mcd_isa_detach (device_t dev) 107{ 108 struct mcd_softc * sc; 109 int error; 110 111 sc = device_get_softc(dev); 112 error = 0; 113 114 destroy_dev(sc->mcd_dev_t); 115 116 mcd_release_resources(dev); 117 118 return (error); 119} 120 121static int 122mcd_alloc_resources (device_t dev) 123{ 124 struct mcd_softc * sc; 125 int error; 126 127 sc = device_get_softc(dev); 128 error = 0; 129 130 if (sc->port_type) { 131 sc->port = bus_alloc_resource(dev, sc->port_type, &sc->port_rid, 132 0, ~0, 1, RF_ACTIVE); 133 if (sc->port == NULL) { 134 device_printf(dev, "Unable to allocate PORT resource.\n"); 135 error = ENOMEM; 136 goto bad; 137 } 138 sc->port_bst = rman_get_bustag(sc->port); 139 sc->port_bsh = rman_get_bushandle(sc->port); 140 } 141 142 if (sc->irq_type) { 143 sc->irq = bus_alloc_resource(dev, sc->irq_type, &sc->irq_rid, 144 0, ~0, 1, RF_ACTIVE); 145 if (sc->irq == NULL) { 146 device_printf(dev, "Unable to allocate IRQ resource.\n"); 147 error = ENOMEM; 148 goto bad; 149 } 150 } 151 152 if (sc->drq_type) { 153 sc->drq = bus_alloc_resource(dev, sc->drq_type, &sc->drq_rid, 154 0, ~0, 1, RF_ACTIVE); 155 if (sc->drq == NULL) { 156 device_printf(dev, "Unable to allocate DRQ resource.\n"); 157 error = ENOMEM; 158 goto bad; 159 } 160 } 161 162 mtx_init(&sc->mtx, device_get_nameunit(dev), 163 "Interrupt lock", MTX_DEF | MTX_RECURSE); 164 165bad: 166 return (error); 167} 168 169static void 170mcd_release_resources (device_t dev) 171{ 172 struct mcd_softc * sc; 173 174 sc = device_get_softc(dev); 175 176 if (sc->irq_ih) 177 bus_teardown_intr(dev, sc->irq, sc->irq_ih); 178 if (sc->port) { 179 bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port); 180 sc->port_bst = 0; 181 sc->port_bsh = 0; 182 } 183 if (sc->irq) 184 bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq); 185 if (sc->drq) 186 bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq); 187 188 if (mtx_initialized(&sc->mtx) != 0) 189 mtx_destroy(&sc->mtx); 190 191 return; 192} 193 194static device_method_t mcd_isa_methods[] = { 195 DEVMETHOD(device_probe, mcd_isa_probe), 196 DEVMETHOD(device_attach, mcd_isa_attach), 197 DEVMETHOD(device_detach, mcd_isa_detach), 198 199 { 0, 0 } 200}; 201 202static driver_t mcd_isa_driver = { 203 "mcd", 204 mcd_isa_methods, 205 sizeof(struct mcd_softc) 206}; 207 208static devclass_t mcd_devclass; 209 210DRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0); 211