- Moved generic_handler() from system.c to system/do_irqctl.c.
- Set privileges of system processes somewhat stricter.
EXTERN int mon_return; /* true if we can return to monitor */
/* Variables that are initialized elsewhere are just extern here. */
-extern struct system_image image[]; /* system image processes */
+extern struct boot_image image[]; /* system image processes */
extern char *t_stack[]; /* task stack space */
extern struct segdesc_s gdt[]; /* global descriptor table */
*/
#define EMPTY_MASK (0)
#define FILLED_MASK (~0)
+#define TASK_CALL_MASK (1 << RECEIVE)
#define USER_CALL_MASK ((1 << SENDREC) | (1 << ECHO))
/* Send masks determine to whom processes can send messages or notifications.
FORWARD _PROTOTYPE( void announce, (void));
FORWARD _PROTOTYPE( void shutdown, (timer_t *tp));
-#define SHUTDOWN_TICKS 5 /* time allowed to do cleanup */
-
/*===========================================================================*
* main *
PUBLIC void main()
{
/* Start the ball rolling. */
- struct system_image *ip; /* boot image pointer */
+ struct boot_image *ip; /* boot image pointer */
register struct proc *rp; /* process pointer */
register struct priv *sp; /* privilege structure pointer */
register int i, s;
int how;
{
/* This function prepares to shutdown MINIX. */
- register struct proc *rp;
static timer_t shutdown_timer;
+ register struct proc *rp;
message m;
/* Show debugging dumps on panics. Make sure that the TTY task is still
*/
kprintf("MINIX will now be shut down ...\n");
tmr_arg(&shutdown_timer)->ta_int = how;
- set_timer(&shutdown_timer, get_uptime() + SHUTDOWN_TICKS, shutdown);
+ set_timer(&shutdown_timer, get_uptime() + HZ, shutdown);
}
vir_bytes vir_addr, vir_bytes bytes) );
_PROTOTYPE( phys_bytes umap_bios, (struct proc *rp, vir_bytes vir_addr,
vir_bytes bytes) );
-_PROTOTYPE( int generic_handler, (irq_hook_t *hook) );
#if (CHIP == INTEL)
* numap_local: umap_local D segment from proc nr instead of pointer
* virtual_copy: copy bytes from one virtual address to another
* get_randomness: accumulate randomness in a buffer
- * generic_handler: interrupt handler for user-level device drivers
*
* Changes:
- * Apr 25, 2005 made mapping of call vector explicit (Jorrit N. Herder)
- * Oct 17, 2004 generic handler and IRQ policies (Jorrit N. Herder)
* Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder)
* Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
- * Sep 10, 2004 system call functions in library (Jorrit N. Herder)
- * 2004 to 2005 various new syscalls (see syslib.h) (Jorrit N. Herder)
+ * 2004 to 2005 various new syscalls (see system.h) (Jorrit N. Herder)
*/
#include "kernel.h"
if (sp->s_proc_nr != NONE) return(ENOSPC);
rc->p_priv = sp; /* assign new slot */
rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
+ rc->p_priv->s_flags = SYS_PROC; /* mark as privileged */
} else {
rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */
rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */
}
-/*===========================================================================*
- * generic_handler *
- *===========================================================================*/
-PUBLIC int generic_handler(hook)
-irq_hook_t *hook;
-{
-/* This function handles hardware interrupt in a simple and generic way. All
- * interrupts are transformed into messages to a driver. The IRQ line will be
- * reenabled if the policy says so.
- */
-
- /* As a side-effect, the interrupt handler gathers random information by
- * timestamping the interrupt events. This is used for /dev/random.
- */
- get_randomness(hook->irq);
-
- /* Add a bit for this interrupt to the process' pending interrupts. When
- * sending the notification message, this bit map will be magically set
- * as an argument.
- */
- priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id);
-
- /* Build notification message and return. */
- lock_notify(HARDWARE, hook->proc_nr);
- return(hook->policy & IRQ_REENABLE);
-}
-
-
/*===========================================================================*
* send_sig *
*===========================================================================*/
$(SYSTEM)(do_trace.o) \
$(SYSTEM)(do_nice.o) \
$(SYSTEM)(do_times.o) \
- $(SYSTEM)(do_alarm.o) \
+ $(SYSTEM)(do_setalarm.o) \
$(SYSTEM)(do_irqctl.o) \
$(SYSTEM)(do_devio.o) \
$(SYSTEM)(do_vdevio.o) \
$(SYSTEM)(do_times.o): do_times.c
$(CC) do_times.c
-$(SYSTEM)(do_alarm.o): do_alarm.c
- $(CC) do_alarm.c
+$(SYSTEM)(do_setalarm.o): do_setalarm.c
+ $(CC) do_setalarm.c
$(SYSTEM)(do_irqctl.o): do_irqctl.c
$(CC) do_irqctl.c
message *m_ptr; /* pointer to request message */
{
/* Handle sys_abort. MINIX is unable to continue. This can originate in the
- * PM (normal abort or panic) or FS (panic), or TTY (user issued CTRL-ALT-DEL
- * or ESC after debugging dumps).
+ * PM (normal abort or panic) or FS (panic), or TTY (after CTRL-ALT-DEL).
*/
int how = m_ptr->ABRT_HOW;
+ int proc_nr;
+ int length;
+ phys_bytes src_phys;
/* See if the monitor is to run the specified instructions. */
if (how == RBT_MONITOR) {
- int proc_nr = m_ptr->ABRT_MON_PROC;
- int length = m_ptr->ABRT_MON_LEN + 1;
- vir_bytes src_vir = (vir_bytes) m_ptr->ABRT_MON_ADDR;
- phys_bytes src_phys = numap_local(proc_nr, src_vir, length);
-
- /* Validate length and address of shutdown code before copying. */
- if (length > kinfo.params_size || src_phys == 0)
- phys_copy(vir2phys("delay;boot"), kinfo.params_base, 11);
- else
- phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
+
+ proc_nr = m_ptr->ABRT_MON_PROC;
+ if (! isokprocn(proc_nr)) return(EINVAL);
+ length = m_ptr->ABRT_MON_LEN + 1;
+ if (length > kinfo.params_size) return(E2BIG);
+ src_phys = numap_local(proc_nr,(vir_bytes)m_ptr->ABRT_MON_ADDR,length);
+ if (! src_phys) return(EFAULT);
+
+ /* Parameters seem ok, copy them and prepare shutting down. */
+ phys_copy(src_phys, kinfo.params_base, (phys_bytes) length);
}
/* Now prepare to shutdown MINIX. */
*/
register struct proc *rp;
+ /* Get process pointer and verify that it had signals pending. If the
+ * process is already dead its flags will be reset.
+ */
rp = proc_addr(m_ptr->SIG_PROC);
- if (isemptyp(rp)) return(EINVAL); /* process already dead? */
+ if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL);
/* PM has finished one kernel signal. Perhaps process is ready now? */
if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */
* The parameters for this system call are:
* m1_i1: PR_PROC_NR (child's process table slot)
* m1_i2: PR_PPROC_NR (parent, process that forked)
- * m1_i3: PR_PID (child pid received from PM)
*/
#include "../system.h"
rpc = proc_addr(m_ptr->PR_PROC_NR);
if (isemptyp(rpp) || ! isemptyp(rpc)) return(EINVAL);
+ /* If this is a system process, make sure the child process gets its own
+ * privilege structure for accounting. This is the only part that can fail,
+ * so do this before allocating the process table slot.
+ */
+ if (priv(rpc)->s_flags & SYS_PROC) {
+ if (OK != (i=get_priv(rpc, SYS_PROC))) return(i); /* get structure */
+ for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++) /* remove pending: */
+ priv(rpc)->s_notify_pending.chunk[i] = 0; /* - notifications */
+ priv(rpc)->s_int_pending = 0; /* - interrupts */
+ sigemptyset(&priv(rpc)->s_sig_pending); /* - signals */
+ }
+
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
#if (CHIP == INTEL)
old_ldt_sel = rpc->p_ldt_sel; /* backup local descriptors */
rpc->p_user_time = 0; /* set all the accounting times to 0 */
rpc->p_sys_time = 0;
- /* If this is a system process, make sure the child process gets its own
- * privilege structure for accounting.
- */
- if (priv(rpc)->s_flags & SYS_PROC) {
- if (OK != (i=get_priv(rpc, SYS_PROC))) return(i); /* get structure */
- for (i=0; i< BITMAP_CHUNKS(NR_SYS_PROCS); i++) /* remove pending: */
- priv(rpc)->s_notify_pending.chunk[i] = 0; /* - notifications */
- priv(rpc)->s_int_pending = 0; /* - interrupts */
- sigemptyset(&priv(rpc)->s_sig_pending); /* - signals */
- }
return(OK);
}
*
* The parameters for this system call are:
* m1_i3: I_REQUEST (what info to get)
- * m1_i4: I_PROC_NR (process to store value at)
* m1_p1: I_VAL_PTR (where to put it)
* m1_i1: I_VAL_LEN (maximum length expected, optional)
* m1_p2: I_VAL_PTR2 (second, optional pointer)
break;
}
case GET_IMAGE: {
- length = sizeof(struct system_image) * NR_BOOT_PROCS;
+ length = sizeof(struct boot_image) * NR_BOOT_PROCS;
src_phys = vir2phys(image);
break;
}
* m5_c1: IRQ_REQUEST (control operation to perform)
* m5_c2: IRQ_VECTOR (irq line that must be controlled)
* m5_i1: IRQ_POLICY (irq policy allows reenabling interrupts)
- * m5_l3: IRQ_HOOK_ID (index of irq hook assigned at kernel)
+ * m5_l3: IRQ_HOOK_ID (provides index to be returned on interrupt)
+ * ,, ,, (returns index of irq hook assigned at kernel)
*
* Author:
* Jorrit N. Herder <jnherder@cs.vu.nl>
#include "../system.h"
+
#if USE_IRQCTL
+FORWARD _PROTOTYPE(int generic_handler, (irq_hook_t *hook));
+
/*===========================================================================*
* do_irqctl *
*===========================================================================*/
return(r);
}
+
+/*===========================================================================*
+ * generic_handler *
+ *===========================================================================*/
+PRIVATE int generic_handler(hook)
+irq_hook_t *hook;
+{
+/* This function handles hardware interrupt in a simple and generic way. All
+ * interrupts are transformed into messages to a driver. The IRQ line will be
+ * reenabled if the policy says so.
+ */
+
+ /* As a side-effect, the interrupt handler gathers random information by
+ * timestamping the interrupt events. This is used for /dev/random.
+ */
+ get_randomness(hook->irq);
+
+ /* Add a bit for this interrupt to the process' pending interrupts. When
+ * sending the notification message, this bit map will be magically set
+ * as an argument.
+ */
+ priv(proc_addr(hook->proc_nr))->s_int_pending |= (1 << hook->notify_id);
+
+ /* Build notification message and return. */
+ lock_notify(HARDWARE, hook->proc_nr);
+ return(hook->policy & IRQ_REENABLE);
+}
+
#endif /* USE_IRQCTL */
int sig_nr = m_ptr->SIG_NUMBER;
if (! isokprocn(proc_nr) || sig_nr > _NSIG) return(EINVAL);
+ if (iskerneln(proc_nr)) return(EPERM);
if (m_ptr->m_source == PM_PROC_NR) {
/* Directly send signal notification to a system process. */
* m_type: SYS_MEMSET
*
* The parameters for this system call are:
- * m1_p1: MEM_PTR (virtual address)
- * m1_i1: MEM_COUNT (returns physical address)
- * m1_i2: MEM_PATTERN (size of datastructure)
+ * m2_p1: MEM_PTR (virtual address)
+ * m2_l1: MEM_COUNT (returns physical address)
+ * m2_l2: MEM_PATTERN (size of datastructure)
*/
#include "../system.h"
caller = m_ptr->m_source;
map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR;
if (! isokprocn(m_ptr->PR_PROC_NR)) return(EINVAL);
+ if (iskerneln(m_ptr->PR_PROC_NR)) return(EPERM);
rp = proc_addr(m_ptr->PR_PROC_NR);
/* Copy the map from PM. */
/* Extract the message parameters and do sanity checking. */
proc_nr = m_ptr->PR_PROC_NR;
if (! isokprocn(proc_nr)) return(EINVAL);
+ if (iskerneln(proc_nr)) return(EPERM);
pri = m_ptr->PR_PRIORITY;
if (pri < PRIO_MIN || pri > PRIO_MAX) return(EINVAL);
/* Make sure this process has its own privileges structure. */
if (! (priv(rp)->s_flags & SYS_PROC))
- get_priv(rp, SYS_PROC);
+ if ((i=get_priv(rp, SYS_PROC)) != OK) return(i);
/* Now update the process' privileges as requested. */
rp->p_priv->s_call_mask = FILLED_MASK;
long port = m_ptr->DIO_PORT;
phys_bytes phys_buf;
- /* Check if process number is OK. */
+ /* Check if process number is OK. A process number is allowed here, because
+ * driver may directly provide a pointer to a buffer at the user-process
+ * that initiated the device I/O. Kernel processes, of course, are denied.
+ */
if (proc_nr == SELF) proc_nr = m_ptr->m_source;
- if (! isokprocn(proc_nr))
- return(EINVAL);
+ if (! isokprocn(proc_nr)) return(EINVAL);
+ if (iskerneln(proc_nr)) return(EPERM);
/* Get and check physical address. */
if ((phys_buf = numap_local(proc_nr, (vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
message *m_ptr; /* pointer to request message */
{
/* A process requests a synchronous alarm, or wants to cancel its alarm. */
+ register struct proc *rp; /* pointer to requesting process */
int proc_nr; /* which process wants the alarm */
long exp_time; /* expiration time for this alarm */
int use_abs_time; /* use absolute or relative time */
clock_t uptime; /* placeholder for current uptime */
/* Extract shared parameters from the request message. */
- proc_nr = m_ptr->m_source; /* process to interrupt later */
exp_time = m_ptr->ALRM_EXP_TIME; /* alarm's expiration time */
use_abs_time = m_ptr->ALRM_ABS_TIME; /* flag for absolute time */
+ proc_nr = m_ptr->m_source; /* process to interrupt later */
+ rp = proc_addr(proc_nr);
+ if (! (priv(rp)->s_flags & SYS_PROC)) return(EPERM);
/* Get the timer structure and set the parameters for this alarm. */
- tp = &(proc_addr(proc_nr)->p_priv->s_alarm_timer);
+ tp = &(priv(rp)->s_alarm_timer);
tmr_arg(tp)->ta_int = proc_nr;
tp->tmr_func = cause_alarm;
register struct proc *rp;
phys_bytes src_phys;
+ if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL);
+ if (iskerneln(m_ptr->SIG_PROC)) return(EPERM);
rp = proc_addr(m_ptr->SIG_PROC);
/* Copy in the sigcontext structure. */
struct sigcontext sc, *scp;
struct sigframe fr, *frp;
+ if (! isokprocn(m_ptr->SIG_PROC)) return(EINVAL);
+ if (iskerneln(m_ptr->SIG_PROC)) return(EPERM);
rp = proc_addr(m_ptr->SIG_PROC);
/* Get the sigmsg structure into our address space. */
int tr_proc_nr = m_ptr->CTL_PROC_NR;
int i;
+ if (! isokprocn(tr_proc_nr)) return(EINVAL);
+ if (iskerneln(tr_proc_nr)) return(EPERM);
+
rp = proc_addr(tr_proc_nr);
if (isemptyp(rp)) return(EIO);
switch (tr_request) {
* m_type: SYS_VIRVCOPY, SYS_PHYSVCOPY
*
* The parameters for this system call are:
- * m5_c1: CP_SRC_SPACE
- * m5_l1: CP_SRC_ADDR
- * m5_i1: CP_SRC_PROC_NR
- * m5_c2: CP_DST_SPACE
- * m5_l2: CP_DST_ADDR
- * m5_i2: CP_DST_PROC_NR
- * m5_l3: CP_NR_BYTES
+ * m1_i3: VCP_VEC_SIZE size of copy request vector
+ * m1_p1: VCP_VEC_ADDR address of vector at caller
+ * m1_i2: VCP_NR_OK number of successfull copies
*/
#include "../system.h"
phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
/* Assume vector with requests is correct. Try to copy everything. */
+ m_ptr->VCP_NR_OK = 0;
for (i=0; i<nr_req; i++) {
req = &vir_cp_req[i];
/* Check if physical addressing is used without SYS_PHYSVCOPY. */
if (((req->src.segment | req->dst.segment) & PHYS_SEG) &&
- m_ptr->m_type != SYS_PHYSVCOPY)
- return(EPERM);
+ m_ptr->m_type != SYS_PHYSVCOPY) return(EPERM);
if ((s=virtual_copy(&req->src, &req->dst, req->count)) != OK)
return(s);
+ m_ptr->VCP_NR_OK ++;
}
return(OK);
}
#if USE_VDEVIO
/* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
-PRIVATE char vdevio_pv_buf[VDEVIO_BUF_SIZE];
+PRIVATE char vdevio_buf[VDEVIO_BUF_SIZE];
+PRIVATE pvb_pair_t *pvb = (pvb_pair_t *) vdevio_buf;
+PRIVATE pvw_pair_t *pvw = (pvw_pair_t *) vdevio_buf;
+PRIVATE pvl_pair_t *pvl = (pvl_pair_t *) vdevio_buf;
-/* SYS_VDEVIO sends a pointer to a (port,value)-pairs vector at the caller.
- * Define the maximum number of (port,value)-pairs that can be handled in a
- * in a single SYS_VDEVIO system call based on the struct definitions.
- */
-#define MAX_PVB_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvb_pair_t))
-#define MAX_PVW_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvw_pair_t))
-#define MAX_PVL_PAIRS ((VDEVIO_BUF_SIZE * sizeof(char)) / sizeof(pvl_pair_t))
-
/*===========================================================================*
* do_vdevio *
* that I/O batch from being interrrupted.
* This is the counterpart of do_devio, which performs a single device I/O.
*/
- pvb_pair_t *pvb_pairs; /* needed for byte values */
- pvw_pair_t *pvw_pairs; /* needed for word values */
- pvl_pair_t *pvl_pairs; /* needed for long values */
- int i;
- int caller_proc; /* process number of caller */
- size_t bytes; /* # bytes to be copied */
- vir_bytes caller_vir; /* virtual address at caller */
- phys_bytes caller_phys; /* physical address at caller */
- phys_bytes kernel_phys; /* physical address in kernel */
-
-
- /* Check if nr of ports is ok and get size of (port,value) data. */
- if (m_ptr->DIO_VEC_SIZE <= 0) return(EINVAL);
- switch(m_ptr->DIO_TYPE) {
- case DIO_BYTE:
- if (m_ptr->DIO_VEC_SIZE > MAX_PVB_PAIRS) return(EINVAL);
- bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvb_pair_t));
- break;
- case DIO_WORD:
- if (m_ptr->DIO_VEC_SIZE > MAX_PVW_PAIRS) return(EINVAL);
- bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvw_pair_t));
- break;
- case DIO_LONG:
- if (m_ptr->DIO_VEC_SIZE > MAX_PVL_PAIRS) return(EINVAL);
- bytes = (size_t) (m_ptr->DIO_VEC_SIZE * sizeof(pvl_pair_t));
- break;
- default: /* this once and for all checks for a correct type */
- return(EINVAL);
- }
+ int vec_size; /* size of vector */
+ int io_in; /* true if input */
+ size_t bytes; /* # bytes to be copied */
+ int caller_proc; /* process number of caller */
+ vir_bytes caller_vir; /* virtual address at caller */
+ phys_bytes caller_phys; /* physical address at caller */
+ int i;
+
+ /* Get the request, size of the request vector, and check the values. */
+ if (m_ptr->DIO_REQUEST == DIO_INPUT) io_in = TRUE;
+ else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) io_in = FALSE;
+ else return(EINVAL);
+ if ((vec_size = m_ptr->DIO_VEC_SIZE) <= 0) return(EINVAL);
+ switch (m_ptr->DIO_TYPE) {
+ case DIO_BYTE: bytes = vec_size * sizeof(pvb_pair_t); break;
+ case DIO_WORD: bytes = vec_size * sizeof(pvw_pair_t); break;
+ case DIO_LONG: bytes = vec_size * sizeof(pvl_pair_t); break;
+ default: return(EINVAL); /* check type once and for all */
+ }
+ if (bytes > sizeof(vdevio_buf)) return(E2BIG);
- /* Calculate physical addresses and copy (port,value)-pairs from user. */
- caller_proc = m_ptr->m_source;
- caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
- caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
- if (0 == caller_phys) return EFAULT;
- kernel_phys = vir2phys(vdevio_pv_buf);
- phys_copy(caller_phys, kernel_phys, (phys_bytes) bytes);
+ /* Calculate physical addresses and copy (port,value)-pairs from user. */
+ caller_proc = m_ptr->m_source;
+ caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
+ caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
+ if (0 == caller_phys) return(EFAULT);
+ phys_copy(caller_phys, vir2phys(vdevio_buf), (phys_bytes) bytes);
- /* Perform actual device I/O for byte, word, and long values. Note that
- * the entire switch is wrapped in lock() and unlock() to prevent the I/O
- * batch from being interrupted. It may be cleaner to do this just around
- * the for loops, but this results in rather lenghty code.
- */
- lock(13, "do_vdevio");
- switch (m_ptr->DIO_TYPE) {
- case DIO_BYTE: /* byte values */
- pvb_pairs = (pvb_pair_t *) vdevio_pv_buf;
- if (DIO_INPUT == m_ptr->DIO_REQUEST) {
- for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
- pvb_pairs[i].value = inb(pvb_pairs[i].port);
- } else {
- for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
- outb(pvb_pairs[i].port, pvb_pairs[i].value);
- }
- break;
- case DIO_WORD: /* word values */
- pvw_pairs = (pvw_pair_t *) vdevio_pv_buf;
- if (DIO_INPUT == m_ptr->DIO_REQUEST) {
- for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
- pvw_pairs[i].value = inw(pvw_pairs[i].port);
- } else {
- for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
- outw(pvw_pairs[i].port, pvw_pairs[i].value);
- }
- break;
- case DIO_LONG: /* fall through: long values */
- default: /* only DIO_LONG can arrive here, see above switch */
- pvl_pairs = (pvl_pair_t *) vdevio_pv_buf;
- if (DIO_INPUT == m_ptr->DIO_REQUEST) {
- for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
- pvl_pairs[i].value = inl(pvl_pairs[i].port);
- } else {
- for (i=0; i < m_ptr->DIO_VEC_SIZE; i++)
- outl(pvb_pairs[i].port, pvl_pairs[i].value);
- }
- }
- unlock(13);
+ /* Perform actual device I/O for byte, word, and long values. Note that
+ * the entire switch is wrapped in lock() and unlock() to prevent the I/O
+ * batch from being interrupted.
+ */
+ lock(13, "do_vdevio");
+ switch (m_ptr->DIO_TYPE) {
+ case DIO_BYTE: /* byte values */
+ if (io_in) for (i=0; i<vec_size; i++) pvb[i].value = inb(pvb[i].port);
+ else for (i=0; i<vec_size; i++) outb(pvb[i].port, pvb[i].value);
+ break;
+ case DIO_WORD: /* word values */
+ if (io_in) for (i=0; i<vec_size; i++) pvw[i].value = inw(pvw[i].port);
+ else for (i=0; i<vec_size; i++) outw(pvw[i].port, pvw[i].value);
+ break;
+ default: /* long values */
+ if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);
+ else for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value);
+ }
+ unlock(13);
- /* Almost done, copy back results for input requests. */
- if (DIO_INPUT == m_ptr->REQUEST)
- phys_copy(kernel_phys, caller_phys, (phys_bytes) bytes);
- return(OK);
+ /* Almost done, copy back results for input requests. */
+ if (io_in) phys_copy(vir2phys(vdevio_buf), caller_phys, (phys_bytes) bytes);
+ return(OK);
}
#endif /* USE_VDEVIO */
* or PRIVATE. The reason for this is that extern variables cannot have a
* default initialization. If such variables are shared, they must also be
* declared in one of the *.h files without the initialization. Examples
- * include 'system_image' (this file) and 'idt' and 'gdt' (protect.c).
+ * include 'boot_image' (this file) and 'idt' and 'gdt' (protect.c).
*
* Changes:
* Nov 10, 2004 removed controller->driver mappings (Jorrit N. Herder)
#define USER_T 8 /* ticks */
#define SYS_T 16 /* ticks */
-PUBLIC struct system_image image[] = {
+PUBLIC struct boot_image image[] = {
{ IDLE, idle_task, IDLE_F, IDLE_T, IDLE_Q, IDLE_S, EMPTY_MASK, EMPTY_MASK, "IDLE" },
- { CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, FILLED_MASK, SYSTEM_SEND_MASK, "CLOCK" },
- { SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, FILLED_MASK, SYSTEM_SEND_MASK, "SYSTEM" },
+ { CLOCK, clock_task, TASK_F, SYS_T, TASK_Q, CLOCK_S, TASK_CALL_MASK, SYSTEM_SEND_MASK, "CLOCK" },
+ { SYSTEM, sys_task, TASK_F, SYS_T, TASK_Q, SYSTEM_S, TASK_CALL_MASK, SYSTEM_SEND_MASK, "SYSTEM" },
{ HARDWARE, 0, TASK_F, SYS_T, TASK_Q, HARDWARE_S, EMPTY_MASK, SYSTEM_SEND_MASK, "KERNEL" },
{ PM_PROC_NR, 0, SYS_F, SYS_T, 3, 0, FILLED_MASK, SERVER_SEND_MASK, "PM" },
{ FS_PROC_NR, 0, SYS_F, SYS_T, 4, 0, FILLED_MASK, SERVER_SEND_MASK, "FS" },
* a compile time error. Note that no space is allocated because 'dummy' is
* declared extern.
*/
-extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct system_image))?1:-1];
+extern int dummy[(NR_BOOT_PROCS==sizeof(image)/sizeof(struct boot_image))?1:-1];
bitchunk_t chunk[BITMAP_CHUNKS(NR_SYS_PROCS)];
} sys_map_t;
-struct system_image {
+struct boot_image {
proc_nr_t proc_nr; /* process number to use */
task_t *initial_pc; /* start function for tasks */
int flags; /* process flags */