ddi.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Jakub Jermar
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00042 #include <ddi/ddi.h>
00043 #include <ddi/ddi_arg.h>
00044 #include <proc/task.h>
00045 #include <security/cap.h>
00046 #include <mm/frame.h>
00047 #include <mm/as.h>
00048 #include <synch/spinlock.h>
00049 #include <syscall/copy.h>
00050 #include <arch.h>
00051 #include <align.h>
00052 #include <errno.h>
00053 
00065 static int ddi_physmem_map(__address pf, __address vp, count_t pages, int flags)
00066 {
00067         ipl_t ipl;
00068         cap_t caps;
00069         mem_backend_data_t backend_data;
00070 
00071         backend_data.base = pf;
00072         backend_data.frames = pages;
00073         
00074         /*
00075          * Make sure the caller is authorised to make this syscall.
00076          */
00077         caps = cap_get(TASK);
00078         if (!(caps & CAP_MEM_MANAGER))
00079                 return EPERM;
00080 
00081         ipl = interrupts_disable();
00082         spinlock_lock(&TASK->lock);
00083         
00084         if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE,
00085                 &phys_backend, &backend_data)) {
00086                 /*
00087                  * The address space area could not have been created.
00088                  * We report it using ENOMEM.
00089                  */
00090                 spinlock_unlock(&TASK->lock);
00091                 interrupts_restore(ipl);
00092                 return ENOMEM;
00093         }
00094         
00095         /*
00096          * Mapping is created on-demand during page fault.
00097          */
00098         
00099         spinlock_unlock(&TASK->lock);
00100         interrupts_restore(ipl);
00101         return 0;
00102 }
00103 
00113 static int ddi_iospace_enable(task_id_t id, __address ioaddr, size_t size)
00114 {
00115         ipl_t ipl;
00116         cap_t caps;
00117         task_t *t;
00118         int rc;
00119         
00120         /*
00121          * Make sure the caller is authorised to make this syscall.
00122          */
00123         caps = cap_get(TASK);
00124         if (!(caps & CAP_IO_MANAGER))
00125                 return EPERM;
00126         
00127         ipl = interrupts_disable();
00128         spinlock_lock(&tasks_lock);
00129         
00130         t = task_find_by_id(id);
00131         
00132         if (!t) {
00133                 /*
00134                  * There is no task with the specified ID.
00135                  */
00136                 spinlock_unlock(&tasks_lock);
00137                 interrupts_restore(ipl);
00138                 return ENOENT;
00139         }
00140 
00141         /* Lock the task and release the lock protecting tasks_btree. */
00142         spinlock_lock(&t->lock);
00143         spinlock_unlock(&tasks_lock);
00144 
00145         rc = ddi_iospace_enable_arch(t, ioaddr, size);
00146         
00147         spinlock_unlock(&t->lock);
00148         interrupts_restore(ipl);
00149         return rc;
00150 }
00151 
00161 __native sys_physmem_map(__native phys_base, __native virt_base, __native pages, 
00162                          __native flags)
00163 {
00164         return (__native) ddi_physmem_map(ALIGN_DOWN((__address) phys_base, FRAME_SIZE),
00165                                           ALIGN_DOWN((__address) virt_base, PAGE_SIZE), (count_t) pages,
00166                                           (int) flags);
00167 }
00168 
00175 __native sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
00176 {
00177         ddi_ioarg_t arg;
00178         int rc;
00179         
00180         rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
00181         if (rc != 0)
00182                 return (__native) rc;
00183                 
00184         return (__native) ddi_iospace_enable((task_id_t) arg.task_id, (__address) arg.ioaddr, (size_t) arg.size);
00185 }
00186 
00195 __native sys_preempt_control(int enable)
00196 {
00197         if (! cap_get(TASK) & CAP_PREEMPT_CONTROL)
00198                 return EPERM;
00199         if (enable)
00200                 preemption_enable();
00201         else
00202                 preemption_disable();
00203         return 0;
00204 }
00205 

Generated on Sun Jun 18 17:28:03 2006 for HelenOS Kernel (ppc64) by  doxygen 1.4.6