Changeset cc63815 in mainline
- Timestamp:
- 2018-02-05T00:54:08Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fdc2253b
- Parents:
- 5c69377
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-02-02 14:35:14)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-02-05 00:54:08)
- Location:
- uspace/lib
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/include/usbhc_iface.h
r5c69377 rcc63815 103 103 } usb_target_t; 104 104 105 // FIXME: DMA buffers shall be part of libdrv anyway. 106 typedef unsigned dma_policy_t; 107 105 108 typedef struct usb_pipe_desc { 106 109 /** Endpoint number. */ -
uspace/lib/usb/include/usb/dma_buffer.h
r5c69377 rcc63815 32 32 * @brief USB host controller library: DMA buffer helpers 33 33 * 34 * Simplifies usage of bounce buffers 34 * Simplifies handling of buffers accessible to hardware. Defines properties of 35 * such buffer, which can be communicated through IPC to allow higher layers to 36 * allocate a buffer that is ready to be passed to HW right away (after being 37 * shared through IPC). 35 38 * 36 * Currently the minimum size allocated is a page, which is wasteful. Could be 37 * extended to support memory pools, which will enable smaller units of 38 * allocation. 39 * Note that although allocated memory is always page-aligned, the buffer itself 40 * may be only a part of it, justifying the existence of page-alignment and 41 * page-crossing flags. 42 * 43 * Also, currently the buffers that are allocated are always contiguous and 44 * page-aligned, regardless of whether the policy requires it. We blindly 45 * believe this fact in dma_buffer_phys, which will yield wrong results if the 46 * buffer is not contiguous. 39 47 */ 40 48 #ifndef LIB_USB_DMA_BUFFER … … 43 51 #include <stdint.h> 44 52 #include <stdlib.h> 53 #include <usbhc_iface.h> 45 54 #include <errno.h> 46 55 47 typedef const struct dma_policy { 48 unsigned flags; 56 #define DMA_POLICY_4GiB (1<<0) /**< Must use only 32-bit addresses */ 57 #define DMA_POLICY_PAGE_ALIGNED (1<<1) /**< The first pointer must be page-aligned */ 58 #define DMA_POLICY_CONTIGUOUS (1<<2) /**< Pages must follow each other physically */ 59 #define DMA_POLICY_NOT_CROSSING (1<<3) /**< Buffer must not cross page boundary. (Implies buffer is no larger than page). */ 49 60 50 #define DMA_POLICY_F_4GiB (1<<0) /**< Must use only 32-bit addresses */ 51 #define DMA_POLICY_F_CONTIGUOUS (1<<1) /**< Pages must follow each other physically */ 52 } dma_policy_t; 61 #define DMA_POLICY_STRICT (-1U) 62 #define DMA_POLICY_DEFAULT DMA_POLICY_STRICT 53 63 54 64 typedef struct dma_buffer { … … 57 67 } dma_buffer_t; 58 68 59 extern int dma_buffer_alloc(dma_buffer_t *db, size_t size);60 extern int dma_buffer_alloc_policy(dma_buffer_t *, size_t, dma_policy_t *);69 extern errno_t dma_buffer_alloc(dma_buffer_t *db, size_t size); 70 extern errno_t dma_buffer_alloc_policy(dma_buffer_t *, size_t, dma_policy_t); 61 71 extern void dma_buffer_free(dma_buffer_t *); 62 72 extern uintptr_t dma_buffer_phys(const dma_buffer_t *, void *); 63 73 64 extern bool dma_buffer_check_policy(const void *, size_t, dma_policy_t *); 74 extern bool dma_buffer_check_policy(const void *, size_t, const dma_policy_t); 75 76 extern errno_t dma_buffer_lock(dma_buffer_t *, void *, size_t); 77 extern void dma_buffer_unlock(dma_buffer_t *, size_t); 65 78 66 79 static inline int dma_buffer_is_set(dma_buffer_t *db) -
uspace/lib/usb/src/dma_buffer.c
r5c69377 rcc63815 39 39 #include "usb/dma_buffer.h" 40 40 41 const dma_policy_t dma_policy_default = { 42 .flags = DMA_POLICY_F_4GiB | DMA_POLICY_F_CONTIGUOUS, 43 }; 44 45 /** 46 * The routine of allocating a DMA buffer. Inlined to force optimization for the47 * default policy.48 * 49 * FIXME: We ignore the non-presence of contiguous flag, for now.50 * /51 static inline int dma_buffer_alloc_internal(dma_buffer_t *db, 52 size_t size, const dma_policy_t *policy)41 /** 42 * Allocate a DMA buffer. 43 * 44 * XXX: Currently cannot make much use of missing constraints, as it always 45 * allocates page-aligned contiguous buffer. We rely on it in dma_buffer_phys. 46 * 47 * @param[in] db dma_buffer_t structure to fill 48 * @param[in] size Size of the required memory space 49 * @param[in] policy dma_policy_t flags to guide the allocation 50 * @return Error code. 51 */ 52 errno_t dma_buffer_alloc_policy(dma_buffer_t *db, size_t size, dma_policy_t policy) 53 53 { 54 54 assert(db); 55 55 56 56 const size_t real_size = ALIGN_UP(size, PAGE_SIZE); 57 const bool need_4gib = !!(policy ->flags & DMA_POLICY_F_4GiB);57 const bool need_4gib = !!(policy & DMA_POLICY_4GiB); 58 58 59 59 const uintptr_t flags = need_4gib ? DMAMEM_4GiB : 0; … … 67 67 68 68 if (ret == EOK) { 69 /* Access the pages to force mapping */ 70 volatile char *buf = address; 71 for (size_t i = 0; i < size; i += PAGE_SIZE) 72 buf[i] = 0xff; 73 69 74 db->virt = address; 70 75 db->phys = phys; … … 73 78 } 74 79 75 /**76 * Allocate a DMA buffer.77 *78 * @param[in] db dma_buffer_t structure to fill79 * @param[in] size Size of the required memory space80 * @param[in] policy dma_policy_t structure to guide81 * @return Error code.82 */83 int dma_buffer_alloc_policy(dma_buffer_t *db, size_t size,84 const dma_policy_t *policy)85 {86 return dma_buffer_alloc_internal(db, size, policy);87 }88 80 89 81 /** … … 94 86 * @return Error code. 95 87 */ 96 int dma_buffer_alloc(dma_buffer_t *db, size_t size)97 { 98 return dma_buffer_alloc_ internal(db, size, &dma_policy_default);88 errno_t dma_buffer_alloc(dma_buffer_t *db, size_t size) 89 { 90 return dma_buffer_alloc_policy(db, size, DMA_POLICY_DEFAULT); 99 91 } 100 92 … … 128 120 * Check whether a memory area is compatible with a policy. 129 121 * 130 * Useful to skip copying, if the buffer is already ready to be given to 131 * hardware. 132 */ 133 bool dma_buffer_check_policy(const void *buffer, size_t size, dma_policy_t *policy) 134 { 135 /* Buffer must be always page aligned */ 136 if (((uintptr_t) buffer) % PAGE_SIZE) 122 * Useful to skip copying when the buffer is already ready to be given to 123 * hardware as is. 124 * 125 * Note that the "as_get_physical_mapping" fails when the page is not mapped 126 * yet, and that the caller is responsible for forcing the mapping. 127 */ 128 bool dma_buffer_check_policy(const void *buffer, size_t size, const dma_policy_t policy) 129 { 130 uintptr_t addr = (uintptr_t) buffer; 131 132 const bool check_4gib = !!(policy & DMA_POLICY_4GiB); 133 const bool check_crossing = !!(policy & DMA_POLICY_NOT_CROSSING); 134 const bool check_alignment = !!(policy & DMA_POLICY_PAGE_ALIGNED); 135 const bool check_contiguous = !!(policy & DMA_POLICY_CONTIGUOUS); 136 137 /* Check the two conditions that are easy */ 138 if (check_crossing && (addr + size - 1) / PAGE_SIZE != addr / PAGE_SIZE) 137 139 goto violated; 138 140 139 const bool check_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);140 const bool check_contiguous = !!(policy->flags & DMA_POLICY_F_CONTIGUOUS);141 if (check_alignment && ((uintptr_t) buffer) % PAGE_SIZE) 142 goto violated; 141 143 142 144 /* … … 145 147 */ 146 148 if (check_contiguous || check_4gib) { 147 const void * 149 const void *virt = buffer; 148 150 uintptr_t phys; 149 151 … … 156 158 goto violated; 157 159 158 while (size <= PAGE_SIZE) {160 while (size >= PAGE_SIZE) { 159 161 /* Move to the next page */ 160 162 virt += PAGE_SIZE; … … 182 184 183 185 /** 186 * Lock an arbitrary buffer for DMA operations, creating a DMA buffer. 187 * 188 * FIXME: To handle page-unaligned buffers, we need to calculate the base 189 * address and lock the whole first page. But as the operation is not yet 190 * implemented in the kernel, it doesn't matter. 191 */ 192 errno_t dma_buffer_lock(dma_buffer_t *db, void *virt, size_t size) 193 { 194 db->virt = virt; 195 return dmamem_map(db->virt, size, 0, 0, &db->phys); 196 } 197 198 /** 199 * Unlock a buffer for DMA operations. 200 */ 201 void dma_buffer_unlock(dma_buffer_t *db, size_t size) 202 { 203 if (db->virt) { 204 dmamem_unmap(db->virt, size); 205 db->virt = NULL; 206 db->phys = 0; 207 } 208 } 209 210 /** 184 211 * @} 185 212 */
Note:
See TracChangeset
for help on using the changeset viewer.