Changeset 3e6ff9a in mainline
- Timestamp:
- 2018-02-01T14:28:41Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e67c50a
- Parents:
- 77ded647
- Location:
- uspace/lib/usb
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/include/usb/dma_buffer.h
r77ded647 r3e6ff9a 32 32 * @brief USB host controller library: DMA buffer helpers 33 33 * 34 * Simplifies usage of bounce buffers .34 * Simplifies usage of bounce buffers 35 35 * 36 36 * Currently the minimum size allocated is a page, which is wasteful. Could be … … 46 46 47 47 typedef const struct dma_policy { 48 bool use64; /**< Whether to use more than initial 4GiB of memory */ 49 size_t alignment; /**< What alignment is needed. At most PAGE_SIZE. */ 48 unsigned flags; 49 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 */ 50 52 } dma_policy_t; 51 53 … … 56 58 57 59 extern int dma_buffer_alloc(dma_buffer_t *db, size_t size); 58 extern int dma_buffer_alloc_policy(dma_buffer_t *, size_t, constdma_policy_t *);60 extern int dma_buffer_alloc_policy(dma_buffer_t *, size_t, dma_policy_t *); 59 61 extern void dma_buffer_free(dma_buffer_t *); 60 62 extern uintptr_t dma_buffer_phys(const dma_buffer_t *, void *); 63 64 extern bool dma_buffer_check_policy(const void *, size_t, dma_policy_t *); 61 65 62 66 static inline int dma_buffer_is_set(dma_buffer_t *db) -
uspace/lib/usb/src/dma_buffer.c
r77ded647 r3e6ff9a 40 40 41 41 const dma_policy_t dma_policy_default = { 42 .use64 = false, 43 .alignment = PAGE_SIZE, 42 .flags = DMA_POLICY_F_4GiB | DMA_POLICY_F_CONTIGUOUS, 44 43 }; 45 44 … … 47 46 * The routine of allocating a DMA buffer. Inlined to force optimization for the 48 47 * default policy. 48 * 49 * FIXME: We ignore the non-presence of contiguous flag, for now. 49 50 */ 50 51 static inline int dma_buffer_alloc_internal(dma_buffer_t *db, … … 53 54 assert(db); 54 55 55 if (policy->alignment > PAGE_SIZE)56 return EINVAL;56 const size_t real_size = ALIGN_UP(size, PAGE_SIZE); 57 const bool need_4gib = !!(policy->flags & DMA_POLICY_F_4GiB); 57 58 58 const size_t aligned_size = ALIGN_UP(size, policy->alignment); 59 const size_t real_size = ALIGN_UP(aligned_size, PAGE_SIZE); 60 const uintptr_t flags = policy->use64 ? 0 : DMAMEM_4GiB; 59 const uintptr_t flags = need_4gib ? DMAMEM_4GiB : 0; 61 60 62 61 uintptr_t phys; … … 127 126 128 127 /** 128 * Check whether a memory area is compatible with a policy. 129 * 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) 137 goto violated; 138 139 const bool check_4gib = !!(policy->flags & DMA_POLICY_F_4GiB); 140 const bool check_contiguous = !!(policy->flags & DMA_POLICY_F_CONTIGUOUS); 141 142 /* 143 * For these conditions, we need to walk through pages and check 144 * physical address of each one 145 */ 146 if (check_contiguous || check_4gib) { 147 const void * virt = buffer; 148 uintptr_t phys; 149 150 /* Get the mapping of the first page */ 151 if (as_get_physical_mapping(virt, &phys)) 152 goto error; 153 154 /* First page can already break 4GiB condition */ 155 if (check_4gib && (phys & DMAMEM_4GiB) != 0) 156 goto violated; 157 158 while (size <= PAGE_SIZE) { 159 /* Move to the next page */ 160 virt += PAGE_SIZE; 161 size -= PAGE_SIZE; 162 163 uintptr_t last_phys = phys; 164 if (as_get_physical_mapping(virt, &phys)) 165 goto error; 166 167 if (check_contiguous && (phys - last_phys) != PAGE_SIZE) 168 goto violated; 169 170 if (check_4gib && (phys & DMAMEM_4GiB) != 0) 171 goto violated; 172 } 173 } 174 175 /* All checks passed */ 176 return true; 177 178 violated: 179 error: 180 return false; 181 } 182 183 /** 129 184 * @} 130 185 */
Note:
See TracChangeset
for help on using the changeset viewer.