summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/ata-dma.c
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2003-08-24 09:22:26 +0000
committersos <sos@FreeBSD.org>2003-08-24 09:22:26 +0000
commitacd43345e5181bc90912ee1da2b67fd9c3d9c7f6 (patch)
treefc8660c3fbead647641e9e7a6968b5a490dfd90f /sys/dev/ata/ata-dma.c
parent2b41ad87c9729efcb95d20102fb76ef2684cb633 (diff)
downloadFreeBSD-src-acd43345e5181bc90912ee1da2b67fd9c3d9c7f6.zip
FreeBSD-src-acd43345e5181bc90912ee1da2b67fd9c3d9c7f6.tar.gz
This is a major rework of the ATA driver (ATAng)
Restructure the way ATA/ATAPI commands are processed, use a common ata_request structure for both. This centralises the way requests are handled so locking is much easier to handle. The driver is now layered much more cleanly to seperate the lowlevel HW access so it can be tailored to specific controllers without touching the upper layers. This is needed to support some of the newer semi-intelligent ATA controllers showing up. The top level drivers (disk, ATAPI devices) are more or less still the same with just corrections to use the new interface. Pull ATA out from under Gaint now that locking can be done in a sane way. Add support for a the National Geode SC1100. Thanks to Soekris engineering for sponsoring a Soekris 4801 to make this support. Fixed alot of small bugs in the chipset code for various chips now we are around in that corner anyways.
Diffstat (limited to 'sys/dev/ata/ata-dma.c')
-rw-r--r--sys/dev/ata/ata-dma.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c
index 4dfff5a..a94bf18 100644
--- a/sys/dev/ata/ata-dma.c
+++ b/sys/dev/ata/ata-dma.c
@@ -36,10 +36,11 @@
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/taskqueue.h>
#include <sys/bus.h>
-#include <dev/pci/pcivar.h>
#include <machine/bus.h>
#include <sys/rman.h>
+#include <dev/pci/pcivar.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-pci.h>
@@ -67,7 +68,7 @@ int
ata_dmainit(struct ata_channel *ch)
{
if (!(ch->dma =
- malloc(sizeof(struct ata_dma_data), M_ATADMA, M_NOWAIT | M_ZERO)))
+ malloc(sizeof(struct ata_dma), M_ATADMA, M_NOWAIT | M_ZERO)))
return ENOMEM;
ch->dma->alloc = ata_dmaalloc;
ch->dma->free = ata_dmafree;
@@ -75,6 +76,7 @@ ata_dmainit(struct ata_channel *ch)
ch->dma->start = ata_dmastart;
ch->dma->stop = ata_dmastop;
ch->dma->alignment = 2;
+ ch->dma->max_iosize = 64*1024;
return 0;
}
@@ -98,9 +100,10 @@ ata_dmaalloc(struct ata_channel *ch)
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, busdma_lock_mutex,
- &Giant, &ch->dma->dmatag)) {
- printf("DMA tag allocation failed, disabling DMA\n");
+ BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL,
+ &ch->dma->dmatag)) {
+ ata_printf(ch, -1,
+ "WARNING - DMA tag allocation failed, disabling DMA\n");
}
}
if (!ch->dma->cdmatag) {
@@ -108,8 +111,8 @@ ata_dmaalloc(struct ata_channel *ch)
BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL,
MAXTABSZ, 1, MAXTABSZ,
- BUS_DMA_ALLOCNOW, busdma_lock_mutex,
- &Giant, &ch->dma->cdmatag)))
+ BUS_DMA_ALLOCNOW, NULL, NULL,
+ &ch->dma->cdmatag)))
return error;
}
if (!ch->dma->ddmatag) {
@@ -117,8 +120,8 @@ ata_dmaalloc(struct ata_channel *ch)
BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL,
MAXPHYS, ATA_DMA_ENTRIES, MAXSEGSZ,
- BUS_DMA_ALLOCNOW, busdma_lock_mutex,
- &Giant, &ch->dma->ddmatag)))
+ BUS_DMA_ALLOCNOW, NULL, NULL,
+ &ch->dma->ddmatag)))
return error;
}
if (!ch->dma->mdmatab) {
@@ -211,12 +214,17 @@ ata_dmasetup(struct ata_device *atadev, caddr_t data, int32_t count)
if (((uintptr_t)data & (ch->dma->alignment - 1)) ||
(count & (ch->dma->alignment - 1))) {
- ata_prtdev(atadev, "non aligned DMA transfer attempted\n");
+ ata_prtdev(atadev, "FAILURE - non aligned DMA transfer attempted\n");
return -1;
}
-
if (!count) {
- ata_prtdev(atadev, "zero length DMA transfer attempted\n");
+ ata_prtdev(atadev, "FAILURE - zero length 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;
@@ -232,12 +240,10 @@ ata_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir)
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;
- bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap,
dir ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
@@ -248,10 +254,13 @@ ata_dmastart(struct ata_channel *ch, caddr_t data, int32_t count, int dir)
int
ata_dmastop(struct ata_channel *ch)
{
+ bus_dmamap_sync(ch->dma->cdmatag, ch->dma->cdmamap, BUS_DMASYNC_POSTWRITE);
+
bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap,
(ch->dma->flags & ATA_DMA_READ) != 0 ?
BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ch->dma->ddmatag, ch->dma->ddmamap);
+
ch->dma->flags = 0;
return 0;
}
OpenPOWER on IntegriCloud