No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / ieee1394 / fwdma.c
blobe1504b0710df4cd5412f6de98c74d571b42000e9
1 /* $NetBSD: fwdma.c,v 1.11 2007/12/11 11:34:08 lukem Exp $ */
2 /*-
3 * Copyright (c) 2003
4 * Hidetoshi Shimokawa. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
17 * This product includes software developed by Hidetoshi Shimokawa.
19 * 4. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: fwdma.c,v 1.11 2007/12/11 11:34:08 lukem Exp $");
39 #if defined(__FreeBSD__)
40 __FBSDID("$FreeBSD: src/sys/dev/firewire/fwdma.c,v 1.9 2007/06/06 14:31:36 simokawa Exp $");
41 #endif
43 #if defined(__FreeBSD__)
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/types.h>
47 #include <sys/kernel.h>
48 #include <sys/conf.h>
49 #include <sys/malloc.h>
50 #if defined(__FreeBSD__) && __FreeBSD_version >= 501102
51 #include <sys/mutex.h>
52 #endif
54 #include <sys/bus.h>
55 #include <sys/bus.h>
57 #ifdef __DragonFly__
58 #include <bus/firewire/fw_port.h>
59 #include <bus/firewire/firewire.h>
60 #include <bus/firewire/firewirereg.h>
61 #include <bus/firewire/fwdma.h>
62 #else
63 #include <dev/firewire/fw_port.h>
64 #include <dev/firewire/firewire.h>
65 #include <dev/firewire/firewirereg.h>
66 #include <dev/firewire/fwdma.h>
67 #endif
68 #elif defined(__NetBSD__)
69 #include <sys/param.h>
70 #include <sys/device.h>
71 #include <sys/systm.h>
72 #include <sys/types.h>
73 #include <sys/kernel.h>
74 #include <sys/malloc.h>
76 #include <sys/bus.h>
78 #include <dev/ieee1394/fw_port.h>
79 #include <dev/ieee1394/firewire.h>
80 #include <dev/ieee1394/firewirereg.h>
81 #include <dev/ieee1394/fwdma.h>
82 #endif
84 static void
85 fwdma_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
87 bus_addr_t *baddr;
89 if (error)
90 printf("fwdma_map_cb: error=%d\n", error);
91 baddr = (bus_addr_t *)arg;
92 *baddr = segs->ds_addr;
95 void *
96 fwdma_malloc(struct firewire_comm *fc, int alignment, bus_size_t size,
97 struct fwdma_alloc *dma, int flag)
99 int err;
101 dma->v_addr = NULL;
102 err = fw_bus_dma_tag_create(
103 /*parent*/ fc->dmat,
104 /*alignment*/ alignment,
105 /*boundary*/ 0,
106 /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT,
107 /*highaddr*/ BUS_SPACE_MAXADDR,
108 /*filter*/NULL, /*filterarg*/NULL,
109 /*maxsize*/ size,
110 /*nsegments*/ 1,
111 /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT,
112 /*flags*/ BUS_DMA_ALLOCNOW,
113 /*lockfunc*/busdma_lock_mutex,
114 /*lockarg*/FW_GMTX(fc),
115 &dma->fw_dma_tag);
116 if (err) {
117 printf("fwdma_malloc: failed(1)\n");
118 return(NULL);
121 err = fw_bus_dmamem_alloc(dma->fw_dma_tag, &dma->v_addr,
122 flag, &dma->dma_map);
123 if (err) {
124 printf("fwdma_malloc: failed(2)\n");
125 fw_bus_dma_tag_destroy(dma->fw_dma_tag);
126 return(NULL);
129 err = fw_bus_dmamap_load(dma->fw_dma_tag, dma->dma_map, dma->v_addr,
130 size, fwdma_map_cb, &dma->bus_addr, flag);
131 if (err != 0) {
132 printf("fwdma_malloc: failed(3)\n");
133 fw_bus_dmamem_free(dma->fw_dma_tag, dma->v_addr, dma->dma_map);
134 fw_bus_dma_tag_destroy(dma->fw_dma_tag);
135 return(NULL);
138 return(dma->v_addr);
141 void
142 fwdma_free(struct firewire_comm *fc, struct fwdma_alloc *dma)
144 fw_bus_dmamap_unload(dma->fw_dma_tag, dma->dma_map);
145 fw_bus_dmamem_free(dma->fw_dma_tag, dma->v_addr, dma->dma_map);
146 fw_bus_dma_tag_destroy(dma->fw_dma_tag);
150 void *
151 fwdma_malloc_size(fw_bus_dma_tag_t dmat, bus_dmamap_t *dmamap,
152 bus_size_t size, bus_addr_t *bus_addr, int flag)
154 void *v_addr;
156 if (fw_bus_dmamem_alloc(dmat, &v_addr, flag, dmamap)) {
157 printf("fwdma_malloc_size: failed(1)\n");
158 return(NULL);
160 if (fw_bus_dmamap_load(dmat, *dmamap, v_addr, size,
161 fwdma_map_cb, bus_addr, flag)) {
162 printf("fwdma_malloc_size: failed(2)\n");
163 fw_bus_dmamem_free(dmat, v_addr, *dmamap);
164 return(NULL);
166 return(v_addr);
169 void
170 fwdma_free_size(fw_bus_dma_tag_t dmat, bus_dmamap_t dmamap, void *vaddr,
171 bus_size_t size)
173 fw_bus_dmamap_unload(dmat, dmamap);
174 fw_bus_dmamem_free(dmat, vaddr, dmamap);
178 * Allocate multisegment dma buffers
179 * each segment size is eqaul to ssize except last segment.
181 struct fwdma_alloc_multi *
182 fwdma_malloc_multiseg(struct firewire_comm *fc, int alignment,
183 int esize, int n, int flag)
185 struct fwdma_alloc_multi *am;
186 struct fwdma_seg *seg;
187 bus_size_t ssize;
188 int nseg, size;
190 if (esize > PAGE_SIZE) {
191 /* round up to PAGE_SIZE */
192 esize = ssize = roundup2(esize, PAGE_SIZE);
193 nseg = n;
194 } else {
195 /* allocate PAGE_SIZE segment for small elements */
196 ssize = rounddown(PAGE_SIZE, esize);
197 nseg = howmany(n, ssize / esize);
199 size = sizeof (struct fwdma_alloc_multi) +
200 sizeof (struct fwdma_seg) * nseg;
201 am = (struct fwdma_alloc_multi *)malloc(size, M_FW, M_WAITOK);
202 if (am == NULL) {
203 printf("fwdma_malloc_multiseg: malloc failed\n");
204 return(NULL);
206 memset(am, 0, size);
207 am->ssize = ssize;
208 am->esize = esize;
209 am->nseg = 0;
210 if (fw_bus_dma_tag_create(
211 /*parent*/ fc->dmat,
212 /*alignment*/ alignment,
213 /*boundary*/ 0,
214 /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT,
215 /*highaddr*/ BUS_SPACE_MAXADDR,
216 /*filter*/NULL, /*filterarg*/NULL,
217 /*maxsize*/ ssize,
218 /*nsegments*/ 1,
219 /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT,
220 /*flags*/ BUS_DMA_ALLOCNOW,
221 /*lockfunc*/busdma_lock_mutex,
222 /*lockarg*/FW_GMTX(fc),
223 &am->fw_dma_tag)) {
224 printf("fwdma_malloc_multiseg: tag_create failed\n");
225 free(am, M_FW);
226 return(NULL);
229 #if 0
230 #if defined(__DragonFly__) || __FreeBSD_version < 500000
231 printf("malloc_multi: ssize=%d nseg=%d\n", ssize, nseg);
232 #else
233 printf("malloc_multi: ssize=%td nseg=%d\n", ssize, nseg);
234 #endif
235 #endif
236 for (seg = &am->seg[0]; nseg --; seg ++) {
237 seg->v_addr = fwdma_malloc_size(am->fw_dma_tag, &seg->dma_map,
238 ssize, &seg->bus_addr, flag);
239 if (seg->v_addr == NULL) {
240 printf("fwdma_malloc_multi: malloc_size failed %d\n",
241 am->nseg);
242 fwdma_free_multiseg(am);
243 return(NULL);
245 am->nseg++;
247 return(am);
250 void
251 fwdma_free_multiseg(struct fwdma_alloc_multi *am)
253 struct fwdma_seg *seg;
255 for (seg = &am->seg[0]; am->nseg --; seg ++) {
256 fwdma_free_size(am->fw_dma_tag, seg->dma_map,
257 seg->v_addr, am->ssize);
259 fw_bus_dma_tag_destroy(am->fw_dma_tag);
260 free(am, M_FW);