xref: /dragonfly/sys/bus/u4b/usb_busdma.h (revision f7f39add)
1*f7f39addSMarkus Pfeiffer /* $FreeBSD: head/sys/dev/usb/usb_busdma.h 266969 2014-06-02 07:08:34Z hselasky $ */
212bd3c8bSSascha Wildner /*-
312bd3c8bSSascha Wildner  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
412bd3c8bSSascha Wildner  *
512bd3c8bSSascha Wildner  * Redistribution and use in source and binary forms, with or without
612bd3c8bSSascha Wildner  * modification, are permitted provided that the following conditions
712bd3c8bSSascha Wildner  * are met:
812bd3c8bSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
912bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
1012bd3c8bSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
1112bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
1212bd3c8bSSascha Wildner  *    documentation and/or other materials provided with the distribution.
1312bd3c8bSSascha Wildner  *
1412bd3c8bSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1512bd3c8bSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1612bd3c8bSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1712bd3c8bSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1812bd3c8bSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1912bd3c8bSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2012bd3c8bSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2112bd3c8bSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2212bd3c8bSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2312bd3c8bSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2412bd3c8bSSascha Wildner  * SUCH DAMAGE.
2512bd3c8bSSascha Wildner  */
2612bd3c8bSSascha Wildner 
2712bd3c8bSSascha Wildner #ifndef _USB_BUSDMA_H_
2812bd3c8bSSascha Wildner #define	_USB_BUSDMA_H_
2912bd3c8bSSascha Wildner 
3012bd3c8bSSascha Wildner #include <sys/uio.h>
3112bd3c8bSSascha Wildner #include <sys/mbuf.h>
3212bd3c8bSSascha Wildner 
33722d05c3SSascha Wildner #include <sys/bus.h>
34722d05c3SSascha Wildner 
35722d05c3SSascha Wildner #define USB_HAVE_BUSDMA 1
3612bd3c8bSSascha Wildner 
3712bd3c8bSSascha Wildner /* defines */
3812bd3c8bSSascha Wildner 
3912bd3c8bSSascha Wildner #define	USB_PAGE_SIZE PAGE_SIZE		/* use system PAGE_SIZE */
4012bd3c8bSSascha Wildner 
4112bd3c8bSSascha Wildner #define	USB_GET_DMA_TAG(dev) NULL	/* XXX */
4212bd3c8bSSascha Wildner 
4312bd3c8bSSascha Wildner /* structure prototypes */
4412bd3c8bSSascha Wildner 
4512bd3c8bSSascha Wildner struct usb_xfer_root;
4612bd3c8bSSascha Wildner struct usb_dma_parent_tag;
4712bd3c8bSSascha Wildner struct usb_dma_tag;
4812bd3c8bSSascha Wildner 
4912bd3c8bSSascha Wildner /*
5012bd3c8bSSascha Wildner  * The following typedef defines the USB DMA load done callback.
5112bd3c8bSSascha Wildner  */
5212bd3c8bSSascha Wildner 
5312bd3c8bSSascha Wildner typedef void (usb_dma_callback_t)(struct usb_dma_parent_tag *udpt);
5412bd3c8bSSascha Wildner 
5512bd3c8bSSascha Wildner /*
5612bd3c8bSSascha Wildner  * The following structure defines physical and non kernel virtual
5712bd3c8bSSascha Wildner  * address of a memory page having size USB_PAGE_SIZE.
5812bd3c8bSSascha Wildner  */
5912bd3c8bSSascha Wildner struct usb_page {
6012bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA
6112bd3c8bSSascha Wildner 	bus_size_t physaddr;
6212bd3c8bSSascha Wildner 	void   *buffer;			/* non Kernel Virtual Address */
6312bd3c8bSSascha Wildner #endif
6412bd3c8bSSascha Wildner };
6512bd3c8bSSascha Wildner 
6612bd3c8bSSascha Wildner /*
6712bd3c8bSSascha Wildner  * The following structure is used when needing the kernel virtual
6812bd3c8bSSascha Wildner  * pointer and the physical address belonging to an offset in an USB
6912bd3c8bSSascha Wildner  * page cache.
7012bd3c8bSSascha Wildner  */
7112bd3c8bSSascha Wildner struct usb_page_search {
7212bd3c8bSSascha Wildner 	void   *buffer;
7312bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA
7412bd3c8bSSascha Wildner 	bus_size_t physaddr;
7512bd3c8bSSascha Wildner #endif
7612bd3c8bSSascha Wildner 	usb_size_t length;
7712bd3c8bSSascha Wildner };
7812bd3c8bSSascha Wildner 
7912bd3c8bSSascha Wildner /*
8012bd3c8bSSascha Wildner  * The following structure is used to keep information about a DMA
8112bd3c8bSSascha Wildner  * memory allocation.
8212bd3c8bSSascha Wildner  */
8312bd3c8bSSascha Wildner struct usb_page_cache {
8412bd3c8bSSascha Wildner 
8512bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA
8612bd3c8bSSascha Wildner 	bus_dma_tag_t tag;
8712bd3c8bSSascha Wildner 	bus_dmamap_t map;
8812bd3c8bSSascha Wildner 	struct usb_page *page_start;
8912bd3c8bSSascha Wildner #endif
9012bd3c8bSSascha Wildner 	struct usb_dma_parent_tag *tag_parent;	/* always set */
9112bd3c8bSSascha Wildner 	void   *buffer;			/* virtual buffer pointer */
9212bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA
9312bd3c8bSSascha Wildner 	usb_size_t page_offset_buf;
9412bd3c8bSSascha Wildner 	usb_size_t page_offset_end;
9512bd3c8bSSascha Wildner 	uint8_t	isread:1;		/* set if we are currently reading
9612bd3c8bSSascha Wildner 					 * from the memory. Else write. */
9712bd3c8bSSascha Wildner 	uint8_t	ismultiseg:1;		/* set if we can have multiple
9812bd3c8bSSascha Wildner 					 * segments */
9912bd3c8bSSascha Wildner #endif
10012bd3c8bSSascha Wildner };
10112bd3c8bSSascha Wildner 
10212bd3c8bSSascha Wildner /*
10312bd3c8bSSascha Wildner  * The following structure describes the parent USB DMA tag.
10412bd3c8bSSascha Wildner  */
10512bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA
10612bd3c8bSSascha Wildner struct usb_dma_parent_tag {
10712bd3c8bSSascha Wildner 	struct cv cv[1];		/* internal condition variable */
10812bd3c8bSSascha Wildner 	bus_dma_tag_t tag;		/* always set */
10912bd3c8bSSascha Wildner 
110722d05c3SSascha Wildner 	struct lock *lock;		/* private mutex, always set */
11112bd3c8bSSascha Wildner 	usb_dma_callback_t *func;	/* load complete callback function */
11212bd3c8bSSascha Wildner 	struct usb_dma_tag *utag_first;/* pointer to first USB DMA tag */
11312bd3c8bSSascha Wildner 	uint8_t	dma_error;		/* set if DMA load operation failed */
11412bd3c8bSSascha Wildner 	uint8_t	dma_bits;		/* number of DMA address lines */
11512bd3c8bSSascha Wildner 	uint8_t	utag_max;		/* number of USB DMA tags */
11612bd3c8bSSascha Wildner };
11712bd3c8bSSascha Wildner #else
11812bd3c8bSSascha Wildner struct usb_dma_parent_tag {};		/* empty struct */
11912bd3c8bSSascha Wildner #endif
12012bd3c8bSSascha Wildner 
12112bd3c8bSSascha Wildner /*
12212bd3c8bSSascha Wildner  * The following structure describes an USB DMA tag.
12312bd3c8bSSascha Wildner  */
12412bd3c8bSSascha Wildner #if USB_HAVE_BUSDMA
12512bd3c8bSSascha Wildner struct usb_dma_tag {
12612bd3c8bSSascha Wildner 	struct usb_dma_parent_tag *tag_parent;
12712bd3c8bSSascha Wildner 	bus_dma_tag_t tag;
12812bd3c8bSSascha Wildner 	usb_size_t align;
12912bd3c8bSSascha Wildner 	usb_size_t size;
13012bd3c8bSSascha Wildner };
13112bd3c8bSSascha Wildner #else
13212bd3c8bSSascha Wildner struct usb_dma_tag {};			/* empty struct */
13312bd3c8bSSascha Wildner #endif
13412bd3c8bSSascha Wildner 
13512bd3c8bSSascha Wildner /* function prototypes */
13612bd3c8bSSascha Wildner 
13712bd3c8bSSascha Wildner int	usb_uiomove(struct usb_page_cache *pc, struct uio *uio,
13812bd3c8bSSascha Wildner 	    usb_frlength_t pc_offset, usb_frlength_t len);
13912bd3c8bSSascha Wildner struct usb_dma_tag *usb_dma_tag_find(struct usb_dma_parent_tag *udpt,
14012bd3c8bSSascha Wildner 	    usb_size_t size, usb_size_t align);
14112bd3c8bSSascha Wildner uint8_t	usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
14212bd3c8bSSascha Wildner 	    usb_size_t size, usb_size_t align);
14312bd3c8bSSascha Wildner uint8_t	usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size);
14412bd3c8bSSascha Wildner uint8_t	usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size,
14512bd3c8bSSascha Wildner 	    uint8_t sync);
14612bd3c8bSSascha Wildner void	usb_bdma_done_event(struct usb_dma_parent_tag *udpt);
14712bd3c8bSSascha Wildner void	usb_bdma_post_sync(struct usb_xfer *xfer);
14812bd3c8bSSascha Wildner void	usb_bdma_pre_sync(struct usb_xfer *xfer);
14912bd3c8bSSascha Wildner void	usb_bdma_work_loop(struct usb_xfer_queue *pq);
15012bd3c8bSSascha Wildner void	usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
151722d05c3SSascha Wildner 	    struct usb_dma_tag *udt, bus_dma_tag_t dmat, struct lock *lock,
15212bd3c8bSSascha Wildner 	    usb_dma_callback_t *func, uint8_t ndmabits, uint8_t nudt);
15312bd3c8bSSascha Wildner void	usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt);
15412bd3c8bSSascha Wildner void	usb_pc_cpu_flush(struct usb_page_cache *pc);
15512bd3c8bSSascha Wildner void	usb_pc_cpu_invalidate(struct usb_page_cache *pc);
15612bd3c8bSSascha Wildner void	usb_pc_dmamap_destroy(struct usb_page_cache *pc);
15712bd3c8bSSascha Wildner void	usb_pc_free_mem(struct usb_page_cache *pc);
15812bd3c8bSSascha Wildner 
15912bd3c8bSSascha Wildner #endif					/* _USB_BUSDMA_H_ */
160