Exemple #1
0
PRIVATE void estimate_cpu_freq(void)
{
	u64_t tsc_delta;
	u64_t cpu_freq;

	irq_hook_t calib_cpu;

	/* set the probe, we use the legacy timer, IRQ 0 */
	put_irq_handler(&calib_cpu, CLOCK_IRQ, calib_cpu_handler);

	/* just in case we are in an SMP single cpu fallback mode */
	BKL_UNLOCK();
	/* set the PIC timer to get some time */
	intr_enable();

	/* loop for some time to get a sample */
	while(probe_ticks < PROBE_TICKS) {
		intr_enable();
	}

	intr_disable();
	/* just in case we are in an SMP single cpu fallback mode */
	BKL_LOCK();

	/* remove the probe */
	rm_irq_handler(&calib_cpu);

	tsc_delta = sub64(tsc1, tsc0);

	cpu_freq = mul64(div64u64(tsc_delta, PROBE_TICKS - 1), make64(system_hz, 0));
	cpu_set_freq(cpuid, cpu_freq);
	cpu_info[cpuid].freq = div64u(cpu_freq, 1000000);
	BOOT_VERBOSE(cpu_print_freq(cpuid));
}
Exemple #2
0
/*======================================================================*
                           init_keyboard
*======================================================================*/
PUBLIC void init_keyboard()
{
	kb_in.count = 0;
	kb_in.p_head = kb_in.p_tail = kb_in.buf;

	put_irq_handler(KEYBOARD_IRQ, keyboard_handler);	/* 设定键盘中断处理程序 */
	enable_irq(KEYBOARD_IRQ);				/* 开键盘中断 */
}
PUBLIC void init_clock()
{
	out_byte(TIMER_MODE, RATE_GENERATOR);
	out_byte(TIMER0, (TIMER_FREQ / HZ));
	out_byte(TIMER0, ((TIMER_FREQ / HZ) >> 8));

	put_irq_handler(CLOCK_IRQ, clock_handler);
	enable_irq(CLOCK_IRQ);
}
Exemple #4
0
int omap3_register_timer_handler(const irq_handler_t handler)
{
	/* Initialize the CLOCK's interrupt hook. */
	omap3_timer_hook.proc_nr_e = NONE;
	omap3_timer_hook.irq = OMAP3_GPT1_IRQ;

	put_irq_handler(&omap3_timer_hook, OMAP3_GPT1_IRQ, handler);

	return 0;
}
Exemple #5
0
/*======================================================================*
                            kernel_main
 *======================================================================*/
PUBLIC int kernel_main()
{
	disp_str("-----\"kernel_main\" begins-----\n");

	TASK*		p_task		= task_table;
	PROCESS*	p_proc		= proc_table;
	char*		p_task_stack	= task_stack + STACK_SIZE_TOTAL;
	u16		selector_ldt	= SELECTOR_LDT_FIRST;
	int i;
	for (i = 0; i < NR_TASKS; i++) {
		strcpy(p_proc->p_name, p_task->name);	// name of the process
		p_proc->pid = i;			// pid

		p_proc->ldt_sel = selector_ldt;

		memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3],
		       sizeof(DESCRIPTOR));
		p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5;
		memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3],
		       sizeof(DESCRIPTOR));
		p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5;
		p_proc->regs.cs	= ((8 * 0) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.ds	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.es	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.fs	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.ss	= ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
			| SA_TIL | RPL_TASK;
		p_proc->regs.gs	= (SELECTOR_KERNEL_GS & SA_RPL_MASK)
			| RPL_TASK;

		p_proc->regs.eip = (u32)p_task->initial_eip;
		p_proc->regs.esp = (u32)p_task_stack;
		p_proc->regs.eflags = 0x1202; /* IF=1, IOPL=1 */

		p_task_stack -= p_task->stacksize;
		p_proc++;
		p_task++;
		selector_ldt += 1 << 3;
	}

	k_reenter = 0;

	p_proc_ready	= proc_table;

        put_irq_handler(CLOCK_IRQ, clock_handler); /* 设定时钟中断处理程序 */
        enable_irq(CLOCK_IRQ);                     /* 让8259A可以接收时钟中断 */

	restart();

	while(1){}
}
Exemple #6
0
/*===========================================================================*
 *			init_profile_clock				     *
 *===========================================================================*/
