00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
#include "ki.h"
00031
00032
00033
00034
00035
00036
00037
extern ULONG
KiStartUnexpectedRange(VOID);
00038
extern ULONG
KiEndUnexpectedRange(VOID);
00039 extern ULONG
KiUnexpectedEntrySize;
00040
00041
00042
VOID
00043
KiInterruptDispatch2ndLvl(
00044 VOID
00045 );
00046
00047
00048
VOID
00049
KiChainedDispatch2ndLvl(
00050 VOID
00051 );
00052
00053
00054 typedef enum {
00055
NoConnect,
00056
NormalConnect,
00057
ChainConnect,
00058
UnkownConnect
00059 }
CONNECT_TYPE, *
PCONNECT_TYPE;
00060
00061 typedef struct {
00062 CONNECT_TYPE Type;
00063 PKINTERRUPT Interrupt;
00064 PKINTERRUPT_ROUTINE NoDispatch;
00065 PKINTERRUPT_ROUTINE InterruptDispatch;
00066 PKINTERRUPT_ROUTINE FloatingDispatch;
00067 PKINTERRUPT_ROUTINE ChainedDispatch;
00068 PKINTERRUPT_ROUTINE *FlatDispatch;
00069 }
DISPATCH_INFO, *
PDISPATCH_INFO;
00070
00071
00072
VOID
00073
KiGetVectorInfo (
00074 IN ULONG Vector,
00075 OUT PDISPATCH_INFO DispatchInfo
00076 );
00077
00078
VOID
00079
KiConnectVectorAndInterruptObject (
00080 IN
PKINTERRUPT Interrupt,
00081 IN CONNECT_TYPE Type
00082 );
00083
00084
00085
VOID
00086 KeInitializeInterrupt (
00087 IN
PKINTERRUPT Interrupt,
00088 IN PKSERVICE_ROUTINE ServiceRoutine,
00089 IN PVOID ServiceContext,
00090 IN PKSPIN_LOCK SpinLock OPTIONAL,
00091 IN ULONG Vector,
00092 IN KIRQL Irql,
00093 IN KIRQL SynchronizeIrql,
00094 IN KINTERRUPT_MODE InterruptMode,
00095 IN BOOLEAN ShareVector,
00096 IN CCHAR ProcessorNumber,
00097 IN BOOLEAN FloatingSave
00098 )
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 {
00150
00151 LONG
Index;
00152 PULONG pl;
00153 PULONG NormalDispatchCode;
00154
00155
00156
00157
00158
00159 Interrupt->Type =
InterruptObject;
00160 Interrupt->Size =
sizeof(
KINTERRUPT);
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 Interrupt->ServiceRoutine = ServiceRoutine;
00171 Interrupt->ServiceContext = ServiceContext;
00172
00173
if (ARGUMENT_PRESENT(SpinLock)) {
00174 Interrupt->ActualLock = SpinLock;
00175 }
else {
00176
KeInitializeSpinLock (&Interrupt->SpinLock);
00177 Interrupt->ActualLock = &Interrupt->SpinLock;
00178 }
00179
00180 Interrupt->Vector = Vector;
00181 Interrupt->Irql = Irql;
00182 Interrupt->SynchronizeIrql = SynchronizeIrql;
00183 Interrupt->Mode = InterruptMode;
00184 Interrupt->ShareVector = ShareVector;
00185 Interrupt->Number = ProcessorNumber;
00186 Interrupt->FloatingSave = FloatingSave;
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 NormalDispatchCode = &(Interrupt->DispatchCode[0]);
00197
00198 pl = NormalDispatchCode;
00199
00200
for (
Index = 0;
Index < NORMAL_DISPATCH_LENGTH;
Index += 1) {
00201 *NormalDispatchCode++ = KiInterruptTemplate[
Index];
00202 }
00203
00204
00205
00206
00207
00208
00209 pl = (PULONG)((PUCHAR)pl + ((PUCHAR)&KiInterruptTemplateObject -
00210 (PUCHAR)KiInterruptTemplate) -4);
00211 *pl = (ULONG)Interrupt;
00212
00213
KeSweepDcache(
FALSE);
00214
00215
00216
00217
00218
00219 Interrupt->Connected =
FALSE;
00220
return;
00221 }
00222
00223 BOOLEAN
00224 KeConnectInterrupt (
00225 IN
PKINTERRUPT Interrupt
00226 )
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 {
00252
DISPATCH_INFO DispatchInfo;
00253 BOOLEAN Connected;
00254 BOOLEAN ConnectError;
00255 BOOLEAN Enabled;
00256 KIRQL Irql;
00257 CCHAR Number;
00258 KIRQL OldIrql;
00259 ULONG Vector;
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 Connected =
FALSE;
00271 ConnectError =
FALSE;
00272 Irql = Interrupt->Irql;
00273 Number = Interrupt->Number;
00274 Vector = Interrupt->Vector;
00275
if ( !((Irql >
HIGH_LEVEL) ||
00276 (Number >=
KeNumberProcessors) ||
00277 (Interrupt->SynchronizeIrql < Irql) ||
00278 (Interrupt->FloatingSave)
00279 )
00280 ) {
00281
00282
00283
00284
00285
00286
00287
KeSetSystemAffinityThread((KAFFINITY)(1<<Number));
00288
00289
00290
00291
00292
00293
KiLockDispatcherDatabase(&OldIrql);
00294
00295
00296
00297
00298
00299
if (!Interrupt->Connected) {
00300
00301
00302
00303
00304
00305
KiGetVectorInfo (
00306 Vector,
00307 &DispatchInfo
00308 );
00309
00310
00311
00312
00313
00314
if (DispatchInfo.
Type ==
NoConnect) {
00315 Connected =
TRUE;
00316 Interrupt->Connected =
TRUE;
00317
00318
00319
00320
00321
00322 InitializeListHead(&Interrupt->InterruptListEntry);
00323
KiConnectVectorAndInterruptObject (Interrupt,
NormalConnect);
00324
00325
00326
00327
00328
00329 Enabled =
HalEnableSystemInterrupt(Vector, Irql, Interrupt->Mode);
00330
if (!Enabled) {
00331 ConnectError =
TRUE;
00332 }
00333
00334
00335 }
else if (DispatchInfo.
Type !=
UnkownConnect &&
00336 Interrupt->ShareVector &&
00337 DispatchInfo.
Interrupt->
ShareVector &&
00338 DispatchInfo.
Interrupt->
Mode == Interrupt->Mode) {
00339
00340
00341
00342
00343
00344
00345 Connected =
TRUE;
00346 Interrupt->Connected =
TRUE;
00347
00348
ASSERT (Irql <=
SYNCH_LEVEL);
00349
00350
00351
00352
00353
00354
if (DispatchInfo.
Type !=
ChainConnect) {
00355
KiConnectVectorAndInterruptObject (DispatchInfo.
Interrupt,
ChainConnect);
00356 }
00357
00358
00359
00360
00361
00362 InsertTailList(
00363 &DispatchInfo.
Interrupt->
InterruptListEntry,
00364 &Interrupt->InterruptListEntry
00365 );
00366
00367 }
00368 }
00369
00370
00371
00372
00373
00374
KiUnlockDispatcherDatabase(OldIrql);
00375
00376
00377
00378
00379
00380
KeRevertToUserAffinityThread();
00381 }
00382
00383
if (Connected && ConnectError) {
00384
#if DBG
00385
DbgPrint (
"HalEnableSystemInterrupt failed\n");
00386
#endif
00387
KeDisconnectInterrupt (Interrupt);
00388 Connected =
FALSE;
00389 }
00390
00391
00392
00393
00394
00395
return Connected;
00396 }
00397
00398 BOOLEAN
00399 KeDisconnectInterrupt (
00400 IN
PKINTERRUPT Interrupt
00401 )
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 {
00425
00426
DISPATCH_INFO DispatchInfo;
00427 BOOLEAN Connected;
00428
PKINTERRUPT Interrupty;
00429 KIRQL Irql;
00430 KIRQL OldIrql;
00431 ULONG Vector;
00432
00433
00434
00435
00436
00437
KeSetSystemAffinityThread((KAFFINITY)(1<<Interrupt->Number));
00438
00439
00440
00441
00442
00443
KiLockDispatcherDatabase(&OldIrql);
00444
00445
00446
00447
00448
00449
00450 Connected = Interrupt->Connected;
00451
if (Connected) {
00452 Irql = Interrupt->Irql;
00453 Vector = Interrupt->Vector;
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
KiGetVectorInfo (
00469 Vector,
00470 &DispatchInfo
00471 );
00472
00473
00474
00475
00476
00477
00478
if (DispatchInfo.
Type ==
ChainConnect) {
00479
00480
ASSERT (Irql <=
SYNCH_LEVEL);
00481
00482
00483
00484
00485
00486
if (Interrupt == DispatchInfo.
Interrupt) {
00487
00488
00489
00490
00491
00492 DispatchInfo.
Interrupt = CONTAINING_RECORD(
00493 DispatchInfo.
Interrupt->
InterruptListEntry.Flink,
00494
KINTERRUPT,
00495 InterruptListEntry
00496 );
00497
00498
KiConnectVectorAndInterruptObject (DispatchInfo.
Interrupt,
ChainConnect);
00499 }
00500
00501
00502
00503
00504
00505 RemoveEntryList(&Interrupt->InterruptListEntry);
00506
00507
00508
00509
00510
00511
00512 Interrupty = CONTAINING_RECORD(
00513 DispatchInfo.
Interrupt->
InterruptListEntry.Flink,
00514
KINTERRUPT,
00515 InterruptListEntry
00516 );
00517
00518
if (DispatchInfo.
Interrupt == Interrupty) {
00519
KiConnectVectorAndInterruptObject (Interrupty,
NormalConnect);
00520 }
00521
00522 }
else {
00523
00524
00525
00526
00527
00528
00529
HalDisableSystemInterrupt(Interrupt->Vector, Irql);
00530
KiConnectVectorAndInterruptObject (Interrupt,
NoConnect);
00531 }
00532
00533
00534
KeSweepIcache(
TRUE);
00535 Interrupt->Connected =
FALSE;
00536 }
00537
00538
00539
00540
00541
00542
KiUnlockDispatcherDatabase(OldIrql);
00543
00544
00545
00546
00547
00548
KeRevertToUserAffinityThread();
00549
00550
00551
00552
00553
00554
return Connected;
00555 }
00556
00557
VOID
00558 KiGetVectorInfo (
00559 IN ULONG Vector,
00560 OUT PDISPATCH_INFO DispatchInfo
00561 )
00562 {
00563 PKINTERRUPT_ROUTINE Dispatch;
00564 ULONG CurrentDispatch;
00565 ULONG DispatchType;
00566
00567
00568
00569
00570
00571
00572 DispatchType = HalSystemVectorDispatchEntry (
00573 Vector,
00574 &DispatchInfo->FlatDispatch,
00575 &DispatchInfo->NoDispatch
00576 );
00577
00578
00579
00580
00581
00582
switch (DispatchType) {
00583
case 0:
00584
00585
00586
00587
00588 DispatchInfo->NoDispatch = (PKINTERRUPT_ROUTINE) (((ULONG) &
KiStartUnexpectedRange) +
00589 (Vector - PRIMARY_VECTOR_BASE) *
KiUnexpectedEntrySize);
00590
00591 DispatchInfo->InterruptDispatch =
KiInterruptDispatch;
00592 DispatchInfo->FloatingDispatch =
KiFloatingDispatch;
00593 DispatchInfo->ChainedDispatch =
KiChainedDispatch;
00594 DispatchInfo->FlatDispatch =
NULL;
00595
00596 CurrentDispatch = (ULONG) KiReturnHandlerAddressFromIDT(Vector);
00597 DispatchInfo->Interrupt = CONTAINING_RECORD (
00598 CurrentDispatch,
00599
KINTERRUPT,
00600 DispatchCode
00601 );
00602
break;
00603
00604
case 1:
00605
00606
00607
00608
00609 DispatchInfo->InterruptDispatch =
KiInterruptDispatch2ndLvl;
00610 DispatchInfo->FloatingDispatch =
KiInterruptDispatch2ndLvl;
00611 DispatchInfo->ChainedDispatch =
KiChainedDispatch2ndLvl;
00612
00613 CurrentDispatch = (ULONG) *DispatchInfo->FlatDispatch;
00614 DispatchInfo->Interrupt = (
PKINTERRUPT) ( (PUCHAR) CurrentDispatch -
00615 (PUCHAR) KiInterruptTemplate +
00616 (PUCHAR) &KiInterruptTemplate2ndDispatch
00617 );
00618
break;
00619
00620
default:
00621
00622
KeBugCheck (MISMATCHED_HAL);
00623 }
00624
00625
00626
00627
00628
00629
00630
if (((PKINTERRUPT_ROUTINE) CurrentDispatch) == DispatchInfo->NoDispatch) {
00631
00632
00633
00634
00635
00636 DispatchInfo->Type =
NoConnect;
00637
00638 }
else {
00639 Dispatch = DispatchInfo->Interrupt->DispatchAddress;
00640
00641
if (Dispatch == DispatchInfo->ChainedDispatch) {
00642
00643
00644
00645
00646 DispatchInfo->Type =
ChainConnect;
00647
00648 }
else if (Dispatch == DispatchInfo->InterruptDispatch ||
00649 Dispatch == DispatchInfo->FloatingDispatch) {
00650
00651
00652
00653
00654 DispatchInfo->Type =
NormalConnect;
00655
00656 }
else {
00657
00658
00659
00660
00661
00662 DispatchInfo->Type =
UnkownConnect;
00663
#if DBG
00664
DbgPrint (
"KiGetVectorInfo not understood\n");
00665
#endif
00666
}
00667 }
00668 }
00669
00670
VOID
00671 KiConnectVectorAndInterruptObject (
00672 IN
PKINTERRUPT Interrupt,
00673 IN CONNECT_TYPE Type
00674 )
00675 {
00676 PKINTERRUPT_ROUTINE DispatchAddress;
00677
DISPATCH_INFO DispatchInfo;
00678 PULONG pl;
00679
00680
00681
00682
00683
00684
KiGetVectorInfo (
00685 Interrupt->Vector,
00686 &DispatchInfo
00687 );
00688
00689
00690
00691
00692
00693
if (Type ==
NoConnect) {
00694
00695 DispatchAddress = DispatchInfo.
NoDispatch;
00696
00697 }
else {
00698
00699
00700
00701
00702
00703 DispatchAddress = DispatchInfo.
ChainedDispatch;
00704
00705
if (Type ==
NormalConnect) {
00706 DispatchAddress = DispatchInfo.
InterruptDispatch;
00707
if (Interrupt->FloatingSave) {
00708 DispatchAddress = DispatchInfo.
FloatingDispatch;
00709 }
00710 }
00711
00712 Interrupt->DispatchAddress = DispatchAddress;
00713
00714
00715
00716
00717
00718 pl = &(Interrupt->DispatchCode[0]);
00719 pl = (PULONG)((PUCHAR)pl +
00720 ((PUCHAR)&KiInterruptTemplateDispatch -
00721 (PUCHAR)KiInterruptTemplate) -4);
00722
00723 *pl = (ULONG)DispatchAddress-(ULONG)((PUCHAR)pl+4);
00724
00725
00726
00727
00728
00729
if (DispatchInfo.
FlatDispatch) {
00730
00731
00732
00733
00734
00735 DispatchAddress = (PKINTERRUPT_ROUTINE)
00736 ((PUCHAR) &(Interrupt->DispatchCode[0]) +
00737 ((PUCHAR) &KiInterruptTemplate2ndDispatch -
00738 (PUCHAR) KiInterruptTemplate));
00739
00740 }
else {
00741
00742
00743
00744
00745
00746 DispatchAddress = (PKINTERRUPT_ROUTINE) &Interrupt->DispatchCode;
00747 }
00748 }
00749
00750
00751
if (DispatchInfo.
FlatDispatch) {
00752
00753
00754
00755
00756
00757 *DispatchInfo.
FlatDispatch = DispatchAddress;
00758
00759 }
else {
00760
00761
00762
00763
00764
00765 KiSetHandlerAddressToIDT (Interrupt->Vector, DispatchAddress);
00766 }
00767 }