diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ata/ata-all.h | 15 | ||||
-rw-r--r-- | sys/dev/ata/ata-chipset.c | 9 | ||||
-rw-r--r-- | sys/dev/ata/ata-dma.c | 46 |
3 files changed, 31 insertions, 39 deletions
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 60698dfa..4065a81 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -272,12 +272,18 @@ struct ata_device { void (*setmode)(struct ata_device *atadev, int mode); }; -/* structure for holding DMA address data */ -struct ata_dmaentry { - u_int32_t base; +/* structure for holding DMA Physical Region Descriptors (PRD) entries */ +struct ata_dma_prdentry { + u_int32_t addr; u_int32_t count; }; +/* structure used by the setprd function */ +struct ata_dmasetprd_args { + void *dmatab; + int error; +}; + /* structure holding DMA related information */ struct ata_dma { bus_dma_tag_t dmatag; /* parent DMA tag */ @@ -285,7 +291,7 @@ struct ata_dma { bus_dmamap_t cdmamap; /* control DMA map */ bus_dma_tag_t ddmatag; /* data DMA tag */ bus_dmamap_t ddmamap; /* data DMA map */ - struct ata_dmaentry *dmatab; /* DMA transfer table */ + void *dmatab; /* DMA transfer table */ bus_addr_t mdmatab; /* bus address of dmatab */ bus_dma_tag_t wdmatag; /* workspace DMA tag */ bus_dmamap_t wdmamap; /* workspace DMA map */ @@ -303,6 +309,7 @@ struct ata_dma { void (*alloc)(struct ata_channel *ch); void (*free)(struct ata_channel *ch); + void (*setprd)(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); 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); diff --git a/sys/dev/ata/ata-chipset.c b/sys/dev/ata/ata-chipset.c index 8f9084c..be5c361 100644 --- a/sys/dev/ata/ata-chipset.c +++ b/sys/dev/ata/ata-chipset.c @@ -1532,6 +1532,7 @@ ata_promise_sx4_command(struct ata_device *atadev, u_int8_t command, u_int64_t lba, u_int16_t count, u_int16_t feature) { struct ata_channel *ch = atadev->channel; + struct ata_dma_prdentry *prd = ch->dma->dmatab; struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(ch->dev)); caddr_t window = rman_get_virtual(ctlr->r_res1); @@ -1564,10 +1565,10 @@ ata_promise_sx4_command(struct ata_device *atadev, u_int8_t command, (window + (ch->unit * ATA_PDC_CHN_OFFSET) + ATA_PDC_HSG_OFFSET); i = idx = 0; do { - wordp[idx++] = htole32(ch->dma->dmatab[i].base); - wordp[idx++] = htole32(ch->dma->dmatab[i].count & ~ATA_DMA_EOT); - length += (ch->dma->dmatab[i].count & ~ATA_DMA_EOT); - } while (!(ch->dma->dmatab[i++].count & ATA_DMA_EOT)); + wordp[idx++] = htole32(prd[i].addr); + wordp[idx++] = htole32(prd[i].count & ~ATA_DMA_EOT); + length += (prd[i].count & ~ATA_DMA_EOT); + } while (!(prd[i++].count & ATA_DMA_EOT)); wordp[idx - 1] |= htole32(ATA_DMA_EOT); wordp = (u_int32_t *) diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index 903dca1..cd719ee 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$"); /* prototypes */ 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 void ata_dmasetprd(void *, bus_dma_segment_t *, int, int); static int ata_dmaload(struct ata_device *, caddr_t, int32_t, int); static int ata_dmaunload(struct ata_channel *); @@ -57,7 +57,6 @@ static int ata_dmaunload(struct ata_channel *); static MALLOC_DEFINE(M_ATADMA, "ATA DMA", "ATA driver DMA"); /* misc defines */ -#define MAXSEGSZ PAGE_SIZE #define MAXTABSZ PAGE_SIZE #define MAXWSPCSZ PAGE_SIZE #define MAXCTLDMASZ (2 * (MAXTABSZ + MAXPHYS)) @@ -73,6 +72,7 @@ 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->setprd = ata_dmasetprd; ch->dma->load = ata_dmaload; ch->dma->unload = ata_dmaunload; ch->dma->alignment = 2; @@ -81,7 +81,6 @@ ata_dmainit(struct ata_channel *ch) } } - static void ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) { @@ -195,45 +194,30 @@ ata_dmafree(struct ata_channel *ch) } } -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) +ata_dmasetprd(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) + struct ata_dmasetprd_args *args = xsc; + struct ata_dma_prdentry *prd = args->dmatab; + int i; + + if ((args->error = error)) 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); - } + prd[i].addr = htole32(segs[i].ds_addr); + prd[i].count = htole32(segs[i].ds_len); } - cba->dmatab[j - 1].count = htole32(lastcount | ATA_DMA_EOT); + prd[i - 1].count |= htole32(ATA_DMA_EOT); } static int 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; + struct ata_dmasetprd_args cba; - if (ch->dma->flags & ATA_DMA_ACTIVE) { + if (ch->dma->flags & ATA_DMA_LOADED) { ata_prtdev(atadev, "FAILURE - already active DMA on this device\n"); return -1; } @@ -258,7 +242,7 @@ ata_dmaload(struct ata_device *atadev, caddr_t data, int32_t count, int dir) 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) + ch->dma->setprd, &cba, 0) || cba.error) return -1; bus_dmamap_sync(ch->dma->ddmatag, ch->dma->ddmamap, |