usb_mem.h revision 1.23.32.4 1 /* $NetBSD: usb_mem.h,v 1.23.32.4 2008/05/21 05:03:48 itohy Exp $ */
2 /* $FreeBSD: src/sys/dev/usb/usb_mem.h,v 1.21 2005/01/06 01:43:29 imp Exp $ */
3
4 /*-
5 * Copyright (c) 1998, 2007 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (lennart (at) augustsson.net) at
10 * Carlstedt Research & Technology.
11 *
12 * This code is derived from software contributed to The NetBSD Foundation
13 * by ITOH Yasufumi (itohy (at) NetBSD.org).
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. All advertising materials mentioning features or use of this software
24 * must display the following acknowledgement:
25 * This product includes software developed by the NetBSD
26 * Foundation, Inc. and its contributors.
27 * 4. Neither the name of The NetBSD Foundation nor the names of its
28 * contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
32 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
33 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
34 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
35 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
42 */
43
44 /* track memory allocation/free */
45 #define USBMEM_DEBUG
46
47 #define USB_DMA_NSEG (btoc(MAXPHYS) + 1)
48
49 typedef struct usb_dma_block {
50 #ifdef __FreeBSD__
51 bus_dma_tag_t tag;
52 #endif
53 bus_dmamap_t map;
54 usb_busdma_kaddr_t kaddr;
55 bus_dma_segment_t segs[1];
56 int nsegs;
57 size_t size;
58 size_t align;
59 int flags;
60 #define USB_DMA_FULLBLOCK 0x0001
61 #define USB_DMA_MARKED_TO_FREE 0x0002
62 LIST_ENTRY(usb_dma_block) next;
63 #ifdef USBMEM_DEBUG
64 TAILQ_ENTRY(usb_dma_block) b_debug_next;
65 const char *b_fn;
66 int b_ln;
67 #endif
68 } usb_dma_block_t;
69
70 #if defined(__NetBSD__) || defined(__OpenBSD__)
71 #define DMAADDR(dma, o) \
72 ((dma)->block->map->dm_segs[0].ds_addr + (dma)->offs + (o))
73 #define USB_MEM_SYNC(utag, dma, ops) \
74 bus_dmamap_sync((utag)->tag, (dma)->block->map, \
75 (dma)->offs, (dma)->len, (ops))
76 #define USB_MEM_SYNC2(utag, dma, off, len, ops) \
77 bus_dmamap_sync((utag)->tag, (dma)->block->map, \
78 (dma)->offs + (off), (len), (ops))
79 #elif defined(__FreeBSD__)
80 #define DMAADDR(dma, o) \
81 ((dma)->block->segs[0].ds_addr + (dma)->offs + (o))
82 /*
83 * XXX overkill
84 * FreeBSD can't sync map partially
85 */
86 #define USB_MEM_SYNC(utag, dma, ops) \
87 bus_dmamap_sync((dma)->block->tag, (dma)->block->map, (ops))
88 #define USB_MEM_SYNC2(utag, dma, off, len, ops) \
89 bus_dmamap_sync((dma)->block->tag, (dma)->block->map, (ops))
90 #endif
91
92 #define KERNADDR(dma, o) \
93 ((void *)((char *)(dma)->block->kaddr + (dma)->offs + (o)))
94
95 typedef struct {
96 struct usb_dma_block *block;
97 u_int offs;
98 u_int len;
99 } usb_dma_t;
100
101 /*
102 * DMA memory
103 */
104 struct usb_dmamem {
105 #if defined(__NetBSD__) || defined(__OpenBSD__)
106 bus_dma_segment_t ud_segs[USB_DMA_NSEG];
107 int ud_nsegs;
108 size_t ud_len;
109 #elif defined(__FreeBSD__)
110 bus_dma_tag_t ud_tag;
111 bus_dmamap_t ud_map;
112 #endif
113 usb_busdma_kaddr_t ud_kaddr;
114
115 SIMPLEQ_ENTRY(usb_dmamem) ud_next;
116
117 #ifdef USBMEM_DEBUG
118 TAILQ_ENTRY(usb_dmamem) ud_debug_next;
119 const char *ud_fn;
120 int ud_ln;
121 #endif
122 };
123
124 /*
125 * DMA buffer
126 */
127 struct usb_buffer_dma {
128 enum { UB_NONE, UB_BUF, UB_ALLOC_MAP, UB_MAP } ub_type;
129 int ub_flags;
130 #define USB_BUFFL_ASYNCMAP 0x01 /* created with BUS_DMA_ALLOCNOW */
131 #define USB_BUFFL_MAP 0x02 /* created without BUS_DMA_ALLOCNOW */
132
133 usb_dma_t ub_allocbuf;
134 struct usb_dmamem *ub_dmamem;
135
136 #if defined(__NetBSD__) || defined(__OpenBSD__)
137 bus_dmamap_t ub_map;
138 bus_dma_segment_t ub_bufseg;
139 #define _USB_BUFFER_NSEGS(ub) (ub)->ub_map->dm_nsegs
140 #define USB_BUFFER_NSEGS(ub) \
141 ((ub)->ub_type == UB_BUF ? 1 : _USB_BUFFER_NSEGS(ub))
142 #define USB_BUFFER_SEGS(ub) \
143 ((ub)->ub_type == UB_BUF ? \
144 &(ub)->ub_bufseg : (ub)->ub_map->dm_segs)
145
146 #elif defined(__FreeBSD__)
147 bus_dma_tag_t ub_curtag;
148 bus_dma_tag_t ub_asynctag;
149 bus_dmamap_t ub_map;
150 bus_dma_segment_t ub_segs[USB_DMA_NSEG];
151 int ub_nsegs;
152 int ub_error;
153 #define _USB_BUFFER_NSEGS(ub) (ub)->ub_nsegs
154 #define USB_BUFFER_NSEGS(ub) (_USB_BUFFER_NSEGS(ub))
155 #define USB_BUFFER_SEGS(ub) (ub)->ub_segs
156 #endif
157 };
158
159
160 #ifdef USBMEM_DEBUG
161 struct usb_frag_debug {
162 const char *f_fn;
163 int f_ln;
164 struct usb_frag_dma *f_frag;
165 TAILQ_ENTRY(usb_frag_debug) f_debug_next;
166 };
167 #endif
168
169 /*
170 * per host controller
171 */
172 typedef struct usb_dma_tag {
173 /*
174 * bus_dma(9) tag, filled by host controller driver
175 */
176 #if defined(__NetBSD__) || defined(__OpenBSD__)
177 bus_dma_tag_t tag;
178 #endif
179 #ifdef __FreeBSD__
180 bus_dma_tag_t tag_parent;
181 bus_dma_tag_t tag_buffer;
182 #endif
183
184 /*
185 * Lists of free DMA memory
186 */
187 LIST_HEAD(, usb_dma_block) blk_freelist;
188 int blk_nfree;
189 LIST_HEAD(, usb_frag_dma) frag_freelist;
190 /* for statistical and diagnostic purposes */
191 int nblks; /* number of allocated buffers */
192 int nfrags; /* number of allocated fragments */
193
194 /* for delayed free */
195 SIMPLEQ_HEAD(, usb_dmamem) uds_idle, uds_tobefreed;
196 /* for statistical and diagnostic purposes */
197 int nbufs; /* number of allocated buffer structures */
198
199 struct usb_task unmap_task;
200
201 #ifdef USBMEM_DEBUG
202 const char *devname;
203 TAILQ_HEAD(usb_debug_dmamem_head, usb_dmamem) uds_lease;
204 TAILQ_HEAD(usb_debug_blk_head, usb_dma_block) blks_lease;
205 TAILQ_HEAD(usb_debug_frag_head, usb_frag_debug)
206 frags_lease, free_frag_debug;
207 #define USBMEM_DEBUG_NFRAG 100
208 struct usb_frag_debug frag_debug_chunk[USBMEM_DEBUG_NFRAG];
209 int frag_debug_used, frag_debug_used_max;
210 #endif
211 } usb_dma_tag_t;
212
213 /*
214 * bufer pointer
215 */
216 union usb_bufptr {
217 /* plain buffer */
218 struct {
219 unsigned char *p_buf;
220 } ptr_p;
221 /* mbuf */
222 struct {
223 struct mbuf *m_mbuf;
224 int m_off;
225 } ptr_m;
226 };
227
228 /*
229 * auxillary storage (bounce buffer)
230 */
231 /* auxillary buffer description */
232 struct usb_aux_desc {
233 int aux_len; /* Auxillary storage size. */
234 void *aux_kern; /* Kernel address of aux storage */
235 union usb_bufptr aux_ptr; /* Original aux data pointer. */
236 };
237
238 #ifdef USBMEM_DEBUG
239 #define usb_allocmem usb_allocmem_debug
240 #define usb_freemem usb_freemem_debug
241 #define usb_alloc_buffer_dma usb_alloc_buffer_dma_debug
242 #define usb_free_buffer_dma usb_free_buffer_dma_debug
243 #define usb_clean_buffer_dma usb_clean_buffer_dma_debug
244 #define usb_dma_tag_init usb_dma_tag_init_debug
245 #define usb_dma_tag_finish usb_dma_tag_finish_debug
246 #define USBMEM_DEBUGPARAMS , const char *, int
247 #else
248 #define USBMEM_DEBUGPARAMS
249 #endif
250
251 usbd_status usb_allocmem(usb_dma_tag_t *, size_t, size_t, usb_dma_t *
252 USBMEM_DEBUGPARAMS);
253 void usb_freemem(usb_dma_tag_t *, usb_dma_t *
254 USBMEM_DEBUGPARAMS);
255 usbd_status usb_alloc_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
256 void *, size_t, void **
257 USBMEM_DEBUGPARAMS);
258 void usb_free_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
259 enum usbd_waitflg
260 USBMEM_DEBUGPARAMS);
261 void usb_map_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
262 void *, size_t);
263 usbd_status usb_map_mbuf_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
264 struct mbuf *);
265 void usb_unmap_dma(usb_dma_tag_t *u, struct usb_buffer_dma *);
266 usbd_status usb_alloc_dma_resources(usb_dma_tag_t *,
267 struct usb_buffer_dma *);
268 void usb_free_dma_resources(usb_dma_tag_t *,
269 struct usb_buffer_dma *);
270 void usb_sync_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
271 int /*ops*/);
272 void usb_clean_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *
273 USBMEM_DEBUGPARAMS);
274 usbd_status usb_insert_transfer_dma(usbd_xfer_handle, usb_dma_tag_t *,
275 struct usb_buffer_dma *);
276 void usb_transfer_complete_dma(usbd_xfer_handle, usb_dma_tag_t *,
277 struct usb_buffer_dma *);
278 void usb_dma_tag_init(usb_dma_tag_t *
279 #ifdef USBMEM_DEBUG
280 , device_ptr_t
281 #endif
282 USBMEM_DEBUGPARAMS);
283 void usb_dma_tag_finish(usb_dma_tag_t *
284 USBMEM_DEBUGPARAMS);
285
286 void usb_bufptr_init(union usb_bufptr *, usbd_xfer_handle);
287 void usb_bufptr_advance(union usb_bufptr *, int /*len*/,
288 int /*is_mbuf*/);
289 void usb_bufptr_rd(const union usb_bufptr *, const void *,
290 int /*len*/, int /*is_mbuf*/);
291 void usb_bufptr_wr(const union usb_bufptr *, void *,
292 int /*len*/, int /*is_mbuf*/);
293
294 #ifdef USBMEM_DEBUG
295 #undef USBMEM_DEBUGPARAMS
296 #ifndef USBMEM_PRIVATE
297 #undef usb_allocmem
298 #define usb_allocmem(utag, sz, al, dma) \
299 usb_allocmem_debug(utag, sz, al, dma, __FILE__, __LINE__)
300 #undef usb_freemem
301 #define usb_freemem(utag, dma) \
302 usb_freemem_debug(utag, dma, __FILE__, __LINE__)
303 #undef usb_alloc_buffer_dma
304 #define usb_alloc_buffer_dma(utag, ub, ptr, sz, padr) \
305 usb_alloc_buffer_dma_debug(utag, ub, ptr, sz, padr, __FILE__, __LINE__)
306 #undef usb_free_buffer_dma
307 #define usb_free_buffer_dma(utag, ub, w) \
308 usb_free_buffer_dma_debug(utag, ub, w, __FILE__, __LINE__)
309 #undef usb_clean_buffer_dma
310 #define usb_clean_buffer_dma(utag, ub) \
311 usb_clean_buffer_dma_debug(utag, ub, __FILE__, __LINE__)
312 #undef usb_dma_tag_init
313 #define usb_dma_tag_init(utag) \
314 usb_dma_tag_init_debug(utag, (device_ptr_t)sc, __FILE__, __LINE__)
315 #undef usb_dma_tag_finish
316 #define usb_dma_tag_finish(utag) \
317 usb_dma_tag_finish_debug(utag, __FILE__, __LINE__)
318 #endif /* !USBMEM_PRIVATE */
319 #endif /* USBMEM_DEBUG */
320