Add the beginnings of context switch and decrementer exception handler.
[reactos.git] / reactos / ntoskrnl / ke / powerpc / ppc_irq.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/i386/irq.c
6 * PURPOSE: IRQ handling
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /*
12 * NOTE: In general the PIC interrupt priority facilities are used to
13 * preserve the NT IRQL semantics, global interrupt disables are only used
14 * to keep the PIC in a consistent state
15 *
16 */
17
18 /* INCLUDES ****************************************************************/
19
20 #include <ntoskrnl.h>
21 #include <ppcmmu/mmu.h>
22
23 #define NDEBUG
24 #include <internal/debug.h>
25
26 KDPC KiExpireTimerDpc;
27 extern ULONG KiMaximumDpcQueueDepth;
28 extern ULONG KiMinimumDpcRate;
29 extern ULONG KiAdjustDpcThreshold;
30 extern ULONG KiIdealDpcRate;
31 extern LONG KiTickOffset;
32 extern ULONG KeMaximumIncrement;
33 extern ULONG KeMinimumIncrement;
34 extern ULONG KeTimeAdjustment;
35
36 /* GLOBALS *****************************************************************/
37
38 /* Interrupt handler list */
39
40 #define NR_TRAPS 16
41 #ifdef CONFIG_SMP
42
43 #define INT_NAME2(intnum) KiUnexpectedInterrupt##intnum
44
45 #define BUILD_INTERRUPT_HANDLER(intnum) \
46 VOID INT_NAME2(intnum)(VOID);
47
48 #define D(x,y) \
49 BUILD_INTERRUPT_HANDLER(x##y)
50
51 #define D16(x) \
52 D(x,0) D(x,1) D(x,2) D(x,3) \
53 D(x,4) D(x,5) D(x,6) D(x,7) \
54 D(x,8) D(x,9) D(x,A) D(x,B) \
55 D(x,C) D(x,D) D(x,E) D(x,F)
56
57 D16(3) D16(4) D16(5) D16(6)
58 D16(7) D16(8) D16(9) D16(A)
59 D16(B) D16(C) D16(D) D16(E)
60 D16(F)
61
62 #define L(x,y) \
63 (ULONG)& INT_NAME2(x##y)
64
65 #define L16(x) \
66 L(x,0), L(x,1), L(x,2), L(x,3), \
67 L(x,4), L(x,5), L(x,6), L(x,7), \
68 L(x,8), L(x,9), L(x,A), L(x,B), \
69 L(x,C), L(x,D), L(x,E), L(x,F)
70
71 static ULONG irq_handler[ROUND_UP(NR_TRAPS, 16)] = {
72 L16(3), L16(4), L16(5), L16(6),
73 L16(7), L16(8), L16(9), L16(A),
74 L16(B), L16(C), L16(D), L16(E)
75 };
76
77 #undef L
78 #undef L16
79 #undef D
80 #undef D16
81
82 #else /* CONFIG_SMP */
83
84 void trap_handler_0(void);
85 void trap_handler_1(void);
86 void trap_handler_2(void);
87 void trap_handler_3(void);
88 void trap_handler_4(void);
89 void trap_handler_5(void);
90 void trap_handler_6(void);
91 void trap_handler_7(void);
92 void trap_handler_8(void);
93 void trap_handler_9(void);
94 void trap_handler_10(void);
95 void trap_handler_11(void);
96 void trap_handler_12(void);
97 void trap_handler_13(void);
98 void trap_handler_14(void);
99 void trap_handler_15(void);
100
101 static unsigned int trap_handler[NR_TRAPS] __attribute__((unused)) =
102 {
103 (int)&trap_handler_0,
104 (int)&trap_handler_1,
105 (int)&trap_handler_2,
106 (int)&trap_handler_3,
107 (int)&trap_handler_4,
108 (int)&trap_handler_5,
109 (int)&trap_handler_6,
110 (int)&trap_handler_7,
111 (int)&trap_handler_8,
112 (int)&trap_handler_9,
113 (int)&trap_handler_10,
114 (int)&trap_handler_11,
115 (int)&trap_handler_12,
116 (int)&trap_handler_13,
117 (int)&trap_handler_14,
118 (int)&trap_handler_15,
119 };
120
121 #endif /* CONFIG_SMP */
122
123 /*
124 * PURPOSE: Object describing each isr
125 * NOTE: The data in this table is only modified at passsive level but can
126 * be accessed at any irq level.
127 */
128
129 typedef struct
130 {
131 LIST_ENTRY ListHead;
132 KSPIN_LOCK Lock;
133 ULONG Count;
134 }
135 ISR_TABLE, *PISR_TABLE;
136
137 #ifdef CONFIG_SMP
138 static ISR_TABLE IsrTable[NR_TRAPS][MAXIMUM_PROCESSORS];
139 #else
140 static ISR_TABLE IsrTable[NR_TRAPS][1];
141 #endif
142
143 #define TAG_ISR_LOCK TAG('I', 'S', 'R', 'L')
144
145 /* FUNCTIONS ****************************************************************/
146
147 VOID
148 INIT_FUNCTION
149 NTAPI
150 KeInitInterrupts (VOID)
151 {
152 int i, j;
153
154 /*
155 * Setup the IDT entries to point to the interrupt handlers
156 */
157 for (i=0;i<NR_TRAPS;i++)
158 {
159 #ifdef CONFIG_SMP
160 for (j = 0; j < MAXIMUM_PROCESSORS; j++)
161 #else
162 j = 0;
163 #endif
164 {
165 InitializeListHead(&IsrTable[i][j].ListHead);
166 KeInitializeSpinLock(&IsrTable[i][j].Lock);
167 IsrTable[i][j].Count = 0;
168 }
169 }
170 }
171
172 static VOID
173 KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
174 PKTRAP_FRAME TrapFrame)
175 {
176 }
177
178 static VOID
179 KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
180 PKIRQ_TRAPFRAME IrqTrapFrame)
181 {
182 }
183
184 /*
185 * NOTE: On Windows this function takes exactly one parameter and EBP is
186 * guaranteed to point to KTRAP_FRAME. The function is used only
187 * by HAL, so there's no point in keeping that prototype.
188 *
189 * @implemented
190 */
191 VOID
192 STDCALL
193 KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
194 IN KIRQL Irql)
195 {
196 PKPRCB Prcb = KeGetCurrentPrcb();
197 PKTHREAD CurrentThread;
198 PKPROCESS CurrentProcess;
199
200 /* Make sure we don't go further if we're in early boot phase. */
201 if (!(Prcb) || !(Prcb->CurrentThread)) return;
202
203 /* Get the current thread and process */
204 CurrentThread = Prcb->CurrentThread;
205 CurrentProcess = CurrentThread->ApcState.Process;
206
207 /* Check if we came from user mode */
208 if (TrapFrame->PreviousMode != KernelMode)
209 {
210 /* Update user times */
211 CurrentThread->UserTime++;
212 InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
213 Prcb->UserTime++;
214 }
215 else
216 {
217 /* Check IRQ */
218 if (Irql > DISPATCH_LEVEL)
219 {
220 /* This was an interrupt */
221 Prcb->InterruptTime++;
222 }
223 else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
224 {
225 /* This was normal kernel time */
226 CurrentThread->KernelTime++;
227 InterlockedIncrement((PLONG)&CurrentProcess->KernelTime);
228 }
229 else if (Irql == DISPATCH_LEVEL)
230 {
231 /* This was DPC time */
232 Prcb->DpcTime++;
233 }
234
235 /* Update CPU kernel time in all cases */
236 Prcb->KernelTime++;
237 }
238
239 /* Set the last DPC Count and request rate */
240 Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
241 Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
242 Prcb->DpcRequestRate) / 2;
243
244 /* Check if we should request a DPC */
245 if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
246 {
247 /* Request one */
248 HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
249
250 /* Update the depth if needed */
251 if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
252 (Prcb->MaximumDpcQueueDepth > 1))
253 {
254 /* Decrease the maximum depth by one */
255 Prcb->MaximumDpcQueueDepth--;
256 }
257 }
258 else
259 {
260 /* Decrease the adjustment threshold */
261 if (!(--Prcb->AdjustDpcThreshold))
262 {
263 /* We've hit 0, reset it */
264 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
265
266 /* Check if we've hit queue maximum */
267 if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
268 {
269 /* Increase maximum by one */
270 Prcb->MaximumDpcQueueDepth++;
271 }
272 }
273 }
274
275 /*
276 * If we're at end of quantum request software interrupt. The rest
277 * is handled in KiDispatchInterrupt.
278 *
279 * NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine
280 * which checks for quantum end will not be executed and decrementing
281 * the quantum here can result in overflow. This is not a problem since
282 * we don't care about the quantum value anymore after the QuantumEnd
283 * flag is set.
284 */
285 if ((CurrentThread->Quantum -= 3) <= 0)
286 {
287 Prcb->QuantumEnd = TRUE;
288 HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
289 }
290 }
291
292
293 /*
294 * NOTE: On Windows this function takes exactly zero parameters and EBP is
295 * guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL.
296 * The function is used only by HAL, so there's no point in keeping
297 * that prototype.
298 *
299 * @implemented
300 */
301 VOID
302 STDCALL
303 KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
304 IN KIRQL Irql,
305 IN ULONG Increment)
306 {
307 LONG OldOffset;
308 LARGE_INTEGER Time;
309 ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);
310
311 /* Update interrupt time */
312 Time.LowPart = SharedUserData->InterruptTime.LowPart;
313 Time.HighPart = SharedUserData->InterruptTime.High1Time;
314 Time.QuadPart += Increment;
315 SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
316 SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
317 SharedUserData->InterruptTime.High1Time = Time.u.HighPart;
318
319 /* Increase the tick offset */
320 KiTickOffset -= Increment;
321 OldOffset = KiTickOffset;
322
323 /* Check if this isn't a tick yet */
324 if (KiTickOffset > 0)
325 {
326 /* Expire timers */
327 KeInsertQueueDpc(&KiExpireTimerDpc, 0, 0);
328 }
329 else
330 {
331 /* Setup time structure for system time */
332 Time.LowPart = SharedUserData->SystemTime.LowPart;
333 Time.HighPart = SharedUserData->SystemTime.High1Time;
334 Time.QuadPart += KeTimeAdjustment;
335 SharedUserData->SystemTime.High2Time = Time.HighPart;
336 SharedUserData->SystemTime.LowPart = Time.LowPart;
337 SharedUserData->SystemTime.High1Time = Time.HighPart;
338
339 /* Setup time structure for tick time */
340 Time.LowPart = KeTickCount.LowPart;
341 Time.HighPart = KeTickCount.High1Time;
342 Time.QuadPart += 1;
343 KeTickCount.High2Time = Time.HighPart;
344 KeTickCount.LowPart = Time.LowPart;
345 KeTickCount.High1Time = Time.HighPart;
346 SharedUserData->TickCount.High2Time = Time.HighPart;
347 SharedUserData->TickCount.LowPart = Time.LowPart;
348 SharedUserData->TickCount.High1Time = Time.HighPart;
349
350 /* Update tick count in shared user data as well */
351 SharedUserData->TickCountLowDeprecated++;
352
353 /* Queue a DPC that will expire timers */
354 KeInsertQueueDpc(&KiExpireTimerDpc, 0, 0);
355 }
356
357 /* Update process and thread times */
358 if (OldOffset <= 0)
359 {
360 /* This was a tick, calculate the next one */
361 KiTickOffset += KeMaximumIncrement;
362 KeUpdateRunTime(TrapFrame, Irql);
363 }
364 }
365
366 VOID STDCALL
367 KiInterruptDispatch2 (ULONG vector, KIRQL old_level)
368 /*
369 * FUNCTION: Calls all the interrupt handlers for a given irq.
370 * ARGUMENTS:
371 * vector - The number of the vector to call handlers for.
372 * old_level - The irql of the processor when the irq took place.
373 * NOTES: Must be called at DIRQL.
374 */
375 {
376 PKINTERRUPT isr;
377 PLIST_ENTRY current;
378 KIRQL oldlvl;
379 PISR_TABLE CurrentIsr;
380
381 DPRINT("I(0x%.08x, 0x%.08x)\n", vector, old_level);
382
383 /*
384 * Iterate the list until one of the isr tells us its device interrupted
385 */
386 CurrentIsr = &IsrTable[vector][(ULONG)KeGetCurrentProcessorNumber()];
387
388 KiAcquireSpinLock(&CurrentIsr->Lock);
389
390 CurrentIsr->Count++;
391 current = CurrentIsr->ListHead.Flink;
392
393 while (current != &CurrentIsr->ListHead)
394 {
395 isr = CONTAINING_RECORD(current,KINTERRUPT,InterruptListEntry);
396 oldlvl = KeAcquireInterruptSpinLock(isr);
397 if (isr->ServiceRoutine(isr, isr->ServiceContext))
398 {
399 KeReleaseInterruptSpinLock(isr, oldlvl);
400 break;
401 }
402 KeReleaseInterruptSpinLock(isr, oldlvl);
403 current = current->Flink;
404 }
405 KiReleaseSpinLock(&CurrentIsr->Lock);
406 }
407
408 VOID
409 KiInterruptDispatch3 (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
410 /*
411 * FUNCTION: Calls the irq specific handler for an irq
412 * ARGUMENTS:
413 * irq = IRQ that has interrupted
414 */
415 {
416 KIRQL old_level;
417 KTRAP_FRAME KernelTrapFrame;
418 PKTHREAD CurrentThread;
419 PKTRAP_FRAME OldTrapFrame=NULL;
420
421 /*
422 * At this point we have interrupts disabled, nothing has been done to
423 * the PIC.
424 */
425
426 KeGetCurrentPrcb()->InterruptCount++;
427
428 /*
429 * Notify the rest of the kernel of the raised irq level. For the
430 * default HAL this will send an EOI to the PIC and alter the IRQL.
431 */
432 if (!HalBeginSystemInterrupt (vector,
433 vector,
434 &old_level))
435 {
436 return;
437 }
438
439
440 /*
441 * Enable interrupts
442 * NOTE: Only higher priority interrupts will get through
443 */
444 _enable();
445
446 #ifndef CONFIG_SMP
447 if (vector == 0)
448 {
449 KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
450 KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
451 }
452 else
453 #endif
454 {
455 /*
456 * Actually call the ISR.
457 */
458 KiInterruptDispatch2(vector, old_level);
459 }
460
461 /*
462 * End the system interrupt.
463 */
464 _disable();
465
466 if (old_level==PASSIVE_LEVEL)
467 {
468 HalEndSystemInterrupt (APC_LEVEL, 0);
469
470 CurrentThread = KeGetCurrentThread();
471 if (CurrentThread!=NULL && CurrentThread->ApcState.UserApcPending)
472 {
473 DPRINT("PID: %d, TID: %d CS %04x/%04x\n",
474 ((PETHREAD)CurrentThread)->ThreadsProcess->UniqueProcessId,
475 ((PETHREAD)CurrentThread)->Cid.UniqueThread,
476 Trapframe->Cs,
477 CurrentThread->TrapFrame ? CurrentThread->TrapFrame->Cs : 0);
478 if (CurrentThread->TrapFrame == NULL)
479 {
480 OldTrapFrame = CurrentThread->TrapFrame;
481 KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
482 CurrentThread->TrapFrame = &KernelTrapFrame;
483 }
484
485 _enable();
486 KiDeliverApc(UserMode, NULL, NULL);
487 _disable();
488
489 ASSERT(KeGetCurrentThread() == CurrentThread);
490 if (CurrentThread->TrapFrame == &KernelTrapFrame)
491 {
492 KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
493 CurrentThread->TrapFrame = OldTrapFrame;
494 }
495 }
496 KeLowerIrql(PASSIVE_LEVEL);
497 }
498 else
499 {
500 HalEndSystemInterrupt (old_level, 0);
501 }
502
503 }
504
505 static VOID
506 KeDumpIrqList(VOID)
507 {
508 PKINTERRUPT current;
509 PLIST_ENTRY current_entry;
510 LONG i, j;
511 KIRQL oldlvl;
512 BOOLEAN printed;
513
514 for (i=0;i<NR_TRAPS;i++)
515 {
516 printed = FALSE;
517 KeRaiseIrql(i,&oldlvl);
518
519 for (j=0; j < KeNumberProcessors; j++)
520 {
521 KiAcquireSpinLock(&IsrTable[i][j].Lock);
522
523 current_entry = IsrTable[i][j].ListHead.Flink;
524 current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
525 while (current_entry!=&(IsrTable[i][j].ListHead))
526 {
527 if (printed == FALSE)
528 {
529 printed = TRUE;
530 DPRINT("For irq %x:\n",i);
531 }
532 DPRINT(" Isr %x\n",current);
533 current_entry = current_entry->Flink;
534 current = CONTAINING_RECORD(current_entry,KINTERRUPT,InterruptListEntry);
535 }
536 KiReleaseSpinLock(&IsrTable[i][j].Lock);
537 }
538 KeLowerIrql(oldlvl);
539 }
540 }
541
542 /*
543 * @implemented
544 */
545 BOOLEAN
546 STDCALL
547 KeConnectInterrupt(PKINTERRUPT InterruptObject)
548 {
549 KIRQL oldlvl,synch_oldlvl;
550 PKINTERRUPT ListHead;
551 ULONG Vector;
552 PISR_TABLE CurrentIsr;
553 BOOLEAN Result;
554
555 DPRINT("KeConnectInterrupt()\n");
556
557 Vector = InterruptObject->Vector;
558
559 if (Vector < 0 || Vector >= NR_TRAPS)
560 return FALSE;
561
562 ASSERT (InterruptObject->Number < KeNumberProcessors);
563
564 KeSetSystemAffinityThread(1 << InterruptObject->Number);
565
566 CurrentIsr = &IsrTable[Vector][(ULONG)InterruptObject->Number];
567
568 KeRaiseIrql(Vector,&oldlvl);
569 KiAcquireSpinLock(&CurrentIsr->Lock);
570
571 /*
572 * Check if the vector is already in use that we can share it
573 */
574 if (!IsListEmpty(&CurrentIsr->ListHead))
575 {
576 ListHead = CONTAINING_RECORD(CurrentIsr->ListHead.Flink,KINTERRUPT,InterruptListEntry);
577 if (InterruptObject->ShareVector == FALSE || ListHead->ShareVector==FALSE)
578 {
579 KiReleaseSpinLock(&CurrentIsr->Lock);
580 KeLowerIrql(oldlvl);
581 KeRevertToUserAffinityThread();
582 return FALSE;
583 }
584 }
585
586 synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
587
588 DPRINT("%x %x\n",CurrentIsr->ListHead.Flink, CurrentIsr->ListHead.Blink);
589
590 Result = HalEnableSystemInterrupt(Vector, InterruptObject->Irql, InterruptObject->Mode);
591 if (Result)
592 {
593 InsertTailList(&CurrentIsr->ListHead,&InterruptObject->InterruptListEntry);
594 DPRINT("%x %x\n",InterruptObject->InterruptListEntry.Flink, InterruptObject->InterruptListEntry.Blink);
595 }
596
597 InterruptObject->Connected = TRUE;
598 KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
599
600 /*
601 * Release the table spinlock
602 */
603 KiReleaseSpinLock(&CurrentIsr->Lock);
604 KeLowerIrql(oldlvl);
605
606 KeDumpIrqList();
607
608 KeRevertToUserAffinityThread();
609
610 return Result;
611 }
612
613 /*
614 * @implemented
615 *
616 * FUNCTION: Releases a drivers isr
617 * ARGUMENTS:
618 * InterruptObject = isr to release
619 */
620 BOOLEAN
621 STDCALL
622 KeDisconnectInterrupt(PKINTERRUPT InterruptObject)
623 {
624 KIRQL oldlvl,synch_oldlvl;
625 PISR_TABLE CurrentIsr;
626 BOOLEAN State;
627
628 DPRINT1("KeDisconnectInterrupt\n");
629 ASSERT (InterruptObject->Number < KeNumberProcessors);
630
631 /* Set the affinity */
632 KeSetSystemAffinityThread(1 << InterruptObject->Number);
633
634 /* Get the ISR Tabe */
635 CurrentIsr = &IsrTable[InterruptObject->Vector]
636 [(ULONG)InterruptObject->Number];
637
638 /* Raise IRQL to required level and lock table */
639 KeRaiseIrql(InterruptObject->Vector,&oldlvl);
640 KiAcquireSpinLock(&CurrentIsr->Lock);
641
642 /* Check if it's actually connected */
643 if ((State = InterruptObject->Connected))
644 {
645 /* Lock the Interrupt */
646 synch_oldlvl = KeAcquireInterruptSpinLock(InterruptObject);
647
648 /* Remove this one, and check if all are gone */
649 RemoveEntryList(&InterruptObject->InterruptListEntry);
650 if (IsListEmpty(&CurrentIsr->ListHead))
651 {
652 /* Completely Disable the Interrupt */
653 HalDisableSystemInterrupt(InterruptObject->Vector, InterruptObject->Irql);
654 }
655
656 /* Disconnect it */
657 InterruptObject->Connected = FALSE;
658
659 /* Release the interrupt lock */
660 KeReleaseInterruptSpinLock(InterruptObject, synch_oldlvl);
661 }
662 /* Release the table spinlock */
663 KiReleaseSpinLock(&CurrentIsr->Lock);
664 KeLowerIrql(oldlvl);
665
666 /* Go back to default affinity */
667 KeRevertToUserAffinityThread();
668
669 /* Return Old Interrupt State */
670 return State;
671 }
672
673 /*
674 * @implemented
675 */
676 VOID
677 STDCALL
678 KeInitializeInterrupt(PKINTERRUPT Interrupt,
679 PKSERVICE_ROUTINE ServiceRoutine,
680 PVOID ServiceContext,
681 PKSPIN_LOCK SpinLock,
682 ULONG Vector,
683 KIRQL Irql,
684 KIRQL SynchronizeIrql,
685 KINTERRUPT_MODE InterruptMode,
686 BOOLEAN ShareVector,
687 CHAR ProcessorNumber,
688 BOOLEAN FloatingSave)
689 {
690 /* Set the Interrupt Header */
691 Interrupt->Type = InterruptObject;
692 Interrupt->Size = sizeof(KINTERRUPT);
693
694 /* Check if we got a spinlock */
695 if (SpinLock)
696 {
697 Interrupt->ActualLock = SpinLock;
698 }
699 else
700 {
701 /* This means we'll be usin the built-in one */
702 KeInitializeSpinLock(&Interrupt->SpinLock);
703 Interrupt->ActualLock = &Interrupt->SpinLock;
704 }
705
706 /* Set the other settings */
707 Interrupt->ServiceRoutine = ServiceRoutine;
708 Interrupt->ServiceContext = ServiceContext;
709 Interrupt->Vector = Vector;
710 Interrupt->Irql = Irql;
711 Interrupt->SynchronizeIrql = SynchronizeIrql;
712 Interrupt->Mode = InterruptMode;
713 Interrupt->ShareVector = ShareVector;
714 Interrupt->Number = ProcessorNumber;
715 Interrupt->FloatingSave = FloatingSave;
716
717 /* Disconnect it at first */
718 Interrupt->Connected = FALSE;
719 }
720
721 VOID KePrintInterruptStatistic(VOID)
722 {
723 LONG i, j;
724
725 for (j = 0; j < KeNumberProcessors; j++)
726 {
727 DPRINT1("CPU%d:\n", j);
728 for (i = 0; i < NR_TRAPS; i++)
729 {
730 if (IsrTable[i][j].Count)
731 {
732 DPRINT1(" Irq %x(%d): %d\n", i, i, IsrTable[i][j].Count);
733 }
734 }
735 }
736 }
737
738 BOOLEAN
739 NTAPI
740 KeDisableInterrupts(VOID)
741 {
742 ULONG Flags = 0;
743 BOOLEAN Return;
744
745 Flags = __readmsr();
746 Return = (Flags & 0x8000) ? TRUE: FALSE;
747
748 /* Disable interrupts */
749 _disable();
750 return Return;
751 }
752
753 ULONG
754 NTAPI
755 KdpServiceDispatcher(ULONG Service, PCHAR Buffer, ULONG Length);
756
757 VOID
758 NTAPI
759 KiSystemService(ppc_trap_frame_t *trap_frame)
760 {
761 int i;
762 PKSYSTEM_ROUTINE SystemRoutine;
763
764 switch(trap_frame->gpr[8])
765 {
766 case 0x10000: /* DebugService */
767 for( i = 0; i < trap_frame->gpr[5]; i++ )
768 SetPhysByte(0x800003f8, ((PCHAR)trap_frame->gpr[4])[i]);
769
770 trap_frame->gpr[3] = KdpServiceDispatcher
771 (trap_frame->gpr[3],
772 (PCHAR)trap_frame->gpr[4],
773 trap_frame->gpr[5]);
774 break;
775 case 0xf0000: /* Thread startup */
776 /* XXX how to use UserThread (gpr[6]) */
777 SystemRoutine = (PKSYSTEM_ROUTINE)trap_frame->gpr[3];
778 SystemRoutine((PKSTART_ROUTINE)trap_frame->gpr[4],
779 (PVOID)trap_frame->gpr[5]);
780 break;
781 }
782 }
783
784 /* EOF */