| 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_TRANSFER_H_ |
| 29 | #define	_USB_TRANSFER_H_ |
| 30 | |
| 31 | /* |
| 32 | * A few words about USB transfer states: |
| 33 | * ====================================== |
| 34 | * |
| 35 | * USB transfers can have multiple states, because they can be |
| 36 | * cancelled and started again and this cannot always be done |
| 37 | * atomically under a mutex. One reason for this is that the USB |
| 38 | * hardware sometimes needs to wait for DMA controllers to finish |
| 39 | * which is done asynchronously and grows the statemachine. |
| 40 | */ |
| 41 | |
| 42 | /* |
| 43 | * The following structure defines the messages that is used to signal |
| 44 | * the "done_p" USB process. |
| 45 | */ |
| 46 | struct usb_done_msg { |
| 47 | 	struct usb_proc_msg hdr; |
| 48 | 	struct usb_xfer_root *xroot; |
| 49 | }; |
| 50 | |
| 51 | #define	USB_DMATAG_TO_XROOT(dpt)				\ |
| 52 | 	__containerof(dpt, struct usb_xfer_root, dma_parent_tag) |
| 53 | |
| 54 | /* |
| 55 | * The following structure is used to keep information about memory |
| 56 | * that should be automatically freed at the moment all USB transfers |
| 57 | * have been freed. |
| 58 | */ |
| 59 | struct usb_xfer_root { |
| 60 | 	struct usb_dma_parent_tag dma_parent_tag; |
| 61 | #if USB_HAVE_BUSDMA |
| 62 | 	struct usb_xfer_queue dma_q; |
| 63 | #endif |
| 64 | 	struct usb_xfer_queue done_q; |
| 65 | 	struct usb_done_msg done_m[2]; |
| 66 | 	struct cv cv_drain; |
| 67 | |
| 68 | 	struct usb_process *done_p;	/* pointer to callback process */ |
| 69 | 	void *memory_base; |
| 70 | 	struct mtx *xfer_mtx;	/* cannot be changed during operation */ |
| 71 | #if USB_HAVE_BUSDMA |
| 72 | 	struct usb_page_cache *dma_page_cache_start; |
| 73 | 	struct usb_page_cache *dma_page_cache_end; |
| 74 | #endif |
| 75 | 	struct usb_page_cache *xfer_page_cache_start; |
| 76 | 	struct usb_page_cache *xfer_page_cache_end; |
| 77 | 	struct usb_bus *bus;		/* pointer to USB bus (cached) */ |
| 78 | 	struct usb_device *udev;	/* pointer to USB device */ |
| 79 | |
| 80 | 	usb_size_t memory_size; |
| 81 | 	usb_size_t setup_refcount; |
| 82 | #if USB_HAVE_BUSDMA |
| 83 | 	usb_frcount_t dma_nframes;	/* number of page caches to load */ |
| 84 | 	usb_frcount_t dma_currframe;	/* currect page cache number */ |
| 85 | 	usb_frlength_t dma_frlength_0;	/* length of page cache zero */ |
| 86 | 	uint8_t	dma_error;		/* set if virtual memory could not be |
| 87 | 					 * loaded */ |
| 88 | #endif |
| 89 | 	uint8_t	done_sleep;		/* set if done thread is sleeping */ |
| 90 | }; |
| 91 | |
| 92 | /* |
| 93 | * The following structure is used when setting up an array of USB |
| 94 | * transfers. |
| 95 | */ |
| 96 | struct usb_setup_params { |
| 97 | 	struct usb_dma_tag *dma_tag_p; |
| 98 | 	struct usb_page *dma_page_ptr; |
| 99 | 	struct usb_page_cache *dma_page_cache_ptr;	/* these will be |
| 100 | 							 * auto-freed */ |
| 101 | 	struct usb_page_cache *xfer_page_cache_ptr;	/* these will not be |
| 102 | 							 * auto-freed */ |
| 103 | 	struct usb_device *udev; |
| 104 | 	struct usb_xfer *curr_xfer; |
| 105 | 	const struct usb_config *curr_setup; |
| 106 | 	const struct usb_pipe_methods *methods; |
| 107 | 	void *buf; |
| 108 | 	usb_frlength_t *xfer_length_ptr; |
| 109 | |
| 110 | 	usb_size_t size[7]; |
| 111 | 	usb_frlength_t bufsize; |
| 112 | 	usb_frlength_t bufsize_max; |
| 113 | |
| 114 | 	uint32_t hc_max_frame_size; |
| 115 | 	uint16_t hc_max_packet_size; |
| 116 | 	uint8_t	hc_max_packet_count; |
| 117 | 	enum usb_dev_speed speed; |
| 118 | 	uint8_t	dma_tag_max; |
| 119 | 	usb_error_t err; |
| 120 | }; |
| 121 | |
| 122 | /* function prototypes */ |
| 123 | |
| 124 | uint8_t	usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, |
| 125 | 	 struct usb_page_cache **ppc, usb_size_t size, usb_size_t align, |
| 126 | 	 usb_size_t count); |
| 127 | void	usb_dma_delay_done_cb(struct usb_xfer *); |
| 128 | void	usb_command_wrapper(struct usb_xfer_queue *pq, |
| 129 | 	 struct usb_xfer *xfer); |
| 130 | void	usbd_pipe_enter(struct usb_xfer *xfer); |
| 131 | void	usbd_pipe_start(struct usb_xfer_queue *pq); |
| 132 | void	usbd_transfer_dequeue(struct usb_xfer *xfer); |
| 133 | void	usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error); |
| 134 | void	usbd_transfer_enqueue(struct usb_xfer_queue *pq, |
| 135 | 	 struct usb_xfer *xfer); |
| 136 | void	usbd_transfer_setup_sub(struct usb_setup_params *parm); |
| 137 | void	usbd_ctrl_transfer_setup(struct usb_device *udev); |
| 138 | void	usbd_clear_stall_locked(struct usb_device *udev, |
| 139 | 	 struct usb_endpoint *ep); |
| 140 | void	usbd_clear_data_toggle(struct usb_device *udev, |
| 141 | 	 struct usb_endpoint *ep); |
| 142 | usb_callback_t usbd_do_request_callback; |
| 143 | usb_callback_t usb_handle_request_callback; |
| 144 | usb_callback_t usb_do_clear_stall_callback; |
| 145 | void	usbd_transfer_timeout_ms(struct usb_xfer *xfer, |
| 146 | 	 void (*cb) (void *arg), usb_timeout_t ms); |
| 147 | usb_timeout_t usbd_get_dma_delay(struct usb_device *udev); |
| 148 | void	usbd_transfer_power_ref(struct usb_xfer *xfer, int val); |
| 149 | uint8_t	usbd_xfer_get_isochronous_start_frame(struct usb_xfer *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t *); |
| 150 | |
| 151 | #endif					/* _USB_TRANSFER_H_ */ |