cdromdrive: clean-up and extend READ_TOC command.

This commit is contained in:
Maxim Poliakovski 2023-09-25 23:13:46 +02:00
parent 637844269f
commit 99f596ea19

View File

@ -143,6 +143,8 @@ AddrMsf CdromDrive::lba_to_msf(const int lba) {
} }
uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) { uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) {
int tot_tracks, data_len;
uint8_t start_track, session_num;
uint8_t* out_ptr; uint8_t* out_ptr;
uint16_t alloc_len = READ_WORD_BE_U(&cmd_ptr[7]); uint16_t alloc_len = READ_WORD_BE_U(&cmd_ptr[7]);
bool is_msf = !!(cmd_ptr[1] & 2); bool is_msf = !!(cmd_ptr[1] & 2);
@ -157,9 +159,8 @@ uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) {
return 0; return 0;
switch(format) { switch(format) {
case 0: { case 0: // Formatted TOC
int tot_tracks, data_len; start_track = cmd_ptr[6];
uint8_t start_track = cmd_ptr[6];
if (!start_track) { // special case: track zero (lead-in) as starting track if (!start_track) { // special case: track zero (lead-in) as starting track
// return all tracks starting with track 1 plus lead-out // return all tracks starting with track 1 plus lead-out
start_track = 1; start_track = 1;
@ -207,19 +208,27 @@ uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) {
} }
} }
return data_len; return data_len;
} case 1: // Multi-session info
case 1:
std::memset(data_ptr, 0, 12); std::memset(data_ptr, 0, 12);
data_ptr[1] = 10; // TOC data length data_ptr[1] = 10; // TOC data length
data_ptr[2] = 1; // first session number data_ptr[2] = 1; // first session number
data_ptr[3] = 1; // last session number data_ptr[3] = 1; // last session number
data_ptr[5] = this->tracks[0].adr_ctrl;
data_ptr[6] = 1;
if (is_msf) {
AddrMsf msf = lba_to_msf(this->tracks[0].start_lba + 150);
data_ptr[ 8] = 0; // reserved
data_ptr[ 9] = msf.min;
data_ptr[10] = msf.sec;
data_ptr[11] = msf.frm;
}
return 12; return 12;
case 2: case 2: // Raw TOC
{ session_num = cmd_ptr[6];
// TOC if (!session_num)
int session_num = cmd_ptr[6]; session_num = 1;
if (session_num > 1) { if (session_num > 1) {
LOG_F(ERROR, "CDROM: unsupported session number %d", session_num); LOG_F(ERROR, "CDROM: invalid session number %d", session_num);
this->set_error(ScsiSense::ILLEGAL_REQ, ScsiError::INVALID_CDB); this->set_error(ScsiSense::ILLEGAL_REQ, ScsiError::INVALID_CDB);
return 0; return 0;
} }
@ -231,19 +240,19 @@ uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) {
out_ptr[3] = 1; // last session number out_ptr[3] = 1; // last session number
out_ptr += 4; out_ptr += 4;
// descriptor #1 -> first track // descriptor #1 -> first track
out_ptr[0] = 1; out_ptr[0] = session_num;
out_ptr[1] = this->tracks[0].adr_ctrl; out_ptr[1] = this->tracks[0].adr_ctrl;
out_ptr[3] = 0xA0; // point -> first track out_ptr[3] = 0xA0; // point -> first track
out_ptr[8] = 1; // first track number out_ptr[8] = 1; // first track number
out_ptr += 11; out_ptr += 11;
// descriptor #2 -> last track // descriptor #2 -> last track
out_ptr[0] = 1; out_ptr[0] = session_num;
out_ptr[1] = this->tracks[0].adr_ctrl; out_ptr[1] = this->tracks[0].adr_ctrl;
out_ptr[3] = 0xA1; // point -> last track out_ptr[3] = 0xA1; // point -> last track
out_ptr[8] = 1; // last track number out_ptr[8] = 1; // last track number
out_ptr += 11; out_ptr += 11;
// descriptor #3 -> lead-out // descriptor #3 -> lead-out
out_ptr[0] = 1; out_ptr[0] = session_num;
out_ptr[1] = this->tracks[0].adr_ctrl; out_ptr[1] = this->tracks[0].adr_ctrl;
out_ptr[3] = 0xA2; // point -> lead-out out_ptr[3] = 0xA2; // point -> lead-out
if (is_msf) { if (is_msf) {
@ -257,7 +266,7 @@ uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) {
} }
out_ptr += 11; out_ptr += 11;
// descriptor #4 -> data track // descriptor #4 -> data track
out_ptr[0] = 1; out_ptr[0] = session_num;
out_ptr[1] = this->tracks[0].adr_ctrl; out_ptr[1] = this->tracks[0].adr_ctrl;
out_ptr[3] = 1; // point -> data track out_ptr[3] = 1; // point -> data track
if (is_msf) { if (is_msf) {
@ -268,7 +277,6 @@ uint32_t CdromDrive::read_toc(uint8_t *cmd_ptr, uint8_t *data_ptr) {
out_ptr[10] = msf.frm; out_ptr[10] = msf.frm;
} }
return 48; return 48;
}
default: default:
LOG_F(ERROR, "CDROM: unsupported format in READ_TOC"); LOG_F(ERROR, "CDROM: unsupported format in READ_TOC");
this->set_error(ScsiSense::ILLEGAL_REQ, ScsiError::INVALID_CDB); this->set_error(ScsiSense::ILLEGAL_REQ, ScsiError::INVALID_CDB);