xref: /freebsd/sys/dev/ata/ata-dma.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
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