#include "types.h" #include "everdrive.h" #include #include #include "sys.h" #include "errors.h" //#include "rom.h" #include "disk.h" #define CMD0 0x40 // software reset #define CMD1 0x41 // brings card out of idle state #define CMD2 0x42 // not used in SPI mode #define CMD3 0x43 // not used in SPI mode #define CMD4 0x44 // not used in SPI mode #define CMD5 0x45 // Reserved #define CMD6 0x46 // Reserved #define CMD7 0x47 // not used in SPI mode #define CMD8 0x48 // Reserved #define CMD9 0x49 // ask card to send card speficic data (CSD) #define CMD10 0x4A // ask card to send card identification (CID) #define CMD11 0x4B // not used in SPI mode #define CMD12 0x4C // stop transmission on multiple block read #define CMD13 0x4D // ask the card to send it's status register #define CMD14 0x4E // Reserved #define CMD15 0x4F // not used in SPI mode #define CMD16 0x50 // sets the block length used by the memory card #define CMD17 0x51 // read single block #define CMD18 0x52 // read multiple block #define CMD19 0x53 // Reserved #define CMD20 0x54 // not used in SPI mode #define CMD21 0x55 // Reserved #define CMD22 0x56 // Reserved #define CMD23 0x57 // Reserved #define CMD24 0x58 // writes a single block #define CMD25 0x59 // writes multiple blocks #define CMD26 0x5A // not used in SPI mode #define CMD27 0x5B // change the bits in CSD #define CMD28 0x5C // sets the write protection bit #define CMD29 0x5D // clears the write protection bit #define CMD30 0x5E // checks the write protection bit #define CMD31 0x5F // Reserved #define CMD32 0x60 // Sets the address of the first sector of the erase group #define CMD33 0x61 // Sets the address of the last sector of the erase group #define CMD34 0x62 // removes a sector from the selected group #define CMD35 0x63 // Sets the address of the first group #define CMD36 0x64 // Sets the address of the last erase group #define CMD37 0x65 // removes a group from the selected section #define CMD38 0x66 // erase all selected groups #define CMD39 0x67 // not used in SPI mode #define CMD40 0x68 // not used in SPI mode #define CMD41 0x69 // Reserved #define CMD42 0x6A // locks a block // CMD43 ... CMD57 are Reserved #define CMD58 0x7A // reads the OCR register #define CMD59 0x7B // turns CRC off // CMD60 ... CMD63 are not used in SPI mode #define ED_STATE_DMA_BUSY 0 #define ED_STATE_DMA_TOUT 1 #define ED_STATE_TXE 2 #define ED_STATE_RXF 3 #define ED_STATE_SPI 4 #define SPI_CFG_SPD0 0 #define SPI_CFG_SPD1 1 #define SPI_CFG_SS 2 #define SPI_CFG_RD 3 #define SPI_CFG_DAT 4 #define SPI_CFG_1BIT 5 #define SAV_EEP_ON 0 #define SAV_SRM_ON 1 #define SAV_EEP_SIZE 2 #define SAV_SRM_SIZE 3 //was missing //#define BI_SPI_SPD_LO 0 #define BI_SPI_SPD_LO 2 // around 200khz (only for sd initialization) #define BI_SPI_SPD_25 1 #define BI_SPI_SPD_50 0 void evd_setSpiSpeed(u8 speed); u8 evd_mmcCmd(u8 cmd, u32 arg); u8 sd_mode; volatile u8 spi_cfg; volatile u8 evd_cfg; u8 sd_type; volatile u32 *regs_ptr = (u32 *) 0xA8040000; /* result[2] <= ad[15:8] == {ad[6], ad[1], ad[0], ad[7], ad[5], ad[4], ad[3], ad[2]} ^ 8'h37 ^ prv[7:0]; prv[7:0] <= ad[15:8]; */ void (*dma_busy_callback)(); void evd_setDmaAddr(u32 addr) { } inline u32 bi_reg_rd(u32 reg) { *(vu32 *) (REGS_BASE); return *(vu32 *) (REGS_BASE + reg * 4); } inline void bi_reg_wr(u32 reg, u32 data) { *(vu32 *) (REGS_BASE); *(vu32 *) (REGS_BASE + reg * 4) = data; } void bi_init() { evd_cfg = ED_CFG_SDRAM_ON; spi_cfg = 0 | BI_SPI_SPD_LO; bi_reg_wr(REG_KEY, 0x1234); bi_reg_wr(REG_CFG, evd_cfg); bi_reg_wr(REG_SPI_CFG, spi_cfg); } void bi_speed50() { spi_cfg = 0 | BI_SPI_SPD_50; bi_reg_wr(REG_KEY, 0x1234); bi_reg_wr(REG_SPI_CFG, spi_cfg); } void bi_speed25() { spi_cfg = 0 | BI_SPI_SPD_25; bi_reg_wr(REG_KEY, 0x1234); bi_reg_wr(REG_SPI_CFG, spi_cfg); } void bi_load_firmware(u8 *firm) { u32 i; u16 f_ctr = 0; evd_cfg &= ~ED_CFG_SDRAM_ON; bi_reg_wr(REG_CFG, evd_cfg); bi_reg_wr(REG_CFG_CNT, 0); sleep(10); bi_reg_wr(REG_CFG_CNT, 1); sleep(10); i = 0; for (;;) { bi_reg_wr(REG_CFG_DAT, *(u16 *) & firm[i]); while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0); f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0; if (f_ctr >= 47)break; f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0; if (f_ctr >= 47)break; } while ((bi_reg_rd(REG_CFG_CNT) & 4) == 0) { bi_reg_wr(REG_CFG_DAT, 0xffff); while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0); } sleep(20); bi_init(); } void evd_init() { volatile u8 val; sd_mode = 0; dma_busy_callback = 0; sleep(1); val = regs_ptr[0]; spi_cfg = (0 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1) | (1 << SPI_CFG_SS); evd_cfg = (1 << ED_CFG_SDRAM_ON); val = regs_ptr[0]; regs_ptr[REG_KEY] = 0x1234; val = regs_ptr[0]; regs_ptr[REG_CFG] = evd_cfg; val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; evd_fifoRxf(); if (!evd_fifoRxf()) { val = regs_ptr[0]; regs_ptr[REG_DMA_LEN] = 7; //clean 16k val = regs_ptr[0]; regs_ptr[REG_DMA_RAM_ADDR] = (ROM_LEN - 0x200000) / 2048; val = regs_ptr[0]; regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM; while (evd_isDmaBusy()); } } void evd_ulockRegs(){ volatile u8 val; val = regs_ptr[0]; regs_ptr[REG_KEY] = 0x1234; } void evd_lockRegs() { volatile u8 val; val = regs_ptr[0]; regs_ptr[REG_KEY] = 0; } u8 evd_fifoRxf() { u16 val; //regs_ptr[REG_STATE]++; val = regs_ptr[REG_STATUS]; return (val >> ED_STATE_RXF) & 1; } u8 evd_fifoTxe() { u16 val; //regs_ptr[REG_STATE]++; val = regs_ptr[REG_STATUS]; return (val >> ED_STATE_TXE) & 1; } u8 evd_isDmaBusy() { u16 val; //volatile u32 i; sleep(1); if(dma_busy_callback != 0)dma_busy_callback(); //regs_ptr[REG_STATE]++; val = regs_ptr[REG_STATUS]; return (val >> ED_STATE_DMA_BUSY) & 1; } u8 evd_isDmaTimeout() { u16 val; //regs_ptr[REG_STATE]++; val = regs_ptr[REG_STATUS]; return (val >> ED_STATE_DMA_TOUT) & 1; } u8 evd_fifoRdToCart(u32 cart_addr, u16 blocks) { volatile u8 val; cart_addr /= 2048; val = regs_ptr[0]; regs_ptr[REG_DMA_LEN] = (blocks - 1); val = regs_ptr[0]; regs_ptr[REG_DMA_RAM_ADDR] = cart_addr; val = regs_ptr[0]; regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM; while (evd_isDmaBusy()); if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; return 0; } u8 evd_fifoWrFromCart(u32 cart_addr, u16 blocks) { volatile u8 val; cart_addr /= 2048; val = regs_ptr[0]; regs_ptr[REG_DMA_LEN] = (blocks - 1); val = regs_ptr[0]; regs_ptr[REG_DMA_RAM_ADDR] = cart_addr; val = regs_ptr[0]; regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO; while (evd_isDmaBusy()); if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; return 0; } u8 evd_fifoRd(void *buff, u16 blocks) { volatile u8 val; u32 len = blocks == 0 ? 65536 * 512 : blocks * 512; u32 ram_buff_addr = DMA_BUFF_ADDR / 2048; //(ROM_LEN - len - 65536 * 4) / 2048; val = regs_ptr[0]; regs_ptr[REG_DMA_LEN] = (blocks - 1); val = regs_ptr[0]; regs_ptr[REG_DMA_RAM_ADDR] = ram_buff_addr; val = regs_ptr[0]; regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM; while (evd_isDmaBusy()); dma_read_s(buff, (0xb0000000 + ram_buff_addr * 2048), len); if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; return 0; } u8 evd_fifoWr(void *buff, u16 blocks) { volatile u8 val; u32 len = blocks == 0 ? 65536 * 512 : blocks * 512; u32 ram_buff_addr = DMA_BUFF_ADDR / 2048; //(ROM_LEN - len - 65536 * 4) / 2048; dma_write_s(buff, (0xb0000000 + ram_buff_addr * 1024 * 2), len); val = regs_ptr[0]; regs_ptr[REG_DMA_LEN] = (blocks - 1); val = regs_ptr[0]; regs_ptr[REG_DMA_RAM_ADDR] = ram_buff_addr; val = regs_ptr[0]; regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO; while (evd_isDmaBusy()); if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT; return 0; } u8 evd_isSpiBusy() { volatile u16 val; regs_ptr[REG_STATUS]; val = regs_ptr[REG_STATUS]; return (val >> ED_STATE_SPI) & 1; } u8 evd_SPI(u8 dat) { volatile u8 val; val = regs_ptr[0]; regs_ptr[REG_SPI] = dat; while (evd_isSpiBusy()); //osInvalICache((u32*) & regs_ptr[REG_SPI], 1); val = regs_ptr[REG_SPI]; return val; } void evd_spiSSOn() { volatile u8 val; if (sd_mode)return; spi_cfg &= ~(1 << SPI_CFG_SS); val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } void evd_spiSSOff() { volatile u8 val; spi_cfg |= (1 << SPI_CFG_SS); val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } void evd_enableSDMode() { sd_mode = 1; } void evd_enableSPIMode() { sd_mode = 0; } u8 evd_isSDMode() { return sd_mode; } void evd_SDcmdWriteMode(u8 bit1_mode) { volatile u8 val; if (!sd_mode)return; spi_cfg &= ~((1 << SPI_CFG_RD) | (1 << SPI_CFG_DAT)); if (bit1_mode) { spi_cfg |= (1 << SPI_CFG_1BIT); } else { spi_cfg &= ~(1 << SPI_CFG_1BIT); } val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } void evd_SDcmdReadMode(u8 bit1_mode) { volatile u8 val; if (!sd_mode)return; spi_cfg |= (1 << SPI_CFG_RD); spi_cfg &= ~(1 << SPI_CFG_DAT); if (bit1_mode) { spi_cfg |= (1 << SPI_CFG_1BIT); } else { spi_cfg &= ~(1 << SPI_CFG_1BIT); } val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } void evd_SDdatWriteMode(u8 bit4_mode) { volatile u8 val; if (!sd_mode)return; spi_cfg &= ~(1 << SPI_CFG_RD); spi_cfg |= (1 << SPI_CFG_DAT); if (bit4_mode) { spi_cfg |= (1 << SPI_CFG_1BIT); } else { spi_cfg &= ~(1 << SPI_CFG_1BIT); } val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } void evd_SDdatReadMode(u8 bit4_mode) { volatile u8 val; if (!sd_mode)return; spi_cfg |= (1 << SPI_CFG_RD) | (1 << SPI_CFG_DAT); if (bit4_mode) { spi_cfg |= (1 << SPI_CFG_1BIT); } else { spi_cfg &= ~(1 << SPI_CFG_1BIT); } val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } void evd_setSpiSpeed(u8 speed) { volatile u8 val; spi_cfg &= ~3; //((1 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1)); spi_cfg |= speed & 3; val = regs_ptr[0]; regs_ptr[REG_SPI_CFG] = spi_cfg; } u8 evd_mmcReadToCart(u32 cart_addr, u32 len) { volatile u8 val; cart_addr /= 2048; val = regs_ptr[0]; regs_ptr[REG_DMA_LEN] = (len - 1); val = regs_ptr[0]; regs_ptr[REG_DMA_RAM_ADDR] = cart_addr; val = regs_ptr[0]; regs_ptr[REG_DMA_CFG] = DCFG_SD_TO_RAM; while (evd_isDmaBusy()); if (evd_isDmaTimeout())return EVD_ERROR_MMC_TIMEOUT; return 0; } void evd_setCfgBit(u8 option, u8 state) { volatile u8 val; if (state)evd_cfg |= (1 << option); else evd_cfg &= ~(1 << option); val = regs_ptr[0]; regs_ptr[REG_CFG] = evd_cfg; val = regs_ptr[0]; } u16 evd_readReg(u8 reg) { volatile u32 tmp; tmp = regs_ptr[0]; return regs_ptr[reg]; } void evd_setSaveType(u8 type) { u8 eeprom_on, sram_on, eeprom_size, sram_size; eeprom_on = 0; sram_on = 0; eeprom_size = 0; sram_size = 0; switch (type) { case SAVE_TYPE_EEP16k: eeprom_on = 1; eeprom_size = 1; break; case SAVE_TYPE_EEP4k: eeprom_on = 1; break; case SAVE_TYPE_SRAM: sram_on = 1; break; case SAVE_TYPE_SRAM128: sram_on = 1; sram_size = 1; break; case SAVE_TYPE_FLASH: sram_on = 0; sram_size = 1; break; default: sram_on = 0; sram_size = 0; break; } volatile u8 val; val = regs_ptr[0]; regs_ptr[REG_SAV_CFG] = (eeprom_on << SAV_EEP_ON | sram_on << SAV_SRM_ON | eeprom_size << SAV_EEP_SIZE | sram_size << SAV_SRM_SIZE); } void evd_writeReg(u8 reg, u16 val) { volatile u8 tmp; tmp = regs_ptr[0]; regs_ptr[reg] = val; } void evd_mmcSetDmaSwap(u8 state) { evd_setCfgBit(ED_CFG_SWAP, state); } void evd_writeMsg(u8 dat) { evd_writeReg(REG_MSG, dat); } u8 evd_readMsg() { return evd_readReg(REG_MSG); } u16 evd_getFirmVersion() { return evd_readReg(REG_VER); } void evd_setDmaCallback(void (*callback)()) { dma_busy_callback = callback; }