IDE dword reads and writes reverted to original operation, fixes the last hard disk problems;

ATAPI CD-ROM word reads no longer incorrectly discard the upper 16 bits, fixes the CD-ROM problems;
Significantly rewrote parts of the AHA-154x and BusLogic emulation, NT 3.1 RTM and MS-DOS drivers now works correctly;
The function in cdrom.c to read data blocks from the disc now correctly advances the position of the sector to read in non-passthrough mode, fixes multiblock reads from directly mounted ISO's;
Both ATAPI and SCSI now always check for Unit Attention and Not Ready on command execution.
This commit is contained in:
OBattler
2017-01-20 23:53:19 +01:00
parent b613873ff3
commit 3f612ab71a
9 changed files with 551 additions and 376 deletions

View File

@@ -306,7 +306,6 @@ typedef struct __attribute__((packed)) Mailbox32_t
} u; } u;
} Mailbox32_t; } Mailbox32_t;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// CCB - Buslogic SCSI Command Control Block // CCB - Buslogic SCSI Command Control Block
@@ -511,6 +510,10 @@ typedef struct __attribute__((packed)) Buslogic_t
int DmaChannel; int DmaChannel;
int IrqEnabled; int IrqEnabled;
int Mbx24bit; int Mbx24bit;
int MailboxOutInterrupts;
int MbiActive[256];
int DoScan;
int PendingInterrupt;
} Buslogic_t; } Buslogic_t;
int scsi_model = 1; int scsi_model = 1;
@@ -518,7 +521,9 @@ int scsi_base = 0x330;
int scsi_dma = 6; int scsi_dma = 6;
int scsi_irq = 11; int scsi_irq = 11;
int buslogic_do_log = 0; int buslogic_do_log = 1;
int BuslogicCallback = 0;
static void BuslogicStartMailbox(Buslogic_t *Buslogic); static void BuslogicStartMailbox(Buslogic_t *Buslogic);
@@ -538,9 +543,20 @@ void BuslogicLog(const char *format, ...)
static void BuslogicClearInterrupt(Buslogic_t *Buslogic) static void BuslogicClearInterrupt(Buslogic_t *Buslogic)
{ {
BuslogicLog("Buslogic: Clearing Interrupt 0x%02X\n", Buslogic->Interrupt); BuslogicLog("Buslogic: Lowering Interrupt 0x%02X\n", Buslogic->Interrupt);
Buslogic->Interrupt = 0; Buslogic->Interrupt = 0;
BuslogicLog("Lowering IRQ %i\n", Buslogic->Irq);
picintc(1 << Buslogic->Irq); picintc(1 << Buslogic->Irq);
if (Buslogic->PendingInterrupt)
{
Buslogic->Interrupt = Buslogic->PendingInterrupt;
BuslogicLog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", Buslogic->Interrupt);
if (Buslogic->MailboxOutInterrupts || !(Buslogic->Interrupt & INTR_MBOA))
{
if (Buslogic->IrqEnabled) picint(1 << Buslogic->Irq);
}
Buslogic->PendingInterrupt = 0;
}
} }
static void BuslogicLocalRam(Buslogic_t *Buslogic) static void BuslogicLocalRam(Buslogic_t *Buslogic)
@@ -568,6 +584,7 @@ static void BuslogicLocalRam(Buslogic_t *Buslogic)
static void BuslogicReset(Buslogic_t *Buslogic) static void BuslogicReset(Buslogic_t *Buslogic)
{ {
BuslogicCallback = 0;
Buslogic->Status = STAT_IDLE | STAT_INIT; Buslogic->Status = STAT_IDLE | STAT_INIT;
Buslogic->Geometry = 0x80; Buslogic->Geometry = 0x80;
Buslogic->Command = 0xFF; Buslogic->Command = 0xFF;
@@ -578,6 +595,9 @@ static void BuslogicReset(Buslogic_t *Buslogic)
Buslogic->ExtendedLUNCCBFormat = 0; Buslogic->ExtendedLUNCCBFormat = 0;
Buslogic->MailboxOutPosCur = 0; Buslogic->MailboxOutPosCur = 0;
Buslogic->MailboxInPosCur = 0; Buslogic->MailboxInPosCur = 0;
Buslogic->MailboxOutInterrupts = 0;
Buslogic->DoScan = 0;
Buslogic->PendingInterrupt = 0;
BuslogicClearInterrupt(Buslogic); BuslogicClearInterrupt(Buslogic);
@@ -596,32 +616,94 @@ static void BuslogicResetControl(Buslogic_t *Buslogic, uint8_t Reset)
static void BuslogicCommandComplete(Buslogic_t *Buslogic) static void BuslogicCommandComplete(Buslogic_t *Buslogic)
{ {
Buslogic->Status |= STAT_IDLE;
Buslogic->DataReply = 0; Buslogic->DataReply = 0;
Buslogic->Status |= STAT_IDLE;
if (Buslogic->Command != 0x02) if (Buslogic->Command != 0x02)
{ {
Buslogic->Status &= ~STAT_DFULL; Buslogic->Status &= ~STAT_DFULL;
Buslogic->Interrupt = INTR_ANY | INTR_HACC; Buslogic->Interrupt = (INTR_ANY | INTR_HACC);
picint(1 << Buslogic->Irq); BuslogicLog("Raising IRQ %i\n", Buslogic->Irq);
if (Buslogic->IrqEnabled) picint(1 << Buslogic->Irq);
} }
Buslogic->Command = 0xFF; Buslogic->Command = 0xFF;
Buslogic->CmdParam = 0; Buslogic->CmdParam = 0;
} }
static uint32_t BuslogicMailboxInRead(Buslogic_t *Buslogic, uint8_t *CompletionCode)
{
Mailbox32_t TempMailbox32;
Mailbox_t TempMailboxIn;
uint32_t Incoming = 0;
Incoming = Buslogic->MailboxInAddr + (Buslogic->MailboxInPosCur * (Buslogic->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t)));
if (Buslogic->Mbx24bit)
{
DMAPageRead(Incoming, &TempMailboxIn, sizeof(Mailbox_t));
*CompletionCode = TempMailboxIn.CmdStatus;
}
else
{
DMAPageRead(Incoming, &TempMailbox32, sizeof(Mailbox32_t));
*CompletionCode = TempMailbox32.u.in.CompletionCode;
}
return Incoming;
}
static void BuslogicMailboxInAdvance(Buslogic_t *Buslogic)
{
Buslogic->MailboxInPosCur = (Buslogic->MailboxInPosCur + 1) % Buslogic->MailboxCount;
}
static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *CmdBlock, static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *CmdBlock,
uint8_t HostStatus, uint8_t TargetStatus, uint8_t MailboxCompletionCode) uint8_t HostStatus, uint8_t TargetStatus, uint8_t MailboxCompletionCode)
{ {
Mailbox32_t Mailbox32; Mailbox32_t Mailbox32;
Mailbox_t MailboxIn; Mailbox_t MailboxIn;
Mailbox32_t TempMailbox32;
Mailbox_t TempMailboxIn;
uint32_t Incoming = 0;
uint32_t i = 0;
uint8_t CompletionCode = 0;
Mailbox32.CCBPointer = CCBPointer; Mailbox32.CCBPointer = CCBPointer;
Mailbox32.u.in.HostStatus = HostStatus; Mailbox32.u.in.HostStatus = HostStatus;
Mailbox32.u.in.TargetStatus = TargetStatus; Mailbox32.u.in.TargetStatus = TargetStatus;
Mailbox32.u.in.CompletionCode = MailboxCompletionCode; Mailbox32.u.in.CompletionCode = MailboxCompletionCode;
uint32_t Incoming = Buslogic->MailboxInAddr + (Buslogic->MailboxInPosCur * (Buslogic->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); Incoming = 0;
if (!Buslogic->StrictRoundRobinMode)
{
uint8_t MailboxCur = Buslogic->MailboxInPosCur;
/* Search for a filled mailbox - stop if we have scanned all mailboxes. */
do
{
/* Fetch mailbox from guest memory. */
Incoming = BuslogicMailboxInRead(Buslogic, &CompletionCode);
/* Check the next mailbox. */
BuslogicMailboxInAdvance(Buslogic);
} while ((CompletionCode != MBI_FREE) && (MailboxCur != Buslogic->MailboxInPosCur));
}
else
{
Incoming = BuslogicMailboxInRead(Buslogic, &CompletionCode);
}
if (CompletionCode != MBI_FREE)
{
return;
}
if (MailboxCompletionCode != MBI_NOT_FOUND) if (MailboxCompletionCode != MBI_NOT_FOUND)
{ {
@@ -629,12 +711,16 @@ static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *C
CmdBlock->common.TargetStatus = TargetStatus; CmdBlock->common.TargetStatus = TargetStatus;
//Rewrite the CCB up to the CDB. //Rewrite the CCB up to the CDB.
if (CmdBlock->common.TargetStatus != 0x02) if ((CmdBlock->common.TargetStatus != 0x02) && (CCBPointer != 0))
{ {
BuslogicLog("CCB rewritten to the CDB (pointer %08X, length %i)\n", CCBPointer, offsetof(CCBC, Cdb)); BuslogicLog("CCB rewritten to the CDB (pointer %08X, length %i)\n", CCBPointer, offsetof(CCBC, Cdb));
DMAPageWrite(CCBPointer, CmdBlock, offsetof(CCBC, Cdb)); DMAPageWrite(CCBPointer, CmdBlock, offsetof(CCBC, Cdb));
} }
} }
else
{
BuslogicLog("Mailbox not found!\n");
}
BuslogicLog("Host Status 0x%02X, Target Status 0x%02X\n", HostStatus, TargetStatus); BuslogicLog("Host Status 0x%02X, Target Status 0x%02X\n", HostStatus, TargetStatus);
@@ -645,20 +731,36 @@ static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *C
BuslogicLog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer)); BuslogicLog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer));
DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t)); DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t));
BuslogicLog("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming);
} }
else else
{ {
BuslogicLog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer); BuslogicLog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer);
if (Incoming != 0)
{
DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t)); DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t));
BuslogicLog("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming);
}
} }
Buslogic->MailboxInPosCur++; /* Advance to the next mailbox. */
if (Buslogic->MailboxInPosCur > Buslogic->MailboxCount) if (Buslogic->StrictRoundRobinMode)
Buslogic->MailboxInPosCur = 0; {
BuslogicMailboxInAdvance(Buslogic);
}
if (Buslogic->Interrupt & INTR_HACC)
{
BuslogicLog("Pending IRQ\n");
Buslogic->PendingInterrupt = INTR_MBIF | INTR_ANY;
}
else
{
Buslogic->Interrupt = INTR_MBIF | INTR_ANY; Buslogic->Interrupt = INTR_MBIF | INTR_ANY;
picint(1 << Buslogic->Irq); BuslogicLog("Raising IRQ %i\n", Buslogic->Irq);
if (Buslogic->IrqEnabled) picint(1 << Buslogic->Irq);
}
} }
static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG) static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG)
@@ -688,6 +790,8 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi
uint32_t sg_buffer_pos = 0; uint32_t sg_buffer_pos = 0;
uint32_t DataPointer, DataLength; uint32_t DataPointer, DataLength;
uint32_t ScatterGatherEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32));
if (Is24bit) if (Is24bit)
{ {
DataPointer = ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataPointer); DataPointer = ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataPointer);
@@ -699,17 +803,9 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi
DataLength = BuslogicRequests->CmdBlock.new.DataLength; DataLength = BuslogicRequests->CmdBlock.new.DataLength;
} }
/* 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); BuslogicLog("Data Buffer write: length %d, pointer 0x%04X\n", DataLength, DataPointer);
if (DataLength && BuslogicRequests->CmdBlock.common.ControlByte != 0x03) if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && DataLength)
{ {
if (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || if (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND ||
BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)
@@ -717,7 +813,7 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi
uint32_t ScatterGatherRead; uint32_t ScatterGatherRead;
uint32_t ScatterEntry; uint32_t ScatterEntry;
SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS];
uint32_t ScatterGatherLeft = DataLength / (Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t ScatterGatherLeft = DataLength / ScatterGatherEntryLength;
uint32_t ScatterGatherAddrCurrent = DataPointer; uint32_t ScatterGatherAddrCurrent = DataPointer;
uint32_t DataToTransfer = 0; uint32_t DataToTransfer = 0;
@@ -734,11 +830,15 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi
{ {
uint32_t Address; uint32_t Address;
BuslogicLog("BusLogic S/G Write: ScatterEntry=%u\n", ScatterEntry);
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
DataToTransfer += ScatterGatherBuffer[ScatterEntry].Segment; DataToTransfer += ScatterGatherBuffer[ScatterEntry].Segment;
BuslogicLog("BusLogic S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer);
} }
ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); ScatterGatherAddrCurrent += ScatterGatherRead * ScatterGatherEntryLength;
} while (ScatterGatherLeft > 0); } while (ScatterGatherLeft > 0);
BuslogicLog("Data to transfer (S/G) %d\n", DataToTransfer); BuslogicLog("Data to transfer (S/G) %d\n", DataToTransfer);
@@ -749,7 +849,7 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi
//checking its length, so do this procedure for both no read/write commands. //checking its length, so do this procedure for both no read/write commands.
if (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT || BuslogicRequests->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)); ScatterGatherLeft = DataLength / ScatterGatherEntryLength;
ScatterGatherAddrCurrent = DataPointer; ScatterGatherAddrCurrent = DataPointer;
do do
@@ -765,9 +865,13 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi
{ {
uint32_t Address; uint32_t Address;
BuslogicLog("BusLogic S/G Write: ScatterEntry=%u\n", ScatterEntry);
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment;
BuslogicLog("BusLogic S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer);
DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer);
sg_buffer_pos += DataToTransfer; sg_buffer_pos += DataToTransfer;
} }
@@ -819,42 +923,40 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
DataLength = BuslogicRequests->CmdBlock.new.DataLength; DataLength = BuslogicRequests->CmdBlock.new.DataLength;
} }
if (DataLength > SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength) /* if (DataLength > SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength)
{ {
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)) 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); 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) if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)
DataLength = 0; */ {
DataLength = 0;
}
BuslogicLog("Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); BuslogicLog("Data Buffer read: length %d, pointer 0x%04X\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 read/write commands. //checking its length, so do this procedure for both read/write commands.
if (DataLength > 0 && (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN || if ((DataLength > 0) &&
BuslogicRequests->CmdBlock.common.ControlByte == 0x00) && BuslogicRequests->CmdBlock.common.ControlByte != 0x03) ((BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) ||
(BuslogicRequests->CmdBlock.common.ControlByte == 0x00)))
{ {
if (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || if ((BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) ||
BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES))
{ {
uint32_t ScatterGatherRead; uint32_t ScatterGatherRead;
uint32_t ScatterEntry; uint32_t ScatterEntry;
SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS];
uint32_t ScatterGatherReqSize = (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t ScatterGatherEntrySize = (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32));
uint32_t ScatterGatherLeft = DataLength / ScatterGatherReqSize; uint32_t ScatterGatherLeft = DataLength / ScatterGatherEntrySize;
uint32_t ScatterGatherLength = (ScatterGatherLeft * ScatterGatherReqSize); // uint32_t ScatterGatherLength = (ScatterGatherLeft * ScatterGatherEntrySize);
uint32_t ScatterGatherAddrCurrent = DataPointer; uint32_t ScatterGatherAddrCurrent = DataPointer;
if (DataLength > ScatterGatherLength)
{
ScatterGatherLeft++;
}
do do
{ {
ScatterGatherRead = (ScatterGatherLeft < ELEMENTS(ScatterGatherBuffer)) ScatterGatherRead = (ScatterGatherLeft < ELEMENTS(ScatterGatherBuffer))
@@ -869,35 +971,56 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
uint32_t Address; uint32_t Address;
uint32_t DataToTransfer; uint32_t DataToTransfer;
BuslogicLog("BusLogic S/G: ScatterEntry=%u\n", ScatterEntry);
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment;
BuslogicLog("BusLogic S/G: Writing %i bytes at %08X\n", DataToTransfer, Address);
DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer); DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer);
sg_buffer_pos += DataToTransfer; sg_buffer_pos += DataToTransfer;
} }
ScatterGatherAddrCurrent += ScatterGatherRead * (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); ScatterGatherAddrCurrent += (ScatterGatherRead * ScatterGatherEntrySize);
} while (ScatterGatherLeft > 0); } while (ScatterGatherLeft > 0);
} }
else if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || else if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND ||
BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES)
{ {
uint32_t Address = DataPointer; uint32_t Address = DataPointer;
if (DataLength > 0)
{ BuslogicLog("BusLogic DMA: Writing %i bytes at %08X\n", DataLength, Address);
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); DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].CmdBuffer, DataLength);
} }
} }
if ((BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES))
{
uint32_t Residual;
/* Should be 0 when scatter/gather? */
if (DataLength >= SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength)
{
Residual = BuslogicGetDataLength(BuslogicRequests);
Residual -= SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength;
} }
else
{
Residual = 0;
} }
SCSIDevices[BuslogicRequests->TargetID][BuslogicRequests->LUN].InitLength = 0; if (BuslogicRequests->Is24bit)
{
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, Residual);
BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
}
else
{
BuslogicRequests->CmdBlock.new.DataLength = Residual;
BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
}
}
} }
uint8_t BuslogicRead(uint16_t Port, void *p) uint8_t BuslogicRead(uint16_t Port, void *p)
@@ -942,7 +1065,7 @@ uint8_t BuslogicRead(uint16_t Port, void *p)
break; break;
} }
BuslogicLog("Buslogic: Read Port 0x%02X, Returned Value %02X\n", Port, Temp); // BuslogicLog("Buslogic: Read Port 0x%02X, Returned Value %02X\n", Port, Temp);
return Temp; return Temp;
} }
@@ -980,7 +1103,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic_t *Buslogic = (Buslogic_t *)p; Buslogic_t *Buslogic = (Buslogic_t *)p;
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
BuslogicLog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); // BuslogicLog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val);
switch (Port & 3) switch (Port & 3)
{ {
@@ -999,16 +1122,9 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
break; break;
case 1: case 1:
if ((Val == 0x02) && (Buslogic->Command == 0xFF)) if (!(Buslogic->Status & STAT_IDLE) && (Buslogic->Command == 0xFF) && (Val != 0x02) && (Val != 0x05))
{ {
for (i = 0; i < CDROM_NUM; i++) break; /* Any command other than 02 and 05 can only be executed when the IDLE bit is set. */
{
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][cdrom_drives[i].scsi_device_lun] = 1;
}
}
break;
} }
if (Buslogic->Command == 0xFF) if (Buslogic->Command == 0xFF)
@@ -1021,6 +1137,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
switch (Buslogic->Command) switch (Buslogic->Command)
{ {
case 0x00: case 0x00:
case 0x02:
case 0x04: case 0x04:
case 0x0A: case 0x0A:
case 0x0B: case 0x0B:
@@ -1030,6 +1147,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->CmdParamLeft = 0; Buslogic->CmdParamLeft = 0;
break; break;
case 0x05:
case 0x07: case 0x07:
case 0x08: case 0x08:
case 0x09: case 0x09:
@@ -1066,6 +1184,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
break; break;
case 0x81: case 0x81:
BuslogicLog("Command 0x81 on %s\n", scsi_model ? "BusLogic" : "Adaptec");
Buslogic->CmdParamLeft = scsi_model ? sizeof(MailboxInitExtended_t) : 0; Buslogic->CmdParamLeft = scsi_model ? sizeof(MailboxInitExtended_t) : 0;
break; break;
@@ -1113,14 +1232,48 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
} }
break; break;
case 0x02:
if (Buslogic->Status & STAT_INIT)
{
Buslogic->Status |= STAT_INVCMD;
}
else
{
if (!BuslogicCallback)
{
BuslogicLog("SCSI started\n");
BuslogicCallback = 1;
}
else
{
BuslogicLog("SCSI reactivated\n");
}
Buslogic->DoScan = 1;
}
Buslogic->DataReplyLeft = 0;
break;
case 0x04: case 0x04:
Buslogic->DataBuf[0] = 0x41; Buslogic->DataBuf[0] = 0x41;
Buslogic->DataBuf[1] = scsi_model ? 0x41 : 0x30; Buslogic->DataBuf[1] = scsi_model ? 0x41 : 0x30;
Buslogic->DataBuf[2] = '5'; Buslogic->DataBuf[2] = scsi_model ? '5' : '3';
Buslogic->DataBuf[3] = '0'; Buslogic->DataBuf[3] = scsi_model ? '0' : '1';
Buslogic->DataReplyLeft = 4; Buslogic->DataReplyLeft = 4;
break; break;
case 0x05:
if (Buslogic->CmdBuf[0] <= 1)
{
Buslogic->MailboxOutInterrupts = Buslogic->CmdBuf[0];
BuslogicLog("Mailbox out interrupts: %s\n", Buslogic->MailboxOutInterrupts ? "ON" : "OFF");
}
else
{
Buslogic->Status |= STAT_INVCMD;
}
Buslogic->DataReplyLeft = 0;
break;
case 0x06: case 0x06:
Buslogic->DataReplyLeft = 0; Buslogic->DataReplyLeft = 0;
break; break;
@@ -1226,6 +1379,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Address.mid = Buslogic->CmdBuf[1]; Address.mid = Buslogic->CmdBuf[1];
Address.lo = Buslogic->CmdBuf[2]; Address.lo = Buslogic->CmdBuf[2];
FIFOBuf = ADDR_TO_U32(Address); FIFOBuf = ADDR_TO_U32(Address);
BuslogicLog("Buslogic FIFO: Writing 64 bytes at %08X\n", FIFOBuf);
DMAPageWrite(FIFOBuf, &Buslogic->LocalRam.u8View[64], 64); DMAPageWrite(FIFOBuf, &Buslogic->LocalRam.u8View[64], 64);
} }
break; break;
@@ -1265,6 +1419,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->IrqEnabled = 0; Buslogic->IrqEnabled = 0;
else else
Buslogic->IrqEnabled = 1; Buslogic->IrqEnabled = 1;
BuslogicLog("Lowering IRQ %i\n", Buslogic->Irq);
picintc(1 << Buslogic->Irq); picintc(1 << Buslogic->Irq);
break; break;
@@ -1408,6 +1563,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
} }
break; break;
default:
case 0x22: //undocumented case 0x22: //undocumented
case 0x28: //only for the Adaptec 154xC series case 0x28: //only for the Adaptec 154xC series
case 0x29: //only for the Adaptec 154xC series case 0x29: //only for the Adaptec 154xC series
@@ -1449,14 +1605,6 @@ static uint8_t BuslogicConvertSenseLength(uint8_t RequestSenseLength)
return RequestSenseLength; return RequestSenseLength;
} }
static void BuslogicSenseBufferAllocate(BuslogicRequests_t *BuslogicRequests)
{
uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength);
if (SenseLength)
BuslogicRequests->RequestSenseBuffer = (uint8_t *)malloc(SenseLength);
}
static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Copy) static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Copy)
{ {
uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength); uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength);
@@ -1481,56 +1629,31 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co
BuslogicLog("Request Sense address: %02X\n", SenseBufferAddress); BuslogicLog("Request Sense address: %02X\n", SenseBufferAddress);
if (SenseBufferAddress)
{
BuslogicLog("BuslogicSenseBufferFree(): Writing %i bytes at %08X\n", SenseLength, SenseBufferAddress);
DMAPageWrite(SenseBufferAddress, cdrom[cdrom_id].sense, SenseLength); DMAPageWrite(SenseBufferAddress, cdrom[cdrom_id].sense, SenseLength);
} }
//Free the sense buffer when needed. }
free(BuslogicRequests->RequestSenseBuffer);
} }
static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, Mailbox32_t *Mailbox32) static void BuslogicCDROMCommand(Buslogic_t *Buslogic, uint8_t Id, uint8_t Lun, uint8_t cdrom_id)
{ {
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
uint8_t Id, Lun;
uint8_t cdrom_id;
uint8_t cdrom_phase; uint8_t cdrom_phase;
uint32_t temp = 0; uint32_t temp = 0;
uint8_t temp_cdb[12]; uint8_t temp_cdb[12];
//Fetch data from the Command Control Block.
DMAPageRead(CCBPointer, &BuslogicRequests->CmdBlock, sizeof(CCB32));
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;
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))
{
cdrom_id = scsi_cdrom_drives[Id][Lun];
BuslogicLog("SCSI Target ID %i detected and working\n", Id);
BuslogicRequests->CCBPointer = CCBPointer;
BuslogicRequests->Is24bit = Buslogic->Mbx24bit;
if (Mailbox32->u.out.ActionCode == MBO_START)
{
BuslogicSenseBufferAllocate(BuslogicRequests);
BuslogicDataBufferAllocate(BuslogicRequests, BuslogicRequests->Is24bit);
uint32_t i; uint32_t i;
BuslogicLog("CD-ROM command being executed on: SCSI ID %i, SCSI LUN %i, CD-ROM %i\n", Id, Lun, cdrom_id);
BuslogicLog("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++)
{
BuslogicLog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]); BuslogicLog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]);
}
memset(temp_cdb, 0, cdrom[cdrom_id].cdb_len); memset(temp_cdb, 0, cdrom[cdrom_id].cdb_len);
if (BuslogicRequests->CmdBlock.common.CdbLength <= cdrom[cdrom_id].cdb_len) if (BuslogicRequests->CmdBlock.common.CdbLength <= cdrom[cdrom_id].cdb_len)
@@ -1542,36 +1665,13 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer,
memcpy(temp_cdb, BuslogicRequests->CmdBlock.common.Cdb, cdrom[cdrom_id].cdb_len); memcpy(temp_cdb, BuslogicRequests->CmdBlock.common.Cdb, cdrom[cdrom_id].cdb_len);
} }
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. */
if (BuslogicRequests->CmdBlock.common.CdbLength != 12) 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. */ 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);
BuslogicLog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode);
//This not ready/unit attention stuff below is only for the Buslogic!
//The Adaptec one is in scsi_cdrom.c.
if (!cdrom_drives[cdrom_id].check_on_execution)
{
if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND))
{
if (!cdrom_pre_execution_check(cdrom_id, temp_cdb))
{
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
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);
return;
}
}
}
memset(SCSIDevices[Id][Lun].CmdBuffer, 0, 390144); memset(SCSIDevices[Id][Lun].CmdBuffer, 0, 390144);
//Finally, execute the SCSI command immediately and get the transfer length. //Finally, execute the SCSI command immediately and get the transfer length.
@@ -1602,76 +1702,91 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer,
/* Error (Check Condition) - call the phase callback to complete the command. */ /* Error (Check Condition) - call the phase callback to complete the command. */
cdrom_phase_callback(cdrom_id); cdrom_phase_callback(cdrom_id);
} }
SCSICallback[Id][Lun] = cdrom[cdrom_id].callback;
if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (SCSIDevices[Id][Lun].InitLength != 0)) BuslogicLog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", cdrom[cdrom_id].sense[2], cdrom[cdrom_id].sense[12], cdrom[cdrom_id].sense[13]);
{
BuslogicDataBufferFree(BuslogicRequests);
} }
if (BuslogicRequests->RequestSenseBuffer) static int BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK)); {
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
uint8_t Id, Lun;
uint8_t cdrom_id;
uint8_t cdrom_phase;
uint8_t last_id = scsi_model ? 15 : 7;
//Fetch data from the Command Control Block.
DMAPageRead(CCBPointer, &BuslogicRequests->CmdBlock, sizeof(CCB32));
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;
if ((Id > last_id) || (Lun > 7))
{
BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR);
return 1;
}
BuslogicLog("Scanning SCSI Target ID %i\n", Id);
cdrom_id = scsi_cdrom_drives[Id][Lun];
BuslogicRequests->CCBPointer = CCBPointer;
BuslogicRequests->Is24bit = Buslogic->Mbx24bit;
SCSIStatus = SCSI_STATUS_OK;
BuslogicDataBufferAllocate(BuslogicRequests, BuslogicRequests->Is24bit);
if (!buslogic_scsi_drive_is_cdrom(Id, Lun))
{
BuslogicLog("SCSI Target ID %i and LUN %i have no device attached\n", Id, Lun);
BuslogicDataBufferFree(BuslogicRequests);
BuslogicSenseBufferFree(BuslogicRequests, 0);
BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
} }
else else
{ {
BuslogicLog("Mailbox32->u.out.ActionCode = %02X\n", Mailbox32->u.out.ActionCode); BuslogicLog("SCSI Target ID %i and LUN %i detected and working\n", Id, Lun);
SCSICallback[Id][Lun] = 50 * SCSI_TIME;
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 (BuslogicRequests->CmdBlock.common.ControlByte > 0x03)
{
BuslogicLog("Invalid control byte: %02X\n", BuslogicRequests->CmdBlock.common.ControlByte);
} }
BuslogicCDROMCommand(Buslogic, Id, Lun, cdrom_id);
BuslogicDataBufferFree(BuslogicRequests);
BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK));
BuslogicLog("Request complete\n"); BuslogicLog("Request complete\n");
if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES)
{
temp = BuslogicGetDataLength(BuslogicRequests);
temp -= SCSIDevices[Id][Lun].InitLength;
if (BuslogicRequests->Is24bit)
{
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, temp);
BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
}
else
{
BuslogicRequests->CmdBlock.new.DataLength = temp;
BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
}
}
else if (BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)
{
if (BuslogicRequests->Is24bit)
{
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, 0);
BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
}
else
{
BuslogicRequests->CmdBlock.new.DataLength = 0;
BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
}
}
if (SCSIStatus == SCSI_STATUS_OK) if (SCSIStatus == SCSI_STATUS_OK)
{ {
BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS);
MBI_SUCCESS);
} }
else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION)
{ {
BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR);
MBI_ERROR);
}
}
else
{
BuslogicMailboxIn(Buslogic, CCBPointer, &BuslogicRequests->CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
// if (Mailbox32->u.out.ActionCode == MBO_START && Lun == 0)
if (Mailbox32->u.out.ActionCode == MBO_START && Lun <= 7)
BuslogicStartMailbox(Buslogic);
} }
} }
static void BuslogicSCSIRequestAbort(Buslogic_t *Buslogic, uint32_t CCBPointer) return 1;
}
static int BuslogicSCSIRequestAbort(Buslogic_t *Buslogic, uint32_t CCBPointer)
{ {
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
CCBU CmdBlock; CCBU CmdBlock;
@@ -1681,6 +1796,8 @@ static void BuslogicSCSIRequestAbort(Buslogic_t *Buslogic, uint32_t CCBPointer)
//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.
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND);
return 1;
} }
static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32) static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32)
@@ -1707,70 +1824,127 @@ static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32)
return Outgoing; return Outgoing;
} }
static void BuslogicStartMailbox(Buslogic_t *Buslogic) static void BuslogicMailboxOutAdvance(Buslogic_t *Buslogic)
{
Buslogic->MailboxOutPosCur = (Buslogic->MailboxOutPosCur + 1) % Buslogic->MailboxCount;
}
static int BuslogicProcessMailbox(Buslogic_t *Buslogic)
{ {
Mailbox32_t Mailbox32; Mailbox32_t Mailbox32;
Mailbox_t MailboxOut; Mailbox_t MailboxOut;
uint32_t Outgoing; uint32_t Outgoing;
uint8_t MailboxOutCur = Buslogic->MailboxOutPosCur; uint8_t CmdStatus = MBO_FREE;
uint32_t CodeOffset = 0;
int old_irq_enabled = Buslogic->IrqEnabled;
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
int ret = 0;
CodeOffset = Buslogic->Mbx24bit ? offsetof(Mailbox_t, CmdStatus) : offsetof(Mailbox32_t, u.out.ActionCode);
if (!Buslogic->StrictRoundRobinMode)
{
uint8_t MailboxCur = Buslogic->MailboxOutPosCur;
/* Search for a filled mailbox - stop if we have scanned all mailboxes. */
do do
{ {
/* Fetch mailbox from guest memory. */
Outgoing = BuslogicMailboxOut(Buslogic, &Mailbox32); Outgoing = BuslogicMailboxOut(Buslogic, &Mailbox32);
Buslogic->MailboxOutPosCur = (Buslogic->MailboxOutPosCur + 1) % Buslogic->MailboxCount;
} while (Mailbox32.u.out.ActionCode == MBO_FREE && MailboxOutCur != Buslogic->MailboxOutPosCur);
uint8_t CmdStatus = MBO_FREE; /* Check the next mailbox. */
uint32_t CodeOffset = Buslogic->Mbx24bit ? offsetof(Mailbox_t, CmdStatus) : offsetof(Mailbox32_t, u.out.ActionCode); BuslogicMailboxOutAdvance(Buslogic);
} while ((Mailbox32.u.out.ActionCode == MBO_FREE) && (MailboxCur != Buslogic->MailboxOutPosCur));
}
else
{
Outgoing = BuslogicMailboxOut(Buslogic, &Mailbox32);
}
/* Check if the mailbox is actually loaded. */
if (Mailbox32.u.out.ActionCode == MBO_FREE)
{
BuslogicLog("No loaded mailbox left\n");
if (Buslogic->MailboxOutInterrupts)
{
if (Buslogic->Interrupt & INTR_HACC)
{
BuslogicLog("Pending IRQ\n");
Buslogic->PendingInterrupt = INTR_MBOA | INTR_ANY;
}
else
{
BuslogicLog("Raising IRQ %i\n", Buslogic->Irq);
Buslogic->Interrupt = INTR_MBOA | INTR_ANY;
if (Buslogic->IrqEnabled) picint(1 << Buslogic->Irq);
}
}
return 0;
}
/* We got the mailbox, mark it as free in the guest. */
if (Mailbox32.u.out.ActionCode != MBO_FREE)
{
BuslogicLog("BuslogicStartMailbox(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus)); DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus));
}
if (Mailbox32.u.out.ActionCode == MBO_START || Mailbox32.u.out.ActionCode == MBO_FREE) if ((Mailbox32.u.out.ActionCode == MBO_START) || (Mailbox32.u.out.ActionCode == MBO_FREE))
{ {
BuslogicLog("Start Mailbox Command\n"); BuslogicLog("Start Mailbox Command\n");
BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer, &Mailbox32); ret = BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer, &Mailbox32);
} }
else if (Mailbox32.u.out.ActionCode == MBO_ABORT) else if (Mailbox32.u.out.ActionCode == MBO_ABORT)
{ {
BuslogicLog("Abort Mailbox Command\n"); BuslogicLog("Abort Mailbox Command\n");
BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer); ret = BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer);
} }
else
{
BuslogicLog("Invalid action code: %02X\n", Mailbox32.u.out.ActionCode);
ret = 0;
} }
void BuslogicCommandCallback(int id, int lun, void *p) /* Advance to the next mailbox. */
if (Buslogic->StrictRoundRobinMode)
{
BuslogicMailboxOutAdvance(Buslogic);
}
return ret;
}
void BuslogicCommandCallback(void *p)
{ {
Buslogic_t *Buslogic = (Buslogic_t *)p; Buslogic_t *Buslogic = (Buslogic_t *)p;
SCSICallback[id][lun] = 0; int ret = 0;
int i = 0;
// BuslogicLog("BusLogic Callback!\n");
if (Buslogic->MailboxCount) if (Buslogic->MailboxCount)
{ {
BuslogicStartMailbox(Buslogic); ret = BuslogicProcessMailbox(Buslogic);
}
}
void BuslogicCommandCallback0(void *p) BuslogicCallback += 50 * SCSI_TIME;
{
BuslogicCommandCallback(cdrom_drives[0].scsi_device_id, cdrom_drives[0].scsi_device_lun, p);
} }
else
void BuslogicCommandCallback1(void *p)
{ {
BuslogicCommandCallback(cdrom_drives[1].scsi_device_id, cdrom_drives[1].scsi_device_lun, p); fatal("Callback active with mailbox count 0!\n");
} }
void BuslogicCommandCallback2(void *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, cdrom_drives[3].scsi_device_lun, p);
} }
void *BuslogicInit() void *BuslogicInit()
{ {
int i = 0;
Buslogic_t *Buslogic = malloc(sizeof(Buslogic_t)); Buslogic_t *Buslogic = malloc(sizeof(Buslogic_t));
memset(Buslogic, 0, sizeof(Buslogic_t)); memset(Buslogic, 0, sizeof(Buslogic_t));
@@ -1782,27 +1956,16 @@ void *BuslogicInit()
BuslogicLog("Building CD-ROM map...\n"); BuslogicLog("Building CD-ROM map...\n");
build_scsi_cdrom_map(); build_scsi_cdrom_map();
if (buslogic_scsi_drive_is_cdrom(cdrom_drives[0].scsi_device_id, cdrom_drives[0].scsi_device_lun)) for (i = 0; i < CDROM_NUM; i++)
{ {
SCSIDevices[cdrom_drives[0].scsi_device_id][cdrom_drives[0].scsi_device_lun].LunType == SCSI_CDROM; if (buslogic_scsi_drive_is_cdrom(cdrom_drives[i].scsi_device_id, cdrom_drives[i].scsi_device_lun))
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, cdrom_drives[1].scsi_device_lun))
{ {
SCSIDevices[cdrom_drives[1].scsi_device_id][cdrom_drives[1].scsi_device_lun].LunType == SCSI_CDROM; SCSIDevices[cdrom_drives[i].scsi_device_id][cdrom_drives[i].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, cdrom_drives[2].scsi_device_lun))
{
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, cdrom_drives[3].scsi_device_lun))
{
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);
} }
timer_add(BuslogicCommandCallback, &BuslogicCallback, &BuslogicCallback, Buslogic);
BuslogicLog("Buslogic on port 0x%04X\n", scsi_base); BuslogicLog("Buslogic on port 0x%04X\n", scsi_base);
BuslogicResetControl(Buslogic, CTRL_HRST); BuslogicResetControl(Buslogic, CTRL_HRST);

