mirror of
https://github.com/parasyte/alt64
synced 2024-11-10 11:15:11 -05:00
597 lines
12 KiB
C
597 lines
12 KiB
C
|
|
#include "types.h"
|
|
#include "everdrive.h"
|
|
#include <libdragon.h>
|
|
#include <stdio.h>
|
|
#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;
|
|
}
|