diff options
author | joerg <joerg@FreeBSD.org> | 2001-06-29 07:36:29 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 2001-06-29 07:36:29 +0000 |
commit | 99064451943d2624692c9d819492b03ec00ebfcd (patch) | |
tree | 26b185d25159dd387d41c613bab5c3e274d8978f /sys/isa/fd.c | |
parent | d0edfde0be0809c3c85d83aeb3b5632863906be4 (diff) | |
download | FreeBSD-src-99064451943d2624692c9d819492b03ec00ebfcd.zip FreeBSD-src-99064451943d2624692c9d819492b03ec00ebfcd.tar.gz |
First stab at fixing resource deallocation, and implementing fdc(4) as
a KLD. Still doesn't work well except in the PCMCIA case (now if only
pccardd(8) could load and unload drivers dynamically...). Mainly, it
tries to find fdc0 on the PCI bus for whatever obscure reasons, but i
need someone who understands driver(9) to fix this. However, it's at least
already better than before, and i'm tired of maintaining too many private
changes in my tree, given the large patches bde submitted. :)
Idea of a KLD triggered by: Michael Reifenberger <root@nihil.plaut.de>
Diffstat (limited to 'sys/isa/fd.c')
-rw-r--r-- | sys/isa/fd.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/sys/isa/fd.c b/sys/isa/fd.c index d742117..1aff68b 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -179,6 +179,8 @@ struct fd_data { struct callout_handle toffhandle; struct callout_handle tohandle; struct devstat device_stats; + eventhandler_tag clonetag; + dev_t masterdev; device_t dev; fdu_t fdu; }; @@ -506,7 +508,7 @@ static int fdc_alloc_resources(struct fdc_data *fdc) { device_t dev; - int ispnp, ispcmcia; + int ispnp, ispcmcia, nports; dev = fdc->fdc_dev; ispnp = (fdc->flags & FDC_ISPNP) != 0; @@ -525,12 +527,13 @@ fdc_alloc_resources(struct fdc_data *fdc) * uses the register with offset 6 for pseudo-DMA, and the * one with offset 7 as control register. */ + nports = ispcmcia ? 8 : (ispnp ? 1 : 6); fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &fdc->rid_ioport, 0ul, ~0ul, - ispcmcia ? 8 : (ispnp ? 1 : 6), - RF_ACTIVE); + nports, RF_ACTIVE); if (fdc->res_ioport == 0) { - device_printf(dev, "cannot reserve I/O port range\n"); + device_printf(dev, "cannot reserve I/O port range (%d ports)\n", + nports); return ENXIO; } fdc->portt = rman_get_bustag(fdc->res_ioport); @@ -578,7 +581,7 @@ fdc_alloc_resources(struct fdc_data *fdc) 0ul, ~0ul, 1, RF_ACTIVE); if (fdc->res_ctl == 0) { device_printf(dev, - "cannot reserve control I/O port range\n"); + "cannot reserve control I/O port range (control port)\n"); return ENXIO; } fdc->ctlt = rman_get_bustag(fdc->res_ctl); @@ -769,8 +772,10 @@ out: return (error); } +#endif /* NCARD > 0 */ + static int -fdc_pccard_detach(device_t dev) +fdc_detach(device_t dev) { struct fdc_data *fdc; int error; @@ -781,6 +786,12 @@ fdc_pccard_detach(device_t dev) if ((error = bus_generic_detach(dev))) return (error); + /* reset controller, turn motor off */ + fdout_wr(fdc, 0); + + if ((fdc->flags & FDC_NODMA) == 0) + isa_dma_release(fdc->dmachan); + if ((fdc->flags & FDC_ATTACHED) == 0) { device_printf(dev, "already unloaded\n"); return (0); @@ -794,8 +805,6 @@ fdc_pccard_detach(device_t dev) return (0); } -#endif /* NCARD > 0 */ - /* * Add a child device to the fdc controller. It will then be probed etc. */ @@ -886,7 +895,7 @@ static device_method_t fdc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fdc_probe), DEVMETHOD(device_attach, fdc_attach), - DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_detach, fdc_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), @@ -913,7 +922,7 @@ static device_method_t fdc_pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fdc_pccard_probe), DEVMETHOD(device_attach, fdc_attach), - DEVMETHOD(device_detach, fdc_pccard_detach), + DEVMETHOD(device_detach, fdc_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), @@ -1162,6 +1171,11 @@ fd_detach(device_t dev) struct fd_data *fd; fd = device_get_softc(dev); + devstat_remove_entry(&fd->device_stats); + destroy_dev(fd->masterdev); + cdevsw_remove(&fd_cdevsw); + /* XXX need to destroy cloned devs as well */ + EVENTHANDLER_DEREGISTER(dev_clone, fd->clonetag); untimeout(fd_turnoff, fd, fd->toffhandle); return (0); |