void init_profile_clock(u32_t freq)
{
  int irq;

  if((irq = arch_init_profile_clock(freq)) >= 0) {
	/* Register interrupt handler for statistical system profiling.  */
	profile_clock_hook.proc_nr_e = CLOCK;
	put_irq_handler(&profile_clock_hook, irq, profile_clock_handler);
	enable_irq(&profile_clock_hook);
  }
}
Exemple #7
0
void main(void) {

  intr_init();

  init_pit();

  outb(0x21, 0xf8);
  outb(0xa1, 0xff);

  put_irq_handler(0, keyborad_handler);
  put_irq_handler(12, mouse_handler);
  put_irq_handler(0, timer_handler);

  kprintf("\n%s %s.%s. Copyright (c)  2013 loulanguju\n", KERNEL_NAME, KERNEL_RELEASE, KERNEL_VERSION);
  kprintf("Executing in %s mode.\n\n",  "32-bit protected");

  while (1) {// do while
  }

  return ;
}
Exemple #8
0
PUBLIC void init_keyboard()
{
	kb_in.count = 0;
	kb_in.p_head = kb_in.p_tail = kb_in.buf;

	vk.count = 0;
	vk.p_head = vk.p_tail = vk.buf;

	put_irq_handler(KEYBOARD_IRQ, keyboard_handler);	//设定键盘的中断处理程序
	enable_irq(KEYBOARD_IRQ);				//打开键盘中断
	
	//清屏
	clearScreen();
}
Exemple #9
0
/*======================================================================*
                           init_keyboard
*======================================================================*/
PUBLIC void init_keyboard()
{
    kb_in.count = 0;
    kb_in.p_head = kb_in.p_tail = kb_in.buf;

    caps_lock   = 0;
    num_lock    = 1;
    scroll_lock = 0;

    set_leds();

        put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*设定键盘中断处理程序*/
        enable_irq(KEYBOARD_IRQ);                       /*开键盘中断*/
}
Exemple #10
0
/**
 * <Ring 1> Check hard drive, set IRQ handler, enable IRQ and initialize data
 *          structures.
 *****************************************************************************/
