From 3f086f752329d29fc6b21c2fa33ff7646fdfb345 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sun, 1 Jan 2017 00:36:22 +0100 Subject: [PATCH] Buslogic now fully working on DOS and NT (probably Win9x too) Removed unused c sources. SCSI layer bugfixes. --- src/buslogic.c | 271 +++++++++++++++++++++++--------------------- src/scattergather.c | 149 ------------------------ src/scattergather.h | 24 ---- src/scsi.c | 4 +- src/scsi_cdrom.c | 186 ++++++++++++++---------------- 5 files changed, 232 insertions(+), 402 deletions(-) delete mode 100644 src/scattergather.c delete mode 100644 src/scattergather.h diff --git a/src/buslogic.c b/src/buslogic.c index 34d71f6d5..ab7267247 100644 --- a/src/buslogic.c +++ b/src/buslogic.c @@ -513,7 +513,6 @@ typedef struct __attribute__((packed)) Buslogic_t int DmaChannel; int IrqEnabled; int Mbx24bit; - int CommandEnable; } Buslogic_t; int scsi_base = 0x330; @@ -522,6 +521,8 @@ int scsi_irq = 11; int buslogic_do_log = 0; +static void BuslogicStartMailbox(Buslogic_t *Buslogic); + void BuslogicLog(const char *format, ...) { 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; 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)); } 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)); } @@ -690,7 +691,10 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB 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) { @@ -727,11 +731,12 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB 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 - //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) { ScatterGatherLeft = DataLength / (Is24bit ? sizeof(SGE) : sizeof(SGE32)); ScatterGatherAddrCurrent = DataPointer; + uint8_t *DataBuffer = (uint8_t *)SCSIDevices[scsi_cdrom_id].CmdBuffer; do { @@ -749,7 +754,8 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, CCBU *CmdB Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; 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)); @@ -779,11 +785,14 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) DataPointer = BuslogicRequests->CmdBlock.new.DataPointer; 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 - //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 || BuslogicRequests->CmdBlock.common.ControlByte == 0x00)) { @@ -795,6 +804,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) SGE32 ScatterGatherBuffer[MAX_SG_DESCRIPTORS]; uint32_t ScatterGatherLeft = DataLength / (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); uint32_t ScatterGatherAddrCurrent = DataPointer; + uint8_t *DataBuffer = (uint8_t *)SCSIDevices[scsi_cdrom_id].CmdBuffer; do { @@ -813,7 +823,8 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; 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)); @@ -826,6 +837,21 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) 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) @@ -1273,7 +1299,7 @@ static uint8_t BuslogicConvertSenseLength(uint8_t RequestSenseLength) else if (RequestSenseLength == 1) RequestSenseLength = 0; - pclog("Request Sense length %i\n", RequestSenseLength); + BuslogicLog("Request Sense length %i\n", RequestSenseLength); return RequestSenseLength; } @@ -1305,10 +1331,9 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co else { 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); } @@ -1316,31 +1341,7 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co free(BuslogicRequests->RequestSenseBuffer); } -static void BuslogicSCSIRequestComplete(Buslogic_t *Buslogic, BuslogicRequests_t *BuslogicRequests) -{ - 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) +static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, Mailbox32_t *Mailbox32) { BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; CCBU CmdBlock; @@ -1358,7 +1359,7 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer) 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 (Id == scsi_cdrom_id) + if (Id == scsi_cdrom_id && Lun == 0) { 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)); - BuslogicSenseBufferAllocate(BuslogicRequests); - - 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) + if (Mailbox32->u.out.ActionCode == MBO_START) { - SCSIRead(Id, SCSIDevices[Id].InitLength); - } - else if (CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) - { - SCSIWrite(Id, SCSIDevices[Id].InitLength); - } + BuslogicSenseBufferAllocate(BuslogicRequests); + + BuslogicDataBufferAllocate(BuslogicRequests, &BuslogicRequests->CmdBlock, BuslogicRequests->Is24bit); - //Finally, execute the SCSI command immediately and get the transfer length. - SCSIPhase = SCSI_PHASE_COMMAND; - SCSIExecCommand(Id, Lun, BuslogicRequests->CmdBlock.common.Cdb); - SCSIGetLength(Id, &SCSIDevices[Id].InitLength); - - if (SCSIPhase == SCSI_PHASE_DATAIN) - { - SCSIReadData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); - } + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (!(SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & ALLOW_UA) && SCSISense.UnitAttention) + { + SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); + SCSIStatus = SCSI_STATUS_CHECK_CONDITION; + SCSICallback[Id]=50*SCSI_TIME; + } + + /* 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 || - BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) - { - if (BuslogicRequests->Is24bit) + /* Next it's time for NOT READY. */ + if ((SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & CHECK_READY) && !cdrom->ready()) { - U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[Id].InitLength); - BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength)); - } - else + BuslogicLog("Not ready\n"); + SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); + SCSIStatus = SCSI_STATUS_CHECK_CONDITION; + 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; - BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength); + SCSIRead(Id, SCSIDevices[Id].InitLength); } + 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"); - 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 { - BuslogicDataBufferFree(BuslogicRequests); - - if (BuslogicRequests->RequestSenseBuffer) - BuslogicSenseBufferFree(BuslogicRequests, 1); + if (Mailbox32->u.out.ActionCode == MBO_START) + { + BuslogicDataBufferFree(BuslogicRequests); + + if (BuslogicRequests->RequestSenseBuffer) + BuslogicSenseBufferFree(BuslogicRequests, 1); + } BuslogicMailboxIn(Buslogic, CCBPointer, &CmdBlock, CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); + + 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); } -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) { Mailbox_t MailboxOut; @@ -1517,21 +1538,16 @@ static void BuslogicStartMailbox(Buslogic_t *Buslogic) 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"); - BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer); + BuslogicSCSIRequestSetup(Buslogic, Mailbox32.CCBPointer, &Mailbox32); } else if (Mailbox32.u.out.ActionCode == MBO_ABORT) { BuslogicLog("Abort Mailbox Command\n"); BuslogicSCSIRequestAbort(Buslogic, Mailbox32.CCBPointer); } - else - { - BuslogicLog("Free Mailbox Command\n"); - BuslogicSCSIRequestFree(Buslogic, Mailbox32.CCBPointer); - } } void BuslogicCommandCallback(void *p) @@ -1539,8 +1555,10 @@ void BuslogicCommandCallback(void *p) Buslogic_t *Buslogic = (Buslogic_t *)p; SCSICallback[scsi_cdrom_id] = 0; - if (Buslogic->MailboxCount) + if (Buslogic->MailboxCount) + { BuslogicStartMailbox(Buslogic); + } } void *BuslogicInit() @@ -1552,12 +1570,11 @@ void *BuslogicInit() Buslogic->DmaChannel = scsi_dma; io_sethandler(scsi_base, 0x0004, BuslogicRead, NULL, NULL, BuslogicWrite, NULL, NULL, Buslogic); - timer_add(BuslogicCommandCallback, &SCSICallback[scsi_cdrom_id], &SCSICallback[scsi_cdrom_id], Buslogic); BuslogicLog("Buslogic on port 0x%04X\n", scsi_base); - BuslogicReset(Buslogic); + BuslogicResetControl(Buslogic, CTRL_HRST); return Buslogic; } diff --git a/src/scattergather.c b/src/scattergather.c deleted file mode 100644 index 8965d4bac..000000000 --- a/src/scattergather.c +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright holders: SA1988 - see COPYING for more details -*/ -/*Scatter/Gather emulation*/ -#include -#include -#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; - } -} \ No newline at end of file diff --git a/src/scattergather.h b/src/scattergather.h deleted file mode 100644 index 99c142ae1..000000000 --- a/src/scattergather.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/scsi.c b/src/scsi.c index 7649847a8..e98855066 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -23,9 +23,9 @@ void SCSIGetLength(uint8_t id, int *datalen) } //Execute SCSI command -void SCSIExecCommand(uint8_t id, uint8_t 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 diff --git a/src/scsi_cdrom.c b/src/scsi_cdrom.c index bc862411a..4c1ea766f 100644 --- a/src/scsi_cdrom.c +++ b/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); } -static void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA) +void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA) { if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA) { @@ -678,7 +678,65 @@ static int SCSICDROM_TOC(uint8_t id, uint8_t *cdb) 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 pos=0; @@ -694,14 +752,6 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb) int max_length = 0; int track = 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; @@ -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 execution under it, error out and report the condition. */ +#if 0 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); SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSICallback[id]=50*SCSI_TIME; return; } +#endif if (cdb[0] == GPCMD_READ_TOC_PMA_ATIP) SCSISense.UnitAttention = 0; - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - clear the UNIT ATTENTION condition if it's set. */ - if (cdb[0]!=GPCMD_REQUEST_SENSE) - { - SCSIClearSense(cdb[0], 1); - } - +#if 0 /* Next it's time for NOT 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; return; } +#endif prev_status = cd_status; cd_status = cdrom->status(); @@ -770,62 +817,7 @@ void SCSICDROM_Command(uint8_t id, uint8_t lun, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - len = cdb[4]; - - /*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); + SCSICDROMRequestSense(id, cdb, sense); break; 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)) { - //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; SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); 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: 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 { @@ -1056,10 +1048,6 @@ SCSIOut: { SCSIStatus = SCSI_STATUS_CHECK_CONDITION; 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; break; } @@ -1199,7 +1187,7 @@ SCSIOut: SCSIDevices[id].CmdBufferLength = 8; SCSIDMAResetPosition(id); - return; + break; case GPCMD_PLAY_AUDIO_10: 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; @@ -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_CD_MSF: case GPCMD_READ_CD: - //pclog("Total data length requested: %d\n", datalen); + pclog("Total data length requested: %d\n", datalen); while (datalen > 0) { - read_length = cdrom_read_data(data); //Fill the buffer the data it needs - if (!read_length) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); - SCSICallback[id]=50*SCSI_TIME; - break; - } - else - { + read_length = cdrom_read_data(data); //Fill the buffer the data it needs + if (!read_length) + { + SCSIStatus = SCSI_STATUS_CHECK_CONDITION; + SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0x00); + SCSICallback[id]=50*SCSI_TIME; + break; + } + else + { //Continue reading data until the sector length is 0. data += 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++; SectorLen--; if (SectorLen == 0) - { break; - } } - break; + return; } }