Update sd_* API for flexibility and performance.
This commit is contained in:
@@ -602,6 +602,10 @@ int FileWriteAdv(fileTYPE *file, void *pBuffer, int length, int failres)
|
||||
printf("FileWriteAdv error(%d).\n", ret);
|
||||
return failres;
|
||||
}
|
||||
|
||||
file->offset += ret;
|
||||
if (file->offset > file->size) file->size = FileGetSize(file);
|
||||
return ret;
|
||||
}
|
||||
else if (file->zip)
|
||||
{
|
||||
@@ -613,9 +617,6 @@ int FileWriteAdv(fileTYPE *file, void *pBuffer, int length, int failres)
|
||||
printf("FileWriteAdv error(unknown file type).\n");
|
||||
return failres;
|
||||
}
|
||||
|
||||
file->offset += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int FileWriteSec(fileTYPE *file, void *pBuffer)
|
||||
|
||||
18
spi.cpp
18
spi.cpp
@@ -103,13 +103,13 @@ void spi_uio_cmd32_cont(uint8_t cmd, uint32_t parm)
|
||||
}
|
||||
|
||||
/* User_io related SPI functions */
|
||||
uint8_t spi_uio_cmd_cont(uint8_t cmd)
|
||||
uint16_t spi_uio_cmd_cont(uint8_t cmd)
|
||||
{
|
||||
EnableIO();
|
||||
return spi_b(cmd);
|
||||
return spi_w(cmd);
|
||||
}
|
||||
|
||||
uint8_t spi_uio_cmd(uint8_t cmd)
|
||||
uint16_t spi_uio_cmd(uint8_t cmd)
|
||||
{
|
||||
uint8_t res = spi_uio_cmd_cont(cmd);
|
||||
DisableIO();
|
||||
@@ -192,14 +192,14 @@ void spi_write(const uint8_t *addr, uint16_t len, int wide)
|
||||
}
|
||||
}
|
||||
|
||||
void spi_block_read(uint8_t *addr, int wide)
|
||||
void spi_block_read(uint8_t *addr, int wide, int sz)
|
||||
{
|
||||
if (wide) fpga_spi_fast_block_read((uint16_t*)addr, 256);
|
||||
else fpga_spi_fast_block_read_8(addr, 512);
|
||||
if (wide) fpga_spi_fast_block_read((uint16_t*)addr, sz/2);
|
||||
else fpga_spi_fast_block_read_8(addr, sz);
|
||||
}
|
||||
|
||||
void spi_block_write(const uint8_t *addr, int wide)
|
||||
void spi_block_write(const uint8_t *addr, int wide, int sz)
|
||||
{
|
||||
if (wide) fpga_spi_fast_block_write((const uint16_t*)addr, 256);
|
||||
else fpga_spi_fast_block_write_8(addr, 512);
|
||||
if (wide) fpga_spi_fast_block_write((const uint16_t*)addr, sz/2);
|
||||
else fpga_spi_fast_block_write_8(addr, sz);
|
||||
}
|
||||
|
||||
8
spi.h
8
spi.h
@@ -41,8 +41,8 @@ uint32_t spi32_w(uint32_t parm);
|
||||
/* block transfer functions */
|
||||
void spi_read(uint8_t *addr, uint16_t len, int wide);
|
||||
void spi_write(const uint8_t *addr, uint16_t len, int wide);
|
||||
void spi_block_read(uint8_t *addr, int wide);
|
||||
void spi_block_write(const uint8_t *addr, int wide);
|
||||
void spi_block_read(uint8_t *addr, int wide, int sz = 512);
|
||||
void spi_block_write(const uint8_t *addr, int wide, int sz = 512);
|
||||
|
||||
/* OSD related SPI functions */
|
||||
void EnableOsd_on(int target);
|
||||
@@ -52,8 +52,8 @@ void spi_osd_cmd8_cont(uint8_t cmd, uint8_t parm);
|
||||
void spi_osd_cmd8(uint8_t cmd, uint8_t parm);
|
||||
|
||||
/* User_io related SPI functions */
|
||||
uint8_t spi_uio_cmd_cont(uint8_t cmd);
|
||||
uint8_t spi_uio_cmd(uint8_t cmd);
|
||||
uint16_t spi_uio_cmd_cont(uint8_t cmd);
|
||||
uint16_t spi_uio_cmd(uint8_t cmd);
|
||||
uint8_t spi_uio_cmd8_cont(uint8_t cmd, uint8_t parm);
|
||||
uint8_t spi_uio_cmd8(uint8_t cmd, uint8_t parm);
|
||||
uint16_t spi_uio_cmd16(uint8_t cmd, uint16_t parm);
|
||||
|
||||
341
user_io.cpp
341
user_io.cpp
@@ -39,9 +39,12 @@
|
||||
static char core_path[1024] = {};
|
||||
static char rbf_path[1024] = {};
|
||||
|
||||
static fileTYPE sd_image[4] = {};
|
||||
static int sd_image_cangrow[4] = {};
|
||||
static uint64_t buffer_lba[4] = { ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,ULLONG_MAX };
|
||||
static fileTYPE sd_image[16] = {};
|
||||
static int sd_image_cangrow[16] = {};
|
||||
static uint64_t buffer_lba[16] = { ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,
|
||||
ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,
|
||||
ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,
|
||||
ULLONG_MAX,ULLONG_MAX,ULLONG_MAX,ULLONG_MAX };
|
||||
|
||||
static int use_save = 0;
|
||||
|
||||
@@ -1343,42 +1346,6 @@ void user_io_sd_set_config(void)
|
||||
*/
|
||||
}
|
||||
|
||||
// read 8+32 bit sd card status word from FPGA
|
||||
uint16_t user_io_sd_get_status(uint32_t *lba, uint16_t *req_type)
|
||||
{
|
||||
uint32_t s;
|
||||
uint16_t c;
|
||||
uint16_t req = 0;
|
||||
|
||||
spi_uio_cmd_cont(UIO_GET_SDSTAT);
|
||||
if (io_ver)
|
||||
{
|
||||
c = spi_w(0);
|
||||
s = spi_w(0);
|
||||
s = (s & 0xFFFF) | (((uint32_t)spi_w(0))<<16);
|
||||
req = spi_w(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//note: using 32bit big-endian transfer!
|
||||
c = spi_in();
|
||||
s = spi_in();
|
||||
s = (s << 8) | spi_in();
|
||||
s = (s << 8) | spi_in();
|
||||
s = (s << 8) | spi_in();
|
||||
req = spi_in();
|
||||
}
|
||||
DisableIO();
|
||||
|
||||
if (lba)
|
||||
*lba = s;
|
||||
|
||||
if (req)
|
||||
*req_type = req;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// read 8 bit keyboard LEDs status from FPGA
|
||||
uint16_t user_io_kbdled_get_status(void)
|
||||
{
|
||||
@@ -2626,179 +2593,211 @@ void user_io_poll()
|
||||
|
||||
while (1)
|
||||
{
|
||||
const int buf_sz = 16;
|
||||
static uint8_t buffer[4][buf_sz * 512];
|
||||
uint32_t lba;
|
||||
uint16_t req_type = 0;
|
||||
uint16_t c = user_io_sd_get_status(&lba, &req_type);
|
||||
//if(c&3) printf("user_io_sd_get_status: cmd=%02x, lba=%08x\n", c, lba);
|
||||
int disk = -1;
|
||||
int ack = 0;
|
||||
int op = 0;
|
||||
static uint8_t buffer[16][16384];
|
||||
uint64_t lba;
|
||||
uint32_t blkpow = 9;
|
||||
uint32_t sz = 512;
|
||||
uint32_t blksz = 1;
|
||||
|
||||
// valid sd commands start with "5x" to avoid problems with
|
||||
// cores that don't implement this command
|
||||
if ((c & 0xf0) == 0x50)
|
||||
uint16_t c = spi_uio_cmd_cont(UIO_GET_SDSTAT);
|
||||
if (c & 0x8000)
|
||||
{
|
||||
// check if core requests configuration
|
||||
if ((c & 0xC) == 0xC)
|
||||
disk = (c >> 2) & 0xF;
|
||||
op = c & 3;
|
||||
ack = disk << 8;
|
||||
spi_w(0);
|
||||
lba = spi_w(0);
|
||||
lba = (lba & 0xFFFF) | (((uint32_t)spi_w(0)) << 16);
|
||||
blkpow = 7 + ((c >> 6) & 7);
|
||||
blksz = (((c >> 9) & 0x3F) + 1);
|
||||
sz = blksz << blkpow;
|
||||
if (sz > sizeof(buffer[0]))
|
||||
{
|
||||
printf("core requests SD config\n");
|
||||
user_io_sd_set_config();
|
||||
sz = sizeof(buffer[0]);
|
||||
blksz = sz >> blkpow;
|
||||
}
|
||||
|
||||
if (c & 0x3802)
|
||||
//if (op) printf("c=%X, op=%d, blkpow=%d, sz=%d, lba=%llu, disk=%d\n", c, op, blkpow, sz, lba, disk);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = spi_w(0);
|
||||
if ((c & 0xf0) == 0x50 && (c & 0x3F03))
|
||||
{
|
||||
int disk = 3;
|
||||
if (c & 0x0002) disk = 0;
|
||||
else if (c & 0x0800) disk = 1;
|
||||
else if (c & 0x1000) disk = 2;
|
||||
lba = spi_w(0);
|
||||
lba = (lba & 0xFFFF) | (((uint32_t)spi_w(0)) << 16);
|
||||
|
||||
//printf("SD WR %d on %d\n", lba, disk);
|
||||
|
||||
if (use_save) menu_process_save();
|
||||
|
||||
buffer_lba[disk] = -1;
|
||||
|
||||
// Fetch sector data from FPGA ...
|
||||
EnableIO();
|
||||
spi_w(UIO_SECTOR_WR | ((c & 4) ? 0 : ((disk + 1) << 8)));
|
||||
spi_block_read(buffer[disk], fio_size);
|
||||
DisableIO();
|
||||
|
||||
if (sd_image[disk].type == 2 && !lba)
|
||||
// check if core requests configuration
|
||||
if ((c & 0xC) == 0xC)
|
||||
{
|
||||
//Create the file
|
||||
if (FileOpenEx(&sd_image[disk], sd_image[disk].path, O_CREAT | O_RDWR | O_SYNC))
|
||||
printf("core requests SD config\n");
|
||||
user_io_sd_set_config();
|
||||
}
|
||||
|
||||
if (c & 0x0003)
|
||||
{
|
||||
disk = 0;
|
||||
op = (c & 1) ? 1 : 2;
|
||||
}
|
||||
else if (c & 0x0900)
|
||||
{
|
||||
disk = 1;
|
||||
op = (c & 0x100) ? 1 : 2;
|
||||
}
|
||||
else if (c & 0x1200)
|
||||
{
|
||||
disk = 2;
|
||||
op = (c & 0x200) ? 1 : 2;
|
||||
}
|
||||
else if (c & 0x2400)
|
||||
{
|
||||
disk = 3;
|
||||
op = (c & 0x400) ? 1 : 2;
|
||||
}
|
||||
|
||||
ack = ((c & 4) ? 0 : ((disk + 1) << 8));
|
||||
}
|
||||
}
|
||||
DisableIO();
|
||||
|
||||
if (op == 2)
|
||||
{
|
||||
//printf("SD WR %d on %d\n", lba, disk);
|
||||
|
||||
if (use_save) menu_process_save();
|
||||
|
||||
buffer_lba[disk] = -1;
|
||||
|
||||
// Fetch sector data from FPGA ...
|
||||
EnableIO();
|
||||
spi_w(UIO_SECTOR_WR | ack);
|
||||
spi_block_read(buffer[disk], fio_size, sz);
|
||||
DisableIO();
|
||||
|
||||
if (sd_image[disk].type == 2 && !lba)
|
||||
{
|
||||
//Create the file
|
||||
if (FileOpenEx(&sd_image[disk], sd_image[disk].path, O_CREAT | O_RDWR | O_SYNC))
|
||||
{
|
||||
diskled_on();
|
||||
if (FileWriteSec(&sd_image[disk], buffer[disk]))
|
||||
{
|
||||
diskled_on();
|
||||
if (FileWriteSec(&sd_image[disk], buffer[disk]))
|
||||
{
|
||||
sd_image[disk].size = 512;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error in creating file: %s\n", sd_image[disk].path);
|
||||
sd_image[disk].size = sz;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ... and write it to disk
|
||||
__off64_t size = sd_image[disk].size >> 9;
|
||||
if (size && lba <= size)
|
||||
printf("Error in creating file: %s\n", sd_image[disk].path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ... and write it to disk
|
||||
uint64_t size = sd_image[disk].size >> blkpow;
|
||||
if (size && lba <= size)
|
||||
{
|
||||
diskled_on();
|
||||
if (FileSeek(&sd_image[disk], lba << blkpow, SEEK_SET))
|
||||
{
|
||||
diskled_on();
|
||||
if (FileSeekLBA(&sd_image[disk], lba))
|
||||
if (!sd_image_cangrow[disk])
|
||||
{
|
||||
int sz = 512;
|
||||
if (!sd_image_cangrow[disk])
|
||||
{
|
||||
__off64_t rem = sd_image[disk].size - sd_image[disk].offset;
|
||||
sz = (rem >= 512) ? 512 : (int)rem;
|
||||
}
|
||||
if(sz && FileWriteAdv(&sd_image[disk], buffer[disk], sz))
|
||||
{
|
||||
if (size == lba && sd_image_cangrow[disk])
|
||||
{
|
||||
size++;
|
||||
sd_image[disk].size = size << 9;
|
||||
}
|
||||
}
|
||||
__off64_t rem = sd_image[disk].size - sd_image[disk].offset;
|
||||
sz = (rem >= sz) ? sz : (int)rem;
|
||||
}
|
||||
|
||||
if (sz) FileWriteAdv(&sd_image[disk], buffer[disk], sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c & 0x0701)
|
||||
}
|
||||
else if (op & 1)
|
||||
{
|
||||
uint32_t buf_n = sizeof(buffer[0]) >> blkpow;
|
||||
//printf("SD RD (%llu,%d) on %d, WIDE=%d\n", lba, sz, disk, fio_size);
|
||||
|
||||
int done = 0;
|
||||
uint32_t offset;
|
||||
|
||||
if ((buffer_lba[disk] == (uint64_t)-1) || lba < buffer_lba[disk] || (lba + blksz - buffer_lba[disk]) > buf_n)
|
||||
{
|
||||
int disk = 3;
|
||||
if (c & 0x0001) disk = 0;
|
||||
else if (c & 0x0100) disk = 1;
|
||||
else if (c & 0x0200) disk = 2;
|
||||
|
||||
//printf("SD RD %d on %d, WIDE=%d\n", lba, disk, fio_size);
|
||||
|
||||
int done = 0;
|
||||
uint32_t offset;
|
||||
|
||||
if ((buffer_lba[disk] == (uint64_t)-1) || lba < buffer_lba[disk] || lba >(buffer_lba[disk] + buf_sz - 1))
|
||||
buffer_lba[disk] = -1;
|
||||
if (sd_image[disk].size)
|
||||
{
|
||||
buffer_lba[disk] = -1;
|
||||
if (sd_image[disk].size)
|
||||
diskled_on();
|
||||
if (FileSeek(&sd_image[disk], lba << blkpow, SEEK_SET))
|
||||
{
|
||||
diskled_on();
|
||||
if (FileSeekLBA(&sd_image[disk], lba))
|
||||
if (FileReadAdv(&sd_image[disk], buffer[disk], sizeof(buffer[disk])))
|
||||
{
|
||||
if (FileReadAdv(&sd_image[disk], buffer[disk], sizeof(buffer[disk])))
|
||||
{
|
||||
done = 1;
|
||||
buffer_lba[disk] = lba;
|
||||
}
|
||||
done = 1;
|
||||
buffer_lba[disk] = lba;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Even after error we have to provide the block to the core
|
||||
//Give an empty block.
|
||||
if (!done)
|
||||
//Even after error we have to provide the block to the core
|
||||
//Give an empty block.
|
||||
if (!done)
|
||||
{
|
||||
if (sd_image[disk].type == 2)
|
||||
{
|
||||
if (sd_image[disk].type == 2)
|
||||
if (is_megacd())
|
||||
{
|
||||
if (is_megacd())
|
||||
mcd_fill_blanksave(buffer[disk], lba);
|
||||
}
|
||||
else if (is_pce())
|
||||
{
|
||||
memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
if (!lba)
|
||||
{
|
||||
mcd_fill_blanksave(buffer[disk], lba);
|
||||
}
|
||||
else if (is_pce())
|
||||
{
|
||||
memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
if (!lba)
|
||||
{
|
||||
memcpy(buffer[disk], "HUBM\x00\x88\x10\x80", 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer[disk], -1, sizeof(buffer[disk]));
|
||||
memcpy(buffer[disk], "HUBM\x00\x88\x10\x80", 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
memset(buffer[disk], -1, sizeof(buffer[disk]));
|
||||
}
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (lba - buffer_lba[disk])*512;
|
||||
done = 1;
|
||||
}
|
||||
|
||||
//hexdump(buffer, 32, 0);
|
||||
|
||||
// data is now stored in buffer. send it to fpga
|
||||
EnableIO();
|
||||
spi_w(UIO_SECTOR_RD | ((c & 4) ? 0 : ((disk + 1) << 8)));
|
||||
spi_block_write(buffer[disk] + offset, fio_size);
|
||||
DisableIO();
|
||||
|
||||
if (sd_image[disk].type == 2)
|
||||
{
|
||||
buffer_lba[disk] = -1;
|
||||
}
|
||||
else if(done && (lba == (buffer_lba[disk] + buf_sz - 1)))
|
||||
{
|
||||
diskled_on();
|
||||
if (FileReadAdv(&sd_image[disk], buffer[disk], sizeof(buffer[disk])))
|
||||
{
|
||||
buffer_lba[disk] += buf_sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
buffer_lba[disk] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (lba - buffer_lba[disk]) << blkpow;
|
||||
done = 1;
|
||||
}
|
||||
|
||||
// data is now stored in buffer. send it to fpga
|
||||
EnableIO();
|
||||
spi_w(UIO_SECTOR_RD | ack);
|
||||
spi_block_write(buffer[disk] + offset, fio_size, sz);
|
||||
DisableIO();
|
||||
|
||||
if (sd_image[disk].type == 2)
|
||||
{
|
||||
buffer_lba[disk] = -1;
|
||||
}
|
||||
else if(done && (lba + blksz - buffer_lba[disk]) == buf_n)
|
||||
{
|
||||
diskled_on();
|
||||
if (FileReadAdv(&sd_image[disk], buffer[disk], sizeof(buffer[disk])))
|
||||
{
|
||||
buffer_lba[disk] += buf_n;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buffer[disk], 0, sizeof(buffer[disk]));
|
||||
buffer_lba[disk] = -1;
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user