Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenirql.c
Go to the documentation of this file.
00001 /* $Id$ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS kernel 00005 * FILE: ntoskrnl/hal/x86/irql.c 00006 * PURPOSE: Implements IRQLs 00007 * PROGRAMMER: David Welch (welch@cwcom.net) 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <hal.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS ******************************************************************/ 00017 00018 /* 00019 * FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS 00020 */ 00021 00022 typedef union 00023 { 00024 USHORT both; 00025 struct 00026 { 00027 UCHAR master; 00028 UCHAR slave; 00029 }; 00030 } 00031 PIC_MASK; 00032 00033 /* 00034 * PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt 00035 * - At startup enable timer and cascade 00036 */ 00037 #if defined(__GNUC__) 00038 static PIC_MASK pic_mask = {.both = 0xFFFA}; 00039 #else 00040 static PIC_MASK pic_mask = { 0xFFFA }; 00041 #endif 00042 00043 00044 /* 00045 * PURPOSE: Mask for disabling of acknowledged interrupts 00046 */ 00047 #if defined(__GNUC__) 00048 static PIC_MASK pic_mask_intr = {.both = 0x0000}; 00049 #else 00050 static PIC_MASK pic_mask_intr = { 0 }; 00051 #endif 00052 00053 static ULONG HalpPendingInterruptCount[NR_IRQS]; 00054 00055 #define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x) 00056 #define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x) 00057 00058 #ifdef _MSC_VER 00059 00060 #define KiInterruptDispatch2(x, y) 00061 00062 #else 00063 00064 VOID NTAPI 00065 KiInterruptDispatch2 (ULONG Irq, KIRQL old_level); 00066 00067 #endif 00068 00069 /* FUNCTIONS ****************************************************************/ 00070 00071 #undef KeGetCurrentIrql 00072 KIRQL NTAPI KeGetCurrentIrql (VOID) 00073 /* 00074 * PURPOSE: Returns the current irq level 00075 * RETURNS: The current irq level 00076 */ 00077 { 00078 return(KeGetPcr()->Irql); 00079 } 00080 00081 VOID NTAPI HalpInitPICs(VOID) 00082 { 00083 memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount)); 00084 00085 /* Initialization sequence */ 00086 WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11); 00087 WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11); 00088 /* Start of hardware irqs (0x24) */ 00089 WRITE_PORT_UCHAR((PUCHAR)0x21, IRQ_BASE); 00090 WRITE_PORT_UCHAR((PUCHAR)0xa1, IRQ_BASE + 8); 00091 /* 8259-1 is master */ 00092 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4); 00093 /* 8259-2 is slave */ 00094 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2); 00095 /* 8086 mode */ 00096 WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1); 00097 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1); 00098 /* Enable interrupts */ 00099 WRITE_PORT_UCHAR((PUCHAR)0x21, 0xFF); 00100 WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xFF); 00101 00102 /* We can now enable interrupts */ 00103 _enable(); 00104 } 00105 00106 VOID HalpEndSystemInterrupt(KIRQL Irql) 00107 /* 00108 * FUNCTION: Enable all irqs with higher priority. 00109 */ 00110 { 00111 const USHORT mask[] = 00112 { 00113 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 00114 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 00115 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0, 00116 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 00117 }; 00118 00119 /* Interrupts should be disable while enabling irqs of both pics */ 00120 _disable(); 00121 00122 pic_mask_intr.both &= mask[Irql]; 00123 WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master)); 00124 WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); 00125 00126 /* restore ints */ 00127 _enable(); 00128 } 00129 00130 VOID 00131 HalpExecuteIrqs(KIRQL NewIrql) 00132 { 00133 ULONG IrqLimit, i; 00134 IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS); 00135 00136 /* 00137 * For each irq if there have been any deferred interrupts then now 00138 * dispatch them. 00139 */ 00140 for (i = 0; i < IrqLimit; i++) 00141 { 00142 if (HalpPendingInterruptCount[i] > 0) 00143 { 00144 KeGetPcr()->Irql = (KIRQL)IRQ_TO_DIRQL(i); 00145 00146 while (HalpPendingInterruptCount[i] > 0) 00147 { 00148 /* 00149 * For each deferred interrupt execute all the handlers at DIRQL. 00150 */ 00151 HalpPendingInterruptCount[i]--; 00152 //HalpHardwareInt[i](); 00153 } 00154 //KeGetPcr()->Irql--; 00155 //HalpEndSystemInterrupt(KeGetPcr()->Irql); 00156 } 00157 } 00158 00159 } 00160 00161 VOID 00162 HalpLowerIrql(KIRQL NewIrql) 00163 { 00164 if (NewIrql >= PROFILE_LEVEL) 00165 { 00166 KeGetPcr()->Irql = NewIrql; 00167 return; 00168 } 00169 HalpExecuteIrqs(NewIrql); 00170 if (NewIrql >= DISPATCH_LEVEL) 00171 { 00172 KeGetPcr()->Irql = NewIrql; 00173 return; 00174 } 00175 KeGetPcr()->Irql = DISPATCH_LEVEL; 00176 if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST]) 00177 { 00178 ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE; 00179 KiDispatchInterrupt(); 00180 } 00181 KeGetPcr()->Irql = APC_LEVEL; 00182 if (NewIrql == APC_LEVEL) 00183 { 00184 return; 00185 } 00186 if (KeGetCurrentThread() != NULL && 00187 KeGetCurrentThread()->ApcState.KernelApcPending) 00188 { 00189 KiDeliverApc(KernelMode, NULL, NULL); 00190 } 00191 KeGetPcr()->Irql = PASSIVE_LEVEL; 00192 } 00193 00194 /********************************************************************** 00195 * NAME EXPORTED 00196 * KfLowerIrql 00197 * 00198 * DESCRIPTION 00199 * Restores the irq level on the current processor 00200 * 00201 * ARGUMENTS 00202 * NewIrql = Irql to lower to 00203 * 00204 * RETURN VALUE 00205 * None 00206 * 00207 * NOTES 00208 * Uses fastcall convention 00209 */ 00210 VOID FASTCALL 00211 KfLowerIrql (KIRQL NewIrql) 00212 { 00213 DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql); 00214 00215 if (NewIrql > KeGetPcr()->Irql) 00216 { 00217 DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n", 00218 __FILE__, __LINE__, NewIrql, KeGetPcr()->Irql); 00219 KeBugCheck(IRQL_NOT_LESS_OR_EQUAL); 00220 for(;;); 00221 } 00222 00223 HalpLowerIrql(NewIrql); 00224 } 00225 00226 /********************************************************************** 00227 * NAME EXPORTED 00228 * KfRaiseIrql 00229 * 00230 * DESCRIPTION 00231 * Raises the hardware priority (irql) 00232 * 00233 * ARGUMENTS 00234 * NewIrql = Irql to raise to 00235 * 00236 * RETURN VALUE 00237 * previous irq level 00238 * 00239 * NOTES 00240 * Uses fastcall convention 00241 */ 00242 00243 KIRQL FASTCALL 00244 KfRaiseIrql (KIRQL NewIrql) 00245 { 00246 KIRQL OldIrql; 00247 00248 DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql); 00249 00250 if (NewIrql < KeGetPcr()->Irql) 00251 { 00252 DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n", 00253 __FILE__,__LINE__,KeGetPcr()->Irql,NewIrql); 00254 KeBugCheck (IRQL_NOT_GREATER_OR_EQUAL); 00255 for(;;); 00256 } 00257 00258 OldIrql = KeGetPcr()->Irql; 00259 KeGetPcr()->Irql = NewIrql; 00260 return OldIrql; 00261 } 00262 00263 /********************************************************************** 00264 * NAME EXPORTED 00265 * KeRaiseIrqlToDpcLevel 00266 * 00267 * DESCRIPTION 00268 * Raises the hardware priority (irql) to DISPATCH level 00269 * 00270 * ARGUMENTS 00271 * None 00272 * 00273 * RETURN VALUE 00274 * Previous irq level 00275 * 00276 * NOTES 00277 * Calls KfRaiseIrql 00278 */ 00279 00280 KIRQL NTAPI 00281 KeRaiseIrqlToDpcLevel (VOID) 00282 { 00283 return KfRaiseIrql (DISPATCH_LEVEL); 00284 } 00285 00286 00287 /********************************************************************** 00288 * NAME EXPORTED 00289 * KeRaiseIrqlToSynchLevel 00290 * 00291 * DESCRIPTION 00292 * Raises the hardware priority (irql) to CLOCK2 level 00293 * 00294 * ARGUMENTS 00295 * None 00296 * 00297 * RETURN VALUE 00298 * Previous irq level 00299 * 00300 * NOTES 00301 * Calls KfRaiseIrql 00302 */ 00303 00304 KIRQL NTAPI 00305 KeRaiseIrqlToSynchLevel (VOID) 00306 { 00307 return KfRaiseIrql (DISPATCH_LEVEL); 00308 } 00309 00310 00311 BOOLEAN NTAPI 00312 HalBeginSystemInterrupt (KIRQL Irql, 00313 ULONG Vector, 00314 PKIRQL OldIrql) 00315 { 00316 ULONG irq; 00317 if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) 00318 { 00319 return(FALSE); 00320 } 00321 irq = Vector - IRQ_BASE; 00322 pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt 00323 00324 if (irq < 8) 00325 { 00326 WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master)); 00327 WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20); 00328 } 00329 else 00330 { 00331 WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); 00332 /* Send EOI to the PICs */ 00333 WRITE_PORT_UCHAR((PUCHAR)0x20,0x20); 00334 WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20); 00335 } 00336 #if 0 00337 if (KeGetPcr()->Irql >= Irql) 00338 { 00339 HalpPendingInterruptCount[irq]++; 00340 return(FALSE); 00341 } 00342 #endif 00343 *OldIrql = KeGetPcr()->Irql; 00344 KeGetPcr()->Irql = Irql; 00345 00346 return(TRUE); 00347 } 00348 00349 00350 VOID NTAPI HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2) 00351 /* 00352 * FUNCTION: Finish a system interrupt and restore the specified irq level. 00353 */ 00354 { 00355 HalpLowerIrql(Irql); 00356 HalpEndSystemInterrupt(Irql); 00357 } 00358 00359 VOID 00360 NTAPI 00361 HalDisableSystemInterrupt( 00362 ULONG Vector, 00363 KIRQL Irql) 00364 { 00365 ULONG irq; 00366 00367 if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) 00368 { 00369 ASSERT(FALSE); 00370 return; 00371 } 00372 00373 irq = Vector - IRQ_BASE; 00374 pic_mask.both |= (1 << irq); 00375 if (irq < 8) 00376 { 00377 WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.slave)); 00378 } 00379 else 00380 { 00381 WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); 00382 } 00383 00384 return; 00385 } 00386 00387 00388 BOOLEAN 00389 NTAPI 00390 HalEnableSystemInterrupt( 00391 ULONG Vector, 00392 KIRQL Irql, 00393 KINTERRUPT_MODE InterruptMode) 00394 { 00395 ULONG irq; 00396 00397 if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS) 00398 return FALSE; 00399 00400 irq = Vector - IRQ_BASE; 00401 pic_mask.both &= ~(1 << irq); 00402 if (irq < 8) 00403 { 00404 WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master)); 00405 } 00406 else 00407 { 00408 WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave)); 00409 } 00410 00411 return TRUE; 00412 } 00413 00414 00415 VOID FASTCALL 00416 HalRequestSoftwareInterrupt( 00417 IN KIRQL Request) 00418 { 00419 switch (Request) 00420 { 00421 case APC_LEVEL: 00422 ((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE; 00423 break; 00424 00425 case DISPATCH_LEVEL: 00426 ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE; 00427 break; 00428 00429 default: 00430 DbgBreakPoint(); 00431 } 00432 } 00433 00434 VOID FASTCALL 00435 HalClearSoftwareInterrupt( 00436 IN KIRQL Request) 00437 { 00438 switch (Request) 00439 { 00440 case APC_LEVEL: 00441 ((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = FALSE; 00442 break; 00443 00444 case DISPATCH_LEVEL: 00445 ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE; 00446 break; 00447 00448 default: 00449 DbgBreakPoint(); 00450 } 00451 } 00452 00453 /* EOF */ Generated on Sun May 27 2012 04:28:41 for ReactOS by
1.7.6.1
|