diff --git a/include/libleo/internal.h b/include/libleo/internal.h index 7997020..f83f7d8 100644 --- a/include/libleo/internal.h +++ b/include/libleo/internal.h @@ -198,6 +198,7 @@ extern s32 __leoSetReset(void); extern s32 __osLeoInterrupt(void); extern u16 leoLba_to_vzone(u32 lba); extern u16 leoLba_to_phys(u32 lba); +extern void leoSet_mseq(u16 rwmode); extern s32 __leoActive; extern s32 __leoResetCalled; diff --git a/src/libleo/leoint.c b/src/libleo/leoint.c index 5456385..4556764 100644 --- a/src/libleo/leoint.c +++ b/src/libleo/leoint.c @@ -3,8 +3,12 @@ extern vu16 LEOrw_flags; extern u8 LEOC2_Syndrome[2][0xE8*4]; +extern block_param_form LEOc2_param; -void* read_write_track(); +u32 read_write_track(); +u32 leoChk_mecha_int(void); +void leosetup_BM(void); +u32 leochk_err_reg(void); void leointerrupt(void* arg) { u32 result; @@ -50,7 +54,164 @@ void leointerrupt(void* arg) { } } -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leoint/read_write_track.s") +u32 read_write_track(void) { + u32 message; + u32 block; + u32 retry_cntr; + block_param_form block_param; + u16 bnum; + u8* temp; + u32 c2datasize; + + block_param.bytes = LEOtgt_param.sec_bytes; + block_param.blkbytes = LEOtgt_param.blk_bytes; + if (LEOrw_flags & 0x2000) { + //Sector Mode + block_param.blkbytes = block_param.bytes; + } + block_param.pntr = LEOwrite_pointer; + LEOwrite_pointer += block_param.blkbytes; + if (LEOtgt_param.rdwr_blocks == 2) { + LEOwrite_pointer += block_param.blkbytes; + } + retry_cntr = 0; + for (;;) { + LEOPiInfo->transferInfo.transferMode = 1; + LEOPiInfo->transferInfo.blockNum = 0; + LEOPiInfo->transferInfo.block[0].C1ErrNum = 0; + LEOPiInfo->transferInfo.block[0].sectorSize = block_param.bytes; + LEOPiInfo->transferInfo.block[0].dramAddr = block_param.pntr; + LEOPiInfo->transferInfo.block[0].C2Addr = &LEOC2_Syndrome[0]; + if (LEOrw_flags & 0x2000) { + //Sector Mode + LEOtgt_param.rdwr_blocks = 1; + LEOPiInfo->transferInfo.transferMode = 3; + } else if (LEOtgt_param.rdwr_blocks == 2) { + LEOPiInfo->transferInfo.transferMode = 2; + LEOPiInfo->transferInfo.block[1] = LEOPiInfo->transferInfo.block[0]; + LEOPiInfo->transferInfo.block[1].C2Addr = &LEOC2_Syndrome[1]; + LEOPiInfo->transferInfo.block[1].dramAddr = ((u8*)LEOPiInfo->transferInfo.block[1].dramAddr + block_param.blkbytes); + } + message = leoChk_mecha_int(); + if (message == 0) { + if (LEOrw_flags & 0x8000) { + //Write Mode + leoSet_mseq(1); + } else { + //Read Mode + leoSet_mseq(0); + } + leosetup_BM(); + LEOPiInfo->transferInfo.bmCtlShadow = LEOasic_bm_ctl_shadow; + LEOPiInfo->transferInfo.seqCtlShadow = LEOasic_seq_ctl_shadow; + if (LEOrw_flags & 0x8000) { + LEOPiInfo->transferInfo.cmdType = 1; + osWritebackDCache(block_param.pntr, block_param.blkbytes * LEOtgt_param.rdwr_blocks); + osEPiStartDma(LEOPiInfo, &LEOPiDmaParam, 1); + osRecvMesg(&LEOdma_que, NULL, 1); + LEOasic_bm_ctl_shadow = LEOPiInfo->transferInfo.bmCtlShadow; + LEOasic_seq_ctl_shadow = LEOPiInfo->transferInfo.seqCtlShadow; + bnum = LEOPiInfo->transferInfo.blockNum; + message = LEOPiInfo->transferInfo.block[bnum].errStatus; + if (message == 0) { + return message; + } + goto track_end; + } else { + if (LEOrw_flags & 0x4000) { + osRecvMesg(&LEOc2ctrl_que, NULL, 1); + osSendMesg(&LEOc2ctrl_que, NULL, 0); + } + LEOPiInfo->transferInfo.cmdType = 0; + osInvalDCache(block_param.pntr, block_param.blkbytes * LEOtgt_param.rdwr_blocks); + osEPiStartDma(LEOPiInfo, &LEOPiDmaParam, 0); + block = 0; + while (LEOtgt_param.rdwr_blocks != 0) { + osRecvMesg(&LEOdma_que, NULL, 1); + LEOasic_bm_ctl_shadow = LEOPiInfo->transferInfo.bmCtlShadow; + LEOasic_seq_ctl_shadow = LEOPiInfo->transferInfo.seqCtlShadow; + message = LEOPiInfo->transferInfo.block[block].errStatus; + if (message != 0) { + goto track_end; + } + if (LEOrw_flags & 0x2000) { + return 0; + } + if (LEOPiInfo->transferInfo.block[block].C1ErrNum) { + if (LEOPiInfo->transferInfo.block[block].C1ErrSector[0] < 0x55) { + if (LEOtgt_param.rdwr_blocks == 1) { + osEPiReadIo(LEOPiInfo, 0x05000514, &message); + if (message & 0x10000000) { + message = 4; + goto track_end; + } + } + + if (block == 0) { + temp = LEOC2_Syndrome[0]; + } else { + temp = LEOC2_Syndrome[1]; + } + c2datasize = block_param.bytes * 4; + block_param.c2buff_e = temp + c2datasize; + osInvalDCache(temp, c2datasize); + block_param.err_num = LEOPiInfo->transferInfo.block[block].C1ErrNum; + block_param.err_pos[0] = LEOPiInfo->transferInfo.block[block].C1ErrSector[0]; + block_param.err_pos[1] = LEOPiInfo->transferInfo.block[block].C1ErrSector[1]; + block_param.err_pos[2] = LEOPiInfo->transferInfo.block[block].C1ErrSector[2]; + block_param.err_pos[3] = LEOPiInfo->transferInfo.block[block].C1ErrSector[3]; + osRecvMesg(&LEOc2ctrl_que, NULL, 1); + LEOrw_flags |= 0x4000; + LEOc2_param = block_param; + osSendMesg(&LEOcontrol_que, (void* )0x80000, 1); + } + } else { + if (LEOtgt_param.rdwr_blocks == 1) { + if ((*(u32*)&LEOC2_Syndrome[block][0x00] | *(u32*)&LEOC2_Syndrome[block][0x04] | *(u32*)&LEOC2_Syndrome[block][0x08] | *(u32*)&LEOC2_Syndrome[block][0x0C]) != 0) { + message = 0x17; + goto track_end; + } + } + } + block++; + block_param.pntr += block_param.blkbytes; + LEOtgt_param.start_block ^= 1; + LEOtgt_param.rdwr_blocks--; + } + } + return 0; + } +track_end: + if (message == 0x16) { + message = leochk_err_reg(); + } +do_retry: + if (leoChk_err_retry(message) || (LEOrw_flags & 0x1000) || retry_cntr++ == 0x40) { + break; + } + if ((retry_cntr & 7) == 0) { + message = leoSend_asic_cmd_w(0x30001, 0); + if (message != 0) { + goto do_retry; + } + } + if (message == 0x18 || (message == 0x17 && retry_cntr == 0x20)) { + message = leoDetect_index_w(); + if (message != 0) { + goto do_retry; + } + } + if (LEOrw_flags & 0x8000) { + message = leoSeek_i(1); + } else { + message = leoSeek_i(0); + } + if (message != 0) { + goto do_retry; + } + } + return message; +} u32 leoChk_mecha_int(void) { u32 stat = leoWait_mecha_cmd_done(ASIC_RD_SEEK); diff --git a/src/libleo/leomecha.c b/src/libleo/leomecha.c index a2909ff..566e51b 100644 --- a/src/libleo/leomecha.c +++ b/src/libleo/leomecha.c @@ -3,6 +3,7 @@ extern u32 asic_cur_status; // static? extern u32 unit_atten; // static? +extern s32 currentCommand; s32 osEPiWriteIo(OSPiHandle *, u32 , u32 ); @@ -245,8 +246,6 @@ s32 leoRecv_event_mesg(s32 control) { return 0; } -#ifdef NON_MATCHING -// https://decomp.me/scratch/BFO8S u32 leoChk_err_retry(u32 sense) { if ((currentCommand == LEO_COMMAND_READ_DISK_ID) || (currentCommand == LEO_COMMAND_START_STOP)) { switch (sense) { @@ -265,10 +264,8 @@ u32 leoChk_err_retry(u32 sense) { switch (sense) { case LEO_SENSE_POWERONRESET_DEVICERESET_OCCURED: unit_atten |= 2; - break; case LEO_SENSE_MEDIUM_MAY_HAVE_CHANGED: unit_atten |= 1; - break; case LEO_SENSE_DIAGNOSTIC_FAILURE: case LEO_SENSE_COMMAND_PHASE_ERROR: case LEO_SENSE_WAITING_NMI: @@ -282,9 +279,6 @@ u32 leoChk_err_retry(u32 sense) { return 0; } -#else -#pragma GLOBAL_ASM("asm/nonmatchings/libleo/leomecha/leoChk_err_retry.s") -#endif u8 leoChk_cur_drvmode(void) { u8 devstat = 0;