summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>1999-10-09 19:57:13 +0000
committersos <sos@FreeBSD.org>1999-10-09 19:57:13 +0000
commit69ddfc2954d2d29861c84671c9856219a0d49951 (patch)
tree2c3edc3459eacefe5edd36bef26ab00bc8af640e /sys
parent23477e965b1901f8d7197ec89a37918208102322 (diff)
downloadFreeBSD-src-69ddfc2954d2d29861c84671c9856219a0d49951.zip
FreeBSD-src-69ddfc2954d2d29861c84671c9856219a0d49951.tar.gz
Add support for the HPT366 chip, this is used on the Abit boards and
their HotRod controller and on SIIG PCI ultra DMA controller. These changes also made lots of the Promise code go away, its all much more generic this way. Get rid of atapi_immed_cmd, instead use the queue to move atapi commands from interrupt context if nessesary, the entire atapi layer has gotten an overhaul. Lots of fixes to utililize the new features in subr_disk.c etc, and get rid of the last biots of softc arrays in the drivers, the only one left is atadevices which cannot easily go away (yet). Use our own malloc names, its a lot easier to track memory usage this way. General cleanup overall.
Diffstat (limited to 'sys')
-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