2 * Copyright (C) 2008 svpe, #wiidev at efnet
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // pretty much everything here has been reversed from the twilight hack elf loader
18 // my implementation is *really* bad and will fail fail in random situations.
19 // it should not be used anywhere else. i recommend waiting for the libogc update.
20 // you have been warned....
28 static char *sd_path
__attribute__((aligned(32))) = "/dev/sdio/slot0";
29 static s32 sd_fd
= -1;
31 static u32 status
__attribute__((aligned(32)));
33 s32
sd_send_cmd(u32 cmd
, u32 type
, u32 resp
, u32 arg
, u32 blocks
, u32 bsize
, u32 addr
)
35 static u32 request
[9] __attribute__((aligned(32)));
36 static u32 reply
[4] __attribute__((aligned(32)));
39 memset(request
, 0, sizeof(request
));
40 memset(reply
, 0, sizeof(reply
));
52 r
= IOS_Ioctl(sd_fd
, 7, (u8
*)request
, 36, (u8
*)reply
, 0x10);
53 // printf("sd_send_cmd(%x, %x, %x, %x, %x, %x, %x) = %d", cmd, type, resp, arg, blocks, bsize, addr, r);
54 // printf(" -> %x %x %x %x\n", reply[0], reply[1], reply[2], reply[3]); // TODO: add some argument for this reply
63 r
= IOS_Ioctl(sd_fd
, 4, 0, 0, (u8
*)&status
, 4);
64 // printf("sd_reset(): r = %d; status = %d\n", r, status);
72 r
= sd_send_cmd(7, 3, 2, status
& 0xFFFF0000, 0, 0, 0);
73 // printf("sd_select(): r = %d\n", r);
77 s32
sd_set_blocklen(u32 len
)
81 r
= sd_send_cmd(0x10, 3, 1, len
, 0, 0, 0);
82 // printf("sd_set_blocklen(%x) = %d\n", len, r);
89 static u32 data
__attribute__((aligned(32)));
90 static u32 query
[6] __attribute__((aligned(32)));
93 memset(query
, 0, 0x18);
99 r
= IOS_Ioctl(sd_fd
, 2, (u8
*)query
, 0x18, (u8
*)&data
, 4);
100 // printf("sd_get_hcreg() = %d; r = %d\n", data & 0xFF, r);
104 s32
sd_set_hcreg(u8 value
)
107 static u32 query
[6] __attribute__((aligned(32)));
109 memset(query
, 0, 0x18);
115 r
= IOS_Ioctl(sd_fd
, 1, (u8
*)query
, 0x18, 0, 0);
116 // printf("sd_set_hcreg(%d) = %d\n", value, r);
120 s32
sd_set_buswidth(u8 w
)
125 r
= sd_send_cmd(0x37, 3, 1, status
& 0xFFFF0000, 0, 0, 0);
128 r
= sd_send_cmd(6, 3, 1, (w
== 4 ? 2 : 0), 0, 0, 0);
132 reg
= sd_get_hcreg();
137 return sd_set_hcreg(reg
);
143 static u32 c
__attribute__((aligned(32)));
146 r
= IOS_Ioctl(sd_fd
, 6, &c
, 4, 0, 0);
147 // printf("sd_clock() = %d\n", r);
151 s32
sd_read(u32 n
, u8
*buf
)
154 static u8 buffer
[0x200] __attribute__((aligned(32)));
155 static u32 query
[9] __attribute__((aligned(32)));
156 static u32 res
[4] __attribute__((aligned(32)));
158 static ioctlv v
[3] __attribute__((aligned(32)));
160 // printf("sd_read(%d) called\n", n);
162 memset(buffer
, 0xAA, 0x200); // why is this buffer filled with 0xAA? is this really needed?
163 memset(query
, 0, 0x24);
164 memset(res
, 0, 0x10);
169 query
[3] = n
* 0x200; // arg
170 query
[4] = 1; // block_count
171 query
[5] = 0x200; // sector size
172 query
[6] = (u32
)buffer
; // buffer
176 v
[0].data
= (u32
*)query
;
178 v
[1].data
=(u32
*)buffer
;
180 v
[2].data
= (u32
*)res
;
183 r
= IOS_Ioctlv(sd_fd
, 7, 2, 1, v
);
187 printf("sd_read() = %d\n", r
);
188 printf(" %x %x %x %x\n", res
[0], res
[1], res
[2], res
[3]);
192 memcpy(buf
, buffer
, 0x200);
203 // printf("sd_init() called more than once. using old sd_fd: %d\n", sd_fd);
207 sd_fd
= IOS_Open(sd_path
, 0);
208 // printf("sd_fd = %d\n", sd_fd);
213 // TODO: close sd_fd on failure and do proper error check here
219 r
= sd_set_blocklen(0x200);
222 r
= sd_set_buswidth(4);
236 return IOS_Close(sd_fd
);