PRIVATE void init_hd()
{
	int i;
	/* Get the number of drives from the BIOS data area */
	u8 * pNrDrives = (u8*)(0x475);
	printl("NrDrives:%d.\n", *pNrDrives);
	assert(*pNrDrives);

	put_irq_handler(AT_WINI_IRQ, hd_handler);
	enable_irq(CASCADE_IRQ);
	enable_irq(AT_WINI_IRQ);
	for (i = 0; i < (sizeof(hd_info) / sizeof(hd_info[0])); i++)
		memset(&hd_info[i], 0, sizeof(hd_info[0]));
	hd_info[0].open_cnt = 0;
}
Exemple #11
0
PRIVATE void init_hd()
{
    int i;
    
    u8_t *pNrDrives = (u8_t*)(0x475);
    kprintf("NrDrives:%d.\n", *pNrDrives);
    
    put_irq_handler(AT_WINI_IRQ, hd_handler);
    enable_irq(CASCADE_IRQ);
    enable_irq(AT_WINI_IRQ);

    for (i = 0; i < (sizeof (hd_info) / sizeof (hd_info[0])); ++i)
        memset(&hd_info[i], 0, sizeof (hd_info[0]));
    hd_info[0].open_cnt = 0;
}
Exemple #12
0
PUBLIC void init_clock()
{
	/* init 8253 8254 TIMER */
	out_byte(TIMER_MODE,RATE_GENERATOR);
	out_byte(TIMER0,(u8)(TIMER_FREQ/HZ));
	out_byte(TIMER0,(u8)((TIMER_FREQ/HZ)>>8));

	put_irq_handler(CLOCK_IRQ,clock_handler);
	enable_irq(CLOCK_IRQ);
	MESSAGE m;
	m.EXPIRETIME=2000000000;
	m.source=TASK_SYS;
	set_timer(&m);
	nextexpiretime=-1;
}
Exemple #13
0
//初始化键盘中断
PUBLIC void init_keyboard()
{
    kb_in.count = 0;
    kb_in.p_head = kb_in.p_tail = kb_in.buf;

    shift_l = shift_r = 0;
    alt_l = alt_r = 0;
    ctrl_l = ctrl_r = 0;

    caps_lock = 0;
    num_lock = 1;
    scroll_lock = 0;

    put_irq_handler(KEYBOARD_IRQ, keyboard_handler);
    enable_irq(KEYBOARD_IRQ);
}
Exemple #14
0
PUBLIC void init_hd()
{
	/* Get the number of drives from the BIOS data area */
	u8* pNrDrives = (u8*)(0x475);
	disp_str("NrDrives:");
	disp_int(*pNrDrives);
	disp_str("\n");

	put_irq_handler(AT_WINI_IRQ, hd_handler);
	enable_irq(CASCADE_IRQ);	//打开级联中断线
	enable_irq(AT_WINI_IRQ);	//打开硬盘中断线
	
	int i = 0;
	for(i = 0; i < (sizeof(hd_info) / sizeof(hd_info[0])); i++)
		memset(&hd_info[i], 0, sizeof(hd_info[0]));
	hd_info[0].open_cnt = 0;
}
Exemple #15
0
PUBLIC void init_keyboard(TTY *p_tty) {
    kb_in.count  = 0;
    kb_in.p_head = kb_in.p_tail = kb_in.buf;

    code_with_E0 = 0;
    shift_l = shift_r = 0;
    ctrl_l  = ctrl_r  = 0;
    alt_l   = alt_r   = 0;
    num_lock    = 1;
    caps_lock   = 0;
    scroll_lock = 0;

    set_leds();
	
    put_irq_handler(KEYBOARD_IRQ, keyboard_handler);
    enable_irq(KEYBOARD_IRQ);
}
Exemple #16
0
Fichier : hd.c Projet : Zach41/OS
PRIVATE void init_hd() {
    /* 初始化硬盘 */
    u8* pNrDrives = (u8*)(0x475); /* 从0x475处取得系统硬盘数,地址由BIOS指定 */
    printl("NR Drives: %d\n", *pNrDrives);
    assert(*pNrDrives);
    
    put_irq_handler(AT_WINI_IRQ, hd_handler);
    /* 开启级联的中断口 */
    enable_irq(CASCADE_IRQ);
    enable_irq(AT_WINI_IRQ);

    for (int i=0; i< (sizeof(hd_info) / sizeof(hd_info[0])); i++) {
	memset(&hd_info[i], 0, sizeof(hd_info[0]));
    }
    hd_info[0].open_cnt = 0;
    
}
Exemple #17
0
/*======================================================================*
                            init_keyboard
*----------------------------------------------------------------------*
 * 作用:初始化键盘中断处理函数,开启键盘中断
 *======================================================================*/
