Annotation of prex-old/sys/arch/i386/pc/interrupt.c, Revision 1.1.1.1.2.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
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: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * interrupt.c - interrupt handling routines for intel 8259 chip
32: */
33:
34: #include <kernel.h>
35: #include <irq.h>
36: #include <cpu.h>
1.1.1.1.2.1! nbrk 37: #include <locore.h>
1.1 nbrk 38:
39: /* I/O address for master/slave programmable interrupt controller */
40: #define PIC_M 0x20
41: #define PIC_S 0xa0
42:
43: /* Edge/level control register */
44: #define ELCR 0x4d0
45:
46: /*
47: * Interrupt priority level
48: *
1.1.1.1.2.1! nbrk 49: * Each interrupt has its logical priority level, with 0 being
! 50: * the highest priority. While some ISR is running, all lower
! 51: * priority interrupts are masked off.
1.1 nbrk 52: */
53: volatile int irq_level;
54:
55: /*
56: * Interrupt mapping table
57: */
58: static int ipl_table[NIRQS]; /* Vector -> level */
59: static u_int mask_table[NIPLS]; /* Level -> mask */
60:
61: /*
62: * Set mask for current ipl
63: */
64: static void
65: update_mask(void)
66: {
67: u_int mask = mask_table[irq_level];
68:
69: outb(mask & 0xff, PIC_M + 1);
70: outb(mask >> 8, PIC_S + 1);
71: }
72:
73: /*
74: * Unmask interrupt in PIC for specified irq.
75: * The interrupt mask table is also updated.
76: * Assumed CPU interrupt is disabled in caller.
77: */
78: void
79: interrupt_unmask(int vector, int level)
80: {
81: int i;
82: u_int unmask = (u_int)~(1 << vector);
83:
84: ipl_table[vector] = level;
85: /*
86: * Unmask target interrupt for all
87: * lower interrupt levels.
88: */
89: for (i = 0; i < level; i++)
90: mask_table[i] &= unmask;
91: update_mask();
92: }
93:
94: /*
95: * Mask interrupt in PIC for specified irq.
96: * Interrupt must be disabled when this routine is called.
97: */
98: void
99: interrupt_mask(int vector)
100: {
101: int i, level;
102: u_int mask = (u_int)(1 << vector);
103:
104: level = ipl_table[vector];
105: for (i = 0; i < level; i++)
106: mask_table[i] |= mask;
107: ipl_table[vector] = IPL_NONE;
108: update_mask();
109: }
110:
111: /*
112: * Setup interrupt mode.
113: * Select whether an interrupt trigger is edge or level.
114: */
115: void
116: interrupt_setup(int vector, int mode)
117: {
118: int port;
119: u_int bit;
120: u_char val;
121:
122: port = vector < 8 ? ELCR : ELCR + 1;
123: bit = (u_int)(1 << (vector & 7));
124:
125: val = inb(port);
126: if (mode == IMODE_LEVEL)
127: val |= bit;
128: else
129: val &= ~bit;
130: outb(val, port);
131: }
132:
133: /*
134: * Common interrupt handler.
1.1.1.1.2.1! nbrk 135: *
! 136: * This routine is called from low level interrupt routine
! 137: * written in assemble code. The interrupt flag is automatically
! 138: * disabled by h/w in CPU when the interrupt is occurred. The
! 139: * target interrupt will be masked in ICU while the irq handler
1.1 nbrk 140: * is called.
141: */
142: void
143: interrupt_handler(struct cpu_regs *regs)
144: {
145: int vector = (int)regs->trap_no;
146: int old_ipl, new_ipl;
147:
148: /* Adjust interrupt level */
149: old_ipl = irq_level;
150: new_ipl = ipl_table[vector];
151: if (new_ipl > old_ipl) /* Ignore spurious interrupt */
152: irq_level = new_ipl;
153: update_mask();
154:
155: /* Send acknowledge to PIC for specified irq */
156: if (vector & 8) /* Slave ? */
157: outb(0x20, PIC_S); /* Non specific EOI to slave */
158: outb(0x20, PIC_M); /* Non specific EOI to master */
159:
160: /* Dispatch interrupt */
1.1.1.1.2.1! nbrk 161: interrupt_enable();
1.1 nbrk 162: irq_handler(vector);
1.1.1.1.2.1! nbrk 163: interrupt_disable();
1.1 nbrk 164:
165: /* Restore interrupt level */
166: irq_level = old_ipl;
167: update_mask();
1.1.1.1.2.1! nbrk 168: }
! 169:
! 170: void interrupt_save(int *sts)
! 171: {
! 172: *sts = (int)(get_eflags() & EFL_IF);
! 173: }
! 174:
! 175: void interrupt_restore(int sts)
! 176: {
! 177: set_eflags((get_eflags() & ~EFL_IF) | sts);
1.1 nbrk 178: }
179:
180: /*
181: * Initialize 8259 interrupt controllers.
182: * All interrupts will be masked off in ICU.
183: */
184: void
185: interrupt_init(void)
186: {
187: int i;
188:
189: irq_level = IPL_NONE;
190:
191: for (i = 0; i < NIRQS; i++)
192: ipl_table[i] = IPL_NONE;
193:
194: for (i = 0; i < NIPLS; i++)
195: mask_table[i] = 0xfffb;
196:
197: outb_p(0x11, PIC_M); /* Start initialization edge, master */
198: outb_p(0x20, PIC_M + 1); /* Set h/w vector = 0x20 */
199: outb_p(0x04, PIC_M + 1); /* Chain to slave (IRQ2) */
200: outb_p(0x01, PIC_M + 1); /* 8086 mode */
201:
202: outb_p(0x11, PIC_S); /* Start initialization edge, master */
203: outb_p(0x28, PIC_S + 1); /* Set h/w vector = 0x28 */
204: outb_p(0x02, PIC_S + 1); /* Slave (cascade) */
205: outb_p(0x01, PIC_S + 1); /* 8086 mode */
206:
207: outb(0xff, PIC_S + 1); /* Mask all */
208: outb(0xfb, PIC_M + 1); /* Mask all except IRQ2 (cascade) */
209: }
CVSweb