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:
617
src/buslogic.c
617
src/buslogic.c
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
69
src/cdrom.c
69
src/cdrom.c
@@ -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:
|
||||||
|
@@ -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);
|
||||||
|
36
src/ide.c
36
src/ide.c
@@ -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;
|
||||||
|
@@ -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];
|
||||||
|
18
src/scsi.c
18
src/scsi.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user