uboot/cpu/i386/interrupts.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <asm/interrupt.h>
  26
  27
  28struct idt_entry {
  29        u16     base_low;
  30        u16     selector;
  31        u8      res;
  32        u8      access;
  33        u16     base_high;
  34} __attribute__ ((packed));
  35
  36
  37struct idt_entry idt[256];
  38
  39
  40asm (".globl irq_return\n"
  41     "irq_return:\n"
  42     "     addl  $4, %esp\n"
  43     "     popa\n"
  44     "     iret\n");
  45
  46void __attribute__ ((regparm(0))) default_isr(void);
  47asm ("default_isr: iret\n");
  48
  49asm ("idt_ptr:\n"
  50        ".word  0x800\n" /* size of the table 8*256 bytes */
  51        ".long  idt\n"   /* offset */
  52        ".word  0x18\n");/* data segment */
  53
  54void set_vector(u8 intnum, void *routine)
  55{
  56        idt[intnum].base_high = (u16)((u32)(routine + gd->reloc_off) >> 16);
  57        idt[intnum].base_low = (u16)((u32)(routine + gd->reloc_off) & 0xffff);
  58}
  59
  60
  61int cpu_init_interrupts(void)
  62{
  63        int i;
  64
  65        /* Just in case... */
  66        disable_interrupts();
  67
  68        /* Setup the IDT */
  69        for (i=0;i<256;i++) {
  70                idt[i].access = 0x8e;
  71                idt[i].res = 0;
  72                idt[i].selector = 0x10;
  73                set_vector(i, default_isr);
  74        }
  75
  76        asm ("cs lidt idt_ptr\n");
  77
  78        /* It is now safe to enable interrupts */
  79        enable_interrupts();
  80
  81        return 0;
  82}
  83
  84void enable_interrupts(void)
  85{
  86        asm("sti\n");
  87}
  88
  89int disable_interrupts(void)
  90{
  91        long flags;
  92
  93        asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : );
  94
  95        return (flags&0x200); /* IE flags is bit 9 */
  96}
  97