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 
#include "ki.h"
00028 
00029 
VOID
00030 KeInitializeInterrupt (
00031     IN 
PKINTERRUPT Interrupt,
00032     IN PKSERVICE_ROUTINE ServiceRoutine,
00033     IN PVOID ServiceContext,
00034     IN PKSPIN_LOCK SpinLock OPTIONAL,
00035     IN ULONG Vector,
00036     IN KIRQL Irql,
00037     IN KIRQL SynchronizeIrql,
00038     IN KINTERRUPT_MODE InterruptMode,
00039     IN BOOLEAN ShareVector,
00040     IN CCHAR ProcessorNumber,
00041     IN BOOLEAN FloatingSave
00042     )
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 {
00095 
00096     LONG 
Index;
00097 
00098     
00099     
00100     
00101 
00102     Interrupt->Type = 
InterruptObject;
00103     Interrupt->Size = 
sizeof(
KINTERRUPT);
00104 
00105     
00106     
00107     
00108     
00109     
00110     
00111     
00112 
00113     Interrupt->ServiceRoutine = ServiceRoutine; 
00114     Interrupt->ServiceContext = ServiceContext;
00115 
00116     
if (ARGUMENT_PRESENT(SpinLock)) {
00117         Interrupt->ActualLock = SpinLock;
00118 
00119     } 
else {
00120         Interrupt->SpinLock = 0;
00121         Interrupt->ActualLock = &Interrupt->SpinLock;
00122     }
00123 
00124     Interrupt->Vector = Vector;
00125     Interrupt->Irql = Irql;
00126     Interrupt->SynchronizeIrql = SynchronizeIrql;
00127     Interrupt->Mode = InterruptMode;
00128     Interrupt->ShareVector = ShareVector;
00129     Interrupt->Number = ProcessorNumber;
00130     Interrupt->FloatingSave = FloatingSave;
00131 
00132     
00133     
00134     
00135 
00136     Interrupt->Connected = 
FALSE;
00137     
return;
00138 }
00139 
00140 BOOLEAN
00141 KeConnectInterrupt (
00142     IN 
PKINTERRUPT Interrupt
00143     )
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 {
00169 
00170     BOOLEAN Connected;
00171     
PKINTERRUPT Interruptx;
00172     KIRQL Irql;
00173     
CHAR Number;
00174     KIRQL OldIrql;
00175     ULONG Vector;
00176 
00177     
00178     
00179     
00180     
00181     
00182     
00183     
00184     
00185     
00186     
00187 
00188     Connected = 
FALSE;
00189     Irql = Interrupt->Irql;
00190     Number = Interrupt->Number;
00191     Vector = Interrupt->Vector;
00192     
if ((((Vector >= MAXIMUM_VECTOR) || (Irql > 
HIGH_LEVEL) ||
00193        ((Vector <= 
HIGH_LEVEL) &&
00194        ((((1 << Vector) & PCR->ReservedVectors) != 0) || (Vector != Irql))) ||
00195        (Number >= 
KeNumberProcessors))) == 
FALSE) {
00196 
00197         
00198         
00199         
00200 
00201         
KeSetSystemAffinityThread((KAFFINITY)(1 << Number));
00202 
00203         
00204         
00205         
00206 
00207         
KiLockDispatcherDatabase(&OldIrql);
00208 
00209         
00210         
00211         
00212         
00213         
00214         
00215         
00216         
00217         
00218         
00219         
00220 
00221         
if (Interrupt->Connected == 
FALSE) {
00222             
if (PCR->InterruptRoutine[Vector] ==
00223                 (PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode)) {
00224                 Connected = 
TRUE;
00225                 Interrupt->Connected = 
TRUE;
00226                 
if (Interrupt->FloatingSave != 
FALSE) {
00227                     Interrupt->DispatchAddress = 
KiFloatingDispatch;
00228 
00229                 } 
else {
00230                     
if (Interrupt->Irql == Interrupt->SynchronizeIrql) {
00231                         Interrupt->DispatchAddress =
00232                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchSame;
00233 
00234                     } 
else {
00235                         Interrupt->DispatchAddress =
00236                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchRaise;
00237                     }
00238                 }
00239 
00240                 
00241                 
00242                 
00243                 
00244                 
00245 
00246 
00247                 RtlMoveMemory(Interrupt->DispatchCode, 
00248                               Interrupt->DispatchAddress, 
00249                               DISPATCH_LENGTH*4);
00250 
00251                 PCR->InterruptRoutine[Vector] =
00252                             (PKINTERRUPT_ROUTINE)(&Interrupt->DispatchCode);
00253 
00254                 
HalEnableSystemInterrupt(Vector, Irql, Interrupt->Mode);
00255 
00256             } 
else {
00257                 Interruptx = CONTAINING_RECORD(PCR->InterruptRoutine[Vector],
00258                                                
KINTERRUPT,
00259                                                DispatchCode[0]);
00260 
00261                 
if (Interrupt->Mode == Interruptx->
Mode) {
00262                     Connected = 
TRUE;
00263                     Interrupt->Connected = 
TRUE;
00264                     
ASSERT (Irql <= KiSynchIrql);
00265                     
if (Interruptx->
DispatchAddress != 
KiChainedDispatch) {
00266                         InitializeListHead(&Interruptx->
InterruptListEntry);
00267                         Interruptx->
DispatchAddress = 
KiChainedDispatch;
00268         
00269                         RtlMoveMemory(Interruptx->
DispatchCode, 
00270                                       Interruptx->
DispatchAddress,
00271                                       DISPATCH_LENGTH*4);
00272                     }
00273 
00274                     InsertTailList(&Interruptx->
InterruptListEntry,
00275                                    &Interrupt->InterruptListEntry);
00276                 }
00277             }
00278         }
00279 
00280         
00281         
00282         
00283 
00284         
KiUnlockDispatcherDatabase(OldIrql);
00285 
00286         
00287         
00288         
00289 
00290         
KeRevertToUserAffinityThread();
00291     }
00292 
00293     
00294     
00295     
00296 
00297     
return Connected;
00298 }
00299 
00300 BOOLEAN
00301 KeDisconnectInterrupt (
00302     IN 
PKINTERRUPT Interrupt
00303     )
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 {
00327 
00328     BOOLEAN Connected;
00329     
PKINTERRUPT Interruptx;
00330     
PKINTERRUPT Interrupty;
00331     KIRQL Irql;
00332     KIRQL OldIrql;
00333     ULONG Vector;
00334 
00335     
00336     
00337     
00338 
00339     
KeSetSystemAffinityThread((KAFFINITY)(1 << Interrupt->Number));
00340 
00341     
00342     
00343     
00344 
00345     
KiLockDispatcherDatabase(&OldIrql);
00346 
00347     
00348     
00349     
00350     
00351 
00352     Connected = Interrupt->Connected;
00353     
if (Connected != 
FALSE) {
00354         Irql = Interrupt->Irql;
00355         Vector = Interrupt->Vector;
00356 
00357         
00358         
00359         
00360         
00361         
00362         
00363         
00364         
00365 
00366         Interruptx = CONTAINING_RECORD(PCR->InterruptRoutine[Vector],
00367                                        
KINTERRUPT,
00368                                        DispatchCode[0]);
00369 
00370         
if (Interruptx->
DispatchAddress ==
00371                                 (PKINTERRUPT_ROUTINE)
KiChainedDispatch) {
00372             
ASSERT (Irql <= KiSynchIrql);
00373             
if (Interrupt == Interruptx) {
00374                 Interruptx = CONTAINING_RECORD(Interruptx->
InterruptListEntry.Flink,
00375                                                
KINTERRUPT, InterruptListEntry);
00376                 Interruptx->
DispatchAddress =
00377                                 (PKINTERRUPT_ROUTINE)
KiChainedDispatch;
00378 
00379                 RtlMoveMemory(Interruptx->
DispatchCode, 
00380                               Interruptx->
DispatchAddress,
00381                               DISPATCH_LENGTH*4);
00382 
00383                 PCR->InterruptRoutine[Vector] =
00384                                 (PKINTERRUPT_ROUTINE)(&Interruptx->
DispatchCode);
00385             }
00386 
00387             RemoveEntryList(&Interrupt->InterruptListEntry);
00388             Interrupty = CONTAINING_RECORD(Interruptx->
InterruptListEntry.Flink,
00389                                            
KINTERRUPT,
00390                                            InterruptListEntry);
00391 
00392             
if (Interruptx == Interrupty) {
00393                 
if (Interrupty->
FloatingSave != 
FALSE) {
00394                     Interrupty->
DispatchAddress = 
KiFloatingDispatch;
00395 
00396                 } 
else {
00397                     
if (Interrupty->
Irql == Interrupty->
SynchronizeIrql) {
00398                         Interrupty->
DispatchAddress =
00399                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchSame;
00400 
00401                     } 
else {
00402                         Interrupty->
DispatchAddress =
00403                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchRaise;
00404                     }
00405                 }
00406 
00407                 
00408                 
00409                 
00410                 
00411                 
00412 
00413                 RtlMoveMemory(Interrupty->
DispatchCode, 
00414                               Interrupty->
DispatchAddress,
00415                               DISPATCH_LENGTH*4);
00416 
00417                 PCR->InterruptRoutine[Vector] =
00418                                (PKINTERRUPT_ROUTINE)(&Interrupty->
DispatchCode);
00419                 }
00420 
00421         } 
else {
00422             
HalDisableSystemInterrupt(Vector, Irql);
00423             PCR->InterruptRoutine[Vector] =
00424                     (PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode);
00425         }
00426 
00427         Interrupt->Connected = 
FALSE;
00428     }
00429 
00430     
00431     
00432     
00433 
00434     
KiUnlockDispatcherDatabase(OldIrql);
00435 
00436     
00437     
00438     
00439 
00440     
KeRevertToUserAffinityThread();
00441     
00442     
00443     
00444     
00445 
00446     
return Connected;
00447 }