Two-phased SCSI write-direction commands on the AHA and BusLogic SCSI controllers, fixes residual lengths for such commands;

Cleaned up the handlers for the BusLogic Execute SCSI Command command;
Made the AHA-1542CF use version 2.01 of the BIOS;
The CD-ROM GET EVENT STATUS NOTIFICATION fix is back.
This commit is contained in:
OBattler
2017-10-11 01:17:41 +02:00
parent 5be5a38db6
commit 4484ce9597
9 changed files with 713 additions and 704 deletions

View File

@@ -9,7 +9,7 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)cdrom.c 1.0.14 2017/10/09
* Version: @(#)cdrom.c 1.0.15 2017/10/10
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -2016,47 +2016,6 @@ static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packe
}
}
/*SCSI Get Event Status Notification*/
static uint32_t cdrom_get_event_status(uint8_t id, uint8_t *buffer)
{
uint8_t event_code, media_status = 0;
if (buffer[5])
{
media_status = MS_TRAY_OPEN;
if (cdrom_drives[id].handler->stop)
{
cdrom_drives[id].handler->stop(id);
}
}
else
{
media_status = MS_MEDIA_PRESENT;
}
event_code = MEC_NO_CHANGE;
if (media_status != MS_TRAY_OPEN)
{
if (!buffer[4])
{
event_code = MEC_NEW_MEDIA;
cdrom_drives[id].handler->load(id);
}
else if (buffer[4]==2)
{
event_code = MEC_EJECT_REQUESTED;
cdrom_drives[id].handler->eject(id);
}
}
buffer[4] = event_code;
buffer[5] = media_status;
buffer[6] = 0;
buffer[7] = 0;
return 8;
}
void cdrom_insert(uint8_t id)
{
cdrom[id].unit_attention = 1;
@@ -2160,6 +2119,15 @@ skip_ready_check:
}
/* Next it's time for NOT READY. */
if (!ready)
{
cdrom[id].media_status = MEC_MEDIA_REMOVAL;
}
else
{
cdrom[id].media_status = (cdrom[id].unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE;
}
if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready)
{
cdrom_log("CD-ROM %i: Not ready (%02X)\n", id, cdb[0]);
@@ -2396,7 +2364,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
SCSIPhase = SCSI_PHASE_DATA_IN;
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
{
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (cdb[4] < SCSI_BufferLength))
{
SCSI_BufferLength = cdb[4];
}
@@ -2420,7 +2388,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2451,7 +2419,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
}
else
{
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2501,7 +2469,7 @@ cdrom_readtoc_fallback:
cdbufferb[1] = (len - 2) & 0xff;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2584,7 +2552,7 @@ cdrom_readtoc_fallback:
cdrom[id].packet_len = max_len * alloc_length;
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (cdrom[id].packet_len < SCSI_BufferLength))
{
SCSI_BufferLength = cdrom[id].packet_len;
}
@@ -2620,7 +2588,7 @@ cdrom_readtoc_fallback:
}
else
{
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2648,7 +2616,7 @@ cdrom_readtoc_fallback:
len = 8;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2729,7 +2697,7 @@ cdrom_readtoc_fallback:
alloc_length = len;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
{
SCSI_BufferLength = alloc_length;
}
@@ -2752,7 +2720,7 @@ cdrom_readtoc_fallback:
len = (cdb[7] << 8) | cdb[8];
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2814,7 +2782,7 @@ cdrom_readtoc_fallback:
cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff;
cdbufferb[3] = (alloc_length - 4) & 0xff;
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2864,7 +2832,12 @@ cdrom_readtoc_fallback:
if (gesn_cdb->class & (1 << GESN_MEDIA))
{
gesn_event_header->notification_class |= GESN_MEDIA;
used_len = cdrom_get_event_status(id, cdbufferb);
cdbufferb[4] = cdrom[id].media_status; /* Bits 7-4 = Reserved, Bits 4-1 = Media Status */
cdbufferb[5] = 1; /* Power Status (1 = Active) */
cdbufferb[6] = 0;
cdbufferb[7] = 0;
used_len = 8;
}
else
{
@@ -2873,7 +2846,9 @@ cdrom_readtoc_fallback:
}
gesn_event_header->len = used_len - sizeof(*gesn_event_header);
if (SCSI_BufferLength == -1)
memcpy(cdbufferb, gesn_event_header, 4);
if ((SCSI_BufferLength == -1) || (used_len < SCSI_BufferLength))
{
SCSI_BufferLength = used_len;
}
@@ -2917,7 +2892,7 @@ cdrom_readtoc_fallback:
len=34;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -2985,7 +2960,7 @@ cdrom_readtoc_fallback:
}
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -3154,7 +3129,7 @@ cdrom_readtoc_fallback:
}
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -3174,7 +3149,7 @@ cdrom_readtoc_fallback:
}
else
{
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -3224,7 +3199,7 @@ cdrom_readtoc_fallback:
{
ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb);
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
{
SCSI_BufferLength = alloc_length;
}
@@ -3361,7 +3336,7 @@ atapi_out:
cdbufferb[size_idx] = idx - preamble_len;
len=idx;
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -3430,7 +3405,7 @@ atapi_out:
return;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}

