1 /*-------------------------------------------------------------
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
36 #include "processor.h"
42 #define EXI_LOCK_DEVS 32
44 #define EXI_MAX_CHANNELS 3
45 #define EXI_MAX_DEVICES 3
47 #define EXI_DEVICE0 0x0080
48 #define EXI_DEVICE1 0x0100
49 #define EXI_DEVICE2 0x0200
51 #define EXI_EXI_IRQ 0x0002
52 #define EXI_TC_IRQ 0x0008
53 #define EXI_EXT_IRQ 0x0800
54 #define EXI_EXT_BIT 0x1000
56 #define _SHIFTL(v, s, w) \
57 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
58 #define _SHIFTR(v, s, w) \
59 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
68 typedef struct _exibus_priv
{
69 EXICallback CallbackEXI
;
70 EXICallback CallbackTC
;
71 EXICallback CallbackEXT
;
84 static lwp_queue _lckdev_queue
;
85 static struct _lck_dev lckdevs
[EXI_LOCK_DEVS
];
86 static exibus_priv eximap
[EXI_MAX_CHANNELS
];
87 static u64 last_exi_idtime
[EXI_MAX_CHANNELS
];
89 static u32 exi_id_serport1
= 0;
91 static u32 exi_uart_chan
= EXI_CHANNEL_0
;
92 static u32 exi_uart_dev
= EXI_DEVICE_0
;
93 static u32 exi_uart_barnacle_enabled
= 0;
94 static u32 exi_uart_enabled
= 0;
96 static void __exi_irq_handler(u32
,void *);
97 static void __tc_irq_handler(u32
,void *);
98 static void __ext_irq_handler(u32
,void *);
101 static vu32
* const _exiReg
= (u32
*)0xCC006800;
102 #elif defined(HW_RVL)
103 static vu32
* const _exiReg
= (u32
*)0xCD006800;
105 #error HW model unknown.
108 static __inline__
void __exi_clearirqs(s32 nChn
,u32 nEXIIrq
,u32 nTCIrq
,u32 nEXTIrq
)
112 printf("__exi_clearirqs(%d,%d,%d,%d)\n",nChn
,nEXIIrq
,nTCIrq
,nEXTIrq
);
114 d
= (_exiReg
[nChn
*5]&~(EXI_EXI_IRQ
|EXI_TC_IRQ
|EXI_EXT_IRQ
));
115 if(nEXIIrq
) d
|= EXI_EXI_IRQ
;
116 if(nTCIrq
) d
|= EXI_TC_IRQ
;
117 if(nEXTIrq
) d
|= EXI_EXT_IRQ
;
121 static __inline__
void __exi_setinterrupts(s32 nChn
,exibus_priv
*exi
)
123 exibus_priv
*pexi
= &eximap
[EXI_CHANNEL_2
];
125 printf("__exi_setinterrupts(%d,%p)\n",nChn
,exi
);
127 if(nChn
==EXI_CHANNEL_0
) {
128 __MaskIrq((IRQMASK(IRQ_EXI0_EXI
)|IRQMASK(IRQ_EXI2_EXI
)));
129 if(!(exi
->flags
&EXI_FLAG_LOCKED
) && (exi
->CallbackEXI
|| pexi
->CallbackEXI
))
130 __UnmaskIrq((IRQMASK(IRQ_EXI0_EXI
)|IRQMASK(IRQ_EXI2_EXI
)));
131 } else if(nChn
==EXI_CHANNEL_1
) {
132 __MaskIrq(IRQMASK(IRQ_EXI1_EXI
));
133 if(!(exi
->flags
&EXI_FLAG_LOCKED
) && exi
->CallbackEXI
) __UnmaskIrq(IRQMASK(IRQ_EXI1_EXI
));
134 } else if(nChn
==EXI_CHANNEL_2
) { //explicitly use of channel 2 only if debugger is attached.
135 __MaskIrq(IRQMASK(IRQ_EXI0_EXI
));
136 if(!(exi
->flags
&EXI_FLAG_LOCKED
) && IRQ_GetHandler(IRQ_PI_DEBUG
)) __UnmaskIrq(IRQMASK(IRQ_EXI2_EXI
));
140 static void __exi_initmap(exibus_priv
*exim
)
145 __lwp_queue_initialize(&_lckdev_queue
,lckdevs
,EXI_LOCK_DEVS
,sizeof(struct _lck_dev
));
147 for(i
=0;i
<EXI_MAX_CHANNELS
;i
++) {
149 m
->CallbackEXI
= NULL
;
150 m
->CallbackEXT
= NULL
;
151 m
->CallbackTC
= NULL
;
159 m
->lckd_dev_bits
= 0;
160 __lwp_queue_init_empty(&m
->lckd_dev
);
164 static s32
__exi_probe(s32 nChn
)
170 exibus_priv
*exi
= &eximap
[nChn
];
172 printf("__exi_probe(%d)\n",nChn
);
174 _CPU_ISR_Disable(level
);
175 val
= _exiReg
[nChn
*5];
176 if(!(exi
->flags
&EXI_FLAG_ATTACH
)) {
177 if(val
&EXI_EXT_IRQ
) {
178 __exi_clearirqs(nChn
,0,0,1);
180 last_exi_idtime
[nChn
] = 0;
182 if(_exiReg
[nChn
*5]&EXI_EXT_BIT
) {
184 if(last_exi_idtime
[nChn
]==0) last_exi_idtime
[nChn
] = time
;
185 if((val
=diff_usec(last_exi_idtime
[nChn
],time
)+10)<30) ret
= 0;
188 printf("val = %u, ret = %d, last_exi_idtime[chn] = %llu\n",val
,ret
,last_exi_idtime
[nChn
]);
190 _CPU_ISR_Restore(level
);
194 last_exi_idtime
[nChn
] = 0;
195 _CPU_ISR_Restore(level
);
200 if(!(_exiReg
[nChn
*5]&EXI_EXT_BIT
) || (_exiReg
[nChn
*5]&EXI_EXT_IRQ
)) {
202 last_exi_idtime
[nChn
] = 0;
205 _CPU_ISR_Restore(level
);
209 static s32
__exi_attach(s32 nChn
,EXICallback ext_cb
)
213 exibus_priv
*exi
= &eximap
[nChn
];
215 printf("__exi_attach(%d,%p)\n",nChn
,ext_cb
);
217 _CPU_ISR_Disable(level
);
219 if(!(exi
->flags
&EXI_FLAG_ATTACH
)) {
220 if(__exi_probe(nChn
)==1) {
221 __exi_clearirqs(nChn
,1,0,0);
222 exi
->CallbackEXT
= ext_cb
;
223 __UnmaskIrq(((IRQMASK(IRQ_EXI0_EXT
))>>(nChn
*3)));
224 exi
->flags
|= EXI_FLAG_ATTACH
;
228 _CPU_ISR_Restore(level
);
232 s32
EXI_Lock(s32 nChn
,s32 nDev
,EXICallback unlockCB
)
235 struct _lck_dev
*lckd
;
236 exibus_priv
*exi
= &eximap
[nChn
];
238 printf("EXI_Lock(%d,%d,%p)\n",nChn
,nDev
,unlockCB
);
240 _CPU_ISR_Disable(level
);
241 if(exi
->flags
&EXI_FLAG_LOCKED
) {
242 if(unlockCB
&& !(exi
->lckd_dev_bits
&(1<<nDev
))) {
243 lckd
= (struct _lck_dev
*)__lwp_queue_getI(&_lckdev_queue
);
246 exi
->lckd_dev_bits
|= (1<<nDev
);
248 lckd
->unlockcb
= unlockCB
;
249 __lwp_queue_appendI(&exi
->lckd_dev
,&lckd
->node
);
252 _CPU_ISR_Restore(level
);
256 exi
->lockeddev
= nDev
;
257 exi
->flags
|= EXI_FLAG_LOCKED
;
258 __exi_setinterrupts(nChn
,exi
);
260 _CPU_ISR_Restore(level
);
264 s32
EXI_Unlock(s32 nChn
)
268 struct _lck_dev
*lckd
;
269 exibus_priv
*exi
= &eximap
[nChn
];
271 printf("EXI_Unlock(%d)\n",nChn
);
273 _CPU_ISR_Disable(level
);
274 if(!(exi
->flags
&EXI_FLAG_LOCKED
)) {
275 _CPU_ISR_Restore(level
);
279 exi
->flags
&= ~EXI_FLAG_LOCKED
;
280 __exi_setinterrupts(nChn
,exi
);
283 _CPU_ISR_Restore(level
);
288 lckd
= (struct _lck_dev
*)__lwp_queue_getI(&exi
->lckd_dev
);
289 __lwp_queue_appendI(&_lckdev_queue
,&lckd
->node
);
293 exi
->lckd_dev_bits
&= ~(1<<dev
);
296 _CPU_ISR_Restore(level
);
300 s32
EXI_Select(s32 nChn
,s32 nDev
,s32 nFrq
)
304 exibus_priv
*exi
= &eximap
[nChn
];
306 printf("EXI_Select(%d,%d,%d)\n",nChn
,nDev
,nFrq
);
308 _CPU_ISR_Disable(level
);
310 if(exi
->flags
&EXI_FLAG_SELECT
) {
312 printf("EXI_Select(): allready selected.\n");
314 _CPU_ISR_Restore(level
);
318 if(nChn
!=EXI_CHANNEL_2
) {
319 if(nDev
==EXI_DEVICE_0
&& !(exi
->flags
&EXI_FLAG_ATTACH
)) {
320 if(__exi_probe(nChn
)==0) {
321 _CPU_ISR_Restore(level
);
325 if(!(exi
->flags
&EXI_FLAG_LOCKED
) || exi
->lockeddev
!=nDev
) {
327 printf("EXI_Select(): not locked or wrong dev(%d).\n",exi
->lockeddev
);
329 _CPU_ISR_Restore(level
);
334 exi
->flags
|= EXI_FLAG_SELECT
;
335 val
= _exiReg
[nChn
*5];
336 val
= (val
&0x405)|(0x80<<nDev
)|(nFrq
<<4);
337 _exiReg
[nChn
*5] = val
;
339 if(exi
->flags
&EXI_FLAG_ATTACH
) {
340 if(nChn
==EXI_CHANNEL_0
) __MaskIrq(IRQMASK(IRQ_EXI0_EXT
));
341 else if(nChn
==EXI_CHANNEL_1
) __MaskIrq(IRQMASK(IRQ_EXI1_EXT
));
344 _CPU_ISR_Restore(level
);
348 s32
EXI_SelectSD(s32 nChn
,s32 nDev
,s32 nFrq
)
353 exibus_priv
*exi
= &eximap
[nChn
];
355 printf("EXI_SelectSD(%d,%d,%d)\n",nChn
,nDev
,nFrq
);
357 _CPU_ISR_Disable(level
);
359 if(exi
->flags
&EXI_FLAG_SELECT
) {
361 printf("EXI_SelectSD(): allready selected.\n");
363 _CPU_ISR_Restore(level
);
367 if(nChn
!=EXI_CHANNEL_2
) {
368 if(nDev
==EXI_DEVICE_0
&& !(exi
->flags
&EXI_FLAG_ATTACH
)) {
369 if((ret
=__exi_probe(nChn
))==1) {
370 if(!exi
->exi_idtime
) ret
= EXI_GetID(nChn
,EXI_DEVICE_0
,&id
);
373 _CPU_ISR_Restore(level
);
377 if(!(exi
->flags
&EXI_FLAG_LOCKED
) || exi
->lockeddev
!=nDev
) {
379 printf("EXI_SelectSD(): not locked or wrong dev(%d).\n",exi
->lockeddev
);
381 _CPU_ISR_Restore(level
);
386 exi
->flags
|= EXI_FLAG_SELECT
;
387 val
= _exiReg
[nChn
*5];
388 val
= (val
&0x405)|(nFrq
<<4);
389 _exiReg
[nChn
*5] = val
;
391 if(exi
->flags
&EXI_FLAG_ATTACH
) {
392 if(nChn
==EXI_CHANNEL_0
) __MaskIrq(IRQMASK(IRQ_EXI0_EXT
));
393 else if(nChn
==EXI_CHANNEL_1
) __MaskIrq(IRQMASK(IRQ_EXI1_EXT
));
396 _CPU_ISR_Restore(level
);
400 s32
EXI_Deselect(s32 nChn
)
404 exibus_priv
*exi
= &eximap
[nChn
];
406 printf("EXI_Deselect(%d)\n",nChn
);
408 _CPU_ISR_Disable(level
);
410 if(!(exi
->flags
&EXI_FLAG_SELECT
)) {
411 _CPU_ISR_Restore(level
);
415 exi
->flags
&= ~EXI_FLAG_SELECT
;
416 val
= _exiReg
[nChn
*5];
417 _exiReg
[nChn
*5] = (val
&0x405);
419 if(exi
->flags
&EXI_FLAG_ATTACH
) {
420 if(nChn
==EXI_CHANNEL_0
) __UnmaskIrq(IRQMASK(IRQ_EXI0_EXT
));
421 else if(nChn
==EXI_CHANNEL_1
) __UnmaskIrq(IRQMASK(IRQ_EXI1_EXT
));
424 if(nChn
!=EXI_CHANNEL_2
&& val
&EXI_DEVICE0
) {
425 if(__exi_probe(nChn
)==0) {
426 _CPU_ISR_Restore(level
);
430 _CPU_ISR_Restore(level
);
434 s32
EXI_Sync(s32 nChn
)
439 exibus_priv
*exi
= &eximap
[nChn
];
441 printf("EXI_Sync(%d)\n",nChn
);
443 while(_exiReg
[nChn
*5+3]&0x0001);
445 _CPU_ISR_Disable(level
);
448 if(exi
->flags
&EXI_FLAG_SELECT
&& exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
)) {
449 if(exi
->flags
&EXI_FLAG_IMM
) {
453 val
= _exiReg
[nChn
*5+4];
454 for(i
=0;i
<cnt
;i
++) ((u8
*)buf
)[i
] = (val
>>((3-i
)*8))&0xFF;
457 exi
->flags
&= ~(EXI_FLAG_DMA
|EXI_FLAG_IMM
);
460 _CPU_ISR_Restore(level
);
464 s32
EXI_Imm(s32 nChn
,void *pData
,u32 nLen
,u32 nMode
,EXICallback tc_cb
)
468 exibus_priv
*exi
= &eximap
[nChn
];
470 printf("EXI_Imm(%d,%p,%d,%d,%p)\n",nChn
,pData
,nLen
,nMode
,tc_cb
);
472 _CPU_ISR_Disable(level
);
474 if(exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
) || !(exi
->flags
&EXI_FLAG_SELECT
)) {
475 _CPU_ISR_Restore(level
);
479 exi
->CallbackTC
= tc_cb
;
481 __exi_clearirqs(nChn
,0,1,0);
482 __UnmaskIrq(IRQMASK((IRQ_EXI0_TC
+(nChn
*3))));
484 exi
->flags
|= EXI_FLAG_IMM
;
486 exi
->imm_buff
= pData
;
488 if(nMode
!=EXI_READ
) {
489 for(i
=0,value
=0;i
<nLen
;i
++) value
|= (((u8
*)pData
)[i
])<<((3-i
)*8);
490 _exiReg
[nChn
*5+4] = value
;
492 if(nMode
==EXI_WRITE
) exi
->imm_len
= 0;
494 _exiReg
[nChn
*5+3] = (((nLen
-1)&0x03)<<4)|((nMode
&0x03)<<2)|0x01;
496 _CPU_ISR_Restore(level
);
500 s32
EXI_ImmEx(s32 nChn
,void *pData
,u32 nLen
,u32 nMode
)
506 printf("EXI_ImmEx(%d,%p,%d,%d)\n",nChn
,pData
,nLen
,nMode
);
513 if(!EXI_Imm(nChn
,buf
,tc
,nMode
,NULL
)) break;
514 if(!EXI_Sync(nChn
)) break;
523 s32
EXI_Dma(s32 nChn
,void *pData
,u32 nLen
,u32 nMode
,EXICallback tc_cb
)
526 exibus_priv
*exi
= &eximap
[nChn
];
528 printf("EXI_Dma(%d,%p,%d,%d,%p)\n",nChn
,pData
,nLen
,nMode
,tc_cb
);
530 _CPU_ISR_Disable(level
);
532 if(exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
) || !(exi
->flags
&EXI_FLAG_SELECT
)) {
534 printf("EXI_Dma(%04x): abort\n",exi
->flags
);
536 _CPU_ISR_Restore(level
);
540 printf("EXI_Dma(tccb: %p)\n",tc_cb
);
542 exi
->CallbackTC
= tc_cb
;
544 __exi_clearirqs(nChn
,0,1,0);
545 __UnmaskIrq((IRQMASK((IRQ_EXI0_TC
+(nChn
*3)))));
548 exi
->imm_buff
= NULL
;
550 exi
->flags
|= EXI_FLAG_DMA
;
552 _exiReg
[nChn
*5+1] = (u32
)pData
&0x03FFFFE0;
553 _exiReg
[nChn
*5+2] = nLen
;
554 _exiReg
[nChn
*5+3] = ((nMode
&0x03)<<2)|0x03;
556 _CPU_ISR_Restore(level
);
560 s32
EXI_GetState(s32 nChn
)
562 exibus_priv
*exi
= &eximap
[nChn
];
566 static s32
__unlocked_handler(s32 nChn
,s32 nDev
)
570 printf("__unlocked_handler(%d,%d)\n",nChn
,nDev
);
572 EXI_GetID(nChn
,nDev
,&nId
);
576 s32
EXI_GetID(s32 nChn
,s32 nDev
,u32
*nId
)
581 exibus_priv
*exi
= &eximap
[nChn
];
584 printf("EXI_GetID(exi_id = %d)\n",exi
->exi_id
);
586 if(nChn
<EXI_CHANNEL_2
&& nDev
==EXI_DEVICE_0
) {
587 if(__exi_probe(nChn
)==0) return 0;
588 if(exi
->exi_idtime
==last_exi_idtime
[nChn
]) {
590 printf("EXI_GetID(exi_id = %d)\n",exi
->exi_id
);
596 printf("EXI_GetID(setting interrupts,%08x)\n",exi
->flags
);
598 if(__exi_attach(nChn
,NULL
)==0) return 0;
599 idtime
= last_exi_idtime
[nChn
];
602 printf("EXI_GetID(interrupts set)\n");
605 if(nChn
<EXI_CHANNEL_2
&& nDev
==EXI_DEVICE_0
) lck
= 1;
607 if(lck
) ret
= EXI_Lock(nChn
,nDev
,__unlocked_handler
);
608 else ret
= EXI_Lock(nChn
,nDev
,NULL
);
611 if(EXI_Select(nChn
,nDev
,EXI_SPEED1MHZ
)==1) {
613 EXI_Imm(nChn
,®
,2,EXI_WRITE
,NULL
);
615 EXI_Imm(nChn
,nId
,4,EXI_READ
,NULL
);
622 if(nChn
<EXI_CHANNEL_2
&& nDev
==EXI_DEVICE_0
) {
626 _CPU_ISR_Disable(level
);
627 if(idtime
==last_exi_idtime
[nChn
]) {
628 exi
->exi_idtime
= idtime
;
632 _CPU_ISR_Restore(level
);
634 printf("EXI_GetID(exi_id = %d)\n",exi
->exi_id
);
640 s32
EXI_Attach(s32 nChn
,EXICallback ext_cb
)
644 exibus_priv
*exi
= &eximap
[nChn
];
646 printf("EXI_Attach(%d)\n",nChn
);
650 _CPU_ISR_Disable(level
);
651 if(exi
->exi_idtime
) {
652 ret
= __exi_attach(nChn
,ext_cb
);
655 _CPU_ISR_Restore(level
);
659 s32
EXI_Detach(s32 nChn
)
663 exibus_priv
*exi
= &eximap
[nChn
];
665 printf("EXI_Detach(%d)\n",nChn
);
667 _CPU_ISR_Disable(level
);
668 if(exi
->flags
&EXI_FLAG_ATTACH
) {
669 if(exi
->flags
&EXI_FLAG_LOCKED
&& exi
->lockeddev
!=EXI_DEVICE_0
) ret
= 0;
671 exi
->flags
&= ~EXI_FLAG_ATTACH
;
672 __MaskIrq(((IRQMASK(IRQ_EXI0_EXI
)|IRQMASK(IRQ_EXI0_TC
)|IRQMASK(IRQ_EXI0_EXT
))>>(nChn
*3)));
675 _CPU_ISR_Restore(level
);
679 EXICallback
EXI_RegisterEXICallback(s32 nChn
,EXICallback exi_cb
)
682 EXICallback old
= NULL
;
683 exibus_priv
*exi
= &eximap
[nChn
];
685 printf("EXI_RegisterEXICallback(%d,%p)\n",nChn
,exi_cb
);
687 _CPU_ISR_Disable(level
);
688 old
= exi
->CallbackEXI
;
689 exi
->CallbackEXI
= exi_cb
;
690 if(nChn
==EXI_CHANNEL_2
) __exi_setinterrupts(EXI_CHANNEL_0
,&eximap
[EXI_CHANNEL_0
]);
691 else __exi_setinterrupts(nChn
,exi
);
692 _CPU_ISR_Restore(level
);
696 s32
EXI_Probe(s32 nChn
)
700 exibus_priv
*exi
= &eximap
[nChn
];
702 printf("EXI_Probe(%d)\n",nChn
);
704 if((ret
=__exi_probe(nChn
))==1) {
705 if(exi
->exi_idtime
==0) {
706 if(EXI_GetID(nChn
,EXI_DEVICE_0
,&id
)==0) ret
= 0;
712 s32
EXI_ProbeEx(s32 nChn
)
714 if(EXI_Probe(nChn
)==1) return 1;
715 if(last_exi_idtime
[nChn
]==0) return -1;
719 void EXI_ProbeReset()
721 last_exi_idtime
[0] = 0;
722 last_exi_idtime
[1] = 0;
724 eximap
[0].exi_idtime
= 0;
725 eximap
[1].exi_idtime
= 0;
729 EXI_GetID(EXI_CHANNEL_0
,EXI_DEVICE_2
,&exi_id_serport1
);
735 printf("__exi_init(): init expansion system.\n");
745 __exi_initmap(eximap
);
747 IRQ_Request(IRQ_EXI0_EXI
,__exi_irq_handler
,NULL
);
748 IRQ_Request(IRQ_EXI0_TC
,__tc_irq_handler
,NULL
);
749 IRQ_Request(IRQ_EXI0_EXT
,__ext_irq_handler
,NULL
);
750 IRQ_Request(IRQ_EXI1_EXI
,__exi_irq_handler
,NULL
);
751 IRQ_Request(IRQ_EXI1_TC
,__tc_irq_handler
,NULL
);
752 IRQ_Request(IRQ_EXI1_EXT
,__ext_irq_handler
,NULL
);
753 IRQ_Request(IRQ_EXI2_EXI
,__exi_irq_handler
,NULL
);
754 IRQ_Request(IRQ_EXI2_TC
,__tc_irq_handler
,NULL
);
759 void __exi_irq_handler(u32 nIrq
,void *pCtx
)
762 exibus_priv
*exi
= NULL
;
763 const u32 fact
= 0x55555556;
765 chan
= ((fact
*(nIrq
-IRQ_EXI0_EXI
))>>1)&0x0f;
766 dev
= _SHIFTR((_exiReg
[chan
*5]&0x380),8,2);
769 __exi_clearirqs(chan
,1,0,0);
771 if(!exi
->CallbackEXI
) return;
773 printf("__exi_irq_handler(%p)\n",exi
->CallbackEXI
);
775 exi
->CallbackEXI(chan
,dev
);
778 void __tc_irq_handler(u32 nIrq
,void *pCtx
)
780 u32 cnt
,len
,d
,chan
,dev
;
783 exibus_priv
*exi
= NULL
;
784 const u32 fact
= 0x55555556;
786 chan
= ((fact
*(nIrq
-IRQ_EXI0_TC
))>>1)&0x0f;
787 dev
= _SHIFTR((_exiReg
[chan
*5]&0x380),8,2);
790 __MaskIrq(IRQMASK(nIrq
));
791 __exi_clearirqs(chan
,0,1,0);
793 tccb
= exi
->CallbackTC
;
795 printf("__tc_irq_handler(%p)\n",tccb
);
799 exi
->CallbackTC
= NULL
;
800 if(exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
)) {
801 if(exi
->flags
&EXI_FLAG_IMM
) {
805 d
= _exiReg
[chan
*5+4];
807 for(cnt
=0;cnt
<len
;cnt
++) ((u8
*)buf
)[cnt
] = (d
>>((3-cnt
)*8))&0xFF;
811 exi
->flags
&= ~(EXI_FLAG_DMA
|EXI_FLAG_IMM
);
816 void __ext_irq_handler(u32 nIrq
,void *pCtx
)
820 exibus_priv
*exi
= NULL
;
821 const u32 fact
= 0x55555556;
823 chan
= ((fact
*(nIrq
-IRQ_EXI0_EXT
))>>1)&0x0f;
824 dev
= _SHIFTR((_exiReg
[chan
*5]&0x380),8,2);
827 __MaskIrq(IRQMASK(nIrq
));
828 __exi_clearirqs(chan
,0,0,1);
830 exi
->flags
&= ~EXI_FLAG_ATTACH
;
831 if(exi
->CallbackEXT
) exi
->CallbackEXT(chan
,dev
);
833 printf("__ext_irq_handler(%p)\n",exi
->CallbackEXT
);
839 static s32
__probebarnacle(s32 chn
,u32 dev
,u32
*rev
)
843 if(chn
!=EXI_CHANNEL_2
&& dev
==EXI_DEVICE_0
) {
844 if(EXI_Attach(chn
,NULL
)==0) return 0;
848 if(EXI_Lock(chn
,dev
,NULL
)==1) {
849 if(EXI_Select(chn
,dev
,EXI_SPEED1MHZ
)==1) {
851 if(EXI_Imm(chn
,®
,sizeof(u32
),EXI_WRITE
,NULL
)==0) ret
|= 0x0001;
852 if(EXI_Sync(chn
)==0) ret
|= 0x0002;
853 if(EXI_Imm(chn
,rev
,sizeof(u32
),EXI_READ
,NULL
)==0) ret
|= 0x0004;
854 if(EXI_Sync(chn
)==0) ret
|= 0x0008;
855 if(EXI_Deselect(chn
)==0) ret
|= 0x0010;
861 if(chn
!=EXI_CHANNEL_2
&& dev
==EXI_DEVICE_0
) EXI_Detach(chn
);
864 if((*rev
+0x00010000)==0xffff) return 0;
869 static s32
__queuelength()
874 if(EXI_Select(exi_uart_chan
,exi_uart_dev
,EXI_SPEED8MHZ
)==0) return -1;
877 EXI_Imm(exi_uart_chan
,®
,sizeof(u32
),EXI_WRITE
,NULL
);
878 EXI_Sync(exi_uart_chan
);
879 EXI_Imm(exi_uart_chan
,&len
,sizeof(u8
),EXI_READ
,NULL
);
880 EXI_Sync(exi_uart_chan
);
882 EXI_Deselect(exi_uart_chan
);
887 void __SYS_EnableBarnacle(s32 chn
,u32 dev
)
891 if(EXI_GetID(chn
,dev
,&id
)==0) return;
893 if(id
==0x01020000 || id
==0x0004 || id
==0x80000010 || id
==0x80000008
894 || id
==0x80000004 || id
==0xffff || id
==0x80000020 || id
==0x0020
895 || id
==0x0010 || id
==0x0008 || id
==0x01010000 || id
==0x04040404
896 || id
==0x04021000 || id
==0x03010000 || id
==0x02020000
897 || id
==0x04020300 || id
==0x04020200 || id
==0x04130000
898 || id
==0x04120000 || id
==0x04060000 || id
==0x04220000) return;
900 if(__probebarnacle(chn
,dev
,&rev
)==0) return;
905 exi_uart_barnacle_enabled
= 0xa5ff005a;
906 exi_uart_enabled
= 0xa5ff005a;
911 if((exi_uart_enabled
+0x5a010000)==0x005a) return 0;
913 exi_uart_chan
= EXI_CHANNEL_0
;
914 exi_uart_dev
= EXI_DEVICE_1
;
916 exi_uart_enabled
= 0xa5ff005a;
920 s32
WriteUARTN(void *buf
,u32 len
)
926 if((exi_uart_enabled
+0x5a010000)!=0x005a) return 2;
927 if(EXI_Lock(exi_uart_chan
,exi_uart_dev
,NULL
)==0) return 0;
930 while((ptr
-(u8
*)buf
)<len
) {
931 if(*ptr
=='\n') *ptr
= '\r';
938 if((qlen
=__queuelength())<0) {
941 } else if(qlen
>=12 || qlen
>=len
) {
942 if(EXI_Select(exi_uart_chan
,exi_uart_dev
,EXI_SPEED8MHZ
)==0) {
948 EXI_Imm(exi_uart_chan
,®
,sizeof(u32
),EXI_WRITE
,NULL
);
949 EXI_Sync(exi_uart_chan
);
951 while(qlen
>0 && len
>0) {
957 EXI_Imm(exi_uart_chan
,ptr
,cnt
,EXI_WRITE
,NULL
);
958 EXI_Sync(exi_uart_chan
);
965 EXI_Deselect(exi_uart_chan
);
968 EXI_Unlock(exi_uart_chan
);