diff --git a/docs/02_n64_commands.md b/docs/02_n64_commands.md index 7655977..a583648 100644 --- a/docs/02_n64_commands.md +++ b/docs/02_n64_commands.md @@ -22,7 +22,7 @@ | `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation | | `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from SD card to flashcart | | `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from flashcart to SD card | -| `D` | **DD_SD_INFO** | pi_address | table_size | --- | --- | Set 64DD disk SD sector info | +| `D` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode | | `w` | **WRITEBACK_PENDING** | pending_status | --- | --- | --- | Get save writeback status (is write queued to the SD card) | | `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it | | `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer | diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index 2b9f5c3..aa0a74b 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -28,9 +28,9 @@ SRC_FILES = \ init.c \ interrupt.c \ io.c \ - ipl2.S \ main.c \ menu.c \ + reboot.S \ sc64.c \ syscalls.c \ test.c \ diff --git a/sw/bootloader/N64.ld b/sw/bootloader/N64.ld index 70f94f4..251b0d0 100644 --- a/sw/bootloader/N64.ld +++ b/sw/bootloader/N64.ld @@ -9,10 +9,6 @@ ENTRY(entry_handler) __exception_stack_size = 8k; __stack_size = 16k; -__bootloader_start = ORIGIN(ram); -__bootloader_size = LENGTH(ram); -__bootloader_end = __bootloader_start + __bootloader_size; - SECTIONS { .boot : { KEEP(*(.text.rom_header)); diff --git a/sw/bootloader/src/boot.c b/sw/bootloader/src/boot.c index 8ab0e5e..728c344 100644 --- a/sw/bootloader/src/boot.c +++ b/sw/bootloader/src/boot.c @@ -4,7 +4,8 @@ #include "vr4300.h" -extern uint32_t ipl2 __attribute__((section(".data"))); +extern uint32_t reboot_start __attribute__((section(".text"))); +extern size_t reboot_size __attribute__((section(".text"))); typedef struct { @@ -29,16 +30,16 @@ static const ipl3_crc32_t ipl3_crc32[] = { }; -static io32_t *boot_get_device_base (boot_info_t *info) { +static io32_t *boot_get_device_base (boot_params_t *params) { io32_t *device_base_address = ROM_CART; - if (info->device_type == BOOT_DEVICE_TYPE_DD) { + if (params->device_type == BOOT_DEVICE_TYPE_64DD) { device_base_address = ROM_DDIPL; } return device_base_address; } -static bool boot_get_cic_seed (boot_info_t *info) { - io32_t *base = boot_get_device_base(info); +static bool boot_detect_cic_seed (boot_params_t *params) { + io32_t *base = boot_get_device_base(params); uint32_t ipl3[1008] __attribute__((aligned(8))); @@ -48,7 +49,7 @@ static bool boot_get_cic_seed (boot_info_t *info) { for (int i = 0; i < sizeof(ipl3_crc32) / sizeof(ipl3_crc32_t); i++) { if (ipl3_crc32[i].crc32 == crc32) { - info->cic_seed = ipl3_crc32[i].seed; + params->cic_seed = ipl3_crc32[i].seed; return true; } } @@ -56,32 +57,49 @@ static bool boot_get_cic_seed (boot_info_t *info) { return false; } -void boot (boot_info_t *info, bool detect_cic_seed) { - if (info->tv_type == BOOT_TV_TYPE_PASSTHROUGH) { - info->tv_type = OS_INFO->tv_type; +void boot (boot_params_t *params) { + if (params->tv_type == BOOT_TV_TYPE_PASSTHROUGH) { + params->tv_type = OS_INFO->tv_type; } - if (detect_cic_seed) { - if (!boot_get_cic_seed(info)) { - info->cic_seed = 0x3F; + if (params->detect_cic_seed) { + if (!boot_detect_cic_seed(params)) { + params->cic_seed = 0x3F; } } + OS_INFO->mem_size_6105 = OS_INFO->mem_size; + asm volatile ( "li $t1, %[status] \n" "mtc0 $t1, $12 \n" :: [status] "i" (C0_SR_CU1 | C0_SR_CU0 | C0_SR_FR) ); - OS_INFO->mem_size_6105 = OS_INFO->mem_size; - while (!(cpu_io_read(&SP->SR) & SP_SR_HALT)); - cpu_io_write(&SP->SR, SP_SR_CLR_INTR | SP_SR_SET_HALT); + cpu_io_write(&SP->SR, + SP_SR_CLR_SIG7 | + SP_SR_CLR_SIG6 | + SP_SR_CLR_SIG5 | + SP_SR_CLR_SIG4 | + SP_SR_CLR_SIG3 | + SP_SR_CLR_SIG2 | + SP_SR_CLR_SIG1 | + SP_SR_CLR_SIG0 | + SP_SR_CLR_INTR_BREAK | + SP_SR_CLR_SSTEP | + SP_SR_CLR_INTR | + SP_SR_CLR_BROKE | + SP_SR_SET_HALT + ); + cpu_io_write(&SP->SEMAPHORE, 0); + cpu_io_write(&SP->PC, 0); while (cpu_io_read(&SP->DMA_BUSY)); cpu_io_write(&PI->SR, PI_SR_CLR_INTR | PI_SR_RESET); + while ((cpu_io_read(&VI->CURR_LINE) & ~(VI_CURR_LINE_FIELD)) != 0); cpu_io_write(&VI->V_INTR, 0x3FF); cpu_io_write(&VI->H_LIMITS, 0); cpu_io_write(&VI->CURR_LINE, 0); @@ -90,11 +108,12 @@ void boot (boot_info_t *info, bool detect_cic_seed) { while (cpu_io_read(&SP->SR) & SP_SR_DMA_BUSY); - uint32_t *ipl2_src = &ipl2; - io32_t *ipl2_dst = SP_MEM->IMEM; + uint32_t *reboot_src = &reboot_start; + io32_t *reboot_dst = SP_MEM->IMEM; + size_t reboot_instructions = (size_t) (&reboot_size) / sizeof(uint32_t); - for (int i = 0; i < 8; i++) { - cpu_io_write(&ipl2_dst[i], ipl2_src[i]); + for (int i = 0; i < reboot_instructions; i++) { + cpu_io_write(&reboot_dst[i], reboot_src[i]); } cpu_io_write(&PI->DOM[0].LAT, 0xFF); @@ -102,7 +121,7 @@ void boot (boot_info_t *info, bool detect_cic_seed) { cpu_io_write(&PI->DOM[0].PGS, 0x0F); cpu_io_write(&PI->DOM[0].RLS, 0x03); - io32_t *base = boot_get_device_base(info); + io32_t *base = boot_get_device_base(params); uint32_t pi_config = pi_io_read(base); cpu_io_write(&PI->DOM[0].LAT, pi_config & 0xFF); @@ -121,32 +140,30 @@ void boot (boot_info_t *info, bool detect_cic_seed) { cpu_io_write(&ipl3_dst[i], pi_io_read(&ipl3_src[i])); } - register void (*entry_point)(void) asm ("t3"); register uint32_t boot_device asm ("s3"); register uint32_t tv_type asm ("s4"); register uint32_t reset_type asm ("s5"); register uint32_t cic_seed asm ("s6"); register uint32_t version asm ("s7"); - void *stack_pointer; - entry_point = (void (*)(void)) UNCACHED(&SP_MEM->DMEM[16]); - boot_device = (info->device_type & 0x01); - tv_type = (info->tv_type & 0x03); - reset_type = (info->reset_type & 0x01); - cic_seed = (info->cic_seed & 0xFF); - version = (info->tv_type == BOOT_TV_TYPE_PAL) ? 6 : 1; - stack_pointer = (void *) UNCACHED(&SP_MEM->IMEM[1020]); + boot_device = (params->device_type & 0x01); + tv_type = (params->tv_type & 0x03); + reset_type = (params->reset_type & 0x01); + cic_seed = (params->cic_seed & 0xFF); + version = (params->tv_type == BOOT_TV_TYPE_PAL) ? 6 + : (params->tv_type == BOOT_TV_TYPE_NTSC) ? 1 + : (params->tv_type == BOOT_TV_TYPE_MPAL) ? 4 + : 0; asm volatile ( - "move $sp, %[stack_pointer] \n" - "jr %[entry_point] \n" :: - [entry_point] "r" (entry_point), + "la $t3, reboot \n" + "jr $t3 \n" :: [boot_device] "r" (boot_device), [tv_type] "r" (tv_type), [reset_type] "r" (reset_type), [cic_seed] "r" (cic_seed), - [version] "r" (version), - [stack_pointer] "r" (stack_pointer) + [version] "r" (version) : + "t3" ); while (1); diff --git a/sw/bootloader/src/boot.h b/sw/bootloader/src/boot.h index 7563dfc..850861d 100644 --- a/sw/bootloader/src/boot.h +++ b/sw/bootloader/src/boot.h @@ -8,7 +8,7 @@ typedef enum { BOOT_DEVICE_TYPE_ROM = 0, - BOOT_DEVICE_TYPE_DD = 1, + BOOT_DEVICE_TYPE_64DD = 1, } boot_device_type_t; typedef enum { @@ -29,10 +29,11 @@ typedef struct { boot_reset_type_t reset_type; boot_tv_type_t tv_type; uint8_t cic_seed; -} boot_info_t; + bool detect_cic_seed; +} boot_params_t; -void boot (boot_info_t *info, bool detect_cic_seed); +void boot (boot_params_t *params); #endif diff --git a/sw/bootloader/src/io.h b/sw/bootloader/src/io.h index 49a7d22..23e1569 100644 --- a/sw/bootloader/src/io.h +++ b/sw/bootloader/src/io.h @@ -10,7 +10,7 @@ typedef volatile uint8_t io8_t; typedef volatile uint32_t io32_t; -#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1)) +#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1)) #define PHYSICAL(address) ((typeof(address)) (((io32_t) (address)) & (0x1FFFFFFFUL))) #define UNCACHED(address) ((typeof(address)) (((io32_t) (address)) | (0xA0000000UL))) @@ -38,6 +38,8 @@ typedef struct { io32_t DMA_FULL; io32_t DMA_BUSY; io32_t SEMAPHORE; + io32_t __reserved[0xFFF8]; + io32_t PC; } sp_regs_t; #define SP_BASE (0x04040000UL) @@ -156,6 +158,8 @@ typedef struct { #define VI_CR_PIXEL_ADVANCE_3 (1 << 15) #define VI_CR_DITHER_FILTER_ON (1 << 16) +#define VI_CURR_LINE_FIELD (1 << 0) + typedef struct { io32_t MADDR; diff --git a/sw/bootloader/src/ipl2.S b/sw/bootloader/src/ipl2.S deleted file mode 100644 index 23f9f6a..0000000 --- a/sw/bootloader/src/ipl2.S +++ /dev/null @@ -1,17 +0,0 @@ -.set noat -.set noreorder - - -.section .text.ipl2, "ax", %progbits -.type ipl2, %object -ipl2: - .global ipl2 - lui $t5, 0xBFC0 -1: - lw $t0, 0x7FC($t5) - addiu $t5, $t5, 0x7C0 - andi $t0, $t0, 0x80 - bnel $t0, $zero, 1b - lui $t5, 0xBFC0 - lw $t0, 0x24($t5) - lui $t3, 0xB000 diff --git a/sw/bootloader/src/main.c b/sw/bootloader/src/main.c index a4de2a1..8c81ad0 100644 --- a/sw/bootloader/src/main.c +++ b/sw/bootloader/src/main.c @@ -8,37 +8,40 @@ void main (void) { sc64_error_t error; - boot_info_t boot_info; - sc64_boot_info_t sc64_boot_info; + sc64_boot_params_t sc64_boot_params; - if ((error = sc64_get_boot_info(&sc64_boot_info)) != SC64_OK) { + if ((error = sc64_get_boot_params(&sc64_boot_params)) != SC64_OK) { error_display("Could not obtain boot info: %d", error); } - switch (sc64_boot_info.boot_mode) { + boot_params_t boot_params; + + boot_params.reset_type = OS_INFO->reset_type; + boot_params.tv_type = sc64_boot_params.tv_type; + boot_params.cic_seed = (sc64_boot_params.cic_seed & 0xFF); + boot_params.detect_cic_seed = (sc64_boot_params.cic_seed == CIC_SEED_AUTO); + + switch (sc64_boot_params.boot_mode) { case BOOT_MODE_MENU: - menu_load_and_run(); + menu_load(); + boot_params.device_type = BOOT_DEVICE_TYPE_ROM; + boot_params.reset_type = BOOT_RESET_TYPE_NMI; break; case BOOT_MODE_ROM: - boot_info.device_type = BOOT_DEVICE_TYPE_ROM; + boot_params.device_type = BOOT_DEVICE_TYPE_ROM; break; case BOOT_MODE_DDIPL: - boot_info.device_type = BOOT_DEVICE_TYPE_DD; + boot_params.device_type = BOOT_DEVICE_TYPE_64DD; break; default: - error_display("Unknown boot mode selected [%d]\n", sc64_boot_info.boot_mode); + error_display("Unknown boot mode selected [%d]\n", sc64_boot_params.boot_mode); break; } - boot_info.reset_type = OS_INFO->reset_type; - boot_info.tv_type = sc64_boot_info.tv_type; - boot_info.cic_seed = (sc64_boot_info.cic_seed & 0xFF); - bool detect_cic_seed = (sc64_boot_info.cic_seed == CIC_SEED_AUTO); - deinit(); - boot(&boot_info, detect_cic_seed); + boot(&boot_params); } diff --git a/sw/bootloader/src/menu.c b/sw/bootloader/src/menu.c index 67af086..f7ce23f 100644 --- a/sw/bootloader/src/menu.c +++ b/sw/bootloader/src/menu.c @@ -1,41 +1,35 @@ #include "error.h" #include "fatfs/ff.h" -#include "init.h" #include "io.h" #include "menu.h" #include "sc64.h" -extern const void __bootloader_start __attribute__((section(".data"))); -extern const void __bootloader_end __attribute__((section(".data"))); - - -#define ROM_ENTRY_OFFSET (8) -#define ROM_CODE_OFFSET (4096) -#define ROM_MAX_LOAD_SIZE (1 * 1024 * 1024) +#define ROM_ADDRESS (0x10000000) +#define FILL_SIZE (0x101000) static const char *fatfs_error_codes[] = { - "Succeeded", - "A hard error occurred in the low level disk I/O layer", - "Assertion failed", - "The physical drive cannot work", - "Could not find the file", - "Could not find the path", - "The path name format is invalid", - "Access denied due to prohibited access or directory full", - "Access denied due to prohibited access", - "The file/directory object is invalid", - "The physical drive is write protected", - "The logical drive number is invalid", - "The volume has no work area", - "There is no valid FAT volume", - "The f_mkfs() aborted due to any problem", - "Could not get a grant to access the volume within defined period", - "The operation is rejected according to the file sharing policy", - "LFN working buffer could not be allocated", - "Number of open files > FF_FS_LOCK", - "Given parameter is invalid", + "Succeeded", + "A hard error occurred in the low level disk I/O layer", + "Assertion failed", + "The physical drive cannot work", + "Could not find the file", + "Could not find the path", + "The path name format is invalid", + "Access denied due to prohibited access or directory full", + "Access denied due to prohibited access", + "The file/directory object is invalid", + "The physical drive is write protected", + "The logical drive number is invalid", + "The volume has no work area", + "There is no valid FAT volume", + "The f_mkfs() aborted due to any problem", + "Could not get a grant to access the volume within defined period", + "The operation is rejected according to the file sharing policy", + "LFN working buffer could not be allocated", + "Number of open files > FF_FS_LOCK", + "Given parameter is invalid", }; @@ -47,27 +41,55 @@ static const char *fatfs_error_codes[] = { } -static void menu_check_load_address (void *address, size_t size) { - void *menu_start = address; - void *menu_end = (address + size); - void *usable_ram_start = (void *) (0x80000400UL); - void *usable_ram_end = (void *) (0x80400000UL); - void *bootloader_start = (void *) (&__bootloader_start); - void *bootloader_end = (void *) (&__bootloader_end); +static void fix_menu_file_size (FIL *fil) { + fil->obj.objsize = ALIGN(f_size(fil), FF_MAX_SS); +} - if ((menu_start < usable_ram_start) || (menu_end > usable_ram_end)) { - error_display("Incorrect menu load address/size.\nReason: Outside of usable RAM space\n"); +static void fill_remaining_menu_space (size_t menu_file_size) { + if (menu_file_size >= FILL_SIZE) { + return; } - if ((menu_start < bootloader_end) && (bootloader_start < menu_end)) { - error_display("Incorrect menu load address/size.\nReason: Overlapping bootloader space\n"); + sc64_error_t error; + uint32_t rom_write_enable_restore; + + if ((error = sc64_get_config(CFG_ID_ROM_WRITE_ENABLE, &rom_write_enable_restore)) != SC64_OK) { + error_display("Command CONFIG_GET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error); + } + + if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true)) != SC64_OK) { + error_display("Command CONFIG_SET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error); + } + + uint8_t fill_buffer[4096] __attribute__((aligned(8))); + + for (int i = 0; i < sizeof(fill_buffer); i++) { + fill_buffer[i] = 0; + } + + uint32_t address = (ROM_ADDRESS + menu_file_size); + uint32_t left = (FILL_SIZE - menu_file_size); + + while (left > 0) { + size_t block = (left > sizeof(fill_buffer)) ? sizeof(fill_buffer) : left; + pi_dma_write((io32_t *) (address), fill_buffer, block); + address += block; + left -= block; + } + + if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, rom_write_enable_restore)) != SC64_OK) { + error_display("Command CONFIG_SET [CFG_ID_ROM_WRITE_ENABLE] failed: %d", error); } } -void menu_load_and_run (void) { +void menu_load (void) { sc64_error_t error; bool writeback_pending; + FRESULT fresult; + FATFS fs; + FIL fil; + UINT bytes_read; do { if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) { @@ -79,32 +101,12 @@ void menu_load_and_run (void) { error_display("Could not disable writeback: %d", error); } - void (* menu)(void); - FRESULT fresult; - FATFS fs; - FIL fil; - UINT br; - size_t size = ROM_MAX_LOAD_SIZE; - FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error. No SD card or invalid partition table"); FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable (sc64menu.n64)"); - FF_CHECK(f_lseek(&fil, ROM_ENTRY_OFFSET), "Could not seek to entry point offset"); - FF_CHECK(f_read(&fil, &menu, sizeof(menu), &br), "Could not read entry point"); - FF_CHECK(f_lseek(&fil, ROM_CODE_OFFSET), "Could not seek to code start offset"); - if ((f_size(&fil) - ROM_CODE_OFFSET) < size) { - size = (size_t) (f_size(&fil) - ROM_CODE_OFFSET); - } - menu_check_load_address(menu, size); - cache_data_hit_writeback_invalidate(menu, size); - cache_inst_hit_invalidate(menu, size); - FF_CHECK(f_read(&fil, menu, size, &br), "Could not read menu file"); - FF_CHECK((br != size) ? FR_INT_ERR : FR_OK, "Read size is different than expected"); + fix_menu_file_size(&fil); + FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file"); + FF_CHECK((bytes_read != f_size(&fil)) ? FR_INT_ERR : FR_OK, "Read size is different than expected"); + fill_remaining_menu_space(f_size(&fil)); FF_CHECK(f_close(&fil), "Could not close menu file"); FF_CHECK(f_unmount(""), "Could not unmount drive"); - - deinit(); - - menu(); - - while (1); } diff --git a/sw/bootloader/src/menu.h b/sw/bootloader/src/menu.h index 505608b..6663ded 100644 --- a/sw/bootloader/src/menu.h +++ b/sw/bootloader/src/menu.h @@ -2,7 +2,7 @@ #define MENU_H__ -void menu_load_and_run (void); +void menu_load (void); #endif diff --git a/sw/bootloader/src/reboot.S b/sw/bootloader/src/reboot.S new file mode 100644 index 0000000..f73639c --- /dev/null +++ b/sw/bootloader/src/reboot.S @@ -0,0 +1,114 @@ +#define IPL3_ENTRY 0xA4000040 +#define REBOOT_ADDRESS 0xA4001000 +#define STACK_ADDRESS 0xA4001FF0 + +#define RI_ADDRESS 0xA4700000 + +#define RI_MODE 0x00 +#define RI_CONFIG 0x04 +#define RI_CURRENT_LOAD 0x08 +#define RI_SELECT 0x0C +#define RI_REFRESH 0x10 +#define RI_LATENCY 0x14 + +#define RI_MODE_RESET 0x00000000 +#define RI_MODE_STANDBY 0x0000000E + +#define RDRAM_RESET_DELAY 1024 +#define RDRAM_STANDBY_DELAY 512 + +.set noat +.section .text.reboot, "ax", %progbits +.type reboot, %object +reboot_start: + .global reboot_start + +# NOTE: CIC x105 requirement +ipl2: +.set noreorder + lui $t5, 0xBFC0 +1: + lw $t0, 0x7FC($t5) + addiu $t5, $t5, 0x7C0 + andi $t0, $t0, 0x80 + bnel $t0, $zero, 1b + lui $t5, 0xBFC0 + lw $t0, 0x24($t5) + lui $t3, 0xB000 +.set reorder + +reboot_entry: + .set reboot, REBOOT_ADDRESS + (. - reboot_start) + .global reboot + + li $sp, STACK_ADDRESS + + bnez $s5, reset_rdram_skip + +reset_rdram: + li $t0, RI_ADDRESS + + li $t1, RI_MODE_RESET + sw $t1, RI_MODE($t0) + + li $t2, RDRAM_RESET_DELAY +1: + addiu $t2, (-1) + bnez $t2, 1b + + sw $zero, RI_CONFIG($t0) + sw $zero, RI_CURRENT_LOAD($t0) + sw $zero, RI_SELECT($t0) + sw $zero, RI_REFRESH($t0) + + li $t1, RI_MODE_STANDBY + sw $t1, RI_MODE($t0) + + li $t2, RDRAM_STANDBY_DELAY +1: + addiu $t2, (-1) + bnez $t2, 1b +reset_rdram_skip: + +prepare_registers: + la $t0, ra_table + sll $t1, $s4, 2 + add $t0, $t1 + lw $ra, ($t0) + + move $at, $zero + move $v0, $zero + move $v1, $zero + move $a0, $zero + move $a1, $zero + move $a2, $zero + move $a3, $zero + move $t0, $zero + move $t1, $zero + move $t2, $zero + move $t4, $zero + move $t5, $zero + move $t6, $zero + move $t7, $zero + move $s0, $zero + move $s1, $zero + move $s2, $zero + move $t8, $zero + move $t9, $zero + move $k0, $zero + move $k1, $zero + move $gp, $zero + move $fp, $zero + +run_ipl3: + li $t3, IPL3_ENTRY + jr $t3 + +ra_values: + .set ra_table, REBOOT_ADDRESS + (. - reboot_start) + .word 0xA4001554 + .word 0xA4001550 + .word 0xA4001554 + + .set reboot_size, (. - reboot_start) + .global reboot_size diff --git a/sw/bootloader/src/sc64.c b/sw/bootloader/src/sc64.c index d2c9a45..b560f60 100644 --- a/sw/bootloader/src/sc64.c +++ b/sw/bootloader/src/sc64.c @@ -42,7 +42,7 @@ typedef enum { CMD_ID_SD_SECTOR_SET = 'I', CMD_ID_SD_READ = 's', CMD_ID_SD_WRITE = 'S', - CMD_ID_DD_SD_INFO = 'D', + CMD_ID_DISK_MAPPING_SET = 'D', CMD_ID_WRITEBACK_PENDING = 'w', CMD_ID_WRITEBACK_SD_INFO = 'W', CMD_ID_FLASH_PROGRAM = 'K', @@ -174,24 +174,29 @@ sc64_error_t sc64_set_setting (sc64_setting_id_t id, uint32_t value) { return sc64_execute_cmd(&cmd); } -sc64_error_t sc64_get_boot_info (sc64_boot_info_t *info) { +sc64_error_t sc64_get_boot_params (sc64_boot_params_t *params) { sc64_error_t error; uint32_t value; if ((error = sc64_get_config(CFG_ID_BOOT_MODE, &value)) != SC64_OK) { return error; } - info->boot_mode = value; + params->boot_mode = value; - if ((error = sc64_get_config(CFG_ID_CIC_SEED, &value)) != SC64_OK) { - return error; - } - info->cic_seed = value; + if (params->boot_mode != BOOT_MODE_MENU) { + if ((error = sc64_get_config(CFG_ID_CIC_SEED, &value)) != SC64_OK) { + return error; + } + params->cic_seed = value; - if ((error = sc64_get_config(CFG_ID_TV_TYPE, &value)) != SC64_OK) { - return error; + if ((error = sc64_get_config(CFG_ID_TV_TYPE, &value)) != SC64_OK) { + return error; + } + params->tv_type = value; + } else { + params->cic_seed = CIC_SEED_AUTO; + params->tv_type = TV_TYPE_PASSTHROUGH; } - info->tv_type = value; return SC64_OK; } @@ -361,9 +366,9 @@ sc64_error_t sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t cou } -sc64_error_t sc64_dd_set_sd_info (void *address, uint32_t length) { +sc64_error_t sc64_set_disk_mapping (void *address, uint32_t length) { sc64_cmd_t cmd = { - .id = CMD_ID_DD_SD_INFO, + .id = CMD_ID_DISK_MAPPING_SET, .arg = { (uint32_t) (address), length } }; return sc64_execute_cmd(&cmd); diff --git a/sw/bootloader/src/sc64.h b/sw/bootloader/src/sc64.h index f8b5b57..775acb7 100644 --- a/sw/bootloader/src/sc64.h +++ b/sw/bootloader/src/sc64.h @@ -3,6 +3,7 @@ #include +#include #include @@ -96,7 +97,7 @@ typedef struct { sc64_boot_mode_t boot_mode; sc64_cic_seed_t cic_seed; sc64_tv_type_t tv_type; -} sc64_boot_info_t; +} sc64_boot_params_t; typedef struct { uint8_t second; @@ -142,7 +143,7 @@ sc64_error_t sc64_get_config (sc64_cfg_id_t id, uint32_t *value); sc64_error_t sc64_set_config (sc64_cfg_id_t id, uint32_t value); sc64_error_t sc64_get_setting (sc64_setting_id_t id, uint32_t *value); sc64_error_t sc64_set_setting (sc64_setting_id_t id, uint32_t value); -sc64_error_t sc64_get_boot_info (sc64_boot_info_t *info); +sc64_error_t sc64_get_boot_params (sc64_boot_params_t *params); sc64_error_t sc64_get_time (sc64_rtc_time_t *t); sc64_error_t sc64_set_time (sc64_rtc_time_t *t); @@ -162,7 +163,7 @@ sc64_error_t sc64_sd_set_byte_swap (bool enabled); sc64_error_t sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count); sc64_error_t sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t count); -sc64_error_t sc64_dd_set_sd_info (void *address, uint32_t length); +sc64_error_t sc64_set_disk_mapping (void *address, uint32_t length); sc64_error_t sc64_writeback_pending (bool *pending); sc64_error_t sc64_writeback_enable (void *address); diff --git a/sw/bootloader/src/startup.S b/sw/bootloader/src/startup.S index 638e067..25228de 100644 --- a/sw/bootloader/src/startup.S +++ b/sw/bootloader/src/startup.S @@ -41,12 +41,12 @@ entry_handler: la $sp, _sp bss_init: - la $a0, _sbss - la $a1, _ebss + la $a0, _sbss + la $a1, _ebss 1: - sd $zero, 0($a0) - addiu $a0, 8 - bltu $a0, $a1, 1b + sd $zero, 0($a0) + addiu $a0, 8 + bltu $a0, $a1, 1b la $t0, init jalr $t0 diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index 2a0757c..a962982 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -636,7 +636,7 @@ void cfg_process (void) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } - dd_set_sd_info(args[0], args[1]); + dd_set_disk_mapping(args[0], args[1]); break; case 'w': diff --git a/sw/controller/src/dd.c b/sw/controller/src/dd.c index 82d4e74..9db7bb3 100644 --- a/sw/controller/src/dd.c +++ b/sw/controller/src/dd.c @@ -22,6 +22,9 @@ #define DD_SPIN_UP_TIME (2000) +#define DD_THB_UNMAPPED (0xFFFFFFFF) +#define DD_THB_WRITABLE_FLAG (1 << 31) + typedef enum { DD_CMD_SEEK_READ = 0x01, @@ -100,7 +103,7 @@ static uint16_t dd_track_head_block (void) { return (track | head | block); } -static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table) { +static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table, bool is_write) { uint32_t tmp; sd_disk_info_t info = p.sd_disk_info[p.sd_current_disk]; if (info.thb_table_address == 0xFFFFFFFF) { @@ -109,9 +112,13 @@ static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table) uint32_t thb_entry_address = (info.thb_table_address + (index * sizeof(uint32_t))); fpga_mem_read(thb_entry_address, sizeof(uint32_t), (uint8_t *) (&tmp)); uint32_t start_offset = SWAP32(tmp); - if (start_offset == 0xFFFFFFFF) { + if (start_offset == DD_THB_UNMAPPED) { return 0; } + if (is_write && ((start_offset & DD_THB_WRITABLE_FLAG) == 0)) { + return 0; + } + start_offset &= ~(DD_THB_WRITABLE_FLAG); p.block_offset = (start_offset % SD_SECTOR_SIZE); uint32_t block_length = ((p.sector_info.sector_size + 1) * DD_BLOCK_DATA_SECTORS_NUM); uint32_t end_offset = ((start_offset + block_length) - 1); @@ -130,7 +137,7 @@ static bool dd_block_read_request (void) { uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS; if (p.sd_mode) { uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE]; - uint32_t sectors = dd_fill_sd_sector_table(index, sector_table); + uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, false); bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors); dd_set_block_ready(!error); } else { @@ -152,7 +159,7 @@ static bool dd_block_write_request (void) { uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS; if (p.sd_mode) { uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE]; - uint32_t sectors = dd_fill_sd_sector_table(index, sector_table); + uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, true); bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors); dd_set_block_ready(!error); } else { @@ -244,7 +251,7 @@ void dd_set_sd_mode (bool value) { p.sd_mode = value; } -void dd_set_sd_info (uint32_t address, uint32_t length) { +void dd_set_disk_mapping (uint32_t address, uint32_t length) { sd_disk_info_t info; length /= sizeof(info); p.sd_current_disk = 0; @@ -289,7 +296,7 @@ void dd_init (void) { p.drive_type = DD_DRIVE_TYPE_RETAIL; p.sd_mode = false; p.sd_current_disk = 0; - dd_set_sd_info(0, 0); + dd_set_disk_mapping(0, 0); } void dd_process (void) { diff --git a/sw/controller/src/dd.h b/sw/controller/src/dd.h index df5114d..cdd84fd 100644 --- a/sw/controller/src/dd.h +++ b/sw/controller/src/dd.h @@ -25,7 +25,7 @@ dd_disk_state_t dd_get_disk_state (void); bool dd_set_disk_state (dd_disk_state_t state); bool dd_get_sd_mode (void); void dd_set_sd_mode (bool value); -void dd_set_sd_info (uint32_t address, uint32_t length); +void dd_set_disk_mapping (uint32_t address, uint32_t length); void dd_handle_button (void); void dd_init (void); void dd_process (void); diff --git a/sw/controller/src/fpga.h b/sw/controller/src/fpga.h index 69e9b5e..f14fe76 100644 --- a/sw/controller/src/fpga.h +++ b/sw/controller/src/fpga.h @@ -58,7 +58,7 @@ typedef enum { } fpga_reg_t; -#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1)) +#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1)) #define SWAP16(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8)) #define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24)