diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 331ea5feb781..0c653b54d9cf 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 30dd825767ce..3322575b30c6 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 *);