Fixed once and for all the DOS CD-ROM bugs in the BT-54x SCSI adapter.

Added notes regarding NT 3.1 297.1 and 340.1's setup bugs with the Adaptec driver in the BT-54x SCSI adapter.
Bugfixes to the SCSI layer (SCSIReset())
This commit is contained in:
TC1995
2016-12-27 18:48:38 +01:00
parent 547185fd7f
commit df78ce0529
5 changed files with 122 additions and 108 deletions

View File

@@ -3,8 +3,8 @@
*/ */
/*Buslogic SCSI emulation (including Adaptec 154x ISA software backward compatibility)*/ /*Buslogic SCSI emulation (including Adaptec 154x ISA software backward compatibility)*/
/* ToDo: */ //Note: for the Adaptec-enabled Windows NT betas, install from HDD at the moment due to a bug in the round robin outgoing
/* Improve DOS support */ //mailboxes.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -513,6 +513,7 @@ typedef struct Buslogic_t
int DmaChannel; int DmaChannel;
int IrqEnabled; int IrqEnabled;
int Mbx24bit; int Mbx24bit;
int CommandEnable;
} Buslogic_t; } Buslogic_t;
int scsi_base = 0x330; int scsi_base = 0x330;
@@ -535,7 +536,7 @@ void BuslogicLog(const char *format, ...)
static void BuslogicClearInterrupt(Buslogic_t *Buslogic) static void BuslogicClearInterrupt(Buslogic_t *Buslogic)
{ {
pclog("Buslogic: Clearing Interrupt 0x%02X\n", Buslogic->Interrupt); BuslogicLog("Buslogic: Clearing Interrupt 0x%02X\n", Buslogic->Interrupt);
Buslogic->Interrupt = 0; Buslogic->Interrupt = 0;
picintc(1 << Buslogic->Irq); picintc(1 << Buslogic->Irq);
} }
@@ -628,20 +629,20 @@ static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *C
//Rewrite the CCB up to the CDB. //Rewrite the CCB up to the CDB.
DMAPageWrite(CCBPointer, CmdBlock, offsetof(CCBC, Cdb)); DMAPageWrite(CCBPointer, CmdBlock, offsetof(CCBC, Cdb));
} }
pclog("Host Status 0x%02X, Target Status 0x%02X\n", HostStatus, TargetStatus);
BuslogicLog("Host Status 0x%02X, Target Status 0x%02X\n", HostStatus, TargetStatus);
if (Buslogic->Mbx24bit) if (Buslogic->Mbx24bit)
{ {
MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode; MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode;
U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer); U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer);
pclog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%08X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); BuslogicLog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%08X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer));
DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t)); DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t));
} }
else else
{ {
pclog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%08X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer); BuslogicLog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%08X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer);
DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t)); DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t));
} }
@@ -649,7 +650,7 @@ static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *C
Buslogic->MailboxInPosCur++; Buslogic->MailboxInPosCur++;
if (Buslogic->MailboxInPosCur > Buslogic->MailboxCount) if (Buslogic->MailboxInPosCur > Buslogic->MailboxCount)
Buslogic->MailboxInPosCur = 0; Buslogic->MailboxInPosCur = 0;
Buslogic->Interrupt = INTR_MBIF | INTR_ANY; Buslogic->Interrupt = INTR_MBIF | INTR_ANY;
picint(1 << Buslogic->Irq); picint(1 << Buslogic->Irq);
} }
@@ -692,7 +693,7 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB
if (CmdBlock->common.Cdb[0] == GPCMD_TEST_UNIT_READY) if (CmdBlock->common.Cdb[0] == GPCMD_TEST_UNIT_READY)
DataLength = 0; DataLength = 0;
pclog("Data Buffer write: length %d, pointer %d\n", DataLength, DataPointer); BuslogicLog("Data Buffer write: length %d, pointer %d\n", DataLength, DataPointer);
if (DataLength && CmdBlock->common.ControlByte != 0x03) if (DataLength && CmdBlock->common.ControlByte != 0x03)
{ {
@@ -788,7 +789,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)
DataLength = 0; DataLength = 0;
pclog("Data Buffer read: length %d, pointer %d\n", DataLength, DataPointer); BuslogicLog("Data Buffer read: length %d, pointer %d\n", DataLength, DataPointer);
//If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without //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 length/read/write commands. //checking its length, so do this procedure for both no length/read/write commands.
@@ -907,8 +908,11 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
case 1: case 1:
if ((Val == 0x02) && (Buslogic->Command == 0xFF)) if ((Val == 0x02) && (Buslogic->Command == 0xFF))
{ {
SCSICallback[scsi_cdrom_id] = 1; if (Buslogic->MailboxCount)
break; {
SCSICallback[scsi_cdrom_id] = 1;
break;
}
} }
if (Buslogic->Command == 0xFF) if (Buslogic->Command == 0xFF)
@@ -917,7 +921,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->CmdParam = 0; Buslogic->CmdParam = 0;
Buslogic->Status &= ~(STAT_INVCMD | STAT_IDLE); Buslogic->Status &= ~(STAT_INVCMD | STAT_IDLE);
pclog("Buslogic: Operation Code 0x%02X\n", Val); BuslogicLog("Buslogic: Operation Code 0x%02X\n", Val);
switch (Buslogic->Command) switch (Buslogic->Command)
{ {
case 0x00: case 0x00:
@@ -990,7 +994,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
if (!Buslogic->CmdParamLeft) if (!Buslogic->CmdParamLeft)
{ {
pclog("Running Operation Code 0x%02X\n", Buslogic->Command); BuslogicLog("Running Operation Code 0x%02X\n", Buslogic->Command);
switch (Buslogic->Command) switch (Buslogic->Command)
{ {
case 0x00: case 0x00:
@@ -1010,7 +1014,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
BuslogicLog("Buslogic Initialize Mailbox Command\n"); BuslogicLog("Buslogic Initialize Mailbox Command\n");
BuslogicLog("Mailbox Out Address=0x%08X\n", Buslogic->MailboxOutAddr); BuslogicLog("Mailbox Out Address=0x%08X\n", Buslogic->MailboxOutAddr);
BuslogicLog("Mailbox In Address=0x%08X\n", Buslogic->MailboxInAddr); BuslogicLog("Mailbox In Address=0x%08X\n", Buslogic->MailboxInAddr);
pclog("Initialized Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, ADDR_TO_U32(MailboxInit->Address)); BuslogicLog("Initialized Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, ADDR_TO_U32(MailboxInit->Address));
Buslogic->Status &= ~STAT_INIT; Buslogic->Status &= ~STAT_INIT;
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
@@ -1030,7 +1034,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
BuslogicLog("Buslogic Extended Initialize Mailbox Command\n"); BuslogicLog("Buslogic Extended Initialize Mailbox Command\n");
BuslogicLog("Mailbox Out Address=0x%08X\n", Buslogic->MailboxOutAddr); BuslogicLog("Mailbox Out Address=0x%08X\n", Buslogic->MailboxOutAddr);
BuslogicLog("Mailbox In Address=0x%08X\n", Buslogic->MailboxInAddr); BuslogicLog("Mailbox In Address=0x%08X\n", Buslogic->MailboxInAddr);
pclog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, MailboxInit->Address); BuslogicLog("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInit->Count, MailboxInit->Address);
Buslogic->Status &= ~STAT_INIT; Buslogic->Status &= ~STAT_INIT;
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
@@ -1065,19 +1069,19 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
case 0x07: case 0x07:
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
Buslogic->LocalRam.structured.autoSCSIData.uBusOnDelay = Buslogic->CmdBuf[0]; Buslogic->LocalRam.structured.autoSCSIData.uBusOnDelay = Buslogic->CmdBuf[0];
pclog("Bus-on time: %d\n", Buslogic->CmdBuf[0]); BuslogicLog("Bus-on time: %d\n", Buslogic->CmdBuf[0]);
break; break;
case 0x08: case 0x08:
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
Buslogic->LocalRam.structured.autoSCSIData.uBusOffDelay = Buslogic->CmdBuf[0]; Buslogic->LocalRam.structured.autoSCSIData.uBusOffDelay = Buslogic->CmdBuf[0];
pclog("Bus-off time: %d\n", Buslogic->CmdBuf[0]); BuslogicLog("Bus-off time: %d\n", Buslogic->CmdBuf[0]);
break; break;
case 0x09: case 0x09:
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
Buslogic->LocalRam.structured.autoSCSIData.uDMATransferRate = Buslogic->CmdBuf[0]; Buslogic->LocalRam.structured.autoSCSIData.uDMATransferRate = Buslogic->CmdBuf[0];
pclog("DMA transfer rate: %02X\n", Buslogic->CmdBuf[0]); BuslogicLog("DMA transfer rate: %02X\n", Buslogic->CmdBuf[0]);
break; break;
case 0x0A: case 0x0A:
@@ -1112,8 +1116,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
*/ */
Reply->uCharacterD = 'D'; /* BusLogic model. */ Reply->uCharacterD = 'D'; /* BusLogic model. */
Reply->uHostBusType = 'A'; /* ISA bus. */ Reply->uHostBusType = 'A'; /* ISA bus. */
BuslogicLog("Return Setup Information: %d\n", Buslogic->CmdBuf[0]);
pclog("Return Setup Information: %d\n", Buslogic->CmdBuf[0]);
} }
break; break;
@@ -1144,7 +1147,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Reply->cMailbox = Buslogic->MailboxCount; Reply->cMailbox = Buslogic->MailboxCount;
Reply->uMailboxAddressBase = Buslogic->MailboxOutAddr; Reply->uMailboxAddressBase = Buslogic->MailboxOutAddr;
memcpy(Reply->aFirmwareRevision, "07B", sizeof(Reply->aFirmwareRevision)); memcpy(Reply->aFirmwareRevision, "07B", sizeof(Reply->aFirmwareRevision));
pclog("Return Extended Setup Information: %d\n", Buslogic->CmdBuf[0]); BuslogicLog("Return Extended Setup Information: %d\n", Buslogic->CmdBuf[0]);
} }
break; break;
@@ -1321,7 +1324,7 @@ static void BuslogicSCSIRequestComplete(Buslogic_t *Buslogic, BuslogicRequests_t
if (BuslogicRequests->RequestSenseBuffer) if (BuslogicRequests->RequestSenseBuffer)
BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK)); BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK));
if (Status == SCSI_STATUS_OK) if (Status == SCSI_STATUS_OK)
{ {
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK,
@@ -1330,7 +1333,7 @@ static void BuslogicSCSIRequestComplete(Buslogic_t *Buslogic, BuslogicRequests_t
else if (Status == SCSI_STATUS_CHECK_CONDITION) else if (Status == SCSI_STATUS_CHECK_CONDITION)
{ {
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION,
MBI_ERROR); MBI_ERROR);
} }
} }
@@ -1344,19 +1347,18 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
DMAPageRead(CCBPointer, &CmdBlock, sizeof(CCB32)); DMAPageRead(CCBPointer, &CmdBlock, sizeof(CCB32));
BuslogicRequests->TargetID = Buslogic->Mbx24bit ? CmdBlock.old.Id : CmdBlock.new.Id; BuslogicRequests->TargetID = Buslogic->Mbx24bit ? CmdBlock.old.Id : CmdBlock.new.Id;
BuslogicRequests->LUN = Buslogic->Mbx24bit ? CmdBlock.old.Lun : CmdBlock.new.Lun;
Id = BuslogicRequests->TargetID; Id = BuslogicRequests->TargetID;
Lun = BuslogicRequests->LUN; BuslogicRequests->LUN = Buslogic->Mbx24bit ? CmdBlock.old.Lun : CmdBlock.new.Lun;
Lun = BuslogicRequests->LUN;
pclog("Scanning SCSI Target ID %i\n", Id); BuslogicLog("Scanning SCSI Target ID %i\n", Id);
//Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon. //Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon.
if (Id < ELEMENTS(SCSIDevices)) if (Id < ELEMENTS(SCSIDevices))
{ {
if (Id == scsi_cdrom_id && Lun == 0) if (Id == scsi_cdrom_id)
{ {
pclog("SCSI Target ID %i detected and working\n", Id); BuslogicLog("SCSI Target ID %i detected and working\n", Id);
BuslogicRequests->CCBPointer = CCBPointer; BuslogicRequests->CCBPointer = CCBPointer;
BuslogicRequests->Is24bit = Buslogic->Mbx24bit; BuslogicRequests->Is24bit = Buslogic->Mbx24bit;
@@ -1366,17 +1368,16 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit); BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit);
BuslogicSenseBufferAllocate(BuslogicRequests); BuslogicSenseBufferAllocate(BuslogicRequests);
#if 1 //for finding bugs.
uint32_t i; uint32_t i;
pclog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]); BuslogicLog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]);
for (i = 1; i < BuslogicRequests->CmdBlock.common.CdbLength; i++) for (i = 1; i < BuslogicRequests->CmdBlock.common.CdbLength; i++)
pclog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[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);
pclog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte);
pclog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength);
pclog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode);
#endif
//First, get the data buffer otherwise putting it after the //First, get the data buffer otherwise putting it after the
//exec function results into not getting read/write commands right and //exec function results into not getting read/write commands right and
//failing to detect the device. //failing to detect the device.
@@ -1392,12 +1393,12 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
//Finally, execute the SCSI command immediately and get the transfer length. //Finally, execute the SCSI command immediately and get the transfer length.
SCSIPhase = SCSI_PHASE_COMMAND; SCSIPhase = SCSI_PHASE_COMMAND;
SCSIExecCommand(Id, BuslogicRequests->CmdBlock.common.Cdb); SCSIExecCommand(Id, Lun, BuslogicRequests->CmdBlock.common.Cdb);
SCSIGetLength(Id, &SCSIDevices[Id].InitLength); SCSIGetLength(Id, &SCSIDevices[Id].InitLength);
if (SCSIPhase == SCSI_PHASE_DATAOUT) if (SCSIPhase == SCSI_PHASE_DATAOUT)
{ {
SCSIWriteData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); SCSIWriteData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength);
} }
else if (SCSIPhase == SCSI_PHASE_DATAIN) else if (SCSIPhase == SCSI_PHASE_DATAIN)
{ {
@@ -1415,30 +1416,22 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
if (BuslogicRequests->Is24bit) if (BuslogicRequests->Is24bit)
{ {
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIStatus == SCSI_STATUS_OK ? 0 : SCSIDevices[Id].InitLength); U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIStatus == SCSI_STATUS_OK ? 0 : SCSIDevices[Id].InitLength);
pclog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength)); BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
} }
else else
{ {
BuslogicRequests->CmdBlock.new.DataLength = SCSIStatus == SCSI_STATUS_OK ? 0 : SCSIDevices[Id].InitLength; BuslogicRequests->CmdBlock.new.DataLength = SCSIStatus == SCSI_STATUS_OK ? 0 : SCSIDevices[Id].InitLength;
pclog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength); BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
} }
} }
//If the initialized data length is higher than the requested length, signal complete request. //If the initialized data length is higher than the requested length, signal complete request.
if (SCSIDevices[Id].InitLength >= SCSIDevices[Id].buffer_size || SCSIDevices[Id].InitLength == 0) if (SCSIDevices[Id].InitLength >= SCSIDevices[Id].buffer_size || SCSIDevices[Id].InitLength == 0)
BuslogicSCSIRequestComplete(Buslogic, BuslogicRequests); BuslogicSCSIRequestComplete(Buslogic, BuslogicRequests);
} }
else else
{ {
pclog("No device is present in the SCSI bus\n"); BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
BuslogicDataBufferFree(BuslogicRequests);
if (BuslogicRequests->RequestSenseBuffer)
BuslogicSenseBufferFree(BuslogicRequests, 1);
BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK,
MBI_ERROR);
} }
} }
} }
@@ -1508,14 +1501,18 @@ static void BuslogicStartMailbox(Buslogic_t *Buslogic)
if (Mailbox32.u.out.ActionCode == MBO_START) if (Mailbox32.u.out.ActionCode == MBO_START)
{ {
pclog("Start Mailbox Command\n"); BuslogicLog("Start Mailbox Command\n");
BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer); BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer);
} }
else if (Mailbox32.u.out.ActionCode == MBO_ABORT) else if (Mailbox32.u.out.ActionCode == MBO_ABORT)
{ {
pclog("Abort Mailbox Command\n"); BuslogicLog("Abort Mailbox Command\n");
BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer); BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer);
} }
else
{
BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer);
}
} }
void BuslogicCommandCallback(void *p) void BuslogicCommandCallback(void *p)
@@ -1523,11 +1520,7 @@ void BuslogicCommandCallback(void *p)
Buslogic_t *Buslogic = (Buslogic_t *)p; Buslogic_t *Buslogic = (Buslogic_t *)p;
SCSICallback[scsi_cdrom_id] = 0; SCSICallback[scsi_cdrom_id] = 0;
BuslogicStartMailbox(Buslogic);
if (Buslogic->MailboxCount)
{
BuslogicStartMailbox(Buslogic);
}
} }
void *BuslogicInit() void *BuslogicInit()