View File

@@ -779,6 +779,7 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
int transferred_blocks = 0; int transferred_blocks = 0;
int temp_len = 0; int temp_len = 0;
int chunk = 0;
if (cdb[0] == 0x43) if (cdb[0] == 0x43)
{ {
@@ -791,13 +792,14 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
memcpy(cdb, in_cdb, 12); memcpy(cdb, in_cdb, 12);
temp_block_length = ioctl_get_block_length(id, cdb, cdrom[id].requested_blocks, 0); temp_block_length = ioctl_get_block_length(id, cdb, cdrom[id].requested_blocks, 0);
*len = 0;
if (temp_block_length != -1) if (temp_block_length != -1)
{ {
if (temp_block_length > 65534) 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; block_length = temp_block_length / cdrom[id].requested_blocks;
blocks_at_once = 32768 / block_length; blocks_at_once = 32768 / block_length;
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): Expected transfer length %i is bigger than 65534, splitting the transfer into chunks of %i blocks...\n", id, temp_block_length, blocks_at_once);
buffer_pos = 0; buffer_pos = 0;
temp_pos = cdrom[id].sector_pos; temp_pos = cdrom[id].sector_pos;
@@ -806,12 +808,15 @@ static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t
temp_len = 0; temp_len = 0;
split_block_read_iterate: split_block_read_iterate:
if (temp_requested_blocks < blocks_at_once) chunk = (cdrom[id].requested_blocks - transferred_blocks);
if (chunk < blocks_at_once)
{ {
cdrom_ioctl[id].actual_requested_blocks = temp_requested_blocks; cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): The remaining chunk (%i blocks) is less than a complete split block\n", id, chunk);
cdrom_ioctl[id].actual_requested_blocks = chunk;
} }
else else
{ {
cdrom_ioctl_log("CD-ROM %i: ioctl_pass_through(): The remaining chunk (%i blocks) is more or equal than a complete split block\n", id, chunk);
cdrom_ioctl[id].actual_requested_blocks = blocks_at_once; 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_ioctl_log("CD-ROM %i: ioctl_pass_through(): Transferring %i blocks...\n", id, cdrom_ioctl[id].actual_requested_blocks);
@@ -819,8 +824,9 @@ split_block_read_iterate:
ret = SCSICommand(id, cdb, buf + buffer_pos, &temp_len, 0); ret = SCSICommand(id, cdb, buf + buffer_pos, &temp_len, 0);
*len += temp_len; *len += temp_len;
transferred_blocks += cdrom_ioctl[id].actual_requested_blocks; transferred_blocks += cdrom_ioctl[id].actual_requested_blocks;
if (ret && (transferred_blocks >= cdrom[id].requested_blocks)) if (ret && (transferred_blocks < cdrom[id].requested_blocks))
{ {
/* Return value was successful and there are still more blocks left to transfer. */
temp_pos += cdrom_ioctl[id].actual_requested_blocks; temp_pos += cdrom_ioctl[id].actual_requested_blocks;
buffer_pos += (cdrom_ioctl[id].actual_requested_blocks * block_length); buffer_pos += (cdrom_ioctl[id].actual_requested_blocks * block_length);
goto split_block_read_iterate; goto split_block_read_iterate;

View File

@@ -3,6 +3,8 @@
*/ */
/*ISO CD-ROM support*/ /*ISO CD-ROM support*/
#include <stdarg.h>
#include "ibm.h" #include "ibm.h"
#include "cdrom.h" #include "cdrom.h"
#include "cdrom-iso.h" #include "cdrom-iso.h"
@@ -10,12 +12,12 @@
static CDROM iso_cdrom; static CDROM iso_cdrom;
int cdrom_iso_do_log = 1; int cdrom_iso_do_log = 0;
void cdrom_iso_log(const char *format, ...) void cdrom_iso_log(const char *format, ...)
{ {
#ifdef ENABLE_CDROM_ISO_LOG #ifdef ENABLE_CDROM_ISO_LOG
if (cdrom_do_log) if (cdrom_iso_do_log)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
@@ -273,12 +275,14 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
if (cdrom_sector_flags & 0x80) /* Sync */ if (cdrom_sector_flags & 0x80) /* Sync */
{ {
cdrom_iso_log("CD-ROM %i: Sync\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12); memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12);
cdrom_sector_size += 12; cdrom_sector_size += 12;
temp_b += 12; temp_b += 12;
} }
if (cdrom_sector_flags & 0x20) /* Header */ if (cdrom_sector_flags & 0x20) /* Header */
{ {
cdrom_iso_log("CD-ROM %i: Header\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4); memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4);
cdrom_sector_size += 4; cdrom_sector_size += 4;
temp_b += 4; temp_b += 4;
@@ -289,6 +293,7 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
{ {
if (!(cdrom_sector_flags & 0x10)) /* No user data */ if (!(cdrom_sector_flags & 0x10)) /* No user data */
{ {
cdrom_iso_log("CD-ROM %i: Sub-header\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8); memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8);
cdrom_sector_size += 8; cdrom_sector_size += 8;
temp_b += 8; temp_b += 8;
@@ -296,12 +301,14 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
} }
if (cdrom_sector_flags & 0x10) /* User data */ if (cdrom_sector_flags & 0x10) /* User data */
{ {
cdrom_iso_log("CD-ROM %i: User data\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048); memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048);
cdrom_sector_size += 2048; cdrom_sector_size += 2048;
temp_b += 2048; temp_b += 2048;
} }
if (cdrom_sector_flags & 0x08) /* EDC/ECC */ if (cdrom_sector_flags & 0x08) /* EDC/ECC */
{ {
cdrom_iso_log("CD-ROM %i: EDC/ECC\n", id);
memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288); memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288);
cdrom_sector_size += 288; cdrom_sector_size += 288;
temp_b += 288; temp_b += 288;
@@ -312,34 +319,37 @@ static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf
if ((cdrom_sector_flags & 0x06) == 0x02) if ((cdrom_sector_flags & 0x06) == 0x02)
{ {
/* Add error flags. */ /* Add error flags. */
cdrom_iso_log("CD-ROM %i: Error flags\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 294); memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 294);
cdrom_sector_size += 294; cdrom_sector_size += 294;
} }
else if ((cdrom_sector_flags & 0x06) == 0x04) else if ((cdrom_sector_flags & 0x06) == 0x04)
{ {
/* Add error flags. */ /* Add error flags. */
cdrom_iso_log("CD-ROM %i: Full error flags\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296); memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296);
cdrom_sector_size += 296; cdrom_sector_size += 296;
} }
if ((cdrom_sector_flags & 0x700) == 0x100) if ((cdrom_sector_flags & 0x700) == 0x100)
{ {
cdrom_iso_log("CD-ROM %i: Raw subchannel data\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96); memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96);
cdrom_sector_size += 96; cdrom_sector_size += 96;
} }
else if ((cdrom_sector_flags & 0x700) == 0x200) else if ((cdrom_sector_flags & 0x700) == 0x200)
{ {
cdrom_iso_log("CD-ROM %i: Q subchannel data\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16); memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16);
cdrom_sector_size += 16; cdrom_sector_size += 16;
} }
else if ((cdrom_sector_flags & 0x700) == 0x400) else if ((cdrom_sector_flags & 0x700) == 0x400)
{ {
cdrom_iso_log("CD-ROM %i: R/W subchannel data\n", id);
memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96); memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96);
cdrom_sector_size += 96; cdrom_sector_size += 96;
} }
memcpy(buffer, b, cdrom_sector_size);
*len = cdrom_sector_size; *len = cdrom_sector_size;
return 1; return 1;

View File

@@ -330,12 +330,10 @@ void cdrom_init(int id, int cdb_len_setting, int bus_type)
if (!cdrom_drives[id].bus_type) if (!cdrom_drives[id].bus_type)
{ {
cdrom_set_signature(id); cdrom_set_signature(id);
cdrom_drives[id].check_on_execution = 1;
cdrom_drives[id].max_blocks_at_once = 1; cdrom_drives[id].max_blocks_at_once = 1;
} }
else else
{ {
cdrom_drives[id].check_on_execution = scsi_model ? 0 : 1;
cdrom_drives[id].max_blocks_at_once = 85; cdrom_drives[id].max_blocks_at_once = 85;
} }
cdrom[id].status = READY_STAT | DSC_STAT; cdrom[id].status = READY_STAT | DSC_STAT;
@@ -880,13 +878,13 @@ static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int al
else else
{ {
if (cdrom_current_mode(id) == 2) if (cdrom_current_mode(id) == 2)
{
if (direction == 0)
{ {
if (cdrom_drives[id].bus_type) if (cdrom_drives[id].bus_type)
{ {
SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len; SCSIDevices[cdrom_drives[id].scsi_device_id][cdrom_drives[id].scsi_device_lun].InitLength = alloc_len;
} }
if (direction == 0)
{
cdrom_command_read_dma(id); cdrom_command_read_dma(id);
} }
else else
@@ -1121,6 +1119,8 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
int i = 0; int i = 0;
int temp_len = 0; int temp_len = 0;
int last_valid_data_pos = 0;
if (cdrom_drives[id].handler->pass_through) if (cdrom_drives[id].handler->pass_through)
{ {
cdsize = cdrom_drives[id].handler->size(id); cdsize = cdrom_drives[id].handler->size(id);
@@ -1156,7 +1156,9 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
for (i = 0; i < cdrom[id].requested_blocks; i++) for (i = 0; i < cdrom[id].requested_blocks; i++)
{ {
ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + cdrom[id].data_pos, cdrom[id].sector_pos, msf, type, flags, &temp_len); ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + cdrom[id].data_pos, cdrom[id].sector_pos + i, msf, type, flags, &temp_len);
last_valid_data_pos = cdrom[id].data_pos;
cdrom[id].data_pos += temp_len; cdrom[id].data_pos += temp_len;
cdrom[id].old_len += temp_len; cdrom[id].old_len += temp_len;
@@ -1170,7 +1172,7 @@ int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len)
} }
} }
cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]); cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[last_valid_data_pos + 0], cdbufferb[last_valid_data_pos + 1], cdbufferb[last_valid_data_pos + 2], cdbufferb[last_valid_data_pos + 3], cdbufferb[last_valid_data_pos + 4], cdbufferb[last_valid_data_pos + 5], cdbufferb[last_valid_data_pos + 6], cdbufferb[last_valid_data_pos + 7]);
} }
return 1; return 1;
@@ -1616,13 +1618,10 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
cdrom[id].sector_len = 0; cdrom[id].sector_len = 0;
/* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */
if (cdrom_drives[id].check_on_execution)
{
if (cdrom_pre_execution_check(id, cdb) == 0) if (cdrom_pre_execution_check(id, cdb) == 0)
{ {
return; return;
} }
}
cdrom[id].prev_status = cdrom[id].cd_status; cdrom[id].prev_status = cdrom[id].cd_status;
cdrom[id].cd_status = cdrom_drives[id].handler->status(id); cdrom[id].cd_status = cdrom_drives[id].handler->status(id);
@@ -2645,7 +2644,7 @@ int cdrom_mode_select_return(uint8_t id, int ret)
} }
} }
int cdrom_phase_callback(uint8_t id); void cdrom_phase_callback(uint8_t id);
int cdrom_read_from_ide_dma(uint8_t channel) int cdrom_read_from_ide_dma(uint8_t channel)
{ {
@@ -2799,58 +2798,72 @@ int cdrom_write_to_dma(uint8_t id)
return 1; return 1;
} }
void cdrom_irq_raise(uint8_t id)
{
if (!cdrom_drives[id].bus_type)
{
ide_irq_raise(&(ide_drives[cdrom_drives[id].ide_channel]));
}
}
/* If the result is 1, issue an IRQ, otherwise not. */ /* If the result is 1, issue an IRQ, otherwise not. */
int cdrom_phase_callback(uint8_t id) void cdrom_phase_callback(uint8_t id)
{ {
switch(cdrom[id].packet_status) switch(cdrom[id].packet_status)
{ {
case CDROM_PHASE_IDLE: case CDROM_PHASE_IDLE:
// cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id);
cdrom[id].pos=0; cdrom[id].pos=0;
cdrom[id].phase = 1; cdrom[id].phase = 1;
cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT); cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT);
return 0; return;
case CDROM_PHASE_COMMAND: case CDROM_PHASE_COMMAND:
// cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id);
cdrom[id].status = BUSY_STAT | (cdrom[id].status &ERR_STAT); cdrom[id].status = BUSY_STAT | (cdrom[id].status &ERR_STAT);
memcpy(cdrom[id].atapi_cdb, (uint8_t *) cdrom[id].buffer, cdrom[id].cdb_len); memcpy(cdrom[id].atapi_cdb, (uint8_t *) cdrom[id].buffer, cdrom[id].cdb_len);
cdrom_command(id, cdrom[id].atapi_cdb); cdrom_command(id, cdrom[id].atapi_cdb);
return 0; return;
case CDROM_PHASE_COMPLETE: case CDROM_PHASE_COMPLETE:
// cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id);
cdrom[id].status = READY_STAT; cdrom[id].status = READY_STAT;
cdrom[id].phase = 3; cdrom[id].phase = 3;
cdrom[id].packet_status = 0xFF; cdrom[id].packet_status = 0xFF;
return 1; cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_OUT: case CDROM_PHASE_DATA_OUT:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id);
cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT); cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT);
cdrom[id].phase = 0; cdrom[id].phase = 0;
return 1; cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_OUT_DMA: case CDROM_PHASE_DATA_OUT_DMA:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id);
cdrom_read_from_dma(id); cdrom_read_from_dma(id);
cdrom[id].packet_status = CDROM_PHASE_COMPLETE; cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT; cdrom[id].status = READY_STAT;
cdrom[id].phase = 3; cdrom[id].phase = 3;
return 1; cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_IN: case CDROM_PHASE_DATA_IN:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id);
cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT); cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT);
cdrom[id].phase = 2; cdrom[id].phase = 2;
return 1; cdrom_irq_raise(id);
return;
case CDROM_PHASE_DATA_IN_DMA: case CDROM_PHASE_DATA_IN_DMA:
// cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id);
cdrom_write_to_dma(id); cdrom_write_to_dma(id);
cdrom[id].packet_status = CDROM_PHASE_COMPLETE; cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT; cdrom[id].status = READY_STAT;
cdrom[id].phase = 3; cdrom[id].phase = 3;
return 1; cdrom_irq_raise(id);
return;
case CDROM_PHASE_ERROR: case CDROM_PHASE_ERROR:
// cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id); cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id);
cdrom[id].status = READY_STAT | ERR_STAT; cdrom[id].status = READY_STAT | ERR_STAT;
cdrom[id].phase = 3; cdrom[id].phase = 3;
return 1; cdrom_irq_raise(id);
return;
} }
} }
@@ -2957,7 +2970,7 @@ void cdrom_write(uint8_t channel, uint32_t val, int length)
cdrom[id].pos++; cdrom[id].pos++;
break; break;
case 2: case 2:
cdbufferw[cdrom[id].pos >> 1] = val & 0xff; cdbufferw[cdrom[id].pos >> 1] = val & 0xffff;
cdrom[id].pos += 2; cdrom[id].pos += 2;
break; break;
case 4: case 4:

View File

@@ -129,9 +129,6 @@ typedef struct __attribute__((__packed__))
uint8_t bus_mode; /* Bit 0 = PIO suported; uint8_t bus_mode; /* Bit 0 = PIO suported;
Bit 1 = DMA supportd. */ Bit 1 = DMA supportd. */
uint8_t check_on_execution; /* 0 = Not Ready/Unit Attention checkeck is performed on the controller's side before command execution;
1 = Not Ready/Unit Attention checkeck is performed on command execution. */
uint8_t ide_channel; uint8_t ide_channel;
uint8_t scsi_device_id; uint8_t scsi_device_id;
@@ -190,7 +187,7 @@ void build_scsi_cdrom_map();
int cdrom_CDROM_PHASE_to_scsi(uint8_t id); int cdrom_CDROM_PHASE_to_scsi(uint8_t id);
int cdrom_atapi_phase_to_scsi(uint8_t id); int cdrom_atapi_phase_to_scsi(uint8_t id);
void cdrom_command(uint8_t id, uint8_t *cdb); void cdrom_command(uint8_t id, uint8_t *cdb);
int cdrom_phase_callback(uint8_t id); void cdrom_phase_callback(uint8_t id);
uint32_t cdrom_read(uint8_t channel, int length); uint32_t cdrom_read(uint8_t channel, int length);
void cdrom_write(uint8_t channel, uint32_t val, int length); void cdrom_write(uint8_t channel, uint32_t val, int length);
int cdrom_lba_to_msf_accurate(int lba); int cdrom_lba_to_msf_accurate(int lba);

View File

@@ -202,7 +202,7 @@ int image_is_hdi(const char *s)
int ide_enable[4] = { 1, 1, 0, 0 }; int ide_enable[4] = { 1, 1, 0, 0 };
int ide_irq[4] = { 14, 15, 10, 11 }; int ide_irq[4] = { 14, 15, 10, 11 };
static inline void ide_irq_raise(IDE *ide) void ide_irq_raise(IDE *ide)
{ {
if ((ide->board > 3) || ide->irqstat) if ((ide->board > 3) || ide->irqstat)
{ {
@@ -344,7 +344,7 @@ static void ide_identify(IDE *ide)
h = hdc[cur_ide[ide->board]].hpc; /* Heads */ h = hdc[cur_ide[ide->board]].hpc; /* Heads */
s = hdc[cur_ide[ide->board]].spt; /* Sectors */ s = hdc[cur_ide[ide->board]].spt; /* Sectors */
ide->buffer[0] = 0x40; /* Fixed disk */ // ide->buffer[0] = 0x40; /* Fixed disk */
ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */ ide->buffer[1] = hdc[cur_ide[ide->board]].tracks; /* Cylinders */
ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */ ide->buffer[3] = hdc[cur_ide[ide->board]].hpc; /* Heads */
ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */ ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */
@@ -403,10 +403,11 @@ static void ide_atapi_identify(IDE *ide)
ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */
ide_padstr((char *) (ide->buffer + 23), emulator_version, 8); /* Firmware */ ide_padstr((char *) (ide->buffer + 23), emulator_version, 8); /* Firmware */
ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */
ide->buffer[48] = 1; /*Dword transfers supported*/
ide->buffer[49] = 0x200; /* LBA supported */ ide->buffer[49] = 0x200; /* LBA supported */
ide->buffer[51] = 2 << 8; /*PIO timing mode*/ ide->buffer[51] = 2 << 8; /*PIO timing mode*/
ide->buffer[73] = 6; ide->buffer[73] = 6;
ide->buffer[73] = 9; ide->buffer[74] = 9;
ide->buffer[80] = 0x10; /*ATA/ATAPI-4 supported*/ ide->buffer[80] = 0x10; /*ATA/ATAPI-4 supported*/
if ((ide->board < 2) && (cdrom_drives[cdrom_id].bus_mode & 2)) if ((ide->board < 2) && (cdrom_drives[cdrom_id].bus_mode & 2))
@@ -736,7 +737,7 @@ void resetide(void)
if (ide_drives[d].type != IDE_NONE) if (ide_drives[d].type != IDE_NONE)
{ {
ide_drives[d].dma_identify_data[0] = 7; ide_drives[d].dma_identify_data[0] = 7;
ide_drives[d].dma_identify_data[1] = 7 | (1 << 15); ide_drives[d].dma_identify_data[1] = 7 | (1 << 10);
ide_drives[d].dma_identify_data[2] = 0x3f; ide_drives[d].dma_identify_data[2] = 0x3f;
} }
@@ -835,7 +836,9 @@ void writeidew(int ide_board, uint16_t val)
void writeidel(int ide_board, uint32_t val) void writeidel(int ide_board, uint32_t val)
{ {
// ide_log("WriteIDEl %08X\n", val); // ide_log("WriteIDEl %08X\n", val);
ide_write_data(ide_board, val, 4); // ide_write_data(ide_board, val, 4);
writeidew(ide_board, val);
writeidew(ide_board, val >> 16);
} }
void writeide(int ide_board, uint16_t addr, uint8_t val) void writeide(int ide_board, uint16_t addr, uint8_t val)
@@ -1349,7 +1352,7 @@ uint32_t ide_read_data(int ide_board, int length)
ide->pos += 2; ide->pos += 2;
break; break;
case 4: case 4:
temp = idebufferb[ide->pos >> 2]; temp = idebufferl[ide->pos >> 2];
ide->pos += 4; ide->pos += 4;
break; break;
default: default:
@@ -1559,17 +1562,21 @@ int all_blocks_total = 0;
uint16_t readidew(int ide_board) uint16_t readidew(int ide_board)
{ {
uint16_t temp; return ide_read_data(ide_board, 2);
temp = ide_read_data(ide_board, 2);
return temp;
} }
/* uint32_t readidel(int ide_board)
{
// ide_log("Read IDEl %i\n", ide_board);
return ide_read_data(ide_board, 4);
} */
uint32_t readidel(int ide_board) uint32_t readidel(int ide_board)
{ {
uint16_t temp; uint16_t temp;
// ide_log("Read IDEl %i\n", ide_board); // pclog("Read IDEl %i\n", ide_board);
temp = ide_read_data(ide_board, 4); temp = readidew(ide_board);
return temp; return temp | (readidew(ide_board) << 16);
} }
int times30=0; int times30=0;
@@ -2015,10 +2022,7 @@ void callbackide(int ide_board)
goto abort_cmd; goto abort_cmd;
} }
if (cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]])) cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]]);
{
ide_irq_raise(ide);
}
idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback; idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback;
ide_log("IDE callback now: %i\n", idecallback[ide_board]); ide_log("IDE callback now: %i\n", idecallback[ide_board]);
return; return;

