Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/ddi/ddi.c

    r3164e3b rc0699467  
    4545#include <mm/frame.h>
    4646#include <mm/as.h>
    47 #include <mm/page.h>
    4847#include <synch/mutex.h>
    4948#include <syscall/copy.h>
     
    5352#include <errno.h>
    5453#include <trace.h>
    55 #include <bitops.h>
    5654
    5755/** This lock protects the parea_btree. */
     
    8987/** Map piece of physical memory into virtual address space of current task.
    9088 *
    91  * @param phys  Physical address of the starting frame.
     89 * @param pf    Physical address of the starting frame.
     90 * @param vp    Virtual address of the starting page.
    9291 * @param pages Number of pages to map.
    9392 * @param flags Address space area flags for the mapping.
    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)
     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 */
     101NO_TRACE static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, size_t pages,
     102    unsigned int flags)
    107103{
    108104        ASSERT(TASK);
    109105       
    110         if ((phys % FRAME_SIZE) != 0)
     106        if ((pf % FRAME_SIZE) != 0)
     107                return EBADMEM;
     108       
     109        if ((vp % PAGE_SIZE) != 0)
    111110                return EBADMEM;
    112111       
     
    119118       
    120119        mem_backend_data_t backend_data;
    121         backend_data.base = phys;
     120        backend_data.base = pf;
    122121        backend_data.frames = pages;
    123122       
     
    130129        btree_node_t *nodep;
    131130        parea_t *parea = (parea_t *) btree_search(&parea_btree,
    132             (btree_key_t) phys, &nodep);
     131            (btree_key_t) pf, &nodep);
    133132       
    134133        if ((parea != NULL) && (parea->frames >= pages)) {
     
    150149       
    151150        irq_spinlock_lock(&zones.lock, true);
    152         size_t znum = find_zone(ADDR2PFN(phys), pages, 0);
     151        size_t znum = find_zone(ADDR2PFN(pf), pages, 0);
    153152       
    154153        if (znum == (size_t) -1) {
     
    166165        }
    167166       
    168         if (zones.info[znum].flags & (ZONE_FIRMWARE | ZONE_RESERVED)) {
    169                 /*
    170                  * Frames are part of firmware or reserved zone
     167        if (zones.info[znum].flags & ZONE_FIRMWARE) {
     168                /*
     169                 * Frames are part of firmware
    171170                 * -> allow mapping for privileged tasks.
    172171                 */
     
    183182       
    184183map:
    185         if (!as_area_create(TASK->as, flags, FRAMES2SIZE(pages),
    186             AS_AREA_ATTR_NONE, &phys_backend, &backend_data, virt, bound)) {
     184        if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
     185            AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
    187186                /*
    188187                 * The address space area was not created.
     
    208207}
    209208
    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 
    250209/** Enable range of I/O space for task.
    251210 *
     
    258217 *
    259218 */
    260 NO_TRACE static int iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
     219NO_TRACE static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr,
     220    size_t size)
    261221{
    262222        /*
     
    283243        /* Lock the task and release the lock protecting tasks_btree. */
    284244        irq_spinlock_exchange(&tasks_lock, &task->lock);
     245       
    285246        int rc = ddi_iospace_enable_arch(task, ioaddr, size);
     247       
    286248        irq_spinlock_unlock(&task->lock, true);
    287249       
    288250        return rc;
     251}
     252
     253/** Wrapper for SYS_PHYSMEM_MAP syscall.
     254 *
     255 * @param phys_base Physical base address to map
     256 * @param virt_base Destination virtual address
     257 * @param pages Number of pages
     258 * @param flags Flags of newly mapped pages
     259 *
     260 * @return 0 on success, otherwise it returns error code found in errno.h
     261 *
     262 */
     263sysarg_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);
    289269}
    290270
     
    303283                return (sysarg_t) rc;
    304284       
    305         return (sysarg_t) iospace_enable((task_id_t) arg.task_id,
     285        return (sysarg_t) ddi_iospace_enable((task_id_t) arg.task_id,
    306286            (uintptr_t) arg.ioaddr, (size_t) arg.size);
    307287}
    308288
    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 
    423289/** @}
    424290 */
Note: See TracChangeset for help on using the changeset viewer.