|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/hal/ppc/prep/interrupt.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
1 /*- 2 * Copyright (c) 2009, 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 management routines for intel 8259 chip 32 */ 33 34 #include <kernel.h> 35 #include <hal.h> 36 #include <irq.h> 37 #include <io.h> 38 #include <cpufunc.h> 39 #include <context.h> 40 #include <trap.h> 41 #include <clock.h> 42 #include <locore.h> 43 #include <sys/ipl.h> 44 45 /* Number of IRQ lines */ 46 #define NIRQS 16 47 48 /* I/O address for master/slave programmable interrupt controller */ 49 #define PIC_M 0x20 50 #define PIC_S 0xa0 51 52 /* Edge/level control register */ 53 #define ELCR 0x4d0 54 55 /* 56 * Interrupt priority level 57 * 58 * Each interrupt has its logical priority level, with 0 being 59 * the highest priority. While some ISR is running, all lower 60 * priority interrupts are masked off. 61 */ 62 static volatile int irq_level; 63 64 /* 65 * Interrupt mapping table 66 */ 67 static int ipl_table[NIRQS]; /* Vector -> level */ 68 static u_int mask_table[NIPLS]; /* Level -> mask */ 69 70 /* 71 * Set mask for current ipl 72 */ 73 static void 74 update_mask(void) 75 { 76 u_int mask = mask_table[irq_level]; 77 78 outb(PIC_M + 1, mask & 0xff); 79 outb(PIC_S + 1, mask >> 8); 80 } 81 82 /* 83 * Unmask interrupt in PIC for specified irq. 84 * The interrupt mask table is also updated. 85 * Assumed CPU interrupt is disabled in caller. 86 */ 87 void 88 interrupt_unmask(int vector, int level) 89 { 90 u_int unmask = (u_int)~(1 << vector); 91 int i, s; 92 93 s = splhigh(); 94 ipl_table[vector] = level; 95 /* 96 * Unmask target interrupt for all 97 * lower interrupt levels. 98 */ 99 for (i = 0; i < level; i++) 100 mask_table[i] &= unmask; 101 update_mask(); 102 splx(s); 103 } 104 105 /* 106 * Mask interrupt in PIC for specified irq. 107 * Interrupt must be disabled when this routine is called. 108 */ 109 void 110 interrupt_mask(int vector) 111 { 112 u_int mask = (u_int)(1 << vector); 113 int i, level, s; 114 115 s = splhigh(); 116 level = ipl_table[vector]; 117 for (i = 0; i < level; i++) 118 mask_table[i] |= mask; 119 ipl_table[vector] = IPL_NONE; 120 update_mask(); 121 splx(s); 122 } 123 124 /* 125 * Setup interrupt mode. 126 * Select whether an interrupt trigger is edge or level. 127 */ 128 void 129 interrupt_setup(int vector, int mode) 130 { 131 int port, s; 132 u_int bit; 133 u_char val; 134 135 s = splhigh(); 136 port = vector < 8 ? ELCR : ELCR + 1; 137 bit = (u_int)(1 << (vector & 7)); 138 139 val = inb(port); 140 if (mode == IMODE_LEVEL) 141 val |= bit; 142 else 143 val &= ~bit; 144 outb(port, val); 145 splx(s); 146 } 147 148 /* 149 * Get interrupt source. 150 */ 151 static int 152 interrupt_lookup(void) 153 { 154 int irq; 155 156 outb(PIC_M, 0x0c); /* poll and ack */ 157 irq = inb(PIC_M) & 7; 158 if (irq == 2) { 159 outb(PIC_S, 0x0c); 160 irq = (inb(PIC_M) & 7) + 8; 161 } 162 return irq; 163 } 164 165 /* 166 * Common interrupt handler. 167 * 168 * This routine is called from the low level interrupt routine 169 * written in assemble code. The interrupt flag is automatically 170 * disabled by h/w in CPU when the interrupt is occurred. The 171 * target interrupt will be masked in ICU while the irq handler 172 * is called. 173 */ 174 void 175 interrupt_handler(struct cpu_regs *regs) 176 { 177 int vector; 178 int old_ipl, new_ipl; 179 180 /* Handle decrementer interrupt */ 181 if (regs->trap_no == TRAP_DECREMENTER) { 182 clock_isr(NULL); 183 return; 184 } 185 186 /* Find pending interrupt */ 187 vector = interrupt_lookup(); 188 189 /* Adjust interrupt level */ 190 old_ipl = irq_level; 191 new_ipl = ipl_table[vector]; 192 if (new_ipl > old_ipl) /* Ignore spurious interrupt */ 193 irq_level = new_ipl; 194 update_mask(); 195 196 /* Dispatch interrupt */ 197 splon(); 198 irq_handler(vector); 199 sploff(); 200 201 /* Restore interrupt level */ 202 irq_level = old_ipl; 203 update_mask(); 204 } 205 206 /* 207 * Initialize 8259 interrupt controllers. 208 * All interrupts will be masked off in ICU. 209 */ 210 void 211 interrupt_init(void) 212 { 213 int i; 214 215 irq_level = IPL_NONE; 216 217 for (i = 0; i < NIRQS; i++) 218 ipl_table[i] = IPL_NONE; 219 220 for (i = 0; i < NIPLS; i++) 221 mask_table[i] = 0xfffb; 222 223 outb(PIC_M, 0x11); /* Start initialization edge, master */ 224 outb(PIC_M + 1, 0x00); /* Set h/w vector = 0x0 */ 225 outb(PIC_M + 1, 0x04); /* Chain to slave (IRQ2) */ 226 outb(PIC_M + 1, 0x01); /* 8086 mode */ 227 228 outb(PIC_S, 0x11); /* Start initialization edge, master */ 229 outb(PIC_S + 1, 0x08); /* Set h/w vector = 0x8 */ 230 outb(PIC_S + 1, 0x02); /* Slave (cascade) */ 231 outb(PIC_S + 1, 0x01); /* 8086 mode */ 232 233 outb(PIC_S, 0x0b); /* Read ISR by default */ 234 outb(PIC_M, 0x0b); /* Read ISR by default */ 235 236 outb(PIC_S + 1, 0xff); /* Mask all */ 237 outb(PIC_M + 1, 0xfb); /* Mask all except IRQ2 (cascade) */ 238 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |