diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 669b67e0ffc7..69698ed1df56 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -195,12 +195,6 @@ ata_pcimatch(device_t dev) return "Intel PIIX4 ATA controller"; case 0x522910b9: return "AcerLabs Aladdin ATA controller"; - case 0x4d33105a: - return "Promise Ultra/33 ATA controller"; - case 0x4d38105a: - return "Promise Ultra/66 ATA controller"; - case 0x00041103: - return "HighPoint HPT366 ATA controller"; case 0x05711106: /* 82c586 & 82c686 */ switch (pci_read_config(dev, 0x08, 1)) { case 1: @@ -209,6 +203,14 @@ ata_pcimatch(device_t dev) return "VIA 82C686 ATA controller"; } return "VIA Apollo ATA controller"; + case 0x55131039: + return "SiS 5591 ATA controller"; + case 0x4d33105a: + return "Promise Ultra/33 ATA controller"; + case 0x4d38105a: + return "Promise Ultra/66 ATA controller"; + case 0x00041103: + return "HighPoint HPT366 ATA controller"; /* unsupported but known chipsets, generic DMA only */ case 0x05961106: @@ -766,6 +768,7 @@ ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask) u_int8_t status; u_int32_t timeout = 0; + DELAY(1); while (timeout <= 5000000) { /* timeout 5 secs */ status = inb(scp->ioaddr + ATA_STATUS); diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index c94b410b2ecd..e51f36eb9369 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -82,7 +82,7 @@ static void ad_attach(void *); static int32_t ad_getparam(struct ad_softc *); static void ad_start(struct ad_softc *); static void ad_timeout(struct ad_request *); -static int8_t ad_version(u_int16_t); +static int32_t ad_version(u_int16_t); static void ad_drvinit(void); /* internal vars */ @@ -105,7 +105,7 @@ apiomode(struct ata_params *ap) static __inline int wdmamode(struct ata_params *ap) { - if (ap->atavalid & 2) { + if ((ap->atavalid & 2) && ad_version(ap->versmajor) >= 2) { if (ap->wdmamodes & 4) return 2; if (ap->wdmamodes & 2) return 1; if (ap->wdmamodes & 1) return 0; @@ -116,7 +116,7 @@ wdmamode(struct ata_params *ap) static __inline int udmamode(struct ata_params *ap) { - if (ap->atavalid & 4) { + if ((ap->atavalid & 4) && ad_version(ap->versmajor) >= 3) { if (ap->udmamodes & 0x10) return (ap->cblid ? 4 : 2); if (ap->udmamodes & 0x08) return (ap->cblid ? 3 : 2); if (ap->udmamodes & 0x04) return 2; @@ -209,7 +209,7 @@ ad_attach(void *notused) wdmamode(adp->ata_parm), udmamode(adp->ata_parm), adp->ata_parm->cblid); - printf("ad%d: <%s/%s> ATA-%c disk at ata%d as %s\n", + printf("ad%d: <%s/%s> ATA-%d disk at ata%d as %s\n", adp->lun, model_buf, revision_buf, ad_version(adp->ata_parm->versmajor), ctlr, (adp->unit == ATA_MASTER) ? "master" : "slave "); @@ -257,8 +257,9 @@ ad_getparam(struct ad_softc *adp) /* select drive */ outb(adp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | adp->unit); DELAY(1); - ata_command(adp->controller, adp->unit, ATA_C_ATA_IDENTIFY, - 0, 0, 0, 0, 0, ATA_WAIT_INTR); + if (ata_command(adp->controller, adp->unit, ATA_C_ATA_IDENTIFY, + 0, 0, 0, 0, 0, ATA_WAIT_INTR)) + return -1; if (ata_wait(adp->controller, adp->unit, ATA_S_READY | ATA_S_DSC | ATA_S_DRQ)) return -1; @@ -476,8 +477,9 @@ ad_transfer(struct ad_request *request) else cmd = request->flags & AR_F_READ ? ATA_C_READ : ATA_C_WRITE; - ata_command(adp->controller, adp->unit, cmd, - cylinder, head, sector, count, 0, ATA_IMMEDIATE); + if (ata_command(adp->controller, adp->unit, cmd, + cylinder, head, sector, count, 0, ATA_IMMEDIATE)) + printf("ad%d: wouldn't take transfer command - HELP!\n", adp->lun); } /* if this is a DMA transaction start it, return and wait for interrupt */ @@ -553,6 +555,8 @@ oops: if (request->retries++ < AD_MAX_RETRIES) printf(" retrying\n"); else { + ata_dmainit(adp->controller, adp->unit, + apiomode(adp->ata_parm), -1, -1); adp->flags &= ~AD_F_DMA_ENABLED; printf(" falling back to PIO mode\n"); } @@ -563,8 +567,10 @@ oops: /* if using DMA, try once again in PIO mode */ if (request->flags & AR_F_DMA_USED) { untimeout((timeout_t *)ad_timeout, request,request->timeout_handle); - + ata_dmainit(adp->controller, adp->unit, + apiomode(adp->ata_parm), -1, -1); request->flags |= AR_F_FORCE_PIO; + adp->flags &= ~AD_F_DMA_ENABLED; TAILQ_INSERT_HEAD(&adp->controller->ata_queue, request, chain); return ATA_OP_FINISHED; } @@ -576,7 +582,6 @@ oops: /* if we arrived here with forced PIO mode, DMA doesn't work right */ if (request->flags & AR_F_FORCE_PIO) { - adp->flags &= ~AD_F_DMA_ENABLED; printf("ad%d: DMA problem encountered, fallback to PIO mode\n", adp->lun); } @@ -666,17 +671,15 @@ ad_timeout(struct ad_request *request) struct ad_softc *adp = request->device; adp->controller->running = NULL; - printf("ata%d-%s: ad_timeout: lost disk contact - resetting\n", - adp->controller->lun, - (adp->unit == ATA_MASTER) ? "master" : "slave"); + printf("ad%d: ad_timeout: lost disk contact - resetting\n", adp->lun); if (request->flags & AR_F_DMA_USED) { ata_dmadone(adp->controller); if (request->retries == AD_MAX_RETRIES) { + ata_dmainit(adp->controller, adp->unit, + apiomode(adp->ata_parm), -1, -1); adp->flags &= ~AD_F_DMA_ENABLED; - printf("ata%d-%s: ad_timeout: trying fallback to PIO mode\n", - adp->controller->lun, - (adp->unit == ATA_MASTER) ? "master" : "slave"); + printf("ad%d: ad_timeout: trying fallback to PIO mode\n", adp->lun); request->retries = 0; } } @@ -695,17 +698,17 @@ ad_timeout(struct ad_request *request) ata_reinit(adp->controller); } -static int8_t +static int32_t ad_version(u_int16_t version) { int32_t bit; if (version == 0xffff) - return '?'; + return 0; for (bit = 15; bit >= 0; bit--) if (version & (1<= 2 && apiomode >= 4) { + int32_t word40; + + word40 = pci_read_config(scp->dev, 0x40, 4); + word40 >>= scp->unit * 16; + + /* Check for timing config usable for DMA on controller */ + if (!((word40 & 0x3300) == 0x2300 && + ((word40 >> (device == ATA_MASTER ? 0 : 4)) & 1) == 1)) + break; + + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + printf("ata%d: %s: %s setting up WDMA2 mode on PIIX chip\n", + scp->lun, (device == ATA_MASTER) ? "master" : "slave", + (error) ? "failed" : "success"); + if (!error) { + scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; + return 0; + } + } break; case 0x522910b9: /* AcerLabs Aladdin IV/V */ @@ -297,6 +318,37 @@ ata_dmainit(struct ata_softc *scp, int32_t device, /* we could set PIO mode timings, but we assume the BIOS did that */ break; + case 0x55131039: /* SiS 5591 */ + 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_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + printf("ata%d: %s: %s setting up UDMA2 mode on SiS chip\n", + scp->lun, (device == ATA_MASTER) ? "master" : "slave", + (error) ? "failed" : "success"); + if (!error) { + pci_write_config(scp->dev, 0x40 + (devno << 1), 0xa301, 2); + scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_UDMA2; + return 0; + } + } + if (wdmamode >=2 && apiomode >= 4) { + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + printf("ata%d: %s: %s setting up WDMA2 mode on SiS chip\n", + scp->lun, (device == ATA_MASTER) ? "master" : "slave", + (error) ? "failed" : "success"); + if (!error) { + pci_write_config(scp->dev, 0x40 + (devno << 1), 0x0301, 2); + scp->mode[(device == ATA_MASTER) ? 0 : 1] = ATA_MODE_WDMA2; + return 0; + } + } + /* we could set PIO mode timings, but we assume the BIOS did that */ + 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 */ @@ -427,7 +479,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, if (((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) && (inb(scp->bmaddr + ATA_BMSTAT_PORT) & ((device == ATA_MASTER) ? - ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) { + ATA_BMSTAT_DMA_MASTER : ATA_BMSTAT_DMA_SLAVE))) { error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 8b8643a4ffc0..d47b92a8f8d6 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -198,8 +198,9 @@ atapi_getparam(struct atapi_softc *atp) /* select drive */ outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit); DELAY(1); - ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY, - 0, 0, 0, 0, 0, ATA_WAIT_INTR); + if (ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY, + 0, 0, 0, 0, 0, ATA_WAIT_INTR)) + return -1; if (atapi_wait(atp, ATA_S_DRQ)) return -1; insw(atp->controller->ioaddr + ATA_DATA, buffer, @@ -261,7 +262,7 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, splx(s); #ifdef ATAPI_DEBUG - printf("atapi: phew, got back from tsleep\n"); + printf("%s: phew, got back from tsleep\n", request->device->devname); #endif error = request->error; free(request, M_ATAPI); @@ -276,7 +277,8 @@ atapi_transfer(struct atapi_request *request) int8_t reason; #ifdef ATAPI_DEBUG - printf("atapi: starting %s ", atapi_cmd2str(request->ccb[0])); + printf("%s: starting %s ", + request->device->devname, atapi_cmd2str(request->ccb[0])); atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb)); #endif /* start timeout for this command */ @@ -306,10 +308,11 @@ atapi_transfer(struct atapi_request *request) } /* start ATAPI operation */ - ata_command(atp->controller, atp->unit, ATA_C_PACKET_CMD, - request->bytecount, 0, 0, 0, - (atp->flags & ATAPI_F_DMA_USED) ? ATA_F_DMA : 0, - ATA_IMMEDIATE); + if (ata_command(atp->controller, atp->unit, ATA_C_PACKET_CMD, + request->bytecount, 0, 0, 0, + (atp->flags & ATAPI_F_DMA_USED) ? ATA_F_DMA : 0, + ATA_IMMEDIATE)) + printf("%s: failure to send ATAPI packet command\n", atp->devname); if (atp->flags & ATAPI_F_DMA_USED) ata_dmastart(atp->controller); @@ -330,7 +333,7 @@ atapi_transfer(struct atapi_request *request) } if (timout <= 0) { request->result = inb(atp->controller->ioaddr + ATA_ERROR); - printf("atapi_transfer: device hanging on packet cmd\n"); + printf("%s: failure to execute ATAPI packet command\n", atp->devname); return; } @@ -353,7 +356,7 @@ atapi_interrupt(struct atapi_request *request) *buffer = (int8_t *)&request->sense; #ifdef ATAPI_DEBUG - printf("atapi_interrupt: enter\n"); + printf("%s: atapi_interrupt: enter\n", atp->devname); #endif reason = (inb(atp->controller->ioaddr+ATA_IREASON) & (ATA_I_CMD|ATA_I_IN)) | (atp->controller->status & ATA_S_DRQ); @@ -361,7 +364,7 @@ atapi_interrupt(struct atapi_request *request) if (reason == ATAPI_P_CMDOUT) { if (!(atp->controller->status & ATA_S_DRQ)) { request->result = inb(atp->controller->ioaddr + ATA_ERROR); - printf("atapi_interrupt: command interrupt, but no DRQ\n"); + printf("%s: command interrupt, but no DRQ\n", atp->devname); goto op_finished; } outsw(atp->controller->ioaddr + ATA_DATA, request->ccb, @@ -373,7 +376,7 @@ atapi_interrupt(struct atapi_request *request) dma_stat = ata_dmadone(atp->controller); if (atapi_wait(atp, 0) < 0) { - printf("atapi_interrupt: timeout waiting for status"); + printf("%s: timeout waiting for status", atp->devname); atp->flags &= ~ATAPI_F_DMA_USED; request->result = inb(atp->controller->ioaddr + ATA_ERROR) | ATAPI_SK_RESERVED; @@ -396,17 +399,15 @@ atapi_interrupt(struct atapi_request *request) length = inb(atp->controller->ioaddr + ATA_CYL_LSB); length |= inb(atp->controller->ioaddr + ATA_CYL_MSB) << 8; #ifdef ATAPI_DEBUG - printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); + printf("%s: length=%d reason=0x%02x\n", atp->devname, length, reason); #endif switch (reason) { case ATAPI_P_WRITE: if (request->flags & A_READ) { request->result = inb(atp->controller->ioaddr + ATA_ERROR); - printf("ata%d-%s: %s trying to write on read buffer\n", - atp->controller->lun, - (atp->unit == ATA_MASTER) ? "master" : "slave", - atapi_cmd2str(atp->cmd)); + printf("%s: %s trying to write on read buffer\n", + atp->devname, atapi_cmd2str(atp->cmd)); goto op_finished; } atapi_write(request, length); @@ -415,20 +416,15 @@ atapi_interrupt(struct atapi_request *request) case ATAPI_P_READ: if (!(request->flags & A_READ)) { request->result = inb(atp->controller->ioaddr + ATA_ERROR); - printf("ata%d-%s: %s trying to read on write buffer\n", - atp->controller->lun, - (atp->unit == ATA_MASTER) ? "master" : "slave", - atapi_cmd2str(atp->cmd)); + printf("%s: %s trying to read on write buffer\n", + atp->devname, atapi_cmd2str(atp->cmd)); goto op_finished; } atapi_read(request, length); return ATA_OP_CONTINUES; case ATAPI_P_DONEDRQ: - printf("ata%d-%s: %s DONEDRQ\n", - atp->controller->lun, - (atp->unit == ATA_MASTER) ? "master" : "slave", - atapi_cmd2str(atp->cmd)); + printf("%s: %s DONEDRQ\n", atp->devname, atapi_cmd2str(atp->cmd)); if (request->flags & A_READ) atapi_read(request, length); else @@ -445,14 +441,14 @@ atapi_interrupt(struct atapi_request *request) #ifdef ATAPI_DEBUG if (request->bytecount > 0) { - printf("atapi_interrupt: %s size problem, %d bytes residue\n", - (request->flags & A_READ) ? "read" : "write", + printf("%s: %s size problem, %d bytes residue\n", + atp->devname, (request->flags & A_READ) ? "read" : "write", request->bytecount); } #endif goto op_finished; default: - printf("atapi_interrupt: unknown transfer phase %d\n", reason); + printf("%s: unknown transfer phase %d\n", atp->devname, reason); } op_finished: @@ -473,7 +469,8 @@ op_finished: if (request->result) { switch ((request->result & ATAPI_SK_MASK)) { case ATAPI_SK_RESERVED: - printf("atapi_error: %s - timeout error = %02x\n", + printf("%s: %s - timeout error = %02x\n", + atp->devname, atapi_cmd2str(atp->cmd), request->result & ATAPI_E_MASK); request->error = EIO; break; @@ -483,8 +480,8 @@ op_finished: break; case ATAPI_SK_RECOVERED_ERROR: - printf("atapi_error: %s - recovered error\n", - atapi_cmd2str(atp->cmd)); + printf("%s: %s - recovered error\n", + atp->devname, atapi_cmd2str(atp->cmd)); request->error = 0; break; @@ -498,8 +495,8 @@ op_finished: break; default: - printf("atapi: %s - %s asc=%02x ascq=%02x error=%02x\n", - atapi_cmd2str(atp->cmd), + printf("%s: %s - %s asc=%02x ascq=%02x error=%02x\n", + atp->devname, atapi_cmd2str(atp->cmd), atapi_skey2str(request->sense.sense_key), request->sense.asc, request->sense.ascq, request->result & ATAPI_E_MASK); @@ -514,7 +511,7 @@ op_finished: wakeup((caddr_t)request); } #ifdef ATAPI_DEBUG - printf("atapi_interrupt: error=0x%02x\n", request->result); + printf("%s: error=0x%02x\n", request->device->devname, request->result); #endif return ATA_OP_FINISHED; } @@ -559,7 +556,7 @@ atapi_dump(int8_t *label, void *data, int32_t len) { u_int8_t *p = data; - printf ("atapi: %s %02x", label, *p++); + printf ("%s %02x", label, *p++); while (--len > 0) printf ("-%02x", *p++); printf ("\n"); @@ -575,8 +572,8 @@ atapi_read(struct atapi_request *request, int32_t length) *buffer = (int8_t *)&request->sense; if (request->bytecount < length) { - printf("atapi_interrupt: read data overrun %d/%d\n", - length, request->bytecount); + printf("%s: read data overrun %d/%d\n", + request->device->devname, length, request->bytecount); #ifdef ATA_16BIT_ONLY insw(request->device->controller->ioaddr + ATA_DATA, (void *)((uintptr_t)*buffer), length / sizeof(int16_t)); @@ -604,8 +601,8 @@ atapi_write(struct atapi_request *request, int32_t length) *buffer = (int8_t *)&request->sense; if (request->bytecount < length) { - printf("atapi_interrupt: write data underrun %d/%d\n", - length, request->bytecount); + printf("%s: write data underrun %d/%d\n", + request->device->devname, length, request->bytecount); #ifdef ATA_16BIT_ONLY outsw(request->device->controller->ioaddr + ATA_DATA, (void *)((uintptr_t)*buffer), length / sizeof(int16_t)); @@ -629,9 +626,8 @@ atapi_timeout(struct atapi_request *request) struct atapi_softc *atp = request->device; atp->controller->running = NULL; - printf("ata%d-%s: atapi_timeout: cmd=%s - resetting\n", - atp->controller->lun, (atp->unit == ATA_MASTER) ? "master" : "slave", - atapi_cmd2str(request->ccb[0])); + printf("%s: atapi_timeout: cmd=%s - resetting\n", + atp->devname, atapi_cmd2str(request->ccb[0])); #ifdef ATAPI_DEBUG atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb)); #endif diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index a8c7b9382408..7cbcbde07fc5 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -235,6 +235,7 @@ struct atapi_softc { struct ata_softc *controller; /* ptr to parent ctrl */ struct atapi_params *atapi_parm; /* ata device params */ int32_t unit; /* ATA_MASTER or ATA_SLAVE */ + int8_t *devname; /* this devices name */ int8_t cmd; /* last cmd executed */ u_int32_t flags; /* drive flags */ #define ATAPI_F_DMA_ENABLED 0x0001 diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index 2e75f3ab1cf0..f7544f56b34b 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -215,9 +215,10 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats) acd->changer_info = NULL; acd->atp->flags |= ATAPI_F_MEDIA_CHANGED; if (stats == NULL) { - if (!(acd->stats = malloc(sizeof(struct devstat), - M_ACD, M_NOWAIT))) + if (!(acd->stats = malloc(sizeof(struct devstat), M_ACD, M_NOWAIT))) { + free(acd, M_ACD); return NULL; + } bzero(acd->stats, sizeof(struct devstat)); } else @@ -238,6 +239,8 @@ acd_init_lun(struct atapi_softc *atp, int32_t lun, struct devstat *stats) UID_ROOT, GID_OPERATOR, 0644, "acd%dc", lun); dev->si_drv1 = acd; dev->si_iosize_max = 252 * DEV_BSIZE; + if ((acd->atp->devname = malloc(8, M_ACD, M_NOWAIT))) + sprintf(acd->atp->devname, "acd%d", acd->lun); return acd; } diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index 17b917999f35..c8a06715636e 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -117,6 +117,8 @@ afdattach(struct atapi_softc *atp) dev = disk_create(fdp->lun, &fdp->disk, 0, &afd_cdevsw, &afddisk_cdevsw); dev->si_drv1 = fdp; dev->si_iosize_max = 252 * DEV_BSIZE; + if ((fdp->atp->devname = malloc(8, M_AFD, M_NOWAIT))) + sprintf(fdp->atp->devname, "afd%d", fdp->lun); return 0; } diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index 9204993c5040..9e4d8ead9a17 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -148,6 +148,8 @@ astattach(struct atapi_softc *atp) UID_ROOT, GID_OPERATOR, 0640, "nrast%d", stp->lun); dev->si_drv1 = stp; dev->si_iosize_max = 252 * DEV_BSIZE; + if ((stp->atp->devname = malloc(8, M_AST, M_NOWAIT))) + sprintf(stp->atp->devname, "ast%d", stp->lun); return 0; }