1 /* 2 * Copyright (c) 1991 The Regents of the University of California. 3 * Copyright (c) 2005,2008 The DragonFly Project. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The DragonFly Project 7 * by Matthew Dillon <dillon@backplane.com> 8 * 9 * This code is derived from software contributed to Berkeley by 10 * William Jolitz. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in 20 * the documentation and/or other materials provided with the 21 * distribution. 22 * 3. Neither the name of The DragonFly Project nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific, prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 30 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 31 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 34 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * $DragonFly: src/sys/platform/pc64/icu/icu_abi.c,v 1.1 2008/08/29 17:07:16 dillon Exp $ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/machintr.h> 46 #include <sys/interrupt.h> 47 #include <sys/bus.h> 48 49 #include <machine/segments.h> 50 #include <machine/md_var.h> 51 #include <machine_base/isa/intr_machdep.h> 52 #include <machine/globaldata.h> 53 54 #include <sys/thread2.h> 55 56 #include "icu.h" 57 #include "icu_ipl.h" 58 59 #ifndef APIC_IO 60 61 extern void ICU_INTREN(int); 62 extern void ICU_INTRDIS(int); 63 64 extern inthand_t 65 IDTVEC(icu_fastintr0), IDTVEC(icu_fastintr1), 66 IDTVEC(icu_fastintr2), IDTVEC(icu_fastintr3), 67 IDTVEC(icu_fastintr4), IDTVEC(icu_fastintr5), 68 IDTVEC(icu_fastintr6), IDTVEC(icu_fastintr7), 69 IDTVEC(icu_fastintr8), IDTVEC(icu_fastintr9), 70 IDTVEC(icu_fastintr10), IDTVEC(icu_fastintr11), 71 IDTVEC(icu_fastintr12), IDTVEC(icu_fastintr13), 72 IDTVEC(icu_fastintr14), IDTVEC(icu_fastintr15); 73 74 static int icu_vectorctl(int, int, int); 75 static int icu_setvar(int, const void *); 76 static int icu_getvar(int, void *); 77 static void icu_finalize(void); 78 static void icu_cleanup(void); 79 80 static inthand_t *icu_fastintr[ICU_HWI_VECTORS] = { 81 &IDTVEC(icu_fastintr0), &IDTVEC(icu_fastintr1), 82 &IDTVEC(icu_fastintr2), &IDTVEC(icu_fastintr3), 83 &IDTVEC(icu_fastintr4), &IDTVEC(icu_fastintr5), 84 &IDTVEC(icu_fastintr6), &IDTVEC(icu_fastintr7), 85 &IDTVEC(icu_fastintr8), &IDTVEC(icu_fastintr9), 86 &IDTVEC(icu_fastintr10), &IDTVEC(icu_fastintr11), 87 &IDTVEC(icu_fastintr12), &IDTVEC(icu_fastintr13), 88 &IDTVEC(icu_fastintr14), &IDTVEC(icu_fastintr15) 89 }; 90 91 struct machintr_abi MachIntrABI = { 92 MACHINTR_ICU, 93 .intrdis = ICU_INTRDIS, 94 .intren = ICU_INTREN, 95 .vectorctl =icu_vectorctl, 96 .setvar = icu_setvar, 97 .getvar = icu_getvar, 98 .finalize = icu_finalize, 99 .cleanup = icu_cleanup 100 }; 101 102 static int icu_imcr_present; 103 104 /* 105 * WARNING! SMP builds can use the ICU now so this code must be MP safe. 106 */ 107 static 108 int 109 icu_setvar(int varid, const void *buf) 110 { 111 int error = 0; 112 113 switch(varid) { 114 case MACHINTR_VAR_IMCR_PRESENT: 115 icu_imcr_present = *(const int *)buf; 116 break; 117 default: 118 error = ENOENT; 119 break; 120 } 121 return (error); 122 } 123 124 static 125 int 126 icu_getvar(int varid, void *buf) 127 { 128 int error = 0; 129 130 switch(varid) { 131 case MACHINTR_VAR_IMCR_PRESENT: 132 *(int *)buf = icu_imcr_present; 133 break; 134 default: 135 error = ENOENT; 136 break; 137 } 138 return (error); 139 } 140 141 /* 142 * Called before interrupts are physically enabled 143 */ 144 static void 145 icu_finalize(void) 146 { 147 int intr; 148 149 for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) { 150 machintr_intrdis(intr); 151 } 152 machintr_intren(ICU_IRQ_SLAVE); 153 154 /* 155 * If an IMCR is present, programming bit 0 disconnects the 8259 156 * from the BSP. The 8259 may still be connected to LINT0 on the BSP's 157 * LAPIC. 158 * 159 * If we are running SMP the LAPIC is active, try to use virtual wire 160 * mode so we can use other interrupt sources within the LAPIC in 161 * addition to the 8259. 162 */ 163 if (icu_imcr_present) { 164 #if defined(SMP) 165 outb(0x22, 0x70); 166 outb(0x23, 0x01); 167 #endif 168 } 169 } 170 171 /* 172 * Called after interrupts physically enabled but before the 173 * critical section is released. 174 */ 175 static 176 void 177 icu_cleanup(void) 178 { 179 mdcpu->gd_fpending = 0; 180 } 181 182 183 static 184 int 185 icu_vectorctl(int op, int intr, int flags) 186 { 187 int error; 188 register_t ef; 189 190 if (intr < 0 || intr >= ICU_HWI_VECTORS || intr == ICU_IRQ_SLAVE) 191 return (EINVAL); 192 193 ef = read_rflags(); 194 cpu_disable_intr(); 195 error = 0; 196 197 switch(op) { 198 case MACHINTR_VECTOR_SETUP: 199 setidt(IDT_OFFSET + intr, icu_fastintr[intr], SDT_SYSIGT, SEL_KPL, 0); 200 machintr_intren(intr); 201 break; 202 case MACHINTR_VECTOR_TEARDOWN: 203 case MACHINTR_VECTOR_SETDEFAULT: 204 setidt(IDT_OFFSET + intr, icu_fastintr[intr], SDT_SYSIGT, SEL_KPL, 0); 205 machintr_intrdis(intr); 206 break; 207 default: 208 error = EOPNOTSUPP; 209 break; 210 } 211 write_rflags(ef); 212 return (error); 213 } 214 215 #endif 216