summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-07-15 16:39:40 +0000
committernjl <njl@FreeBSD.org>2004-07-15 16:39:40 +0000
commitc36db208d38f01c3ff26d7b70f852cde01fb15ee (patch)
tree31248b222d1fcc22f1ef0014a458a2ba78c7d29d /sys/dev
parentb29a887bf7550805f96453af9dcb83b22b2a68ff (diff)
downloadFreeBSD-src-c36db208d38f01c3ff26d7b70f852cde01fb15ee.zip
FreeBSD-src-c36db208d38f01c3ff26d7b70f852cde01fb15ee.tar.gz
Re-work for fdc_acpi. Expose fdc_add_child() and move the static
hints-based probe to fdc_hints_probe(). Also: * Fix some resource leaks when attach fails. * Remove the FDC_ATTACHED flag. It was supposed to prevent multiple unloads but this is not necessary.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdc/fdc.c57
-rw-r--r--sys/dev/fdc/fdcvar.h6
2 files changed, 36 insertions, 27 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index 331ea5f..0c653b5 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -241,7 +241,6 @@ static int enable_fifo(fdc_p fdc);
static int fd_sense_drive_status(fdc_p, int *);
static int fd_sense_int(fdc_p, int *, int *);
static int fd_read_status(fdc_p);
-static void fdc_add_child(device_t, const char *, int);
static int fd_probe(device_t);
static int fd_attach(device_t);
static int fd_detach(device_t);
@@ -517,29 +516,38 @@ fdc_release_resources(struct fdc_data *fdc)
device_t dev;
dev = fdc->fdc_dev;
+ if (fdc->fdc_intr) {
+ BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
+ fdc->fdc_intr);
+ fdc->fdc_intr = NULL;
+ }
if (fdc->res_irq != 0) {
bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
fdc->res_irq);
bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
fdc->res_irq);
+ fdc->res_irq = NULL;
}
if (fdc->res_ctl != 0) {
bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
fdc->res_ctl);
bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
fdc->res_ctl);
+ fdc->res_ctl = NULL;
}
if (fdc->res_ioport != 0) {
bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
fdc->res_ioport);
bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
fdc->res_ioport);
+ fdc->res_ioport = NULL;
}
if (fdc->res_drq != 0) {
bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
fdc->res_drq);
bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
fdc->res_drq);
+ fdc->res_ioport = NULL;
}
}
@@ -613,14 +621,6 @@ fdc_detach(device_t dev)
/* reset controller, turn motor off */
fdout_wr(fdc, 0);
- if ((fdc->flags & FDC_ATTACHED) == 0) {
- device_printf(dev, "already unloaded\n");
- return (0);
- }
- fdc->flags &= ~FDC_ATTACHED;
-
- BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
- fdc->fdc_intr);
fdc_release_resources(fdc);
return (0);
}
@@ -628,38 +628,36 @@ fdc_detach(device_t dev)
/*
* Add a child device to the fdc controller. It will then be probed etc.
*/
-static void
+device_t
fdc_add_child(device_t dev, const char *name, int unit)
{
- int fdu, flags;
+ int flags;
struct fdc_ivars *ivar;
device_t child;
ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
if (ivar == NULL)
- return;
+ return (NULL);
child = device_add_child(dev, name, unit);
if (child == NULL) {
free(ivar, M_DEVBUF);
- return;
+ return (NULL);
}
device_set_ivars(child, ivar);
- if (resource_int_value(name, unit, "drive", &fdu) != 0)
- fdu = 0;
- fdc_set_fdunit(child, fdu);
- fdc_set_fdtype(child, FDT_NONE);
+ ivar->fdunit = unit;
+ ivar->fdtype = FDT_NONE;
if (resource_int_value(name, unit, "flags", &flags) == 0)
device_set_flags(child, flags);
if (resource_disabled(name, unit))
device_disable(child);
+ return (child);
}
int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
- const char *name, *dname;
- int i, dunit, error;
+ int error;
fdc = device_get_softc(dev);
fdc->fdc_dev = dev;
@@ -671,7 +669,7 @@ fdc_attach(device_t dev)
return error;
}
fdc->fdcu = device_get_unit(dev);
- fdc->flags |= FDC_ATTACHED | FDC_NEEDS_RESET;
+ fdc->flags |= FDC_NEEDS_RESET;
fdc->state = DEVIDLE;
@@ -679,18 +677,28 @@ fdc_attach(device_t dev)
fdout_wr(fdc, fdc->fdout = 0);
bioq_init(&fdc->head);
+ return (0);
+}
+
+int
+fdc_hints_probe(device_t dev)
+{
+ const char *name, *dname;
+ int i, error, dunit;
+
/*
* Probe and attach any children. We should probably detect
* devices from the BIOS unless overridden.
*/
name = device_get_nameunit(dev);
i = 0;
- while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
+ while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
+ resource_int_value(dname, dunit, "drive", &dunit);
fdc_add_child(dev, dname, dunit);
+ }
if ((error = bus_generic_attach(dev)) != 0)
return (error);
-
return (0);
}
@@ -732,9 +740,8 @@ fd_probe(device_t dev)
fd->fdsu = fdsu;
fd->fdu = device_get_unit(dev);
- type = FD_DTYPE(flags);
-
/* Auto-probe if fdinfo is present, but always allow override. */
+ type = FD_DTYPE(flags);
if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
fd->type = type;
goto done;
@@ -820,7 +827,7 @@ fd_probe(device_t dev)
return (ENXIO);
done:
- /* This doesn't work before the first reset. Or set_motor?? */
+ /* This doesn't work before the first reset. */
if ((fdc->flags & FDC_HAS_FIFO) == 0 &&
fdc->fdct == FDC_ENHANCED &&
(device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 &&
diff --git a/sys/dev/fdc/fdcvar.h b/sys/dev/fdc/fdcvar.h
index 30dd825..3322575 100644
--- a/sys/dev/fdc/fdcvar.h
+++ b/sys/dev/fdc/fdcvar.h
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 2004 M. Warner Losh.
* All rights reserved.
*
@@ -80,7 +80,6 @@ struct fdc_data
int dmacnt;
int dmachan;
int flags;
-#define FDC_ATTACHED 0x01
#define FDC_STAT_VALID 0x08
#define FDC_HAS_FIFO 0x10
#define FDC_NEEDS_RESET 0x20
@@ -137,8 +136,11 @@ void fdout_wr(fdc_p, u_int8_t);
int fd_cmd(struct fdc_data *, int, ...);
void fdc_release_resources(struct fdc_data *);
int fdc_attach(device_t);
+int fdc_hints_probe(device_t);
int fdc_detach(device_t dev);
+device_t fdc_add_child(device_t, const char *, int);
int fdc_initial_reset(struct fdc_data *);
int fdc_print_child(device_t, device_t);
int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
int fdc_write_ivar(device_t, device_t, int, uintptr_t);
+int fdc_isa_alloc_resources(device_t, struct fdc_data *);
OpenPOWER on IntegriCloud