summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-all.c326
-rw-r--r--sys/dev/ata/ata-all.h22
-rw-r--r--sys/dev/ata/ata-disk.c37
-rw-r--r--sys/dev/ata/ata-disk.h1
-rw-r--r--sys/dev/ata/atapi-all.c23
-rw-r--r--sys/dev/ata/atapi-all.h2
-rw-r--r--sys/dev/ata/atapi-cd.c51
-rw-r--r--sys/dev/ata/atapi-cd.h4
-rw-r--r--sys/dev/ata/atapi-fd.c56
-rw-r--r--sys/dev/ata/atapi-fd.h2
-rw-r--r--sys/dev/ata/atapi-tape.c21
-rw-r--r--sys/dev/ata/atapi-tape.h2
12 files changed, 349 insertions, 198 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 2206ef8..bbd1b6e 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -69,21 +69,25 @@ static struct intr_config_hook *ata_delayed_attach = NULL;
static char ata_conf[256];
static MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
+/* misc defines */
+#define MASTER 0
+#define SLAVE 1
+
int
ata_probe(device_t dev)
{
- struct ata_softc *scp = device_get_softc(dev);
+ struct ata_softc *scp;
int rid;
- int mask = 0;
- u_int8_t status0, status1;
- if (!scp || scp->flags & ATA_ATTACHED)
+ if (!dev)
+ return ENXIO;
+ scp = device_get_softc(dev);
+ if (!scp || scp->devices)
return ENXIO;
/* initialize the softc basics */
scp->active = ATA_IDLE;
scp->dev = dev;
- scp->devices = 0;
rid = ATA_IOADDR_RID;
scp->r_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
@@ -107,28 +111,7 @@ ata_probe(device_t dev)
(int)rman_get_start(scp->r_altio),
(scp->r_bmio) ? (int)rman_get_start(scp->r_bmio) : 0);
- /* do we have any signs of ATA/ATAPI HW being present ? */
- ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
- DELAY(1);
- status0 = ATA_INB(scp->r_io, ATA_STATUS);
- if ((status0 & 0xf8) != 0xf8 && status0 != 0xa5)
- mask |= 0x01;
- ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
- DELAY(1);
- status1 = ATA_INB(scp->r_io, ATA_STATUS);
- if ((status1 & 0xf8) != 0xf8 && status1 != 0xa5)
- mask |= 0x02;
-
- if (bootverbose)
- ata_printf(scp, -1, "mask=%02x status0=%02x status1=%02x\n",
- mask, status0, status1);
- if (!mask)
- goto failure;
-
- ata_reset(scp, &mask);
-
- if (!mask)
- goto failure;
+ ata_reset(scp);
TAILQ_INIT(&scp->ata_queue);
TAILQ_INIT(&scp->atapi_queue);
@@ -149,10 +132,13 @@ failure:
int
ata_attach(device_t dev)
{
- struct ata_softc *scp = device_get_softc(dev);
+ struct ata_softc *scp;
int error, rid;
- if (!scp || scp->flags & ATA_ATTACHED)
+ if (!dev)
+ return ENXIO;
+ scp = device_get_softc(dev);
+ if (!scp)
return ENXIO;
rid = ATA_IRQ_RID;
@@ -197,19 +183,26 @@ ata_attach(device_t dev)
atapi_attach(scp, ATA_SLAVE);
#endif
}
- scp->flags |= ATA_ATTACHED;
return 0;
}
int
ata_detach(device_t dev)
{
- struct ata_softc *scp = device_get_softc(dev);
+ struct ata_softc *scp;
+ int s;
- if (!scp || !(scp->flags & ATA_ATTACHED))
+ if (!dev)
+ return ENXIO;
+ scp = device_get_softc(dev);
+ if (!scp || !scp->devices)
return ENXIO;
- /* make sure device is not busy SOS XXX */
+ /* make sure channel is not busy SOS XXX */
+ s = splbio();
+ while (!atomic_cmpset_int(&scp->active, ATA_IDLE, ATA_ACTIVE))
+ tsleep((caddr_t)&s, PRIBIO, "atachm", hz/4);
+ splx(s);
/* disable interrupts on devices */
ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
@@ -218,30 +211,31 @@ ata_detach(device_t dev)
ATA_OUTB(scp->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_4BIT);
#ifdef DEV_ATADISK
- if (scp->devices & ATA_ATA_MASTER)
- ad_detach(scp->dev_softc[0]);
- if (scp->devices & ATA_ATA_SLAVE)
- ad_detach(scp->dev_softc[1]);
+ if (scp->devices & ATA_ATA_MASTER && scp->dev_softc[MASTER])
+ ad_detach(scp->dev_softc[MASTER]);
+ if (scp->devices & ATA_ATA_SLAVE && scp->dev_softc[SLAVE])
+ ad_detach(scp->dev_softc[SLAVE]);
#endif
#if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST)
- if (scp->devices & ATA_ATAPI_MASTER)
- atapi_detach(scp->dev_softc[0]);
- if (scp->devices & ATA_ATAPI_SLAVE)
- atapi_detach(scp->dev_softc[1]);
+ if (scp->devices & ATA_ATAPI_MASTER && scp->dev_softc[MASTER])
+ atapi_detach(scp->dev_softc[MASTER]);
+ if (scp->devices & ATA_ATAPI_SLAVE && scp->dev_softc[SLAVE])
+ atapi_detach(scp->dev_softc[SLAVE]);
#endif
- if (scp->dev_param[ATA_DEV(ATA_MASTER)]) {
- free(scp->dev_param[ATA_DEV(ATA_MASTER)], M_ATA);
- scp->dev_param[ATA_DEV(ATA_MASTER)] = NULL;
+ if (scp->dev_param[MASTER]) {
+ free(scp->dev_param[MASTER], M_ATA);
+ scp->dev_param[MASTER] = NULL;
}
- if (scp->dev_param[ATA_DEV(ATA_SLAVE)]) {
- free(scp->dev_param[ATA_DEV(ATA_SLAVE)], M_ATA);
- scp->dev_param[ATA_DEV(ATA_SLAVE)] = NULL;
+ if (scp->dev_param[SLAVE]) {
+ free(scp->dev_param[SLAVE], M_ATA);
+ scp->dev_param[SLAVE] = NULL;
}
- scp->dev_softc[ATA_DEV(ATA_MASTER)] = NULL;
- scp->dev_softc[ATA_DEV(ATA_SLAVE)] = NULL;
- scp->mode[ATA_DEV(ATA_MASTER)] = ATA_PIO;
- scp->mode[ATA_DEV(ATA_SLAVE)] = ATA_PIO;
+ scp->dev_softc[MASTER] = NULL;
+ scp->dev_softc[SLAVE] = NULL;
+ scp->mode[MASTER] = ATA_PIO;
+ scp->mode[SLAVE] = ATA_PIO;
+ scp->devices = 0;
bus_teardown_intr(dev, scp->r_irq, scp->ih);
bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, scp->r_irq);
@@ -249,7 +243,7 @@ ata_detach(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, ATA_BMADDR_RID, scp->r_bmio);
bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, scp->r_altio);
bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, scp->r_io);
- scp->flags &= ~ATA_ATTACHED;
+ scp->active = ATA_IDLE;
return 0;
}
@@ -336,7 +330,7 @@ ata_boot_attach(void)
if (ata_getparam(scp, ATA_MASTER, ATA_C_ATA_IDENTIFY))
scp->devices &= ~ATA_ATA_MASTER;
if (scp->devices & ATA_ATAPI_MASTER)
- if (ata_getparam(scp, ATA_MASTER,ATA_C_ATAPI_IDENTIFY))
+ if (ata_getparam(scp, ATA_MASTER, ATA_C_ATAPI_IDENTIFY))
scp->devices &= ~ATA_ATAPI_MASTER;
}
@@ -407,15 +401,14 @@ ata_intr(void *data)
break;
#endif
case ATA_WAIT_INTR:
+ case ATA_WAIT_INTR | ATA_REINITING:
wakeup((caddr_t)scp);
break;
case ATA_WAIT_READY:
+ case ATA_WAIT_READY | ATA_REINITING:
break;
- case ATA_REINITING:
- return;
-
case ATA_IDLE:
if (scp->flags & ATA_QUEUED) {
scp->active = ATA_ACTIVE; /* XXX */
@@ -435,7 +428,9 @@ ata_intr(void *data)
}
#endif
}
- scp->active = ATA_IDLE;
+ scp->active &= ATA_REINITING;
+ if (scp->active & ATA_REINITING)
+ return;
scp->running = NULL;
ata_start(scp);
return;
@@ -457,10 +452,10 @@ ata_start(struct ata_softc *scp)
#ifdef DEV_ATADISK
/* find & call the responsible driver if anything on the ATA queue */
if (TAILQ_EMPTY(&scp->ata_queue)) {
- if (scp->devices & (ATA_ATA_MASTER) && scp->dev_softc[0])
- ad_start((struct ad_softc *)scp->dev_softc[0]);
- if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[1])
- ad_start((struct ad_softc *)scp->dev_softc[1]);
+ if (scp->devices & (ATA_ATA_MASTER) && scp->dev_softc[MASTER])
+ ad_start((struct ad_softc *)scp->dev_softc[MASTER]);
+ if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[SLAVE])
+ ad_start((struct ad_softc *)scp->dev_softc[SLAVE]);
}
if ((ad_request = TAILQ_FIRST(&scp->ata_queue))) {
TAILQ_REMOVE(&scp->ata_queue, ad_request, chain);
@@ -474,10 +469,10 @@ ata_start(struct ata_softc *scp)
#if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST)
/* find & call the responsible driver if anything on the ATAPI queue */
if (TAILQ_EMPTY(&scp->atapi_queue)) {
- if (scp->devices & (ATA_ATAPI_MASTER) && scp->dev_softc[0])
- atapi_start((struct atapi_softc *)scp->dev_softc[0]);
- if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[1])
- atapi_start((struct atapi_softc *)scp->dev_softc[1]);
+ if (scp->devices & (ATA_ATAPI_MASTER) && scp->dev_softc[MASTER])
+ atapi_start((struct atapi_softc *)scp->dev_softc[MASTER]);
+ if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[SLAVE])
+ atapi_start((struct atapi_softc *)scp->dev_softc[SLAVE]);
}
if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) {
TAILQ_REMOVE(&scp->atapi_queue, atapi_request, chain);
@@ -491,27 +486,35 @@ ata_start(struct ata_softc *scp)
}
void
-ata_reset(struct ata_softc *scp, int *mask)
+ata_reset(struct ata_softc *scp)
{
- int timeout;
- u_int8_t a, b, ostat0, ostat1;
- u_int8_t status0 = ATA_S_BUSY, status1 = ATA_S_BUSY;
+ u_int8_t lsb, msb, ostat0, ostat1;
+ u_int8_t stat0 = ATA_S_BUSY, stat1 = ATA_S_BUSY;
+ int mask = 0, timeout;
- /* get the current status of the devices */
- ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
- DELAY(10);
- ostat1 = ATA_INB(scp->r_io, ATA_STATUS);
+ /* do we have any signs of ATA/ATAPI HW being present ? */
ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
- DELAY(10);
+ DELAY(1);
ostat0 = ATA_INB(scp->r_io, ATA_STATUS);
+ if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5)
+ mask |= 0x01;
+ ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
+ DELAY(1);
+ ostat1 = ATA_INB(scp->r_io, ATA_STATUS);
+ if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5)
+ mask |= 0x02;
+
+ scp->devices = 0;
+ if (!mask)
+ return;
/* in some setups we dont want to test for a slave */
if (scp->flags & ATA_NO_SLAVE)
- *mask &= ~0x02;
+ mask &= ~0x02;
if (bootverbose)
ata_printf(scp, -1, "mask=%02x ostat0=%02x ostat2=%02x\n",
- *mask, ostat0, ostat1);
+ mask, ostat0, ostat1);
/* reset channel */
ATA_OUTB(scp->r_altio, ATA_ALTSTAT, ATA_A_IDS | ATA_A_RESET);
@@ -519,86 +522,85 @@ ata_reset(struct ata_softc *scp, int *mask)
ATA_OUTB(scp->r_altio, ATA_ALTSTAT, ATA_A_IDS);
DELAY(100000);
ATA_INB(scp->r_io, ATA_ERROR);
- scp->devices = 0;
/* wait for BUSY to go inactive */
for (timeout = 0; timeout < 310000; timeout++) {
- if (status0 & ATA_S_BUSY) {
+ if (stat0 & ATA_S_BUSY) {
ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(10);
- status0 = ATA_INB(scp->r_io, ATA_STATUS);
- if (!(status0 & ATA_S_BUSY)) {
+ stat0 = ATA_INB(scp->r_io, ATA_STATUS);
+ if (!(stat0 & ATA_S_BUSY)) {
/* check for ATAPI signature while its still there */
- a = ATA_INB(scp->r_io, ATA_CYL_LSB);
- b = ATA_INB(scp->r_io, ATA_CYL_MSB);
+ lsb = ATA_INB(scp->r_io, ATA_CYL_LSB);
+ msb = ATA_INB(scp->r_io, ATA_CYL_MSB);
if (bootverbose)
ata_printf(scp, ATA_MASTER,
- "ATAPI probe a=%02x b=%02x\n", a, b);
- if (a == ATAPI_MAGIC_LSB && b == ATAPI_MAGIC_MSB)
+ "ATAPI probe %02x %02x\n", lsb, msb);
+ if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB)
scp->devices |= ATA_ATAPI_MASTER;
}
}
- if (status1 & ATA_S_BUSY) {
+ if (stat1 & ATA_S_BUSY) {
ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(10);
- status1 = ATA_INB(scp->r_io, ATA_STATUS);
- if (!(status1 & ATA_S_BUSY)) {
+ stat1 = ATA_INB(scp->r_io, ATA_STATUS);
+ if (!(stat1 & ATA_S_BUSY)) {
/* check for ATAPI signature while its still there */
- a = ATA_INB(scp->r_io, ATA_CYL_LSB);
- b = ATA_INB(scp->r_io, ATA_CYL_MSB);
+ lsb = ATA_INB(scp->r_io, ATA_CYL_LSB);
+ msb = ATA_INB(scp->r_io, ATA_CYL_MSB);
if (bootverbose)
ata_printf(scp, ATA_SLAVE,
- "ATAPI probe a=%02x b=%02x\n", a, b);
- if (a == ATAPI_MAGIC_LSB && b == ATAPI_MAGIC_MSB)
+ "ATAPI probe %02x %02x\n", lsb, msb);
+ if (lsb == ATAPI_MAGIC_LSB && msb == ATAPI_MAGIC_MSB)
scp->devices |= ATA_ATAPI_SLAVE;
}
}
- if (*mask == 0x01) /* wait for master only */
- if (!(status0 & ATA_S_BUSY))
+ if (mask == 0x01) /* wait for master only */
+ if (!(stat0 & ATA_S_BUSY))
break;
- if (*mask == 0x02) /* wait for slave only */
- if (!(status1 & ATA_S_BUSY))
+ if (mask == 0x02) /* wait for slave only */
+ if (!(stat1 & ATA_S_BUSY))
break;
- if (*mask == 0x03) /* wait for both master & slave */
- if (!(status0 & ATA_S_BUSY) && !(status1 & ATA_S_BUSY))
+ if (mask == 0x03) /* wait for both master & slave */
+ if (!(stat0 & ATA_S_BUSY) && !(stat1 & ATA_S_BUSY))
break;
DELAY(100);
}
DELAY(10);
ATA_OUTB(scp->r_altio, ATA_ALTSTAT, ATA_A_4BIT);
- if (status0 & ATA_S_BUSY)
- *mask &= ~0x01;
- if (status1 & ATA_S_BUSY)
- *mask &= ~0x02;
+ if (stat0 & ATA_S_BUSY)
+ mask &= ~0x01;
+ if (stat1 & ATA_S_BUSY)
+ mask &= ~0x02;
if (bootverbose)
- ata_printf(scp, -1, "mask=%02x status0=%02x status1=%02x\n",
- *mask, status0, status1);
- if (!*mask)
+ ata_printf(scp, -1, "mask=%02x stat0=%02x stat1=%02x\n",
+ mask, stat0, stat1);
+ if (!mask)
return;
- if (*mask & 0x01 && ostat0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) {
+ if (mask & 0x01 && ostat0 != 0x00 && !(scp->devices & ATA_ATAPI_MASTER)) {
ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(10);
ATA_OUTB(scp->r_io, ATA_ERROR, 0x58);
ATA_OUTB(scp->r_io, ATA_CYL_LSB, 0xa5);
- a = ATA_INB(scp->r_io, ATA_ERROR);
- b = ATA_INB(scp->r_io, ATA_CYL_LSB);
+ lsb = ATA_INB(scp->r_io, ATA_ERROR);
+ msb = ATA_INB(scp->r_io, ATA_CYL_LSB);
if (bootverbose)
- ata_printf(scp, ATA_MASTER, "ATA probe a=%02x b=%02x\n", a, b);
- if (a != 0x58 && b == 0xa5)
+ ata_printf(scp, ATA_MASTER, "ATA probe %02x %02x\n", lsb, msb);
+ if (lsb != 0x58 && msb == 0xa5)
scp->devices |= ATA_ATA_MASTER;
}
- if (*mask & 0x02 && ostat1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) {
+ if (mask & 0x02 && ostat1 != 0x00 && !(scp->devices & ATA_ATAPI_SLAVE)) {
ATA_OUTB(scp->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
DELAY(10);
ATA_OUTB(scp->r_io, ATA_ERROR, 0x58);
ATA_OUTB(scp->r_io, ATA_CYL_LSB, 0xa5);
- a = ATA_INB(scp->r_io, ATA_ERROR);
- b = ATA_INB(scp->r_io, ATA_CYL_LSB);
+ lsb = ATA_INB(scp->r_io, ATA_ERROR);
+ msb = ATA_INB(scp->r_io, ATA_CYL_LSB);
if (bootverbose)
- ata_printf(scp, ATA_SLAVE, "ATA probe a=%02x b=%02x\n", a, b);
- if (a != 0x58 && b == 0xa5)
+ ata_printf(scp, ATA_SLAVE, "ATA probe %02x %02x\n", lsb, msb);
+ if (lsb != 0x58 && msb == 0xa5)
scp->devices |= ATA_ATA_SLAVE;
}
if (bootverbose)
@@ -608,36 +610,74 @@ ata_reset(struct ata_softc *scp, int *mask)
int
ata_reinit(struct ata_softc *scp)
{
- int mask = 0, odevices;
+ int devices, misdev, newdev;
scp->active = ATA_REINITING;
scp->running = NULL;
- if (scp->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER))
- mask |= 0x01;
- if (scp->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE))
- mask |= 0x02;
- if (mask) {
- odevices = scp->devices;
- ata_printf(scp, -1, "resetting devices .. ");
- ata_reset(scp, &mask);
- if (odevices != scp->devices)
- printf(" device dissapeared! 0x%02x ", odevices & ~scp->devices);
+ devices = scp->devices;
+ ata_printf(scp, -1, "resetting devices .. ");
+ ata_reset(scp);
+ if ((misdev = devices & ~scp->devices)) {
+ printf("\ndevice(s) disappeared! 0x%02x\n", misdev);
#ifdef DEV_ATADISK
- if (scp->devices & (ATA_ATA_MASTER) && scp->dev_softc[0])
- ad_reinit((struct ad_softc *)scp->dev_softc[0]);
- if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[1])
- ad_reinit((struct ad_softc *)scp->dev_softc[1]);
+ if (misdev & ATA_ATA_MASTER && scp->dev_softc[MASTER])
+ ad_detach(scp->dev_softc[MASTER]);
+ if (misdev & ATA_ATA_SLAVE && scp->dev_softc[SLAVE])
+ ad_detach(scp->dev_softc[SLAVE]);
#endif
#if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST)
- if (scp->devices & (ATA_ATAPI_MASTER) && scp->dev_softc[0])
- atapi_reinit((struct atapi_softc *)scp->dev_softc[0]);
- if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[1])
- atapi_reinit((struct atapi_softc *)scp->dev_softc[1]);
+ if (misdev & ATA_ATAPI_MASTER && scp->dev_softc[MASTER])
+ atapi_detach(scp->dev_softc[MASTER]);
+ if (misdev & ATA_ATAPI_SLAVE && scp->dev_softc[SLAVE])
+ atapi_detach(scp->dev_softc[SLAVE]);
#endif
- printf("done\n");
+ if (misdev & ATA_ATA_MASTER || misdev & ATA_ATAPI_MASTER) {
+ free(scp->dev_param[MASTER], M_ATA);
+ scp->dev_param[MASTER] = NULL;
+ }
+ if (misdev & ATA_ATA_SLAVE || misdev & ATA_ATAPI_SLAVE) {
+ free(scp->dev_param[SLAVE], M_ATA);
+ scp->dev_param[SLAVE] = NULL;
+ }
+ }
+ if ((newdev = ~devices & scp->devices)) {
+ printf("\ndevice(s) appeared! 0x%02x\n", newdev);
+ if (newdev & ATA_ATA_MASTER)
+ if (ata_getparam(scp, ATA_MASTER, ATA_C_ATA_IDENTIFY))
+ newdev &= ~ATA_ATA_MASTER;
+ if (newdev & ATA_ATA_SLAVE)
+ if (ata_getparam(scp, ATA_SLAVE, ATA_C_ATA_IDENTIFY))
+ newdev &= ~ATA_ATA_SLAVE;
+ if (newdev & ATA_ATAPI_MASTER)
+ if (ata_getparam(scp, ATA_MASTER, ATA_C_ATAPI_IDENTIFY))
+ newdev &= ~ATA_ATAPI_MASTER;
+ if (newdev & ATA_ATAPI_SLAVE)
+ if (ata_getparam(scp, ATA_SLAVE, ATA_C_ATAPI_IDENTIFY))
+ newdev &= ~ATA_ATAPI_SLAVE;
}
scp->active = ATA_IDLE;
+#ifdef DEV_ATADISK
+ if (newdev & ATA_ATA_MASTER && !scp->dev_softc[MASTER])
+ ad_attach(scp, ATA_MASTER);
+ else if (scp->devices & ATA_ATA_MASTER && scp->dev_softc[MASTER])
+ ad_reinit((struct ad_softc *)scp->dev_softc[MASTER]);
+ if (newdev & ATA_ATA_SLAVE && !scp->dev_softc[SLAVE])
+ ad_attach(scp, ATA_SLAVE);
+ else if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[SLAVE])
+ ad_reinit((struct ad_softc *)scp->dev_softc[SLAVE]);
+#endif
+#if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST)
+ if (newdev & ATA_ATAPI_MASTER && !scp->dev_softc[MASTER])
+ atapi_attach(scp, ATA_MASTER);
+ else if (scp->devices & (ATA_ATAPI_MASTER) && scp->dev_softc[MASTER])
+ atapi_reinit((struct atapi_softc *)scp->dev_softc[MASTER]);
+ if (newdev & ATA_ATAPI_SLAVE && !scp->dev_softc[SLAVE])
+ atapi_attach(scp, ATA_SLAVE);
+ else if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[SLAVE])
+ atapi_reinit((struct atapi_softc *)scp->dev_softc[SLAVE]);
+#endif
+ printf("done\n");
ata_start(scp);
return 0;
}
@@ -651,12 +691,12 @@ ata_service(struct ata_softc *scp)
ata_dmastatus(scp) | ATA_BMSTAT_INTERRUPT);
#ifdef DEV_ATADISK
if ((ATA_INB(scp->r_io, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) {
- if ((scp->devices & ATA_ATA_MASTER) && scp->dev_softc[0])
- return ad_service((struct ad_softc *)scp->dev_softc[0], 0);
+ if ((scp->devices & ATA_ATA_MASTER) && scp->dev_softc[MASTER])
+ return ad_service((struct ad_softc *)scp->dev_softc[MASTER], 0);
}
else {
- if ((scp->devices & ATA_ATA_SLAVE) && scp->dev_softc[1])
- return ad_service((struct ad_softc *)scp->dev_softc[1], 0);
+ if ((scp->devices & ATA_ATA_SLAVE) && scp->dev_softc[SLAVE])
+ return ad_service((struct ad_softc *)scp->dev_softc[SLAVE], 0);
}
#endif
}
@@ -751,7 +791,7 @@ ata_command(struct ata_softc *scp, int device, u_int8_t command,
switch (flags) {
case ATA_WAIT_INTR:
- scp->active = ATA_WAIT_INTR;
+ scp->active |= ATA_WAIT_INTR;
asleep((caddr_t)scp, PRIBIO, "atacmd", 10 * hz);
ATA_OUTB(scp->r_io, ATA_CMD, command);
@@ -761,14 +801,13 @@ ata_command(struct ata_softc *scp, int device, u_int8_t command,
if (await(PRIBIO, 10 * hz)) {
ata_printf(scp, device, "ata_command: timeout waiting for intr\n");
- scp->active = ATA_IDLE;
+ scp->active &= ~ATA_WAIT_INTR;
error = -1;
}
break;
case ATA_WAIT_READY:
- if (scp->active != ATA_REINITING)
- scp->active = ATA_WAIT_READY;
+ scp->active |= ATA_WAIT_READY;
ATA_OUTB(scp->r_io, ATA_CMD, command);
if (ata_wait(scp, device, ATA_S_READY) < 0) {
ata_printf(scp, device,
@@ -776,8 +815,7 @@ ata_command(struct ata_softc *scp, int device, u_int8_t command,
command, scp->status, scp->error);
error = -1;
}
- if (scp->active != ATA_REINITING)
- scp->active = ATA_IDLE;
+ scp->active &= ~ATA_WAIT_READY;
break;
case ATA_IMMEDIATE:
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index d90189d..b02fd3b 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -312,8 +312,7 @@ struct ata_softc {
#define ATA_ATAPI_DMA_RO 0x02
#define ATA_USE_16BIT 0x04
#define ATA_NO_SLAVE 0x08
-#define ATA_ATTACHED 0x10
-#define ATA_QUEUED 0x20
+#define ATA_QUEUED 0x10
int devices; /* what is present */
#define ATA_ATA_MASTER 0x01
@@ -324,14 +323,14 @@ struct ata_softc {
u_int8_t status; /* last controller status */
u_int8_t error; /* last controller error */
int active; /* active processing request */
-#define ATA_IDLE 0x0
-#define ATA_IMMEDIATE 0x1
-#define ATA_WAIT_INTR 0x2
-#define ATA_WAIT_READY 0x3
-#define ATA_ACTIVE 0x4
-#define ATA_ACTIVE_ATA 0x5
-#define ATA_ACTIVE_ATAPI 0x6
-#define ATA_REINITING 0x7
+#define ATA_IDLE 0x0000
+#define ATA_IMMEDIATE 0x0001
+#define ATA_WAIT_INTR 0x0002
+#define ATA_WAIT_READY 0x0004
+#define ATA_ACTIVE 0x0008
+#define ATA_ACTIVE_ATA 0x0010
+#define ATA_ACTIVE_ATAPI 0x0020
+#define ATA_REINITING 0x0040
TAILQ_HEAD(, ad_request) ata_queue; /* head of ATA queue */
TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */
@@ -348,7 +347,7 @@ int ata_detach(device_t);
int ata_resume(device_t);
void ata_start(struct ata_softc *);
-void ata_reset(struct ata_softc *, int *);
+void ata_reset(struct ata_softc *);
int ata_reinit(struct ata_softc *);
int ata_wait(struct ata_softc *, int, u_int8_t);
int ata_command(struct ata_softc *, int, u_int8_t, u_int16_t, u_int8_t, u_int8_t, u_int8_t, u_int8_t, int);
@@ -370,6 +369,7 @@ void ata_dmastart(struct ata_softc *, int, struct ata_dmaentry *, int);
int ata_dmastatus(struct ata_softc *);
int ata_dmadone(struct ata_softc *);
+/* macros to hide busspace uglyness */
#define ATA_INB(res, offset) \
bus_space_read_1(rman_get_bustag((res)), \
rman_get_bushandle((res)), (offset))
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index d834b95..359681b 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -96,12 +96,10 @@ ad_attach(struct ata_softc *scp, int device)
dev_t dev;
int secsperint;
-
if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
ata_printf(scp, device, "failed to allocate driver storage\n");
return;
}
- scp->dev_softc[ATA_DEV(device)] = adp;
adp->controller = scp;
adp->unit = device;
#ifdef ATA_STATIC_ID
@@ -169,7 +167,6 @@ ad_attach(struct ata_softc *scp, int device)
dev->si_drv1 = adp;
dev->si_iosize_max = 256 * DEV_BSIZE;
adp->dev = dev;
-
bioq_init(&adp->queue);
if (bootverbose) {
@@ -204,15 +201,40 @@ ad_attach(struct ata_softc *scp, int device)
(adp->unit == ATA_MASTER) ? "master" : "slave",
(adp->flags & AD_F_TAG_ENABLED) ? "tagged " : "",
ata_mode2str(adp->controller->mode[ATA_DEV(adp->unit)]));
+
+ /* store our softc signalling we are ready to go */
+ scp->dev_softc[ATA_DEV(device)] = adp;
}
void
ad_detach(struct ad_softc *adp)
{
+ struct ad_request *request;
+ struct bio *bp;
+
+ adp->flags |= AD_F_DETACHING;
+ TAILQ_FOREACH(request, &adp->controller->ata_queue, chain) {
+ if (request->device != adp)
+ continue;
+ TAILQ_REMOVE(&adp->controller->ata_queue, request, chain);
+ request->bp->bio_error = ENXIO;
+ request->bp->bio_flags |= BIO_ERROR;
+ biodone(request->bp);
+ ad_free(request);
+ }
+ while ((bp = bioq_first(&adp->queue))) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ }
disk_invalidate(&adp->disk);
disk_destroy(adp->dev);
devstat_remove_entry(&adp->stats);
+ if (ata_command(adp->controller, adp->unit, ATA_C_FLUSHCACHE,
+ 0, 0, 0, 0, 0, ATA_WAIT_INTR))
+ printf("ad%d: flushing cache on detach failed\n", adp->lun);
ata_free_lun(&adp_lun_map, adp->lun);
+ adp->controller->dev_softc[ATA_DEV(adp->unit)] = NULL;
free(adp, M_AD);
}
@@ -239,6 +261,13 @@ adstrategy(struct bio *bp)
struct ad_softc *adp = bp->bio_dev->si_drv1;
int s;
+ if (adp->flags & AD_F_DETACHING) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ return;
+ }
+
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
bp->bio_resid = 0;
@@ -876,7 +905,7 @@ ad_reinit(struct ad_softc *adp)
/* reinit disk parameters */
ad_invalidatequeue(adp, NULL);
ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI, 0, 0, 0,
- adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY);
+ adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_INTR);
if (adp->controller->mode[ATA_DEV(adp->unit)] >= ATA_DMA)
ata_dmainit(adp->controller, adp->unit, ata_pmode(AD_PARAM),
ata_wmode(AD_PARAM), ata_umode(AD_PARAM));
diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h
index 8a6d4f2..6d760cd 100644
--- a/sys/dev/ata/ata-disk.h
+++ b/sys/dev/ata/ata-disk.h
@@ -68,6 +68,7 @@ struct ad_softc {
#define AD_F_LBA_ENABLED 0x0002
#define AD_F_32B_ENABLED 0x0004
#define AD_F_TAG_ENABLED 0x0008
+#define AD_F_DETACHING 0x0010
struct ad_request *tags[32]; /* tag array of requests */
int outstanding; /* tags not serviced yet */
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index 5607569..4eec739 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -35,6 +35,7 @@
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/malloc.h>
+#include <sys/bio.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
@@ -114,13 +115,18 @@ notfound:
free(atp, M_ATAPI);
atp = NULL;
}
- /* store our softc */
+
+ /* store our softc signalling we are ready to go */
scp->dev_softc[ATA_DEV(device)] = atp;
}
void
atapi_detach(struct atapi_softc *atp)
{
+ struct atapi_request *request;
+
+ atp->flags |= ATAPI_F_DETACHING;
+
switch (ATP_PARAM->device_type) {
#ifdef DEV_ATAPICD
case ATAPI_TYPE_CDROM:
@@ -140,6 +146,21 @@ atapi_detach(struct atapi_softc *atp)
default:
return;
}
+ TAILQ_FOREACH(request, &atp->controller->atapi_queue, chain) {
+ if (request->device != atp)
+ continue;
+ TAILQ_REMOVE(&atp->controller->atapi_queue, request, chain);
+ if (request->driver) {
+ struct bio *bp = (struct bio *) request->driver;
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ }
+ if (request->dmatab)
+ free(request->dmatab, M_DEVBUF);
+ free(request, M_ATAPI);
+ }
+ atp->controller->dev_softc[ATA_DEV(atp->unit)] = NULL;
free(atp, M_ATAPI);
}
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index eae2342..e08589d 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -150,7 +150,7 @@ struct atapi_softc {
u_int8_t cmd; /* last cmd executed */
int flags; /* drive flags */
#define ATAPI_F_MEDIA_CHANGED 0x0001
-
+#define ATAPI_F_DETACHING 0x0002
};
typedef int atapi_callback_t(struct atapi_request *);
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 41c922f..7f7e6e5 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -98,6 +98,7 @@ static int acd_set_speed(struct acd_softc *cdp, int);
/* internal vars */
static u_int32_t acd_lun_map = 0;
+static eventhandler_tag acd_tag;
static MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
int
@@ -110,7 +111,7 @@ acdattach(struct atapi_softc *atp)
if (!acd_cdev_done) {
cdevsw_add(&acd_cdevsw);
- EVENTHANDLER_REGISTER(dev_clone, acd_clone, 0, 1000);
+ acd_tag = EVENTHANDLER_REGISTER(dev_clone, acd_clone, 0, 1000);
acd_cdev_done++;
}
@@ -213,13 +214,36 @@ void
acddetach(struct atapi_softc *atp)
{
struct acd_softc *cdp = atp->driver;
+ struct bio *bp;
+ int subdev;
- destroy_dev(cdp->dev1);
- destroy_dev(cdp->dev2);
if (cdp->changer_info) {
- /* should free all cdp's here, not possible yet SOS XXX */
+ for (subdev = 0; subdev < cdp->changer_info->slots; subdev++) {
+ if (cdp->driver[subdev] == cdp)
+ continue;
+ while ((bp = bioq_first(&cdp->driver[subdev]->queue))) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ }
+ destroy_dev(cdp->dev1);
+ destroy_dev(cdp->dev2);
+ devstat_remove_entry(cdp->stats);
+ free(cdp->stats, M_ACD);
+ free(cdp->atp->devname, M_ACD);
+ ata_free_lun(&acd_lun_map, cdp->lun);
+ free(cdp, M_ACD);
+ }
+ free(cdp->driver, M_ACD);
free(cdp->changer_info, M_ACD);
}
+ while ((bp = bioq_first(&cdp->queue))) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ }
+ destroy_dev(cdp->dev1);
+ destroy_dev(cdp->dev2);
devstat_remove_entry(cdp->stats);
free(cdp->stats, M_ACD);
free(cdp->atp->devname, M_ACD);
@@ -234,7 +258,7 @@ acd_init_lun(struct atapi_softc *atp, struct devstat *stats)
if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT | M_ZERO)))
return NULL;
- bioq_init(&cdp->bio_queue);
+ bioq_init(&cdp->queue);
cdp->atp = atp;
cdp->lun = ata_get_lun(&acd_lun_map);
cdp->block_size = 2048;
@@ -1097,6 +1121,13 @@ acdstrategy(struct bio *bp)
struct acd_softc *cdp = bp->bio_dev->si_drv1;
int s;
+ if (cdp->atp->flags & ATAPI_F_DETACHING) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ return;
+ }
+
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
bp->bio_resid = 0;
@@ -1108,7 +1139,7 @@ acdstrategy(struct bio *bp)
bp->bio_resid = bp->bio_bcount;
s = splbio();
- bioqdisksort(&cdp->bio_queue, bp);
+ bioqdisksort(&cdp->queue, bp);
ata_start(cdp->atp->controller);
splx(s);
}
@@ -1117,7 +1148,7 @@ void
acd_start(struct atapi_softc *atp)
{
struct acd_softc *cdp = atp->driver;
- struct bio *bp = bioq_first(&cdp->bio_queue);
+ struct bio *bp = bioq_first(&cdp->queue);
u_int32_t lba, lastlba, count;
int8_t ccb[16];
int track, blocksize;
@@ -1126,13 +1157,13 @@ acd_start(struct atapi_softc *atp)
int i;
cdp = cdp->driver[cdp->changer_info->current_slot];
- bp = bioq_first(&cdp->bio_queue);
+ bp = bioq_first(&cdp->queue);
/* check for work pending on any other slot */
for (i = 0; i < cdp->changer_info->slots; i++) {
if (i == cdp->changer_info->current_slot)
continue;
- if (bioq_first(&(cdp->driver[i]->bio_queue))) {
+ if (bioq_first(&(cdp->driver[i]->queue))) {
if (!bp || time_second > (cdp->timestamp + 10)) {
acd_select_slot(cdp->driver[i]);
return;
@@ -1142,7 +1173,7 @@ acd_start(struct atapi_softc *atp)
}
if (!bp)
return;
- bioq_remove(&cdp->bio_queue, bp);
+ bioq_remove(&cdp->queue, bp);
/* reject all queued entries if media changed */
if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED) {
diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h
index 3644806..2d8ccb3 100644
--- a/sys/dev/ata/atapi-cd.h
+++ b/sys/dev/ata/atapi-cd.h
@@ -167,6 +167,8 @@ struct cappage {
u_int8_t :3;
u_int16_t max_write_speed; /* max raw data rate in bytes/1000 */
u_int16_t cur_write_speed; /* current data rate in bytes/1000 */
+ u_int16_t copy_protect_rev;
+ u_int16_t reserved4;
};
/* CDROM Changer mechanism status structure */
@@ -298,7 +300,7 @@ struct acd_softc {
int flags; /* device state flags */
#define F_LOCKED 0x0001 /* this unit is locked */
- struct bio_queue_head bio_queue; /* Queue of i/o requests */
+ struct bio_queue_head queue; /* queue of i/o requests */
struct toc toc; /* table of disc contents */
struct {
u_int32_t volsize; /* volume size in blocks */
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 02d817d..d52ecd7 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -89,7 +89,7 @@ afdattach(struct atapi_softc *atp)
printf("afd: out of memory\n");
return -1;
}
- bioq_init(&fdp->bio_queue);
+ bioq_init(&fdp->queue);
fdp->atp = atp;
fdp->lun = ata_get_lun(&afd_lun_map);
@@ -122,7 +122,13 @@ void
afddetach(struct atapi_softc *atp)
{
struct afd_softc *fdp = atp->driver;
+ struct bio *bp;
+ while ((bp = bioq_first(&fdp->queue))) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ }
disk_invalidate(&fdp->disk);
disk_destroy(fdp->dev);
devstat_remove_entry(&fdp->stats);
@@ -181,25 +187,27 @@ afd_describe(struct afd_softc *fdp)
printf(" transfer limit %d blks,", fdp->transfersize);
printf(" %s\n", ata_mode2str(fdp->atp->controller->mode[
ATA_DEV(fdp->atp->unit)]));
- printf("afd%d: Medium: ", fdp->lun);
- switch (fdp->header.medium_type) {
- case MFD_2DD:
- printf("720KB DD disk"); break;
+ if (fdp->header.medium_type) {
+ printf("afd%d: Medium: ", fdp->lun);
+ switch (fdp->header.medium_type) {
+ case MFD_2DD:
+ printf("720KB DD disk"); break;
- case MFD_HD_12:
- printf("1.2MB HD disk"); break;
+ case MFD_HD_12:
+ printf("1.2MB HD disk"); break;
- case MFD_HD_144:
- printf("1.44MB HD disk"); break;
+ case MFD_HD_144:
+ printf("1.44MB HD disk"); break;
- case MFD_UHD:
- printf("120MB UHD disk"); break;
+ case MFD_UHD:
+ printf("120MB UHD disk"); break;
- default:
- printf("Unknown media (0x%x)", fdp->header.medium_type);
+ default:
+ printf("Unknown (0x%x)", fdp->header.medium_type);
+ }
+ if (fdp->header.wp) printf(", writeprotected");
}
- if (fdp->header.wp) printf(", writeprotected");
- printf("\n");
+ printf("\n");
}
else {
printf("afd%d: %luMB <%.40s> [%d/%d/%d] at ata%d-%s %s\n",
@@ -277,6 +285,13 @@ afdstrategy(struct bio *bp)
struct afd_softc *fdp = bp->bio_dev->si_drv1;
int s;
+ if (fdp->atp->flags & ATAPI_F_DETACHING) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ return;
+ }
+
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
bp->bio_resid = 0;
@@ -285,7 +300,7 @@ afdstrategy(struct bio *bp)
}
s = splbio();
- bioqdisksort(&fdp->bio_queue, bp);
+ bioqdisksort(&fdp->queue, bp);
ata_start(fdp->atp->controller);
splx(s);
}
@@ -294,7 +309,7 @@ void
afd_start(struct atapi_softc *atp)
{
struct afd_softc *fdp = atp->driver;
- struct bio *bp = bioq_first(&fdp->bio_queue);
+ struct bio *bp = bioq_first(&fdp->queue);
u_int32_t lba;
u_int16_t count;
int8_t ccb[16];
@@ -303,7 +318,7 @@ afd_start(struct atapi_softc *atp)
if (!bp)
return;
- bioq_remove(&fdp->bio_queue, bp);
+ bioq_remove(&fdp->queue, bp);
/* should reject all queued entries if media have changed. */
if (fdp->atp->flags & ATAPI_F_MEDIA_CHANGED) {
@@ -353,7 +368,8 @@ afd_start(struct atapi_softc *atp)
ccb[8] = count;
atapi_queue_cmd(fdp->atp, ccb, data_ptr, count * fdp->cap.sector_size,
- (bp->bio_cmd == BIO_READ) ? ATPR_F_READ : 0, 30, afd_done, bp);
+ (bp->bio_cmd == BIO_READ) ? ATPR_F_READ : 0, 30,
+ afd_done, bp);
}
static int
@@ -423,5 +439,5 @@ afd_prevent_allow(struct afd_softc *fdp, int lock)
int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0,30, NULL, NULL);
+ return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
}
diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h
index 8c633d4..84d5669 100644
--- a/sys/dev/ata/atapi-fd.h
+++ b/sys/dev/ata/atapi-fd.h
@@ -74,7 +74,7 @@ struct afd_softc {
struct atapi_softc *atp; /* controller structure */
int lun; /* logical device unit */
int transfersize; /* max size of each transfer */
- struct bio_queue_head bio_queue; /* queue of i/o requests */
+ struct bio_queue_head queue; /* queue of i/o requests */
struct afd_header header; /* capabilities page info */
struct afd_cappage cap; /* capabilities page info */
struct disk disk; /* virtual drives */
diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c
index af3e7af..7fa8fc5 100644
--- a/sys/dev/ata/atapi-tape.c
+++ b/sys/dev/ata/atapi-tape.c
@@ -101,7 +101,7 @@ astattach(struct atapi_softc *atp)
printf("ast: out of memory\n");
return -1;
}
- bioq_init(&stp->bio_queue);
+ bioq_init(&stp->queue);
stp->atp = atp;
stp->lun = ata_get_lun(&ast_lun_map);
if (ast_sense(stp)) {
@@ -151,7 +151,13 @@ void
astdetach(struct atapi_softc *atp)
{
struct ast_softc *stp = atp->driver;
+ struct bio *bp;
+ while ((bp = bioq_first(&stp->queue))) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ }
destroy_dev(stp->dev1);
destroy_dev(stp->dev2);
devstat_remove_entry(&stp->stats);
@@ -414,6 +420,13 @@ aststrategy(struct bio *bp)
struct ast_softc *stp = bp->bio_dev->si_drv1;
int s;
+ if (stp->atp->flags & ATAPI_F_DETACHING) {
+ bp->bio_error = ENXIO;
+ bp->bio_flags |= BIO_ERROR;
+ biodone(bp);
+ return;
+ }
+
/* if it's a null transfer, return immediatly. */
if (bp->bio_bcount == 0) {
bp->bio_resid = 0;
@@ -447,7 +460,7 @@ aststrategy(struct bio *bp)
}
s = splbio();
- bioq_insert_tail(&stp->bio_queue, bp);
+ bioq_insert_tail(&stp->queue, bp);
ata_start(stp->atp->controller);
splx(s);
}
@@ -456,7 +469,7 @@ void
ast_start(struct atapi_softc *atp)
{
struct ast_softc *stp = atp->driver;
- struct bio *bp = bioq_first(&stp->bio_queue);
+ struct bio *bp = bioq_first(&stp->queue);
u_int32_t blkcount;
int8_t ccb[16];
@@ -470,7 +483,7 @@ ast_start(struct atapi_softc *atp)
else
ccb[0] = ATAPI_WRITE;
- bioq_remove(&stp->bio_queue, bp);
+ bioq_remove(&stp->queue, bp);
blkcount = bp->bio_bcount / stp->blksize;
ccb[1] = 1;
diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h
index 24d90e6..7611af2 100644
--- a/sys/dev/ata/atapi-tape.h
+++ b/sys/dev/ata/atapi-tape.h
@@ -154,7 +154,7 @@ struct ast_softc {
#define F_ONSTREAM 0x0100 /* OnStream ADR device */
int blksize; /* block size (512 | 1024) */
- struct bio_queue_head bio_queue; /* queue of i/o requests */
+ struct bio_queue_head queue; /* queue of i/o requests */
struct atapi_params *param; /* drive parameters table */
struct ast_cappage cap; /* capabilities page info */
struct devstat stats; /* devstat entry */
OpenPOWER on IntegriCloud