View File

@@ -62,6 +62,7 @@ extern int idecallback[4];
extern char ide_fn[IDE_NUM][512]; extern char ide_fn[IDE_NUM][512];
void ide_irq_raise(IDE *ide);
void ide_irq_lower(IDE *ide); void ide_irq_lower(IDE *ide);
IDE ide_drives[IDE_NUM]; IDE ide_drives[IDE_NUM];

View File

@@ -16,22 +16,6 @@
uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE; uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE;
uint8_t SCSIStatus = SCSI_STATUS_OK; uint8_t SCSIStatus = SCSI_STATUS_OK;
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*/ uint8_t scsi_cdrom_id = 3; /*common setting*/
//Initialization function for the SCSI layer //Initialization function for the SCSI layer
@@ -41,8 +25,6 @@ void SCSIReset(uint8_t id, uint8_t lun)
if (buslogic_scsi_drive_is_cdrom(id, lun)) if (buslogic_scsi_drive_is_cdrom(id, lun))
{ {
SCSICallback[id][lun] = 0;
cdrom_reset(cdrom_id); cdrom_reset(cdrom_id);
SCSIDevices[id][lun].LunType = SCSI_CDROM; SCSIDevices[id][lun].LunType = SCSI_CDROM;
} }

View File

@@ -188,7 +188,6 @@ int MediaPresent;
extern uint8_t SCSIStatus; extern uint8_t SCSIStatus;
extern uint8_t SCSIPhase; extern uint8_t SCSIPhase;
extern int SCSICallback[16][8];
extern uint8_t scsi_cdrom_id; extern uint8_t scsi_cdrom_id;
struct struct