1 // Copyright 2017 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <stdint.h> 8 #include <sys/types.h> 9 #include <ddk/io-buffer.h> 10 #include <ddk/protocol/usb.h> 11 #include <ddk/protocol/usb/request.h> 12 #include <zircon/hw/usb.h> 13 #include <zircon/listnode.h> 14 15 #include <threads.h> 16 17 __BEGIN_CDECLS; 18 19 // cache maintenance ops 20 #define USB_REQUEST_CACHE_INVALIDATE ZX_VMO_OP_CACHE_INVALIDATE 21 #define USB_REQUEST_CACHE_CLEAN ZX_VMO_OP_CACHE_CLEAN 22 #define USB_REQUEST_CACHE_CLEAN_INVALIDATE ZX_VMO_OP_CACHE_CLEAN_INVALIDATE 23 #define USB_REQUEST_CACHE_SYNC ZX_VMO_OP_CACHE_SYNC 24 25 typedef struct { 26 list_node_t free_reqs; 27 mtx_t lock; 28 //offset of the list_node_t* (used for queueing) in usb_request_t. 29 uint64_t node_offset; 30 } usb_request_pool_t; 31 32 typedef struct { 33 list_node_t node; 34 } usb_req_internal_t; 35 36 #define USB_REQ_TO_REQ_INTERNAL(req, size) \ 37 ((usb_req_internal_t *)((uintptr_t)(req) + (size))) 38 #define REQ_INTERNAL_TO_USB_REQ(ctx, size) ((usb_request_t *)((uintptr_t)(ctx) - (size))) 39 40 // usb_request_alloc() creates a new usb request with payload space of data_size. 41 zx_status_t usb_request_alloc(usb_request_t** out, uint64_t data_size, 42 uint8_t ep_address, size_t req_size); 43 44 // usb_request_alloc_vmo() creates a new usb request with the given VMO. 45 zx_status_t usb_request_alloc_vmo(usb_request_t** out, zx_handle_t vmo_handle, uint64_t vmo_offset, 46 uint64_t length, uint8_t ep_address, size_t req_size); 47 48 // usb_request_init() initializes the statically allocated usb request with the given VMO. 49 // This will free any resources allocated by the usb request but not the usb request itself. 50 zx_status_t usb_request_init(usb_request_t* req, zx_handle_t vmo_handle, 51 uint64_t vmo_offset, uint64_t length, uint8_t ep_address); 52 53 // usb_request_set_sg_list() copies the scatter gather list to the request. 54 // Future transfers using this request will determine where in the VMO to store read / write data 55 // using the scatter gather list. 56 // This will free any existing scatter gather list stored in the request. 57 zx_status_t usb_request_set_sg_list(usb_request_t* req, phys_iter_sg_entry_t* sg_list, 58 size_t sg_count); 59 60 // usb_request_copy_from() copies data from the usb_request's vm object. 61 // Out of range operations are ignored. 62 ssize_t usb_request_copy_from(usb_request_t* req, void* data, size_t length, size_t offset); 63 64 // usb_request_copy_to() copies data into a usb_request's vm object. 65 // Out of range operations are ignored. 66 ssize_t usb_request_copy_to(usb_request_t* req, const void* data, size_t length, size_t offset); 67 68 // usb_request_mmap() maps the usb request's vm object. The 'data' field is set with the 69 // mapped address if this function succeeds. 70 zx_status_t usb_request_mmap(usb_request_t* req, void** data); 71 72 // usb_request_cacheop() performs a cache maintenance op against the request's internal 73 // buffer. 74 zx_status_t usb_request_cacheop(usb_request_t* req, uint32_t op, size_t offset, size_t length); 75 76 // usb_request_cache_flush() performs a cache flush on a range of memory in the request's buffer 77 zx_status_t usb_request_cache_flush(usb_request_t* req, zx_off_t offset, size_t length); 78 79 // usb_request_cache_flush_invalidate() performs a cache flush and invalidate on a range of memory 80 // in the request's buffer 81 zx_status_t usb_request_cache_flush_invalidate(usb_request_t* req, zx_off_t offset, size_t length); 82 83 // Looks up the physical pages backing this request's vm object. 84 zx_status_t usb_request_physmap(usb_request_t* req, zx_handle_t bti_handle); 85 86 // usb_request_release() frees the message data -- should be called only by the entity that allocated it 87 void usb_request_release(usb_request_t* req); 88 89 // usb_request_complete() must be called by the processor when the request has 90 // completed or failed and the request and any virtual or physical memory obtained 91 // from it may not be touched again by the processor. 92 // 93 // The complete_cb() will be called as the last action of this method. 94 void usb_request_complete(usb_request_t* req, zx_status_t status, zx_off_t actual, 95 const usb_request_complete_t* complete_cb); 96 97 // initializes a phys_iter_t for a usb request 98 // max_length is the maximum length of a range returned by usb_request_phys_iter_next() 99 // max_length must be either a positive multiple of PAGE_SIZE, or zero for no limit. 100 void usb_request_phys_iter_init(phys_iter_t* iter, usb_request_t* req, size_t max_length); 101 102 // returns the next physical address and length for the iterator up to size max_length. 103 // return value is length, or zero if iteration is done. 104 size_t usb_request_phys_iter_next(phys_iter_t* iter, zx_paddr_t* out_paddr); 105 106 // usb_request_pool_init() initializes the given pool. A driver may use 107 // a pool for recycling their own usb requests. 108 void usb_request_pool_init(usb_request_pool_t* pool, uint64_t node_offset); 109 110 // usb_request_pool_add() adds the request to the pool. 111 zx_status_t usb_request_pool_add(usb_request_pool_t* pool, usb_request_t* req); 112 113 // returns a request from the pool that has a buffer of the given length, 114 // or null if no such request exists. 115 // The request is not re-initialized in any way and should be set accordingly by the user. 116 usb_request_t* usb_request_pool_get(usb_request_pool_t* pool, size_t length); 117 118 // releases all usb requests stored in the pool. 119 void usb_request_pool_release(usb_request_pool_t* pool); 120 121 // Assumes usb_req_internal_t struct is allocated at parent_req_size offset in a usb request. 122 // Adds a request to the head of the list using the list_node_t pointer from that struct. 123 zx_status_t usb_req_list_add_head(list_node_t* list, usb_request_t* req, size_t parent_req_size); 124 // Assumes usb_req_internal_t is allocated at parent_req_size offset in a usb request. Adds a 125 // request to the tail of the list using the list_node_t pointer from that internal struct. 126 zx_status_t usb_req_list_add_tail(list_node_t* list, usb_request_t* req, size_t parent_req_size); 127 // Assumes usb_req_internal_t is allocated at parent_req_size offset in a usb request. Removes a 128 // request from the head of the list and returns the usb_request_t. 129 usb_request_t* usb_req_list_remove_head(list_node_t* list, size_t parent_req_size); 130 131 __END_CDECLS; 132