View File

@@ -294,7 +294,7 @@ void initpc(int argc, char *argv[])
resetide(); resetide();
if (buslogic_enabled) if (buslogic_enabled)
{ {
SCSIReset(scsi_cdrom_id); SCSIReset();
device_add(&BuslogicDevice); device_add(&BuslogicDevice);
} }
@@ -421,7 +421,7 @@ void resetpchard()
if (buslogic_enabled) if (buslogic_enabled)
{ {
SCSIReset(scsi_cdrom_id); SCSIReset();
device_add(&BuslogicDevice); device_add(&BuslogicDevice);
} }

View File

@@ -23,9 +23,9 @@ void SCSIGetLength(uint8_t id, int *datalen)
} }
//Execute SCSI command //Execute SCSI command
void SCSIExecCommand(uint8_t id, uint8_t *cdb) void SCSIExecCommand(uint8_t id, uint8_t lun, uint8_t *cdb)
{ {
SCSICDROM_Command(id, cdb); SCSICDROM_Command(id, lun, cdb);
} }
//Read pending data from the resulting SCSI command //Read pending data from the resulting SCSI command
@@ -43,7 +43,7 @@ void SCSIWriteData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
///// /////
void SCSIDMAResetPosition(uint8_t Id) void SCSIDMAResetPosition(uint8_t Id)
{ {
//Reset position in memory after reaching the //Reset position in memory after reaching its limit
SCSIDevices[Id].pos = 0; SCSIDevices[Id].pos = 0;
} }
@@ -90,21 +90,33 @@ void SCSIWrite(uint8_t Id, uint32_t len_size)
///// /////
//Initialization function for the SCSI layer //Initialization function for the SCSI layer
void SCSIReset(uint8_t Id) void SCSIReset(void)
{ {
page_flags[GPMODE_CDROM_AUDIO_PAGE] &= 0xFD; /* Clear changed flag for CDROM AUDIO mode page. */ page_flags[GPMODE_CDROM_AUDIO_PAGE] &= 0xFD; /* Clear changed flag for CDROM AUDIO mode page. */
memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */ memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */
if (cdrom_enabled && scsi_cdrom_enabled) int drive;
SCSICallback[0]=0;
SCSICallback[1]=0;
SCSICallback[2]=0;
SCSICallback[3]=0;
SCSICallback[4]=0;
SCSICallback[5]=0;
SCSICallback[6]=0;
for (drive=0;drive<7;drive++)
{ {
SCSICallback[Id]=0; if ((scsi_cdrom_id == drive) && cdrom_enabled && scsi_cdrom_enabled)
SCSIDevices[Id].LunType = SCSI_CDROM; {
SCSIDevices[drive].LunType = SCSI_CDROM;
}
else
{
SCSIDevices[drive].LunType = SCSI_NONE;
}
} }
else
{
SCSIDevices[Id].LunType = SCSI_NONE;
}
page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED;
SCSISense.UnitAttention = 0; SCSISense.UnitAttention = 0;

View File

@@ -244,20 +244,18 @@ extern int cdrom_sector_size, cdrom_sector_ismsf;
#define SCSI_PHASE_BUS_FREE ( 8 ) #define SCSI_PHASE_BUS_FREE ( 8 )
#define SCSI_PHASE_SELECT ( 9 ) #define SCSI_PHASE_SELECT ( 9 )
#define BUFFER_LEN 262144
struct struct
{ {
uint32_t buffer_size; uint32_t buffer_size;
uint32_t pos; uint32_t pos;
uint8_t *Cdb; uint8_t *Cdb;
uint8_t CmdBuffer[BUFFER_LEN]; uint8_t CmdBuffer[262144];
uint32_t CmdBufferLength; uint32_t CmdBufferLength;
int LunType; int LunType;
uint32_t InitLength; uint32_t InitLength;
} SCSIDevices[7]; } SCSIDevices[7];
extern void SCSIReset(uint8_t Id); extern void SCSIReset(void);
uint32_t SCSICDROMModeSense(uint8_t *buf, uint32_t pos, uint8_t type); uint32_t SCSICDROMModeSense(uint8_t *buf, uint32_t pos, uint8_t type);
uint8_t SCSICDROMSetProfile(uint8_t *buf, uint8_t *index, uint16_t profile); uint8_t SCSICDROMSetProfile(uint8_t *buf, uint8_t *index, uint16_t profile);

View File

@@ -23,14 +23,14 @@ uint8_t SCSICommandTable[0x100] =
{ {
[GPCMD_TEST_UNIT_READY] = CHECK_READY | NONDATA, [GPCMD_TEST_UNIT_READY] = CHECK_READY | NONDATA,
[GPCMD_REQUEST_SENSE] = ALLOW_UA, [GPCMD_REQUEST_SENSE] = ALLOW_UA,
[GPCMD_READ_6] = CHECK_READY | READDATA, [GPCMD_READ_6] = CHECK_READY,
[GPCMD_INQUIRY] = ALLOW_UA, [GPCMD_INQUIRY] = ALLOW_UA,
[GPCMD_MODE_SELECT_6] = 0, [GPCMD_MODE_SELECT_6] = 0,
[GPCMD_MODE_SENSE_6] = 0, [GPCMD_MODE_SENSE_6] = 0,
[GPCMD_START_STOP_UNIT] = CHECK_READY, [GPCMD_START_STOP_UNIT] = CHECK_READY,
[GPCMD_PREVENT_REMOVAL] = CHECK_READY, [GPCMD_PREVENT_REMOVAL] = CHECK_READY,
[GPCMD_READ_CDROM_CAPACITY] = CHECK_READY, [GPCMD_READ_CDROM_CAPACITY] = CHECK_READY,
[GPCMD_READ_10] = CHECK_READY | READDATA, [GPCMD_READ_10] = CHECK_READY,
[GPCMD_SEEK] = CHECK_READY | NONDATA, [GPCMD_SEEK] = CHECK_READY | NONDATA,
[GPCMD_READ_SUBCHANNEL] = CHECK_READY, [GPCMD_READ_SUBCHANNEL] = CHECK_READY,
[GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY | ALLOW_UA, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS [GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY | ALLOW_UA, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS
@@ -50,14 +50,14 @@ uint8_t SCSICommandTable[0x100] =
[GPCMD_MODE_SELECT_10] = 0, [GPCMD_MODE_SELECT_10] = 0,
[GPCMD_MODE_SENSE_10] = 0, [GPCMD_MODE_SENSE_10] = 0,
[GPCMD_PLAY_AUDIO_12] = CHECK_READY, [GPCMD_PLAY_AUDIO_12] = CHECK_READY,
[GPCMD_READ_12] = CHECK_READY | READDATA, [GPCMD_READ_12] = CHECK_READY,
[GPCMD_READ_DVD_STRUCTURE] = CHECK_READY, [GPCMD_READ_DVD_STRUCTURE] = CHECK_READY,
[GPCMD_READ_CD_MSF] = CHECK_READY | READDATA, [GPCMD_READ_CD_MSF] = CHECK_READY,
[GPCMD_SET_SPEED] = 0, [GPCMD_SET_SPEED] = 0,
[GPCMD_PLAY_CD] = CHECK_READY, [GPCMD_PLAY_CD] = CHECK_READY,
[GPCMD_MECHANISM_STATUS] = 0, [GPCMD_MECHANISM_STATUS] = 0,
[GPCMD_READ_CD] = CHECK_READY | READDATA, [GPCMD_READ_CD] = CHECK_READY,
[GPCMD_SEND_DVD_STRUCTURE] = CHECK_READY [GPCMD_SEND_DVD_STRUCTURE] = CHECK_READY
}; };
uint8_t mode_sense_pages[0x40] = uint8_t mode_sense_pages[0x40] =
@@ -677,14 +677,23 @@ static int SCSICDROM_TOC(uint8_t id, uint8_t *cdb)
return TocFormat; return TocFormat;
} }
void SCSICDROM_Command(uint8_t id, uint8_t *cdb) void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
{ {
if (cdrom->medium_changed()) if (lun > 0)
{ {
pclog("Media changed\n"); //pclog("Invalid LUN, only LUN 0 is supported\n");
SCSICDROM_Insert(); SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
SCSICallback[id]=50*SCSI_TIME;
return;
} }
if (cdrom->medium_changed())
{
//pclog("Media changed\n");
SCSICDROM_Insert();
}
if (!cdrom->ready() && SCSISense.UnitAttention) if (!cdrom->ready() && SCSISense.UnitAttention)
{ {
/* If the drive is not ready, there is no reason to keep the /* If the drive is not ready, there is no reason to keep the
@@ -697,7 +706,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
execution under it, error out and report the condition. */ execution under it, error out and report the condition. */
if (!(SCSICommandTable[cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention) if (!(SCSICommandTable[cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention)
{ {
pclog("UNIT ATTENTION: Command not allowed to pass through\n"); //pclog("UNIT ATTENTION: Command not allowed to pass through\n");
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSICallback[id]=50*SCSI_TIME; SCSICallback[id]=50*SCSI_TIME;
@@ -714,13 +723,15 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
/* Next it's time for NOT READY. */ /* Next it's time for NOT READY. */
if ((SCSICommandTable[cdb[0]] & CHECK_READY) && !cdrom->ready()) if ((SCSICommandTable[cdb[0]] & CHECK_READY) && !cdrom->ready())
{ {
pclog("Not ready\n"); //pclog("Not ready\n");
SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0);
SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSICallback[id]=50*SCSI_TIME; SCSICallback[id]=50*SCSI_TIME;
return; return;
} }
SCSICallback[id] = 0;
prev_status = cd_status; prev_status = cd_status;
cd_status = cdrom->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))) if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED)))
@@ -779,12 +790,12 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
if (SectorLBA > (cdrom->size() - 1)) if (SectorLBA > (cdrom->size() - 1))
{ {
pclog("Trying to read beyond the end of disc\n"); //pclog("Trying to read beyond the end of disc\n");
SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
SCSICallback[id]=50*SCSI_TIME; SCSICallback[id]=50*SCSI_TIME;
break; break;
} }
if (!SectorLen) if (!SectorLen)
{ {
@@ -1137,7 +1148,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
if (SectorLBA > (cdrom->size() - 1)) if (SectorLBA > (cdrom->size() - 1))
{ {
pclog("Trying to read beyond the end of disc\n"); //pclog("Trying to read beyond the end of disc\n");
SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
if (SCSISense.UnitAttention) if (SCSISense.UnitAttention)
@@ -1176,11 +1187,11 @@ void SCSICDROM_Command(uint8_t id, uint8_t *cdb)
break; break;
// case GPCMD_SEND_DVD_STRUCTURE: // case GPCMD_SEND_DVD_STRUCTURE:
default: default:
SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
SCSICallback[id]=50*SCSI_TIME; SCSICallback[id]=50*SCSI_TIME;
break; break;
} }
} }
@@ -1201,7 +1212,7 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
int ret = 0; int ret = 0;
msf = cdb[1] & 2; msf = cdb[1] & 2;
switch (cdb[0]) switch (cdb[0])
{ {
case GPCMD_REQUEST_SENSE: case GPCMD_REQUEST_SENSE:
@@ -1257,7 +1268,7 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
case GPCMD_READ_6: case GPCMD_READ_6:
case GPCMD_READ_10: case GPCMD_READ_10:
case GPCMD_READ_12: case GPCMD_READ_12:
pclog("Total data length requested: %d\n", datalen); //pclog("Total data length requested: %d\n", datalen);
while (datalen > 0) while (datalen > 0)
{ {
read_length = cdrom_read_data(data); //Fill the buffer the data it needs read_length = cdrom_read_data(data); //Fill the buffer the data it needs
@@ -1274,7 +1285,7 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
data += read_length; data += read_length;
} }
pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * 2048); //pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * 2048);
SectorLBA++; SectorLBA++;
SectorLen--; SectorLen--;
@@ -1284,7 +1295,7 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
break; break;
} }
} }
break; return;
case GPCMD_INQUIRY: case GPCMD_INQUIRY:
if (cdb[1] & 1) if (cdb[1] & 1)
@@ -1371,7 +1382,7 @@ SCSIOut:
SCSIDevices[id].CmdBuffer[1] = (datalen - 2)&255; SCSIDevices[id].CmdBuffer[1] = (datalen - 2)&255;
SCSIDevices[id].CmdBuffer[2] = 3; /*120mm data CD-ROM*/ SCSIDevices[id].CmdBuffer[2] = 3; /*120mm data CD-ROM*/
} }
break; return;
case GPCMD_READ_CDROM_CAPACITY: case GPCMD_READ_CDROM_CAPACITY:
if (cdrom->read_capacity) if (cdrom->read_capacity)
@@ -1388,7 +1399,7 @@ SCSIOut:
SCSIDevices[id].CmdBuffer[3] = Size & 0xff; SCSIDevices[id].CmdBuffer[3] = Size & 0xff;
SCSIDevices[id].CmdBuffer[6] = 8; /* 2048 = 0x0800 */ SCSIDevices[id].CmdBuffer[6] = 8; /* 2048 = 0x0800 */
} }
pclog("Sector size %04X\n", Size); //pclog("Sector size %i\n", Size);
break; break;
case GPCMD_READ_SUBCHANNEL: case GPCMD_READ_SUBCHANNEL:
@@ -1417,7 +1428,7 @@ SCSIOut:
datalen = cdrom->readtoc_raw(SCSIDevices[id].CmdBuffer, msf, datalen); datalen = cdrom->readtoc_raw(SCSIDevices[id].CmdBuffer, msf, datalen);
break; break;
} }
break; return;
case GPCMD_READ_HEADER: case GPCMD_READ_HEADER:
if (cdrom->read_header) if (cdrom->read_header)
@@ -1443,7 +1454,7 @@ SCSIOut:
SCSIDevices[id].CmdBuffer[0]=1; /*2048 bytes user data*/ SCSIDevices[id].CmdBuffer[0]=1; /*2048 bytes user data*/
SCSIDevices[id].CmdBuffer[1]=SCSIDevices[id].CmdBuffer[2]=SCSIDevices[id].CmdBuffer[3]=0; SCSIDevices[id].CmdBuffer[1]=SCSIDevices[id].CmdBuffer[2]=SCSIDevices[id].CmdBuffer[3]=0;
} }
break; return;
case GPCMD_GET_CONFIGURATION: case GPCMD_GET_CONFIGURATION:
Index = 0; Index = 0;
@@ -1670,7 +1681,7 @@ SCSIOut:
case GPCMD_READ_CD_MSF: case GPCMD_READ_CD_MSF:
case GPCMD_READ_CD: case GPCMD_READ_CD:
pclog("Total data length requested: %d\n", datalen); //pclog("Total data length requested: %d\n", datalen);
while (datalen > 0) while (datalen > 0)
{ {
read_length = cdrom_read_data(data); //Fill the buffer the data it needs read_length = cdrom_read_data(data); //Fill the buffer the data it needs
@@ -1687,7 +1698,7 @@ SCSIOut:
data += read_length; data += read_length;
} }
pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * cdrom_sector_size); //pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * cdrom_sector_size);
SectorLBA++; SectorLBA++;
SectorLen--; SectorLen--;
@@ -1697,7 +1708,7 @@ SCSIOut:
break; break;
} }
} }
break; return;
case GPCMD_MECHANISM_STATUS: case GPCMD_MECHANISM_STATUS:
SCSIDevices[id].CmdBuffer[0] = 0; SCSIDevices[id].CmdBuffer[0] = 0;