7#include "irx_imports.h"
20IRX_ID(
"mmcedrv", MAJOR, MINOR);
22extern struct irx_export_table _exp_mmcedrv;
24s64 mmcedrv_get_size(
int fd)
33 wrbuf[0x1] = MMCE_CMD_FS_LSEEK64;
34 wrbuf[0x2] = MMCE_RESERVED;
50 res = mmce_sio2_tx_rx_pio(0xd, 0x16, wrbuf, rdbuf, &timeout_1s);
53 DPRINTF(
"%s ERROR: P1 - Timedout waiting for /ACK\n", __func__);
57 if (rdbuf[0x1] != MMCE_REPLY_CONST) {
58 DPRINTF(
"%s ERROR: Invalid response from card. Got 0x%x, Expected 0x%x\n", __func__, rdbuf[0x1], MMCE_REPLY_CONST);
62 position = (s64)rdbuf[0xd] << 56;
63 position |= (s64)rdbuf[0xe] << 48;
64 position |= (s64)rdbuf[0xf] << 40;
65 position |= (s64)rdbuf[0x10] << 32;
66 position |= (s64)rdbuf[0x11] << 24;
67 position |= (s64)rdbuf[0x12] << 16;
68 position |= (s64)rdbuf[0x13] << 8;
69 position |= (s64)rdbuf[0x14];
71 DPRINTF(
"%s position %lli\n", __func__, position);
76int mmcedrv_read_sector(
int fd, u32 sector, u32 count,
void *buffer)
84 DPRINTF(
"%s fd: %i, starting sector: %i, count: %i\n", __func__, fd, sector, count);
87 wrbuf[0x1] = MMCE_CMD_FS_READ_SECTOR;
88 wrbuf[0x2] = MMCE_RESERVED;
91 wrbuf[0x4] = (sector & 0x00FF0000) >> 16;
92 wrbuf[0x5] = (sector & 0x0000FF00) >> 8;
93 wrbuf[0x6] = (sector & 0x000000FF);
95 wrbuf[0x7] = (count & 0x00FF0000) >> 16;
96 wrbuf[0x8] = (count & 0x0000FF00) >> 8;
97 wrbuf[0x9] = (count & 0x000000FF);
104 res = mmce_sio2_tx_rx_pio(0xB, 0xB, wrbuf, rdbuf, &timeout_2s);
106 DPRINTF(
"%s ERROR: P1 - Timedout waiting for /ACK\n", __func__);
111 if (rdbuf[0x1] != MMCE_REPLY_CONST) {
112 DPRINTF(
"%s ERROR: Invalid response from card. Got 0x%x, Expected 0x%x\n", __func__, rdbuf[0x1], MMCE_REPLY_CONST);
117 if (rdbuf[0x9] != 0x0) {
118 DPRINTF(
"%s ERROR: P1 - Got bad return value from card, res %i\n", __func__, rdbuf[0x9]);
124 res = mmce_sio2_rx_dma(buffer, (count * 2048));
126 DPRINTF(
"%s ERROR: P2 - Timedout waiting for /ACK\n", __func__);
132 res = mmce_sio2_tx_rx_pio(0x0, 0x5, wrbuf, rdbuf, &timeout_1s);
134 DPRINTF(
"%s ERROR: P3 - Timedout waiting for /ACK\n", __func__);
141 sectors_read = rdbuf[0x1] << 16;
142 sectors_read |= rdbuf[0x2] << 8;
143 sectors_read |= rdbuf[0x3];
145 if (sectors_read != count) {
146 DPRINTF(
"%s ERROR: Sectors read: %i, expected: %i\n", __func__, sectors_read, count);
152int mmcedrv_read(
int fd,
int size,
void *ptr)
157 DPRINTF(
"%s: fd: %i, size: %i\n", __func__, fd, size);
162 wrbuf[0x0] = MMCE_ID;
163 wrbuf[0x1] = MMCE_CMD_FS_READ;
164 wrbuf[0x2] = MMCE_RESERVED;
167 wrbuf[0x5] = (size & 0xFF000000) >> 24;
168 wrbuf[0x6] = (size & 0x00FF0000) >> 16;
169 wrbuf[0x7] = (size & 0x0000FF00) >> 8;
170 wrbuf[0x8] = (size & 0x000000FF);
176 res = mmce_sio2_tx_rx_pio(0xA, 0xA, wrbuf, rdbuf, &timeout_2s);
178 DPRINTF(
"%s ERROR: P1 - Timedout waiting for /ACK\n", __func__);
183 if (rdbuf[0x1] != MMCE_REPLY_CONST) {
184 DPRINTF(
"%s ERROR: Invalid response from card. Got 0x%x, Expected 0x%x\n", __func__, rdbuf[0x1], MMCE_REPLY_CONST);
189 if (rdbuf[0x9] != 0x0) {
190 DPRINTF(
"%s ERROR: P1 - Got bad return value from card, res %i\n", __func__, rdbuf[0x9]);
196 res = mmce_sio2_rx_mixed(ptr, size);
198 DPRINTF(
"%s ERROR: P2 - Timedout waiting for /ACK\n", __func__);
204 res = mmce_sio2_tx_rx_pio(0x0, 0x6, wrbuf, rdbuf, &timeout_1s);
206 DPRINTF(
"%s ERROR: P3 - Timedout waiting for /ACK\n", __func__);
213 bytes_read = rdbuf[0x1] << 24;
214 bytes_read |= rdbuf[0x2] << 16;
215 bytes_read |= rdbuf[0x3] << 8;
216 bytes_read |= rdbuf[0x4];
218 if (bytes_read != size) {
219 DPRINTF(
"%s WARN: bytes read: %i, expected: %i\n", __func__, bytes_read, size);
221 if (bytes_read > size)
229int mmcedrv_write(
int fd,
int size,
void *ptr)
234 DPRINTF(
"%s: fd: %i, size: %i\n", __func__, fd, size);
239 wrbuf[0x0] = MMCE_ID;
240 wrbuf[0x1] = MMCE_CMD_FS_WRITE;
241 wrbuf[0x2] = MMCE_RESERVED;
244 wrbuf[0x5] = (size & 0xFF000000) >> 24;
245 wrbuf[0x6] = (size & 0x00FF0000) >> 16;
246 wrbuf[0x7] = (size & 0x0000FF00) >> 8;
247 wrbuf[0x8] = (size & 0x000000FF);
253 res = mmce_sio2_tx_rx_pio(0xA, 0xA, wrbuf, rdbuf, &timeout_1s);
255 DPRINTF(
"%s ERROR: P1 - Timedout waiting for /ACK\n", __func__);
260 if (rdbuf[0x1] != MMCE_REPLY_CONST) {
261 DPRINTF(
"%s ERROR: Invalid response from card. Got 0x%x, Expected 0x%x\n", __func__, rdbuf[0x1], MMCE_REPLY_CONST);
266 if (rdbuf[0x9] != 0x0) {
267 DPRINTF(
"%s ERROR: P1 - Got bad return value from card 0x%x\n", __func__, rdbuf[0x9]);
273 res = mmce_sio2_tx_mixed(ptr, size);
275 DPRINTF(
"%s ERROR: P2 - Timedout waiting for /ACK\n", __func__);
281 res = mmce_sio2_tx_rx_pio(0x0, 0x6, wrbuf, rdbuf, &timeout_1s);
283 DPRINTF(
"%s ERROR: P3 - Timedout waiting for /ACK\n", __func__);
290 bytes_written = rdbuf[0x1] << 24;
291 bytes_written |= rdbuf[0x2] << 16;
292 bytes_written |= rdbuf[0x3] << 8;
293 bytes_written |= rdbuf[0x4];
295 if (bytes_written != size) {
296 DPRINTF(
"%s bytes written: %i, expected: %i\n", __func__, bytes_written, size);
299 return bytes_written;
302int mmcedrv_lseek(
int fd,
int offset,
int whence)
307 DPRINTF(
"%s: fd: %i, offset: %i, whence: %i\n", __func__, fd, offset, whence);
312 wrbuf[0x0] = MMCE_ID;
313 wrbuf[0x1] = MMCE_CMD_FS_LSEEK;
314 wrbuf[0x2] = MMCE_RESERVED;
316 wrbuf[0x4] = (offset & 0xFF000000) >> 24;
317 wrbuf[0x5] = (offset & 0x00FF0000) >> 16;
318 wrbuf[0x6] = (offset & 0x0000FF00) >> 8;
319 wrbuf[0x7] = (offset & 0x000000FF);
320 wrbuf[0x8] = (u8)(whence);
324 res = mmce_sio2_tx_rx_pio(0x9, 0xe, wrbuf, rdbuf, &timeout_1s);
328 DPRINTF(
"%s ERROR: P1 - Timedout waiting for /ACK\n", __func__);
332 if (rdbuf[0x1] != MMCE_REPLY_CONST) {
333 DPRINTF(
"%s ERROR: Invalid response from card. Got 0x%x, Expected 0x%x\n", __func__, rdbuf[0x1], MMCE_REPLY_CONST);
337 position = rdbuf[0x9] << 24;
338 position |= rdbuf[0xa] << 16;
339 position |= rdbuf[0xb] << 8;
340 position |= rdbuf[0xc];
342 DPRINTF(
"%s position %i\n", __func__, position);
348void mmcedrv_config_set(
int setting,
int value)
351 case MMCEDRV_SETTING_PORT:
352 if (value == 2 || value == 3)
353 mmce_sio2_set_port(value);
355 DPRINTF(
"Invalid port setting: %i\n", value);
358 case MMCEDRV_SETTING_ACK_WAIT_CYCLES:
360 mmce_sio2_update_ack_wait_cycles(value);
364 case MMCEDRV_SETTING_USE_ALARMS:
365 mmce_sio2_set_use_alarm(value);
373int __start(
int argc,
char *argv[])
377 DPRINTF(
"Multipurpose Memory Card Emulator Driver (MMCEDRV) v%d.%d by the MMCE team\n", MAJOR, MINOR);
380 rv = mmce_sio2_init();
382 DPRINTF(
"mmce_sio2_init failed, rv %i\n", rv);
383 return MODULE_NO_RESIDENT_END;
387 if (RegisterLibraryEntries(&_exp_mmcedrv) != 0) {
388 DPRINTF(
"ERROR: library already registered\n");
389 return MODULE_NO_RESIDENT_END;
393 if (lib_modload != NULL) {
394 DPRINTF(
"modload 0x%x detected\n", lib_modload->version);
395 if (lib_modload->version > 0x102)
396 return MODULE_REMOVABLE_END;
398 DPRINTF(
"modload not detected! this is serious!\n");
401 return MODULE_RESIDENT_END;
404int __stop(
int argc,
char *argv[])
406 DPRINTF(
"Unloading module\n");
410 return MODULE_NO_RESIDENT_END;
413int _start(
int argc,
char *argv[])
416 return __start(argc, argv);
418 return __stop(-argc, argv);
iop_library_t * ioplib_getByName(const char *name)
get library object of any IRX Module