fix issue with HBC stub + 64B L2 cache (tueidj)
[libogc.git] / libogc / usbgecko.c
blobcfbe4de6a9f62288a07ee25cb1c02e0033ce3f2b
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <errno.h>
5 #include <signal.h>
6 #include <gccore.h>
7 #include <machine/processor.h>
9 #include "usbgecko.h"
11 #define _SHIFTL(v, s, w) \
12 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
13 #define _SHIFTR(v, s, w) \
14 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
17 static u32 usbgecko_inited = 0;
18 static lwpq_t wait_exi_queue[2];
20 static s32 __usbgecko_exi_unlock(s32 chan,s32 dev)
22 LWP_ThreadBroadcast(wait_exi_queue[chan]);
23 return 1;
26 static void __usbgecko_init()
28 u32 i;
30 for(i=0;i<EXI_CHANNEL_2;i++) {
31 LWP_InitQueue(&wait_exi_queue[i]);
33 usbgecko_inited = 1;
36 static __inline__ void __usbgecko_exi_wait(s32 chn)
38 u32 level;
40 _CPU_ISR_Disable(level);
41 if(!usbgecko_inited) __usbgecko_init();
42 while(EXI_Lock(chn,EXI_DEVICE_0,__usbgecko_exi_unlock)==0) {
43 LWP_ThreadSleep(wait_exi_queue[chn]);
45 _CPU_ISR_Restore(level);
48 static __inline__ int __send_command(s32 chn,u16 *cmd)
50 s32 ret = 0;
52 if(!EXI_Select(chn,EXI_DEVICE_0,EXI_SPEED32MHZ)) ret |= 0x01;
53 if(!EXI_Imm(chn,cmd,sizeof(u16),EXI_READWRITE,NULL)) ret |= 0x02;
54 if(!EXI_Sync(chn)) ret |= 0x04;
55 if(!EXI_Deselect(chn)) ret |= 0x08;
57 if(ret) return 0;
58 return 1;
61 static int __usb_sendbyte(s32 chn,char ch)
63 s32 ret;
64 u16 val;
66 val = (0xB000|_SHIFTL(ch,4,8));
67 ret = __send_command(chn,&val);
68 if(ret==1 && !(val&0x0400)) ret = 0;
70 return ret;
73 static int __usb_recvbyte(s32 chn,char *ch)
75 s32 ret;
76 u16 val;
78 *ch = 0;
79 val = 0xA000;
80 ret = __send_command(chn,&val);
81 if(ret==1 && !(val&0x0800)) ret = 0;
82 else if(ret==1) *ch = (val&0xff);
84 return ret;
87 int __usb_checksend(s32 chn)
89 s32 ret;
90 u16 val;
92 val = 0xC000;
93 ret = __send_command(chn,&val);
94 if(ret==1 && !(val&0x0400)) ret = 0;
96 return ret;
99 int __usb_checkrecv(s32 chn)
101 s32 ret;
102 u16 val;
104 val = 0xD000;
105 ret = __send_command(chn,&val);
106 if(ret==1 && !(val&0x0400)) ret = 0;
108 return ret;
111 void usb_flush(s32 chn)
113 char tmp;
115 __usbgecko_exi_wait(chn);
116 while(__usb_recvbyte(chn,&tmp));
117 EXI_Unlock(chn);
120 int usb_isgeckoalive(s32 chn)
122 u32 id = 0;
123 s32 ret;
124 u16 val;
126 if (EXI_GetID(chn, EXI_DEVICE_0, &id) == 0)
127 return 0;
129 if (id != 0)
130 return 0;
132 __usbgecko_exi_wait(chn);
134 val = 0x9000;
135 ret = __send_command(chn,&val);
136 if(ret==1 && !(val&0x0470)) ret = 0;
138 EXI_Unlock(chn);
140 return ret;
143 int usb_recvbuffer_ex(s32 chn,void *buffer,int size, int retries)
145 s32 ret;
146 s32 left = size;
147 char *ptr = (char*)buffer;
149 __usbgecko_exi_wait(chn);
150 while(left>0) {
151 ret = __usb_recvbyte(chn,ptr);
152 if(ret==0) break;
154 ptr++;
155 left--;
157 if (retries >= 0) {
158 retries--;
159 if (retries == 0)
160 break;
163 EXI_Unlock(chn);
165 return (size - left);
168 int usb_recvbuffer(s32 chn,void *buffer,int size) {
169 return usb_recvbuffer_ex(chn, buffer, size, -1);
172 int usb_sendbuffer_ex(s32 chn,const void *buffer,int size, int retries)
174 s32 ret;
175 s32 left = size;
176 char *ptr = (char*)buffer;
178 __usbgecko_exi_wait(chn);
179 while(left>0) {
180 ret = __usb_sendbyte(chn,*ptr);
181 if(ret==0) break;
183 ptr++;
184 left--;
186 if (retries >= 0) {
187 retries--;
188 if (retries == 0)
189 break;
192 EXI_Unlock(chn);
194 return (size - left);
197 int usb_sendbuffer(s32 chn,const void *buffer,int size) {
198 return usb_sendbuffer_ex(chn, buffer, size, -1);
201 int usb_recvbuffer_safe_ex(s32 chn,void *buffer,int size, int retries)
203 s32 ret;
204 s32 left = size;
205 char *ptr = (char*)buffer;
207 __usbgecko_exi_wait(chn);
208 while(left>0) {
209 if(__usb_checkrecv(chn)) {
210 ret = __usb_recvbyte(chn,ptr);
211 if(ret==0) break;
213 ptr++;
214 left--;
217 if (retries >= 0) {
218 retries--;
219 if (retries == 0)
220 break;
223 EXI_Unlock(chn);
225 return (size - left);
228 int usb_recvbuffer_safe(s32 chn,void *buffer,int size) {
229 return usb_recvbuffer_safe_ex(chn, buffer, size, -1);
232 int usb_sendbuffer_safe_ex(s32 chn,const void *buffer,int size, int retries)
234 s32 ret;
235 s32 left = size;
236 char *ptr = (char*)buffer;
238 __usbgecko_exi_wait(chn);
239 while(left>0) {
240 if(__usb_checksend(chn)) {
241 ret = __usb_sendbyte(chn,*ptr);
242 if(ret==0) break;
244 ptr++;
245 left--;
248 if (retries >= 0) {
249 retries--;
250 if (retries == 0)
251 break;
254 EXI_Unlock(chn);
256 return (size - left);
259 int usb_sendbuffer_safe(s32 chn,const void *buffer,int size) {
260 return usb_sendbuffer_safe_ex(chn, buffer, size, -1);