PUBLIC void init_keyboard()
{
	code_with_E0 = FALSE;
	shift_l	= FALSE;
	shift_r	= FALSE;
	ctrl_l	= FALSE;
	ctrl_r	= FALSE;
	alt_l	= FALSE;
	alt_l	= FALSE;
	
	// 初始化键盘缓冲区结构体
	kb_in.count = 0;
	kb_in.p_head = kb_in.p_tail = kb_in.buf;

	// **************************** 设置 键盘中断 处理函数 ****************************
	put_irq_handler(KEYBOARD_IRQ, keyboard_handler);
	enable_irq(KEYBOARD_IRQ);
}
Exemple #18
0
void kernel_main(void)
{
  clear();
  clear_line(13);
  s32_print("memory size", (u8*)(0xb8000+160*13));
  //int memsize = memtest(0x00400000, 0xbfffffff) / (1024 * 1024);
  // 0x2000000 = 32MB
  // because of bochs will alert memory access more than the memory size,
  //   so limit address to 0x2000000, if use qemu, it works fine.
  memsize = memtest(0x00400000, 0x2000000);
  int memsize_mb = memsize / (1024 * 1024);

  u8 stack_str[10]="y";
  u8 *sp = stack_str;
  sp = s32_itoa(memsize_mb, stack_str, 10);
  
  clear();
#if 1
  clear_line(24);
  s32_print("memory size", (u8*)(0xb8000+160*24));
  s32_print(sp, (u8*)(0xb8000+160*24 + 12*2));
  s32_print("MB", (u8*)(0xb8000+160*24 + 12*2 + 4*2));
#endif

  void setup_paging(void);
  //setup_paging();
 
  put_irq_handler(CLOCK_IRQ, clock_handler);
  enable_irq(CLOCK_IRQ);

  ready_process = proc_table;



  init_proc();

  cur_vb = (u8*)0xb8000+160;

  void restart(void);
  restart();
  s32_print("xxxxxxxxxxx", (u8*)(0xb8000+160*15));
  while(1);

}
Exemple #19
0
/*<ring 1>
功能:
    初始化硬盘,其中包括显示主机硬盘数、启动硬盘驱动程序及初始化hd_info
参数:
    (无)
返回值:
    (无)
*/
static void init_hd(){
    int i;
    u8 *p_drivers_count=(u8*)(0x475);
#ifdef DEBUG_HD
    printl("Drivers_count:%d.\n",*p_drivers_count);
#endif
    assert(*p_drivers_count,"");

    /*启动硬盘中断,由于硬盘中断接在级联从片上,所以需要同时启动主片上的对应驱动*/
    put_irq_handler(AT_WINI_IRQ,hd_handler);
    enable_irq(CASCADE_IRQ);
    enable_irq(AT_WINI_IRQ);
    
    /*hd_info初始化*/
    for(i=0;i<ARRAY_LENGTH(hd_info);i++){
        memset(&hd_info[i],0,sizeof(hd_info[0]));
    }
    hd_info[0].open_count=0;
}
Exemple #20
0
// ----------------------------------------------------------------------------
// kernel_main 由内核跳入
PUBLIC int kernel_main() {
	disp_str("-----\"kernel_main\" begins-----\n");

    TASK    *p_task         = task_table;
    PROCESS *p_proc         = proc_table;
    char    *p_task_stack   = task_stack + STACK_SIZE_TOTAL;
    u16     selector_ldt    = SELECTOR_LDT_FIRST;

    int i;
    for (i = 0; i < NR_TASKS; ++i) {
        // name of the process
        strcpy(p_proc->p_name, p_task->name);
        // pid
        p_proc->pid = i;

        p_proc->ldt_sel = selector_ldt;

        // 由 8 的倍数的偏移变成数组的下标
        // 进程的两个 ldt 为了简化起见, 分别被初始化位内核代码段和内核数据段
        // 只是改变了以下 DPL 以让其运行在低特权级下
        memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3], sizeof(DESCRIPTOR));
        // chage the DPL
        p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5;
        memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3], sizeof(DESCRIPTOR));
        p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5;
        
        p_proc->regs.cs     = ((8 * 0) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
        p_proc->regs.ds     = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
        p_proc->regs.es     = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
        p_proc->regs.fs     = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
        p_proc->regs.ss     = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
        p_proc->regs.gs     = (SELECTOR_KERNEL_GS & SA_RPL_MASK) | RPL_TASK;

        p_proc->regs.eip    = (u32)p_task->initial_eip;
        p_proc->regs.esp    = (u32)p_task_stack;
        p_proc->regs.eflags = 0x1202;   // IF = 1, IOPL = 1, bit 2 is always 1

        p_task_stack        -= p_task->stacksize;
        ++p_proc;
        ++p_task;
        selector_ldt        += 1 << 3;
    }

	proc_table[0].ticks = proc_table[0].priority = 15; // 0x96
	proc_table[1].ticks = proc_table[1].priority = 5;  // 0x32
	proc_table[2].ticks = proc_table[2].priority = 3;  // 0x1E

    k_reenter           = 0;
    ticks               = 0;

    p_proc_ready        = proc_table;

    // 初始化 8253 PIT
    out_byte(TIMER_MODE, RATE_GENERATOR);
    out_byte(TIMER0, (u8)(TIMER_FREQ / HZ));
    out_byte(TIMER0, (u8)((TIMER_FREQ / HZ) >> 8));

    put_irq_handler(CLOCK_IRQ, clock_handler);  // 设定时钟中断处理程序
    enable_irq(CLOCK_IRQ);                      // 让8259A可以接收时钟中断

    restart();

    while (1) {}
}
Exemple #21
0
PUBLIC int kernel_main(void) 
{
	TASK *p_task = task_table; 
	PROCESS *p_proc = proc_table;
	char *p_task_stack = task_stack + STACK_SIZE_TOTAL;
	u16 selector_ldt = SELECTOR_LDT_FIRST; 
	int i; 



	for(i = 0; i < NR_TASKS; i++) {
		//strcpy(p_proc->p_name, p_task->name);	
		//p_proc->pid = i; 

		/* initialize the ldt selector for process A*/
		p_proc->ldt_sel = selector_ldt; 

		/*initialize two ldt desciptors for process A
		 * the code desciptor equals to kernel code desciptor
		 * the data desciptor equals to the kernel data desciptor*/
		memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3], 
				sizeof(DESCRIPTOR)); 
		p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5; 
		memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3], 
				sizeof(DESCRIPTOR)); 
		p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5; 

		/*initialize the segment registers for process A*/ 
		p_proc->regs.cs = ((8 * 0) & SA_RPL_MASK & SA_TI_MASK ) | 
			SA_TIL | RPL_TASK;
		p_proc->regs.ds = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK ) | 
			SA_TIL | RPL_TASK;
		p_proc->regs.es = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK ) | 
			SA_TIL | RPL_TASK;
		p_proc->regs.fs = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK ) | 
			SA_TIL | RPL_TASK;
		p_proc->regs.ss = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK ) | 
			SA_TIL | RPL_TASK;
		p_proc->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK ) | RPL_TASK;

		/* initialize eip address for process A 
		 * eip will point to function testA*/
		p_proc->regs.eip = (u32) p_task->initial_eip;

		/* process A will use a new stack */
		p_proc->regs.esp = (u32) p_task_stack;
		
		/*IF =1, IOFL =1 => unblock interrupt and 
		 process can use io ports*/ 
		p_proc->regs.eflags = 0x1202; 
		
		p_task_stack -= p_task->stack_size; 
		p_proc++; 
		p_task++; 
		selector_ldt += 0x08;
	}

	k_reenter = 0;

	/*jump to new process*/
	p_proc_ready = proc_table;

	/*register clock_handler, enable clock_irq*/
	put_irq_handler(CLOCK_IRQ, clock_handler);
	enable_irq(CLOCK_IRQ);

	restart();

	while(TRUE) {} 
	return 0;
}
Exemple #22
0
PUBLIC int init_local_timer(unsigned freq)
{
#ifdef USE_APIC
	/* if we know the address, lapic is enabled and we should use it */
	if (lapic_addr) {
		unsigned cpu = cpuid;
		tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000);
		lapic_set_timer_one_shot(1000000/system_hz);
	} else
	{
		BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n"));
#else
	{
#endif
		init_8253A_timer(freq);
		estimate_cpu_freq();
		/* always only 1 cpu in the system */
		tsc_per_ms[0] = div64u(cpu_get_freq(0), 1000);
	}

	return 0;
}

