Home | History | Annotate | Line # | Download | only in usb
usb_mem.h revision 1.23.32.3
      1 /*	$NetBSD: usb_mem.h,v 1.23.32.3 2007/06/17 01:25:46 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 #ifdef USBMEM_DEBUG
    214 #define usb_allocmem		usb_allocmem_debug
    215 #define usb_freemem		usb_freemem_debug
    216 #define usb_alloc_buffer_dma	usb_alloc_buffer_dma_debug
    217 #define usb_free_buffer_dma	usb_free_buffer_dma_debug
    218 #define usb_clean_buffer_dma	usb_clean_buffer_dma_debug
    219 #define usb_dma_tag_init	usb_dma_tag_init_debug
    220 #define usb_dma_tag_finish	usb_dma_tag_finish_debug
    221 #define USBMEM_DEBUGPARAMS	, const char *, int
    222 #else
    223 #define USBMEM_DEBUGPARAMS
    224 #endif
    225 
    226 usbd_status	usb_allocmem(usb_dma_tag_t *, size_t, size_t, usb_dma_t *
    227 		    USBMEM_DEBUGPARAMS);
    228 void		usb_freemem(usb_dma_tag_t *, usb_dma_t *
    229 		    USBMEM_DEBUGPARAMS);
    230 usbd_status	usb_alloc_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
    231 		    void *, size_t, void **
    232 		    USBMEM_DEBUGPARAMS);
    233 void		usb_free_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
    234 		    enum usbd_waitflg
    235 		    USBMEM_DEBUGPARAMS);
    236 void		usb_map_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
    237 		    void *, size_t);
    238 usbd_status	usb_map_mbuf_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
    239 		    struct mbuf *);
    240 void		usb_unmap_dma(usb_dma_tag_t *u, struct usb_buffer_dma *);
    241 usbd_status	usb_alloc_dma_resources(usb_dma_tag_t *,
    242 		    struct usb_buffer_dma *);
    243 void		usb_free_dma_resources(usb_dma_tag_t *,
    244 		    struct usb_buffer_dma *);
    245 void		usb_sync_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *,
    246 		    int /*ops*/);
    247 void		usb_clean_buffer_dma(usb_dma_tag_t *, struct usb_buffer_dma *
    248 		    USBMEM_DEBUGPARAMS);
    249 usbd_status	usb_insert_transfer_dma(usbd_xfer_handle, usb_dma_tag_t *,
    250 		    struct usb_buffer_dma *);
    251 void		usb_transfer_complete_dma(usbd_xfer_handle, usb_dma_tag_t *,
    252 		    struct usb_buffer_dma *);
    253 void		usb_dma_tag_init(usb_dma_tag_t *
    254 #ifdef USBMEM_DEBUG
    255 		    , device_ptr_t
    256 #endif
    257 		    USBMEM_DEBUGPARAMS);
    258 void		usb_dma_tag_finish(usb_dma_tag_t *
    259 		    USBMEM_DEBUGPARAMS);
    260 
    261 #ifdef USBMEM_DEBUG
    262 #undef USBMEM_DEBUGPARAMS
    263 #ifndef USBMEM_PRIVATE
    264 #undef usb_allocmem
    265 #define usb_allocmem(utag, sz, al, dma) \
    266 	usb_allocmem_debug(utag, sz, al, dma, __FILE__, __LINE__)
    267 #undef usb_freemem
    268 #define usb_freemem(utag, dma) \
    269 	usb_freemem_debug(utag, dma, __FILE__, __LINE__)
    270 #undef usb_alloc_buffer_dma
    271 #define usb_alloc_buffer_dma(utag, ub, ptr, sz, padr) \
    272 	usb_alloc_buffer_dma_debug(utag, ub, ptr, sz, padr, __FILE__, __LINE__)
    273 #undef usb_free_buffer_dma
    274 #define usb_free_buffer_dma(utag, ub, w) \
    275 	usb_free_buffer_dma_debug(utag, ub, w, __FILE__, __LINE__)
    276 #undef usb_clean_buffer_dma
    277 #define usb_clean_buffer_dma(utag, ub) \
    278 	usb_clean_buffer_dma_debug(utag, ub, __FILE__, __LINE__)
    279 #undef usb_dma_tag_init
    280 #define usb_dma_tag_init(utag) \
    281 	usb_dma_tag_init_debug(utag, (device_ptr_t)sc, __FILE__, __LINE__)
    282 #undef usb_dma_tag_finish
    283 #define usb_dma_tag_finish(utag) \
    284 	usb_dma_tag_finish_debug(utag, __FILE__, __LINE__)
    285 #endif	/* !USBMEM_PRIVATE */
    286 #endif	/* USBMEM_DEBUG */
    287