usb_busdma.h revision 190181
1/* $FreeBSD: head/sys/dev/usb/usb_busdma.h 190181 2009-03-20 21:50:54Z thompsa $ */
2/*-
3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#ifndef _USB2_BUSDMA_H_
28#define	_USB2_BUSDMA_H_
29
30#include <sys/uio.h>
31#include <sys/mbuf.h>
32
33#include <machine/bus.h>
34
35/* defines */
36
37#define	USB_PAGE_SIZE PAGE_SIZE		/* use system PAGE_SIZE */
38
39#ifdef __FreeBSD__
40#if (__FreeBSD_version >= 700020)
41#define	USB_GET_DMA_TAG(dev) bus_get_dma_tag(dev)
42#else
43#define	USB_GET_DMA_TAG(dev) NULL	/* XXX */
44#endif
45#endif
46
47/* structure prototypes */
48
49struct usb2_xfer_root;
50struct usb2_dma_parent_tag;
51
52/*
53 * The following typedef defines the USB DMA load done callback.
54 */
55
56typedef void (usb2_dma_callback_t)(struct usb2_dma_parent_tag *udpt);
57
58/*
59 * The following structure defines physical and non kernel virtual
60 * address of a memory page having size USB_PAGE_SIZE.
61 */
62struct usb2_page {
63#if USB_HAVE_BUSDMA
64	bus_size_t physaddr;
65	void   *buffer;			/* non Kernel Virtual Address */
66#endif
67};
68
69/*
70 * The following structure is used when needing the kernel virtual
71 * pointer and the physical address belonging to an offset in an USB
72 * page cache.
73 */
74struct usb2_page_search {
75	void   *buffer;
76#if USB_HAVE_BUSDMA
77	bus_size_t physaddr;
78#endif
79	usb2_size_t length;
80};
81
82/*
83 * The following structure is used to keep information about a DMA
84 * memory allocation.
85 */
86struct usb2_page_cache {
87
88#if USB_HAVE_BUSDMA && defined(__FreeBSD__)
89	bus_dma_tag_t tag;
90	bus_dmamap_t map;
91#endif
92#if USB_HAVE_BUSDMA && defined(__NetBSD__)
93	bus_dma_tag_t tag;
94	bus_dmamap_t map;
95	bus_dma_segment_t *p_seg;
96#endif
97#if USB_HAVE_BUSDMA
98	struct usb2_page *page_start;
99#endif
100	struct usb2_dma_parent_tag *tag_parent;	/* always set */
101	void   *buffer;			/* virtual buffer pointer */
102#if USB_HAVE_BUSDMA && defined(_NetBSD__)
103	int	n_seg;
104#endif
105#if USB_HAVE_BUSDMA
106	usb2_size_t page_offset_buf;
107	usb2_size_t page_offset_end;
108	uint8_t	isread:1;		/* set if we are currently reading
109					 * from the memory. Else write. */
110	uint8_t	ismultiseg:1;		/* set if we can have multiple
111					 * segments */
112#endif
113};
114
115/*
116 * The following structure describes the parent USB DMA tag.
117 */
118struct usb2_dma_parent_tag {
119#if USB_HAVE_BUSDMA && defined(__FreeBSD__)
120	struct cv cv[1];		/* internal condition variable */
121#endif
122#if USB_HAVE_BUSDMA
123	bus_dma_tag_t tag;		/* always set */
124
125	struct mtx *mtx;		/* private mutex, always set */
126	usb2_dma_callback_t *func;	/* load complete callback function */
127	struct usb2_dma_tag *utag_first;/* pointer to first USB DMA tag */
128	uint8_t	dma_error;		/* set if DMA load operation failed */
129	uint8_t	dma_bits;		/* number of DMA address lines */
130	uint8_t	utag_max;		/* number of USB DMA tags */
131#endif
132};
133
134/*
135 * The following structure describes an USB DMA tag.
136 */
137struct usb2_dma_tag {
138#if USB_HAVE_BUSDMA && defined(__NetBSD__)
139	bus_dma_segment_t *p_seg;
140#endif
141#if USB_HAVE_BUSDMA
142	struct usb2_dma_parent_tag *tag_parent;
143	bus_dma_tag_t tag;
144
145	usb2_size_t align;
146	usb2_size_t size;
147#endif
148#if USB_HAVE_BUSDMA && defined(__NetBSD__)
149	usb2_size_t n_seg;
150#endif
151};
152
153/* function prototypes */
154
155int	usb2_uiomove(struct usb2_page_cache *pc, struct uio *uio,
156	    usb2_frlength_t pc_offset, usb2_frlength_t len);
157struct usb2_dma_tag *usb2_dma_tag_find(struct usb2_dma_parent_tag *udpt,
158	    usb2_size_t size, usb2_size_t align);
159uint8_t	usb2_pc_alloc_mem(struct usb2_page_cache *pc, struct usb2_page *pg,
160	    usb2_size_t size, usb2_size_t align);
161uint8_t	usb2_pc_dmamap_create(struct usb2_page_cache *pc, usb2_size_t size);
162uint8_t	usb2_pc_load_mem(struct usb2_page_cache *pc, usb2_size_t size,
163	    uint8_t sync);
164void	usb2_bdma_done_event(struct usb2_dma_parent_tag *udpt);
165void	usb2_bdma_post_sync(struct usb2_xfer *xfer);
166void	usb2_bdma_pre_sync(struct usb2_xfer *xfer);
167void	usb2_bdma_work_loop(struct usb2_xfer_queue *pq);
168void	usb2_bzero(struct usb2_page_cache *cache, usb2_frlength_t offset,
169	    usb2_frlength_t len);
170void	usb2_copy_in(struct usb2_page_cache *cache, usb2_frlength_t offset,
171	    const void *ptr, usb2_frlength_t len);
172int	usb2_copy_in_user(struct usb2_page_cache *cache, usb2_frlength_t offset,
173	    const void *ptr, usb2_frlength_t len);
174void	usb2_copy_out(struct usb2_page_cache *cache, usb2_frlength_t offset,
175	    void *ptr, usb2_frlength_t len);
176int	usb2_copy_out_user(struct usb2_page_cache *cache, usb2_frlength_t offset,
177	    void *ptr, usb2_frlength_t len);
178void	usb2_dma_tag_setup(struct usb2_dma_parent_tag *udpt,
179	    struct usb2_dma_tag *udt, bus_dma_tag_t dmat, struct mtx *mtx,
180	    usb2_dma_callback_t *func, uint8_t ndmabits, uint8_t nudt);
181void	usb2_dma_tag_unsetup(struct usb2_dma_parent_tag *udpt);
182void	usb2_get_page(struct usb2_page_cache *pc, usb2_frlength_t offset,
183	    struct usb2_page_search *res);
184void	usb2_m_copy_in(struct usb2_page_cache *cache, usb2_frlength_t dst_offset,
185	    struct mbuf *m, usb2_size_t src_offset, usb2_frlength_t src_len);
186void	usb2_pc_cpu_flush(struct usb2_page_cache *pc);
187void	usb2_pc_cpu_invalidate(struct usb2_page_cache *pc);
188void	usb2_pc_dmamap_destroy(struct usb2_page_cache *pc);
189void	usb2_pc_free_mem(struct usb2_page_cache *pc);
190
191#endif					/* _USB2_BUSDMA_H_ */
192