mirror of
https://github.com/opnsense/src.git
synced 2026-04-21 14:17:06 -04:00
Patch up some of the evilness left over from the early newbus porting.
In particular: - Don't leave resources allocated in the probe routine. Allocate them during probe and release them. Probe's job is to identify devices only. - Don't abuse the ivars pointer.. (!). Create real ivars and use the proper access system. (the bus_read_ivar method) - Don't add the children until attach() has successfully grabbed the hardware, otherwise there are potential leaks if attach fails.
This commit is contained in:
parent
2e22df0b11
commit
37286586ff
3 changed files with 288 additions and 166 deletions
|
|
@ -186,6 +186,10 @@ struct fd_data {
|
|||
device_t dev;
|
||||
fdu_t fdu;
|
||||
};
|
||||
|
||||
struct fdc_ivars {
|
||||
int fdunit;
|
||||
};
|
||||
static devclass_t fd_devclass;
|
||||
|
||||
/***********************************************************************\
|
||||
|
|
@ -207,7 +211,6 @@ int in_fdc(struct fdc_data *);
|
|||
int out_fdc(struct fdc_data *, int);
|
||||
|
||||
/* internal functions */
|
||||
static void fdc_add_device(device_t, const char *, int);
|
||||
static void fdc_intr(void *);
|
||||
static void set_motor(struct fdc_data *, int, int);
|
||||
# define TURNON 1
|
||||
|
|
@ -607,31 +610,14 @@ fd_read_status(fdc_p fdc, int fdsu)
|
|||
/* autoconfiguration stuff */
|
||||
/****************************************************************************/
|
||||
|
||||
static struct isa_pnp_id fdc_ids[] = {
|
||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
||||
{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* fdc controller section.
|
||||
*/
|
||||
static int
|
||||
fdc_probe(device_t dev)
|
||||
fdc_alloc_resources(struct fdc_data *fdc)
|
||||
{
|
||||
int error, ispnp, ic_type;
|
||||
struct fdc_data *fdc;
|
||||
device_t dev;
|
||||
int ispnp;
|
||||
|
||||
/* Check pnp ids */
|
||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
||||
if (error == ENXIO)
|
||||
return ENXIO;
|
||||
ispnp = (error == 0);
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
bzero(fdc, sizeof *fdc);
|
||||
fdc->fdc_dev = dev;
|
||||
dev = fdc->fdc_dev;
|
||||
ispnp = fdc->fdc_ispnp;
|
||||
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
|
||||
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
|
||||
|
||||
|
|
@ -641,8 +627,7 @@ fdc_probe(device_t dev)
|
|||
RF_ACTIVE);
|
||||
if (fdc->res_ioport == 0) {
|
||||
device_printf(dev, "cannot reserve I/O port range\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->portt = rman_get_bustag(fdc->res_ioport);
|
||||
fdc->porth = rman_get_bushandle(fdc->res_ioport);
|
||||
|
|
@ -679,9 +664,8 @@ fdc_probe(device_t dev)
|
|||
&fdc->rid_ctl, 0ul, ~0ul,
|
||||
1, RF_ACTIVE);
|
||||
if (fdc->res_ctl == 0) {
|
||||
device_printf(dev, "cannot reserve I/O port range\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
device_printf(dev, "cannot reserve I/O port range 2\n");
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->ctlt = rman_get_bustag(fdc->res_ctl);
|
||||
fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
|
||||
|
|
@ -692,20 +676,100 @@ fdc_probe(device_t dev)
|
|||
RF_ACTIVE);
|
||||
if (fdc->res_irq == 0) {
|
||||
device_printf(dev, "cannot reserve interrupt line\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ,
|
||||
&fdc->rid_drq, 0ul, ~0ul, 1,
|
||||
RF_ACTIVE);
|
||||
if (fdc->res_drq == 0) {
|
||||
device_printf(dev, "cannot reserve DMA request line\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->dmachan = fdc->res_drq->r_start;
|
||||
error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
INTR_TYPE_BIO, fdc_intr, fdc, &fdc->fdc_intr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fdc_release_resources(struct fdc_data *fdc)
|
||||
{
|
||||
device_t dev;
|
||||
|
||||
dev = fdc->fdc_dev;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* autoconfiguration stuff */
|
||||
/****************************************************************************/
|
||||
|
||||
static struct isa_pnp_id fdc_ids[] = {
|
||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
||||
{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
|
||||
{0}
|
||||
};
|
||||
|
||||
static int
|
||||
fdc_read_ivar(device_t dev, device_t child, int which, u_long *result)
|
||||
{
|
||||
struct fdc_ivars *ivars = device_get_ivars(child);
|
||||
|
||||
switch (which) {
|
||||
case FDC_IVAR_FDUNIT:
|
||||
*result = ivars->fdunit;
|
||||
break;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fdc controller section.
|
||||
*/
|
||||
static int
|
||||
fdc_probe(device_t dev)
|
||||
{
|
||||
int error, ic_type;
|
||||
struct fdc_data *fdc;
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
bzero(fdc, sizeof *fdc);
|
||||
fdc->fdc_dev = dev;
|
||||
|
||||
/* Check pnp ids */
|
||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
||||
if (error == ENXIO)
|
||||
return ENXIO;
|
||||
fdc->fdc_ispnp = (error == 0);
|
||||
|
||||
/* Attempt to allocate our resources for the duration of the probe */
|
||||
error = fdc_alloc_resources(fdc);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/* First - lets reset the floppy controller */
|
||||
fdout_wr(fdc, 0);
|
||||
|
|
@ -749,57 +813,31 @@ fdc_probe(device_t dev)
|
|||
if (device_get_flags(fdc->fdc_dev) & FDC_IS_PCMCIA)
|
||||
return(0);
|
||||
#endif
|
||||
return (0);
|
||||
|
||||
out:
|
||||
if (fdc->fdc_intr)
|
||||
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
fdc->fdc_intr);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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_release_resources(fdc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Aped dfr@freebsd.org's isa_add_device().
|
||||
* Add a child device to the fdc controller. It will then be probed etc.
|
||||
*/
|
||||
static void
|
||||
fdc_add_device(device_t dev, const char *name, int unit)
|
||||
fdc_add_child(device_t dev, const char *name, int unit)
|
||||
{
|
||||
int disabled, *ivar;
|
||||
int disabled;
|
||||
struct fdc_ivars *ivar;
|
||||
device_t child;
|
||||
|
||||
ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT);
|
||||
if (ivar == 0)
|
||||
if (ivar == NULL)
|
||||
return;
|
||||
if (resource_int_value(name, unit, "drive", ivar) != 0)
|
||||
*ivar = 0;
|
||||
bzero(ivar, sizeof *ivar);
|
||||
if (resource_int_value(name, unit, "drive", &ivar->fdunit) != 0)
|
||||
ivar->fdunit = 0;
|
||||
child = device_add_child(dev, name, unit);
|
||||
device_set_ivars(child, ivar);
|
||||
if (child == 0)
|
||||
if (child == NULL)
|
||||
return;
|
||||
device_set_ivars(child, ivar);
|
||||
if (resource_int_value(name, unit, "disabled", &disabled) == 0
|
||||
&& disabled != 0)
|
||||
device_disable(child);
|
||||
|
|
@ -808,17 +846,22 @@ fdc_add_device(device_t dev, const char *name, int unit)
|
|||
static int
|
||||
fdc_attach(device_t dev)
|
||||
{
|
||||
struct fdc_data *fdc = device_get_softc(dev);
|
||||
fdcu_t fdcu = device_get_unit(dev);
|
||||
int i;
|
||||
struct fdc_data *fdc;
|
||||
int i, error;
|
||||
|
||||
for (i = resource_query_string(-1, "at", device_get_nameunit(dev));
|
||||
i != -1;
|
||||
i = resource_query_string(i, "at", device_get_nameunit(dev)))
|
||||
fdc_add_device(dev, resource_query_name(i),
|
||||
resource_query_unit(i));
|
||||
|
||||
fdc->fdcu = fdcu;
|
||||
fdc = device_get_softc(dev);
|
||||
error = fdc_alloc_resources(fdc);
|
||||
if (error) {
|
||||
device_printf(dev, "cannot re-aquire resources\n");
|
||||
return error;
|
||||
}
|
||||
error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
INTR_TYPE_BIO, fdc_intr, fdc, &fdc->fdc_intr);
|
||||
if (error) {
|
||||
device_printf(dev, "cannot setup interrupt\n");
|
||||
return error;
|
||||
}
|
||||
fdc->fdcu = device_get_unit(dev);
|
||||
fdc->flags |= FDC_ATTACHED;
|
||||
|
||||
/* Acquire the DMA channel forever, The driver will do the rest */
|
||||
|
|
@ -832,8 +875,15 @@ fdc_attach(device_t dev)
|
|||
bufq_init(&fdc->head);
|
||||
|
||||
/*
|
||||
* Probe and attach any children as were configured above.
|
||||
* Probe and attach any children. We should probably detect
|
||||
* devices from the BIOS unless overridden.
|
||||
*/
|
||||
for (i = resource_query_string(-1, "at", device_get_nameunit(dev));
|
||||
i != -1;
|
||||
i = resource_query_string(i, "at", device_get_nameunit(dev)))
|
||||
fdc_add_child(dev, resource_query_name(i),
|
||||
resource_query_unit(i));
|
||||
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
|
||||
|
|
@ -844,7 +894,7 @@ fdc_print_child(device_t me, device_t child)
|
|||
|
||||
retval += bus_print_child_header(me, child);
|
||||
retval += printf(" on %s drive %d\n", device_get_nameunit(me),
|
||||
*(int *)device_get_ivars(child));
|
||||
fdc_get_fdunit(child));
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
|
@ -860,6 +910,7 @@ static device_method_t fdc_methods[] = {
|
|||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
||||
/* Our children never use any other bus interface methods. */
|
||||
|
||||
{ 0, 0 }
|
||||
|
|
|
|||
217
sys/isa/fd.c
217
sys/isa/fd.c
|
|
@ -186,6 +186,10 @@ struct fd_data {
|
|||
device_t dev;
|
||||
fdu_t fdu;
|
||||
};
|
||||
|
||||
struct fdc_ivars {
|
||||
int fdunit;
|
||||
};
|
||||
static devclass_t fd_devclass;
|
||||
|
||||
/***********************************************************************\
|
||||
|
|
@ -207,7 +211,6 @@ int in_fdc(struct fdc_data *);
|
|||
int out_fdc(struct fdc_data *, int);
|
||||
|
||||
/* internal functions */
|
||||
static void fdc_add_device(device_t, const char *, int);
|
||||
static void fdc_intr(void *);
|
||||
static void set_motor(struct fdc_data *, int, int);
|
||||
# define TURNON 1
|
||||
|
|
@ -607,31 +610,14 @@ fd_read_status(fdc_p fdc, int fdsu)
|
|||
/* autoconfiguration stuff */
|
||||
/****************************************************************************/
|
||||
|
||||
static struct isa_pnp_id fdc_ids[] = {
|
||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
||||
{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* fdc controller section.
|
||||
*/
|
||||
static int
|
||||
fdc_probe(device_t dev)
|
||||
fdc_alloc_resources(struct fdc_data *fdc)
|
||||
{
|
||||
int error, ispnp, ic_type;
|
||||
struct fdc_data *fdc;
|
||||
device_t dev;
|
||||
int ispnp;
|
||||
|
||||
/* Check pnp ids */
|
||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
||||
if (error == ENXIO)
|
||||
return ENXIO;
|
||||
ispnp = (error == 0);
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
bzero(fdc, sizeof *fdc);
|
||||
fdc->fdc_dev = dev;
|
||||
dev = fdc->fdc_dev;
|
||||
ispnp = fdc->fdc_ispnp;
|
||||
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
|
||||
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
|
||||
|
||||
|
|
@ -641,8 +627,7 @@ fdc_probe(device_t dev)
|
|||
RF_ACTIVE);
|
||||
if (fdc->res_ioport == 0) {
|
||||
device_printf(dev, "cannot reserve I/O port range\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->portt = rman_get_bustag(fdc->res_ioport);
|
||||
fdc->porth = rman_get_bushandle(fdc->res_ioport);
|
||||
|
|
@ -679,9 +664,8 @@ fdc_probe(device_t dev)
|
|||
&fdc->rid_ctl, 0ul, ~0ul,
|
||||
1, RF_ACTIVE);
|
||||
if (fdc->res_ctl == 0) {
|
||||
device_printf(dev, "cannot reserve I/O port range\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
device_printf(dev, "cannot reserve I/O port range 2\n");
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->ctlt = rman_get_bustag(fdc->res_ctl);
|
||||
fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
|
||||
|
|
@ -692,20 +676,100 @@ fdc_probe(device_t dev)
|
|||
RF_ACTIVE);
|
||||
if (fdc->res_irq == 0) {
|
||||
device_printf(dev, "cannot reserve interrupt line\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ,
|
||||
&fdc->rid_drq, 0ul, ~0ul, 1,
|
||||
RF_ACTIVE);
|
||||
if (fdc->res_drq == 0) {
|
||||
device_printf(dev, "cannot reserve DMA request line\n");
|
||||
error = ENXIO;
|
||||
goto out;
|
||||
return ENXIO;
|
||||
}
|
||||
fdc->dmachan = fdc->res_drq->r_start;
|
||||
error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
INTR_TYPE_BIO, fdc_intr, fdc, &fdc->fdc_intr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fdc_release_resources(struct fdc_data *fdc)
|
||||
{
|
||||
device_t dev;
|
||||
|
||||
dev = fdc->fdc_dev;
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* autoconfiguration stuff */
|
||||
/****************************************************************************/
|
||||
|
||||
static struct isa_pnp_id fdc_ids[] = {
|
||||
{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
|
||||
{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
|
||||
{0}
|
||||
};
|
||||
|
||||
static int
|
||||
fdc_read_ivar(device_t dev, device_t child, int which, u_long *result)
|
||||
{
|
||||
struct fdc_ivars *ivars = device_get_ivars(child);
|
||||
|
||||
switch (which) {
|
||||
case FDC_IVAR_FDUNIT:
|
||||
*result = ivars->fdunit;
|
||||
break;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fdc controller section.
|
||||
*/
|
||||
static int
|
||||
fdc_probe(device_t dev)
|
||||
{
|
||||
int error, ic_type;
|
||||
struct fdc_data *fdc;
|
||||
|
||||
fdc = device_get_softc(dev);
|
||||
bzero(fdc, sizeof *fdc);
|
||||
fdc->fdc_dev = dev;
|
||||
|
||||
/* Check pnp ids */
|
||||
error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
|
||||
if (error == ENXIO)
|
||||
return ENXIO;
|
||||
fdc->fdc_ispnp = (error == 0);
|
||||
|
||||
/* Attempt to allocate our resources for the duration of the probe */
|
||||
error = fdc_alloc_resources(fdc);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/* First - lets reset the floppy controller */
|
||||
fdout_wr(fdc, 0);
|
||||
|
|
@ -749,57 +813,31 @@ fdc_probe(device_t dev)
|
|||
if (device_get_flags(fdc->fdc_dev) & FDC_IS_PCMCIA)
|
||||
return(0);
|
||||
#endif
|
||||
return (0);
|
||||
|
||||
out:
|
||||
if (fdc->fdc_intr)
|
||||
BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
fdc->fdc_intr);
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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_release_resources(fdc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Aped dfr@freebsd.org's isa_add_device().
|
||||
* Add a child device to the fdc controller. It will then be probed etc.
|
||||
*/
|
||||
static void
|
||||
fdc_add_device(device_t dev, const char *name, int unit)
|
||||
fdc_add_child(device_t dev, const char *name, int unit)
|
||||
{
|
||||
int disabled, *ivar;
|
||||
int disabled;
|
||||
struct fdc_ivars *ivar;
|
||||
device_t child;
|
||||
|
||||
ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT);
|
||||
if (ivar == 0)
|
||||
if (ivar == NULL)
|
||||
return;
|
||||
if (resource_int_value(name, unit, "drive", ivar) != 0)
|
||||
*ivar = 0;
|
||||
bzero(ivar, sizeof *ivar);
|
||||
if (resource_int_value(name, unit, "drive", &ivar->fdunit) != 0)
|
||||
ivar->fdunit = 0;
|
||||
child = device_add_child(dev, name, unit);
|
||||
device_set_ivars(child, ivar);
|
||||
if (child == 0)
|
||||
if (child == NULL)
|
||||
return;
|
||||
device_set_ivars(child, ivar);
|
||||
if (resource_int_value(name, unit, "disabled", &disabled) == 0
|
||||
&& disabled != 0)
|
||||
device_disable(child);
|
||||
|
|
@ -808,17 +846,22 @@ fdc_add_device(device_t dev, const char *name, int unit)
|
|||
static int
|
||||
fdc_attach(device_t dev)
|
||||
{
|
||||
struct fdc_data *fdc = device_get_softc(dev);
|
||||
fdcu_t fdcu = device_get_unit(dev);
|
||||
int i;
|
||||
struct fdc_data *fdc;
|
||||
int i, error;
|
||||
|
||||
for (i = resource_query_string(-1, "at", device_get_nameunit(dev));
|
||||
i != -1;
|
||||
i = resource_query_string(i, "at", device_get_nameunit(dev)))
|
||||
fdc_add_device(dev, resource_query_name(i),
|
||||
resource_query_unit(i));
|
||||
|
||||
fdc->fdcu = fdcu;
|
||||
fdc = device_get_softc(dev);
|
||||
error = fdc_alloc_resources(fdc);
|
||||
if (error) {
|
||||
device_printf(dev, "cannot re-aquire resources\n");
|
||||
return error;
|
||||
}
|
||||
error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
|
||||
INTR_TYPE_BIO, fdc_intr, fdc, &fdc->fdc_intr);
|
||||
if (error) {
|
||||
device_printf(dev, "cannot setup interrupt\n");
|
||||
return error;
|
||||
}
|
||||
fdc->fdcu = device_get_unit(dev);
|
||||
fdc->flags |= FDC_ATTACHED;
|
||||
|
||||
/* Acquire the DMA channel forever, The driver will do the rest */
|
||||
|
|
@ -832,8 +875,15 @@ fdc_attach(device_t dev)
|
|||
bufq_init(&fdc->head);
|
||||
|
||||
/*
|
||||
* Probe and attach any children as were configured above.
|
||||
* Probe and attach any children. We should probably detect
|
||||
* devices from the BIOS unless overridden.
|
||||
*/
|
||||
for (i = resource_query_string(-1, "at", device_get_nameunit(dev));
|
||||
i != -1;
|
||||
i = resource_query_string(i, "at", device_get_nameunit(dev)))
|
||||
fdc_add_child(dev, resource_query_name(i),
|
||||
resource_query_unit(i));
|
||||
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
|
||||
|
|
@ -844,7 +894,7 @@ fdc_print_child(device_t me, device_t child)
|
|||
|
||||
retval += bus_print_child_header(me, child);
|
||||
retval += printf(" on %s drive %d\n", device_get_nameunit(me),
|
||||
*(int *)device_get_ivars(child));
|
||||
fdc_get_fdunit(child));
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
|
@ -860,6 +910,7 @@ static device_method_t fdc_methods[] = {
|
|||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, fdc_print_child),
|
||||
DEVMETHOD(bus_read_ivar, fdc_read_ivar),
|
||||
/* Our children never use any other bus interface methods. */
|
||||
|
||||
{ 0, 0 }
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ struct fdc_data
|
|||
bus_space_handle_t ctlh;
|
||||
void *fdc_intr;
|
||||
struct device *fdc_dev;
|
||||
int fdc_ispnp;
|
||||
};
|
||||
|
||||
/***********************************************************************\
|
||||
|
|
@ -98,3 +99,22 @@ typedef enum fdc_type fdc_t;
|
|||
|
||||
#define FDUNIT(s) (((s)>>6)&03)
|
||||
#define FDTYPE(s) ((s)&077)
|
||||
|
||||
/*
|
||||
* fdc maintains a set (1!) of ivars per child of each controller.
|
||||
*/
|
||||
enum fdc_device_ivars {
|
||||
FDC_IVAR_FDUNIT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Simple access macros for the ivars.
|
||||
*/
|
||||
#define FDC_ACCESSOR(A, B, T) \
|
||||
static __inline T fdc_get_ ## A(device_t dev) \
|
||||
{ \
|
||||
uintptr_t v; \
|
||||
BUS_READ_IVAR(device_get_parent(dev), dev, FDC_IVAR_ ## B, &v); \
|
||||
return (T) v; \
|
||||
}
|
||||
FDC_ACCESSOR(fdunit, FDUNIT, int)
|
||||
|
|
|
|||
Loading…
Reference in a new issue