mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
super slow usb storage reading implemented
This commit is contained in:
parent
388a872a8c
commit
8410cbe191
@ -84,7 +84,6 @@ module cpu_cfg (
|
||||
end else begin
|
||||
if (sys.n64_soft_reset) begin
|
||||
cfg.sdram_switch <= skip_bootloader;
|
||||
cfg.sdram_writable <= 1'b0;
|
||||
end
|
||||
if (cfg.cmd_request) begin
|
||||
cfg.cpu_busy <= 1'b1;
|
||||
|
@ -222,4 +222,5 @@ exception_disable_watchdog:
|
||||
li $t1, ~(C0_SR_IM7)
|
||||
and $t0, $t0, $t1
|
||||
mtc0 $t0, C0_STATUS
|
||||
mtc0 $zero, C0_COMPARE
|
||||
jr $ra
|
||||
|
@ -217,7 +217,6 @@ static void exception_vprint (const char *fmt, va_list args) {
|
||||
|
||||
vsniprintf(line, sizeof(line), fmt, args);
|
||||
exception_print_string(line);
|
||||
sc64_uart_print_string(line);
|
||||
}
|
||||
|
||||
static void exception_print (const char* fmt, ...) {
|
||||
@ -276,7 +275,9 @@ void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask,
|
||||
|
||||
if (exception_code == EXCEPTION_INTERRUPT) {
|
||||
if (interrupt_mask & INTERRUPT_MASK_TIMER) {
|
||||
exception_print("Bootloader did not finish within 1 second limit\n\n");
|
||||
exception_disable_watchdog();
|
||||
exception_print("Still loading after 1 second limit...\n\n");
|
||||
return;
|
||||
}
|
||||
} else if (exception_code == EXCEPTION_SYSCALL) {
|
||||
uint32_t code = (((*instruction_address) & SYSCALL_CODE_MASK) >> SYSCALL_CODE_BIT);
|
||||
|
@ -3,24 +3,42 @@
|
||||
#include "../sc64.h"
|
||||
|
||||
|
||||
DSTATUS status[__DRIVE_COUNT] = { STA_NOINIT, STA_NOINIT };
|
||||
|
||||
|
||||
DSTATUS disk_status (BYTE pdrv) {
|
||||
return 0;
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
return STA_NODISK;
|
||||
}
|
||||
return status[pdrv];
|
||||
}
|
||||
|
||||
DSTATUS disk_initialize (BYTE pdrv) {
|
||||
return 0;
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
return STA_NODISK;
|
||||
}
|
||||
if (!sc64_storage_init((drive_id_t) (pdrv))) {
|
||||
status[pdrv] &= ~(STA_NOINIT);
|
||||
}
|
||||
return status[pdrv];
|
||||
}
|
||||
|
||||
DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
||||
if (sc64_storage_read(pdrv, buff, sector, count)) {
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if (sc64_storage_read((drive_id_t) (pdrv), buff, sector, count)) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
#ifndef FF_FS_READONLY
|
||||
#if !FF_FS_READONLY
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
||||
if (sc64_storage_write(pdrv, buff, sector, count)) {
|
||||
if (pdrv >= __DRIVE_COUNT) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if (sc64_storage_write((drive_id_t) (pdrv), buff, sector, count)) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
return RES_OK;
|
||||
|
@ -8,14 +8,14 @@
|
||||
/ Function Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_FS_READONLY 1
|
||||
#define FF_FS_READONLY 0
|
||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||
/ and optional writing functions as well. */
|
||||
|
||||
|
||||
#define FF_FS_MINIMIZE 2
|
||||
#define FF_FS_MINIMIZE 1
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: Basic functions are fully enabled.
|
||||
@ -34,7 +34,7 @@
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 0
|
||||
#define FF_USE_FASTSEEK 1
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#define FF_USE_LFN 1
|
||||
#define FF_USE_LFN 2
|
||||
#define FF_MAX_LFN 255
|
||||
/* The FF_USE_LFN switches the support for LFN (long file name).
|
||||
/
|
||||
|
@ -56,6 +56,99 @@ void sc64_get_info (sc64_info_t *info) {
|
||||
info->boot_mode = (boot_mode_t) sc64_query_config(CFG_ID_BOOT_MODE);
|
||||
}
|
||||
|
||||
void sc64_init (void) {
|
||||
while (!sc64_check_presence());
|
||||
sc64_wait_cpu_ready();
|
||||
sc64_change_config(CFG_ID_SDRAM_SWITCH, true);
|
||||
}
|
||||
|
||||
static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
||||
uint32_t args[2] = { drive, 0 };
|
||||
uint32_t result[2];
|
||||
do {
|
||||
sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result);
|
||||
} while (result[0]);
|
||||
return result[1];
|
||||
}
|
||||
|
||||
bool sc64_storage_init (drive_id_t drive) {
|
||||
uint32_t args[2] = { drive, 0 };
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sc64_drive_start_read_and_wait (drive_id_t drive, uint32_t sector) {
|
||||
uint32_t args[2] = { drive, sector };
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_READ, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sc64_drive_start_write_and_wait (drive_id_t drive, uint32_t sector) {
|
||||
uint32_t args[2] = { drive, sector };
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_WRITE, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count) {
|
||||
io32_t *src = SC64->BUFFER;
|
||||
uint8_t *dst = (uint8_t *) (buffer);
|
||||
|
||||
while (count > 0) {
|
||||
if (sc64_drive_start_read_and_wait(drive, sector)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||
uint32_t data = pi_io_read(src + i);
|
||||
*dst++ = ((data >> 24) & 0xFF);
|
||||
*dst++ = ((data >> 16) & 0xFF);
|
||||
*dst++ = ((data >> 8) & 0xFF);
|
||||
*dst++ = ((data >> 0) & 0xFF);
|
||||
}
|
||||
sector += 1;
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) {
|
||||
uint8_t *src = (uint8_t *) (buffer);
|
||||
io32_t *dst = SC64->BUFFER;
|
||||
|
||||
while (count > 0) {
|
||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||
uint32_t data = 0;
|
||||
data |= ((*src++) << 24);
|
||||
data |= ((*src++) << 16);
|
||||
data |= ((*src++) << 8);
|
||||
data |= ((*src++) << 0);
|
||||
pi_io_write((dst + i), data);
|
||||
}
|
||||
if (sc64_drive_start_write_and_wait(drive, sector)) {
|
||||
return true;
|
||||
}
|
||||
sector += 1;
|
||||
count -= 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void sc64_uart_put_char (char c) {
|
||||
#ifdef DEBUG
|
||||
uint32_t args[2] = { (uint32_t) (c), 0 };
|
||||
@ -68,84 +161,3 @@ void sc64_uart_print_string (const char *text) {
|
||||
sc64_uart_put_char (*text++);
|
||||
}
|
||||
}
|
||||
|
||||
void sc64_init (void) {
|
||||
while (!sc64_check_presence());
|
||||
sc64_wait_cpu_ready();
|
||||
sc64_change_config(CFG_ID_SDRAM_SWITCH, true);
|
||||
sc64_uart_print_string("\033c");
|
||||
}
|
||||
|
||||
static bool sc64_wait_drive_ready (uint8_t drive) {
|
||||
bool error;
|
||||
uint32_t args[2] = { drive, 0 };
|
||||
uint32_t result[2];
|
||||
do {
|
||||
error = sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result);
|
||||
} while (!result[0]);
|
||||
return error;
|
||||
}
|
||||
|
||||
static bool sc64_drive_read_sector (uint8_t drive, void *buffer, uint32_t sector) {
|
||||
io32_t *src = SC64->BUFFER;
|
||||
uint8_t *dst = (uint8_t *) (buffer);
|
||||
uint32_t args[2] = { drive, sector };
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_READ, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < SECTOR_SIZE; i += sizeof(uint32_t)) {
|
||||
uint32_t data = pi_io_read(src++);
|
||||
*dst++ = ((data >> 24) & 0xFF);
|
||||
*dst++ = ((data >> 16) & 0xFF);
|
||||
*dst++ = ((data >> 8) & 0xFF);
|
||||
*dst++ = ((data >> 0) & 0xFF);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sc64_storage_read (uint8_t drive, void *buffer, uint32_t sector, uint32_t count) {
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (sc64_drive_read_sector(drive, buffer, (sector + i))) {
|
||||
return true;
|
||||
}
|
||||
buffer += SECTOR_SIZE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool sc64_drive_write_sector (uint8_t drive, void *buffer, uint32_t sector) {
|
||||
uint8_t *src = (uint8_t *) (buffer);
|
||||
io32_t *dst = SC64->BUFFER;
|
||||
uint32_t args[2] = { drive, sector };
|
||||
uint32_t data;
|
||||
if (sc64_wait_drive_ready(drive)) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < SECTOR_SIZE; i += sizeof(uint32_t)) {
|
||||
data = ((*src++) << 24);
|
||||
data |= ((*src++) << 16);
|
||||
data |= ((*src++) << 8);
|
||||
data |= ((*src++) << 0);
|
||||
pi_io_write(dst++, data);
|
||||
}
|
||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_WRITE, args, NULL)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sc64_storage_write (uint8_t drive, void *buffer, uint32_t sector, uint32_t count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (sc64_drive_write_sector(drive, buffer, (sector + i))) {
|
||||
return true;
|
||||
}
|
||||
buffer += SECTOR_SIZE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -9,9 +9,10 @@
|
||||
|
||||
#define SC64_CMD_QUERY ('Q')
|
||||
#define SC64_CMD_CONFIG ('C')
|
||||
#define SC64_CMD_DRIVE_BUSY (0xF0)
|
||||
#define SC64_CMD_DRIVE_READ (0xF1)
|
||||
#define SC64_CMD_DRIVE_WRITE (0xF2)
|
||||
#define SC64_CMD_DRIVE_INIT (0xF0)
|
||||
#define SC64_CMD_DRIVE_BUSY (0xF1)
|
||||
#define SC64_CMD_DRIVE_READ (0xF2)
|
||||
#define SC64_CMD_DRIVE_WRITE (0xF3)
|
||||
#define SC64_CMD_UART_PUT (0xFF)
|
||||
|
||||
#define SC64_VERSION_2 (0x53437632)
|
||||
@ -38,16 +39,6 @@ typedef enum {
|
||||
CFG_ID_IS_VIEWER_ENABLE,
|
||||
} cfg_id_t;
|
||||
|
||||
typedef enum {
|
||||
SAVE_TYPE_NONE = 0,
|
||||
SAVE_TYPE_EEPROM_4K = 1,
|
||||
SAVE_TYPE_EEPROM_16K = 2,
|
||||
SAVE_TYPE_SRAM = 3,
|
||||
SAVE_TYPE_FLASHRAM = 4,
|
||||
SAVE_TYPE_SRAM_BANKED = 5,
|
||||
SAVE_TYPE_FLASHRAM_PKST2 = 6,
|
||||
} save_type_t;
|
||||
|
||||
typedef enum {
|
||||
CIC_SEED_UNKNOWN = 0xFFFF,
|
||||
} cic_seed_t;
|
||||
@ -73,15 +64,22 @@ typedef struct {
|
||||
tv_type_t tv_type;
|
||||
} sc64_info_t;
|
||||
|
||||
typedef enum {
|
||||
DRIVE_SD = 0,
|
||||
DRIVE_USB = 1,
|
||||
__DRIVE_COUNT = 2
|
||||
} drive_id_t;
|
||||
|
||||
|
||||
bool sc64_check_presence (void);
|
||||
uint32_t sc64_query_config (cfg_id_t id);
|
||||
void sc64_change_config (cfg_id_t id, uint32_t value);
|
||||
void sc64_get_info (sc64_info_t *info);
|
||||
void sc64_uart_print_string (const char *text);
|
||||
void sc64_init (void);
|
||||
bool sc64_storage_read (uint8_t drive, void *buffer, uint32_t sector, uint32_t count);
|
||||
bool sc64_storage_write (uint8_t drive, void *buffer, uint32_t sector, uint32_t count);
|
||||
bool sc64_storage_init (drive_id_t drive);
|
||||
bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count);
|
||||
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count);
|
||||
void sc64_uart_print_string (const char *text);
|
||||
|
||||
|
||||
#endif
|
||||
|
129
sw/pc/sc64.py
129
sw/pc/sc64.py
@ -19,6 +19,7 @@ class SC64Exception(Exception):
|
||||
|
||||
|
||||
class SC64:
|
||||
__CFG_ID_SDRAM_WRITABLE = 2
|
||||
__CFG_ID_DD_ENABLE = 3
|
||||
__CFG_ID_SAVE_TYPE = 4
|
||||
__CFG_ID_CIC_SEED = 5
|
||||
@ -45,12 +46,12 @@ class SC64:
|
||||
__DDIPL_ROM_LENGTH = 0x400000
|
||||
|
||||
__DEBUG_ID_TEXT = 0x01
|
||||
__DEBUG_ID_FSD_READ = 0xF1
|
||||
__DEBUG_ID_FSD_WRITE = 0xF2
|
||||
__DEBUG_ID_FSD_SECTOR = 0xF3
|
||||
__DEBUG_ID_INTERNAL = 0xFE
|
||||
__INTERNAL_ID_IS_VIEWER = 0
|
||||
__INTERNAL_ID_DD_BLOCK = 1
|
||||
__DEBUG_ID_EVENT = 0xFE
|
||||
|
||||
__EVENT_ID_FSD_READ = 0
|
||||
__EVENT_ID_FSD_WRITE = 1
|
||||
__EVENT_ID_DD_BLOCK = 2
|
||||
__EVENT_ID_IS_VIEWER = 3
|
||||
|
||||
__DD_DRIVE_ID_RETAIL = 3
|
||||
__DD_DRIVE_ID_DEVELOPMENT = 4
|
||||
@ -67,6 +68,7 @@ class SC64:
|
||||
self.__fsd_file = None
|
||||
self.__disk_file = None
|
||||
self.__disk_lba_table = []
|
||||
self.__dd_turbo = False
|
||||
self.__isv_line_buffer = bytearray()
|
||||
self.__find_sc64()
|
||||
|
||||
@ -187,11 +189,6 @@ class SC64:
|
||||
self.__read_cmd_status("C")
|
||||
|
||||
|
||||
def __debug_write(self, type: int, data: bytes) -> None:
|
||||
self.__write_cmd("D", type, len(data))
|
||||
self.__write(data)
|
||||
|
||||
|
||||
def __read_file_from_sdram(self, file: str, offset: int, length: int, align: int = 2) -> None:
|
||||
with open(file, "wb") as f:
|
||||
transfer_size = self.__align(length, align)
|
||||
@ -543,27 +540,53 @@ class SC64:
|
||||
raise SC64Exception("No DD disk file provided for disk info creation")
|
||||
|
||||
|
||||
def __debug_process_fsd_set_sector(self, data: bytes) -> None:
|
||||
sector = int.from_bytes(data[0:4], byteorder='big')
|
||||
def __debug_process_fsd_read(self, data: bytes) -> None:
|
||||
sector = int.from_bytes(data[0:4], byteorder='little')
|
||||
if (self.__fsd_file):
|
||||
self.__fsd_file.seek(sector * 512)
|
||||
|
||||
|
||||
def __debug_process_fsd_read(self, data: bytes) -> None:
|
||||
length = int.from_bytes(data[0:4], byteorder='big')
|
||||
if (self.__fsd_file):
|
||||
self.__debug_write(self.__DEBUG_ID_FSD_READ, self.__fsd_file.read(length))
|
||||
self.__write_cmd("T", 0, 512)
|
||||
self.__write(self.__fsd_file.read(512))
|
||||
else:
|
||||
self.__debug_write(self.__DEBUG_ID_FSD_READ, bytes(length))
|
||||
self.__write_cmd("T", 0, 0)
|
||||
|
||||
|
||||
def __debug_process_fsd_write(self, data: bytes) -> None:
|
||||
sector = int.from_bytes(data[0:4], byteorder='little')
|
||||
if (self.__fsd_file):
|
||||
self.__fsd_file.write(data)
|
||||
self.__fsd_file.seek(sector * 512)
|
||||
self.__write_cmd("F", 0, 512)
|
||||
self.__fsd_file.write(self.__read(512))
|
||||
else:
|
||||
self.__write_cmd("F", 0, 0)
|
||||
|
||||
|
||||
def __debug_process_dd_block(self, data: bytes) -> None:
|
||||
transfer_mode = int.from_bytes(data[0:4], byteorder='little')
|
||||
sdram_offset = int.from_bytes(data[4:8], byteorder='little')
|
||||
disk_file_offset = int.from_bytes(data[8:12], byteorder='big')
|
||||
block_length = int.from_bytes(data[12:16], byteorder='little')
|
||||
|
||||
if (self.__disk_file):
|
||||
self.__disk_file.seek(disk_file_offset)
|
||||
if (transfer_mode):
|
||||
if (not self.__dd_turbo):
|
||||
# Fixes weird bug in Mario Artist Paint Studio prototype minigame
|
||||
time.sleep(0.016)
|
||||
self.__write_cmd("S", sdram_offset, block_length)
|
||||
self.__write(self.__disk_file.read(block_length))
|
||||
else:
|
||||
self.__write_cmd("L", sdram_offset, block_length)
|
||||
self.__disk_file.write(self.__read(block_length))
|
||||
|
||||
|
||||
def __debug_process_is_viewer(self, data: bytes) -> None:
|
||||
self.__isv_line_buffer.extend(data)
|
||||
length = int.from_bytes(data[0:4], byteorder='little')
|
||||
address = int.from_bytes(data[4:8], byteorder='little')
|
||||
offset = (address & 0x01)
|
||||
transfer_length = self.__align(length + offset, 2)
|
||||
self.__write_cmd("L", (address & 0xFFFFFFFE), transfer_length)
|
||||
text = self.__read(transfer_length)[offset:][:length]
|
||||
self.__isv_line_buffer.extend(text)
|
||||
try:
|
||||
while (len(self.__isv_line_buffer) > 0):
|
||||
line_end = self.__isv_line_buffer.index(b'\n')
|
||||
@ -574,48 +597,32 @@ class SC64:
|
||||
pass
|
||||
|
||||
|
||||
def __debug_process_dd_block(self, data: bytes) -> None:
|
||||
transfer_mode = int.from_bytes(data[0:4], byteorder='big')
|
||||
sdram_offset = int.from_bytes(data[4:8], byteorder='big')
|
||||
disk_file_offset = int.from_bytes(data[8:12], byteorder='big')
|
||||
block_length = int.from_bytes(data[12:16], byteorder='big')
|
||||
def __debug_process_event(self, event_data: bytes) -> None:
|
||||
id = int.from_bytes(event_data[0:4], byteorder="big")
|
||||
data = event_data[4:]
|
||||
|
||||
print(f"64DD Block {'R' if transfer_mode else 'W'} - LBA: {self.__disk_lba_table.index(disk_file_offset):4}, Offset: 0x{disk_file_offset:08X}")
|
||||
|
||||
if (self.__disk_file):
|
||||
self.__disk_file.seek(disk_file_offset)
|
||||
if (transfer_mode):
|
||||
time.sleep(0.016) # Fixes weird bug in Mario Artist Paint Studio minigame
|
||||
self.__write_cmd("S", sdram_offset, block_length)
|
||||
self.__write(self.__disk_file.read(block_length))
|
||||
else:
|
||||
write_data = data[16:]
|
||||
self.__disk_file.write(write_data)
|
||||
|
||||
|
||||
def __debug_process_internal(self, internal_data: bytes) -> None:
|
||||
id = internal_data[0]
|
||||
start_alignmnet = internal_data[1]
|
||||
length = int.from_bytes(internal_data[2:4], byteorder="big")
|
||||
data = internal_data[(4 + start_alignmnet):][:length]
|
||||
|
||||
if (id == self.__INTERNAL_ID_IS_VIEWER):
|
||||
self.__debug_process_is_viewer(data)
|
||||
elif (id == self.__INTERNAL_ID_DD_BLOCK):
|
||||
if (id == self.__EVENT_ID_FSD_READ):
|
||||
self.__debug_process_fsd_read(data)
|
||||
elif (id == self.__EVENT_ID_FSD_WRITE):
|
||||
self.__debug_process_fsd_write(data)
|
||||
elif (id == self.__EVENT_ID_DD_BLOCK):
|
||||
self.__debug_process_dd_block(data)
|
||||
elif (id == self.__EVENT_ID_IS_VIEWER):
|
||||
self.__debug_process_is_viewer(data)
|
||||
|
||||
|
||||
def debug_init(self, fsd_file: str = None, disk_file: str = None, is_viewer_enabled: bool = False) -> None:
|
||||
def debug_init(self, fsd_file: str = None, disk_file: str = None, dd_turbo: bool = False) -> None:
|
||||
if (fsd_file):
|
||||
self.__fsd_file = open(fsd_file, "rb+")
|
||||
|
||||
if (disk_file):
|
||||
self.__disk_file = open(disk_file, "rb+")
|
||||
self.__dd_turbo = dd_turbo
|
||||
|
||||
|
||||
def debug_loop(self, is_viewer_enabled: bool = False) -> None:
|
||||
self.__change_config(self.__CFG_ID_SDRAM_WRITABLE, is_viewer_enabled)
|
||||
self.__change_config(self.__CFG_ID_IS_VIEWER_ENABLE, is_viewer_enabled)
|
||||
|
||||
|
||||
def debug_loop(self) -> None:
|
||||
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
||||
|
||||
start_indicator = bytearray()
|
||||
@ -645,14 +652,8 @@ class SC64:
|
||||
else:
|
||||
if (id == self.__DEBUG_ID_TEXT):
|
||||
print(data.decode(encoding="ascii", errors="backslashreplace"), end="")
|
||||
elif (id == self.__DEBUG_ID_FSD_READ):
|
||||
self.__debug_process_fsd_read(data)
|
||||
elif (id == self.__DEBUG_ID_FSD_WRITE):
|
||||
self.__debug_process_fsd_write(data)
|
||||
elif (id == self.__DEBUG_ID_FSD_SECTOR):
|
||||
self.__debug_process_fsd_set_sector(data)
|
||||
elif (id == self.__DEBUG_ID_INTERNAL):
|
||||
self.__debug_process_internal(data)
|
||||
elif (id == self.__DEBUG_ID_EVENT):
|
||||
self.__debug_process_event(data)
|
||||
else:
|
||||
print(f"\033[35mGot unknown id: {id}, length: {length}\033[0m", file=sys.stderr)
|
||||
|
||||
@ -722,6 +723,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("-c", metavar="cic_seed", default="0xFFFF", required=False, help="set CIC seed")
|
||||
parser.add_argument("-s", metavar="save_type", default="0", required=False, help="set save type (0 - 6)")
|
||||
parser.add_argument("-d", default=False, action="store_true", required=False, help="enable 64DD emulation")
|
||||
parser.add_argument("-df", default=False, action="store_true", required=False, help="set 64DD emulation to turbo mode")
|
||||
parser.add_argument("-r", default=False, action="store_true", required=False, help="perform reading operation instead of writing")
|
||||
parser.add_argument("-l", metavar="length", default="0x101000", required=False, help="specify ROM length to read")
|
||||
parser.add_argument("-u", metavar="update_path", default=None, required=False, help="path to update file")
|
||||
@ -747,6 +749,7 @@ if __name__ == "__main__":
|
||||
tv_type = int(args.t)
|
||||
cic_seed = int(args.c, 0)
|
||||
dd_enable = args.d
|
||||
dd_turbo = args.df
|
||||
is_read = args.r
|
||||
rom_length = int(args.l, 0)
|
||||
update_file = args.u
|
||||
@ -818,7 +821,7 @@ if __name__ == "__main__":
|
||||
sc64.reset_n64()
|
||||
|
||||
if (debug_server):
|
||||
sc64.debug_init(sd_file, disk_file, is_viewer_enabled)
|
||||
sc64.debug_init(sd_file, disk_file, dd_turbo)
|
||||
if (is_viewer_enabled):
|
||||
print(f"Setting IS-Viewer 64 emulation to [Enabled]")
|
||||
if (sd_file):
|
||||
@ -828,7 +831,7 @@ if __name__ == "__main__":
|
||||
sc64.set_dd_configuration_for_disk(disk_file)
|
||||
print(f"Setting 64DD disk state to [Changed]")
|
||||
sc64.set_dd_disk_state("changed" if disk_file else "ejected")
|
||||
sc64.debug_loop()
|
||||
sc64.debug_loop(is_viewer_enabled)
|
||||
|
||||
except SC64Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
@ -66,6 +66,7 @@ struct process {
|
||||
uint16_t cic_seed;
|
||||
uint8_t tv_type;
|
||||
enum boot_mode boot_mode;
|
||||
bool usb_drive_busy;
|
||||
};
|
||||
|
||||
static struct process p;
|
||||
@ -79,6 +80,10 @@ static void change_scr_bits (uint32_t mask, bool value) {
|
||||
}
|
||||
}
|
||||
|
||||
static void set_usb_drive_not_busy (void) {
|
||||
p.usb_drive_busy = false;
|
||||
}
|
||||
|
||||
static void set_save_type (enum save_type save_type) {
|
||||
uint32_t save_offset = DEFAULT_SAVE_OFFSET;
|
||||
|
||||
@ -252,6 +257,7 @@ void cfg_init (void) {
|
||||
p.cic_seed = 0xFFFF;
|
||||
p.tv_type = 0x03;
|
||||
p.boot_mode = BOOT_MODE_MENU_SD;
|
||||
p.usb_drive_busy = false;
|
||||
}
|
||||
|
||||
|
||||
@ -273,38 +279,66 @@ void process_cfg (void) {
|
||||
cfg_query(args);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
args[0] = usb_debug_tx_ready();
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (!usb_debug_tx_data(args[0], (size_t) args[1])) {
|
||||
case 0xF0:
|
||||
if (args[0] == 0) {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if (args[0] == 1) {
|
||||
p.usb_drive_busy = false;
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
if (!usb_debug_rx_ready(&args[0], (size_t *) (&args[1]))) {
|
||||
case 0xF1:
|
||||
if (args[0] == 0) {
|
||||
args[0] = 0;
|
||||
args[1] = 0;
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if (args[0] == 1) {
|
||||
args[0] = p.usb_drive_busy;
|
||||
} else {
|
||||
args[0] = 0;
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
}
|
||||
args[1] = 0;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
args[0] = usb_debug_rx_busy();
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
if (!usb_debug_rx_data(args[0], (size_t) args[1])) {
|
||||
case 0xF2:
|
||||
if ((args[0] & 0xFF) == 0) {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_FSD_READ;
|
||||
event.trigger = CALLBACK_BUFFER_WRITE;
|
||||
event.callback = set_usb_drive_not_busy;
|
||||
if (usb_put_event(&event, &args[1], sizeof(args[1]))) {
|
||||
p.usb_drive_busy = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
usb_debug_reset();
|
||||
case 0xF3:
|
||||
if ((args[0] & 0xFF) == 0) {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_FSD_WRITE;
|
||||
event.trigger = CALLBACK_BUFFER_READ;
|
||||
event.callback = set_usb_drive_not_busy;
|
||||
if (usb_put_event(&event, &args[1], sizeof(args[1]))) {
|
||||
p.usb_drive_busy = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
case 0xFF:
|
||||
uart_put((char) (args[0] & 0xFF));
|
||||
break;
|
||||
|
||||
|
@ -84,35 +84,36 @@ static bool dd_block_valid (void) {
|
||||
return (p.thb_table[dd_track_head_block()] != 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static bool dd_block_request (void) {
|
||||
if (!usb_internal_debug_tx_ready()) {
|
||||
return false;
|
||||
}
|
||||
static void dd_set_block_ready (void) {
|
||||
p.block_ready = true;
|
||||
}
|
||||
|
||||
if (!(DD->SCR & DD_SCR_DISK_INSERTED)) {
|
||||
static bool dd_block_request (void) {
|
||||
if (!(DD->SCR & DD_SCR_DISK_INSERTED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
io32_t offset = p.thb_table[dd_track_head_block()];
|
||||
uint32_t length = ((DD->SECTOR_SIZE + 1) * DD_USER_SECTORS_PER_BLOCK);
|
||||
size_t transfer_length = 16;
|
||||
|
||||
io32_t *dst = (io32_t *) (DD_USB_BUFFER_OFFSET);
|
||||
uint32_t data[4] = {
|
||||
p.transfer_mode,
|
||||
(uint32_t) (p.block_buffer),
|
||||
offset,
|
||||
length,
|
||||
};
|
||||
|
||||
*dst++ = SWAP32(p.transfer_mode);
|
||||
*dst++ = SWAP32((uint32_t) (p.block_buffer));
|
||||
*dst++ = offset;
|
||||
*dst++ = SWAP32(length);
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_DD_BLOCK;
|
||||
event.trigger = p.transfer_mode ? CALLBACK_SDRAM_WRITE : CALLBACK_SDRAM_READ;
|
||||
event.callback = dd_set_block_ready;
|
||||
|
||||
if (!p.transfer_mode) {
|
||||
transfer_length += length;
|
||||
if (usb_put_event(&event, data, sizeof(data))) {
|
||||
p.block_ready = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
usb_internal_debug_tx_data(INT_DBG_ID_DD_BLOCK, DD_USB_BUFFER_OFFSET, transfer_length);
|
||||
|
||||
p.block_ready = false;
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dd_block_ready (void) {
|
||||
@ -120,11 +121,7 @@ static bool dd_block_ready (void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p.transfer_mode) {
|
||||
return p.block_ready;
|
||||
} else {
|
||||
return usb_internal_debug_tx_ready();
|
||||
}
|
||||
return p.block_ready;
|
||||
}
|
||||
|
||||
static void dd_sector_read (void) {
|
||||
@ -191,10 +188,6 @@ uint16_t dd_get_drive_id (void) {
|
||||
return DD->DRIVE_ID;
|
||||
}
|
||||
|
||||
void dd_set_block_ready (bool value) {
|
||||
p.block_ready = value;
|
||||
}
|
||||
|
||||
void dd_set_thb_table_offset (uint32_t offset) {
|
||||
p.thb_table = (io32_t *) (SDRAM_BASE + offset);
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ void dd_set_drive_id (uint16_t id);
|
||||
uint16_t dd_get_drive_id (void);
|
||||
void dd_set_thb_table_offset (uint32_t offset);
|
||||
uint32_t dd_get_thb_table_offset (void);
|
||||
void dd_set_block_ready (bool value);
|
||||
void dd_init (void);
|
||||
void process_dd (void);
|
||||
|
||||
|
@ -17,6 +17,7 @@ typedef struct {
|
||||
|
||||
struct process {
|
||||
bool enabled;
|
||||
bool ready;
|
||||
uint32_t current_read_pointer;
|
||||
is_viewer_t *ISV;
|
||||
};
|
||||
@ -26,6 +27,7 @@ struct process p;
|
||||
|
||||
void isv_set_enabled (bool enabled) {
|
||||
p.enabled = enabled;
|
||||
p.ready = true;
|
||||
}
|
||||
|
||||
bool isv_get_enabled (void) {
|
||||
@ -35,10 +37,15 @@ bool isv_get_enabled (void) {
|
||||
|
||||
void isv_init (void) {
|
||||
p.enabled = false;
|
||||
p.ready = true;
|
||||
p.current_read_pointer = 0;
|
||||
p.ISV = (is_viewer_t *) (IS64_OFFSET);
|
||||
}
|
||||
|
||||
void isv_set_ready (void) {
|
||||
p.ready = true;
|
||||
}
|
||||
|
||||
void process_isv (void) {
|
||||
if (!p.enabled || (p.ISV->ID != IS64_TOKEN)) {
|
||||
p.current_read_pointer = 0;
|
||||
@ -48,12 +55,19 @@ void process_isv (void) {
|
||||
|
||||
uint32_t read_pointer = SWAP32(p.ISV->RD_PTR);
|
||||
|
||||
if ((read_pointer != p.current_read_pointer) && usb_internal_debug_tx_ready()) {
|
||||
if (p.ready && (read_pointer != p.current_read_pointer)) {
|
||||
bool wrap = read_pointer < p.current_read_pointer;
|
||||
size_t length = ((wrap ? sizeof(p.ISV->BUFFER) : read_pointer) - p.current_read_pointer);
|
||||
uint32_t address = (uint32_t) (&p.ISV->BUFFER[p.current_read_pointer]);
|
||||
uint32_t data[2] = {
|
||||
((wrap ? sizeof(p.ISV->BUFFER) : read_pointer) - p.current_read_pointer),
|
||||
(uint32_t) (&p.ISV->BUFFER[p.current_read_pointer]),
|
||||
};
|
||||
|
||||
if (usb_internal_debug_tx_data(INT_DBG_ID_IS_VIEWER, address, length)) {
|
||||
usb_event_t event;
|
||||
event.id = EVENT_ID_IS_VIEWER;
|
||||
event.trigger = CALLBACK_SDRAM_READ;
|
||||
event.callback = isv_set_ready;
|
||||
if (usb_put_event(&event, data, sizeof(data))) {
|
||||
p.ready = false;
|
||||
p.current_read_pointer = wrap ? 0 : read_pointer;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,10 @@ typedef volatile uint32_t io32_t;
|
||||
|
||||
#define RAM_BASE (0x00000000UL)
|
||||
#define RAM (*((io32_t *) RAM_BASE))
|
||||
#define RAM_SIZE (16 * 1024)
|
||||
#define RAM_SIZE (15 * 1024)
|
||||
#define RAMBUFFER_BASE (0x00003C00UL)
|
||||
#define RAMBUFFER (*((io8_t *) RAMBUFFER_BASE))
|
||||
#define RAMBUFFER_SIZE (1 * 1024)
|
||||
|
||||
|
||||
#define FLASH_BASE (0x10000000UL)
|
||||
|
@ -66,128 +66,52 @@ static bool tx_word (uint32_t data) {
|
||||
#define USB_DMA_TOKEN (0x444D4100)
|
||||
#define USB_ERR_TOKEN (0x45525200)
|
||||
|
||||
#define DEBUG_ID_INTERNAL (0xFE)
|
||||
#define DEBUG_ID_EVENT (0xFE)
|
||||
|
||||
|
||||
enum state {
|
||||
STATE_IDLE,
|
||||
STATE_ARGS,
|
||||
STATE_DATA,
|
||||
STATE_RESPONSE,
|
||||
STATE_DEBUG_TX,
|
||||
STATE_INTERNAL_DEBUG_TX_START,
|
||||
STATE_INTERNAL_DEBUG_TX_DATA,
|
||||
STATE_INTERNAL_DEBUG_TX_END,
|
||||
STATE_EVENT,
|
||||
};
|
||||
|
||||
struct process {
|
||||
enum state state;
|
||||
uint8_t counter;
|
||||
uint32_t counter;
|
||||
uint8_t cmd;
|
||||
uint32_t args[2];
|
||||
bool error;
|
||||
bool dma_in_progress;
|
||||
bool queried;
|
||||
|
||||
bool debug_rx_busy;
|
||||
uint32_t debug_rx_address;
|
||||
size_t debug_rx_length;
|
||||
|
||||
bool debug_tx_busy;
|
||||
uint32_t debug_tx_address;
|
||||
size_t debug_tx_length;
|
||||
|
||||
bool internal_debug_tx_busy;
|
||||
uint8_t internal_debug_tx_step;
|
||||
uint32_t internal_debug_tx_address;
|
||||
size_t internal_debug_tx_length;
|
||||
uint32_t internal_debug_tx_id_length;
|
||||
uint32_t internal_debug_tx_info;
|
||||
bool event_pending;
|
||||
bool event_callback_pending;
|
||||
usb_event_t event;
|
||||
uint8_t event_data[16];
|
||||
uint32_t event_data_length;
|
||||
};
|
||||
|
||||
static struct process p;
|
||||
|
||||
|
||||
bool usb_debug_rx_ready (uint32_t *type, size_t *length) {
|
||||
if (p.state != STATE_DATA || p.cmd != 'D' || p.debug_rx_busy) {
|
||||
bool usb_put_event (usb_event_t *event, void *data, uint32_t length) {
|
||||
if (p.event_pending || p.event_callback_pending) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*type = p.args[0];
|
||||
*length = (size_t) p.args[1];
|
||||
uint8_t *src = (uint8_t *) (data);
|
||||
uint8_t *dst = p.event_data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool usb_debug_rx_busy (void) {
|
||||
return p.debug_rx_busy;
|
||||
}
|
||||
|
||||
bool usb_debug_rx_data (uint32_t address, size_t length) {
|
||||
if (p.debug_rx_busy) {
|
||||
return false;
|
||||
p.event_pending = true;
|
||||
p.event_callback_pending = false;
|
||||
p.event = *event;
|
||||
p.event_data_length = length <= sizeof(p.event_data) ? length : sizeof(p.event_data);
|
||||
for (int i = 0; i < p.event_data_length; i++) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
p.debug_rx_busy = true;
|
||||
p.debug_rx_address = address;
|
||||
p.debug_rx_length = length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool usb_debug_tx_ready (void) {
|
||||
return !p.debug_tx_busy;
|
||||
}
|
||||
|
||||
bool usb_debug_tx_data (uint32_t address, size_t length) {
|
||||
if (p.debug_tx_busy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
p.debug_tx_busy = true;
|
||||
p.debug_tx_address = address;
|
||||
p.debug_tx_length = length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void usb_debug_reset (void) {
|
||||
uint8_t tmp;
|
||||
|
||||
if (p.state == STATE_DATA && p.cmd == 'D') {
|
||||
for (size_t i = 0; i < p.args[1]; i++) {
|
||||
rx_byte(&tmp);
|
||||
}
|
||||
p.args[1] = 0;
|
||||
}
|
||||
if (p.state == STATE_DEBUG_TX) {
|
||||
p.state = STATE_IDLE;
|
||||
}
|
||||
p.debug_rx_busy = false;
|
||||
p.debug_tx_busy = false;
|
||||
|
||||
USB->SCR = USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
|
||||
}
|
||||
|
||||
bool usb_internal_debug_tx_ready (void) {
|
||||
return !p.internal_debug_tx_busy;
|
||||
}
|
||||
|
||||
bool usb_internal_debug_tx_data (internal_debug_id_t id, uint32_t address, size_t length) {
|
||||
if (p.internal_debug_tx_busy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t start_address = address & 0xFFFFFFFC;
|
||||
uint32_t end_address = ALIGN((address + length), 4);
|
||||
size_t dma_length = end_address - start_address;
|
||||
uint8_t start_alignment = address & 0x03;
|
||||
|
||||
p.internal_debug_tx_busy = true;
|
||||
p.internal_debug_tx_address = start_address;
|
||||
p.internal_debug_tx_length = dma_length;
|
||||
p.internal_debug_tx_id_length = ((DEBUG_ID_INTERNAL << 24) | (dma_length + 4));
|
||||
p.internal_debug_tx_info = ((id << 24) | (start_alignment << 16) | (length & 0xFFFF));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -234,12 +158,11 @@ static void handle_escape (void) {
|
||||
|
||||
|
||||
void usb_init (void) {
|
||||
USB->SCR = USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
|
||||
USB->SCR = (USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
|
||||
|
||||
p.state = STATE_IDLE;
|
||||
p.debug_rx_busy = false;
|
||||
p.debug_tx_busy = false;
|
||||
p.internal_debug_tx_busy = false;
|
||||
p.event_pending = false;
|
||||
p.event_callback_pending = false;
|
||||
|
||||
rx_word_current_byte = 0;
|
||||
rx_word_buffer = 0;
|
||||
@ -267,13 +190,9 @@ void process_usb (void) {
|
||||
p.error = true;
|
||||
p.state = STATE_RESPONSE;
|
||||
}
|
||||
} else if (p.debug_tx_busy) {
|
||||
p.state = STATE_DEBUG_TX;
|
||||
p.dma_in_progress = false;
|
||||
} else if (p.internal_debug_tx_busy) {
|
||||
p.state = STATE_INTERNAL_DEBUG_TX_START;
|
||||
p.dma_in_progress = false;
|
||||
p.internal_debug_tx_step = 0;
|
||||
} else if (p.event_pending && (!p.event_callback_pending)) {
|
||||
p.state = STATE_EVENT;
|
||||
p.counter = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -281,6 +200,7 @@ void process_usb (void) {
|
||||
if (rx_word(&p.args[p.counter])) {
|
||||
p.counter += 1;
|
||||
if (p.counter == 2) {
|
||||
p.counter = 0;
|
||||
p.state = STATE_DATA;
|
||||
}
|
||||
}
|
||||
@ -311,6 +231,7 @@ void process_usb (void) {
|
||||
|
||||
case 'R':
|
||||
case 'W':
|
||||
case 'L':
|
||||
case 'S':
|
||||
if (!dma_busy()) {
|
||||
if (!p.dma_in_progress) {
|
||||
@ -319,8 +240,17 @@ void process_usb (void) {
|
||||
dma_start(p.args[0], p.args[1], DMA_ID_USB, dir);
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
if (p.cmd == 'S') {
|
||||
dd_set_block_ready(true);
|
||||
if (p.cmd == 'L' || p.cmd == 'S') {
|
||||
if (p.event_callback_pending) {
|
||||
if (p.cmd == 'L' && p.event.trigger == CALLBACK_SDRAM_READ) {
|
||||
p.event_callback_pending = false;
|
||||
p.event.callback();
|
||||
}
|
||||
if (p.cmd == 'S' && p.event.trigger == CALLBACK_SDRAM_WRITE) {
|
||||
p.event_callback_pending = false;
|
||||
p.event.callback();
|
||||
}
|
||||
}
|
||||
p.state = STATE_IDLE;
|
||||
} else {
|
||||
p.state = STATE_RESPONSE;
|
||||
@ -329,18 +259,36 @@ void process_usb (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (!dma_busy() && p.debug_rx_busy && p.args[1] > 0) {
|
||||
if (!p.dma_in_progress) {
|
||||
dma_start(p.debug_rx_address, p.debug_rx_length, DMA_ID_USB, DMA_DIR_TO_SDRAM);
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
p.args[1] -= p.debug_rx_length > p.args[1] ? p.args[1] : p.debug_rx_length;
|
||||
p.dma_in_progress = false;
|
||||
p.debug_rx_busy = false;
|
||||
case 'F':
|
||||
case 'T':
|
||||
while ((p.args[0] + p.counter) != (p.args[0] + p.args[1])) {
|
||||
uint8_t *buffer = (uint8_t *) (RAMBUFFER_BASE + p.args[0] + p.counter);
|
||||
if (p.cmd == 'F') {
|
||||
if (tx_byte(*buffer)) {
|
||||
p.counter += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p.cmd == 'T') {
|
||||
if (rx_byte(buffer)) {
|
||||
p.counter += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p.args[1] == 0) {
|
||||
if ((p.args[0] + p.counter) == (p.args[0] + p.args[1])) {
|
||||
if (p.event_callback_pending) {
|
||||
if (p.cmd == 'F' && p.event.trigger == CALLBACK_BUFFER_READ) {
|
||||
p.event_callback_pending = false;
|
||||
p.event.callback();
|
||||
}
|
||||
if (p.cmd == 'T' && p.event.trigger == CALLBACK_BUFFER_WRITE) {
|
||||
p.event_callback_pending = false;
|
||||
p.event.callback();
|
||||
}
|
||||
}
|
||||
p.state = STATE_IDLE;
|
||||
}
|
||||
break;
|
||||
@ -358,50 +306,28 @@ void process_usb (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_DEBUG_TX:
|
||||
if (!dma_busy()) {
|
||||
if (!p.dma_in_progress) {
|
||||
dma_start(p.debug_tx_address, p.debug_tx_length, DMA_ID_USB, DMA_DIR_FROM_SDRAM);
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
p.debug_tx_busy = false;
|
||||
p.state = STATE_IDLE;
|
||||
case STATE_EVENT:
|
||||
if ((p.counter == 0) && tx_word(USB_DMA_TOKEN | '@')) {
|
||||
p.counter += 1;
|
||||
}
|
||||
if ((p.counter == 1) && tx_word((DEBUG_ID_EVENT << 24) | (sizeof(p.event.id) + p.event_data_length))) {
|
||||
p.counter += 1;
|
||||
}
|
||||
if ((p.counter == 2) && tx_word(p.event.id)) {
|
||||
p.counter += 1;
|
||||
}
|
||||
if (p.counter >= 3) {
|
||||
while (((p.counter - 3) < p.event_data_length) && tx_byte(p.event_data[p.counter - 3])) {
|
||||
p.counter += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_INTERNAL_DEBUG_TX_START:
|
||||
uint32_t header_data[] = {
|
||||
(USB_DMA_TOKEN | '@'),
|
||||
p.internal_debug_tx_id_length,
|
||||
p.internal_debug_tx_info,
|
||||
};
|
||||
|
||||
if (tx_word(header_data[p.internal_debug_tx_step])) {
|
||||
p.internal_debug_tx_step += 1;
|
||||
if (p.internal_debug_tx_step >= 3) {
|
||||
p.state = STATE_INTERNAL_DEBUG_TX_DATA;
|
||||
if ((p.counter == (p.event_data_length + 3)) && tx_word(USB_CMP_TOKEN | 'H')) {
|
||||
if (p.event.callback != NULL) {
|
||||
p.event_callback_pending = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_INTERNAL_DEBUG_TX_DATA:
|
||||
if (!dma_busy()) {
|
||||
if (!p.dma_in_progress) {
|
||||
dma_start(p.internal_debug_tx_address, p.internal_debug_tx_length, DMA_ID_USB, DMA_DIR_FROM_SDRAM);
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
p.internal_debug_tx_busy = false;
|
||||
p.state = STATE_INTERNAL_DEBUG_TX_END;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_INTERNAL_DEBUG_TX_END:
|
||||
if (tx_word(USB_CMP_TOKEN | 'H')) {
|
||||
p.event_pending = false;
|
||||
p.state = STATE_IDLE;
|
||||
}
|
||||
p.state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8,17 +8,33 @@
|
||||
typedef enum {
|
||||
INT_DBG_ID_IS_VIEWER = 0,
|
||||
INT_DBG_ID_DD_BLOCK = 1,
|
||||
INT_DBG_ID_FSD_READ = 2,
|
||||
INT_DBG_ID_FSD_WRITE = 3,
|
||||
} internal_debug_id_t;
|
||||
|
||||
typedef enum {
|
||||
EVENT_ID_FSD_READ = 0,
|
||||
EVENT_ID_FSD_WRITE = 1,
|
||||
EVENT_ID_DD_BLOCK = 2,
|
||||
EVENT_ID_IS_VIEWER = 3,
|
||||
} usb_event_id_t;
|
||||
|
||||
bool usb_debug_rx_ready (uint32_t *type, size_t *length);
|
||||
bool usb_debug_rx_busy (void);
|
||||
bool usb_debug_rx_data (uint32_t address, size_t length);
|
||||
bool usb_debug_tx_ready (void);
|
||||
bool usb_debug_tx_data (uint32_t address, size_t length);
|
||||
void usb_debug_reset (void);
|
||||
bool usb_internal_debug_tx_ready (void);
|
||||
bool usb_internal_debug_tx_data (internal_debug_id_t id, uint32_t address, size_t length);
|
||||
typedef enum {
|
||||
CALLBACK_NONE = 0,
|
||||
CALLBACK_SDRAM_WRITE = 1,
|
||||
CALLBACK_SDRAM_READ = 2,
|
||||
CALLBACK_BUFFER_WRITE = 3,
|
||||
CALLBACK_BUFFER_READ = 4,
|
||||
} usb_event_callback_t;
|
||||
|
||||
typedef struct {
|
||||
usb_event_id_t id;
|
||||
usb_event_callback_t trigger;
|
||||
void (*callback)(void);
|
||||
} usb_event_t;
|
||||
|
||||
|
||||
bool usb_put_event (usb_event_t *event, void *data, uint32_t length);
|
||||
void usb_init (void);
|
||||
void process_usb (void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user