diff options
-rw-r--r-- | sys/dev/ata/ata-all.c | 347 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 33 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 111 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.h | 17 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 231 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 313 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 50 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 158 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 38 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.h | 20 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 108 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.h | 98 |
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; |