summaryrefslogtreecommitdiffstats
path: root/sys/isa/fd.c
diff options
context:
space:
mode:
authorjoerg <joerg@FreeBSD.org>2001-06-29 07:36:29 +0000
committerjoerg <joerg@FreeBSD.org>2001-06-29 07:36:29 +0000
commit99064451943d2624692c9d819492b03ec00ebfcd (patch)
tree26b185d25159dd387d41c613bab5c3e274d8978f /sys/isa/fd.c
parentd0edfde0be0809c3c85d83aeb3b5632863906be4 (diff)
downloadFreeBSD-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.c34
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);
OpenPOWER on IntegriCloud