Changes in kernel/generic/src/ddi/ddi.c [c0699467:3164e3b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ddi/ddi.c
rc0699467 r3164e3b 45 45 #include <mm/frame.h> 46 46 #include <mm/as.h> 47 #include <mm/page.h> 47 48 #include <synch/mutex.h> 48 49 #include <syscall/copy.h> … … 52 53 #include <errno.h> 53 54 #include <trace.h> 55 #include <bitops.h> 54 56 55 57 /** This lock protects the parea_btree. */ … … 87 89 /** Map piece of physical memory into virtual address space of current task. 88 90 * 89 * @param pf Physical address of the starting frame. 90 * @param vp Virtual address of the starting page. 91 * @param phys Physical address of the starting frame. 91 92 * @param pages Number of pages to map. 92 93 * @param flags Address space area flags for the mapping. 93 * 94 * @return 0 on success, EPERM if the caller lacks capabilities to use this 95 * syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there 96 * is no task matching the specified ID or the physical address space 97 * is not enabled for mapping and ENOMEM if there was a problem in 98 * creating address space area. 99 * 100 */ 101 NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages, 102 unsigned int flags) 94 * @param virt Virtual address of the starting page. 95 * @param bound Lowest virtual address bound. 96 * 97 * @return EOK on success. 98 * @return EPERM if the caller lacks capabilities to use this syscall. 99 * @return EBADMEM if phys is not page aligned. 100 * @return ENOENT if there is no task matching the specified ID or 101 * the physical address space is not enabled for mapping. 102 * @return ENOMEM if there was a problem in creating address space area. 103 * 104 */ 105 NO_TRACE static int physmem_map(uintptr_t phys, size_t pages, 106 unsigned int flags, uintptr_t *virt, uintptr_t bound) 103 107 { 104 108 ASSERT(TASK); 105 109 106 if ((pf % FRAME_SIZE) != 0) 107 return EBADMEM; 108 109 if ((vp % PAGE_SIZE) != 0) 110 if ((phys % FRAME_SIZE) != 0) 110 111 return EBADMEM; 111 112 … … 118 119 119 120 mem_backend_data_t backend_data; 120 backend_data.base = p f;121 backend_data.base = phys; 121 122 backend_data.frames = pages; 122 123 … … 129 130 btree_node_t *nodep; 130 131 parea_t *parea = (parea_t *) btree_search(&parea_btree, 131 (btree_key_t) p f, &nodep);132 (btree_key_t) phys, &nodep); 132 133 133 134 if ((parea != NULL) && (parea->frames >= pages)) { … … 149 150 150 151 irq_spinlock_lock(&zones.lock, true); 151 size_t znum = find_zone(ADDR2PFN(p f), pages, 0);152 size_t znum = find_zone(ADDR2PFN(phys), pages, 0); 152 153 153 154 if (znum == (size_t) -1) { … … 165 166 } 166 167 167 if (zones.info[znum].flags & ZONE_FIRMWARE) {168 /* 169 * Frames are part of firmware 168 if (zones.info[znum].flags & (ZONE_FIRMWARE | ZONE_RESERVED)) { 169 /* 170 * Frames are part of firmware or reserved zone 170 171 * -> allow mapping for privileged tasks. 171 172 */ … … 182 183 183 184 map: 184 if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,185 AS_AREA_ATTR_NONE, &phys_backend, &backend_data )) {185 if (!as_area_create(TASK->as, flags, FRAMES2SIZE(pages), 186 AS_AREA_ATTR_NONE, &phys_backend, &backend_data, virt, bound)) { 186 187 /* 187 188 * The address space area was not created. … … 207 208 } 208 209 210 NO_TRACE static int physmem_unmap(uintptr_t virt) 211 { 212 // TODO: implement unmap 213 return EOK; 214 } 215 216 /** Wrapper for SYS_PHYSMEM_MAP syscall. 217 * 218 * @param phys Physical base address to map 219 * @param pages Number of pages 220 * @param flags Flags of newly mapped pages 221 * @param virt_ptr Destination virtual address 222 * @param bound Lowest virtual address bound. 223 * 224 * @return 0 on success, otherwise it returns error code found in errno.h 225 * 226 */ 227 sysarg_t sys_physmem_map(uintptr_t phys, size_t pages, unsigned int flags, 228 void *virt_ptr, uintptr_t bound) 229 { 230 uintptr_t virt = (uintptr_t) -1; 231 int rc = physmem_map(ALIGN_DOWN(phys, FRAME_SIZE), pages, flags, 232 &virt, bound); 233 if (rc != EOK) 234 return rc; 235 236 rc = copy_to_uspace(virt_ptr, &virt, sizeof(virt)); 237 if (rc != EOK) { 238 physmem_unmap((uintptr_t) virt); 239 return rc; 240 } 241 242 return EOK; 243 } 244 245 sysarg_t sys_physmem_unmap(uintptr_t virt) 246 { 247 return physmem_unmap(virt); 248 } 249 209 250 /** Enable range of I/O space for task. 210 251 * … … 217 258 * 218 259 */ 219 NO_TRACE static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, 220 size_t size) 260 NO_TRACE static int iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size) 221 261 { 222 262 /* … … 243 283 /* Lock the task and release the lock protecting tasks_btree. */ 244 284 irq_spinlock_exchange(&tasks_lock, &task->lock); 245 246 285 int rc = ddi_iospace_enable_arch(task, ioaddr, size); 247 248 286 irq_spinlock_unlock(&task->lock, true); 249 287 250 288 return rc; 251 }252 253 /** Wrapper for SYS_PHYSMEM_MAP syscall.254 *255 * @param phys_base Physical base address to map256 * @param virt_base Destination virtual address257 * @param pages Number of pages258 * @param flags Flags of newly mapped pages259 *260 * @return 0 on success, otherwise it returns error code found in errno.h261 *262 */263 sysarg_t sys_physmem_map(sysarg_t phys_base, sysarg_t virt_base,264 sysarg_t pages, sysarg_t flags)265 {266 return (sysarg_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,267 FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),268 (size_t) pages, (int) flags);269 289 } 270 290 … … 283 303 return (sysarg_t) rc; 284 304 285 return (sysarg_t) ddi_iospace_enable((task_id_t) arg.task_id,305 return (sysarg_t) iospace_enable((task_id_t) arg.task_id, 286 306 (uintptr_t) arg.ioaddr, (size_t) arg.size); 287 307 } 288 308 309 sysarg_t sys_iospace_disable(ddi_ioarg_t *uspace_io_arg) 310 { 311 // TODO: implement 312 return ENOTSUP; 313 } 314 315 NO_TRACE static int dmamem_map(uintptr_t virt, size_t size, unsigned int map_flags, 316 unsigned int flags, void **phys) 317 { 318 ASSERT(TASK); 319 320 // TODO: implement locking of non-anonymous mapping 321 return page_find_mapping(virt, phys); 322 } 323 324 NO_TRACE static int dmamem_map_anonymous(size_t size, unsigned int map_flags, 325 unsigned int flags, void **phys, uintptr_t *virt, uintptr_t bound) 326 { 327 ASSERT(TASK); 328 329 size_t pages = SIZE2FRAMES(size); 330 uint8_t order; 331 332 /* We need the 2^order >= pages */ 333 if (pages == 1) 334 order = 0; 335 else 336 order = fnzb(pages - 1) + 1; 337 338 *phys = frame_alloc_noreserve(order, 0); 339 if (*phys == NULL) 340 return ENOMEM; 341 342 mem_backend_data_t backend_data; 343 backend_data.base = (uintptr_t) *phys; 344 backend_data.frames = pages; 345 346 if (!as_area_create(TASK->as, map_flags, size, 347 AS_AREA_ATTR_NONE, &phys_backend, &backend_data, virt, bound)) { 348 frame_free_noreserve((uintptr_t) *phys); 349 return ENOMEM; 350 } 351 352 return EOK; 353 } 354 355 NO_TRACE static int dmamem_unmap(uintptr_t virt, size_t size) 356 { 357 // TODO: implement unlocking & unmap 358 return EOK; 359 } 360 361 NO_TRACE static int dmamem_unmap_anonymous(uintptr_t virt) 362 { 363 // TODO: implement unlocking & unmap 364 return EOK; 365 } 366 367 sysarg_t sys_dmamem_map(size_t size, unsigned int map_flags, unsigned int flags, 368 void *phys_ptr, void *virt_ptr, uintptr_t bound) 369 { 370 if ((flags & DMAMEM_FLAGS_ANONYMOUS) == 0) { 371 /* 372 * Non-anonymous DMA mapping 373 */ 374 375 void *phys; 376 int rc = dmamem_map((uintptr_t) virt_ptr, size, map_flags, 377 flags, &phys); 378 379 if (rc != EOK) 380 return rc; 381 382 rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys)); 383 if (rc != EOK) { 384 dmamem_unmap((uintptr_t) virt_ptr, size); 385 return rc; 386 } 387 } else { 388 /* 389 * Anonymous DMA mapping 390 */ 391 392 void *phys; 393 uintptr_t virt = (uintptr_t) -1; 394 int rc = dmamem_map_anonymous(size, map_flags, flags, 395 &phys, &virt, bound); 396 if (rc != EOK) 397 return rc; 398 399 rc = copy_to_uspace(phys_ptr, &phys, sizeof(phys)); 400 if (rc != EOK) { 401 dmamem_unmap_anonymous((uintptr_t) virt); 402 return rc; 403 } 404 405 rc = copy_to_uspace(virt_ptr, &virt, sizeof(virt)); 406 if (rc != EOK) { 407 dmamem_unmap_anonymous((uintptr_t) virt); 408 return rc; 409 } 410 } 411 412 return EOK; 413 } 414 415 sysarg_t sys_dmamem_unmap(uintptr_t virt, size_t size, unsigned int flags) 416 { 417 if ((flags & DMAMEM_FLAGS_ANONYMOUS) == 0) 418 return dmamem_unmap(virt, size); 419 else 420 return dmamem_unmap_anonymous(virt); 421 } 422 289 423 /** @} 290 424 */
Note:
See TracChangeset
for help on using the changeset viewer.