diff options
-rw-r--r-- | sys/dev/ata/ata-all.c | 3 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 42 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 86 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.h | 1 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 602 | ||||
-rw-r--r-- | sys/dev/ata/ata-isa.c | 27 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.c | 39 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 56 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 1 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 25 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.h | 114 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 1 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 1 |
13 files changed, 658 insertions, 340 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 9d4d1e9..067cf1c 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -249,6 +249,7 @@ ata_detach(device_t dev) 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); @@ -1251,7 +1252,7 @@ ata_change_mode(struct ata_device *atadev, int mode) } 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 */ } diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index ee2bf2c..a5681f1 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -158,6 +158,18 @@ struct ata_dmaentry { 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; @@ -176,6 +188,7 @@ struct ata_device { int mode; /* transfermode */ int cmd; /* last cmd executed */ void *result; /* misc data */ + struct ata_dmastate dmastate; /* dma state */ }; /* structure describing an ATA channel */ @@ -185,6 +198,7 @@ struct ata_channel { 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 */ @@ -259,12 +273,14 @@ int ata_wmode(struct ata_params *); 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); +void ata_dmastart(struct ata_device *, 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)\ @@ -294,10 +310,18 @@ int ata_dmadone(struct ata_channel *); bus_space_read_multi_2(rman_get_bustag((res)), \ rman_get_bushandle((res)), \ (offset), (addr), (count)) +#define ATA_INSW_STRM(res, offset, addr, count) \ + bus_space_read_multi_stream_2(rman_get_bustag((res)), \ + rman_get_bushandle((res)), \ + (offset), (addr), (count)) #define ATA_INSL(res, offset, addr, count) \ bus_space_read_multi_4(rman_get_bustag((res)), \ rman_get_bushandle((res)), \ (offset), (addr), (count)) +#define ATA_INSL_STRM(res, offset, addr, count) \ + bus_space_read_multi_stream_4(rman_get_bustag((res)), \ + rman_get_bushandle((res)), \ + (offset), (addr), (count)) #define ATA_OUTB(res, offset, value) \ bus_space_write_1(rman_get_bustag((res)), \ rman_get_bushandle((res)), (offset), (value)) @@ -311,7 +335,15 @@ int ata_dmadone(struct ata_channel *); bus_space_write_multi_2(rman_get_bustag((res)), \ rman_get_bushandle((res)), \ (offset), (addr), (count)) +#define ATA_OUTSW_STRM(res, offset, addr, count) \ + bus_space_write_multi_stream_2(rman_get_bustag((res)), \ + rman_get_bushandle((res)), \ + (offset), (addr), (count)) #define ATA_OUTSL(res, offset, addr, count) \ bus_space_write_multi_4(rman_get_bustag((res)), \ rman_get_bushandle((res)), \ (offset), (addr), (count)) +#define ATA_OUTSL_STRM(res, offset, addr, count) \ + bus_space_write_multi_stream_4(rman_get_bustag((res)), \ + rman_get_bushandle((res)), \ + (offset), (addr), (count)) diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 8f21ea1..b4dbf87 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -106,6 +106,8 @@ ad_attach(struct ata_device *atadev) { struct ad_softc *adp; dev_t dev; + u_int32_t lbasize; + u_int64_t lbasize48; if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) { ata_prtdev(atadev, "failed to allocate driver storage\n"); @@ -123,20 +125,26 @@ ad_attach(struct ata_device *atadev) adp->total_secs = atadev->param->cylinders * adp->heads * adp->sectors; bioq_init(&adp->queue); + lbasize = (u_int32_t)atadev->param->lba_size_lo | + ((u_int32_t)atadev->param->lba_size_hi << 16); + /* does this device need oldstyle CHS addressing */ if (!ad_version(atadev->param->version_major) || - !(atadev->param->atavalid & ATA_FLAG_54_58) || !atadev->param->lba_size) + !(atadev->param->atavalid & ATA_FLAG_54_58) || !lbasize) adp->flags |= AD_F_CHS_USED; /* use the 28bit LBA size if valid */ - if (atadev->param->cylinders == 16383 && - adp->total_secs < atadev->param->lba_size) - adp->total_secs = atadev->param->lba_size; + if (atadev->param->cylinders == 16383 && adp->total_secs < lbasize) + adp->total_secs = lbasize; + + lbasize48 = (u_int64_t)atadev->param->lba_size48_1 | + ((u_int64_t)atadev->param->lba_size48_2 << 16) | + ((u_int64_t)atadev->param->lba_size48_3 << 32) | + ((u_int64_t)atadev->param->lba_size48_4 << 48); /* use the 48bit LBA size if valid */ - if (atadev->param->support.address48 && - atadev->param->lba_size48 > 268435455) - adp->total_secs = atadev->param->lba_size48; + if (atadev->param->support.address48 && lbasize48 > 268435455) + adp->total_secs = lbasize48; ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); /* use multiple sectors/interrupt if device supports it */ @@ -168,11 +176,10 @@ ad_attach(struct ata_device *atadev) /* 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)) { @@ -235,6 +242,7 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */ biofinish(request->bp, NULL, ENXIO); ad_free(request); } + ata_dmafree(atadev); while ((bp = bioq_first(&adp->queue))) { bioq_remove(&adp->queue, bp); biofinish(bp, NULL, ENXIO); @@ -366,7 +374,7 @@ ad_start(struct ata_device *atadev) if (bp->bio_cmd == BIO_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; } @@ -430,8 +438,7 @@ ad_transfer(struct ad_request *request) /* does this drive & transfer work with DMA ? */ request->flags &= ~ADR_F_DMA_USED; if (adp->device->mode >= ATA_DMA && - !ata_dmasetup(adp->device->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; @@ -480,8 +487,7 @@ ad_transfer(struct ad_request *request) } /* 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->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -514,13 +520,13 @@ ad_transfer(struct ad_request *request) /* output the data */ if (adp->device->channel->flags & ATA_USE_16BIT) - ATA_OUTSW(adp->device->channel->r_io, ATA_DATA, - (void *)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int16_t)); + ATA_OUTSW_STRM(adp->device->channel->r_io, ATA_DATA, + (void *)((uintptr_t)request->data + request->donecount), + request->currentsize / sizeof(int16_t)); else - ATA_OUTSL(adp->device->channel->r_io, ATA_DATA, - (void *)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int32_t)); + ATA_OUTSL_STRM(adp->device->channel->r_io, ATA_DATA, + (void *)((uintptr_t)request->data + request->donecount), + request->currentsize / sizeof(int32_t)); return ATA_OP_CONTINUES; transfer_failed: @@ -551,7 +557,7 @@ ad_interrupt(struct ad_request *request) /* 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) @@ -578,8 +584,7 @@ ad_interrupt(struct ad_request *request) 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); @@ -590,8 +595,7 @@ ad_interrupt(struct ad_request *request) 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); @@ -623,13 +627,15 @@ ad_interrupt(struct ad_request *request) else { /* data ready, read in */ if (adp->device->channel->flags & ATA_USE_16BIT) - ATA_INSW(adp->device->channel->r_io, ATA_DATA, - (void*)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int16_t)); + ATA_INSW_STRM(adp->device->channel->r_io, ATA_DATA, + (void*)((uintptr_t)request->data + + request->donecount), request->currentsize / + sizeof(int16_t)); else - ATA_INSL(adp->device->channel->r_io, ATA_DATA, - (void*)((uintptr_t)request->data + request->donecount), - request->currentsize / sizeof(int32_t)); + ATA_INSL_STRM(adp->device->channel->r_io, ATA_DATA, + (void*)((uintptr_t)request->data + + request->donecount), request->currentsize / + sizeof(int32_t)); } } @@ -743,8 +749,7 @@ ad_service(struct ad_softc *adp, int change) 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->flags & ADR_F_READ); return ATA_OP_CONTINUES; } return ATA_OP_FINISHED; @@ -753,8 +758,6 @@ ad_service(struct ad_softc *adp, int change) static void ad_free(struct ad_request *request) { - if (request->dmatab) - free(request->dmatab, M_DEVBUF); request->softc->tags[request->tag] = NULL; free(request, M_AD); } @@ -829,11 +832,10 @@ ad_timeout(struct ad_request *request) 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; } @@ -863,13 +865,11 @@ ad_reinit(struct ata_device *atadev) 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 diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index ad5e37d..80ae15c 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -48,7 +48,6 @@ struct ad_request { struct bio *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 */ }; diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 2bcaf42..5104a05 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -36,80 +36,184 @@ #include <sys/bus.h> #include <sys/disk.h> #include <sys/devicestat.h> -#include <vm/vm.h> -#include <vm/pmap.h> #include <pci/pcivar.h> #include <machine/bus.h> #include <sys/rman.h> #include <dev/ata/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; - - 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; + struct ata_channel *ch; + struct ata_dc_cb_args ccba; + struct ata_dmastate *ds; + int error; + + 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) { - 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); + + if (ch->dmatag) { + bus_dma_tag_destroy(ch->dmatag); + ch->dmatag = NULL; + } +} + +static void +ata_dmacreate(struct ata_device *atadev, int apiomode, int mode) +{ + + 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 0x248a8086: /* Intel ICH3 mobile */ case 0x248b8086: /* Intel ICH3 */ @@ -133,7 +237,7 @@ ata_dmainit(struct ata_channel *ch, int device, (pci_read_config(parent, 0x48, 4) & ~mask48) | new48, 4); pci_write_config(parent, 0x54, word54 | (0x1000<<devno), 2); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -163,7 +267,7 @@ ata_dmainit(struct ata_channel *ch, int device, (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; } } @@ -191,7 +295,7 @@ ata_dmainit(struct ata_channel *ch, int device, 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; } } @@ -205,7 +309,7 @@ ata_dmainit(struct ata_channel *ch, int device, 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)) { @@ -238,7 +342,7 @@ ata_dmainit(struct ata_channel *ch, int device, mask44 = 0x0000000f; new44 = 0x0000000b; } - if (ch->unit) { + if (channel) { mask40 <<= 16; new40 <<= 16; mask44 <<= 4; @@ -250,7 +354,7 @@ ata_dmainit(struct ata_channel *ch, int device, 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; } } @@ -262,11 +366,11 @@ ata_dmainit(struct ata_channel *ch, int device, 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, @@ -275,7 +379,7 @@ ata_dmainit(struct ata_channel *ch, int device, 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; } } @@ -283,12 +387,14 @@ ata_dmainit(struct ata_channel *ch, int device, 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) @@ -304,11 +410,11 @@ ata_dmainit(struct ata_channel *ch, int device, 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) @@ -324,11 +430,11 @@ ata_dmainit(struct ata_channel *ch, int device, 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) @@ -342,8 +448,8 @@ ata_dmainit(struct ata_channel *ch, int device, 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; } } @@ -361,14 +467,39 @@ ata_dmainit(struct ata_channel *ch, int device, 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 0x74411022: /* AMD 768 */ @@ -381,7 +512,7 @@ ata_dmainit(struct ata_channel *ch, int device, (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x53 - devno, 0xc6, 1); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -396,7 +527,7 @@ ata_dmainit(struct ata_channel *ch, int device, (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x53 - devno, 0xc5, 1); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -448,7 +579,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[6], 1); - atadev->mode = ATA_UDMA6; + ata_dmacreate(atadev, apiomode, ATA_UDMA6); return; } } @@ -460,7 +591,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[5], 1); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -472,7 +603,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[4], 1); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -484,7 +615,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, 0x53 - devno, reg_val[2], 1); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -496,11 +627,11 @@ via_82c586: if (bootverbose) ata_prtdev(atadev, "%s setting WDMA2 on %s chip\n", (error) ? "failed" : "success", - (ch->chiptype == 0x74091022) ? "AMD" : "VIA"); + (chiptype == 0x74091022) ? "AMD" : "VIA"); 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; } } @@ -531,7 +662,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0x8000, 2); - atadev->mode = ATA_UDMA5; + ata_dmacreate(atadev, apiomode, ATA_UDMA5); return; } } @@ -543,7 +674,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0x9000, 2); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -555,7 +686,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0xb000, 2); - atadev->mode = ATA_UDMA2; + ata_dmacreate(atadev, apiomode, ATA_UDMA2); return; } } @@ -574,7 +705,7 @@ via_82c586: (error) ? "failed" : "success"); if (!error) { pci_write_config(parent, reg, val | 0x9000, 2); - atadev->mode = ATA_UDMA4; + ata_dmacreate(atadev, apiomode, ATA_UDMA4); return; } } @@ -586,11 +717,11 @@ via_82c586: (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) @@ -598,7 +729,7 @@ via_82c586: (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; } } @@ -610,7 +741,7 @@ via_82c586: (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; } } @@ -627,11 +758,11 @@ via_82c586: 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; } } @@ -647,11 +778,11 @@ via_82c586: 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; } } @@ -664,18 +795,18 @@ via_82c586: 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 */ @@ -689,7 +820,7 @@ via_82c586: 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; } } @@ -704,8 +835,9 @@ via_82c586: 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; } } @@ -713,7 +845,7 @@ via_82c586: 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); @@ -721,8 +853,8 @@ via_82c586: 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; } } @@ -733,8 +865,8 @@ via_82c586: 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; } } @@ -745,12 +877,12 @@ via_82c586: 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) @@ -766,7 +898,7 @@ via_82c586: 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; } } @@ -786,7 +918,7 @@ via_82c586: 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; } } @@ -809,7 +941,7 @@ via_82c586: 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; } } @@ -820,7 +952,7 @@ via_82c586: 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, @@ -829,7 +961,7 @@ via_82c586: 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; } } @@ -837,15 +969,16 @@ via_82c586: break; case 0x4d69105a: /* 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; } } @@ -853,27 +986,29 @@ via_82c586: 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; } } @@ -884,7 +1019,7 @@ via_82c586: 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; } } @@ -895,7 +1030,7 @@ via_82c586: 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; } } @@ -903,59 +1038,59 @@ via_82c586: case 0x4d30105a: /* Promise Ultra/FastTrak 100 controllers */ case 0x0d30105a: /* Promise OEM ATA100 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; } } /* FALLTHROUGH */ 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; } } @@ -966,76 +1101,76 @@ via_82c586: 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; } } @@ -1046,44 +1181,42 @@ via_82c586: 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; } } @@ -1102,52 +1235,81 @@ via_82c586: } } +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; + 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!"); 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; + + cba.dmatab = ds->dmatab; + if (bus_dmamap_load(ds->ddmatag, ds->ddmamap, data, count, + ata_dmasetupd_cb, &cba, 0) || cba.error) + ds->flags = ATA_DS_ACTIVE; + bus_dmamap_sync(ds->cdmatag, ds->cdmamap, BUS_DMASYNC_PREWRITE); + return 0; } void -ata_dmastart(struct ata_channel *ch, int device, - struct ata_dmaentry *dmatab, int dir) +ata_dmastart(struct ata_device *atadev, int dir) { + struct ata_channel *ch; + struct ata_dmastate *ds; + + ch = atadev->channel; + ds = &atadev->dmastate; + bus_dmamap_sync(ds->ddmatag, ds->ddmamap, dir ? BUS_DMASYNC_PREREAD : + BUS_DMASYNC_PREWRITE); + if (dir) + ds->flags |= ATA_DS_READ; ch->flags |= ATA_DMA_ACTIVE; - ATA_OUTL(ch->r_bmio, ATA_BMDTP_PORT, vtophys(dmatab)); + 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) | @@ -1157,16 +1319,24 @@ ata_dmastart(struct ata_channel *ch, int device, } 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); + ds->flags = 0; return error & ATA_BMSTAT_MASK; } @@ -1177,7 +1347,7 @@ ata_dmastatus(struct ata_channel *ch) } 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; @@ -1191,14 +1361,15 @@ cyrix_timing(struct ata_channel *ch, int devno, int mode) 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; @@ -1220,7 +1391,7 @@ promise_timing(struct ata_channel *ch, int devno, int mode) 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: @@ -1251,16 +1422,19 @@ promise_timing(struct ata_channel *ch, int devno, int mode) } 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; @@ -1275,8 +1449,8 @@ hpt_timing(struct ata_channel *ch, int devno, int mode) 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; @@ -1291,7 +1465,7 @@ hpt_timing(struct ata_channel *ch, int devno, int mode) 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; @@ -1353,13 +1527,13 @@ hpt_timing(struct ata_channel *ch, int devno, int mode) } 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); } @@ -1368,7 +1542,7 @@ hpt_cable80(struct ata_channel *ch) 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; } diff --git a/sys/dev/ata/ata-isa.c b/sys/dev/ata/ata-isa.c index cb04242..244f3ad 100644 --- a/sys/dev/ata/ata-isa.c +++ b/sys/dev/ata/ata-isa.c @@ -107,33 +107,40 @@ DRIVER_MODULE(ata, isa, ata_isa_driver, ata_devclass, 0, 0); */ #include "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, int dir) { } int -ata_dmadone(struct ata_channel *ch) +ata_dmadone(struct ata_device *atadev) { return -1; } diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index 079e09c..7b22f1e 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -28,6 +28,7 @@ * $FreeBSD$ */ +#include "opt_ata.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -363,13 +364,19 @@ ata_pci_attach(device_t dev) type = pci_get_devid(dev); class = pci_get_class(dev); subclass = pci_get_subclass(dev); - cmd = pci_read_config(dev, PCIR_COMMAND, 4); + cmd = pci_read_config(dev, PCIR_COMMAND, 2); if (!(cmd & PCIM_CMD_PORTEN)) { device_printf(dev, "ATA channel disabled by BIOS\n"); return 0; } +#ifdef ATA_ENABLE_BUSMASTER + if (!(cmd & PCIM_CMD_BUSMASTEREN)) { + pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); + cmd = pci_read_config(dev, PCIR_COMMAND, 2); + } +#endif /* is busmastering supported ? */ if ((cmd & (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) == (PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN)) { @@ -403,22 +410,28 @@ ata_pci_attach(device_t dev) break; case 0x00041103: /* HighPoint HPT366/368/370/372 default setup */ - if (pci_get_revid(dev) < 2) { /* HPT 366 */ + if (pci_get_revid(dev) < 2) { /* HPT366 */ /* turn off interrupt prediction */ pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x80), 1); break; } - /* turn off interrupt prediction */ - pci_write_config(dev, 0x51, (pci_read_config(dev, 0x51, 1) & ~0x03), 1); - pci_write_config(dev, 0x55, (pci_read_config(dev, 0x55, 1) & ~0x03), 1); + if (pci_get_revid(dev) < 5) { /* HPT368/370 */ + /* turn off interrupt prediction */ + pci_write_config(dev, 0x51, + (pci_read_config(dev, 0x51, 1) & ~0x03), 1); + pci_write_config(dev, 0x55, + (pci_read_config(dev, 0x55, 1) & ~0x03), 1); - /* turn on interrupts */ - pci_write_config(dev, 0x5a, (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); + /* turn on interrupts */ + pci_write_config(dev, 0x5a, + (pci_read_config(dev, 0x5a, 1) & ~0x10), 1); - /* set clocks etc */ - pci_write_config(dev, 0x5b, 0x22, 1); - break; + /* set clocks etc */ + pci_write_config(dev, 0x5b, 0x22, 1); + break; + } + /* FALLTHROUGH */ case 0x00051103: /* HighPoint HPT372 default setup */ case 0x00081103: /* HighPoint HPT374 default setup */ @@ -481,6 +494,10 @@ ata_pci_attach(device_t dev) (pci_get_revid(dev) >= 0x92) ? 0x03 : 0x02, 1); break; + case 0x06461095: /* CMD 646 enable interrupts, set DMA read mode */ + pci_write_config(dev, 0x71, 0x01, 1); + break; + case 0x10001042: /* RZ 100? known bad, no DMA */ case 0x10011042: case 0x06401095: /* CMD 640 known bad, no DMA */ @@ -631,7 +648,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, start, end, count, flags); if (res) { start = rman_get_start(res) + 2; - end = rman_get_start(res) + ATA_ALTIOSIZE - 1; + end = start + ATA_ALTIOSIZE - 1; count = ATA_ALTIOSIZE; BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, SYS_RES_IOPORT, myrid, res); diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 5a2e790..a48d79e 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -74,7 +74,7 @@ atapi_attach(struct ata_device *atadev) ATA_SLEEPLOCK_CH(atadev->channel, ATA_CONTROL); 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) ? @@ -82,7 +82,7 @@ atapi_attach(struct ata_device *atadev) 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); @@ -152,10 +152,9 @@ atapi_detach(struct ata_device *atadev) struct bio *bp = (struct bio *) request->driver; biofinish(bp, NULL, ENXIO); } - 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; @@ -186,7 +185,7 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data, 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; } @@ -212,8 +211,6 @@ atapi_queue_cmd(struct ata_device *atadev, int8_t *ccb, caddr_t data, 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; } @@ -279,8 +276,7 @@ atapi_transfer(struct atapi_request *request) ((request->ccb[0] == ATAPI_WRITE || request->ccb[0] == ATAPI_WRITE_BIG) && !(atadev->channel->flags & ATA_ATAPI_DMA_RO))) && - !ata_dmasetup(atadev->channel, atadev->unit, request->dmatab, - (void *)request->data, request->bytecount)) { + !ata_dmasetup(atadev, (void *)request->data, request->bytecount)) { request->flags |= ATPR_F_DMA_USED; } @@ -291,8 +287,7 @@ atapi_transfer(struct atapi_request *request) ata_prtdev(atadev, "failure to send ATAPI packet command\n"); if (request->flags & ATPR_F_DMA_USED) - ata_dmastart(atadev->channel, atadev->unit, - request->dmatab, request->flags & ATPR_F_READ); + ata_dmastart(atadev, request->flags & ATPR_F_READ); /* command interrupt device ? just return */ if (atadev->param->drq_type == ATAPI_DRQT_INTR) @@ -320,8 +315,8 @@ atapi_transfer(struct atapi_request *request) DELAY(10); /* send actual command */ - ATA_OUTSW(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, - request->ccbsize / sizeof(int16_t)); + ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, + request->ccbsize / sizeof(int16_t)); return ATA_OP_CONTINUES; } @@ -343,13 +338,13 @@ atapi_interrupt(struct atapi_request *request) atapi_finish(request); return ATA_OP_FINISHED; } - ATA_OUTSW(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, - request->ccbsize / sizeof(int16_t)); + ATA_OUTSW_STRM(atadev->channel->r_io, ATA_DATA, (int16_t *)request->ccb, + request->ccbsize / sizeof(int16_t)); return ATA_OP_CONTINUES; } 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); @@ -471,14 +466,14 @@ atapi_reinit(struct ata_device *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); } @@ -533,11 +528,11 @@ atapi_read(struct atapi_request *request, int length) *buffer = (int8_t *)&request->sense; if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) - ATA_INSW(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int16_t)); + ATA_INSW_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + size / sizeof(int16_t)); else - ATA_INSL(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int32_t)); + ATA_INSL_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + size / sizeof(int32_t)); if (request->bytecount < length) { ata_prtdev(request->device, "read data overrun %d/%d\n", @@ -562,11 +557,11 @@ atapi_write(struct atapi_request *request, int length) *buffer = (int8_t *)&request->sense; if (ch->flags & ATA_USE_16BIT || (size % sizeof(int32_t))) - ATA_OUTSW(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int16_t)); + ATA_OUTSW_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + size / sizeof(int16_t)); else - ATA_OUTSL(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), - size / sizeof(int32_t)); + ATA_OUTSL_STRM(ch->r_io, ATA_DATA, (void *)((uintptr_t)*buffer), + size / sizeof(int32_t)); if (request->bytecount < length) { ata_prtdev(request->device, "write data underrun %d/%d\n", @@ -588,11 +583,8 @@ atapi_finish(struct atapi_request *request) 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); @@ -608,9 +600,9 @@ atapi_timeout(struct atapi_request *request) atapi_cmd2str(request->ccb[0])); 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"); diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index 88e6f1a..63d4a75 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -166,7 +166,6 @@ struct atapi_request { 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 */ }; diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index df65921..4018401 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -45,6 +45,7 @@ #include <sys/fcntl.h> #include <sys/conf.h> #include <sys/ctype.h> +#include <machine/bus.h> #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-cd.h> @@ -223,6 +224,7 @@ acddetach(struct ata_device *atadev) free(entry, M_ACD); } destroy_dev(cdp->dev); + EVENTHANDLER_DEREGISTER(dev_clone, cdp->clone_evh); devstat_remove_entry(cdp->stats); free(cdp->stats, M_ACD); ata_free_name(atadev); @@ -253,6 +255,28 @@ acd_init_lun(struct ata_device *atadev) return cdp; } +/* + * Handle dev_clone events, so that acd can be used as root device. + */ +static void +acd_clone(void *arg, char *name, int namelen, dev_t *dev) +{ + struct acd_softc *cdp; + char *p; + int unit; + + cdp = arg; + if (*dev != NODEV) + return; + if (!dev_stdclone(name, &p, "acd", &unit)) + return; + /* Handle compatability slices. */ + if (*p != '\0' && strcmp(p, "a") != 0 && strcmp(p, "c") != 0) + return; + if (unit == cdp->lun) + *dev = makedev(acd_cdevsw.d_maj, dkmakeminor(cdp->lun, 0, 0)); +} + static void acd_make_dev(struct acd_softc *cdp) { @@ -267,6 +291,7 @@ acd_make_dev(struct acd_softc *cdp) dev->si_bsize_phys = 2048; /* XXX SOS */ cdp->dev = dev; cdp->device->flags |= ATA_D_MEDIA_CHANGED; + cdp->clone_evh = EVENTHANDLER_REGISTER(dev_clone, acd_clone, cdp, 1000); } static void diff --git a/sys/dev/ata/atapi-cd.h b/sys/dev/ata/atapi-cd.h index e40191d..038c4f0 100644 --- a/sys/dev/ata/atapi-cd.h +++ b/sys/dev/ata/atapi-cd.h @@ -76,11 +76,6 @@ struct audiopage { } port[4]; }; -/* CDROM Capabilities and Mechanical Status Page */ -struct cappage { - /* mode page data header */ - u_int16_t data_length; - u_int8_t medium_type; #define MST_TYPE_MASK_LOW 0x0f #define MST_FMT_NONE 0x00 #define MST_DATA_120 0x01 @@ -101,15 +96,35 @@ struct cappage { #define MST_DOOR_OPEN 0x71 #define MST_FMT_ERROR 0x72 +#define MST_MECH_CADDY 0 +#define MST_MECH_TRAY 1 +#define MST_MECH_POPUP 2 +#define MST_MECH_CHANGER 4 +#define MST_MECH_CARTRIDGE 5 + +#define MST_DLEN_32 0 +#define MST_DLEN_16 1 +#define MST_DLEN_24 2 +#define MST_DLEN_24_I2S 3 + +#define ATAPI_CDROM_CAP_PAGE 0x2a + +/* CDROM Capabilities and Mechanical Status Page */ +struct cappage { + /* mode page data header */ + u_int16_t data_length; + u_int8_t medium_type; + u_int8_t dev_spec; u_int8_t unused[2]; u_int16_t blk_desc_len; /* capabilities page */ u_int8_t page_code; -#define ATAPI_CDROM_CAP_PAGE 0x2a u_int8_t param_len; + +#if BYTE_ORDER == LITTLE_ENDIAN u_int8_t read_cdr :1; /* supports CD-R read */ u_int8_t read_cdrw :1; /* supports CD-RW read */ u_int8_t read_packet :1; /* supports reading packet tracks */ @@ -117,6 +132,7 @@ struct cappage { u_int8_t read_dvdr :1; /* supports DVD-R read */ u_int8_t read_dvdram :1; /* supports DVD-RAM read */ u_int8_t reserved2_67 :2; + u_int8_t write_cdr :1; /* supports CD-R write */ u_int8_t write_cdrw :1; /* supports CD-RW write */ u_int8_t test_write :1; /* supports test writing */ @@ -124,6 +140,7 @@ struct cappage { u_int8_t write_dvdr :1; /* supports DVD-R write */ u_int8_t write_dvdram :1; /* supports DVD-RAM write */ u_int8_t reserved3_67 :2; + u_int8_t audio_play :1; /* audio play supported */ u_int8_t composite :1; /* composite audio/video supported */ u_int8_t dport1 :1; /* digital audio on port 1 */ @@ -132,6 +149,7 @@ struct cappage { u_int8_t mode2_form2 :1; /* mode 2 form 2 format */ u_int8_t multisession :1; /* multi-session photo-CD */ u_int8_t burnproof :1; /* supports burnproof */ + u_int8_t cd_da :1; /* audio-CD read supported */ u_int8_t cd_da_stream :1; /* CD-DA streaming */ u_int8_t rw :1; /* combined R-W subchannels */ @@ -140,21 +158,64 @@ struct cappage { u_int8_t isrc :1; /* can return the ISRC info */ u_int8_t upc :1; /* can return the catalog number UPC */ u_int8_t :1; + u_int8_t lock :1; /* can be locked */ u_int8_t locked :1; /* current lock state */ u_int8_t prevent :1; /* prevent jumper installed */ u_int8_t eject :1; /* can eject */ u_int8_t :1; u_int8_t mech :3; /* loading mechanism type */ -#define MST_MECH_CADDY 0 -#define MST_MECH_TRAY 1 -#define MST_MECH_POPUP 2 -#define MST_MECH_CHANGER 4 -#define MST_MECH_CARTRIDGE 5 u_int8_t sep_vol :1; /* independent volume of channels */ u_int8_t sep_mute :1; /* independent mute of channels */ u_int8_t:6; +#else + /* This is read using 16-bit stream transfers */ + u_int8_t reserved2_67 :2; + u_int8_t read_dvdram :1; /* supports DVD-RAM read */ + u_int8_t read_dvdr :1; /* supports DVD-R read */ + u_int8_t read_dvdrom :1; /* supports DVD-ROM read */ + u_int8_t read_packet :1; /* supports reading packet tracks */ + u_int8_t read_cdrw :1; /* supports CD-RW read */ + u_int8_t read_cdr :1; /* supports CD-R read */ + + u_int8_t reserved3_67 :2; + u_int8_t write_dvdram :1; /* supports DVD-RAM write */ + u_int8_t write_dvdr :1; /* supports DVD-R write */ + u_int8_t reserved3_3 :1; + u_int8_t test_write :1; /* supports test writing */ + u_int8_t write_cdrw :1; /* supports CD-RW write */ + u_int8_t write_cdr :1; /* supports CD-R write */ + + u_int8_t burnproof :1; /* supports burnproof */ + u_int8_t multisession :1; /* multi-session photo-CD */ + u_int8_t mode2_form2 :1; /* mode 2 form 2 format */ + u_int8_t mode2_form1 :1; /* mode 2 form 1 (XA) read */ + u_int8_t dport2 :1; /* digital audio on port 2 */ + u_int8_t dport1 :1; /* digital audio on port 1 */ + u_int8_t composite :1; /* composite audio/video supported */ + u_int8_t audio_play :1; /* audio play supported */ + + u_int8_t :1; + u_int8_t upc :1; /* can return the catalog number UPC */ + u_int8_t isrc :1; /* can return the ISRC info */ + u_int8_t c2 :1; /* C2 error pointers supported */ + u_int8_t rw_corr :1; /* R-W subchannel data corrected */ + u_int8_t rw :1; /* combined R-W subchannels */ + u_int8_t cd_da_stream :1; /* CD-DA streaming */ + u_int8_t cd_da :1; /* audio-CD read supported */ + + u_int8_t mech :3; /* loading mechanism type */ + u_int8_t :1; + u_int8_t eject :1; /* can eject */ + u_int8_t prevent :1; /* prevent jumper installed */ + u_int8_t locked :1; /* current lock state */ + u_int8_t lock :1; /* can be locked */ + + u_int8_t:6; + u_int8_t sep_mute :1; /* independent mute of channels */ + u_int8_t sep_vol :1; /* independent volume of channels */ +#endif u_int16_t max_read_speed; /* max raw data rate in bytes/1000 */ u_int16_t max_vol_levels; /* number of discrete volume levels */ @@ -162,40 +223,48 @@ struct cappage { u_int16_t cur_read_speed; /* current data rate in bytes/1000 */ u_int8_t reserved3; +#if BYTE_ORDER == LITTLE_ENDIAN u_int8_t bckf :1; /* data valid on failing edge of BCK */ u_int8_t rch :1; /* high LRCK indicates left channel */ u_int8_t lsbf :1; /* set if LSB first */ u_int8_t dlen :2; -#define MST_DLEN_32 0 -#define MST_DLEN_16 1 -#define MST_DLEN_24 2 -#define MST_DLEN_24_I2S 3 u_int8_t :3; +#else + u_int8_t :3; + + u_int8_t dlen :2; + u_int8_t lsbf :1; /* set if LSB first */ + u_int8_t rch :1; /* high LRCK indicates left channel */ + u_int8_t bckf :1; /* data valid on failing edge of BCK */ +#endif + u_int16_t max_write_speed; /* max raw data rate in bytes/1000 */ u_int16_t cur_write_speed; /* current data rate in bytes/1000 */ u_int16_t copy_protect_rev; u_int16_t reserved4; }; -/* CDROM Changer mechanism status structure */ -struct changer { - u_int8_t current_slot :5; /* active changer slot */ - u_int8_t mech_state :2; /* current changer state */ #define CH_READY 0 #define CH_LOADING 1 #define CH_UNLOADING 2 #define CH_INITIALIZING 3 - u_int8_t fault :1; /* fault in last operation */ - u_int8_t reserved0 :5; - u_int8_t cd_state :3; /* current mechanism state */ #define CD_IDLE 0 #define CD_AUDIO_ACTIVE 1 #define CD_AUDIO_SCAN 2 #define CD_HOST_ACTIVE 3 #define CD_NO_STATE 7 +/* CDROM Changer mechanism status structure */ +struct changer { + u_int8_t current_slot :5; /* active changer slot */ + u_int8_t mech_state :2; /* current changer state */ + + u_int8_t fault :1; /* fault in last operation */ + u_int8_t reserved0 :5; + u_int8_t cd_state :3; /* current mechanism state */ + u_int8_t current_lba[3]; /* current LBA */ u_int8_t slots; /* number of available slots */ u_int16_t table_length; /* slot table length */ @@ -326,4 +395,5 @@ struct acd_softc { struct disklabel disklabel; /* fake disk label */ struct devstat *stats; /* devstat entry */ dev_t dev; /* device place holders */ + eventhandler_tag clone_evh; }; diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index 5a20ae5..b4f2cdb 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -39,6 +39,7 @@ #include <sys/disk.h> #include <sys/devicestat.h> #include <sys/cdio.h> +#include <machine/bus.h> #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-fd.h> diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index 764a9ef..51a3386 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -40,6 +40,7 @@ #include <sys/mtio.h> #include <sys/disklabel.h> #include <sys/devicestat.h> +#include <machine/bus.h> #include <dev/ata/ata-all.h> #include <dev/ata/atapi-all.h> #include <dev/ata/atapi-tape.h> |