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     
00137 
00138     
for (
Index = 0; 
Index < DISPATCH_LENGTH; 
Index += 1) {
00139         Interrupt->DispatchCode[
Index] = KiInterruptTemplate[
Index];
00140     }
00141 
00142     
KeSweepIcache(
FALSE);
00143 
00144     
00145     
00146     
00147 
00148     Interrupt->Connected = 
FALSE;
00149     
return;
00150 }
00151 
00152 BOOLEAN
00153 KeConnectInterrupt (
00154     IN 
PKINTERRUPT Interrupt
00155     )
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 {
00181 
00182     BOOLEAN Connected;
00183     
PKINTERRUPT Interruptx;
00184     KIRQL Irql;
00185     
CHAR Number;
00186     KIRQL OldIrql;
00187     KIRQL PreviousIrql;
00188     ULONG Vector;
00189 
00190     
00191     
00192     
00193     
00194     
00195     
00196     
00197     
00198     
00199     
00200 
00201     Connected = 
FALSE;
00202     Irql = Interrupt->Irql;
00203     Number = Interrupt->Number;
00204     Vector = Interrupt->Vector;
00205     
if ((((Vector >= MAXIMUM_VECTOR) || (Irql > 
HIGH_LEVEL) ||
00206        ((Vector <= 
HIGH_LEVEL) &&
00207        ((((1 << Vector) & PCR->ReservedVectors) != 0) || (Vector != Irql))) ||
00208        (Number >= 
KeNumberProcessors))) == 
FALSE) {
00209 
00210         
00211         
00212         
00213 
00214         
KeSetSystemAffinityThread((KAFFINITY)(1 << Number));
00215 
00216         
00217         
00218         
00219 
00220         
KiLockDispatcherDatabase(&OldIrql);
00221 
00222         
00223         
00224         
00225         
00226         
00227         
00228         
00229         
00230         
00231         
00232         
00233 
00234         
if (Interrupt->Connected == 
FALSE) {
00235             
if (PCR->InterruptRoutine[Vector] ==
00236                 (PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode)) {
00237                 Connected = 
TRUE;
00238                 Interrupt->Connected = 
TRUE;
00239                 
if (Interrupt->FloatingSave != 
FALSE) {
00240                     Interrupt->DispatchAddress = 
KiFloatingDispatch;
00241 
00242                 } 
else {
00243                     
if (Interrupt->Irql == Interrupt->SynchronizeIrql) {
00244                         Interrupt->DispatchAddress =
00245                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchSame;
00246 
00247                     } 
else {
00248                         Interrupt->DispatchAddress =
00249                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchRaise;
00250                     }
00251                 }
00252 
00253                 PCR->InterruptRoutine[Vector] =
00254                             (PKINTERRUPT_ROUTINE)(&Interrupt->DispatchCode);
00255 
00256                 
HalEnableSystemInterrupt(Vector, Irql, Interrupt->Mode);
00257 
00258             } 
else {
00259                 Interruptx = CONTAINING_RECORD(PCR->InterruptRoutine[Vector],
00260                                                
KINTERRUPT,
00261                                                DispatchCode[0]);
00262 
00263                 
if (Interrupt->Mode == Interruptx->
Mode) {
00264                     Connected = 
TRUE;
00265                     Interrupt->Connected = 
TRUE;
00266                     
KeRaiseIrql(
max(Irql, (KIRQL)KiSynchIrql), &PreviousIrql);
00267                     
if (Interruptx->
DispatchAddress != 
KiChainedDispatch) {
00268                         InitializeListHead(&Interruptx->
InterruptListEntry);
00269                         Interruptx->
DispatchAddress = 
KiChainedDispatch;
00270                     }
00271 
00272                     InsertTailList(&Interruptx->
InterruptListEntry,
00273                                    &Interrupt->InterruptListEntry);
00274 
00275                     
KeLowerIrql(PreviousIrql);
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     KIRQL PreviousIrql;
00334     ULONG Vector;
00335 
00336     
00337     
00338     
00339 
00340     
KeSetSystemAffinityThread((KAFFINITY)(1 << Interrupt->Number));
00341 
00342     
00343     
00344     
00345 
00346     
KiLockDispatcherDatabase(&OldIrql);
00347 
00348     
00349     
00350     
00351     
00352 
00353     Connected = Interrupt->Connected;
00354     
if (Connected != 
FALSE) {
00355         Irql = Interrupt->Irql;
00356         Vector = Interrupt->Vector;
00357 
00358         
00359         
00360         
00361         
00362         
00363         
00364         
00365         
00366 
00367         Interruptx = CONTAINING_RECORD(PCR->InterruptRoutine[Vector],
00368                                        
KINTERRUPT,
00369                                        DispatchCode[0]);
00370 
00371         
if (Interruptx->
DispatchAddress == 
KiChainedDispatch) {
00372             
KeRaiseIrql(
max(Irql, (KIRQL)KiSynchIrql), &PreviousIrql);
00373             
if (Interrupt == Interruptx) {
00374                 Interruptx = CONTAINING_RECORD(Interruptx->
InterruptListEntry.Flink,
00375                                                
KINTERRUPT, InterruptListEntry);
00376                 Interruptx->
DispatchAddress = 
KiChainedDispatch;
00377                 PCR->InterruptRoutine[Vector] =
00378                                 (PKINTERRUPT_ROUTINE)(&Interruptx->
DispatchCode);
00379             }
00380 
00381             RemoveEntryList(&Interrupt->InterruptListEntry);
00382             Interrupty = CONTAINING_RECORD(Interruptx->
InterruptListEntry.Flink,
00383                                            
KINTERRUPT,
00384                                            InterruptListEntry);
00385 
00386             
if (Interruptx == Interrupty) {
00387                 
if (Interrupty->
FloatingSave != 
FALSE) {
00388                     Interrupty->
DispatchAddress = 
KiFloatingDispatch;
00389 
00390                 } 
else {
00391                     
if (Interrupty->
Irql == Interrupty->
SynchronizeIrql) {
00392                         Interrupty->
DispatchAddress =
00393                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchSame;
00394 
00395                     } 
else {
00396                         Interrupty->
DispatchAddress =
00397                                     (PKINTERRUPT_ROUTINE)
KiInterruptDispatchRaise;
00398                     }
00399                 }
00400 
00401                 PCR->InterruptRoutine[Vector] =
00402                                (PKINTERRUPT_ROUTINE)(&Interrupty->
DispatchCode);
00403                 }
00404 
00405             
KeLowerIrql(PreviousIrql);
00406 
00407         } 
else {
00408             
HalDisableSystemInterrupt(Vector, Irql);
00409             PCR->InterruptRoutine[Vector] =
00410                     (PKINTERRUPT_ROUTINE)(&KxUnexpectedInterrupt.DispatchCode);
00411         }
00412 
00413         
KeSweepIcache(
TRUE);
00414         Interrupt->Connected = 
FALSE;
00415     }
00416 
00417     
00418     
00419     
00420 
00421     
KiUnlockDispatcherDatabase(OldIrql);
00422 
00423     
00424     
00425     
00426 
00427     
KeRevertToUserAffinityThread();
00428 
00429     
00430     
00431     
00432 
00433     
return Connected;
00434 }