port-work; won't compile or even work
[ppcskel.git] / gecko.c
1 /*
2         BootMii - a Free Software replacement for the Nintendo/BroadOn bootloader.
3         Requires mini.
4
5 Copyright (c) 2008              Nuke - <wiinuke@gmail.com>
6 Copyright (C) 2008, 2009        Hector Martin "marcan" <marcan@marcansoft.com>
7 Copyright (C) 2009              Andre Heider "dhewg" <dhewg@wiibrew.org>
8
9 # This code is licensed to you under the terms of the GNU GPL, version 2;
10 # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
11 */
12
13 #include "bootmii_ppc.h"
14 #include "printf.h"
15
16 #define         EXI_REG_BASE                    0xd806800
17 #define         EXI0_REG_BASE                   (EXI_REG_BASE+0x000)
18 #define         EXI1_REG_BASE                   (EXI_REG_BASE+0x014)
19 #define         EXI2_REG_BASE                   (EXI_REG_BASE+0x028)
20
21 #define         EXI0_CSR                                (EXI0_REG_BASE+0x000)
22 #define         EXI0_MAR                                (EXI0_REG_BASE+0x004)
23 #define         EXI0_LENGTH                             (EXI0_REG_BASE+0x008)
24 #define         EXI0_CR                                 (EXI0_REG_BASE+0x00c)
25 #define         EXI0_DATA                               (EXI0_REG_BASE+0x010)
26
27 #define         EXI1_CSR                                (EXI1_REG_BASE+0x000)
28 #define         EXI1_MAR                                (EXI1_REG_BASE+0x004)
29 #define         EXI1_LENGTH                             (EXI1_REG_BASE+0x008)
30 #define         EXI1_CR                                 (EXI1_REG_BASE+0x00c)
31 #define         EXI1_DATA                               (EXI1_REG_BASE+0x010)
32
33 #define         EXI2_CSR                                (EXI2_REG_BASE+0x000)
34 #define         EXI2_MAR                                (EXI2_REG_BASE+0x004)
35 #define         EXI2_LENGTH                             (EXI2_REG_BASE+0x008)
36 #define         EXI2_CR                                 (EXI2_REG_BASE+0x00c)
37 #define         EXI2_DATA                               (EXI2_REG_BASE+0x010)
38
39 static int gecko_console_enabled = 0;
40
41 static u32 _gecko_command(u32 command) {
42         u32 i;
43         // Memory Card Port B (Channel 1, Device 0, Frequency 3 (32Mhz Clock))
44         write32(EXI1_CSR, 0xd0);
45         write32(EXI1_DATA, command);
46         write32(EXI1_CR, 0x19);
47         i = 1000;
48         while ((read32(EXI1_CR) & 1) && (i--));
49         i = read32(EXI1_DATA);
50         write32(EXI1_CSR, 0);
51         return i;
52 }
53
54 static u32 _gecko_getid(void)
55 {
56         u32 i;
57         // Memory Card Port B (Channel 1, Device 0, Frequency 3 (32Mhz Clock))
58         write32(EXI1_CSR, 0xd0);
59         write32(EXI1_DATA, 0);
60         write32(EXI1_CR, 0x19);
61         while (read32(EXI1_CR) & 1);
62         write32(EXI1_CR, 0x39);
63         while (read32(EXI1_CR) & 1);
64         i = read32(EXI1_DATA);
65         write32(EXI1_CSR, 0);
66         return i;
67 }
68
69 static u32 _gecko_sendbyte(char sendbyte) {
70         u32 i = 0;
71         i = _gecko_command(0xB0000000 | (sendbyte<<20));
72         if (i&0x04000000)
73                 return 1; // Return 1 if byte was sent
74         return 0;
75 }
76
77 #if 0
78 static u32 _gecko_recvbyte(char *recvbyte) {
79         u32 i = 0;
80         *recvbyte = 0;
81         i = _gecko_command(0xA0000000);
82         if (i&0x08000000) {
83                 // Return 1 if byte was received
84                 *recvbyte = (i>>16)&0xff;
85                 return 1;
86         }
87         return 0;
88 }
89
90 static u32 _gecko_checksend(void) {
91         u32 i = 0;
92         i = _gecko_command(0xC0000000);
93         if (i&0x04000000)
94                 return 1; // Return 1 if safe to send
95         return 0;
96 }
97
98 static u32 _gecko_checkrecv(void) {
99         u32 i = 0;
100         i = _gecko_command(0xD0000000);
101         if (i&0x04000000)
102                 return 1; // Return 1 if safe to recv
103         return 0;
104 }
105
106 static void gecko_flush(void) {
107         char tmp;
108         while(_gecko_recvbyte(&tmp));
109 }
110 #endif
111
112 static int gecko_isalive(void) {
113         u32 i;
114
115         i = _gecko_getid();
116         if (i != 0x00000000)
117                 return 0;
118
119         i = _gecko_command(0x90000000);
120         if ((i & 0xFFFF0000) != 0x04700000)
121                 return 0;
122
123         return 1;
124 }
125
126 #if 0
127 static int gecko_recvbuffer(void *buffer, u32 size) {
128         u32 left = size;
129         char *ptr = (char*)buffer;
130
131         while(left>0) {
132                 if(!_gecko_recvbyte(ptr))
133                         break;
134                 ptr++;
135                 left--;
136         }
137         return (size - left);
138 }
139 #endif
140
141 static int gecko_sendbuffer(const void *buffer, u32 size) {
142         u32 left = size;
143         char *ptr = (char*)buffer;
144
145         while(left>0) {
146                 if(!_gecko_sendbyte(*ptr))
147                         break;
148                 ptr++;
149                 left--;
150         }
151         return (size - left);
152 }
153
154 #if 0
155 static int gecko_recvbuffer_safe(void *buffer, u32 size) {
156         u32 left = size;
157         char *ptr = (char*)buffer;
158         
159         while(left>0) {
160                 if(_gecko_checkrecv()) {
161                         if(!_gecko_recvbyte(ptr))
162                                 break;
163                         ptr++;
164                         left--;
165                 }
166         }
167         return (size - left);
168 }
169
170 static int gecko_sendbuffer_safe(const void *buffer, u32 size) {
171         u32 left = size;
172         char *ptr = (char*)buffer;
173         
174         while(left>0) {
175                 if(_gecko_checksend()) {
176                         if(!_gecko_sendbyte(*ptr))
177                                 break;
178                         ptr++;
179                         left--;
180                 }
181         }
182         return (size - left);
183 }
184 #endif
185
186 void gecko_init(void)
187 {
188         // unlock EXI
189         write32(0x0d00643c, 0);
190
191         write32(EXI0_CSR, 0);
192         write32(EXI1_CSR, 0);
193         write32(EXI2_CSR, 0);
194         write32(EXI0_CSR, 0x2000);
195         write32(EXI0_CSR, 3<<10);
196         write32(EXI1_CSR, 3<<10);
197
198         if (!gecko_isalive())
199                 return;
200
201         gecko_console_enabled = 1;
202 }
203
204 int printf(const char *fmt, ...) {
205         if (!gecko_console_enabled)
206                 return 0;
207
208         udelay(100); // evil hack :)
209
210         va_list args;
211         char buffer[1024];
212         int i;
213
214         va_start(args, fmt);
215         i = vsprintf(buffer, fmt, args);
216         va_end(args);
217
218         return gecko_sendbuffer(buffer, i);
219 }
220