Index: dev/disk/ata/ata-all.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/ata-all.c,v retrieving revision 1.7 diff -u -r1.7 ata-all.c --- dev/disk/ata/ata-all.c 7 Aug 2003 21:16:51 -0000 1.7 +++ dev/disk/ata/ata-all.c 27 Oct 2003 12:15:55 -0000 @@ -275,6 +275,7 @@ ch->device[MASTER].mode = ATA_PIO; ch->device[SLAVE].mode = ATA_PIO; ch->devices = 0; + ata_dmafreetags(ch); bus_teardown_intr(dev, ch->r_irq, ch->ih); bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); @@ -1354,7 +1355,7 @@ } ATA_SLEEPLOCK_CH(atadev->channel, ATA_ACTIVE); - ata_dmainit(atadev->channel, atadev->unit, pmode, wmode, umode); + ata_dmainit(atadev, pmode, wmode, umode); ATA_UNLOCK_CH(atadev->channel); ata_start(atadev->channel); /* XXX SOS */ } Index: dev/disk/ata/ata-all.h =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/ata-all.h,v retrieving revision 1.3 diff -u -r1.3 ata-all.h --- dev/disk/ata/ata-all.h 19 Jul 2003 21:14:18 -0000 1.3 +++ dev/disk/ata/ata-all.h 27 Oct 2003 12:15:55 -0000 @@ -159,6 +159,18 @@ u_int32_t count; }; +struct ata_dmastate { + bus_dma_tag_t ddmatag; /* data DMA tag */ + bus_dmamap_t ddmamap; /* data DMA map */ + bus_dma_tag_t cdmatag; /* control DMA tag */ + bus_dmamap_t cdmamap; /* control DMA map */ + 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 */ +}; + /* structure describing an ATA/ATAPI device */ struct ata_device { struct ata_channel *channel; @@ -178,6 +190,7 @@ int mode; /* transfermode */ int cmd; /* last cmd executed */ void *result; /* misc data */ + struct ata_dmastate dmastate; /* dma state */ }; /* structure describing an ATA channel */ @@ -187,6 +200,7 @@ struct resource *r_io; /* io addr resource handle */ struct resource *r_altio; /* altio addr resource handle */ struct resource *r_bmio; /* bmio addr resource handle */ + 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 */ @@ -263,12 +277,14 @@ int ata_umode(struct ata_params *); int ata_find_dev(device_t, u_int32_t, u_int32_t); -void *ata_dmaalloc(struct ata_channel *, int); -void ata_dmainit(struct ata_channel *, int, int, int, int); -int ata_dmasetup(struct ata_channel *, int, struct ata_dmaentry *, caddr_t, int); -void ata_dmastart(struct ata_channel *, int, struct ata_dmaentry *, int); +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_channel *); +int ata_dmadone(struct ata_device *); /* macros for locking a channel */ #define ATA_LOCK_CH(ch, value)\ Index: dev/disk/ata/ata-disk.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/ata-disk.c,v retrieving revision 1.7 diff -u -r1.7 ata-disk.c --- dev/disk/ata/ata-disk.c 7 Aug 2003 21:16:51 -0000 1.7 +++ dev/disk/ata/ata-disk.c 27 Oct 2003 12:15:55 -0000 @@ -176,11 +176,10 @@ /* use DMA if allowed and if drive/controller supports it */ if (ata_dma) - ata_dmainit(atadev->channel, atadev->unit, ata_pmode(atadev->param), + ata_dmainit(atadev, ata_pmode(atadev->param), ata_wmode(atadev->param), ata_umode(atadev->param)); else - ata_dmainit(atadev->channel, atadev->unit, - ata_pmode(atadev->param), -1, -1); + ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1); /* use tagged queueing if allowed and supported */ if (ata_tags && ad_tagsupported(adp)) { @@ -249,6 +248,7 @@ biodone(request->bp); ad_free(request); } + ata_dmafree(atadev); while ((bp = bufq_first(&adp->queue))) { bufq_remove(&adp->queue, bp); bp->b_error = ENXIO; @@ -412,7 +412,7 @@ if (bp->b_flags & B_READ) request->flags |= ADR_F_READ; if (adp->device->mode >= ATA_DMA) { - if (!(request->dmatab = ata_dmaalloc(atadev->channel, atadev->unit))) + if (ata_dmaalloc(atadev)) adp->device->mode = ATA_PIO; } @@ -476,8 +476,7 @@ /* does this drive & transfer work with DMA ? */ request->flags &= ~ADR_F_DMA_USED; if (adp->device->mode >= ATA_DMA && - !ata_dmasetup(adp->device->channel, adp->device->unit, - request->dmatab, request->data, request->bytecount)) { + !ata_dmasetup(adp->device, request->data, request->bytecount)) { request->flags |= ADR_F_DMA_USED; request->currentsize = request->bytecount; @@ -526,8 +525,8 @@ } /* start transfer, return and wait for interrupt */ - ata_dmastart(adp->device->channel, adp->device->unit, - request->dmatab, request->flags & ADR_F_READ); + ata_dmastart(adp->device, request->data, request->bytecount, + request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -598,7 +597,7 @@ /* finish DMA transfer */ if (request->flags & ADR_F_DMA_USED) - dma_stat = ata_dmadone(adp->device->channel); + dma_stat = ata_dmadone(adp->device); /* do we have a corrected soft error ? */ if (adp->device->channel->status & ATA_S_CORR) @@ -625,8 +624,7 @@ if (request->retries++ < AD_MAX_RETRIES) printf(" retrying\n"); else { - ata_dmainit(adp->device->channel, adp->device->unit, - ata_pmode(adp->device->param), -1, -1); + ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); printf(" falling back to PIO mode\n"); } TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain); @@ -637,8 +635,7 @@ if (request->flags & ADR_F_DMA_USED) { untimeout((timeout_t *)ad_timeout, request,request->timeout_handle); ad_invalidatequeue(adp, request); - ata_dmainit(adp->device->channel, adp->device->unit, - ata_pmode(adp->device->param), -1, -1); + ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); request->flags |= ADR_F_FORCE_PIO; printf(" trying PIO mode\n"); TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain); @@ -791,8 +788,8 @@ ad_invalidatequeue(adp, NULL); return ATA_OP_FINISHED; } - ata_dmastart(adp->device->channel, adp->device->unit, - request->dmatab, request->flags & ADR_F_READ); + ata_dmastart(adp->device, request->data, request->bytecount, + request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } return ATA_OP_FINISHED; @@ -801,13 +798,8 @@ static void ad_free(struct ad_request *request) { - int s = splbio(); - - if (request->dmatab) - free(request->dmatab, M_DEVBUF); request->softc->tags[request->tag] = NULL; free(request, M_AD); - splx(s); } static void @@ -880,11 +872,10 @@ request->tag, request->serv); if (request->flags & ADR_F_DMA_USED) { - ata_dmadone(adp->device->channel); + ata_dmadone(adp->device); ad_invalidatequeue(adp, request); if (request->retries == AD_MAX_RETRIES) { - ata_dmainit(adp->device->channel, adp->device->unit, - ata_pmode(adp->device->param), -1, -1); + ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); ata_prtdev(adp->device, "trying fallback to PIO mode\n"); request->retries = 0; } @@ -915,13 +906,11 @@ 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->channel, atadev->unit, - ata_pmode(adp->device->param), + ata_dmainit(atadev, ata_pmode(adp->device->param), ata_wmode(adp->device->param), ata_umode(adp->device->param)); else - ata_dmainit(atadev->channel, atadev->unit, - ata_pmode(adp->device->param), -1, -1); + ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1); } void Index: dev/disk/ata/ata-disk.h =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/ata-disk.h,v retrieving revision 1.2 diff -u -r1.2 ata-disk.h --- dev/disk/ata/ata-disk.h 17 Jun 2003 04:28:22 -0000 1.2 +++ dev/disk/ata/ata-disk.h 27 Oct 2003 12:15:55 -0000 @@ -49,7 +49,6 @@ struct buf *bp; /* associated bio ptr */ u_int8_t tag; /* tag ID of this request */ int serv; /* request had service */ - struct ata_dmaentry *dmatab; /* DMA transfer table */ TAILQ_ENTRY(ad_request) chain; /* list management */ }; Index: dev/disk/ata/ata-dma.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/ata-dma.c,v retrieving revision 1.3 diff -u -r1.3 ata-dma.c --- dev/disk/ata/ata-dma.c 7 Aug 2003 21:16:51 -0000 1.3 +++ dev/disk/ata/ata-dma.c 27 Oct 2003 12:15:55 -0000 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -45,72 +46,178 @@ #include "ata-all.h" /* prototypes */ -static void cyrix_timing(struct ata_channel *, int, int); -static void promise_timing(struct ata_channel *, int, int); -static void hpt_timing(struct ata_channel *, int, int); -static int hpt_cable80(struct ata_channel *); +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 *); /* misc defines */ -#ifdef __alpha__ -#undef vtophys -#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) -#endif -#define ATAPI_DEVICE(ch, device) \ - ((device == ATA_MASTER && ch->devices & ATA_ATAPI_MASTER) || \ - (device == ATA_SLAVE && ch->devices & ATA_ATAPI_SLAVE)) +#define ATAPI_DEVICE(atadev) \ + ((atadev->unit == ATA_MASTER && \ + atadev->channel->devices & ATA_ATAPI_MASTER) || \ + (atadev->unit == ATA_SLAVE && \ + atadev->channel->devices & ATA_ATAPI_SLAVE)) + +#define MAXSEGSZ PAGE_SIZE +#define MAXTABSZ PAGE_SIZE +#define MAXCTLDMASZ (2 * (MAXTABSZ + MAXPHYS)) + +struct ata_dc_cb_args { + bus_addr_t maddr; + int error; +}; + +static void +ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct ata_dc_cb_args *cba = (struct ata_dc_cb_args *)xsc; + + if (!(cba->error = error)) + cba->maddr = segs[0].ds_addr; +} -void * -ata_dmaalloc(struct ata_channel *ch, int device) +int +ata_dmaalloc(struct ata_device *atadev) { - void *dmatab; + struct ata_channel *ch; + struct ata_dc_cb_args ccba; + struct ata_dmastate *ds; + int error; - if ((dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) { - if (((uintptr_t)dmatab >> PAGE_SHIFT) ^ - (((uintptr_t)dmatab + PAGE_SIZE - 1) >> PAGE_SHIFT)) { - ata_printf(ch, device, "dmatab crosses page boundary, no DMA\n"); - free(dmatab, M_DEVBUF); - dmatab = NULL; + ch = atadev->channel; + ds = &atadev->dmastate; + if (!ds->cdmatag) { + if ((error = bus_dma_tag_create(ch->dmatag, 1, PAGE_SIZE, + BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, + MAXTABSZ, 1, MAXTABSZ, + BUS_DMA_ALLOCNOW, &ds->cdmatag))) + return error; + } + if (!ds->ddmatag) { + if ((error = bus_dma_tag_create(ch->dmatag, ch->alignment + 1, 0, + BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, + MAXPHYS, ATA_DMA_ENTRIES, MAXSEGSZ, + BUS_DMA_ALLOCNOW, &ds->ddmatag))) + return error; + } + if (!ds->mdmatab) { + if ((error = bus_dmamem_alloc(ds->cdmatag, (void **)&ds->dmatab, 0, + &ds->cdmamap))) + return error; + + if ((error = bus_dmamap_load(ds->cdmatag, ds->cdmamap, ds->dmatab, + MAXTABSZ, ata_dmasetupc_cb, &ccba, + 0)) != 0 || ccba.error != 0) { + bus_dmamem_free(ds->cdmatag, ds->dmatab, ds->cdmamap); + return error; } + ds->mdmatab = ccba.maddr; + } + if (!ds->ddmamap) { + if ((error = bus_dmamap_create(ds->ddmatag, 0, &ds->ddmamap)) != 0) + return error; + } + return 0; +} + +void +ata_dmafree(struct ata_device *atadev) +{ + struct ata_dmastate *ds; + + ds = &atadev->dmastate; + if (ds->mdmatab) { + bus_dmamap_unload(ds->cdmatag, ds->cdmamap); + bus_dmamem_free(ds->cdmatag, ds->dmatab, ds->cdmamap); + ds->mdmatab = 0; + ds->cdmamap = NULL; + ds->dmatab = NULL; + } + if (ds->ddmamap) { + bus_dmamap_destroy(ds->ddmatag, ds->ddmamap); + ds->ddmamap = NULL; + } + if (ds->cdmatag) { + bus_dma_tag_destroy(ds->cdmatag); + ds->cdmatag = NULL; + } + if (ds->ddmatag) { + bus_dma_tag_destroy(ds->ddmatag); + ds->ddmatag = NULL; } - return dmatab; } void -ata_dmainit(struct ata_channel *ch, int device, - int apiomode, int wdmamode, int udmamode) +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) { - struct ata_device *atadev = &ch->device[ATA_DEV(device)]; - device_t parent = device_get_parent(ch->dev); - int devno = (ch->unit << 1) + ATA_DEV(device); + atadev->mode = mode; + if (!atadev->channel->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); + } + } +} + +void +ata_dmainit(struct ata_device *atadev, + int apiomode, int wdmamode, int udmamode) +{ + 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 (!ch->r_bmio) + if (!atadev->channel->r_bmio) return; /* if simplex controller, only allow DMA on primary channel */ - if (ch->unit == 1) { - ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, - ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & + 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(ch->r_bmio, ATA_BMSTAT_PORT) & ATA_BMSTAT_DMA_SIMPLEX) { + 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) */ - ch->alignment = 0x1; + atadev->channel->alignment = 0x1; #if 1 - if (udmamode > 2 && !ch->device[ATA_DEV(device)].param->hwres_cblid) { + if (udmamode > 2 && !atadev->param->hwres_cblid) { ata_prtdev(atadev,"DMA limited to UDMA33, non-ATA66 cable or device\n"); udmamode = 2; } #endif - switch (ch->chiptype) { + switch (chiptype) { case 0x24db8086: /* Intel ICH5 */ case 0x24cb8086: /* Intel ICH4 */ @@ -136,7 +243,7 @@ (pci_read_config(parent, 0x48, 4) & ~mask48) | new48, 4); pci_write_config(parent, 0x54, word54 | (0x1000<mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -166,7 +273,7 @@ (pci_read_config(parent, 0x48, 4) & ~mask48) | new48, 4); pci_write_config(parent, 0x54, word54 | (1 << devno), 2); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -194,7 +301,7 @@ pci_write_config(parent, 0x48, (pci_read_config(parent, 0x48, 4) & ~mask48) | new48, 4); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -208,7 +315,7 @@ int32_t mask40, new40, mask44, new44; /* if SITRE not set doit for both channels */ - if (!((pci_read_config(parent,0x40,4)>>(ch->unit<<8))&0x4000)) { + 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)) { @@ -241,7 +348,7 @@ mask44 = 0x0000000f; new44 = 0x0000000b; } - if (ch->unit) { + if (channel) { mask40 <<= 16; new40 <<= 16; mask44 <<= 4; @@ -253,7 +360,7 @@ pci_write_config(parent, 0x44, (pci_read_config(parent, 0x44, 4) & ~mask44)| new44, 4); - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -265,11 +372,11 @@ int32_t word40; word40 = pci_read_config(parent, 0x40, 4); - word40 >>= ch->unit * 16; + word40 >>= channel * 16; /* Check for timing config usable for DMA on controller */ if (!((word40 & 0x3300) == 0x2300 && - ((word40 >> (device == ATA_MASTER ? 0 : 4)) & 1) == 1)) + ((word40 >> (device ? 4 : 0)) & 1) == 1)) break; error = ata_command(atadev, ATA_C_SETFEATURES, 0, @@ -278,7 +385,7 @@ ata_prtdev(atadev, "%s setting WDMA2 on Intel chip\n", (error) ? "failed" : "success"); if (!error) { - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -286,12 +393,14 @@ case 0x522910b9: /* AcerLabs Aladdin IV/V */ /* the older Aladdin doesn't support ATAPI DMA on both master & slave */ - if (pci_get_revid(parent) < 0xc2 && - ch->devices & ATA_ATAPI_MASTER && ch->devices & ATA_ATAPI_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; } - if (udmamode >= 5 && pci_get_revid(parent) >= 0xc4) { + 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) @@ -307,11 +416,11 @@ pci_write_config(parent, 0x54, word54, 4); pci_write_config(parent, 0x53, pci_read_config(parent, 0x53, 1) | 0x03, 1); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } - if (udmamode >= 4 && pci_get_revid(parent) >= 0xc2) { + if (udmamode >= 4 && chiprev >= 0xc2) { error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_UDMA4, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) @@ -327,11 +436,11 @@ pci_write_config(parent, 0x54, word54, 4); pci_write_config(parent, 0x53, pci_read_config(parent, 0x53, 1) | 0x03, 1); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } - if (udmamode >= 2 && pci_get_revid(parent) >= 0x20) { + if (udmamode >= 2 && chiprev >= 0x20) { error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) @@ -345,8 +454,8 @@ pci_write_config(parent, 0x54, word54, 4); pci_write_config(parent, 0x53, pci_read_config(parent, 0x53, 1) | 0x03, 1); - ch->flags |= ATA_ATAPI_DMA_RO; - atadev->mode = ATA_UDMA2; + atadev->channel->flags |= ATA_ATAPI_DMA_RO; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -364,14 +473,39 @@ if (!error) { pci_write_config(parent, 0x53, pci_read_config(parent, 0x53, 1) | 0x03, 1); - ch->flags |= ATA_ATAPI_DMA_RO; - atadev->mode = ATA_WDMA2; + 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); - /* we could set PIO mode timings, but we assume the BIOS did that */ + 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 */ @@ -381,11 +515,11 @@ case 0x05711106: /* VIA 82C571, 82C586, 82C596, 82C686, 8231,8233,8235 */ { int via_modes[5][7] = { - { 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00 }, /* ATA33 */ - { 0x00, 0x00, 0xea, 0x00, 0xe8, 0x00, 0x00 }, /* ATA66 */ - { 0x00, 0x00, 0xf4, 0x00, 0xf1, 0xf0, 0x00 }, /* ATA100 */ - { 0x00, 0x00, 0xf6, 0x00, 0xf2, 0xf1, 0xf0 }, /* VIA ATA133 */ - { 0x00, 0x00, 0xc0, 0x00, 0xc5, 0xc6, 0x00 }}; /* AMD/nVIDIA */ + { 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, 0x00 }}; /* AMD/nVIDIA */ int *reg_val = NULL; char *chip = "VIA"; @@ -415,18 +549,18 @@ udmamode = imin(udmamode, 2); reg_val = via_modes[0]; } - else if (ch->chiptype == 0x74411022 || /* AMD 768 */ - ch->chiptype == 0x74111022) { /* AMD 766 */ + else if (chiptype == 0x74411022 || /* AMD 768 */ + chiptype == 0x74111022) { /* AMD 766 */ udmamode = imin(udmamode, 5); reg_val = via_modes[4]; chip = "AMD"; } - else if (ch->chiptype == 0x74091022) { /* AMD 756 */ + else if (chiptype == 0x74091022) { /* AMD 756 */ udmamode = imin(udmamode, 4); reg_val = via_modes[4]; chip = "AMD"; } - else if (ch->chiptype == 0x01bc10de) { /* nVIDIA */ + else if (chiptype == 0x01bc10de) { /* nVIDIA */ udmamode = imin(udmamode, 5); reg_val = via_modes[4]; chip = "nVIDIA"; @@ -442,7 +576,7 @@ (error) ? "failed" : "success", chip); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[6], 1); - atadev->mode = ATA_UDMA6; + ata_dmacreate(atadev, apiomode, ATA_UDMA6); return; } } @@ -454,7 +588,7 @@ (error) ? "failed" : "success", chip); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[5], 1); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -466,7 +600,7 @@ (error) ? "failed" : "success", chip); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[4], 1); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -478,7 +612,7 @@ (error) ? "failed" : "success", chip); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[2], 1); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -491,7 +625,7 @@ if (!error) { pci_write_config(parent, 0x53 - devno, 0x0b, 1); pci_write_config(parent, 0x4b - devno, 0x31, 1); - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -523,7 +657,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0x8000, 2); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -535,7 +669,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0x9000, 2); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -547,7 +681,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0xb000, 2); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -566,7 +700,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0x9000, 2); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -578,11 +712,11 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0xa000, 2); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } - } else if (udmamode >= 2 && pci_get_revid(parent) > 0xc1) { + } 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) @@ -590,7 +724,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x40 + (devno << 1), 0xa301, 2); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -602,7 +736,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x40 + (devno << 1), 0x0301, 2); - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -611,10 +745,10 @@ case 0x06801095: /* SiI 0680 ATA133 controller */ { - u_int8_t ureg = 0xac + (ATA_DEV(device) * 0x02) + (ch->unit * 0x10); + u_int8_t ureg = 0xac + (device * 0x02) + (channel * 0x10); u_int8_t uval = pci_read_config(parent, ureg, 1); - u_int8_t mreg = ch->unit ? 0x84 : 0x80; - u_int8_t mask = ATA_DEV(device) ? 0x30 : 0x03; + 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 */ @@ -628,7 +762,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, ureg, (uval & 0x3f) | 0x01, 1); - atadev->mode = ATA_UDMA6; + ata_dmacreate(atadev, apiomode, ATA_UDMA6); return; } } @@ -640,7 +774,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, ureg, (uval & 0x3f) | 0x02, 1); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -652,7 +786,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, ureg, (uval & 0x3f) | 0x03, 1); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -664,7 +798,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, ureg, (uval & 0x3f) | 0x07, 1); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -680,7 +814,7 @@ (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, ureg - 0x4, 0x10c1, 2); - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -702,11 +836,11 @@ ata_prtdev(atadev, "%s setting UDMA5 on CMD chip\n", (error) ? "failed" : "success"); if (!error) { - umode = pci_read_config(parent, ch->unit ? 0x7b : 0x73, 1); - umode &= ~(device == ATA_MASTER ? 0x35 : 0xca); - umode |= (device == ATA_MASTER ? 0x05 : 0x0a); - pci_write_config(parent, ch->unit ? 0x7b : 0x73, umode, 1); - atadev->mode = ATA_UDMA5; + 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; } } @@ -722,11 +856,11 @@ ata_prtdev(atadev, "%s setting UDMA4 on CMD chip\n", (error) ? "failed" : "success"); if (!error) { - umode = pci_read_config(parent, ch->unit ? 0x7b : 0x73, 1); - umode &= ~(device == ATA_MASTER ? 0x35 : 0xca); - umode |= (device == ATA_MASTER ? 0x15 : 0x4a); - pci_write_config(parent, ch->unit ? 0x7b : 0x73, umode, 1); - atadev->mode = ATA_UDMA4; + 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; } } @@ -739,18 +873,18 @@ ata_prtdev(atadev, "%s setting UDMA2 on CMD chip\n", (error) ? "failed" : "success"); if (!error) { - umode = pci_read_config(parent, ch->unit ? 0x7b : 0x73, 1); - umode &= ~(device == ATA_MASTER ? 0x35 : 0xca); - umode |= (device == ATA_MASTER ? 0x11 : 0x42); - pci_write_config(parent, ch->unit ? 0x7b : 0x73, umode, 1); - atadev->mode = ATA_UDMA2; + 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, ch->unit ? 0x7b : 0x73, - pci_read_config(parent, ch->unit ? 0x7b : 0x73, 1)& - ~(device == ATA_MASTER ? 0x35 : 0xca), 1); + 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 */ @@ -764,7 +898,7 @@ int32_t offset = (devno < 3) ? (devno << 1) : 7; pci_write_config(parent, 0x54 + offset, 0x3f, 1); - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -779,8 +913,9 @@ ata_prtdev(atadev, "%s setting WDMA2 on Cypress chip\n", error ? "failed" : "success"); if (!error) { - pci_write_config(ch->dev, ch->unit ? 0x4e:0x4c, 0x2020, 2); - atadev->mode = ATA_WDMA2; + pci_write_config(atadev->channel->dev, + channel ? 0x4e:0x4c, 0x2020, 2); + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -788,7 +923,7 @@ break; case 0x01021078: /* Cyrix 5530 ATA33 controller */ - ch->alignment = 0xf; /* DMA engine requires 16 byte alignment */ + atadev->channel->alignment = 0xf; if (udmamode >= 2) { error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_UDMA2, ATA_C_F_SETXFER, ATA_WAIT_READY); @@ -796,8 +931,8 @@ ata_prtdev(atadev, "%s setting UDMA2 on Cyrix chip\n", (error) ? "failed" : "success"); if (!error) { - cyrix_timing(ch, devno, ATA_UDMA2); - atadev->mode = ATA_UDMA2; + cyrix_timing(atadev, devno, ATA_UDMA2); + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -808,8 +943,8 @@ ata_prtdev(atadev, "%s setting WDMA2 on Cyrix chip\n", (error) ? "failed" : "success"); if (!error) { - cyrix_timing(ch, devno, ATA_WDMA2); - atadev->mode = ATA_WDMA2; + cyrix_timing(atadev, devno, ATA_WDMA2); + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -820,12 +955,12 @@ ata_prtdev(atadev, "%s setting %s on Cyrix chip\n", (error) ? "failed" : "success", ata_mode2str(ATA_PIO0 + apiomode)); - cyrix_timing(ch, devno, ATA_PIO0 + apiomode); + cyrix_timing(atadev, devno, ATA_PIO0 + apiomode); atadev->mode = ATA_PIO0 + apiomode; return; case 0x02121166: /* ServerWorks CSB5 ATA66/100 controller */ - if (udmamode >= 5 && pci_get_revid(parent) >= 0x92) { + if (udmamode >= 5 && chiprev >= 0x92) { error = ata_command(atadev, ATA_C_SETFEATURES, 0, ATA_UDMA5, ATA_C_F_SETXFER, ATA_WAIT_READY); if (bootverbose) @@ -841,7 +976,7 @@ reg56 &= ~(0xf << (devno * 4)); reg56 |= (0x5 << (devno * 4)); pci_write_config(parent, 0x56, reg56, 2); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -861,7 +996,7 @@ reg56 &= ~(0xf << (devno * 4)); reg56 |= (0x4 << (devno * 4)); pci_write_config(parent, 0x56, reg56, 2); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -884,7 +1019,7 @@ reg56 &= ~(0xf << (devno * 4)); reg56 |= (0x2 << (devno * 4)); pci_write_config(parent, 0x56, reg56, 2); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -895,7 +1030,7 @@ ata_prtdev(atadev, "%s setting WDMA2 on ServerWorks chip\n", (error) ? "failed" : "success"); if (!error) { - int offset = (ch->unit * 2) + (device == ATA_MASTER); + int offset = devno ^ 0x01; int word44 = pci_read_config(parent, 0x44, 4); pci_write_config(parent, 0x54, @@ -904,7 +1039,7 @@ word44 &= ~(0xff << (offset << 8)); word44 |= (0x20 << (offset << 8)); pci_write_config(parent, 0x44, 0x20, 4); - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -915,15 +1050,16 @@ case 0x5275105a: /* Promise TX2 ATA133 controllers */ case 0x6269105a: /* Promise TX2 ATA133 controllers */ case 0x7275105a: /* Promise TX2 ATA133 controllers */ - ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 6 && !(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { + 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) { - atadev->mode = ATA_UDMA6; + ata_dmacreate(atadev, apiomode, ATA_UDMA6); return; } } @@ -931,27 +1067,29 @@ case 0x4d68105a: /* Promise TX2 ATA100 controllers */ case 0x6268105a: /* Promise TX2 ATA100 controllers */ - ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 5 && !(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { + 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) { - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } - ATA_OUTB(ch->r_bmio, ATA_BMDEVSPEC_0, 0x0b); - if (udmamode >= 4 && !(ATA_INB(ch->r_bmio, ATA_BMDEVSPEC_1) & 0x04)) { + 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) { - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -962,7 +1100,7 @@ ata_prtdev(atadev, "%s setting UDMA on Promise chip\n", (error) ? "failed" : "success"); if (!error) { - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -973,7 +1111,7 @@ ata_prtdev(atadev, "%s setting WDMA2 on Promise chip\n", (error) ? "failed" : "success"); if (!error) { - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -981,16 +1119,16 @@ case 0x0d30105a: /* Promise OEM ATA100 controllers */ case 0x4d30105a: /* Promise Ultra/FastTrak 100 controllers */ - if (!ATAPI_DEVICE(ch, device) && udmamode >= 5 && - !(pci_read_config(parent, 0x50, 2)&(ch->unit ? 1<<11 : 1<<10))){ + 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(ch, devno, ATA_UDMA5); - atadev->mode = ATA_UDMA5; + promise_timing(atadev, devno, ATA_UDMA5); + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -998,43 +1136,43 @@ case 0x0d38105a: /* Promise FastTrak 66 controllers */ case 0x4d38105a: /* Promise Ultra/FastTrak 66 controllers */ - if (!ATAPI_DEVICE(ch, device) && udmamode >= 4 && - !(pci_read_config(parent, 0x50, 2)&(ch->unit ? 1<<11 : 1<<10))){ + 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(ch, devno, ATA_UDMA4); - atadev->mode = ATA_UDMA4; + promise_timing(atadev, devno, ATA_UDMA4); + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } /* FALLTHROUGH */ case 0x4d33105a: /* Promise Ultra/FastTrak 33 controllers */ - if (!ATAPI_DEVICE(ch, device) && udmamode >= 2) { + 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(ch, devno, ATA_UDMA2); - atadev->mode = ATA_UDMA2; + promise_timing(atadev, devno, ATA_UDMA2); + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } - if (!ATAPI_DEVICE(ch, device) && wdmamode >= 2 && apiomode >= 4) { + 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(ch, devno, ATA_WDMA2); - atadev->mode = ATA_WDMA2; + promise_timing(atadev, devno, ATA_WDMA2); + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -1045,76 +1183,76 @@ ata_prtdev(atadev, "%s setting PIO%d on Promise chip\n", (error) ? "failed" : "success", (apiomode >= 0) ? apiomode : 0); - promise_timing(ch, devno, ATA_PIO0 + apiomode); + 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(ch, device) && udmamode >= 6 && hpt_cable80(ch) && - ((ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x05) || - (ch->chiptype == 0x00051103 && pci_get_revid(parent) >= 0x01) || - (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07))) { + 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(ch, devno, ATA_UDMA6); - atadev->mode = ATA_UDMA6; + hpt_timing(atadev, devno, ATA_UDMA6); + ata_dmacreate(atadev, apiomode, ATA_UDMA6); return; } } - if (!ATAPI_DEVICE(ch, device) && udmamode >= 5 && hpt_cable80(ch) && - ((ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x03) || - (ch->chiptype == 0x00051103 && pci_get_revid(parent) >= 0x01) || - (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07))) { + 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(ch, devno, ATA_UDMA5); - atadev->mode = ATA_UDMA5; + hpt_timing(atadev, devno, ATA_UDMA5); + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } - if (!ATAPI_DEVICE(ch, device) && udmamode >= 4 && hpt_cable80(ch)) { + 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(ch, devno, ATA_UDMA4); - atadev->mode = ATA_UDMA4; + hpt_timing(atadev, devno, ATA_UDMA4); + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } - if (!ATAPI_DEVICE(ch, device) && udmamode >= 2) { + 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(ch, devno, ATA_UDMA2); - atadev->mode = ATA_UDMA2; + hpt_timing(atadev, devno, ATA_UDMA2); + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } - if (!ATAPI_DEVICE(ch, device) && wdmamode >= 2 && apiomode >= 4) { + 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(ch, devno, ATA_WDMA2); - atadev->mode = ATA_WDMA2; + hpt_timing(atadev, devno, ATA_WDMA2); + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -1125,44 +1263,42 @@ ata_prtdev(atadev, "%s setting PIO%d on HighPoint chip\n", (error) ? "failed" : "success", (apiomode >= 0) ? apiomode : 0); - hpt_timing(ch, devno, ATA_PIO0 + apiomode); + hpt_timing(atadev, devno, ATA_PIO0 + apiomode); atadev->mode = ATA_PIO0 + apiomode; return; case 0x000116ca: /* Cenatek Rocket Drive controller */ if (wdmamode >= 0 && - (ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) & - ((device==ATA_MASTER)?ATA_BMSTAT_DMA_MASTER:ATA_BMSTAT_DMA_SLAVE))) - atadev->mode = ATA_DMA; + (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 ((device == ATA_MASTER && ch->devices & ATA_ATAPI_MASTER) || - (device == ATA_SLAVE && ch->devices & ATA_ATAPI_SLAVE)) + 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(ch->r_bmio, ATA_BMSTAT_PORT) & - ((device==ATA_MASTER) ? - ATA_BMSTAT_DMA_MASTER : ATA_BMSTAT_DMA_SLAVE))) { - atadev->mode = ATA_DMA; + (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) && ch->r_bmio) { + 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) { - atadev->mode = ATA_WDMA2; + ata_dmacreate(atadev, apiomode, ATA_WDMA2); return; } } @@ -1181,72 +1317,111 @@ } } +struct ata_dmasetup_data_cb_args { + struct ata_dmaentry *dmatab; + int error; +}; + +static void +ata_dmasetupd_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct ata_dmasetup_data_cb_args *cba = + (struct ata_dmasetup_data_cb_args *)xsc; + bus_size_t cnt; + u_int32_t lastcount; + int i, j; + + cba->error = error; + if (error != 0) + return; + lastcount = j = 0; + for (i = 0; i < nsegs; i++) { + /* + * A maximum segment size was specified for bus_dma_tag_create, but + * some busdma code does not seem to honor this, so fix up if needed. + */ + for (cnt = 0; cnt < segs[i].ds_len; cnt += MAXSEGSZ, j++) { + cba->dmatab[j].base = htole32(segs[i].ds_addr + cnt); + lastcount = ulmin(segs[i].ds_len - cnt, MAXSEGSZ) & 0xffff; + cba->dmatab[j].count = htole32(lastcount); + } + } + cba->dmatab[j - 1].count = htole32(lastcount | ATA_DMA_EOT); +} + int -ata_dmasetup(struct ata_channel *ch, int device, struct ata_dmaentry *dmatab, - caddr_t data, int32_t count) +ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) { - u_int32_t dma_count, dma_base; - int i = 0; + struct ata_channel *ch = atadev->channel; if (((uintptr_t)data & ch->alignment) || (count & ch->alignment)) { - ata_printf(ch, device, "non aligned DMA transfer attempted\n"); + ata_prtdev(atadev, "non aligned DMA transfer attempted\n"); return -1; } if (!count) { - ata_printf(ch, device, "zero length DMA transfer attempted\n"); + ata_prtdev(atadev, "zero length DMA transfer attempted\n"); return -1; } - - dma_base = vtophys(data); - dma_count = imin(count, (PAGE_SIZE - ((uintptr_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) { - ata_printf(ch, device, "too many segments in DMA table\n"); - return -1; - } - dma_base = vtophys(data); - dma_count = imin(count, PAGE_SIZE); - data += imin(count, PAGE_SIZE); - count -= imin(count, PAGE_SIZE); - } - dmatab[i].base = dma_base; - dmatab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT; return 0; } -void -ata_dmastart(struct ata_channel *ch, int device, - struct ata_dmaentry *dmatab, int dir) +int +ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) { + struct ata_channel *ch = atadev->channel; + struct ata_dmastate *ds = &atadev->dmastate; + struct ata_dmasetup_data_cb_args cba; + + if (ds->flags & ATA_DS_ACTIVE) + panic("ata_dmasetup: transfer active on this device!"); + + cba.dmatab = ds->dmatab; + bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_PREWRITE); + if (bus_dmamap_load(ds->ddmatag, ds->ddmamap, data, count, + ata_dmasetupd_cb, &cba, 0) || cba.error) + return -1; + + bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(ds->ddmatag, ds->ddmamap, dir ? BUS_DMASYNC_PREREAD : + BUS_DMASYNC_PREWRITE); + ch->flags |= ATA_DMA_ACTIVE; - ATA_OUTL(ch->r_bmio, ATA_BMDTP_PORT, vtophys(dmatab)); + ds->flags = ATA_DS_ACTIVE; + if (dir) + ds->flags |= ATA_DS_READ; + + ATA_OUTL(ch->r_bmio, ATA_BMDTP_PORT, ds->mdmatab); ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, dir ? ATA_BMCMD_WRITE_READ : 0); ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, (ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT) | (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) | ATA_BMCMD_START_STOP); + return 0; } int -ata_dmadone(struct ata_channel *ch) +ata_dmadone(struct ata_device *atadev) { + struct ata_channel *ch; + struct ata_dmastate *ds; int error; + ch = atadev->channel; + ds = &atadev->dmastate; + bus_dmamap_sync(ds->ddmatag, ds->ddmamap, (ds->flags & ATA_DS_READ) != 0 ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ds->ddmatag, ds->ddmamap); + ATA_OUTB(ch->r_bmio, ATA_BMCMD_PORT, ATA_INB(ch->r_bmio, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); - ch->flags &= ~ATA_DMA_ACTIVE; error = ATA_INB(ch->r_bmio, ATA_BMSTAT_PORT); ATA_OUTB(ch->r_bmio, ATA_BMSTAT_PORT, error | ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); - return error & ATA_BMSTAT_MASK; + ch->flags &= ~ATA_DMA_ACTIVE; + ds->flags = 0; + return (error & ATA_BMSTAT_MASK); } int @@ -1256,7 +1431,7 @@ } static void -cyrix_timing(struct ata_channel *ch, int devno, int mode) +cyrix_timing(struct ata_device *atadev, int devno, int mode) { u_int32_t reg20 = 0x0000e132; u_int32_t reg24 = 0x00017771; @@ -1270,14 +1445,15 @@ case ATA_WDMA2: reg24 = 0x00002020; break; case ATA_UDMA2: reg24 = 0x00911030; break; } - ATA_OUTL(ch->r_bmio, (devno << 3) + 0x20, reg20); - ATA_OUTL(ch->r_bmio, (devno << 3) + 0x24, reg24); + 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_channel *ch, int devno, int mode) +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; @@ -1299,7 +1475,7 @@ t->prefetch = 1; t->errdy = 1; t->syncin = 1; } - switch (ch->chiptype) { + switch (atadev->channel->chiptype) { case 0x4d33105a: /* Promise Ultra/Fasttrak 33 */ switch (mode) { default: @@ -1330,16 +1506,19 @@ } break; } - pci_write_config(device_get_parent(ch->dev), 0x60 + (devno<<2), timing, 4); + pci_write_config(device_get_parent(atadev->channel->dev), + 0x60 + (devno << 2), timing, 4); } static void -hpt_timing(struct ata_channel *ch, int devno, int mode) +hpt_timing(struct ata_device *atadev, int devno, int mode) { - device_t parent = device_get_parent(ch->dev); + 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 (ch->chiptype == 0x00081103 && pci_get_revid(parent) >= 0x07) { + if (chiptype == 0x00081103 && chiprev >= 0x07) { switch (mode) { /* HPT374 */ case ATA_PIO0: timing = 0x0ac1f48a; break; case ATA_PIO1: timing = 0x0ac1f465; break; @@ -1354,8 +1533,8 @@ default: timing = 0x0d029d5e; } } - else if ((ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x05) || - (ch->chiptype == 0x00051103 && pci_get_revid(parent) >= 0x01)) { + 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; @@ -1370,7 +1549,7 @@ default: timing = 0x0d029d5e; } } - else if (ch->chiptype == 0x00041103 && pci_get_revid(parent) >= 0x03) { + else if (chiptype == 0x00041103 && chiprev >= 0x03) { switch (mode) { /* HPT370 */ case ATA_PIO0: timing = 0x06914e57; break; case ATA_PIO1: timing = 0x06914e43; break; @@ -1432,13 +1611,13 @@ } static int -hpt_cable80(struct ata_channel *ch) +hpt_cable80(struct ata_device *atadev) { - device_t parent = device_get_parent(ch->dev); + device_t parent = device_get_parent(atadev->channel->dev); u_int8_t reg, val, res; - if (ch->chiptype == 0x00081103 && pci_get_function(parent) == 1) { - reg = ch->unit ? 0x57 : 0x53; + 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); } @@ -1447,7 +1626,7 @@ val = pci_read_config(parent, reg, 1); pci_write_config(parent, reg, val & 0xfe, 1); } - res = pci_read_config(parent, 0x5a, 1) & (ch->unit ? 0x01 : 0x02); + res = pci_read_config(parent, 0x5a, 1) & (atadev->channel->unit ? 0x1:0x2); pci_write_config(parent, reg, val, 1); return !res; } Index: dev/disk/ata/ata-isa.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/ata-isa.c,v retrieving revision 1.3 diff -u -r1.3 ata-isa.c --- dev/disk/ata/ata-isa.c 7 Aug 2003 21:16:51 -0000 1.3 +++ dev/disk/ata/ata-isa.c 27 Oct 2003 12:15:55 -0000 @@ -108,33 +108,40 @@ */ #include "use_pci.h" #if NPCI == 0 -void * -ata_dmaalloc(struct ata_channel *ch, int device) +int +ata_dmaalloc(struct ata_device *atadev) +{ + return ENXIO; +} + +void +ata_dmafree(struct ata_device *atadev) +{ +} + +void +ata_dmafreetags(struct ata_channel *ch) { - return 0; } void -ata_dmainit(struct ata_channel *ch, int device, - int piomode, int wdmamode, int udmamode) +ata_dmainit(struct ata_device *atadev, int piomode, int wdmamode, int udmamode) { } int -ata_dmasetup(struct ata_channel *ch, int device, struct ata_dmaentry *dmatab, - caddr_t data, int32_t count) +ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) { return -1; } void -ata_dmastart(struct ata_channel *ch, int device, - struct ata_dmaentry *dmatab, int dir) +ata_dmastart(struct ata_device *atadev, caddr_t data, int32_t count, int dir) { } int -ata_dmadone(struct ata_channel *ch) +ata_dmadone(struct ata_device *atadev) { return -1; } Index: dev/disk/ata/atapi-all.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/atapi-all.c,v retrieving revision 1.4 diff -u -r1.4 atapi-all.c --- dev/disk/ata/atapi-all.c 7 Aug 2003 21:16:51 -0000 1.4 +++ dev/disk/ata/atapi-all.c 27 Oct 2003 12:15:55 -0000 @@ -50,6 +50,7 @@ #include "atapi-all.h" /* prototypes */ +static void atapi_reset(struct ata_device *); static void atapi_read(struct atapi_request *, int); static void atapi_write(struct atapi_request *, int); static void atapi_finish(struct atapi_request *); @@ -79,8 +80,9 @@ ata_umode(atadev->param), atadev->param->support_dma); ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); + atapi_reset(atadev); if (atapi_dma && !(atadev->param->drq_type == ATAPI_DRQT_INTR)) { - ata_dmainit(atadev->channel, atadev->unit, + ata_dmainit(atadev, (ata_pmode(atadev->param) < 0) ? (atadev->param->support_dma ? 4:0):ata_pmode(atadev->param), (ata_wmode(atadev->param) < 0) ? @@ -88,7 +90,7 @@ ata_umode(atadev->param)); } else - ata_dmainit(atadev->channel, atadev->unit, + ata_dmainit(atadev, ata_pmode(atadev->param) < 0 ? 0 : ata_pmode(atadev->param), -1, -1); ATA_UNLOCK_CH(atadev->channel); @@ -161,10 +163,9 @@ bp->b_error = ENXIO; biodone(bp); } - if (request->dmatab) - free(request->dmatab, M_DEVBUF); free(request, M_ATAPI); } + ata_dmafree(atadev); free(atadev->result, M_ATAPI); atadev->driver = NULL; atadev->flags = 0; @@ -196,7 +197,7 @@ request->driver = driver; } if (atadev->mode >= ATA_DMA) { - if (!(request->dmatab = ata_dmaalloc(atadev->channel, atadev->unit))) + if (ata_dmaalloc(atadev)) atadev->mode = ATA_PIO; } @@ -225,8 +226,6 @@ error = request->error; if (error) bcopy(&request->sense, atadev->result, sizeof(struct atapi_reqsense)); - if (request->dmatab) - free(request->dmatab, M_DEVBUF); free(request, M_ATAPI); return error; } @@ -294,8 +293,7 @@ ((request->ccb[0] == ATAPI_WRITE || request->ccb[0] == ATAPI_WRITE_BIG) && !(atadev->channel->flags & ATA_ATAPI_DMA_RO))) && - !ata_dmasetup(atadev->channel, atadev->unit, request->dmatab, - (void *)request->data, request->bytecount)) { + !ata_dmasetup(atadev, (void *)request->data, request->bytecount)) { request->flags |= ATPR_F_DMA_USED; } @@ -307,8 +305,8 @@ ata_prtdev(atadev, "failure to send ATAPI packet command\n"); if (request->flags & ATPR_F_DMA_USED) - ata_dmastart(atadev->channel, atadev->unit, - request->dmatab, request->flags & ATPR_F_READ); + ata_dmastart(atadev, request->data, request->bytecount, + request->flags & ATPR_F_READ); /* command interrupt device ? just return */ if (atadev->param->drq_type == ATAPI_DRQT_INTR) @@ -365,7 +363,7 @@ } if (request->flags & ATPR_F_DMA_USED) { - dma_stat = ata_dmadone(atadev->channel); + dma_stat = ata_dmadone(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); @@ -485,16 +483,18 @@ void atapi_reinit(struct ata_device *atadev) { + atapi_reset(atadev); + /* reinit device parameters */ if (atadev->mode >= ATA_DMA) - ata_dmainit(atadev->channel, atadev->unit, + 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->channel, atadev->unit, + ata_dmainit(atadev, ata_pmode(atadev->param)<0 ? 0 : ata_pmode(atadev->param), -1, -1); } @@ -538,6 +538,43 @@ } static void +atapi_reset(struct ata_device *atadev) +{ + struct ata_channel *ch = atadev->channel; + u_int8_t stat, lsb, msb; + int timeout; + + ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + DELAY(10); + ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_4BIT | ATA_A_IDS); + DELAY(10); + ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + DELAY(10); + ATA_OUTB(ch->r_io, ATA_CMD, ATA_C_ATAPI_RESET); + + for (timeout = 10000; timeout; timeout--) { + DELAY(100); + ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + DELAY(10); + lsb = ATA_INB(ch->r_io, ATA_CYL_LSB); + msb = ATA_INB(ch->r_io, ATA_CYL_MSB); + stat = ATA_INB(ch->r_io, ATA_STATUS); + if ((stat & ATA_S_BUSY) == 0) + break; + } + + if (bootverbose) + ata_prtdev(atadev, "stat %x, lsb %x, msb %x\n", stat, lsb, msb); + + if (timeout == 0) + ata_prtdev(atadev, "soft reset failed\n"); + + ATA_OUTB(ch->r_io, ATA_DRIVE, ATA_D_IBM | atadev->unit); + DELAY(10); + ATA_OUTB(ch->r_altio, ATA_ALTSTAT, ATA_A_4BIT); +} + +static void atapi_read(struct atapi_request *request, int length) { int8_t **buffer = (int8_t **)&request->data; @@ -604,11 +641,8 @@ atapi_cmd2str(request->ccb[0])); #endif if (request->callback) { - if (!((request->callback)(request))) { - if (request->dmatab) - free(request->dmatab, M_DEVBUF); + if (!((request->callback)(request))) free(request, M_ATAPI); - } } else wakeup((caddr_t)request); @@ -619,31 +653,37 @@ { struct ata_device *atadev = request->device; + ATA_FORCELOCK_CH(atadev->channel, ATA_CONTROL); atadev->channel->running = NULL; ata_prtdev(atadev, "%s command timeout - resetting\n", atapi_cmd2str(request->ccb[0])); + atapi_reset(atadev); + if (request->flags & ATPR_F_DMA_USED) { - ata_dmadone(atadev->channel); + ata_dmadone(atadev); if (request->retries == ATAPI_MAX_RETRIES) { - ata_dmainit(atadev->channel, atadev->unit, + ata_dmainit(atadev, (ata_pmode(atadev->param) < 0) ? 0 : ata_pmode(atadev->param), -1, -1); ata_prtdev(atadev, "trying fallback to PIO mode\n"); request->retries = 0; } } + ATA_UNLOCK_CH(atadev->channel); /* if retries still permit, reinject this request */ if (request->retries++ < ATAPI_MAX_RETRIES) { + int s = splbio(); TAILQ_INSERT_HEAD(&atadev->channel->atapi_queue, request, chain); + ata_start(atadev->channel); + splx(s); } else { /* retries all used up, return error */ request->error = EIO; wakeup((caddr_t)request); } - ata_reinit(atadev->channel); } static char * Index: dev/disk/ata/atapi-all.h =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/atapi-all.h,v retrieving revision 1.2 diff -u -r1.2 atapi-all.h --- dev/disk/ata/atapi-all.h 17 Jun 2003 04:28:22 -0000 1.2 +++ dev/disk/ata/atapi-all.h 27 Oct 2003 12:15:55 -0000 @@ -167,7 +167,6 @@ caddr_t data; /* pointer to data buf */ atapi_callback_t *callback; /* ptr to callback func */ - struct ata_dmaentry *dmatab; /* DMA transfer table */ void *driver; /* driver specific */ TAILQ_ENTRY(atapi_request) chain; /* list management */ }; Index: dev/disk/ata/atapi-cd.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/atapi-cd.c,v retrieving revision 1.8 diff -u -r1.8 atapi-cd.c --- dev/disk/ata/atapi-cd.c 7 Aug 2003 21:16:51 -0000 1.8 +++ dev/disk/ata/atapi-cd.c 27 Oct 2003 12:15:55 -0000 @@ -47,6 +47,9 @@ #include #include #include + +#include + #include "ata-all.h" #include "atapi-all.h" #include "atapi-cd.h" Index: dev/disk/ata/atapi-fd.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/atapi-fd.c,v retrieving revision 1.7 diff -u -r1.7 atapi-fd.c --- dev/disk/ata/atapi-fd.c 7 Aug 2003 21:16:51 -0000 1.7 +++ dev/disk/ata/atapi-fd.c 27 Oct 2003 12:15:55 -0000 @@ -42,6 +42,9 @@ #include #include #include + +#include + #include "ata-all.h" #include "atapi-all.h" #include "atapi-fd.h" Index: dev/disk/ata/atapi-tape.c =================================================================== RCS file: /scratch/dcvs/src/sys/dev/disk/ata/atapi-tape.c,v retrieving revision 1.7 diff -u -r1.7 atapi-tape.c --- dev/disk/ata/atapi-tape.c 7 Aug 2003 21:16:51 -0000 1.7 +++ dev/disk/ata/atapi-tape.c 27 Oct 2003 12:15:55 -0000 @@ -43,6 +43,9 @@ #include #include #include + +#include + #include "ata-all.h" #include "atapi-all.h" #include "atapi-tape.h"