1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-05-10 02:54:24 +00:00
oot/src/libleo/leo/leocmdex.c
fig02 2278bcb2c3
Remove Variables.h; Decouple z64.h from global.h (#2507)
* progress

* z64.h issues sorted

* remove variables.h

* format

* n64 fix

* another fix

* did the wrong fix

* fix libleo

* fix bss

* review

* remove instead of comment
2025-04-19 22:04:08 -04:00

264 lines
8.6 KiB
C

#include "ultra64/leo.h"
#include "ultra64/leoappli.h"
#include "ultra64/leodrive.h"
#include "attributes.h"
#include "ultra64.h"
extern vu16 LEOrw_flags;
static void (*cmd_tbl[16])(void) = {
NULL, leoClr_queue, leoInquiry, leoTest_unit_rdy, leoRezero, leoRead,
leoWrite, leoSeek, leoStart_stop, leoRd_capacity, leoTranslate, leoMode_sel,
leoReadDiskId, leoReadTimer, leoSetTimer, leoClr_reset,
};
static LEOCmdRead system_read_cmd = {
{ LEO_COMMAND_READ, 0, 0, 0, 0, 0, 0, 0, 0 }, 12, 1, 0, 0,
};
static const u8 system_lba[8] = { 0, 1, 8, 9, 0, 0, 0, 0 };
OSPiHandle* LEOPiInfo;
OSIoMesg LEOPiDmaParam;
s32 currentCommand;
u8 leoRead_system_area(void);
void leomain(void* arg0) {
u32 cur_status;
u32 sense_code;
u8 disktype_bak;
((u8*)&LEO_country_code)[0] = *(vu8*)OS_PHYSICAL_TO_K1(0x10);
((u8*)&LEO_country_code)[1] = *(vu8*)OS_PHYSICAL_TO_K1(0x90);
((u8*)&LEO_country_code)[2] = *(vu8*)OS_PHYSICAL_TO_K1(0x110);
((u8*)&LEO_country_code)[3] = *(vu8*)OS_PHYSICAL_TO_K1(0x190);
LEOasic_seq_ctl_shadow = 0;
LEOasic_bm_ctl_shadow = 0;
LEOdrive_flag = 0;
LEOclr_que_flag = 0;
leoInitUnit_atten();
LEOPiInfo = osLeoDiskInit();
LEOPiDmaParam.hdr.pri = 1;
LEOPiDmaParam.hdr.retQueue = &LEOdma_que;
osEPiReadIo(LEOPiInfo, ASIC_STATUS, &cur_status);
if (!(cur_status & 0x400000) && (cur_status & 0x06800000)) {
leoDrive_reset();
}
while (true) {
osRecvMesg(&LEOcommand_que, (OSMesg*)&LEOcur_command, OS_MESG_BLOCK);
currentCommand = LEOcur_command->header.command;
if (LEOcur_command->header.command == 0) {
leoDrive_reset();
osRecvMesg(&LEOevent_que, NULL, OS_MESG_NOBLOCK);
continue;
}
sense_code = leoChk_asic_ready(0x10001);
cur_status = leoChkUnit_atten();
do {
if (cur_status == 0) {
if (sense_code == 0) {
continue;
}
} else {
switch (sense_code) {
case 3:
case 37:
case 41:
case 43:
break;
case 49:
if (leoRetUnit_atten() == 43) {
sense_code = 43;
}
break;
default:
sense_code = leoRetUnit_atten();
}
}
switch (sense_code) {
case 47:
switch (LEOcur_command->header.command) {
case 2:
case 8:
case 11:
case 12:
case 13:
case 14:
case 15:
continue;
}
break;
case 49:
switch (LEOcur_command->header.command) {
case 2:
case 11:
case 13:
case 14:
case 15:
continue;
default:
sense_code = 42;
}
break;
case 43:
switch (LEOcur_command->header.command) {
case 15:
leoClrUA_RESET();
FALLTHROUGH;
case 2:
case 13:
case 14:
continue;
}
break;
default:
/* empty */;
}
if (LEOcur_command->header.command == 3) {
LEOcur_command->data.modeSelect.reserve1 = leoChk_cur_drvmode();
}
LEOcur_command->header.sense = sense_code;
LEOcur_command->header.status = 2;
goto post_exe;
} while (0);
if (LEOdrive_flag == 0) {
switch (LEOcur_command->header.command) {
case 2:
case 3:
case 8:
case 11:
case 13:
case 14:
case 15:
break;
default:
if (LEO_country_code == 0) {
osEPiReadIo(LEOPiInfo, ASIC_ID_REG, &cur_status);
if ((cur_status & 0x70000) != 0x40000) {
while (true) {}
}
}
if (leoRead_system_area() != 0) {
LEOcur_command->header.status = 2;
goto post_exe;
}
if ((LEOcur_command->header.sense =
leoSend_asic_cmd_w(0xB0001, LEO_sys_data.param.disk_type << 16)) != 0) {
LEOcur_command->header.status = 2;
goto post_exe;
}
if ((LEO_sys_data.param.disk_type & 0xF0) != 0x10) {
goto invalid_disktype;
}
LEOdisk_type = (LEO_sys_data.param.disk_type & 0xF);
if (LEOdisk_type >= 7) {
invalid_disktype:
LEOcur_command->header.sense = 0xBU;
LEOcur_command->header.status = 2;
goto post_exe;
}
LEOdrive_flag = -1;
}
}
cmd_tbl[LEOcur_command->header.command]();
post_exe:
if (LEOcur_command->header.control & 0x80) {
osSendMesg(LEOcur_command->header.post, (void*)(s32)LEOcur_command->header.sense, OS_MESG_BLOCK);
}
if (LEOclr_que_flag != 0) {
leoClr_queue();
}
}
}
u8 leoRead_system_area(void) {
LEOCmdRead dummy_cmd;
void* backup_pointer;
u32 retry_cntr;
s32 read_mode;
backup_pointer = LEOcur_command;
LEOcur_command = (LEOCmd*)&dummy_cmd;
read_mode = 0;
retry_cntr = 0;
while (true) {
LEOdisk_type = 0;
// For lba_to_phys to avoid dealing with alternative tracks on the disk
LEO_sys_data.param.defect_num[0] = 0;
LEOrw_flags = 0x3000;
dummy_cmd = system_read_cmd;
dummy_cmd.buffPtr = &LEO_sys_data;
if (read_mode == 0) {
// read System LBA 12 (+0, this is an offset value for leoRead_common)
// see system_read_cmd premade struct
leoRead_common(0);
switch (dummy_cmd.header.sense) {
case LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION:
do {
// if expecting a retail disk, LBA 12 is expected to do a read error, if not then freeze
} while (LEO_country_code != 0);
retry_cntr = 0;
read_mode--;
continue;
case LEO_SENSE_UNRECOVERED_READ_ERROR:
do {
// if expecting a development disk, LBA 12 is expected to read correctly, if not then freeze
} while (LEO_country_code == 0);
retry_cntr = 0;
read_mode--;
continue;
}
} else {
// read System LBA 0,1,8,9 (or 2,3,10,11 for dev)
dummy_cmd.lba = system_lba[retry_cntr & 3];
if (LEO_country_code == 0) {
dummy_cmd.lba += 2;
}
leoRead_common(0);
if (dummy_cmd.header.status == LEO_STATUS_GOOD) {
do {
// if disk country and set country code in libleo mismatch, then freeze
} while (LEO_sys_data.param.country != LEO_country_code);
goto sys_read_end;
}
}
system_retry:
if (leoChk_err_retry(dummy_cmd.header.sense) != LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) {
break;
}
if (retry_cntr++ >= 0x40U) {
break;
}
if ((retry_cntr & 7) == 0) {
// Recalibrate drive every 8th tries
if ((dummy_cmd.header.sense = leoSend_asic_cmd_w(0x30001, 0)) == LEO_SENSE_NO_ADDITIONAL_SENSE_INFOMATION) {
continue;
}
goto system_retry;
}
}
sys_read_end:
LEOcur_command = backup_pointer;
LEOcur_command->header.sense = dummy_cmd.header.sense;
return GET_ERROR(*LEOcur_command);
}