Merge pull request #68 from TC1995/master
Buslogic now fully working on DOS and NT (probably Win9x too)
This commit is contained in:
271
src/buslogic.c
271
src/buslogic.c
@@ -513,7 +513,6 @@ typedef struct __attribute__((packed)) Buslogic_t
|
|||||||
int DmaChannel;
|
int DmaChannel;
|
||||||
int IrqEnabled;
|
int IrqEnabled;
|
||||||
int Mbx24bit;
|
int Mbx24bit;
|
||||||
int CommandEnable;
|
|
||||||
} Buslogic_t;
|
} Buslogic_t;
|
||||||
|
|
||||||
int scsi_base = 0x330;
|
int scsi_base = 0x330;
|
||||||
@@ -522,6 +521,8 @@ int scsi_irq = 11;
|
|||||||
|
|
||||||
int buslogic_do_log = 0;
|
int buslogic_do_log = 0;
|
||||||
|
|
||||||
|
static void BuslogicStartMailbox(Buslogic_t *Buslogic);
|
||||||
|
|
||||||
void BuslogicLog(const char *format, ...)
|
void BuslogicLog(const char *format, ...)
|
||||||
{
|
{
|
||||||
if (buslogic_do_log)
|
if (buslogic_do_log)
|
||||||
@@ -636,13 +637,13 @@ static void BuslogicMailboxIn(Buslogic_t *Buslogic, uint32_t CCBPointer, CCBU *C
|
|||||||
{
|
{
|
||||||
MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode;
|
MailboxIn.CmdStatus = Mailbox32.u.in.CompletionCode;
|
||||||
U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer);
|
U32_TO_ADDR(MailboxIn.CCBPointer, Mailbox32.CCBPointer);
|
||||||
BuslogicLog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%08X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer));
|
BuslogicLog("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", MailboxIn.CmdStatus, ADDR_TO_U32(MailboxIn.CCBPointer));
|
||||||
|
|
||||||
DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t));
|
DMAPageWrite(Incoming, &MailboxIn, sizeof(Mailbox_t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BuslogicLog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%08X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer);
|
BuslogicLog("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", Mailbox32.u.in.CompletionCode, Mailbox32.CCBPointer);
|
||||||
|
|
||||||
DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t));
|
DMAPageWrite(Incoming, &Mailbox32, sizeof(Mailbox32_t));
|
||||||
}
|
}
|
||||||
@@ -690,7 +691,10 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB
|
|||||||
DataLength = CmdBlock->new.DataLength;
|
DataLength = CmdBlock->new.DataLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
pclog("Data Buffer write: length %d, pointer 0x%04X\n", DataLength, DataPointer);
|
if (CmdBlock->common.Cdb[0] == GPCMD_TEST_UNIT_READY)
|
||||||
|
DataLength = 0;
|
||||||
|
|
||||||
|
BuslogicLog("Data Buffer write: length %d, pointer 0x%04X\n", DataLength, DataPointer);
|
||||||
|
|
||||||
if (DataLength && CmdBlock->common.ControlByte != 0x03)
|
if (DataLength && CmdBlock->common.ControlByte != 0x03)
|
||||||
{
|
{
|
||||||
@@ -727,11 +731,12 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB
|
|||||||
SCSIDevices[scsi_cdrom_id].InitLength = DataToTransfer;
|
SCSIDevices[scsi_cdrom_id].InitLength = DataToTransfer;
|
||||||
|
|
||||||
//If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without
|
//If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without
|
||||||
//checking its length, so do this procedure for both no length/read/write commands.
|
//checking its length, so do this procedure for both no read/write commands.
|
||||||
if (CmdBlock->common.ControlByte == CCB_DATA_XFER_OUT || CmdBlock->common.ControlByte == 0x00)
|
if (CmdBlock->common.ControlByte == CCB_DATA_XFER_OUT || CmdBlock->common.ControlByte == 0x00)
|
||||||
{
|
{
|
||||||
ScatterGatherLeft = DataLength / (Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
ScatterGatherLeft = DataLength / (Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
||||||
ScatterGatherAddrCurrent = DataPointer;
|
ScatterGatherAddrCurrent = DataPointer;
|
||||||
|
uint8_t *DataBuffer = (uint8_t *)SCSIDevices[scsi_cdrom_id].CmdBuffer;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -749,7 +754,8 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB
|
|||||||
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
|
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
|
||||||
DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment;
|
DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment;
|
||||||
|
|
||||||
DMAPageRead(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, DataToTransfer);
|
DMAPageRead(Address, DataBuffer, DataToTransfer);
|
||||||
|
DataBuffer += DataToTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
||||||
@@ -779,11 +785,14 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
|
|||||||
DataPointer = BuslogicRequests->CmdBlock.new.DataPointer;
|
DataPointer = BuslogicRequests->CmdBlock.new.DataPointer;
|
||||||
DataLength = BuslogicRequests->CmdBlock.new.DataLength;
|
DataLength = BuslogicRequests->CmdBlock.new.DataLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
pclog("Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer);
|
if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)
|
||||||
|
DataLength = 0;
|
||||||
|
|
||||||
|
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 no length/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 == CCB_DATA_XFER_IN ||
|
||||||
BuslogicRequests->CmdBlock.common.ControlByte == 0x00))
|
BuslogicRequests->CmdBlock.common.ControlByte == 0x00))
|
||||||
{
|
{
|
||||||
@@ -795,6 +804,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
|
|||||||
SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS];
|
SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS];
|
||||||
uint32_t ScatterGatherLeft = DataLength / (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
uint32_t ScatterGatherLeft = DataLength / (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
||||||
uint32_t ScatterGatherAddrCurrent = DataPointer;
|
uint32_t ScatterGatherAddrCurrent = DataPointer;
|
||||||
|
uint8_t *DataBuffer = (uint8_t *)SCSIDevices[scsi_cdrom_id].CmdBuffer;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -813,7 +823,8 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
|
|||||||
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
|
Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer;
|
||||||
DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment;
|
DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment;
|
||||||
|
|
||||||
DMAPageWrite(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, DataToTransfer);
|
DMAPageWrite(Address, DataBuffer, DataToTransfer);
|
||||||
|
DataBuffer += DataToTransfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScatterGatherAddrCurrent += ScatterGatherRead * (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
ScatterGatherAddrCurrent += ScatterGatherRead * (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32));
|
||||||
@@ -826,6 +837,21 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests)
|
|||||||
DMAPageWrite(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, SCSIDevices[scsi_cdrom_id].InitLength);
|
DMAPageWrite(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, SCSIDevices[scsi_cdrom_id].InitLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES ||
|
||||||
|
BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)
|
||||||
|
{
|
||||||
|
if (BuslogicRequests->Is24bit)
|
||||||
|
{
|
||||||
|
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[scsi_cdrom_id].InitLength);
|
||||||
|
BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BuslogicRequests->CmdBlock.new.DataLength = SCSIDevices[scsi_cdrom_id].InitLength;
|
||||||
|
BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BuslogicRead(uint16_t Port, void *p)
|
uint8_t BuslogicRead(uint16_t Port, void *p)
|
||||||
@@ -1273,7 +1299,7 @@ static uint8_t BuslogicConvertSenseLength(uint8_t RequestSenseLength)
|
|||||||
else if (RequestSenseLength == 1)
|
else if (RequestSenseLength == 1)
|
||||||
RequestSenseLength = 0;
|
RequestSenseLength = 0;
|
||||||
|
|
||||||
pclog("Request Sense length %i\n", RequestSenseLength);
|
BuslogicLog("Request Sense length %i\n", RequestSenseLength);
|
||||||
|
|
||||||
return RequestSenseLength;
|
return RequestSenseLength;
|
||||||
}
|
}
|
||||||
@@ -1305,10 +1331,9 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
SenseBufferAddress = BuslogicRequests->CmdBlock.new.SensePointer;
|
SenseBufferAddress = BuslogicRequests->CmdBlock.new.SensePointer;
|
||||||
SenseBufferAddress += BuslogicRequests->CmdBlock.common.CdbLength + offsetof(CCB32, Cdb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pclog("Request Sense address: %02X\n", SenseBufferAddress);
|
BuslogicLog("Request Sense address: %02X\n", SenseBufferAddress);
|
||||||
|
|
||||||
DMAPageWrite(SenseBufferAddress, BuslogicRequests->RequestSenseBuffer, SenseLength);
|
DMAPageWrite(SenseBufferAddress, BuslogicRequests->RequestSenseBuffer, SenseLength);
|
||||||
}
|
}
|
||||||
@@ -1316,31 +1341,7 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co
|
|||||||
free(BuslogicRequests->RequestSenseBuffer);
|
free(BuslogicRequests->RequestSenseBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuslogicSCSIRequestComplete(Buslogic_t *Buslogic, BuslogicRequests_t *BuslogicRequests)
|
static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
|
||||||
{
|
|
||||||
uint8_t Status = SCSIStatus;
|
|
||||||
uint32_t CCBPointer = BuslogicRequests->CCBPointer;
|
|
||||||
CCBU CmdBlock;
|
|
||||||
memcpy(&CmdBlock, &BuslogicRequests->CmdBlock, sizeof(CCBU));
|
|
||||||
|
|
||||||
BuslogicDataBufferFree(BuslogicRequests);
|
|
||||||
|
|
||||||
if (BuslogicRequests->RequestSenseBuffer)
|
|
||||||
BuslogicSenseBufferFree(BuslogicRequests, (Status != SCSI_STATUS_OK));
|
|
||||||
|
|
||||||
if (Status == SCSI_STATUS_OK)
|
|
||||||
{
|
|
||||||
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK,
|
|
||||||
MBI_SUCCESS);
|
|
||||||
}
|
|
||||||
else if (Status == SCSI_STATUS_CHECK_CONDITION)
|
|
||||||
{
|
|
||||||
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION,
|
|
||||||
MBI_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
|
|
||||||
{
|
{
|
||||||
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
|
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
|
||||||
CCBU CmdBlock;
|
CCBU CmdBlock;
|
||||||
@@ -1358,7 +1359,7 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
|
|||||||
BuslogicLog("Scanning SCSI Target ID %i\n", Id);
|
BuslogicLog("Scanning SCSI Target ID %i\n", Id);
|
||||||
|
|
||||||
//Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon.
|
//Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon.
|
||||||
if (Id == scsi_cdrom_id)
|
if (Id == scsi_cdrom_id && Lun == 0)
|
||||||
{
|
{
|
||||||
BuslogicLog("SCSI Target ID %i detected and working\n", Id);
|
BuslogicLog("SCSI Target ID %i detected and working\n", Id);
|
||||||
|
|
||||||
@@ -1367,69 +1368,118 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer)
|
|||||||
|
|
||||||
memcpy(&BuslogicRequests->CmdBlock, &CmdBlock, sizeof(CmdBlock));
|
memcpy(&BuslogicRequests->CmdBlock, &CmdBlock, sizeof(CmdBlock));
|
||||||
|
|
||||||
BuslogicSenseBufferAllocate(BuslogicRequests);
|
if (Mailbox32->u.out.ActionCode == MBO_START)
|
||||||
|
|
||||||
BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit);
|
|
||||||
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
pclog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]);
|
|
||||||
for (i = 1; i < BuslogicRequests->CmdBlock.common.CdbLength; i++)
|
|
||||||
pclog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]);
|
|
||||||
|
|
||||||
pclog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte);
|
|
||||||
pclog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength);
|
|
||||||
pclog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode);
|
|
||||||
|
|
||||||
//First, get the data buffer otherwise putting it after the
|
|
||||||
//exec function results into not getting read/write commands right and
|
|
||||||
//failing to detect the device.
|
|
||||||
|
|
||||||
if (CmdBlock.common.ControlByte == CCB_DATA_XFER_IN)
|
|
||||||
{
|
{
|
||||||
SCSIRead(Id, SCSIDevices[Id].InitLength);
|
BuslogicSenseBufferAllocate(BuslogicRequests);
|
||||||
}
|
|
||||||
else if (CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT)
|
BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit);
|
||||||
{
|
|
||||||
SCSIWrite(Id, SCSIDevices[Id].InitLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Finally, execute the SCSI command immediately and get the transfer length.
|
/* If the UNIT ATTENTION condition is set and the command does not allow
|
||||||
SCSIPhase = SCSI_PHASE_COMMAND;
|
execution under it, error out and report the condition. */
|
||||||
SCSIExecCommand(Id, Lun, BuslogicRequests->CmdBlock.common.Cdb);
|
if (!(SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention)
|
||||||
SCSIGetLength(Id, &SCSIDevices[Id].InitLength);
|
{
|
||||||
|
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
|
||||||
if (SCSIPhase == SCSI_PHASE_DATAIN)
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
{
|
SCSICallback[Id]=50*SCSI_TIME;
|
||||||
SCSIReadData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength);
|
}
|
||||||
}
|
|
||||||
|
/* Unless the command is REQUEST SENSE, clear the sense. This will *NOT*
|
||||||
|
clear the UNIT ATTENTION condition if it's set. */
|
||||||
|
if (BuslogicRequests->CmdBlock.common.Cdb[0]!=GPCMD_REQUEST_SENSE)
|
||||||
|
{
|
||||||
|
if (SCSISense.UnitAttention)
|
||||||
|
{
|
||||||
|
SCSISense.UnitAttention = 0;
|
||||||
|
SCSIClearSense(BuslogicRequests->CmdBlock.common.Cdb[0], 0);
|
||||||
|
SCSIStatus = SCSI_STATUS_OK;
|
||||||
|
BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK,
|
||||||
|
MBI_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES ||
|
/* Next it's time for NOT READY. */
|
||||||
BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)
|
if ((SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & CHECK_READY) && !cdrom->ready())
|
||||||
{
|
|
||||||
if (BuslogicRequests->Is24bit)
|
|
||||||
{
|
{
|
||||||
U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[Id].InitLength);
|
BuslogicLog("Not ready\n");
|
||||||
BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength));
|
SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0);
|
||||||
}
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
else
|
SCSICallback[Id]=50*SCSI_TIME;
|
||||||
|
BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION,
|
||||||
|
MBI_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SenseLength = BuslogicConvertSenseLength(BuslogicRequests->CmdBlock.common.RequestSenseLength);
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
BuslogicLog("SCSI Cdb[0]=0x%02X\n", BuslogicRequests->CmdBlock.common.Cdb[0]);
|
||||||
|
for (i = 1; i < BuslogicRequests->CmdBlock.common.CdbLength; i++)
|
||||||
|
BuslogicLog("SCSI Cdb[%i]=%i\n", i, BuslogicRequests->CmdBlock.common.Cdb[i]);
|
||||||
|
|
||||||
|
BuslogicLog("Transfer Control %02X\n", BuslogicRequests->CmdBlock.common.ControlByte);
|
||||||
|
BuslogicLog("CDB Length %i\n", BuslogicRequests->CmdBlock.common.CdbLength);
|
||||||
|
BuslogicLog("CCB Opcode %x\n", BuslogicRequests->CmdBlock.common.Opcode);
|
||||||
|
|
||||||
|
//First, get the data buffer otherwise putting it after the
|
||||||
|
//exec function results into not getting read/write commands right and
|
||||||
|
//failing to detect the device.
|
||||||
|
|
||||||
|
if (CmdBlock.common.ControlByte == CCB_DATA_XFER_IN)
|
||||||
{
|
{
|
||||||
BuslogicRequests->CmdBlock.new.DataLength = SCSIDevices[Id].InitLength;
|
SCSIRead(Id, SCSIDevices[Id].InitLength);
|
||||||
BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength);
|
|
||||||
}
|
}
|
||||||
|
else if (CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT)
|
||||||
|
{
|
||||||
|
SCSIWrite(Id, SCSIDevices[Id].InitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Finally, execute the SCSI command immediately and get the transfer length.
|
||||||
|
|
||||||
|
SCSIPhase = SCSI_PHASE_COMMAND;
|
||||||
|
SCSIExecCommand(Id, BuslogicRequests->CmdBlock.common.Cdb, SenseLength);
|
||||||
|
SCSIGetLength(Id, &SCSIDevices[Id].InitLength);
|
||||||
|
|
||||||
|
if (SCSIPhase == SCSI_PHASE_DATAIN)
|
||||||
|
{
|
||||||
|
SCSIReadData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength,SenseLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BuslogicDataBufferFree(BuslogicRequests);
|
||||||
|
|
||||||
|
if (BuslogicRequests->RequestSenseBuffer)
|
||||||
|
BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK));
|
||||||
}
|
}
|
||||||
|
|
||||||
BuslogicLog("Request complete\n");
|
BuslogicLog("Request complete\n");
|
||||||
BuslogicSCSIRequestComplete(Buslogic, BuslogicRequests);
|
BuslogicLog("SCSI Status %002X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq);
|
||||||
|
|
||||||
|
if (SCSIStatus == SCSI_STATUS_OK)
|
||||||
|
{
|
||||||
|
BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_OK,
|
||||||
|
MBI_SUCCESS);
|
||||||
|
}
|
||||||
|
else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION)
|
||||||
|
{
|
||||||
|
BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION,
|
||||||
|
MBI_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BuslogicDataBufferFree(BuslogicRequests);
|
if (Mailbox32->u.out.ActionCode == MBO_START)
|
||||||
|
{
|
||||||
if (BuslogicRequests->RequestSenseBuffer)
|
BuslogicDataBufferFree(BuslogicRequests);
|
||||||
BuslogicSenseBufferFree(BuslogicRequests, 1);
|
|
||||||
|
if (BuslogicRequests->RequestSenseBuffer)
|
||||||
|
BuslogicSenseBufferFree(BuslogicRequests, 1);
|
||||||
|
}
|
||||||
|
|
||||||
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
|
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
|
||||||
|
|
||||||
|
if (Mailbox32->u.out.ActionCode == MBO_START)
|
||||||
|
BuslogicStartMailbox(Buslogic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,35 +1495,6 @@ static void BuslogicSCSIRequestAbort(Buslogic_t *Buslogic, uint32_t CCBPointer)
|
|||||||
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND);
|
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BuslogicSCSIRequestFree(Buslogic_t *Buslogic, uint32_t CCBPointer)
|
|
||||||
{
|
|
||||||
BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests;
|
|
||||||
CCBU CmdBlock;
|
|
||||||
uint8_t Id, Lun;
|
|
||||||
|
|
||||||
//Fetch data from the Command Control Block.
|
|
||||||
DMAPageRead(CCBPointer, &CmdBlock, sizeof(CCB32));
|
|
||||||
|
|
||||||
BuslogicRequests->TargetID = Buslogic->Mbx24bit ? CmdBlock.old.Id : CmdBlock.new.Id;
|
|
||||||
|
|
||||||
Id = BuslogicRequests->TargetID;
|
|
||||||
|
|
||||||
//Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon.
|
|
||||||
if (Id == scsi_cdrom_id)
|
|
||||||
{
|
|
||||||
BuslogicSCSIRequestComplete(Buslogic, BuslogicRequests);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BuslogicDataBufferFree(BuslogicRequests);
|
|
||||||
|
|
||||||
if (BuslogicRequests->RequestSenseBuffer)
|
|
||||||
BuslogicSenseBufferFree(BuslogicRequests, 1);
|
|
||||||
|
|
||||||
BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32)
|
static uint32_t BuslogicMailboxOut(Buslogic_t *Buslogic, Mailbox32_t *Mailbox32)
|
||||||
{
|
{
|
||||||
Mailbox_t MailboxOut;
|
Mailbox_t MailboxOut;
|
||||||
@@ -1517,21 +1538,16 @@ static void BuslogicStartMailbox(Buslogic_t *Buslogic)
|
|||||||
|
|
||||||
DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus));
|
DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, sizeof(CmdStatus));
|
||||||
|
|
||||||
if (Mailbox32.u.out.ActionCode == MBO_START)
|
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);
|
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);
|
BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
BuslogicLog("Free Mailbox Command\n");
|
|
||||||
BuslogicSCSIRequestFree(Buslogic, Mailbox32.CCBPointer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuslogicCommandCallback(void *p)
|
void BuslogicCommandCallback(void *p)
|
||||||
@@ -1539,8 +1555,10 @@ void BuslogicCommandCallback(void *p)
|
|||||||
Buslogic_t *Buslogic = (Buslogic_t *)p;
|
Buslogic_t *Buslogic = (Buslogic_t *)p;
|
||||||
|
|
||||||
SCSICallback[scsi_cdrom_id] = 0;
|
SCSICallback[scsi_cdrom_id] = 0;
|
||||||
if (Buslogic->MailboxCount)
|
if (Buslogic->MailboxCount)
|
||||||
|
{
|
||||||
BuslogicStartMailbox(Buslogic);
|
BuslogicStartMailbox(Buslogic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *BuslogicInit()
|
void *BuslogicInit()
|
||||||
@@ -1552,12 +1570,11 @@ void *BuslogicInit()
|
|||||||
Buslogic->DmaChannel = scsi_dma;
|
Buslogic->DmaChannel = scsi_dma;
|
||||||
|
|
||||||
io_sethandler(scsi_base, 0x0004, BuslogicRead, NULL, NULL, BuslogicWrite, NULL, NULL, Buslogic);
|
io_sethandler(scsi_base, 0x0004, BuslogicRead, NULL, NULL, BuslogicWrite, NULL, NULL, Buslogic);
|
||||||
|
|
||||||
timer_add(BuslogicCommandCallback, &SCSICallback[scsi_cdrom_id], &SCSICallback[scsi_cdrom_id], Buslogic);
|
timer_add(BuslogicCommandCallback, &SCSICallback[scsi_cdrom_id], &SCSICallback[scsi_cdrom_id], Buslogic);
|
||||||
|
|
||||||
BuslogicLog("Buslogic on port 0x%04X\n", scsi_base);
|
BuslogicLog("Buslogic on port 0x%04X\n", scsi_base);
|
||||||
|
|
||||||
BuslogicReset(Buslogic);
|
BuslogicResetControl(Buslogic, CTRL_HRST);
|
||||||
|
|
||||||
return Buslogic;
|
return Buslogic;
|
||||||
}
|
}
|
||||||
|
@@ -1,149 +0,0 @@
|
|||||||
/* Copyright holders: SA1988
|
|
||||||
see COPYING for more details
|
|
||||||
*/
|
|
||||||
/*Scatter/Gather emulation*/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "ibm.h"
|
|
||||||
|
|
||||||
#include "scattergather.h"
|
|
||||||
|
|
||||||
static uint8_t *SegmentBufferGet(SGBUF *SegmentBuf, uint32_t Data)
|
|
||||||
{
|
|
||||||
uint32_t DataSize;
|
|
||||||
uint8_t *Buffer;
|
|
||||||
|
|
||||||
if (SegmentBuf->SegmentIndex == SegmentBuf->SegmentNum
|
|
||||||
&& !SegmentBuf->SegmentLeft)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataSize = MIN(Data, SegmentBuf->SegmentLeft);
|
|
||||||
Buffer = SegmentBuf->SegmentPtrCur;
|
|
||||||
SegmentBuf->SegmentLeft -= Data;
|
|
||||||
|
|
||||||
if (!SegmentBuf->SegmentLeft)
|
|
||||||
{
|
|
||||||
SegmentBuf->SegmentIndex++;
|
|
||||||
|
|
||||||
if (SegmentBuf->SegmentIndex < SegmentBuf->SegmentNum)
|
|
||||||
{
|
|
||||||
SegmentBuf->SegmentPtrCur = SegmentBuf->SegmentPtr[SegmentBuf->SegmentIndex].Address;
|
|
||||||
SegmentBuf->SegmentLeft = SegmentBuf->SegmentPtr[SegmentBuf->SegmentIndex].Length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SegmentBuf->SegmentPtrCur = (uint8_t *)SegmentBuf->SegmentPtrCur + DataSize;
|
|
||||||
|
|
||||||
return Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t *SegmentBufferGetNextSegment(SGBUF *SegmentBuf, uint32_t Segment)
|
|
||||||
{
|
|
||||||
if (!Segment)
|
|
||||||
Segment = SegmentBuf->SegmentLeft;
|
|
||||||
|
|
||||||
return SegmentBufferGet(SegmentBuf, Segment);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SegmentBufferCopy(SGBUF *SegmentDst, SGBUF *SegmentSrc, uint32_t Copy)
|
|
||||||
{
|
|
||||||
uint32_t Left = Copy;
|
|
||||||
while (Left)
|
|
||||||
{
|
|
||||||
uint32_t ThisCopy = MIN(MIN(SegmentDst->SegmentLeft, Left), SegmentSrc->SegmentLeft);
|
|
||||||
if (!ThisCopy)
|
|
||||||
break;
|
|
||||||
|
|
||||||
uint32_t Tmp = ThisCopy;
|
|
||||||
uint8_t *BufDst = SegmentBufferGet(SegmentDst, Tmp);
|
|
||||||
uint8_t *BufSrc = SegmentBufferGet(SegmentSrc, Tmp);
|
|
||||||
|
|
||||||
memcpy(BufSrc, BufDst, ThisCopy);
|
|
||||||
|
|
||||||
BufDst += ThisCopy;
|
|
||||||
BufSrc -= ThisCopy;
|
|
||||||
Left -= ThisCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Copy - Left;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SegmentBufferCopyFromBuf(SGBUF *SegmentBuf, uint8_t *BufSrc, uint32_t Copy)
|
|
||||||
{
|
|
||||||
uint32_t Left = Copy;
|
|
||||||
while (Left)
|
|
||||||
{
|
|
||||||
uint32_t ThisCopy = MIN(MIN(SegmentBuf->SegmentLeft, Left), (uint32_t)BufSrc);
|
|
||||||
if (!ThisCopy)
|
|
||||||
break;
|
|
||||||
|
|
||||||
uint32_t Tmp = ThisCopy;
|
|
||||||
uint8_t *BufDst = SegmentBufferGet(SegmentBuf, Tmp);
|
|
||||||
|
|
||||||
memcpy(BufDst, BufSrc, ThisCopy);
|
|
||||||
|
|
||||||
BufDst += ThisCopy;
|
|
||||||
BufSrc -= ThisCopy;
|
|
||||||
Left -= ThisCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Copy - Left;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SegmentBufferCopyToBuf(SGBUF *SegmentBuf, uint8_t *BufDst, uint32_t Copy)
|
|
||||||
{
|
|
||||||
uint32_t Left = Copy;
|
|
||||||
while (Left)
|
|
||||||
{
|
|
||||||
uint32_t ThisCopy = MIN(MIN(SegmentBuf->SegmentLeft, Left), (uint32_t)BufDst);
|
|
||||||
if (!ThisCopy)
|
|
||||||
break;
|
|
||||||
|
|
||||||
uint32_t Tmp = ThisCopy;
|
|
||||||
uint8_t *BufSrc = SegmentBufferGet(SegmentBuf, Tmp);
|
|
||||||
|
|
||||||
memcpy(BufSrc, BufDst, ThisCopy);
|
|
||||||
|
|
||||||
BufSrc += ThisCopy;
|
|
||||||
BufDst -= ThisCopy;
|
|
||||||
Left -= ThisCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Copy - Left;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SegmentBufferAdvance(SGBUF *SegmentBuf, uint32_t Advance)
|
|
||||||
{
|
|
||||||
uint32_t Left = Advance;
|
|
||||||
while (Left)
|
|
||||||
{
|
|
||||||
uint32_t ThisAdvance = Left;
|
|
||||||
SegmentBufferGet(SegmentBuf, ThisAdvance);
|
|
||||||
if (!ThisAdvance)
|
|
||||||
break;
|
|
||||||
|
|
||||||
Left -= ThisAdvance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Advance - Left;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SegmentBufferInit(SGBUF *SegmentBuf, const SGSEG *SegmentPtr, uint32_t Segments)
|
|
||||||
{
|
|
||||||
SegmentBuf->SegmentPtr = SegmentPtr;
|
|
||||||
SegmentBuf->SegmentNum = (unsigned)Segments;
|
|
||||||
SegmentBuf->SegmentIndex = 0;
|
|
||||||
|
|
||||||
if (Segments && SegmentPtr)
|
|
||||||
{
|
|
||||||
SegmentBuf->SegmentPtrCur = SegmentPtr[0].Address;
|
|
||||||
SegmentBuf->SegmentLeft = SegmentPtr[0].Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SegmentBuf->SegmentPtrCur = NULL;
|
|
||||||
SegmentBuf->SegmentLeft = 0;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,24 +0,0 @@
|
|||||||
#ifndef _SCATTERGATHER_H_
|
|
||||||
#define _SCATTERGATHER_H_
|
|
||||||
|
|
||||||
typedef struct SGSEG
|
|
||||||
{
|
|
||||||
uint8_t Address[512];
|
|
||||||
uint32_t Length;
|
|
||||||
} SGSEG;
|
|
||||||
|
|
||||||
typedef struct SGBUF
|
|
||||||
{
|
|
||||||
const SGSEG *SegmentPtr;
|
|
||||||
unsigned SegmentNum;
|
|
||||||
unsigned SegmentIndex;
|
|
||||||
uint8_t *SegmentPtrCur;
|
|
||||||
uint32_t SegmentLeft;
|
|
||||||
} SGBUF;
|
|
||||||
|
|
||||||
uint32_t SegmentBufferCopy(SGBUF *SegmentDst, SGBUF *SegmentSrc, uint32_t Copy);
|
|
||||||
uint8_t *SegmentBufferGetNextSegment(SGBUF *SegmentBuf, uint32_t Segment);
|
|
||||||
uint32_t SegmentBufferAdvance(SGBUF *SegmentBuf, uint32_t Advance);
|
|
||||||
void SegmentBufferInit(SGBUF *SegmentBuf, const SGSEG *SegmentPtr, uint32_t Segments);
|
|
||||||
|
|
||||||
#endif
|
|
@@ -23,9 +23,9 @@ void SCSIGetLength(uint8_t id, int *datalen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Execute SCSI command
|
//Execute SCSI command
|
||||||
void SCSIExecCommand(uint8_t id, uint8_t lun, uint8_t *cdb)
|
void SCSIExecCommand(uint8_t id, uint8_t *cdb, uint8_t sense)
|
||||||
{
|
{
|
||||||
SCSICDROM_Command(id, lun, cdb);
|
SCSICDROM_Command(id, cdb, sense);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read pending data from the resulting SCSI command
|
//Read pending data from the resulting SCSI command
|
||||||
|
186
src/scsi_cdrom.c
186
src/scsi_cdrom.c
@@ -636,11 +636,11 @@ int cdrom_read_data(uint8_t *buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pclog("CD-ROM sector size: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags);
|
pclog("CD-ROM sector size: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags);
|
||||||
return cdrom_add_error_and_subchannel(b, real_sector_type);
|
return cdrom_add_error_and_subchannel(b, real_sector_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA)
|
void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA)
|
||||||
{
|
{
|
||||||
if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA)
|
if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA)
|
||||||
{
|
{
|
||||||
@@ -678,7 +678,65 @@ static int SCSICDROM_TOC(uint8_t id, uint8_t *cdb)
|
|||||||
return TocFormat;
|
return TocFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
void SCSICDROMRequestSense(uint8_t id, uint8_t *cdb, uint8_t sense)
|
||||||
|
{
|
||||||
|
/*Will return 18 bytes of 0*/
|
||||||
|
memset(SCSIDevices[id].CmdBuffer,0,512);
|
||||||
|
|
||||||
|
SCSIDevices[id].CmdBuffer[0]=0x80|0x70;
|
||||||
|
|
||||||
|
if ((SCSISense.SenseKey > 0) || (cd_status < CD_STATUS_PLAYING))
|
||||||
|
{
|
||||||
|
if (SenseCompleted)
|
||||||
|
{
|
||||||
|
SCSIDevices[id].CmdBuffer[2]=SENSE_ILLEGAL_REQUEST;
|
||||||
|
SCSIDevices[id].CmdBuffer[12]=ASC_AUDIO_PLAY_OPERATION;
|
||||||
|
SCSIDevices[id].CmdBuffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SCSIDevices[id].CmdBuffer[2]=SCSISense.SenseKey;
|
||||||
|
SCSIDevices[id].CmdBuffer[12]=SCSISense.Asc;
|
||||||
|
SCSIDevices[id].CmdBuffer[13]=SCSISense.Ascq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED))
|
||||||
|
{
|
||||||
|
SCSIDevices[id].CmdBuffer[2]=SENSE_ILLEGAL_REQUEST;
|
||||||
|
SCSIDevices[id].CmdBuffer[12]=ASC_AUDIO_PLAY_OPERATION;
|
||||||
|
SCSIDevices[id].CmdBuffer[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SCSISense.UnitAttention)
|
||||||
|
{
|
||||||
|
SCSIDevices[id].CmdBuffer[2]=SENSE_UNIT_ATTENTION;
|
||||||
|
SCSIDevices[id].CmdBuffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED;
|
||||||
|
SCSIDevices[id].CmdBuffer[13]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SCSIDevices[id].CmdBuffer[7]=10;
|
||||||
|
|
||||||
|
SCSIPhase = SCSI_PHASE_DATAIN;
|
||||||
|
SCSIStatus = SCSI_STATUS_OK;
|
||||||
|
SCSICallback[id]=60*SCSI_TIME;
|
||||||
|
SCSIDevices[id].CmdBufferLength = sense;
|
||||||
|
|
||||||
|
SCSIDMAResetPosition(id);
|
||||||
|
|
||||||
|
if (SCSIDevices[id].CmdBuffer[2] == SENSE_UNIT_ATTENTION)
|
||||||
|
{
|
||||||
|
/* If the last remaining sense is unit attention, clear
|
||||||
|
that condition. */
|
||||||
|
SCSISense.UnitAttention = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the sense stuff as per the spec. */
|
||||||
|
SCSIClearSense(cdb[0], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCSICDROM_Command(uint8_t id, uint8_t *cdb, uint8_t sense)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int pos=0;
|
int pos=0;
|
||||||
@@ -694,14 +752,6 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
|||||||
int max_length = 0;
|
int max_length = 0;
|
||||||
int track = 0;
|
int track = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (lun > 0)
|
|
||||||
{
|
|
||||||
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_INV_FIELD_IN_CMD_PACKET, 0);
|
|
||||||
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
|
||||||
SCSICallback[id]=50*SCSI_TIME;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
msf = cdb[1] & 2;
|
msf = cdb[1] & 2;
|
||||||
|
|
||||||
@@ -721,25 +771,21 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
|||||||
|
|
||||||
/* If the UNIT ATTENTION condition is set and the command does not allow
|
/* If the UNIT ATTENTION condition is set and the command does not allow
|
||||||
execution under it, error out and report the condition. */
|
execution under it, error out and report the condition. */
|
||||||
|
#if 0
|
||||||
if (!(SCSICommandTable[cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention)
|
if (!(SCSICommandTable[cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention)
|
||||||
{
|
{
|
||||||
pclog("UNIT ATTENTION: Command not allowed to pass through\n");
|
pclog("UNIT ATTENTION\n");
|
||||||
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
|
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
|
||||||
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
SCSICallback[id]=50*SCSI_TIME;
|
SCSICallback[id]=50*SCSI_TIME;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cdb[0] == GPCMD_READ_TOC_PMA_ATIP)
|
if (cdb[0] == GPCMD_READ_TOC_PMA_ATIP)
|
||||||
SCSISense.UnitAttention = 0;
|
SCSISense.UnitAttention = 0;
|
||||||
|
|
||||||
/* Unless the command is REQUEST SENSE, clear the sense. This will *NOT*
|
#if 0
|
||||||
clear the UNIT ATTENTION condition if it's set. */
|
|
||||||
if (cdb[0]!=GPCMD_REQUEST_SENSE)
|
|
||||||
{
|
|
||||||
SCSIClearSense(cdb[0], 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next it's time for NOT READY. */
|
/* Next it's time for NOT READY. */
|
||||||
if ((SCSICommandTable[cdb[0]] & CHECK_READY) && !cdrom->ready())
|
if ((SCSICommandTable[cdb[0]] & CHECK_READY) && !cdrom->ready())
|
||||||
{
|
{
|
||||||
@@ -749,6 +795,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
|||||||
SCSICallback[id]=50*SCSI_TIME;
|
SCSICallback[id]=50*SCSI_TIME;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
prev_status = cd_status;
|
prev_status = cd_status;
|
||||||
cd_status = cdrom->status();
|
cd_status = cdrom->status();
|
||||||
@@ -770,62 +817,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GPCMD_REQUEST_SENSE:
|
case GPCMD_REQUEST_SENSE:
|
||||||
len = cdb[4];
|
SCSICDROMRequestSense(id, cdb, sense);
|
||||||
|
|
||||||
/*Will return 18 bytes of 0*/
|
|
||||||
memset(SCSIDevices[id].CmdBuffer,0,512);
|
|
||||||
|
|
||||||
SCSIDevices[id].CmdBuffer[0]=0x80|0x70;
|
|
||||||
|
|
||||||
if ((SCSISense.SenseKey > 0) || (cd_status < CD_STATUS_PLAYING))
|
|
||||||
{
|
|
||||||
if (SenseCompleted)
|
|
||||||
{
|
|
||||||
SCSIDevices[id].CmdBuffer[2]=SENSE_ILLEGAL_REQUEST;
|
|
||||||
SCSIDevices[id].CmdBuffer[12]=ASC_AUDIO_PLAY_OPERATION;
|
|
||||||
SCSIDevices[id].CmdBuffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SCSIDevices[id].CmdBuffer[2]=SCSISense.SenseKey;
|
|
||||||
SCSIDevices[id].CmdBuffer[12]=SCSISense.Asc;
|
|
||||||
SCSIDevices[id].CmdBuffer[13]=SCSISense.Ascq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED))
|
|
||||||
{
|
|
||||||
SCSIDevices[id].CmdBuffer[2]=SENSE_ILLEGAL_REQUEST;
|
|
||||||
SCSIDevices[id].CmdBuffer[12]=ASC_AUDIO_PLAY_OPERATION;
|
|
||||||
SCSIDevices[id].CmdBuffer[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SCSISense.UnitAttention)
|
|
||||||
{
|
|
||||||
SCSIDevices[id].CmdBuffer[2]=SENSE_UNIT_ATTENTION;
|
|
||||||
SCSIDevices[id].CmdBuffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED;
|
|
||||||
SCSIDevices[id].CmdBuffer[13]=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SCSIDevices[id].CmdBuffer[7]=10;
|
|
||||||
|
|
||||||
SCSIPhase = SCSI_PHASE_DATAIN;
|
|
||||||
SCSIStatus = SCSI_STATUS_OK;
|
|
||||||
SCSICallback[id]=60*SCSI_TIME;
|
|
||||||
SCSIDevices[id].CmdBufferLength = len;
|
|
||||||
|
|
||||||
SCSIDMAResetPosition(id);
|
|
||||||
|
|
||||||
if (SCSIDevices[id].CmdBuffer[2] == SENSE_UNIT_ATTENTION)
|
|
||||||
{
|
|
||||||
/* If the last remaining sense is unit attention, clear
|
|
||||||
that condition. */
|
|
||||||
SCSISense.UnitAttention = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear the sense stuff as per the spec. */
|
|
||||||
SCSIClearSense(cdb[0], 0);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GPCMD_READ_6:
|
case GPCMD_READ_6:
|
||||||
@@ -851,7 +843,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
|||||||
|
|
||||||
if (SectorLBA > (cdrom->size() - 1))
|
if (SectorLBA > (cdrom->size() - 1))
|
||||||
{
|
{
|
||||||
//pclog("Trying to read beyond the end of disc\n");
|
pclog("Trying to read beyond the end of disc\n");
|
||||||
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
|
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
|
||||||
SCSICallback[id]=50*SCSI_TIME;
|
SCSICallback[id]=50*SCSI_TIME;
|
||||||
@@ -881,7 +873,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb)
|
|||||||
case GPCMD_SEEK_10:
|
case GPCMD_SEEK_10:
|
||||||
if (cdb[0] == GPCMD_SEEK_6)
|
if (cdb[0] == GPCMD_SEEK_6)
|
||||||
{
|
{
|
||||||
pos = (cdb[2]<<8)|cdb[3];
|
pos = ((((uint32_t) cdb[1]) & 0x1f)<<16)|(((uint32_t) cdb[2])<<8)|((uint32_t) cdb[3]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1056,10 +1048,6 @@ SCSIOut:
|
|||||||
{
|
{
|
||||||
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00);
|
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00);
|
||||||
if (SCSISense.UnitAttention)
|
|
||||||
{
|
|
||||||
SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0);
|
|
||||||
}
|
|
||||||
SCSICallback[id]=50*SCSI_TIME;
|
SCSICallback[id]=50*SCSI_TIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1199,7 +1187,7 @@ SCSIOut:
|
|||||||
SCSIDevices[id].CmdBufferLength = 8;
|
SCSIDevices[id].CmdBufferLength = 8;
|
||||||
|
|
||||||
SCSIDMAResetPosition(id);
|
SCSIDMAResetPosition(id);
|
||||||
return;
|
break;
|
||||||
|
|
||||||
case GPCMD_PLAY_AUDIO_10:
|
case GPCMD_PLAY_AUDIO_10:
|
||||||
case GPCMD_PLAY_AUDIO_MSF:
|
case GPCMD_PLAY_AUDIO_MSF:
|
||||||
@@ -1606,7 +1594,7 @@ SCSIOut:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
|
void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen, uint8_t senselen)
|
||||||
{
|
{
|
||||||
int read_length = 0;
|
int read_length = 0;
|
||||||
|
|
||||||
@@ -1617,34 +1605,32 @@ void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen)
|
|||||||
case GPCMD_READ_12:
|
case GPCMD_READ_12:
|
||||||
case GPCMD_READ_CD_MSF:
|
case GPCMD_READ_CD_MSF:
|
||||||
case GPCMD_READ_CD:
|
case GPCMD_READ_CD:
|
||||||
//pclog("Total data length requested: %d\n", datalen);
|
pclog("Total data length requested: %d\n", datalen);
|
||||||
while (datalen > 0)
|
while (datalen > 0)
|
||||||
{
|
{
|
||||||
read_length = cdrom_read_data(data); //Fill the buffer the data it needs
|
read_length = cdrom_read_data(data); //Fill the buffer the data it needs
|
||||||
if (!read_length)
|
if (!read_length)
|
||||||
{
|
{
|
||||||
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
|
||||||
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0);
|
SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00);
|
||||||
SCSICallback[id]=50*SCSI_TIME;
|
SCSICallback[id]=50*SCSI_TIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Continue reading data until the sector length is 0.
|
//Continue reading data until the sector length is 0.
|
||||||
data += read_length;
|
data += read_length;
|
||||||
datalen -= read_length;
|
datalen -= read_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
//pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * 2048);
|
pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * cdrom_sector_size);
|
||||||
|
|
||||||
SectorLBA++;
|
SectorLBA++;
|
||||||
SectorLen--;
|
SectorLen--;
|
||||||
|
|
||||||
if (SectorLen == 0)
|
if (SectorLen == 0)
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user