PUBLIC void stop_local_timer(void)
{
#ifdef USE_APIC
	if (lapic_addr) {
		lapic_stop_timer();
		apic_eoi();
	} else
#endif
	{
		stop_8253A_timer();
	}
}

PUBLIC void restart_local_timer(void)
{
#ifdef USE_APIC
	if (lapic_addr) {
		lapic_restart_timer();
	}
#endif
}

PUBLIC int register_local_timer_handler(const irq_handler_t handler)
{
#ifdef USE_APIC
	if (lapic_addr) {
		/* Using APIC, it is configured in apic_idt_init() */
		BOOT_VERBOSE(printf("Using LAPIC timer as tick source\n"));
	} else
#endif
	{
		/* Using PIC, Initialize the CLOCK's interrupt hook. */
		pic_timer_hook.proc_nr_e = NONE;
		pic_timer_hook.irq = CLOCK_IRQ;

		put_irq_handler(&pic_timer_hook, CLOCK_IRQ, handler);
	}

	return 0;
}

PUBLIC void cycles_accounting_init(void)
{
#ifdef CONFIG_SMP
	unsigned cpu = cpuid;
#endif

	read_tsc_64(get_cpu_var_ptr(cpu, tsc_ctr_switch));

	make_zero64(get_cpu_var(cpu, cpu_last_tsc));
	make_zero64(get_cpu_var(cpu, cpu_last_idle));
}
/*===========================================================================*
 *				do_irqctl				     *
 *===========================================================================*/
