From abbd603d9a1663d30b3343dd65e96de64265d1b8 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Tue, 3 Jan 2017 19:07:18 +0100 Subject: [PATCH] Buslogic specific features and commands marked as invalid when the Adaptec 154x scsi controller is selected. Some SCSI layer bugfixes. --- src/buslogic.c | 341 +++++++++++++++++++++++++------------------ src/scsi.c | 22 +-- src/scsi.h | 7 +- src/scsi_cdrom.c | 372 ++++++++++++++++++++++++----------------------- 4 files changed, 397 insertions(+), 345 deletions(-) diff --git a/src/buslogic.c b/src/buslogic.c index 03dd1106d..c35702292 100644 --- a/src/buslogic.c +++ b/src/buslogic.c @@ -1,10 +1,7 @@ /* Copyright holders: SA1988 see COPYING for more details */ -/*Buslogic SCSI emulation (including Adaptec 154x ISA software backward compatibility)*/ - -//Note: for the Adaptec-enabled Windows NT betas, install from HDD at the moment due to a bug in the round robin outgoing -//mailboxes. +/*Buslogic SCSI emulation (including Adaptec 154x ISA software backward compatibility) and the Adaptec 154x itself*/ #include #include @@ -461,7 +458,7 @@ typedef union __attribute__((packed)) CCBU // Adapter limits // -#define MAX_SG_DESCRIPTORS 32 +#define MAX_SG_DESCRIPTORS (scsi_model ? 32 : 17) typedef struct __attribute__((packed)) SGE32 { @@ -679,28 +676,28 @@ static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries } } -void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdBlock, int Is24bit) +void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bit) { if (Is24bit) { - DataPointer = ADDR_TO_U32(CmdBlock->old.DataPointer); - DataLength = ADDR_TO_U32(CmdBlock->old.DataLength); + DataPointer = ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataPointer); + DataLength = ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength); } else { - DataPointer = CmdBlock->new.DataPointer; - DataLength = CmdBlock->new.DataLength; + DataPointer = BuslogicRequests->CmdBlock.new.DataPointer; + DataLength = BuslogicRequests->CmdBlock.new.DataLength; } - if (CmdBlock->common.Cdb[0] == GPCMD_TEST_UNIT_READY) + if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) DataLength = 0; BuslogicLog("Data Buffer write: length %d, pointer 0x%04X\n", DataLength, DataPointer); - if (DataLength && CmdBlock->common.ControlByte != 0x03) + if (DataLength && BuslogicRequests->CmdBlock.common.ControlByte != 0x03) { - if (CmdBlock->common.Opcode == SCATTER_GATHER_COMMAND || - CmdBlock->common.Opcode == SCATTER_GATHER_COMMAND_RES) + if (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || + BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { uint32_t ScatterGatherRead; uint32_t ScatterEntry; @@ -729,15 +726,17 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); } while (ScatterGatherLeft > 0); + BuslogicLog("Data to transfer (S/G) %d\n", DataToTransfer); + SCSIDevices[scsi_cdrom_id].InitLength = DataToTransfer; + SCSIDevices[scsi_cdrom_id].CmdBuffer[SCSIDevices[scsi_cdrom_id].pos++] = SCSIDevices[scsi_cdrom_id].InitLength; //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. - if (CmdBlock->common.ControlByte == CCB_DATA_XFER_OUT || CmdBlock->common.ControlByte == 0x00) + if (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT || BuslogicRequests->CmdBlock.common.ControlByte == 0x00) { ScatterGatherLeft = DataLength / (Is24bit ? sizeof(SGE) : sizeof(SGE32)); ScatterGatherAddrCurrent = DataPointer; - uint8_t *DataBuffer = (uint8_t *)SCSIDevices[scsi_cdrom_id].CmdBuffer; do { @@ -755,19 +754,19 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; - DMAPageRead(Address, DataBuffer, DataToTransfer); - DataBuffer += DataToTransfer; + DMAPageRead(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, DataToTransfer); } ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); } while (ScatterGatherLeft > 0); } } - else if (CmdBlock->common.Opcode == SCSI_INITIATOR_COMMAND || - CmdBlock->common.Opcode == SCSI_INITIATOR_COMMAND_RES) + else if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || + BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { uint32_t Address = DataPointer; SCSIDevices[scsi_cdrom_id].InitLength = DataLength; + SCSIDevices[scsi_cdrom_id].CmdBuffer[SCSIDevices[scsi_cdrom_id].pos++] = SCSIDevices[scsi_cdrom_id].InitLength; DMAPageRead(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, SCSIDevices[scsi_cdrom_id].InitLength); } @@ -795,7 +794,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) //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 read/write commands. if (DataLength > 0 && (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN || - BuslogicRequests->CmdBlock.common.ControlByte == 0x00)) + BuslogicRequests->CmdBlock.common.ControlByte == 0x00) && BuslogicRequests->CmdBlock.common.ControlByte != 0x03) { if (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) @@ -805,7 +804,6 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; uint32_t ScatterGatherLeft = DataLength / (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t ScatterGatherAddrCurrent = DataPointer; - uint8_t *DataBuffer = (uint8_t *)SCSIDevices[scsi_cdrom_id].CmdBuffer; do { @@ -824,8 +822,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; - DMAPageWrite(Address, DataBuffer, DataToTransfer); - DataBuffer += DataToTransfer; + DMAPageWrite(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, DataToTransfer); } ScatterGatherAddrCurrent += ScatterGatherRead * (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); @@ -839,20 +836,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) } } - if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES || - BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) - { - if (BuslogicRequests->Is24bit) - { - U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[scsi_cdrom_id].InitLength); - BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength)); - } - else - { - BuslogicRequests->CmdBlock.new.DataLength = SCSIDevices[scsi_cdrom_id].InitLength; - BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength); - } - } + SCSIDevices[scsi_cdrom_id].InitLength = 0; } uint8_t BuslogicRead(uint16_t Port, void *p) @@ -957,17 +941,16 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x21: case 0x24: case 0x25: + Buslogic->CmdParamLeft = 1; + break; + case 0x8B: case 0x8D: case 0x8F: case 0x96: - Buslogic->CmdParamLeft = 1; - break; + Buslogic->CmdParamLeft = scsi_model ? 1 : 0; + break; - - Buslogic->CmdParamLeft = 1; - break; - case 0x91: Buslogic->CmdParamLeft = 2; break; @@ -986,7 +969,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x81: - Buslogic->CmdParamLeft = sizeof(MailboxInitExtended_t); + Buslogic->CmdParamLeft = scsi_model ? sizeof(MailboxInitExtended_t) : 0; break; case 0x28: @@ -1092,12 +1075,16 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Reply->cMailbox = Buslogic->MailboxCount; U32_TO_ADDR(Reply->MailboxAddress, Buslogic->MailboxOutAddr); - Reply->uSignature = 'B'; - /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too - * friendly with Adaptec hardware and upsetting the HBA state. - */ - Reply->uCharacterD = 'D'; /* BusLogic model. */ - Reply->uHostBusType = 'A'; /* ISA bus. */ + if (scsi_model) + { + Reply->uSignature = 'B'; + /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too + * friendly with Adaptec hardware and upsetting the HBA state. + */ + Reply->uCharacterD = 'D'; /* BusLogic model. */ + Reply->uHostBusType = 'A'; /* ISA bus. */ + } + BuslogicLog("Return Setup Information: %d\n", Buslogic->CmdBuf[0]); } break; @@ -1179,72 +1166,120 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x81: { - Buslogic->Mbx24bit = 0; - - MailboxInitExtended_t *MailboxInit = (MailboxInitExtended_t *)Buslogic->CmdBuf; + if (scsi_model) + { + Buslogic->Mbx24bit = 0; + + MailboxInitExtended_t *MailboxInit = (MailboxInitExtended_t *)Buslogic->CmdBuf; - Buslogic->MailboxCount = MailboxInit->Count; - Buslogic->MailboxOutAddr = MailboxInit->Address; - Buslogic->MailboxInAddr = MailboxInit->Address + (Buslogic->MailboxCount * sizeof(Mailbox32_t)); - - BuslogicLog("Buslogic Extended Initialize Mailbox Command\n"); - BuslogicLog("Mailbox Out Address=0x%08X\n", Buslogic->MailboxOutAddr); - BuslogicLog("Mailbox In Address=0x%08X\n", Buslogic->MailboxInAddr); - BuslogicLog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, MailboxInit->Address); - - Buslogic->Status &= ~STAT_INIT; - Buslogic->DataReplyLeft = 0; + Buslogic->MailboxCount = MailboxInit->Count; + Buslogic->MailboxOutAddr = MailboxInit->Address; + Buslogic->MailboxInAddr = MailboxInit->Address + (Buslogic->MailboxCount * sizeof(Mailbox32_t)); + + BuslogicLog("Buslogic Extended Initialize Mailbox Command\n"); + BuslogicLog("Mailbox Out Address=0x%08X\n", Buslogic->MailboxOutAddr); + BuslogicLog("Mailbox In Address=0x%08X\n", Buslogic->MailboxInAddr); + BuslogicLog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, MailboxInit->Address); + + Buslogic->Status &= ~STAT_INIT; + Buslogic->DataReplyLeft = 0; + } + else + { + Buslogic->DataReplyLeft = 0; + Buslogic->Status |= STAT_INVCMD; + } } break; case 0x84: - Buslogic->DataBuf[0] = '7'; - Buslogic->DataReplyLeft = 1; + if (scsi_model) + { + Buslogic->DataBuf[0] = '7'; + Buslogic->DataReplyLeft = 1; + } + else + { + Buslogic->DataReplyLeft = 0; + Buslogic->Status |= STAT_INVCMD; + } break; case 0x85: - Buslogic->DataBuf[0] = 'B'; - Buslogic->DataReplyLeft = 1; + if (scsi_model) + { + Buslogic->DataBuf[0] = 'B'; + Buslogic->DataReplyLeft = 1; + } + else + { + Buslogic->DataReplyLeft = 0; + Buslogic->Status |= STAT_INVCMD; + } break; case 0x8B: { - int i; - - /* The reply length is set by the guest and is found in the first byte of the command buffer. */ - Buslogic->DataReplyLeft = Buslogic->CmdBuf[0]; - memset(Buslogic->DataBuf, 0, Buslogic->DataReplyLeft); - const char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ - int cCharsToTransfer = Buslogic->DataReplyLeft <= sizeof(aModelName) - ? Buslogic->DataReplyLeft - : sizeof(aModelName); + if (scsi_model) + { + int i; + + /* The reply length is set by the guest and is found in the first byte of the command buffer. */ + Buslogic->DataReplyLeft = Buslogic->CmdBuf[0]; + memset(Buslogic->DataBuf, 0, Buslogic->DataReplyLeft); + const char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ + int cCharsToTransfer = Buslogic->DataReplyLeft <= sizeof(aModelName) + ? Buslogic->DataReplyLeft + : sizeof(aModelName); - for (i = 0; i < cCharsToTransfer; i++) - Buslogic->DataBuf[i] = aModelName[i]; + for (i = 0; i < cCharsToTransfer; i++) + Buslogic->DataBuf[i] = aModelName[i]; + } + else + { + Buslogic->DataReplyLeft = 0; + Buslogic->Status |= STAT_INVCMD; + } } break; case 0x8D: { - Buslogic->DataReplyLeft = Buslogic->CmdBuf[0]; - ReplyInquireExtendedSetupInformation *Reply = (ReplyInquireExtendedSetupInformation *)Buslogic->DataBuf; + if (scsi_model) + { + Buslogic->DataReplyLeft = Buslogic->CmdBuf[0]; + ReplyInquireExtendedSetupInformation *Reply = (ReplyInquireExtendedSetupInformation *)Buslogic->DataBuf; - Reply->uBusType = 'A'; /* ISA style */ - Reply->u16ScatterGatherLimit = 8192; - Reply->cMailbox = Buslogic->MailboxCount; - Reply->uMailboxAddressBase = Buslogic->MailboxOutAddr; - memcpy(Reply->aFirmwareRevision, "07B", sizeof(Reply->aFirmwareRevision)); - BuslogicLog("Return Extended Setup Information: %d\n", Buslogic->CmdBuf[0]); + Reply->uBusType = 'A'; /* ISA style */ + Reply->u16ScatterGatherLimit = 8192; + Reply->cMailbox = Buslogic->MailboxCount; + Reply->uMailboxAddressBase = Buslogic->MailboxOutAddr; + memcpy(Reply->aFirmwareRevision, "07B", sizeof(Reply->aFirmwareRevision)); + BuslogicLog("Return Extended Setup Information: %d\n", Buslogic->CmdBuf[0]); + } + else + { + Buslogic->DataReplyLeft = 0; + Buslogic->Status |= STAT_INVCMD; + } } break; case 0x8F: - if (Buslogic->CmdBuf[0] == 0) - Buslogic->StrictRoundRobinMode = 0; - else if (Buslogic->CmdBuf[0] == 1) - Buslogic->StrictRoundRobinMode = 1; - - Buslogic->DataReplyLeft = 0; + if (scsi_model) + { + if (Buslogic->CmdBuf[0] == 0) + Buslogic->StrictRoundRobinMode = 0; + else if (Buslogic->CmdBuf[0] == 1) + Buslogic->StrictRoundRobinMode = 1; + + Buslogic->DataReplyLeft = 0; + } + else + { + Buslogic->DataReplyLeft = 0; + Buslogic->Status |= STAT_INVCMD; + } break; case 0x91: @@ -1258,12 +1293,15 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x96: - if (Buslogic->CmdBuf[0] == 0) - Buslogic->ExtendedLUNCCBFormat = 0; - else if (Buslogic->CmdBuf[0] == 1) - Buslogic->ExtendedLUNCCBFormat = 1; - - Buslogic->DataReplyLeft = 0; + if (scsi_model) + { + if (Buslogic->CmdBuf[0] == 0) + Buslogic->ExtendedLUNCCBFormat = 0; + else if (Buslogic->CmdBuf[0] == 1) + Buslogic->ExtendedLUNCCBFormat = 1; + + Buslogic->DataReplyLeft = 0; + } break; case 0x22: //undocumented @@ -1284,11 +1322,13 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 2: - Buslogic->Interrupt = Val; //For Buslogic + if (scsi_model) + Buslogic->Interrupt = Val; //For Buslogic break; case 3: - Buslogic->Geometry = Val; //For Buslogic + if (scsi_model) + Buslogic->Geometry = Val; //For Buslogic break; } } @@ -1345,14 +1385,13 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, Mailbox32_t *Mailbox32) { BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; - CCBU CmdBlock; uint8_t Id, Lun; //Fetch data from the Command Control Block. - DMAPageRead(CCBPointer, &CmdBlock, sizeof(CCB32)); + DMAPageRead(CCBPointer, &BuslogicRequests->CmdBlock, sizeof(CCB32)); - BuslogicRequests->TargetID = Buslogic->Mbx24bit ? CmdBlock.old.Id : CmdBlock.new.Id; - BuslogicRequests->LUN = Buslogic->Mbx24bit ? CmdBlock.old.Lun : CmdBlock.new.Lun; + BuslogicRequests->TargetID = Buslogic->Mbx24bit ? BuslogicRequests->CmdBlock.old.Id : BuslogicRequests->CmdBlock.new.Id; + BuslogicRequests->LUN = Buslogic->Mbx24bit ? BuslogicRequests->CmdBlock.old.Lun : BuslogicRequests->CmdBlock.new.Lun; Id = BuslogicRequests->TargetID; Lun = BuslogicRequests->LUN; @@ -1367,21 +1406,27 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, BuslogicRequests->CCBPointer = CCBPointer; BuslogicRequests->Is24bit = Buslogic->Mbx24bit; - memcpy(&BuslogicRequests->CmdBlock, &CmdBlock, sizeof(CmdBlock)); - if (Mailbox32->u.out.ActionCode == MBO_START) { BuslogicSenseBufferAllocate(BuslogicRequests); - BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit); + BuslogicDataBufferAllocate(BuslogicRequests, BuslogicRequests->Is24bit); - uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength); + uint32_t i; + + 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]); + + BuslogicLog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte); + BuslogicLog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength); + BuslogicLog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode); - if ((CmdBlock.common.ControlByte != 0x03) && (CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND)) + if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND)) { if (cdrom->medium_changed()) { - pclog("Media changed\n"); + BuslogicLog("Media changed\n"); SCSICDROM_Insert(); } @@ -1433,42 +1478,44 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, return; } } - - uint32_t i; - - 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]); - - BuslogicLog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte); - BuslogicLog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength); - BuslogicLog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode); //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. - if (CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) + if (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) { - SCSIRead(Id, SCSIDevices[Id].InitLength); + SCSIRead(Id, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); } - else if (CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) + else if (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) { - SCSIWrite(Id, SCSIDevices[Id].InitLength); - } + SCSIWrite(Id, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); + } //Finally, execute the SCSI command immediately and get the transfer length. SCSIPhase = SCSI_PHASE_COMMAND; - SCSIExecCommand(Id, BuslogicRequests->CmdBlock.common.Cdb, SenseLength); + SCSIExecCommand(Id, SCSIDevices[Id].CmdBuffer, BuslogicRequests->CmdBlock.common.Cdb); SCSIGetLength(Id, &SCSIDevices[Id].InitLength); - + if (SCSIPhase == SCSI_PHASE_DATAIN) { - SCSIReadData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength,SenseLength); + SCSIReadData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); + } + else if (SCSIPhase == SCSI_PHASE_DATAOUT) + { + if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_MODE_SELECT_6 || + BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_MODE_SELECT_10) + { + //Mode Sense/Select stuff + if ((SCSIDevices[Id].pos >= prefix_len+4) && (page_flags[page_current] & PAGE_CHANGEABLE)) + { + mode_pages_in[page_current][SCSIDevices[Id].pos - prefix_len - 4] = SCSIDevices[Id].CmdBuffer[SCSIDevices[Id].pos - 2]; + mode_pages_in[page_current][SCSIDevices[Id].pos - prefix_len - 3] = SCSIDevices[Id].CmdBuffer[SCSIDevices[Id].pos - 1]; + } + } } - BuslogicDataBufferFree(BuslogicRequests); if (BuslogicRequests->RequestSenseBuffer) @@ -1476,7 +1523,23 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, } BuslogicLog("Request complete\n"); - BuslogicLog("SCSI Status %002X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); + BuslogicLog("SCSI Status %02X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); + + + if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES || + BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) + { + if (BuslogicRequests->Is24bit) + { + U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[Id].InitLength); + BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength)); + } + else + { + BuslogicRequests->CmdBlock.new.DataLength = SCSIDevices[Id].InitLength; + BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength); + } + } if (SCSIStatus == SCSI_STATUS_OK) { @@ -1491,15 +1554,7 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, } else { - if (Mailbox32->u.out.ActionCode == MBO_START) - { - BuslogicDataBufferFree(BuslogicRequests); - - if (BuslogicRequests->RequestSenseBuffer) - BuslogicSenseBufferFree(BuslogicRequests, 1); - } - - BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); + BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); if (Mailbox32->u.out.ActionCode == MBO_START) BuslogicStartMailbox(Buslogic); @@ -1610,11 +1665,11 @@ void BuslogicClose(void *p) device_t BuslogicDevice = { - "Buslogic BT-542B", + "Adaptec/Buslogic", 0, BuslogicInit, BuslogicClose, - NULL,//BuslogicAvailable, + NULL, NULL, NULL, NULL diff --git a/src/scsi.c b/src/scsi.c index e98855066..539c50791 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -23,9 +23,9 @@ void SCSIGetLength(uint8_t id, int *datalen) } //Execute SCSI command -void SCSIExecCommand(uint8_t id, uint8_t *cdb, uint8_t sense) +void SCSIExecCommand(uint8_t id, uint8_t *buffer, uint8_t *cdb) { - SCSICDROM_Command(id, cdb, sense); + SCSICDROM_Command(id, buffer, cdb); } //Read pending data from the resulting SCSI command @@ -42,7 +42,7 @@ void SCSIDMAResetPosition(uint8_t Id) } //Read data from buffer with given position in buffer memory -void SCSIRead(uint8_t Id, uint32_t len_size) +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; @@ -51,7 +51,7 @@ void SCSIRead(uint8_t Id, uint32_t len_size) for (c = 0; c <= len_size; c++) //Count as many bytes as the length of the buffer is requested { - memcpy(SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].CmdBuffer + SCSIDevices[Id].pos, len_size); + memcpy(dstbuf, srcbuf + SCSIDevices[Id].pos, len_size); SCSIDevices[Id].pos = c; //pclog("SCSI Read: position at %i\n", SCSIDevices[Id].pos); @@ -59,24 +59,14 @@ void SCSIRead(uint8_t Id, uint32_t len_size) } //Write data to buffer with given position in buffer memory -void SCSIWrite(uint8_t Id, uint32_t len_size) +void SCSIWrite(uint8_t Id, uint8_t *srcbuf, uint8_t *dstbuf, 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(SCSIDevices[Id].CmdBuffer + SCSIDevices[Id].pos, SCSIDevices[Id].CmdBuffer, len_size); + memcpy(srcbuf + SCSIDevices[Id].pos, dstbuf, len_size); SCSIDevices[Id].pos = c; - - //Mode Sense/Select stuff - if ((SCSIDevices[Id].pos >= prefix_len+4) && (page_flags[page_current] & PAGE_CHANGEABLE)) - { - mode_pages_in[page_current][SCSIDevices[Id].pos - prefix_len - 4] = SCSIDevices[Id].CmdBuffer[SCSIDevices[Id].pos - 2]; - mode_pages_in[page_current][SCSIDevices[Id].pos - prefix_len - 3] = SCSIDevices[Id].CmdBuffer[SCSIDevices[Id].pos - 1]; - } //pclog("SCSI Write: position at %i\n", SCSIDevices[Id].pos); } diff --git a/src/scsi.h b/src/scsi.h index 2ca3ad795..44a3ddfd7 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -171,6 +171,8 @@ uint32_t DataPointer; int SectorLBA; int SectorLen; +int MediaPresent; + extern uint8_t SCSIStatus; extern uint8_t SCSIPhase; extern int SCSICallback[16]; @@ -178,6 +180,8 @@ extern uint8_t scsi_cdrom_id; struct { + uint8_t SenseBuffer[18]; + uint8_t SenseLength; uint8_t UnitAttention; uint8_t SenseKey; uint8_t Asc; @@ -245,9 +249,8 @@ extern int cdrom_sector_size, cdrom_sector_ismsf; struct { - int lba_pos, lba_len; uint32_t pos; - uint8_t CmdBuffer[262144]; + uint8_t CmdBuffer[512*512]; uint32_t CmdBufferLength; int LunType; uint32_t InitLength; diff --git a/src/scsi_cdrom.c b/src/scsi_cdrom.c index d08f440e0..a004bee43 100644 --- a/src/scsi_cdrom.c +++ b/src/scsi_cdrom.c @@ -642,8 +642,9 @@ int cdrom_read_data(uint8_t *buffer) void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA) { - if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA) + if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA || (SCSISense.SenseKey == SENSE_ILLEGAL_REQUEST && SCSISense.Asc == ASC_INV_FIELD_IN_CMD_PACKET)) { + pclog("Sense cleared\n"); ScsiPrev=Command; SCSISenseCodeOk(); } @@ -678,65 +679,7 @@ static int SCSICDROM_TOC(uint8_t id, uint8_t *cdb) return TocFormat; } -void SCSICDROMRequestSense(uint8_t id, uint8_t *cdb, uint8_t sense) -{ - /*Will return 18 bytes of 0*/ - memset(SCSIDevices[id].CmdBuffer,0,512); - - SCSIDevices[id].CmdBuffer[0]=0x80|0x70; - - if ((SCSISense.SenseKey > 0) || (cd_status < CD_STATUS_PLAYING)) - { - if (SenseCompleted) - { - SCSIDevices[id].CmdBuffer[2]=SENSE_ILLEGAL_REQUEST; - SCSIDevices[id].CmdBuffer[12]=ASC_AUDIO_PLAY_OPERATION; - SCSIDevices[id].CmdBuffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } - else - { - SCSIDevices[id].CmdBuffer[2]=SCSISense.SenseKey; - SCSIDevices[id].CmdBuffer[12]=SCSISense.Asc; - SCSIDevices[id].CmdBuffer[13]=SCSISense.Ascq; - } - } - else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED)) - { - SCSIDevices[id].CmdBuffer[2]=SENSE_ILLEGAL_REQUEST; - SCSIDevices[id].CmdBuffer[12]=ASC_AUDIO_PLAY_OPERATION; - SCSIDevices[id].CmdBuffer[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } - else - { - if (SCSISense.UnitAttention) - { - SCSIDevices[id].CmdBuffer[2]=SENSE_UNIT_ATTENTION; - SCSIDevices[id].CmdBuffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - SCSIDevices[id].CmdBuffer[13]=0; - } - } - - SCSIDevices[id].CmdBuffer[7]=10; - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = sense; - - SCSIDMAResetPosition(id); - - if (SCSIDevices[id].CmdBuffer[2] == SENSE_UNIT_ATTENTION) - { - /* If the last remaining sense is unit attention, clear - that condition. */ - SCSISense.UnitAttention = 0; - } - - /* Clear the sense stuff as per the spec. */ - SCSIClearSense(cdb[0], 0); -} - -void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) +void SCSICDROM_Command(uint8_t id, uint8_t *cmdbuffer, uint8_t *cdb) { int len; int pos=0; @@ -754,7 +697,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) int ret = 0; msf = cdb[1] & 2; - + prev_status = cd_status; cd_status = cdrom->status(); if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED))) @@ -764,7 +707,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) else { SenseCompleted = 0; - } + } switch (cdb[0]) { @@ -775,8 +718,63 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) break; case GPCMD_REQUEST_SENSE: - SCSICDROMRequestSense(id, cdb, sense); - break; + len = cdb[4]; + + /*Will return 18 bytes of 0*/ + memset(cmdbuffer,0,512); + + cmdbuffer[0]=0x80|0x70; + + if ((SCSISense.SenseKey > 0) || (cd_status < CD_STATUS_PLAYING)) + { + if (SenseCompleted) + { + cmdbuffer[2]=SENSE_ILLEGAL_REQUEST; + cmdbuffer[12]=ASC_AUDIO_PLAY_OPERATION; + cmdbuffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + } + else + { + cmdbuffer[2]=SCSISense.SenseKey; + cmdbuffer[12]=SCSISense.Asc; + cmdbuffer[13]=SCSISense.Ascq; + } + } + else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED)) + { + cmdbuffer[2]=SENSE_ILLEGAL_REQUEST; + cmdbuffer[12]=ASC_AUDIO_PLAY_OPERATION; + cmdbuffer[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + } + else + { + if (SCSISense.UnitAttention) + { + cmdbuffer[2]=SENSE_UNIT_ATTENTION; + cmdbuffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + cmdbuffer[13]=0; + } + } + + cmdbuffer[7]=10; + + SCSIPhase = SCSI_PHASE_DATAIN; + SCSIStatus = SCSI_STATUS_OK; + SCSICallback[id]=60*SCSI_TIME; + SCSIDevices[id].CmdBufferLength = len; + + SCSIDMAResetPosition(id); + + if (cmdbuffer[2] == SENSE_UNIT_ATTENTION) + { + /* If the last remaining sense is unit attention, clear + that condition. */ + SCSISense.UnitAttention = 0; + } + + /* Clear the sense stuff as per the spec. */ + SCSIClearSense(cdb[0], 0); + return; case GPCMD_READ_6: case GPCMD_READ_10: @@ -837,7 +835,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) { pos = (cdb[2]<<24)|(cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; } - cdrom->seek(SCSIDevices[id].lba_pos); + cdrom->seek(pos); SCSIPhase = SCSI_PHASE_STATUS; SCSIStatus = SCSI_STATUS_OK; @@ -846,23 +844,24 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) case GPCMD_INQUIRY: max_length = cdb[4]; + len = max_length; if (cdb[1] & 1) { PreambleLen = 4; SizeIndex = 3; - SCSIDevices[id].CmdBuffer[Idx++] = 05; - SCSIDevices[id].CmdBuffer[Idx++] = cdb[2]; - SCSIDevices[id].CmdBuffer[Idx++] = 0; + cmdbuffer[Idx++] = 05; + cmdbuffer[Idx++] = cdb[2]; + cmdbuffer[Idx++] = 0; Idx++; switch (cdb[2]) { case 0x00: - SCSIDevices[id].CmdBuffer[Idx++] = 0x00; - SCSIDevices[id].CmdBuffer[Idx++] = 0x83; + cmdbuffer[Idx++] = 0x00; + cmdbuffer[Idx++] = 0x83; break; case 0x83: @@ -873,26 +872,26 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) SCSICallback[id]=50*SCSI_TIME; return; } - SCSIDevices[id].CmdBuffer[Idx++] = 0x02; - SCSIDevices[id].CmdBuffer[Idx++] = 0x00; - SCSIDevices[id].CmdBuffer[Idx++] = 0x00; - SCSIDevices[id].CmdBuffer[Idx++] = 20; - ScsiPadStr8(SCSIDevices[id].CmdBuffer + Idx, 20, "53R141"); /* Serial */ + cmdbuffer[Idx++] = 0x02; + cmdbuffer[Idx++] = 0x00; + cmdbuffer[Idx++] = 0x00; + cmdbuffer[Idx++] = 20; + ScsiPadStr8(cmdbuffer + Idx, 20, "53R141"); /* Serial */ Idx += 20; - if (Idx + 72 > SCSIDevices[id].CmdBufferLength) + if (Idx + 72 > max_length) { goto SCSIOut; } - SCSIDevices[id].CmdBuffer[Idx++] = 0x02; - SCSIDevices[id].CmdBuffer[Idx++] = 0x01; - SCSIDevices[id].CmdBuffer[Idx++] = 0x00; - SCSIDevices[id].CmdBuffer[Idx++] = 68; - ScsiPadStr8(SCSIDevices[id].CmdBuffer + Idx, 8, "86Box"); /* Vendor */ + cmdbuffer[Idx++] = 0x02; + cmdbuffer[Idx++] = 0x01; + cmdbuffer[Idx++] = 0x00; + cmdbuffer[Idx++] = 68; + ScsiPadStr8(cmdbuffer + Idx, 8, "86Box"); /* Vendor */ Idx += 8; - ScsiPadStr8(SCSIDevices[id].CmdBuffer + Idx, 40, "86BoxCD 1.00"); /* Product */ + ScsiPadStr8(cmdbuffer + Idx, 40, "86BoxCD 1.00"); /* Product */ Idx += 40; - ScsiPadStr8(SCSIDevices[id].CmdBuffer + Idx, 20, "53R141"); /* Product */ + ScsiPadStr8(cmdbuffer + Idx, 20, "53R141"); /* Product */ Idx += 20; break; @@ -908,23 +907,23 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense) PreambleLen = 5; SizeIndex = 4; - SCSIDevices[id].CmdBuffer[0] = 0x05; /*CD-ROM*/ - SCSIDevices[id].CmdBuffer[1] = 0x80; /*Removable*/ - SCSIDevices[id].CmdBuffer[2] = 0; - SCSIDevices[id].CmdBuffer[3] = 0x21; - SCSIDevices[id].CmdBuffer[4] = 31; - SCSIDevices[id].CmdBuffer[5] = 0; - SCSIDevices[id].CmdBuffer[6] = 0; - SCSIDevices[id].CmdBuffer[7] = 0; - ScsiPadStr8(SCSIDevices[id].CmdBuffer + 8, 8, "86Box"); /* Vendor */ - ScsiPadStr8(SCSIDevices[id].CmdBuffer + 16, 16, "86BoxCD"); /* Product */ - ScsiPadStr8(SCSIDevices[id].CmdBuffer + 32, 4, emulator_version); /* Revision */ + cmdbuffer[0] = 0x05; /*CD-ROM*/ + cmdbuffer[1] = 0x80; /*Removable*/ + cmdbuffer[2] = 0; + cmdbuffer[3] = 0x21; + cmdbuffer[4] = 31; + cmdbuffer[5] = 0; + cmdbuffer[6] = 0; + cmdbuffer[7] = 0; + ScsiPadStr8(cmdbuffer + 8, 8, "86Box"); /* Vendor */ + ScsiPadStr8(cmdbuffer + 16, 16, "86BoxCD"); /* Product */ + ScsiPadStr8(cmdbuffer + 32, 4, emulator_version); /* Revision */ Idx = 36; } SCSIOut: - SCSIDevices[id].CmdBuffer[SizeIndex] = Idx - PreambleLen; + cmdbuffer[SizeIndex] = Idx - PreambleLen; len=Idx; SCSIPhase = SCSI_PHASE_DATAIN; @@ -950,8 +949,8 @@ SCSIOut: page_current = cdb[2]; if (page_flags[page_current] & PAGE_CHANGEABLE) - page_flags[GPMODE_CDROM_AUDIO_PAGE] |= PAGE_CHANGED; - + page_flags[GPMODE_CDROM_AUDIO_PAGE] |= PAGE_CHANGED; + SCSIPhase = SCSI_PHASE_DATAOUT; SCSIStatus = SCSI_STATUS_OK; SCSICallback[id]=60*SCSI_TIME; @@ -969,7 +968,7 @@ SCSIOut: Temp = cdb[2] & 0x3F; - memset(SCSIDevices[id].CmdBuffer, 0, len); + memset(cmdbuffer, 0, len); if (!(mode_sense_pages[cdb[2] & 0x3f] & IMPLEMENTED)) { @@ -981,23 +980,23 @@ SCSIOut: if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = SCSICDROMModeSense(SCSIDevices[id].CmdBuffer, 4, Temp); - SCSIDevices[id].CmdBuffer[0] = len - 1; - SCSIDevices[id].CmdBuffer[1] = 3; /*120mm data CD-ROM*/ + len = SCSICDROMModeSense(cmdbuffer, 4, Temp); + cmdbuffer[0] = len - 1; + cmdbuffer[1] = 3; /*120mm data CD-ROM*/ } else { - len = SCSICDROMModeSense(SCSIDevices[id].CmdBuffer, 8, Temp); - SCSIDevices[id].CmdBuffer[0] = (len - 2)>>8; - SCSIDevices[id].CmdBuffer[1] = (len - 2)&255; - SCSIDevices[id].CmdBuffer[2] = 3; /*120mm data CD-ROM*/ + len = SCSICDROMModeSense(cmdbuffer, 8, Temp); + cmdbuffer[0] = (len - 2)>>8; + cmdbuffer[1] = (len - 2)&255; + cmdbuffer[2] = 3; /*120mm data CD-ROM*/ } SCSIPhase = SCSI_PHASE_DATAIN; SCSIStatus = SCSI_STATUS_OK; SCSICallback[id]=60*SCSI_TIME; SCSIDevices[id].CmdBufferLength = len; - + SCSIDMAResetPosition(id); return; @@ -1027,17 +1026,17 @@ SCSIOut: case GPCMD_READ_CDROM_CAPACITY: if (cdrom->read_capacity) { - cdrom->read_capacity(SCSIDevices[id].CmdBuffer); + cdrom->read_capacity(cmdbuffer); } else { Size = cdrom->size() - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(SCSIDevices[id].CmdBuffer, 0, 8); - SCSIDevices[id].CmdBuffer[0] = (Size >> 24) & 0xff; - SCSIDevices[id].CmdBuffer[1] = (Size >> 16) & 0xff; - SCSIDevices[id].CmdBuffer[2] = (Size >> 8) & 0xff; - SCSIDevices[id].CmdBuffer[3] = Size & 0xff; - SCSIDevices[id].CmdBuffer[6] = 8; /* 2048 = 0x0800 */ + memset(cmdbuffer, 0, 8); + cmdbuffer[0] = (Size >> 24) & 0xff; + cmdbuffer[1] = (Size >> 16) & 0xff; + cmdbuffer[2] = (Size >> 8) & 0xff; + cmdbuffer[3] = Size & 0xff; + cmdbuffer[6] = 8; /* 2048 = 0x0800 */ } SCSIPhase = SCSI_PHASE_DATAIN; @@ -1059,11 +1058,11 @@ SCSIOut: } pos = 0; - SCSIDevices[id].CmdBuffer[pos++] = 0; - SCSIDevices[id].CmdBuffer[pos++] = 0; /*Audio status*/ - SCSIDevices[id].CmdBuffer[pos++] = 0; SCSIDevices[id].CmdBuffer[pos++] = 0; /*Subchannel length*/ - SCSIDevices[id].CmdBuffer[pos++] = 1; /*Format code*/ - SCSIDevices[id].CmdBuffer[1] = cdrom->getcurrentsubchannel(&SCSIDevices[id].CmdBuffer[5], msf); + cmdbuffer[pos++] = 0; + cmdbuffer[pos++] = 0; /*Audio status*/ + cmdbuffer[pos++] = 0; cmdbuffer[pos++] = 0; /*Subchannel length*/ + cmdbuffer[pos++] = 1; /*Format code*/ + cmdbuffer[1] = cdrom->getcurrentsubchannel(&cmdbuffer[5], msf); len = 16; if (!Temp) len = 4; @@ -1081,19 +1080,19 @@ SCSIOut: { case 0: /*Normal*/ len = cdb[8]|(cdb[7]<<8); - len = cdrom->readtoc(SCSIDevices[id].CmdBuffer, cdb[6], msf, len, 0); + len = cdrom->readtoc(cmdbuffer, cdb[6], msf, len, 0); break; case 1: /*Multi session*/ len = cdb[8]|(cdb[7]<<8); - len = cdrom->readtoc_session(SCSIDevices[id].CmdBuffer, msf, len); - SCSIDevices[id].CmdBuffer[0] = 0; - SCSIDevices[id].CmdBuffer[1] = 0xA; + len = cdrom->readtoc_session(cmdbuffer, msf, len); + cmdbuffer[0] = 0; + cmdbuffer[1] = 0xA; break; case 2: /*Raw*/ len = cdb[8]|(cdb[7]<<8); - len = cdrom->readtoc_raw(SCSIDevices[id].CmdBuffer, msf, len); + len = cdrom->readtoc_raw(cmdbuffer, msf, len); break; default: @@ -1113,7 +1112,7 @@ SCSIOut: case GPCMD_READ_HEADER: if (cdrom->read_header) { - cdrom->read_header(cdb, SCSIDevices[id].CmdBuffer); + cdrom->read_header(cdb, cmdbuffer); } else { @@ -1127,12 +1126,12 @@ SCSIOut: { real_pos = SectorLBA; } - SCSIDevices[id].CmdBuffer[4] = (real_pos >> 24); - SCSIDevices[id].CmdBuffer[5] = ((real_pos >> 16) & 0xff); - SCSIDevices[id].CmdBuffer[6] = ((real_pos >> 8) & 0xff); - SCSIDevices[id].CmdBuffer[7] = real_pos & 0xff; - SCSIDevices[id].CmdBuffer[0]=1; /*2048 bytes user data*/ - SCSIDevices[id].CmdBuffer[1]=SCSIDevices[id].CmdBuffer[2]=SCSIDevices[id].CmdBuffer[3]=0; + cmdbuffer[4] = (real_pos >> 24); + cmdbuffer[5] = ((real_pos >> 16) & 0xff); + cmdbuffer[6] = ((real_pos >> 8) & 0xff); + cmdbuffer[7] = real_pos & 0xff; + cmdbuffer[0]=1; /*2048 bytes user data*/ + cmdbuffer[1]=cmdbuffer[2]=cmdbuffer[3]=0; } SCSIPhase = SCSI_PHASE_DATAIN; @@ -1165,6 +1164,7 @@ SCSIOut: if ((cdrom_drive < 1) || (cdrom_drive == 200) || (cd_status <= CD_STATUS_DATA_ONLY) || !cdrom->is_track_audio(pos, (cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0)) { + pclog("Invalid mode for this track\n"); SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_MODE_FOR_THIS_TRACK, 0x00); SCSICallback[id]=50*SCSI_TIME; @@ -1201,29 +1201,29 @@ SCSIOut: if (len > 512) /* XXX: assume 1 sector */ len = 512; - memset(SCSIDevices[id].CmdBuffer, 0, len); + memset(cmdbuffer, 0, len); /* * the number of sectors from the media tells us which profile * to use as current. 0 means there is no media */ if (len > CD_MAX_SECTORS ) { - SCSIDevices[id].CmdBuffer[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - SCSIDevices[id].CmdBuffer[7] = MMC_PROFILE_DVD_ROM & 0xff; + cmdbuffer[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; + cmdbuffer[7] = MMC_PROFILE_DVD_ROM & 0xff; } else if (len <= CD_MAX_SECTORS) { - SCSIDevices[id].CmdBuffer[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - SCSIDevices[id].CmdBuffer[7] = MMC_PROFILE_CD_ROM & 0xff; + cmdbuffer[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; + cmdbuffer[7] = MMC_PROFILE_CD_ROM & 0xff; } - SCSIDevices[id].CmdBuffer[10] = 0x02 | 0x01; /* persistent and current */ + cmdbuffer[10] = 0x02 | 0x01; /* persistent and current */ len = 12; /* headers: 8 + 4 */ - len += SCSICDROMSetProfile(SCSIDevices[id].CmdBuffer, &Index, MMC_PROFILE_DVD_ROM); - len += SCSICDROMSetProfile(SCSIDevices[id].CmdBuffer, &Index, MMC_PROFILE_CD_ROM); - SCSIDevices[id].CmdBuffer[0] = ((len-4) >> 24) & 0xff; - SCSIDevices[id].CmdBuffer[1] = ((len-4) >> 16) & 0xff; - SCSIDevices[id].CmdBuffer[2] = ((len-4) >> 8) & 0xff; - SCSIDevices[id].CmdBuffer[3] = (len-4) & 0xff; + len += SCSICDROMSetProfile(cmdbuffer, &Index, MMC_PROFILE_DVD_ROM); + len += SCSICDROMSetProfile(cmdbuffer, &Index, MMC_PROFILE_CD_ROM); + cmdbuffer[0] = ((len-4) >> 24) & 0xff; + cmdbuffer[1] = ((len-4) >> 16) & 0xff; + cmdbuffer[2] = ((len-4) >> 8) & 0xff; + cmdbuffer[3] = (len-4) & 0xff; SCSIPhase = SCSI_PHASE_DATAIN; SCSIStatus = SCSI_STATUS_OK; @@ -1235,7 +1235,7 @@ SCSIOut: case GPCMD_GET_EVENT_STATUS_NOTIFICATION: gesn_cdb = (void *)cdb; - gesn_event_header = (void *)SCSIDevices[id].CmdBuffer; + gesn_event_header = (void *)cmdbuffer; /* It is fine by the MMC spec to not support async mode operations */ if (!(gesn_cdb->polled & 0x01)) @@ -1274,7 +1274,7 @@ SCSIOut: if (gesn_cdb->class & (1 << GESN_MEDIA)) { gesn_event_header->notification_class |= GESN_MEDIA; - len = SCSICDROMEventStatus(SCSIDevices[id].CmdBuffer); + len = SCSICDROMEventStatus(cmdbuffer); } else { @@ -1309,18 +1309,18 @@ SCSIOut: case GPCMD_READ_DISC_INFORMATION: if (cdrom->read_disc_information) { - cdrom->read_disc_information(SCSIDevices[id].CmdBuffer); + cdrom->read_disc_information(cmdbuffer); } else { - SCSIDevices[id].CmdBuffer[1] = 32; - SCSIDevices[id].CmdBuffer[2] = 0xe; /* last session complete, disc finalized */ - SCSIDevices[id].CmdBuffer[3] = 1; /* first track on disc */ - SCSIDevices[id].CmdBuffer[4] = 1; /* # of sessions */ - SCSIDevices[id].CmdBuffer[5] = 1; /* first track of last session */ - SCSIDevices[id].CmdBuffer[6] = 1; /* last track of last session */ - SCSIDevices[id].CmdBuffer[7] = 0x20; /* unrestricted use */ - SCSIDevices[id].CmdBuffer[8] = 0x00; /* CD-ROM */ + cmdbuffer[1] = 32; + cmdbuffer[2] = 0xe; /* last session complete, disc finalized */ + cmdbuffer[3] = 1; /* first track on disc */ + cmdbuffer[4] = 1; /* # of sessions */ + cmdbuffer[5] = 1; /* first track of last session */ + cmdbuffer[6] = 1; /* last track of last session */ + cmdbuffer[7] = 0x20; /* unrestricted use */ + cmdbuffer[8] = 0x00; /* CD-ROM */ } SCSIPhase = SCSI_PHASE_DATAIN; @@ -1343,7 +1343,7 @@ SCSIOut: if (cdrom->read_track_information) { - ret = cdrom->read_track_information(cdb, SCSIDevices[id].CmdBuffer); + ret = cdrom->read_track_information(cdb, cmdbuffer); if (!ret) { @@ -1353,9 +1353,9 @@ SCSIOut: return; } - len = SCSIDevices[id].CmdBuffer[0]; + len = cmdbuffer[0]; len <<= 8; - len |= SCSIDevices[id].CmdBuffer[1]; + len |= cmdbuffer[1]; len += 2; } else @@ -1369,26 +1369,26 @@ SCSIOut: } len = 36; - SCSIDevices[id].CmdBuffer[1] = 34; - SCSIDevices[id].CmdBuffer[2] = 1; /* track number (LSB) */ - SCSIDevices[id].CmdBuffer[3] = 1; /* session number (LSB) */ - SCSIDevices[id].CmdBuffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - SCSIDevices[id].CmdBuffer[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - SCSIDevices[id].CmdBuffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - SCSIDevices[id].CmdBuffer[8] = 0; /* track start address is 0 */ - SCSIDevices[id].CmdBuffer[24] = (cdrom->size() >> 24) & 0xff; /* track size */ - SCSIDevices[id].CmdBuffer[25] = (cdrom->size() >> 16) & 0xff; /* track size */ - SCSIDevices[id].CmdBuffer[26] = (cdrom->size() >> 8) & 0xff; /* track size */ - SCSIDevices[id].CmdBuffer[27] = cdrom->size() & 0xff; /* track size */ - SCSIDevices[id].CmdBuffer[32] = 0; /* track number (MSB) */ - SCSIDevices[id].CmdBuffer[33] = 0; /* session number (MSB) */ + cmdbuffer[1] = 34; + cmdbuffer[2] = 1; /* track number (LSB) */ + cmdbuffer[3] = 1; /* session number (LSB) */ + cmdbuffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ + cmdbuffer[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ + cmdbuffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ + cmdbuffer[8] = 0; /* track start address is 0 */ + cmdbuffer[24] = (cdrom->size() >> 24) & 0xff; /* track size */ + cmdbuffer[25] = (cdrom->size() >> 16) & 0xff; /* track size */ + cmdbuffer[26] = (cdrom->size() >> 8) & 0xff; /* track size */ + cmdbuffer[27] = cdrom->size() & 0xff; /* track size */ + cmdbuffer[32] = 0; /* track number (MSB) */ + cmdbuffer[33] = 0; /* session number (MSB) */ } if (len > max_length) { len = max_length; - SCSIDevices[id].CmdBuffer[0] = ((max_length - 2) >> 8) & 0xff; - SCSIDevices[id].CmdBuffer[1] = (max_length - 2) & 0xff; + cmdbuffer[0] = ((max_length - 2) >> 8) & 0xff; + cmdbuffer[1] = (max_length - 2) & 0xff; } SCSIPhase = SCSI_PHASE_DATAIN; @@ -1420,7 +1420,7 @@ SCSIOut: } } - memset(SCSIDevices[id].CmdBuffer, 0, len > 256 * 512 + 4 ? 256 * 512 + 4 : len); + memset(cmdbuffer, 0, len > 256 * 512 + 4 ? 256 * 512 + 4 : len); switch (cdb[7]) { @@ -1428,11 +1428,14 @@ SCSIOut: case 0xff: if (cdb[1] == 0) { - DVDRet = SCSICDROMReadDVDStructure(cdb[7], cdb, SCSIDevices[id].CmdBuffer); + DVDRet = SCSICDROMReadDVDStructure(cdb[7], cdb, cmdbuffer); if (DVDRet < 0) { + SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, -DVDRet, 0x00); + SCSICallback[id]=50*SCSI_TIME; + return; } else { @@ -1509,14 +1512,14 @@ SCSIOut: break; case GPCMD_MECHANISM_STATUS: - SCSIDevices[id].CmdBuffer[0] = 0; - SCSIDevices[id].CmdBuffer[1] = 0; - SCSIDevices[id].CmdBuffer[2] = 0; - SCSIDevices[id].CmdBuffer[3] = 0; - SCSIDevices[id].CmdBuffer[4] = 0; - SCSIDevices[id].CmdBuffer[5] = 1; - SCSIDevices[id].CmdBuffer[6] = 0; - SCSIDevices[id].CmdBuffer[7] = 0; + cmdbuffer[0] = 0; + cmdbuffer[1] = 0; + cmdbuffer[2] = 0; + cmdbuffer[3] = 0; + cmdbuffer[4] = 0; + cmdbuffer[5] = 1; + cmdbuffer[6] = 0; + cmdbuffer[7] = 0; SCSIPhase = SCSI_PHASE_DATAIN; SCSIStatus = SCSI_STATUS_OK; @@ -1528,7 +1531,7 @@ SCSIOut: } } -void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen, uint8_t senselen) +void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen) { int read_length = 0; @@ -1539,12 +1542,13 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen, ui case GPCMD_READ_12: case GPCMD_READ_CD_MSF: case GPCMD_READ_CD: - pclog("Total data length requested: %d\n", datalen); + pclog("Total data length requested: %d\n", datalen); while (datalen > 0) { read_length = cdrom_read_data(data); //Fill the buffer the data it needs if (!read_length) { + pclog("Invalid read\n"); SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); SCSICallback[id]=50*SCSI_TIME; @@ -1565,6 +1569,6 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen, ui if (SectorLen == 0) break; } - return; + break; } }