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"
13 
14 #define _SHIFTL(v, s, w)	\
15     ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
16 #define _SHIFTR(v, s, w)	\
17     ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
18 
19 #define SISR_ERRORMASK(chn)			(0x0f000000>>((chn)<<3))
20 #define SIPOLL_ENABLE(chn)			(0x80000000>>((chn)+24))
21 
22 #define SICOMCSR_TCINT				(1<<31)
23 #define SICOMCSR_TCINT_ENABLE		(1<<30)
24 #define SICOMCSR_COMERR				(1<<29)
25 #define SICOMCSR_RDSTINT			(1<<28)
26 #define SICOMCSR_RDSTINT_ENABLE		(1<<27)
27 #define SICOMCSR_TSTART				(1<<0)
28 
29 #define SISR_UNDERRUN				0x0001
30 #define SISR_OVERRUN				0x0002
31 #define SISR_COLLISION				0x0004
32 #define SISR_NORESPONSE				0x0008
33 #define SISR_WRST					0x0010
34 #define SISR_RDST					0x0020
35 
36 typedef union _sicomcsr {
37 	u32 val;
38 	struct {
39 		u32 tcint		: 1;
40 		u32 tcintmsk	: 1;
41 		u32 comerr		: 1;
42 		u32 rdstint		: 1;
43 		u32 rdstintmsk	: 1;
44 		u32 pad2		: 4;
45 		u32 outlen		: 7;
46 		u32 pad1		: 1;
47 		u32 inlen		: 7;
48 		u32 pad0		: 5;
49 		u32 channel		: 2;
50 		u32 tstart		: 1;
51 	} csrmap;
52 } sicomcsr;
53 
54 static struct _sipacket {
55 	s32 chan;
56 	void *out;
57 	u32 out_bytes;
58 	void *in;
59 	u32 in_bytes;
60 	SICallback callback;
61 	u64 fire;
62 } sipacket[4];
63 
64 static struct _sicntrl {
65 	s32 chan;
66 	u32 poll;
67 	u32 in_bytes;
68 	void *in;
69 	SICallback callback;
70 } sicntrl = {
71 	-1,
72 	0,
73 	0,
74 	NULL,
75 	NULL
76 };
77 
78 static struct _xy {
79 	u16 line;
80 	u8 cnt;
81 } xy[2][12] = {
82 	{
83 		{0x00F6,0x02},{0x000F,0x12},{0x001E,0x09},{0x002C,0x06},
84 		{0x0034,0x05},{0x0041,0x04},{0x0057,0x03},{0x0057,0x03},
85 		{0x0057,0x03},{0x0083,0x02},{0x0083,0x02},{0x0083,0x02}
86 	},
87 
88 	{
89 		{0x0128,0x02},{0x000F,0x15},{0x001D,0x0B},{0x002D,0x07},
90 		{0x0034,0x06},{0x003F,0x05},{0x004E,0x04},{0x0068,0x03},
91 		{0x0068,0x03},{0x0068,0x03},{0x0068,0x03},{0x009C,0x02}
92 	}
93 };
94 
95 u32 __PADFixBits = 0;
96 
97 static u32 sampling_rate = 0;
98 static u32 cmdtypeandstatus$47 = 0;
99 static u32 cmdtypeandstatus$223 = 0;
100 static u32 cmdfixdevice[4] = {0,0,0,0};
101 static u32 si_type[4] = {8,8,8,8};
102 static u32 inputBufferVCount[4] = {0,0,0,0};
103 static u32 inputBufferValid[4] = {0,0,0,0};
104 static u32 inputBuffer[4][2] = {{0,0},{0,0},{0,0},{0,0}};
105 static RDSTHandler rdstHandlers[4] = {NULL,NULL,NULL,NULL};
106 static u64 typeTime[4] = {0,0,0,0};
107 static u64 xferTime[4] = {0,0,0,0};
108 static SICallback typeCallback[4][4] = {{NULL,NULL,NULL,NULL},
109 										{NULL,NULL,NULL,NULL},
110 										{NULL,NULL,NULL,NULL},
111 										{NULL,NULL,NULL,NULL}};
112 static syswd_t si_alarm[4];
113 
114 #if defined(HW_DOL)
115 	static vu32* const _siReg = (u32*)0xCC006400;
116 #elif defined(HW_RVL)
117 	static vu32* const _siReg = (u32*)0xCD006400;
118 #else
119 	#error HW model unknown.
120 #endif
121 
122 static vu16* const _viReg = (u16*)0xCC002000;
123 
124 static u32 __si_transfer(s32 chan,void *out,u32 out_len,void *in,u32 in_len,SICallback cb);
125 
__si_getxy()126 static __inline__ struct _xy* __si_getxy()
127 {
128 	switch(VIDEO_GetCurrentTvMode()) {
129 		case VI_NTSC:
130 		case VI_MPAL:
131 		case VI_EURGB60:
132 			return xy[0];
133 			break;
134 		case VI_PAL:
135 			return xy[1];
136 			break;
137 	}
138 	return NULL;
139 }
140 
__si_cleartcinterrupt()141 static __inline__ void __si_cleartcinterrupt()
142 {
143 	_siReg[13] = (_siReg[13]|SICOMCSR_TCINT)&SICOMCSR_TCINT;
144 }
145 
__si_alarmhandler(syswd_t thealarm,void * cbarg)146 static void __si_alarmhandler(syswd_t thealarm,void *cbarg)
147 {
148 	u32 chn = 0;
149 
150 	while(chn<4)
151    {
152 		if(si_alarm[chn]==thealarm)
153          break;
154 		chn++;
155 	}
156 	if(chn==4)
157       return;
158 
159 	if(sipacket[chn].chan!=-1) {
160 		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;
161 	}
162 }
163 
__si_completetransfer()164 static u32 __si_completetransfer()
165 {
166 	u32 val,cnt,i;
167 	u32 *in;
168 	u32 sisr = _siReg[14];
169 
170 	__si_cleartcinterrupt();
171 
172 	if(sicntrl.chan==-1) return sisr;
173 
174 	xferTime[sicntrl.chan] = gettime();
175 
176 	in = (u32*)sicntrl.in;
177 	cnt = (sicntrl.in_bytes/4);
178 	for(i=0;i<cnt;i++) in[i] = _siReg[32+i];
179 	if(sicntrl.in_bytes&0x03) {
180 		val = _siReg[32+cnt];
181 		for(i=0;i<(sicntrl.in_bytes&0x03);i++) ((u8*)in)[(cnt*4)+i] = (val>>((3-i)*8))&0xff;
182 	}
183 	if(_siReg[13]&SICOMCSR_COMERR) {
184 		sisr = (sisr>>((3-sicntrl.chan)*8))&0x0f;
185 		if(sisr&SISR_NORESPONSE && !(si_type[sicntrl.chan]&SI_ERR_BUSY)) si_type[sicntrl.chan] = SI_ERROR_NO_RESPONSE;
186 		if(!sisr) sisr = SISR_COLLISION;
187 	} else {
188 		typeTime[sicntrl.chan] = gettime();
189 		sisr = 0;
190 	}
191 
192 	sicntrl.chan = -1;
193 	return sisr;
194 }
195 
__si_transfer(s32 chan,void * out,u32 out_len,void * in,u32 in_len,SICallback cb)196 static u32 __si_transfer(s32 chan,void *out,u32 out_len,void *in,u32 in_len,SICallback cb)
197 {
198 	u32 level,cnt,i;
199 	sicomcsr csr;
200 	_CPU_ISR_Disable(level);
201 	if(sicntrl.chan!=-1) {
202 		_CPU_ISR_Restore(level);
203 		return 0;
204 	}
205 	_siReg[14] &= SISR_ERRORMASK(chan);
206 
207 	sicntrl.chan = chan;
208 	sicntrl.callback = cb;
209 	sicntrl.in_bytes = in_len;
210 	sicntrl.in = in;
211 	cnt = ((out_len+3)/4);
212 	for(i=0;i<cnt;i++)  _siReg[32+i] = ((u32*)out)[i];
213 
214 	csr.val = _siReg[13];
215 	csr.csrmap.tcint = 1;
216 	csr.csrmap.tcintmsk = 0;
217 	if(cb) csr.csrmap.tcintmsk = 1;
218 
219 	if(out_len==128) out_len = 0;
220 	csr.csrmap.outlen = out_len&0x7f;
221 
222 	if(in_len==128) in_len = 0;
223 	csr.csrmap.inlen = in_len&0x7f;
224 
225 	csr.csrmap.channel = chan&0x03;
226 	csr.csrmap.tstart = 1;
227 	_siReg[13] = csr.val;
228 	_CPU_ISR_Restore(level);
229 
230 	return 1;
231 }
232 
__si_calltypandstatuscallback(s32 chan,u32 type)233 static void __si_calltypandstatuscallback(s32 chan,u32 type)
234 {
235 	SICallback cb = NULL;
236 	u32 typ       = 0;
237 	while(typ<4) {
238 		cb = typeCallback[chan][typ];
239 		if(cb) {
240 			typeCallback[chan][typ] = NULL;
241 			cb(chan,type);
242 		}
243 		typ++;
244 	}
245 }
246 
__si_gettypecallback(s32 chan,u32 type)247 static void __si_gettypecallback(s32 chan,u32 type)
248 {
249 	u32 sipad_en,id;
250 
251 	si_type[chan] = (si_type[chan]&~SI_ERR_BUSY)|type;
252 	typeTime[chan] = gettime();
253 	sipad_en = __PADFixBits&SI_CHAN_BIT(chan);
254 	__PADFixBits &= ~SI_CHAN_BIT(chan);
255 
256 	if(type&0x0f || ((si_type[chan]&SI_TYPE_MASK)-SI_TYPE_GC)
257 		|| !(si_type[chan]&SI_GC_WIRELESS) || si_type[chan]&SI_WIRELESS_IR) {
258 		SYS_SetWirelessID(chan,0);
259 		__si_calltypandstatuscallback(chan,si_type[chan]);
260 		return;
261 	}
262 
263 	id = _SHIFTL(SYS_GetWirelessID(chan),8,16);
264 	if(sipad_en && id&SI_WIRELESS_FIX_ID) {
265 		cmdfixdevice[chan] = 0x4e100000|(id&0x00CFFF00);
266 		si_type[chan] = SI_ERR_BUSY;
267 		SI_Transfer(chan,&cmdfixdevice[chan],3,&si_type[chan],3,__si_gettypecallback,0);
268 		return;
269 	}
270 
271 	if(si_type[chan]&SI_WIRELESS_FIX_ID) {
272 		if((id&0x00CFFF00)==(si_type[chan]&0x00CFFF00)) goto exit;
273 		if(!(id&SI_WIRELESS_FIX_ID)) {
274 			id = SI_WIRELESS_FIX_ID|(si_type[chan]&0x00CFFF00);
275 			SYS_SetWirelessID(chan,_SHIFTR(id,8,16));
276 		}
277 		cmdfixdevice[chan] = 0x4e000000|id;
278 		si_type[chan] = SI_ERR_BUSY;
279 		SI_Transfer(chan,&cmdfixdevice[chan],3,&si_type[chan],3,__si_gettypecallback,0);
280 		return;
281 	}
282 
283 	if(si_type[chan]&SI_WIRELESS_RECEIVED) {
284 		id = SI_WIRELESS_FIX_ID|(si_type[chan]&0x00CFFF00);
285 		SYS_SetWirelessID(chan,_SHIFTR(id,8,16));
286 
287 		cmdfixdevice[chan] = 0x4e000000|id;
288 		si_type[chan] = SI_ERR_BUSY;
289 		SI_Transfer(chan,&cmdfixdevice[chan],3,&si_type[chan],3,__si_gettypecallback,0);
290 		return;
291 	}
292 	SYS_SetWirelessID(chan,0);
293 
294 exit:
295 	__si_calltypandstatuscallback(chan,si_type[chan]);
296 }
297 
__si_transfernext(u32 chan)298 static void __si_transfernext(u32 chan)
299 {
300 	u32 cnt;
301 	u64 now;
302 	s64 diff;
303 	cnt = 0;
304 	while(cnt<4) {
305 		chan++;
306 		chan %= 4;
307 		if(sipacket[chan].chan!=-1) {
308 			now = gettime();
309 			diff = (now - sipacket[chan].fire);
310 			if(diff>=0) {
311 				if(!__si_transfer(sipacket[chan].chan,sipacket[chan].out,sipacket[chan].out_bytes,sipacket[chan].in,sipacket[chan].in_bytes,sipacket[chan].callback)) break;
312 				SYS_CancelAlarm(si_alarm[chan]);
313 				sipacket[chan].chan = -1;
314 			}
315 		}
316 		cnt++;
317 	}
318 }
319 
__si_interrupthandler(u32 irq,void * ctx)320 static void __si_interrupthandler(u32 irq,void *ctx)
321 {
322 	SICallback cb;
323 	u32 chn,curr_line,line,ret;
324 	sicomcsr csr;
325 
326 	csr.val = _siReg[13];
327 	if(csr.csrmap.tcintmsk && csr.csrmap.tcint) {
328 		chn = sicntrl.chan;
329 		cb = sicntrl.callback;
330 		sicntrl.callback = NULL;
331 
332 		ret = __si_completetransfer();
333 		__si_transfernext(chn);
334 
335 		if(cb) cb(chn,ret);
336 
337 		_siReg[14] &= SISR_ERRORMASK(chn);
338 
339 		if(si_type[chn]==SI_ERR_BUSY && !SI_IsChanBusy(chn)) SI_Transfer(chn,&cmdtypeandstatus$47,1,&si_type[chn],3,__si_gettypecallback,65);
340 	}
341 
342 	if(csr.csrmap.rdstintmsk && csr.csrmap.rdstint) {
343 		curr_line = VIDEO_GetCurrentLine();
344 		curr_line++;
345 		line = _SHIFTR(sicntrl.poll,16,10);
346 
347 		chn = 0;
348 		while(chn<4) {
349 			if(SI_GetResponseRaw(chn)) inputBufferVCount[chn] = curr_line;
350 			chn++;
351 		}
352 
353 		chn = 0;
354 		while(chn<4) {
355 			if(sicntrl.poll&SIPOLL_ENABLE(chn)) {
356 				if(!inputBufferVCount[chn] || ((line>>1)+inputBufferVCount[chn])<curr_line) return;
357 			}
358 			chn++;
359 		}
360 
361 		chn = 0;
362 		while(chn<4) inputBufferVCount[chn++] = 0;
363 
364 		chn = 0;
365 		while(chn<4) {
366 			if(rdstHandlers[chn]) rdstHandlers[chn](irq,ctx);
367 			chn++;
368 		}
369 	}
370 }
371 
SI_Sync()372 u32 SI_Sync()
373 {
374 	u32 level,ret;
375 
376 	while(_siReg[13]&SICOMCSR_TSTART);
377 
378 	_CPU_ISR_Disable(level);
379 	ret = __si_completetransfer();
380 	__si_transfernext(4);
381 	_CPU_ISR_Restore(level);
382 
383 	return ret;
384 }
385 
SI_Busy()386 u32 SI_Busy()
387 {
388 	return (sicntrl.chan==-1)?0:1;
389 }
390 
SI_IsChanBusy(s32 chan)391 u32 SI_IsChanBusy(s32 chan)
392 {
393 	u32 ret = 0;
394 
395 	if(sipacket[chan].chan!=-1 || sicntrl.chan==chan) ret = 1;
396 
397 	return ret;
398 }
399 
SI_SetXY(u16 line,u8 cnt)400 void SI_SetXY(u16 line,u8 cnt)
401 {
402 	u32 level;
403 	_CPU_ISR_Disable(level);
404 	sicntrl.poll = (sicntrl.poll&~0x3ffff00)|_SHIFTL(line,16,10)|_SHIFTL(cnt,8,8);
405 	_siReg[12] = sicntrl.poll;
406 	_CPU_ISR_Restore(level);
407 }
408 
SI_EnablePolling(u32 poll)409 void SI_EnablePolling(u32 poll)
410 {
411 	u32 level,mask;
412 	_CPU_ISR_Disable(level);
413 	poll >>= 24;
414 	mask = (poll>>4)&0x0f;
415 	sicntrl.poll &= ~mask;
416 
417 	poll &= (0x03fffff0|mask);
418 
419 	sicntrl.poll |= (poll&~0x03ffff00);
420 	SI_TransferCommands();
421 	_siReg[12] = sicntrl.poll;
422 	_CPU_ISR_Restore(level);
423 }
424 
SI_DisablePolling(u32 poll)425 void SI_DisablePolling(u32 poll)
426 {
427 	u32 level,mask;
428 	_CPU_ISR_Disable(level);
429 	mask = (poll>>24)&0xf0;
430 	sicntrl.poll &= ~mask;
431 	_siReg[12] = sicntrl.poll;
432 	_CPU_ISR_Restore(level);
433 }
434 
SI_SetSamplingRate(u32 samplingrate)435 void SI_SetSamplingRate(u32 samplingrate)
436 {
437 	u32 div,level;
438 	struct _xy *xy = NULL;
439 
440 	if(samplingrate>11) samplingrate = 11;
441 
442 	_CPU_ISR_Disable(level);
443 	sampling_rate = samplingrate;
444 	xy = __si_getxy();
445 
446 	div = 1;
447 	if(_viReg[54]&0x0001) div = 2;
448 
449 	SI_SetXY(div*xy[samplingrate].line,xy[samplingrate].cnt);
450 	_CPU_ISR_Restore(level);
451 }
452 
SI_RefreshSamplingRate()453 void SI_RefreshSamplingRate()
454 {
455 	SI_SetSamplingRate(sampling_rate);
456 }
457 
SI_GetStatus(s32 chan)458 u32 SI_GetStatus(s32 chan)
459 {
460 	u32 level,sisr;
461 
462 	_CPU_ISR_Disable(level);
463 	sisr = (_siReg[14]>>((3-chan)<<3));
464 	if(sisr&SISR_NORESPONSE && !(si_type[chan]&SI_ERR_BUSY)) si_type[chan] = SI_ERROR_NO_RESPONSE;
465 	_CPU_ISR_Restore(level);
466 	return sisr;
467 }
468 
SI_GetResponseRaw(s32 chan)469 u32 SI_GetResponseRaw(s32 chan)
470 {
471 	u32 status,ret;
472 	ret = 0;
473 	status = SI_GetStatus(chan);
474 	if(status&SISR_RDST) {
475 		inputBuffer[chan][0] = _siReg[(chan*3)+1];
476 		inputBuffer[chan][1] = _siReg[(chan*3)+2];
477 		inputBufferValid[chan] = 1;
478 		ret = 1;
479 	}
480 	return ret;
481 }
482 
SI_GetResponse(s32 chan,void * buf)483 u32 SI_GetResponse(s32 chan,void *buf)
484 {
485 	u32 level,valid;
486 	_CPU_ISR_Disable(level);
487 	SI_GetResponseRaw(chan);
488 	valid = inputBufferValid[chan];
489 	inputBufferValid[chan] = 0;
490 	if(valid) {
491 		((u32*)buf)[0] = inputBuffer[chan][0];
492 		((u32*)buf)[1] = inputBuffer[chan][1];
493 	}
494 	_CPU_ISR_Restore(level);
495 	return valid;
496 }
497 
SI_SetCommand(s32 chan,u32 cmd)498 void SI_SetCommand(s32 chan,u32 cmd)
499 {
500 	_siReg[chan*3] = cmd;
501 }
502 
SI_GetCommand(s32 chan)503 u32 SI_GetCommand(s32 chan)
504 {
505 	return (_siReg[chan*3]);
506 }
507 
SI_Transfer(s32 chan,void * out,u32 out_len,void * in,u32 in_len,SICallback cb,u32 us_delay)508 u32 SI_Transfer(s32 chan,void *out,u32 out_len,void *in,u32 in_len,SICallback cb,u32 us_delay)
509 {
510 	u32 ret = 0;
511 	u32 level;
512 	s64 diff;
513 	u64 now,fire;
514 	struct timespec tb;
515 	_CPU_ISR_Disable(level);
516 	if(sipacket[chan].chan==-1 && sicntrl.chan!=chan) {
517 		ret = 1;
518 		fire = now = gettime();
519 		if(us_delay) fire = xferTime[chan]+microsecs_to_ticks(us_delay);
520 		diff = (now - fire);
521 		if(diff<0) {
522 			tb.tv_sec = 0;
523 			tb.tv_nsec = ticks_to_nanosecs((fire - now));
524 			SYS_SetAlarm(si_alarm[chan],&tb,__si_alarmhandler,NULL);
525 		} else if(__si_transfer(chan,out,out_len,in,in_len,cb)) {
526 			_CPU_ISR_Restore(level);
527 			return ret;
528 		}
529 		sipacket[chan].chan = chan;
530 		sipacket[chan].out = out;
531 		sipacket[chan].out_bytes = out_len;
532 		sipacket[chan].in = in;
533 		sipacket[chan].in_bytes = in_len;
534 		sipacket[chan].callback = cb;
535 		sipacket[chan].fire = fire;
536 	}
537 	_CPU_ISR_Restore(level);
538 	return ret;
539 }
540 
SI_GetType(s32 chan)541 u32 SI_GetType(s32 chan)
542 {
543 	u32 level,type;
544 	u64 now;
545 	s64 diff;
546 	_CPU_ISR_Disable(level);
547 	now = gettime();
548 	type = si_type[chan];
549 	diff = (now - typeTime[chan]);
550 	if(sicntrl.poll&(0x80>>chan)) {
551 		if(type!=SI_ERROR_NO_RESPONSE) {
552 			typeTime[chan] = gettime();
553 			_CPU_ISR_Restore(level);
554 			return type;
555 		}
556 		si_type[chan] = type = SI_ERR_BUSY;
557 	} else if(diff==millisecs_to_ticks(50) && type!=SI_ERROR_NO_RESPONSE) {
558 		_CPU_ISR_Restore(level);
559 		return type;
560 	} else if(diff==millisecs_to_ticks(75)) si_type[chan] = SI_ERR_BUSY;
561 	else si_type[chan] = type = SI_ERR_BUSY;
562 
563 	typeTime[chan] = gettime();
564 
565 	SI_Transfer(chan,&cmdtypeandstatus$223,1,&si_type[chan],3,__si_gettypecallback,65);
566 	_CPU_ISR_Restore(level);
567 
568 	return type;
569 }
570 
SI_GetTypeAsync(s32 chan,SICallback cb)571 u32 SI_GetTypeAsync(s32 chan,SICallback cb)
572 {
573 	u32 level;
574 	u32 type,i;
575 	_CPU_ISR_Disable(level);
576 	type = SI_GetType(chan);
577 	if(si_type[chan]&SI_ERR_BUSY) {
578 		i=0;
579 		for(i=0;i<4;i++) {
580 			if(!typeCallback[chan][i] && typeCallback[chan][i]!=cb) {
581 				typeCallback[chan][i] = cb;
582 				break;
583 			}
584 		}
585 		_CPU_ISR_Restore(level);
586 		return type;
587 	}
588 
589 	cb(chan,type);
590 	_CPU_ISR_Restore(level);
591 	return type;
592 }
593 
SI_TransferCommands()594 void SI_TransferCommands()
595 {
596 	_siReg[14] = 0x80000000;
597 }
598 
SI_RegisterPollingHandler(RDSTHandler handler)599 u32 SI_RegisterPollingHandler(RDSTHandler handler)
600 {
601 	u32 level,i;
602 
603 	_CPU_ISR_Disable(level);
604 
605 	i = 0;
606 	for(i=0;i<4;i++) {
607 		if(rdstHandlers[i]==handler) {
608 			_CPU_ISR_Restore(level);
609 			return 1;
610 		}
611 	}
612 
613 	for(i=0;i<4;i++) {
614 		if(rdstHandlers[i]==NULL) {
615 			rdstHandlers[i] = handler;
616 			SI_EnablePollingInterrupt(TRUE);
617 			_CPU_ISR_Restore(level);
618 			return 1;
619 		}
620 	}
621 
622 	_CPU_ISR_Restore(level);
623 	return 0;
624 }
625 
SI_UnregisterPollingHandler(RDSTHandler handler)626 u32 SI_UnregisterPollingHandler(RDSTHandler handler)
627 {
628 	u32 level,i;
629 
630 	_CPU_ISR_Disable(level);
631 	for(i=0;i<4;i++) {
632 		if(rdstHandlers[i]==handler) {
633 			rdstHandlers[i] = NULL;
634 			for(i=0;i<4;i++) {
635 				if(rdstHandlers[i]!=NULL) break;
636 			}
637 			if(i>=4) SI_EnablePollingInterrupt(FALSE);
638 
639 			_CPU_ISR_Restore(level);
640 			return 1;
641 		}
642 	}
643 	_CPU_ISR_Restore(level);
644 	return 0;
645 }
646 
SI_EnablePollingInterrupt(s32 enable)647 u32 SI_EnablePollingInterrupt(s32 enable)
648 {
649 	sicomcsr csr;
650 	u32 level,ret,i;
651 
652 	_CPU_ISR_Disable(level);
653 
654 	ret = 0;
655 	csr.val = _siReg[13];
656 	if(csr.csrmap.rdstintmsk) ret = 1;
657 
658 	if(enable) {
659 		csr.csrmap.rdstintmsk = 1;
660 		for(i=0;i<4;i++) inputBufferVCount[i] = 0;
661 	} else
662 		csr.csrmap.rdstintmsk = 0;
663 
664 	csr.val &= 0x7ffffffe;
665 	_siReg[13] = csr.val;
666 
667 	_CPU_ISR_Restore(level);
668 	return ret;
669 }
670 
__si_init()671 void __si_init()
672 {
673 	u32 i;
674 	for(i=0;i<4;i++) {
675 		sipacket[i].chan = -1;
676 		SYS_CreateAlarm(&si_alarm[i]);
677 	}
678 	sicntrl.poll = 0;
679 
680 	SI_SetSamplingRate(0);
681 	while(_siReg[13]&0x0001);
682 	_siReg[13] = 0x80000000;
683 
684 	_siReg[15] &= ~0x80000000;		// permit exi clock to be set to 32MHz
685 
686 	IRQ_Request(IRQ_PI_SI,__si_interrupthandler,NULL);
687 	__UnmaskIrq(IRQMASK(IRQ_PI_SI));
688 
689 	SI_GetType(0);
690 	SI_GetType(1);
691 	SI_GetType(2);
692 	SI_GetType(3);
693 }
694