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 extern void __UnmaskIrq(u32
);
109 extern void __MaskIrq(u32
);
111 static __inline__
void __exi_clearirqs(s32 nChn
,u32 nEXIIrq
,u32 nTCIrq
,u32 nEXTIrq
)
115 printf("__exi_clearirqs(%d,%d,%d,%d)\n",nChn
,nEXIIrq
,nTCIrq
,nEXTIrq
);
117 d
= (_exiReg
[nChn
*5]&~(EXI_EXI_IRQ
|EXI_TC_IRQ
|EXI_EXT_IRQ
));
118 if(nEXIIrq
) d
|= EXI_EXI_IRQ
;
119 if(nTCIrq
) d
|= EXI_TC_IRQ
;
120 if(nEXTIrq
) d
|= EXI_EXT_IRQ
;
124 static __inline__
void __exi_setinterrupts(s32 nChn
,exibus_priv
*exi
)
126 exibus_priv
*pexi
= &eximap
[EXI_CHANNEL_2
];
128 printf("__exi_setinterrupts(%d,%p)\n",nChn
,exi
);
130 if(nChn
==EXI_CHANNEL_0
) {
131 __MaskIrq((IRQMASK(IRQ_EXI0_EXI
)|IRQMASK(IRQ_EXI2_EXI
)));
132 if(!(exi
->flags
&EXI_FLAG_LOCKED
) && (exi
->CallbackEXI
|| pexi
->CallbackEXI
))
133 __UnmaskIrq((IRQMASK(IRQ_EXI0_EXI
)|IRQMASK(IRQ_EXI2_EXI
)));
134 } else if(nChn
==EXI_CHANNEL_1
) {
135 __MaskIrq(IRQMASK(IRQ_EXI1_EXI
));
136 if(!(exi
->flags
&EXI_FLAG_LOCKED
) && exi
->CallbackEXI
) __UnmaskIrq(IRQMASK(IRQ_EXI1_EXI
));
137 } else if(nChn
==EXI_CHANNEL_2
) { //explicitly use of channel 2 only if debugger is attached.
138 __MaskIrq(IRQMASK(IRQ_EXI0_EXI
));
139 if(!(exi
->flags
&EXI_FLAG_LOCKED
) && IRQ_GetHandler(IRQ_PI_DEBUG
)) __UnmaskIrq(IRQMASK(IRQ_EXI2_EXI
));
143 static void __exi_initmap(exibus_priv
*exim
)
148 __lwp_queue_initialize(&_lckdev_queue
,lckdevs
,EXI_LOCK_DEVS
,sizeof(struct _lck_dev
));
150 for(i
=0;i
<EXI_MAX_CHANNELS
;i
++) {
152 m
->CallbackEXI
= NULL
;
153 m
->CallbackEXT
= NULL
;
154 m
->CallbackTC
= NULL
;
162 m
->lckd_dev_bits
= 0;
163 __lwp_queue_init_empty(&m
->lckd_dev
);
167 static s32
__exi_probe(s32 nChn
)
173 exibus_priv
*exi
= &eximap
[nChn
];
175 printf("__exi_probe(%d)\n",nChn
);
177 _CPU_ISR_Disable(level
);
178 val
= _exiReg
[nChn
*5];
179 if(!(exi
->flags
&EXI_FLAG_ATTACH
)) {
180 if(val
&EXI_EXT_IRQ
) {
181 __exi_clearirqs(nChn
,0,0,1);
183 last_exi_idtime
[nChn
] = 0;
185 if(_exiReg
[nChn
*5]&EXI_EXT_BIT
) {
187 if(last_exi_idtime
[nChn
]==0) last_exi_idtime
[nChn
] = time
;
188 if((val
=diff_usec(last_exi_idtime
[nChn
],time
)+10)<30) ret
= 0;
191 printf("val = %u, ret = %d, last_exi_idtime[chn] = %llu\n",val
,ret
,last_exi_idtime
[nChn
]);
193 _CPU_ISR_Restore(level
);
197 last_exi_idtime
[nChn
] = 0;
198 _CPU_ISR_Restore(level
);
203 if(!(_exiReg
[nChn
*5]&EXI_EXT_BIT
) || (_exiReg
[nChn
*5]&EXI_EXT_IRQ
)) {
205 last_exi_idtime
[nChn
] = 0;
208 _CPU_ISR_Restore(level
);
212 static s32
__exi_attach(s32 nChn
,EXICallback ext_cb
)
216 exibus_priv
*exi
= &eximap
[nChn
];
218 printf("__exi_attach(%d,%p)\n",nChn
,ext_cb
);
220 _CPU_ISR_Disable(level
);
222 if(!(exi
->flags
&EXI_FLAG_ATTACH
)) {
223 if(__exi_probe(nChn
)==1) {
224 __exi_clearirqs(nChn
,1,0,0);
225 exi
->CallbackEXT
= ext_cb
;
226 __UnmaskIrq(((IRQMASK(IRQ_EXI0_EXT
))>>(nChn
*3)));
227 exi
->flags
|= EXI_FLAG_ATTACH
;
231 _CPU_ISR_Restore(level
);
235 s32
EXI_Lock(s32 nChn
,s32 nDev
,EXICallback unlockCB
)
238 struct _lck_dev
*lckd
;
239 exibus_priv
*exi
= &eximap
[nChn
];
241 printf("EXI_Lock(%d,%d,%p)\n",nChn
,nDev
,unlockCB
);
243 _CPU_ISR_Disable(level
);
244 if(exi
->flags
&EXI_FLAG_LOCKED
) {
245 if(unlockCB
&& !(exi
->lckd_dev_bits
&(1<<nDev
))) {
246 lckd
= (struct _lck_dev
*)__lwp_queue_getI(&_lckdev_queue
);
249 exi
->lckd_dev_bits
|= (1<<nDev
);
251 lckd
->unlockcb
= unlockCB
;
252 __lwp_queue_appendI(&exi
->lckd_dev
,&lckd
->node
);
255 _CPU_ISR_Restore(level
);
259 exi
->lockeddev
= nDev
;
260 exi
->flags
|= EXI_FLAG_LOCKED
;
261 __exi_setinterrupts(nChn
,exi
);
263 _CPU_ISR_Restore(level
);
267 s32
EXI_Unlock(s32 nChn
)
271 struct _lck_dev
*lckd
;
272 exibus_priv
*exi
= &eximap
[nChn
];
274 printf("EXI_Unlock(%d)\n",nChn
);
276 _CPU_ISR_Disable(level
);
277 if(!(exi
->flags
&EXI_FLAG_LOCKED
)) {
278 _CPU_ISR_Restore(level
);
282 exi
->flags
&= ~EXI_FLAG_LOCKED
;
283 __exi_setinterrupts(nChn
,exi
);
286 _CPU_ISR_Restore(level
);
291 lckd
= (struct _lck_dev
*)__lwp_queue_getI(&exi
->lckd_dev
);
292 __lwp_queue_appendI(&_lckdev_queue
,&lckd
->node
);
296 exi
->lckd_dev_bits
&= ~(1<<dev
);
299 _CPU_ISR_Restore(level
);
303 s32
EXI_Select(s32 nChn
,s32 nDev
,s32 nFrq
)
307 exibus_priv
*exi
= &eximap
[nChn
];
309 printf("EXI_Select(%d,%d,%d)\n",nChn
,nDev
,nFrq
);
311 _CPU_ISR_Disable(level
);
313 if(exi
->flags
&EXI_FLAG_SELECT
) {
315 printf("EXI_Select(): allready selected.\n");
317 _CPU_ISR_Restore(level
);
321 if(nChn
!=EXI_CHANNEL_2
) {
322 if(nDev
==EXI_DEVICE_0
&& !(exi
->flags
&EXI_FLAG_ATTACH
)) {
323 if(__exi_probe(nChn
)==0) {
324 _CPU_ISR_Restore(level
);
328 if(!(exi
->flags
&EXI_FLAG_LOCKED
) || exi
->lockeddev
!=nDev
) {
330 printf("EXI_Select(): not locked or wrong dev(%d).\n",exi
->lockeddev
);
332 _CPU_ISR_Restore(level
);
337 exi
->flags
|= EXI_FLAG_SELECT
;
338 val
= _exiReg
[nChn
*5];
339 val
= (val
&0x405)|(0x80<<nDev
)|(nFrq
<<4);
340 _exiReg
[nChn
*5] = val
;
342 if(exi
->flags
&EXI_FLAG_ATTACH
) {
343 if(nChn
==EXI_CHANNEL_0
) __MaskIrq(IRQMASK(IRQ_EXI0_EXT
));
344 else if(nChn
==EXI_CHANNEL_1
) __MaskIrq(IRQMASK(IRQ_EXI1_EXT
));
347 _CPU_ISR_Restore(level
);
351 s32
EXI_SelectSD(s32 nChn
,s32 nDev
,s32 nFrq
)
356 exibus_priv
*exi
= &eximap
[nChn
];
358 printf("EXI_SelectSD(%d,%d,%d)\n",nChn
,nDev
,nFrq
);
360 _CPU_ISR_Disable(level
);
362 if(exi
->flags
&EXI_FLAG_SELECT
) {
364 printf("EXI_SelectSD(): allready selected.\n");
366 _CPU_ISR_Restore(level
);
370 if(nChn
!=EXI_CHANNEL_2
) {
371 if(nDev
==EXI_DEVICE_0
&& !(exi
->flags
&EXI_FLAG_ATTACH
)) {
372 if((ret
=__exi_probe(nChn
))==1) {
373 if(!exi
->exi_idtime
) ret
= EXI_GetID(nChn
,EXI_DEVICE_0
,&id
);
376 _CPU_ISR_Restore(level
);
380 if(!(exi
->flags
&EXI_FLAG_LOCKED
) || exi
->lockeddev
!=nDev
) {
382 printf("EXI_SelectSD(): not locked or wrong dev(%d).\n",exi
->lockeddev
);
384 _CPU_ISR_Restore(level
);
389 exi
->flags
|= EXI_FLAG_SELECT
;
390 val
= _exiReg
[nChn
*5];
391 val
= (val
&0x405)|(nFrq
<<4);
392 _exiReg
[nChn
*5] = val
;
394 if(exi
->flags
&EXI_FLAG_ATTACH
) {
395 if(nChn
==EXI_CHANNEL_0
) __MaskIrq(IRQMASK(IRQ_EXI0_EXT
));
396 else if(nChn
==EXI_CHANNEL_1
) __MaskIrq(IRQMASK(IRQ_EXI1_EXT
));
399 _CPU_ISR_Restore(level
);
403 s32
EXI_Deselect(s32 nChn
)
407 exibus_priv
*exi
= &eximap
[nChn
];
409 printf("EXI_Deselect(%d)\n",nChn
);
411 _CPU_ISR_Disable(level
);
413 if(!(exi
->flags
&EXI_FLAG_SELECT
)) {
414 _CPU_ISR_Restore(level
);
418 exi
->flags
&= ~EXI_FLAG_SELECT
;
419 val
= _exiReg
[nChn
*5];
420 _exiReg
[nChn
*5] = (val
&0x405);
422 if(exi
->flags
&EXI_FLAG_ATTACH
) {
423 if(nChn
==EXI_CHANNEL_0
) __UnmaskIrq(IRQMASK(IRQ_EXI0_EXT
));
424 else if(nChn
==EXI_CHANNEL_1
) __UnmaskIrq(IRQMASK(IRQ_EXI1_EXT
));
427 if(nChn
!=EXI_CHANNEL_2
&& val
&EXI_DEVICE0
) {
428 if(__exi_probe(nChn
)==0) {
429 _CPU_ISR_Restore(level
);
433 _CPU_ISR_Restore(level
);
437 s32
EXI_Sync(s32 nChn
)
442 exibus_priv
*exi
= &eximap
[nChn
];
444 printf("EXI_Sync(%d)\n",nChn
);
446 while(_exiReg
[nChn
*5+3]&0x0001);
448 _CPU_ISR_Disable(level
);
451 if(exi
->flags
&EXI_FLAG_SELECT
&& exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
)) {
452 if(exi
->flags
&EXI_FLAG_IMM
) {
456 val
= _exiReg
[nChn
*5+4];
457 for(i
=0;i
<cnt
;i
++) ((u8
*)buf
)[i
] = (val
>>((3-i
)*8))&0xFF;
460 exi
->flags
&= ~(EXI_FLAG_DMA
|EXI_FLAG_IMM
);
463 _CPU_ISR_Restore(level
);
467 s32
EXI_Imm(s32 nChn
,void *pData
,u32 nLen
,u32 nMode
,EXICallback tc_cb
)
471 exibus_priv
*exi
= &eximap
[nChn
];
473 printf("EXI_Imm(%d,%p,%d,%d,%p)\n",nChn
,pData
,nLen
,nMode
,tc_cb
);
475 _CPU_ISR_Disable(level
);
477 if(exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
) || !(exi
->flags
&EXI_FLAG_SELECT
)) {
478 _CPU_ISR_Restore(level
);
482 exi
->CallbackTC
= tc_cb
;
484 __exi_clearirqs(nChn
,0,1,0);
485 __UnmaskIrq(IRQMASK((IRQ_EXI0_TC
+(nChn
*3))));
487 exi
->flags
|= EXI_FLAG_IMM
;
489 exi
->imm_buff
= pData
;
491 if(nMode
!=EXI_READ
) {
492 for(i
=0,value
=0;i
<nLen
;i
++) value
|= (((u8
*)pData
)[i
])<<((3-i
)*8);
493 _exiReg
[nChn
*5+4] = value
;
495 if(nMode
==EXI_WRITE
) exi
->imm_len
= 0;
497 _exiReg
[nChn
*5+3] = (((nLen
-1)&0x03)<<4)|((nMode
&0x03)<<2)|0x01;
499 _CPU_ISR_Restore(level
);
503 s32
EXI_ImmEx(s32 nChn
,void *pData
,u32 nLen
,u32 nMode
)
509 printf("EXI_ImmEx(%d,%p,%d,%d)\n",nChn
,pData
,nLen
,nMode
);
516 if(!EXI_Imm(nChn
,buf
,tc
,nMode
,NULL
)) break;
517 if(!EXI_Sync(nChn
)) break;
526 s32
EXI_Dma(s32 nChn
,void *pData
,u32 nLen
,u32 nMode
,EXICallback tc_cb
)
529 exibus_priv
*exi
= &eximap
[nChn
];
531 printf("EXI_Dma(%d,%p,%d,%d,%p)\n",nChn
,pData
,nLen
,nMode
,tc_cb
);
533 _CPU_ISR_Disable(level
);
535 if(exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
) || !(exi
->flags
&EXI_FLAG_SELECT
)) {
537 printf("EXI_Dma(%04x): abort\n",exi
->flags
);
539 _CPU_ISR_Restore(level
);
543 printf("EXI_Dma(tccb: %p)\n",tc_cb
);
545 exi
->CallbackTC
= tc_cb
;
547 __exi_clearirqs(nChn
,0,1,0);
548 __UnmaskIrq((IRQMASK((IRQ_EXI0_TC
+(nChn
*3)))));
551 exi
->imm_buff
= NULL
;
553 exi
->flags
|= EXI_FLAG_DMA
;
555 _exiReg
[nChn
*5+1] = (u32
)pData
&0x03FFFFE0;
556 _exiReg
[nChn
*5+2] = nLen
;
557 _exiReg
[nChn
*5+3] = ((nMode
&0x03)<<2)|0x03;
559 _CPU_ISR_Restore(level
);
563 s32
EXI_GetState(s32 nChn
)
565 exibus_priv
*exi
= &eximap
[nChn
];
569 static s32
__unlocked_handler(s32 nChn
,s32 nDev
)
573 printf("__unlocked_handler(%d,%d)\n",nChn
,nDev
);
575 EXI_GetID(nChn
,nDev
,&nId
);
579 s32
EXI_GetID(s32 nChn
,s32 nDev
,u32
*nId
)
584 exibus_priv
*exi
= &eximap
[nChn
];
587 printf("EXI_GetID(exi_id = %d)\n",exi
->exi_id
);
589 if(nChn
<EXI_CHANNEL_2
&& nDev
==EXI_DEVICE_0
) {
590 if(__exi_probe(nChn
)==0) return 0;
591 if(exi
->exi_idtime
==last_exi_idtime
[nChn
]) {
593 printf("EXI_GetID(exi_id = %d)\n",exi
->exi_id
);
599 printf("EXI_GetID(setting interrupts,%08x)\n",exi
->flags
);
601 if(__exi_attach(nChn
,NULL
)==0) return 0;
602 idtime
= last_exi_idtime
[nChn
];
605 printf("EXI_GetID(interrupts set)\n");
608 if(nChn
<EXI_CHANNEL_2
&& nDev
==EXI_DEVICE_0
) lck
= 1;
610 if(lck
) ret
= EXI_Lock(nChn
,nDev
,__unlocked_handler
);
611 else ret
= EXI_Lock(nChn
,nDev
,NULL
);
614 if(EXI_Select(nChn
,nDev
,EXI_SPEED1MHZ
)==1) {
616 EXI_Imm(nChn
,®
,2,EXI_WRITE
,NULL
);
618 EXI_Imm(nChn
,nId
,4,EXI_READ
,NULL
);
625 if(nChn
<EXI_CHANNEL_2
&& nDev
==EXI_DEVICE_0
) {
629 _CPU_ISR_Disable(level
);
630 if(idtime
==last_exi_idtime
[nChn
]) {
631 exi
->exi_idtime
= idtime
;
635 _CPU_ISR_Restore(level
);
637 printf("EXI_GetID(exi_id = %d)\n",exi
->exi_id
);
643 s32
EXI_Attach(s32 nChn
,EXICallback ext_cb
)
647 exibus_priv
*exi
= &eximap
[nChn
];
649 printf("EXI_Attach(%d)\n",nChn
);
653 _CPU_ISR_Disable(level
);
654 if(exi
->exi_idtime
) {
655 ret
= __exi_attach(nChn
,ext_cb
);
658 _CPU_ISR_Restore(level
);
662 s32
EXI_Detach(s32 nChn
)
666 exibus_priv
*exi
= &eximap
[nChn
];
668 printf("EXI_Detach(%d)\n",nChn
);
670 _CPU_ISR_Disable(level
);
671 if(exi
->flags
&EXI_FLAG_ATTACH
) {
672 if(exi
->flags
&EXI_FLAG_LOCKED
&& exi
->lockeddev
!=EXI_DEVICE_0
) ret
= 0;
674 exi
->flags
&= ~EXI_FLAG_ATTACH
;
675 __MaskIrq(((IRQMASK(IRQ_EXI0_EXI
)|IRQMASK(IRQ_EXI0_TC
)|IRQMASK(IRQ_EXI0_EXT
))>>(nChn
*3)));
678 _CPU_ISR_Restore(level
);
682 EXICallback
EXI_RegisterEXICallback(s32 nChn
,EXICallback exi_cb
)
685 EXICallback old
= NULL
;
686 exibus_priv
*exi
= &eximap
[nChn
];
688 printf("EXI_RegisterEXICallback(%d,%p)\n",nChn
,exi_cb
);
690 _CPU_ISR_Disable(level
);
691 old
= exi
->CallbackEXI
;
692 exi
->CallbackEXI
= exi_cb
;
693 if(nChn
==EXI_CHANNEL_2
) __exi_setinterrupts(EXI_CHANNEL_0
,&eximap
[EXI_CHANNEL_0
]);
694 else __exi_setinterrupts(nChn
,exi
);
695 _CPU_ISR_Restore(level
);
699 s32
EXI_Probe(s32 nChn
)
703 exibus_priv
*exi
= &eximap
[nChn
];
705 printf("EXI_Probe(%d)\n",nChn
);
707 if((ret
=__exi_probe(nChn
))==1) {
708 if(exi
->exi_idtime
==0) {
709 if(EXI_GetID(nChn
,EXI_DEVICE_0
,&id
)==0) ret
= 0;
715 s32
EXI_ProbeEx(s32 nChn
)
717 if(EXI_Probe(nChn
)==1) return 1;
718 if(last_exi_idtime
[nChn
]==0) return -1;
722 void EXI_ProbeReset()
724 last_exi_idtime
[0] = 0;
725 last_exi_idtime
[1] = 0;
727 eximap
[0].exi_idtime
= 0;
728 eximap
[1].exi_idtime
= 0;
732 EXI_GetID(EXI_CHANNEL_0
,EXI_DEVICE_2
,&exi_id_serport1
);
738 printf("__exi_init(): init expansion system.\n");
748 __exi_initmap(eximap
);
750 IRQ_Request(IRQ_EXI0_EXI
,__exi_irq_handler
,NULL
);
751 IRQ_Request(IRQ_EXI0_TC
,__tc_irq_handler
,NULL
);
752 IRQ_Request(IRQ_EXI0_EXT
,__ext_irq_handler
,NULL
);
753 IRQ_Request(IRQ_EXI1_EXI
,__exi_irq_handler
,NULL
);
754 IRQ_Request(IRQ_EXI1_TC
,__tc_irq_handler
,NULL
);
755 IRQ_Request(IRQ_EXI1_EXT
,__ext_irq_handler
,NULL
);
756 IRQ_Request(IRQ_EXI2_EXI
,__exi_irq_handler
,NULL
);
757 IRQ_Request(IRQ_EXI2_TC
,__tc_irq_handler
,NULL
);
762 void __exi_irq_handler(u32 nIrq
,void *pCtx
)
765 exibus_priv
*exi
= NULL
;
766 const u32 fact
= 0x55555556;
768 chan
= ((fact
*(nIrq
-IRQ_EXI0_EXI
))>>1)&0x0f;
769 dev
= _SHIFTR((_exiReg
[chan
*5]&0x380),8,2);
772 __exi_clearirqs(chan
,1,0,0);
774 if(!exi
->CallbackEXI
) return;
776 printf("__exi_irq_handler(%p)\n",exi
->CallbackEXI
);
778 exi
->CallbackEXI(chan
,dev
);
781 void __tc_irq_handler(u32 nIrq
,void *pCtx
)
783 u32 cnt
,len
,d
,chan
,dev
;
786 exibus_priv
*exi
= NULL
;
787 const u32 fact
= 0x55555556;
789 chan
= ((fact
*(nIrq
-IRQ_EXI0_TC
))>>1)&0x0f;
790 dev
= _SHIFTR((_exiReg
[chan
*5]&0x380),8,2);
793 __MaskIrq(IRQMASK(nIrq
));
794 __exi_clearirqs(chan
,0,1,0);
796 tccb
= exi
->CallbackTC
;
798 printf("__tc_irq_handler(%p)\n",tccb
);
802 exi
->CallbackTC
= NULL
;
803 if(exi
->flags
&(EXI_FLAG_DMA
|EXI_FLAG_IMM
)) {
804 if(exi
->flags
&EXI_FLAG_IMM
) {
808 d
= _exiReg
[chan
*5+4];
810 for(cnt
=0;cnt
<len
;cnt
++) ((u8
*)buf
)[cnt
] = (d
>>((3-cnt
)*8))&0xFF;
814 exi
->flags
&= ~(EXI_FLAG_DMA
|EXI_FLAG_IMM
);
819 void __ext_irq_handler(u32 nIrq
,void *pCtx
)
823 exibus_priv
*exi
= NULL
;
824 const u32 fact
= 0x55555556;
826 chan
= ((fact
*(nIrq
-IRQ_EXI0_EXT
))>>1)&0x0f;
827 dev
= _SHIFTR((_exiReg
[chan
*5]&0x380),8,2);
830 __MaskIrq(IRQMASK(nIrq
));
831 __exi_clearirqs(chan
,0,0,1);
833 exi
->flags
&= ~EXI_FLAG_ATTACH
;
834 if(exi
->CallbackEXT
) exi
->CallbackEXT(chan
,dev
);
836 printf("__ext_irq_handler(%p)\n",exi
->CallbackEXT
);
842 static s32
__probebarnacle(s32 chn
,u32 dev
,u32
*rev
)
846 if(chn
!=EXI_CHANNEL_2
&& dev
==EXI_DEVICE_0
) {
847 if(EXI_Attach(chn
,NULL
)==0) return 0;
851 if(EXI_Lock(chn
,dev
,NULL
)==1) {
852 if(EXI_Select(chn
,dev
,EXI_SPEED1MHZ
)==1) {
854 if(EXI_Imm(chn
,®
,sizeof(u32
),EXI_WRITE
,NULL
)==0) ret
|= 0x0001;
855 if(EXI_Sync(chn
)==0) ret
|= 0x0002;
856 if(EXI_Imm(chn
,rev
,sizeof(u32
),EXI_READ
,NULL
)==0) ret
|= 0x0004;
857 if(EXI_Sync(chn
)==0) ret
|= 0x0008;
858 if(EXI_Deselect(chn
)==0) ret
|= 0x0010;
864 if(chn
!=EXI_CHANNEL_2
&& dev
==EXI_DEVICE_0
) EXI_Detach(chn
);
867 if((*rev
+0x00010000)==0xffff) return 0;
872 static s32
__queuelength()
877 if(EXI_Select(exi_uart_chan
,exi_uart_dev
,EXI_SPEED8MHZ
)==0) return -1;
880 EXI_Imm(exi_uart_chan
,®
,sizeof(u32
),EXI_WRITE
,NULL
);
881 EXI_Sync(exi_uart_chan
);
882 EXI_Imm(exi_uart_chan
,&len
,sizeof(u8
),EXI_READ
,NULL
);
883 EXI_Sync(exi_uart_chan
);
885 EXI_Deselect(exi_uart_chan
);
890 void __SYS_EnableBarnacle(s32 chn
,u32 dev
)
894 if(EXI_GetID(chn
,dev
,&id
)==0) return;
896 if(id
==0x01020000 || id
==0x0004 || id
==0x80000010 || id
==0x80000008
897 || id
==0x80000004 || id
==0xffff || id
==0x80000020 || id
==0x0020
898 || id
==0x0010 || id
==0x0008 || id
==0x01010000 || id
==0x04040404
899 || id
==0x04021000 || id
==0x03010000 || id
==0x02020000
900 || id
==0x04020300 || id
==0x04020200 || id
==0x04130000
901 || id
==0x04120000 || id
==0x04060000 || id
==0x04220000) return;
903 if(__probebarnacle(chn
,dev
,&rev
)==0) return;
908 exi_uart_barnacle_enabled
= 0xa5ff005a;
909 exi_uart_enabled
= 0xa5ff005a;
914 if((exi_uart_enabled
+0x5a010000)==0x005a) return 0;
916 exi_uart_chan
= EXI_CHANNEL_0
;
917 exi_uart_dev
= EXI_DEVICE_1
;
919 exi_uart_enabled
= 0xa5ff005a;
923 s32
WriteUARTN(void *buf
,u32 len
)
929 if((exi_uart_enabled
+0x5a010000)!=0x005a) return 2;
930 if(EXI_Lock(exi_uart_chan
,exi_uart_dev
,NULL
)==0) return 0;
933 while((ptr
-(u8
*)buf
)<len
) {
934 if(*ptr
=='\n') *ptr
= '\r';
941 if((qlen
=__queuelength())<0) {
944 } else if(qlen
>=12 || qlen
>=len
) {
945 if(EXI_Select(exi_uart_chan
,exi_uart_dev
,EXI_SPEED8MHZ
)==0) {
951 EXI_Imm(exi_uart_chan
,®
,sizeof(u32
),EXI_WRITE
,NULL
);
952 EXI_Sync(exi_uart_chan
);
954 while(qlen
>0 && len
>0) {
960 EXI_Imm(exi_uart_chan
,ptr
,cnt
,EXI_WRITE
,NULL
);
961 EXI_Sync(exi_uart_chan
);
968 EXI_Deselect(exi_uart_chan
);
971 EXI_Unlock(exi_uart_chan
);