/[pcsx2_0.9.7]/trunk/fps2bios/kernel/iopload/intrman/intrman.c
ViewVC logotype

Contents of /trunk/fps2bios/kernel/iopload/intrman/intrman.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 5 months ago) by william
File MIME type: text/plain
File size: 16841 byte(s)
exported r3113 from ./upstream/trunk
1
2 #define _GNU_SOURCE
3
4 #include "kloadcore.h"
5 #include "kexcepman.h"
6 #include "kintrman.h"
7 #include "err.h"
8
9 #define ICFG (*(volatile int*)0xbf801450)
10 #define IREG (*(volatile int*)0xbf801070)
11 #define IMASK (*(volatile int*)0xbf801074)
12 #define ICTRL (*(volatile int*)0xbf801078)
13 #define DMA_ICR (*(volatile int*)0xbf8010F4)
14 #define DMA_ICR2 (*(volatile int*)0xbf801574)
15
16 #define EXCEP_CAUSE (*(volatile int*)0x40C)
17
18 int debug=1;
19
20 #define _dprintf(fmt, args...) \
21 if (debug > 0) __printf("intrman: " fmt, ## args)
22
23 struct intrHandler {
24 u32 handler;
25 void *arg;
26 };
27
28 func context_switch_required_handler;
29 func context_switch_handler;
30
31 // Additional interrupt mask applied after IMASK
32 u32 soft_hw_intr_mask;
33
34 int unknown2[4]; //0x1280 up
35
36 #define INTR_STACK_SIZE 0x800
37 unsigned char tempstack[INTR_STACK_SIZE];
38
39 u32 *extable;
40 struct intrHandler *intrtable;
41
42 extern struct export export_stub;
43
44 int _start();
45 int IntrHandler();
46 void intrman_retonly();
47
48 /////////////////////////////syscalls//////////////////////////////////
49 __inline void syscall_0();
50 void syscall_1_CpuDisableIntr();
51 void syscall_2_CpuEnableIntr();
52 void syscall_3_intrman_call14();
53 void syscall_4_intrman_call17_19();
54 void syscall_5_intrman_call18_20();
55 void goto_EXCEP_Sys_handler();
56 void syscall_8_threadman();
57
58 func syscall[] = {
59 (func)syscall_0,
60 /* (func)syscall_1_CpuDisableIntr,
61 (func)syscall_2_CpuEnableIntr,
62 (func)syscall_3_intrman_call14,
63 (func)syscall_4_intrman_call17_19,
64 (func)syscall_5_intrman_call18_20,
65 (func)goto_EXCEP_Sys_handler,
66 (func)goto_EXCEP_Sys_handler,
67 (func)syscall_8_threadman,
68 (func)goto_EXCEP_Sys_handler,
69 (func)goto_EXCEP_Sys_handler,
70 (func)goto_EXCEP_Sys_handler,
71 (func)goto_EXCEP_Sys_handler,
72 (func)goto_EXCEP_Sys_handler,
73 (func)goto_EXCEP_Sys_handler,
74 (func)goto_EXCEP_Sys_handler*/
75 };
76
77 ///////////////////////////////////////////////////////////////////////
78 int intrmanDeinit() {
79 return 0;
80 }
81
82 ///////////////////////////////////////////////////////////////////////
83 int intrman_call2()
84 {
85 IMASK = 0x00;
86 DMA_ICR = 0x00;
87 DMA_ICR2 = 0x00;
88 return 0;
89 }
90
91 ///////////////////////////////////////////////////////////////////////
92 int intrman_call3(){
93 return (int)&unknown2;
94 }
95
96 ///////////////////////////////////////////////////////////////////////
97 //
98 // interrupt values 0x2E - 0x3F are equivalent to 0x1E - 0x2F with a mode set
99 // interrupt values 0x20 - 0x2D have their mode forced to zero
100 //
101 // mode specifies what registers to save around the call
102 // 0 = don't save anything, handler will not change anything
103 // 1 = save t0 - t9, gp and fp
104 // 2 = save t0 - t9, gp, fp and s0 - s7
105 //
106 // arg is the value passed to the interrupt handler when it is called
107 //
108 int RegisterIntrHandler(int interrupt, int mode, intrh_func handler, void *arg)
109 {
110 u32 ictrl;
111
112 _dprintf("%s interrupt=%x, mode=%x\n", __FUNCTION__, interrupt, mode);
113 if (QueryIntrContext()){
114 // cannot be called from within an interrupt
115 _dprintf("%s ERROR_INTR_CONTEXT\n", __FUNCTION__);
116 return ERROR_INTR_CONTEXT;
117 }
118 CpuSuspendIntr(&ictrl);
119
120 if (interrupt < 0 || interrupt > 0x3F) {
121 CpuResumeIntr(ictrl);
122 _dprintf("%s ERROR_ILLEGAL_INTRCODE\n", __FUNCTION__);
123 return ERROR_ILLEGAL_INTRCODE;
124 }
125 int real_interrupt = interrupt;
126 int real_mode = mode;
127
128 if (interrupt >= 0x2E){
129 real_interrupt -= 0x10;
130 } else if (interrupt >= 0x20){
131 real_mode = 0;
132 }
133
134 if (intrtable[real_interrupt].handler){
135 CpuResumeIntr(ictrl);
136 _dprintf("%s ERROR_DOES_EXIST\n", __FUNCTION__);
137 return ERROR_DOES_EXIST;
138 }
139 intrtable[real_interrupt].handler = (mode & 0x03) | (u32)handler;
140 intrtable[real_interrupt].arg = arg;
141 CpuResumeIntr(ictrl);
142 return 0;
143 }
144
145 ///////////////////////////////////////////////////////////////////////
146 int ReleaseIntrHandler(int interrupt)
147 {
148 u32 ictrl;
149
150 if (QueryIntrContext()){
151 // Cannot be called from within an interrupt
152 return ERROR_INTR_CONTEXT;
153 }
154 CpuSuspendIntr(&ictrl);
155
156 if (interrupt < 0 || interrupt >= 0x40) {
157 CpuResumeIntr(ictrl);
158 return ERROR_ILLEGAL_INTRCODE;
159 }
160 if (interrupt >= 0x2E){
161 interrupt -= 0x10;
162 }
163
164 if (intrtable[interrupt].handler){
165 intrtable[interrupt].handler = 0;
166 CpuResumeIntr(ictrl);
167 return 0;
168 }
169 CpuResumeIntr(ictrl);
170 return ERROR_DOES_EXIST;
171 }
172
173 ///////////////////////////////////////////////////////////////////////
174 int CpuSuspendIntr(u32 *ictrl)
175 {
176 u32 rval = ICTRL;
177 if (ictrl) *ictrl = rval;
178 if (rval == 0) return ERROR_CPUDI;
179 return 0;
180 }
181
182 ///////////////////////////////////////////////////////////////////////
183 int CpuResumeIntr(u32 ictrl)
184 {
185 ICTRL = ictrl;
186 return 0;
187 }
188
189 ///////////////////////////////////////////////////////////////////////
190 int CpuDisableIntr()
191 {
192 if (ICTRL) return 0;
193 return ERROR_CPUDI;
194 }
195
196 ///////////////////////////////////////////////////////////////////////
197 int CpuEnableIntr()
198 {
199 //_dprintf("%s\n", __FUNCTION__);
200 // intrman_syscall_08();
201 // _dprintf("syscall ok\n");
202 CpuEnableICTRL();
203 return 0;
204 }
205
206 ///////////////////////////////////////////////////////////////////////
207 int CpuGetICTRL()
208 {
209 return ICTRL;
210 }
211
212 ///////////////////////////////////////////////////////////////////////
213 int CpuEnableICTRL()
214 {
215 ICTRL = 1;
216 return 1;
217 }
218
219 ///////////////////////////////////////////////////////////////////////
220 void intrman_syscall_04()
221 {
222 __asm__ (
223 "li $3, 4\n"
224 "syscall\n"
225 );
226 }
227
228 ///////////////////////////////////////////////////////////////////////
229 void intrman_syscall_08()
230 {
231 __asm__ (
232 "li $3, 8\n"
233 "syscall\n"
234 );
235 }
236
237 ///////////////////////////////////////////////////////////////////////
238 void intrman_syscall_10()
239 {
240 __asm__ (
241 "li $3, 16\n"
242 "syscall\n"
243 );
244 }
245
246 ///////////////////////////////////////////////////////////////////////
247 void intrman_syscall_14()
248 {
249 __asm__ (
250 "li $3, 20\n"
251 "syscall\n"
252 );
253 }
254
255 ///////////////////////////////////////////////////////////////////////
256 void intrman_syscall_0C()
257 {
258 __asm__ (
259 "li $3, 12\n"
260 "syscall\n"
261 );
262 }
263
264 ///////////////////////////////////////////////////////////////////////
265 //
266 // Interrupt:
267 // 0 - 0x1F normal interrupt
268 // 0x20 - 0x26
269 // 0x27 - 0x2D
270 //
271 // Return 0 for success, -101 for invalid interrupt number
272 //
273 #define ERROR_BAD_NUMBER -101
274 #define INUM_DMA_0 0x20
275 #define INUM_DMA_BERR 0x27
276 #define INUM_DMA_7 0x28
277 #define IMODE_DMA_IRM 0x100
278 #define IMODE_DMA_IQE 0x200
279 #define INUM_DMA 3
280
281 int EnableIntr(int interrupt)
282 {
283 int retval = 0;
284 u32 low_irq = interrupt & 0xFF;
285 u32 high_irq = interrupt & 0xFFFFFF00;
286
287 u32 ictrl;
288 CpuSuspendIntr(&ictrl);
289
290 if( interrupt < 0 ) {
291 retval = ERROR_BAD_NUMBER;
292 }
293 else if (low_irq < INUM_DMA_0){
294 IMASK |= (1 << low_irq);
295 } else if (low_irq < INUM_DMA_BERR){
296 DMA_ICR = (DMA_ICR & ((~(1<<(low_irq-INUM_DMA_0)))&0x00FFFFFF))
297 | (1 << (INUM_DMA_BERR-INUM_DMA_0 + 16))
298 | (1<<(low_irq-INUM_DMA_0+0x10))
299 | ((high_irq & IMODE_DMA_IRM) ? (1<<(low_irq-INUM_DMA_0)) : 0);
300
301 DMA_ICR2 = (DMA_ICR2 & ((~(1<<(low_irq-INUM_DMA_0)))&0x00FFFFFF))
302 | ((high_irq & IMODE_DMA_IQE) ? (1<<(low_irq-0x10)) : 0);
303
304 IMASK |= 1<<INUM_DMA;
305 } else if ( (low_irq-INUM_DMA_7)<6){ // low_irq = 0x27 isn't handled?
306
307 u32 extra = 0;
308 if (high_irq & IMODE_DMA_IQE)
309 extra = (1<<(low_irq-INUM_DMA_7 + (INUM_DMA_BERR-INUM_DMA_0)));
310
311 DMA_ICR2=(DMA_ICR2&(~(1<<(low_irq-INUM_DMA_7 + (INUM_DMA_BERR-INUM_DMA_0))) & 0x00FFFFFF)) | (1<<(low_irq-INUM_DMA_7+0x10)) | extra;
312 DMA_ICR |= (DMA_ICR&0x00FFFFFF)| (1 << (INUM_DMA_BERR-INUM_DMA_0 + 16));
313
314 IMASK |= 1<<INUM_DMA;
315 } else {
316 retval = ERROR_BAD_NUMBER;
317 }
318
319 CpuResumeIntr(ictrl);
320 return retval;
321 }
322
323 ///////////////////////////////////////////////////////////////////////
324 //not checked
325 int DisableIntr(int interrupt, int *oldstat){
326 u32 ictrl;
327 u32 old_IMASK;
328 u32 low_irq;
329 u32 stat;
330 u32 ret;
331
332 low_irq = interrupt & 0xFF;
333
334 CpuSuspendIntr(&ictrl);
335
336 ret = -101;
337 stat = -103;
338
339 if (low_irq<0) goto end;
340
341 ret = 0;
342
343 if (low_irq<0x20)
344 {
345 old_IMASK=IMASK;
346 IMASK&=~(1<<low_irq);
347
348 if (old_IMASK&(1<<low_irq))
349 {
350 stat = low_irq;
351 goto end;
352 }
353
354 ret = -103;
355 goto end;
356 }
357
358 if (low_irq<0x27)
359 {
360
361 if (DMA_ICR & 0xFFFFFF & (1<<(low_irq-0x10)))
362 {
363 if (((DMA_ICR & 0xFFFFFF)>>(low_irq-0x20)) & 0x01) stat = low_irq | 0x100;
364
365 if (DMA_ICR2 & (1<<(low_irq-0x20))) stat |= 0x200;
366
367 DMA_ICR2 &= ~(1<<(low_irq-0x20)) & 0xFFFFFF;
368
369 goto end;
370 }
371
372 ret = -103;
373 goto end;
374 }
375
376 if (low_irq<0x2E)
377 {
378 if (DMA_ICR2 & 0xFFFFFF & (1<<(low_irq-0x18)))
379 {
380 stat = low_irq;
381
382 if (((DMA_ICR2 & 0xFFFFFF)>>(low_irq-0x21))&0x01) stat |= 0x200;
383
384 DMA_ICR2 &= ~(1<<(low_irq-0x18)) & 0xFFFFFF;
385
386 goto end;
387 }
388
389 ret = -103;
390 goto end;
391 }
392
393 end:
394 if (oldstat) *(volatile int*)oldstat = stat;
395 CpuResumeIntr(ictrl);
396 return ret;
397 }
398
399 ///////////////////////////////////////////////////////////////////////
400 // Enable
401 void intrman_call16(int interrupt)
402 {
403 u32 ictrl;
404 CpuSuspendIntr(&ictrl);
405
406 interrupt &= 0xFF;
407
408 if (interrupt < 0x20){
409 soft_hw_intr_mask |= (1 << interrupt);
410 } else if (interrupt < 0x28){
411 unknown2[1] |= 1 << (interrupt-0x08);
412 } else if (interrupt < 0x2E){
413 unknown2[2] |= 1 << (interrupt-0x10);
414 }
415
416 CpuResumeIntr(ictrl);
417 }
418
419 ///////////////////////////////////////////////////////////////////////
420 // Disable
421 void intrman_call15(int interrupt)
422 {
423 u32 ictrl;
424 CpuSuspendIntr(&ictrl);
425
426 interrupt &= 0xFF;
427
428 if (interrupt < 0x20){
429 soft_hw_intr_mask &= ~(1 << interrupt);
430 } else if (interrupt < 0x28){
431 unknown2[1] &= ~(1 << (interrupt-0x08));
432 } else if (interrupt < 0x2E){
433 unknown2[2] &= ~(1 << (interrupt-0x10));
434 }
435
436 CpuResumeIntr(ictrl);
437 }
438
439 ///////////////////////////////////////////////////////////////////////
440 void intrman_call27(int arg0)
441 {
442 unknown2[3]=arg0;
443 }
444
445 ///////////////////////////////////////////////////////////////////////
446 //
447 int IntrHandler()
448 {
449 u32 masked_icr = DMA_ICR & unknown2[1];
450
451 _dprintf("%s\n", __FUNCTION__);
452
453
454 while (masked_icr & 0x7F008000){
455 int i;
456 if (masked_icr & 0x00008000){
457 // Int 0x25
458 func int_func = (func)(intrtable[0x25].handler & 0xFFFFFFFC);
459 DMA_ICR &= 0x00FF7FFF;
460 if (int_func){
461 int_func(intrtable[0x25].arg);
462 }
463 }
464 // Check each DMA interrupt
465 // The bits 24 - 30 are set for DMA channels 0 - 6 (ints 0x20 - 0x26 respectively)
466 // The bits 16 - 23 are the corresponding mask bits - the interrupt is only generated if the mask bit is set.
467 for (i=0; i < 7; ++i){
468 u32 ibit = 0x01000000 << i;
469 if (masked_icr & ibit){
470 func int_func = (func)(intrtable[0x20+i].handler & 0xFFFFFFFC);
471 DMA_ICR &= (ibit | 0x00FFFFFF);
472 if (int_func){
473 if (!int_func(intrtable[0x20+i].arg)){
474 // Disable / mask the interrupt if it was not handled
475 DMA_ICR &= (~(0x00010000 << i) & 0x00FFFFFF);
476 }
477 }
478 }
479 }
480 }
481 DMA_ICR &= 0x007FFFFF;
482 while (DMA_ICR & 0x00800000){
483 // do nothing
484 }
485
486 {
487 u32 temp_icr = DMA_ICR;
488 temp_icr &= 0x007FFFFF;
489 temp_icr |= 0x00800000;
490 DMA_ICR = temp_icr;
491 }
492
493 return 1;
494 }
495
496 ///////////////////////////////////////////////////////////////////////
497 //
498 // Default context switch handler - does not switch context.
499 //
500 int default_ctx_switch_handler(u32 sp_in)
501 {
502 return sp_in;
503 }
504
505 ///////////////////////////////////////////////////////////////////////
506 //
507 // Default routine to request a context switch. Does not request one.
508 //
509 int default_ctx_switch_required_handler()
510 {
511 return 0;
512 }
513
514
515 void SetCtxSwitchHandler(func handler){
516 context_switch_handler = handler;
517 }
518
519 void* ResetCtxSwitchHandler()
520 {
521 context_switch_handler = default_ctx_switch_handler;
522 return &context_switch_handler;
523 }
524
525 void SetCtxSwitchReqHandler(func handler)
526 {
527 context_switch_required_handler = handler;
528 }
529
530 int ResetCtxSwitchReqHandler()
531 {
532 context_switch_required_handler = default_ctx_switch_required_handler;
533 }
534
535 ///////////////////////////////////////////////////////////////////////
536 // Return non-zero if sp is in an interrupt context
537 int QueryIntrStack(unsigned char* sp)
538 {
539 int retval = 0;
540 if ( (sp < tempstack + INTR_STACK_SIZE) && (sp > tempstack) ){
541 retval = 1;
542 }
543 return retval;
544 }
545
546 ///////////////////////////////////////////////////////////////////////
547 // Return non-zero is we're currently in a interrupt context
548 int QueryIntrContext()
549 {
550 unsigned char* sp;
551 __asm__ ("move %0, $29\n" : "=r"(sp) :);
552
553 return QueryIntrStack(sp);
554 }
555
556 ///////////////////////////////////////////////////////////////////////
557 //
558 int iCatchMultiIntr()
559 {
560 unsigned char* sp;
561 __asm__ ("move %0, $29\n" : "=r"(sp) :);
562
563 if (QueryIntrStack(sp)){
564 if (sp >= tempstack + 0x160){
565 u32 SR;
566 __asm__ ("mfc0 %0, $12\n" : "=r"(SR));
567 if (SR & 1 == 0){
568 u32 set_SR = SR | 1;
569 __asm__ volatile (
570 "mtc0 %0, $12\n"
571 "nop\n"
572 "nop\n"
573 "mtc0 %1, $12\n" : : "r"(set_SR), "r" (SR)
574 );
575 }
576 return SR;
577 }
578 }
579 return 0;
580 }
581
582
583 ///////////////////////////////////////////////////////////////////////
584 // called by EXCEP_Sys_handler
585 void EXCEP_Sys_8() {
586 _dprintf("%s\n", __FUNCTION__);
587 }
588 ///////////////////////////////////////////////////////////////////////
589 //not finished
590 void syscall_3_intrman_call14(){
591 }
592
593 ///////////////////////////////////////////////////////////////////////
594 //not finished
595 void syscall_4_intrman_call17_19(){
596 }
597
598 ///////////////////////////////////////////////////////////////////////
599 __inline void syscall_0(){
600 func funct;
601 funct=(func)((*(volatile int*)(0x404))+4);
602 __asm__ (
603 "jr %0\n"
604 "rfe\n"
605 : "=r" (funct)
606 );
607 }
608
609 ///////////////////////////////////////////////////////////////////////
610 void retonly(){}
611
612 u32 callContextSwitchRequiredHandler()
613 {
614 if (NULL != context_switch_required_handler){
615 return context_switch_required_handler();
616 } else {
617 return 0;
618 }
619 }
620
621 //////////////////////////////entrypoint///////////////////////////////
622 struct export export_stub={
623 0x41C00000,
624 0,
625 VER(1, 2), // 1.2 => 0x102
626 0,
627 "intrman",
628 (func)_start, // entrypoint
629 (func)intrmanDeinit,
630 (func)intrman_call2,
631 (func)intrman_call3,
632 (func)RegisterIntrHandler,
633 (func)ReleaseIntrHandler,
634 (func)EnableIntr,
635 (func)DisableIntr,
636 (func)CpuDisableIntr,
637 (func)CpuEnableIntr,
638 (func)intrman_syscall_04, // 0x0A
639 (func)intrman_syscall_08,
640 (func)CpuGetICTRL,
641 (func)CpuEnableICTRL,
642 (func)intrman_syscall_0C, // 0x0E
643 (func)intrman_call15,
644 (func)intrman_call16, // 0x10
645 (func)CpuSuspendIntr,
646 (func)CpuResumeIntr,
647 (func)CpuSuspendIntr,
648 (func)CpuResumeIntr,
649 (func)intrman_syscall_10,
650 (func)intrman_syscall_14,
651 (func)QueryIntrContext, // 0x17
652 (func)QueryIntrStack,
653 (func)iCatchMultiIntr,
654 (func)retonly,
655 (func)intrman_call27,
656 (func)SetCtxSwitchHandler, // 0x1C (called by threadman)
657 (func)ResetCtxSwitchHandler,
658 (func)SetCtxSwitchReqHandler, // 0x1E (called by threadman)
659 (func)ResetCtxSwitchReqHandler,
660 0
661 };
662
663 extern struct exHandler EXCEP_Int_priority_exception_handler;
664 extern struct exHandler EXCEP_Int_handler;
665 extern struct exHandler EXCEP_Sys_handler;
666
667 //////////////////////////////entrypoint///////////////////////////////
668 int _start(){
669 int i;
670
671 intrtable = (struct intrHandler*)(GetExHandlersTable() + 0x40);
672
673 IMASK = 0x00;
674 DMA_ICR = 0x00;
675 DMA_ICR2 = 0x00;
676
677 for (i=0; i < 0x2F; i++) {
678 intrtable[i].handler = 0;
679 intrtable[i].arg = 0;
680 }
681
682 soft_hw_intr_mask = 0xFFFFFFFF;
683 unknown2[1] = -1;
684 unknown2[2] = -1;
685 unknown2[0] = (int)intrtable;
686
687 RegisterExceptionHandler(0, &EXCEP_Int_handler);
688 RegisterPriorityExceptionHandler(0, 3, &EXCEP_Int_priority_exception_handler);
689 RegisterExceptionHandler(8, &EXCEP_Sys_handler);
690 RegisterIntrHandler(3, 1, &IntrHandler, 0);
691 RegisterLibraryEntries(&export_stub);
692
693 return 0;
694 }
695
696 void ijb_ping1()
697 {
698 _dprintf("%s\n", __FUNCTION__);
699 unsigned char* x = tempstack;
700 }
701 void ijb_trace3(u32 a0, u32 a1, u32 a2, u32 a3)
702 {
703 __printf("trace3: 0x%x, 0x%x, 0x%x\n", a0, a1, a2);
704 while (1){}
705 }

  ViewVC Help
Powered by ViewVC 1.1.22