Home | History | Annotate | Line # | Download | only in usb
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