diff options
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.c | 198 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 55 | ||||
-rw-r--r-- | sys/dev/ata/ata-card.c | 11 | ||||
-rw-r--r-- | sys/dev/ata/ata-cbus.c | 109 | ||||
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 1887 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 58 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.h | 2 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 1616 | ||||
-rw-r--r-- | sys/dev/ata/ata-isa.c | 13 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.c | 748 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.h | 262 | ||||
-rw-r--r-- | sys/dev/ata/ata-raid.c | 30 | ||||
-rw-r--r-- | sys/dev/ata/ata-raid.h | 2 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 46 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 2 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 8 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.h | 4 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 4 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.h | 2 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 2 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.h | 2 |
22 files changed, 2606 insertions, 2456 deletions
diff --git a/sys/conf/files b/sys/conf/files index a67a535..9f739db 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -300,6 +300,7 @@ dev/ata/ata-cbus.c optional ata pc98 dev/ata/ata-card.c optional ata card dev/ata/ata-card.c optional ata pccard dev/ata/ata-pci.c optional ata pci +dev/ata/ata-chipset.c optional ata pci dev/ata/ata-dma.c optional ata pci dev/ata/ata-disk.c optional atadisk dev/ata/ata-raid.c optional atadisk diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 9fb6aa5..183bdb2 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -135,9 +135,9 @@ ata_probe(device_t dev) (int)rman_get_start(ch->r_altio), (ch->r_bmio) ? (int)rman_get_start(ch->r_bmio) : 0); - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); ata_reset(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); ch->device[MASTER].channel = ch; ch->device[MASTER].unit = ATA_MASTER; @@ -183,13 +183,16 @@ ata_attach(device_t dev) return error; } + if (ch->dma) + ch->dma->create(ch); + /* * do not attach devices if we are in early boot, this is done later * when interrupts are enabled by a hook into the boot process. * otherwise attach what the probe has found in ch->devices. */ if (!ata_delayed_attach) { - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); if (ch->devices & ATA_ATA_SLAVE) if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) ch->devices &= ~ATA_ATA_SLAVE; @@ -217,7 +220,7 @@ ata_attach(device_t dev) #ifdef DEV_ATAPICAM atapi_cam_attach_bus(ch); #endif - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); } return 0; } @@ -233,7 +236,7 @@ ata_detach(device_t dev) return ENXIO; /* make sure channel is not busy */ - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(ch, ATA_CONTROL); s = splbio(); @@ -267,7 +270,8 @@ ata_detach(device_t dev) ch->device[MASTER].mode = ATA_PIO; ch->device[SLAVE].mode = ATA_PIO; ch->devices = 0; - ata_dmafreetags(ch); + if (ch->dma) + ch->dma->destroy(ch); bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); @@ -280,7 +284,7 @@ ata_detach(device_t dev) ch->r_bmio = NULL; ch->r_irq = NULL; ATA_UNLOCK_CH(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); return 0; } @@ -293,9 +297,9 @@ ata_resume(device_t dev) if (!dev || !(ch = device_get_softc(dev))) return ENXIO; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); error = ata_reinit(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); return error; } @@ -329,10 +333,10 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) case ATAREINIT: if (!device || !(ch = device_get_softc(device))) return ENXIO; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE); error = ata_reinit(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); return error; case ATAGMODE: @@ -356,7 +360,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) if (!device || !(ch = device_get_softc(device))) return ENXIO; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); if ((iocmd->device == MASTER || iocmd->device == -1) && iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) { ata_change_mode(&ch->device[MASTER],iocmd->u.mode.mode[MASTER]); @@ -372,7 +376,7 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) } else iocmd->u.mode.mode[SLAVE] = -1; - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); return 0; case ATAGPARM: @@ -446,8 +450,10 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) if (iocmd->u.atapi.flags & ATAPI_CMD_WRITE) { error = copyin(iocmd->u.atapi.data, buf, iocmd->u.atapi.count); - if (error) + if (error) { + free(buf, M_ATA); return error; + } } error = atapi_queue_cmd(atadev, iocmd->u.atapi.ccb, buf, iocmd->u.atapi.count, @@ -535,7 +541,7 @@ ata_boot_attach(void) for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { if (!(ch = devclass_get_softc(ata_devclass, ctlr))) continue; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); if (ch->devices & ATA_ATA_SLAVE) if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) ch->devices &= ~ATA_ATA_SLAVE; @@ -548,26 +554,26 @@ ata_boot_attach(void) if (ch->devices & ATA_ATAPI_MASTER) if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY)) ch->devices &= ~ATA_ATAPI_MASTER; - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); } #ifdef DEV_ATADISK /* now we know whats there, do the real attach, first the ATA disks */ for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { if (!(ch = devclass_get_softc(ata_devclass, ctlr))) continue; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); if (ch->devices & ATA_ATA_MASTER) ad_attach(&ch->device[MASTER]); if (ch->devices & ATA_ATA_SLAVE) ad_attach(&ch->device[SLAVE]); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); } #endif /* then the atapi devices */ for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) { if (!(ch = devclass_get_softc(ata_devclass, ctlr))) continue; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); #if DEV_ATAPIALL if (ch->devices & ATA_ATAPI_MASTER) atapi_attach(&ch->device[MASTER]); @@ -577,7 +583,7 @@ ata_boot_attach(void) #ifdef DEV_ATAPICAM atapi_cam_attach_bus(ch); #endif - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); } if (ata_delayed_attach) { config_intrhook_disestablish(ata_delayed_attach); @@ -593,15 +599,8 @@ static void ata_intr(void *data) { struct ata_channel *ch = (struct ata_channel *)data; - /* - * on PCI systems we might share an interrupt line with another - * device or our twin ATA channel, so call ch->intr_func to figure - * out if it is really an interrupt we should process here - */ - if (!ch->intr_func(ch)) - return; - /* if drive is busy it didn't interrupt */ + /* if device is busy it didn't interrupt */ if (ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_BUSY) { DELAY(100); if (!(ATA_INB(ch->r_altio, ATA_ALTSTAT) & ATA_S_DRQ)) @@ -651,7 +650,7 @@ ata_intr(void *data) } ch->running = NULL; ATA_UNLOCK_CH(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); ata_start(ch); return; } @@ -667,7 +666,7 @@ ata_start(struct ata_channel *ch) #endif int s; - ch->lock_func(ch, ATA_LF_LOCK); + ch->locking(ch, ATA_LF_LOCK); if (!ATA_LOCK_CH(ch, ATA_ACTIVE)) return; @@ -710,7 +709,7 @@ ata_start(struct ata_channel *ch) } #endif ATA_UNLOCK_CH(ch); - ch->lock_func(ch, ATA_LF_UNLOCK); + ch->locking(ch, ATA_LF_UNLOCK); splx(s); } @@ -725,14 +724,14 @@ ata_reset(struct ata_channel *ch) ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_MASTER); DELAY(10); ostat0 = ATA_INB(ch->r_io, ATA_STATUS); - if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) { + if ((ostat0 & 0xf8) == 0x50 && ostat0 != 0xa5) { stat0 = ATA_S_BUSY; mask |= 0x01; } ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); DELAY(10); ostat1 = ATA_INB(ch->r_io, ATA_STATUS); - if ((ostat1 & 0xf8) != 0xf8 && ostat1 != 0xa5) { + if ((ostat1 & 0xf8) == 0x50 && ostat1 != 0xa5) { stat1 = ATA_S_BUSY; mask |= 0x02; } @@ -748,7 +747,7 @@ ata_reset(struct ata_channel *ch) } if (bootverbose) - ata_printf(ch, -1, "mask=%02x ostat0=%02x ostat2=%02x\n", + ata_printf(ch, -1, "pre reset mask=%02x ostat0=%02x ostat2=%02x\n", mask, ostat0, ostat1); /* reset channel */ @@ -811,7 +810,7 @@ ata_reset(struct ata_channel *ch) if (stat1 & ATA_S_BUSY) mask &= ~0x02; if (bootverbose) - ata_printf(ch, -1, "mask=%02x stat0=%02x stat1=%02x\n", + ata_printf(ch, -1, "after reset mask=%02x stat0=%02x stat1=%02x\n", mask, stat0, stat1); if (!mask) return; @@ -901,32 +900,32 @@ ata_reinit(struct ata_channel *ch) } newdev = ~devices & ch->devices; #ifdef DEV_ATADISK - if (newdev & ATA_ATA_MASTER && !ch->device[MASTER].driver) - ad_attach(&ch->device[MASTER]); - else if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) { - ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY); - ad_reinit(&ch->device[MASTER]); - } if (newdev & ATA_ATA_SLAVE && !ch->device[SLAVE].driver) ad_attach(&ch->device[SLAVE]); else if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) { ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY); ad_reinit(&ch->device[SLAVE]); } + if (newdev & ATA_ATA_MASTER && !ch->device[MASTER].driver) + ad_attach(&ch->device[MASTER]); + else if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) { + ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY); + ad_reinit(&ch->device[MASTER]); + } #endif #if DEV_ATAPIALL - if (newdev & ATA_ATAPI_MASTER && !ch->device[MASTER].driver) - atapi_attach(&ch->device[MASTER]); - else if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) { - ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY); - atapi_reinit(&ch->device[MASTER]); - } if (newdev & ATA_ATAPI_SLAVE && !ch->device[SLAVE].driver) atapi_attach(&ch->device[SLAVE]); else if (ch->devices & (ATA_ATAPI_SLAVE) && ch->device[SLAVE].driver) { ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY); atapi_reinit(&ch->device[SLAVE]); } + if (newdev & ATA_ATAPI_MASTER && !ch->device[MASTER].driver) + atapi_attach(&ch->device[MASTER]); + else if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) { + ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY); + atapi_reinit(&ch->device[MASTER]); + } #endif #ifdef DEV_ATAPICAM atapi_cam_reinit_bus(ch); @@ -942,8 +941,10 @@ ata_service(struct ata_channel *ch) { /* do we have a SERVICE request from the drive ? */ if ((ch->status & (ATA_S_SERVICE|ATA_S_ERROR|ATA_S_DRQ)) == ATA_S_SERVICE) { +#if 0 /* XXX */ ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - ata_dmastatus(ch) | ATA_BMSTAT_INTERRUPT); + ch->dma->status(ch) | ATA_BMSTAT_INTERRUPT); +#endif #ifdef DEV_ATADISK if ((ATA_INB(ch->r_io, ATA_DRIVE) & ATA_SLAVE) == ATA_MASTER) { if ((ch->devices & ATA_ATA_MASTER) && ch->device[MASTER].driver) @@ -1250,7 +1251,7 @@ ata_enclosure_status(struct ata_device *atadev, u_int8_t id1, id2, cnt, div; if (atadev->flags & ATA_D_ENC_PRESENT) { - atadev->channel->lock_func(atadev->channel, ATA_LF_LOCK); + atadev->channel->locking(atadev->channel, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); ata_enclosure_sensor(atadev, 1, 0x4e, 0); id1 = ata_enclosure_sensor(atadev, 0, 0x4f, 0); @@ -1271,7 +1272,7 @@ ata_enclosure_status(struct ata_device *atadev, *v05 = ata_enclosure_sensor(atadev, 0, 0x23, 0) * 27; *v12 = ata_enclosure_sensor(atadev, 0, 0x24, 0) * 61; ATA_UNLOCK_CH(atadev->channel); - atadev->channel->lock_func(atadev->channel, ATA_LF_UNLOCK); + atadev->channel->locking(atadev->channel, ATA_LF_UNLOCK); return 0; } return ENXIO; @@ -1283,7 +1284,7 @@ ata_enclosure_print(struct ata_device *atadev) u_int8_t id, st; int fan, temp, v05, v12; - atadev->channel->lock_func(atadev->channel, ATA_LF_LOCK); + atadev->channel->locking(atadev->channel, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); ata_enclosure_start(atadev); id = ATA_INB(atadev->channel->r_io, ATA_DRIVE); @@ -1292,7 +1293,7 @@ ata_enclosure_print(struct ata_device *atadev) DELAY(1); ata_enclosure_end(atadev); ATA_UNLOCK_CH(atadev->channel); - atadev->channel->lock_func(atadev->channel, ATA_LF_UNLOCK); + atadev->channel->locking(atadev->channel, ATA_LF_UNLOCK); switch (id & 0x93) { case 0x00: @@ -1306,11 +1307,12 @@ ata_enclosure_print(struct ata_device *atadev) ata_prtdev(atadev, "SuperSwap enclosure"); break; default: - atadev->flags &= ~ATA_D_ENC_PRESENT; + atadev->flags &= ~ATA_D_ENC_PRESENT; return; } atadev->flags |= ATA_D_ENC_PRESENT; + ata_enclosure_leds(atadev, ATA_LED_GREEN); if (ata_enclosure_status(atadev, &fan, &temp, &v05, &v12)) printf(" detected\n"); else @@ -1337,31 +1339,8 @@ ata_enclosure_leds(struct ata_device *atadev, u_int8_t color) static void ata_change_mode(struct ata_device *atadev, int mode) { - int umode, wmode, pmode; - - umode = ata_umode(atadev->param); - wmode = ata_wmode(atadev->param); - pmode = ata_pmode(atadev->param); - - switch (mode & ATA_DMA_MASK) { - case ATA_UDMA: - if ((mode & ATA_MODE_MASK) < umode) - umode = mode & ATA_MODE_MASK; - break; - case ATA_WDMA: - if ((mode & ATA_MODE_MASK) < wmode) - wmode = mode & ATA_MODE_MASK; - umode = -1; - break; - default: - if (((mode & ATA_MODE_MASK) - ATA_PIO0) < pmode) - pmode = (mode & ATA_MODE_MASK) - ATA_PIO0; - umode = -1; - wmode = -1; - } - ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE); - ata_dmainit(atadev, pmode, wmode, umode); + atadev->setmode(atadev, mode); ATA_UNLOCK_CH(atadev->channel); ata_start(atadev->channel); } @@ -1452,8 +1431,13 @@ ata_mode2str(int mode) case ATA_PIO3: return "PIO3"; case ATA_PIO4: return "PIO4"; case ATA_DMA: return "BIOSDMA"; + case ATA_WDMA0: return "WDMA0"; + case ATA_WDMA1: return "WDMA1"; case ATA_WDMA2: return "WDMA2"; + case ATA_UDMA0: return "UDMA16"; + case ATA_UDMA1: return "UDMA25"; case ATA_UDMA2: return "UDMA33"; + case ATA_UDMA3: return "UDMA40"; case ATA_UDMA4: return "UDMA66"; case ATA_UDMA5: return "UDMA100"; case ATA_UDMA6: return "UDMA133"; @@ -1465,29 +1449,33 @@ int ata_pmode(struct ata_params *ap) { if (ap->atavalid & ATA_FLAG_64_70) { - if (ap->apiomodes & 2) - return 4; - if (ap->apiomodes & 1) - return 3; + if (ap->apiomodes & 0x02) + return ATA_PIO4; + if (ap->apiomodes & 0x01) + return ATA_PIO3; } if (ap->retired_piomode == 2) - return 2; + return ATA_PIO2; if (ap->retired_piomode == 1) - return 1; + return ATA_PIO1; if (ap->retired_piomode == 0) - return 0; - return -1; + return ATA_PIO0; + if (ap->support_dma) + return ATA_PIO4; + return ATA_PIO0; } int ata_wmode(struct ata_params *ap) { if (ap->mwdmamodes & 0x04) - return 2; + return ATA_WDMA2; if (ap->mwdmamodes & 0x02) - return 1; + return ATA_WDMA1; if (ap->mwdmamodes & 0x01) - return 0; + return ATA_WDMA0; + if (ap->support_dma) + return ATA_WDMA2; return -1; } @@ -1496,23 +1484,41 @@ ata_umode(struct ata_params *ap) { if (ap->atavalid & ATA_FLAG_88) { if (ap->udmamodes & 0x40) - return 6; + return ATA_UDMA6; if (ap->udmamodes & 0x20) - return 5; + return ATA_UDMA5; if (ap->udmamodes & 0x10) - return 4; + return ATA_UDMA4; if (ap->udmamodes & 0x08) - return 3; + return ATA_UDMA3; if (ap->udmamodes & 0x04) - return 2; + return ATA_UDMA2; if (ap->udmamodes & 0x02) - return 1; + return ATA_UDMA1; if (ap->udmamodes & 0x01) - return 0; + return ATA_UDMA0; } return -1; } +int +ata_limit_mode(struct ata_device *atadev, int mode, int maxmode) +{ + if (maxmode && mode > maxmode) + mode = maxmode; + + if (mode >= ATA_UDMA0 && ata_umode(atadev->param) > 0) + return min(mode, ata_umode(atadev->param)); + + if (mode >= ATA_WDMA0 && ata_wmode(atadev->param) > 0) + return min(mode, ata_wmode(atadev->param)); + + if (mode > ata_pmode(atadev->param)) + return min(mode, ata_pmode(atadev->param)); + + return mode; +} + static void bswap(int8_t *buf, int len) { diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 323a99d..52d4348 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -120,11 +120,11 @@ /* misc defines */ #define ATA_PRIMARY 0x1f0 #define ATA_SECONDARY 0x170 -#define ATA_PC98_BANK 0x432 +#define ATA_PC98_BANK 0x432 #define ATA_IOSIZE 0x08 #define ATA_ALTIOSIZE 0x01 #define ATA_BMIOSIZE 0x08 -#define ATA_PC98_BANKIOSIZE 0x01 +#define ATA_PC98_BANKIOSIZE 0x01 #define ATA_OP_FINISHED 0x00 #define ATA_OP_CONTINUES 0x01 #define ATA_IOADDR_RID 0 @@ -145,7 +145,6 @@ #define ATA_BMCMD_WRITE_READ 0x08 #define ATA_BMDEVSPEC_0 0x01 - #define ATA_BMSTAT_PORT 0x02 #define ATA_BMSTAT_ACTIVE 0x01 #define ATA_BMSTAT_ERROR 0x02 @@ -172,8 +171,8 @@ struct ata_dmastate { struct ata_dmaentry *dmatab; /* DMA transfer table */ bus_addr_t mdmatab; /* bus address of dmatab */ int flags; /* debugging */ -#define ATA_DS_ACTIVE 0x01 /* debugging */ -#define ATA_DS_READ 0x02 /* transaction is a read */ +#define ATA_DS_ACTIVE 0x01 /* debugging */ +#define ATA_DS_READ 0x02 /* transaction is a read */ }; /* structure describing an ATA/ATAPI device */ @@ -192,12 +191,26 @@ struct ata_device { #define ATA_D_MEDIA_CHANGED 0x0004 #define ATA_D_ENC_PRESENT 0x0008 - int mode; /* transfermode */ int cmd; /* last cmd executed */ void *result; /* misc data */ + int mode; /* transfermode */ + void (*setmode)(struct ata_device *, int); struct ata_dmastate dmastate; /* dma state */ }; +/* structure holding DMA function pointers */ +struct ata_dma_funcs { + void (*create)(struct ata_channel *); + void (*destroy)(struct ata_channel *); + int (*alloc)(struct ata_device *); + void (*free)(struct ata_device *); + int (*setup)(struct ata_device *, caddr_t, int32_t); + int (*start)(struct ata_device *, caddr_t, int32_t, int); + int (*stop)(struct ata_device *); + int (*status)(struct ata_channel *); + u_int32_t alignment; /* dma engine alignment */ +}; + /* structure describing an ATA channel */ struct ata_channel { struct device *dev; /* device handle */ @@ -208,10 +221,9 @@ struct ata_channel { bus_dma_tag_t dmatag; /* parent dma tag */ struct resource *r_irq; /* interrupt of this channel */ void *ih; /* interrupt handle */ - int (*intr_func)(struct ata_channel *); /* interrupt function */ - u_int32_t chiptype; /* pciid of controller chip */ - u_int32_t alignment; /* dma engine min alignment */ - int flags; /* controller flags */ + struct ata_dma_funcs *dma; /* DMA functions */ + u_int32_t chiptype; /* controller chip PCI id */ + int flags; /* channel flags */ #define ATA_NO_SLAVE 0x01 #define ATA_USE_16BIT 0x02 #define ATA_USE_PC98GEOM 0x04 @@ -243,7 +255,7 @@ struct ata_channel { #define ATA_ACTIVE_ATAPI 0x0040 #define ATA_CONTROL 0x0080 - void (*lock_func)(struct ata_channel *, int);/* controller lock function */ + void (*locking)(struct ata_channel *, int); #define ATA_LF_LOCK 0x0001 #define ATA_LF_UNLOCK 0x0002 @@ -286,16 +298,7 @@ char *ata_mode2str(int); int ata_pmode(struct ata_params *); int ata_wmode(struct ata_params *); int ata_umode(struct ata_params *); -int ata_find_dev(device_t, u_int32_t, u_int32_t); - -int ata_dmaalloc(struct ata_device *); -void ata_dmafree(struct ata_device *); -void ata_dmafreetags(struct ata_channel *); -void ata_dmainit(struct ata_device *, int, int, int); -int ata_dmasetup(struct ata_device *, caddr_t, int32_t); -int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); -int ata_dmastatus(struct ata_channel *); -int ata_dmadone(struct ata_device *); +int ata_limit_mode(struct ata_device *, int, int); /* macros for locking a channel */ #define ATA_LOCK_CH(ch, value) \ @@ -325,7 +328,7 @@ int ata_dmadone(struct ata_device *); (offset), (addr), (count)) #define ATA_INSW_STRM(res, offset, addr, count) \ bus_space_read_multi_stream_2(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ + rman_get_bushandle((res)), \ (offset), (addr), (count)) #define ATA_INSL(res, offset, addr, count) \ bus_space_read_multi_4(rman_get_bustag((res)), \ @@ -333,7 +336,7 @@ int ata_dmadone(struct ata_device *); (offset), (addr), (count)) #define ATA_INSL_STRM(res, offset, addr, count) \ bus_space_read_multi_stream_4(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ + rman_get_bushandle((res)), \ (offset), (addr), (count)) #define ATA_OUTB(res, offset, value) \ bus_space_write_1(rman_get_bustag((res)), \ @@ -350,7 +353,7 @@ int ata_dmadone(struct ata_device *); (offset), (addr), (count)) #define ATA_OUTSW_STRM(res, offset, addr, count) \ bus_space_write_multi_stream_2(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ + rman_get_bushandle((res)), \ (offset), (addr), (count)) #define ATA_OUTSL(res, offset, addr, count) \ bus_space_write_multi_4(rman_get_bustag((res)), \ @@ -358,5 +361,5 @@ int ata_dmadone(struct ata_device *); (offset), (addr), (count)) #define ATA_OUTSL_STRM(res, offset, addr, count) \ bus_space_write_multi_stream_4(rman_get_bustag((res)), \ - rman_get_bushandle((res)), \ + rman_get_bushandle((res)), \ (offset), (addr), (count)) diff --git a/sys/dev/ata/ata-card.c b/sys/dev/ata/ata-card.c index ef1c338..31ff4ab 100644 --- a/sys/dev/ata/ata-card.c +++ b/sys/dev/ata/ata-card.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,12 +61,6 @@ ata_pccard_match(device_t dev) return(ENXIO); } -static int -ata_pccard_intrnoop(struct ata_channel *ch) -{ - return 1; -} - static void ata_pccard_locknoop(struct ata_channel *ch, int type) { @@ -116,8 +110,7 @@ ata_pccard_probe(device_t dev) ch->unit = 0; ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE); - ch->intr_func = ata_pccard_intrnoop; - ch->lock_func = ata_pccard_locknoop; + ch->locking = ata_pccard_locknoop; return ata_probe(dev); } diff --git a/sys/dev/ata/ata-cbus.c b/sys/dev/ata/ata-cbus.c index 854b55e..38a2d20 100644 --- a/sys/dev/ata/ata-cbus.c +++ b/sys/dev/ata/ata-cbus.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 2002, 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/ata.h> #include <sys/bus.h> #include <sys/malloc.h> #include <machine/resource.h> @@ -50,9 +51,21 @@ struct ata_cbus_controller { struct resource *altio; struct resource *bankio; struct resource *irq; + void *ih; + void (*setmode)(struct ata_device *, int); + void (*locking)(struct ata_channel *, int); int current_bank; + struct { + void (*function)(void *); + void *argument; + } interrupt[2]; }; +/* local prototypes */ +static void ata_cbus_intr(void *); +static void ata_cbus_banking(struct ata_channel *, int); +static void ata_cbus_setmode(struct ata_device *, int); + static int ata_cbus_probe(device_t dev) { @@ -93,37 +106,49 @@ ata_cbus_probe(device_t dev) static int ata_cbus_attach(device_t dev) { - struct ata_cbus_controller *scp = device_get_softc(dev); + struct ata_cbus_controller *ctlr = device_get_softc(dev); int rid; /* allocate resources */ rid = ATA_IOADDR_RID; - scp->io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports, + ctlr->io = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, ata_pc98_ports, ATA_IOSIZE, RF_ACTIVE); - if (!scp->io) + if (!ctlr->io) return ENOMEM; - isa_load_resourcev(scp->io, ata_pc98_ports, ATA_IOSIZE); + isa_load_resourcev(ctlr->io, ata_pc98_ports, ATA_IOSIZE); rid = ATA_PC98_ALTADDR_RID; - scp->altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - rman_get_start(scp->io)+ATA_PC98_ALTOFFSET, + ctlr->altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + rman_get_start(ctlr->io)+ATA_PC98_ALTOFFSET, ~0, ATA_ALTIOSIZE, RF_ACTIVE); - if (!scp->altio) + if (!ctlr->altio) return ENOMEM; rid = ATA_PC98_BANKADDR_RID; - scp->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + ctlr->bankio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, ATA_PC98_BANK, ~0, ATA_PC98_BANKIOSIZE, RF_ACTIVE); - if (!scp->bankio) + if (!ctlr->bankio) return ENOMEM; rid = 0; - scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, - 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); + if (!(ctlr->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, + 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE))) { + device_printf(dev, "unable to alloc interrupt\n"); + return ENXIO; + } + + if ((bus_setup_intr(dev, ctlr->irq, INTR_TYPE_BIO | INTR_ENTROPY, + ata_cbus_intr, ctlr, &ctlr->ih))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + + ctlr->locking = ata_cbus_banking; + ctlr->current_bank = -1; + ctlr->setmode = ata_cbus_setmode;; - scp->current_bank = -1; if (!device_add_child(dev, "ata", 0)) return ENOMEM; if (!device_add_child(dev, "ata", 1)) @@ -136,18 +161,18 @@ static struct resource * ata_cbus_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - struct ata_cbus_controller *scp = device_get_softc(dev); + struct ata_cbus_controller *ctlr = device_get_softc(dev); if (type == SYS_RES_IOPORT) { switch (*rid) { case ATA_IOADDR_RID: - return scp->io; + return ctlr->io; case ATA_ALTADDR_RID: - return scp->altio; + return ctlr->altio; } } if (type == SYS_RES_IRQ) { - return scp->irq; + return ctlr->irq; } return 0; } @@ -157,8 +182,14 @@ ata_cbus_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *intr, void *arg, void **cookiep) { - return BUS_SETUP_INTR(device_get_parent(dev), dev, irq, - flags, intr, arg, cookiep); + struct ata_cbus_controller *controller = device_get_softc(dev); + int unit = ((struct ata_channel *)device_get_softc(child))->unit; + + controller->interrupt[unit].function = intr; + controller->interrupt[unit].argument = arg; + *cookiep = controller; + + return 0; } static int @@ -173,40 +204,48 @@ ata_cbus_print_child(device_t dev, device_t child) return retval; } -static int -ata_cbus_intr(struct ata_channel *ch) +static void +ata_cbus_intr(void *data) { - struct ata_cbus_controller *scp = - device_get_softc(device_get_parent(ch->dev)); + struct ata_cbus_controller *ctlr = data; - return (ch->unit == scp->current_bank); + if (ctlr->current_bank != -1 && + ctlr->interrupt[ctlr->current_bank].argument) + ctlr->interrupt[ctlr->current_bank]. + function(ctlr->interrupt[ctlr->current_bank].argument); } static void ata_cbus_banking(struct ata_channel *ch, int flags) { - struct ata_cbus_controller *scp = + struct ata_cbus_controller *ctlr = device_get_softc(device_get_parent(ch->dev)); switch (flags) { case ATA_LF_LOCK: - if (scp->current_bank == ch->unit) + if (ctlr->current_bank == ch->unit) break; - while (!atomic_cmpset_acq_int(&scp->current_bank, -1, ch->unit)) - tsleep((caddr_t)ch->lock_func, PRIBIO, "atalck", 1); - bus_space_write_1(rman_get_bustag(scp->bankio), - rman_get_bushandle(scp->bankio), 0, ch->unit); + while (!atomic_cmpset_acq_int(&ctlr->current_bank, -1, ch->unit)) + tsleep((caddr_t)ch->locking, PRIBIO, "atalck", 1); + bus_space_write_1(rman_get_bustag(ctlr->bankio), + rman_get_bushandle(ctlr->bankio), 0, ch->unit); break; case ATA_LF_UNLOCK: - if (scp->current_bank == -1 || scp->current_bank != ch->unit) + if (ctlr->current_bank == -1 || ctlr->current_bank != ch->unit) break; - atomic_store_rel_int(&scp->current_bank, -1); + atomic_store_rel_int(&ctlr->current_bank, -1); break; } return; } +static void +ata_cbus_setmode(struct ata_device *atadev, int mode) +{ + atadev->mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX); +} + static device_method_t ata_cbus_methods[] = { /* device_interface */ DEVMETHOD(device_probe, ata_cbus_probe), @@ -232,6 +271,7 @@ DRIVER_MODULE(atacbus, isa, ata_cbus_driver, ata_cbus_devclass, 0, 0); static int ata_cbussub_probe(device_t dev) { + struct ata_cbus_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); device_t *children; int count, i; @@ -244,8 +284,9 @@ ata_cbussub_probe(device_t dev) } free(children, M_TEMP); ch->flags |= ATA_USE_16BIT | ATA_USE_PC98GEOM; - ch->intr_func = ata_cbus_intr; - ch->lock_func = ata_cbus_banking; + ch->device[MASTER].setmode = ctlr->setmode; + ch->device[SLAVE].setmode = ctlr->setmode; + ch->locking = ctlr->locking; return ata_probe(dev); } diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c new file mode 100644 index 0000000..8860226 --- /dev/null +++ b/sys/dev/ata/ata-chipset.c @@ -0,0 +1,1887 @@ +/*- + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include "opt_ata.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/ata.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <machine/stdarg.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <pci/pcivar.h> +#include <pci/pcireg.h> +#include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> + +/* misc defines */ +#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev)) +#define ATAPI_DEVICE(atadev) \ + ((atadev->unit == ATA_MASTER && \ + atadev->channel->devices & ATA_ATAPI_MASTER) ||\ + (atadev->unit == ATA_SLAVE && \ + atadev->channel->devices & ATA_ATAPI_SLAVE)) + +/* local prototypes */ +static int ata_generic_chipinit(device_t); +static void ata_generic_intr(void *); +static void ata_generic_setmode(struct ata_device *, int); +static int ata_acard_chipinit(device_t); +static void ata_acard_intr(void *); +static void ata_acard_850_setmode(struct ata_device *, int); +static void ata_acard_86X_setmode(struct ata_device *, int); +static int ata_ali_chipinit(device_t); +static void ata_ali_setmode(struct ata_device *, int); +static int ata_amd_chipinit(device_t); +static int ata_cyrix_chipinit(device_t); +static void ata_cyrix_setmode(struct ata_device *, int); +static int ata_cypress_chipinit(device_t); +static void ata_cypress_setmode(struct ata_device *, int); +static int ata_highpoint_chipinit(device_t); +static void ata_highpoint_intr(void *); +static void ata_highpoint_setmode(struct ata_device *, int); +static int ata_highpoint_check_80pin(struct ata_device *, int); +static int ata_intel_chipinit(device_t); +static void ata_intel_old_setmode(struct ata_device *, int); +static void ata_intel_new_setmode(struct ata_device *, int); +static int ata_nvidia_chipinit(device_t); +static int ata_via_chipinit(device_t); +static void ata_via_family_setmode(struct ata_device *, int); +static void ata_via_southbridge_fixup(device_t); +static int ata_promise_chipinit(device_t); +static void ata_promise_intr(void *); +static void ata_promise_tx2_intr(void *); +static void ata_promise_setmode(struct ata_device *, int); +static int ata_promise_dmainit(struct ata_channel *); +static int ata_promise_dmastart(struct ata_device *, caddr_t, int32_t, int); +static int ata_promise_dmastop(struct ata_device *); +static int ata_serverworks_chipinit(device_t); +static void ata_serverworks_setmode(struct ata_device *, int); +static int ata_sii_chipinit(device_t); +static void ata_cmd_intr(void *); +static void ata_sii_setmode(struct ata_device *, int); +static void ata_cmd_setmode(struct ata_device *, int); +static int ata_sis_chipinit(device_t); +static void ata_sis_setmode(struct ata_device *, int); +static int ata_mode2idx(int); +static int ata_check_80pin(struct ata_device *, int); +static int ata_find_dev(device_t, u_int32_t, u_int32_t); +static struct ata_chip_id *ata_match_chip(device_t, struct ata_chip_id *); +static int ata_default_interrupt(device_t); +static void ata_pci_serialize(struct ata_channel *, int); + +/* generic or unknown ATA chipset init code */ +int +ata_generic_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + device_set_desc(dev, "GENERIC ATA controller"); + ctlr->chipinit = ata_generic_chipinit; + return 0; +} + +static int +ata_generic_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + ctlr->setmode = ata_generic_setmode; + return 0; +} + +static void +ata_generic_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch; + u_int8_t dmastat; + int unit; + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < 2; unit++) { + if (!(ch = ctlr->interrupt[unit].argument)) + continue; + if (ch->flags & ATA_DMA_ACTIVE) { + if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + DELAY(1); + } + ctlr->interrupt[unit].function(ch); + } +} + +static void +ata_generic_setmode(struct ata_device *atadev, int mode) +{ + if (mode >= ATA_DMA) + atadev->mode = ATA_DMA; + else + atadev->mode = ATA_PIO; + return; +} + +/* + * Acard chipset support functions + */ +int +ata_acard_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_ATP850R, 0, ATPOLD, 0x00, ATA_UDMA2, "Acard ATP850" }, + { ATA_ATP860A, 0, 0, 0x00, ATA_UDMA4, "Acard ATP860A" }, + { ATA_ATP860R, 0, 0, 0x00, ATA_UDMA4, "Acard ATP860R" }, + { ATA_ATP865A, 0, 0, 0x00, ATA_UDMA6, "Acard ATP865A" }, + { ATA_ATP865R, 0, 0, 0x00, ATA_UDMA6, "Acard ATP865R" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_acard_chipinit; + return 0; +} + +static int +ata_acard_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int rid = ATA_IRQ_RID; + + if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return ENXIO; + } + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ata_acard_intr, ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + if (ctlr->chip->cfg1 == ATPOLD) { + ctlr->setmode = ata_acard_850_setmode; + ctlr->locking = ata_pci_serialize; + } + else + ctlr->setmode = ata_acard_86X_setmode; + return 0; +} + +static void +ata_acard_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch; + u_int8_t dmastat; + int unit; + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < 2; unit++) { + if (ctlr->chip->cfg1 == ATPOLD && ctlr->locked_ch != unit) + continue; + ch = ctlr->interrupt[unit].argument; + if (ch->flags & ATA_DMA_ACTIVE) { + if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + DELAY(1); + ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, + ATA_INB(ch->r_bmio, ATA_BMCMD_PORT)&~ATA_BMCMD_START_STOP); + DELAY(1); + } + ctlr->interrupt[unit].function(ch); + } +} + +static void +ata_acard_850_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + + mode = ata_limit_mode(atadev, mode, + ATAPI_DEVICE(atadev)?ATA_PIO_MAX:ctlr->chip->max_dma); + +/* XXX missing WDMA0+1 + PIO modes */ + if (mode >= ATA_WDMA2) { + error = ata_command(atadev, ATA_C_SETFEATURES, 0, + mode, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + u_int8_t reg54 = pci_read_config(parent, 0x54, 1); + + reg54 &= ~(0x03 << (devno << 1)); + if (mode >= ATA_UDMA0) + reg54 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 1)); + pci_write_config(parent, 0x54, reg54, 1); + pci_write_config(parent, 0x4a, 0xa6, 1); + pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); + atadev->mode = mode; + return; + } + } + /* we could set PIO mode timings, but we assume the BIOS did that */ +} + +static void +ata_acard_86X_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + + + mode = ata_limit_mode(atadev, mode, + ATAPI_DEVICE(atadev)?ATA_PIO_MAX:ctlr->chip->max_dma); + + mode = ata_check_80pin(atadev, mode); + +/* XXX missing WDMA0+1 + PIO modes */ + if (mode >= ATA_WDMA2) { + error = ata_command(atadev, ATA_C_SETFEATURES, 0, + mode, ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + u_int16_t reg44 = pci_read_config(parent, 0x44, 2); + + reg44 &= ~(0x000f << (devno << 2)); + if (mode >= ATA_UDMA0) + reg44 |= (((mode & ATA_MODE_MASK) + 1) << (devno << 2)); + pci_write_config(parent, 0x44, reg44, 2); + pci_write_config(parent, 0x4a, 0xa6, 1); + pci_write_config(parent, 0x40 + devno, 0x31, 1); + atadev->mode = mode; + return; + } + } + /* we could set PIO mode timings, but we assume the BIOS did that */ +} + +/* + * Acer Labs Inc (ALI) chipset support functions + */ +int +ata_ali_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_ALI_5229, 0xc4, 0, ALICABLE, ATA_UDMA5, "AcerLabs Aladdin" }, + { ATA_ALI_5229, 0xc2, 0, ALICABLE, ATA_UDMA4, "AcerLabs Aladdin" }, + { ATA_ALI_5229, 0x20, 0, ALIOLD, ATA_UDMA2, "AcerLabs Aladdin" }, + { ATA_ALI_5229, 0x00, 0, ALIOLD, ATA_WDMA2, "AcerLabs Aladdin" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_ali_chipinit; + return 0; +} + +static int +ata_ali_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + /* AcerLabs Aladdin need to deactivate the ATAPI FIFO */ + pci_write_config(dev, 0x53, (pci_read_config(dev, 0x53, 1) & ~0x01)|0x02,1); + + if (ctlr->chip->cfg2 & ALICABLE) + pci_write_config(dev, 0x4b, pci_read_config(dev, 0x4b, 1) | 0x08, 1); + ctlr->setmode = ata_ali_setmode; + return 0; +} + +static void +ata_ali_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + if (ctlr->chip->cfg2 & ALICABLE) { + if (mode > ATA_UDMA2 && + pci_read_config(parent, 0x4a, 1) & (1 << atadev->channel->unit)) { + ata_prtdev(atadev, + "DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + } + else + mode = ata_check_80pin(atadev, mode); + + if (ctlr->chip->cfg2 & ALIOLD) { + /* doesn't support ATAPI DMA on write */ + atadev->channel->flags |= ATA_ATAPI_DMA_RO; + if (atadev->channel->devices & ATA_ATAPI_MASTER && + atadev->channel->devices & ATA_ATAPI_SLAVE) { + /* doesn't support ATAPI DMA on two ATAPI devices */ + ata_prtdev(atadev, "two atapi devices on this channel, no DMA\n"); + ata_limit_mode(atadev, mode, ATA_PIO_MAX); + } + } + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + if (mode >= ATA_UDMA0) { + u_int8_t udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f}; + u_int32_t word54 = pci_read_config(parent, 0x54, 4); + + pci_write_config(parent, 0x58 + (atadev->channel->unit << 2), + 0x00310001, 4); + + pci_write_config(parent, 0x4b, + pci_read_config(parent, 0x4b, 1) | 0x01, 1); + word54 &= ~(0x000f000f << (devno << 2)); + word54 |= (((udma[mode&ATA_MODE_MASK]<<16)|0x05)<<(devno<<2)); + pci_write_config(parent, 0x54, word54, 4); + pci_write_config(parent, 0x53, + pci_read_config(parent, 0x53, 1) | 0x03, 1); + } + else { + u_int32_t piotimings[] = + { 0x006d0003, 0x00580002, 0x00440001, 0x00330001, + 0x00310001, 0x00440001, 0x00330001, 0x00310001}; + + pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 4) & + ~(0x0008000f << (devno << 2)), 4); + + pci_write_config(parent, 0x58 + (atadev->channel->unit << 2), + piotimings[ata_mode2idx(mode)], 4); + + pci_write_config(parent, 0x53, mode > ATA_PIO_MAX ? + (pci_read_config(parent, 0x53, 1) | 0x03, 1) : + (pci_read_config(parent, 0x53, 1) & ~0x01)|0x02,1); + } + atadev->mode = mode; + } +} + +/* + * American Micro Devices (AMD) support function + */ +int +ata_amd_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_AMD756, 0x00, AMDNVIDIA, 0x00, ATA_UDMA4, "AMD 756" }, + { ATA_AMD766, 0x00, AMDNVIDIA, AMDCABLE|AMDBUG, ATA_UDMA5, "AMD 766" }, + { ATA_AMD768, 0x00, AMDNVIDIA, AMDCABLE, ATA_UDMA5, "AMD 768" }, + { ATA_AMD8111, 0x00, AMDNVIDIA, 0x00, ATA_UDMA6, "AMD 8111" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_amd_chipinit; + return 0; +} + +static int +ata_amd_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + /* set prefetch, postwrite */ + if (ctlr->chip->cfg2 & AMDBUG) + pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) & 0x0f, 1); + else + pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1); + + ctlr->setmode = ata_via_family_setmode; + return 0; +} + +/* + * Cyrix chipset support functions + */ +int +ata_cyrix_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (pci_get_devid(dev) == ATA_CYRIX_5530) { + device_set_desc(dev, "Cyrix 5530 ATA33 controller"); + ctlr->chipinit = ata_cyrix_chipinit; + return 0; + } + return ENXIO; +} + +static int +ata_cyrix_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + ctlr->setmode = ata_cyrix_setmode; + return 0; +} + +static void +ata_cyrix_setmode(struct ata_device *atadev, int mode) +{ + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + u_int32_t piotiming[] = + { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }; + u_int32_t dmatiming[] = { 0x00077771, 0x00012121, 0x00002020 }; + u_int32_t udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 }; + int error; + + mode = ata_limit_mode(atadev, mode, ATA_UDMA2); + atadev->channel->dma->alignment = 16; + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on Cyrix chip\n", + (error) ? "failed" : "success", ata_mode2str(mode)); + if (!error) { + if (mode >= ATA_UDMA0) { + ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, + udmatiming[mode % ATA_MODE_MASK]); + } + else if (mode >= ATA_WDMA0) { + ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, + dmatiming[mode % ATA_MODE_MASK]); + } + else { + ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x20, + piotiming[mode % ATA_MODE_MASK]); + } + atadev->mode = mode; + } +} + +/* + * Cypress chipset support functions + */ +int +ata_cypress_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + /* + * the Cypress chip is a mess, it contains two ATA functions, but + * both channels are visible on the first one. + * simply ignore the second function for now, as the right + * solution (ignoring the second channel on the first function) + * doesn't work with the crappy ATA interrupt setup on the alpha. + */ + if (pci_get_devid(dev) == ATA_CYPRESS_82C693 && + pci_get_function(dev) == 0 && + pci_get_subclass(dev) == PCIS_STORAGE_IDE) { + device_set_desc(dev, "Cypress 82C693 ATA controller"); + ctlr->chipinit = ata_cypress_chipinit; + return 0; + } + return ENXIO; +} + +static int +ata_cypress_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + ctlr->setmode = ata_cypress_setmode; + return 0; +} + +static void +ata_cypress_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + int error; + +/* XXX missing WDMA0+1 + PIO modes */ + if (mode == ATA_WDMA2) { + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting WDMA2 on Cypress chip\n", + error ? "failed" : "success"); + if (!error) { + pci_write_config(parent, atadev->channel->unit?0x4e:0x4c,0x2020,2); + atadev->mode = mode; + return; + } + } + /* we could set PIO mode timings, but we assume the BIOS did that */ +} + +/* + * HighPoint chipset support functions + */ +int +ata_highpoint_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_HPT366, 0x05, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" }, + { ATA_HPT366, 0x03, HPT370, 0x00, ATA_UDMA5, "HighPoint HPT370" }, + { ATA_HPT366, 0x02, HPT366, 0x00, ATA_UDMA4, "HighPoint HPT368" }, + { ATA_HPT366, 0x00, HPT366, HPTOLD, ATA_UDMA4, "HighPoint HPT366" }, + { ATA_HPT372, 0x01, HPT372, 0x00, ATA_UDMA6, "HighPoint HPT372" }, + { ATA_HPT374, 0x07, HPT374, 0x00, ATA_UDMA6, "HighPoint HPT374" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_highpoint_chipinit; + return 0; +} + +static int +ata_highpoint_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int rid = ATA_IRQ_RID; + + if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return ENXIO; + } + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ata_highpoint_intr, ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + + if (ctlr->chip->cfg2 == HPTOLD) { + /* turn off interrupt prediction */ + pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x80), 1); + } + else { + /* turn off interrupt prediction */ + pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1); + pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1); + + /* turn on interrupts */ + pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); + + /* set clocks etc */ + if (ctlr->chip->cfg1 < HPT372) + pci_write_config(dev, 0x5b, 0x22, 1); + else + pci_write_config(dev, 0x5b, + (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1); + } + ctlr->setmode = ata_highpoint_setmode; + return 0; +} + +static void +ata_highpoint_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch; + u_int8_t dmastat; + int unit; + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < 2; unit++) { + if (!(ch = ctlr->interrupt[unit].argument)) + continue; + if (((dmastat = ch->dma->status(ch)) & + (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT))!=ATA_BMSTAT_INTERRUPT) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); + DELAY(1); + ctlr->interrupt[unit].function(ch); + } +} + +static void +ata_highpoint_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + u_int32_t timings33[][4] = { + /* HPT366 HPT370 HPT372 HPT374 mode */ + { 0x40d0a7aa, 0x06914e57, 0x0d029d5e, 0x0ac1f48a }, /* PIO 0 */ + { 0x40d0a7a3, 0x06914e43, 0x0d029d26, 0x0ac1f465 }, /* PIO 1 */ + { 0x40d0a753, 0x06514e33, 0x0c829ca6, 0x0a81f454 }, /* PIO 2 */ + { 0x40c8a742, 0x06514e22, 0x0c829c84, 0x0a81f443 }, /* PIO 3 */ + { 0x40c8a731, 0x06514e21, 0x0c829c62, 0x0a81f442 }, /* PIO 4 */ + { 0x20c8a797, 0x26514e97, 0x2c82922e, 0x228082ea }, /* MWDMA 0 */ + { 0x20c8a732, 0x26514e33, 0x2c829266, 0x22808254 }, /* MWDMA 1 */ + { 0x20c8a731, 0x26514e21, 0x2c829262, 0x22808242 }, /* MWDMA 2 */ + { 0x10c8a731, 0x16514e31, 0x1c82dc62, 0x121882ea }, /* UDMA 0 */ + { 0x10cba731, 0x164d4e31, 0x1c9adc62, 0x12148254 }, /* UDMA 1 */ + { 0x10caa731, 0x16494e31, 0x1c91dc62, 0x120c8242 }, /* UDMA 2 */ + { 0x10cfa731, 0x166d4e31, 0x1c8edc62, 0x128c8242 }, /* UDMA 3 */ + { 0x10c9a731, 0x16454e31, 0x1c8ddc62, 0x12ac8242 }, /* UDMA 4 */ + { 0, 0x16454e31, 0x1c6ddc62, 0x12848242 }, /* UDMA 5 */ + { 0, 0, 0x1c81dc62, 0x12808242 } /* UDMA 6 */ + }; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + if (ctlr->chip->cfg1 == HPT366) + mode = ata_limit_mode(atadev, mode, + ATAPI_DEVICE(atadev) ? ATA_PIO_MAX : ATA_UDMA4); + + mode = ata_highpoint_check_80pin(atadev, mode); + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on HighPoint chip\n", + (error) ? "failed" : "success", ata_mode2str(mode)); + if (!error) + pci_write_config(parent, 0x40 + (devno << 2), + timings33[ata_mode2idx(mode)][ctlr->chip->cfg1], 4); + atadev->mode = mode; +} + +static int +ata_highpoint_check_80pin(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + u_int8_t reg, val, res; + + if (ctlr->chip->cfg1 == HPT374 && pci_get_function(parent) == 1) { + reg = atadev->channel->unit ? 0x57 : 0x53; + val = pci_read_config(parent, reg, 1); + pci_write_config(parent, reg, val | 0x80, 1); + } + else { + reg = 0x5b; + val = pci_read_config(parent, reg, 1); + pci_write_config(parent, reg, val & 0xfe, 1); + } + res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x1:0x2); + pci_write_config(parent, reg, val, 1); + + if (mode > ATA_UDMA2 && res) { + ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + return mode; +} + +/* + * Intel chipset support functions + */ +int +ata_intel_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_I82371FB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX" }, + { ATA_I82371SB, 0, 0, 0x00, ATA_WDMA2, "Intel PIIX3" }, + { ATA_I82371AB, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" }, + { ATA_I82443MX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" }, + { ATA_I82451NX, 0, 0, 0x00, ATA_UDMA2, "Intel PIIX4" }, + { ATA_I82801AB, 0, 0, 0x00, ATA_UDMA2, "Intel ICH0" }, + { ATA_I82801AA, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" }, + { ATA_I82372FB, 0, 0, 0x00, ATA_UDMA4, "Intel ICH" }, + { ATA_I82801BA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" }, + { ATA_I82801BA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH2" }, + { ATA_I82801CA, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" }, + { ATA_I82801CA_1, 0, 0, 0x00, ATA_UDMA5, "Intel ICH3" }, + { ATA_I82801DB, 0, 0, 0x00, ATA_UDMA5, "Intel ICH4" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_intel_chipinit; + return 0; +} + +static int +ata_intel_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + if (ctlr->chip->chiptype == ATA_I82371FB) + ctlr->setmode = ata_intel_old_setmode; + else + ctlr->setmode = ata_intel_new_setmode; + return 0; +} + +static void +ata_intel_old_setmode(struct ata_device *atadev, int mode) +{ + /* NOT YET */ +} + +static void +ata_intel_new_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + u_int32_t reg40 = pci_read_config(parent, 0x40, 4); + u_int8_t reg44 = pci_read_config(parent, 0x44, 1); + u_int8_t reg48 = pci_read_config(parent, 0x48, 1); + u_int16_t reg4a = pci_read_config(parent, 0x4a, 2); + u_int16_t reg54 = pci_read_config(parent, 0x54, 2); + u_int32_t mask40 = 0, new40 = 0; + u_int8_t mask44 = 0, new44 = 0; + int error; + u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23, + 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 }; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + if (ctlr->chip->max_dma && mode > ATA_UDMA2 && !(reg54 & (0x10 << devno))) { + ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + if (mode >= ATA_UDMA0) { + pci_write_config(parent, 0x48, reg48 | (0x0001 << devno), 2); + pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno<<2))) | + (0x01 + !(mode & 0x01)), 2); + } + else { + pci_write_config(parent, 0x48, reg48 & ~(0x0001 << devno), 2); + pci_write_config(parent, 0x4a, (reg4a & ~(0x3 << (devno << 2))), 2); + } + if (mode >= ATA_UDMA2) + pci_write_config(parent, 0x54, reg54 | (0x1 << devno), 2); + else + pci_write_config(parent, 0x54, reg54 & ~(0x1 << devno), 2); + + if (mode >= ATA_UDMA5) + pci_write_config(parent, 0x54, reg54 | (0x10000 << devno), 2); + else + pci_write_config(parent, 0x54, reg54 & ~(0x10000 << devno), 2); + + reg40 &= ~0x00ff00ff; + reg40 |= 0x40774077; + + if (atadev->unit == ATA_MASTER) { + mask40 = 0x3300; + new40 = timings[ata_mode2idx(mode)] << 8; + } + else { + mask44 = 0x0f; + new44 = ((timings[ata_mode2idx(mode)] & 0x30) >> 2) | + (timings[ata_mode2idx(mode)] & 0x03); + } + if (atadev->channel->unit) { + mask40 <<= 16; + new40 <<= 16; + mask44 <<= 4; + new44 <<= 4; + } + pci_write_config(parent, 0x40, (reg40 & ~mask40) | new40, 4); + pci_write_config(parent, 0x44, (reg44 & ~mask44) | new44, 1); + atadev->mode = mode; + } +} + +/* + * nVidia chipset support functions + */ +int +ata_nvidia_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_NFORCE1, 0, AMDNVIDIA, NVIDIA|AMDBUG, ATA_UDMA5, "nVidia nForce" }, + { ATA_NFORCE2, 0, AMDNVIDIA, NVIDIA|AMDBUG, ATA_UDMA6, "nVidia nForce2" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_nvidia_chipinit; + return 0; +} + +static int +ata_nvidia_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + /* set prefetch, postwrite */ + if (ctlr->chip->cfg2 & AMDBUG) + pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) & 0x0f, 1); + else + pci_write_config(dev, 0x51, pci_read_config(dev, 0x51, 1) | 0xf0, 1); + + ctlr->setmode = ata_via_family_setmode; + return 0; +} + +/* + * Promise chipset support functions + */ +int +ata_promise_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_PDC20246, 0, PROLD, 0x00, ATA_UDMA2, "Promise" }, + { ATA_PDC20262, 0, PRNEW, 0x00, ATA_UDMA4, "Promise" }, + { ATA_PDC20263, 0, PRNEW, 0x00, ATA_UDMA4, "Promise" }, + { ATA_PDC20265, 0, PRNEW, 0x00, ATA_UDMA5, "Promise" }, + { ATA_PDC20267, 0, PRNEW, 0x00, ATA_UDMA5, "Promise" }, + { ATA_PDC20268, 0, PRTX2, PRTX4, ATA_UDMA5, "Promise TX2" }, + { ATA_PDC20268R, 0, PRTX2, PRTX4, ATA_UDMA5, "Promise TX2" }, + { ATA_PDC20269, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" }, + { ATA_PDC20271, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" }, + { ATA_PDC20275, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" }, + { ATA_PDC20276, 0, PRTX2, PRSX6K, ATA_UDMA6, "Promise TX2" }, + { ATA_PDC20277, 0, PRTX2, 0x00, ATA_UDMA6, "Promise TX2" }, + { ATA_PDC20376, 0, PRTX2, 0x00, ATA_UDMA6, "Promise SATA" }, + { 0, 0, 0, 0, 0, 0}}; + char *desc, buffer[64]; + uintptr_t devid = 0; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + /* if we are on a SuperTrak SX6000 dont attach */ + if (idx->cfg2 & PRSX6K && + !BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)), + GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) && + devid == ATA_I960RM && pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) + return ENXIO; + + if (idx->cfg2 & PRTX4 && + !BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)), + GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) && + devid == ATA_DEC_21150 && + pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) { + static long start = 0, end = 0; + + /* we belive we are on a TX4, now do our (simple) magic */ + if (pci_get_slot(dev) == 1) { + bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &end); + desc = "Promise TX4 (channel 0+1)"; + } + else if (pci_get_slot(dev) == 2 && start && end) { + bus_set_resource(dev, SYS_RES_IRQ, 0, start, end); + start = end = 0; + desc = "Promise TX4 (channel 2+3)"; + } + else { + start = end = 0; + desc = "Promise TX2"; + } + } + else + desc = idx->text; + sprintf(buffer, "%s %s controller", desc, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_promise_chipinit; + return 0; +} + +static int +ata_promise_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int rid = ATA_IRQ_RID; + + if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return ENXIO; + } + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ctlr->chip->cfg1 == PRTX2 ? + ata_promise_tx2_intr : ata_promise_intr, + ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + ctlr->setmode = ata_promise_setmode; + if (ctlr->chip->cfg1 == PRNEW ) + ctlr->dmainit = ata_promise_dmainit; + return 0; +} + +static void +ata_promise_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch = ctlr->interrupt[0].argument; + u_int8_t dmastat; + int unit; + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < 2; unit++) { + if (!(ch = ctlr->interrupt[unit].argument)) + continue; + if (ATA_INL(ch->r_bmio, (ch->unit ? 0x14 : 0x1c)) & + (ch->unit ? 0x00004000 : 0x00000400)) { + if (ch->flags & ATA_DMA_ACTIVE) { + if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, + dmastat | ATA_BMSTAT_INTERRUPT); + DELAY(1); + } + ctlr->interrupt[unit].function(ch); + } + } +} + +static void +ata_promise_tx2_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch; + u_int8_t dmastat; + int unit; + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < 2; unit++) { + if (!(ch = ctlr->interrupt[unit].argument)) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); + if (ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x20) { + if (ch->flags & ATA_DMA_ACTIVE) { + if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, + dmastat | ATA_BMSTAT_INTERRUPT); + DELAY(1); + } + ctlr->interrupt[unit].function(ch); + } + } +} + +static void +ata_promise_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + u_int32_t timings33[][2] = { + /* PROLD PRNEW mode */ + { 0x004ff329, 0x004fff2f }, /* PIO 0 */ + { 0x004fec25, 0x004ff82a }, /* PIO 1 */ + { 0x004fe823, 0x004ff026 }, /* PIO 2 */ + { 0x004fe622, 0x004fec24 }, /* PIO 3 */ + { 0x004fe421, 0x004fe822 }, /* PIO 4 */ + { 0x004567f3, 0x004acef6 }, /* MWDMA 0 */ + { 0x004467f3, 0x0048cef6 }, /* MWDMA 1 */ + { 0x004367f3, 0x0046cef6 }, /* MWDMA 2 */ + { 0x004367f3, 0x0046cef6 }, /* UDMA 0 */ + { 0x004247f3, 0x00448ef6 }, /* UDMA 1 */ + { 0x004127f3, 0x00436ef6 }, /* UDMA 2 */ + { 0, 0x00424ef6 }, /* UDMA 3 */ + { 0, 0x004127f3 }, /* UDMA 4 */ + { 0, 0x004127f3 } /* UDMA 5 */ + }; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + /* is this a TX2 or later chip ? */ + if (ctlr->chip->cfg1 >= PRTX2) { + ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); + if (mode > ATA_UDMA2 && + ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04) { + ata_prtdev(atadev, + "DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + } + else { + if (mode > ATA_UDMA2 && (pci_read_config(parent, 0x50, 2) & + (atadev->channel->unit ? 1 << 11 : 1 << 10))) { + ata_prtdev(atadev, + "DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + if (!ATAPI_DEVICE(atadev) && mode > ATA_PIO_MAX) + mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX); + } + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + if (ctlr->chip->cfg1 < PRTX2) + pci_write_config(device_get_parent(atadev->channel->dev), + 0x60 + (devno << 2), + timings33[ctlr->chip->cfg1][ata_mode2idx(mode)],4); + atadev->mode = mode; + } + return; +} + +static int +ata_promise_dmainit(struct ata_channel *ch) +{ + int error; + + if ((error = ata_dmainit(ch))) + return error; + + ch->dma->start = ata_promise_dmastart; + ch->dma->stop = ata_promise_dmastop; + return 0; +} + +static int +ata_promise_dmastart(struct ata_device *atadev, + caddr_t data, int32_t count, int dir) +{ + struct ata_channel *ch = atadev->channel; + int error; + + if ((error = ata_dmastart(atadev, data, count, dir))) + return error; + + if (ch->flags & ATA_48BIT_ACTIVE) { + ATA_OUTB(ch->r_bmio, (ch->unit ? 0x09 : 0x11), + ATA_INB(ch->r_bmio, (ch->unit ? 0x09 : 0x11)) | + (ch->unit ? 0x08 : 0x02)); + ATA_OUTL(ch->r_bmio, (ch->unit ? 0x1c : 0x20), + (dir ? 0x05000000 : 0x06000000) | (count >> 1)); + } + return 0; +} + +static int +ata_promise_dmastop(struct ata_device *atadev) +{ + struct ata_channel *ch = atadev->channel; + + if (ch->flags & ATA_48BIT_ACTIVE) { + ATA_OUTB(ch->r_bmio, (ch->unit ? 0x09 : 0x11), + ATA_INB(ch->r_bmio, (ch->unit ? 0x09 : 0x11)) & + ~(ch->unit ? 0x08 : 0x02)); + ATA_OUTL(ch->r_bmio, (ch->unit ? 0x1c : 0x20), 0); + } + return ata_dmastop(atadev); +} + +/* + * ServerWorks chipset support functions + */ +int +ata_serverworks_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_ROSB4, 0x00, SWKS33, 0x00, ATA_UDMA2, "ServerWorks ROSB4" }, + { ATA_CSB5, 0x92, SWKS100, 0x00, ATA_UDMA5, "ServerWorks CSB5" }, + { ATA_CSB5, 0x00, SWKS66, 0x00, ATA_UDMA4, "ServerWorks CSB5" }, + { ATA_CSB6, 0x00, SWKS100, 0x00, ATA_UDMA5, "ServerWorks CSB6" }, + { ATA_CSB6_1, 0x00, SWKS66, 0x00, ATA_UDMA4, "ServerWorks CSB6" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_serverworks_chipinit; + return 0; +} + +static int +ata_serverworks_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + if (ctlr->chip->cfg1 > SWKS33) + pci_write_config(dev, 0x5a, + (pci_read_config(dev, 0x5a, 1) & ~0x40) | + (ctlr->chip->cfg1 == SWKS100) ? 0x03 : 0x02, 1); + else + pci_write_config(dev, 0x64, + (pci_read_config(dev, 0x64, 4) & ~0x00002000) | + 0x00004000, 4); + ctlr->setmode = ata_serverworks_setmode; + return 0; +} + +static void +ata_serverworks_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int offset = devno ^ 0x01; + int error; + u_int8_t timings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + mode = ata_check_80pin(atadev, mode); + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + if (mode >= ATA_UDMA0) { + pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 1) | + (0x01 << devno), 1); + pci_write_config(parent, 0x56, + (pci_read_config(parent, 0x56, 2) & + ~(0xf << (devno << 2))) | + ((mode & ATA_MODE_MASK) << (devno << 2)), 2); + } + else + pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 1) | + ~(0x01 << devno), 1); + + pci_write_config(parent, 0x54, pci_read_config(parent, 0x54, 1) & + ~(0x01 << devno), 1); + pci_write_config(parent, 0x44, + (pci_read_config(parent, 0x44, 4) & + ~(0xff << (offset << 8))) | + (timings[ata_mode2idx(mode)] << (offset << 8)), 4); + atadev->mode = mode; + } +} + +/* + * Silicon Image (former CMD) chipset support functions + */ +int +ata_sii_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_SII0680, 0x00, SII_SETCLK, 0x00, ATA_UDMA6, "SiI 0680" }, + { ATA_CMD649, 0x00, 0, SII_INTR, ATA_UDMA5, "CMD 649" }, + { ATA_CMD648, 0x00, 0, SII_INTR, ATA_UDMA4, "CMD 648" }, + { ATA_CMD646, 0x07, 0, 0x00, ATA_UDMA2, "CMD 646U2" }, + { ATA_CMD646, 0x00, 0, 0x00, ATA_WDMA2, "CMD 646" }, + { 0, 0, 0, 0, 0, 0}}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_sii_chipinit; + return 0; +} + +static int +ata_sii_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int rid = ATA_IRQ_RID; + + if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return ENXIO; + } + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ctlr->chip->cfg2 & SII_INTR ? + ata_cmd_intr : ata_generic_intr, + ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + + if (ctlr->chip->cfg1 == SII_SETCLK) { + if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) + pci_write_config(dev, 0x8a, + (pci_read_config(dev, 0x8a, 1) & 0x0F) | 0x10, 1); + if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) + device_printf(dev, "%s could not set ATA133 clock\n", + ctlr->chip->text); + ctlr->setmode = ata_sii_setmode; + } + else + ctlr->setmode = ata_cmd_setmode; + return 0; +} + +static void +ata_cmd_intr(void *data) +{ + struct ata_pci_controller *ctlr = data; + struct ata_channel *ch; + u_int8_t dmastat; + int unit; + + /* implement this as a toggle instead to balance load XXX */ + for (unit = 0; unit < 2; unit++) { + if (!(ch = ctlr->interrupt[unit].argument)) + continue; + if (!(pci_read_config(device_get_parent(ch->dev), 0x71, 1) & + (ch->unit ? 0x08 : 0x04))) + continue; + pci_write_config(device_get_parent(ch->dev), 0x71, + (ch->unit ? 0x08 : 0x04), 1); + if (ch->flags & ATA_DMA_ACTIVE) { + if (!((dmastat = ch->dma->status(ch)) & ATA_BMSTAT_INTERRUPT)) + continue; + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); + DELAY(1); + } + ctlr->interrupt[unit].function(ch); + } +} + +static void +ata_sii_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 4) + (ATA_DEV(atadev->unit) << 1); + int mreg = atadev->channel->unit ? 0x84 : 0x80; + int mask = 0x03 << (ATA_DEV(atadev->unit) << 2); + int mval = pci_read_config(parent, mreg, 1) & ~mask; + int error; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + mode = ata_check_80pin(atadev, mode); + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + if (mode >= ATA_UDMA0) { + u_int8_t udmatimings[] = { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 }; + u_int8_t ureg = 0xac + devno; + + pci_write_config(parent, mreg, + mval | (0x03 << (ATA_DEV(atadev->unit) << 2)), 1); + pci_write_config(parent, ureg, + (pci_read_config(parent, ureg, 1) & 0x3f) | + udmatimings[mode & ATA_MODE_MASK], 1); + + } + else if (mode >= ATA_WDMA0) { + u_int8_t dreg = 0xa8 + devno; + u_int16_t dmatimings[] = { 0x2208, 0x10c2, 0x10c1 }; + + pci_write_config(parent, mreg, + mval | (0x02 << (ATA_DEV(atadev->unit) << 2)), 1); + pci_write_config(parent, dreg, dmatimings[mode & ATA_MODE_MASK], 2); + + } + else { + u_int8_t preg = 0xa4 + devno; + u_int16_t piotimings[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; + + pci_write_config(parent, mreg, + mval | (0x01 << (ATA_DEV(atadev->unit) << 2)), 1); + pci_write_config(parent, preg, piotimings[mode & ATA_MODE_MASK], 2); + } + atadev->mode = mode; + } +} + +static void +ata_cmd_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + mode = ata_check_80pin(atadev, mode); + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + int treg = 0x54 + (devno < 3) ? (devno << 1) : 7; + int ureg = atadev->channel->unit ? 0x7b : 0x73; + + if (mode >= ATA_UDMA0) { + int udmatimings[][2] = { { 0x31, 0xc2 }, { 0x21, 0x82 }, + { 0x11, 0x42 }, { 0x25, 0x8a }, + { 0x15, 0x4a }, { 0x05, 0x0a } }; + + u_int8_t umode = pci_read_config(parent, ureg, 1); + + umode &= ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca); + umode |= udmatimings[ATA_DEV(atadev->unit)][mode & ATA_MODE_MASK]; + pci_write_config(parent, ureg, umode, 1); + } + else if (mode >= ATA_WDMA0) { + int dmatimings[] = { 0x87, 0x32, 0x3f }; + + pci_write_config(parent, treg, dmatimings[mode & ATA_MODE_MASK], 1); + pci_write_config(parent, ureg, + pci_read_config(parent, ureg, 1) & + ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1); + } + else { + int piotimings[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f }; + pci_write_config(parent, treg, + piotimings[(mode & ATA_MODE_MASK) - ATA_PIO0], 1); + pci_write_config(parent, ureg, + pci_read_config(parent, ureg, 1) & + ~(atadev->unit == ATA_MASTER ? 0x35 : 0xca), 1); + } + atadev->mode = mode; + } +} + +/* + * SiS chipset support functions + */ +int +ata_sis_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_SIS963, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 963" }, /* south */ + { ATA_SIS962, 0x00, SIS133NEW, 0, ATA_UDMA6, "SiS 962" }, /* south */ + + { ATA_SIS755, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 755" }, /* ext south */ + { ATA_SIS752, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 752" }, /* unknown */ + { ATA_SIS751, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 751" }, /* unknown */ + { ATA_SIS750, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 750" }, /* unknown */ + { ATA_SIS748, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 748" }, /* unknown */ + { ATA_SIS746, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 746" }, /* ext south */ + { ATA_SIS745, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 745" }, /* 1chip */ + { ATA_SIS740, 0x00, SIS_SOUTH, 0, ATA_UDMA5, "SiS 740" }, /* ext south */ + { ATA_SIS735, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 735" }, /* 1chip */ + { ATA_SIS733, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 733" }, /* 1chip */ + { ATA_SIS730, 0x00, SIS100OLD, 0, ATA_UDMA5, "SiS 730" }, /* 1chip */ + + { ATA_SIS658, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 658" }, /* ext south */ + { ATA_SIS655, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 655" }, /* ext south */ + { ATA_SIS652, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 652" }, /* unknown */ + { ATA_SIS651, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 651" }, /* ext south */ + { ATA_SIS650, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 650" }, /* ext south */ + { ATA_SIS648, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 648" }, /* ext south */ + { ATA_SIS646, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 645DX" },/* ext south */ + { ATA_SIS645, 0x00, SIS_SOUTH, 0, ATA_UDMA6, "SiS 645" }, /* ext south */ + { ATA_SIS640, 0x00, SIS_SOUTH, 0, ATA_UDMA4, "SiS 640" }, /* ext south */ + { ATA_SIS635, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 635" }, /* unknown */ + { ATA_SIS633, 0x00, SIS100NEW, 0, ATA_UDMA5, "SiS 633" }, /* unknown */ + { ATA_SIS630, 0x30, SIS100NEW, 0, ATA_UDMA5, "SiS 630S" }, /* 1chip */ + { ATA_SIS630, 0x00, SIS66, 0, ATA_UDMA4, "SiS 630" }, /* 1chip */ + { ATA_SIS620, 0x00, SIS66, 0, ATA_UDMA4, "SiS 620" }, /* 1chip */ + + { ATA_SIS550, 0x00, SIS66, 0, ATA_UDMA5, "SiS 550" }, + { ATA_SIS540, 0x00, SIS66, 0, ATA_UDMA4, "SiS 540" }, + { ATA_SIS530, 0x00, SIS66, 0, ATA_UDMA4, "SiS 530" }, + { 0, 0, 0, 0, 0, 0 }}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + if (idx->cfg1 == SIS_SOUTH) { + pci_write_config(dev, 0x57, pci_read_config(dev, 0x57, 1) & 0x7f, 1); + if (pci_read_config(dev, 0x00, 4) == ATA_SIS5518) { + idx->cfg1 = SIS133NEW; + sprintf(buffer, "SiS 96X %s controller",ata_mode2str(idx->max_dma)); + } + else { + if (ata_find_dev(dev, ATA_SISSOUTH, 0x10)) + idx->cfg1 = SIS133OLD; + else { + idx->max_dma = ATA_UDMA5; + idx->cfg1 = SIS100NEW; + } + sprintf(buffer, "SiS 961 %s controller",ata_mode2str(idx->max_dma)); + } + pci_write_config(dev, 0x57, pci_read_config(dev, 0x57, 1) | 0x80, 1); + } + else + sprintf(buffer,"%s %s controller",idx->text,ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_sis_chipinit; + return 0; +} + +static int +ata_sis_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + switch (ctlr->chip->cfg1) { + case SIS66: + case SIS100OLD: + pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 1) | 0x04, 1); + break; + case SIS100NEW: + case SIS133OLD: + pci_write_config(dev, 0x49, pci_read_config(dev, 0x49, 1) | 0x01, 1); + break; + case SIS133NEW: + pci_write_config(dev, 0x50, pci_read_config(dev, 0x50, 2) & 0xfff7, 2); + pci_write_config(dev, 0x52, pci_read_config(dev, 0x52, 2) & 0xfff7, 2); + break; + default: + return ENXIO; + } + ctlr->setmode = ata_sis_setmode; + return 0; +} + +static void +ata_sis_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int error; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + if (ctlr->chip->cfg1 == SIS133NEW) { + if (mode > ATA_UDMA2 && + pci_read_config(parent, atadev->channel->unit?0x52:0x50,2)&0x8000){ + ata_prtdev(atadev, + "DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + } + else { + if (mode > ATA_UDMA2 && + pci_read_config(parent, 0x48, 1) & atadev->channel->unit?0x20:0x10){ + ata_prtdev(atadev, + "DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + } + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", + ata_mode2str(mode), ctlr->chip->text); + if (!error) { + switch (ctlr->chip->cfg1) { + case SIS133NEW: { + u_int32_t timings[] = + { 0x28269008, 0x0c266008, 0x04263008, 0x0c0a3008, 0x05093008, + 0x22190608, 0x0c0a3008, 0x05093008, 0x050939fc, 0x050936ac, + 0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c}; + u_int32_t reg; + + reg = (pci_read_config(parent, 0x57, 1)&0x40?0x70:0x40)+(devno<<2); + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 4); + break; + } + case SIS133OLD: { + u_int16_t timings[] = + { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031, + 0x8f31, 0x8a31, 0x8731, 0x8531, 0x8331, 0x8231, 0x8131 }; + + u_int16_t reg = 0x40 + (devno << 1); + + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2); + break; + } + case SIS100NEW: { + u_int16_t timings[] = + { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, + 0x0031, 0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 }; + u_int16_t reg = 0x40 + (devno << 1); + + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2); + break; + } + case SIS100OLD: + case SIS66: { + u_int16_t timings[] = + { 0x0c0b, 0x0607, 0x0404, 0x0303, 0x0301, 0x0404, 0x0303, + 0x0301, 0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 }; + u_int16_t reg = 0x40 + (devno << 1); + + pci_write_config(parent, reg, timings[ata_mode2idx(mode)], 2); + break; + } + } + atadev->mode = mode; + } +} + +/* VIA chipsets */ +int +ata_via_ident(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + struct ata_chip_id *idx; + static struct ata_chip_id ids[] = + {{ ATA_VIA82C586, 0x02, VIA33, 0x00, ATA_UDMA2, "VIA 82C586b" }, + { ATA_VIA82C586, 0x00, VIA33, 0x00, ATA_WDMA2, "VIA 82C586" }, + { ATA_VIA82C596, 0x12, VIA66, VIACLK, ATA_UDMA4, "VIA 82C596b" }, + { ATA_VIA82C596, 0x00, VIA33, 0x00, ATA_UDMA2, "VIA 82C596" }, + { ATA_VIA82C686, 0x40, VIA100, VIABUG, ATA_UDMA5, "VIA 82C686b"}, + { ATA_VIA82C686, 0x10, VIA66, VIACLK, ATA_UDMA4, "VIA 82C686a" }, + { ATA_VIA82C686, 0x00, VIA33, 0x00, ATA_UDMA2, "VIA 82C686" }, + { ATA_VIA8231, 0x00, VIA100, VIABUG, ATA_UDMA5, "VIA 8231" }, + { ATA_VIA8233, 0x00, VIA100, 0x00, ATA_UDMA5, "VIA 8233" }, + { ATA_VIA8233C, 0x00, VIA100, 0x00, ATA_UDMA5, "VIA 8233c" }, + { ATA_VIA8233A, 0x00, VIA133, 0x00, ATA_UDMA6, "VIA 8233a" }, + { ATA_VIA8235, 0x00, VIA133, 0x00, ATA_UDMA6, "VIA 8235" }, + { 0, 0, 0, 0, 0, 0 }}; + char buffer[64]; + + if (!(idx = ata_match_chip(dev, ids))) + return ENXIO; + + sprintf(buffer, "%s %s controller", idx->text, ata_mode2str(idx->max_dma)); + device_set_desc_copy(dev, buffer); + ctlr->chip = idx; + ctlr->chipinit = ata_via_chipinit; + return 0; +} + +static int +ata_via_chipinit(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + + if (ata_default_interrupt(dev)) + return ENXIO; + + /* prepare for ATA-66 on the 82C686a and 82C596b */ + if (ctlr->chip->cfg2 & VIACLK) + pci_write_config(dev, 0x50, 0x030b030b, 4); + + /* the southbridge might need the data corruption fix */ + if (ctlr->chip->cfg2 & VIABUG) + ata_via_southbridge_fixup(dev); + + /* set prefetch, postwrite */ + pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1); + + /* set fifo configuration half'n'half */ + pci_write_config(dev, 0x43, + (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1); + + /* set status register read retry */ + pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1); + + /* set DMA read & end-of-sector fifo flush */ + pci_write_config(dev, 0x46, + (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1); + + /* set sector size */ + pci_write_config(dev, 0x60, DEV_BSIZE, 2); + pci_write_config(dev, 0x68, DEV_BSIZE, 2); + + ctlr->setmode = ata_via_family_setmode; + return 0; +} + +static void +ata_via_southbridge_fixup(device_t dev) +{ + device_t *children; + int nchildren, i; + + if (device_get_children(device_get_parent(dev), &children, &nchildren)) + return; + + for (i = 0; i < nchildren; i++) { + if (pci_get_devid(children[i]) == ATA_VIA8363 || + pci_get_devid(children[i]) == ATA_VIA8371 || + pci_get_devid(children[i]) == ATA_VIA8662 || + pci_get_devid(children[i]) == ATA_VIA8361) { + u_int8_t reg76 = pci_read_config(children[i], 0x76, 1); + + if ((reg76 & 0xf0) != 0xd0) { + device_printf(dev, + "Correcting VIA config for southbridge data corruption bug\n"); + pci_write_config(children[i], 0x75, 0x80, 1); + pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1); + } + break; + } + } + free(children, M_TEMP); +} + +/* common code for VIA, AMD & nVidia */ +static void +ata_via_family_setmode(struct ata_device *atadev, int mode) +{ + device_t parent = device_get_parent(atadev->channel->dev); + struct ata_pci_controller *ctlr = device_get_softc(parent); + u_int8_t timings[] = { 0xff, 0xff, 0xff, 0x55, 0x51, 0xff, 0x55, 0x51, + 0x51, 0x51, 0x51, 0x51, 0x51, 0x51 }; + int modes[][7] = { + { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ + { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ + { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ + { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */ + { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */ + int devno = (atadev->channel->unit << 1) + ATA_DEV(atadev->unit); + int reg = 0x53 - devno; + int error; + + mode = ata_limit_mode(atadev, mode, ctlr->chip->max_dma); + + if (ctlr->chip->cfg2 & AMDCABLE) { + if (mode > ATA_UDMA2 && !pci_read_config(parent, 0x42, 1) & (1<<devno)){ + ata_prtdev(atadev, + "DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + } + else + mode = ata_check_80pin(atadev, mode); + + if (ctlr->chip->cfg2 & NVIDIA) + reg += 0x10; + + pci_write_config(parent, reg - 0x08, timings[ata_mode2idx(mode)], 1); + + error = ata_command(atadev, ATA_C_SETFEATURES, 0, mode, + ATA_C_F_SETXFER, ATA_WAIT_READY); + if (bootverbose) + ata_prtdev(atadev, "%s setting %s on %s chip\n", + (error) ? "failed" : "success", ata_mode2str(mode), + ctlr->chip->text); + if (!error) { + if (mode >= ATA_UDMA0) + pci_write_config(parent, reg, + modes[ctlr->chip->cfg1][mode & ATA_MODE_MASK], 1); + else + pci_write_config(parent, reg, 0x8b, 1); + atadev->mode = mode; + } +} + +/* misc functions */ +static int +ata_mode2idx(int mode) +{ + if ((mode & ATA_DMA_MASK) == ATA_UDMA0) + return (mode & ATA_MODE_MASK) + 8; + if ((mode & ATA_DMA_MASK) == ATA_WDMA0) + return (mode & ATA_MODE_MASK) + 5; + return (mode & ATA_MODE_MASK) - ATA_PIO0; +} + +static int +ata_check_80pin(struct ata_device *atadev, int mode) +{ + if (mode > ATA_UDMA2 && !atadev->param->hwres_cblid) { + ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); + mode = ATA_UDMA2; + } + return mode; +} + +static int +ata_find_dev(device_t dev, u_int32_t devid, u_int32_t revid) +{ + device_t *children; + int nchildren, i; + + if (device_get_children(device_get_parent(dev), &children, &nchildren)) + return 0; + + for (i = 0; i < nchildren; i++) { + if (pci_get_devid(children[i]) == devid && + pci_get_revid(children[i]) >= revid) { + free(children, M_TEMP); + return 1; + } + } + free(children, M_TEMP); + return 0; +} + +static struct ata_chip_id * +ata_match_chip(device_t dev, struct ata_chip_id *index) +{ + while (index->chiptype != 0) { + if (ata_find_dev(dev, index->chiptype, index->chiprev)) + return index; + index++; + } + return NULL; +} + +static int +ata_default_interrupt(device_t dev) +{ + struct ata_pci_controller *ctlr = device_get_softc(dev); + int rid = ATA_IRQ_RID; + + if (!ATA_MASTERDEV(dev)) { + if (!(ctlr->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return ENXIO; + } + if ((bus_setup_intr(dev, ctlr->r_irq, INTR_TYPE_BIO | INTR_ENTROPY, + ata_generic_intr, ctlr, &ctlr->handle))) { + device_printf(dev, "unable to setup interrupt\n"); + return ENXIO; + } + } + return 0; +} + +static void +ata_pci_serialize(struct ata_channel *ch, int flags) +{ + struct ata_pci_controller *scp = + device_get_softc(device_get_parent(ch->dev)); + + switch (flags) { + case ATA_LF_LOCK: + if (scp->locked_ch == ch->unit) + break; + while (!atomic_cmpset_acq_int(&scp->locked_ch, -1, ch->unit)) + tsleep((caddr_t)ch->locking, PRIBIO, "atalck", 1); + break; + + case ATA_LF_UNLOCK: + if (scp->locked_ch == -1 || scp->locked_ch != ch->unit) + break; + atomic_store_rel_int(&scp->locked_ch, -1); + wakeup((caddr_t)ch->locking); + break; + } + return; +} diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 49f2062..450011a 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,7 @@ #include <machine/bus.h> #include <sys/rman.h> #include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> #include <dev/ata/ata-disk.h> #include <dev/ata/ata-raid.h> @@ -182,11 +183,10 @@ ad_attach(struct ata_device *atadev) } /* use DMA if allowed and if drive/controller supports it */ - if (ata_dma) - ata_dmainit(atadev, ata_pmode(atadev->param), - ata_wmode(atadev->param), ata_umode(atadev->param)); + if (ata_dma && atadev->channel->dma) + atadev->setmode(atadev, ATA_DMA_MAX); else - ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1); + atadev->setmode(atadev, ATA_PIO_MAX); /* use tagged queueing if allowed and supported */ if (ata_tags && ad_tagsupported(adp)) { @@ -249,7 +249,8 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */ biofinish(request->bp, NULL, ENXIO); ad_free(request); } - ata_dmafree(atadev); + if (atadev->channel->dma) + atadev->channel->dma->free(atadev); while ((bp = bioq_first(&adp->queue))) { bioq_remove(&adp->queue, bp); biofinish(bp, NULL, ENXIO); @@ -288,12 +289,12 @@ adclose(dev_t dev, int flags, int fmt, struct thread *td) { struct ad_softc *adp = dev->si_drv1; - adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL); if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY)) ata_prtdev(adp->device, "flushing cache on close failed\n"); ATA_UNLOCK_CH(adp->device->channel); - adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK); return 0; } @@ -326,9 +327,9 @@ addump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t leng if (!once) { /* force PIO mode for dumps */ adp->device->mode = ATA_PIO; - adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK); ata_reinit(adp->device->channel); - adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK); once = 1; } @@ -388,7 +389,7 @@ ad_start(struct ata_device *atadev) if (bp->bio_cmd == BIO_READ) request->flags |= ADR_F_READ; - if (adp->device->mode >= ATA_DMA && ata_dmaalloc(atadev)) + if (adp->device->mode >= ATA_DMA && atadev->channel->dma->alloc(atadev)) adp->device->mode = ATA_PIO; /* insert in tag array */ @@ -452,7 +453,7 @@ ad_transfer(struct ad_request *request) /* does this drive & transfer work with DMA ? */ request->flags &= ~ADR_F_DMA_USED; if (adp->device->mode >= ATA_DMA && - !ata_dmasetup(adp->device, request->data, request->bytecount)) { + !adp->device->channel->dma->setup(adp->device, request->data, request->bytecount)) { request->flags |= ADR_F_DMA_USED; request->currentsize = request->bytecount; @@ -501,7 +502,7 @@ ad_transfer(struct ad_request *request) } /* start transfer, return and wait for interrupt */ - ata_dmastart(adp->device, request->data, request->bytecount, + adp->device->channel->dma->start(adp->device, request->data, request->bytecount, request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -571,7 +572,7 @@ ad_interrupt(struct ad_request *request) /* finish DMA transfer */ if (request->flags & ADR_F_DMA_USED) - dma_stat = ata_dmadone(adp->device); + dma_stat = adp->device->channel->dma->stop(adp->device); /* do we have a corrected soft error ? */ if (adp->device->channel->status & ATA_S_CORR) @@ -596,24 +597,24 @@ ad_interrupt(struct ad_request *request) if (request->retries++ < AD_MAX_RETRIES) printf(" retrying\n"); else { - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); + adp->device->setmode(adp->device, ATA_PIO_MAX); printf(" falling back to PIO mode\n"); } TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain); return ATA_OP_FINISHED; } - +#if 0 /* XXX*/ /* if using DMA, try once again in PIO mode */ if (request->flags & ADR_F_DMA_USED) { untimeout((timeout_t *)ad_timeout, request,request->timeout_handle); ad_invalidatequeue(adp, request); - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); + adp->device->setmode(adp->device, ATA_PIO_MAX); request->flags |= ADR_F_FORCE_PIO; printf(" trying PIO mode\n"); TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain); return ATA_OP_FINISHED; } - +#endif request->flags |= ADR_F_ERROR; printf(" status=%02x error=%02x\n", adp->device->channel->status, adp->device->channel->error); @@ -761,7 +762,7 @@ ad_service(struct ad_softc *adp, int change) ad_invalidatequeue(adp, NULL); return ATA_OP_FINISHED; } - ata_dmastart(adp->device, request->data, request->bytecount, + adp->device->channel->dma->start(adp->device, request->data, request->bytecount, request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -802,12 +803,10 @@ ad_invalidatequeue(struct ad_softc *adp, struct ad_request *request) static int ad_tagsupported(struct ad_softc *adp) { + /* check for controllers that we know doesn't support tags */ switch (adp->device->channel->chiptype) { - case 0x0d30105a: /* Promises before TX2 doesn't work with tagged queuing */ - case 0x0d38105a: - case 0x4d30105a: - case 0x4d33105a: - case 0x4d38105a: + case ATA_PDC20265: case ATA_PDC20263: case ATA_PDC20267: + case ATA_PDC20246: case ATA_PDC20262: return 0; } @@ -851,10 +850,10 @@ ad_timeout(struct ad_request *request) request->tag, request->serv); if (request->flags & ADR_F_DMA_USED) { - ata_dmadone(adp->device); + adp->device->channel->dma->stop(adp->device); ad_invalidatequeue(adp, request); if (request->retries == AD_MAX_RETRIES) { - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); + adp->device->setmode(adp->device, ATA_PIO_MAX); ata_prtdev(adp->device, "trying fallback to PIO mode\n"); request->retries = 0; } @@ -883,12 +882,7 @@ ad_reinit(struct ata_device *atadev) ad_invalidatequeue(atadev->driver, NULL); ata_command(atadev, ATA_C_SET_MULTI, 0, adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY); - if (adp->device->mode >= ATA_DMA) - ata_dmainit(atadev, ata_pmode(adp->device->param), - ata_wmode(adp->device->param), - ata_umode(adp->device->param)); - else - ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1); + atadev->setmode(atadev, adp->device->mode); } void diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index 0c190d1..db9156b 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index c6ab3a5..7f1353b 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/ata.h> +#include <sys/kernel.h> #include <sys/endian.h> #include <sys/malloc.h> #include <sys/bus.h> @@ -38,32 +39,54 @@ #include <machine/bus.h> #include <sys/rman.h> #include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> /* prototypes */ -static void ata_dmacreate(struct ata_device *, int, int); -static void ata_dmasetupd_cb(void *, bus_dma_segment_t *, int, int); static void ata_dmasetupc_cb(void *, bus_dma_segment_t *, int, int); -static void cyrix_timing(struct ata_device *, int, int); -static void promise_timing(struct ata_device *, int, int); -static void hpt_timing(struct ata_device *, int, int); -static int hpt_cable80(struct ata_device *); +static int ata_dmaalloc(struct ata_device *); +static void ata_dmafree(struct ata_device *); +static void ata_dmacreate(struct ata_channel *); +static void ata_dmadestroy(struct ata_channel *); +static void ata_dmasetupd_cb(void *, bus_dma_segment_t *, int, int); +static int ata_dmasetup(struct ata_device *, caddr_t, int32_t); +/* +static int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); +static int ata_dmastop(struct ata_device *); +*/ +static int ata_dmastatus(struct ata_channel *); -/* misc defines */ -#define ATAPI_DEVICE(atadev) \ - ((atadev->unit == ATA_MASTER && \ - atadev->channel->devices & ATA_ATAPI_MASTER) || \ - (atadev->unit == ATA_SLAVE && \ - atadev->channel->devices & ATA_ATAPI_SLAVE)) +/* local vars */ +static MALLOC_DEFINE(M_ATADMA, "ATA DMA", "ATA driver DMA"); -#define MAXSEGSZ PAGE_SIZE -#define MAXTABSZ PAGE_SIZE -#define MAXCTLDMASZ (2 * (MAXTABSZ + MAXPHYS)) +/* misc defines */ +#define MAXSEGSZ PAGE_SIZE +#define MAXTABSZ PAGE_SIZE +#define MAXCTLDMASZ (2 * (MAXTABSZ + MAXPHYS)) struct ata_dc_cb_args { bus_addr_t maddr; int error; }; +int +ata_dmainit(struct ata_channel *ch) +{ + if (!(ch->dma = + malloc(sizeof(struct ata_dma_funcs), M_ATADMA, M_NOWAIT | M_ZERO))) + return ENOMEM; + ch->dma->create = ata_dmacreate; + ch->dma->destroy = ata_dmadestroy; + ch->dma->alloc = ata_dmaalloc; + ch->dma->free = ata_dmafree; + ch->dma->setup = ata_dmasetup; + ch->dma->start = ata_dmastart; + ch->dma->stop = ata_dmastop; + ch->dma->status = ata_dmastatus; + ch->dma->alignment = 2; + return 0; +} + + static void ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) { @@ -73,7 +96,7 @@ ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) cba->maddr = segs[0].ds_addr; } -int +static int ata_dmaalloc(struct ata_device *atadev) { struct ata_channel *ch; @@ -92,7 +115,7 @@ ata_dmaalloc(struct ata_device *atadev) return error; } if (!ds->ddmatag) { - if ((error = bus_dma_tag_create(ch->dmatag, ch->alignment + 1, 0, + if ((error = bus_dma_tag_create(ch->dmatag, ch->dma->alignment, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXPHYS, ATA_DMA_ENTRIES, MAXSEGSZ, @@ -119,7 +142,7 @@ ata_dmaalloc(struct ata_device *atadev) return 0; } -void +static void ata_dmafree(struct ata_device *atadev) { struct ata_dmastate *ds; @@ -146,1326 +169,27 @@ ata_dmafree(struct ata_device *atadev) } } -void -ata_dmafreetags(struct ata_channel *ch) -{ - - if (ch->dmatag) { - bus_dma_tag_destroy(ch->dmatag); - ch->dmatag = NULL; - } -} - static void -ata_dmacreate(struct ata_device *atadev, int apiomode, int mode) +ata_dmacreate(struct ata_channel *ch) { - atadev->mode = mode; - if (!atadev->channel->dmatag) { + if (!ch->dmatag) { if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXCTLDMASZ, ATA_DMA_ENTRIES, - BUS_SPACE_MAXSIZE_32BIT, 0, - &atadev->channel->dmatag)) { - ata_prtdev(atadev, "DMA tag allocation failed, disabling DMA\n"); - ata_dmainit(atadev, apiomode, -1, -1); + BUS_SPACE_MAXSIZE_32BIT, 0, &ch->dmatag)) { + printf("DMA tag allocation failed, disabling DMA\n"); } } } -void -ata_dmainit(struct ata_device *atadev, int apiomode, int wdmamode, int udmamode) +static void +ata_dmadestroy(struct ata_channel *ch) { - device_t parent = device_get_parent(atadev->channel->dev); - int chiptype = atadev->channel->chiptype; - int chiprev = pci_get_revid(parent); - int channel = atadev->channel->unit; - int device = ATA_DEV(atadev->unit); - int devno = (channel << 1) + device; - int error; - - /* set our most pessimistic default mode */ - atadev->mode = ATA_PIO; - - if (!atadev->channel->r_bmio) - return; - - /* if simplex controller, only allow DMA on primary channel */ - if (channel == 1) { - ATA_OUTB(atadev->channel->r_bmio, ATA_BMSTAT_PORT, - ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); - if (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - ATA_BMSTAT_DMA_SIMPLEX) { - ata_prtdev(atadev, "simplex device, DMA on primary only\n"); - return; - } - } - - /* DMA engine address alignment is usually 1 word (2 bytes) */ - atadev->channel->alignment = 0x1; - -#if 1 - if (udmamode > 2 && !atadev->param->hwres_cblid) { - ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); - udmamode = 2; - } -#endif - switch (chiptype) { - - case 0x24cb8086: /* Intel ICH4 */ - case 0x248a8086: /* Intel ICH3 mobile */ - case 0x248b8086: /* Intel ICH3 */ - case 0x244a8086: /* Intel ICH2 mobile */ - case 0x244b8086: /* Intel ICH2 */ - if (udmamode >= 5) { - int32_t mask48, new48; - int16_t word54; - - word54 = pci_read_config(parent, 0x54, 2); - if (word54 & (0x10 << devno)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER,ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - mask48 = (1 << devno) + (3 << (16 + (devno << 2))); - new48 = (1 << devno) + (1 << (16 + (devno << 2))); - pci_write_config(parent, 0x48, - (pci_read_config(parent, 0x48, 4) & - ~mask48) | new48, 4); - pci_write_config(parent, 0x54, word54 | (0x1000<<devno), 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - } - /* make sure eventual ATA100 mode from the BIOS is disabled */ - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 2) & ~(0x1000<<devno),2); - /* FALLTHROUGH */ - - case 0x24118086: /* Intel ICH */ - case 0x76018086: /* Intel ICH */ - if (udmamode >= 4) { - int32_t mask48, new48; - int16_t word54; - - word54 = pci_read_config(parent, 0x54, 2); - if (word54 & (0x10 << devno)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - mask48 = (1 << devno) + (3 << (16 + (devno << 2))); - new48 = (1 << devno) + (2 << (16 + (devno << 2))); - pci_write_config(parent, 0x48, - (pci_read_config(parent, 0x48, 4) & - ~mask48) | new48, 4); - pci_write_config(parent, 0x54, word54 | (1 << devno), 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - } - /* make sure eventual ATA66 mode from the BIOS is disabled */ - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 2) & ~(1 << devno), 2); - /* FALLTHROUGH */ - - case 0x71118086: /* Intel PIIX4 */ - case 0x84CA8086: /* Intel PIIX4 */ - case 0x71998086: /* Intel PIIX4e */ - case 0x24218086: /* Intel ICH0 */ - if (udmamode >= 2) { - int32_t mask48, new48; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - mask48 = (1 << devno) + (3 << (16 + (devno << 2))); - new48 = (1 << devno) + (2 << (16 + (devno << 2))); - pci_write_config(parent, 0x48, - (pci_read_config(parent, 0x48, 4) & - ~mask48) | new48, 4); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - /* make sure eventual ATA33 mode from the BIOS is disabled */ - pci_write_config(parent, 0x48, - pci_read_config(parent, 0x48, 4) & ~(1 << devno), 4); - /* FALLTHROUGH */ - - case 0x70108086: /* Intel PIIX3 */ - if (wdmamode >= 2 && apiomode >= 4) { - int32_t mask40, new40, mask44, new44; - - /* if SITRE not set doit for both channels */ - if (!((pci_read_config(parent, 0x40, 4) >> (channel<<8)) & 0x4000)){ - new40 = pci_read_config(parent, 0x40, 4); - new44 = pci_read_config(parent, 0x44, 4); - if (!(new40 & 0x00004000)) { - new44 &= ~0x0000000f; - new44 |= ((new40&0x00003000)>>10)|((new40&0x00000300)>>8); - } - if (!(new40 & 0x40000000)) { - new44 &= ~0x000000f0; - new44 |= ((new40&0x30000000)>>22)|((new40&0x03000000)>>20); - } - new40 |= 0x40004000; - pci_write_config(parent, 0x40, new40, 4); - pci_write_config(parent, 0x44, new44, 4); - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - if (device == ATA_MASTER) { - mask40 = 0x0000330f; - new40 = 0x00002307; - mask44 = 0; - new44 = 0; - } - else { - mask40 = 0x000000f0; - new40 = 0x00000070; - mask44 = 0x0000000f; - new44 = 0x0000000b; - } - if (channel) { - mask40 <<= 16; - new40 <<= 16; - mask44 <<= 4; - new44 <<= 4; - } - pci_write_config(parent, 0x40, - (pci_read_config(parent, 0x40, 4) & ~mask40)| - new40, 4); - pci_write_config(parent, 0x44, - (pci_read_config(parent, 0x44, 4) & ~mask44)| - new44, 4); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x12308086: /* Intel PIIX */ - if (wdmamode >= 2 && apiomode >= 4) { - int32_t word40; - - word40 = pci_read_config(parent, 0x40, 4); - word40 >>= channel * 16; - - /* Check for timing config usable for DMA on controller */ - if (!((word40 & 0x3300) == 0x2300 && - ((word40 >> (device ? 4 : 0)) & 1) == 1)) - break; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - break; - - case 0x522910b9: /* AcerLabs Aladdin IV/V */ - /* the older Aladdin doesn't support ATAPI DMA on both master & slave */ - if (chiprev < 0xc2 && - atadev->channel->devices & ATA_ATAPI_MASTER && - atadev->channel->devices & ATA_ATAPI_SLAVE) { - ata_prtdev(atadev, "two atapi devices on this channel, no DMA\n"); - break; - } - pci_write_config(parent, 0x58 + (channel << 2), 0x00310001, 4); - if (udmamode >= 5 && chiprev >= 0xc4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - - pci_write_config(parent, 0x4b, - pci_read_config(parent, 0x4b, 1) | 0x01, 1); - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x000f0005 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4 && chiprev >= 0xc2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - - pci_write_config(parent, 0x4b, - pci_read_config(parent, 0x4b, 1) | 0x01, 1); - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x00080005 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2 && chiprev >= 0x20) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x000a0005 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - atadev->channel->flags |= ATA_ATAPI_DMA_RO; - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - - /* make sure eventual UDMA mode from the BIOS is disabled */ - pci_write_config(parent, 0x56, pci_read_config(parent, 0x56, 2) & - ~(0x0008 << (devno << 2)), 2); - - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Acer chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x53, - pci_read_config(parent, 0x53, 1) | 0x03, 1); - atadev->channel->flags |= ATA_ATAPI_DMA_RO; - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - pci_write_config(parent, 0x53, - (pci_read_config(parent, 0x53, 1) & ~0x01) | 0x02, 1); - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on Acer chip\n", - (error) ? "failed" : "success", - (apiomode >= 0) ? apiomode : 0); - if (!error) { - int32_t word54 = pci_read_config(parent, 0x54, 4); - int32_t timing; - - switch(ATA_PIO0 + apiomode) { - case ATA_PIO0: timing = 0x006d0003; - case ATA_PIO1: timing = 0x00580002; - case ATA_PIO2: timing = 0x00440001; - case ATA_PIO3: timing = 0x00330001; - case ATA_PIO4: timing = 0x00310001; - default: timing = 0x006d0003; - } - pci_write_config(parent, 0x58 + (channel << 2), timing, 4); - word54 &= ~(0x000f000f << (devno << 2)); - word54 |= (0x00000004 << (devno << 2)); - pci_write_config(parent, 0x54, word54, 4); - atadev->mode = ATA_PIO0 + apiomode; - return; - } - break; - - case 0x01bc10de: /* nVIDIA nForce */ - case 0x006510de: /* nVIDIA nForce2 */ - case 0x74411022: /* AMD 768 */ - case 0x74111022: /* AMD 766 */ - case 0x74091022: /* AMD 756 */ - case 0x05711106: /* VIA 82C571, 82C586, 82C596, 82C686, 8231,8233,8235 */ - { - int via_modes[5][7] = { - { 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* VIA ATA33 */ - { 0x00, 0x00, 0xea, 0x00, 0xe8, 0x00, 0x00 }, /* VIA ATA66 */ - { 0x00, 0x00, 0xf4, 0x00, 0xf1, 0xf0, 0x00 }, /* VIA ATA100 */ - { 0x00, 0x00, 0xf6, 0x00, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */ - { 0x00, 0x00, 0xc0, 0x00, 0xc5, 0xc6, 0xc7 }}; /* AMD/nVIDIA */ - int reg = 0x53 - devno; - int *reg_val = NULL; - char *chip = "VIA"; - - if (ata_find_dev(parent, 0x31471106, 0) || /* 8233a */ - ata_find_dev(parent, 0x31771106, 0)) { /* 8235 */ - udmamode = imin(udmamode, 6); - reg_val = via_modes[3]; - } - else if (ata_find_dev(parent, 0x06861106, 0x40) || /* 82C686b */ - ata_find_dev(parent, 0x82311106, 0) || /* 8231 */ - ata_find_dev(parent, 0x30741106, 0) || /* 8233 */ - ata_find_dev(parent, 0x31091106, 0)) { /* 8233c */ - udmamode = imin(udmamode, 5); - reg_val = via_modes[2]; - } - else if (ata_find_dev(parent, 0x06861106, 0x10) || /* 82C686a */ - ata_find_dev(parent, 0x05961106, 0x12)) { /* 82C596b */ - udmamode = imin(udmamode, 4); - reg_val = via_modes[1]; - } - else if (ata_find_dev(parent, 0x06861106, 0)) { /* 82C686 */ - udmamode = imin(udmamode, 2); - reg_val = via_modes[1]; - } - else if (ata_find_dev(parent, 0x05961106, 0) || /* 82C596a */ - ata_find_dev(parent, 0x05861106, 0x03)) { /* 82C586b */ - udmamode = imin(udmamode, 2); - reg_val = via_modes[0]; - } - else if (chiptype == 0x74411022 || /* AMD 768 */ - chiptype == 0x74111022) { /* AMD 766 */ - udmamode = imin(udmamode, 5); - reg_val = via_modes[4]; - chip = "AMD"; - } - else if (chiptype == 0x74091022) { /* AMD 756 */ - udmamode = imin(udmamode, 4); - reg_val = via_modes[4]; - chip = "AMD"; - } - else if (chiptype == 0x006510de) { /* nForce2 */ - udmamode = imin(udmamode, 6); - reg += 0x10; - reg_val = via_modes[4]; - chip = "nVidia"; - } - else if (chiptype == 0x01bc10de) { /* nForce */ - udmamode = imin(udmamode, 5); - reg += 0x10; - reg_val = via_modes[4]; - chip = "nVidia"; - } - else - udmamode = 0; - - if (udmamode || wdmamode) - pci_write_config(parent, reg - 0x08, 0x20, 1); - - if (udmamode >= 6) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg, reg_val[6], 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg, reg_val[5], 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg, reg_val[4], 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg, reg_val[2], 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on %s chip\n", - (error) ? "failed" : "success", chip); - if (!error) { - pci_write_config(parent, reg, 0x0b, 1); - pci_write_config(parent, reg - 0x08, 0x31, 1); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x55131039: /* SiS 5591 */ - if (ata_find_dev(parent, 0x06301039, 0x30) || /* SiS 630 */ - ata_find_dev(parent, 0x06331039, 0) || /* SiS 633 */ - ata_find_dev(parent, 0x06351039, 0) || /* SiS 635 */ - ata_find_dev(parent, 0x06401039, 0) || /* SiS 640 */ - ata_find_dev(parent, 0x06451039, 0) || /* SiS 645 */ - ata_find_dev(parent, 0x06501039, 0) || /* SiS 650 */ - ata_find_dev(parent, 0x07301039, 0) || /* SiS 730 */ - ata_find_dev(parent, 0x07331039, 0) || /* SiS 733 */ - ata_find_dev(parent, 0x07351039, 0) || /* SiS 735 */ - ata_find_dev(parent, 0x07401039, 0) || /* SiS 740 */ - ata_find_dev(parent, 0x07451039, 0) || /* SiS 745 */ - ata_find_dev(parent, 0x07501039, 0)) { /* SiS 750 */ - int8_t reg = 0x40 + (devno << 1); - int16_t val = pci_read_config(parent, reg, 2) & 0x0fff; - - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0x8000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0x9000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0xb000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - } else if (ata_find_dev(parent, 0x05301039, 0) || /* SiS 530 */ - ata_find_dev(parent, 0x05401039, 0) || /* SiS 540 */ - ata_find_dev(parent, 0x06201039, 0) || /* SiS 620 */ - ata_find_dev(parent, 0x06301039, 0)) { /* SiS 630 */ - int8_t reg = 0x40 + (devno << 1); - int16_t val = pci_read_config(parent, reg, 2) & 0x0fff; - - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0x9000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, reg, val | 0xa000, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - } else if (udmamode >= 2 && chiprev > 0xc1) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x40 + (devno << 1), 0xa301, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >=2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on SiS chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x06801095: /* Sil 0680 ATA133 controller */ - { - u_int8_t ureg = 0xac + (device * 0x02) + (channel * 0x10); - u_int8_t uval = pci_read_config(parent, ureg, 1); - u_int8_t mreg = channel ? 0x84 : 0x80; - u_int8_t mask = device ? 0x30 : 0x03; - u_int8_t mode = pci_read_config(parent, mreg, 1); - - /* enable UDMA mode */ - pci_write_config(parent, mreg, - (mode & ~mask) | (device ? 0x30 : 0x03), 1); - if (udmamode >= 6) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on Sil chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & 0x3f) | 0x01, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Sil chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & 0x3f) | 0x02, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Sil chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & 0x3f) | 0x03, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Sil chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg, (uval & 0x3f) | 0x07, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - - /* disable UDMA mode and enable WDMA mode */ - pci_write_config(parent, mreg, - (mode & ~mask) | (device ? 0x20 : 0x02), 1); - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Sil chip\n", - (error) ? "failed" : "success"); - if (!error) { - pci_write_config(parent, ureg - 0x4, 0x10c1, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - - /* restore PIO mode */ - pci_write_config(parent, mreg, mode, 1); - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x06491095: /* CMD 649 ATA100 controller */ - if (udmamode >= 5) { - u_int8_t umode; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on CMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1); - umode &= ~(device ? 0xca : 0x35); - umode |= (device ? 0x0a : 0x05); - pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - /* FALLTHROUGH */ - - case 0x06481095: /* CMD 648 ATA66 controller */ - if (udmamode >= 4) { - u_int8_t umode; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on CMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1); - umode &= ~(device ? 0xca : 0x35); - umode |= (device ? 0x4a : 0x15); - pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - u_int8_t umode; - - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on CMD chip\n", - (error) ? "failed" : "success"); - if (!error) { - umode = pci_read_config(parent, channel ? 0x7b : 0x73, 1); - umode &= ~(device ? 0xca : 0x35); - umode |= (device ? 0x42 : 0x11); - pci_write_config(parent, channel ? 0x7b : 0x73, umode, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - /* make sure eventual UDMA mode from the BIOS is disabled */ - pci_write_config(parent, channel ? 0x7b : 0x73, - pci_read_config(parent, channel ? 0x7b : 0x73, 1) & - ~(device ? 0xca : 0x53), 1); - /* FALLTHROUGH */ - - case 0x06461095: /* CMD 646 ATA controller */ - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on CMD chip\n", - error ? "failed" : "success"); - if (!error) { - int32_t offset = (devno < 3) ? (devno << 1) : 7; - - pci_write_config(parent, 0x54 + offset, 0x3f, 1); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0xc6931080: /* Cypress 82c693 ATA controller */ - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Cypress chip\n", - error ? "failed" : "success"); - if (!error) { - pci_write_config(atadev->channel->dev, - channel ? 0x4e:0x4c, 0x2020, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x01021078: /* Cyrix 5530 ATA33 controller */ - atadev->channel->alignment = 0xf; - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Cyrix chip\n", - (error) ? "failed" : "success"); - if (!error) { - cyrix_timing(atadev, devno, ATA_UDMA2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Cyrix chip\n", - (error) ? "failed" : "success"); - if (!error) { - cyrix_timing(atadev, devno, ATA_WDMA2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, ATA_C_F_SETXFER, - ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting %s on Cyrix chip\n", - (error) ? "failed" : "success", - ata_mode2str(ATA_PIO0 + apiomode)); - cyrix_timing(atadev, devno, ATA_PIO0 + apiomode); - atadev->mode = ATA_PIO0 + apiomode; - return; - - case 0x02131166: /* ServerWorks CSB6 ATA 100 controller (chan 0+1) */ - case 0x02121166: /* ServerWorks CSB5 ATA66/100 controller */ - if (udmamode >= 5 && (chiptype == 0x02131166 || - (chiptype == 0x02121166 && chiprev >= 0x92))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg56; - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) | - (0x01 << devno), 1); - reg56 = pci_read_config(parent, 0x56, 2); - reg56 &= ~(0xf << (devno * 4)); - reg56 |= (0x5 << (devno * 4)); - pci_write_config(parent, 0x56, reg56, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - /* FALLTHROUGH */ - - case 0x02171166: /* ServerWorks CSB6 ATA 66 controller (chan 2) */ - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg56; - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) | - (0x01 << devno), 1); - reg56 = pci_read_config(parent, 0x56, 2); - reg56 &= ~(0xf << (devno * 4)); - reg56 |= (0x4 << (devno * 4)); - pci_write_config(parent, 0x56, reg56, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - /* FALLTHROUGH */ - - case 0x02111166: /* ServerWorks ROSB4 ATA33 controller */ - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg56; - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) | - (0x01 << devno), 1); - reg56 = pci_read_config(parent, 0x56, 2); - reg56 &= ~(0xf << (devno * 4)); - reg56 |= (0x2 << (devno * 4)); - pci_write_config(parent, 0x56, reg56, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on ServerWorks chip\n", - (error) ? "failed" : "success"); - if (!error) { - int offset = devno ^ 0x01; - int word44 = pci_read_config(parent, 0x44, 4); - - pci_write_config(parent, 0x54, - pci_read_config(parent, 0x54, 1) & - ~(0x01 << devno), 1); - word44 &= ~(0xff << (offset << 8)); - word44 |= (0x20 << (offset << 8)); - pci_write_config(parent, 0x44, 0x20, 4); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x4d69105a: /* Promise TX2 ATA133 controllers */ - case 0x6269105a: /* Promise TX2 ATA133 controllers */ - case 0x1275105a: /* Promise TX2 ATA133 controllers */ - case 0x5275105a: /* Promise TX2 ATA133 controllers */ - case 0x7275105a: /* Promise TX2 ATA133 controllers */ - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 6 && - !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - /* FALLTHROUGH */ - - case 0x4d68105a: /* Promise TX2 ATA100 controllers */ - case 0x6268105a: /* Promise TX2 ATA100 controllers */ - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 5 && - !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - ATA_OUTB(atadev->channel->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 4 && - !(ATA_INB(atadev->channel->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - break; - - case 0x0d30105a: /* Promise OEM ATA100 controllers */ - case 0x4d30105a: /* Promise Ultra/FastTrak 100 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 5 && - !(pci_read_config(parent, 0x50, 2) & (channel ? 1<<11 : 1<<10))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_UDMA5); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - /* FALLTHROUGH */ - case 0x0d38105a: /* Promise FastTrak 66 controllers */ - case 0x4d38105a: /* Promise Ultra/FastTrak 66 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 4 && - !(pci_read_config(parent, 0x50, 2) & (channel ? 1<<11 : 1<<10))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_UDMA4); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - /* FALLTHROUGH */ - - case 0x4d33105a: /* Promise Ultra/FastTrak 33 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_UDMA2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (!ATAPI_DEVICE(atadev) && wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n", - (error) ? "failed" : "success"); - if (!error) { - promise_timing(atadev, devno, ATA_WDMA2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on Promise chip\n", - (error) ? "failed" : "success", - (apiomode >= 0) ? apiomode : 0); - promise_timing(atadev, devno, ATA_PIO0 + apiomode); - atadev->mode = ATA_PIO0 + apiomode; - return; - - case 0x00041103: /* HighPoint HPT366/368/370/372 controllers */ - case 0x00051103: /* HighPoint HPT372 controllers */ - case 0x00081103: /* HighPoint HPT374 controllers */ - if (!ATAPI_DEVICE(atadev) && udmamode >= 6 && hpt_cable80(atadev) && - ((chiptype == 0x00041103 && chiprev >= 0x05) || - (chiptype == 0x00051103 && chiprev >= 0x01) || - (chiptype == 0x00081103 && chiprev >= 0x07))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA6 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA6); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (!ATAPI_DEVICE(atadev) && udmamode >= 5 && hpt_cable80(atadev) && - ((chiptype == 0x00041103 && chiprev >= 0x03) || - (chiptype == 0x00051103 && chiprev >= 0x01) || - (chiptype == 0x00081103 && chiprev >= 0x07))) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA5 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA5); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - if (!ATAPI_DEVICE(atadev) && udmamode >= 4 && hpt_cable80(atadev)) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA4 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA4); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (!ATAPI_DEVICE(atadev) && udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting UDMA2 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_UDMA2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (!ATAPI_DEVICE(atadev) && wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on HighPoint chip\n", - (error) ? "failed" : "success"); - if (!error) { - hpt_timing(atadev, devno, ATA_WDMA2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on HighPoint chip\n", - (error) ? "failed" : "success", - (apiomode >= 0) ? apiomode : 0); - hpt_timing(atadev, devno, ATA_PIO0 + apiomode); - atadev->mode = ATA_PIO0 + apiomode; - return; - - case 0x00091191: /* Acard ATP865R controller */ - case 0x00081191: /* Acard ATP865 controller */ - if (ATAPI_DEVICE(atadev)) - break; - if (udmamode >= 6) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA6, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up UDMA6 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg44 = pci_read_config(parent, 0x44, 2); - - reg44 &= ~(0x000f << (devno << 2)); - reg44 |= (0x0007 << (devno << 2)); - pci_write_config(parent, 0x44, reg44, 2); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + devno, 0x031, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA6); - return; - } - } - if (udmamode >= 5) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up UDMA5 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg44 = pci_read_config(parent, 0x44, 2); - - reg44 &= ~(0x000f << (devno << 2)); - reg44 |= (0x0006 << (devno << 2)); - pci_write_config(parent, 0x44, reg44, 2); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + devno, 0x031, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA5); - return; - } - } - /* FALLTHROUGH */ - - case 0x00071191: /* Acard ATP860R controller */ - case 0x00061191: /* Acard ATP860 controller */ - if (ATAPI_DEVICE(atadev)) - break; - if (udmamode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up UDMA4 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg44 = pci_read_config(parent, 0x44, 2); - - reg44 &= ~(0x000f << (devno << 2)); - reg44 |= (0x0005 << (devno << 2)); - pci_write_config(parent, 0x44, reg44, 2); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + devno, 0x031, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA4); - return; - } - } - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up UDMA2 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg44 = pci_read_config(parent, 0x44, 2); - - reg44 &= ~(0x000f << (devno << 2)); - reg44 |= (0x0003 << (devno << 2)); - pci_write_config(parent, 0x44, reg44, 2); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + devno, 0x031, 1); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up WDMA2 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int16_t reg44 = pci_read_config(parent, 0x44, 2); - - reg44 &= ~(0x000f << (devno << 2)); - pci_write_config(parent, 0x44, reg44, 2); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + devno, 0x031, 1); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x00051191: /* Acard ATP850UF controller */ - if (ATAPI_DEVICE(atadev)) - break; - if (udmamode >= 2) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up UDMA2 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int8_t reg54 = pci_read_config(parent, 0x54, 1); - - reg54 |= (0x03 << (devno << 1)); - pci_write_config(parent, 0x54, reg54, 1); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); - ata_dmacreate(atadev, apiomode, ATA_UDMA2); - return; - } - } - if (wdmamode >= 2 && apiomode >= 4) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting up WDMA2 mode on Acard chip\n", - (error) ? "failed" : "success"); - if (!error) { - u_int8_t reg54 = pci_read_config(parent, 0x54, 1); - - reg54 &= ~(0x03 << (devno << 1)); - pci_write_config(parent, 0x54, reg54, 1); - pci_write_config(parent, 0x4a, 0xa6, 1); - pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - /* we could set PIO mode timings, but we assume the BIOS did that */ - break; - - case 0x000116ca: /* Cenatek Rocket Drive controller */ - if (wdmamode >= 0 && - (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - (device ? ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) - ata_dmacreate(atadev, apiomode, ATA_DMA); - else - atadev->mode = ATA_PIO; - return; - - default: /* unknown controller chip */ - /* better not try generic DMA on ATAPI devices it almost never works */ - if (ATAPI_DEVICE(atadev)) - break; - - /* if controller says its setup for DMA take the easy way out */ - /* the downside is we dont know what DMA mode we are in */ - if ((udmamode >= 0 || wdmamode >= 2) && - (ATA_INB(atadev->channel->r_bmio, ATA_BMSTAT_PORT) & - (device ? ATA_BMSTAT_DMA_SLAVE : ATA_BMSTAT_DMA_MASTER))) { - ata_dmacreate(atadev, apiomode, ATA_DMA); - return; - } - - /* well, we have no support for this, but try anyways */ - if ((wdmamode >= 2 && apiomode >= 4) && atadev->channel->r_bmio) { - error = ata_command(atadev, ATA_C_SETFEATURES, 0, - ATA_WDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting WDMA2 on generic chip\n", - (error) ? "failed" : "success"); - if (!error) { - ata_dmacreate(atadev, apiomode, ATA_WDMA2); - return; - } - } - } - error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_PIO0 + apiomode, - ATA_C_F_SETXFER, ATA_WAIT_READY); - if (bootverbose) - ata_prtdev(atadev, "%s setting PIO%d on generic chip\n", - (error) ? "failed" : "success", apiomode < 0 ? 0 : apiomode); - if (!error) - atadev->mode = ATA_PIO0 + apiomode; - else { - if (bootverbose) - ata_prtdev(atadev, "using PIO mode set by BIOS\n"); - atadev->mode = ATA_PIO; + if (ch->dmatag) { + bus_dma_tag_destroy(ch->dmatag); + ch->dmatag = NULL; } } @@ -1501,12 +225,13 @@ ata_dmasetupd_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) cba->dmatab[j - 1].count = htole32(lastcount | ATA_DMA_EOT); } -int +static int ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) { struct ata_channel *ch = atadev->channel; - if (((uintptr_t)data & ch->alignment) || (count & ch->alignment)) { + if (((uintptr_t)data & (ch->dma->alignment - 1)) || + (count & (ch->dma->alignment - 1))) { ata_prtdev(atadev, "non aligned DMA transfer attempted\n"); return -1; } @@ -1528,20 +253,6 @@ ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) if (ds->flags & ATA_DS_ACTIVE) panic("ata_dmasetup: transfer active on this device!"); - switch(ch->chiptype) { - case 0x0d38105a: /* Promise Fasttrak 66 */ - case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */ - case 0x0d30105a: /* Promise OEM ATA 100 */ - case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */ - if (ch->flags & ATA_48BIT_ACTIVE) { - ATA_OUTB(ch->r_bmio, (ch->unit ? 0x09 : 0x11), - ATA_INB(ch->r_bmio, (ch->unit ? 0x09 : 0x11)) | - (ch->unit ? 0x08 : 0x02)); - ATA_OUTL(ch->r_bmio, (ch->unit ? 0x1c : 0x20), - (dir ? 0x05000000 : 0x06000000) | (count >> 1)); - } - } - cba.dmatab = ds->dmatab; bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_PREWRITE); if (bus_dmamap_load(ds->ddmatag, ds->ddmamap, data, count, @@ -1566,25 +277,12 @@ ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) } int -ata_dmadone(struct ata_device *atadev) +ata_dmastop(struct ata_device *atadev) { struct ata_channel *ch = atadev->channel; struct ata_dmastate *ds = &atadev->dmastate; int error; - switch(ch->chiptype) { - case 0x0d38105a: /* Promise Fasttrak 66 */ - case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */ - case 0x0d30105a: /* Promise OEM ATA 100 */ - case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */ - if (ch->flags & ATA_48BIT_ACTIVE) { - ATA_OUTB(ch->r_bmio, (ch->unit ? 0x09 : 0x11), - ATA_INB(ch->r_bmio, (ch->unit ? 0x09 : 0x11)) & - ~(ch->unit ? 0x08 : 0x02)); - ATA_OUTL(ch->r_bmio, (ch->unit ? 0x1c : 0x20), 0); - } - } - error = ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT); ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); @@ -1599,210 +297,8 @@ ata_dmadone(struct ata_device *atadev) return (error & ATA_BMSTAT_MASK); } -int +static int ata_dmastatus(struct ata_channel *ch) { return ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; } - -static void -cyrix_timing(struct ata_device *atadev, int devno, int mode) -{ - u_int32_t reg20 = 0x0000e132; - u_int32_t reg24 = 0x00017771; - - switch (mode) { - case ATA_PIO0: reg20 = 0x0000e132; break; - case ATA_PIO1: reg20 = 0x00018121; break; - case ATA_PIO2: reg20 = 0x00024020; break; - case ATA_PIO3: reg20 = 0x00032010; break; - case ATA_PIO4: reg20 = 0x00040010; break; - case ATA_WDMA2: reg24 = 0x00002020; break; - case ATA_UDMA2: reg24 = 0x00911030; break; - } - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x20, reg20); - ATA_OUTL(atadev->channel->r_bmio, (devno << 3) + 0x24, reg24); -} - -static void -promise_timing(struct ata_device *atadev, int devno, int mode) -{ - u_int32_t timing = 0; - /* XXX: Endianess */ - struct promise_timing { - u_int8_t pa:4; - u_int8_t prefetch:1; - u_int8_t iordy:1; - u_int8_t errdy:1; - u_int8_t syncin:1; - u_int8_t pb:5; - u_int8_t mb:3; - u_int8_t mc:4; - u_int8_t dmaw:1; - u_int8_t dmar:1; - u_int8_t iordyp:1; - u_int8_t dmarqp:1; - u_int8_t reserved:8; - } *t = (struct promise_timing*)&timing; - - t->iordy = 1; t->iordyp = 1; - if (mode >= ATA_DMA) { - t->prefetch = 1; t->errdy = 1; t->syncin = 1; - } - - switch (atadev->channel->chiptype) { - case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */ - switch (mode) { - default: - case ATA_PIO0: t->pa = 9; t->pb = 19; t->mb = 7; t->mc = 15; break; - case ATA_PIO1: t->pa = 5; t->pb = 12; t->mb = 7; t->mc = 15; break; - case ATA_PIO2: t->pa = 3; t->pb = 8; t->mb = 7; t->mc = 15; break; - case ATA_PIO3: t->pa = 2; t->pb = 6; t->mb = 7; t->mc = 15; break; - case ATA_PIO4: t->pa = 1; t->pb = 4; t->mb = 7; t->mc = 15; break; - case ATA_WDMA2: t->pa = 3; t->pb = 7; t->mb = 3; t->mc = 3; break; - case ATA_UDMA2: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; - } - break; - - case 0x0d38105a: /* Promise Fasttrak 66 */ - case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */ - case 0x0d30105a: /* Promise OEM ATA 100 */ - case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */ - switch (mode) { - default: - case ATA_PIO0: t->pa = 15; t->pb = 31; t->mb = 7; t->mc = 15; break; - case ATA_PIO1: t->pa = 10; t->pb = 24; t->mb = 7; t->mc = 15; break; - case ATA_PIO2: t->pa = 6; t->pb = 16; t->mb = 7; t->mc = 15; break; - case ATA_PIO3: t->pa = 4; t->pb = 12; t->mb = 7; t->mc = 15; break; - case ATA_PIO4: t->pa = 2; t->pb = 8; t->mb = 7; t->mc = 15; break; - case ATA_WDMA2: t->pa = 6; t->pb = 14; t->mb = 6; t->mc = 6; break; - case ATA_UDMA2: t->pa = 6; t->pb = 14; t->mb = 2; t->mc = 2; break; - case ATA_UDMA4: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; - case ATA_UDMA5: t->pa = 3; t->pb = 7; t->mb = 1; t->mc = 1; break; - } - break; - } - pci_write_config(device_get_parent(atadev->channel->dev), - 0x60 + (devno << 2), timing, 4); -} - -static void -hpt_timing(struct ata_device *atadev, int devno, int mode) -{ - device_t parent = device_get_parent(atadev->channel->dev); - u_int32_t chiptype = atadev->channel->chiptype; - int chiprev = pci_get_revid(parent); - u_int32_t timing; - - if (chiptype == 0x00081103 && chiprev >= 0x07) { - switch (mode) { /* HPT374 */ - case ATA_PIO0: timing = 0x0ac1f48a; break; - case ATA_PIO1: timing = 0x0ac1f465; break; - case ATA_PIO2: timing = 0x0a81f454; break; - case ATA_PIO3: timing = 0x0a81f443; break; - case ATA_PIO4: timing = 0x0a81f442; break; - case ATA_WDMA2: timing = 0x22808242; break; - case ATA_UDMA2: timing = 0x120c8242; break; - case ATA_UDMA4: timing = 0x12ac8242; break; - case ATA_UDMA5: timing = 0x12848242; break; - case ATA_UDMA6: timing = 0x12808242; break; - default: timing = 0x0d029d5e; - } - } - else if ((chiptype == 0x00041103 && chiprev >= 0x05) || - (chiptype == 0x00051103 && chiprev >= 0x01)) { - switch (mode) { /* HPT372 */ - case ATA_PIO0: timing = 0x0d029d5e; break; - case ATA_PIO1: timing = 0x0d029d26; break; - case ATA_PIO2: timing = 0x0c829ca6; break; - case ATA_PIO3: timing = 0x0c829c84; break; - case ATA_PIO4: timing = 0x0c829c62; break; - case ATA_WDMA2: timing = 0x2c829262; break; - case ATA_UDMA2: timing = 0x1c91dc62; break; - case ATA_UDMA4: timing = 0x1c8ddc62; break; - case ATA_UDMA5: timing = 0x1c6ddc62; break; - case ATA_UDMA6: timing = 0x1c81dc62; break; - default: timing = 0x0d029d5e; - } - } - else if (chiptype == 0x00041103 && chiprev >= 0x03) { - switch (mode) { /* HPT370 */ - case ATA_PIO0: timing = 0x06914e57; break; - case ATA_PIO1: timing = 0x06914e43; break; - case ATA_PIO2: timing = 0x06514e33; break; - case ATA_PIO3: timing = 0x06514e22; break; - case ATA_PIO4: timing = 0x06514e21; break; - case ATA_WDMA2: timing = 0x26514e21; break; - case ATA_UDMA2: timing = 0x16494e31; break; - case ATA_UDMA4: timing = 0x16454e31; break; - case ATA_UDMA5: timing = 0x16454e31; break; - default: timing = 0x06514e57; - } - pci_write_config(parent, 0x40 + (devno << 2) , timing, 4); - } - else { /* HPT36[68] */ - switch (pci_read_config(parent, 0x41 + (devno << 2), 1)) { - case 0x85: /* 25Mhz */ - switch (mode) { - case ATA_PIO0: timing = 0x40d08585; break; - case ATA_PIO1: timing = 0x40d08572; break; - case ATA_PIO2: timing = 0x40ca8542; break; - case ATA_PIO3: timing = 0x40ca8532; break; - case ATA_PIO4: timing = 0x40ca8521; break; - case ATA_WDMA2: timing = 0x20ca8521; break; - case ATA_UDMA2: timing = 0x10cf8521; break; - case ATA_UDMA4: timing = 0x10c98521; break; - default: timing = 0x01208585; - } - break; - default: - case 0xa7: /* 33MHz */ - switch (mode) { - case ATA_PIO0: timing = 0x40d0a7aa; break; - case ATA_PIO1: timing = 0x40d0a7a3; break; - case ATA_PIO2: timing = 0x40d0a753; break; - case ATA_PIO3: timing = 0x40c8a742; break; - case ATA_PIO4: timing = 0x40c8a731; break; - case ATA_WDMA2: timing = 0x20c8a731; break; - case ATA_UDMA2: timing = 0x10caa731; break; - case ATA_UDMA4: timing = 0x10c9a731; break; - default: timing = 0x0120a7a7; - } - break; - case 0xd9: /* 40Mhz */ - switch (mode) { - case ATA_PIO0: timing = 0x4018d9d9; break; - case ATA_PIO1: timing = 0x4010d9c7; break; - case ATA_PIO2: timing = 0x4010d997; break; - case ATA_PIO3: timing = 0x4010d974; break; - case ATA_PIO4: timing = 0x4008d963; break; - case ATA_WDMA2: timing = 0x2008d943; break; - case ATA_UDMA2: timing = 0x100bd943; break; - case ATA_UDMA4: timing = 0x100fd943; break; - default: timing = 0x0120d9d9; - } - } - } - pci_write_config(parent, 0x40 + (devno << 2) , timing, 4); -} - -static int -hpt_cable80(struct ata_device *atadev) -{ - device_t parent = device_get_parent(atadev->channel->dev); - u_int8_t reg, val, res; - - if (atadev->channel->chiptype==0x00081103 && pci_get_function(parent)==1) { - reg = atadev->channel->unit ? 0x57 : 0x53; - val = pci_read_config(parent, reg, 1); - pci_write_config(parent, reg, val | 0x80, 1); - } - else { - reg = 0x5b; - val = pci_read_config(parent, reg, 1); - pci_write_config(parent, reg, val & 0xfe, 1); - } - res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x1:0x2); - pci_write_config(parent, reg, val, 1); - return !res; -} diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c index 1034858..a8a6296 100644 --- a/sys/dev/ata/ata-isa.c +++ b/sys/dev/ata/ata-isa.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,15 +49,11 @@ static struct isa_pnp_id ata_ids[] = { {0x0106d041, "Plus Hardcard II"}, /* PNP0601 */ {0x0206d041, "Plus Hardcard IIXL/EZ"}, /* PNP0602 */ {0x0306d041, "Generic ATA"}, /* PNP0603 */ + /* PNP0680 */ + {0x8006d041, "Standard bus mastering IDE hard disk controller"}, {0} }; -static int -ata_isa_intrnoop(struct ata_channel *ch) -{ - return 1; - -} static void ata_isa_lock(struct ata_channel *ch, int type) { @@ -91,8 +87,7 @@ ata_isa_probe(device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, rid, io); ch->unit = 0; ch->flags |= ATA_USE_16BIT; - ch->intr_func = ata_isa_intrnoop; - ch->lock_func = ata_isa_lock; + ch->locking = ata_isa_lock; return ata_probe(dev); } diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index d77d65a..065e0b0 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,364 +45,74 @@ #include <pci/pcivar.h> #include <pci/pcireg.h> #include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> -/* device structures */ -struct ata_pci_controller { - struct resource *bmio; - int bmaddr; - struct resource *irq; - int irqcnt; - int lock; -}; +/* local vars */ +static MALLOC_DEFINE(M_ATAPCI, "ATA PCI", "ATA driver PCI"); /* misc defines */ #define IOMASK 0xfffffffc -#define GRANDPARENT(dev) device_get_parent(device_get_parent(dev)) -#define ATA_MASTERDEV(dev) ((pci_get_progif(dev) & 0x80) && \ - (pci_get_progif(dev) & 0x05) != 0x05) - -int -ata_find_dev(device_t dev, u_int32_t devid, u_int32_t revid) -{ - device_t *children; - int nchildren, i; - - if (device_get_children(device_get_parent(dev), &children, &nchildren)) - return 0; - - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == devid && - pci_get_revid(children[i]) >= revid) { - free(children, M_TEMP); - return 1; - } - } - free(children, M_TEMP); - return 0; -} -static void -ata_via_southbridge_fixup(device_t dev) -{ - device_t *children; - int nchildren, i; - - if (device_get_children(device_get_parent(dev), &children, &nchildren)) - return; - - for (i = 0; i < nchildren; i++) { - if (pci_get_devid(children[i]) == 0x03051106 || /* VIA VT8363 */ - pci_get_devid(children[i]) == 0x03911106 || /* VIA VT8371 */ - pci_get_devid(children[i]) == 0x31021106 || /* VIA VT8662 */ - pci_get_devid(children[i]) == 0x31121106) { /* VIA VT8361 */ - u_int8_t reg76 = pci_read_config(children[i], 0x76, 1); - - if ((reg76 & 0xf0) != 0xd0) { - device_printf(dev, - "Correcting VIA config for southbridge data corruption bug\n"); - pci_write_config(children[i], 0x75, 0x80, 1); - pci_write_config(children[i], 0x76, (reg76 & 0x0f) | 0xd0, 1); - } - break; - } - } - free(children, M_TEMP); -} +/* prototypes */ +static int ata_pci_add_child(device_t, int); +static void ata_pci_locknoop(struct ata_channel *, int); -static const char * -ata_pci_match(device_t dev) +static int +ata_pci_probe(device_t dev) { if (pci_get_class(dev) != PCIC_STORAGE) - return NULL; - - switch (pci_get_devid(dev)) { - /* supported chipsets */ - case 0x12308086: - return "Intel PIIX ATA controller"; - - case 0x70108086: - return "Intel PIIX3 ATA controller"; - - case 0x71118086: - case 0x71998086: - case 0x84ca8086: - return "Intel PIIX4 ATA33 controller"; - - case 0x24218086: - return "Intel ICH0 ATA33 controller"; - - case 0x24118086: - case 0x76018086: - return "Intel ICH ATA66 controller"; - - case 0x244a8086: - case 0x244b8086: - return "Intel ICH2 ATA100 controller"; - - case 0x248a8086: - case 0x248b8086: - return "Intel ICH3 ATA100 controller"; - - case 0x24cb8086: - return "Intel ICH4 ATA100 controller"; - - case 0x522910b9: - if (pci_get_revid(dev) >= 0xc4) - return "AcerLabs Aladdin ATA100 controller"; - else if (pci_get_revid(dev) >= 0xc2) - return "AcerLabs Aladdin ATA66 controller"; - else if (pci_get_revid(dev) >= 0x20) - return "AcerLabs Aladdin ATA33 controller"; - else - return "AcerLabs Aladdin ATA controller"; - - case 0x05711106: - if (ata_find_dev(dev, 0x05861106, 0x02)) - return "VIA 82C586 ATA33 controller"; - if (ata_find_dev(dev, 0x05861106, 0)) - return "VIA 82C586 ATA controller"; - if (ata_find_dev(dev, 0x05961106, 0x12)) - return "VIA 82C596 ATA66 controller"; - if (ata_find_dev(dev, 0x05961106, 0)) - return "VIA 82C596 ATA33 controller"; - if (ata_find_dev(dev, 0x06861106, 0x40)) - return "VIA 82C686 ATA100 controller"; - if (ata_find_dev(dev, 0x06861106, 0x10)) - return "VIA 82C686 ATA66 controller"; - if (ata_find_dev(dev, 0x06861106, 0)) - return "VIA 82C686 ATA33 controller"; - if (ata_find_dev(dev, 0x82311106, 0)) - return "VIA 8231 ATA100 controller"; - if (ata_find_dev(dev, 0x30741106, 0) || - ata_find_dev(dev, 0x31091106, 0)) - return "VIA 8233 ATA100 controller"; - if (ata_find_dev(dev, 0x31471106, 0)) - return "VIA 8233 ATA133 controller"; - if (ata_find_dev(dev, 0x31771106, 0)) - return "VIA 8235 ATA133 controller"; - return "VIA Apollo ATA controller"; - - case 0x55131039: - if (ata_find_dev(dev, 0x06301039, 0x30) || - ata_find_dev(dev, 0x06331039, 0) || - ata_find_dev(dev, 0x06351039, 0) || - ata_find_dev(dev, 0x06401039, 0) || - ata_find_dev(dev, 0x06451039, 0) || - ata_find_dev(dev, 0x06501039, 0) || - ata_find_dev(dev, 0x07301039, 0) || - ata_find_dev(dev, 0x07331039, 0) || - ata_find_dev(dev, 0x07351039, 0) || - ata_find_dev(dev, 0x07401039, 0) || - ata_find_dev(dev, 0x07451039, 0) || - ata_find_dev(dev, 0x07501039, 0)) - return "SiS 5591 ATA100 controller"; - else if (ata_find_dev(dev, 0x05301039, 0) || - ata_find_dev(dev, 0x05401039, 0) || - ata_find_dev(dev, 0x06201039, 0) || - ata_find_dev(dev, 0x06301039, 0)) - return "SiS 5591 ATA66 controller"; - else - return "SiS 5591 ATA33 controller"; - - case 0x06801095: - return "Sil 0680 ATA133 controller"; - - case 0x06491095: - return "CMD 649 ATA100 controller"; - - case 0x06481095: - return "CMD 648 ATA66 controller"; - - case 0x06461095: - return "CMD 646 ATA controller"; - - case 0xc6931080: - if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) - return "Cypress 82C693 ATA controller"; - return NULL; - - case 0x01021078: - return "Cyrix 5530 ATA33 controller"; - - case 0x74091022: - return "AMD 756 ATA66 controller"; - - case 0x74111022: - return "AMD 766 ATA100 controller"; - - case 0x74411022: - return "AMD 768 ATA100 controller"; - - case 0x01bc10de: - return "nVidia nForce ATA100 controller"; - - case 0x006510de: - return "nVidia nForce ATA133 controller"; - - case 0x02111166: - return "ServerWorks ROSB4 ATA33 controller"; - - case 0x02121166: - if (pci_get_revid(dev) >= 0x92) - return "ServerWorks CSB5 ATA100 controller"; - else - return "ServerWorks CSB5 ATA66 controller"; - - case 0x02131166: - return "ServerWorks CSB6 ATA100 controller (channel 0+1)"; - - case 0x02171166: - return "ServerWorks CSB6 ATA66 controller (channel 2)"; - - case 0x4d33105a: - return "Promise ATA33 controller"; - - case 0x0d38105a: - case 0x4d38105a: - return "Promise ATA66 controller"; - - case 0x0d30105a: - case 0x4d30105a: - return "Promise ATA100 controller"; - - case 0x4d68105a: - case 0x6268105a: - { - uintptr_t devid = 0; - - /* test if we are behind the right type of bridge */ - if (!BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)), - GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) && - devid == 0x00221011 && - pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) { - static long start = 0, end = 0; - - /* we belive we are on a TX4, now do our (simple) magic */ - if (pci_get_slot(dev) == 1) { - bus_get_resource(dev, SYS_RES_IRQ, 0, &start, &end); - return "Promise TX4 ATA100 controller (channel 0+1)"; - } - else if (pci_get_slot(dev) == 2 && start && end) { - bus_set_resource(dev, SYS_RES_IRQ, 0, start, end); - start = end = 0; - return "Promise TX4 ATA100 controller (channel 2+3)"; - } - else - start = end = 0; - } - } - return "Promise TX2 ATA100 controller"; - - case 0x1275105a: - case 0x5275105a: - case 0x7275105a: - { - uintptr_t devid = 0; - - /* if we are on a SuperTrak SX6000 dont attach */ - if (!BUS_READ_IVAR(device_get_parent(GRANDPARENT(dev)), - GRANDPARENT(dev), PCI_IVAR_DEVID, &devid) && - devid == 0x09628086 && - pci_get_class(GRANDPARENT(dev)) == PCIC_BRIDGE) - break; - } - /* FALLTHROUGH */ - - case 0x4d69105a: - case 0x6269105a: - return "Promise TX2 ATA133 controller"; - - case 0x00041103: - switch (pci_get_revid(dev)) { - case 0x00: - case 0x01: - return "HighPoint HPT366 ATA66 controller"; - case 0x02: - return "HighPoint HPT368 ATA66 controller"; - case 0x03: - case 0x04: - return "HighPoint HPT370 ATA100 controller"; - case 0x05: - return "HighPoint HPT372 ATA133 controller"; - } - return NULL; + return ENXIO; - case 0x00051103: - switch (pci_get_revid(dev)) { - case 0x01: - return "HighPoint HPT372 ATA133 controller"; - } - return NULL; - - case 0x00081103: - switch (pci_get_revid(dev)) { - case 0x07: - if (pci_get_function(dev) == 0) - return "HighPoint HPT374 ATA133 controller (channel 0+1)"; - if (pci_get_function(dev) == 1) - return "HighPoint HPT374 ATA133 controller (channel 2+3)"; - return "HighPoint HPT374 ATA133 controller"; + switch (pci_get_vendor(dev)) { + case ATA_ACARD_ID: + return ata_acard_ident(dev); + case ATA_ACER_LABS_ID: + return ata_ali_ident(dev); + case ATA_AMD_ID: + return ata_amd_ident(dev); + case ATA_CYRIX_ID: + return ata_cyrix_ident(dev); + case ATA_CYPRESS_ID: + return ata_cypress_ident(dev); + case ATA_HIGHPOINT_ID: + return ata_highpoint_ident(dev); + case ATA_INTEL_ID: + return ata_intel_ident(dev); + case ATA_NVIDIA_ID: + return ata_nvidia_ident(dev); + case ATA_PROMISE_ID: + return ata_promise_ident(dev); + case ATA_SERVERWORKS_ID: + return ata_serverworks_ident(dev); + case ATA_SILICON_IMAGE_ID: + return ata_sii_ident(dev); + case ATA_SIS_ID: + return ata_sis_ident(dev); + case ATA_VIA_ID: + return ata_via_ident(dev); + + case 0x16ca: + if (pci_get_devid(dev) == 0x000116ca) { + device_set_desc(dev, "Cenatek Rocket Drive controller"); + return 0; } - return NULL; - - case 0x00051191: - return "Acard ATP850 ATA-33 controller"; - - case 0x00061191: - case 0x00071191: - return "Acard ATP860 ATA-66 controller"; - - case 0x00081191: - case 0x00091191: - return "Acard ATP865 ATA-133 controller"; - - case 0x000116ca: - return "Cenatek Rocket Drive controller"; - - /* unsupported but known chipsets, generic DMA only */ - case 0x10001042: - case 0x10011042: - return "RZ 100? ATA controller !WARNING! buggy chip data loss possible"; + return ENXIO; - case 0x06401095: - return "CMD 640 ATA controller !WARNING! buggy chip data loss possible"; + case 0x1042: + if (pci_get_devid(dev)==0x10001042 || pci_get_devid(dev)==0x10011042) { + device_set_desc(dev, + "RZ 100? ATA controller !WARNING! buggy HW data loss possible"); + return 0; + } + return ENXIO; - /* unknown chipsets, try generic DMA if it seems possible */ + /* unknown chipset, try generic DMA if it seems possible */ default: if (pci_get_class(dev) == PCIC_STORAGE && (pci_get_subclass(dev) == PCIS_STORAGE_IDE)) - return "Generic PCI ATA controller"; + return ata_generic_ident(dev); } - return NULL; -} - -static int -ata_pci_probe(device_t dev) -{ - const char *desc = ata_pci_match(dev); - - if (desc) { - device_set_desc(dev, desc); - return 0; - } - else - return ENXIO; -} - -static int -ata_pci_add_child(device_t dev, int unit) -{ - /* check if this is located at one of the std addresses */ - if (ATA_MASTERDEV(dev)) { - if (!device_add_child(dev, "ata", unit)) - return ENOMEM; - } - else { - if (!device_add_child(dev, "ata", - devclass_find_free_unit(ata_devclass, 2))) - return ENOMEM; - } - return 0; + return ENXIO; } static int @@ -436,155 +146,25 @@ ata_pci_attach(device_t dev) /* is there a valid port range to connect to ? */ rid = 0x20; - controller->bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, 1, RF_ACTIVE); - if (!controller->bmio) + controller->r_bmio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!controller->r_bmio) device_printf(dev, "Busmastering DMA not configured\n"); } else device_printf(dev, "Busmastering DMA not supported\n"); - /* do extra chipset specific setups */ - switch (type) { - - case 0x522910b9: /* AcerLabs Aladdin need to activate the ATAPI FIFO */ - pci_write_config(dev, 0x53, - (pci_read_config(dev, 0x53, 1) & ~0x01) | 0x02, 1); - break; - - case 0x0d30105a: /* Promise 66 & 100 (before TX2) need the clock changed */ - case 0x4d30105a: - case 0x0d38105a: - case 0x4d38105a: - ATA_OUTB(controller->bmio, 0x11, ATA_INB(controller->bmio, 0x11)|0x0a); - /* FALLTHROUGH */ - - case 0x4d33105a: /* Promise (before TX2) need burst mode turned on */ - ATA_OUTB(controller->bmio, 0x1f, ATA_INB(controller->bmio, 0x1f)|0x01); - break; - - case 0x00041103: /* HighPoint HPT366/368/370/372 default setup */ - if (pci_get_revid(dev) < 2) { /* HPT366 */ - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, - (pci_read_config(dev, 0x51, 1) & ~0x80), 1); - break; - } - if (pci_get_revid(dev) < 5) { /* HPT368/370 */ - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, - (pci_read_config(dev, 0x51, 1) & ~0x03), 1); - pci_write_config(dev, 0x55, - (pci_read_config(dev, 0x55, 1) & ~0x03), 1); - - /* turn on interrupts */ - pci_write_config(dev, 0x5a, - (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); - - /* set clocks etc */ - pci_write_config(dev, 0x5b, 0x22, 1); - break; - } - /* FALLTHROUGH */ - - case 0x00051103: /* HighPoint HPT372 default setup */ - case 0x00081103: /* HighPoint HPT374 default setup */ - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1); - pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1); - - /* turn on interrupts */ - pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); - - /* set clocks etc */ - pci_write_config(dev, 0x5b, - (pci_read_config(dev, 0x5b, 1) & 0x01) | 0x20, 1); - break; - - case 0x05711106: /* VIA 82C586, '596, '686 default setup */ - /* prepare for ATA-66 on the 82C686a and 82C596b */ - if ((ata_find_dev(dev, 0x06861106, 0x10) && - !ata_find_dev(dev, 0x06861106, 0x40)) || - ata_find_dev(dev, 0x05961106, 0x12)) - pci_write_config(dev, 0x50, 0x030b030b, 4); - - /* the southbridge might need the data corruption fix */ - if (ata_find_dev(dev, 0x06861106, 0x40) || - ata_find_dev(dev, 0x82311106, 0x10)) - ata_via_southbridge_fixup(dev); - /* FALLTHROUGH */ - - case 0x74091022: /* AMD 756 default setup */ - case 0x74111022: /* AMD 766 default setup */ - case 0x74411022: /* AMD 768 default setup */ - case 0x01bc10de: /* nVIDIA nForce default setup */ - /* set prefetch, postwrite */ - pci_write_config(dev, 0x41, pci_read_config(dev, 0x41, 1) | 0xf0, 1); - - /* set fifo configuration half'n'half */ - pci_write_config(dev, 0x43, - (pci_read_config(dev, 0x43, 1) & 0x90) | 0x2a, 1); - - /* set status register read retry */ - pci_write_config(dev, 0x44, pci_read_config(dev, 0x44, 1) | 0x08, 1); - - /* set DMA read & end-of-sector fifo flush */ - pci_write_config(dev, 0x46, - (pci_read_config(dev, 0x46, 1) & 0x0c) | 0xf0, 1); - - /* set sector size */ - pci_write_config(dev, 0x60, DEV_BSIZE, 2); - pci_write_config(dev, 0x68, DEV_BSIZE, 2); - break; - - case 0x02111166: /* ServerWorks ROSB4 enable UDMA33 */ - pci_write_config(dev, 0x64, - (pci_read_config(dev, 0x64, 4) & ~0x00002000) | - 0x00004000, 4); - break; - - case 0x02121166: /* ServerWorks CSB5 enable UDMA66/100 depending on rev */ - pci_write_config(dev, 0x5a, - (pci_read_config(dev, 0x5a, 1) & ~0x40) | - (pci_get_revid(dev) >= 0x92) ? 0x03 : 0x02, 1); - break; - - case 0x06801095: /* Sil 0680 set ATA reference clock speed */ - if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) - pci_write_config(dev, 0x8a, - (pci_read_config(dev, 0x8a, 1) & 0x0F) | 0x10, 1); - if ((pci_read_config(dev, 0x8a, 1) & 0x30) != 0x10) - device_printf(dev, "Sil 0680 could not set clock\n"); - break; - - case 0x06461095: /* CMD 646 enable interrupts, set DMA read mode */ - pci_write_config(dev, 0x71, 0x01, 1); - break; - - case 0x10001042: /* RZ 100? known bad, no DMA */ - case 0x10011042: - case 0x06401095: /* CMD 640 known bad, no DMA */ - controller->bmio = NULL; - device_printf(dev, "Busmastering DMA disabled\n"); - } + /* do chipset specific setups only needed once */ + controller->dmainit = ata_dmainit; + controller->locking = ata_pci_locknoop; + controller->chipinit(dev); - if (controller->bmio) { - controller->bmaddr = rman_get_start(controller->bmio); + if (controller->r_bmio) { + controller->bmaddr = rman_get_start(controller->r_bmio); BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IOPORT, rid, controller->bmio); - controller->bmio = NULL; + SYS_RES_IOPORT, rid, controller->r_bmio); + controller->r_bmio = NULL; } - controller->lock = -1; - - /* - * the Cypress chip is a mess, it contains two ATA functions, but - * both channels are visible on the first one. - * simply ignore the second function for now, as the right - * solution (ignoring the second channel on the first function) - * doesn't work with the crappy ATA interrupt setup on the alpha. - */ - if (pci_get_devid(dev) == 0xc6931080 && pci_get_function(dev) > 1) - return 0; ata_pci_add_child(dev, 0); @@ -595,117 +175,19 @@ ata_pci_attach(device_t dev) } static int -ata_pci_intr(struct ata_channel *ch) +ata_pci_add_child(device_t dev, int unit) { - u_int8_t dmastat; - - /* - * since we might share the IRQ with another device, and in some - * cases with our twin channel, we only want to process interrupts - * that we know this channel generated. - */ - switch (ch->chiptype) { - case 0x00041103: /* HighPoint HPT366/368/370/372 */ - case 0x00051103: /* HighPoint HPT372 */ - case 0x00081103: /* HighPoint HPT374 */ - if (((dmastat = ata_dmastatus(ch)) & - (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != ATA_BMSTAT_INTERRUPT) - return 0; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); - DELAY(1); - return 1; - - case 0x06481095: /* CMD 648 */ - case 0x06491095: /* CMD 649 */ - if (!(pci_read_config(device_get_parent(ch->dev), 0x71, 1) & - (ch->unit ? 0x08 : 0x04))) - return 0; - break; - - case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */ - case 0x0d38105a: /* Promise Fasttrak 66 */ - case 0x4d38105a: /* Promise Ultra/Fasttrak 66 */ - case 0x0d30105a: /* Promise OEM ATA100 */ - case 0x4d30105a: /* Promise Ultra/Fasttrak 100 */ - if (!(ATA_INL(ch->r_bmio, (ch->unit ? 0x14 : 0x1c)) & - (ch->unit ? 0x00004000 : 0x00000400))) - return 0; - break; - - case 0x4d68105a: /* Promise TX2 ATA100 */ - case 0x6268105a: /* Promise TX2 ATA100 */ - case 0x4d69105a: /* Promise TX2 ATA133 */ - case 0x1275105a: /* Promise TX2 ATA133 */ - case 0x5275105a: /* Promise TX2 ATA133 */ - case 0x6269105a: /* Promise TX2 ATA133 */ - case 0x7275105a: /* Promise TX2 ATA133 */ - ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (!(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x20)) - return 0; - break; - - case 0x00051191: /* Acard ATP850 */ - { - struct ata_pci_controller *scp = - device_get_softc(device_get_parent(ch->dev)); - - if (ch->unit != scp->lock) - return 0; - } - /* FALLTHROUGH */ - - case 0x00061191: /* Acard ATP860 */ - case 0x00071191: /* Acard ATP860R */ - case 0x00081191: /* Acard ATP865 */ - case 0x00091191: /* Acard ATP865R */ - if (ch->flags & ATA_DMA_ACTIVE) { - if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT)) - return 0; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat|ATA_BMSTAT_INTERRUPT); - DELAY(1); - ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, - ATA_INB(ch->r_bmio, ATA_BMCMD_PORT)&~ATA_BMCMD_START_STOP); - DELAY(1); - } - return 1; - } - - if (ch->flags & ATA_DMA_ACTIVE) { - if (!((dmastat = ata_dmastatus(ch)) & ATA_BMSTAT_INTERRUPT)) - return 0; - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, dmastat | ATA_BMSTAT_INTERRUPT); - DELAY(1); + /* check if this is located at one of the std addresses */ + if (ATA_MASTERDEV(dev)) { + if (!device_add_child(dev, "ata", unit)) + return ENOMEM; } - return 1; -} - -static void -ata_pci_locknoop(struct ata_channel *ch, int type) -{ -} - -static void -ata_pci_serialize(struct ata_channel *ch, int flags) -{ - struct ata_pci_controller *scp = - device_get_softc(device_get_parent(ch->dev)); - - switch (flags) { - case ATA_LF_LOCK: - if (scp->lock == ch->unit) - break; - while (!atomic_cmpset_acq_int(&scp->lock, -1, ch->unit)) - tsleep((caddr_t)ch->lock_func, PRIBIO, "atalck", 1); - break; - - case ATA_LF_UNLOCK: - if (scp->lock == -1 || scp->lock != ch->unit) - break; - atomic_store_rel_int(&scp->lock, -1); - wakeup((caddr_t)ch->lock_func); - break; + else { + if (!device_add_child(dev, "ata", + devclass_find_free_unit(ata_devclass, 2))) + return ENOMEM; } - return; + return 0; } static int @@ -730,8 +212,8 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct ata_pci_controller *controller = device_get_softc(dev); - struct resource *res = NULL; int unit = ((struct ata_channel *)device_get_softc(child))->unit; + struct resource *res = NULL; int myrid; if (type == SYS_RES_IOPORT) { @@ -798,24 +280,18 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, } if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { - if (ATA_MASTERDEV(dev)) { + if (ATA_MASTERDEV(dev)) { #ifdef __alpha__ return alpha_platform_alloc_ide_intr(unit); #else int irq = (unit == 0 ? 14 : 15); - + return BUS_ALLOC_RESOURCE(device_get_parent(dev), child, SYS_RES_IRQ, rid, irq, irq, 1, flags); #endif } else { - /* primary and secondary channels share interrupt, keep track */ - if (!controller->irq) - controller->irq = BUS_ALLOC_RESOURCE(device_get_parent(dev), - dev, SYS_RES_IRQ, - rid, 0, ~0, 1, flags); - controller->irqcnt++; - return controller->irq; + return controller->r_irq; } } return 0; @@ -825,7 +301,6 @@ static int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r) { - struct ata_pci_controller *controller = device_get_softc(dev); int unit = ((struct ata_channel *)device_get_softc(child))->unit; if (type == SYS_RES_IOPORT) { @@ -867,34 +342,35 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid, SYS_RES_IRQ, rid, r); #endif } - else { - /* primary and secondary channels share interrupt, keep track */ - if (--controller->irqcnt) - return 0; - controller->irq = NULL; - return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, - SYS_RES_IRQ, rid, r); - } + else + return 0; } return EINVAL; } static int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, - int flags, driver_intr_t *intr, void *arg, + int flags, driver_intr_t *function, void *argument, void **cookiep) { if (ATA_MASTERDEV(dev)) { #ifdef __alpha__ - return alpha_platform_setup_ide_intr(child, irq, intr, arg, cookiep); + return alpha_platform_setup_ide_intr(child, irq, function, argument, + cookiep); #else return BUS_SETUP_INTR(device_get_parent(dev), child, irq, - flags, intr, arg, cookiep); + flags, function, argument, cookiep); #endif } - else - return BUS_SETUP_INTR(device_get_parent(dev), dev, irq, - flags, intr, arg, cookiep); + else { + struct ata_pci_controller *controller = device_get_softc(dev); + int unit = ((struct ata_channel *)device_get_softc(child))->unit; + + controller->interrupt[unit].function = function; + controller->interrupt[unit].argument = argument; + *cookiep = controller; + return 0; + } } static int @@ -909,9 +385,15 @@ ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, #endif } else - return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie); + return 0; } +static void +ata_pci_locknoop(struct ata_channel *ch, int flags) +{ +} + + static device_method_t ata_pci_methods[] = { /* device interface */ DEVMETHOD(device_probe, ata_pci_probe), @@ -944,9 +426,10 @@ DRIVER_MODULE(atapci, pci, ata_pci_driver, ata_pci_devclass, 0, 0); static int ata_pcisub_probe(device_t dev) { + struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); struct ata_channel *ch = device_get_softc(dev); device_t *children; - int count, i; + int count, error, i; /* find channel number on this controller */ device_get_children(device_get_parent(dev), &children, &count); @@ -956,19 +439,24 @@ ata_pcisub_probe(device_t dev) } free(children, M_TEMP); - ch->intr_func = ata_pci_intr; + ch->device[MASTER].setmode = ctlr->setmode; + ch->device[SLAVE].setmode = ctlr->setmode; + ch->locking = ctlr->locking; ch->chiptype = pci_get_devid(device_get_parent(dev)); - switch (ch->chiptype) { - case 0x10001042: /* RZ 1000 */ - case 0x10011042: /* RZ 1001 */ - case 0x06401095: /* CMD 640 */ - case 0x00051191: /* Acard ATP850 */ - ch->lock_func = ata_pci_serialize; - break; - default: - ch->lock_func = ata_pci_locknoop; + + if (!(error = ata_probe(dev)) && ch->r_bmio) { + /* if simplex controller, only allow DMA on primary channel */ + ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, + ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & + (ATA_BMSTAT_DMA_MASTER | ATA_BMSTAT_DMA_SLAVE)); + if (ch->unit == 1 && ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & + ATA_BMSTAT_DMA_SIMPLEX) { + ata_printf(ch, -1, "simplex device, DMA on primary only\n"); + return error; + } + error = ctlr->dmainit(ch); } - return ata_probe(dev); + return error; } static device_method_t ata_pcisub_methods[] = { diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h new file mode 100644 index 0000000..157bc6a --- /dev/null +++ b/sys/dev/ata/ata-pci.h @@ -0,0 +1,262 @@ +/*- + * Copyright (c) 2003 Søren Schmidt <sos@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* structure holding chipset config info */ +struct ata_chip_id { + u_int32_t chiptype; + u_int8_t chiprev; + int cfg1; + int cfg2; + u_int8_t max_dma; + char *text; +}; + +/* structure describing a PCI ATA controller */ +struct ata_pci_controller { + struct resource *r_bmio; + int bmaddr; + struct resource *r_irq; + void *handle; + struct ata_chip_id *chip; + int (*chipinit)(device_t); + int (*dmainit)(struct ata_channel *); + void (*setmode)(struct ata_device *, int); + void (*locking)(struct ata_channel *, int); + int locked_ch; + struct { + void (*function)(void *); + void *argument; + } interrupt[2]; +}; + +#define ATA_MASTERDEV(dev) ((pci_get_progif(dev) & 0x80) && \ + (pci_get_progif(dev) & 0x05) != 0x05) + +/* defines for known chipset PCI id's */ +#define ATA_ACARD_ID 0x1191 +#define ATA_ATP850 0x00021191 +#define ATA_ATP850A 0x00041191 +#define ATA_ATP850R 0x00051191 +#define ATA_ATP860A 0x00061191 +#define ATA_ATP860R 0x00071191 +#define ATA_ATP865A 0x00081191 +#define ATA_ATP865R 0x00091191 + +#define ATA_AMD_ID 0x1022 +#define ATA_AMD755 0x74011022 +#define ATA_AMD756 0x74091022 +#define ATA_AMD766 0x74111022 +#define ATA_AMD768 0x74411022 +#define ATA_AMD8111 0x74691022 + +#define ATA_ACER_LABS_ID 0x10b9 +#define ATA_ALI_5229 0x522910b9 + +#define ATA_CYRIX_ID 0x1078 +#define ATA_CYRIX_5530 0x01021078 + +#define ATA_CYPRESS_ID 0x1080 +#define ATA_CYPRESS_82C693 0xc6931080 + +#define ATA_DEC_21150 0x00221011 + +#define ATA_HIGHPOINT_ID 0x1103 +#define ATA_HPT366 0x00041103 +#define ATA_HPT372 0x00051103 +#define ATA_HPT302 0x00061103 +#define ATA_HPT371 0x00071103 +#define ATA_HPT374 0x00081103 + +#define ATA_INTEL_ID 0x8086 +#define ATA_I960RM 0x09628086 +#define ATA_I82371FB 0x12308086 +#define ATA_I82371SB 0x70108086 +#define ATA_I82371AB 0x71118086 +#define ATA_I82443MX 0x71998086 +#define ATA_I82451NX 0x84ca8086 +#define ATA_I82372FB 0x76018086 +#define ATA_I82801AB 0x24218086 +#define ATA_I82801AA 0x24118086 +#define ATA_I82801BA 0x244a8086 +#define ATA_I82801BA_1 0x244b8086 +#define ATA_I82801CA 0x248a8086 +#define ATA_I82801CA_1 0x248b8086 +#define ATA_I82801DB 0x24cb8086 + +#define ATA_NVIDIA_ID 0x10de +#define ATA_NFORCE1 0x01bc10de +#define ATA_NFORCE2 0x006510de + +#define ATA_PROMISE_ID 0x105a +#define ATA_PDC20246 0x4d33105a +#define ATA_PDC20262 0x4d38105a +#define ATA_PDC20263 0x0d38105a +#define ATA_PDC20265 0x0d30105a +#define ATA_PDC20267 0x4d30105a +#define ATA_PDC20268 0x4d68105a +#define ATA_PDC20268R 0x6268105a +#define ATA_PDC20269 0x4d69105a +#define ATA_PDC20271 0x6269105a +#define ATA_PDC20275 0x1275105a +#define ATA_PDC20276 0x5275105a +#define ATA_PDC20277 0x7275105a +#define ATA_PDC20376 0x3376105a + +#define ATA_SERVERWORKS_ID 0x1166 +#define ATA_ROSB4 0x02111166 +#define ATA_CSB5 0x02121166 +#define ATA_CSB6 0x02131166 +#define ATA_CSB6_1 0x02171166 + +#define ATA_SILICON_IMAGE_ID 0x1095 +#define ATA_SII0680 0x06801095 +#define ATA_CMD646 0x06461095 +#define ATA_CMD648 0x06481095 +#define ATA_CMD649 0x06491095 + +#define ATA_SIS_ID 0x1039 +#define ATA_SISSOUTH 0x00081039 +#define ATA_SIS5511 0x55111039 +#define ATA_SIS5513 0x55131039 +#define ATA_SIS5518 0x55181039 +#define ATA_SIS5571 0x55711039 +#define ATA_SIS5591 0x55911039 +#define ATA_SIS5596 0x55961039 +#define ATA_SIS5597 0x55971039 +#define ATA_SIS5598 0x55981039 +#define ATA_SIS5600 0x56001039 +#define ATA_SIS530 0x05301039 +#define ATA_SIS540 0x05401039 +#define ATA_SIS550 0x05501039 +#define ATA_SIS620 0x06201039 +#define ATA_SIS630 0x06301039 +#define ATA_SIS635 0x06351039 +#define ATA_SIS633 0x06331039 +#define ATA_SIS640 0x06401039 +#define ATA_SIS645 0x06451039 +#define ATA_SIS646 0x06461039 +#define ATA_SIS648 0x06481039 +#define ATA_SIS650 0x06501039 +#define ATA_SIS651 0x06511039 +#define ATA_SIS652 0x06521039 +#define ATA_SIS655 0x06551039 +#define ATA_SIS658 0x06581039 +#define ATA_SIS730 0x07301039 +#define ATA_SIS733 0x07331039 +#define ATA_SIS735 0x07351039 +#define ATA_SIS740 0x07401039 +#define ATA_SIS745 0x07451039 +#define ATA_SIS746 0x07461039 +#define ATA_SIS748 0x07481039 +#define ATA_SIS750 0x07501039 +#define ATA_SIS751 0x07511039 +#define ATA_SIS752 0x07521039 +#define ATA_SIS755 0x07551039 +#define ATA_SIS961 0x09611039 +#define ATA_SIS962 0x09621039 +#define ATA_SIS963 0x09631039 + +#define ATA_VIA_ID 0x1106 +#define ATA_VIA82C571 0x05711106 +#define ATA_VIA82C586 0x05861106 +#define ATA_VIA82C596 0x05961106 +#define ATA_VIA82C686 0x06861106 +#define ATA_VIA8231 0x82311106 +#define ATA_VIA8233 0x30741106 +#define ATA_VIA8233A 0x31471106 +#define ATA_VIA8233C 0x31091106 +#define ATA_VIA8235 0x31771106 +#define ATA_VIA8361 0x31121106 +#define ATA_VIA8363 0x03051106 +#define ATA_VIA8371 0x03911106 +#define ATA_VIA8662 0x31021106 + +/* chipset setup related defines */ +#define ATPOLD 1 + +#define ALIOLD 0x01 +#define ALICABLE 0x02 + +#define HPT366 0 +#define HPT370 1 +#define HPT372 2 +#define HPT374 3 +#define HPTOLD 0x01 + +#define PROLD 0 +#define PRNEW 1 +#define PRTX2 2 +#define PRTX4 0x01 +#define PRSX6K 0x02 + +#define SWKS33 0 +#define SWKS66 1 +#define SWKS100 2 + +#define SII_SETCLK 1 +#define SII_INTR 0x01 + +#define SIS_SOUTH 1 +#define SIS133NEW 2 +#define SIS133OLD 3 +#define SIS100NEW 4 +#define SIS100OLD 5 +#define SIS66 6 + +#define VIA33 0 +#define VIA66 1 +#define VIA100 2 +#define VIA133 3 +#define AMDNVIDIA 4 +#define AMDCABLE 0x01 +#define AMDBUG 0x02 +#define NVIDIA 0x04 +#define VIACLK 0x08 +#define VIABUG 0x10 + +/* global prototypes */ +int ata_dmainit(struct ata_channel *); +int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); +int ata_dmastop(struct ata_device *); + +int ata_generic_ident(device_t); +int ata_acard_ident(device_t); +int ata_ali_ident(device_t); +int ata_amd_ident(device_t); +int ata_cyrix_ident(device_t); +int ata_cypress_ident(device_t); +int ata_highpoint_ident(device_t); +int ata_intel_ident(device_t); +int ata_nvidia_ident(device_t); +int ata_promise_ident(device_t); +int ata_serverworks_ident(device_t); +int ata_sii_ident(device_t); +int ata_sis_ident(device_t); +int ata_via_ident(device_t); diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index 6dae432..909f20f 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 2000 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,7 @@ #include <machine/bus.h> #include <sys/rman.h> #include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> #include <dev/ata/ata-disk.h> #include <dev/ata/ata-raid.h> @@ -119,16 +120,12 @@ ata_raiddisk_attach(struct ad_softc *adp) return 0; } - switch(adp->device->channel->chiptype) { - case 0x4d33105a: case 0x4d38105a: case 0x4d30105a: - case 0x0d30105a: case 0x4d68105a: case 0x6268105a: - case 0x4d69105a: case 0x5275105a: case 0x6269105a: - case 0x7275105a: - + switch(adp->device->channel->chiptype & 0xffff) { + case ATA_PROMISE_ID: /* test RAID bit in PCI reg XXX */ return (ar_promise_read_conf(adp, ar_table, 0)); - case 0x00041103: case 0x00051103: case 0x00081103: + case ATA_HIGHPOINT_ID: return (ar_highpoint_read_conf(adp, ar_table)); default: @@ -228,7 +225,7 @@ ar_attach_raid(struct ar_softc *rdp, int update) else printf(" %d FREE ", disk); ad_print(AD_SOFTC(rdp->disks[disk])); - printf(" "); + printf(" "); ata_enclosure_print(AD_SOFTC(rdp->disks[disk])->device); } else if (rdp->disks[disk].flags & AR_DF_ASSIGNED) @@ -276,7 +273,7 @@ ata_raid_create(struct raid_setup *setup) } switch (rdp->disks[disk].device->channel->chiptype & 0xffff) { - case 0x1103: + case ATA_HIGHPOINT_ID: ctlr |= AR_F_HIGHPOINT_RAID; rdp->disks[disk].disk_sectors = AD_SOFTC(rdp->disks[disk])->total_secs; @@ -286,7 +283,7 @@ ata_raid_create(struct raid_setup *setup) ctlr |= AR_F_FREEBSD_RAID; /* FALLTHROUGH */ - case 0x105a: + case ATA_PROMISE_ID: ctlr |= AR_F_PROMISE_RAID; rdp->disks[disk].disk_sectors = PR_LBA(AD_SOFTC(rdp->disks[disk])); @@ -302,7 +299,7 @@ ata_raid_create(struct raid_setup *setup) rdp->flags |= ctlr; if (disk_size) - disk_size = min(rdp->disks[disk].disk_sectors, disk_size); + disk_size = min(rdp->disks[disk].disk_sectors, disk_size); else disk_size = rdp->disks[disk].disk_sectors; rdp->disks[disk].flags = @@ -376,7 +373,14 @@ ata_raid_create(struct raid_setup *setup) rdp->flags |= AR_F_READY; ar_table[array] = rdp; + + /* kick off rebuild here */ + if (setup->type == 2) { + rdp->disks[1].flags &= ~AR_DF_ONLINE; + rdp->disks[1].flags |= AR_DF_SPARE; + } ar_attach_raid(rdp, 1); + ata_raid_rebuild(array); setup->unit = array; return 0; } @@ -1184,7 +1188,7 @@ ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp, int local) if (!info->raid.generation || info->raid.generation > raid->generation){ raid->generation = info->raid.generation; raid->flags = AR_F_PROMISE_RAID; - if (local) + if (local) raid->flags |= AR_F_FREEBSD_RAID; raid->magic_0 = magic; raid->lun = array; diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h index 5853ead..687c698 100644 --- a/sys/dev/ata/ata-raid.h +++ b/sys/dev/ata/ata-raid.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 2000 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 56e124b..d39c69b 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -72,18 +72,10 @@ atapi_attach(struct ata_device *atadev) ata_umode(atadev->param), atadev->param->support_dma); ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); - if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR)) { - ata_dmainit(atadev, - (ata_pmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param), - (ata_wmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 2:0):ata_wmode(atadev->param), - ata_umode(atadev->param)); - } + if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR)) + atadev->setmode(atadev, ATA_DMA_MAX); else - ata_dmainit(atadev, - ata_pmode(atadev->param) < 0 ? 0 : ata_pmode(atadev->param), - -1, -1); + atadev->setmode(atadev, ATA_PIO_MAX); ATA_UNLOCK_CH(atadev->channel); if (!(atadev->result = malloc(sizeof(struct atapi_reqsense), M_ATAPI, @@ -154,7 +146,7 @@ atapi_detach(struct ata_device *atadev) } free(request, M_ATAPI); } - ata_dmafree(atadev); + atadev->channel->dma->free(atadev); free(atadev->result, M_ATAPI); atadev->driver = NULL; atadev->flags = 0; @@ -186,7 +178,7 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data, request->driver = driver; } if (atadev->mode >= ATA_DMA) { - if (ata_dmaalloc(atadev)) + if (atadev->channel->dma->alloc(atadev)) atadev->mode = ATA_PIO; } @@ -282,7 +274,7 @@ atapi_transfer(struct atapi_request *request) ((request->ccb[0] == ATAPI_WRITE || request->ccb[0] == ATAPI_WRITE_BIG) && !(atadev->channel->flags & ATA_ATAPI_DMA_RO))) && - !ata_dmasetup(atadev, (void *)request->data, request->bytecount)) { + !atadev->channel->dma->setup(atadev, (void *)request->data, request->bytecount)) { request->flags |= ATPR_F_DMA_USED; } @@ -294,7 +286,7 @@ atapi_transfer(struct atapi_request *request) ata_prtdev(atadev, "failure to send ATAPI packet command\n"); if (request->flags & ATPR_F_DMA_USED) - ata_dmastart(atadev, request->data, request->bytecount, + atadev->channel->dma->start(atadev, request->data, request->bytecount, request->flags & ATPR_F_READ); /* command interrupt device ? just return */ @@ -324,7 +316,7 @@ atapi_transfer(struct atapi_request *request) /* send actual command */ ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, - request->ccbsize / sizeof(int16_t)); + request->ccbsize / sizeof(int16_t)); return ATA_OP_CONTINUES; } @@ -352,7 +344,7 @@ atapi_interrupt(struct atapi_request *request) } if (request->flags & ATPR_F_DMA_USED) { - dma_stat = ata_dmadone(atadev); + dma_stat = atadev->channel->dma->stop(atadev); if ((atadev->channel->status & (ATA_S_ERROR | ATA_S_DWF)) || dma_stat & ATA_BMSTAT_ERROR) { request->result = ATA_INB(atadev->channel->r_io, ATA_ERROR); @@ -473,17 +465,7 @@ void atapi_reinit(struct ata_device *atadev) { /* reinit device parameters */ - if (atadev->mode >= ATA_DMA) - ata_dmainit(atadev, - (ata_pmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param), - (ata_wmode(atadev->param) < 0) ? - (atadev->param->support_dma ? 2:0):ata_wmode(atadev->param), - ata_umode(atadev->param)); - else - ata_dmainit(atadev, - ata_pmode(atadev->param)<0 ? 0 : ata_pmode(atadev->param), - -1, -1); + atadev->setmode(atadev, atadev->mode); } int @@ -608,11 +590,9 @@ atapi_timeout(struct atapi_request *request) atapi_cmd2str(request->ccb[0])); if (request->flags & ATPR_F_DMA_USED) { - ata_dmadone(atadev); + atadev->channel->dma->stop(atadev); if (request->retries == ATAPI_MAX_RETRIES) { - ata_dmainit(atadev, - (ata_pmode(atadev->param) < 0) ? 0 : - ata_pmode(atadev->param), -1, -1); + atadev->setmode(atadev, ATA_PIO_MAX); ata_prtdev(atadev, "trying fallback to PIO mode\n"); request->retries = 0; } diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index e77db5a..d41b696 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index 9c1133e..60d2302 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1033,7 +1033,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td) break; case CDRIOCWRITESPEED: - { + { int speed = *(int *)addr; if (speed < 177) @@ -1060,11 +1060,11 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td) break; case CDRIOCREADFORMATCAPS: - error = acd_read_format_caps(cdp, (struct cdr_format_capacities *)addr); + error = acd_read_format_caps(cdp, (struct cdr_format_capacities *)addr); break; case CDRIOCFORMAT: - error = acd_format(cdp, (struct cdr_format_params *)addr); + error = acd_format(cdp, (struct cdr_format_params *)addr); break; case DVDIOCREPORTKEY: diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h index 4e21487..19d742c 100644 --- a/sys/dev/ata/atapi-cd.h +++ b/sys/dev/ata/atapi-cd.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -299,7 +299,7 @@ struct write_param { #define CDR_WTYPE_RAW 0x03 u_int8_t test_write :1; /* test write enable */ - u_int8_t link_size_valid :1; + u_int8_t link_size_valid :1; u_int8_t burnproof :1; /* BurnProof enable */ u_int8_t reserved2_7 :1; u_int8_t track_mode :4; /* track mode */ diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index 5d6f66a..b0b0f76 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -204,8 +204,8 @@ afd_describe(struct afd_softc *fdp) printf("Unknown (0x%x)", fdp->cap.medium_type); } if (fdp->cap.wp) printf(", writeprotected"); + printf("\n"); } - printf("\n"); } else { ata_prtdev(fdp->device, "%luMB <%.40s> [%d/%d/%d] at ata%d-%s %s\n", diff --git a/sys/dev/ata/atapi-fd.h b/sys/dev/ata/atapi-fd.h index ee4fc73..e92f79c 100644 --- a/sys/dev/ata/atapi-fd.h +++ b/sys/dev/ata/atapi-fd.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index a0fdc2e..76a5c46 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h index e4dab20..96ef84e 100644 --- a/sys/dev/ata/atapi-tape.h +++ b/sys/dev/ata/atapi-tape.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without |