View File

@@ -59,11 +59,11 @@ static SCSI_CARD scsi_cards[] = {
{ "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, aha_device_reset },
{ "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, aha_device_reset },
{ "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, aha_device_reset },
{ "[ISA] BusLogic BT-545C", "bt545c", &buslogic_device, BuslogicDeviceReset },
{ "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,NULL },
{ "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, NULL },
{ "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, NULL },
{ "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, aha_device_reset },
{ "[PCI] BusLogic BT-545C", "bt545c", &buslogic_device, BuslogicDeviceReset },
{ "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, BuslogicDeviceReset },
{ "", "", NULL, NULL },
};

View File

@@ -12,7 +12,7 @@
*
* NOTE: THIS IS CURRENTLY A MESS, but will be cleaned up as I go.
*
* Version: @(#)scsi_aha154x.c 1.0.24 2017/10/09
* Version: @(#)scsi_aha154x.c 1.0.25 2017/10/10
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Original Buslogic version by SA1988 and Miran Grca.
@@ -390,6 +390,7 @@ typedef struct {
uint16_t rom_shramsz; /* size of shared RAM */
uint16_t rom_fwhigh; /* offset in BIOS of ver ID */
rom_t bios; /* BIOS memory descriptor */
rom_t uppersck; /* BIOS memory descriptor */
uint8_t *rom1; /* main BIOS image */
uint8_t *rom2; /* SCSI-Select image */
@@ -735,10 +736,13 @@ aha_ccb(aha_t *dev)
aha_log("CCB rewritten to the CDB (pointer %08X)\n", CCBPointer);
DMAPageWrite(CCBPointer, (char *)CmdBlock, 18);
dev->ToRaise = INTR_HACC | INTR_ANY;
if (dev->MailboxOutInterrupts)
{
dev->ToRaise |= INTR_MBOA;
dev->ToRaise = INTR_MBOA | INTR_ANY;
}
else
{
dev->ToRaise = 0;
}
}
@@ -822,10 +826,9 @@ aha_rd_sge(int Is24bit, uint32_t SGList, uint32_t Entries, SGE32 *SG)
}
static void
aha_buf_alloc(Req_t *req, int Is24bit)
static int
aha_get_length(Req_t *req, int Is24bit)
{
uint32_t sg_buffer_pos = 0;
uint32_t DataPointer, DataLength;
uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32));
uint32_t Address;
@@ -833,6 +836,7 @@ aha_buf_alloc(Req_t *req, int Is24bit)
if (Is24bit) {
DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer);
DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength);
aha_log("Data length: %08X\n", req->CmdBlock.old.DataLength);
} else {
DataPointer = req->CmdBlock.new.DataPointer;
DataLength = req->CmdBlock.new.DataLength;
@@ -875,15 +879,75 @@ aha_buf_alloc(Req_t *req, int Is24bit)
aha_log("Data to transfer (S/G) %d\n", DataToTransfer);
SCSI_BufferLength = DataToTransfer;
return DataToTransfer;
} else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND ||
req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) {
return DataLength;
} else {
return 0;
}
} else {
return 0;
}
}
aha_log("Allocating buffer for Scatter/Gather (%i bytes)\n", DataToTransfer);
SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(DataToTransfer);
memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, DataToTransfer);
static void
aha_residual_on_error(Req_t *req, int length)
{
if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) ||
(req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) {
/* Should be 0 when scatter/gather? */
if (req->Is24bit) {
U32_TO_ADDR(req->CmdBlock.old.DataLength, length);
aha_log("24-bit Residual data length for reading: %d\n",
ADDR_TO_U32(req->CmdBlock.old.DataLength));
} else {
req->CmdBlock.new.DataLength = length;
aha_log("32-bit Residual data length for reading: %d\n",
req->CmdBlock.new.DataLength);
}
}
}
static void
aha_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir)
{
uint32_t sg_buffer_pos = 0;
uint32_t DataPointer, DataLength;
uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32));
uint32_t Address;
uint32_t Residual;
/* uint32_t CCBPointer = req->CCBPointer; */
if (Is24bit) {
DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer);
DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength);
} else {
DataPointer = req->CmdBlock.new.DataPointer;
DataLength = req->CmdBlock.new.DataLength;
}
aha_log("Data Buffer %s: length %d, pointer 0x%04X\n",
dir ? "write" : "read", SCSI_BufferLength, DataPointer);
if ((req->CmdBlock.common.ControlByte != 0x03) && DataLength) {
if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND ||
req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) {
uint32_t SGRead;
uint32_t ScatterEntry;
SGE32 SGBuffer[MAX_SG_DESCRIPTORS];
uint32_t SGLeft = DataLength / SGEntryLength;
uint32_t SGAddrCurrent = DataPointer;
uint32_t DataToTransfer = 0;
TransferLength -= SCSI_BufferLength;
/* 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 read/write commands. */
if ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) ||
(req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) ||
(req->CmdBlock.common.ControlByte == 0x00)) {
SGLeft = DataLength / SGEntryLength;
SGAddrCurrent = DataPointer;
@@ -898,17 +962,32 @@ aha_buf_alloc(Req_t *req, int Is24bit)
for (ScatterEntry=0; ScatterEntry<SGRead; ScatterEntry++) {
aha_log("S/G Write: ScatterEntry=%u\n", ScatterEntry);
/* If we've already written all data, do nothing. */
if (SCSI_BufferLength <= 0)
{
continue;
}
Address = SGBuffer[ScatterEntry].SegmentPointer;
DataToTransfer = SGBuffer[ScatterEntry].Segment;
aha_log("S/G Write: Address=%08X DatatoTransfer=%u\n", Address, DataToTransfer);
aha_log("S/G Write: Address=%08X DatatoTransfer=%u\n", Address, (SCSI_BufferLength < DataToTransfer) ? SCSI_BufferLength : DataToTransfer);
DMAPageRead(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer);
if (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00)))
{
DMAPageRead(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, (SCSI_BufferLength < DataToTransfer) ? SCSI_BufferLength : DataToTransfer);
}
else
if (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00)))
{
DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, (SCSI_BufferLength < DataToTransfer) ? SCSI_BufferLength : DataToTransfer);
}
sg_buffer_pos += DataToTransfer;
SCSI_BufferLength -= DataToTransfer;
}
SGAddrCurrent += SGRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32));
} while (SGLeft > 0);
} while (SGLeft > 0);
}
} else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND ||
req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) {
@@ -916,104 +995,25 @@ aha_buf_alloc(Req_t *req, int Is24bit)
SCSI_BufferLength = DataLength;
aha_log("Allocating buffer for direct transfer (%i bytes)\n", DataLength);
SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(DataLength);
memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, DataLength);
if (DataLength > 0) {
DMAPageRead(Address,
(char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer,
SCSI_BufferLength);
if ((DataLength > 0) && (SCSI_BufferLength > 0)) {
if (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00)))
{
DMAPageRead(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, (SCSI_BufferLength < DataLength) ? SCSI_BufferLength : DataLength);
}
else
if (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00)))
{
DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, (SCSI_BufferLength < DataLength) ? SCSI_BufferLength : DataLength);
}
}
}
}
}
static void
aha_buf_free(Req_t *req)
{
SGE32 SGBuffer[MAX_SG_DESCRIPTORS];
uint32_t DataPointer = 0;
uint32_t DataLength = 0;
uint32_t sg_buffer_pos = 0;
uint32_t SGRead;
uint32_t ScatterEntry;
uint32_t SGEntrySize;
uint32_t SGLeft;
uint32_t SGAddrCurrent;
uint32_t Address;
uint32_t Residual;
uint32_t DataToTransfer;
if (req->Is24bit) {
DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer);
DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength);
} else {
DataPointer = req->CmdBlock.new.DataPointer;
DataLength = req->CmdBlock.new.DataLength;
}
if ((DataLength != 0) && (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY)) {
aha_log("Data length not 0 with TEST UNIT READY: %i (%i)\n",
DataLength, SCSI_BufferLength);
}
if (req->CmdBlock.common.Cdb[0] == GPCMD_TEST_UNIT_READY) {
DataLength = 0;
}
aha_log("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 read/write commands. */
if ((DataLength > 0) &&
((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) ||
(req->CmdBlock.common.ControlByte == 0x00))) {
if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) ||
(req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) {
SGEntrySize = (req->Is24bit ? sizeof(SGE) : sizeof(SGE32));
SGLeft = DataLength / SGEntrySize;
SGAddrCurrent = DataPointer;
do {
SGRead = (SGLeft < ELEMENTS(SGBuffer)) ? SGLeft : ELEMENTS(SGBuffer);
SGLeft -= SGRead;
aha_rd_sge(req->Is24bit, SGAddrCurrent,
SGRead, SGBuffer);
for (ScatterEntry=0; ScatterEntry<SGRead; ScatterEntry++) {
aha_log("S/G: ScatterEntry=%u\n", ScatterEntry);
Address = SGBuffer[ScatterEntry].SegmentPointer;
DataToTransfer = SGBuffer[ScatterEntry].Segment;
aha_log("S/G: Writing %i bytes at %08X\n", DataToTransfer, Address);
DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer + sg_buffer_pos, DataToTransfer);
sg_buffer_pos += DataToTransfer;
}
SGAddrCurrent += (SGRead * SGEntrySize);
} while (SGLeft > 0);
} else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND ||
req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) {
Address = DataPointer;
aha_log("DMA: Writing %i bytes at %08X\n",
DataLength, Address);
DMAPageWrite(Address, (char *)SCSIDevices[req->TargetID][req->LUN].CmdBuffer, DataLength);
}
}
if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) ||
(req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) {
/* Should be 0 when scatter/gather? */
if (DataLength >= SCSI_BufferLength) {
Residual = DataLength;
Residual -= SCSI_BufferLength;
if (TransferLength > 0) {
Residual = TransferLength;
} else {
Residual = 0;
}
@@ -1028,7 +1028,26 @@ aha_buf_free(Req_t *req)
req->CmdBlock.new.DataLength);
}
}
}
static void
aha_buf_alloc(Req_t *req, int length)
{
if (SCSIDevices[req->TargetID][req->LUN].CmdBuffer != NULL) {
free(SCSIDevices[req->TargetID][req->LUN].CmdBuffer);
SCSIDevices[req->TargetID][req->LUN].CmdBuffer = NULL;
}
aha_log("Allocating data buffer (%i bytes)\n", length);
SCSIDevices[req->TargetID][req->LUN].CmdBuffer = (uint8_t *) malloc(length);
memset(SCSIDevices[req->TargetID][req->LUN].CmdBuffer, 0, length);
}
static void
aha_buf_free(Req_t *req)
{
if (SCSIDevices[req->TargetID][req->LUN].CmdBuffer != NULL) {
free(SCSIDevices[req->TargetID][req->LUN].CmdBuffer);
SCSIDevices[req->TargetID][req->LUN].CmdBuffer = NULL;
@@ -1059,7 +1078,7 @@ SenseBufferFree(Req_t *req, int Copy)
uint32_t SenseBufferAddress;
uint8_t temp_sense[256];
if (SenseLength && Copy) {
if (SenseLength/* && Copy*/) {
scsi_device_request_sense(req->TargetID, req->LUN, temp_sense, SenseLength);
/*
@@ -1093,15 +1112,20 @@ aha_scsi_cmd(aha_t *dev)
uint8_t temp_cdb[12];
uint32_t i;
int target_cdb_len = 12;
int target_data_len;
uint8_t bit24 = !!req->Is24bit;
id = req->TargetID;
lun = req->LUN;
target_cdb_len = scsi_device_cdb_length(id, lun);
target_data_len = aha_get_length(req, bit24);
if (!scsi_device_valid(id, lun))
fatal("SCSI target on %02i:%02i has disappeared\n", id, lun);
aha_buf_alloc(req, target_data_len);
aha_log("SCSI command being executed on ID %i, LUN %i\n", id, lun);
aha_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]);
@@ -1116,7 +1140,24 @@ aha_scsi_cmd(aha_t *dev)
memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len);
}
scsi_device_command(id, lun, req->CmdBlock.common.CdbLength, temp_cdb);
SCSI_BufferLength = target_data_len;
scsi_device_command_phase0(id, lun, req->CmdBlock.common.CdbLength, temp_cdb);
if (SCSIPhase == SCSI_PHASE_DATA_OUT)
{
aha_buf_dma_transfer(req, bit24, target_data_len, 1);
scsi_device_command_phase1(id, lun);
}
else if (SCSIPhase == SCSI_PHASE_DATA_IN)
{
aha_buf_dma_transfer(req, bit24, target_data_len, 0);
}
else
{
if (target_data_len) {
aha_residual_on_error(req, target_data_len);
}
}
aha_buf_free(req);
@@ -1132,6 +1173,8 @@ aha_scsi_cmd(aha_t *dev)
CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR);
}
aha_log("SCSIStatus = %02X\n", SCSIStatus);
if (temp_cdb[0] == 0x42) {
thread_wait_event(dev->evt, 10);
}
@@ -1158,6 +1201,7 @@ aha_req_setup(aha_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
Req_t *req = &dev->Req;
uint8_t id, lun;
uint8_t max_id = SCSI_ID_MAX-1;
int len;
/* Fetch data from the Command Control Block. */
DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32));
@@ -1182,11 +1226,12 @@ aha_req_setup(aha_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
SCSIStatus = SCSI_STATUS_OK;
SCSI_BufferLength = 0;
aha_buf_alloc(req, req->Is24bit);
if (! scsi_device_present(id, lun)) {
aha_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun);
aha_buf_free(req);
len = aha_get_length(req, req->Is24bit);
if (len) {
aha_residual_on_error(req, len);
}
SenseBufferFree(req, 0);
aha_mbi_setup(dev, CCBPointer, &req->CmdBlock,
CCB_SELECTION_TIMEOUT,SCSI_STATUS_OK,MBI_ERROR);
@@ -1232,12 +1277,14 @@ aha_mbo(aha_t *dev, Mailbox32_t *Mailbox32)
{
Mailbox_t MailboxOut;
uint32_t Outgoing;
uint32_t ccbp;
if (dev->Mbx24bit) {
Outgoing = dev->MailboxOutAddr + (dev->MailboxOutPosCur * sizeof(Mailbox_t));
DMAPageRead(Outgoing, (char *)&MailboxOut, sizeof(Mailbox_t));
Mailbox32->CCBPointer = ADDR_TO_U32(MailboxOut.CCBPointer);
ccbp = *(uint32_t *) &MailboxOut;
Mailbox32->CCBPointer = (ccbp >> 24) | ((ccbp >> 8) & 0xff00) | ((ccbp << 8) & 0xff0000);
Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus;
} else {
Outgoing = dev->MailboxOutAddr + (dev->MailboxOutPosCur * sizeof(Mailbox32_t));
@@ -1267,8 +1314,6 @@ aha_do_mail(aha_t *dev)
CodeOffset = dev->Mbx24bit ? 0 : 7;
uint8_t MailboxCur = dev->MailboxOutPosCur;
/* Search for a filled mailbox - stop if we have scanned all mailboxes. */
do {
/* Fetch mailbox from guest memory. */
@@ -1276,7 +1321,7 @@ aha_do_mail(aha_t *dev)
/* Check the next mailbox. */
aha_mbo_adv(dev);
} while ((mb32.u.out.ActionCode != MBO_START) && (mb32.u.out.ActionCode != MBO_ABORT) && (MailboxCur != dev->MailboxOutPosCur));
} while ((mb32.u.out.ActionCode != MBO_START) && (dev->MailboxIsBIOS || (mb32.u.out.ActionCode != MBO_ABORT)));
if (mb32.u.out.ActionCode == MBO_START) {
aha_log("Start Mailbox Command\n");
@@ -1288,14 +1333,17 @@ aha_do_mail(aha_t *dev)
aha_log("Invalid action code: %02X\n", mb32.u.out.ActionCode);
}
if ((mb32.u.out.ActionCode == MBO_START) || (mb32.u.out.ActionCode == MBO_ABORT)) {
if ((mb32.u.out.ActionCode == MBO_START) || (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT))) {
/* We got the mailbox, mark it as free in the guest. */
aha_log("aha_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus));
DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, 1);
raise_irq(dev, 0, dev->ToRaise);
if (dev->ToRaise)
{
raise_irq(dev, 0, dev->ToRaise);
while (dev->Interrupt) {
while (dev->Interrupt) {
}
}
}
}
@@ -1967,13 +2015,15 @@ aha_setbios(aha_t *dev)
*
* Start out with a fake BIOS firmware version.
*/
dev->fwh = '1';
dev->fwl = '0';
dev->fwh = '3';
dev->fwl = '4';
#if 0
if (dev->rom_fwhigh != 0x0000) {
/* Read firmware version from the BIOS. */
dev->fwh = dev->bios.rom[dev->rom_fwhigh] + 0x30;
dev->fwl = dev->bios.rom[dev->rom_fwhigh+1] + 0x30;
}
#endif
}
@@ -2081,7 +2131,7 @@ aha_init(device_t *info)
case AHA_154xCF:
strcpy(dev->name, "AHA-154xCF");
dev->bios_path = L"roms/scsi/adaptec/aha1542cf211.bin";
dev->bios_path = L"roms/scsi/adaptec/aha1542cf201.bin";
dev->nvr_path = L"aha1542cf.nvr";
dev->bid = 'E';
dev->rom_shram = 0x3F80; /* shadow RAM address base */

View File

@@ -273,7 +273,7 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cmd_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
if (sector_len > 0) {
cmd_log("BIOS DMA: Reading %i bytes at %08X\n",
SCSI_BufferLength, dma_address);
@@ -295,13 +295,6 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
dev->CmdBuffer = (uint8_t *)malloc(SCSI_BufferLength);
memset(dev->CmdBuffer, 0x00, SCSI_BufferLength);
if (sector_len > 0) {
cmd_log("BIOS DMA: Reading %i bytes at %08X\n",
SCSI_BufferLength, dma_address);
DMAPageRead(dma_address,
(char *)dev->CmdBuffer, SCSI_BufferLength);
}
cdb[0] = GPCMD_WRITE_10;
cdb[1] = (cmd->lun & 7) << 5;
cdb[2] = (lba >> 24) & 0xff;
@@ -314,7 +307,16 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cmd_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount);
#endif
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
if (sector_len > 0) {
cmd_log("BIOS DMA: Reading %i bytes at %08X\n",
SCSI_BufferLength, dma_address);
DMAPageRead(dma_address,
(char *)dev->CmdBuffer, SCSI_BufferLength);
}
scsi_device_command_phase1(cmd->id, cmd->lun);
if (dev->CmdBuffer != NULL) {
free(dev->CmdBuffer);
@@ -335,7 +337,7 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cdb[7] = (sector_len >> 8) & 0xff;
cdb[8] = sector_len & 0xff;
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
@@ -353,7 +355,7 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cdb[0] = GPCMD_FORMAT_UNIT;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
@@ -394,7 +396,7 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cdb[4] = (lba >> 8) & 0xff;
cdb[5] = lba & 0xff;
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
return((SCSIStatus == SCSI_STATUS_OK) ? 1 : 0);
@@ -408,7 +410,7 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cdb[0] = GPCMD_TEST_UNIT_READY;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));
@@ -418,7 +420,7 @@ scsi_bios_command(uint8_t max_id, BIOSCMD *cmd, int8_t islba)
cdb[0] = GPCMD_REZERO_UNIT;
cdb[1] = (cmd->lun & 7) << 5;
scsi_device_command(cmd->id, cmd->lun, 12, cdb);
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
return(completion_code(scsi_device_sense(cmd->id, cmd->lun)));

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
*
* The generic SCSI device command handler.
*
* Version: @(#)scsi_device.c 1.0.6 2017/10/07
* Version: @(#)scsi_device.c 1.0.7 2017/10/10
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -278,7 +278,7 @@ int scsi_device_block_shift(uint8_t scsi_id, uint8_t scsi_lun)
}
void scsi_device_command_common(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb, int multi_phase)
void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
{
uint8_t phase = 0;
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;
@@ -322,7 +322,7 @@ void scsi_device_command_common(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len,
scsi_device_target_phase_callback(lun_type, id);
} else {
/* Command first phase complete - call the callback to execute the second phase. */
if (multi_phase || (SCSIPhase != SCSI_PHASE_DATA_OUT))
if (SCSIPhase != SCSI_PHASE_DATA_OUT)
{
scsi_device_target_phase_callback(lun_type, id);
SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id);
@@ -336,16 +336,6 @@ void scsi_device_command_common(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len,
}
}
void scsi_device_command(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
{
scsi_device_command_common(scsi_id, scsi_lun, cdb_len, cdb, 1);
}
void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len, uint8_t *cdb)
{
scsi_device_command_common(scsi_id, scsi_lun, cdb_len, cdb, 0);
}
void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t lun_type = SCSIDevices[scsi_id][scsi_lun].LunType;

View File

@@ -8,7 +8,7 @@
*
* Definitions for the generic SCSI device command handler.
*
* Version: @(#)scsi_device.h 1.0.3 2017/10/04
* Version: @(#)scsi_device.h 1.0.4 2017/10/10
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>

View File

@@ -6,7 +6,7 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.c 1.0.12 2017/10/09
* Version: @(#)scsi_disk.c 1.0.13 2017/10/10
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2017 Miran Grca.
@@ -1469,7 +1469,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case GPCMD_REQUEST_SENSE:
/* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE
should forget about the not ready, and report unit attention straight away. */
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (cdb[4] < SCSI_BufferLength))
{
SCSI_BufferLength = cdb[4];
}
@@ -1487,7 +1487,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case GPCMD_MECHANISM_STATUS:
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -1538,7 +1538,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
alloc_length = shdc[id].packet_len = max_len << 9;
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
{
SCSI_BufferLength = alloc_length;
}
@@ -1640,7 +1640,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
alloc_length = len;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
{
SCSI_BufferLength = alloc_length;
}
@@ -1663,7 +1663,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
len = (cdb[7] << 8) | cdb[8];
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -1720,7 +1720,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
alloc_length = shdc[id].packet_len = max_len << 9;
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (alloc_length < SCSI_BufferLength))
{
SCSI_BufferLength = alloc_length;
}
@@ -1865,7 +1865,7 @@ atapi_out:
len = max_len;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}
@@ -1911,7 +1911,7 @@ atapi_out:
return;
}
if (SCSI_BufferLength == -1)
if ((SCSI_BufferLength == -1) || (len < SCSI_BufferLength))
{
SCSI_BufferLength = len;
}

View File

@@ -1044,7 +1044,7 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa
int c = 0;
int d = 0;
LPTSTR lptsTemp;
device_t *sound_dev, *midi_dev;
device_t *sound_dev/*, *midi_dev*/;
char *s;
switch (message)
@@ -1116,22 +1116,19 @@ static BOOL CALLBACK win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wPa
if (midi_device_available(c))
{
midi_dev = midi_device_getdevice(c);
/* midi_dev = midi_device_getdevice(c); */
if (midi_dev)
if (c == 0)
{
if (c == 0)
{
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2152));
}
else
{
mbstowcs(lptsTemp, s, strlen(s) + 1);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp);
}
settings_list_to_midi[d] = c;
d++;
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)plat_get_string(IDS_2152));
}
else
{
mbstowcs(lptsTemp, s, strlen(s) + 1);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp);
}
settings_list_to_midi[d] = c;
d++;
}
c++;