Subversion Repositories HelenOS

Rev

Rev 1839 | Rev 2012 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2006 Jakub Jermar
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup genericddi
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file
  35.  * @brief   Device Driver Interface functions.
  36.  *
  37.  * This file contains functions that comprise the Device Driver Interface.
  38.  * These are the functions for mapping physical memory and enabling I/O
  39.  * space to tasks.
  40.  */
  41.  
  42. #include <ddi/ddi.h>
  43. #include <ddi/ddi_arg.h>
  44. #include <proc/task.h>
  45. #include <security/cap.h>
  46. #include <mm/frame.h>
  47. #include <mm/as.h>
  48. #include <synch/spinlock.h>
  49. #include <syscall/copy.h>
  50. #include <arch.h>
  51. #include <align.h>
  52. #include <errno.h>
  53.  
  54. /** Map piece of physical memory into virtual address space of current task.
  55.  *
  56.  * @param pf Physical frame address of the starting frame.
  57.  * @param vp Virtual page address of the starting page.
  58.  * @param pages Number of pages to map.
  59.  * @param flags Address space area flags for the mapping.
  60.  *
  61.  * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
  62.  *     ENOENT if there is no task matching the specified ID and ENOMEM if
  63.  *     there was a problem in creating address space area.
  64.  */
  65. static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
  66. {
  67.     ipl_t ipl;
  68.     cap_t caps;
  69.     mem_backend_data_t backend_data;
  70.  
  71.     backend_data.base = pf;
  72.     backend_data.frames = pages;
  73.    
  74.     /*
  75.      * Make sure the caller is authorised to make this syscall.
  76.      */
  77.     caps = cap_get(TASK);
  78.     if (!(caps & CAP_MEM_MANAGER))
  79.         return EPERM;
  80.  
  81.     ipl = interrupts_disable();
  82.     spinlock_lock(&TASK->lock);
  83.    
  84.     if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE,
  85.         &phys_backend, &backend_data)) {
  86.         /*
  87.          * The address space area could not have been created.
  88.          * We report it using ENOMEM.
  89.          */
  90.         spinlock_unlock(&TASK->lock);
  91.         interrupts_restore(ipl);
  92.         return ENOMEM;
  93.     }
  94.    
  95.     /*
  96.      * Mapping is created on-demand during page fault.
  97.      */
  98.    
  99.     spinlock_unlock(&TASK->lock);
  100.     interrupts_restore(ipl);
  101.     return 0;
  102. }
  103.  
  104. /** Enable range of I/O space for task.
  105.  *
  106.  * @param id Task ID of the destination task.
  107.  * @param ioaddr Starting I/O address.
  108.  * @param size Size of the enabled I/O space..
  109.  *
  110.  * @return 0 on success, EPERM if the caller lacks capabilities to use this syscall,
  111.  *     ENOENT if there is no task matching the specified ID.
  112.  */
  113. static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
  114. {
  115.     ipl_t ipl;
  116.     cap_t caps;
  117.     task_t *t;
  118.     int rc;
  119.    
  120.     /*
  121.      * Make sure the caller is authorised to make this syscall.
  122.      */
  123.     caps = cap_get(TASK);
  124.     if (!(caps & CAP_IO_MANAGER))
  125.         return EPERM;
  126.    
  127.     ipl = interrupts_disable();
  128.     spinlock_lock(&tasks_lock);
  129.    
  130.     t = task_find_by_id(id);
  131.    
  132.     if ((!t) || (!context_check(CONTEXT, t->context))) {
  133.         /*
  134.          * There is no task with the specified ID
  135.          * or the task belongs to a different security
  136.          * context.
  137.          */
  138.         spinlock_unlock(&tasks_lock);
  139.         interrupts_restore(ipl);
  140.         return ENOENT;
  141.     }
  142.  
  143.     /* Lock the task and release the lock protecting tasks_btree. */
  144.     spinlock_lock(&t->lock);
  145.     spinlock_unlock(&tasks_lock);
  146.  
  147.     rc = ddi_iospace_enable_arch(t, ioaddr, size);
  148.    
  149.     spinlock_unlock(&t->lock);
  150.     interrupts_restore(ipl);
  151.     return rc;
  152. }
  153.  
  154. /** Wrapper for SYS_MAP_PHYSMEM syscall.
  155.  *
  156.  * @param phys_base Physical base address to map
  157.  * @param virt_base Destination virtual address
  158.  * @param pages Number of pages
  159.  * @param flags Flags of newly mapped pages
  160.  *
  161.  * @return 0 on success, otherwise it returns error code found in errno.h
  162.  */
  163. unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base, unative_t pages,
  164.              unative_t flags)
  165. {
  166.     return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base, FRAME_SIZE),
  167.                       ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE), (count_t) pages,
  168.                       (int) flags);
  169. }
  170.  
  171. /** Wrapper for SYS_ENABLE_IOSPACE syscall.
  172.  *
  173.  * @param uspace_io_arg User space address of DDI argument structure.
  174.  *
  175.  * @return 0 on success, otherwise it returns error code found in errno.h
  176.  */
  177. unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
  178. {
  179.     ddi_ioarg_t arg;
  180.     int rc;
  181.    
  182.     rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
  183.     if (rc != 0)
  184.         return (unative_t) rc;
  185.        
  186.     return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id, (uintptr_t) arg.ioaddr, (size_t) arg.size);
  187. }
  188.  
  189. /** Disable or enable preemption.
  190.  *
  191.  * @param enable If non-zero, the preemption counter will be decremented, leading to potential
  192.  *       enabling of preemption. Otherwise the preemption counter will be incremented,
  193.  *       preventing preemption from occurring.
  194.  *
  195.  * @return Zero on success or EPERM if callers capabilities are not sufficient.
  196.  */
  197. unative_t sys_preempt_control(int enable)
  198. {
  199.         if (! cap_get(TASK) & CAP_PREEMPT_CONTROL)
  200.                 return EPERM;
  201.         if (enable)
  202.                 preemption_enable();
  203.         else
  204.                 preemption_disable();
  205.         return 0;
  206. }
  207.  
  208. /** @}
  209.  */
  210.