diff --git a/src/buslogic.c b/src/buslogic.c index 0d62b8d53..e4a8d8b9a 100644 --- a/src/buslogic.c +++ b/src/buslogic.c @@ -685,6 +685,7 @@ static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bit) { + uint32_t sg_buffer_pos = 0; uint32_t DataPointer, DataLength; if (Is24bit) @@ -698,8 +699,13 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi DataLength = BuslogicRequests->CmdBlock.new.DataLength; } - if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) - DataLength = 0; + /* if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) + DataLength = 0; */ + + if ((BuslogicRequests->CmdBlock.common.Cdb[0] != GPCMD_MODE_SELECT_6) && (BuslogicRequests->CmdBlock.common.Cdb[0] != GPCMD_MODE_SELECT_10)) + { + return; + } BuslogicLog("Data Buffer write: length %d, pointer 0x%04X\n", DataLength, DataPointer); @@ -737,8 +743,7 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi BuslogicLog("Data to transfer (S/G) %d\n", DataToTransfer); - SCSIDevices[BuslogicRequests->TargetID].InitLength = DataToTransfer; - SCSIDevices[BuslogicRequests->TargetID].CmdBuffer[SCSIDevices[BuslogicRequests->TargetID].pos++] = SCSIDevices[BuslogicRequests->TargetID].InitLength; + SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength = DataToTransfer; //If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without //checking its length, so do this procedure for both no read/write commands. @@ -763,7 +768,8 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; - DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, DataToTransfer); + DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); + sg_buffer_pos += DataToTransfer; } ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); @@ -774,10 +780,12 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { uint32_t Address = DataPointer; - SCSIDevices[BuslogicRequests->TargetID].InitLength = DataLength; - SCSIDevices[BuslogicRequests->TargetID].CmdBuffer[SCSIDevices[BuslogicRequests->TargetID].pos++] = SCSIDevices[BuslogicRequests->TargetID].InitLength; + SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength = DataLength; - DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, SCSIDevices[BuslogicRequests->TargetID].InitLength); + if (DataLength > 0) + { + DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength); + } } } } @@ -798,6 +806,8 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) { uint32_t sg_buffer_pos = 0; + uint32_t transfer_length = 0; + if (BuslogicRequests->Is24bit) { DataPointer = ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataPointer); @@ -808,9 +818,19 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) DataPointer = BuslogicRequests->CmdBlock.new.DataPointer; DataLength = BuslogicRequests->CmdBlock.new.DataLength; } + + if (DataLength > SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength) + { + DataLength = SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength; + } + + if ((DataLength != 0) && (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)) + { + BuslogicLog("Data length not 0 with TEST UNIT READY: %i (%i)\n", DataLength, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength); + } - if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) - DataLength = 0; + /* if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) + DataLength = 0; */ BuslogicLog("Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); @@ -852,7 +872,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; - DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer + sg_buffer_pos, DataToTransfer); + DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); sg_buffer_pos += DataToTransfer; } @@ -863,11 +883,21 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { uint32_t Address = DataPointer; - DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, SCSIDevices[BuslogicRequests->TargetID].InitLength); + if (DataLength > 0) + { + if (DataLength > SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength) + { + DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength); + } + else + { + DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer, DataLength); + } + } } } - SCSIDevices[BuslogicRequests->TargetID].InitLength = 0; + SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength = 0; } uint8_t BuslogicRead(uint16_t Port, void *p) @@ -916,15 +946,20 @@ uint8_t BuslogicRead(uint16_t Port, void *p) return Temp; } -int buslogic_scsi_drive_is_cdrom(uint8_t id) +int buslogic_scsi_drive_is_cdrom(uint8_t id, uint8_t lun) { - if (scsi_cdrom_drives[id] >= CDROM_NUM) + if (lun > 7) + { + return 0; + } + + if (scsi_cdrom_drives[id][lun] >= CDROM_NUM) { return 0; } else { - if (cdrom_drives[scsi_cdrom_drives[id]].enabled && cdrom_drives[scsi_cdrom_drives[id]].bus_type && (cdrom_drives[scsi_cdrom_drives[id]].bus_mode & 2)) + if (cdrom_drives[scsi_cdrom_drives[id][lun]].enabled && cdrom_drives[scsi_cdrom_drives[id][lun]].bus_type && (cdrom_drives[scsi_cdrom_drives[id][lun]].bus_mode & 2)) { return 1; } @@ -939,6 +974,10 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) { int i = 0; + uint8_t j = 0; + + uint8_t max_id = scsi_model ? 16 : 8; + Buslogic_t *Buslogic = (Buslogic_t *)p; BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; BuslogicLog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); @@ -964,9 +1003,9 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) { for (i = 0; i < CDROM_NUM; i++) { - if (buslogic_scsi_drive_is_cdrom(cdrom_drives[i].scsi_device_id)) + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun)) { - SCSICallback[cdrom_drives[i].scsi_device_id] = 1; + SCSICallback[cdrom_drives[i].scsi_device_id][cdrom_drives[i].scsi_device_lun] = 1; } } break; @@ -1105,13 +1144,16 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x0A: - for (i = 0; i < 8; i++) + for (i = 0; i < max_id; i++) { - if (buslogic_scsi_drive_is_cdrom(i)) - Buslogic->DataBuf[i] = 1; - - Buslogic->DataBuf[7] = 0; - Buslogic->DataReplyLeft = 8; + for (j = 0; j < 8; j++) + { + if (buslogic_scsi_drive_is_cdrom(i, j)) + Buslogic->DataBuf[i] = 1; + + Buslogic->DataBuf[7] = 0; + Buslogic->DataReplyLeft = 8; + } } break; @@ -1147,14 +1189,16 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) } break; - case 0x23: - for (i = 0; i < 8; i++) + for (i = 0; i < max_id; i++) { - if (buslogic_scsi_drive_is_cdrom(i)) - Buslogic->DataBuf[i] = 1; + for (i = 0; j < 8; j++) + { + if (buslogic_scsi_drive_is_cdrom(i, j)) + Buslogic->DataBuf[i] = 1; - Buslogic->DataReplyLeft = 8; + Buslogic->DataReplyLeft = 8; + } } break; @@ -1200,13 +1244,15 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x24: { - uint8_t i; uint16_t TargetsPresentMask = 0; - for (i=0;iDataBuf[0] = TargetsPresentMask&0x0F; Buslogic->DataBuf[1] = TargetsPresentMask>>8; @@ -1414,6 +1460,7 @@ static void BuslogicSenseBufferAllocate(BuslogicRequests_t *BuslogicRequests) static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Copy) { uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength); + uint8_t cdrom_id = scsi_cdrom_drives[BuslogicRequests->TargetID][BuslogicRequests->LUN]; if (SenseLength && Copy) { @@ -1434,8 +1481,7 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co BuslogicLog("Request Sense address: %02X\n", SenseBufferAddress); - // DMAPageWrite(SenseBufferAddress, BuslogicRequests->RequestSenseBuffer, SenseLength); - DMAPageWrite(SenseBufferAddress, cdrom[BuslogicRequests->TargetID].sense, SenseLength); + DMAPageWrite(SenseBufferAddress, cdrom[cdrom_id].sense, SenseLength); } //Free the sense buffer when needed. free(BuslogicRequests->RequestSenseBuffer); @@ -1451,6 +1497,8 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, uint32_t temp = 0; + uint8_t temp_cdb[12]; + //Fetch data from the Command Control Block. DMAPageRead(CCBPointer, &BuslogicRequests->CmdBlock, sizeof(CCB32)); @@ -1463,9 +1511,9 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, BuslogicLog("Scanning SCSI Target ID %i\n", Id); //Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon. - if (buslogic_scsi_drive_is_cdrom(Id) && Lun == 0) + if (buslogic_scsi_drive_is_cdrom(Id, Lun)) { - cdrom_id = scsi_cdrom_drives[Id]; + cdrom_id = scsi_cdrom_drives[Id][Lun]; BuslogicLog("SCSI Target ID %i detected and working\n", Id); @@ -1483,6 +1531,22 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, BuslogicLog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]); for (i = 1; i < BuslogicRequests->CmdBlock.common.CdbLength; i++) BuslogicLog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]); + + memset(temp_cdb, 0, cdrom[cdrom_id].cdb_len); + if (BuslogicRequests->CmdBlock.common.CdbLength <= cdrom[cdrom_id].cdb_len) + { + memcpy(temp_cdb, BuslogicRequests->CmdBlock.common.Cdb, BuslogicRequests->CmdBlock.common.CdbLength); + } + else + { + memcpy(temp_cdb, BuslogicRequests->CmdBlock.common.Cdb, cdrom[cdrom_id].cdb_len); + } + + if (BuslogicRequests->CmdBlock.common.CdbLength != 12) + { + cdrom[cdrom_id].request_length = temp_cdb[1]; /* Since that field in the cdrom struct is never used when the bus type is SCSI, let's use it for this scope. */ + temp_cdb[1] &= 0x1f; /* Make sure the LUN field of the temporary CDB is always 0, otherwise Daemon Tools drives will misehave when a command is passed through to them. */ + } BuslogicLog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte); BuslogicLog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength); @@ -1495,11 +1559,11 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, { if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND)) { - if (!cdrom_pre_execution_check(cdrom_id, BuslogicRequests->CmdBlock.common.Cdb)) + if (!cdrom_pre_execution_check(cdrom_id, temp_cdb)) { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[Id]=50*SCSI_TIME; - SCSIDevices[BuslogicRequests->TargetID].InitLength = 0; + SCSICallback[Id][Lun]=50*SCSI_TIME; + SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength = 0; if (BuslogicRequests->RequestSenseBuffer) BuslogicSenseBufferFree(BuslogicRequests, 1); BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); @@ -1508,28 +1572,13 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, } } - //First, get the data buffer otherwise putting it after the - //exec function results into not getting read/write commands right and - //failing to detect the device. - - /* Note by Tohka: After looking at the code, both functions do a copy of one part of the buffer to another, - with no purpose, whatsoever, and then end up with SCSIDevices.pos being equal to the InitLength. - SCSIReadData does not use pos at all, and the write code does, but in a useless way, therefore that - variable is going away. - All I am going to do at this point is zero the buffer. - Also, instead of directly calling SCSIReadData from here, this will be modified to call the CD-ROM - callback for the correct CD-ROM drive, and make that call SCSIReadData. - Since the new code will have the target ID and LUN inside the cdrom struct, as well as a copy of the Cdb - and the InitLength (in cdrom[id].request_length), it can be called from there and do everything needed. */ - - memset(SCSIDevices[Id].CmdBuffer, 0, 390144); + memset(SCSIDevices[Id][Lun].CmdBuffer, 0, 390144); //Finally, execute the SCSI command immediately and get the transfer length. SCSIPhase = SCSI_PHASE_COMMAND; - cdrom_command(cdrom_id, BuslogicRequests->CmdBlock.common.Cdb); - // SCSIDevices[Id].InitLength = cdrom[cdrom_id].0; - // SCSIGetLength(Id, &SCSIDevices[Id].InitLength); + SCSIDevices[Id][Lun].InitLength = 0; + cdrom_command(cdrom_id, temp_cdb); SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); if (SCSIStatus == SCSI_STATUS_OK) { @@ -1553,9 +1602,12 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, /* Error (Check Condition) - call the phase callback to complete the command. */ cdrom_phase_callback(cdrom_id); } - SCSICallback[Id] = cdrom[cdrom_id].callback; + SCSICallback[Id][Lun] = cdrom[cdrom_id].callback; - BuslogicDataBufferFree(BuslogicRequests); + if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (SCSIDevices[Id][Lun].InitLength != 0)) + { + BuslogicDataBufferFree(BuslogicRequests); + } if (BuslogicRequests->RequestSenseBuffer) BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK)); @@ -1563,7 +1615,7 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, else { BuslogicLog("Mailbox32->u.out.ActionCode = %02X\n", Mailbox32->u.out.ActionCode); - SCSICallback[Id] = 50 * SCSI_TIME; + SCSICallback[Id][Lun] = 50 * SCSI_TIME; } BuslogicLog("Request complete\n"); @@ -1571,7 +1623,7 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { temp = BuslogicGetDataLength(BuslogicRequests); - temp -= SCSIDevices[Id].InitLength; + temp -= SCSIDevices[Id][Lun].InitLength; if (BuslogicRequests->Is24bit) { @@ -1686,11 +1738,11 @@ static void BuslogicStartMailbox(Buslogic_t *Buslogic) } } -void BuslogicCommandCallback(int Id, void *p) +void BuslogicCommandCallback(int id, int lun, void *p) { Buslogic_t *Buslogic = (Buslogic_t *)p; - SCSICallback[Id] = 0; + SCSICallback[id][lun] = 0; if (Buslogic->MailboxCount) { BuslogicStartMailbox(Buslogic); @@ -1699,22 +1751,22 @@ void BuslogicCommandCallback(int Id, void *p) void BuslogicCommandCallback0(void *p) { - BuslogicCommandCallback(cdrom_drives[0].scsi_device_id, p); + BuslogicCommandCallback(cdrom_drives[0].scsi_device_id, cdrom_drives[0].scsi_device_lun, p); } void BuslogicCommandCallback1(void *p) { - BuslogicCommandCallback(cdrom_drives[1].scsi_device_id, p); + BuslogicCommandCallback(cdrom_drives[1].scsi_device_id, cdrom_drives[1].scsi_device_lun, p); } void BuslogicCommandCallback2(void *p) { - BuslogicCommandCallback(cdrom_drives[2].scsi_device_id, p); + BuslogicCommandCallback(cdrom_drives[2].scsi_device_id, cdrom_drives[2].scsi_device_lun, p); } void BuslogicCommandCallback3(void *p) { - BuslogicCommandCallback(cdrom_drives[3].scsi_device_id, p); + BuslogicCommandCallback(cdrom_drives[3].scsi_device_id, cdrom_drives[3].scsi_device_lun, p); } void *BuslogicInit() @@ -1730,25 +1782,25 @@ void *BuslogicInit() BuslogicLog("Building CD-ROM map...\n"); build_scsi_cdrom_map(); - if (buslogic_scsi_drive_is_cdrom(cdrom_drives[0].scsi_device_id)) + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[0].scsi_device_id, cdrom_drives[0].scsi_device_lun)) { - SCSIDevices[cdrom_drives[0].scsi_device_id].LunType == SCSI_CDROM; - timer_add(BuslogicCommandCallback0, &SCSICallback[cdrom_drives[0].scsi_device_id], &SCSICallback[cdrom_drives[0].scsi_device_id], Buslogic); + SCSIDevices[cdrom_drives[0].scsi_device_id][cdrom_drives[0].scsi_device_lun].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback0, &SCSICallback[cdrom_drives[0].scsi_device_id][cdrom_drives[0].scsi_device_lun], &SCSICallback[cdrom_drives[0].scsi_device_id][cdrom_drives[0].scsi_device_lun], Buslogic); } - if (buslogic_scsi_drive_is_cdrom(cdrom_drives[1].scsi_device_id)) + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[1].scsi_device_id, cdrom_drives[1].scsi_device_lun)) { - SCSIDevices[cdrom_drives[1].scsi_device_id].LunType == SCSI_CDROM; - timer_add(BuslogicCommandCallback1, &SCSICallback[cdrom_drives[1].scsi_device_id], &SCSICallback[cdrom_drives[1].scsi_device_id], Buslogic); + SCSIDevices[cdrom_drives[1].scsi_device_id][cdrom_drives[1].scsi_device_lun].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback1, &SCSICallback[cdrom_drives[1].scsi_device_id][cdrom_drives[1].scsi_device_lun], &SCSICallback[cdrom_drives[1].scsi_device_id][cdrom_drives[1].scsi_device_lun], Buslogic); } - if (buslogic_scsi_drive_is_cdrom(cdrom_drives[2].scsi_device_id)) + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[2].scsi_device_id, cdrom_drives[2].scsi_device_lun)) { - SCSIDevices[cdrom_drives[2].scsi_device_id].LunType == SCSI_CDROM; - timer_add(BuslogicCommandCallback2, &SCSICallback[cdrom_drives[2].scsi_device_id], &SCSICallback[cdrom_drives[2].scsi_device_id], Buslogic); + SCSIDevices[cdrom_drives[2].scsi_device_id][cdrom_drives[2].scsi_device_lun].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback2, &SCSICallback[cdrom_drives[2].scsi_device_id][cdrom_drives[2].scsi_device_lun], &SCSICallback[cdrom_drives[2].scsi_device_id][cdrom_drives[2].scsi_device_lun], Buslogic); } - if (buslogic_scsi_drive_is_cdrom(cdrom_drives[3].scsi_device_id)) + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[3].scsi_device_id, cdrom_drives[3].scsi_device_lun)) { - SCSIDevices[cdrom_drives[3].scsi_device_id].LunType == SCSI_CDROM; - timer_add(BuslogicCommandCallback3, &SCSICallback[cdrom_drives[3].scsi_device_id], &SCSICallback[cdrom_drives[3].scsi_device_id], Buslogic); + SCSIDevices[cdrom_drives[3].scsi_device_id][cdrom_drives[3].scsi_device_lun].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback3, &SCSICallback[cdrom_drives[3].scsi_device_id][cdrom_drives[3].scsi_device_lun], &SCSICallback[cdrom_drives[3].scsi_device_id][cdrom_drives[3].scsi_device_lun], Buslogic); } BuslogicLog("Buslogic on port 0x%04X\n", scsi_base); diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 3f87f4798..7fc61eeb3 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -37,7 +37,7 @@ enum CD_PAUSED }; -int cdrom_ioctl_do_log = 1; +int cdrom_ioctl_do_log = 0; void cdrom_ioctl_log(const char *format, ...) { @@ -517,34 +517,23 @@ struct sptd_with_sense UCHAR data[65536]; } sptd; -static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, int no_length_check) +static int ioctl_get_block_length(uint8_t id, const UCHAR *cdb, int number_of_blocks, int no_length_check) { - HANDLE fh; - DWORD ioctl_bytes; - DWORD out_size; - int ioctl_rv = 0; int sector_type = 0; int temp_len = 0; - SCSISense.SenseKey = 0; - SCSISense.Asc = 0; - SCSISense.Ascq = 0; + if (no_length_check) + { + return 8192; + } - *len = 0; - memset(&sptd, 0, sizeof(sptd)); - sptd.s.Length = sizeof(SCSI_PASS_THROUGH); - sptd.s.CdbLength = 12; - sptd.s.DataIn = SCSI_IOCTL_DATA_IN; - sptd.s.TimeOutValue = 80 * 60; - goto bypass_check; - if (no_length_check) goto bypass_check; switch (cdb[0]) { case 0x08: case 0x28: case 0xa8: /* READ (6), READ (10), READ (12) */ - sptd.s.DataTransferLength = 2048 * cdrom[id].requested_blocks; + return 2048 * number_of_blocks; break; case 0xb9: sector_type = (cdb[1] >> 2) & 7; @@ -554,7 +543,7 @@ static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, if (sector_type == 0) { cdrom_illegal_mode(id); - return 1; + return -1; } } goto common_handler; @@ -567,7 +556,7 @@ static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, if (sector_type == 0) { cdrom_illegal_mode(id); - return 1; + return -1; } } common_handler: @@ -595,16 +584,38 @@ common_handler: if (temp_len <= 0) { cdrom_illegal_mode(id); - return 1; + return -1; } - sptd.s.DataTransferLength = temp_len * cdrom[id].requested_blocks; + return temp_len * cdrom[id].requested_blocks; break; default: -bypass_check: /* Other commands */ - sptd.s.DataTransferLength = 65536; + return 8192; break; } + +} + +static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, int no_length_check) +{ + HANDLE fh; + DWORD ioctl_bytes; + DWORD out_size; + int ioctl_rv = 0; + int sector_type = 0; + int temp_len = 0; + + SCSISense.SenseKey = 0; + SCSISense.Asc = 0; + SCSISense.Ascq = 0; + + *len = 0; + memset(&sptd, 0, sizeof(sptd)); + sptd.s.Length = sizeof(SCSI_PASS_THROUGH); + sptd.s.CdbLength = 12; + sptd.s.DataIn = SCSI_IOCTL_DATA_IN; + sptd.s.TimeOutValue = 80 * 60; + sptd.s.DataTransferLength = ioctl_get_block_length(id, cdb, cdrom_ioctl[id].actual_requested_blocks, no_length_check); sptd.s.SenseInfoOffset = (uintptr_t)&sptd.sense - (uintptr_t)&sptd; sptd.s.SenseInfoLength = 32; sptd.s.DataBufferOffset = (uintptr_t)&sptd.data - (uintptr_t)&sptd; @@ -755,6 +766,19 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t const UCHAR cdb[12]; int ret; + + int block_length = 0; + + int temp_block_length = 0; + int temp_pos = 0; + + int blocks_at_once = 0; + int buffer_pos = 0; + + int temp_requested_blocks = 0; + int transferred_blocks = 0; + + int temp_len = 0; if (cdb[0] == 0x43) { @@ -765,9 +789,57 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t ioctl_open(id, 0); memcpy(cdb, in_cdb, 12); - ret = SCSICommand(id, cdb, buf, len, 0); - memcpy(b, buf, *len); + temp_block_length = ioctl_get_block_length(id, cdb, cdrom[id].requested_blocks, 0); + if (temp_block_length != -1) + { + if (temp_block_length > 65534) + { + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is bigger than 65534, splitting the transfer...\n", id, temp_block_length); + block_length = temp_block_length / cdrom[id].requested_blocks; + blocks_at_once = 32768 / block_length; + + buffer_pos = 0; + temp_pos = cdrom[id].sector_pos; + temp_requested_blocks = cdrom[id].requested_blocks; + transferred_blocks = 0; + temp_len = 0; + +split_block_read_iterate: + if (temp_requested_blocks < blocks_at_once) + { + cdrom_ioctl[id].actual_requested_blocks = temp_requested_blocks; + } + else + { + cdrom_ioctl[id].actual_requested_blocks = blocks_at_once; + } + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Transferring %i blocks...\n", id, cdrom_ioctl[id].actual_requested_blocks); + cdrom_update_cdb(cdb, temp_pos, cdrom_ioctl[id].actual_requested_blocks); + ret = SCSICommand(id, cdb, buf + buffer_pos, &temp_len, 0); + *len += temp_len; + transferred_blocks += cdrom_ioctl[id].actual_requested_blocks; + if (ret && (transferred_blocks >= cdrom[id].requested_blocks)) + { + temp_pos += cdrom_ioctl[id].actual_requested_blocks; + buffer_pos += (cdrom_ioctl[id].actual_requested_blocks * block_length); + goto split_block_read_iterate; + } + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Split transfer done\n", id); + } + else + { + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is smaller than 65534, transferring all at once...\n", id, temp_block_length); + cdrom_ioctl[id].actual_requested_blocks = cdrom[id].requested_blocks; + ret = SCSICommand(id, cdb, buf, len, 0); + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Single transfer done\n", id); + } + memcpy(b, buf, *len); + } + else + { + cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is -1, this indicates an illegal mode\n", id, temp_block_length); + } cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); diff --git a/src/cdrom.c b/src/cdrom.c index 3e9e30d22..0aad0daf8 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -33,7 +33,22 @@ cdrom_t cdrom[CDROM_NUM]; cdrom_drive_t cdrom_drives[CDROM_NUM]; uint8_t atapi_cdrom_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -uint8_t scsi_cdrom_drives[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +uint8_t scsi_cdrom_drives[16][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } }; static struct __attribute__((__packed__)) { @@ -240,13 +255,13 @@ void build_atapi_cdrom_map() } } -int find_cdrom_for_scsi_id(uint8_t scsi_id) +int find_cdrom_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t i = 0; for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drives[i].bus_type && (cdrom_drives[i].scsi_device_id == scsi_id)) + if (cdrom_drives[i].bus_type && (cdrom_drives[i].scsi_device_id == scsi_id) && (cdrom_drives[i].scsi_device_lun == scsi_lun)) { return i; } @@ -257,15 +272,22 @@ int find_cdrom_for_scsi_id(uint8_t scsi_id) void build_scsi_cdrom_map() { uint8_t i = 0; - - memset(scsi_cdrom_drives, 0xff, 16); + uint8_t j = 0; for (i = 0; i < 16; i++) { - scsi_cdrom_drives[i] = find_cdrom_for_scsi_id(i); - if (scsi_cdrom_drives[i] != 0xff) + memset(scsi_cdrom_drives[i], 0xff, 8); + } + + for (i = 0; i < 16; i++) + { + for (j = 0; j < 8; j++) { - cdrom_init(scsi_cdrom_drives[i], 12, 1); + scsi_cdrom_drives[i][j] = find_cdrom_for_scsi_id(i, j); + if (scsi_cdrom_drives[i][j] != 0xff) + { + cdrom_init(scsi_cdrom_drives[i][j], 12, 1); + } } } } @@ -849,6 +871,10 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al } if (cdrom_request_length_is_zero(id) || (len == 0) || (cdrom_current_mode(id) == 0)) { + if (cdrom_drives[id].bus_type) + { + SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = 0; + } cdrom_command_complete(id); } else @@ -857,7 +883,7 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al { if (cdrom_drives[id].bus_type) { - SCSIDevices[cdrom_drives[id].scsi_device_id].InitLength = alloc_len; + SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len; } if (direction == 0) { @@ -928,6 +954,15 @@ static void cdrom_not_ready(uint8_t id) cdrom_cmd_error(id); } +/* This is 05/00/00, based on what a Daemon Tools drive returns for such a case. */ +static void cdrom_illegal_lun(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = 0; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + static void cdrom_illegal_opcode(uint8_t id) { cdrom_sense_key = SENSE_ILLEGAL_REQUEST; @@ -1007,7 +1042,7 @@ static int cdrom_pass_through(uint8_t id, int *len) if ((cdrom_sense_key != 0) || (cdrom_asc != 0) || (cdrom_ascq != 0)) { /* Command failed with sense, error with that sense. */ - cdrom_log("CD-ROM %i: Command failed with sense, error with that sense.\n", id); + cdrom_log("CD-ROM %i: Command failed with sense, error with that sense (%02X/%02X/%02X).\n", id, cdrom_sense_key, cdrom_asc, cdrom_ascq); cdrom_cmd_error(id); return 0; } @@ -1020,58 +1055,58 @@ static int cdrom_pass_through(uint8_t id, int *len) } } -int cdrom_update_cdb(uint8_t id) +int cdrom_update_cdb(uint8_t *cdb, int lba_pos, int number_of_blocks) { int temp = 0; - switch(cdrom[id].current_cdb[0]) + switch(cdb[0]) { case GPCMD_READ_6: - cdrom[id].current_cdb[1] = (cdrom[id].sector_pos >> 16) & 0xff; - cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 8) & 0xff; - cdrom[id].current_cdb[3] = cdrom[id].sector_pos & 0xff; + cdb[1] = (lba_pos >> 16) & 0xff; + cdb[2] = (lba_pos >> 8) & 0xff; + cdb[3] = lba_pos & 0xff; break; case GPCMD_READ_10: - cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 24) & 0xff; - cdrom[id].current_cdb[3] = (cdrom[id].sector_pos >> 16) & 0xff; - cdrom[id].current_cdb[4] = (cdrom[id].sector_pos >> 8) & 0xff; - cdrom[id].current_cdb[5] = cdrom[id].sector_pos & 0xff; - cdrom[id].current_cdb[7] = (cdrom[id].requested_blocks >> 8) & 0xff; - cdrom[id].current_cdb[8] = cdrom[id].requested_blocks & 0xff; + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; break; case GPCMD_READ_12: - cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 24) & 0xff; - cdrom[id].current_cdb[3] = (cdrom[id].sector_pos >> 16) & 0xff; - cdrom[id].current_cdb[4] = (cdrom[id].sector_pos >> 8) & 0xff; - cdrom[id].current_cdb[5] = cdrom[id].sector_pos & 0xff; - cdrom[id].current_cdb[6] = (cdrom[id].requested_blocks >> 24) & 0xff; - cdrom[id].current_cdb[7] = (cdrom[id].requested_blocks >> 16) & 0xff; - cdrom[id].current_cdb[8] = (cdrom[id].requested_blocks >> 8) & 0xff; - cdrom[id].current_cdb[9] = cdrom[id].requested_blocks & 0xff; + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 24) & 0xff; + cdb[7] = (number_of_blocks >> 16) & 0xff; + cdb[8] = (number_of_blocks >> 8) & 0xff; + cdb[9] = number_of_blocks & 0xff; break; case GPCMD_READ_CD_MSF: - temp = cdrom_lba_to_msf_accurate(cdrom[id].sector_pos); - cdrom[id].current_cdb[3] = (temp >> 16) & 0xff; - cdrom[id].current_cdb[4] = (temp >> 8) & 0xff; - cdrom[id].current_cdb[5] = temp & 0xff; + temp = cdrom_lba_to_msf_accurate(lba_pos); + cdb[3] = (temp >> 16) & 0xff; + cdb[4] = (temp >> 8) & 0xff; + cdb[5] = temp & 0xff; - temp = cdrom_lba_to_msf_accurate(cdrom[id].sector_pos + cdrom[id].requested_blocks - 1); - cdrom[id].current_cdb[6] = (temp >> 16) & 0xff; - cdrom[id].current_cdb[7] = (temp >> 8) & 0xff; - cdrom[id].current_cdb[8] = temp & 0xff; + temp = cdrom_lba_to_msf_accurate(lba_pos + number_of_blocks - 1); + cdb[6] = (temp >> 16) & 0xff; + cdb[7] = (temp >> 8) & 0xff; + cdb[8] = temp & 0xff; break; case GPCMD_READ_CD: - cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 24) & 0xff; - cdrom[id].current_cdb[3] = (cdrom[id].sector_pos >> 16) & 0xff; - cdrom[id].current_cdb[4] = (cdrom[id].sector_pos >> 8) & 0xff; - cdrom[id].current_cdb[5] = cdrom[id].sector_pos & 0xff; - cdrom[id].current_cdb[6] = (cdrom[id].requested_blocks >> 16) & 0xff; - cdrom[id].current_cdb[7] = (cdrom[id].requested_blocks >> 8) & 0xff; - cdrom[id].current_cdb[8] = cdrom[id].requested_blocks & 0xff; + cdb[2] = (lba_pos >> 24) & 0xff; + cdb[3] = (lba_pos >> 16) & 0xff; + cdb[4] = (lba_pos >> 8) & 0xff; + cdb[5] = lba_pos & 0xff; + cdb[6] = (number_of_blocks >> 16) & 0xff; + cdb[7] = (number_of_blocks >> 8) & 0xff; + cdb[8] = number_of_blocks & 0xff; break; } } @@ -1177,7 +1212,7 @@ int cdrom_read_blocks(uint8_t id, int *len, int first_batch) cdrom_log("Reading %i blocks starting from %i...\n", cdrom[id].requested_blocks, cdrom[id].sector_pos); - cdrom_update_cdb(id); + cdrom_update_cdb(cdrom[id].current_cdb, cdrom[id].sector_pos, cdrom[id].requested_blocks); ret = cdrom_read_data(id, msf, type, flags, len); @@ -1385,9 +1420,19 @@ int cdrom_pre_execution_check(uint8_t id, uint8_t *cdb) { int ready = 0; + if (cdrom_drives[id].bus_type) + { + if (((cdrom[id].request_length >> 5) & 7) != cdrom_drives[id].scsi_device_lun) + { + cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", id, ((cdrom[id].request_length >> 5) & 7)); + cdrom_illegal_lun(id); + return 0; + } + } + if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) { - cdrom_log("CD-ROM %i: Attempting to unknown command %02X over %s\n", id, cdb[0], cdrom_drives[id].bus_type ? "SCSI" : "ATAPI"); + cdrom_log("CD-ROM %i: Attempting to execute unknown command %02X over %s\n", id, cdb[0], cdrom_drives[id].bus_type ? "SCSI" : "ATAPI"); cdrom_illegal_opcode(id); return 0; } @@ -2630,11 +2675,11 @@ int cdrom_read_from_ide_dma(uint8_t channel) } } -int cdrom_read_from_scsi_dma(uint8_t scsi_id) +int cdrom_read_from_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t *cdbufferb; - uint8_t id = scsi_cdrom_drives[scsi_id]; + uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; cdbufferb = (uint8_t *) cdrom[id].buffer; @@ -2643,8 +2688,8 @@ int cdrom_read_from_scsi_dma(uint8_t scsi_id) return 0; } - cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id].InitLength); - memcpy(cdbufferb, SCSIDevices[scsi_id].CmdBuffer, SCSIDevices[scsi_id].InitLength); + cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id][scsi_lun].InitLength); + memcpy(cdbufferb, SCSIDevices[scsi_id][scsi_lun].CmdBuffer, SCSIDevices[scsi_id][scsi_lun].InitLength); return 1; } @@ -2657,7 +2702,7 @@ int cdrom_read_from_dma(uint8_t id) if (cdrom_drives[id].bus_type) { - ret = cdrom_read_from_scsi_dma(cdrom_drives[id].scsi_device_id); + ret = cdrom_read_from_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); } else { @@ -2713,11 +2758,11 @@ int cdrom_write_to_ide_dma(uint8_t channel) } } -int cdrom_write_to_scsi_dma(uint8_t scsi_id) +int cdrom_write_to_scsi_dma(uint8_t scsi_id, uint8_t scsi_lun) { uint8_t *cdbufferb; - uint8_t id = scsi_cdrom_drives[scsi_id]; + uint8_t id = scsi_cdrom_drives[scsi_id][scsi_lun]; if (id > CDROM_NUM) { @@ -2726,10 +2771,10 @@ int cdrom_write_to_scsi_dma(uint8_t scsi_id) cdbufferb = (uint8_t *) cdrom[id].buffer; - cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id].InitLength); - memcpy(SCSIDevices[scsi_id].CmdBuffer, cdbufferb, SCSIDevices[scsi_id].InitLength); + cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id][scsi_lun].InitLength); + memcpy(SCSIDevices[scsi_id][scsi_lun].CmdBuffer, cdbufferb, SCSIDevices[scsi_id][scsi_lun].InitLength); cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); - cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id].CmdBuffer[0], SCSIDevices[scsi_id].CmdBuffer[1], SCSIDevices[scsi_id].CmdBuffer[2], SCSIDevices[scsi_id].CmdBuffer[3], SCSIDevices[scsi_id].CmdBuffer[4], SCSIDevices[scsi_id].CmdBuffer[5], SCSIDevices[scsi_id].CmdBuffer[6], SCSIDevices[scsi_id].CmdBuffer[7]); + cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id][scsi_lun].CmdBuffer[0], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[1], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[2], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[3], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[4], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[5], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[6], SCSIDevices[scsi_id][scsi_lun].CmdBuffer[7]); return 1; } @@ -2739,7 +2784,7 @@ int cdrom_write_to_dma(uint8_t id) if (cdrom_drives[id].bus_type) { - ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id); + ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id, cdrom_drives[id].scsi_device_lun); } else { @@ -2810,14 +2855,15 @@ int cdrom_phase_callback(uint8_t id) } /* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -uint8_t cdrom_read(uint8_t channel) +uint32_t cdrom_read(uint8_t channel, int length) { uint8_t *cdbufferb; + uint16_t *cdbufferw; + uint32_t *cdbufferl; uint8_t id = atapi_cdrom_drives[channel]; - // uint16_t temp = 0; - uint8_t temp = 0; + uint32_t temp = 0; int ret = 0; if (id > CDROM_NUM) @@ -2826,15 +2872,33 @@ uint8_t cdrom_read(uint8_t channel) } cdbufferb = (uint8_t *) cdrom[id].buffer; + cdbufferw = cdrom[id].buffer; + cdbufferl = (uint32_t *) cdrom[id].buffer; - temp = cdbufferb[cdrom[id].pos]; - - cdrom[id].pos++; - cdrom[id].request_pos++; + switch(length) + { + case 1: + temp = cdbufferb[cdrom[id].pos]; + cdrom[id].pos++; + cdrom[id].request_pos++; + break; + case 2: + temp = cdbufferw[cdrom[id].pos >> 1]; + cdrom[id].pos += 2; + cdrom[id].request_pos += 2; + break; + case 4: + temp = cdbufferl[cdrom[id].pos >> 2]; + cdrom[id].pos += 4; + cdrom[id].request_pos += 4; + break; + default: + return 0; + } if (cdrom[id].packet_status == CDROM_PHASE_DATA_IN) { - cdrom[id].total_read++; + cdrom[id].total_read += length; ret = cdrom_block_check(id); /* If the block check has returned 0, this means all the requested blocks have been read, therefore the command has finished. */ if (ret) @@ -2866,9 +2930,12 @@ uint8_t cdrom_read(uint8_t channel) } /* Reimplement as 8-bit due to reimplementation of IDE data read and write. */ -void cdrom_write(uint8_t channel, uint8_t val) +void cdrom_write(uint8_t channel, uint32_t val, int length) { + uint8_t i = 0; uint8_t *cdbufferb; + uint16_t *cdbufferw; + uint32_t *cdbufferl; uint8_t id = atapi_cdrom_drives[channel]; @@ -2880,14 +2947,34 @@ void cdrom_write(uint8_t channel, uint8_t val) } cdbufferb = (uint8_t *) cdrom[id].buffer; + cdbufferw = cdrom[id].buffer; + cdbufferl = (uint32_t *) cdrom[id].buffer; - cdbufferb[cdrom[id].pos] = val; - cdrom[id].pos++; + switch(length) + { + case 1: + cdbufferb[cdrom[id].pos] = val & 0xff; + cdrom[id].pos++; + break; + case 2: + cdbufferw[cdrom[id].pos >> 1] = val & 0xff; + cdrom[id].pos += 2; + break; + case 4: + cdbufferl[cdrom[id].pos >> 2] = val; + cdrom[id].pos += 4; + break; + default: + return; + } if (cdrom[id].packet_status == CDROM_PHASE_DATA_OUT) { - ret = cdrom_mode_select_write(id, val); - cdrom_mode_select_return(id, ret); + for (i = 0; i < length; i++) + { + ret = cdrom_mode_select_write(id, val); + cdrom_mode_select_return(id, ret); + } return; } else if (cdrom[id].packet_status == CDROM_PHASE_IDLE) diff --git a/src/cdrom.h b/src/cdrom.h index 032e2978d..759c5e134 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -94,7 +94,7 @@ typedef struct __attribute__((__packed__)) int prev_status; int unit_attention; - uint8_t sense[18]; + uint8_t sense[256]; int request_pos; @@ -135,6 +135,7 @@ typedef struct __attribute__((__packed__)) uint8_t ide_channel; uint8_t scsi_device_id; + uint8_t scsi_device_lun; uint8_t sound_on; } cdrom_drive_t; @@ -143,7 +144,7 @@ extern cdrom_drive_t cdrom_drives[CDROM_NUM]; extern uint8_t atapi_cdrom_drives[8]; -extern uint8_t scsi_cdrom_drives[16]; +extern uint8_t scsi_cdrom_drives[16][8]; extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); @@ -175,6 +176,7 @@ typedef struct uint32_t cd_end; int16_t cd_buffer[BUF_SIZE]; int cd_buflen; + int actual_requested_blocks; } cdrom_ioctl_t; void ioctl_close(uint8_t id); @@ -189,8 +191,8 @@ int cdrom_CDROM_PHASE_to_scsi(uint8_t id); int cdrom_atapi_phase_to_scsi(uint8_t id); void cdrom_command(uint8_t id, uint8_t *cdb); int cdrom_phase_callback(uint8_t id); -uint8_t cdrom_read(uint8_t channel); -void cdrom_write(uint8_t channel, uint8_t val); +uint32_t cdrom_read(uint8_t channel, int length); +void cdrom_write(uint8_t channel, uint32_t val, int length); int cdrom_lba_to_msf_accurate(int lba); void cdrom_reset(uint8_t id); void cdrom_set_signature(int id); diff --git a/src/ide.c b/src/ide.c index c0d98f3a6..5c4063f01 100644 --- a/src/ide.c +++ b/src/ide.c @@ -344,6 +344,7 @@ static void ide_identify(IDE *ide) h = hdc[cur_ide[ide->board]].hpc; /* Heads */ s = hdc[cur_ide[ide->board]].spt; /* Sectors */ + ide->buffer[0] = 0x40; /* Fixed disk */ ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */ ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */ ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */ @@ -372,6 +373,7 @@ static void ide_identify(IDE *ide) ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; ide->buffer[60] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[61] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) >> 16; + ide->buffer[80] = 0x1e; /*ATA-1 to ATA-4 supported*/ // ide->buffer[63] = 7; /*Multiword DMA*/ if (ide->board < 2) { @@ -380,8 +382,8 @@ static void ide_identify(IDE *ide) ide->buffer[63] = ide->dma_identify_data[1]; ide->buffer[65] = 150; ide->buffer[66] = 150; - ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/ - ide->buffer[88] = ide->dma_identify_data[2]; + // ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/ + // ide->buffer[88] = ide->dma_identify_data[2]; } } @@ -405,6 +407,7 @@ static void ide_atapi_identify(IDE *ide) ide->buffer[51] = 2 << 8; /*PIO timing mode*/ ide->buffer[73] = 6; ide->buffer[73] = 9; + ide->buffer[80] = 0x10; /*ATA/ATAPI-4 supported*/ if ((ide->board < 2) && (cdrom_drives[cdrom_id].bus_mode & 2)) { @@ -751,12 +754,14 @@ void resetide(void) int idetimes = 0; -void ide_write_data(int ide_board, uint8_t val) +void ide_write_data(int ide_board, uint32_t val, int length) { int ret = 0; IDE *ide = &ide_drives[cur_ide[ide_board]]; uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint16_t *idebufferw = ide->buffer; + uint32_t *idebufferl = (uint32_t *) ide->buffer; #if 0 if (ide_drive_is_cdrom(ide)) @@ -768,12 +773,14 @@ void ide_write_data(int ide_board, uint8_t val) // ide_log("Write IDEw %04X\n",val); if (ide->command == WIN_PACKETCMD) { + ide->pos = 0; + if (!ide_drive_is_cdrom(ide)) { return; } - cdrom_write(cur_ide[ide_board], val); + cdrom_write(cur_ide[ide_board], val, length); if (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback) { @@ -783,8 +790,23 @@ void ide_write_data(int ide_board, uint8_t val) } else { - idebufferb[ide->pos] = val; - ide->pos++; + switch(length) + { + case 1: + idebufferb[ide->pos] = val & 0xff; + ide->pos++; + break; + case 2: + idebufferw[ide->pos >> 1] = val & 0xffff; + ide->pos += 2; + break; + case 4: + idebufferl[ide->pos >> 2] = val; + ide->pos += 4; + break; + default: + return; + } if (ide->pos>=512) { @@ -807,15 +829,13 @@ void ide_write_data(int ide_board, uint8_t val) void writeidew(int ide_board, uint16_t val) { // ide_log("WriteIDEw %04X\n", val); - ide_write_data(ide_board, val); - ide_write_data(ide_board, val >> 8); + ide_write_data(ide_board, val, 2); } void writeidel(int ide_board, uint32_t val) { // ide_log("WriteIDEl %08X\n", val); - writeidew(ide_board, val); - writeidew(ide_board, val >> 16); + ide_write_data(ide_board, val, 4); } void writeide(int ide_board, uint16_t addr, uint8_t val) @@ -832,7 +852,8 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) switch (addr) { case 0x1F0: /* Data */ - ide_write_data(ide_board, val); + // writeidew(ide_board, val | (val << 8)); + writeidew(ide_board, val | (val << 8)); return; /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ @@ -1292,21 +1313,24 @@ ide_bad_command: // fatal("Bad IDE write %04X %02X\n", addr, val); } -uint8_t ide_read_data(int ide_board) +uint32_t ide_read_data(int ide_board, int length) { IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint8_t temp; + uint32_t temp; uint8_t *idebufferb = (uint8_t *) ide->buffer; + uint16_t *idebufferw = ide->buffer; + uint32_t *idebufferl = (uint32_t *) ide->buffer; if (ide->command == WIN_PACKETCMD) { + ide->pos = 0; if (!ide_drive_is_cdrom(ide)) { ide_log("Drive not CD-ROM (position: %i)\n", ide->pos); return 0; } - temp = cdrom_read(cur_ide[ide_board]); + temp = cdrom_read(cur_ide[ide_board], length); if (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback) { idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback; @@ -1314,8 +1338,23 @@ uint8_t ide_read_data(int ide_board) } else { - temp = idebufferb[ide->pos]; - ide->pos++; + switch (length) + { + case 1: + temp = idebufferb[ide->pos]; + ide->pos++; + break; + case 2: + temp = idebufferw[ide->pos >> 1]; + ide->pos += 2; + break; + case 4: + temp = idebufferb[ide->pos >> 2]; + ide->pos += 4; + break; + default: + return 0; + } } if (ide->pos>=512 && ide->command != WIN_PACKETCMD) { @@ -1367,7 +1406,10 @@ uint8_t readide(int ide_board, uint16_t addr) switch (addr) { case 0x1F0: /* Data */ - return ide_read_data(ide_board); + // temp = ide_read_data(ide_board, 1); + tempw = readidew(ide_board); + // pclog("Read IDEW %04X\n", tempw); + temp = tempw & 0xff; break; /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), @@ -1517,20 +1559,17 @@ int all_blocks_total = 0; uint16_t readidew(int ide_board) { - uint16_t temp = 0; - uint16_t temp2 = 0; - temp = ide_read_data(ide_board); - temp2 = ide_read_data(ide_board); - temp2 <<= 8; - return (temp | temp2); + uint16_t temp; + temp = ide_read_data(ide_board, 2); + return temp; } uint32_t readidel(int ide_board) { uint16_t temp; // ide_log("Read IDEl %i\n", ide_board); - temp = readidew(ide_board); - return temp | (readidew(ide_board) << 16); + temp = ide_read_data(ide_board, 4); + return temp; } int times30=0; diff --git a/src/mem.c b/src/mem.c index 7d5e965ed..e79b54d6c 100644 --- a/src/mem.c +++ b/src/mem.c @@ -975,7 +975,7 @@ int mmu_page_fault_check(uint32_t addr, int rw, uint32_t flags, int pde, int is_ if (!(flags & 1)) { - pclog("Trying to read or write a page that is not present!\n"); + // pclog("Trying to read or write a page that is not present!\n"); is_page_fault = 1; } @@ -983,12 +983,12 @@ int mmu_page_fault_check(uint32_t addr, int rw, uint32_t flags, int pde, int is_ { if (!(flags & 4) && mem_cpl3_check()) { - pclog("Trying to read a system page from user mode!\n"); + // pclog("Trying to read a system page from user mode!\n"); is_page_fault = 1; } if (rw && !(flags & 2) && (mem_cpl3_check() || (cr0 & WP_FLAG))) { - pclog("Trying to write a read-only-for-user page from user mode!\n"); + // pclog("Trying to write a read-only-for-user page from user mode!\n"); is_page_fault = 1; } } diff --git a/src/pc.c b/src/pc.c index 13408d206..764af631c 100644 --- a/src/pc.c +++ b/src/pc.c @@ -275,7 +275,7 @@ void initpc(int argc, char *argv[]) { if (cdrom_drives[i].bus_type) { - SCSIReset(cdrom_drives[i].scsi_device_id); + SCSIReset(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun); } if (cdrom_drives[i].host_drive == 0) @@ -453,7 +453,7 @@ void resetpchard() { if (cdrom_drives[i].bus_type) { - SCSIReset(cdrom_drives[i].scsi_device_id); + SCSIReset(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun); } } @@ -736,6 +736,7 @@ void loadconfig(char *fn) cdrom_drives[0].bus_type = config_get_int(NULL, "cdrom_1_bus_type", 0); cdrom_drives[0].ide_channel = config_get_int(NULL, "cdrom_1_ide_channel", 2); cdrom_drives[0].scsi_device_id = config_get_int(NULL, "cdrom_1_scsi_device_id", 2); + cdrom_drives[0].scsi_device_lun = config_get_int(NULL, "cdrom_1_scsi_device_lun", 0); p = (char *)config_get_string(NULL, "cdrom_1_iso_path", ""); if (p) strcpy(cdrom_iso[0].iso_path, p); @@ -748,6 +749,7 @@ void loadconfig(char *fn) cdrom_drives[1].bus_type = config_get_int(NULL, "cdrom_2_bus_type", 0); cdrom_drives[1].ide_channel = config_get_int(NULL, "cdrom_2_ide_channel", 3); cdrom_drives[1].scsi_device_id = config_get_int(NULL, "cdrom_2_scsi_device_id", 3); + cdrom_drives[1].scsi_device_lun = config_get_int(NULL, "cdrom_2_scsi_device_lun", 0); p = (char *)config_get_string(NULL, "cdrom_2_iso_path", ""); if (p) strcpy(cdrom_iso[1].iso_path, p); @@ -760,6 +762,7 @@ void loadconfig(char *fn) cdrom_drives[2].bus_type = config_get_int(NULL, "cdrom_3_bus_type", 0); cdrom_drives[2].ide_channel = config_get_int(NULL, "cdrom_3_ide_channel", 4); cdrom_drives[2].scsi_device_id = config_get_int(NULL, "cdrom_3_scsi_device_id", 4); + cdrom_drives[2].scsi_device_lun = config_get_int(NULL, "cdrom_3_scsi_device_lun", 0); p = (char *)config_get_string(NULL, "cdrom_3_iso_path", ""); if (p) strcpy(cdrom_iso[2].iso_path, p); @@ -772,6 +775,7 @@ void loadconfig(char *fn) cdrom_drives[3].bus_type = config_get_int(NULL, "cdrom_4_bus_type", 0); cdrom_drives[3].ide_channel = config_get_int(NULL, "cdrom_4_ide_channel", 5); cdrom_drives[3].scsi_device_id = config_get_int(NULL, "cdrom_4_scsi_device_id", 5); + cdrom_drives[3].scsi_device_lun = config_get_int(NULL, "cdrom_4_scsi_device_lun", 0); p = (char *)config_get_string(NULL, "cdrom_4_iso_path", ""); if (p) strcpy(cdrom_iso[3].iso_path, p); @@ -951,6 +955,7 @@ void saveconfig() config_set_int(NULL, "cdrom_1_bus_type", cdrom_drives[0].bus_type); config_set_int(NULL, "cdrom_1_ide_channel", cdrom_drives[0].ide_channel); config_set_int(NULL, "cdrom_1_scsi_device_id", cdrom_drives[0].scsi_device_id); + config_set_int(NULL, "cdrom_1_scsi_device_lun", cdrom_drives[0].scsi_device_lun); config_set_string(NULL, "cdrom_1_iso_path", cdrom_iso[0].iso_path); @@ -959,7 +964,8 @@ void saveconfig() config_set_int(NULL, "cdrom_2_sound_on", cdrom_drives[1].sound_on); config_set_int(NULL, "cdrom_2_bus_type", cdrom_drives[1].bus_type); config_set_int(NULL, "cdrom_2_ide_channel", cdrom_drives[1].ide_channel); - config_set_int(NULL, "cdrom_2_scsi_device_id", cdrom_drives[1].scsi_device_id); + config_set_int(NULL, "cdrom_2_scsi_device_id", cdrom_drives[1].scsi_device_id); + config_set_int(NULL, "cdrom_2_scsi_device_lun", cdrom_drives[1].scsi_device_lun); config_set_string(NULL, "cdrom_2_iso_path", cdrom_iso[1].iso_path); @@ -968,7 +974,8 @@ void saveconfig() config_set_int(NULL, "cdrom_3_sound_on", cdrom_drives[2].sound_on); config_set_int(NULL, "cdrom_3_bus_type", cdrom_drives[2].bus_type); config_set_int(NULL, "cdrom_3_ide_channel", cdrom_drives[2].ide_channel); - config_set_int(NULL, "cdrom_3_scsi_device_id", cdrom_drives[2].scsi_device_id); + config_set_int(NULL, "cdrom_3_scsi_device_id", cdrom_drives[2].scsi_device_id); + config_set_int(NULL, "cdrom_3_scsi_device_lun", cdrom_drives[2].scsi_device_lun); config_set_string(NULL, "cdrom_3_iso_path", cdrom_iso[2].iso_path); @@ -977,7 +984,8 @@ void saveconfig() config_set_int(NULL, "cdrom_4_sound_on", cdrom_drives[3].sound_on); config_set_int(NULL, "cdrom_4_bus_type", cdrom_drives[3].bus_type); config_set_int(NULL, "cdrom_4_ide_channel", cdrom_drives[3].ide_channel); - config_set_int(NULL, "cdrom_4_scsi_device_id", cdrom_drives[3].scsi_device_id); + config_set_int(NULL, "cdrom_4_scsi_device_id", cdrom_drives[3].scsi_device_id); + config_set_int(NULL, "cdrom_4_scsi_device_lun", cdrom_drives[3].scsi_device_lun); config_set_string(NULL, "cdrom_4_iso_path", cdrom_iso[3].iso_path); diff --git a/src/pc.rc b/src/pc.rc index c90783586..10067fd2d 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -56,6 +56,7 @@ BEGIN MENUITEM "&I:",IDM_CDROM_1_I MENUITEM "&J:",IDM_CDROM_1_J END + MENUITEM SEPARATOR POPUP "S&CSI ID..." BEGIN MENUITEM "&0",IDM_CDROM_1_0 @@ -74,6 +75,17 @@ BEGIN MENUITEM "14",IDM_CDROM_1_14 MENUITEM "15",IDM_CDROM_1_15 END + POPUP "SCSI &LUN..." + BEGIN + MENUITEM "&0",IDM_CDROM_1_LUN_0 + MENUITEM "&1",IDM_CDROM_1_LUN_1 + MENUITEM "&2",IDM_CDROM_1_LUN_2 + MENUITEM "&3",IDM_CDROM_1_LUN_3 + MENUITEM "&4",IDM_CDROM_1_LUN_4 + MENUITEM "&5",IDM_CDROM_1_LUN_5 + MENUITEM "&6",IDM_CDROM_1_LUN_6 + MENUITEM "&7",IDM_CDROM_1_LUN_7 + END MENUITEM SEPARATOR MENUITEM "&ISO...",IDM_CDROM_1_ISO END @@ -98,6 +110,7 @@ BEGIN MENUITEM "&I:",IDM_CDROM_2_I MENUITEM "&J:",IDM_CDROM_2_J END + MENUITEM SEPARATOR POPUP "S&CSI ID..." BEGIN MENUITEM "&0",IDM_CDROM_2_0 @@ -116,6 +129,17 @@ BEGIN MENUITEM "14",IDM_CDROM_2_14 MENUITEM "15",IDM_CDROM_2_15 END + POPUP "SCSI &LUN..." + BEGIN + MENUITEM "&0",IDM_CDROM_2_LUN_0 + MENUITEM "&1",IDM_CDROM_2_LUN_1 + MENUITEM "&2",IDM_CDROM_2_LUN_2 + MENUITEM "&3",IDM_CDROM_2_LUN_3 + MENUITEM "&4",IDM_CDROM_2_LUN_4 + MENUITEM "&5",IDM_CDROM_2_LUN_5 + MENUITEM "&6",IDM_CDROM_2_LUN_6 + MENUITEM "&7",IDM_CDROM_2_LUN_7 + END MENUITEM SEPARATOR MENUITEM "&ISO...",IDM_CDROM_2_ISO END @@ -140,6 +164,7 @@ BEGIN MENUITEM "&I:",IDM_CDROM_3_I MENUITEM "&J:",IDM_CDROM_3_J END + MENUITEM SEPARATOR POPUP "S&CSI ID..." BEGIN MENUITEM "&0",IDM_CDROM_3_0 @@ -158,6 +183,17 @@ BEGIN MENUITEM "14",IDM_CDROM_3_14 MENUITEM "15",IDM_CDROM_3_15 END + POPUP "SCSI &LUN..." + BEGIN + MENUITEM "&0",IDM_CDROM_3_LUN_0 + MENUITEM "&1",IDM_CDROM_3_LUN_1 + MENUITEM "&2",IDM_CDROM_3_LUN_2 + MENUITEM "&3",IDM_CDROM_3_LUN_3 + MENUITEM "&4",IDM_CDROM_3_LUN_4 + MENUITEM "&5",IDM_CDROM_3_LUN_5 + MENUITEM "&6",IDM_CDROM_3_LUN_6 + MENUITEM "&7",IDM_CDROM_3_LUN_7 + END MENUITEM SEPARATOR MENUITEM "&ISO...",IDM_CDROM_3_ISO END @@ -181,6 +217,7 @@ BEGIN MENUITEM "&I:",IDM_CDROM_4_I MENUITEM "&J:",IDM_CDROM_4_J END + MENUITEM SEPARATOR POPUP "S&CSI ID..." BEGIN MENUITEM "&0",IDM_CDROM_4_0 @@ -199,6 +236,17 @@ BEGIN MENUITEM "14",IDM_CDROM_4_14 MENUITEM "15",IDM_CDROM_4_15 END + POPUP "SCSI &LUN..." + BEGIN + MENUITEM "&0",IDM_CDROM_4_LUN_0 + MENUITEM "&1",IDM_CDROM_4_LUN_1 + MENUITEM "&2",IDM_CDROM_4_LUN_2 + MENUITEM "&3",IDM_CDROM_4_LUN_3 + MENUITEM "&4",IDM_CDROM_4_LUN_4 + MENUITEM "&5",IDM_CDROM_4_LUN_5 + MENUITEM "&6",IDM_CDROM_4_LUN_6 + MENUITEM "&7",IDM_CDROM_4_LUN_7 + END MENUITEM SEPARATOR MENUITEM "&ISO...",IDM_CDROM_4_ISO END diff --git a/src/resources.h b/src/resources.h index 0c70ea07b..406bfba81 100644 --- a/src/resources.h +++ b/src/resources.h @@ -65,6 +65,14 @@ #define IDM_CDROM_1_13 40713 #define IDM_CDROM_1_14 40714 #define IDM_CDROM_1_15 40715 +#define IDM_CDROM_1_LUN_0 40800 +#define IDM_CDROM_1_LUN_1 40801 +#define IDM_CDROM_1_LUN_2 40802 +#define IDM_CDROM_1_LUN_3 40803 +#define IDM_CDROM_1_LUN_4 40804 +#define IDM_CDROM_1_LUN_5 40805 +#define IDM_CDROM_1_LUN_6 40806 +#define IDM_CDROM_1_LUN_7 40807 #define IDM_CDROM_2_ISO 41100 #define IDM_CDROM_2_RELOAD 41101 #define IDM_CDROM_2_EMPTY 41200 @@ -95,6 +103,14 @@ #define IDM_CDROM_2_13 41713 #define IDM_CDROM_2_14 41714 #define IDM_CDROM_2_15 41715 +#define IDM_CDROM_2_LUN_0 41800 +#define IDM_CDROM_2_LUN_1 41801 +#define IDM_CDROM_2_LUN_2 41802 +#define IDM_CDROM_2_LUN_3 41803 +#define IDM_CDROM_2_LUN_4 41804 +#define IDM_CDROM_2_LUN_5 41805 +#define IDM_CDROM_2_LUN_6 41806 +#define IDM_CDROM_2_LUN_7 41807 #define IDM_CDROM_3_ISO 42100 #define IDM_CDROM_3_RELOAD 42101 #define IDM_CDROM_3_EMPTY 42200 @@ -125,6 +141,14 @@ #define IDM_CDROM_3_13 42713 #define IDM_CDROM_3_14 42714 #define IDM_CDROM_3_15 42715 +#define IDM_CDROM_3_LUN_0 42800 +#define IDM_CDROM_3_LUN_1 42801 +#define IDM_CDROM_3_LUN_2 42802 +#define IDM_CDROM_3_LUN_3 42803 +#define IDM_CDROM_3_LUN_4 42804 +#define IDM_CDROM_3_LUN_5 42805 +#define IDM_CDROM_3_LUN_6 42806 +#define IDM_CDROM_3_LUN_7 42807 #define IDM_CDROM_4_ISO 43100 #define IDM_CDROM_4_RELOAD 43101 #define IDM_CDROM_4_EMPTY 43200 @@ -155,6 +179,14 @@ #define IDM_CDROM_4_13 43713 #define IDM_CDROM_4_14 43714 #define IDM_CDROM_4_15 43715 +#define IDM_CDROM_4_LUN_0 43800 +#define IDM_CDROM_4_LUN_1 43801 +#define IDM_CDROM_4_LUN_2 43802 +#define IDM_CDROM_4_LUN_3 43803 +#define IDM_CDROM_4_LUN_4 43804 +#define IDM_CDROM_4_LUN_5 43805 +#define IDM_CDROM_4_LUN_6 43806 +#define IDM_CDROM_4_LUN_7 43807 #define IDM_IDE_TER_ENABLED 44000 #define IDM_IDE_TER_IRQ9 44009 #define IDM_IDE_TER_IRQ10 44010 diff --git a/src/scsi.c b/src/scsi.c index 5f709815d..17f573b14 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -16,82 +16,38 @@ uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE; uint8_t SCSIStatus = SCSI_STATUS_OK; -int SCSICallback[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +int SCSICallback[16][8] = { { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } }; uint8_t scsi_cdrom_id = 3; /*common setting*/ -//Get the transfer length of the command -void SCSIGetLength(uint8_t id, int *datalen) -{ - *datalen = SCSIDevices[id].CmdBufferLength; -} - -#if 0 -//Execute SCSI command -void SCSIExecCommand(uint8_t id, uint8_t *buffer, uint8_t *cdb) -{ - SCSICDROM_Command(id, buffer, cdb); -} - -//Read pending data from the resulting SCSI command -void SCSIReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen) -{ - SCSICDROM_ReadData(id, cdb, data, datalen); -} - -///// -void SCSIDMAResetPosition(uint8_t Id) -{ - //Reset position in memory after reaching its limit - SCSIDevices[Id].pos = 0; -} - -//Read data from buffer with given position in buffer memory -void SCSIRead(uint8_t Id, uint8_t *dstbuf, uint8_t *srcbuf, uint32_t len_size) -{ - if (!len_size) //If there's no data, don't try to do anything. - return; - - int c; - - for (c = 0; c <= len_size; c++) //Count as many bytes as the length of the buffer is requested - { - memcpy(dstbuf, srcbuf + SCSIDevices[Id].pos, len_size); - SCSIDevices[Id].pos = c; - - //pclog("SCSI Read: position at %i\n", SCSIDevices[Id].pos); - } -} - -//Write data to buffer with given position in buffer memory -void SCSIWrite(uint8_t Id, uint8_t *srcbuf, uint8_t *dstbuf, uint32_t len_size) -{ - int c; - - for (c = 0; c <= len_size; c++) //Count as many bytes as the length of the buffer is requested - { - memcpy(srcbuf + SCSIDevices[Id].pos, dstbuf, len_size); - SCSIDevices[Id].pos = c; - - //pclog("SCSI Write: position at %i\n", SCSIDevices[Id].pos); - } -} -///// -#endif - //Initialization function for the SCSI layer -void SCSIReset(uint8_t Id) +void SCSIReset(uint8_t id, uint8_t lun) { - uint8_t cdrom_id = scsi_cdrom_drives[Id]; + uint8_t cdrom_id = scsi_cdrom_drives[id][lun]; - if (buslogic_scsi_drive_is_cdrom(Id)) + if (buslogic_scsi_drive_is_cdrom(id, lun)) { - SCSICallback[cdrom_id]=0; + SCSICallback[id][lun] = 0; cdrom_reset(cdrom_id); - SCSIDevices[Id].LunType = SCSI_CDROM; + SCSIDevices[id][lun].LunType = SCSI_CDROM; } else { - SCSIDevices[Id].LunType = SCSI_NONE; + SCSIDevices[id][lun].LunType = SCSI_NONE; } } diff --git a/src/scsi.h b/src/scsi.h index e59d5b60a..125131732 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -188,7 +188,7 @@ int MediaPresent; extern uint8_t SCSIStatus; extern uint8_t SCSIPhase; -extern int SCSICallback[16]; +extern int SCSICallback[16][8]; extern uint8_t scsi_cdrom_id; struct @@ -221,14 +221,13 @@ extern int prev_status; struct { - uint32_t pos; uint8_t CmdBuffer[390144]; uint32_t CmdBufferLength; int LunType; uint32_t InitLength; -} SCSIDevices[16]; +} SCSIDevices[16][8]; -extern void SCSIReset(uint8_t Id); +extern void SCSIReset(uint8_t id, uint8_t lun); uint32_t SCSICDROMModeSense(uint8_t *buf, uint32_t pos, uint8_t type); uint8_t SCSICDROMSetProfile(uint8_t *buf, uint8_t *index, uint16_t profile); diff --git a/src/vid_s3.c b/src/vid_s3.c index caaf63cb8..896447174 100644 --- a/src/vid_s3.c +++ b/src/vid_s3.c @@ -2314,7 +2314,7 @@ void *s3_bahamas64_init() { s3_t *s3 = s3_init("roms/bahamas64.BIN", S3_VISION864); - s3->id = 0xc1; /*Vision864P*/ + s3->id = 0xc0; /*Vision864P*/ s3->id_ext = s3->id_ext_pci = 0xc1; s3->packed_mmio = 0; @@ -2393,7 +2393,7 @@ void *s3_phoenix_vision864_init() { s3_t *s3 = s3_init("roms/86c864p.bin", S3_VISION864); - s3->id = 0xc1; /*Vision864P*/ + s3->id = 0xc0; /*Vision864P*/ s3->id_ext = s3->id_ext_pci = 0xc1; s3->packed_mmio = 0; @@ -2413,7 +2413,7 @@ void *s3_diamond_stealth64_init() s3_t *s3 = s3_init("roms/STEALT64.BIN", S3_VISION864); svga_t *svga = &s3->svga; - s3->id = 0xc1; /*Vision864P*/ + s3->id = 0xc0; /*Vision864P*/ s3->id_ext = s3->id_ext_pci = 0xc1; s3->packed_mmio = 0; @@ -2432,7 +2432,7 @@ void *s3_miro_vision964_init() { s3_t *s3 = s3_init("roms/mirocrystal.VBI", S3_VISION964); - s3->id = 0xd1; /*Vision964P*/ + s3->id = 0xd0; /*Vision964P*/ s3->id_ext = s3->id_ext_pci = 0xd1; s3->packed_mmio = 1; diff --git a/src/win.c b/src/win.c index 0d0ac7b5a..d9c98fe24 100644 --- a/src/win.c +++ b/src/win.c @@ -526,6 +526,7 @@ int valid_irqs[6] = { 9, 10, 11, 12, 14, 15 }; int valid_dma_channels[3] = { 5, 6, 7 }; int valid_ide_channels[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; int valid_scsi_ids[15] = { 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15 }; +int valid_scsi_luns[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; int find_in_array(int *array, int val, int len, int menu_base) { @@ -663,18 +664,25 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (!find_in_array(valid_ide_channels, cdrom_drives[e].ide_channel, 8, IDM_CDROM_1_C + (e * 1000))) { - fatal("Tertiary IDE controller: Invalid IRQ\n"); + fatal("CD-ROM %i: Invalid IDE channel\n", e); } CheckMenuItem(menu, IDM_CDROM_1_C + (e * 1000) + cdrom_drives[e].ide_channel, MF_CHECKED); if (!find_in_array(valid_scsi_ids, cdrom_drives[e].scsi_device_id, 15, IDM_CDROM_1_0 + (e * 1000))) { - fatal("Tertiary IDE controller: Invalid IRQ\n"); + fatal("CD-ROM %i: Invalid SCSI ID\n", e); } CheckMenuItem(menu, IDM_CDROM_1_0 + (e * 1000) + cdrom_drives[e].scsi_device_id, MF_CHECKED); + if (!find_in_array(valid_scsi_luns, cdrom_drives[e].scsi_device_lun, 8, IDM_CDROM_1_LUN_0 + (e * 1000))) + { + fatal("CD-ROM %i: Invalid SCSI LUN\n", e); + } + + CheckMenuItem(menu, IDM_CDROM_1_LUN_0 + (e * 1000) + cdrom_drives[e].scsi_device_lun, MF_CHECKED); + if (cdrom_drives[e].host_drive == 200) { CheckMenuItem(menu, IDM_CDROM_1_ISO + (e * 1000), MF_CHECKED); @@ -1685,6 +1693,26 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM pause = 0; break; + case IDM_CDROM_1_LUN_0 ... IDM_CDROM_1_LUN_7: + case IDM_CDROM_2_LUN_0 ... IDM_CDROM_2_LUN_7: + case IDM_CDROM_3_LUN_0 ... IDM_CDROM_3_LUN_7: + case IDM_CDROM_4_LUN_0 ... IDM_CDROM_4_LUN_7: + menu_sub_param = LOWORD(wParam) % 100; + cdrom_id = convert_cdrom_id(LOWORD(wParam) - menu_sub_param - IDM_CDROM_1_LUN_0); + if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) + { + break; + } + pause = 1; + Sleep(100); + CheckMenuItem(hmenu, IDM_CDROM_1_LUN_0 + (cdrom_id * 1000) + cdrom_drives[cdrom_id].scsi_device_lun, MF_UNCHECKED); + cdrom_drives[cdrom_id].scsi_device_lun = menu_sub_param; + CheckMenuItem(hmenu, IDM_CDROM_1_LUN_0 + (cdrom_id * 1000) + cdrom_drives[cdrom_id].scsi_device_lun, MF_CHECKED); + saveconfig(); + resetpchard(); + pause = 0; + break; + case IDM_IDE_TER_ENABLED: if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) {