155bfaed1SSøren Schmidt /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
49a14aa01SUlrich Spörlein * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org>
555bfaed1SSøren Schmidt * All rights reserved.
655bfaed1SSøren Schmidt *
755bfaed1SSøren Schmidt * Redistribution and use in source and binary forms, with or without
855bfaed1SSøren Schmidt * modification, are permitted provided that the following conditions
955bfaed1SSøren Schmidt * are met:
1055bfaed1SSøren Schmidt * 1. Redistributions of source code must retain the above copyright
1155bfaed1SSøren Schmidt * notice, this list of conditions and the following disclaimer,
1255bfaed1SSøren Schmidt * without modification, immediately at the beginning of the file.
1355bfaed1SSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright
1455bfaed1SSøren Schmidt * notice, this list of conditions and the following disclaimer in the
1555bfaed1SSøren Schmidt * documentation and/or other materials provided with the distribution.
1655bfaed1SSøren Schmidt *
1755bfaed1SSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1855bfaed1SSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1955bfaed1SSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2055bfaed1SSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2155bfaed1SSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2255bfaed1SSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2355bfaed1SSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2455bfaed1SSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2555bfaed1SSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2655bfaed1SSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2755bfaed1SSøren Schmidt */
2855bfaed1SSøren Schmidt
2955bfaed1SSøren Schmidt #include <sys/param.h>
3055bfaed1SSøren Schmidt #include <sys/systm.h>
31a2dca80aSSøren Schmidt #include <sys/ata.h>
32bb5bdd38SSøren Schmidt #include <sys/kernel.h>
33a30d4b32SMike Barcroft #include <sys/endian.h>
3455bfaed1SSøren Schmidt #include <sys/malloc.h>
35f6b1c44dSScott Long #include <sys/lock.h>
36a7a120f6SSøren Schmidt #include <sys/sema.h>
375fdbb0d2SSøren Schmidt #include <sys/taskqueue.h>
385df3ca78SSøren Schmidt #include <vm/uma.h>
39f1cb6ca3SSøren Schmidt #include <sys/bus.h>
4021c3015aSDoug Rabson #include <machine/bus.h>
41b17f7a1aSSøren Schmidt #include <sys/rman.h>
42c50cf4acSSøren Schmidt #include <dev/ata/ata-all.h>
4355bfaed1SSøren Schmidt
442b0a1c08SSøren Schmidt /* prototypes */
45104c094eSSøren Schmidt static void ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
469f82379cSSøren Schmidt static void ata_dmaalloc(device_t dev);
479f82379cSSøren Schmidt static void ata_dmafree(device_t dev);
489f82379cSSøren Schmidt static void ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
499f82379cSSøren Schmidt static int ata_dmaload(struct ata_request *request, void *addr, int *nsegs);
509f82379cSSøren Schmidt static int ata_dmaunload(struct ata_request *request);
51bb5bdd38SSøren Schmidt
52bb5bdd38SSøren Schmidt /* local vars */
535bb84bc8SRobert Watson static MALLOC_DEFINE(M_ATADMA, "ata_dma", "ATA driver DMA");
542b0a1c08SSøren Schmidt
552b0a1c08SSøren Schmidt /* misc defines */
567800211bSSøren Schmidt #define MAXTABSZ PAGE_SIZE
570068f98fSSøren Schmidt #define MAXWSPCSZ PAGE_SIZE*2
587800211bSSøren Schmidt
597800211bSSøren Schmidt struct ata_dc_cb_args {
607800211bSSøren Schmidt bus_addr_t maddr;
617800211bSSøren Schmidt int error;
627800211bSSøren Schmidt };
637800211bSSøren Schmidt
646419d0b0SSøren Schmidt void
ata_dmainit(device_t dev)650068f98fSSøren Schmidt ata_dmainit(device_t dev)
66bb5bdd38SSøren Schmidt {
670068f98fSSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
68104c094eSSøren Schmidt struct ata_dc_cb_args dcba;
690068f98fSSøren Schmidt
701510a2b0SMarius Strobl if (ch->dma.alloc == NULL)
719f82379cSSøren Schmidt ch->dma.alloc = ata_dmaalloc;
721510a2b0SMarius Strobl if (ch->dma.free == NULL)
739f82379cSSøren Schmidt ch->dma.free = ata_dmafree;
741510a2b0SMarius Strobl if (ch->dma.setprd == NULL)
759f82379cSSøren Schmidt ch->dma.setprd = ata_dmasetprd;
761510a2b0SMarius Strobl if (ch->dma.load == NULL)
779f82379cSSøren Schmidt ch->dma.load = ata_dmaload;
781510a2b0SMarius Strobl if (ch->dma.unload == NULL)
799f82379cSSøren Schmidt ch->dma.unload = ata_dmaunload;
801510a2b0SMarius Strobl if (ch->dma.alignment == 0)
819f82379cSSøren Schmidt ch->dma.alignment = 2;
821510a2b0SMarius Strobl if (ch->dma.boundary == 0)
839f82379cSSøren Schmidt ch->dma.boundary = 65536;
841510a2b0SMarius Strobl if (ch->dma.segsize == 0)
8503befed8SJohn Baldwin ch->dma.segsize = 65536;
861510a2b0SMarius Strobl if (ch->dma.max_iosize == 0)
87cd853791SKonstantin Belousov ch->dma.max_iosize = (ATA_DMA_ENTRIES - 1) * PAGE_SIZE;
881510a2b0SMarius Strobl if (ch->dma.max_address == 0)
899f82379cSSøren Schmidt ch->dma.max_address = BUS_SPACE_MAXADDR_32BIT;
901510a2b0SMarius Strobl if (ch->dma.dma_slots == 0)
91ebbb35baSAlexander Motin ch->dma.dma_slots = 1;
92104c094eSSøren Schmidt
93104c094eSSøren Schmidt if (bus_dma_tag_create(bus_get_dma_tag(dev), ch->dma.alignment, 0,
94104c094eSSøren Schmidt ch->dma.max_address, BUS_SPACE_MAXADDR,
95104c094eSSøren Schmidt NULL, NULL, ch->dma.max_iosize,
96104c094eSSøren Schmidt ATA_DMA_ENTRIES, ch->dma.segsize,
97104c094eSSøren Schmidt 0, NULL, NULL, &ch->dma.dmatag))
98104c094eSSøren Schmidt goto error;
99104c094eSSøren Schmidt
100104c094eSSøren Schmidt if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, 64 * 1024,
101104c094eSSøren Schmidt ch->dma.max_address, BUS_SPACE_MAXADDR,
102104c094eSSøren Schmidt NULL, NULL, MAXWSPCSZ, 1, MAXWSPCSZ,
103104c094eSSøren Schmidt 0, NULL, NULL, &ch->dma.work_tag))
104104c094eSSøren Schmidt goto error;
105104c094eSSøren Schmidt
1061ae5318fSMarius Strobl if (bus_dmamem_alloc(ch->dma.work_tag, (void **)&ch->dma.work,
1071ae5318fSMarius Strobl BUS_DMA_WAITOK | BUS_DMA_COHERENT,
108104c094eSSøren Schmidt &ch->dma.work_map))
109104c094eSSøren Schmidt goto error;
110104c094eSSøren Schmidt
111104c094eSSøren Schmidt if (bus_dmamap_load(ch->dma.work_tag, ch->dma.work_map, ch->dma.work,
112104c094eSSøren Schmidt MAXWSPCSZ, ata_dmasetupc_cb, &dcba, 0) ||
113104c094eSSøren Schmidt dcba.error) {
114104c094eSSøren Schmidt bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
115104c094eSSøren Schmidt goto error;
116104c094eSSøren Schmidt }
117104c094eSSøren Schmidt ch->dma.work_bus = dcba.maddr;
118104c094eSSøren Schmidt return;
119104c094eSSøren Schmidt
120104c094eSSøren Schmidt error:
121104c094eSSøren Schmidt device_printf(dev, "WARNING - DMA initialization failed, disabling DMA\n");
122104c094eSSøren Schmidt ata_dmafini(dev);
123104c094eSSøren Schmidt }
124104c094eSSøren Schmidt
125104c094eSSøren Schmidt void
ata_dmafini(device_t dev)126104c094eSSøren Schmidt ata_dmafini(device_t dev)
127104c094eSSøren Schmidt {
128104c094eSSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
129104c094eSSøren Schmidt
130104c094eSSøren Schmidt if (ch->dma.work_bus) {
131104c094eSSøren Schmidt bus_dmamap_unload(ch->dma.work_tag, ch->dma.work_map);
132104c094eSSøren Schmidt bus_dmamem_free(ch->dma.work_tag, ch->dma.work, ch->dma.work_map);
133104c094eSSøren Schmidt ch->dma.work_bus = 0;
134104c094eSSøren Schmidt ch->dma.work = NULL;
135104c094eSSøren Schmidt }
136104c094eSSøren Schmidt if (ch->dma.work_tag) {
137104c094eSSøren Schmidt bus_dma_tag_destroy(ch->dma.work_tag);
138104c094eSSøren Schmidt ch->dma.work_tag = NULL;
139104c094eSSøren Schmidt }
140104c094eSSøren Schmidt if (ch->dma.dmatag) {
141104c094eSSøren Schmidt bus_dma_tag_destroy(ch->dma.dmatag);
142104c094eSSøren Schmidt ch->dma.dmatag = NULL;
143104c094eSSøren Schmidt }
144bb5bdd38SSøren Schmidt }
145bb5bdd38SSøren Schmidt
1467800211bSSøren Schmidt static void
ata_dmasetupc_cb(void * xsc,bus_dma_segment_t * segs,int nsegs,int error)1477800211bSSøren Schmidt ata_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
1488563f77dSSøren Schmidt {
1499f82379cSSøren Schmidt struct ata_dc_cb_args *dcba = (struct ata_dc_cb_args *)xsc;
1508563f77dSSøren Schmidt
1519f82379cSSøren Schmidt if (!(dcba->error = error))
1529f82379cSSøren Schmidt dcba->maddr = segs[0].ds_addr;
1538563f77dSSøren Schmidt }
1547800211bSSøren Schmidt
1556419d0b0SSøren Schmidt static void
ata_dmaalloc(device_t dev)1560068f98fSSøren Schmidt ata_dmaalloc(device_t dev)
1577800211bSSøren Schmidt {
1580068f98fSSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
1599f82379cSSøren Schmidt struct ata_dc_cb_args dcba;
160104c094eSSøren Schmidt int i;
1617800211bSSøren Schmidt
162104c094eSSøren Schmidt /* alloc and setup needed dma slots */
163104c094eSSøren Schmidt bzero(ch->dma.slot, sizeof(struct ata_dmaslot) * ATA_DMA_SLOTS);
164104c094eSSøren Schmidt for (i = 0; i < ch->dma.dma_slots; i++) {
165104c094eSSøren Schmidt struct ata_dmaslot *slot = &ch->dma.slot[i];
166104c094eSSøren Schmidt
167104c094eSSøren Schmidt if (bus_dma_tag_create(ch->dma.dmatag, PAGE_SIZE, PAGE_SIZE,
168104c094eSSøren Schmidt ch->dma.max_address, BUS_SPACE_MAXADDR,
169104c094eSSøren Schmidt NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE,
170104c094eSSøren Schmidt 0, NULL, NULL, &slot->sg_tag)) {
171104c094eSSøren Schmidt device_printf(ch->dev, "FAILURE - create sg_tag\n");
172104c094eSSøren Schmidt goto error;
173104c094eSSøren Schmidt }
174104c094eSSøren Schmidt
1751ae5318fSMarius Strobl if (bus_dmamem_alloc(slot->sg_tag, (void **)&slot->sg, BUS_DMA_WAITOK,
1761ae5318fSMarius Strobl &slot->sg_map)) {
177104c094eSSøren Schmidt device_printf(ch->dev, "FAILURE - alloc sg_map\n");
178104c094eSSøren Schmidt goto error;
179104c094eSSøren Schmidt }
180104c094eSSøren Schmidt
181104c094eSSøren Schmidt if (bus_dmamap_load(slot->sg_tag, slot->sg_map, slot->sg, MAXTABSZ,
182104c094eSSøren Schmidt ata_dmasetupc_cb, &dcba, 0) || dcba.error) {
183104c094eSSøren Schmidt device_printf(ch->dev, "FAILURE - load sg\n");
184104c094eSSøren Schmidt goto error;
185104c094eSSøren Schmidt }
186104c094eSSøren Schmidt slot->sg_bus = dcba.maddr;
187104c094eSSøren Schmidt
188104c094eSSøren Schmidt if (bus_dma_tag_create(ch->dma.dmatag,
189104c094eSSøren Schmidt ch->dma.alignment, ch->dma.boundary,
190104c094eSSøren Schmidt ch->dma.max_address, BUS_SPACE_MAXADDR,
191104c094eSSøren Schmidt NULL, NULL, ch->dma.max_iosize,
192104c094eSSøren Schmidt ATA_DMA_ENTRIES, ch->dma.segsize,
193104c094eSSøren Schmidt BUS_DMA_ALLOCNOW, NULL, NULL, &slot->data_tag)) {
194104c094eSSøren Schmidt device_printf(ch->dev, "FAILURE - create data_tag\n");
195104c094eSSøren Schmidt goto error;
196104c094eSSøren Schmidt }
197104c094eSSøren Schmidt
198104c094eSSøren Schmidt if (bus_dmamap_create(slot->data_tag, 0, &slot->data_map)) {
199104c094eSSøren Schmidt device_printf(ch->dev, "FAILURE - create data_map\n");
200104c094eSSøren Schmidt goto error;
201104c094eSSøren Schmidt }
202104c094eSSøren Schmidt }
203104c094eSSøren Schmidt
2046419d0b0SSøren Schmidt return;
2056419d0b0SSøren Schmidt
2066419d0b0SSøren Schmidt error:
2070068f98fSSøren Schmidt device_printf(dev, "WARNING - DMA allocation failed, disabling DMA\n");
2080068f98fSSøren Schmidt ata_dmafree(dev);
2098563f77dSSøren Schmidt }
2108563f77dSSøren Schmidt
211bb5bdd38SSøren Schmidt static void
ata_dmafree(device_t dev)2120068f98fSSøren Schmidt ata_dmafree(device_t dev)
21355bfaed1SSøren Schmidt {
2140068f98fSSøren Schmidt struct ata_channel *ch = device_get_softc(dev);
215104c094eSSøren Schmidt int i;
2160068f98fSSøren Schmidt
217104c094eSSøren Schmidt /* free all dma slots */
218104c094eSSøren Schmidt for (i = 0; i < ATA_DMA_SLOTS; i++) {
219104c094eSSøren Schmidt struct ata_dmaslot *slot = &ch->dma.slot[i];
220104c094eSSøren Schmidt
221104c094eSSøren Schmidt if (slot->sg_bus) {
222104c094eSSøren Schmidt bus_dmamap_unload(slot->sg_tag, slot->sg_map);
223104c094eSSøren Schmidt slot->sg_bus = 0;
224f2972d7eSSøren Schmidt }
225f07894dbSJohn Baldwin if (slot->sg) {
226104c094eSSøren Schmidt bus_dmamem_free(slot->sg_tag, slot->sg, slot->sg_map);
227104c094eSSøren Schmidt slot->sg = NULL;
228f2972d7eSSøren Schmidt }
229104c094eSSøren Schmidt if (slot->data_map) {
230104c094eSSøren Schmidt bus_dmamap_destroy(slot->data_tag, slot->data_map);
231104c094eSSøren Schmidt slot->data_map = NULL;
232104c094eSSøren Schmidt }
233104c094eSSøren Schmidt if (slot->sg_tag) {
234104c094eSSøren Schmidt bus_dma_tag_destroy(slot->sg_tag);
235104c094eSSøren Schmidt slot->sg_tag = NULL;
236104c094eSSøren Schmidt }
237104c094eSSøren Schmidt if (slot->data_tag) {
238104c094eSSøren Schmidt bus_dma_tag_destroy(slot->data_tag);
239104c094eSSøren Schmidt slot->data_tag = NULL;
240104c094eSSøren Schmidt }
2417800211bSSøren Schmidt }
2427800211bSSøren Schmidt }
2437800211bSSøren Schmidt
2447800211bSSøren Schmidt static void
ata_dmasetprd(void * xsc,bus_dma_segment_t * segs,int nsegs,int error)2458b68793aSSøren Schmidt ata_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
24655bfaed1SSøren Schmidt {
2478b68793aSSøren Schmidt struct ata_dmasetprd_args *args = xsc;
2488b68793aSSøren Schmidt struct ata_dma_prdentry *prd = args->dmatab;
2498b68793aSSøren Schmidt int i;
2507800211bSSøren Schmidt
2518b68793aSSøren Schmidt if ((args->error = error))
2527800211bSSøren Schmidt return;
2538b68793aSSøren Schmidt
2547800211bSSøren Schmidt for (i = 0; i < nsegs; i++) {
2558b68793aSSøren Schmidt prd[i].addr = htole32(segs[i].ds_addr);
2568b68793aSSøren Schmidt prd[i].count = htole32(segs[i].ds_len);
2577800211bSSøren Schmidt }
2588b68793aSSøren Schmidt prd[i - 1].count |= htole32(ATA_DMA_EOT);
2592f3ad9baSKevin Lo KASSERT(nsegs <= ATA_DMA_ENTRIES, ("too many DMA segment entries\n"));
260eeda55ceSSøren Schmidt args->nsegs = nsegs;
2617800211bSSøren Schmidt }
2627800211bSSøren Schmidt
263bb5bdd38SSøren Schmidt static int
ata_dmaload(struct ata_request * request,void * addr,int * entries)2649f82379cSSøren Schmidt ata_dmaload(struct ata_request *request, void *addr, int *entries)
2657800211bSSøren Schmidt {
2669f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(request->parent);
2679f82379cSSøren Schmidt struct ata_dmasetprd_args dspa;
268b39424baSSøren Schmidt int error;
26955bfaed1SSøren Schmidt
2709f82379cSSøren Schmidt ATA_DEBUG_RQ(request, "dmaload");
2719f82379cSSøren Schmidt
272104c094eSSøren Schmidt if (request->dma) {
273ebbb35baSAlexander Motin device_printf(request->parent,
2749f82379cSSøren Schmidt "FAILURE - already active DMA on this device\n");
275b39424baSSøren Schmidt return EIO;
2768563f77dSSøren Schmidt }
2779f82379cSSøren Schmidt if (!request->bytecount) {
278ebbb35baSAlexander Motin device_printf(request->parent,
2799f82379cSSøren Schmidt "FAILURE - zero length DMA transfer attempted\n");
280b39424baSSøren Schmidt return EIO;
2815fdbb0d2SSøren Schmidt }
2824b861b15SAlexander Motin if (request->bytecount & (ch->dma.alignment - 1)) {
283ebbb35baSAlexander Motin device_printf(request->parent,
2844b861b15SAlexander Motin "FAILURE - odd-sized DMA transfer attempt %d %% %d\n",
2854b861b15SAlexander Motin request->bytecount, ch->dma.alignment);
286b39424baSSøren Schmidt return EIO;
28780344be5SSøren Schmidt }
2889f82379cSSøren Schmidt if (request->bytecount > ch->dma.max_iosize) {
289ebbb35baSAlexander Motin device_printf(request->parent,
2909f82379cSSøren Schmidt "FAILURE - oversized DMA transfer attempt %d > %d\n",
2919f82379cSSøren Schmidt request->bytecount, ch->dma.max_iosize);
292b39424baSSøren Schmidt return EIO;
29355bfaed1SSøren Schmidt }
294091a610aSSøren Schmidt
295ebbb35baSAlexander Motin /* set our slot. XXX SOS NCQ will change that */
296ebbb35baSAlexander Motin request->dma = &ch->dma.slot[0];
297091a610aSSøren Schmidt
2989f82379cSSøren Schmidt if (addr)
2999f82379cSSøren Schmidt dspa.dmatab = addr;
3009f82379cSSøren Schmidt else
301104c094eSSøren Schmidt dspa.dmatab = request->dma->sg;
3029f82379cSSøren Schmidt
303512a3aa0SAlexander Motin if (request->flags & ATA_R_DATA_IN_CCB)
304dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(request->dma->data_tag,
305dd0b4fb6SKonstantin Belousov request->dma->data_map, request->ccb,
306dd0b4fb6SKonstantin Belousov ch->dma.setprd, &dspa, BUS_DMA_NOWAIT);
307dd0b4fb6SKonstantin Belousov else
308dd0b4fb6SKonstantin Belousov error = bus_dmamap_load(request->dma->data_tag, request->dma->data_map,
3099f82379cSSøren Schmidt request->data, request->bytecount,
310dd0b4fb6SKonstantin Belousov ch->dma.setprd, &dspa, BUS_DMA_NOWAIT);
311dd0b4fb6SKonstantin Belousov if (error || (error = dspa.error)) {
312ebbb35baSAlexander Motin device_printf(request->parent, "FAILURE - load data\n");
3139f82379cSSøren Schmidt goto error;
3149f82379cSSøren Schmidt }
3159f82379cSSøren Schmidt
3169f82379cSSøren Schmidt if (entries)
3179f82379cSSøren Schmidt *entries = dspa.nsegs;
3189f82379cSSøren Schmidt
319104c094eSSøren Schmidt bus_dmamap_sync(request->dma->sg_tag, request->dma->sg_map,
3209f82379cSSøren Schmidt BUS_DMASYNC_PREWRITE);
321104c094eSSøren Schmidt bus_dmamap_sync(request->dma->data_tag, request->dma->data_map,
3229f82379cSSøren Schmidt (request->flags & ATA_R_READ) ?
3239f82379cSSøren Schmidt BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
324091a610aSSøren Schmidt return 0;
3259f82379cSSøren Schmidt
3269f82379cSSøren Schmidt error:
3279f82379cSSøren Schmidt ata_dmaunload(request);
3289f82379cSSøren Schmidt return EIO;
32955bfaed1SSøren Schmidt }
33055bfaed1SSøren Schmidt
3318563f77dSSøren Schmidt int
ata_dmaunload(struct ata_request * request)3329f82379cSSøren Schmidt ata_dmaunload(struct ata_request *request)
33355bfaed1SSøren Schmidt {
3349f82379cSSøren Schmidt ATA_DEBUG_RQ(request, "dmaunload");
335eeda55ceSSøren Schmidt
336104c094eSSøren Schmidt if (request->dma) {
337104c094eSSøren Schmidt bus_dmamap_sync(request->dma->sg_tag, request->dma->sg_map,
338eeda55ceSSøren Schmidt BUS_DMASYNC_POSTWRITE);
339104c094eSSøren Schmidt bus_dmamap_sync(request->dma->data_tag, request->dma->data_map,
3409f82379cSSøren Schmidt (request->flags & ATA_R_READ) ?
3417800211bSSøren Schmidt BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
3425fdbb0d2SSøren Schmidt
343104c094eSSøren Schmidt bus_dmamap_unload(request->dma->data_tag, request->dma->data_map);
344104c094eSSøren Schmidt request->dma = NULL;
3459f82379cSSøren Schmidt }
346566cf07aSSøren Schmidt return 0;
34755bfaed1SSøren Schmidt }
348