int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in) //experimental { if(handelNAND.isSDHC == 0) sector_no <<= 9; inittarget(&handelNAND); sdmmc_write16(REG_SDSTOP,0x100); #ifdef DATA32_SUPPORT sdmmc_write32(REG_SDBLKCOUNT32,numsectors); #else sdmmc_write16(REG_SDBLKCOUNT,numsectors); #endif handelNAND.data = in; handelNAND.size = numsectors << 9; sdmmc_send_command(&handelNAND,0x52C19,sector_no); inittarget(&handelSD); return geterror(&handelNAND); }
void tmio_init() { tmio_mask16(REG_DATACTL32, 0x0800, 0x0000); tmio_mask16(REG_DATACTL32, 0x1000, 0x0000); tmio_mask16(REG_DATACTL32, 0x0000, 0x0402); tmio_mask16(REG_DATACTL, 0x2200, 0x0002); #ifdef DATA32_SUPPORT tmio_mask16(REG_DATACTL, 0x0020, 0x0000); tmio_write16(REG_SDBLKLEN32, TMIO_BBS); #else tmio_mask16(REG_DATACTL32, 0x0020, 0x0000); tmio_mask16(REG_DATACTL, 0x0020, 0x0000); tmio_write16(REG_SDBLKLEN32, 0); #endif tmio_write16(REG_SDBLKCOUNT32, 1); tmio_mask16(REG_SDRESET, 0x0001, 0x0000); tmio_mask16(REG_SDRESET, 0x0000, 0x0001); tmio_write32(REG_SDIRMASK, ~TMIO_MASK_ALL); tmio_mask16(0xFC, 0x0000, 0x00DB); tmio_mask16(0xFE, 0x0000, 0x00DB); tmio_mask16(REG_SDPORTSEL, 0x0002, 0x0000); #ifdef DATA32_SUPPORT tmio_write16(REG_SDCLKCTL, 0x0020); tmio_write16(REG_SDOPT, 0x40EE); #else tmio_write16(REG_SDCLKCTL, 0x0040); tmio_write16(REG_SDOPT, 0x40EB); #endif tmio_mask16(REG_SDPORTSEL, 0x0002, 0x0000); tmio_write16(REG_SDBLKLEN, TMIO_BBS); tmio_write16(REG_SDSTOP, 0); inittarget(TMIO_DEV_SDMC); }
int NO_INLINE sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out) { if(handelSD.isSDHC == 0) sector_no <<= 9; inittarget(&handelSD); sdmmc_write16(REG_SDSTOP,0x100); #ifdef DATA32_SUPPORT sdmmc_write16(REG_SDBLKCOUNT32,numsectors); sdmmc_write16(REG_SDBLKLEN32,0x200); #endif sdmmc_write16(REG_SDBLKCOUNT,numsectors); handelSD.data = out; handelSD.size = numsectors << 9; sdmmc_send_command(&handelSD,0x33C12,sector_no); return geterror(&handelSD); }
int SD_Init() { inittarget(&handelSD); //waitcycles(0x3E8); waitcycles(0xF000); DEBUGPRINT(topScreen, "0x00000 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0,0); DEBUGPRINT(topScreen, "0x10408 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10408,0x1AA); //uint32_t temp = (handelSD.ret[0] == 0x1AA) << 0x1E; uint32_t temp = (handelSD.error & 0x1) << 0x1E; DEBUGPRINT(topScreen, "0x10769 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 15*8, RGB(40, 40, 40), RGB(208, 208, 208)); DEBUGPRINT(topScreen, "temp: ", temp, 10, 20 + 16*8, RGB(40, 40, 40), RGB(208, 208, 208)); //int count = 0; uint32_t temp2 = 0; do { do { sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10); sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp); temp2 = 1; } while ( !(handelSD.error & 1) ); //DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208)); //DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208)); //DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208)); } while((handelSD.ret[0] & 0x80000000) == 0); //do //{ // sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10); // sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp); // // DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208)); // DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208)); // DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208)); //} //while(!(handelSD.ret[0] & 0x80000000)); if(!((handelSD.ret[0] >> 30) & 1) || !temp) temp2 = 0; handelSD.isSDHC = temp2; //handelSD.isSDHC = (handelSD.ret[0] & 0x40000000); DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10602,0); if((handelSD.error & 0x4)) return -1; DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10403,0); if((handelSD.error & 0x4)) return -1; handelSD.initarg = handelSD.ret[0] >> 0x10; DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10); if((handelSD.error & 0x4)) return -1; handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1); handelSD.clk = 1; setckl(1); DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10); if((handelSD.error & 0x4)) return -1; DEBUGPRINT(topScreen, "0x10437 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10); if((handelSD.error & 0x4)) return -1; DEBUGPRINT(topScreen, "0x10446 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); handelSD.SDOPT = 1; sdmmc_send_command(&handelSD,0x10446,0x2); if((handelSD.error & 0x4)) return -1; DEBUGPRINT(topScreen, "0x1040D ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x1040D,handelSD.initarg << 0x10); if((handelSD.error & 0x4)) return -1; DEBUGPRINT(topScreen, "0x10410 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelSD,0x10410,0x200); if((handelSD.error & 0x4)) return -1; handelSD.clk |= 0x200; return 0; }
int Nand_Init() { inittarget(&handelNAND); waitcycles(0xF000); DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0,0); DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); do { do { sdmmc_send_command(&handelNAND,0x10701,0x100000); DEBUGPRINT(topScreen, "error ", handelNAND.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208)); DEBUGPRINT(topScreen, "ret: ", handelNAND.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208)); DEBUGPRINT(topScreen, "test ", 3, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208)); } while ( !(handelNAND.error & 1) ); } while((handelNAND.ret[0] & 0x80000000) == 0); DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0x10602,0x0); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0); handelNAND.clk = 1; setckl(1); sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); handelNAND.SDOPT = 1; sdmmc_send_command(&handelNAND,0x10506,0x3B70100); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0x10506,0x3B90100); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x1040D ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0x1040D,handelNAND.initarg << 0x10); if((handelNAND.error & 0x4))return -1; DEBUGPRINT(topScreen, "0x10410 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208)); sdmmc_send_command(&handelNAND,0x10410,0x200); if((handelNAND.error & 0x4))return -1; handelNAND.clk |= 0x200; inittarget(&handelSD); return 0; }
void InitSD() { //NAND handelNAND.isSDHC = 0; handelNAND.SDOPT = 0; handelNAND.res = 0; handelNAND.initarg = 1; handelNAND.clk = 0x80; handelNAND.devicenumber = 1; //SD handelSD.isSDHC = 0; handelSD.SDOPT = 0; handelSD.res = 0; handelSD.initarg = 0; handelSD.clk = 0x80; handelSD.devicenumber = 0; //sdmmc_mask16(0x100,0x800,0); //sdmmc_mask16(0x100,0x1000,0); //sdmmc_mask16(0x100,0x0,0x402); //sdmmc_mask16(0xD8,0x22,0x2); //sdmmc_mask16(0x100,0x2,0); //sdmmc_mask16(0xD8,0x22,0); //sdmmc_write16(0x104,0); //sdmmc_write16(0x108,1); //sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this //sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this //sdmmc_mask16(0x20,0,0x31D); //sdmmc_mask16(0x22,0,0x837F); //sdmmc_mask16(0xFC,0,0xDB); //sdmmc_mask16(0xFE,0,0xDB); ////sdmmc_write16(REG_SDCLKCTL,0x20); ////sdmmc_write16(REG_SDOPT,0x40EE); ////sdmmc_mask16(0x02,0x3,0); //sdmmc_write16(REG_SDCLKCTL,0x40); //sdmmc_write16(REG_SDOPT,0x40EB); //sdmmc_mask16(0x02,0x3,0); //sdmmc_write16(REG_SDBLKLEN,0x200); //sdmmc_write16(REG_SDSTOP,0); *(volatile uint16_t*)0x10006100 &= 0xF7FFu; //SDDATACTL32 *(volatile uint16_t*)0x10006100 &= 0xEFFFu; //SDDATACTL32 #ifdef DATA32_SUPPORT *(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32 #else *(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32 #endif *(volatile uint16_t*)0x100060D8 = (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2; #ifdef DATA32_SUPPORT *(volatile uint16_t*)0x10006100 &= 0xFFFFu; //SDDATACTL32 *(volatile uint16_t*)0x100060D8 &= 0xFFDFu; //SDDATACTL *(volatile uint16_t*)0x10006104 = 512; //SDBLKLEN32 #else *(volatile uint16_t*)0x10006100 &= 0xFFFDu; //SDDATACTL32 *(volatile uint16_t*)0x100060D8 &= 0xFFDDu; //SDDATACTL *(volatile uint16_t*)0x10006104 = 0; //SDBLKLEN32 #endif *(volatile uint16_t*)0x10006108 = 1; //SDBLKCOUNT32 *(volatile uint16_t*)0x100060E0 &= 0xFFFEu; //SDRESET *(volatile uint16_t*)0x100060E0 |= 1u; //SDRESET *(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0 *(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1 *(volatile uint16_t*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7 *(volatile uint16_t*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8 *(volatile uint16_t*)0x10006002 &= 0xFFFCu; //SDPORTSEL #ifdef DATA32_SUPPORT *(volatile uint16_t*)0x10006024 = 0x20; *(volatile uint16_t*)0x10006028 = 0x40EE; #else *(volatile uint16_t*)0x10006024 = 0x40; //Nintendo sets this to 0x20 *(volatile uint16_t*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE #endif *(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL *(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN *(volatile uint16_t*)0x10006008 = 0; //SDSTOP inittarget(&handelSD); }
uint32_t tmio_wrprotected(enum tmio_dev_id target) { inittarget(target); return tmio_read32(REG_SDSTATUS) & TMIO_STAT_WRPROTECT; }
uint32_t tmio_init_sdmc() { uint32_t resp; uint32_t r; if (tmio_dev[TMIO_DEV_SDMC].total_size > 0) return 0; //SD tmio_dev[TMIO_DEV_SDMC].isSDHC = 0; tmio_dev[TMIO_DEV_SDMC].SDOPT = 0; tmio_dev[TMIO_DEV_SDMC].res = 0; tmio_dev[TMIO_DEV_SDMC].initarg = 0; tmio_dev[TMIO_DEV_SDMC].clk = 0x80; inittarget(TMIO_DEV_SDMC); waitcycles(0xF000); tmio_send_command(MMC_IDLE,0,0); r = tmio_send_command(SD_SEND_IF_COND | TMIO_CMD_RESP_R1,0x1AA,1); if(r) return r; uint32_t temp = tmio_wait_respend() ? 0 : 0x1 << 0x1E; uint32_t temp2 = 0; do { while(1) { tmio_send_command(MMC_APP_CMD | TMIO_CMD_RESP_R1, tmio_dev[TMIO_DEV_SDMC].initarg << 0x10,0); temp2 = 1; if(tmio_send_command(SD_APP_OP_COND | TMIO_CMD_APP | TMIO_CMD_RESP_R3, 0x00FF8000 | temp,1)) continue; if(!tmio_wait_respend()) break; } resp = tmio_read32(REG_SDRESP0); } while((resp & 0x80000000) == 0); if(!((resp >> 30) & 1) || !temp) temp2 = 0; tmio_dev[TMIO_DEV_SDMC].isSDHC = temp2; tmio_send_command(MMC_ALL_SEND_CID | TMIO_CMD_RESP_R2,0,0); r = tmio_send_command(MMC_SET_RELATIVE_ADDR | TMIO_CMD_RESP_R1,0,1); if(r) return r; r = tmio_wait_respend(); if(r) return r; tmio_dev[TMIO_DEV_SDMC].initarg = tmio_read32(REG_SDRESP0) >> 0x10; tmio_send_command(MMC_SEND_CSD | TMIO_CMD_RESP_R2, tmio_dev[TMIO_DEV_SDMC].initarg << 0x10,0); r = tmio_wait_respend(); if(r) return r; tmio_dev[TMIO_DEV_SDMC].total_size = calcSDSize((uint8_t*)TMIO_BASE + REG_SDRESP0,-1); tmio_dev[TMIO_DEV_SDMC].clk = 1; setckl(1); tmio_send_command(MMC_SELECT_CARD | TMIO_CMD_RESP_R1B, tmio_dev[TMIO_DEV_SDMC].initarg << 0x10,0); r = tmio_send_command(MMC_APP_CMD | TMIO_CMD_RESP_R1, tmio_dev[TMIO_DEV_SDMC].initarg << 0x10,1); if(r) return r; tmio_dev[TMIO_DEV_SDMC].SDOPT = 1; r = tmio_send_command(MMC_SWITCH | TMIO_CMD_APP | TMIO_CMD_RESP_R1, 0x2,1); if(r) return r; r = tmio_send_command(MMC_SEND_STATUS | TMIO_CMD_RESP_R1, tmio_dev[TMIO_DEV_SDMC].initarg << 0x10,1); if(r) return r; r = tmio_send_command(MMC_SET_BLOCKLEN | TMIO_CMD_RESP_R1,TMIO_BBS,1); if(r) return r; tmio_dev[TMIO_DEV_SDMC].clk |= 0x200; return 0; }
uint32_t tmio_init_nand() { uint32_t r; if (tmio_dev[TMIO_DEV_NAND].total_size > 0) return 0; //NAND tmio_dev[TMIO_DEV_NAND].isSDHC = 0; tmio_dev[TMIO_DEV_NAND].SDOPT = 0; tmio_dev[TMIO_DEV_NAND].res = 0; tmio_dev[TMIO_DEV_NAND].initarg = 1; tmio_dev[TMIO_DEV_NAND].clk = 0x80; inittarget(TMIO_DEV_NAND); waitcycles(0xF000); tmio_send_command(MMC_IDLE,0,0); do { do tmio_send_command(MMC_SEND_OP_COND | TMIO_CMD_RESP_R3, 0x100000,0); while (tmio_wait_respend()); } while((tmio_read32(REG_SDRESP0) & 0x80000000) == 0); tmio_send_command(MMC_ALL_SEND_CID | TMIO_CMD_RESP_R2,0x0,0); r = tmio_send_command(MMC_SET_RELATIVE_ADDR | TMIO_CMD_RESP_R1, tmio_dev[TMIO_DEV_NAND].initarg << 0x10,1); if(r) return r; r = tmio_send_command(MMC_SEND_CSD | TMIO_CMD_RESP_R2, tmio_dev[TMIO_DEV_NAND].initarg << 0x10,1); if(r) return r; r = tmio_wait_respend(); if(r) return r; tmio_dev[TMIO_DEV_NAND].total_size = calcSDSize((uint8_t*)TMIO_BASE + REG_SDRESP0,0); tmio_dev[TMIO_DEV_NAND].clk = 1; setckl(1); tmio_send_command(MMC_SELECT_CARD | TMIO_CMD_RESP_R1, tmio_dev[TMIO_DEV_NAND].initarg << 0x10,0); tmio_dev[TMIO_DEV_NAND].SDOPT = 1; r = tmio_send_command(MMC_SWITCH | TMIO_CMD_RESP_R1B,0x3B70100,1); if(r) return r; r = tmio_send_command(MMC_SWITCH | TMIO_CMD_RESP_R1B,0x3B90100,1); if(r) return r; r = tmio_send_command(MMC_SEND_STATUS | TMIO_CMD_RESP_R1, tmio_dev[TMIO_DEV_NAND].initarg << 0x10,1); if(r) return r; r = tmio_send_command(MMC_SET_BLOCKLEN | TMIO_CMD_RESP_R1,TMIO_BBS,1); if(r) return r; tmio_dev[TMIO_DEV_NAND].clk |= 0x200; inittarget(TMIO_DEV_SDMC); return 0; }
uint32_t tmio_writesectors(enum tmio_dev_id target, uint32_t sector_no, uint32_t numsectors, uint8_t *in) { uint32_t error, mask; if(tmio_dev[target].isSDHC == 0) sector_no <<= 9; inittarget(target); tmio_write16(REG_SDSTOP,0x100); #ifdef DATA32_SUPPORT tmio_write16(REG_SDBLKCOUNT32,numsectors); tmio_write16(REG_SDBLKLEN32,TMIO_BBS); #endif tmio_write16(REG_SDBLKCOUNT,numsectors); mask = TMIO_MASK_GW; #ifdef DATA32_SUPPORT tmio_write16(REG_DATACTL32,TMIO32_ENABLE | TMIO32_IRQ_TXRQ); #else mask |= TMIO_STAT_RXRDY; #endif tmio_write32(REG_SDIRMASK,~mask); tmio_send_command(MMC_WRITE_BLOCK_MULTI | TMIO_CMD_RESP_R1 | TMIO_CMD_DATA_PRESENT | TMIO_CMD_TRANSFER_MULTI, sector_no, 0); #ifdef DATA32_SUPPORT uint32_t *dataPtr32 = (uint32_t*)in; #else uint16_t *dataPtr = (uint16_t*)in; #endif while(numsectors > 0) { tmio_wfi(); error = tmio_read32(REG_SDSTATUS) & TMIO_MASK_GW; if(error) return error; #ifdef DATA32_SUPPORT if((tmio_read16(REG_DATACTL32) & TMIO32_STAT_BUSY)) continue; #endif #ifdef DATA32_SUPPORT for(int i = 0; i<TMIO_BBS; i+=4) { tmio_write32(REG_SDFIFO32,*dataPtr32++); } #else for(int i = 0; i<TMIO_BBS; i+=2) { tmio_write16(REG_SDFIFO,*dataPtr++); } #endif numsectors--; } waitDataend = 1; return 0; }
uint32_t tmio_readsectors(enum tmio_dev_id target, uint32_t sector_no, uint32_t numsectors, uint8_t *out) { uint32_t error, mask; if(tmio_dev[target].isSDHC == 0) sector_no <<= 9; inittarget(target); tmio_write16(REG_SDSTOP,0x100); #ifdef DATA32_SUPPORT tmio_write16(REG_SDBLKCOUNT32,numsectors); tmio_write16(REG_SDBLKLEN32,TMIO_BBS); #endif tmio_write16(REG_SDBLKCOUNT,numsectors); mask = TMIO_MASK_GW; #ifdef DATA32_SUPPORT tmio_write16(REG_DATACTL32,TMIO32_ENABLE | TMIO32_IRQ_RXRDY); #else mask |= TMIO_STAT_RXRDY; #endif tmio_write32(REG_SDIRMASK,~mask); tmio_send_command(MMC_READ_BLOCK_MULTI | TMIO_CMD_RESP_R1 | TMIO_CMD_DATA_PRESENT | TMIO_CMD_TRANSFER_READ | TMIO_CMD_TRANSFER_MULTI, sector_no, 0); uint16_t *dataPtr = (uint16_t*)out; uint32_t *dataPtr32 = (uint32_t*)out; int useBuf32 = 0 == (3 & ((uint32_t)dataPtr)); while(numsectors > 0) { tmio_wfi(); error = tmio_read32(REG_SDSTATUS) & TMIO_MASK_GW; if(error) return error; #ifdef DATA32_SUPPORT if(!(tmio_read16(REG_DATACTL32) & TMIO32_STAT_RXRDY)) continue; #endif #ifdef DATA32_SUPPORT if(useBuf32) { for(int i = 0; i<TMIO_BBS; i+=4) { *dataPtr32++ = tmio_read32(REG_SDFIFO32); } } else { #endif for(int i = 0; i<TMIO_BBS; i+=2) { *dataPtr++ = tmio_read16(REG_SDFIFO); } #ifdef DATA32_SUPPORT } #endif numsectors--; } return 0; }