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