aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2009-02-19 12:47:24 +0000
committerAlexander Motin <mav@FreeBSD.org>2009-02-19 12:47:24 +0000
commitb50bb79c6a7ec1d6a10db60ccf107ff3f9825f48 (patch)
treeebbbf416f6cb65d574f788efa836329c852e5273
parent7077d84d7bcb5dd79d4d06b2e766ba9a00c214e5 (diff)
downloadsrc-b50bb79c6a7ec1d6a10db60ccf107ff3f9825f48.tar.gz
src-b50bb79c6a7ec1d6a10db60ccf107ff3f9825f48.zip
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.
Notes
Notes: svn path=/head/; revision=188812
-rw-r--r--sys/dev/ata/ata-all.c18
-rw-r--r--sys/dev/ata/ata-all.h1
-rw-r--r--sys/dev/ata/ata-card.c8
-rw-r--r--sys/dev/ata/ata-cbus.c17
-rw-r--r--sys/dev/ata/ata-isa.c8
-rw-r--r--sys/dev/ata/ata-pci.c10
-rw-r--r--sys/dev/ata/ata-usb.c9
7 files changed, 58 insertions, 13 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 0bda3217c839..bf33d1bbeebb 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -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));
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 4b7fe82941ac..998442e1ab2b 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -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 */
diff --git a/sys/dev/ata/ata-card.c b/sys/dev/ata/ata-card.c
index 9a66419e3029..09a2c9f71a32 100644
--- a/sys/dev/ata/ata-card.c
+++ b/sys/dev/ata/ata-card.c
@@ -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,
diff --git a/sys/dev/ata/ata-cbus.c b/sys/dev/ata/ata-cbus.c
index e0a15efb20dc..1a39d2949dea 100644
--- a/sys/dev/ata/ata-cbus.c
+++ b/sys/dev/ata/ata-cbus.c
@@ -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 ++) {
@@ -298,6 +302,17 @@ ata_cbuschannel_attach(device_t 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)
{
struct ata_cbus_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -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),
diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c
index bad2c4ec7a75..6b1af81c5f12 100644
--- a/sys/dev/ata/ata-isa.c
+++ b/sys/dev/ata/ata-isa.c
@@ -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,
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index ebba0946802a..c2f295309a6c 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -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;
diff --git a/sys/dev/ata/ata-usb.c b/sys/dev/ata/ata-usb.c
index f4d7fa03cddb..5c868b23fdc4 100644
--- a/sys/dev/ata/ata-usb.c
+++ b/sys/dev/ata/ata-usb.c
@@ -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++)