diff options
-rw-r--r-- | sys/dev/ata/ata-all.h | 6 | ||||
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 33 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 39 | ||||
-rw-r--r-- | sys/dev/ata/ata-lowlevel.c | 37 | ||||
-rw-r--r-- | sys/dev/ata/ata-pci.c | 10 |
5 files changed, 59 insertions, 66 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index da5a142..f272684 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -247,14 +247,16 @@ struct ata_dma { bus_addr_t mdmatab; /* bus address of dmatab */ u_int32_t alignment; /* DMA engine alignment */ u_int32_t max_iosize; /* DMA engine max IO size */ + u_int32_t cur_iosize; /* DMA engine current IO size */ int flags; #define ATA_DMA_ACTIVE 0x01 /* DMA transfer in progress */ #define ATA_DMA_READ 0x02 /* transaction is a read */ void (*alloc)(struct ata_channel *ch); void (*free)(struct ata_channel *ch); - int (*setup)(struct ata_device *atadev, caddr_t data, int32_t count); - int (*start)(struct ata_channel *ch, caddr_t data, int32_t count, int dir); + int (*load)(struct ata_device *atadev, caddr_t data, int32_t count,int dir); + int (*unload)(struct ata_channel *ch); + int (*start)(struct ata_channel *ch); int (*stop)(struct ata_channel *ch); }; diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index bf27fcc..83aedea 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -90,10 +90,10 @@ static void ata_promise_tx2_intr(void *); static void ata_promise_mio_intr(void *); static void ata_promise_setmode(struct ata_device *, int); static void ata_promise_new_dmainit(struct ata_channel *); -static int ata_promise_new_dmastart(struct ata_channel *, caddr_t, int32_t,int); +static int ata_promise_new_dmastart(struct ata_channel *); static int ata_promise_new_dmastop(struct ata_channel *); static void ata_promise_mio_dmainit(struct ata_channel *); -static int ata_promise_mio_dmastart(struct ata_channel *, caddr_t, int32_t,int); +static int ata_promise_mio_dmastart(struct ata_channel *); static int ata_promise_mio_dmastop(struct ata_channel *); static int ata_serverworks_chipinit(device_t); static void ata_serverworks_setmode(struct ata_device *, int); @@ -1360,27 +1360,25 @@ ata_promise_new_dmainit(struct ata_channel *ch) } static int -ata_promise_new_dmastart(struct ata_channel *ch, - caddr_t data, int32_t count, int dir) +ata_promise_new_dmastart(struct ata_channel *ch) { struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(ch->dev)); - int error; - if ((error = ata_dmastart(ch, data, count, dir))) - return error; if (ch->flags & ATA_48BIT_ACTIVE) { ATA_OUTB(ctlr->r_io1, 0x11, ATA_INB(ctlr->r_io1, 0x11) | (ch->unit ? 0x08 : 0x02)); ATA_OUTL(ctlr->r_io1, 0x20, - (dir ? 0x05000000 : 0x06000000) | (count >> 1)); + ((ch->dma->flags & ATA_DMA_READ) ? 0x05000000 : 0x06000000) | + (ch->dma->cur_iosize >> 1)); } ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab); ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, - (dir ? ATA_BMCMD_WRITE_READ : 0) | ATA_BMCMD_START_STOP); - return error; + ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) | + ATA_BMCMD_START_STOP); + return 0; } static int @@ -1399,7 +1397,6 @@ ata_promise_new_dmastop(struct ata_channel *ch) ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); - ata_dmastop(ch); return error; } @@ -1414,19 +1411,13 @@ ata_promise_mio_dmainit(struct ata_channel *ch) } static int -ata_promise_mio_dmastart(struct ata_channel *ch, - caddr_t data, int32_t count, int dir) +ata_promise_mio_dmastart(struct ata_channel *ch) { - int error; - - if ((error = ata_dmastart(ch, data, count, dir))) - return error; - ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab); ATA_IDX_OUTL(ch, ATA_BMCTL_PORT, (ATA_IDX_INL(ch, ATA_BMCTL_PORT) & ~0x000000c0) | - ((dir) ? 0x00000080 : 0x000000c0)); - return error; + ((ch->dma->flags & ATA_DMA_READ) ? 0x00000080 : 0x000000c0)); + return 0; } static int @@ -1434,7 +1425,7 @@ ata_promise_mio_dmastop(struct ata_channel *ch) { ATA_IDX_OUTL(ch, ATA_BMCTL_PORT, ATA_IDX_INL(ch, ATA_BMCTL_PORT) & ~0x00000080); - return ata_dmastop(ch); + return 0; } /* diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index d625ab1..a052f08 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -49,7 +49,8 @@ __FBSDID("$FreeBSD$"); static void ata_dmaalloc(struct ata_channel *); static void ata_dmafree(struct ata_channel *); static void ata_dmasetupd_cb(void *, bus_dma_segment_t *, int, int); -static int ata_dmasetup(struct ata_device *, caddr_t, int32_t); +static int ata_dmaload(struct ata_device *, caddr_t, int32_t, int); +static int ata_dmaunload(struct ata_channel *); /* local vars */ static MALLOC_DEFINE(M_ATADMA, "ATA DMA", "ATA driver DMA"); @@ -70,9 +71,8 @@ ata_dmainit(struct ata_channel *ch) if ((ch->dma = malloc(sizeof(struct ata_dma), M_ATADMA, M_NOWAIT|M_ZERO))) { ch->dma->alloc = ata_dmaalloc; ch->dma->free = ata_dmafree; - ch->dma->setup = ata_dmasetup; - ch->dma->start = ata_dmastart; - ch->dma->stop = ata_dmastop; + ch->dma->load = ata_dmaload; + ch->dma->unload = ata_dmaunload; ch->dma->alignment = 2; ch->dma->max_iosize = 64*1024; } @@ -194,38 +194,35 @@ ata_dmasetupd_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) } static int -ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count) +ata_dmaload(struct ata_device *atadev, caddr_t data, int32_t count, int dir) { struct ata_channel *ch = atadev->channel; + struct ata_dmasetup_data_cb_args cba; - if (((uintptr_t)data & (ch->dma->alignment - 1)) || - (count & (ch->dma->alignment - 1))) { - ata_prtdev(atadev, "FAILURE - non aligned DMA transfer attempted\n"); + if (ch->dma->flags & ATA_DMA_ACTIVE) { + ata_prtdev(atadev, "FAILURE - already active DMA on this device\n"); return -1; } if (!count) { ata_prtdev(atadev, "FAILURE - zero length DMA transfer attempted\n"); return -1; } + if (((uintptr_t)data & (ch->dma->alignment - 1)) || + (count & (ch->dma->alignment - 1))) { + ata_prtdev(atadev, "FAILURE - non aligned DMA transfer attempted\n"); + return -1; + } if (count > ch->dma->max_iosize) { ata_prtdev(atadev, "FAILURE - oversized DMA transfer attempted %d > %d\n", count, ch->dma->max_iosize); return -1; } - return 0; -} - -int -ata_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir) -{ - struct ata_dmasetup_data_cb_args cba; - - if (ch->dma->flags & ATA_DMA_ACTIVE) - panic("ata_dmasetup: transfer active on this device!"); cba.dmatab = ch->dma->dmatab; + bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_PREWRITE); + if (bus_dmamap_load(ch->dma->ddmatag, ch->dma->ddmamap, data, count, ata_dmasetupd_cb, &cba, 0) || cba.error) return -1; @@ -233,12 +230,14 @@ ata_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir) bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap, dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); + ch->dma->cur_iosize = count; ch->dma->flags = dir ? (ATA_DMA_ACTIVE | ATA_DMA_READ) : ATA_DMA_ACTIVE; + return 0; } int -ata_dmastop(struct ata_channel *ch) +ata_dmaunload(struct ata_channel *ch) { bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_POSTWRITE); @@ -247,6 +246,8 @@ ata_dmastop(struct ata_channel *ch) BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ch->dma->ddmatag, ch->dma->ddmamap); + ch->dma->cur_iosize = 0; ch->dma->flags = 0; + return 0; } diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index f4c8f0e..f6f8700 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -111,10 +111,11 @@ ata_transaction(struct ata_request *request) /* ATA DMA data transfer commands */ case ATA_R_DMA: - /* check sanity and setup DMA engine */ - if (request->device->channel->dma->setup(request->device, - request->data, - request->bytecount)) { + /* check sanity, setup SG list and DMA engine */ + if (request->device->channel->dma->load(request->device, + request->data, + request->bytecount, + request->flags & ATA_R_READ)) { ata_prtdev(request->device, "setting up DMA failed\n"); request->result = EIO; break; @@ -130,10 +131,7 @@ ata_transaction(struct ata_request *request) } /* start DMA engine */ - if (request->device->channel->dma->start(request->device->channel, - request->data, - request->bytecount, - request->flags & ATA_R_READ)) { + if (request->device->channel->dma->start(request->device->channel)) { ata_prtdev(request->device, "error starting DMA\n"); request->result = EIO; break; @@ -208,10 +206,11 @@ ata_transaction(struct ata_request *request) break; } - /* check sanity and setup DMA engine */ - if (request->device->channel->dma->setup(request->device, - request->data, - request->bytecount)) { + /* check sanity, setup SG list and DMA engine */ + if (request->device->channel->dma->load(request->device, + request->data, + request->bytecount, + request->flags & ATA_R_READ)) { ata_prtdev(request->device, "setting up DMA failed\n"); request->result = EIO; break; @@ -253,10 +252,7 @@ ata_transaction(struct ata_request *request) ATA_PROTO_ATAPI_12 ? 6 : 8); /* start DMA engine */ - if (request->device->channel->dma->start(request->device->channel, - request->data, - request->bytecount, - request->flags & ATA_R_READ)) { + if (request->device->channel->dma->start(request->device->channel)) { request->result = EIO; break; } @@ -373,6 +369,9 @@ ata_interrupt(void *data) else request->donecount = request->bytecount; + /* release SG list etc */ + ch->dma->unload(ch); + /* done with HW */ break; @@ -458,6 +457,7 @@ ata_interrupt(void *data) ata_prtdev(request->device, "unknown transfer phase\n"); request->status = ATA_S_ERROR; } + /* done with HW */ break; @@ -474,6 +474,9 @@ ata_interrupt(void *data) request->status |= ATA_S_ERROR; else request->donecount = request->bytecount; + + /* release SG list etc */ + ch->dma->unload(ch); /* done with HW */ break; @@ -481,7 +484,7 @@ ata_interrupt(void *data) ata_finish(request); - /* unlock the ATA HW for new work */ + /* unlock the ATA channel for new work */ ch->running = NULL; ATA_UNLOCK_CH(ch); ch->locking(ch, ATA_LF_UNLOCK); diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c index fb950d9..01ca793 100644 --- a/sys/dev/ata/ata-pci.c +++ b/sys/dev/ata/ata-pci.c @@ -411,17 +411,14 @@ ata_pci_allocate(device_t dev, struct ata_channel *ch) } static int -ata_pci_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir) +ata_pci_dmastart(struct ata_channel *ch) { - int error; - - if ((error = ata_dmastart(ch, data, count, dir))) - return error; ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->mdmatab); ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, - (dir ? ATA_BMCMD_WRITE_READ : 0) | ATA_BMCMD_START_STOP); + ((ch->dma->flags & ATA_DMA_READ) ? ATA_BMCMD_WRITE_READ : 0) | + ATA_BMCMD_START_STOP); return 0; } @@ -434,7 +431,6 @@ ata_pci_dmastop(struct ata_channel *ch) ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); - ata_dmastop(ch); return error; } |