1/*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
| 1/*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)isa.c 7.2 (Berkeley) 5/13/91
|
38 */ 39 40#include "opt_auto_eoi.h" 41 42#include <sys/param.h> 43#ifndef SMP 44#include <machine/lock.h> 45#endif 46#include <sys/systm.h> 47#include <sys/syslog.h> 48#include <machine/ipl.h> 49#include <machine/md_var.h> 50#include <machine/segments.h> 51#if defined(APIC_IO) 52#include <machine/smp.h> 53#include <machine/smptests.h> /** FAST_HI */ 54#endif /* APIC_IO */ 55#include <i386/isa/isa_device.h> 56#ifdef PC98 57#include <pc98/pc98/pc98.h> 58#include <pc98/pc98/pc98_machdep.h> 59#include <pc98/pc98/epsonio.h> 60#else 61#include <i386/isa/isa.h> 62#endif 63#include <i386/isa/icu.h> 64 65#include <i386/isa/intr_machdep.h> 66#include <sys/interrupt.h> 67#ifdef APIC_IO 68#include <machine/clock.h> 69#endif 70 71/* XXX should be in suitable include files */ 72#ifdef PC98 73#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ 74#define ICU_SLAVEID 7 75#else 76#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ 77#define ICU_SLAVEID 2 78#endif 79 80#ifdef APIC_IO 81/* 82 * This is to accommodate "mixed-mode" programming for 83 * motherboards that don't connect the 8254 to the IO APIC. 84 */ 85#define AUTO_EOI_1 1 86#endif 87 88#define NR_INTRNAMES (1 + ICU_LEN + 2 * ICU_LEN) 89 90u_long *intr_countp[ICU_LEN]; 91inthand2_t *intr_handler[ICU_LEN]; 92u_int intr_mask[ICU_LEN]; 93static u_int* intr_mptr[ICU_LEN]; 94void *intr_unit[ICU_LEN]; 95 96static inthand_t *fastintr[ICU_LEN] = { 97 &IDTVEC(fastintr0), &IDTVEC(fastintr1), 98 &IDTVEC(fastintr2), &IDTVEC(fastintr3), 99 &IDTVEC(fastintr4), &IDTVEC(fastintr5), 100 &IDTVEC(fastintr6), &IDTVEC(fastintr7), 101 &IDTVEC(fastintr8), &IDTVEC(fastintr9), 102 &IDTVEC(fastintr10), &IDTVEC(fastintr11), 103 &IDTVEC(fastintr12), &IDTVEC(fastintr13), 104 &IDTVEC(fastintr14), &IDTVEC(fastintr15) 105#if defined(APIC_IO) 106 , &IDTVEC(fastintr16), &IDTVEC(fastintr17), 107 &IDTVEC(fastintr18), &IDTVEC(fastintr19), 108 &IDTVEC(fastintr20), &IDTVEC(fastintr21), 109 &IDTVEC(fastintr22), &IDTVEC(fastintr23) 110#endif /* APIC_IO */ 111}; 112 113static inthand_t *slowintr[ICU_LEN] = { 114 &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), 115 &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), 116 &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), 117 &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) 118#if defined(APIC_IO) 119 , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19), 120 &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23) 121#endif /* APIC_IO */ 122}; 123 124static inthand2_t isa_strayintr; 125 126#ifdef PC98 127#define NMI_PARITY 0x04 128#define NMI_EPARITY 0x02 129#else 130#define NMI_PARITY (1 << 7) 131#define NMI_IOCHAN (1 << 6) 132#define ENMI_WATCHDOG (1 << 7) 133#define ENMI_BUSTIMER (1 << 6) 134#define ENMI_IOSTATUS (1 << 5) 135#endif 136 137/* 138 * Handle a NMI, possibly a machine check. 139 * return true to panic system, false to ignore. 140 */ 141int 142isa_nmi(cd) 143 int cd; 144{ 145#ifdef PC98 146 int port = inb(0x33); 147 if (epson_machine_id == 0x20) 148 epson_outb(0xc16, epson_inb(0xc16) | 0x1); 149 if (port & NMI_PARITY) { 150 panic("BASE RAM parity error, likely hardware failure."); 151 } else if (port & NMI_EPARITY) { 152 panic("EXTENDED RAM parity error, likely hardware failure."); 153 } else { 154 printf("\nNMI Resume ??\n"); 155 return(0); 156 } 157#else /* IBM-PC */ 158 int isa_port = inb(0x61); 159 int eisa_port = inb(0x461); 160 161 if (isa_port & NMI_PARITY) 162 panic("RAM parity error, likely hardware failure."); 163 164 if (isa_port & NMI_IOCHAN) 165 panic("I/O channel check, likely hardware failure."); 166 167 /* 168 * On a real EISA machine, this will never happen. However it can 169 * happen on ISA machines which implement XT style floating point 170 * error handling (very rare). Save them from a meaningless panic. 171 */ 172 if (eisa_port == 0xff) 173 return(0); 174 175 if (eisa_port & ENMI_WATCHDOG) 176 panic("EISA watchdog timer expired, likely hardware failure."); 177 178 if (eisa_port & ENMI_BUSTIMER) 179 panic("EISA bus timeout, likely hardware failure."); 180 181 if (eisa_port & ENMI_IOSTATUS) 182 panic("EISA I/O port status error."); 183 184 printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port); 185 return(0); 186#endif 187} 188 189/* 190 * Fill in default interrupt table (in case of spuruious interrupt 191 * during configuration of kernel, setup interrupt control unit 192 */ 193void 194isa_defaultirq() 195{ 196 int i; 197 198 /* icu vectors */ 199 for (i = 0; i < ICU_LEN; i++) 200 icu_unset(i, (inthand2_t *)NULL); 201 202 /* initialize 8259's */ 203 outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ 204 205 outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ 206 outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ 207#ifdef PC98 208#ifdef AUTO_EOI_1 209 outb(IO_ICU1+ICU_IMR_OFFSET, 0x1f); /* (master) auto EOI, 8086 mode */ 210#else 211 outb(IO_ICU1+ICU_IMR_OFFSET, 0x1d); /* (master) 8086 mode */ 212#endif 213#else /* IBM-PC */ 214#ifdef AUTO_EOI_1 215 outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ 216#else 217 outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */ 218#endif 219#endif /* PC98 */ 220 outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ 221 outb(IO_ICU1, 0x0a); /* default to IRR on read */ 222#ifndef PC98 223 outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ 224#endif /* !PC98 */ 225 226 outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ 227 outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ 228 outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ 229#ifdef PC98 230 outb(IO_ICU2+ICU_IMR_OFFSET,9); /* 8086 mode */ 231#else /* IBM-PC */ 232#ifdef AUTO_EOI_2 233 outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ 234#else 235 outb(IO_ICU2+ICU_IMR_OFFSET,1); /* 8086 mode */ 236#endif 237#endif /* PC98 */ 238 outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ 239 outb(IO_ICU2, 0x0a); /* default to IRR on read */ 240} 241 242/* 243 * Caught a stray interrupt, notify 244 */ 245static void 246isa_strayintr(vcookiep) 247 void *vcookiep; 248{ 249 int intr = (void **)vcookiep - &intr_unit[0]; 250 251 /* DON'T BOTHER FOR NOW! */ 252 /* for some reason, we get bursts of intr #7, even if not enabled! */ 253 /* 254 * Well the reason you got bursts of intr #7 is because someone 255 * raised an interrupt line and dropped it before the 8259 could 256 * prioritize it. This is documented in the intel data book. This 257 * means you have BAD hardware! I have changed this so that only 258 * the first 5 get logged, then it quits logging them, and puts 259 * out a special message. rgrimes 3/25/1993 260 */ 261 /* 262 * XXX TODO print a different message for #7 if it is for a 263 * glitch. Glitches can be distinguished from real #7's by 264 * testing that the in-service bit is _not_ set. The test 265 * must be done before sending an EOI so it can't be done if 266 * we are using AUTO_EOI_1. 267 */ 268 if (intrcnt[1 + intr] <= 5) 269 log(LOG_ERR, "stray irq %d\n", intr); 270 if (intrcnt[1 + intr] == 5) 271 log(LOG_CRIT, 272 "too many stray irq %d's; not logging any more\n", intr); 273} 274 275/* 276 * Return a bitmap of the current interrupt requests. This is 8259-specific 277 * and is only suitable for use at probe time. 278 */ 279intrmask_t 280isa_irq_pending() 281{ 282 u_char irr1; 283 u_char irr2; 284 285 irr1 = inb(IO_ICU1); 286 irr2 = inb(IO_ICU2); 287 return ((irr2 << 8) | irr1); 288} 289 290int 291update_intr_masks(void) 292{ 293 int intr, n=0; 294 u_int mask,*maskptr; 295 296 for (intr=0; intr < ICU_LEN; intr ++) { 297#if defined(APIC_IO) 298 /* no 8259 SLAVE to ignore */ 299#else 300 if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */ 301#endif /* APIC_IO */ 302 maskptr = intr_mptr[intr]; 303 if (!maskptr) continue; 304 *maskptr |= 1 << intr; 305 mask = *maskptr; 306 if (mask != intr_mask[intr]) { 307#if 0 308 printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n", 309 intr, intr_mask[intr], mask, maskptr); 310#endif 311 intr_mask[intr]=mask; 312 n++; 313 } 314 315 } 316 return (n); 317} 318 319static const char * 320isa_get_nameunit(int id) 321{ 322 static char buf[32]; 323 struct isa_device *dp; 324 325 if (id == -1) 326 return ("pci"); /* XXX may also be eisa */ 327 if (id == 0) 328 return ("clk0"); /* XXX may also be sloppy driver */ 329 if (id == 1) 330 return ("rtc0");
| 38 */ 39 40#include "opt_auto_eoi.h" 41 42#include <sys/param.h> 43#ifndef SMP 44#include <machine/lock.h> 45#endif 46#include <sys/systm.h> 47#include <sys/syslog.h> 48#include <machine/ipl.h> 49#include <machine/md_var.h> 50#include <machine/segments.h> 51#if defined(APIC_IO) 52#include <machine/smp.h> 53#include <machine/smptests.h> /** FAST_HI */ 54#endif /* APIC_IO */ 55#include <i386/isa/isa_device.h> 56#ifdef PC98 57#include <pc98/pc98/pc98.h> 58#include <pc98/pc98/pc98_machdep.h> 59#include <pc98/pc98/epsonio.h> 60#else 61#include <i386/isa/isa.h> 62#endif 63#include <i386/isa/icu.h> 64 65#include <i386/isa/intr_machdep.h> 66#include <sys/interrupt.h> 67#ifdef APIC_IO 68#include <machine/clock.h> 69#endif 70 71/* XXX should be in suitable include files */ 72#ifdef PC98 73#define ICU_IMR_OFFSET 2 /* IO_ICU{1,2} + 2 */ 74#define ICU_SLAVEID 7 75#else 76#define ICU_IMR_OFFSET 1 /* IO_ICU{1,2} + 1 */ 77#define ICU_SLAVEID 2 78#endif 79 80#ifdef APIC_IO 81/* 82 * This is to accommodate "mixed-mode" programming for 83 * motherboards that don't connect the 8254 to the IO APIC. 84 */ 85#define AUTO_EOI_1 1 86#endif 87 88#define NR_INTRNAMES (1 + ICU_LEN + 2 * ICU_LEN) 89 90u_long *intr_countp[ICU_LEN]; 91inthand2_t *intr_handler[ICU_LEN]; 92u_int intr_mask[ICU_LEN]; 93static u_int* intr_mptr[ICU_LEN]; 94void *intr_unit[ICU_LEN]; 95 96static inthand_t *fastintr[ICU_LEN] = { 97 &IDTVEC(fastintr0), &IDTVEC(fastintr1), 98 &IDTVEC(fastintr2), &IDTVEC(fastintr3), 99 &IDTVEC(fastintr4), &IDTVEC(fastintr5), 100 &IDTVEC(fastintr6), &IDTVEC(fastintr7), 101 &IDTVEC(fastintr8), &IDTVEC(fastintr9), 102 &IDTVEC(fastintr10), &IDTVEC(fastintr11), 103 &IDTVEC(fastintr12), &IDTVEC(fastintr13), 104 &IDTVEC(fastintr14), &IDTVEC(fastintr15) 105#if defined(APIC_IO) 106 , &IDTVEC(fastintr16), &IDTVEC(fastintr17), 107 &IDTVEC(fastintr18), &IDTVEC(fastintr19), 108 &IDTVEC(fastintr20), &IDTVEC(fastintr21), 109 &IDTVEC(fastintr22), &IDTVEC(fastintr23) 110#endif /* APIC_IO */ 111}; 112 113static inthand_t *slowintr[ICU_LEN] = { 114 &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3), 115 &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7), 116 &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11), 117 &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15) 118#if defined(APIC_IO) 119 , &IDTVEC(intr16), &IDTVEC(intr17), &IDTVEC(intr18), &IDTVEC(intr19), 120 &IDTVEC(intr20), &IDTVEC(intr21), &IDTVEC(intr22), &IDTVEC(intr23) 121#endif /* APIC_IO */ 122}; 123 124static inthand2_t isa_strayintr; 125 126#ifdef PC98 127#define NMI_PARITY 0x04 128#define NMI_EPARITY 0x02 129#else 130#define NMI_PARITY (1 << 7) 131#define NMI_IOCHAN (1 << 6) 132#define ENMI_WATCHDOG (1 << 7) 133#define ENMI_BUSTIMER (1 << 6) 134#define ENMI_IOSTATUS (1 << 5) 135#endif 136 137/* 138 * Handle a NMI, possibly a machine check. 139 * return true to panic system, false to ignore. 140 */ 141int 142isa_nmi(cd) 143 int cd; 144{ 145#ifdef PC98 146 int port = inb(0x33); 147 if (epson_machine_id == 0x20) 148 epson_outb(0xc16, epson_inb(0xc16) | 0x1); 149 if (port & NMI_PARITY) { 150 panic("BASE RAM parity error, likely hardware failure."); 151 } else if (port & NMI_EPARITY) { 152 panic("EXTENDED RAM parity error, likely hardware failure."); 153 } else { 154 printf("\nNMI Resume ??\n"); 155 return(0); 156 } 157#else /* IBM-PC */ 158 int isa_port = inb(0x61); 159 int eisa_port = inb(0x461); 160 161 if (isa_port & NMI_PARITY) 162 panic("RAM parity error, likely hardware failure."); 163 164 if (isa_port & NMI_IOCHAN) 165 panic("I/O channel check, likely hardware failure."); 166 167 /* 168 * On a real EISA machine, this will never happen. However it can 169 * happen on ISA machines which implement XT style floating point 170 * error handling (very rare). Save them from a meaningless panic. 171 */ 172 if (eisa_port == 0xff) 173 return(0); 174 175 if (eisa_port & ENMI_WATCHDOG) 176 panic("EISA watchdog timer expired, likely hardware failure."); 177 178 if (eisa_port & ENMI_BUSTIMER) 179 panic("EISA bus timeout, likely hardware failure."); 180 181 if (eisa_port & ENMI_IOSTATUS) 182 panic("EISA I/O port status error."); 183 184 printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port); 185 return(0); 186#endif 187} 188 189/* 190 * Fill in default interrupt table (in case of spuruious interrupt 191 * during configuration of kernel, setup interrupt control unit 192 */ 193void 194isa_defaultirq() 195{ 196 int i; 197 198 /* icu vectors */ 199 for (i = 0; i < ICU_LEN; i++) 200 icu_unset(i, (inthand2_t *)NULL); 201 202 /* initialize 8259's */ 203 outb(IO_ICU1, 0x11); /* reset; program device, four bytes */ 204 205 outb(IO_ICU1+ICU_IMR_OFFSET, NRSVIDT); /* starting at this vector index */ 206 outb(IO_ICU1+ICU_IMR_OFFSET, IRQ_SLAVE); /* slave on line 7 */ 207#ifdef PC98 208#ifdef AUTO_EOI_1 209 outb(IO_ICU1+ICU_IMR_OFFSET, 0x1f); /* (master) auto EOI, 8086 mode */ 210#else 211 outb(IO_ICU1+ICU_IMR_OFFSET, 0x1d); /* (master) 8086 mode */ 212#endif 213#else /* IBM-PC */ 214#ifdef AUTO_EOI_1 215 outb(IO_ICU1+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ 216#else 217 outb(IO_ICU1+ICU_IMR_OFFSET, 1); /* 8086 mode */ 218#endif 219#endif /* PC98 */ 220 outb(IO_ICU1+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ 221 outb(IO_ICU1, 0x0a); /* default to IRR on read */ 222#ifndef PC98 223 outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */ 224#endif /* !PC98 */ 225 226 outb(IO_ICU2, 0x11); /* reset; program device, four bytes */ 227 outb(IO_ICU2+ICU_IMR_OFFSET, NRSVIDT+8); /* staring at this vector index */ 228 outb(IO_ICU2+ICU_IMR_OFFSET, ICU_SLAVEID); /* my slave id is 7 */ 229#ifdef PC98 230 outb(IO_ICU2+ICU_IMR_OFFSET,9); /* 8086 mode */ 231#else /* IBM-PC */ 232#ifdef AUTO_EOI_2 233 outb(IO_ICU2+ICU_IMR_OFFSET, 2 | 1); /* auto EOI, 8086 mode */ 234#else 235 outb(IO_ICU2+ICU_IMR_OFFSET,1); /* 8086 mode */ 236#endif 237#endif /* PC98 */ 238 outb(IO_ICU2+ICU_IMR_OFFSET, 0xff); /* leave interrupts masked */ 239 outb(IO_ICU2, 0x0a); /* default to IRR on read */ 240} 241 242/* 243 * Caught a stray interrupt, notify 244 */ 245static void 246isa_strayintr(vcookiep) 247 void *vcookiep; 248{ 249 int intr = (void **)vcookiep - &intr_unit[0]; 250 251 /* DON'T BOTHER FOR NOW! */ 252 /* for some reason, we get bursts of intr #7, even if not enabled! */ 253 /* 254 * Well the reason you got bursts of intr #7 is because someone 255 * raised an interrupt line and dropped it before the 8259 could 256 * prioritize it. This is documented in the intel data book. This 257 * means you have BAD hardware! I have changed this so that only 258 * the first 5 get logged, then it quits logging them, and puts 259 * out a special message. rgrimes 3/25/1993 260 */ 261 /* 262 * XXX TODO print a different message for #7 if it is for a 263 * glitch. Glitches can be distinguished from real #7's by 264 * testing that the in-service bit is _not_ set. The test 265 * must be done before sending an EOI so it can't be done if 266 * we are using AUTO_EOI_1. 267 */ 268 if (intrcnt[1 + intr] <= 5) 269 log(LOG_ERR, "stray irq %d\n", intr); 270 if (intrcnt[1 + intr] == 5) 271 log(LOG_CRIT, 272 "too many stray irq %d's; not logging any more\n", intr); 273} 274 275/* 276 * Return a bitmap of the current interrupt requests. This is 8259-specific 277 * and is only suitable for use at probe time. 278 */ 279intrmask_t 280isa_irq_pending() 281{ 282 u_char irr1; 283 u_char irr2; 284 285 irr1 = inb(IO_ICU1); 286 irr2 = inb(IO_ICU2); 287 return ((irr2 << 8) | irr1); 288} 289 290int 291update_intr_masks(void) 292{ 293 int intr, n=0; 294 u_int mask,*maskptr; 295 296 for (intr=0; intr < ICU_LEN; intr ++) { 297#if defined(APIC_IO) 298 /* no 8259 SLAVE to ignore */ 299#else 300 if (intr==ICU_SLAVEID) continue; /* ignore 8259 SLAVE output */ 301#endif /* APIC_IO */ 302 maskptr = intr_mptr[intr]; 303 if (!maskptr) continue; 304 *maskptr |= 1 << intr; 305 mask = *maskptr; 306 if (mask != intr_mask[intr]) { 307#if 0 308 printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n", 309 intr, intr_mask[intr], mask, maskptr); 310#endif 311 intr_mask[intr]=mask; 312 n++; 313 } 314 315 } 316 return (n); 317} 318 319static const char * 320isa_get_nameunit(int id) 321{ 322 static char buf[32]; 323 struct isa_device *dp; 324 325 if (id == -1) 326 return ("pci"); /* XXX may also be eisa */ 327 if (id == 0) 328 return ("clk0"); /* XXX may also be sloppy driver */ 329 if (id == 1) 330 return ("rtc0");
|
346 return "???"; 347 348found_device: 349 snprintf(buf, sizeof(buf), "%s%d", dp->id_driver->name, dp->id_unit); 350 return (buf); 351} 352 353void 354update_intrname(int intr, int device_id) 355{ 356 char buf[32]; 357 char *cp; 358 const char *name; 359 int name_index, off, strayintr; 360 361 /* 362 * Initialise strings for bitbucket and stray interrupt counters. 363 * These have statically allocated indices 0 and 1 through ICU_LEN. 364 */ 365 if (intrnames[0] == '\0') { 366 off = sprintf(intrnames, "???") + 1; 367 for (strayintr = 0; strayintr < ICU_LEN; strayintr++) 368 off += sprintf(intrnames + off, "stray irq%d", 369 strayintr) + 1; 370 } 371 372 name = isa_get_nameunit(device_id); 373 if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf)) 374 goto use_bitbucket; 375 376 /* 377 * Search for `buf' in `intrnames'. In the usual case when it is 378 * not found, append it to the end if there is enough space (the \0 379 * terminator for the previous string, if any, becomes a separator). 380 */ 381 for (cp = intrnames, name_index = 0; 382 cp != eintrnames && name_index < NR_INTRNAMES; 383 cp += strlen(cp) + 1, name_index++) { 384 if (*cp == '\0') { 385 if (strlen(buf) >= eintrnames - cp) 386 break; 387 strcpy(cp, buf); 388 goto found; 389 } 390 if (strcmp(cp, buf) == 0) 391 goto found; 392 } 393 394use_bitbucket: 395 printf("update_intrname: counting %s irq%d as %s\n", name, intr, 396 intrnames); 397 name_index = 0; 398found: 399 intr_countp[intr] = &intrcnt[name_index]; 400} 401 402int 403icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) 404{ 405#ifdef FAST_HI 406 int select; /* the select register is 8 bits */ 407 int vector; 408 u_int32_t value; /* the window register is 32 bits */ 409#endif /* FAST_HI */ 410 u_long ef; 411 u_int mask = (maskptr ? *maskptr : 0); 412 413#if defined(APIC_IO) 414 if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */ 415#else 416 if ((u_int)intr >= ICU_LEN || intr == ICU_SLAVEID) 417#endif /* APIC_IO */ 418 if (intr_handler[intr] != isa_strayintr) 419 return (EBUSY); 420 421 ef = read_eflags(); 422 disable_intr(); 423 intr_handler[intr] = handler; 424 intr_mptr[intr] = maskptr; 425 intr_mask[intr] = mask | (1 << intr); 426 intr_unit[intr] = arg; 427#ifdef FAST_HI 428 if (flags & INTR_FAST) { 429 vector = TPR_FAST_INTS + intr; 430 setidt(vector, fastintr[intr], 431 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 432 } 433 else { 434 vector = TPR_SLOW_INTS + intr; 435#ifdef APIC_INTR_REORDER 436#ifdef APIC_INTR_HIGHPRI_CLOCK 437 /* XXX: Hack (kludge?) for more accurate clock. */ 438 if (intr == apic_8254_intr || intr == 8) { 439 vector = TPR_FAST_INTS + intr; 440 } 441#endif 442#endif 443 setidt(vector, slowintr[intr], 444 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 445 } 446#ifdef APIC_INTR_REORDER 447 set_lapic_isrloc(intr, vector); 448#endif 449 /* 450 * Reprogram the vector in the IO APIC. 451 */ 452 if (int_to_apicintpin[intr].ioapic >= 0) { 453 select = int_to_apicintpin[intr].redirindex; 454 value = io_apic_read(int_to_apicintpin[intr].ioapic, 455 select) & ~IOART_INTVEC; 456 io_apic_write(int_to_apicintpin[intr].ioapic, 457 select, value | vector); 458 } 459#else 460 setidt(ICU_OFFSET + intr, 461 flags & INTR_FAST ? fastintr[intr] : slowintr[intr], 462 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 463#endif /* FAST_HI */ 464 INTREN(1 << intr); 465 MPINTR_UNLOCK(); 466 write_eflags(ef); 467 return (0); 468} 469 470void 471register_imask(dvp, mask) 472 struct isa_device *dvp; 473 u_int mask; 474{ 475 if (dvp->id_alive && dvp->id_irq) { 476 int intr; 477 478 intr = ffs(dvp->id_irq) - 1; 479 intr_mask[intr] = mask | (1 <<intr); 480 } 481 (void) update_intr_masks(); 482} 483 484int 485icu_unset(intr, handler) 486 int intr; 487 inthand2_t *handler; 488{ 489 u_long ef; 490 491 if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) 492 return (EINVAL); 493 494 INTRDIS(1 << intr); 495 ef = read_eflags(); 496 disable_intr(); 497 intr_countp[intr] = &intrcnt[1 + intr]; 498 intr_handler[intr] = isa_strayintr; 499 intr_mptr[intr] = NULL; 500 intr_mask[intr] = HWI_MASK | SWI_MASK; 501 intr_unit[intr] = &intr_unit[intr]; 502#ifdef FAST_HI_XXX 503 /* XXX how do I re-create dvp here? */ 504 setidt(flags & INTR_FAST ? TPR_FAST_INTS + intr : TPR_SLOW_INTS + intr, 505 slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 506#else /* FAST_HI */ 507#ifdef APIC_INTR_REORDER 508 set_lapic_isrloc(intr, ICU_OFFSET + intr); 509#endif 510 setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL, 511 GSEL(GCODE_SEL, SEL_KPL)); 512#endif /* FAST_HI */ 513 MPINTR_UNLOCK(); 514 write_eflags(ef); 515 return (0); 516}
| 348 return "???"; 349 350found_device: 351 snprintf(buf, sizeof(buf), "%s%d", dp->id_driver->name, dp->id_unit); 352 return (buf); 353} 354 355void 356update_intrname(int intr, int device_id) 357{ 358 char buf[32]; 359 char *cp; 360 const char *name; 361 int name_index, off, strayintr; 362 363 /* 364 * Initialise strings for bitbucket and stray interrupt counters. 365 * These have statically allocated indices 0 and 1 through ICU_LEN. 366 */ 367 if (intrnames[0] == '\0') { 368 off = sprintf(intrnames, "???") + 1; 369 for (strayintr = 0; strayintr < ICU_LEN; strayintr++) 370 off += sprintf(intrnames + off, "stray irq%d", 371 strayintr) + 1; 372 } 373 374 name = isa_get_nameunit(device_id); 375 if (snprintf(buf, sizeof(buf), "%s irq%d", name, intr) >= sizeof(buf)) 376 goto use_bitbucket; 377 378 /* 379 * Search for `buf' in `intrnames'. In the usual case when it is 380 * not found, append it to the end if there is enough space (the \0 381 * terminator for the previous string, if any, becomes a separator). 382 */ 383 for (cp = intrnames, name_index = 0; 384 cp != eintrnames && name_index < NR_INTRNAMES; 385 cp += strlen(cp) + 1, name_index++) { 386 if (*cp == '\0') { 387 if (strlen(buf) >= eintrnames - cp) 388 break; 389 strcpy(cp, buf); 390 goto found; 391 } 392 if (strcmp(cp, buf) == 0) 393 goto found; 394 } 395 396use_bitbucket: 397 printf("update_intrname: counting %s irq%d as %s\n", name, intr, 398 intrnames); 399 name_index = 0; 400found: 401 intr_countp[intr] = &intrcnt[name_index]; 402} 403 404int 405icu_setup(int intr, inthand2_t *handler, void *arg, u_int *maskptr, int flags) 406{ 407#ifdef FAST_HI 408 int select; /* the select register is 8 bits */ 409 int vector; 410 u_int32_t value; /* the window register is 32 bits */ 411#endif /* FAST_HI */ 412 u_long ef; 413 u_int mask = (maskptr ? *maskptr : 0); 414 415#if defined(APIC_IO) 416 if ((u_int)intr >= ICU_LEN) /* no 8259 SLAVE to ignore */ 417#else 418 if ((u_int)intr >= ICU_LEN || intr == ICU_SLAVEID) 419#endif /* APIC_IO */ 420 if (intr_handler[intr] != isa_strayintr) 421 return (EBUSY); 422 423 ef = read_eflags(); 424 disable_intr(); 425 intr_handler[intr] = handler; 426 intr_mptr[intr] = maskptr; 427 intr_mask[intr] = mask | (1 << intr); 428 intr_unit[intr] = arg; 429#ifdef FAST_HI 430 if (flags & INTR_FAST) { 431 vector = TPR_FAST_INTS + intr; 432 setidt(vector, fastintr[intr], 433 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 434 } 435 else { 436 vector = TPR_SLOW_INTS + intr; 437#ifdef APIC_INTR_REORDER 438#ifdef APIC_INTR_HIGHPRI_CLOCK 439 /* XXX: Hack (kludge?) for more accurate clock. */ 440 if (intr == apic_8254_intr || intr == 8) { 441 vector = TPR_FAST_INTS + intr; 442 } 443#endif 444#endif 445 setidt(vector, slowintr[intr], 446 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 447 } 448#ifdef APIC_INTR_REORDER 449 set_lapic_isrloc(intr, vector); 450#endif 451 /* 452 * Reprogram the vector in the IO APIC. 453 */ 454 if (int_to_apicintpin[intr].ioapic >= 0) { 455 select = int_to_apicintpin[intr].redirindex; 456 value = io_apic_read(int_to_apicintpin[intr].ioapic, 457 select) & ~IOART_INTVEC; 458 io_apic_write(int_to_apicintpin[intr].ioapic, 459 select, value | vector); 460 } 461#else 462 setidt(ICU_OFFSET + intr, 463 flags & INTR_FAST ? fastintr[intr] : slowintr[intr], 464 SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 465#endif /* FAST_HI */ 466 INTREN(1 << intr); 467 MPINTR_UNLOCK(); 468 write_eflags(ef); 469 return (0); 470} 471 472void 473register_imask(dvp, mask) 474 struct isa_device *dvp; 475 u_int mask; 476{ 477 if (dvp->id_alive && dvp->id_irq) { 478 int intr; 479 480 intr = ffs(dvp->id_irq) - 1; 481 intr_mask[intr] = mask | (1 <<intr); 482 } 483 (void) update_intr_masks(); 484} 485 486int 487icu_unset(intr, handler) 488 int intr; 489 inthand2_t *handler; 490{ 491 u_long ef; 492 493 if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr]) 494 return (EINVAL); 495 496 INTRDIS(1 << intr); 497 ef = read_eflags(); 498 disable_intr(); 499 intr_countp[intr] = &intrcnt[1 + intr]; 500 intr_handler[intr] = isa_strayintr; 501 intr_mptr[intr] = NULL; 502 intr_mask[intr] = HWI_MASK | SWI_MASK; 503 intr_unit[intr] = &intr_unit[intr]; 504#ifdef FAST_HI_XXX 505 /* XXX how do I re-create dvp here? */ 506 setidt(flags & INTR_FAST ? TPR_FAST_INTS + intr : TPR_SLOW_INTS + intr, 507 slowintr[intr], SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 508#else /* FAST_HI */ 509#ifdef APIC_INTR_REORDER 510 set_lapic_isrloc(intr, ICU_OFFSET + intr); 511#endif 512 setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL, 513 GSEL(GCODE_SEL, SEL_KPL)); 514#endif /* FAST_HI */ 515 MPINTR_UNLOCK(); 516 write_eflags(ef); 517 return (0); 518}
|