Use channel driver's attach/detach routines instead of ata_attach()/
ata_detach() to implement IOCATAATTACH/IOCATADETACH ioctls. This will permit channel drivers to properly shutdown port hardware on channel detach and init it on attach.
This commit is contained in:
parent
facbd7451d
commit
6127a7d95a
@ -385,30 +385,32 @@ ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
|
||||
|
||||
case IOCATAREINIT:
|
||||
if (*value >= devclass_get_maxunit(ata_devclass) ||
|
||||
!(device = devclass_get_device(ata_devclass, *value)))
|
||||
!(device = devclass_get_device(ata_devclass, *value)) ||
|
||||
!device_is_attached(device))
|
||||
return ENXIO;
|
||||
error = ata_reinit(device);
|
||||
break;
|
||||
|
||||
case IOCATAATTACH:
|
||||
if (*value >= devclass_get_maxunit(ata_devclass) ||
|
||||
!(device = devclass_get_device(ata_devclass, *value)))
|
||||
!(device = devclass_get_device(ata_devclass, *value)) ||
|
||||
!device_is_attached(device))
|
||||
return ENXIO;
|
||||
/* XXX SOS should enable channel HW on controller */
|
||||
error = ata_attach(device);
|
||||
error = DEVICE_ATTACH(device);
|
||||
break;
|
||||
|
||||
case IOCATADETACH:
|
||||
if (*value >= devclass_get_maxunit(ata_devclass) ||
|
||||
!(device = devclass_get_device(ata_devclass, *value)))
|
||||
!(device = devclass_get_device(ata_devclass, *value)) ||
|
||||
!device_is_attached(device))
|
||||
return ENXIO;
|
||||
error = ata_detach(device);
|
||||
/* XXX SOS should disable channel HW on controller */
|
||||
error = DEVICE_DETACH(device);
|
||||
break;
|
||||
|
||||
case IOCATADEVICES:
|
||||
if (devices->channel >= devclass_get_maxunit(ata_devclass) ||
|
||||
!(device = devclass_get_device(ata_devclass, devices->channel)))
|
||||
!(device = devclass_get_device(ata_devclass, devices->channel)) ||
|
||||
!device_is_attached(device))
|
||||
return ENXIO;
|
||||
bzero(devices->name[0], 32);
|
||||
bzero(&devices->params[0], sizeof(struct ata_params));
|
||||
|
@ -500,6 +500,7 @@ struct ata_resource {
|
||||
struct ata_channel {
|
||||
device_t dev; /* device handle */
|
||||
int unit; /* physical channel */
|
||||
int attached; /* channel is attached */
|
||||
struct ata_resource r_io[ATA_MAX_RES];/* I/O resources */
|
||||
struct resource *r_irq; /* interrupt of this channel */
|
||||
void *ih; /* interrupt handle */
|
||||
|
@ -91,6 +91,10 @@ ata_pccard_attach(device_t dev)
|
||||
struct resource *io, *ctlio;
|
||||
int i, rid, err;
|
||||
|
||||
if (ch->attached)
|
||||
return (0);
|
||||
ch->attached = 1;
|
||||
|
||||
/* allocate the io range to get start and length */
|
||||
rid = ATA_IOADDR_RID;
|
||||
if (!(io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
|
||||
@ -142,6 +146,10 @@ ata_pccard_detach(device_t dev)
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
int i;
|
||||
|
||||
if (!ch->attached)
|
||||
return (0);
|
||||
ch->attached = 0;
|
||||
|
||||
ata_detach(dev);
|
||||
if (ch->r_io[ATA_CONTROL].res != ch->r_io[ATA_DATA].res)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID,
|
||||
|
@ -279,6 +279,10 @@ ata_cbuschannel_attach(device_t dev)
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
int i;
|
||||
|
||||
if (ch->attached)
|
||||
return (0);
|
||||
ch->attached = 1;
|
||||
|
||||
ch->unit = (intptr_t)device_get_ivars(dev);
|
||||
/* setup the resource vectors */
|
||||
for (i = ATA_DATA; i <= ATA_COMMAND; i ++) {
|
||||
@ -297,6 +301,17 @@ ata_cbuschannel_attach(device_t dev)
|
||||
return ata_attach(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
ata_cbuschannel_detach(device_t dev)
|
||||
{
|
||||
|
||||
if (!ch->attached)
|
||||
return (0);
|
||||
ch->attached = 0;
|
||||
|
||||
return ata_detach(dev);
|
||||
}
|
||||
|
||||
static int
|
||||
ata_cbuschannel_banking(device_t dev, int flags)
|
||||
{
|
||||
@ -343,7 +358,7 @@ static device_method_t ata_cbuschannel_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, ata_cbuschannel_probe),
|
||||
DEVMETHOD(device_attach, ata_cbuschannel_attach),
|
||||
DEVMETHOD(device_detach, ata_detach),
|
||||
DEVMETHOD(device_detach, ata_cbuschannel_detach),
|
||||
DEVMETHOD(device_suspend, ata_suspend),
|
||||
DEVMETHOD(device_resume, ata_resume),
|
||||
|
||||
|
@ -103,6 +103,10 @@ ata_isa_attach(device_t dev)
|
||||
u_long tmp;
|
||||
int i, rid;
|
||||
|
||||
if (ch->attached)
|
||||
return (0);
|
||||
ch->attached = 1;
|
||||
|
||||
/* allocate the io port range */
|
||||
rid = ATA_IOADDR_RID;
|
||||
if (!(io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
|
||||
@ -146,6 +150,10 @@ ata_isa_detach(device_t dev)
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
if (!ch->attached)
|
||||
return (0);
|
||||
ch->attached = 0;
|
||||
|
||||
error = ata_detach(dev);
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID,
|
||||
|
@ -550,8 +550,9 @@ ata_pcichannel_attach(device_t dev)
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
/* take care of green memory */
|
||||
bzero(ch, sizeof(struct ata_channel));
|
||||
if (ch->attached)
|
||||
return (0);
|
||||
ch->attached = 1;
|
||||
|
||||
ch->unit = (intptr_t)device_get_ivars(dev);
|
||||
|
||||
@ -565,8 +566,13 @@ static int
|
||||
ata_pcichannel_detach(device_t dev)
|
||||
{
|
||||
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
if (!ch->attached)
|
||||
return (0);
|
||||
ch->attached = 0;
|
||||
|
||||
if ((error = ata_detach(dev)))
|
||||
return error;
|
||||
|
||||
|
@ -842,8 +842,9 @@ ata_usbchannel_attach(device_t dev)
|
||||
{
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
|
||||
/* take care of green memory */
|
||||
bzero(ch, sizeof(struct ata_channel));
|
||||
if (ch->attached)
|
||||
return (0);
|
||||
ch->attached = 1;
|
||||
|
||||
/* initialize the softc basics */
|
||||
ch->dev = dev;
|
||||
@ -876,6 +877,10 @@ ata_usbchannel_detach(device_t dev)
|
||||
device_t *children;
|
||||
int nchildren, i;
|
||||
|
||||
if (!ch->attached)
|
||||
return (0);
|
||||
ch->attached = 0;
|
||||
|
||||
/* detach & delete all children */
|
||||
if (!device_get_children(dev, &children, &nchildren)) {
|
||||
for (i = 0; i < nchildren; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user