update DI disc code
[libogc.git] / libogc / si.c
blob0dd47e2142fc0b7cf25c7f44247860607f4ea3ff
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <time.h>
5 #include "asm.h"
6 #include "processor.h"
7 #include "system.h"
8 #include "ogcsys.h"
9 #include "video.h"
10 #include "irq.h"
11 #include "si.h"
12 #include "lwp_watchdog.h"
14 //#define _SI_DEBUG
16 #define _SHIFTL(v, s, w) \
17 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
18 #define _SHIFTR(v, s, w) \
19 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
21 #define SISR_ERRORMASK(chn) (0x0f000000>>((chn)<<3))
22 #define SIPOLL_ENABLE(chn) (0x80000000>>((chn)+24))
24 #define SICOMCSR_TCINT (1<<31)
25 #define SICOMCSR_TCINT_ENABLE (1<<30)
26 #define SICOMCSR_COMERR (1<<29)
27 #define SICOMCSR_RDSTINT (1<<28)
28 #define SICOMCSR_RDSTINT_ENABLE (1<<27)
29 #define SICOMCSR_TSTART (1<<0)
31 #define SISR_UNDERRUN 0x0001
32 #define SISR_OVERRUN 0x0002
33 #define SISR_COLLISION 0x0004
34 #define SISR_NORESPONSE 0x0008
35 #define SISR_WRST 0x0010
36 #define SISR_RDST 0x0020
38 typedef union _sicomcsr {
39 u32 val;
40 struct {
41 u32 tcint : 1;
42 u32 tcintmsk : 1;
43 u32 comerr : 1;
44 u32 rdstint : 1;
45 u32 rdstintmsk : 1;
46 u32 pad2 : 4;
47 u32 outlen : 7;
48 u32 pad1 : 1;
49 u32 inlen : 7;
50 u32 pad0 : 5;
51 u32 channel : 2;
52 u32 tstart : 1;
53 } csrmap;
54 } sicomcsr;
56 static struct _sipacket {
57 s32 chan;
58 void *out;
59 u32 out_bytes;
60 void *in;
61 u32 in_bytes;
62 SICallback callback;
63 u64 fire;
64 } sipacket[4];
66 static struct _sicntrl {
67 s32 chan;
68 u32 poll;
69 u32 in_bytes;
70 void *in;
71 SICallback callback;
72 } sicntrl = {
73 -1,
76 NULL,
77 NULL
80 static struct _xy {
81 u16 line;
82 u8 cnt;
83 } xy[2][12] = {
85 {0x00F6,0x02},{0x000F,0x12},{0x001E,0x09},{0x002C,0x06},
86 {0x0034,0x05},{0x0041,0x04},{0x0057,0x03},{0x0057,0x03},
87 {0x0057,0x03},{0x0083,0x02},{0x0083,0x02},{0x0083,0x02}
91 {0x0128,0x02},{0x000F,0x15},{0x001D,0x0B},{0x002D,0x07},
92 {0x0034,0x06},{0x003F,0x05},{0x004E,0x04},{0x0068,0x03},
93 {0x0068,0x03},{0x0068,0x03},{0x0068,0x03},{0x009C,0x02}
97 u32 __PADFixBits = 0;
99 static u32 sampling_rate = 0;
100 static u32 cmdtypeandstatus$47 = 0;
101 static u32 cmdtypeandstatus$223 = 0;
102 static u32 cmdfixdevice[4] = {0,0,0,0};
103 static u32 si_type[4] = {8,8,8,8};
104 static u32 inputBufferVCount[4] = {0,0,0,0};
105 static u32 inputBufferValid[4] = {0,0,0,0};
106 static u32 inputBuffer[4][2] = {{0,0},{0,0},{0,0},{0,0}};
107 static RDSTHandler rdstHandlers[4] = {NULL,NULL,NULL,NULL};
108 static u64 typeTime[4] = {0,0,0,0};
109 static u64 xferTime[4] = {0,0,0,0};
110 static SICallback typeCallback[4][4] = {{NULL,NULL,NULL,NULL},
111 {NULL,NULL,NULL,NULL},
112 {NULL,NULL,NULL,NULL},
113 {NULL,NULL,NULL,NULL}};
114 static syswd_t si_alarm[4];
116 #if defined(HW_DOL)
117 static vu32* const _siReg = (u32*)0xCC006400;
118 #elif defined(HW_RVL)
119 static vu32* const _siReg = (u32*)0xCD006400;
120 #else
121 #error HW model unknown.
122 #endif
124 static vu16* const _viReg = (u16*)0xCC002000;
126 static u32 __si_transfer(s32 chan,void *out,u32 out_len,void *in,u32 in_len,SICallback cb);
128 static __inline__ struct _xy* __si_getxy()
130 switch(VIDEO_GetCurrentTvMode()) {
131 case VI_NTSC:
132 case VI_MPAL:
133 case VI_EURGB60:
134 return xy[0];
135 break;
136 case VI_PAL:
137 return xy[1];
138 break;
140 return NULL;
143 static __inline__ void __si_cleartcinterrupt()
145 _siReg[13] = (_siReg[13]|SICOMCSR_TCINT)&SICOMCSR_TCINT;
148 static void __si_alarmhandler(syswd_t thealarm,void *cbarg)
150 u32 chn;
151 #ifdef _SI_DEBUG
152 printf("__si_alarmhandler(%08x)\n",thealarm);
153 #endif
154 chn = 0;
155 while(chn<4) {
156 if(si_alarm[chn]==thealarm) break;
157 chn++;
159 if(chn==4) return;
161 if(sipacket[chn].chan!=-1) {
162 if(__si_transfer(sipacket[chn].chan,sipacket[chn].out,sipacket[chn].out_bytes,sipacket[chn].in,sipacket[chn].in_bytes,sipacket[chn].callback)) sipacket[chn].chan = -1;
166 static u32 __si_completetransfer()
168 u32 val,sisr,cnt,i;
169 u32 *in;
171 #ifdef _SI_DEBUG
172 printf("__si_completetransfer(csr = %08x,sr = %08x,chan = %d)\n",_siReg[13],_siReg[14],sicntrl.chan);
173 #endif
174 sisr = _siReg[14];
175 __si_cleartcinterrupt();
177 if(sicntrl.chan==-1) return sisr;
179 xferTime[sicntrl.chan] = gettime();
181 in = (u32*)sicntrl.in;
182 cnt = (sicntrl.in_bytes/4);
183 for(i=0;i<cnt;i++) in[i] = _siReg[32+i];
184 if(sicntrl.in_bytes&0x03) {
185 val = _siReg[32+cnt];
186 for(i=0;i<(sicntrl.in_bytes&0x03);i++) ((u8*)in)[(cnt*4)+i] = (val>>((3-i)*8))&0xff;
188 #ifdef _SI_DEBUG
189 printf("__si_completetransfer(csr = %08x)\n",_siReg[13]);
190 #endif
191 if(_siReg[13]&SICOMCSR_COMERR) {
192 sisr = (sisr>>((3-sicntrl.chan)*8))&0x0f;
193 if(sisr&SISR_NORESPONSE && !(si_type[sicntrl.chan]&SI_ERR_BUSY)) si_type[sicntrl.chan] = SI_ERROR_NO_RESPONSE;
194 if(!sisr) sisr = SISR_COLLISION;
195 } else {
196 typeTime[sicntrl.chan] = gettime();
197 sisr = 0;
200 sicntrl.chan = -1;
201 return sisr;
204 static u32 __si_transfer(s32 chan,void *out,u32 out_len,void *in,u32 in_len,SICallback cb)
206 u32 level,cnt,i;
207 sicomcsr csr;
208 #ifdef _SI_DEBUG
209 printf("__si_transfer(%d,%p,%d,%p,%d,%p)\n",chan,out,out_len,in,in_len,cb);
210 #endif
211 _CPU_ISR_Disable(level);
212 if(sicntrl.chan!=-1) {
213 _CPU_ISR_Restore(level);
214 return 0;
216 #ifdef _SI_DEBUG
217 printf("__si_transfer(out = %08x,csr = %08x,sr = %08x)\n",*(u32*)out,_siReg[13],_siReg[14]);
218 #endif
219 _siReg[14] &= SISR_ERRORMASK(chan);
221 sicntrl.chan = chan;
222 sicntrl.callback = cb;
223 sicntrl.in_bytes = in_len;
224 sicntrl.in = in;
225 #ifdef _SI_DEBUG
226 printf("__si_transfer(csr = %08x,sr = %08x)\n",_siReg[13],_siReg[14]);
227 #endif
228 cnt = ((out_len+3)/4);
229 for(i=0;i<cnt;i++) _siReg[32+i] = ((u32*)out)[i];
231 csr.val = _siReg[13];
232 csr.csrmap.tcint = 1;
233 csr.csrmap.tcintmsk = 0;
234 if(cb) csr.csrmap.tcintmsk = 1;
236 if(out_len==128) out_len = 0;
237 csr.csrmap.outlen = out_len&0x7f;
239 if(in_len==128) in_len = 0;
240 csr.csrmap.inlen = in_len&0x7f;
242 csr.csrmap.channel = chan&0x03;
243 csr.csrmap.tstart = 1;
244 #ifdef _SI_DEBUG
245 printf("__si_transfer(csr = %08x)\n",csr.val);
246 #endif
247 _siReg[13] = csr.val;
248 _CPU_ISR_Restore(level);
250 return 1;
253 static void __si_calltypandstatuscallback(s32 chan,u32 type)
255 u32 typ;
256 SICallback cb = NULL;
257 #ifdef _SI_DEBUG
258 printf("__si_calltypandstatuscallback(%d,%08x)\n",chan,type);
259 #endif
260 typ = 0;
261 while(typ<4) {
262 cb = typeCallback[chan][typ];
263 if(cb) {
264 typeCallback[chan][typ] = NULL;
265 cb(chan,type);
267 typ++;
271 static void __si_gettypecallback(s32 chan,u32 type)
273 u32 sipad_en,id;
275 si_type[chan] = (si_type[chan]&~SI_ERR_BUSY)|type;
276 typeTime[chan] = gettime();
277 #ifdef _SI_DEBUG
278 printf("__si_gettypecallback(%d,%08x,%08x)\n",chan,type,si_type[chan]);
279 #endif
280 sipad_en = __PADFixBits&SI_CHAN_BIT(chan);
281 __PADFixBits &= ~SI_CHAN_BIT(chan);
283 if(type&0x0f || ((si_type[chan]&SI_TYPE_MASK)-SI_TYPE_GC)
284 || !(si_type[chan]&SI_GC_WIRELESS) || si_type[chan]&SI_WIRELESS_IR) {
285 SYS_SetWirelessID(chan,0);
286 __si_calltypandstatuscallback(chan,si_type[chan]);
287 return;
290 id = _SHIFTL(SYS_GetWirelessID(chan),8,16);
291 #ifdef _SI_DEBUG
292 printf("__si_gettypecallback(id = %08x)\n",id);
293 #endif
294 if(sipad_en && id&SI_WIRELESS_FIX_ID) {
295 cmdfixdevice[chan] = 0x4e100000|(id&0x00CFFF00);
296 si_type[chan] = SI_ERR_BUSY;
297 SI_Transfer(chan,&cmdfixdevice[chan],3,&si_type[chan],3,__si_gettypecallback,0);
298 return;
301 if(si_type[chan]&SI_WIRELESS_FIX_ID) {
302 if((id&0x00CFFF00)==(si_type[chan]&0x00CFFF00)) goto exit;
303 if(!(id&SI_WIRELESS_FIX_ID)) {
304 id = SI_WIRELESS_FIX_ID|(si_type[chan]&0x00CFFF00);
305 SYS_SetWirelessID(chan,_SHIFTR(id,8,16));
307 cmdfixdevice[chan] = 0x4e000000|id;
308 si_type[chan] = SI_ERR_BUSY;
309 SI_Transfer(chan,&cmdfixdevice[chan],3,&si_type[chan],3,__si_gettypecallback,0);
310 return;
313 if(si_type[chan]&SI_WIRELESS_RECEIVED) {
314 id = SI_WIRELESS_FIX_ID|(si_type[chan]&0x00CFFF00);
315 SYS_SetWirelessID(chan,_SHIFTR(id,8,16));
317 cmdfixdevice[chan] = 0x4e000000|id;
318 si_type[chan] = SI_ERR_BUSY;
319 SI_Transfer(chan,&cmdfixdevice[chan],3,&si_type[chan],3,__si_gettypecallback,0);
320 return;
322 SYS_SetWirelessID(chan,0);
324 exit:
325 __si_calltypandstatuscallback(chan,si_type[chan]);
328 static void __si_transfernext(u32 chan)
330 u32 cnt;
331 u64 now;
332 s64 diff;
333 #ifdef _SI_DEBUG
334 printf("__si_transfernext(%d)\n",chan);
335 #endif
336 cnt = 0;
337 while(cnt<4) {
338 chan++;
339 chan %= 4;
340 #ifdef _SI_DEBUG
341 printf("__si_transfernext(chan = %d,sipacket.chan = %d)\n",chan,sipacket[chan].chan);
342 #endif
343 if(sipacket[chan].chan!=-1) {
344 now = gettime();
345 diff = (now - sipacket[chan].fire);
346 if(diff>=0) {
347 if(!__si_transfer(sipacket[chan].chan,sipacket[chan].out,sipacket[chan].out_bytes,sipacket[chan].in,sipacket[chan].in_bytes,sipacket[chan].callback)) break;
348 SYS_CancelAlarm(si_alarm[chan]);
349 sipacket[chan].chan = -1;
352 cnt++;
356 static void __si_interrupthandler(u32 irq,void *ctx)
358 SICallback cb;
359 u32 chn,curr_line,line,ret;
360 sicomcsr csr;
362 csr.val = _siReg[13];
363 #ifdef _SI_DEBUG
364 printf("__si_interrupthandler(csr = %08x)\n",csr.val);
365 #endif
366 if(csr.csrmap.tcintmsk && csr.csrmap.tcint) {
367 chn = sicntrl.chan;
368 cb = sicntrl.callback;
369 sicntrl.callback = NULL;
371 ret = __si_completetransfer();
372 __si_transfernext(chn);
374 if(cb) cb(chn,ret);
376 _siReg[14] &= SISR_ERRORMASK(chn);
378 if(si_type[chn]==SI_ERR_BUSY && !SI_IsChanBusy(chn)) SI_Transfer(chn,&cmdtypeandstatus$47,1,&si_type[chn],3,__si_gettypecallback,65);
381 if(csr.csrmap.rdstintmsk && csr.csrmap.rdstint) {
382 curr_line = VIDEO_GetCurrentLine();
383 curr_line++;
384 line = _SHIFTR(sicntrl.poll,16,10);
386 chn = 0;
387 while(chn<4) {
388 if(SI_GetResponseRaw(chn)) inputBufferVCount[chn] = curr_line;
389 chn++;
392 chn = 0;
393 while(chn<4) {
394 if(sicntrl.poll&SIPOLL_ENABLE(chn)) {
395 if(!inputBufferVCount[chn] || ((line>>1)+inputBufferVCount[chn])<curr_line) return;
397 chn++;
400 chn = 0;
401 while(chn<4) inputBufferVCount[chn++] = 0;
403 chn = 0;
404 while(chn<4) {
405 if(rdstHandlers[chn]) rdstHandlers[chn](irq,ctx);
406 chn++;
411 u32 SI_Sync()
413 u32 level,ret;
415 while(_siReg[13]&SICOMCSR_TSTART);
417 _CPU_ISR_Disable(level);
418 ret = __si_completetransfer();
419 __si_transfernext(4);
420 _CPU_ISR_Restore(level);
422 return ret;
425 u32 SI_Busy()
427 return (sicntrl.chan==-1)?0:1;
430 u32 SI_IsChanBusy(s32 chan)
432 u32 ret = 0;
434 if(sipacket[chan].chan!=-1 || sicntrl.chan==chan) ret = 1;
436 return ret;
439 void SI_SetXY(u16 line,u8 cnt)
441 u32 level;
442 #ifdef _SI_DEBUG
443 printf("SI_SetXY(%d,%d)\n",line,cnt);
444 #endif
445 _CPU_ISR_Disable(level);
446 sicntrl.poll = (sicntrl.poll&~0x3ffff00)|_SHIFTL(line,16,10)|_SHIFTL(cnt,8,8);
447 _siReg[12] = sicntrl.poll;
448 _CPU_ISR_Restore(level);
451 void SI_EnablePolling(u32 poll)
453 u32 level,mask;
454 #ifdef _SI_DEBUG
455 printf("SI_EnablePolling(%08x)\n",poll);
456 #endif
457 _CPU_ISR_Disable(level);
458 poll >>= 24;
459 mask = (poll>>4)&0x0f;
460 sicntrl.poll &= ~mask;
462 poll &= (0x03fffff0|mask);
464 sicntrl.poll |= (poll&~0x03ffff00);
465 SI_TransferCommands();
466 #ifdef _SI_DEBUG
467 printf("SI_EnablePolling(%08x)\n",sicntrl.poll);
468 #endif
469 _siReg[12] = sicntrl.poll;
470 _CPU_ISR_Restore(level);
473 void SI_DisablePolling(u32 poll)
475 u32 level,mask;
476 #ifdef _SI_DEBUG
477 printf("SI_DisablePolling(%08x)\n",poll);
478 #endif
479 _CPU_ISR_Disable(level);
480 mask = (poll>>24)&0xf0;
481 sicntrl.poll &= ~mask;
482 _siReg[12] = sicntrl.poll;
483 _CPU_ISR_Restore(level);
486 void SI_SetSamplingRate(u32 samplingrate)
488 u32 div,level;
489 struct _xy *xy = NULL;
491 if(samplingrate>11) samplingrate = 11;
493 _CPU_ISR_Disable(level);
494 sampling_rate = samplingrate;
495 xy = __si_getxy();
497 div = 1;
498 if(_viReg[54]&0x0001) div = 2;
500 SI_SetXY(div*xy[samplingrate].line,xy[samplingrate].cnt);
501 _CPU_ISR_Restore(level);
504 void SI_RefreshSamplingRate()
506 SI_SetSamplingRate(sampling_rate);
509 u32 SI_GetStatus(s32 chan)
511 u32 level,sisr;
513 _CPU_ISR_Disable(level);
514 sisr = (_siReg[14]>>((3-chan)<<3));
515 if(sisr&SISR_NORESPONSE && !(si_type[chan]&SI_ERR_BUSY)) si_type[chan] = SI_ERROR_NO_RESPONSE;
516 _CPU_ISR_Restore(level);
517 return sisr;
520 u32 SI_GetResponseRaw(s32 chan)
522 u32 status,ret;
523 #ifdef _SI_DEBUG
524 printf("SI_GetResponseRaw(%d)\n",chan);
525 #endif
526 ret = 0;
527 status = SI_GetStatus(chan);
528 if(status&SISR_RDST) {
529 inputBuffer[chan][0] = _siReg[(chan*3)+1];
530 inputBuffer[chan][1] = _siReg[(chan*3)+2];
531 inputBufferValid[chan] = 1;
532 ret = 1;
534 return ret;
537 u32 SI_GetResponse(s32 chan,void *buf)
539 u32 level,valid;
540 _CPU_ISR_Disable(level);
541 SI_GetResponseRaw(chan);
542 valid = inputBufferValid[chan];
543 inputBufferValid[chan] = 0;
544 #ifdef _SI_DEBUG
545 printf("SI_GetResponse(%d,%p,%d)\n",chan,buf,valid);
546 #endif
547 if(valid) {
548 ((u32*)buf)[0] = inputBuffer[chan][0];
549 ((u32*)buf)[1] = inputBuffer[chan][1];
551 _CPU_ISR_Restore(level);
552 return valid;
555 void SI_SetCommand(s32 chan,u32 cmd)
557 _siReg[chan*3] = cmd;
560 u32 SI_GetCommand(s32 chan)
562 return (_siReg[chan*3]);
565 u32 SI_Transfer(s32 chan,void *out,u32 out_len,void *in,u32 in_len,SICallback cb,u32 us_delay)
567 u32 ret = 0;
568 u32 level;
569 s64 diff;
570 u64 now,fire;
571 struct timespec tb;
572 #ifdef _SI_DEBUG
573 printf("SI_Transfer(%d,%p,%d,%p,%d,%p,%d)\n",chan,out,out_len,in,in_len,cb,us_delay);
574 #endif
575 _CPU_ISR_Disable(level);
576 if(sipacket[chan].chan==-1 && sicntrl.chan!=chan) {
577 ret = 1;
578 fire = now = gettime();
579 if(us_delay) fire = xferTime[chan]+microsecs_to_ticks(us_delay);
580 diff = (now - fire);
581 if(diff<0) {
582 tb.tv_sec = 0;
583 tb.tv_nsec = ticks_to_nanosecs((fire - now));
584 SYS_SetAlarm(si_alarm[chan],&tb,__si_alarmhandler,NULL);
585 } else if(__si_transfer(chan,out,out_len,in,in_len,cb)) {
586 _CPU_ISR_Restore(level);
587 return ret;
589 sipacket[chan].chan = chan;
590 sipacket[chan].out = out;
591 sipacket[chan].out_bytes = out_len;
592 sipacket[chan].in = in;
593 sipacket[chan].in_bytes = in_len;
594 sipacket[chan].callback = cb;
595 sipacket[chan].fire = fire;
596 #ifdef _SI_DEBUG
597 printf("SI_Transfer(%d,%p,%d,%p,%d,%p,%08x%08x)\n",sipacket[chan].chan,sipacket[chan].out,sipacket[chan].out_bytes,sipacket[chan].in,sipacket[chan].in_bytes,sipacket[chan].callback,(u32)(sipacket[chan].fire>>32),(u32)sipacket[chan].fire);
598 #endif
600 _CPU_ISR_Restore(level);
601 return ret;
604 u32 SI_GetType(s32 chan)
606 u32 level,type;
607 u64 now;
608 s64 diff;
609 #ifdef _SI_DEBUG
610 printf("SI_GetType(%d)\n",chan);
611 #endif
612 _CPU_ISR_Disable(level);
613 now = gettime();
614 type = si_type[chan];
615 diff = (now - typeTime[chan]);
616 if(sicntrl.poll&(0x80>>chan)) {
617 if(type!=SI_ERROR_NO_RESPONSE) {
618 typeTime[chan] = gettime();
619 _CPU_ISR_Restore(level);
620 return type;
622 si_type[chan] = type = SI_ERR_BUSY;
623 } else if(diff==millisecs_to_ticks(50) && type!=SI_ERROR_NO_RESPONSE) {
624 _CPU_ISR_Restore(level);
625 return type;
626 } else if(diff==millisecs_to_ticks(75)) si_type[chan] = SI_ERR_BUSY;
627 else si_type[chan] = type = SI_ERR_BUSY;
629 typeTime[chan] = gettime();
631 SI_Transfer(chan,&cmdtypeandstatus$223,1,&si_type[chan],3,__si_gettypecallback,65);
632 _CPU_ISR_Restore(level);
634 return type;
637 u32 SI_GetTypeAsync(s32 chan,SICallback cb)
639 u32 level;
640 u32 type,i;
641 #ifdef _SI_DEBUG
642 printf("SI_GetTypeAsync(%d)\n",chan);
643 #endif
644 _CPU_ISR_Disable(level);
645 type = SI_GetType(chan);
646 if(si_type[chan]&SI_ERR_BUSY) {
647 i=0;
648 for(i=0;i<4;i++) {
649 if(!typeCallback[chan][i] && typeCallback[chan][i]!=cb) {
650 typeCallback[chan][i] = cb;
651 break;
654 _CPU_ISR_Restore(level);
655 return type;
658 cb(chan,type);
659 _CPU_ISR_Restore(level);
660 return type;
663 void SI_TransferCommands()
665 _siReg[14] = 0x80000000;
668 u32 SI_RegisterPollingHandler(RDSTHandler handler)
670 u32 level,i;
672 _CPU_ISR_Disable(level);
674 i = 0;
675 for(i=0;i<4;i++) {
676 if(rdstHandlers[i]==handler) {
677 _CPU_ISR_Restore(level);
678 return 1;
682 for(i=0;i<4;i++) {
683 if(rdstHandlers[i]==NULL) {
684 rdstHandlers[i] = handler;
685 SI_EnablePollingInterrupt(TRUE);
686 _CPU_ISR_Restore(level);
687 return 1;
691 _CPU_ISR_Restore(level);
692 return 0;
695 u32 SI_UnregisterPollingHandler(RDSTHandler handler)
697 u32 level,i;
699 _CPU_ISR_Disable(level);
700 for(i=0;i<4;i++) {
701 if(rdstHandlers[i]==handler) {
702 rdstHandlers[i] = NULL;
703 for(i=0;i<4;i++) {
704 if(rdstHandlers[i]!=NULL) break;
706 if(i>=4) SI_EnablePollingInterrupt(FALSE);
708 _CPU_ISR_Restore(level);
709 return 1;
712 _CPU_ISR_Restore(level);
713 return 0;
716 u32 SI_EnablePollingInterrupt(s32 enable)
718 sicomcsr csr;
719 u32 level,ret,i;
721 _CPU_ISR_Disable(level);
723 ret = 0;
724 csr.val = _siReg[13];
725 if(csr.csrmap.rdstintmsk) ret = 1;
727 if(enable) {
728 csr.csrmap.rdstintmsk = 1;
729 for(i=0;i<4;i++) inputBufferVCount[i] = 0;
730 } else
731 csr.csrmap.rdstintmsk = 0;
733 csr.val &= 0x7ffffffe;
734 _siReg[13] = csr.val;
736 _CPU_ISR_Restore(level);
737 return ret;
740 void __si_init()
742 u32 i;
743 #ifdef _SI_DEBUG
744 printf("__si_init()\n");
745 #endif
746 for(i=0;i<4;i++) {
747 sipacket[i].chan = -1;
748 SYS_CreateAlarm(&si_alarm[i]);
750 sicntrl.poll = 0;
752 SI_SetSamplingRate(0);
753 while(_siReg[13]&0x0001);
754 _siReg[13] = 0x80000000;
756 _siReg[15] &= ~0x80000000; // permit exi clock to be set to 32MHz
758 IRQ_Request(IRQ_PI_SI,__si_interrupthandler,NULL);
759 __UnmaskIrq(IRQMASK(IRQ_PI_SI));
761 SI_GetType(0);
762 SI_GetType(1);
763 SI_GetType(2);
764 SI_GetType(3);