xref: /freebsd/sys/dev/usb/usb_busdma.h (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #ifndef _USB_BUSDMA_H_
29 #define	_USB_BUSDMA_H_
30 
31 #ifndef USB_GLOBAL_INCLUDE_FILE
32 #include <sys/uio.h>
33 #include <sys/mbuf.h>
34 
35 #include <machine/bus.h>
36 #endif
37 
38 /* defines */
39 
40 #define	USB_PAGE_SIZE PAGE_SIZE		/* use system PAGE_SIZE */
41 
42 #define	USB_GET_DMA_TAG(dev) bus_get_dma_tag(dev)
43 
44 /* structure prototypes */
45 
46 struct usb_xfer_root;
47 struct usb_dma_parent_tag;
48 struct usb_dma_tag;
49 
50 /*
51  * The following typedef defines the USB DMA load done callback.
52  */
53 
54 typedef void (usb_dma_callback_t)(struct usb_dma_parent_tag *udpt);
55 
56 /*
57  * The following structure defines physical and non kernel virtual
58  * address of a memory page having size USB_PAGE_SIZE.
59  */
60 struct usb_page {
61 #if USB_HAVE_BUSDMA
62 	bus_addr_t physaddr;
63 	void   *buffer;			/* non Kernel Virtual Address */
64 #endif
65 };
66 
67 /*
68  * The following structure is used when needing the kernel virtual
69  * pointer and the physical address belonging to an offset in an USB
70  * page cache.
71  */
72 struct usb_page_search {
73 	void   *buffer;
74 #if USB_HAVE_BUSDMA
75 	bus_addr_t physaddr;
76 #endif
77 	usb_size_t length;
78 };
79 
80 /*
81  * The following structure is used to keep information about a DMA
82  * memory allocation.
83  */
84 struct usb_page_cache {
85 #if USB_HAVE_BUSDMA
86 	bus_dma_tag_t tag;
87 	bus_dmamap_t map;
88 	struct usb_page *page_start;
89 #endif
90 	struct usb_dma_parent_tag *tag_parent;	/* always set */
91 	void   *buffer;			/* virtual buffer pointer */
92 #if USB_HAVE_BUSDMA
93 	usb_size_t page_offset_buf;
94 	usb_size_t page_offset_end;
95 	uint8_t	isread:1;		/* set if we are currently reading
96 					 * from the memory. Else write. */
97 	uint8_t	ismultiseg:1;		/* set if we can have multiple
98 					 * segments */
99 	uint8_t isloaded:1;		/* Set if map is currently loaded. */
100 #endif
101 };
102 
103 /*
104  * The following structure describes the parent USB DMA tag.
105  */
106 #if USB_HAVE_BUSDMA
107 struct usb_dma_parent_tag {
108 	struct cv cv[1];		/* internal condition variable */
109 	bus_dma_tag_t tag;		/* always set */
110 
111 	struct mtx *mtx;		/* private mutex, always set */
112 	usb_dma_callback_t *func;	/* load complete callback function */
113 	struct usb_dma_tag *utag_first;/* pointer to first USB DMA tag */
114 	uint8_t	dma_error;		/* set if DMA load operation failed */
115 	uint8_t	dma_bits;		/* number of DMA address lines */
116 	uint8_t	utag_max;		/* number of USB DMA tags */
117 };
118 #else
119 struct usb_dma_parent_tag {};		/* empty struct */
120 #endif
121 
122 /*
123  * The following structure describes an USB DMA tag.
124  */
125 #if USB_HAVE_BUSDMA
126 struct usb_dma_tag {
127 	struct usb_dma_parent_tag *tag_parent;
128 	bus_dma_tag_t tag;
129 	usb_size_t align;
130 	usb_size_t size;
131 };
132 #else
133 struct usb_dma_tag {};			/* empty struct */
134 #endif
135 
136 /* function prototypes */
137 
138 int	usb_uiomove(struct usb_page_cache *pc, struct uio *uio,
139 	    usb_frlength_t pc_offset, usb_frlength_t len);
140 struct usb_dma_tag *usb_dma_tag_find(struct usb_dma_parent_tag *udpt,
141 	    usb_size_t size, usb_size_t align);
142 uint8_t	usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
143 	    usb_size_t size, usb_size_t align);
144 uint8_t	usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size);
145 uint8_t	usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size,
146 	    uint8_t sync);
147 void	usb_bdma_done_event(struct usb_dma_parent_tag *udpt);
148 void	usb_bdma_post_sync(struct usb_xfer *xfer);
149 void	usb_bdma_pre_sync(struct usb_xfer *xfer);
150 void	usb_bdma_work_loop(struct usb_xfer_queue *pq);
151 void	usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
152 	    struct usb_dma_tag *udt, bus_dma_tag_t dmat, struct mtx *mtx,
153 	    usb_dma_callback_t *func, uint8_t ndmabits, uint8_t nudt);
154 void	usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt);
155 void	usb_pc_cpu_flush(struct usb_page_cache *pc);
156 void	usb_pc_cpu_invalidate(struct usb_page_cache *pc);
157 void	usb_pc_dmamap_destroy(struct usb_page_cache *pc);
158 void	usb_pc_free_mem(struct usb_page_cache *pc);
159 uint8_t	usb_pc_buffer_is_aligned(struct usb_page_cache *pc,
160 	    usb_frlength_t offset, usb_frlength_t len,
161 	    usb_frlength_t mask);
162 
163 #endif					/* _USB_BUSDMA_H_ */
164