summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata-all.c347
-rw-r--r--sys/dev/ata/ata-all.h33
-rw-r--r--sys/dev/ata/ata-disk.c111
-rw-r--r--sys/dev/ata/ata-disk.h17
-rw-r--r--sys/dev/ata/ata-dma.c231
-rw-r--r--sys/dev/ata/atapi-all.c313
-rw-r--r--sys/dev/ata/atapi-all.h50
-rw-r--r--sys/dev/ata/atapi-cd.c158
-rw-r--r--sys/dev/ata/atapi-fd.c38
-rw-r--r--sys/dev/ata/atapi-fd.h20
-rw-r--r--sys/dev/ata/atapi-tape.c108
-rw-r--r--sys/dev/ata/atapi-tape.h98
12 files changed, 814 insertions, 710 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 14f2f01..62d9db2 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -37,6 +37,7 @@
#include "atapifd.h"
#include "atapist.h"
#include "opt_global.h"
+#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -77,22 +78,22 @@
#endif
/* prototypes */
-#if NPCI > 0
-static void promise_intr(void *);
-#endif
static int32_t ata_probe(int32_t, int32_t, int32_t, device_t, int32_t *);
static void ataintr(void *);
+static int8_t *active2str(int32_t);
-static int32_t atanlun = 0;
+/* local vars */
+static int32_t atanlun = 2;
struct ata_softc *atadevices[MAXATA];
static devclass_t ata_devclass;
+MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
#if NISA > 0
static struct isa_pnp_id ata_ids[] = {
- {0x0006d041, "Generic ESDI/IDE/ATA controller"}, /* PNP0600 */
- {0x0106d041, "Plus Hardcard II"}, /* PNP0601 */
- {0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */
- {0x0306d041, "Generic ATA"}, /* PNP0603 */
+ {0x0006d041, "Generic ESDI/IDE/ATA controller"}, /* PNP0600 */
+ {0x0106d041, "Plus Hardcard II"}, /* PNP0601 */
+ {0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */
+ {0x0306d041, "Generic ATA"}, /* PNP0603 */
{0}
};
@@ -183,35 +184,38 @@ static const char *
ata_pcimatch(device_t dev)
{
switch (pci_get_devid(dev)) {
+ /* supported chipsets */
case 0x12308086:
return "Intel PIIX IDE controller";
case 0x70108086:
return "Intel PIIX3 IDE controller";
case 0x71118086:
return "Intel PIIX4 IDE controller";
+ case 0x522910b9:
+ return "AcerLabs Aladdin IDE controller";
case 0x4d33105a:
return "Promise Ultra/33 IDE controller";
case 0x4d38105a:
return "Promise Ultra/66 IDE controller";
- case 0x522910b9:
- return "AcerLabs Aladdin IDE controller";
case 0x00041103:
return "HighPoint HPT366 IDE controller";
+
+ /* unsupported but known chipsets, generic DMA only */
case 0x05711106: /* 82c586 */
case 0x05961106: /* 82c596 */
- return "VIA Apollo IDE controller";
+ return "VIA Apollo IDE controller (generic mode)";
case 0x06401095:
- return "CMD 640 IDE controller";
+ return "CMD 640 IDE controller (generic mode)";
case 0x06461095:
- return "CMD 646 IDE controller";
+ return "CMD 646 IDE controller (generic mode)";
case 0xc6931080:
- return "Cypress 82C693 IDE controller";
+ return "Cypress 82C693 IDE controller (generic mode)";
case 0x01021078:
- return "Cyrix 5530 IDE controller";
+ return "Cyrix 5530 IDE controller (generic mode)";
default:
if (pci_get_class(dev) == PCIC_STORAGE &&
- pci_get_subclass(dev) == PCIS_STORAGE_IDE)
- return "Unknown PCI IDE controller (using generic mode)";
+ (pci_get_subclass(dev) == PCIS_STORAGE_IDE))
+ return "Unknown PCI IDE controller (generic mode)";
}
return NULL;
}
@@ -247,69 +251,68 @@ ata_pciattach(device_t dev)
cmd = pci_read_config(dev, PCIR_COMMAND, 4);
#ifdef ATA_DEBUG
- printf("ata-pci%d: type=%08x class=%02x subclass=%02x cmd=%08x\n",
- unit, type, class, subclass, cmd);
+ printf("ata-pci%d: type=%08x class=%02x subclass=%02x cmd=%08x if=%02x\n",
+ unit, type, class, subclass, cmd, pci_get_progif(dev));
#endif
- /* if this is a Promise controller handle it specially */
- if (type == 0x4d33105a || type == 0x4d38105a) {
+ if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) {
+ iobase_1 = IO_WD1;
+ altiobase_1 = iobase_1 + ATA_ALTPORT;
+ irq1 = 14;
+ }
+ else {
iobase_1 = pci_read_config(dev, 0x10, 4) & 0xfffc;
altiobase_1 = pci_read_config(dev, 0x14, 4) & 0xfffc;
- iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc;
- altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc;
- irq1 = irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc;
- bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
- outb(bmaddr_1 + 0x1f, inb(bmaddr_1 + 0x1f) | 0x01);
- printf("ata-pci%d: Busmastering DMA supported\n", unit);
+ irq1 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
+ }
+
+ if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) {
+ iobase_2 = IO_WD2;
+ altiobase_2 = iobase_2 + ATA_ALTPORT;
+ irq2 = 15;
}
- /* everybody else seems to do it this way */
else {
- if ((unit == 0) &&
- (pci_get_progif(dev) & PCIP_STORAGE_IDE_MODEPRIM) == 0) {
- iobase_1 = IO_WD1;
- altiobase_1 = iobase_1 + ATA_ALTPORT;
- irq1 = 14;
- }
- else {
- iobase_1 = pci_read_config(dev, 0x10, 4) & 0xfffc;
- altiobase_1 = pci_read_config(dev, 0x14, 4) & 0xfffc;
- irq1 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
- }
- if ((unit == 0) &&
- (pci_get_progif(dev) & PCIP_STORAGE_IDE_MODESEC) == 0) {
- iobase_2 = IO_WD2;
- altiobase_2 = iobase_2 + ATA_ALTPORT;
- irq2 = 15;
- }
- else {
- iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc;
- altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc;
- irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
- }
+ iobase_2 = pci_read_config(dev, 0x18, 4) & 0xfffc;
+ altiobase_2 = pci_read_config(dev, 0x1c, 4) & 0xfffc;
+ bmaddr_2 = (pci_read_config(dev, 0x20, 4) & 0xfffc) + ATA_BM_OFFSET1;
+ irq2 = pci_read_config(dev, PCI_INTERRUPT_REG, 4) & 0xff;
+ }
- /* is this controller busmaster capable ? */
- if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) {
- /* is busmastering support turned on ? */
- if ((pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4) & 5) == 5) {
- /* is there a valid port range to connect to ? */
- if ((bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc)) {
- bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
- printf("ata-pci%d: Busmastering DMA supported\n", unit);
- }
- else
- printf("ata-pci%d: Busmastering DMA not configured\n",unit);
+ /* is this controller busmaster DMA capable ? */
+ if (pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV) {
+ /* is busmastering support turned on ? */
+ if ((pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4) & 5) == 5) {
+ /* is there a valid port range to connect to ? */
+ if ((bmaddr_1 = pci_read_config(dev, 0x20, 4) & 0xfffc)) {
+ bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1;
+ printf("ata-pci%d: Busmastering DMA supported\n", unit);
}
else
- printf("ata-pci%d: Busmastering DMA not enabled\n", unit);
+ printf("ata-pci%d: Busmastering DMA not configured\n", unit);
}
else
+ printf("ata-pci%d: Busmastering DMA not enabled\n", unit);
+ }
+ else {
+ /* the Promise controllers need this to support burst mode */
+ if (type == 0x4d33105a || type == 0x4d38105a)
+ outb(bmaddr_1 + 0x1f, inb(bmaddr_1 + 0x1f) | 0x01);
+
+ /* Promise and HPT366 controllers support busmastering DMA */
+ if (type == 0x4d33105a || type == 0x4d38105a || type == 0x00041103)
+ printf("ata-pci%d: Busmastering DMA supported\n", unit);
+
+ /* we dont know this controller, disable busmastering DMA */
+ else {
+ bmaddr_1 = bmaddr_2 = 0;
printf("ata-pci%d: Busmastering DMA not supported\n", unit);
+ }
}
/* now probe the addresse found for "real" ATA/ATAPI hardware */
lun = 0;
- if (ata_probe(iobase_1, altiobase_1, bmaddr_1, dev, &lun)) {
+ if (iobase_1 && ata_probe(iobase_1, altiobase_1, bmaddr_1, dev, &lun)) {
scp = atadevices[lun];
if (iobase_1 == IO_WD1)
#ifdef __i386__
@@ -324,21 +327,16 @@ ata_pciattach(device_t dev)
int rid = 0;
void *ih;
- irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
- RF_SHAREABLE | RF_ACTIVE);
- if (!irq)
+ if (!(irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE)))
printf("ata_pciattach: Unable to alloc interrupt\n");
-
- if (type == 0x4d33105a || type == 0x4d38105a)
- bus_setup_intr(dev, irq, INTR_TYPE_BIO, promise_intr, scp, &ih);
- else
- bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih);
+ bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih);
}
printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
lun, iobase_1, isa_apic_irq(irq1), unit);
}
lun = 1;
- if (ata_probe(iobase_2, altiobase_2, bmaddr_2, dev, &lun)) {
+ if (iobase_2 && ata_probe(iobase_2, altiobase_2, bmaddr_2, dev, &lun)) {
scp = atadevices[lun];
if (iobase_2 == IO_WD2)
#ifdef __i386__
@@ -353,14 +351,10 @@ ata_pciattach(device_t dev)
int rid = 0;
void *ih;
- if (type != 0x4d33105a && type != 0x4d38105a) {
- irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
- RF_SHAREABLE | RF_ACTIVE);
- if (!irq)
- printf("ata_pciattach: Unable to alloc interrupt\n");
-
- bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih);
- }
+ if (!(irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE)))
+ printf("ata_pciattach: Unable to alloc interrupt\n");
+ bus_setup_intr(dev, irq, INTR_TYPE_BIO, ataintr, scp, &ih);
}
printf("ata%d at 0x%04x irq %d on ata-pci%d\n",
lun, iobase_2, isa_apic_irq(irq2), unit);
@@ -382,52 +376,44 @@ static driver_t ata_pci_driver = {
};
DRIVER_MODULE(ata, pci, ata_pci_driver, ata_devclass, 0, 0);
-
-static void
-promise_intr(void *data)
-{
- struct ata_softc *scp = (struct ata_softc *)data;
- int32_t channel = inl((pci_read_config(scp->dev, 0x20, 4) & 0xfffc) + 0x1c);
-
- if (channel & 0x00000400)
- ataintr(data);
-
- if (channel & 0x00004000)
- ataintr(atadevices[scp->lun + 1]);
-}
#endif
static int32_t
ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
device_t dev, int32_t *unit)
{
- struct ata_softc *scp = atadevices[atanlun];
- int32_t mask = 0;
- int32_t lun = atanlun;
+ struct ata_softc *scp;
+ int32_t lun, mask = 0;
u_int8_t status0, status1;
-#ifdef ATA_STATIC_ID
- atanlun++;
-#endif
- if (lun > MAXATA) {
- printf("ata: unit out of range(%d)\n", lun);
+ if (atanlun > MAXATA) {
+ printf("ata: unit out of range(%d)\n", atanlun);
return 0;
}
- if (scp) {
+
+ /* check if this is located at one of the std addresses */
+ if (ioaddr == IO_WD1)
+ lun = 0;
+ else if (ioaddr == IO_WD2)
+ lun = 1;
+ else
+ lun = atanlun++;
+
+ if ((scp = atadevices[lun])) {
printf("ata%d: unit already attached\n", lun);
return 0;
}
- scp = malloc(sizeof(struct ata_softc), M_DEVBUF, M_NOWAIT);
+ scp = malloc(sizeof(struct ata_softc), M_ATA, M_NOWAIT);
if (scp == NULL) {
printf("ata%d: failed to allocate driver storage\n", lun);
return 0;
}
bzero(scp, sizeof(struct ata_softc));
- scp->unit = *unit;
- scp->lun = lun;
scp->ioaddr = ioaddr;
scp->altioaddr = altioaddr;
+ scp->lun = lun;
+ scp->unit = *unit;
scp->active = ATA_IDLE;
if (bootverbose)
@@ -508,9 +494,6 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr,
if (bmaddr)
scp->bmaddr = bmaddr;
atadevices[scp->lun] = scp;
-#ifndef ATA_STATIC_ID
- atanlun++;
-#endif
#if NAPM > 0
scp->resume_hook.ah_fun = (void *)ata_reinit;
scp->resume_hook.ah_arg = scp;
@@ -526,19 +509,24 @@ ataintr(void *data)
{
struct ata_softc *scp =(struct ata_softc *)data;
- scp->status = inb(scp->ioaddr + ATA_STATUS);
+ /* is this interrupt really for this channel */
+ if (scp->flags & ATA_DMA_ACTIVE)
+ if (!(ata_dmastatus(scp) & ATA_BMSTAT_INTERRUPT))
+ return;
+ if ((scp->status = inb(scp->ioaddr + ATA_STATUS)) == ATA_S_BUSY) /*XXX SOS*/
+ return;
/* find & call the responsible driver to process this interrupt */
switch (scp->active) {
#if NATADISK > 0
case ATA_ACTIVE_ATA:
- if (ad_interrupt(scp->running) == ATA_OP_CONTINUES)
+ if (scp->running && (ad_interrupt(scp->running) == ATA_OP_CONTINUES))
return;
break;
#endif
#if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0
case ATA_ACTIVE_ATAPI:
- if (atapi_interrupt(scp->running) == ATA_OP_CONTINUES)
+ if (scp->running && (atapi_interrupt(scp->running) == ATA_OP_CONTINUES))
return;
break;
#endif
@@ -546,6 +534,9 @@ ataintr(void *data)
wakeup((caddr_t)scp);
break;
+ case ATA_REINITING:
+ return;
+
case ATA_IGNORE_INTR:
break;
@@ -579,7 +570,7 @@ ata_start(struct ata_softc *scp)
return;
#if NATADISK > 0
- /* find & call the responsible driver if anything on ATA queue */
+ /* find & call the responsible driver if anything on the ATA queue */
if ((ad_request = TAILQ_FIRST(&scp->ata_queue))) {
TAILQ_REMOVE(&scp->ata_queue, ad_request, chain);
scp->active = ATA_ACTIVE_ATA;
@@ -593,34 +584,40 @@ ata_start(struct ata_softc *scp)
#endif
#if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0
/*
- * find & call the responsible driver if anything on ATAPI queue.
+ * find & call the responsible driver if anything on the ATAPI queue.
* check for device busy by polling the DSC bit, if busy, check
* for requests to the other device on the channel (if any).
- * if no request can be served, timeout a call to ata_start to
- * try again in a moment. the timeout should probably scale
- * so we dont use too much time polling for slow devices.
+ * if the other device is an ATA disk it already had its chance above.
+ * if no request can be served, timeout a call to ata_start.
*/
if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) {
struct atapi_softc *atp = atapi_request->device;
+ static int32_t interval = 1;
- outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
- DELAY(1);
- if (!(inb(atp->controller->ioaddr + ATA_STATUS) & ATA_S_DSC)) {
- while ((atapi_request = TAILQ_NEXT(atapi_request, chain))) {
- if (atapi_request->device->unit != atp->unit) {
- struct atapi_softc *tmpatp = atapi_request->device;
-
- outb(tmpatp->controller->ioaddr + ATA_DRIVE,
- ATA_D_IBM | tmpatp->unit);
- DELAY(1);
- if (!(inb(tmpatp->controller->ioaddr+ATA_STATUS)&ATA_S_DSC))
- atapi_request = NULL;
- break;
- }
+ if (atp->flags & ATAPI_F_DSC_USED) {
+ outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
+ DELAY(1);
+ if (!(inb(atp->controller->ioaddr + ATA_STATUS) & ATA_S_DSC)) {
+ while ((atapi_request = TAILQ_NEXT(atapi_request, chain))) {
+ if (atapi_request->device->unit != atp->unit) {
+ struct atapi_softc *tmp = atapi_request->device;
+
+ outb(tmp->controller->ioaddr + ATA_DRIVE,
+ ATA_D_IBM | tmp->unit);
+ DELAY(1);
+ if (!inb(tmp->controller->ioaddr+ATA_STATUS)&ATA_S_DSC)
+ atapi_request = NULL;
+ break;
+ }
+ }
+ }
+ if (!atapi_request) {
+ timeout((timeout_t *)ata_start, atp->controller, interval++);
+ return;
}
+ else
+ interval = 1;
}
- if (!atapi_request)
- atapi_request = TAILQ_FIRST(&scp->atapi_queue);
TAILQ_REMOVE(&scp->atapi_queue, atapi_request, chain);
scp->active = ATA_ACTIVE_ATAPI;
scp->running = atapi_request;
@@ -648,12 +645,10 @@ ata_reset(struct ata_softc *scp, int32_t *mask)
outb(scp->altioaddr, ATA_A_IDS);
DELAY(10000);
inb(scp->ioaddr + ATA_ERROR);
- DELAY(1);
- outb(scp->altioaddr, ATA_A_4BIT);
- DELAY(1);
+ DELAY(3000);
/* wait for BUSY to go inactive */
- for (timeout = 0; timeout < 300000; timeout++) {
+ for (timeout = 0; timeout < 310000; timeout++) {
outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
DELAY(1);
status0 = inb(scp->ioaddr + ATA_STATUS);
@@ -661,19 +656,21 @@ ata_reset(struct ata_softc *scp, int32_t *mask)
DELAY(1);
status1 = inb(scp->ioaddr + ATA_STATUS);
if (*mask == 0x01) /* wait for master only */
- if (!(status0 & ATA_S_BSY))
+ if (!(status0 & ATA_S_BUSY))
break;
if (*mask == 0x02) /* wait for slave only */
- if (!(status1 & ATA_S_BSY))
+ if (!(status1 & ATA_S_BUSY))
break;
if (*mask == 0x03) /* wait for both master & slave */
- if (!(status0 & ATA_S_BSY) && !(status1 & ATA_S_BSY))
+ if (!(status0 & ATA_S_BUSY) && !(status1 & ATA_S_BUSY))
break;
DELAY(100);
}
- if (status0 & ATA_S_BSY)
+ DELAY(1);
+ outb(scp->altioaddr, ATA_A_4BIT);
+ if (status0 & ATA_S_BUSY)
*mask &= ~0x01;
- if (status1 & ATA_S_BSY)
+ if (status1 & ATA_S_BUSY)
*mask &= ~0x02;
if (bootverbose)
printf("ata%d: mask=%02x status0=%02x status1=%02x\n",
@@ -683,29 +680,34 @@ ata_reset(struct ata_softc *scp, int32_t *mask)
int32_t
ata_reinit(struct ata_softc *scp)
{
- int32_t mask = 0;
+ int32_t mask = 0, omask;
+ scp->active = ATA_REINITING;
+ scp->running = NULL;
printf("ata%d: resetting devices .. ", scp->lun);
- scp->active = ATA_IDLE;
if (scp->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER))
mask |= 0x01;
if (scp->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE))
mask |= 0x02;
+ omask = mask;
ata_reset(scp, &mask);
+ if (omask != mask)
+ printf(" device dissapeared! %d ", omask & ~mask);
#if NATADISK > 0
- if (scp->devices & (ATA_ATA_MASTER))
+ 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))
+ if (scp->devices & (ATA_ATA_SLAVE) && scp->dev_softc[1])
ad_reinit((struct ad_softc *)scp->dev_softc[1]);
#endif
#if NATAPICD > 0 || NATAPIFD > 0 || NATAPIST > 0
- if (scp->devices & (ATA_ATAPI_MASTER))
+ 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))
+ if (scp->devices & (ATA_ATAPI_SLAVE) && scp->dev_softc[1])
atapi_reinit((struct atapi_softc *)scp->dev_softc[1]);
#endif
printf("done\n");
+ scp->active = ATA_IDLE;
ata_start(scp);
return 0;
}
@@ -730,7 +732,7 @@ ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask)
if (status == 0xff)
return -1;
scp->status = status;
- if (!(status & ATA_S_BSY)) {
+ if (!(status & ATA_S_BUSY)) {
if (status & ATA_S_ERROR)
scp->error = inb(scp->ioaddr + ATA_ERROR);
if ((status & mask) == mask)
@@ -762,8 +764,10 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
/* ready to issue command ? */
if (ata_wait(scp, device, 0) < 0) {
- printf("ata%d-%s: timeout waiting to give command s=%02x e=%02x\n",
- scp->lun, device?"slave":"master", scp->status, scp->error);
+ printf("ata%d-%s: timeout waiting to give command=%02x s=%02x e=%02x\n",
+ scp->lun, device ? "slave" : "master", command,
+ scp->status, scp->error);
+ return -1;
}
outb(scp->ioaddr + ATA_FEATURE, feature);
outb(scp->ioaddr + ATA_CYL_LSB, cylinder);
@@ -772,11 +776,10 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
outb(scp->ioaddr + ATA_SECTOR, sector);
outb(scp->ioaddr + ATA_COUNT, count);
- if (scp->active != ATA_IDLE && flags != ATA_IMMEDIATE)
- printf("DANGER active=%d\n", scp->active);
-
switch (flags) {
case ATA_WAIT_INTR:
+ if (scp->active != ATA_IDLE)
+ printf("DANGER wait_intr active=%s\n", active2str(scp->active));
scp->active = ATA_WAIT_INTR;
outb(scp->ioaddr + ATA_CMD, command);
if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) {
@@ -787,14 +790,19 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command,
break;
case ATA_IGNORE_INTR:
- scp->active = ATA_IGNORE_INTR;
+ if (scp->active != ATA_IDLE && scp->active != ATA_REINITING)
+ printf("DANGER ignore_intr active=%s\n", active2str(scp->active));
+ if (scp->active != ATA_REINITING)
+ scp->active = ATA_IGNORE_INTR;
outb(scp->ioaddr + ATA_CMD, command);
break;
case ATA_IMMEDIATE:
- default:
outb(scp->ioaddr + ATA_CMD, command);
break;
+
+ default:
+ printf("DANGER illegal interrupt flag=%s\n", active2str(flags));
}
#ifdef ATA_DEBUG
printf("ata_command: leaving\n");
@@ -808,17 +816,40 @@ ata_mode2str(int32_t mode)
switch (mode) {
case ATA_MODE_PIO:
return "PIO";
- case ATA_MODE_DMA:
+ case ATA_MODE_WDMA2:
return "DMA";
- case ATA_MODE_UDMA33:
+ case ATA_MODE_UDMA2:
return "UDMA33";
- case ATA_MODE_UDMA66:
+ case ATA_MODE_UDMA3:
+ return "UDMA3";
+ case ATA_MODE_UDMA4:
return "UDMA66";
default:
return "???";
}
}
+static int8_t *
+active2str(int32_t active)
+{
+ switch (active) {
+ case ATA_IDLE:
+ return("ATA_IDLE");
+ case ATA_WAIT_INTR:
+ return("ATA_WAIT_INTR");
+ case ATA_IGNORE_INTR:
+ return("ATA_IGNORE_INTR");
+ case ATA_ACTIVE_ATA:
+ return("ATA_ACTIVE_ATA");
+ case ATA_ACTIVE_ATAPI:
+ return("ATA_ACTIVE_ATAPI");
+ case ATA_REINITING:
+ return("ATA_REINITING");
+ default:
+ return("UNKNOWN");
+ }
+}
+
void
bswap(int8_t *buf, int32_t len)
{
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 96a3336..c14c98f 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -31,6 +31,8 @@
/* ATA register defines */
#define ATA_DATA 0x00 /* data register */
#define ATA_ERROR 0x01 /* (R) error register */
+#define ATA_E_ABORT 0x04 /* command aborted */
+
#define ATA_FEATURE 0x01 /* (W) feature register */
#define ATA_F_DMA 0x01 /* enable DMA */
#define ATA_F_OVL 0x02 /* enable overlap */
@@ -70,11 +72,11 @@
#define ATA_S_CORR 0x04 /* data corrected */
#define ATA_S_DRQ 0x08 /* data request */
#define ATA_S_DSC 0x10 /* drive seek completed */
-#define ATA_S_SERV 0x10 /* drive needs service */
+#define ATA_S_SERVICE 0x10 /* drive needs service */
#define ATA_S_DWF 0x20 /* drive write fault */
-#define ATA_S_DMRD 0x20 /* DMA ready */
-#define ATA_S_DRDY 0x40 /* drive ready */
-#define ATA_S_BSY 0x80 /* busy */
+#define ATA_S_DMA 0x20 /* DMA ready */
+#define ATA_S_READY 0x40 /* drive ready */
+#define ATA_S_BUSY 0x80 /* busy */
#define ATA_ALTPORT 0x206 /* alternate Status register */
#define ATA_A_IDS 0x02 /* disable interrupts */
@@ -104,6 +106,7 @@
#define ATA_BMSTAT_MASK 0x07
#define ATA_BMSTAT_DMA_MASTER 0x20
#define ATA_BMSTAT_DMA_SLAVE 0x40
+#define ATA_BMSTAT_DMA_SIMPLEX 0x80
#define ATA_BMDTP_PORT 0x04
@@ -116,6 +119,7 @@ struct ata_dmaentry {
/* ATA device DMA access modes */
#define ATA_WDMA2 0x22
#define ATA_UDMA2 0x42
+#define ATA_UDMA3 0x43
#define ATA_UDMA4 0x44
/* structure describing an ATA device */
@@ -130,12 +134,14 @@ struct ata_softc {
struct ata_dmaentry *dmatab[2]; /* DMA transfer tables */
int32_t mode[2]; /* transfer mode for devices */
#define ATA_MODE_PIO 0x00
-#define ATA_MODE_DMA 0x01
-#define ATA_MODE_UDMA33 0x02
-#define ATA_MODE_UDMA66 0x04
+#define ATA_MODE_WDMA2 0x01
+#define ATA_MODE_UDMA2 0x02
+#define ATA_MODE_UDMA3 0x04
+#define ATA_MODE_UDMA4 0x08
int32_t flags; /* controller flags */
-#define ATA_ATAPI_DMA_RO 0x01
+#define ATA_DMA_ACTIVE 0x01
+#define ATA_ATAPI_DMA_RO 0x02
int32_t devices; /* what is present */
#define ATA_ATA_MASTER 0x01
@@ -152,6 +158,7 @@ struct ata_softc {
#define ATA_IGNORE_INTR 0x2
#define ATA_ACTIVE_ATA 0x3
#define ATA_ACTIVE_ATAPI 0x4
+#define ATA_REINITING 0x5
TAILQ_HEAD(, ad_request) ata_queue; /* head of ATA queue */
TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */
@@ -162,9 +169,9 @@ struct ata_softc {
};
-#define MAXATA 8
-
+/* array to hold all ata softc's */
extern struct ata_softc *atadevices[];
+#define MAXATA 16
/* public prototypes */
void ata_start(struct ata_softc *);
@@ -174,9 +181,9 @@ int32_t ata_wait(struct ata_softc *, int32_t, u_int8_t);
int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t);
int32_t ata_dmainit(struct ata_softc *, int32_t, int32_t, int32_t, int32_t);
int32_t ata_dmasetup(struct ata_softc *, int32_t, int8_t *, int32_t, int32_t);
-void ata_dmastart(struct ata_softc *, int32_t);
-int32_t ata_dmastatus(struct ata_softc *, int32_t);
-int32_t ata_dmadone(struct ata_softc *, int32_t);
+void ata_dmastart(struct ata_softc *);
+int32_t ata_dmastatus(struct ata_softc *);
+int32_t ata_dmadone(struct ata_softc *);
int8_t *ata_mode2str(int32_t);
void bswap(int8_t *, int32_t);
void btrim(int8_t *, int32_t);
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 7d3cc1e..843b852 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -29,6 +29,8 @@
*/
#include "apm.h"
+#include "opt_global.h"
+#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -87,8 +89,8 @@ static int8_t ad_version(u_int16_t);
static void ad_drvinit(void);
/* internal vars */
-static int32_t adnlun = 0; /* number of config'd drives */
static struct intr_config_hook *ad_attach_hook;
+MALLOC_DEFINE(M_AD, "AD driver", "ATA disk driver");
/* defines */
#define AD_MAX_RETRIES 5
@@ -96,33 +98,35 @@ static struct intr_config_hook *ad_attach_hook;
static __inline int
apiomode(struct ata_params *ap)
{
- if ((ap->atavalid & 2) == 2) {
- if ((ap->apiomodes & 2) == 2) return 4;
- if ((ap->apiomodes & 1) == 1) return 3;
- }
- return -1;
+ if (ap->atavalid & 2) {
+ if (ap->apiomodes & 2) return 4;
+ if (ap->apiomodes & 1) return 3;
+ }
+ return -1;
}
static __inline int
wdmamode(struct ata_params *ap)
{
- if ((ap->atavalid & 2) == 2) {
- if ((ap->wdmamodes & 4) == 4) return 2;
- if ((ap->wdmamodes & 2) == 2) return 1;
- if ((ap->wdmamodes & 1) == 1) return 0;
- }
- return -1;
+ if (ap->atavalid & 2) {
+ if (ap->wdmamodes & 4) return 2;
+ if (ap->wdmamodes & 2) return 1;
+ if (ap->wdmamodes & 1) return 0;
+ }
+ return -1;
}
static __inline int
udmamode(struct ata_params *ap)
{
- if ((ap->atavalid & 4) == 4) {
- if ((ap->udmamodes & 4) == 4) return 2;
- if ((ap->udmamodes & 2) == 2) return 1;
- if ((ap->udmamodes & 1) == 1) return 0;
- }
- return -1;
+ if (ap->atavalid & 4) {
+ if (ap->udmamodes & 0x10 && ap->cblid) return 4;
+ if (ap->udmamodes & 0x08 && ap->cblid) return 3;
+ if (ap->udmamodes & 0x04) return 2;
+ if (ap->udmamodes & 0x02) return 1;
+ if (ap->udmamodes & 0x01) return 0;
+ }
+ return -1;
}
static void
@@ -133,6 +137,7 @@ ad_attach(void *notused)
int8_t model_buf[40+1];
int8_t revision_buf[8+1];
dev_t dev1;
+ static int32_t adnlun = 0;
/* now, run through atadevices and look for ATA disks */
for (ctlr=0; ctlr<MAXATA; ctlr++) {
@@ -144,16 +149,16 @@ ad_attach(void *notused)
adnlun = dev + ctlr * 2;
#endif
if (!(adp = malloc(sizeof(struct ad_softc),
- M_DEVBUF, M_NOWAIT))) {
+ M_AD, M_NOWAIT))) {
printf("ad%d: failed to allocate driver storage\n", adnlun);
continue;
}
bzero(adp, sizeof(struct ad_softc));
adp->controller = atadevices[ctlr];
adp->unit = (dev == 0) ? ATA_MASTER : ATA_SLAVE;
- adp->lun = adnlun;
+ adp->lun = adnlun++;
if (ad_getparam(adp)) {
- free(adp, M_DEVBUF);
+ free(adp, M_AD);
continue;
}
adp->cylinders = adp->ata_parm->cylinders;
@@ -174,7 +179,7 @@ ad_attach(void *notused)
secsperint = min(adp->ata_parm->nsecperint, 16);
if (!ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI,
0, 0, 0, secsperint, 0, ATA_WAIT_INTR) &&
- ata_wait(adp->controller, adp->unit, ATA_S_DRDY) >= 0)
+ ata_wait(adp->controller, adp->unit, ATA_S_READY) >= 0)
adp->transfersize *= secsperint;
/* use DMA if drive & controller supports it */
@@ -224,12 +229,14 @@ ad_attach(void *notused)
dev1 = disk_create(adp->lun, &adp->disk, 0, &ad_cdevsw,
&addisk_cdevsw);
dev1->si_drv1 = adp;
+ dev1->si_iosize_max = 256 * DEV_BSIZE;
+
dev1 = disk_create(adp->lun, &adp->disk, 0, &fakewd_cdevsw,
&fakewddisk_cdevsw);
dev1->si_drv1 = adp;
+ dev1->si_iosize_max = 256 * DEV_BSIZE;
bufq_init(&adp->queue);
- adnlun++;
}
}
}
@@ -248,11 +255,11 @@ ad_getparam(struct ad_softc *adp)
ata_command(adp->controller, adp->unit, ATA_C_ATA_IDENTIFY,
0, 0, 0, 0, 0, ATA_WAIT_INTR);
if (ata_wait(adp->controller, adp->unit,
- ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
+ ATA_S_READY | ATA_S_DSC | ATA_S_DRQ))
return -1;
insw(adp->controller->ioaddr + ATA_DATA, buffer,
sizeof(buffer)/sizeof(int16_t));
- ata_parm = malloc(sizeof(struct ata_params), M_DEVBUF, M_NOWAIT);
+ ata_parm = malloc(sizeof(struct ata_params), M_AD, M_NOWAIT);
if (!ata_parm)
return -1;
bcopy(buffer, ata_parm, sizeof(struct ata_params));
@@ -270,11 +277,6 @@ adopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
struct ad_softc *adp = dev->si_drv1;
struct disklabel *dl;
-#ifdef AD_DEBUG
- printf("adopen: lun=%d adnlun=%d\n", adp->lun, adnlun);
-#endif
-
- dev->si_iosize_max = 256 * DEV_BSIZE;
dl = &adp->disk.d_label;
bzero(dl, sizeof *dl);
dl->d_secsize = DEV_BSIZE;
@@ -284,7 +286,6 @@ adopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
dl->d_secpercyl = adp->sectors * adp->heads;
dl->d_secperunit = adp->total_secs;
ad_sleep(adp, "adop2");
-
return 0;
}
@@ -356,7 +357,7 @@ addump(dev_t dev)
addr += PAGE_SIZE;
}
- if (ata_wait(adp->controller, adp->unit, ATA_S_DRDY | ATA_S_DSC) < 0)
+ if (ata_wait(adp->controller, adp->unit, ATA_S_READY | ATA_S_DSC) < 0)
printf("ad_dump: timeout waiting for final ready\n");
return 0;
@@ -374,7 +375,7 @@ ad_start(struct ad_softc *adp)
if (!bp)
return;
- if (!(request = malloc(sizeof(struct ad_request), M_DEVBUF, M_NOWAIT))) {
+ if (!(request = malloc(sizeof(struct ad_request), M_AD, M_NOWAIT))) {
printf("ad_start: out of memory\n");
return;
}
@@ -466,7 +467,7 @@ ad_transfer(struct ad_request *request)
/* if this is a DMA transaction start it, return and wait for interrupt */
if (request->flags & AR_F_DMA_USED) {
- ata_dmastart(adp->controller, adp->unit);
+ ata_dmastart(adp->controller);
#ifdef AD_DEBUG
printf("ad_transfer: return waiting for DMA interrupt\n");
#endif
@@ -486,12 +487,12 @@ ad_transfer(struct ad_request *request)
/* ready to write PIO data ? */
if (ata_wait(adp->controller, adp->unit,
- ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) < 0) {
+ ATA_S_READY | ATA_S_DSC | ATA_S_DRQ) < 0) {
printf("ad_transfer: timeout waiting for DRQ");
}
/* output the data */
-#if 0
+#ifdef ATA_16BIT_ONLY
outsw(adp->controller->ioaddr + ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int16_t));
@@ -514,7 +515,7 @@ ad_interrupt(struct ad_request *request)
/* finish DMA transfer */
if (request->flags & AR_F_DMA_USED)
- dma_stat = ata_dmadone(adp->controller, adp->unit);
+ dma_stat = ata_dmadone(adp->controller);
/* get drive status */
if (ata_wait(adp->controller, adp->unit, 0) < 0)
@@ -537,18 +538,18 @@ oops:
((request->flags & (AR_F_READ | AR_F_ERROR)) == AR_F_READ)) {
/* ready to receive data? */
- if ((adp->controller->status & (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
- != (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ))
+ if ((adp->controller->status & (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ))
+ != (ATA_S_READY | ATA_S_DSC | ATA_S_DRQ))
printf("ad_interrupt: read interrupt arrived early");
if (ata_wait(adp->controller, adp->unit,
- ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) != 0){
+ ATA_S_READY | ATA_S_DSC | ATA_S_DRQ) != 0){
printf("ad_interrupt: read error detected late");
goto oops;
}
/* data ready, read in */
-#if 0
+#ifdef ATA_16BIT_ONLY
insw(adp->controller->ioaddr + ATA_DATA,
(void *)((uintptr_t)request->data + request->donecount),
request->currentsize / sizeof(int16_t));
@@ -592,7 +593,7 @@ oops:
/* disarm timeout for this transfer */
untimeout((timeout_t *)ad_timeout, request, request->timeout_handle);
- free(request, M_DEVBUF);
+ free(request, M_AD);
ad_start(adp);
#ifdef AD_DEBUG
printf("ad_interrupt: completed\n");
@@ -600,6 +601,17 @@ oops:
return ATA_OP_FINISHED;
}
+void
+ad_reinit(struct ad_softc *adp)
+{
+ /* reinit disk parameters */
+ ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI, 0, 0, 0,
+ adp->transfersize / DEV_BSIZE, 0, ATA_IMMEDIATE);
+ ata_wait(adp->controller, adp->unit, ATA_S_READY);
+ ata_dmainit(adp->controller, adp->unit, apiomode(adp->ata_parm),
+ wdmamode(adp->ata_parm), udmamode(adp->ata_parm));
+}
+
static void
ad_timeout(struct ad_request *request)
{
@@ -610,7 +622,7 @@ ad_timeout(struct ad_request *request)
(adp->unit == ATA_MASTER) ? "master" : "slave");
if (request->flags & AR_F_DMA_USED)
- ata_dmadone(adp->controller, adp->unit);
+ ata_dmadone(adp->controller);
if (request->retries < AD_MAX_RETRIES) {
/* reinject this request */
@@ -623,22 +635,11 @@ ad_timeout(struct ad_request *request)
request->bp->b_flags |= B_ERROR;
devstat_end_transaction_buf(&adp->stats, request->bp);
biodone(request->bp);
- free(request, M_DEVBUF);
+ free(request, M_AD);
}
ata_reinit(adp->controller);
}
-void
-ad_reinit(struct ad_softc *adp)
-{
- /* reinit disk parameters */
- ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI, 0, 0, 0,
- adp->transfersize / DEV_BSIZE, 0, ATA_IMMEDIATE);
- ata_wait(adp->controller, adp->unit, ATA_S_DRDY);
- ata_dmainit(adp->controller, adp->unit, apiomode(adp->ata_parm),
- wdmamode(adp->ata_parm), udmamode(adp->ata_parm));
-}
-
static void
ad_sleep(struct ad_softc *adp, int8_t *mesg)
{
diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h
index 7438a54..4e8e79d 100644
--- a/sys/dev/ata/ata-disk.h
+++ b/sys/dev/ata/ata-disk.h
@@ -113,12 +113,21 @@ struct ata_params {
int16_t erasetime;
int16_t enherasetime;
int16_t apmlevel;
- int16_t reserved92[34];
- int16_t rmvcap;
- int16_t securelevel;
+ int16_t masterpasswdrev;
+ u_int16_t masterhwres:8;
+ u_int16_t slavehwres:5;
+ u_int16_t cblid:1;
+ u_int16_t reserved93_1415:2;
+ int16_t reserved94[32];
+ int16_t rmvstat;
+ int16_t securstat;
+ int16_t reserved129[30];
+ int16_t cfapwrmode;
+ int16_t reserved161[84];
+ int16_t integrity;
};
-/* Structure describing an ATA disk */
+/* structure describing an ATA disk */
struct ad_softc {
struct ata_softc *controller; /* ptr to parent ctrl */
struct ata_params *ata_parm; /* ata device params */
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index 0b32282..f016b91 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -47,14 +47,16 @@
#endif
#include <dev/ata/ata-all.h>
+/* prototypes */
+static void hpt366_timing(struct ata_softc *, int32_t, int32_t);
+
+/* misc defines */
+#define MIN(a,b) ((a)>(b)?(b):(a))
#ifdef __alpha__
#undef vtophys
#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
#endif
-/* misc defines */
-#define MIN(a,b) ((a)>(b)?(b):(a))
-
#if NPCI > 0
int32_t
@@ -71,6 +73,17 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr);
#endif
+ /* if simplex controller, only allow DMA on primary channel */
+ if (scp->unit == 1) {
+ outb(scp->bmaddr + ATA_BMSTAT_PORT, inb(scp->bmaddr + ATA_BMSTAT_PORT) &
+ (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE));
+ if (inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX) {
+ printf("ata%d: simplex device, DMA on primary channel only\n",
+ scp->lun);
+ return -1;
+ }
+ }
+
if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT)))
return -1;
@@ -101,8 +114,8 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
new48 = (1 << devno) + (2 << (16 + (devno << 2)));
pci_write_config(scp->dev, 0x48,
(pci_read_config(scp->dev, 0x48, 4) &
- ~mask48) | new48, 4);
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA33;
+ ~mask48) | new48, 4);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2;
return 0;
}
/* FALLTHROUGH */
@@ -158,7 +171,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
pci_write_config(scp->dev, 0x44,
(pci_read_config(scp->dev, 0x44, 4) & ~mask44) |
new44, 4);
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2;
return 0;
}
break;
@@ -167,28 +180,76 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
/* probably not worth the trouble */
break;
- case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */
- case 0x4d38105a: /* Promise Ultra/66 controllers */
- /* the Promise can only do DMA on ATA disks not on ATAPI devices */
+ case 0x522910b9: /* AcerLabs Aladdin IV/V */
+ /* the Aladdin has to be setup specially for ATAPI devices */
if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
- (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
- break;
+ (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) {
+ int8_t word53 = pci_read_config(scp->dev, 0x53, 1);
- devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1);
- if (udmamode >=4 && type == 0x4d38105a) {
+ /* set atapi fifo, this should always work */
+ pci_write_config(scp->dev, 0x53, (word53 & ~0x01) | 0x02, 1);
+
+ /* if both master & slave are atapi devices dont allow DMA */
+ if (scp->devices & ATA_ATAPI_MASTER &&
+ scp->devices & ATA_ATAPI_SLAVE) {
+ printf("ata%d: Aladdin: two atapi devices on this channel, "
+ "DMA disabled\n", scp->lun);
+ break;
+ }
+ /* if needed set atapi fifo & dma */
+ if ((udmamode >=2) || (wdmamode >= 2 && apiomode >= 4)) {
+ pci_write_config(scp->dev, 0x53, word53 | 0x03, 1);
+ scp->flags |= ATA_ATAPI_DMA_RO;
+ if (device == ATA_MASTER)
+ outb(scp->bmaddr + ATA_BMSTAT_PORT,
+ inb(scp->bmaddr + ATA_BMSTAT_PORT) |
+ ATA_BMSTAT_DMA_MASTER);
+ else
+ outb(scp->bmaddr + ATA_BMSTAT_PORT,
+ inb(scp->bmaddr + ATA_BMSTAT_PORT) |
+ ATA_BMSTAT_DMA_SLAVE);
+ }
+ }
+ if (udmamode >=2) {
+ int32_t word54 = pci_read_config(scp->dev, 0x54, 4);
+
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
- ATA_UDMA4, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
+ ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
if (bootverbose)
- printf("ata%d: %s: %s setting up UDMA4 mode on Promise chip\n",
+ printf("ata%d: %s: %s setting up UDMA2 mode on Aladdin chip\n",
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
(error) ? "failed" : "success");
if (error)
break;
- pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004117f3, 4);
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA66;
+ word54 |= 0x5555;
+ word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2)));
+ pci_write_config(scp->dev, 0x54, word54, 4);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2;
return 0;
+
}
-
+ else if (wdmamode >= 2 && apiomode >= 4) {
+ error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
+ ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
+ if (bootverbose)
+ printf("ata%d: %s: %s setting up WDMA2 mode on Aladdin chip\n",
+ scp->lun, (device == ATA_MASTER) ? "master" : "slave",
+ (error) ? "failed" : "success");
+ if (error)
+ break;
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2;
+ return 0;
+ }
+ break;
+
+ case 0x4d33105a: /* Promise Ultra33 / FastTrak33 controllers */
+ case 0x4d38105a: /* Promise Ultra66 / FastTrak66 controllers */
+ /* the Promise can only do DMA on ATA disks not on ATAPI devices */
+ if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
+ (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
+ break;
+
+ devno = (scp->unit << 1) + ((device == ATA_MASTER) ? 0 : 1);
if (udmamode >=2) {
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
@@ -199,7 +260,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
if (error)
break;
pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004127f3, 4);
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA33;
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2;
return 0;
}
else if (wdmamode >= 2 && apiomode >= 4) {
@@ -212,7 +273,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
if (error)
break;
pci_write_config(scp->dev, 0x60 + (devno << 2), 0x004367f3, 4);
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2;
return 0;
}
else {
@@ -223,59 +284,71 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
}
break;
- case 0x522910b9: /* AcerLabs Aladdin IV/V */
- /* the Aladdin has to be setup specially for ATAPI devices */
+ case 0x00041103: /* HighPoint HPT366 IDE controller */
+ /* punt on ATAPI devices for now */
if ((device == ATA_MASTER && scp->devices & ATA_ATAPI_MASTER) ||
- (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE)) {
- int8_t word53 = pci_read_config(scp->dev, 0x53, 1);
+ (device == ATA_SLAVE && scp->devices & ATA_ATAPI_SLAVE))
+ break;
- /* if needed set atapi fifo & dma */
- if ((udmamode >=2) || (wdmamode >= 2 && apiomode >= 4)) {
- pci_write_config(scp->dev, 0x53, word53 | 0x03, 1);
- scp->flags |= ATA_ATAPI_DMA_RO;
- if (device == ATA_MASTER)
- outb(scp->bmaddr + ATA_BMSTAT_PORT,
- inb(scp->bmaddr + ATA_BMSTAT_PORT) |
- ATA_BMSTAT_DMA_MASTER);
- else
- outb(scp->bmaddr + ATA_BMSTAT_PORT,
- inb(scp->bmaddr + ATA_BMSTAT_PORT) |
- ATA_BMSTAT_DMA_SLAVE);
- }
- else {
- pci_write_config(scp->dev, 0x53, (word53 & ~0x01) | 0x02, 1);
- }
+ devno = (device == ATA_MASTER) ? 0 : 1;
+ if (udmamode >=4 && !(pci_read_config(scp->dev, 0x5a, 1) & 0x2)) {
+ error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
+ ATA_UDMA4, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
+ if (bootverbose)
+ printf("ata%d: %s: %s setting up UDMA4 mode on HPT366 chip\n",
+ scp->lun, (device == ATA_MASTER) ? "master" : "slave",
+ (error) ? "failed" : "success");
+ if (error)
+ break;
+ hpt366_timing(scp, device, ATA_MODE_UDMA4);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA4;
+ return 0;
}
- if (udmamode >=2) {
- int32_t word54 = pci_read_config(scp->dev, 0x54, 4);
-
+ else if (udmamode >=3) {
+ error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
+ ATA_UDMA3, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
+ if (bootverbose)
+ printf("ata%d: %s: %s setting up UDMA3 mode on HPT366 chip\n",
+ scp->lun, (device == ATA_MASTER) ? "master" : "slave",
+ (error) ? "failed" : "success");
+ if (error)
+ break;
+ hpt366_timing(scp, device, ATA_MODE_UDMA3);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA3;
+ return 0;
+ }
+ else if (udmamode >=2) {
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
if (bootverbose)
- printf("ata%d: %s: %s setting up UDMA2 mode on Aladdin chip\n",
+ printf("ata%d: %s: %s setting up UDMA2 mode on HPT366 chip\n",
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
(error) ? "failed" : "success");
if (error)
break;
- word54 |= 0x5555;
- word54 |= (0x0a << (16 + (scp->unit << 3) + (device << 2)));
- pci_write_config(scp->dev, 0x54, word54, 4);
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA33;
+ hpt366_timing(scp, device, ATA_MODE_UDMA2);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2;
return 0;
-
}
else if (wdmamode >= 2 && apiomode >= 4) {
error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0,
ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_IGNORE_INTR);
if (bootverbose)
- printf("ata%d: %s: %s setting up WDMA2 mode on Aladdin chip\n",
+ printf("ata%d: %s: %s setting up WDMA2 mode on HPT366 chip\n",
scp->lun, (device == ATA_MASTER) ? "master" : "slave",
(error) ? "failed" : "success");
if (error)
break;
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
+ hpt366_timing(scp, device, ATA_MODE_WDMA2);
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2;
return 0;
}
+ else {
+ if (bootverbose)
+ printf("ata%d: %s: setting PIO mode on HPT366 chip\n",
+ scp->lun, (device == ATA_MASTER) ? "master" : "slave");
+ hpt366_timing(scp, device, ATA_MODE_PIO);
+ }
break;
default: /* unknown controller chip */
@@ -297,7 +370,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device,
(error) ? "failed" : "success");
if (error)
break;
- scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_DMA;
+ scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2;
return 0;
}
}
@@ -365,28 +438,30 @@ ata_dmasetup(struct ata_softc *scp, int32_t device,
}
void
-ata_dmastart(struct ata_softc *scp, int32_t device)
+ata_dmastart(struct ata_softc *scp)
{
#ifdef ATA_DMADEBUG
printf("ata%d: dmastart\n", scp->lun);
#endif
+ scp->flags |= ATA_DMA_ACTIVE;
outb(scp->bmaddr + ATA_BMCMD_PORT,
inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP);
}
int32_t
-ata_dmadone(struct ata_softc *scp, int32_t device)
+ata_dmadone(struct ata_softc *scp)
{
#ifdef ATA_DMADEBUG
printf("ata%d: dmadone\n", scp->lun);
#endif
outb(scp->bmaddr + ATA_BMCMD_PORT,
inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP);
+ scp->flags &= ~ATA_DMA_ACTIVE;
return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
}
int32_t
-ata_dmastatus(struct ata_softc *scp, int32_t device)
+ata_dmastatus(struct ata_softc *scp)
{
#ifdef ATA_DMADEBUG
printf("ata%d: dmastatus\n", scp->lun);
@@ -394,6 +469,46 @@ ata_dmastatus(struct ata_softc *scp, int32_t device)
return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
}
+static void
+hpt366_timing(struct ata_softc *scp, int32_t device, int32_t mode)
+{
+ u_int32_t timing;
+
+ switch (pci_read_config(scp->dev, (device == ATA_MASTER) ? 0x41 : 0x45, 1)){
+ case 0x85: /* 25Mhz */
+ switch (mode) {
+ case ATA_MODE_PIO: timing = 0xc0ca8521; break;
+ case ATA_MODE_WDMA2: timing = 0xa0ca8521; break;
+ case ATA_MODE_UDMA2:
+ case ATA_MODE_UDMA3: timing = 0x90cf8521; break;
+ case ATA_MODE_UDMA4: timing = 0x90c98521; break;
+ default: timing = 0x01208585;
+ }
+ break;
+ default:
+ case 0xa7: /* 33MHz */
+ switch (mode) {
+ case ATA_MODE_PIO: timing = 0xc0c8a731; break;
+ case ATA_MODE_WDMA2: timing = 0xa0c8a731; break;
+ case ATA_MODE_UDMA2: timing = 0x90caa731; break;
+ case ATA_MODE_UDMA3: timing = 0x90cfa731; break;
+ case ATA_MODE_UDMA4: timing = 0x90c9a731; break;
+ default: timing = 0x0120a7a7;
+ }
+ break;
+ case 0xd9: /* 40Mhz */
+ switch (mode) {
+ case ATA_MODE_PIO: timing = 0xc008d963; break;
+ case ATA_MODE_WDMA2: timing = 0xa008d943; break;
+ case ATA_MODE_UDMA2: timing = 0x900bd943; break;
+ case ATA_MODE_UDMA3: timing = 0x900ad943; break;
+ case ATA_MODE_UDMA4: timing = 0x900fd943; break;
+ default: timing = 0x0120d9d9;
+ }
+ }
+ pci_write_config(scp->dev, 0x40 + (device==ATA_MASTER ? 0 : 4), timing, 4);
+}
+
#else /* NPCI > 0 */
int32_t
@@ -411,18 +526,18 @@ ata_dmasetup(struct ata_softc *scp, int32_t device,
}
void
-ata_dmastart(struct ata_softc *scp, int32_t device)
+ata_dmastart(struct ata_softc *scp)
{
}
int32_t
-ata_dmadone(struct ata_softc *scp, int32_t device)
+ata_dmadone(struct ata_softc *scp)
{
return -1;
}
int32_t
-ata_dmastatus(struct ata_softc *scp, int32_t device)
+ata_dmastatus(struct ata_softc *scp)
{
return -1;
}
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index f600108..509bc04 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -32,6 +32,8 @@
#include "atapicd.h"
#include "atapist.h"
#include "atapifd.h"
+#include "opt_global.h"
+#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -63,6 +65,7 @@ int32_t astattach(struct atapi_softc *);
/* internal vars */
static struct intr_config_hook *atapi_attach_hook;
+MALLOC_DEFINE(M_ATAPI, "ATAPI generic", "ATAPI driver generic layer");
/* defines */
#define ATAPI_MAX_RETRIES 5
@@ -70,9 +73,9 @@ static struct intr_config_hook *atapi_attach_hook;
static __inline int
apiomode(struct atapi_params *ap)
{
- if ((ap->atavalid & 2) == 2) {
- if ((ap->apiomodes & 2) == 2) return 4;
- if ((ap->apiomodes & 1) == 1) return 3;
+ if (ap->atavalid & 2) {
+ if (ap->apiomodes & 2) return 4;
+ if (ap->apiomodes & 1) return 3;
}
return -1;
}
@@ -80,10 +83,10 @@ apiomode(struct atapi_params *ap)
static __inline int
wdmamode(struct atapi_params *ap)
{
- if ((ap->atavalid & 2) == 2) {
- if ((ap->wdmamodes & 4) == 4) return 2;
- if ((ap->wdmamodes & 2) == 2) return 1;
- if ((ap->wdmamodes & 1) == 1) return 0;
+ if (ap->atavalid & 2) {
+ if (ap->wdmamodes & 4) return 2;
+ if (ap->wdmamodes & 2) return 1;
+ if (ap->wdmamodes & 1) return 0;
}
return -1;
}
@@ -91,10 +94,10 @@ wdmamode(struct atapi_params *ap)
static __inline int
udmamode(struct atapi_params *ap)
{
- if ((ap->atavalid & 4) == 4) {
- if ((ap->udmamodes & 4) == 4) return 2;
- if ((ap->udmamodes & 2) == 2) return 1;
- if ((ap->udmamodes & 1) == 1) return 0;
+ if (ap->atavalid & 4) {
+ if (ap->udmamodes & 4) return 2;
+ if (ap->udmamodes & 2) return 1;
+ if (ap->udmamodes & 1) return 0;
}
return -1;
}
@@ -114,7 +117,7 @@ atapi_attach(void *notused)
if (atadevices[ctlr]->devices &
(dev ? ATA_ATAPI_SLAVE : ATA_ATAPI_MASTER)) {
if (!(atp = malloc(sizeof(struct atapi_softc),
- M_DEVBUF, M_NOWAIT))) {
+ M_ATAPI, M_NOWAIT))) {
printf("atapi: failed to allocate driver storage\n");
continue;
}
@@ -122,7 +125,7 @@ atapi_attach(void *notused)
atp->controller = atadevices[ctlr];
atp->unit = (dev == 0) ? ATA_MASTER : ATA_SLAVE;
if (atapi_getparam(atp)) {
- free(atp, M_DEVBUF);
+ free(atp, M_ATAPI);
continue;
}
if (bootverbose)
@@ -173,7 +176,7 @@ notfound:
ctlr, (dev == ATA_MASTER) ? "master" : "slave",
model_buf, revision_buf,
atapi_type(atp->atapi_parm->device_type));
- free(atp, M_DEVBUF);
+ free(atp, M_ATAPI);
atp = NULL;
}
/* store our softc */
@@ -201,7 +204,7 @@ atapi_getparam(struct atapi_softc *atp)
sizeof(buffer)/sizeof(int16_t));
if (atapi_wait(atp, 0))
return -1;
- if (!(atapi_parm = malloc(sizeof(struct atapi_params), M_DEVBUF, M_NOWAIT)))
+ if (!(atapi_parm = malloc(sizeof(struct atapi_params), M_ATAPI, M_NOWAIT)))
return -1;
bcopy(buffer, atapi_parm, sizeof(struct atapi_params));
if (!((atapi_parm->model[0] == 'N' && atapi_parm->model[1] == 'E') ||
@@ -215,47 +218,6 @@ atapi_getparam(struct atapi_softc *atp)
}
int32_t
-atapi_immed_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
- int32_t count, int32_t flags, int32_t timeout)
-{
- struct atapi_request *request;
- int32_t error, s;
-
- if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT)))
- return ENOMEM;
- bzero(request, sizeof(struct atapi_request));
- request->device = atp;
- request->data = data;
- request->bytecount = count;
- request->donecount = 0;
- request->flags = flags;
- request->timeout = timeout * hz;
- request->ccbsize = (atp->atapi_parm->cmdsize) ? 16 : 12;
- bcopy(ccb, request->ccb, request->ccbsize);
-
- s = splbio();
-
- TAILQ_INSERT_HEAD(&atp->controller->atapi_queue, request, chain);
-
- /* try to start controller */
- if (atp->controller->active == ATA_IDLE)
- ata_start(atp->controller);
-
- splx(s);
-
- /* wait for command to complete */
- tsleep((caddr_t)request, PRIBIO, "atpim", 0);
-
-#ifdef ATAPI_DEBUG
- printf("atapi: phew, got back from tsleep\n");
-#endif
-
- error = request->result;
- free(request, M_DEVBUF);
- return error;
-}
-
-int32_t
atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
int32_t count, int32_t flags, int32_t timeout,
atapi_callback_t callback, void *driver, struct buf *bp)
@@ -263,14 +225,13 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
struct atapi_request *request;
int32_t error, s;
- if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT)))
+ if (!(request = malloc(sizeof(struct atapi_request), M_ATAPI, M_NOWAIT)))
return ENOMEM;
bzero(request, sizeof(struct atapi_request));
request->device = atp;
request->data = data;
request->bytecount = count;
- request->donecount = 0;
request->flags = flags;
request->timeout = timeout * hz;
request->ccbsize = (atp->atapi_parm->cmdsize) ? 16 : 12;
@@ -281,18 +242,18 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
request->driver = driver;
}
+ /* append onto controller queue and try to start controller */
s = splbio();
-
- /* link onto controller queue */
TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain);
-
- /* try to start controller */
if (atp->controller->active == ATA_IDLE)
ata_start(atp->controller);
-
splx(s);
- /* wait for command to complete */
+ /* if callback used, then just return, gets called from interrupt context */
+ if (callback)
+ return 0;
+
+ /* wait for request to complete */
tsleep((caddr_t)request, PRIBIO, "atprq", 0);
#ifdef ATAPI_DEBUG
@@ -300,12 +261,36 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data,
#endif
error = request->result;
- if (request->callback) {
- (request->callback)(request);
+ switch ((error & ATAPI_SK_MASK)) {
+ case ATAPI_SK_RESERVED:
+ printf("atapi_error: %s - timeout error = %02x\n",
+ atapi_cmd2str(atp->cmd), error & ATAPI_E_MASK);
+ error = EIO;
+ break;
+
+ case ATAPI_SK_NO_SENSE:
error = 0;
+ break;
+
+ case ATAPI_SK_RECOVERED_ERROR:
+ printf("atapi_error: %s - recovered error\n", atapi_cmd2str(atp->cmd));
+ error = 0;
+ break;
+
+ case ATAPI_SK_NOT_READY:
+ atp->flags |= ATAPI_F_MEDIA_CHANGED;
+ error = EBUSY;
+ break;
+
+ case ATAPI_SK_UNIT_ATTENTION:
+ atp->flags |= ATAPI_F_MEDIA_CHANGED;
+ error = EIO;
+ break;
+
+ default: error = EIO;
}
- free(request, M_DEVBUF);
- return atapi_error(atp, error);
+ free(request, M_ATAPI);
+ return error;
}
void
@@ -319,11 +304,18 @@ atapi_transfer(struct atapi_request *request)
printf("atapi: starting %s ", atapi_cmd2str(request->ccb[0]));
atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb));
#endif
- atp->cmd = request->ccb[0];
-
/* start timeout for this command */
request->timeout_handle = timeout((timeout_t *)atapi_timeout,
request, request->timeout);
+ if (request->ccb[0] != ATAPI_REQUEST_SENSE)
+ atp->cmd = request->ccb[0];
+
+ /* flag if we can trust the DSC bit */
+ if (request->ccb[0] == ATAPI_READ || request->ccb[0] == ATAPI_READ_BIG ||
+ request->ccb[0] == ATAPI_WRITE || request->ccb[0] == ATAPI_WRITE_BIG)
+ atp->flags |= ATAPI_F_DSC_USED;
+ else
+ atp->flags &= ~ATAPI_F_DSC_USED;
/* if DMA enabled setup DMA hardware */
if ((atp->flags & ATAPI_F_DMA_ENABLED) &&
@@ -345,7 +337,7 @@ atapi_transfer(struct atapi_request *request)
ATA_IMMEDIATE);
if (atp->flags & ATAPI_F_DMA_USED)
- ata_dmastart(atp->controller, atp->unit);
+ ata_dmastart(atp->controller);
/* command interrupt device ? just return */
if (atp->atapi_parm->drqtype == ATAPI_DRQT_INTR)
@@ -357,7 +349,7 @@ atapi_transfer(struct atapi_request *request)
reason = inb(atp->controller->ioaddr + ATA_IREASON);
atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
if (((reason & (ATA_I_CMD | ATA_I_IN)) |
- (atp->controller->status&(ATA_S_DRQ|ATA_S_BSY))) == ATAPI_P_CMDOUT)
+ (atp->controller->status&(ATA_S_DRQ|ATA_S_BUSY)))==ATAPI_P_CMDOUT)
break;
DELAY(20);
}
@@ -379,8 +371,12 @@ int32_t
atapi_interrupt(struct atapi_request *request)
{
struct atapi_softc *atp = request->device;
+ int8_t **buffer = (int8_t **)&request->data;
int32_t length, reason, resid, dma_stat = 0;
+ if (request->ccb[0] == ATAPI_REQUEST_SENSE)
+ *buffer = (int8_t *)&request->sense;
+
#ifdef ATAPI_DEBUG
printf("atapi_interrupt: enter\n");
#endif
@@ -399,7 +395,7 @@ atapi_interrupt(struct atapi_request *request)
}
if (atp->flags & ATAPI_F_DMA_USED)
- dma_stat = ata_dmadone(atp->controller, atp->unit);
+ dma_stat = ata_dmadone(atp->controller);
if (atapi_wait(atp, 0) < 0) {
printf("atapi_interrupt: timeout waiting for status");
@@ -417,7 +413,6 @@ atapi_interrupt(struct atapi_request *request)
}
else {
request->result = 0;
- request->donecount = request->bytecount;
request->bytecount = 0;
}
goto op_finished;
@@ -430,7 +425,6 @@ atapi_interrupt(struct atapi_request *request)
#endif
switch (reason) {
-
case ATAPI_P_WRITE:
if (request->flags & A_READ) {
request->result = inb(atp->controller->ioaddr + ATA_ERROR);
@@ -443,23 +437,22 @@ atapi_interrupt(struct atapi_request *request)
if (request->bytecount < length) {
printf("atapi_interrupt: write data underrun %d/%d\n",
length, request->bytecount);
-#if 0
+#ifdef ATA_16BIT_ONLY
outsw(atp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data), length / sizeof(int16_t));
+ (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
#else
outsl(atp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data), length / sizeof(int32_t));
+ (void *)((uintptr_t)*buffer), length / sizeof(int32_t));
#endif
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
outw(atp->controller->ioaddr + ATA_DATA, 0);
}
else {
outsw(atp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data), length / sizeof(int16_t));
+ (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
}
request->bytecount -= length;
- request->donecount += length;
- request->data += length;
+ *buffer += length;
return ATA_OP_CONTINUES;
case ATAPI_P_READ:
@@ -474,31 +467,32 @@ atapi_interrupt(struct atapi_request *request)
if (request->bytecount < length) {
printf("atapi_interrupt: read data overrun %d/%d\n",
length, request->bytecount);
-#if 0
+#ifdef ATA_16BIT_ONLY
insw(atp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data), length / sizeof(int16_t));
+ (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
#else
insl(atp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data), length / sizeof(int32_t));
+ (void *)((uintptr_t)*buffer), length / sizeof(int32_t));
#endif
for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t))
inw(atp->controller->ioaddr + ATA_DATA);
}
else {
insw(atp->controller->ioaddr + ATA_DATA,
- (void *)((uintptr_t)request->data), length / sizeof(int16_t));
+ (void *)((uintptr_t)*buffer), length / sizeof(int16_t));
}
request->bytecount -= length;
- request->donecount += length;
- request->data += length;
+ *buffer += length;
return ATA_OP_CONTINUES;
case ATAPI_P_ABORT:
case ATAPI_P_DONE:
if (atp->controller->status & (ATA_S_ERROR | ATA_S_DWF))
request->result = inb(atp->controller->ioaddr + ATA_ERROR);
- else
- request->result = 0;
+ else
+ if (request->ccb[0] != ATAPI_REQUEST_SENSE)
+ request->result = 0;
+
#ifdef ATAPI_DEBUG
if (request->bytecount > 0) {
printf("atapi_interrupt: %s size problem, %d bytes residue\n",
@@ -513,38 +507,41 @@ atapi_interrupt(struct atapi_request *request)
op_finished:
untimeout((timeout_t *)atapi_timeout, request, request->timeout_handle);
- wakeup((caddr_t)request);
+
+ /* check for error, if valid sense key, queue a request sense cmd */
+ if ((request->result & ATAPI_SK_MASK) &&
+ request->ccb[0] != ATAPI_REQUEST_SENSE) {
+ bzero(request->ccb, request->ccbsize);
+ request->ccb[0] = ATAPI_REQUEST_SENSE;
+ request->ccb[4] = sizeof(struct atapi_reqsense);
+ request->bytecount = sizeof(struct atapi_reqsense);
+ request->flags = A_READ;
+ TAILQ_INSERT_HEAD(&atp->controller->atapi_queue, request, chain);
+ }
+ else if (request->callback) {
+ if (request->result)
+ printf("atapi: %s - %s skey=%01x asc=%02x ascq=%02x error=%02x\n",
+ atapi_cmd2str(atp->cmd), atapi_skey2str(request->sense.sense_key),
+ request->sense.sense_key, request->sense.asc, request->sense.ascq,
+ request->result & ATAPI_E_MASK);
+
+ if (!((request->callback)(request)))
+ free(request, M_ATAPI);
+ }
+ else {
+ if (request->result)
+ printf("atapi: %s - %s skey=%01x asc=%02x ascq=%02x error=%02x\n",
+ atapi_cmd2str(atp->cmd), atapi_skey2str(request->sense.sense_key),
+ request->sense.sense_key, request->sense.asc, request->sense.ascq,
+ request->result & ATAPI_E_MASK);
+ wakeup((caddr_t)request);
+ }
#ifdef ATAPI_DEBUG
printf("atapi_interrupt: error=0x%02x\n", request->result);
#endif
return ATA_OP_FINISHED;
}
-static void
-atapi_timeout(struct atapi_request *request)
-{
- struct atapi_softc *atp = request->device;
-
- printf("ata%d-%s: atapi_timeout: cmd=%s - resetting\n",
- atp->controller->lun, (atp->unit == ATA_MASTER) ? "master" : "slave",
- atapi_cmd2str(request->ccb[0]));
-
- if (request->flags & ATAPI_F_DMA_USED)
- ata_dmadone(atp->controller, atp->unit);
-
- if (request->retries < ATAPI_MAX_RETRIES) {
- /* reinject this request */
- request->retries++;
- TAILQ_INSERT_HEAD(&atp->controller->atapi_queue, request, chain);
- }
- else {
- /* retries all used up, return error */
- request->result = ATAPI_SK_RESERVED | ATAPI_E_ABRT;
- wakeup((caddr_t)request);
- }
- ata_reinit(atp->controller);
-}
-
void
atapi_reinit(struct atapi_softc *atp)
{
@@ -558,50 +555,12 @@ atapi_reinit(struct atapi_softc *atp)
}
int32_t
-atapi_error(struct atapi_softc *atp, int32_t error)
-{
- struct atapi_reqsense sense;
- int8_t cmd = atp->cmd;
-
- if (cmd == ATAPI_REQUEST_SENSE)
- return 0;
-
- switch ((error & ATAPI_SK_MASK)) {
- case ATAPI_SK_RESERVED:
- printf("atapi_error: %s - timeout error = %02x\n",
- atapi_cmd2str(cmd), error & ATAPI_E_MASK);
- return EIO;
-
- case ATAPI_SK_NO_SENSE:
- return 0;
-
- case ATAPI_SK_RECOVERED_ERROR:
- printf("atapi_error: %s - recovered error\n", atapi_cmd2str(cmd));
- return 0;
-
- case ATAPI_SK_NOT_READY:
- atp->flags |= ATAPI_F_MEDIA_CHANGED;
- return EBUSY;
-
- case ATAPI_SK_UNIT_ATTENTION:
- atp->flags |= ATAPI_F_MEDIA_CHANGED;
- return EIO;
- }
-
- atapi_request_sense(atp, &sense);
- printf("atapi_error: %s - %s skey=%01x asc=%02x ascq=%02x error=%02x\n",
- atapi_cmd2str(cmd), atapi_skey2str(sense.sense_key),
- sense.sense_key, sense.asc, sense.ascq, error & ATAPI_E_MASK);
- return EIO;
-}
-
-int32_t
atapi_test_ready(struct atapi_softc *atp)
{
int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return atapi_immed_cmd(atp, ccb, NULL, 0, 0, 30);
+ return atapi_queue_cmd(atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL);
}
int32_t
@@ -623,27 +582,44 @@ atapi_wait_ready(struct atapi_softc *atp, int32_t timeout)
}
void
-atapi_request_sense(struct atapi_softc *atp, struct atapi_reqsense *sense)
-{
- int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0, sizeof(sense),
- 0, 0, 0 ,0 ,0, 0, 0, 0, 0, 0, 0 };
-
- bzero(sense, sizeof(struct atapi_reqsense));
- atapi_immed_cmd(atp, ccb, sense, sizeof(struct atapi_reqsense),
- A_READ, 10);
-}
-
-void
atapi_dump(int8_t *label, void *data, int32_t len)
{
u_int8_t *p = data;
- printf ("atapi: %s %x", label, *p++);
+ printf ("atapi: %s %02x", label, *p++);
while (--len > 0)
printf ("-%02x", *p++);
printf ("\n");
}
+static void
+atapi_timeout(struct atapi_request *request)
+{
+ struct atapi_softc *atp = request->device;
+
+ printf("ata%d-%s: atapi_timeout: cmd=%s - resetting\n",
+ atp->controller->lun, (atp->unit == ATA_MASTER) ? "master" : "slave",
+ atapi_cmd2str(request->ccb[0]));
+#ifdef ATAPI_DEBUG
+ atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb));
+#endif
+
+ if (request->flags & ATAPI_F_DMA_USED)
+ ata_dmadone(atp->controller);
+
+ if (request->retries < ATAPI_MAX_RETRIES) {
+ /* reinject this request */
+ request->retries++;
+ TAILQ_INSERT_HEAD(&atp->controller->atapi_queue, request, chain);
+ }
+ else {
+ /* retries all used up, return error */
+ request->result = ATAPI_SK_RESERVED | ATAPI_E_ABRT;
+ wakeup((caddr_t)request);
+ }
+ ata_reinit(atp->controller);
+}
+
static int8_t *
atapi_type(int32_t type)
{
@@ -681,7 +657,7 @@ atapi_cmd2str(u_int8_t cmd)
case 0x25: return ("READ_CAPACITY");
case 0x28: return ("READ_BIG");
case 0x2a: return ("WRITE_BIG");
- case 0x34: return ("TAPE_READ_POSITION");
+ case 0x34: return ("READ_POSITION");
case 0x35: return ("SYNCHRONIZE_CACHE");
case 0x42: return ("READ_SUBCHANNEL");
case 0x43: return ("READ_TOC");
@@ -750,7 +726,8 @@ atapi_wait(struct atapi_softc *atp, u_int8_t mask)
DELAY(1);
atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS);
}
- if (!(atp->controller->status & ATA_S_BSY) && (atp->controller->status & ATA_S_DRDY))
+ if (!(atp->controller->status & ATA_S_BUSY) &&
+ (atp->controller->status & ATA_S_READY))
break;
DELAY (10);
}
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index 490401b..29cc3ce 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -205,26 +205,26 @@ struct atapi_params {
/* ATAPI request sense structure */
struct atapi_reqsense {
- u_int8_t error_code :7; /* current or deferred errors */
- u_int8_t valid :1; /* follows ATAPI spec */
- u_int8_t segment; /* Segment number */
- u_int8_t sense_key :4; /* sense key */
- u_int8_t reserved2_4 :1; /* reserved */
- u_int8_t ili :1; /* incorrect length indicator */
- u_int8_t eom :1; /* end of medium */
- u_int8_t filemark :1; /* filemark */
- /* cmd information */
+ u_int8_t error_code :7; /* current or deferred errors */
+ u_int8_t valid :1; /* follows ATAPI spec */
+ u_int8_t segment; /* Segment number */
+ u_int8_t sense_key :4; /* sense key */
+ u_int8_t reserved2_4 :1; /* reserved */
+ u_int8_t ili :1; /* incorrect length indicator */
+ u_int8_t eom :1; /* end of medium */
+ u_int8_t filemark :1; /* filemark */
+ /* cmd information */
u_int32_t cmd_info __attribute__((packed));
- u_int8_t sense_length; /* additional sense length (n-7) */
- /* additional cmd specific info */
+ u_int8_t sense_length; /* additional sense len (n-7) */
+ /* additional cmd spec info */
u_int32_t cmd_specific_info __attribute__((packed));
- u_int8_t asc; /* additional sense code */
- u_int8_t ascq; /* additional sense code qualifier */
- u_int8_t replaceable_unit_code; /* field replaceable unit code */
- u_int8_t sk_specific1 :7; /* sense key specific */
- u_int8_t sksv :1; /* sense key specific info valid */
- u_int8_t sk_specific2; /* sense key specific */
- u_int8_t sk_specific3; /* sense key specific */
+ u_int8_t asc; /* additional sense code */
+ u_int8_t ascq; /* additional sense code qual */
+ u_int8_t replaceable_unit_code; /* replaceable unit code */
+ u_int8_t sk_specific1 :7; /* sense key specific */
+ u_int8_t sksv :1; /* sense key specific info OK */
+ u_int8_t sk_specific2; /* sense key specific */
+ u_int8_t sk_specific3; /* sense key specific */
};
struct atapi_softc {
@@ -233,14 +233,14 @@ struct atapi_softc {
int32_t unit; /* ATA_MASTER or ATA_SLAVE */
int8_t cmd; /* last cmd executed */
u_int32_t flags; /* drive flags */
-#define ATAPI_F_MEDIA_CHANGED 0x0001
-#define ATAPI_F_DMA_ENABLED 0x0002
-#define ATAPI_F_DMA_USED 0x0004
-#define ATAPI_F_DRQT_CMD 0x0008
+#define ATAPI_F_DMA_ENABLED 0x0001
+#define ATAPI_F_DMA_USED 0x0002
+#define ATAPI_F_DSC_USED 0x0004
+#define ATAPI_F_MEDIA_CHANGED 0x0008
};
-typedef void atapi_callback_t(struct atapi_request *);
+typedef int32_t atapi_callback_t(struct atapi_request *);
struct atapi_request {
struct atapi_softc *device; /* ptr to parent device */
@@ -248,11 +248,11 @@ struct atapi_request {
u_int8_t ccb[16]; /* command control block */
int32_t ccbsize; /* size of ccb (12 | 16) */
u_int32_t bytecount; /* bytes to transfer */
- u_int32_t donecount; /* bytes transferred */
int32_t timeout; /* timeout for this cmd */
struct callout_handle timeout_handle; /* handle for untimeout */
int32_t retries; /* retry count */
int32_t result; /* result of this cmd */
+ struct atapi_reqsense sense; /* sense data if error */
int32_t flags;
#define A_READ 0x0001
@@ -264,10 +264,8 @@ struct atapi_request {
void atapi_transfer(struct atapi_request *);
int32_t atapi_interrupt(struct atapi_request *);
-int32_t atapi_immed_cmd(struct atapi_softc *, int8_t *, void *, int32_t, int32_t, int32_t);
int32_t atapi_queue_cmd(struct atapi_softc *, int8_t [], void *, int32_t, int32_t, int32_t, atapi_callback_t, void *, struct buf *);
void atapi_reinit(struct atapi_softc *);
-int32_t atapi_error(struct atapi_softc *, int32_t);
int32_t atapi_test_ready(struct atapi_softc *);
int32_t atapi_wait_ready(struct atapi_softc *, int32_t);
void atapi_request_sense(struct atapi_softc *, struct atapi_reqsense *);
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 5287f32..debb3c0 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -72,9 +72,6 @@ static struct cdevsw acd_cdevsw = {
/* bmaj */ 31
};
-/* misc defines */
-#define NUNIT 16 /* max # of devices */
-
/* prototypes */
int32_t acdattach(struct atapi_softc *);
static struct acd_softc *acd_init_lun(struct atapi_softc *, int32_t, struct devstat *);
@@ -82,7 +79,7 @@ static void acd_describe(struct acd_softc *);
static void lba2msf(int32_t, u_int8_t *, u_int8_t *, u_int8_t *);
static int32_t msf2lba(u_int8_t, u_int8_t, u_int8_t);
static void acd_start(struct acd_softc *);
-static void acd_done(struct atapi_request *);
+static int32_t acd_done(struct atapi_request *);
static int32_t acd_read_toc(struct acd_softc *);
static int32_t acd_setchan(struct acd_softc *, u_int8_t, u_int8_t, u_int8_t, u_int8_t);
static void acd_select_slot(struct acd_softc *);
@@ -101,7 +98,7 @@ static int32_t acd_mode_select(struct acd_softc *, void *, int32_t);
static int32_t acd_set_speed(struct acd_softc *cdp, int32_t);
/* internal vars */
-static int32_t acdnlun = 0; /* number of configured drives */
+MALLOC_DEFINE(M_ACD, "ACD driver", "ATAPI CD driver buffers");
int
acdattach(struct atapi_softc *atp)
@@ -109,16 +106,13 @@ acdattach(struct atapi_softc *atp)
struct acd_softc *cdp;
struct changer *chp;
int32_t error, count;
- static int once;
+ static int32_t acd_cdev_done = 0, acdnlun = 0;
- if (!once) {
+ if (!acd_cdev_done) {
cdevsw_add(&acd_cdevsw);
- once++;
- }
- if (acdnlun >= NUNIT) {
- printf("acd: too many units\n");
- return -1;
+ acd_cdev_done++;
}
+
if ((cdp = acd_init_lun(atp, acdnlun, NULL)) == NULL) {
printf("acd: out of memory\n");
return -1;
@@ -131,7 +125,7 @@ acdattach(struct atapi_softc *atp)
break;
}
if (error) {
- free(cdp, M_TEMP);
+ free(cdp, M_ACD);
return -1;
}
cdp->cap.max_read_speed = ntohs(cdp->cap.max_read_speed);
@@ -149,14 +143,14 @@ acdattach(struct atapi_softc *atp)
sizeof(struct changer)>>8, sizeof(struct changer),
0, 0, 0, 0, 0, 0 };
- chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT);
+ chp = malloc(sizeof(struct changer), M_ACD, M_NOWAIT);
if (chp == NULL) {
printf("acd: out of memory\n");
return 0;
}
bzero(chp, sizeof(struct changer));
- error = atapi_immed_cmd(cdp->atp, ccb, chp, sizeof(struct changer),
- A_READ, 60);
+ error = atapi_queue_cmd(cdp->atp, ccb, chp, sizeof(struct changer),
+ A_READ, 60, NULL, NULL, NULL);
#ifdef ACD_DEBUG
printf("error=%02x curr=%02x slots=%d len=%d\n",
error, chp->current_slot, chp->slots, htons(chp->table_length));
@@ -168,7 +162,7 @@ acdattach(struct atapi_softc *atp)
int8_t string[16];
chp->table_length = htons(chp->table_length);
- for (count = 0; count < chp->slots && acdnlun < NUNIT; count++) {
+ for (count = 0; count < chp->slots; count++) {
if (count > 0) {
tmpcdp = acd_init_lun(atp, acdnlun, cdp->stats);
if (!tmpcdp) {
@@ -182,10 +176,6 @@ acdattach(struct atapi_softc *atp)
(chp->slot[count].present ? "CD present" : "empty"));
acdnlun++;
}
- if (acdnlun >= NUNIT) {
- printf("acd: too many units\n");
- return 0;
- }
sprintf(string, "acd%d-", cdp->lun);
devstat_add_entry(cdp->stats, string, tmpcdp->lun, DEV_BSIZE,
DEVSTAT_NO_ORDERED_TAGS,
@@ -209,7 +199,7 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats)
struct acd_softc *acd;
dev_t dev;
- if (!(acd = malloc(sizeof(struct acd_softc), M_TEMP, M_NOWAIT)))
+ if (!(acd = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT)))
return NULL;
bzero(acd, sizeof(struct acd_softc));
bufq_init(&acd->buf_queue);
@@ -223,7 +213,7 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats)
acd->atp->flags |= ATAPI_F_MEDIA_CHANGED;
if (stats == NULL) {
if (!(acd->stats = malloc(sizeof(struct devstat),
- M_TEMP, M_NOWAIT)))
+ M_ACD, M_NOWAIT)))
return NULL;
bzero(acd->stats, sizeof(struct devstat));
}
@@ -232,15 +222,19 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats)
dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0),
UID_ROOT, GID_OPERATOR, 0644, "racd%da", lun);
dev->si_drv1 = acd;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
UID_ROOT, GID_OPERATOR, 0644, "racd%dc", lun);
dev->si_drv1 = acd;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, 0),
UID_ROOT, GID_OPERATOR, 0644, "acd%da", lun);
dev->si_drv1 = acd;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
dev = make_dev(&acd_cdevsw, dkmakeminor(lun, 0, RAW_PART),
UID_ROOT, GID_OPERATOR, 0644, "acd%dc", lun);
dev->si_drv1 = acd;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
return acd;
}
@@ -434,7 +428,6 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
}
dev->si_bsize_phys = 2048; /* XXX SOS */
- dev->si_iosize_max = 254 * DEV_BSIZE;
if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) {
acd_prevent_allow(cdp, 1);
cdp->flags |= F_LOCKED;
@@ -525,7 +518,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
error = suser(p);
if (error)
break;
- error = atapi_error(cdp->atp, atapi_test_ready(cdp->atp));
+ error = atapi_test_ready(cdp->atp);
break;
case CDIOCEJECT:
@@ -665,9 +658,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
break;
}
- if ((error = atapi_immed_cmd(cdp->atp, ccb, &cdp->subchan,
- sizeof(cdp->subchan), A_READ, 10))) {
- error = atapi_error(cdp->atp, error);
+ if ((error = atapi_queue_cmd(cdp->atp, ccb, &cdp->subchan,
+ sizeof(cdp->subchan), A_READ, 10,
+ NULL, NULL, NULL))) {
break;
}
abslba = cdp->subchan.abslba;
@@ -702,8 +695,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
args->end_m, args->end_s, args->end_f,
0, 0, 0, 0, 0, 0, 0 };
- error = atapi_error(cdp->atp,
- atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10));
+ error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10,
+ NULL, NULL, NULL);
break;
}
@@ -716,8 +709,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
args->len>>8, args->len,
0, 0, 0, 0, 0, 0 };
- error = atapi_error(cdp->atp,
- atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10));
+ error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10,
+ NULL, NULL, NULL);
break;
}
@@ -757,8 +750,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
ccb[8] = len>>8;
ccb[9] = len;
- error = atapi_error(cdp->atp,
- atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10));
+ error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10,
+ NULL, NULL, NULL);
break;
}
@@ -793,8 +786,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
#ifndef CD_BUFFER_BLOCKS
#define CD_BUFFER_BLOCKS 13
#endif
- if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352,
- M_TEMP,M_NOWAIT))) {
+ if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, M_ACD, M_NOWAIT))){
error = ENOMEM;
break;
}
@@ -825,7 +817,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
frames -= blocks;
lba += blocks;
}
- free(buffer, M_TEMP);
+ free(buffer, M_ACD);
if (args->address_format == CD_LBA_FORMAT)
args->address.lba = lba;
else if (args->address_format == CD_MSF_FORMAT)
@@ -1095,28 +1087,15 @@ acd_start(struct acd_softc *cdp)
(bp->b_flags&B_READ)?A_READ : 0, 30, acd_done, cdp, bp);
}
-static void
+static int32_t
acd_done(struct atapi_request *request)
{
struct buf *bp = request->bp;
struct acd_softc *cdp = request->driver;
int32_t error = request->result;
- if ((error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION) {
- struct toc buf = cdp->toc;
-
- acd_read_toc(cdp);
- if (bcmp(&buf, &cdp->toc, sizeof(struct toc)))
- cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
- else {
- error = atapi_immed_cmd(cdp->atp, request->ccb, request->data,
- request->bytecount, request->flags, 30);
- if (cdp->flags & F_LOCKED)
- acd_prevent_allow(cdp, 1);
- }
- }
if (error) {
- bp->b_error = atapi_error(request->device, error);
+ bp->b_error = error;
bp->b_flags |= B_ERROR;
}
else {
@@ -1127,12 +1106,13 @@ acd_done(struct atapi_request *request)
devstat_end_transaction_buf(cdp->stats, bp);
biodone(bp);
acd_start(cdp);
+ return 0;
}
static int32_t
acd_read_toc(struct acd_softc *cdp)
{
- int32_t error, ntracks, len;
+ int32_t ntracks, len;
int8_t ccb[16];
bzero(&cdp->toc, sizeof(cdp->toc));
@@ -1141,15 +1121,9 @@ acd_read_toc(struct acd_softc *cdp)
acd_select_slot(cdp);
- error = atapi_test_ready(cdp->atp);
- if ((error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION) {
+ atapi_test_ready(cdp->atp);
+ if (cdp->atp->flags & ATAPI_F_MEDIA_CHANGED)
cdp->flags &= ~(F_WRITTEN | F_TRACK_PREP | F_TRACK_PREPED);
- cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
- error = atapi_test_ready(cdp->atp);
- }
-
- if (error)
- return atapi_error(cdp->atp, error);
cdp->atp->flags &= ~ATAPI_F_MEDIA_CHANGED;
@@ -1157,7 +1131,8 @@ acd_read_toc(struct acd_softc *cdp)
ccb[0] = ATAPI_READ_TOC;
ccb[7] = len>>8;
ccb[8] = len;
- if (atapi_immed_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30)) {
+ if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30,
+ NULL, NULL, NULL)) {
bzero(&cdp->toc, sizeof(cdp->toc));
return 0;
}
@@ -1172,7 +1147,8 @@ acd_read_toc(struct acd_softc *cdp)
ccb[0] = ATAPI_READ_TOC;
ccb[7] = len>>8;
ccb[8] = len;
- if (atapi_immed_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30)) {
+ if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30,
+ NULL, NULL, NULL)) {
bzero(&cdp->toc, sizeof(cdp->toc));
return 0;
}
@@ -1181,8 +1157,8 @@ acd_read_toc(struct acd_softc *cdp)
bzero(ccb, sizeof(ccb));
ccb[0] = ATAPI_READ_CAPACITY;
- if (atapi_immed_cmd(cdp->atp, ccb, &cdp->info, sizeof(cdp->info),
- A_READ, 30))
+ if (atapi_queue_cmd(cdp->atp, ccb, &cdp->info, sizeof(cdp->info),
+ A_READ, 30, NULL, NULL, NULL))
bzero(&cdp->info, sizeof(cdp->info));
cdp->info.volsize = ntohl(cdp->info.volsize);
@@ -1240,7 +1216,7 @@ acd_select_slot(struct acd_softc *cdp)
ccb[1] = 0x01;
ccb[4] = 2;
ccb[8] = cdp->changer_info->current_slot;
- atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10);
+ atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
atapi_wait_ready(cdp->atp, 30);
/* load the wanted slot */
@@ -1248,7 +1224,7 @@ acd_select_slot(struct acd_softc *cdp)
ccb[1] = 0x01;
ccb[4] = 3;
ccb[8] = cdp->slot;
- atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10);
+ atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
atapi_wait_ready(cdp->atp, 30);
cdp->changer_info->current_slot = cdp->slot;
@@ -1272,10 +1248,10 @@ acd_close_disk(struct acd_softc *cdp)
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(cdp->atp, error);
- return atapi_error(cdp->atp, atapi_wait_ready(cdp->atp, 10*60));
+ return error;
+ return atapi_wait_ready(cdp->atp, 10*60);
}
static int32_t
@@ -1366,19 +1342,19 @@ acd_close_track(struct acd_softc *cdp)
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(cdp->atp, ccb1, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(cdp->atp, ccb1, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(cdp->atp, error);
+ return error;
- error = atapi_error(cdp->atp, atapi_wait_ready(cdp->atp, 5*60));
+ error = atapi_wait_ready(cdp->atp, 5*60);
if (error)
- return atapi_error(cdp->atp, error);
+ return error;
- error = atapi_immed_cmd(cdp->atp, ccb2, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(cdp->atp, ccb2, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(cdp->atp, error);
+ return error;
- return atapi_error(cdp->atp, atapi_wait_ready(cdp->atp, 5*60));
+ return atapi_wait_ready(cdp->atp, 5*60);
}
static int32_t
@@ -1392,9 +1368,9 @@ acd_read_track_info(struct acd_softc *cdp,
0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- if ((error = atapi_immed_cmd(cdp->atp, ccb, info, sizeof(*info),
- A_READ, 30)))
- return atapi_error(cdp->atp, error);
+ if ((error = atapi_queue_cmd(cdp->atp, ccb, info, sizeof(*info),
+ A_READ, 30, NULL, NULL, NULL)))
+ return error;
info->track_start_addr = ntohl(info->track_start_addr);
info->next_writeable_addr = ntohl(info->next_writeable_addr);
info->free_blocks = ntohl(info->free_blocks);
@@ -1437,10 +1413,10 @@ acd_blank(struct acd_softc *cdp)
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0, 60*60);
+ error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL);
cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED);
cdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
- return atapi_error(cdp->atp, error);
+ return error;
}
static int32_t
@@ -1449,7 +1425,7 @@ acd_prevent_allow(struct acd_softc *cdp, int32_t 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_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30));
+ return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL);
}
static int32_t
@@ -1458,7 +1434,7 @@ acd_start_stop(struct acd_softc *cdp, int32_t start)
int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30));
+ return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL);
}
static int32_t
@@ -1467,7 +1443,7 @@ acd_pause_resume(struct acd_softc *cdp, int32_t pause)
int8_t ccb[16] = { ATAPI_PAUSE, 0, 0, 0, 0, 0, 0, 0, pause,
0, 0, 0, 0, 0, 0, 0 };
- return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30));
+ return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL);
}
static int32_t
@@ -1478,11 +1454,12 @@ acd_mode_sense(struct acd_softc *cdp, u_int8_t page,
pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ, 10);
+ error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ, 10,
+ NULL, NULL, NULL);
#ifdef ACD_DEBUG
atapi_dump("acd: mode sense ", pagebuf, pagesize);
#endif
- return atapi_error(cdp->atp, error);
+ return error;
}
static int32_t
@@ -1495,8 +1472,8 @@ acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize)
printf("acd: modeselect pagesize=%d\n", pagesize);
atapi_dump("acd: mode select ", pagebuf, pagesize);
#endif
- return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb,
- pagebuf, pagesize, 0, 30));
+ return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0, 30,
+ NULL, NULL, NULL);
}
static int32_t
@@ -1505,6 +1482,5 @@ acd_set_speed(struct acd_softc *cdp, int32_t speed)
int8_t ccb[16] = { ATAPI_SET_SPEED, 0, 0xff, 0xff, speed>>8, speed,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- return atapi_error(cdp->atp, atapi_immed_cmd(cdp->atp, ccb, NULL, 0, 0,30));
+ return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL);
}
-
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 662dc86..01dc368 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -77,22 +77,23 @@ int32_t afdattach(struct atapi_softc *);
static int32_t afd_sense(struct afd_softc *);
static void afd_describe(struct afd_softc *);
static void afd_start(struct afd_softc *);
-static void afd_partial_done(struct atapi_request *);
-static void afd_done(struct atapi_request *);
+static int32_t afd_partial_done(struct atapi_request *);
+static int32_t afd_done(struct atapi_request *);
static int32_t afd_eject(struct afd_softc *, int32_t);
static int32_t afd_start_stop(struct afd_softc *, int32_t);
static int32_t afd_prevent_allow(struct afd_softc *, int32_t);
/* internal vars */
-static int32_t afdnlun = 0; /* number of config'd drives */
+MALLOC_DEFINE(M_AFD, "AFD driver", "ATAPI floppy driver buffers");
int32_t
afdattach(struct atapi_softc *atp)
{
struct afd_softc *fdp;
dev_t dev;
+ static int32_t afdnlun = 0;
- fdp = malloc(sizeof(struct afd_softc), M_TEMP, M_NOWAIT);
+ fdp = malloc(sizeof(struct afd_softc), M_AFD, M_NOWAIT);
if (!fdp) {
printf("afd: out of memory\n");
return -1;
@@ -104,7 +105,7 @@ afdattach(struct atapi_softc *atp)
fdp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
if (afd_sense(fdp)) {
- free(fdp, M_TEMP);
+ free(fdp, M_AFD);
return -1;
}
@@ -118,6 +119,7 @@ afdattach(struct atapi_softc *atp)
0x174);
dev = disk_create(fdp->lun, &fdp->disk, 0, &afd_cdevsw, &afddisk_cdevsw);
dev->si_drv1 = fdp;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
return 0;
}
@@ -133,11 +135,9 @@ afd_sense(struct afd_softc *fdp)
bzero(buffer, sizeof(buffer));
/* get drive capabilities, some drives needs this repeated */
for (count = 0 ; count < 5 ; count++) {
- if (!(error = atapi_immed_cmd(fdp->atp, ccb, buffer, sizeof(buffer),
- A_READ, 30))) {
- error = atapi_error(fdp->atp, error);
+ if (!(error = atapi_queue_cmd(fdp->atp, ccb, buffer, sizeof(buffer),
+ A_READ, 30, NULL, NULL, NULL)))
break;
- }
}
#ifdef AFD_DEBUG
atapi_dump("afd: sense", buffer, sizeof(buffer));
@@ -205,8 +205,6 @@ afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
struct afd_softc *fdp = dev->si_drv1;
struct disklabel *label;
- dev->si_iosize_max = 254 * DEV_BSIZE;
-
fdp->atp->flags &= ~ATAPI_F_MEDIA_CHANGED;
afd_prevent_allow(fdp, 1);
if (afd_sense(fdp))
@@ -331,26 +329,27 @@ afd_start(struct afd_softc *fdp)
(bp->b_flags & B_READ) ? A_READ : 0, 30, afd_done, fdp, bp);
}
-static void
+static int32_t
afd_partial_done(struct atapi_request *request)
{
struct buf *bp = request->bp;
if (request->result) {
- bp->b_error = atapi_error(request->device, request->result);
+ bp->b_error = request->result;
bp->b_flags |= B_ERROR;
}
bp->b_resid += request->bytecount;
+ return 0;
}
-static void
+static int32_t
afd_done(struct atapi_request *request)
{
struct buf *bp = request->bp;
struct afd_softc *fdp = request->driver;
if (request->result || (bp->b_flags & B_ERROR)) {
- bp->b_error = atapi_error(request->device, request->result);
+ bp->b_error = request->result;
bp->b_flags |= B_ERROR;
}
else
@@ -358,6 +357,7 @@ afd_done(struct atapi_request *request)
devstat_end_transaction_buf(&fdp->stats, bp);
biodone(bp);
afd_start(fdp);
+ return 0;
}
static int32_t
@@ -389,10 +389,10 @@ afd_start_stop(struct afd_softc *fdp, int32_t start)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(fdp->atp, ccb, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(fdp->atp, error);
- return atapi_error(fdp->atp, atapi_wait_ready(fdp->atp, 30));
+ return error;
+ return atapi_wait_ready(fdp->atp, 30);
}
static int32_t
@@ -401,5 +401,5 @@ afd_prevent_allow(struct afd_softc *fdp, int32_t 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_error(fdp->atp, atapi_immed_cmd(fdp->atp, ccb, NULL, 0, 0,30));
+ return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0,30, NULL, NULL, NULL);
}
diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h
index a1d30a4..7ae6d85 100644
--- a/sys/dev/ata/atapi-fd.h
+++ b/sys/dev/ata/atapi-fd.h
@@ -46,7 +46,7 @@ struct afd_header {
#define MFD_FMT_ERROR 0x72
u_int8_t reserved0 :7;
- u_int8_t wp :1; /* write protect */
+ u_int8_t wp :1; /* write protect */
u_int8_t unused[4];
};
@@ -56,17 +56,17 @@ struct afd_cappage {
#define ATAPI_REWRITEABLE_CAP_PAGE 0x05
u_int8_t reserved1_6 :1;
- u_int8_t ps :1; /* page save supported */
- u_int8_t page_length; /* page length */
- u_int16_t transfer_rate; /* in kilobits per second */
- u_int8_t heads; /* number of heads */
- u_int8_t sectors; /* number of sectors per track */
- u_int16_t sector_size; /* number of bytes per sector */
- u_int16_t cylinders; /* number of cylinders */
+ u_int8_t ps :1; /* page save supported */
+ u_int8_t page_length; /* page length */
+ u_int16_t transfer_rate; /* in kilobits per second */
+ u_int8_t heads; /* number of heads */
+ u_int8_t sectors; /* number of sectors pr track */
+ u_int16_t sector_size; /* number of bytes per sector */
+ u_int16_t cylinders; /* number of cylinders */
u_int8_t reserved10[10];
- u_int8_t motor_delay; /* motor off delay */
+ u_int8_t motor_delay; /* motor off delay */
u_int8_t reserved21[7];
- u_int16_t rpm; /* rotations per minute */
+ u_int16_t rpm; /* rotations per minute */
u_int8_t reserved30[2];
};
diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c
index f2f20de..94e60bf 100644
--- a/sys/dev/ata/atapi-tape.c
+++ b/sys/dev/ata/atapi-tape.c
@@ -69,15 +69,12 @@ static struct cdevsw ast_cdevsw = {
/* bmaj */ -1
};
-/* misc defines */
-#define NUNIT 8
-
/* prototypes */
int32_t astattach(struct atapi_softc *);
static int32_t ast_sense(struct ast_softc *);
static void ast_describe(struct ast_softc *);
static void ast_start(struct ast_softc *);
-static void ast_done(struct atapi_request *);
+static int32_t ast_done(struct atapi_request *);
static int32_t ast_mode_sense(struct ast_softc *, u_int8_t, void *, int32_t);
static int32_t ast_mode_select(struct ast_softc *, void *, int32_t);
static int32_t ast_write_filemark(struct ast_softc *, u_int8_t);
@@ -90,10 +87,8 @@ static int32_t ast_rewind(struct ast_softc *);
static int32_t ast_erase(struct ast_softc *);
/* internal vars */
-static int32_t astnlun = 0; /* number of config'd drives */
-static int ast_cdev_done = 0;
static u_int64_t ast_total = 0;
-static int32_t ast_buffermode = 0;
+MALLOC_DEFINE(M_AST, "AST driver", "ATAPI tape driver buffers");
int32_t
astattach(struct atapi_softc *atp)
@@ -101,16 +96,13 @@ astattach(struct atapi_softc *atp)
struct ast_softc *stp;
struct ast_readposition position;
dev_t dev;
+ static int32_t ast_cdev_done = 0, astnlun = 0;
if (!ast_cdev_done) {
cdevsw_add(&ast_cdevsw);
ast_cdev_done = 1;
}
- if (astnlun >= NUNIT) {
- printf("ast: too many units\n");
- return -1;
- }
- stp = malloc(sizeof(struct ast_softc), M_TEMP, M_NOWAIT);
+ stp = malloc(sizeof(struct ast_softc), M_AST, M_NOWAIT);
if (!stp) {
printf("ast: out of memory\n");
return -1;
@@ -118,10 +110,10 @@ astattach(struct atapi_softc *atp)
bzero(stp, sizeof(struct ast_softc));
bufq_init(&stp->buf_queue);
stp->atp = atp;
- stp->lun = astnlun;
+ stp->lun = astnlun++;
stp->atp->flags |= ATAPI_F_MEDIA_CHANGED;
if (ast_sense(stp)) {
- free(stp, M_TEMP);
+ free(stp, M_AST);
return -1;
}
ast_describe(stp);
@@ -144,8 +136,8 @@ astattach(struct atapi_softc *atp)
&identify, sizeof(identify));
strncpy(identify.ident, "FBSD", 4);
ast_mode_select(stp, &identify, sizeof(identify));
+ ast_read_position(stp, 0, &position);
}
- ast_read_position(stp, 0, &position);
devstat_add_entry(&stp->stats, "ast", stp->lun, DEV_BSIZE,
DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE,
@@ -153,6 +145,11 @@ astattach(struct atapi_softc *atp)
dev = make_dev(&ast_cdevsw, dkmakeminor(stp->lun, 0, 0),
UID_ROOT, GID_OPERATOR, 0640, "rast%d", stp->lun);
dev->si_drv1 = stp;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
+ dev = make_dev(&ast_cdevsw, dkmakeminor(stp->lun, 0, 1),
+ UID_ROOT, GID_OPERATOR, 0640, "nrast%d", stp->lun);
+ dev->si_drv1 = stp;
+ dev->si_iosize_max = 252 * DEV_BSIZE;
return 0;
}
@@ -241,7 +238,6 @@ astopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p)
if (ast_sense(stp))
printf("ast%d: sense media type failed\n", stp->lun);
- dev->si_iosize_max = 254 * DEV_BSIZE;
stp->flags &= ~(F_DATA_WRITTEN | F_FM_WRITTEN);
stp->flags |= F_OPEN;
stp->atp->flags &= ~ATAPI_F_MEDIA_CHANGED;
@@ -365,7 +361,7 @@ astioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
if ((error = ast_read_position(stp, 0, &position)))
break;
- (u_int32_t *)addr = position.tape;
+ *(u_int32_t *)addr = position.tape;
break;
}
case MTIOCRDHPOS:
@@ -374,7 +370,7 @@ astioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
if ((error = ast_read_position(stp, 1, &position)))
break;
- (u_int32_t *)addr = position.tape;
+ *(u_int32_t *)addr = position.tape;
break;
}
case MTIOCSLOCATE:
@@ -447,17 +443,13 @@ ast_start(struct ast_softc *stp)
if (bp->b_flags & B_READ) {
ccb[0] = ATAPI_READ;
- if (!ast_buffermode) {
- atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 10);
- ast_buffermode = 1;
- }
+ if (!(stp->flags & ATAPI_F_DSC_USED))
+ atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 2*60, NULL, NULL, NULL);
}
else {
ccb[0] = ATAPI_WRITE;
- if (!ast_buffermode) {
- atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 10);
- ast_buffermode = 1;
- }
+ if (!(stp->flags & ATAPI_F_DSC_USED))
+ atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 2*60, NULL, NULL, NULL);
}
bufq_remove(&stp->buf_queue, bp);
@@ -471,10 +463,10 @@ ast_start(struct ast_softc *stp)
devstat_start_transaction(&stp->stats);
atapi_queue_cmd(stp->atp, ccb, bp->b_data, bp->b_bcount,
- (bp->b_flags & B_READ) ? A_READ : 0, 30, ast_done, stp, bp);
+ (bp->b_flags & B_READ) ? A_READ : 0, 60, ast_done, stp, bp);
}
-static void
+static int32_t
ast_done(struct atapi_request *request)
{
struct buf *bp = request->bp;
@@ -482,18 +474,19 @@ ast_done(struct atapi_request *request)
int32_t error = request->result;
if (error) {
- bp->b_error = atapi_error(request->device, error);
+ bp->b_error = error;
bp->b_flags |= B_ERROR;
}
else {
if (!(bp->b_flags & B_READ))
stp->flags |= F_DATA_WRITTEN;
bp->b_resid = request->bytecount;
- ast_total += request->donecount;
+ ast_total += (bp->b_bcount - bp->b_resid);
}
devstat_end_transaction_buf(&stp->stats, bp);
biodone(bp);
ast_start(stp);
+ return 0;
}
static int32_t
@@ -504,11 +497,12 @@ ast_mode_sense(struct ast_softc *stp, u_int8_t page,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(stp->atp, ccb, pagebuf, pagesize, A_READ, 10);
+ error = atapi_queue_cmd(stp->atp, ccb, pagebuf, pagesize, A_READ, 10,
+ NULL, NULL, NULL);
#ifdef AST_DEBUG
atapi_dump("ast: mode sense ", pagebuf, pagesize);
#endif
- return atapi_error(stp->atp, error);
+ return error;
}
static int32_t
@@ -521,7 +515,8 @@ ast_mode_select(struct ast_softc *stp, void *pagebuf, int32_t pagesize)
printf("ast: modeselect pagesize=%d\n", pagesize);
atapi_dump("ast: mode select ", pagebuf, pagesize);
#endif
- return atapi_immed_cmd(stp->atp, ccb, pagebuf, pagesize, 0, 10);
+ return atapi_queue_cmd(stp->atp, ccb, pagebuf, pagesize, 0, 10,
+ NULL, NULL, NULL);
}
static int32_t
@@ -531,7 +526,6 @@ ast_write_filemark(struct ast_softc *stp, u_int8_t function)
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- ast_buffermode = 0;
if (stp->flags & F_ONSTREAM)
ccb[4] = 0x00; /* only flush buffers supported */
else {
@@ -542,10 +536,10 @@ ast_write_filemark(struct ast_softc *stp, u_int8_t function)
stp->flags |= F_FM_WRITTEN;
}
}
- error = atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(stp->atp, error);
- return atapi_error(stp->atp, atapi_wait_ready(stp->atp, 5*60));
+ return error;
+ return atapi_wait_ready(stp->atp, 5*60);
}
static int32_t
@@ -556,14 +550,17 @@ ast_read_position(struct ast_softc *stp, int32_t hard,
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- error = atapi_immed_cmd(stp->atp, ccb, position,
- sizeof(struct ast_readposition), A_READ, 10);
+ error = atapi_queue_cmd(stp->atp, ccb, position,
+ sizeof(struct ast_readposition), A_READ, 10,
+ NULL, NULL, NULL);
+ position->tape = ntohl(position->tape);
+ position->host = ntohl(position->host);
#ifdef AST_DEBUG
printf("ast%d: BOP=%d EOP=%d host=%ld tape=%ld in buf=%d error=%02x\n",
stp->lun, position->bop, position->eop, ntohl(position->host),
ntohl(position->tape), position->blks_in_buf, error);
#endif
- return atapi_error(stp->atp, error);
+ return error;
}
static int32_t
@@ -572,9 +569,7 @@ ast_space(struct ast_softc *stp, u_int8_t function, u_int32_t count)
int8_t ccb[16] = { ATAPI_SPACE, function, count>>16, count>>8, count,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- ast_buffermode = 0;
- return atapi_error(stp->atp,
- atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 60*60));
+ return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL);
}
static int32_t
@@ -585,11 +580,10 @@ ast_locate(struct ast_softc *stp, int32_t hard, int32_t pos)
0, 0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- ast_buffermode = 0;
- error = atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(stp->atp, error);
- return atapi_error(stp->atp, atapi_wait_ready(stp->atp, 60*60));
+ return error;
+ return atapi_wait_ready(stp->atp, 60*60);
}
static int32_t
@@ -598,7 +592,7 @@ ast_prevent_allow(struct ast_softc *stp, int32_t 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_error(stp->atp, atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0,30));
+ return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0,30, NULL, NULL, NULL);
}
static int32_t
@@ -608,16 +602,15 @@ ast_load_unload(struct ast_softc *stp, u_int8_t function)
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- ast_buffermode = 0;
if ((function & SS_EJECT) && !stp->cap.eject)
return 0;
- error = atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(stp->atp, error);
+ return error;
tsleep((caddr_t)&error, PRIBIO, "astlu", 1 * hz);
if (function == SS_EJECT)
return 0;
- return atapi_error(stp->atp, atapi_wait_ready(stp->atp, 60*60));
+ return atapi_wait_ready(stp->atp, 60*60);
}
static int32_t
@@ -627,11 +620,10 @@ ast_rewind(struct ast_softc *stp)
0, 0, 0, 0, 0, 0, 0, 0 };
int32_t error;
- ast_buffermode = 0;
- error = atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 10);
+ error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 10, NULL, NULL, NULL);
if (error)
- return atapi_error(stp->atp, error);
- return atapi_error(stp->atp, atapi_wait_ready(stp->atp, 60*60));
+ return error;
+ return atapi_wait_ready(stp->atp, 60*60);
}
static int32_t
@@ -644,7 +636,5 @@ ast_erase(struct ast_softc *stp)
if ((error = ast_rewind(stp)))
return error;
- ast_buffermode = 0;
- return atapi_error(stp->atp,
- atapi_immed_cmd(stp->atp, ccb, NULL, 0, 0, 60*60));
+ return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL);
}
diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h
index b2b7bd4..7f67460 100644
--- a/sys/dev/ata/atapi-tape.h
+++ b/sys/dev/ata/atapi-tape.h
@@ -31,49 +31,49 @@
/* ATAPI tape drive Capabilities and Mechanical Status Page */
struct ast_cappage {
/* mode page data header */
- u_int8_t data_length; /* total length of data */
- u_int8_t medium_type; /* medium type (if any) */
+ u_int8_t data_length; /* total length of data */
+ u_int8_t medium_type; /* medium type (if any) */
u_int8_t reserved :4;
- u_int8_t mode :3; /* buffering mode */
- u_int8_t write_protect :1; /* media is writeprotected */
- u_int8_t blk_desc_len; /* block Descriptor Length */
+ u_int8_t mode :3; /* buffering mode */
+ u_int8_t write_protect :1; /* media is writeprotected */
+ u_int8_t blk_desc_len; /* block Descriptor Length */
/* capabilities page */
u_int8_t page_code :6;
#define ATAPI_TAPE_CAP_PAGE 0x2a
u_int8_t reserved0_6 :1;
- u_int8_t ps :1; /* parameters saveable */
- u_int8_t page_length; /* page Length == 0x12 */
+ u_int8_t ps :1; /* parameters saveable */
+ u_int8_t page_length; /* page Length == 0x12 */
u_int8_t reserved2;
u_int8_t reserved3;
- u_int8_t readonly :1; /* read Only Mode */
+ u_int8_t readonly :1; /* read Only Mode */
u_int8_t reserved4_1234 :4;
- u_int8_t reverse :1; /* supports reverse direction */
+ u_int8_t reverse :1; /* supports reverse direction */
u_int8_t reserved4_67 :2;
u_int8_t reserved5_012 :3;
- u_int8_t eformat :1; /* supports ERASE formatting */
+ u_int8_t eformat :1; /* supports ERASE formatting */
u_int8_t reserved5_4 :1;
- u_int8_t qfa :1; /* supports QFA formats */
+ u_int8_t qfa :1; /* supports QFA formats */
u_int8_t reserved5_67 :2;
- u_int8_t lock :1; /* supports locking media */
- u_int8_t locked :1; /* the media is locked */
- u_int8_t prevent :1; /* defaults to prevent state */
- u_int8_t eject :1; /* supports eject */
- u_int8_t disconnect :1; /* can break request > ctl */
+ u_int8_t lock :1; /* supports locking media */
+ u_int8_t locked :1; /* the media is locked */
+ u_int8_t prevent :1; /* defaults to prevent state */
+ u_int8_t eject :1; /* supports eject */
+ u_int8_t disconnect :1; /* can break request > ctl */
u_int8_t reserved6_5 :1;
- u_int8_t ecc :1; /* supports error correction */
- u_int8_t compress :1; /* supports data compression */
+ u_int8_t ecc :1; /* supports error correction */
+ u_int8_t compress :1; /* supports data compression */
u_int8_t reserved7_0 :1;
- u_int8_t blk512 :1; /* supports 512b block size */
- u_int8_t blk1024 :1; /* supports 1024b block size */
+ u_int8_t blk512 :1; /* supports 512b block size */
+ u_int8_t blk1024 :1; /* supports 1024b block size */
u_int8_t reserved7_3456 :4;
- u_int8_t blk32k :1; /* supports 32kb block size */
- u_int16_t max_speed; /* supported speed in KBps */
- u_int16_t max_defects; /* max stored defect entries */
- u_int16_t ctl; /* continuous transfer limit */
- u_int16_t speed; /* current Speed, in KBps */
- u_int16_t buffer_size; /* buffer Size, in 512 bytes */
+ u_int8_t blk32k :1; /* supports 32kb block size */
+ u_int16_t max_speed; /* supported speed in KBps */
+ u_int16_t max_defects; /* max stored defect entries */
+ u_int16_t ctl; /* continuous transfer limit */
+ u_int16_t speed; /* current Speed, in KBps */
+ u_int16_t buffer_size; /* buffer Size, in 512 bytes */
u_int8_t reserved18;
u_int8_t reserved19;
};
@@ -81,44 +81,44 @@ struct ast_cappage {
/* ATAPI OnStream ADR data transfer mode page (ADR unique) */
struct ast_transferpage {
/* mode page data header */
- u_int8_t data_length; /* total length of data */
- u_int8_t medium_type; /* medium type (if any) */
- u_int8_t dsp; /* device specific parameter */
- u_int8_t blk_desc_len; /* block Descriptor Length */
+ u_int8_t data_length; /* total length of data */
+ u_int8_t medium_type; /* medium type (if any) */
+ u_int8_t dsp; /* device specific parameter */
+ u_int8_t blk_desc_len; /* block Descriptor Length */
/* data transfer page */
u_int8_t page_code :6;
#define ATAPI_TAPE_TRANSFER_PAGE 0x30
u_int8_t reserved0_6 :1;
- u_int8_t ps :1; /* parameters saveable */
- u_int8_t page_length; /* page Length == 0x02 */
+ u_int8_t ps :1; /* parameters saveable */
+ u_int8_t page_length; /* page Length == 0x02 */
u_int8_t reserved2;
- u_int8_t read32k :1; /* 32k block size (data only) */
- u_int8_t read32k5 :1; /* 32.5k block size (data & AUX) */
+ u_int8_t read32k :1; /* 32k blk size (data only) */
+ u_int8_t read32k5 :1; /* 32.5k blk size (data&AUX) */
u_int8_t reserved3_23 :2;
- u_int8_t write32k :1; /* 32k block size (data only) */
- u_int8_t write32k5 :1; /* 32.5k block size (data & AUX) */
+ u_int8_t write32k :1; /* 32k blk size (data only) */
+ u_int8_t write32k5 :1; /* 32.5k blk size (data&AUX) */
u_int8_t reserved3_6 :1;
- u_int8_t streaming :1; /* streaming mode enable */
+ u_int8_t streaming :1; /* streaming mode enable */
};
/* ATAPI OnStream ADR vendor identification mode page (ADR unique) */
struct ast_identifypage {
/* mode page data header */
- u_int8_t data_length; /* total length of data */
- u_int8_t medium_type; /* medium type (if any) */
- u_int8_t dsp; /* device specific parameter */
- u_int8_t blk_desc_len; /* block Descriptor Length */
+ u_int8_t data_length; /* total length of data */
+ u_int8_t medium_type; /* medium type (if any) */
+ u_int8_t dsp; /* device specific parameter */
+ u_int8_t blk_desc_len; /* block Descriptor Length */
/* data transfer page */
u_int8_t page_code :6;
#define ATAPI_TAPE_IDENTIFY_PAGE 0x36
u_int8_t reserved0_6 :1;
- u_int8_t ps :1; /* parameters saveable */
- u_int8_t page_length; /* page Length == 0x06 */
- u_int8_t ident[4]; /* host id string */
+ u_int8_t ps :1; /* parameters saveable */
+ u_int8_t page_length; /* page Length == 0x06 */
+ u_int8_t ident[4]; /* host id string */
u_int8_t reserved6;
u_int8_t reserved7;
};
@@ -126,17 +126,17 @@ struct ast_identifypage {
/* ATAPI read position structure */
struct ast_readposition {
u_int8_t reserved0_05 :6;
- u_int8_t eop :1; /* end of partition */
- u_int8_t bop :1; /* beginning of partition */
+ u_int8_t eop :1; /* end of partition */
+ u_int8_t bop :1; /* beginning of partition */
u_int8_t reserved1;
u_int8_t reserved2;
u_int8_t reserved3;
- u_int32_t host; /* frame address in buffer */
- u_int32_t tape; /* frame address on tape */
+ u_int32_t host; /* frame address in buffer */
+ u_int32_t tape; /* frame address on tape */
u_int8_t reserved12;
u_int8_t reserved13;
u_int8_t reserved14;
- u_int8_t blks_in_buf; /* blocks in buffer */
+ u_int8_t blks_in_buf; /* blocks in buffer */
u_int8_t reserved16;
u_int8_t reserved17;
u_int8_t reserved18;
OpenPOWER on IntegriCloud