int do_irqctl(struct proc * caller, message * m_ptr)
{
  /* Dismember the request message. */
  int irq_vec;
  int irq_hook_id;
  int notify_id;
  int r = OK;
  int i;
  irq_hook_t *hook_ptr;
  struct priv *privp;

  /* Hook identifiers start at 1 and end at NR_IRQ_HOOKS. */
  irq_hook_id = m_ptr->m_lsys_krn_sys_irqctl.hook_id - 1;
  irq_vec = m_ptr->m_lsys_krn_sys_irqctl.vector;

  /* See what is requested and take needed actions. */
  switch(m_ptr->m_lsys_krn_sys_irqctl.request) {

  /* Enable or disable IRQs. This is straightforward. */
  case IRQ_ENABLE:           
  case IRQ_DISABLE: 
      if (irq_hook_id >= NR_IRQ_HOOKS || irq_hook_id < 0 ||
          irq_hooks[irq_hook_id].proc_nr_e == NONE) return(EINVAL);
      if (irq_hooks[irq_hook_id].proc_nr_e != caller->p_endpoint) return(EPERM);
      if (m_ptr->m_lsys_krn_sys_irqctl.request == IRQ_ENABLE) {
          enable_irq(&irq_hooks[irq_hook_id]);	
      }
      else 
          disable_irq(&irq_hooks[irq_hook_id]);	
      break;

  /* Control IRQ policies. Set a policy and needed details in the IRQ table.
   * This policy is used by a generic function to handle hardware interrupts. 
   */
  case IRQ_SETPOLICY:  

      /* Check if IRQ line is acceptable. */
      if (irq_vec < 0 || irq_vec >= NR_IRQ_VECTORS) return(EINVAL);

      privp= priv(caller);
      if (!privp)
      {
	printf("do_irqctl: no priv structure!\n");
	return EPERM;
      }
      if (privp->s_flags & CHECK_IRQ)
      {
	for (i= 0; i<privp->s_nr_irq; i++)
	{
		if (irq_vec == privp->s_irq_tab[i])
			break;
	}
	if (i >= privp->s_nr_irq)
	{
		printf(
		"do_irqctl: IRQ check failed for proc %d, IRQ %d\n",
			caller->p_endpoint, irq_vec);
		return EPERM;
	}
    }

      /* When setting a policy, the caller must provide an identifier that
       * is returned on the notification message if a interrupt occurs.
       */
      notify_id = m_ptr->m_lsys_krn_sys_irqctl.hook_id;
      if (notify_id > CHAR_BIT * sizeof(irq_id_t) - 1) return(EINVAL);

      /* Try to find an existing mapping to override. */
      hook_ptr = NULL;
      for (i=0; !hook_ptr && i<NR_IRQ_HOOKS; i++) {
          if (irq_hooks[i].proc_nr_e == caller->p_endpoint
              && irq_hooks[i].notify_id == notify_id) {
              irq_hook_id = i;
              hook_ptr = &irq_hooks[irq_hook_id];	/* existing hook */
              rm_irq_handler(&irq_hooks[irq_hook_id]);
          }
      }

      /* If there is nothing to override, find a free hook for this mapping. */
      for (i=0; !hook_ptr && i<NR_IRQ_HOOKS; i++) {
          if (irq_hooks[i].proc_nr_e == NONE) {
              irq_hook_id = i;
              hook_ptr = &irq_hooks[irq_hook_id];	/* free hook */
          }
      }
      if (hook_ptr == NULL) return(ENOSPC);

      /* Install the handler. */
      hook_ptr->proc_nr_e = caller->p_endpoint;	/* process to notify */
      hook_ptr->notify_id = notify_id;		/* identifier to pass */   	
      hook_ptr->policy = m_ptr->m_lsys_krn_sys_irqctl.policy;	/* policy for interrupts */
      put_irq_handler(hook_ptr, irq_vec, generic_handler);
      DEBUGBASIC(("IRQ %d handler registered by %s / %d\n",
			      irq_vec, caller->p_name, caller->p_endpoint));

      /* Return index of the IRQ hook in use. */
      m_ptr->m_krn_lsys_sys_irqctl.hook_id = irq_hook_id + 1;
      break;

  case IRQ_RMPOLICY:
      if (irq_hook_id < 0 || irq_hook_id >= NR_IRQ_HOOKS ||
               irq_hooks[irq_hook_id].proc_nr_e == NONE) {
           return(EINVAL);
      } else if (caller->p_endpoint != irq_hooks[irq_hook_id].proc_nr_e) {
           return(EPERM);
      }
      /* Remove the handler and return. */
      rm_irq_handler(&irq_hooks[irq_hook_id]);
      irq_hooks[irq_hook_id].proc_nr_e = NONE;
      break;

  default:
      r = EINVAL;				/* invalid IRQ REQUEST */
  }
  return(r);
}