diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 000b019fd84c..889fe9265898 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.228 1999/03/10 10:36:29 yokota Exp $ +# $Id: files.i386,v 1.229 1999/03/16 13:34:02 sos Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -35,6 +35,7 @@ ukbdmap.h optional ukbd_dflt_keymap \ clean "ukbdmap.h" # dev/ata/ata-all.c optional ata device-driver +dev/ata/ata-dma.c optional ata device-driver dev/ata/atapi-all.c optional ata device-driver dev/ata/ata-disk.c optional atadisk device-driver dev/ata/atapi-cd.c optional atapicd device-driver diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index f8f1c9e46985..5257487598ea 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-all.c,v 1.3 1999/03/05 09:43:30 sos Exp $ + * $Id: ata-all.c,v 1.4 1999/03/07 21:49:14 sos Exp $ */ #include "ata.h" @@ -41,7 +41,10 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -53,6 +56,10 @@ /* misc defines */ #define UNIT(dev) (dev>>3 & 0x1f) /* assume 8 minor # per unit */ +#define MIN(a,b) ((a)>(b)?(b):(a)) +#if NSMP == 0 +#define isa_apic_irq(x) x +#endif /* prototypes */ #if NISA > 0 @@ -64,7 +71,7 @@ static const char *ata_pciprobe(pcici_t, pcidi_t); static void ata_pciattach(pcici_t, int32_t); static void promise_intr(int32_t); #endif -static int32_t ata_probe(int32_t, int32_t, int32_t *); +static int32_t ata_probe(int32_t, int32_t, int32_t, pcici_t, int32_t *); static void ataintr(int32_t); static int32_t atanlun = 0, sysctrl = 0; @@ -84,7 +91,8 @@ ata_isaprobe(struct isa_device *devp) return 0; } } - res=ata_probe(devp->id_iobase, devp->id_iobase+ATA_ALTPORT, &devp->id_unit); + res = ata_probe(devp->id_iobase, devp->id_iobase + ATA_ALTPORT, 0, 0, + &devp->id_unit); if (res) devp->id_intr = (inthand2_t *)ataintr; return res; @@ -115,20 +123,22 @@ ata_pciprobe(pcici_t tag, pcidi_t type) ((data & PCI_SUBCLASS_MASK) == 0x00010000 || ((data & PCI_SUBCLASS_MASK) == 0x00040000))) { switch (type) { - case 0x71118086: - return "Intel PIIX4 IDE controller"; - case 0x70108086: - return "Intel PIIX3 IDE controller"; case 0x12308086: return "Intel PIIX IDE controller"; + case 0x70108086: + return "Intel PIIX3 IDE controller"; + case 0x71118086: + return "Intel PIIX4 IDE controller"; case 0x4d33105a: return "Promise Ultra/33 IDE controller"; + case 0x522910b9: + return "AcerLabs Aladdin IDE controller"; +#if 0 case 0x05711106: return "VIA Apollo IDE controller"; case 0x01021078: return "Cyrix 5530 IDE controller"; - case 0x522910b9: - return "Acer Aladdin IV/V IDE controller"; +#endif default: return "Unknown PCI IDE controller"; } @@ -140,7 +150,8 @@ static void ata_pciattach(pcici_t tag, int32_t unit) { pcidi_t type, class, cmd; - int32_t iobase_1, iobase_2, altiobase_1, altiobase_2, irq1, irq2; + int32_t iobase_1, iobase_2, altiobase_1, altiobase_2; + int32_t bmaddr_1 = 0, bmaddr_2 = 0, irq1, irq2; int32_t lun; /* set up vendor-specific stuff */ @@ -149,39 +160,22 @@ ata_pciattach(pcici_t tag, int32_t unit) cmd = pci_conf_read(tag, PCI_COMMAND_STATUS_REG); #ifdef ATA_DEBUG - printf("ata: type=%08x class=%08x cmd=%08x\n", type, class, cmd); + printf("ata%d: type=%08x class=%08x cmd=%08x\n", unit, type, class, cmd); #endif - switch (type) { - case 0x71118086: - case 0x70108086: - case 0x12308086: /* Intel PIIX, PIIX3, PIIX4 */ - break; - - case 0x05711106: /* VIA Apollo chipset family */ - break; - - case 0x4d33105a: /* Promise controllers */ - break; - - case 0x01021078: /* Cyrix 5530 */ - break; - - case 0x522910B9: /* Acer Aladdin IV/V (M5229) */ - break; - default: - /* everybody else */ - break; - } - - if (type == 0x4d33105a) { /* the Promise is special */ + /* if this is at Promise controller handle it specially */ + if (type == 0x4d33105a) { iobase_1 = pci_conf_read(tag, 0x10) & 0xfffc; altiobase_1 = pci_conf_read(tag, 0x14) & 0xfffc; iobase_2 = pci_conf_read(tag, 0x18) & 0xfffc; altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc; irq1 = irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff; + bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc; + bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; sysctrl = (pci_conf_read(tag, 0x20) & 0xfffc) + 0x1c; + printf("ata-pci%d: Busmastering DMA supported\n", unit); } + /* everybody else seems to do it this way */ else { if ((class & 0x100) == 0) { iobase_1 = IO_WD1; @@ -203,12 +197,32 @@ ata_pciattach(pcici_t tag, int32_t unit) altiobase_2 = pci_conf_read(tag, 0x1c) & 0xfffc; irq2 = pci_conf_read(tag, PCI_INTERRUPT_REG) & 0xff; } + + /* is this controller busmaster capable ? */ + if (pci_conf_read(tag, PCI_CLASS_REG) & 0x8000) { + /* is busmastering support turned on ? */ + if ((pci_conf_read(tag, PCI_COMMAND_STATUS_REG) & 5) == 5) { + /* is there a valid port range to connect to ? */ + if ((bmaddr_1 = pci_conf_read(tag, 0x20) & 0xfffc)) { + bmaddr_2 = bmaddr_1 + ATA_BM_OFFSET1; + printf("ata-pci%d: Busmastering DMA supported\n", unit); + } + else + printf("ata-pci%d: Busmastering DMA not configured\n",unit); + } + else + printf("ata-pci%d: Busmastering DMA not enabled\n", unit); + } + else + printf("ata-pci%d: Busmastering DMA not supported\n", unit); } /* now probe the addresse found for "real" ATA/ATAPI hardware */ - if (ata_probe(iobase_1, altiobase_1, &lun)) { + lun = 0; + if (ata_probe(iobase_1, altiobase_1, bmaddr_1, tag, &lun)) { if (iobase_1 == IO_WD1) - register_intr(irq1, 0, 0, (inthand2_t *)ataintr, &bio_imask, lun); + register_intr(irq1, (int)"", 0, (inthand2_t *)ataintr, + &bio_imask, lun); else { if (sysctrl) pci_map_int(tag, (inthand2_t *)promise_intr, @@ -217,17 +231,19 @@ ata_pciattach(pcici_t tag, int32_t unit) pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask); } printf("ata%d at 0x%04x irq %d on ata-pci%d\n", - lun, iobase_1, irq1, unit); + lun, iobase_1, isa_apic_irq(irq1), unit); } - if (ata_probe(iobase_2, altiobase_2, &lun)) { + lun = 1; + if (ata_probe(iobase_2, altiobase_2, bmaddr_2, tag, &lun)) { if (iobase_2 == IO_WD2) - register_intr(irq2, 0, 0, (inthand2_t *)ataintr, &bio_imask, lun); + register_intr(irq2, (int)"", 0, (inthand2_t *)ataintr, + &bio_imask, lun); else { if (!sysctrl) pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask); } printf("ata%d at 0x%04x irq %d on ata-pci%d\n", - lun, iobase_2, irq2, unit); + lun, iobase_2, isa_apic_irq(irq2), unit); } } @@ -242,7 +258,8 @@ promise_intr(int32_t unit) #endif static int32_t -ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) +ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, + pcici_t tag, int32_t *unit) { struct ata_softc *scp = atadevices[atanlun]; int32_t mask = 0; @@ -254,7 +271,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) atanlun++; #endif if (lun > MAXATA) { - printf("ata: unit of of range(%d)\n", lun); + printf("ata: unit out of range(%d)\n", lun); return 0; } if (scp) { @@ -268,14 +285,15 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) } bzero(scp, sizeof(struct ata_softc)); - scp->unit = lun; + scp->unit = *unit; + scp->lun = lun; scp->ioaddr = ioaddr; scp->altioaddr = altioaddr; scp->active = ATA_IDLE; #ifdef ATA_DEBUG printf("ata%d: iobase=0x%04x altiobase=0x%04x\n", - scp->unit, scp->ioaddr, scp->altioaddr); + scp->lun, scp->ioaddr, scp->altioaddr); #endif /* do we have any signs of ATA/ATAPI HW being present ? */ @@ -291,7 +309,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) mask |= 0x02; #ifdef ATA_DEBUG printf("ata%d: mask=%02x status0=%02x status1=%02x\n", - scp->unit, mask, status0, status1); + scp->lun, mask, status0, status1); #endif if (!mask) { free(scp, M_DEVBUF); @@ -305,6 +323,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) outb(scp->altioaddr, ATA_A_IDS); DELAY(1000); inb(scp->ioaddr + ATA_ERROR); + DELAY(1); outb(scp->altioaddr, ATA_A_4BIT); DELAY(1); @@ -333,7 +352,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) mask &= ~0x02; #ifdef ATA_DEBUG printf("ata%d: mask=%02x status0=%02x status1=%02x\n", - scp->unit, mask, status0, status1); + scp->lun, mask, status0, status1); #endif if (!mask) { free(scp, M_DEVBUF); @@ -378,18 +397,19 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) } } #ifdef ATA_DEBUG - printf("ata%d: devices = 0x%x\n", scp->unit, scp->devices); + printf("ata%d: devices = 0x%x\n", scp->lun, scp->devices); #endif - if (!(scp->devices & (ATA_ATA_MASTER|ATA_ATAPI_MASTER))) - scp->flags |= ATA_F_SLAVE_ONLY; if (!scp->devices) { free(scp, M_DEVBUF); return 0; } bufq_init(&scp->ata_queue); TAILQ_INIT(&scp->atapi_queue); - *unit = scp->unit; - atadevices[scp->unit] = scp; + *unit = scp->lun; + scp->tag = tag; + if (bmaddr) + scp->bmaddr = bmaddr; + atadevices[scp->lun] = scp; #ifndef ATA_STATIC_ID atanlun++; #endif @@ -402,12 +422,8 @@ ataintr(int32_t unit) struct ata_softc *scp; struct atapi_request *atapi_request; struct buf *ata_request; - static int32_t intcount = 0; -#ifdef ATA_DEBUG - printf("ataintr: entered unit=%d\n", unit); -#endif if (unit < 0 || unit > atanlun) { printf("ataintr: unit %d unusable\n", unit); return; @@ -439,8 +455,9 @@ ataintr(int32_t unit) default: case ATA_IDLE: - if (intcount++ < 5) - printf("ata%d: unwanted interrupt\n", unit); + if (intcount++ < 10) + printf("ata%d: unwanted interrupt %d\n", unit, intcount); + inb(scp->ioaddr + ATA_STATUS); return; } scp->active = ATA_IDLE; @@ -456,34 +473,48 @@ ata_start(struct ata_softc *scp) #ifdef ATA_DEBUG printf("ata_start: entered\n"); #endif - if (scp->active) { + if (scp->active != ATA_IDLE) { printf("ata: unwanted ata_start\n"); return; } +#if NATADISK > 0 /* find & call the responsible driver if anything on ATA queue */ if ((ata_request = bufq_first(&scp->ata_queue))) { scp->active = ATA_ACTIVE_ATA; ad_transfer(ata_request); +#ifdef ATA_DEBUG + printf("ata_start: started ata, leaving\n"); +#endif + return; } +#endif /* find & call the responsible driver if anything on ATAPI queue */ if ((atapi_request = TAILQ_FIRST(&scp->atapi_queue))) { scp->active = ATA_ACTIVE_ATAPI; atapi_transfer(atapi_request); +#ifdef ATA_DEBUG + printf("ata_start: started atapi, leaving\n"); +#endif + return; } } int32_t -ata_wait(struct ata_softc *scp, u_int8_t mask) +ata_wait(struct ata_softc *scp, int32_t device, u_int8_t mask) { u_int8_t status; u_int32_t timeout = 0; - while (timeout++ <= 50000) { /* timeout 5 secs */ + while (timeout++ <= 500000) { /* timeout 5 secs */ status = inb(scp->ioaddr + ATA_STATUS); - if ((status == 0xff) && (scp->flags & ATA_F_SLAVE_ONLY)) { - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); + + /* if drive fails status, reselect the drive just to be sure */ + if (status == 0xff) { + printf("ata%d: %s: no status, reselecting device\n", + scp->lun, device?"slave":"master"); + outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); DELAY(1); status = inb(scp->ioaddr + ATA_STATUS); } @@ -507,21 +538,25 @@ ata_wait(struct ata_softc *scp, u_int8_t mask) int32_t ata_command(struct ata_softc *scp, int32_t device, u_int32_t command, u_int32_t cylinder, u_int32_t head, u_int32_t sector, - u_int32_t count, int32_t flags) + u_int32_t count, u_int32_t feature, int32_t flags) { +#ifdef ATA_DEBUG +printf("ata_command: addr=%04x, device=%02x, cmd=%02x, c=%d, h=%d, s=%d, count=%d, flags=%02x\n", scp->ioaddr, device, command, cylinder, head, sector, count, flags); +#endif + /* ready to issue command ? */ - if (ata_wait(scp, 0) < 0) { - printf("ata_command: timeout waiting to give command"); - return -1; + if (ata_wait(scp, device, 0) < 0) { + printf("ata%d: %s: timeout waiting to give command s=%02x e=%02x\n", + scp->lun, device?"slave":"master", scp->status, scp->error); } - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head); - outb(scp->ioaddr + ATA_PRECOMP, 0); /* no precompensation */ + outb(scp->ioaddr + ATA_FEATURE, feature); outb(scp->ioaddr + ATA_CYL_LSB, cylinder); outb(scp->ioaddr + ATA_CYL_MSB, cylinder >> 8); + outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head); outb(scp->ioaddr + ATA_SECTOR, sector); outb(scp->ioaddr + ATA_COUNT, count); - if (scp->active && flags != ATA_IMMEDIATE) + if (scp->active != ATA_IDLE && flags != ATA_IMMEDIATE) printf("DANGER active=%d\n", scp->active); switch (flags) { @@ -545,6 +580,9 @@ ata_command(struct ata_softc *scp, int32_t device, u_int32_t command, outb(scp->ioaddr + ATA_CMD, command); break; } +#ifdef ATA_DEBUG +printf("ata_command: leaving\n"); +#endif return 0; } @@ -587,4 +625,4 @@ bpack(int8_t *src, int8_t *dst, int32_t len) } dst[j] = 0x00; } -#endif +#endif /* NATA > 0 */ diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index b1b829e27b79..271f650ce290 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -25,22 +25,28 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-all.h,v 1.3 1999/03/05 09:43:30 sos Exp $ + * $Id: ata-all.h,v 1.4 1999/03/07 21:49:14 sos Exp $ */ /* ATA register defines */ #define ATA_DATA 0x00 /* data register */ #define ATA_ERROR 0x01 /* (R) error register */ -#define ATA_PRECOMP 0x01 /* (W) precompensation */ -#define ATA_COUNT 0x02 /* sector count */ +#define ATA_FEATURE 0x01 /* (W) feature register */ +#define ATA_F_DMA 0x01 /* enable DMA */ +#define ATA_F_OVL 0x02 /* enable overlap */ + +#define ATA_COUNT 0x02 /* (W) sector count */ +#define ATA_IREASON 0x02 /* (R) interrupt reason */ #define ATA_I_CMD 0x01 /* cmd (1) | data (0) */ #define ATA_I_IN 0x02 /* read (1) | write (0) */ #define ATA_I_RELEASE 0x04 /* released bus (1) */ +#define ATA_I_TAGMASK 0xf8 /* tag mask */ #define ATA_SECTOR 0x03 /* sector # */ #define ATA_CYL_LSB 0x04 /* cylinder# LSB */ #define ATA_CYL_MSB 0x05 /* cylinder# MSB */ #define ATA_DRIVE 0x06 /* Sector/Drive/Head register */ +#define ATA_D_LBA 0x40 /* use LBA adressing */ #define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */ #define ATA_CMD 0x07 /* command register */ @@ -51,15 +57,21 @@ #define ATA_C_READ_MULTI 0xc4 /* read multi command */ #define ATA_C_WRITE_MULTI 0xc5 /* write multi command */ #define ATA_C_SET_MULTI 0xc6 /* set multi size command */ -#define ATA_C_PACKET_CMD 0xa0 /* set multi size command */ +#define ATA_C_READ_DMA 0xc8 /* read w/DMA command */ +#define ATA_C_WRITE_DMA 0xca /* write w/DMA command */ +#define ATA_C_PACKET_CMD 0xa0 /* packet command */ +#define ATA_C_SETFEATURES 0xef /* features command */ +#define ATA_C_FEA_SETXFER 0x03 /* set transfer mode */ #define ATA_STATUS 0x07 /* status register */ #define ATA_S_ERROR 0x01 /* error */ #define ATA_S_INDEX 0x02 /* index */ #define ATA_S_CORR 0x04 /* data corrected */ #define ATA_S_DRQ 0x08 /* data request */ -#define ATA_S_DSC 0x10 /* drive Seek Completed */ +#define ATA_S_DSC 0x10 /* drive seek completed */ +#define ATA_S_SERV 0x10 /* drive needs service */ #define ATA_S_DWF 0x20 /* drive write fault */ +#define ATA_S_DMRD 0x20 /* DMA ready */ #define ATA_S_DRDY 0x40 /* drive ready */ #define ATA_S_BSY 0x80 /* busy */ @@ -68,28 +80,57 @@ #define ATA_A_RESET 0x04 /* RESET controller */ #define ATA_A_4BIT 0x08 /* 4 head bits */ -/* Misc defines */ +/* misc defines */ #define ATA_MASTER 0x00 #define ATA_SLAVE 0x10 #define ATA_IOSIZE 0x08 #define ATA_OP_FINISHED 0x00 #define ATA_OP_CONTINUES 0x01 -/* Devices types */ +/* devices types */ #define ATA_ATA_MASTER 0x01 #define ATA_ATA_SLAVE 0x02 #define ATA_ATAPI_MASTER 0x04 #define ATA_ATAPI_SLAVE 0x08 -/* Structure describing an ATA device */ -struct ata_softc { - u_int32_t unit; /* this instance's number */ - u_int32_t ioaddr; /* port addr */ - u_int32_t altioaddr; /* alternate port addr */ - void *dmacookie; /* handle for DMA services */ - int32_t flags; /* controller flags */ -#define ATA_F_SLAVE_ONLY 0x0001 +/* busmaster DMA related defines */ +#define ATA_BM_OFFSET1 0x08 +#define ATA_DMA_ENTRIES 256 +#define ATA_DMA_EOT 0x80000000 +#define ATA_BMCMD_PORT 0x00 +#define ATA_BMCMD_START_STOP 0x01 +#define ATA_BMCMD_WRITE_READ 0x08 + +#define ATA_BMSTAT_PORT 0x02 +#define ATA_BMSTAT_MASK 0x07 +#define ATA_BMSTAT_ACTIVE 0x01 +#define ATA_BMSTAT_ERROR 0x02 +#define ATA_BMSTAT_INTERRUPT 0x04 +#define ATA_BMSTAT_DMA_MASTER 0x20 +#define ATA_BMSTAT_DMA_SLAVE 0x40 + +#define ATA_BMDTP_PORT 0x04 + +#define ATA_WDMA2 0x22 +#define ATA_UDMA2 0x42 + +/* structure for holding DMA address data */ +struct ata_dmaentry { + u_int32_t base; + u_int32_t count; +}; + +/* structure describing an ATA device */ +struct ata_softc { + int32_t unit; /* unit on this controller */ + int32_t lun; /* logical unit # */ + pcici_t tag; /* PCI tag for this device */ + int32_t ioaddr; /* port addr */ + int32_t altioaddr; /* alternate port addr */ + int32_t bmaddr; /* bus master DMA port */ + struct ata_dmaentry *dmatab[2]; /* DMA transfer tables */ + int32_t flags; /* controller flags */ int32_t devices; /* what is present */ u_int8_t status; /* last controller status */ u_int8_t error; /* last controller error */ @@ -111,8 +152,13 @@ extern struct ata_softc *atadevices[]; /* public prototypes */ void ata_start(struct ata_softc *); -int32_t ata_wait(struct ata_softc *, u_int8_t); -int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t); +int32_t ata_wait(struct ata_softc *, int32_t, u_int8_t); +int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t); +int32_t ata_dmainit(struct ata_softc *, int32_t, int32_t, int32_t, int32_t); +int32_t ata_dmasetup(struct ata_softc *, int32_t, int8_t *, int32_t, int32_t); +void ata_dmastart(struct ata_softc *, int32_t); +int32_t ata_dmastatus(struct ata_softc *, int32_t); +int32_t ata_dmadone(struct ata_softc *, int32_t); void bswap(int8_t *, int32_t); void btrim(int8_t *, int32_t); void bpack(int8_t *, int8_t *, int32_t); diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 2d8574584467..893b8b96631c 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-disk.c,v 1.3 1999/03/05 09:43:30 sos Exp $ + * $Id: ata-disk.c,v 1.4 1999/03/07 21:49:14 sos Exp $ */ #include "ata.h" @@ -51,6 +51,7 @@ #include #endif #include +#include #include #include #include @@ -64,12 +65,16 @@ static d_ioctl_t adioctl; static d_strategy_t adstrategy; static d_psize_t adpsize; -#define BDEV_MAJOR 0 -#define CDEV_MAJOR 3 +#define BDEV_MAJOR 30 +#define CDEV_MAJOR 116 static struct cdevsw ad_cdevsw = { adopen, adclose, adread, adwrite, adioctl, nostop, nullreset, nodevtotty, +#ifdef NOTYET /* the boot code needs to be fixed to boot arbitrary devices */ seltrue, nommap, adstrategy, "ad", +#else + seltrue, nommap, adstrategy, "wd", +#endif NULL, -1, nodump, adpsize, D_DISK, 0, -1 }; @@ -85,12 +90,45 @@ static void ad_strategy(struct buf *); static void ad_start(struct ad_softc *); static void ad_sleep(struct ad_softc *, int8_t *); static int8_t ad_version(u_int16_t); +int32_t ad_timeout(char *data); static void ad_drvinit(void); static struct ad_softc *adtab[NUNIT]; static int32_t adnlun = 0; /* number of config'd drives */ static struct intr_config_hook *ad_attach_hook; +static __inline int +apiomode(struct ata_params *ap) +{ + if ((ap->atavalid & 2) == 2) { + if ((ap->apiomodes & 2) == 2) return 4; + if ((ap->apiomodes & 1) == 1) return 3; + } + return -1; +} + +static __inline int +wdmamode(struct ata_params *ap) +{ + if ((ap->atavalid & 2) == 2) { + if ((ap->wdmamodes & 4) == 4) return 2; + if ((ap->wdmamodes & 2) == 2) return 1; + if ((ap->wdmamodes & 1) == 1) return 0; + } + return -1; +} + +static __inline int +udmamode(struct ata_params *ap) +{ + if ((ap->atavalid & 4) == 4) { + if ((ap->udmamodes & 4) == 4) return 2; + if ((ap->udmamodes & 2) == 2) return 1; + if ((ap->udmamodes & 1) == 1) return 0; + } + return -1; +} + static void ad_attach(void *notused) { @@ -100,7 +138,8 @@ ad_attach(void *notused) int8_t revision_buf[8+1]; /* now, run through atadevices and look for ATA disks */ - for (ctlr=0; ctlrdevices & (dev ? ATA_ATA_SLAVE : ATA_ATA_MASTER)) { @@ -132,16 +171,26 @@ ad_attach(void *notused) adp->total_secs = adp->ata_parm->lbasize; adp->cylinders = adp->total_secs/(adp->heads*adp->sectors); } + if (adp->ata_parm->atavalid & ATA_FLAG_54_58 && + adp->ata_parm->lbasize) + adp->flags |= AD_F_USE_LBA; - /* support multiple sectors / interrupt ? */ + /* use multiple sectors/interrupt if device supports it */ adp->transfersize = DEV_BSIZE; secsperint = min(adp->ata_parm->nsecperint, 16); if (!ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI, - 0, 0, 0, secsperint, ATA_WAIT_INTR) && - ata_wait(adp->controller, ATA_S_DRDY) >= 0) + 0, 0, 0, secsperint, 0, ATA_WAIT_INTR) && + ata_wait(adp->controller, adp->unit, ATA_S_DRDY) >= 0) adp->transfersize *= secsperint; + /* use DMA if drive & controller supports it */ + if (!ata_dmainit(adp->controller, adp->unit, + apiomode(adp->ata_parm), + wdmamode(adp->ata_parm), + udmamode(adp->ata_parm))) + adp->flags |= AD_F_DMA_ENABLED; + bpack(adp->ata_parm->model, model_buf, sizeof(model_buf)); bpack(adp->ata_parm->revision, revision_buf, sizeof(revision_buf)); @@ -160,9 +209,15 @@ ad_attach(void *notused) adp->heads, adp->sectors, DEV_BSIZE); - printf("ad%d: %d secs/int, %d depth queue \n", + printf("ad%d: piomode=%d, dmamode=%d, udmamode=%d\n", + adnlun, + apiomode(adp->ata_parm), + wdmamode(adp->ata_parm), + udmamode(adp->ata_parm)); + printf("ad%d: %d secs/int, %d depth queue, %s mode\n", adnlun, adp->transfersize / DEV_BSIZE, - adp->ata_parm->queuelen & 0x1f); + adp->ata_parm->queuelen & 0x1f, + (adp->flags & AD_F_DMA_ENABLED) ? "DMA" :"PIO"); devstat_add_entry(&adp->stats, "ad", adnlun, DEV_BSIZE, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, @@ -193,9 +248,13 @@ ad_getparam(struct ad_softc *adp) struct ata_params *ata_parm; int8_t buffer[DEV_BSIZE]; + /* select drive */ + outb(adp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | adp->unit); + DELAY(1); ata_command(adp->controller, adp->unit, ATA_C_ATA_IDENTIFY, - 0, 0, 0, 0, ATA_WAIT_INTR); - if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) + 0, 0, 0, 0, 0, ATA_WAIT_INTR); + if (ata_wait(adp->controller, adp->unit, + ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) return -1; insw(adp->controller->ioaddr + ATA_DATA, buffer, sizeof(buffer)/sizeof(int16_t)); @@ -226,6 +285,7 @@ printf("adopen: lun=%d adnlun=%d\n", lun, adnlun); return ENXIO; /* spinwait if anybody else is reading the disk label */ + /* is this needed anymore ?? SOS XXX */ while (adp->flags & AD_F_LABELLING) tsleep((caddr_t)&adp->flags, PZERO - 1, "adop1", 1); @@ -316,22 +376,20 @@ printf("adstrategy: entered\n"); if (dscheck(bp, adp->slices) <= 0) goto done; - s = splbio(); /* hang around if somebody else is labelling */ if (adp->flags & AD_F_LABELLING) ad_sleep(adp, "adlab"); + s = splbio(); bufqdisksort(&adp->queue, bp); if (!adp->active) ad_start(adp); - if (!adp->controller->active) + if (adp->controller->active == ATA_IDLE) ata_start(adp->controller); - devstat_start_transaction(&adp->stats); - splx(s); return; @@ -373,8 +431,9 @@ printf("ad_start:\n"); if (!(bp = bufq_first(&adp->queue))) return; - bp->b_driver1 = adp; + /* remove from drive queue */ bufq_remove(&adp->queue, bp); + bp->b_driver1 = adp; /* link onto controller queue */ bufq_insert_tail(&adp->controller->ata_queue, bp); @@ -403,41 +462,70 @@ ad_transfer(struct buf *bp) /* setup transfer parameters */ adp->bytecount = bp->b_bcount; - secsprcyl = adp->sectors * adp->heads; - cylinder = blknum / secsprcyl; - head = (blknum % secsprcyl) / adp->sectors; - sector = blknum % adp->sectors; count = howmany(adp->bytecount, DEV_BSIZE); - if (count > 255) /* SOS */ - printf("ad_transfer: count=%d\n", count); + if (adp->flags & AD_F_USE_LBA) { + sector = (blknum >> 0) & 0xff; + cylinder = (blknum >> 8) & 0xffff; + head = ((blknum >> 24) & 0xf) | ATA_D_LBA; + } + else { + secsprcyl = adp->sectors * adp->heads; + cylinder = blknum / secsprcyl; + head = (blknum % secsprcyl) / adp->sectors; + sector = (blknum % adp->sectors) + 1; + } - /* setup transfer length if multible sector access present */ + /* setup first transfer length */ adp->currentsize = min(adp->bytecount, adp->transfersize); - if (adp->currentsize > DEV_BSIZE) + + devstat_start_transaction(&adp->stats); + + /* does this drive & transfer work with DMA ? */ + adp->flags &= ~AD_F_DMA_USED; + if ((adp->flags & AD_F_DMA_ENABLED) && + !ata_dmasetup(adp->controller, adp->unit, + (void *)bp->b_data, adp->bytecount, + (bp->b_flags & B_READ))) { + adp->flags |= AD_F_DMA_USED; + command = (bp->b_flags&B_READ) ? ATA_C_READ_DMA : ATA_C_WRITE_DMA; + adp->currentsize = adp->bytecount; + } + /* does this drive support multi sector transfers ? */ + else if (adp->currentsize > DEV_BSIZE) command = (bp->b_flags&B_READ) ? ATA_C_READ_MULTI:ATA_C_WRITE_MULTI; else command = (bp->b_flags&B_READ) ? ATA_C_READ : ATA_C_WRITE; ata_command(adp->controller, adp->unit, command, cylinder, head, - sector + 1, count, ATA_IMMEDIATE); + sector, count, 0, ATA_IMMEDIATE); } - /* if this is a read operation, return and wait for interrupt */ + /* if this is a DMA transaction start it, return and wait for interrupt */ + if (adp->flags & AD_F_DMA_USED) { + ata_dmastart(adp->controller, adp->unit); +#ifdef AD_DEBUG + printf("ad_transfer: return waiting for DMA interrupt\n"); +#endif + return; + } + + /* calculate this transfer length */ + adp->currentsize = min(adp->bytecount, adp->transfersize); + + /* if this is a PIO read operation, return and wait for interrupt */ if (bp->b_flags & B_READ) { #ifdef AD_DEBUG - printf("ad_transfer: return waiting to read data\n"); + printf("ad_transfer: return waiting for PIO read interrupt\n"); #endif return; } - /* ready to write data ? */ - if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) < 0) { + /* ready to write PIO data ? */ + if (ata_wait(adp->controller, adp->unit, + ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) < 0) { printf("ad_transfer: timeout waiting for DRQ"); } - - /* calculate transfer length */ - adp->currentsize = min(adp->bytecount, adp->transfersize); /* output the data */ #if 0 @@ -459,14 +547,22 @@ int32_t ad_interrupt(struct buf *bp) { struct ad_softc *adp = bp->b_driver1; + int32_t dma_stat = 0; - /* finish DMA stuff */ + /* finish DMA transfer */ + if (adp->flags & AD_F_DMA_USED) { + if (!(ata_dmastatus(adp->controller, adp->unit) & ATA_BMSTAT_INTERRUPT)){ +printf("extra SMP interrupt\n"); + return ATA_OP_CONTINUES; +} + dma_stat = ata_dmadone(adp->controller, adp->unit); + } /* get drive status */ - if (ata_wait(adp->controller, 0) < 0) - printf("ad_interrupt: timeout waiting for status"); - - if (adp->controller->status & (ATA_S_ERROR | ATA_S_CORR)) { + if (ata_wait(adp->controller, adp->unit, 0) < 0) + printf("ad_interrupt: timeout waiting for status"); + if (adp->controller->status & (ATA_S_ERROR | ATA_S_CORR) || + (adp->flags & AD_F_DMA_USED && dma_stat != ATA_BMSTAT_INTERRUPT)) { oops: printf("ad%d: status=%02x error=%02x\n", adp->lun, adp->controller->status, adp->controller->error); @@ -478,23 +574,23 @@ ad_interrupt(struct buf *bp) if (adp->controller->status & ATA_S_CORR) printf("ad_interrupt: soft ECC\n"); } - /* if this was a read operation, get the data */ - if (((bp->b_flags & (B_READ | B_ERROR)) == B_READ) && adp->active) { + + /* if this was a PIO read operation, get the data */ + if (adp->active && !(adp->flags & AD_F_DMA_USED) && + ((bp->b_flags & (B_READ | B_ERROR)) == B_READ)) { /* ready to receive data? */ if ((adp->controller->status & (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) != (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) printf("ad_interrupt: read interrupt arrived early"); - if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) != 0){ + if (ata_wait(adp->controller, adp->unit, + ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ) != 0){ printf("ad_interrupt: read error detected late"); goto oops; } - /* calculate transfer length */ - adp->currentsize = min(adp->bytecount, adp->currentsize); - - /* data are ready, get them */ + /* data ready, read in */ #if 0 insw(adp->controller->ioaddr + ATA_DATA, (void *)((int32_t)bp->b_data + adp->donecount), @@ -510,26 +606,30 @@ ad_interrupt(struct buf *bp) #endif } + /* if this was a DMA operation finish up */ + if (adp->active && (adp->flags & AD_F_DMA_USED) && !(bp->b_flags & B_ERROR)) + adp->bytecount -= adp->currentsize; + /* finish up this tranfer, check for more work on this buffer */ - if (adp->controller->active) { + if (adp->controller->active == ATA_ACTIVE_ATA) { if ((bp->b_flags & B_ERROR) == 0) { adp->donecount += adp->currentsize; #ifdef AD_DEBUG - printf("ad_interrupt: %s operation OK\n", (bp->b_flags & B_READ)?"R":"W"); + printf("ad_interrupt: %s op OK\n", (bp->b_flags & B_READ)?"R":"W"); #endif if (adp->bytecount > 0) { - ad_transfer(bp); /* MESSY!! only needed for W */ + ad_transfer(bp); return ATA_OP_CONTINUES; } } bufq_remove(&adp->controller->ata_queue, bp); bp->b_resid = bp->b_bcount - adp->donecount; - adp->donecount = 0; + biodone(bp); devstat_end_transaction(&adp->stats, bp->b_bcount - bp->b_resid, DEVSTAT_TAG_NONE, (bp->b_flags & B_READ) ? DEVSTAT_READ : DEVSTAT_WRITE); - biodone(bp); + adp->donecount = 0; adp->active = 0; } ad_start(adp); @@ -544,7 +644,7 @@ ad_sleep(struct ad_softc *adp, int8_t *mesg) { int32_t s = splbio(); - while (adp->controller->active) + while (adp->controller->active != ATA_IDLE) tsleep((caddr_t)&adp->controller->active, PZERO - 1, mesg, 1); splx(s); } @@ -569,6 +669,7 @@ ad_drvinit(void) if (!ad_devsw_installed) { cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &ad_cdevsw); + cdevsw_add_generic(0, 3, &ad_cdevsw); /* grap wd entries too */ ad_devsw_installed = 1; } /* register callback for when interrupts are enabled */ diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index bd4a37ffa6b5..5056c78516d6 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-disk.h,v 1.3 1999/03/05 09:43:30 sos Exp $ + * $Id: ata-disk.h,v 1.4 1999/03/07 21:49:14 sos Exp $ */ /* ATA device parameter information */ @@ -37,7 +37,7 @@ struct ata_params { int16_t unfbytespertrk; /* # unformatted bytes/track */ int16_t unfbytes; /* # unformatted bytes/sector */ u_int16_t sectors; /* # sectors/track */ - int16_t vendorunique[3]; + int16_t vendorunique0[3]; int8_t serial[20]; /* serial number */ int16_t buffertype; /* buffer type */ #define ATA_BT_SINGLEPORTSECTOR 1 /* 1 port, 1 sector buffer */ @@ -51,14 +51,27 @@ struct ata_params { int8_t nsecperint; /* sectors per interrupt */ int8_t vendorunique1; int16_t usedmovsd; /* double word read/write? */ - int8_t vendorunique2; - int8_t capability; /* various capability bits */ - int16_t cap_validate; /* validation for above */ + + u_int8_t vendorcap; /* vendor capabilities */ + u_int8_t dmaflag :1; /* DMA supported - always 1 */ + u_int8_t lbaflag :1; /* LBA supported - always 1 */ + u_int8_t iordydis :1; /* IORDY may be disabled */ + u_int8_t iordyflag :1; /* IORDY supported */ + u_int8_t :1; + u_int8_t standby :1; /* standby timer supported */ + u_int8_t :1; + u_int8_t :1; + int16_t capvalidate; /* validation for above */ + int8_t vendorunique3; int8_t opiomode; /* PIO modes 0-2 */ int8_t vendorunique4; int8_t odmamode; /* old DMA modes, not ATA-3 */ + int16_t atavalid; /* fields valid */ +#define ATA_FLAG_54_58 1 /* words 54-58 valid */ +#define ATA_FLAG_64_70 2 /* words 64-70 valid */ + int16_t currcyls; int16_t currheads; int16_t currsectors; @@ -67,17 +80,20 @@ struct ata_params { int8_t currmultsect; int8_t multsectvalid; int32_t lbasize; - int16_t dmasword; /* obsolete in ATA-3 */ - int16_t dmamword; /* multiword DMA modes */ - int16_t eidepiomodes; /* advanced PIO modes */ - int16_t eidedmamin; /* fastest DMA timing */ - int16_t eidedmanorm; /* recommended DMA timing */ - int16_t eidepioblind; /* fastest possible blind PIO */ - int16_t eidepioacked; /* fastest possible IORDY PIO */ + + int16_t sdmamodes; /* singleword DMA modes */ + int16_t wdmamodes; /* multiword DMA modes */ + int16_t apiomodes; /* advanced PIO modes */ + + u_int16_t mwdmamin; /* min. M/W DMA time/word ns */ + u_int16_t mwdmarec; /* rec. M/W DMA time ns */ + u_int16_t pioblind; /* min. PIO cycle w/o flow */ + u_int16_t pioiordy; /* min. PIO cycle IORDY flow */ + int16_t reserved69; int16_t reserved70; - int16_t reserved71; - int16_t reserved72; + u_int16_t rlsovlap; /* rel time (us) for overlap */ + u_int16_t rlsservice; /* rel time (us) for service */ int16_t reserved73; int16_t reserved74; int16_t queuelen; @@ -93,7 +109,7 @@ struct ata_params { int16_t featenab1; int16_t featenab2; int16_t featenab3; - int16_t udmamode; /* UltraDMA modes */ + int16_t udmamodes; /* UltraDMA modes */ int16_t erasetime; int16_t enherasetime; int16_t apmlevel; @@ -120,8 +136,13 @@ struct ad_softc { u_int32_t donecount; /* bytes transferred */ u_int32_t active; /* active processing request */ u_int32_t flags; /* drive flags */ - struct devstat stats; /* devstat entry */ #define AD_F_LABELLING 0x0001 +#define AD_F_USE_LBA 0x0002 +#define AD_F_USE_32BIT 0x0004 +#define AD_F_DMA_ENABLED 0x0008 +#define AD_F_DMA_USED 0x0010 + + struct devstat stats; /* devstat entry */ #ifdef DEVFS void *cdevs_token; void *bdevs_token; diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c new file mode 100644 index 000000000000..1de2f9b824aa --- /dev/null +++ b/sys/dev/ata/ata-dma.c @@ -0,0 +1,366 @@ +/*- + * Copyright (c) 1998,1999 Søren Schmidt + * 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. + * + * $Id$ + */ + +#include "ata.h" +#if NATA > 0 +#include "pci.h" +#if NPCI > 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* misc defines */ +#define MIN(a,b) ((a)>(b)?(b):(a)) + +int32_t +ata_dmainit(struct ata_softc *scp, int32_t device, + int32_t apiomode, int32_t wdmamode, int32_t udmamode) +{ + int32_t type, devno, error; + void *dmatab; + + if (!scp->bmaddr) + return -1; +#ifdef ATA_DEBUGDMA + printf("ata%d: dmainit: ioaddr=0x%x altioaddr=0x%x, bmaddr=0x%x\n", + scp->lun, scp->ioaddr, scp->altioaddr, scp->bmaddr); +#endif + + if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) + return -1; + + if (((int)dmatab>>PAGE_SHIFT)^(((int)dmatab+PAGE_SIZE-1)>>PAGE_SHIFT)) { + printf("ata_dmainit: dmatab crosses page boundary, no DMA\n"); + free(dmatab, M_DEVBUF); + return -1; + } + scp->dmatab[device ? 1 : 0] = dmatab; + + type = pci_conf_read(scp->tag, PCI_ID_REG); + + switch(type) { + + case 0x71118086: /* Intel PIIX4 */ + if (udmamode >= 2) { + int32_t mask48, new48; + + printf("ata%d: %s: settting up UDMA2 mode on PIIX4 chip ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + devno = (scp->unit << 1) + (device) ? 1 : 0; + mask48 = (1 << devno) + (3 << (16 + (devno << 2))); + new48 = (1 << devno) + (2 << (16 + (devno << 2))); + + pci_conf_write(scp->tag, 0x48, + (pci_conf_read(scp->tag, 0x48) & ~mask48) | new48); + return 0; + } + /* 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_conf_read(scp->tag, 0x40) >> (scp->unit<<8)) & 0x4000)) { + new40 = pci_conf_read(scp->tag, 0x40); + new44 = pci_conf_read(scp->tag, 0x44); + 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_conf_write(scp->tag, 0x40, new40); + pci_conf_write(scp->tag, 0x44, new44); + } + printf("ata%d: %s: settting up WDMA2 mode on PIIX3/4 chip ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + if (device == ATA_MASTER) { + mask40 = 0x0000330f; + new40 = 0x00002307; + mask44 = 0; + new44 = 0; + } else { + mask40 = 0x000000f0; + new40 = 0x00000070; + mask44 = 0x0000000f; + new44 = 0x0000000b; + } + if (scp->unit) { + mask40 <<= 16; + new40 <<= 16; + mask44 <<= 4; + new44 <<= 4; + } + pci_conf_write(scp->tag, 0x40, + (pci_conf_read(scp->tag, 0x40) & ~mask40) | new40); + pci_conf_write(scp->tag, 0x44, + (pci_conf_read(scp->tag, 0x44) & ~mask44) | new44); + return 0; + } + break; + + case 0x12308086: /* Intel PIIX */ + /* probably not worth the trouble */ + break; + + case 0x4d33105a: /* Promise Ultra/33 / FastTrack controllers */ + devno = (scp->unit << 1) + (device) ? 1 : 0; + if (udmamode >=2) { + outb(scp->bmaddr + 0x1f, inb(scp->bmaddr + 0x1f) | 0x01); + pci_conf_write(scp->tag, 0x60 + (devno << 2), 0x004127f3); + printf("ata%d: %s: settting up UDMA2 mode on Promise chip ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + } + else if (wdmamode >= 2 && apiomode >= 4) { + outb(scp->bmaddr + 0x1f, inb(scp->bmaddr + 0x1f) | 0x01); + pci_conf_write(scp->tag, 0x60 + (devno << 2), 0x004367f3); + printf("ata%d: %s: settting up WDMA2 mode on Promise chip ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + } + else { + pci_conf_write(scp->tag, 0x60 + (devno << 2), 0x004fe924); + printf("ata%d: %s: settting up PIO mode on Promise chip OK\n", + scp->lun, (device) ? "slave" : "master"); + } + break; + + case 0x522910b9: /* AcerLabs Aladdin IV/V */ + if (udmamode >=2) { + int32_t word54 = pci_conf_read(scp->tag, 0x54); + + printf("ata%d: %s: settting up UDMA2 mode on Aladdin chip ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_UDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + word54 |= 0x5555; + word54 |= (0x0000000A << (16 + (scp->unit << 3) + (device << 2))); + pci_conf_write(scp->tag, 0x54, word54); + return 0; + + } + else if (wdmamode >= 2 && apiomode >= 4) { + printf("ata%d: %s: settting up WDMA2 mode on Aladdin chip ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + return 0; + } + break; + + default: /* well, we have no support for this, but try anyways */ + if ((wdmamode >= 2 && apiomode >= 4) || udmamode >= 2) { + printf("ata%d: %s: settting up generic WDMA2 mode ", + scp->lun, (device) ? "slave" : "master"); + error = ata_command(scp, device, ATA_C_SETFEATURES, 0, 0, 0, + ATA_WDMA2, ATA_C_FEA_SETXFER, ATA_WAIT_INTR); + if (error) { + printf("failed\n"); + break; + } + printf("OK\n"); + return 0; + } + } + free(dmatab, M_DEVBUF); + return -1; +} + +int32_t +ata_dmasetup(struct ata_softc *scp, int32_t device, + int8_t *data, int32_t count, int32_t flags) +{ + struct ata_dmaentry *dmatab; + u_int32_t dma_count, dma_base; + int32_t i = 0; + +#ifdef ATA_DEBUGDMA + printf("ata%d: dmasetup\n", scp->lun); +#endif + if (((u_int32_t)data & 1) || (count & 1)) + return -1; + + if (!count) { + printf("ata%d: zero length DMA transfer attempt on %s\n", + scp->lun, (device ? "slave" : "master")); + return -1; + } + + dmatab = scp->dmatab[device ? 1 : 0]; + dma_base = vtophys(data); + dma_count = MIN(count, (PAGE_SIZE - ((u_int32_t)data & PAGE_MASK))); + data += dma_count; + count -= dma_count; + + while (count) { + dmatab[i].base = dma_base; + dmatab[i].count = (dma_count & 0xffff); + i++; + if (i >= ATA_DMA_ENTRIES) { + printf("ata%d: too many segments in DMA table for %s\n", + scp->lun, (device ? "slave" : "master")); + return -1; + } + dma_base = vtophys(data); + dma_count = MIN(count, PAGE_SIZE); + data += MIN(count, PAGE_SIZE); + count -= MIN(count, PAGE_SIZE); + } +#ifdef ATA_DEBUGDMA +printf("ata_dmasetup: base=%08x count%08x\n", + dma_base, dma_count); +#endif + dmatab[i].base = dma_base; + dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; + + outl(scp->bmaddr + ATA_BMDTP_PORT, vtophys(dmatab)); +#ifdef ATA_DEBUGDMA +printf("dmatab=%08x %08x\n", vtophys(dmatab), inl(scp->bmaddr+ATA_BMDTP_PORT)); +#endif + outb(scp->bmaddr + ATA_BMCMD_PORT, flags ? ATA_BMCMD_WRITE_READ:0); + outb(scp->bmaddr + ATA_BMSTAT_PORT, (inb(scp->bmaddr + ATA_BMSTAT_PORT) | + (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); + return 0; +} + +void +ata_dmastart(struct ata_softc *scp, int32_t device) +{ +#ifdef ATA_DEBUGDMA + printf("ata%d: dmastart\n", scp->lun); +#endif + outb(scp->bmaddr + ATA_BMCMD_PORT, + inb(scp->bmaddr + ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); +} + +int32_t +ata_dmadone(struct ata_softc *scp, int32_t device) +{ +#ifdef ATA_DEBUGDMA + printf("ata%d: dmadone\n", scp->lun); +#endif + outb(scp->bmaddr + ATA_BMCMD_PORT, + inb(scp->bmaddr + ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); + return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; +} + +int32_t +ata_dmastatus(struct ata_softc *scp, int32_t device) +{ +#ifdef ATA_DEBUGDMA + printf("ata%d: dmastatus\n", scp->lun); +#endif + return inb(scp->bmaddr + ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; +} + +#else /* NPCI > 0 */ + +int32_t +ata_dmainit(struct ata_softc *scp, int32_t device, + int32_t piomode, int32_t wdmamode, int32_t udmamode) +{ + return -1; +} + +int32_t +ata_dmasetup(struct ata_softc *scp, int32_t device, + int8_t *data, int32_t count, int32_t flags) +{ + return -1; +} + +void +ata_dmastart(struct ata_softc *scp, int32_t device) +{ +} + +int32_t +ata_dmadone(struct ata_softc *scp, int32_t device) +{ + return -1; +} + +int32_t +ata_dmastatus(struct ata_softc *scp, int32_t device) +{ + return -1; +} + +#endif /* NPCI > 0 */ +#endif /* NATA > 0 */ + diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 992b1268237a..d230b691e1b6 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-all.c,v 1.3 1999/03/05 09:43:30 sos Exp $ + * $Id: atapi-all.c,v 1.4 1999/03/07 21:49:14 sos Exp $ */ #include "ata.h" @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,7 @@ static int8_t *atapi_type(int32_t); #ifdef ATAPI_DEBUG static int8_t *atapi_cmd2str(u_int8_t); #endif -int32_t atapi_wait(struct ata_softc *, u_int8_t); +static int32_t atapi_wait(struct atapi_softc *, u_int8_t); static void atapi_init(void); /* extern references */ @@ -73,7 +74,8 @@ atapi_attach(void *notused) int8_t revision_buf[8+1]; /* now, run through atadevices and look for ATAPI devices */ - for (ctlr=0; ctlrdevices & (dev ? ATA_ATAPI_SLAVE : ATA_ATAPI_MASTER)) { @@ -84,11 +86,12 @@ atapi_attach(void *notused) } bzero(atp, sizeof(struct atapi_softc)); atp->controller = atadevices[ctlr]; - atp->unit = (dev) ? ATA_SLAVE : ATA_MASTER; + atp->unit = (dev == 0) ? ATA_MASTER : ATA_SLAVE; if (atapi_getparam(atp)) { free(atp, M_DEVBUF); continue; } + switch (atp->atapi_parm->device_type) { #if NATAPICD > 0 case ATAPI_TYPE_CDROM: @@ -133,9 +136,12 @@ atapi_getparam(struct atapi_softc *atp) struct atapi_params *atapi_parm; int8_t buffer[DEV_BSIZE]; + /* select drive */ + outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit); + DELAY(1); ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY, - 0, 0, 0, 0, ATA_WAIT_INTR); - if (atapi_wait(atp->controller, ATA_S_DRQ)) + 0, 0, 0, 0, 0, ATA_WAIT_INTR); + if (atapi_wait(atp, ATA_S_DRQ)) return -1; insw(atp->controller->ioaddr + ATA_DATA, buffer, sizeof(buffer)/sizeof(int16_t)); @@ -148,8 +154,6 @@ atapi_getparam(struct atapi_softc *atp) btrim(atapi_parm->model, sizeof(atapi_parm->model)); bswap(atapi_parm->revision, sizeof(atapi_parm->revision)); btrim(atapi_parm->revision, sizeof(atapi_parm->revision)); - bswap(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */ - btrim(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */ atp->atapi_parm = atapi_parm; return 0; } @@ -162,11 +166,10 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, { struct atapi_request *request; int32_t error = 0; - int32_t x; + int32_t s; if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT))) return -1; - x = splbio(); bzero(request, sizeof(struct atapi_request)); request->device = atp; request->data = data; @@ -181,13 +184,15 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, bcopy(ccb, request->ccb, request->ccbsize); /* link onto controller queue */ + s = splbio(); TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain); + splx(s); #ifdef ATAPI_DEBUG printf("atapi: queued %s cmd\n", atapi_cmd2str(ccb[0])); #endif /* try to start controller */ - if (!atp->controller->active) + if (atp->controller->active == ATA_IDLE) ata_start(atp->controller); if (!callback) { /* wait for command to complete */ @@ -200,7 +205,6 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, #endif free(request, M_DEVBUF); } - splx(x); return error; } @@ -209,7 +213,7 @@ atapi_transfer(struct atapi_request *request) { struct atapi_softc *atp; int32_t timeout; - int8_t int_reason; /* not needed really */ + int8_t reason; /* not needed really */ /* get device params */ atp = request->device; @@ -220,7 +224,7 @@ atapi_transfer(struct atapi_request *request) /* start ATAPI operation */ ata_command(atp->controller, atp->unit, ATA_C_PACKET_CMD, - request->bytecount, 0, 0, 0, ATA_IMMEDIATE); + request->bytecount, 0, 0, 0, 0, ATA_IMMEDIATE); /* command interrupt device ? just return */ if (atp->atapi_parm->drqtype == ATAPI_DRQT_INTR) @@ -229,9 +233,9 @@ atapi_transfer(struct atapi_request *request) /* ready to write ATAPI command */ timeout = 5000; /* might be less for fast devices */ while (timeout--) { - int_reason = inb(atp->controller->ioaddr + ATA_COUNT); + reason = inb(atp->controller->ioaddr + ATA_IREASON); atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS); - if (((int_reason & (ATA_I_CMD | ATA_I_IN)) | + if (((reason & (ATA_I_CMD | ATA_I_IN)) | (atp->controller->status&(ATA_S_DRQ|ATA_S_BSY))) == ATAPI_P_CMDOUT) break; DELAY(20); @@ -263,7 +267,7 @@ printf("atapi_interrupt: enter\n"); atp = request->device; /* get drive status */ - if (atapi_wait(atp->controller, 0) < 0) { + if (atapi_wait(atp, 0) < 0) { printf("atapi_interrupt: timeout waiting for status"); /* maybe check sense code ?? SOS */ return ATA_OP_FINISHED; @@ -273,7 +277,7 @@ printf("atapi_interrupt: enter\n"); length = inb(atp->controller->ioaddr + ATA_CYL_LSB); length |= inb(atp->controller->ioaddr + ATA_CYL_MSB) << 8; - reason = (inb(atp->controller->ioaddr + ATA_COUNT)&(ATA_I_CMD|ATA_I_IN)) | + reason = (inb(atp->controller->ioaddr + ATA_IREASON)&(ATA_I_CMD|ATA_I_IN)) | (atp->controller->status & ATA_S_DRQ); #ifdef ATAPI_DEBUG @@ -300,15 +304,13 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); printf("atapi_interrupt: write data underrun %d/%d\n", length, request->bytecount); outsw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), /* + donecount ?? */ - length / sizeof(int16_t)); + (void *)((int32_t)request->data), length / sizeof(int16_t)); for (resid=request->bytecount; residcontroller->ioaddr + ATA_DATA, 0); } else { outsw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), /* + donecount ?? */ - length / sizeof(int16_t)); + (void *)((int32_t)request->data), length / sizeof(int16_t)); } request->bytecount -= length; request->data += length; @@ -323,15 +325,13 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); printf("atapi_interrupt: read data overrun %d/%d\n", length, request->bytecount); insw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), /* + donecount ?? */ - length / sizeof(int16_t)); + (void *)((int32_t)request->data), length / sizeof(int16_t)); for (resid=request->bytecount; residcontroller->ioaddr + ATA_DATA); } else { insw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), /* + donecount ?? */ - length / sizeof(int16_t)); + (void *)((int32_t)request->data), length / sizeof(int16_t)); } request->bytecount -= length; request->data += length; @@ -378,11 +378,12 @@ atapi_error(struct atapi_softc *atp, int32_t error) void atapi_dump(int8_t *label, void *data, int32_t len) { - u_int8_t *p = data; + u_int8_t *p = data; - printf ("atapi: %s %x", label, *p++); - while (--len > 0) printf ("-%02x", *p++); - printf ("\n"); + printf ("atapi: %s %x", label, *p++); + while (--len > 0) + printf ("-%02x", *p++); + printf ("\n"); } static int8_t * @@ -448,20 +449,21 @@ atapi_cmd2str(u_int8_t cmd) } #endif -int32_t -atapi_wait(struct ata_softc *scp, u_int8_t mask) +static int32_t +atapi_wait(struct atapi_softc *atp, u_int8_t mask) { u_int8_t status; u_int32_t timeout = 0; while (timeout++ <= 500000) { /* timeout 5 secs */ - status = inb(scp->ioaddr + ATA_STATUS); - if ((status == 0xff) && (scp->flags & ATA_F_SLAVE_ONLY)) { - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); - DELAY(1); - status = inb(scp->ioaddr + ATA_STATUS); - } + status = inb(atp->controller->ioaddr + ATA_STATUS); + /* if drive fails status, reselect the drive just to be sure */ + if (status == 0xff) { + outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit); + DELAY(1); + status = inb(atp->controller->ioaddr + ATA_STATUS); + } if (!(status & ATA_S_BSY)) break; DELAY (10); @@ -473,7 +475,7 @@ atapi_wait(struct ata_softc *scp, u_int8_t mask) /* Wait 50 msec for bits wanted. */ for (timeout=5000; timeout>0; --timeout) { - status = inb(scp->ioaddr + ATA_STATUS); + status = inb(atp->controller->ioaddr + ATA_STATUS); if ((status & mask) == mask) return (status & ATA_S_ERROR); DELAY (10); diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index 471e1c846bbd..f8337a7ac9a6 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-all.h,v 1.2 1999/03/03 21:10:29 sos Exp $ + * $Id: atapi-all.h,v 1.3 1999/03/07 21:49:14 sos Exp $ */ /* ATAPI misc defines */ @@ -50,7 +50,7 @@ #define ATAPI_SK_HARDWARE_ERROR 0x40 /* non-recoverable HW failure */ #define ATAPI_SK_ILLEGAL_REQUEST 0x50 /* invalid command param(s) */ #define ATAPI_SK_UNIT_ATTENTION 0x60 /* media changed */ -#define ATAPI_SK_DATA_PROTECT 0x70 /* reading read-protected sec */ +#define ATAPI_SK_DATA_PROTECT 0x70 /* write protect */ #define ATAPI_SK_BLANK_CHECK 0x80 /* blank check */ #define ATAPI_SK_VENDOR_SPECIFIC 0x90 /* vendor specific skey */ #define ATAPI_SK_COPY_ABORTED 0xa0 /* copy aborted */ @@ -109,13 +109,25 @@ struct atapi_params { u_int8_t proto :2; /* command protocol */ #define ATAPI_PROTO_ATAPI 2 - int16_t reserved1[9]; + int16_t reserved1; + int16_t reserved2; + int16_t reserved3; + int16_t reserved4; + int16_t reserved5; + int16_t reserved6; + int16_t reserved7; + int16_t reserved8; + int16_t reserved9; int8_t serial[20]; /* serial number */ - int16_t reserved2[3]; + int16_t reserved20; + int16_t reserved21; + int16_t reserved22; int8_t revision[8]; /* firmware revision */ int8_t model[40]; /* model name */ - int16_t reserved3[2]; - u_int8_t vendor_cap; /* vendor capabilities */ + int16_t reserved47; + int16_t reserved48; + + u_int8_t vendorcap; /* vendor capabilities */ u_int8_t dmaflag :1; /* DMA supported */ u_int8_t lbaflag :1; /* LBA supported - always 1 */ u_int8_t iordydis :1; /* IORDY can be disabled */ @@ -124,27 +136,52 @@ struct atapi_params { u_int8_t ovlapflag :1; /* overlap supported */ u_int8_t :1; u_int8_t idmaflag :1; /* interleaved DMA supported */ - int16_t reserved4; - u_int16_t pio_timing; /* PIO cycle timing */ - u_int16_t dma_timing; /* DMA cycle timing */ - u_int16_t flags; + int16_t capvalidate; /* validation for above */ + + u_int16_t piotiming; /* PIO cycle timing */ + u_int16_t dmatiming; /* DMA cycle timing */ + + u_int16_t atavalid; /* fields valid */ #define ATAPI_FLAG_54_58 1 /* words 54-58 valid */ #define ATAPI_FLAG_64_70 2 /* words 64-70 valid */ - int16_t reserved5[8]; - u_int8_t swdma_flag; /* singleword DMA supported */ - u_int8_t swdma_active; /* singleword DMA active */ - u_int8_t mwdma_flag; /* multiword DMA supported */ - u_int8_t mwdma_active; /* multiword DMA active */ - u_int8_t apio_flag; /* advanced PIO supported */ - u_int8_t reserved6; - u_int16_t mwdma_min; /* min. M/W DMA time/word ns */ - u_int16_t mwdma_dflt; /* rec. M/W DMA time ns */ - u_int16_t pio_nfctl_min; /* min. PIO cycle w/o flow */ - u_int16_t pio_iordy_min; /* min. PIO cycle IORDY flow */ - int16_t reserved7[2]; - u_int16_t rls_ovlap; /* rel time (us) for overlap */ - u_int16_t rls_service; /* rel time (us) for service */ + int16_t reserved54[8]; + + int16_t sdmamodes; /* singleword DMA modes */ + int16_t wdmamodes; /* multiword DMA modes */ + int16_t apiomodes; /* advanced PIO modes */ + + u_int16_t mwdmamin; /* min. M/W DMA time/word ns */ + u_int16_t mwdmarec; /* rec. M/W DMA time ns */ + u_int16_t pioblind; /* min. PIO cycle w/o flow */ + u_int16_t pioiordy; /* min. PIO cycle IORDY flow */ + + int16_t reserved69; + int16_t reserved70; + u_int16_t rlsovlap; /* rel time (us) for overlap */ + u_int16_t rlsservice; /* rel time (us) for service */ + int16_t reserved73; + int16_t reserved74; + int16_t queuelen; + int16_t reserved76; + int16_t reserved77; + int16_t reserved78; + int16_t reserved79; + int16_t versmajor; + int16_t versminor; + int16_t featsupp1; + int16_t featsupp2; + int16_t featsupp3; + int16_t featenab1; + int16_t featenab2; + int16_t featenab3; + int16_t udmamodes; /* UltraDMA modes */ + int16_t erasetime; + int16_t enherasetime; + int16_t apmlevel; + int16_t reserved92[34]; + int16_t rmvcap; + int16_t securelevel; }; /* ATAPI REQUEST SENSE structure */ @@ -186,6 +223,8 @@ struct atapi_request { int32_t ccbsize; /* size of ccb (12 | 16) */ int32_t flags; #define A_READ 0x0001 +#define ATAPI_F_DMA_ENABLED 0x0002 +#define ATAPI_F_DMA_USED 0x0004 u_int32_t bytecount; /* bytes to transfer */ u_int32_t result; /* result code */ diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index b01e38724ea8..11c9c368f5a8 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-cd.c,v 1.2 1999/03/03 21:10:29 sos Exp $ + * $Id: atapi-cd.c,v 1.3 1999/03/05 09:43:30 sos Exp $ */ #include "ata.h" @@ -50,6 +50,7 @@ #ifdef DEVFS #include #endif +#include #include #include #include @@ -61,8 +62,8 @@ static d_write_t acdwrite; static d_ioctl_t acdioctl; static d_strategy_t acdstrategy; -#define CDEV_MAJOR 69 -#define BDEV_MAJOR 19 +#define BDEV_MAJOR 31 +#define CDEV_MAJOR 117 static struct cdevsw acd_cdevsw = { acdopen, acdclose, acdread, acdwrite, acdioctl, nostop, nullreset, nodevtotty, @@ -260,7 +261,7 @@ acd_describe(struct acd_softc *cdp) bpack(cdp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf)); printf("acd%d: <%s/%s> CDROM drive at ata%d as %s\n", cdp->lun, model_buf, revision_buf, - cdp->atp->controller->unit, + cdp->atp->controller->lun, (cdp->atp->unit == ATA_MASTER) ? "master" : "slave "); printf("acd%d: drive speed ", cdp->lun); @@ -268,7 +269,10 @@ acd_describe(struct acd_softc *cdp) printf("%d - ", cdp->cap.cur_speed * 1000 / 1024); printf("%dKB/sec", cdp->cap.max_speed * 1000 / 1024); if (cdp->cap.buf_size) - printf(", %dKB cache\n", cdp->cap.buf_size); + printf(", %dKB cache", cdp->cap.buf_size); + if (cdp->atp->flags & ATAPI_F_DMA_ENABLED) + printf(", DMA"); + printf("\n"); printf("acd%d: supported read types:", cdp->lun); comma = 0; @@ -775,7 +779,6 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) frames -= blocks; lba += blocks; } - free(buffer, M_TEMP); if (args->address_format == CD_LBA_FORMAT) args->address.lba = lba; diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index ad5e23fe8efe..1aa3f0fb3e40 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-fd.c,v 1.2 1999/03/05 09:43:30 sos Exp $ + * $Id: atapi-fd.c,v 1.3 1999/03/07 21:49:14 sos Exp $ */ #include "ata.h" @@ -51,6 +51,7 @@ #ifdef DEVFS #include #endif +#include #include #include #include @@ -62,8 +63,8 @@ static d_write_t afdwrite; static d_ioctl_t afdioctl; static d_strategy_t afdstrategy; -#define CDEV_MAJOR 87 -#define BDEV_MAJOR 1 +#define BDEV_MAJOR 32 +#define CDEV_MAJOR 118 static struct cdevsw afd_cdevsw = { afdopen, afdclose, afdread, afdwrite, @@ -176,7 +177,7 @@ afd_describe(struct afd_softc *fdp) bpack(fdp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf)); printf("afd%d: <%s/%s> rewriteable drive at ata%d as %s\n", fdp->lun, model_buf, revision_buf, - fdp->atp->controller->unit, + fdp->atp->controller->lun, (fdp->atp->unit == ATA_MASTER) ? "master" : "slave "); printf("afd%d: %luMB (%u sectors), %u cyls, %u heads, %u S/T, %u B/S\n", afdnlun, @@ -295,9 +296,7 @@ afdstrategy(struct buf *bp) return; } if (dscheck(bp, fdp->slices) <= 0) { - x = splbio(); biodone(bp); - splx(x); return; } x = splbio(); diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index ba963e8848c4..c4e6d1d91578 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-tape.c,v 1.3 1999/03/05 09:43:30 sos Exp $ + * $Id: atapi-tape.c,v 1.4 1999/03/07 21:49:14 sos Exp $ */ #include "ata.h" @@ -47,6 +47,7 @@ #include #endif #include +#include #include #include #include @@ -58,8 +59,8 @@ static d_write_t astwrite; static d_ioctl_t astioctl; static d_strategy_t aststrategy; -#define CDEV_MAJOR 90 -#define BDEV_MAJOR 24 +#define BDEV_MAJOR 33 +#define CDEV_MAJOR 119 static struct cdevsw ast_cdevsw = { astopen, astclose, astread, astwrite, @@ -181,7 +182,7 @@ ast_describe(struct ast_softc *stp) bpack(stp->atp->atapi_parm->revision, revision_buf, sizeof(revision_buf)); printf("ast%d: <%s/%s> tape drive at ata%d as %s\n", stp->lun, model_buf, revision_buf, - stp->atp->controller->unit, + stp->atp->controller->lun, (stp->atp->unit == ATA_MASTER) ? "master" : "slave "); printf("ast%d: ", stp->lun); switch (stp->header.medium_type) { diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 000b019fd84c..889fe9265898 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.228 1999/03/10 10:36:29 yokota Exp $ +# $Id: files.i386,v 1.229 1999/03/16 13:34:02 sos Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -35,6 +35,7 @@ ukbdmap.h optional ukbd_dflt_keymap \ clean "ukbdmap.h" # dev/ata/ata-all.c optional ata device-driver +dev/ata/ata-dma.c optional ata device-driver dev/ata/atapi-all.c optional ata device-driver dev/ata/ata-disk.c optional atadisk device-driver dev/ata/atapi-cd.c optional atapicd device-driver