Skip to content

Commit

Permalink
debug: add support for reading from SD to SDRAM in flashcarts
Browse files Browse the repository at this point in the history
Normally, reading from SD cards involve first issuing a flashcart-specific
command to read SD contents into SDRAM (which is mapped in PI space
as "ROM"), and then run a PI DMA transfer to copy contents into RDRAM,
just like the data was in ROM.

There are use cases in which there is no need for the second half: the
data can stay in SDRAM and be consumed from that. A common one is
flashcart menus that want to load a ROM to boot, and don't need data
to go into RDRAM (it wouldn't even fit).

This commit adds support to this use case by simply checking if the
pointer provided to disk_read (and thus, to fread() by the user) is
in RDRAM or in a PI-mapped space, and calling a new flashcart hook
in the latter case.

This is implemented for now on 64drive and SC64.
  • Loading branch information
rasky committed Feb 3, 2023
1 parent e686c60 commit 215b32f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 10 deletions.
8 changes: 7 additions & 1 deletion src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ typedef struct
DSTATUS (*disk_initialize)(void);
DSTATUS (*disk_status)(void);
DRESULT (*disk_read)(BYTE* buff, LBA_t sector, UINT count);
DRESULT (*disk_read_sdram)(BYTE* buff, LBA_t sector, UINT count);
DRESULT (*disk_write)(const BYTE* buff, LBA_t sector, UINT count);
DRESULT (*disk_ioctl)(BYTE cmd, void* buff);
} fat_disk_t;
Expand All @@ -162,8 +163,10 @@ DSTATUS disk_status(BYTE pdrv)

DRESULT disk_read(BYTE pdrv, BYTE* buff, LBA_t sector, UINT count)
{
if (fat_disks[pdrv].disk_read)
if (fat_disks[pdrv].disk_read && PhysicalAddr(buff) < 0x00800000)
return fat_disks[pdrv].disk_read(buff, sector, count);
if (fat_disks[pdrv].disk_read_sdram && io_accessible(PhysicalAddr(buff)))
return fat_disks[pdrv].disk_read_sdram(buff, sector, count);
return RES_PARERR;
}

Expand Down Expand Up @@ -203,6 +206,7 @@ static fat_disk_t fat_disk_everdrive =
fat_disk_initialize_everdrive,
fat_disk_status_default,
fat_disk_read_everdrive,
NULL,
fat_disk_write_everdrive,
fat_disk_ioctl_default
};
Expand All @@ -212,6 +216,7 @@ static fat_disk_t fat_disk_64drive =
fat_disk_initialize_64drive,
fat_disk_status_default,
fat_disk_read_64drive,
fat_disk_read_sdram_64drive,
fat_disk_write_64drive,
fat_disk_ioctl_default
};
Expand All @@ -221,6 +226,7 @@ static fat_disk_t fat_disk_sc64 =
fat_disk_initialize_sc64,
fat_disk_status_default,
fat_disk_read_sc64,
fat_disk_read_sdram_sc64,
fat_disk_write_sc64,
fat_disk_ioctl_default
};
Expand Down
50 changes: 41 additions & 9 deletions src/debug_sdfs_64drive.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#define D64_CIBASE_ADDRESS 0xB8000000
#define D64_BUFFER 0x00000000
#define D64_REGISTER_SDRAM 0x00000004
#define D64_REGISTER_STATUS 0x00000200
#define D64_REGISTER_COMMAND 0x00000208
#define D64_REGISTER_LBA 0x00000210
Expand All @@ -23,11 +24,48 @@
extern int8_t usb_64drive_wait(void);
extern void usb_64drive_setwritable(int8_t enable);

static void sd_abort_64drive(void)
{
// Operation is taking too long. Probably SD was not inserted.
// Send a COMMAND_ABORT and SD_RESET, and return I/O error.
// Note that because of a 64drive firmware bug, this is not
// sufficient to unblock the 64drive. The USB channel will stay
// unresponsive. We don't currently have a workaround for this.
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_COMMAND, D64_COMMAND_ABORT);
usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_COMMAND, D64_COMMAND_SD_RESET);
usb_64drive_wait();
}

static DRESULT fat_disk_read_sdram_64drive(BYTE* buff, LBA_t sector, UINT count)
{
_Static_assert(FF_MIN_SS == 512, "this function assumes sector size == 512");
_Static_assert(FF_MAX_SS == 512, "this function assumes sector size == 512");

usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_LBA, sector);
usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_LENGTH, count);
usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_SDRAM, PhysicalAddr(buff) >> 1);
usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_COMMAND, D64_COMMAND_SD_READ);
if (usb_64drive_wait() != 0)
{
debugf("[debug] fat_disk_read_sdram_64drive: wait timeout\n");
sd_abort_64drive();
return FR_DISK_ERR;
}
return RES_OK;
}

static DRESULT fat_disk_read_64drive(BYTE* buff, LBA_t sector, UINT count)
{
_Static_assert(FF_MIN_SS == 512, "this function assumes sector size == 512");
_Static_assert(FF_MAX_SS == 512, "this function assumes sector size == 512");

usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_LENGTH, 1);
for (int i=0;i<count;i++)
{
usb_64drive_wait();
Expand All @@ -37,15 +75,7 @@ static DRESULT fat_disk_read_64drive(BYTE* buff, LBA_t sector, UINT count)
if (usb_64drive_wait() != 0)
{
debugf("[debug] fat_disk_read_64drive: wait timeout\n");
// Operation is taking too long. Probably SD was not inserted.
// Send a COMMAND_ABORT and SD_RESET, and return I/O error.
// Note that because of a 64drive firmware bug, this is not
// sufficient to unblock the 64drive. The USB channel will stay
// unresponsive. We don't currently have a workaround for this.
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_COMMAND, D64_COMMAND_ABORT);
usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_COMMAND, D64_COMMAND_SD_RESET);
usb_64drive_wait();
sd_abort_64drive();
return FR_DISK_ERR;
}

Expand All @@ -61,6 +91,8 @@ static DRESULT fat_disk_write_64drive(const BYTE* buff, LBA_t sector, UINT count
_Static_assert(FF_MIN_SS == 512, "this function assumes sector size == 512");
_Static_assert(FF_MAX_SS == 512, "this function assumes sector size == 512");

usb_64drive_wait();
io_write(D64_CIBASE_ADDRESS + D64_REGISTER_LENGTH, 1);
for (int i=0;i<count;i++)
{
if (((uint32_t)buff & 7) == 0)
Expand Down
9 changes: 9 additions & 0 deletions src/debug_sdfs_sc64.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ static DRESULT fat_disk_read_sc64(BYTE* buff, LBA_t sector, UINT count)
return RES_OK;
}

static DRESULT fat_disk_read_sdram_sc64(BYTE* buff, LBA_t sector, UINT count)
{
_Static_assert(FF_MIN_SS == 512, "this function assumes sector size == 512");
_Static_assert(FF_MAX_SS == 512, "this function assumes sector size == 512");
if (sc64_sd_read_sectors((uint32_t)buff, sector, count))
return FR_DISK_ERR;
return RES_OK;
}

static DRESULT fat_disk_write_sc64(const BYTE* buff, LBA_t sector, UINT count)
{
_Static_assert(FF_MIN_SS == 512, "this function assumes sector size == 512");
Expand Down

0 comments on commit 215b32f

Please sign in to comment.