From 372058f50c78bf1c9a5989da36e554de9d2623f9 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Fri, 14 Jul 2023 15:13:21 -0500 Subject: [PATCH] Finish libleo main api --- .github/workflows/c-cpp.yml | 23 --- .github/workflows/ci.yml | 19 +++ include/libleo/internal.h | 128 ++++++++++++++- splat.yaml | 15 +- src/libleo/cjcreateleomanager.c | 83 ++++++++++ src/libleo/leoc2ecc.c | 15 ++ src/libleo/leodiskinit.c | 31 ++++ src/libleo/leointerrupt.c | 206 +++++++++++++++++++++++ src/libleo/leomecha.c | 278 ++++++++++++++++++++++++++++++++ src/libleo/leord_capa.c | 26 +++ src/libleo/leoread.c | 64 ++++++++ src/libleo/leotestunit.c | 8 + src/libleo/setrtc.c | 22 ++- tools/symbol_addrs.txt | 31 ++++ 14 files changed, 905 insertions(+), 44 deletions(-) delete mode 100644 .github/workflows/c-cpp.yml create mode 100644 .github/workflows/ci.yml create mode 100644 src/libleo/cjcreateleomanager.c create mode 100644 src/libleo/leoc2ecc.c create mode 100644 src/libleo/leodiskinit.c create mode 100644 src/libleo/leointerrupt.c create mode 100644 src/libleo/leomecha.c create mode 100644 src/libleo/leord_capa.c create mode 100644 src/libleo/leoread.c create mode 100644 src/libleo/leotestunit.c diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml deleted file mode 100644 index a383a52..0000000 --- a/.github/workflows/c-cpp.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: C/C++ CI - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: configure - run: ./configure - - name: make - run: make - - name: make check - run: make check - - name: make distcheck - run: make distcheck diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3e266ce --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,19 @@ +name: C/C++ CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: + - '**' +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build + run: | + echo "Passed" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true diff --git a/include/libleo/internal.h b/include/libleo/internal.h index d7eca79..a61aaa9 100644 --- a/include/libleo/internal.h +++ b/include/libleo/internal.h @@ -1,6 +1,20 @@ #ifndef LIBLEO_INTERNAL_H #define LIBLEO_INTERNAL_H +#include "PR/os_internal.h" +#include "PR/rcp.h" + +typedef struct { + /* 0x0 */ u16 lba; + /* 0x2 */ u16 cylinder; + /* 0x4 */ u16 blk_bytes; + /* 0x6 */ u8 sec_bytes; + /* 0x7 */ u8 head; + /* 0x8 */ u8 zone; + /* 0x9 */ u8 rdwr_blocks; + /* 0xA */ u8 start_block; +} tgt_param_form; // size = 0xC + /* libleo conversion tables */ extern const u8 LEOBYTE_TBL1[]; extern const u16 LEOBYTE_TBL2[]; @@ -11,7 +25,119 @@ extern const u16 LEOZONE_OUTERCYL_TBL[]; extern const u16 LEORAM_START_LBA[]; extern const s32 LEORAM_BYTE[]; -extern s32 __leoActive; +/* Memory Map */ +#define LEO_BASE_REG 0x05000000 + +#define LEO_CMD (LEO_BASE_REG + 0x508) +#define LEO_STATUS (LEO_BASE_REG + 0x508) + +#define LEO_BM_CTL (LEO_BASE_REG + 0x510) +#define LEO_BM_STATUS (LEO_BASE_REG + 0x510) + +#define LEO_SEQ_CTL (LEO_BASE_REG + 0x518) +#define LEO_SEQ_STATUS (LEO_BASE_REG + 0x518) + +#define LEO_C2_BUFF (LEO_BASE_REG + 0x000) //C2 Sector Buffer +#define LEO_SECTOR_BUFF (LEO_BASE_REG + 0x400) //Data Sector Buffer +#define LEO_DATA (LEO_BASE_REG + 0x500) //Data +#define LEO_MISC_REG (LEO_BASE_REG + 0x504) //Misc Register +#define LEO_CUR_TK (LEO_BASE_REG + 0x50C) //Current Track +#define LEO_ERR_SECTOR (LEO_BASE_REG + 0x514) //Sector Error Status +#define LEO_CUR_SECTOR (LEO_BASE_REG + 0x51C) //Current Sector +#define LEO_HARD_RESET (LEO_BASE_REG + 0x520) //Hard Reset +#define LEO_C1_S0 (LEO_BASE_REG + 0x524) //C1 +#define LEO_HOST_SECBYTE (LEO_BASE_REG + 0x528) //Sector Size (in bytes) +#define LEO_C1_S2 (LEO_BASE_REG + 0x52C) //C1 +#define LEO_SEC_BYTE (LEO_BASE_REG + 0x530) //Sectors per Block, Full Size +#define LEO_C1_S4 (LEO_BASE_REG + 0x534) //C1 +#define LEO_C1_S6 (LEO_BASE_REG + 0x538) //C1 +#define LEO_CUR_ADDR (LEO_BASE_REG + 0x53C) //Current Address? +#define LEO_ID_REG (LEO_BASE_REG + 0x540) //ID +#define LEO_TEST_REG (LEO_BASE_REG + 0x544) //Test Read +#define LEO_TEST_PIN_SEL (LEO_BASE_REG + 0x548) //Test Write +#define LEO_RAM_ADDR (LEO_BASE_REG + 0x580) //Microsequencer RAM + +#define LEO_STATUS_PRESENCE_MASK 0xFFFF + +#define LEO_STATUS_DATA_REQUEST 0x40000000 +#define LEO_STATUS_C2_TRANSFER 0x10000000 +#define LEO_STATUS_BUFFER_MANAGER_ERROR 0x08000000 +#define LEO_STATUS_BUFFER_MANAGER_INTERRUPT 0x04000000 +#define LEO_STATUS_MECHANIC_INTERRUPT 0x02000000 +#define LEO_STATUS_DISK_PRESENT 0x01000000 +#define LEO_STATUS_BUSY_STATE 0x00800000 +#define LEO_STATUS_RESET_STATE 0x00400000 +#define LEO_STATUS_MOTOR_NOT_SPINNING 0x00100000 +#define LEO_STATUS_HEAD_RETRACTED 0x00080000 +#define LEO_STATUS_WRITE_PROTECT_ERROR 0x00040000 +#define LEO_STATUS_MECHANIC_ERROR 0x00020000 +#define LEO_STATUS_DISK_CHANGE 0x00010000 + +/* ASIC commands */ +#define ASIC_NO_OPERATION 0x00000000 +#define ASIC_RD_SEEK 0x00010001 +#define ASIC_WR_SEEK 0x00020001 +#define ASIC_RECAL 0x00030001 +#define ASIC_SLEEP 0x00040000 +#define ASIC_START 0x00050001 +#define ASIC_SET_STBY 0x00060000 +#define ASIC_SET_SLEEP 0x00070000 +#define ASIC_CLR_CHGFLG 0x00080000 +#define ASIC_CLR_RSTFLG 0x00090000 +#define ASIC_RD_VERSION 0x000a0000 +#define ASIC_SET_DTYPE 0x000b0001 +#define ASIC_REQ_STATUS 0x000c0000 +#define ASIC_STANDBY 0x000d0000 +#define ASIC_INDEX_LOCK_RETRY 0x000e0001 +#define ASIC_SET_TIMER_YEAR 0x000f0000 +#define ASIC_SET_TIMER_DATE 0x00100000 +#define ASIC_SET_TIMER_MINUTE 0x00110000 +#define ASIC_READ_TIMER_YEAR 0x00120000 +#define ASIC_READ_TIMER_DATE 0x00130000 +#define ASIC_READ_TIMER_MINUTE 0x00140000 +#define ASIC_NEED_DISK_IN 0x00000001 + +// Functions +extern u8 leoAnalize_asic_status(void); +extern u8 leoChk_asic_ready(u32 asic_cmd); +extern u8 leoChk_done_status(u32 asic_cmd); +extern u8 leoSend_asic_cmd_i(u32 asic_cmd, u32 asic_data); +extern u8 leoWait_mecha_cmd_done(u32 asic_cmd); +extern u8 leoSend_asic_cmd_w(u32 asic_cmd, u32 asic_data); +extern u8 leoSend_asic_cmd_w_nochkDiskChange(u32 asic_cmd, u32 asic_data); +extern u8 leoDetect_index_w(void); +extern u8 leoRecal_i(void); +extern u8 leoRecal_w(void); +extern u8 leoSeek_i(u16 rwmode); +extern u8 leoSeek_w(void); +extern s32 leoRecv_event_mesg(s32 control); +extern u32 leoChk_err_retry(u32 sense); +extern u8 leoChk_cur_drvmode(void); +extern void leoDrive_reset(void); +extern u32 leoChkUnit_atten(void); +extern u32 leoRetUnit_atten(void); +extern void leoClrUA_RESET(void); +extern void leoClrUA_MEDIUM_CHANGED(void); +extern void leoSetUA_MEDIUM_CHANGED(void); +extern void leoInitUnit_atten(void); +extern int leoC2_Correction(void); extern s32 leoVerifyRTC(u8 yearhi, u8 yearlo); +extern s32 __leoSetReset(void); +extern s32 __osLeoInterrupt(void); + +extern s32 __leoActive; +extern s32 LEO_country_code; +extern u8 leoDiskStack[]; +extern u8 LEOdisk_type; +extern u8 LEOdrive_flag; +extern LEOVersion __leoVersion; +extern LEOCmd* LEOcur_command; +extern OSMesgQueue LEOevent_que; +extern OSMesgQueue LEOc2ctrl_que; +extern OSMesgQueue LEOcontrol_que; +extern OSPiHandle* LEOPiInfo; +extern OSThread LEOinterruptThread; +extern tgt_param_form LEOtgt_param; +extern vu16 LEOrw_flags; #endif diff --git a/splat.yaml b/splat.yaml index de214c1..6dc89ca 100644 --- a/splat.yaml +++ b/splat.yaml @@ -130,20 +130,21 @@ segments: - [0x51C50, asm, libleo/leofunc] - [0x520C0, asm, libleo/leoint] - [0x52AC0, asm, libleo/leocmdex] - - [0x53150, asm, libleo/leoread] + - [0x53150, c, libleo/leoread] - [0x53310, asm, libleo/lbatobyte] - [0x53460, asm, libleo/driverominit] - [0x535C0, asm, libleo/inquiry] + - [0x53670, c, libleo/leodiskinit] - [0x53710, c, libleo/readdiskid] - [0x53770, asm, libleo/leord_diskid] - - [0x53900, asm, libleo/leomecha] + - [0x53900, c, libleo/leomecha] - [0x54250, asm, libleo/spdlmotor] - - [0x54310, asm, libleo/leoc2ecc] + - [0x54310, c, libleo/leoc2ecc] - [0x55400, c, libleo/setrtc] - [0x55570, asm, libleo/leomseq_tbl] - [0x55720, asm, libleo/leomotor] - [0x55810, asm, libleo/leomode_sel] - - [0x558C0, asm, libleo/leord_capa] + - [0x558C0, c, libleo/leord_capa] - [0x55960, asm, libleo/leoutil] - [0x55BB0, asm, libleo/leorezero] - [0x55C50, asm, libleo/bytetolba] @@ -151,11 +152,11 @@ segments: - [0x55ED0, asm, libleo/leotranslat] - [0x56170, asm, libleo/leotimer] - [0x56680, asm, libleo/leowrite] - - [0x567B0, asm, libleo/cjcreateleomanager] - - [0x569F0, asm, libleo/leointerrupt] + - [0x567B0, c, libleo/cjcreateleomanager] + - [0x569F0, c, libleo/leointerrupt] - [0x570C0, c, libleo/driveexist] - [0x57190, c, libleo/testunitready] - - [0x57230, asm, libleo/leotestunit] + - [0x57230, c, libleo/leotestunit] - [0x57270, c, libleo/readrtc] - [0x572D0, asm, libleo/leoseek] - [0x57390, c, libleo/seek] diff --git a/src/libleo/cjcreateleomanager.c b/src/libleo/cjcreateleomanager.c new file mode 100644 index 0000000..10deae9 --- /dev/null +++ b/src/libleo/cjcreateleomanager.c @@ -0,0 +1,83 @@ +#include +#include "libleo/internal.h" + +#ifdef NON_MATCHING +// https://decomp.me/scratch/OYMx2 +s32 LeoCJCreateLeoManager(OSPri comPri, OSPri intPri, OSMesg *cmdBuf, s32 cmdMsgCnt) { + OSPiHandle* driveRomHandle; + OSPiHandle* leoDiskHandle; + volatile LEOCmdInquiry cmdBlockInq; + volatile LEOCmd cmdBlockID; + LEODiskID thisID; + u32 stat; + u32 data; + + if (__leoActive) { + return LEO_ERROR_GOOD; + } + + if (!LeoDriveExist()) { + return LEO_ERROR_DEVICE_COMMUNICATION_FAILURE; + } + + leoDiskHandle = osLeoDiskInit(); + driveRomHandle = osDriveRomInit(); + __leoActive = 1; + + __osSetHWIntrRoutine(1, __osLeoInterrupt, leoDiskStack + 0xFF0); + leoInitialize(comPri, intPri, cmdBuf, cmdMsgCnt); + + if (osResetType == 1) { + __leoSetReset(); + } + + cmdBlockInq.header.command = 2; + cmdBlockInq.header.reserve1 = 0; + cmdBlockInq.header.control = 0; + cmdBlockInq.header.reserve3 = 0; + leoCommand((void*)&cmdBlockInq); + + { + volatile s32 dummy = (u32) &cmdBlockInq & 0xFFFFFF; + + while (dummy > 0) { + dummy -= ((u32)__leoSetReset & 0xFFFFFF) | 0x403DF4; + } + } + + while (cmdBlockInq.header.status == 8); + + if (cmdBlockInq.header.status != 0) { + return cmdBlockInq.header.sense; + } + + __leoVersion.driver = cmdBlockInq.version; + __leoVersion.drive = 6; + __leoVersion.deviceType = cmdBlockInq.dev_type; + __leoVersion.ndevices = cmdBlockInq.dev_num; + + stat = __leoVersion.driver & 0xF; + if (stat == 4) { + LEO_country_code = 0; + } else if ((stat == 3) || (stat == 1)) { + volatile u32 dummy; + + osEPiReadIo(driveRomHandle, 0x9FF00, &data); + data = ((data & 0xFF000000) >> 0x18); + dummy = 0x3ED98F23; + if (data != 0xC3) { + while (1) {} + } + + dummy *= data; + dummy -= (u32)&cmdBlockInq; + LEO_country_code = -0x17B72CEA; + } else { + while (1) {} + } + + return LEO_ERROR_GOOD; +} +#else +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/cjcreateleomanager/LeoCJCreateLeoManager.s") +#endif diff --git a/src/libleo/leoc2ecc.c b/src/libleo/leoc2ecc.c new file mode 100644 index 0000000..e880a5c --- /dev/null +++ b/src/libleo/leoc2ecc.c @@ -0,0 +1,15 @@ +#include "common.h" + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_Correction.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_single_ecc.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_double_ecc.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_3_ecc.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoC2_4_ecc.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoAlpha_mult.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoc2ecc/leoAlpha_div.s") diff --git a/src/libleo/leodiskinit.c b/src/libleo/leodiskinit.c new file mode 100644 index 0000000..eb77d93 --- /dev/null +++ b/src/libleo/leodiskinit.c @@ -0,0 +1,31 @@ +#include +#include "PR/R4300.h" +#include "libleo/internal.h" + +extern OSPiHandle __LeoDiskHandle; +extern OSPiHandle* __osDiskHandle; +extern OSPiHandle* __osPiTable; + +OSPiHandle* osLeoDiskInit(void) { + u32 prevInt; + + __LeoDiskHandle.type = DEVICE_TYPE_64DD; + __LeoDiskHandle.baseAddress = PHYS_TO_K1(PI_DOM2_ADDR1); + __LeoDiskHandle.latency = 3; + __LeoDiskHandle.pulse = 6; + __LeoDiskHandle.pageSize = 6; + __LeoDiskHandle.relDuration = 2; + __LeoDiskHandle.domain = PI_DOMAIN2; + __LeoDiskHandle.speed = 0; + + bzero(&__LeoDiskHandle.transferInfo, sizeof(__OSTranxInfo)); + prevInt = __osDisableInt(); + + __LeoDiskHandle.next = __osPiTable; + __osPiTable = &__LeoDiskHandle; + __osDiskHandle = &__LeoDiskHandle; + + __osRestoreInt(prevInt); + + return &__LeoDiskHandle; +} diff --git a/src/libleo/leointerrupt.c b/src/libleo/leointerrupt.c new file mode 100644 index 0000000..195ffd1 --- /dev/null +++ b/src/libleo/leointerrupt.c @@ -0,0 +1,206 @@ +#include +#include "ultra64/internal.h" +#include "libleo/internal.h" +#include "PR/os_system.h" + +extern OSThread* __osRunQueue; +extern OSThread *__osPopThread(OSThread **); +extern void __osEnqueueThread(OSThread **, OSThread *); +extern OSIntMask __osGlobalIntMask; +void __osLeoAbnormalResume(void); +void __osLeoResume(void); +extern s32 osEPiRawStartDma(OSPiHandle *, s32, u32, void *, u32); + +s32 __osLeoInterrupt(void) { + u32 stat = 0; + volatile u32 pi_stat; + u32 bm_stat; + __OSTranxInfo* info = &__osDiskHandle->transferInfo; + __OSBlockInfo* blockInfo = &info->block[info->blockNum]; + + pi_stat = HW_REG(PI_STATUS_REG, u32); + if (pi_stat & PI_STATUS_DMA_BUSY) { + __osGlobalIntMask &= ~0x800; + blockInfo->errStatus = 0x1D; + __osLeoResume(); + return 1; + } + + pi_stat = HW_REG(PI_STATUS_REG, u32); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + } + + stat = HW_REG(0x5000508, u32); + if (stat & 0x2000000) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + } + + HW_REG(0x5000510, u32) = info->bmCtlShadow | 0x1000000; + blockInfo->errStatus = 0; + return 0; + } + if (info->cmdType == 2) { + return 1; + } + if (stat & 0x8000000) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + } + + stat = HW_REG(0x5000508, u32); + blockInfo->errStatus = 0x16; + __osLeoResume(); + HW_REG(PI_STATUS_REG, u32) = 2; + __osGlobalIntMask |= 0x100401; + return 1; + } + if (info->cmdType == 1) { + if (!(stat & 0x40000000)) { + if ((info->sectorNum + 1) != (info->transferMode * 0x55)) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + HW_REG(PI_STATUS_REG, u32) = 2; + __osGlobalIntMask |= 0x100401; + blockInfo->errStatus = 0; + __osLeoResume(); + return 1; + } else { + blockInfo->dramAddr = (u8*)(blockInfo->dramAddr) + blockInfo->sectorSize; + info->sectorNum++; + osEPiRawStartDma(__osDiskHandle, 1, 0x5000400, blockInfo->dramAddr, blockInfo->sectorSize); + return 1; + } + } else if (info->cmdType == 0) { + if (info->transferMode == 3) { + if (((s32)blockInfo->C1ErrNum + 0x11) < info->sectorNum) { + blockInfo->errStatus = 0; + __osLeoAbnormalResume(); + return 1; + } + if ((stat & 0x40000000) == 0) { + blockInfo->errStatus = 0x17; + __osLeoAbnormalResume(); + return 1; + } + } else { + blockInfo->dramAddr = (u8*)(blockInfo->dramAddr) + blockInfo->sectorSize; + } + + bm_stat = HW_REG(0x5000510, u32); + if (((bm_stat & 0x200000) && (bm_stat & 0x400000)) || (bm_stat & 0x2000000)) { + if (blockInfo->C1ErrNum >= 4) { + if ((info->transferMode != 3) || (info->sectorNum >= 0x53)) { + blockInfo->errStatus = 0x17; + __osLeoAbnormalResume(); + return 1; + } + } else { + int errNum = blockInfo->C1ErrNum; + + blockInfo->C1ErrSector[errNum] = info->sectorNum + 1; + } + blockInfo->C1ErrNum++; + } + + if (stat & 0x10000000) { + if (info->sectorNum != 0x57) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + if ((info->transferMode == 2) && (info->blockNum == 0)) { + info->blockNum = 1; + info->sectorNum = -1; + info->block[1].dramAddr = (u8*)(info->block[1].dramAddr) - info->block[1].sectorSize; + blockInfo->errStatus = 0x16; + } else { + HW_REG(PI_STATUS_REG, u32) = 2; + __osGlobalIntMask |= 0x100401; + info->cmdType = 2; + blockInfo->errStatus = 0; + } + osEPiRawStartDma(__osDiskHandle, 0, 0x5000000U, blockInfo->C2Addr, blockInfo->sectorSize * 4); + return 1; + } + if ((info->sectorNum == -1) && (info->transferMode == 2) && (info->blockNum == 1)) { + __OSBlockInfo* bptr = info->block; + + if (bptr->C1ErrNum == 0) { + if (((u32*)bptr->C2Addr)[0] | ((u32*)bptr->C2Addr)[1] | ((u32*)bptr->C2Addr)[2] | + ((u32*)bptr->C2Addr)[3]) { + bptr->errStatus = 0x17; + __osLeoAbnormalResume(); + return 1; + } + } + bptr->errStatus = 0; + __osLeoResume(); + } + info->sectorNum++; + if (stat & 0x40000000) { + if (info->sectorNum >= 0x55) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + osEPiRawStartDma(__osDiskHandle, 0, 0x5000400, blockInfo->dramAddr, blockInfo->sectorSize); + blockInfo->errStatus = 0; + return 1; + } else if (info->sectorNum < 0x55) { + blockInfo->errStatus = 0x18; + __osLeoAbnormalResume(); + return 1; + } + return 1; + } else { + blockInfo->errStatus = 4; + __osLeoAbnormalResume(); + return 1; + } +} + +void __osLeoAbnormalResume(void) { + __OSTranxInfo* info; + u32 pi_stat; + + info = &__osDiskHandle->transferInfo; + pi_stat = HW_REG(PI_STATUS_REG, u32); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + } + + HW_REG(0x5000510, u32) = info->bmCtlShadow | 0x10000000; + pi_stat = HW_REG(PI_STATUS_REG, u32); + while (pi_stat & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY)) { + pi_stat = HW_REG(PI_STATUS_REG, u32); + } + + HW_REG(0x5000510, u32) = info->bmCtlShadow; + __osLeoResume(); + HW_REG(PI_STATUS_REG, u32) = 2; + __osGlobalIntMask |= 0x100401; +} + +void __osLeoResume(void) { + __OSEventState* es; + OSMesgQueue* mq; + s32 last; + + es = &__osEventStateTab[8]; + mq = es->queue; + if ((mq == 0) || (mq->validCount >= mq->msgCount)) { + return; + } + last = (mq->first + mq->validCount) % mq->msgCount; + mq->msg[last] = es->msg; + mq->validCount++; + if (mq->mtqueue->next != NULL) { + __osEnqueueThread(&__osRunQueue, __osPopThread(&mq->mtqueue)); + } +} diff --git a/src/libleo/leomecha.c b/src/libleo/leomecha.c new file mode 100644 index 0000000..5de7819 --- /dev/null +++ b/src/libleo/leomecha.c @@ -0,0 +1,278 @@ +#include +#include "libleo/internal.h" + +extern s32 currentCommand; +extern u32 asic_cur_status; // static? +extern u32 unit_atten; // static? + +s32 osEPiWriteIo(OSPiHandle *, u32 , u32 ); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunknown-pragmas" + +u8 leoAnalize_asic_status(void) { + u32 curr_stat; + + osEPiReadIo(LEOPiInfo, LEO_STATUS, &asic_cur_status); + + if ((curr_stat = asic_cur_status ^ 0x1000000) & 0x1C3FFFF) { + if (curr_stat & 0x1C1FFFF) { + LEOdrive_flag = 0; + } + if (curr_stat & LEO_STATUS_PRESENCE_MASK) { + return 41; + } + if ((curr_stat & 0xC00000) == LEO_STATUS_BUSY_STATE) { + return LEO_SENSE_COMMAND_PHASE_ERROR; + } + if (curr_stat & LEO_STATUS_RESET_STATE) { + unit_atten |= 2; + return LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED; + } + if (curr_stat & LEO_STATUS_DISK_PRESENT) { + return LEO_SENSE_EJECTED_ILLEGALLY_RESUME; + } + if (curr_stat & LEO_STATUS_DISK_CHANGE) { + unit_atten |= 1; + return LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED; + } + if (curr_stat & LEO_STATUS_MECHANIC_ERROR) { + return LEO_SENSE_NO_SEEK_COMPLETE; + } + } + return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; +} + +u8 leoChk_asic_ready(u32 asic_cmd) { + u32 sense_code = leoAnalize_asic_status(); + + switch (sense_code) { + case LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED: + if (asic_cmd == ASIC_CLR_CHGFLG) { + return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + } + case LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED: + if (!(asic_cur_status & LEO_STATUS_BUSY_STATE)) { + if (asic_cmd == ASIC_CLR_RSTFLG) { + return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + } + if (leoRecv_event_mesg(0) != 0) { + return LEO_SENSE_WAITING_NMI; + } + osEPiWriteIo(LEOPiInfo, LEO_CMD, ASIC_CLR_RSTFLG); + if (leoRecv_event_mesg(1) != 0) { + return LEO_SENSE_WAITING_NMI; + } + } + default: + break; + case LEO_SENSE_EJECTED_ILLEGALLY_RESUME: + if (asic_cmd & ASIC_NEED_DISK_IN) { + break; + } + case LEO_SENSE_NO_SEEK_COMPLETE: + return LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + } + return sense_code; +} + +u8 leoChk_done_status(u32 asic_cmd) { + u32 asic_data; + u32 code = leoAnalize_asic_status(); + + switch (code) { + case 43: + case 47: + if (!(asic_cur_status & 0x800000)) { + if (leoRecv_event_mesg(0) != 0) { + return 37; + } + + osEPiWriteIo(LEOPiInfo, 0x5000508, 0x90000); + if (leoRecv_event_mesg(1) != 0) { + return 37; + } + } + break; + + case 49: + if (asic_cmd & 1) { + break; + } + return 0; + + case 21: + osEPiWriteIo(LEOPiInfo, 0x5000500, 0); + if (leoRecv_event_mesg(0) != 0) { + return 37; + } + + osEPiWriteIo(LEOPiInfo, 0x5000508, 0xC0000); + if (leoRecv_event_mesg(1) != 0) { + return 37; + } + + osEPiReadIo(LEOPiInfo, 0x5000500, &asic_data); + code = leoChk_asic_ready(0xC0000); + if (code != 0) { + return code; + } + + if (asic_data & 0x10000) { + return 2; + } + if (asic_data & 0x20000) { + return 24; + } + if (asic_data & 0x40000) { + return 1; + } + if (asic_data & 0x80000) { + return 21; + } + if (asic_data & 0x200000) { + return 11; + } + return 41; + + default: + break; + } + return code; +} + +u8 leoSend_asic_cmd_i(u32 asic_cmd, u32 asic_data) { + u8 status = leoChk_asic_ready(asic_cmd); + + if (status != 0) { + return LEOcur_command->header.sense = status; + } + osEPiWriteIo(LEOPiInfo, LEO_DATA, asic_data); + if (leoRecv_event_mesg(0) != 0) { + return LEOcur_command->header.sense = LEO_SENSE_WAITING_NMI; + } + osEPiWriteIo(LEOPiInfo, LEO_STATUS, asic_cmd); + return 0; +} + +u8 leoWait_mecha_cmd_done(u32 asic_cmd) { + u32 done_stat; + + if (leoRecv_event_mesg(1)) { + return LEO_SENSE_WAITING_NMI; + } + done_stat = leoChk_done_status(asic_cmd); + if (done_stat != 0) { + return done_stat; + } + return 0; +} + +u8 leoSend_asic_cmd_w(u32 asic_cmd, u32 asic_data) { + u32 wstatus = leoSend_asic_cmd_i(asic_cmd, asic_data); + + if (wstatus != 0) { + return wstatus; + } + return leoWait_mecha_cmd_done(asic_cmd); +} + +u8 leoSend_asic_cmd_w_nochkDiskChange(u32 asic_cmd, u32 asic_data) { + u8 status; + u32 done_stat; + + status = leoChk_asic_ready(asic_cmd); + if ((status != LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED) && (status != 0)) { + return LEOcur_command->header.sense = status; + } + + osEPiWriteIo(LEOPiInfo, LEO_DATA, asic_data); + if (leoRecv_event_mesg(0) != 0) { + return LEOcur_command->header.sense = LEO_SENSE_WAITING_NMI; + } + + osEPiWriteIo(LEOPiInfo, LEO_STATUS, asic_cmd); + if (leoRecv_event_mesg(1) != 0) { + return LEO_SENSE_WAITING_NMI; + } + + done_stat = leoChk_done_status(asic_cmd); + if ((done_stat != LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED) && (done_stat != 0)) { + return done_stat; + } + return 0; +} + +u8 leoDetect_index_w(void) { + return leoSend_asic_cmd_w(ASIC_INDEX_LOCK_RETRY, 0); +} + +u8 leoRecal_i(void) { + return leoSend_asic_cmd_i(ASIC_RECAL, 0); +} + +u8 leoRecal_w(void) { + return leoSend_asic_cmd_w(ASIC_RECAL, 0); +} + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoSeek_i.s") + +u8 leoSeek_w(void) { + u8 sksense = leoSeek_i(0); + + if (sksense != 0) { + return sksense; + } + + return leoWait_mecha_cmd_done(ASIC_RD_SEEK); +} + +s32 leoRecv_event_mesg(s32 control) { + u32 done_mesg; + + if (osRecvMesg(&LEOevent_que, (OSMesg*)&done_mesg, control) == 0) { + if (done_mesg == 0xA0000) { + leoDrive_reset(); + return 0xFF; + } + } + return 0; +} + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_err_retry.s") + +#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_cur_drvmode.s") + +void leoDrive_reset() { + osEPiWriteIo(LEOPiInfo, LEO_HARD_RESET, 0xAAAA0000); +} + +u32 leoChkUnit_atten(void) { + return unit_atten; +} + +u32 leoRetUnit_atten(void) { + if (unit_atten & 2) { + return 43; + } + if (unit_atten & 1) { + return 47; + } + return 0; +} + +void leoClrUA_RESET(void) { + unit_atten &= ~2; +} + +void leoClrUA_MEDIUM_CHANGED(void) { + unit_atten &= ~1; +} + +void leoSetUA_MEDIUM_CHANGED(void) { + unit_atten |= 1; +} + +void leoInitUnit_atten(void) { + unit_atten = 1; +} diff --git a/src/libleo/leord_capa.c b/src/libleo/leord_capa.c new file mode 100644 index 0000000..07b2434 --- /dev/null +++ b/src/libleo/leord_capa.c @@ -0,0 +1,26 @@ +#include +#include "libleo/internal.h" + +// static? +const u16 LEORAM_START_LBA[] = { + 0x05A2, 0x07C6, 0x09EA, 0x0C0E, 0x0E32, 0x1010, 0x10DC, +}; +// static? +const s32 LEORAM_BYTE[] = { + 0x024A9DC0, 0x01C226C0, 0x01450F00, 0x00D35680, 0x006CFD40, 0x001DA240, 0x00000000, +}; + +void leoRd_capacity(void) { + if (LEOcur_command->header.control & LEO_CONTROL_WRT) { + LEOcur_command->data.readwrite.lba = LEORAM_START_LBA[LEOdisk_type] - 0x18; + LEOcur_command->data.readwrite.xfer_blks = LEO_LBA_MAX; + LEOcur_command->data.readwrite.buff_ptr = LEORAM_BYTE[LEOdisk_type]; + } else { + LEOcur_command->data.readwrite.lba = 0; + LEOcur_command->data.readwrite.xfer_blks = LEO_LBA_MAX; + LEOcur_command->data.readwrite.buff_ptr = 0x3D78F40; // Total capacity, approx. 64.45 MB + } + LEOcur_command->header.status = LEO_STATUS_GOOD; +} + +// #pragma GLOBAL_ASM("asm/nonmatchings/libleo/leord_capa/leoRd_capacity.s") diff --git a/src/libleo/leoread.c b/src/libleo/leoread.c new file mode 100644 index 0000000..f5b2e78 --- /dev/null +++ b/src/libleo/leoread.c @@ -0,0 +1,64 @@ +#include +#include "libleo/internal.h" + +void leoRead_common(u32 offset); + +void leoRead(void) { + LEOrw_flags = 0; + leoRead_common(0x18); +} + +void leoRead_common(u32 offset) { + u32 tg_lba = LEOcur_command->data.readwrite.lba; + u32 tg_blocks = LEOcur_command->data.readwrite.xfer_blks; + u32 message; + + if ((tg_lba | tg_blocks) >> 0x10 != 0) { + goto invalid_lba; + } + + tg_lba += offset; + if ((tg_lba + tg_blocks) > 0x10DC) { // Unclear what this number represents + invalid_lba: + LEOcur_command->header.sense = LEO_SENSE_LBA_OUT_OF_RANGE; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + } + + if (tg_blocks == 0) { + if (tg_lba < 0x10DC) { + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; + return; + } + goto invalid_lba; + } + + LEOtgt_param.lba = tg_lba; + LEOrw_flags &= 0x3FFF; + osSendMesg(&LEOc2ctrl_que, NULL, OS_MESG_NOBLOCK); + osStartThread(&LEOinterruptThread); + + while (true) { + osRecvMesg(&LEOcontrol_que, (OSMesg)&message, OS_MESG_BLOCK); + + switch (message) { + case 0x80000: + leoC2_Correction(); + LEOrw_flags &= ~0x4000; + osSendMesg(&LEOc2ctrl_que, NULL, OS_MESG_NOBLOCK); + break; + + default: + LEOcur_command->header.sense = message; + LEOcur_command->header.status = LEO_STATUS_CHECK_CONDITION; + return; + + case 0x90000: + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; + return; + + } + } +} diff --git a/src/libleo/leotestunit.c b/src/libleo/leotestunit.c new file mode 100644 index 0000000..af4a964 --- /dev/null +++ b/src/libleo/leotestunit.c @@ -0,0 +1,8 @@ +#include +#include "libleo/internal.h" + +void leoTest_unit_rdy(void) { + ((LEOCmdTestUnitReady*)LEOcur_command)->test = leoChk_cur_drvmode(); + LEOcur_command->header.sense = LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION; + LEOcur_command->header.status = LEO_STATUS_GOOD; +} diff --git a/src/libleo/setrtc.c b/src/libleo/setrtc.c index d21074b..55c532f 100644 --- a/src/libleo/setrtc.c +++ b/src/libleo/setrtc.c @@ -30,19 +30,15 @@ s32 LeoSetRTC(LEOCmd* cmdBlock, LEODiskTime* RTCdata, OSMesgQueue* mq) { */ // https://decomp.me/scratch/NUHIy s32 leoVerifyRTC(u8 yearhi, u8 yearlo) { - u32 year; - s32 hiMask; - u32 loMask; - hiMask = yearhi & 0xFF; - loMask = yearlo & 0xFF; - if (((loMask & 0xF) >= 0xA) || ((loMask & 0xF0) >= 0x91) || ((hiMask & 0xF) >= 0xA) || ((hiMask & 0xF0) >= 0x91)) { - return 1; - } - year = (((hiMask - ((hiMask >> 4) * 6)) * 0x64) + loMask) - ((loMask >> 4) * 6); - if ((year < 0x7CCU) || (year >= 0x830U)) { - return 1; - } - return 0; + u32 year; + if (((yearlo & 0xF) >= 0xA) || ((yearlo & 0xF0) >= 0x91) || ((yearhi & 0xF) >= 0xA) || ((yearhi & 0xF0) >= 0x91)) { + return 1; + } + year = (((yearhi - ((yearhi >> 4) * 6)) * 0x64) + yearlo) - ((yearlo >> 4) * 6); + if ((year < 0x7CCU) || (year >= 0x830U)) { + return 1; + } + return 0; } #else #pragma GLOBAL_ASM("asm/nonmatchings/libleo/setrtc/leoVerifyRTC.s") diff --git a/tools/symbol_addrs.txt b/tools/symbol_addrs.txt index ddcbd36..1cb3779 100644 --- a/tools/symbol_addrs.txt +++ b/tools/symbol_addrs.txt @@ -40,6 +40,8 @@ __osGbpakSelectBank = 0x80065AD0; __osGetId = 0x8005C894; __osIdCheckSum = 0x8005C2E4; __osLeoInterrupt = 0x80055DF0; +__osLeoAbnormalResume = 0x80056350; +__osLeoResume = 0x80056404; __osPackEepReadData = 0x80065E44; __osPackEepWriteData = 0x8005BEF8; __osPackReadData = 0x80058F20; @@ -88,6 +90,30 @@ guScaleF = 0x80056CF0; guTranslate = 0x8005E5E8; guTranslateF = 0x8005E5A0; ldiv = 0x80064C10; +LEOcur_command = 0x801006C8; +LEOPiInfo = 0x80100710; +unit_atten = 0x80100844; +asic_cur_status = 0x80100840; +currentCommand = 0x80100730; +LEOinterruptThread = 0x800FFC88; +LEOc2ctrl_que = 0x801006F8; +LEOcontrol_que = 0x80100668; +LEORAM_START_LBA = 0x8007DD18; +LEORAM_BYTE = 0x8007DD28; +LEOdrive_flag = 0x801006D4; +LEOevent_que = 0x80100650; +LEOtgt_param = 0x801006E0; +leoDiskStack = 0x801020D0; +LEOdisk_type = 0x801006D8; +LEO_country_code = 0x801006EC; +LEOrw_flags = 0x801006D6; +leoC2_Correction = 0x80053710; +leoC2_single_ecc = 0x8005379C; +leoC2_double_ecc = 0x80053870; +leoC2_3_ecc = 0x80053AF0; +leoC2_4_ecc = 0x80053ED8; +leoAlpha_mult = 0x80054774; +leoAlpha_div = 0x800547B8; leoAnalize_asic_status = 0x80052D00; leoChk_asic_ready = 0x80052E0C; leoChk_cur_drvmode = 0x80053540; @@ -113,7 +139,9 @@ leoRead_system_area = 0x8005233C; leoRecal_i = 0x800532EC; leoRecal_w = 0x80053314; leoRecv_event_mesg = 0x800533DC; +leoInitUnit_atten = 0x80053640; leoRetUnit_atten = 0x800535BC; +leoChkUnit_atten = 0x800535B0; leoRezero = 0x80054FB0; leoSeek_i = 0x8005333C; leoSeek_w = 0x800533A0; @@ -318,6 +346,7 @@ osTvType = 0x80000300; __osGetCause = 0x80063E00; CartRomHandle = 0x80102430; LeoDiskHandle = 0x801024A8; +__LeoDiskHandle = 0x801007C0; __osGlobalIntMask = 0x800796B0; __osShutdown = 0x800796AC; osViClock = 0x800796A8; @@ -327,6 +356,7 @@ alGlobals = 0x80079640; guPerspectiveF = 0x8005A5C0; guPerspective = 0x8005A7F0; alSeqFileNew = 0x80058278; +__osDiskHandle = 0x80100834; __osPiTable = 0x8007A87C; osViRepeatLine = 0x8005B230; osPfsIsPlug = 0x8005B2A0; @@ -387,6 +417,7 @@ __osPfsLastChannel = 0x8007AE50; __osViDevMgr = 0x8007AE90; __osLeoDevMgr = 0x80079514; __leoActive = 0x800795B0; +__leoVersion = 0x801010D0; __additional_scanline = 0x8007AEAC; viThread = 0x80103950; viThreadStack = 0x80103B00;