usb_mem.h revision 1.23.32.1 1 /* $NetBSD: usb_mem.h,v 1.23.32.1 2007/05/22 14:57:47 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 caddr_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 *)((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 caddr_t ud_kaddr;
110 #elif defined(__FreeBSD__)
111 void *ud_kaddr;
112 bus_dma_tag_t ud_tag;
113 bus_dmamap_t ud_map;
114 #endif
115
116 SIMPLEQ_ENTRY(usb_dmamem) ud_next;
117
118 #ifdef USBMEM_DEBUG
119 TAILQ_ENTRY(usb_dmamem) ud_debug_next;
120 const char *ud_fn;
121 int ud_ln;
122 #endif
123 };
124
125 /*
126 * DMA buffer
127 */
128 struct usb_buffer_dma {
129 enum { UB_NONE, UB_BUF, UB_ALLOC_MAP, UB_MAP } ub_type;
130 int ub_flags;
131 #define USB_BUFFL_ASYNCMAP 0x01 /* created with BUS_DMA_ALLOCNOW */
132 #define USB_BUFFL_MAP 0x02 /* created without BUS_DMA_ALLOCNOW */
133
134 usb_dma_t ub_allocbuf;
135 struct usb_dmamem *ub_dmamem;
136
137 #if defined(__NetBSD__) || defined(__OpenBSD__)
138 bus_dmamap_t ub_map;
139 bus_dma_segment_t ub_bufseg;
140 #define _USB_BUFFER_NSEGS(ub) (ub)->ub_map->dm_nsegs
141 #define USB_BUFFER_NSEGS(ub) \
142 ((ub)->ub_type == UB_BUF ? 1 : _USB_BUFFER_NSEGS(ub))
143 #define USB_BUFFER_SEGS(ub) \
144 ((ub)->ub_type == UB_BUF ? \
145 &(ub)->ub_bufseg : (ub)->ub_map->dm_segs)
146
147 #elif defined(__FreeBSD__)
148 bus_dma_tag_t ub_curtag;
149 bus_dma_tag_t ub_asynctag;
150 bus_dmamap_t ub_map;
151 bus_dma_segment_t ub_segs[USB_DMA_NSEG];
152 int ub_nsegs;
153 int ub_error;
154 #define _USB_BUFFER_NSEGS(ub) (ub)->ub_nsegs
155 #define USB_BUFFER_NSEGS(ub) (_USB_BUFFER_NSEGS(ub))
156 #define USB_BUFFER_SEGS(ub) (ub)->ub_segs
157 #endif
158 };
159
160
161 #ifdef USBMEM_DEBUG
162 struct usb_frag_debug {
163 const char *f_fn;
164 int f_ln;
165 struct usb_frag_dma *f_frag;
166 TAILQ_ENTRY(usb_frag_debug) f_debug_next;
167 };
168 #endif
169
170 /*
171 * per host controller
172 */
173 typedef struct usb_dma_tag {
174 /*
175 * bus_dma(9) tag, filled by host controller driver
176 */
177 #if defined(__NetBSD__) || defined(__OpenBSD__)
178 bus_dma_tag_t tag;
179 #endif
180 #ifdef __FreeBSD__
181 bus_dma_tag_t tag_parent;
182 bus_dma_tag_t tag_buffer;
183 #endif
184
185 /*
186 * Lists of free DMA memory
187 */
188 LIST_HEAD(, usb_dma_block) blk_freelist;
189 int blk_nfree;
190 LIST_HEAD(, usb_frag_dma) frag_freelist;
191 /* for statistical and diagnostic purposes */
192 int nblks; /* number of allocated buffers */
193 int nfrags; /* number of allocated fragments */
194
195 /* for delayed free */
196 SIMPLEQ_HEAD(, usb_dmamem) uds_idle, uds_tobefreed;
197 /* for statistical and diagnostic purposes */
198 int nbufs; /* number of allocated buffer structures */
199
200 struct usb_task unmap_task;
201
202 #ifdef USBMEM_DEBUG
203 const char *devname;
204 TAILQ_HEAD(usb_debug_dmamem_head, usb_dmamem) uds_lease;
205 TAILQ_HEAD(usb_debug_blk_head, usb_dma_block) blks_lease;
206 TAILQ_HEAD(usb_debug_frag_head, usb_frag_debug)
207 frags_lease, free_frag_debug;
208 #define USBMEM_DEBUG_NFRAG 100
209 struct usb_frag_debug frag_debug_chunk[USBMEM_DEBUG_NFRAG];
210 int frag_debug_used, frag_debug_used_max;
211 #endif
212 } usb_dma_tag_t;
213
214 #ifdef USBMEM_DEBUG
215 #define usb_allocmem usb_allocmem_debug
216 #define usb_freemem usb_freemem_debug
217 #define usb_alloc_buffer_dma usb_alloc_buffer_dma_debug
218 #define usb_free_buffer_dma usb_free_buffer_dma_debug
219 #define usb_clean_buffer_dma usb_clean_buffer_dma_debug
220 #define usb_dma_tag_init usb_dma_tag_init_debug
221 #define usb_dma_tag_finish usb_dma_tag_finish_debug
222 #define USBMEM_DEBUGPARAMS , const char *, int
223 #else
224 #define USBMEM_DEBUGPARAMS
225 #endif
226
227 usbd_status usb_allocmem(usb_dma_tag_t *, size_t, size_t, usb_dma_t *
228 USBMEM_DEBUGPARAMS);
229 void usb_freemem(usb_dma_tag_t *, usb_dma_t *
230 USBMEM_DEBUGPARAMS);
231 usbd_status usb_alloc_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
232 void *, size_t, void **
233 USBMEM_DEBUGPARAMS);
234 void usb_free_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
235 enum usbd_waitflg
236 USBMEM_DEBUGPARAMS);
237 void usb_map_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
238 void *, size_t);
239 void usb_map_mbuf_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
240 struct mbuf *);
241 void usb_unmap_dma(usb_dma_tag_t *u, struct usb_buffer_dma *);
242 usbd_status usb_alloc_dma_resources(usb_dma_tag_t *,
243 struct usb_buffer_dma *);
244 void usb_free_dma_resources(usb_dma_tag_t *,
245 struct usb_buffer_dma *);
246 void usb_sync_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
247 int /*ops*/);
248 void usb_clean_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *
249 USBMEM_DEBUGPARAMS);
250 usbd_status usb_insert_transfer_dma(usbd_xfer_handle, usb_dma_tag_t *,
251 struct usb_buffer_dma *);
252 void usb_transfer_complete_dma(usbd_xfer_handle, usb_dma_tag_t *,
253 struct usb_buffer_dma *);
254 void usb_dma_tag_init(usb_dma_tag_t *
255 #ifdef USBMEM_DEBUG
256 , device_ptr_t
257 #endif
258 USBMEM_DEBUGPARAMS);
259 void usb_dma_tag_finish(usb_dma_tag_t *
260 USBMEM_DEBUGPARAMS);
261
262 #ifdef USBMEM_DEBUG
263 #undef USBMEM_DEBUGPARAMS
264 #ifndef USBMEM_PRIVATE
265 #undef usb_allocmem
266 #define usb_allocmem(utag, sz, al, dma) \
267 usb_allocmem_debug(utag, sz, al, dma, __FILE__, __LINE__)
268 #undef usb_freemem
269 #define usb_freemem(utag, dma) \
270 usb_freemem_debug(utag, dma, __FILE__, __LINE__)
271 #undef usb_alloc_buffer_dma
272 #define usb_alloc_buffer_dma(utag, ub, ptr, sz, padr) \
273 usb_alloc_buffer_dma_debug(utag, ub, ptr, sz, padr, __FILE__, __LINE__)
274 #undef usb_free_buffer_dma
275 #define usb_free_buffer_dma(utag, ub, w) \
276 usb_free_buffer_dma_debug(utag, ub, w, __FILE__, __LINE__)
277 #undef usb_clean_buffer_dma
278 #define usb_clean_buffer_dma(utag, ub) \
279 usb_clean_buffer_dma_debug(utag, ub, __FILE__, __LINE__)
280 #undef usb_dma_tag_init
281 #define usb_dma_tag_init(utag) \
282 usb_dma_tag_init_debug(utag, (device_ptr_t)sc, __FILE__, __LINE__)
283 #undef usb_dma_tag_finish
284 #define usb_dma_tag_finish(utag) \
285 usb_dma_tag_finish_debug(utag, __FILE__, __LINE__)
286 #endif /* !USBMEM_PRIVATE */
287 #endif /* USBMEM_DEBUG */
288