Further changed the Adaptec/BusLogic SCSI callback function from 3-phased to 5-phased, should hopefully further stabilize things.

This commit is contained in:
OBattler
2019-09-25 12:20:43 +02:00
parent 5457352451
commit f6cebad16d
2 changed files with 92 additions and 58 deletions

View File

@@ -891,81 +891,106 @@ static void
x54x_scsi_cmd(x54x_t *dev)
{
Req_t *req = &dev->Req;
uint8_t id, phase, bit24 = !!req->Is24bit;
#ifdef ENABLE_X54X_LOG
uint8_t lun;
#endif
uint8_t temp_cdb[12];
uint32_t i, SenseBufferAddress;
int target_data_len, target_cdb_len = 12;
double p;
uint8_t bit24 = !!req->Is24bit;
uint32_t i, target_cdb_len = 12;
scsi_device_t *sd;
id = req->TargetID;
sd = &scsi_devices[id];
#ifdef ENABLE_X54X_LOG
lun = req->LUN;
#endif
sd = &scsi_devices[req->TargetID];
target_cdb_len = 12;
target_data_len = x54x_get_length(dev, req, bit24);
dev->target_data_len = x54x_get_length(dev, req, bit24);
if (!scsi_device_valid(sd))
fatal("SCSI target on %02i has disappeared\n", id);
fatal("SCSI target on %02i has disappeared\n", req->TargetID);
x54x_log("target_data_len = %i\n", target_data_len);
x54x_log("dev->target_data_len = %i\n", dev->target_data_len);
x54x_log("SCSI command being executed on ID %i, LUN %i\n", id, lun);
x54x_log("SCSI command being executed on ID %i, LUN %i\n", req->TargetID, req->LUN);
x54x_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]);
for (i=1; i<req->CmdBlock.common.CdbLength; i++)
x54x_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]);
memset(temp_cdb, 0x00, target_cdb_len);
memset(dev->temp_cdb, 0x00, target_cdb_len);
if (req->CmdBlock.common.CdbLength <= target_cdb_len) {
memcpy(temp_cdb, req->CmdBlock.common.Cdb,
memcpy(dev->temp_cdb, req->CmdBlock.common.Cdb,
req->CmdBlock.common.CdbLength);
x54x_add_to_period(dev, req->CmdBlock.common.CdbLength);
} else {
memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len);
memcpy(dev->temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len);
x54x_add_to_period(dev, target_cdb_len);
}
dev->Residue = 0;
sd->buffer_length = target_data_len;
sd->buffer_length = dev->target_data_len;
scsi_device_command_phase0(sd, temp_cdb);
phase = sd->phase;
scsi_device_command_phase0(sd, dev->temp_cdb);
dev->scsi_cmd_phase = sd->phase;
x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03));
if (phase != SCSI_PHASE_STATUS) {
if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) {
/* Request sense in non-data mode - sense goes to sense buffer. */
sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) {
SenseBufferAddress = SenseBufferPointer(req);
DMAPageWrite(SenseBufferAddress, scsi_devices[id].sc->temp_buffer, sd->buffer_length);
x54x_add_to_period(dev, sd->buffer_length);
}
scsi_device_command_phase1(sd);
} else {
if (dev->scsi_cmd_phase == SCSI_PHASE_STATUS)
dev->callback_sub_phase = 3;
else
dev->callback_sub_phase = 2;
x54x_log("scsi_devices[%02i].Status = %02X\n", id, sd->status);
}
static void
x54x_scsi_cmd_phase1(x54x_t *dev)
{
Req_t *req = &dev->Req;
double p;
uint8_t bit24 = !!req->Is24bit;
scsi_device_t *sd;
sd = &scsi_devices[req->TargetID];
if (dev->scsi_cmd_phase != SCSI_PHASE_STATUS) {
if ((dev->temp_cdb[0] != 0x03) || (req->CmdBlock.common.ControlByte != 0x03)) {
p = scsi_device_get_callback(sd);
if (p <= 0.0)
x54x_add_to_period(dev, sd->buffer_length);
else
dev->media_period += p;
x54x_buf_dma_transfer(dev, req, bit24, target_data_len, (phase == SCSI_PHASE_DATA_OUT));
x54x_buf_dma_transfer(dev, req, bit24, dev->target_data_len, (dev->scsi_cmd_phase == SCSI_PHASE_DATA_OUT));
scsi_device_command_phase1(sd);
SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK));
}
}
dev->callback_sub_phase = 3;
x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status);
}
static void
x54x_request_sense(x54x_t *dev)
{
Req_t *req = &dev->Req;
uint32_t SenseBufferAddress;
scsi_device_t *sd;
sd = &scsi_devices[req->TargetID];
if (dev->scsi_cmd_phase != SCSI_PHASE_STATUS) {
if ((dev->temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) {
/* Request sense in non-data mode - sense goes to sense buffer. */
sd->buffer_length = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
if ((sd->status != SCSI_STATUS_OK) && (sd->buffer_length > 0)) {
SenseBufferAddress = SenseBufferPointer(req);
DMAPageWrite(SenseBufferAddress, scsi_devices[req->TargetID].sc->temp_buffer, sd->buffer_length);
x54x_add_to_period(dev, sd->buffer_length);
}
scsi_device_command_phase1(sd);
} else
SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK));
} else
SenseBufferFree(dev, req, (sd->status != SCSI_STATUS_OK));
x54x_set_residue(dev, req, target_data_len);
x54x_set_residue(dev, req, dev->target_data_len);
x54x_log("Request complete\n");
@@ -977,7 +1002,8 @@ x54x_scsi_cmd(x54x_t *dev)
CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR);
}
x54x_log("scsi_devices[%02i].Status = %02X\n", id, sd->status);
dev->callback_sub_phase = 4;
x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status);
}
@@ -1029,7 +1055,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
x54x_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun);
x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock,
CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
dev->callback_sub_phase = 2;
dev->callback_sub_phase = 4;
return;
}
@@ -1042,7 +1068,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
x54x_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun);
x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock,
CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR);
dev->callback_sub_phase = 2;
dev->callback_sub_phase = 4;
} else {
x54x_log("SCSI Target ID %i detected and working\n", id);
@@ -1053,7 +1079,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
x54x_log("Invalid opcode: %02X\n",
req->CmdBlock.common.ControlByte);
x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_OP_CODE, SCSI_STATUS_OK, MBI_ERROR);
dev->callback_sub_phase = 2;
dev->callback_sub_phase = 4;
return;
}
if (req->CmdBlock.common.Opcode == 0x81) {
@@ -1061,7 +1087,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
scsi_device_reset(sd);
x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock,
CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS);
dev->callback_sub_phase = 2;
dev->callback_sub_phase = 4;
return;
}
@@ -1069,7 +1095,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
x54x_log("Invalid control byte: %02X\n",
req->CmdBlock.common.ControlByte);
x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_DIRECTION, SCSI_STATUS_OK, MBI_ERROR);
dev->callback_sub_phase = 2;
dev->callback_sub_phase = 4;
return;
}
@@ -1089,7 +1115,7 @@ x54x_req_abort(x54x_t *dev, uint32_t CCBPointer)
x54x_mbi_setup(dev, CCBPointer, &CmdBlock,
0x26, SCSI_STATUS_OK, MBI_NOT_FOUND);
dev->callback_sub_phase = 2;
dev->callback_sub_phase = 4;
}
@@ -1203,7 +1229,7 @@ x54x_cmd_done(x54x_t *dev, int suppress);
static void
x54x_cmd_callback(void *priv)
{
double period, cb_period = 10.0;
double period;
x54x_t *dev = (x54x_t *) priv;
int mailboxes_present, bios_mailboxes_present;
@@ -1226,17 +1252,22 @@ x54x_cmd_callback(void *priv)
dev->callback_phase ^= 1;
break;
case 1:
/* Sub-phase 1 - Do SCSI command. */
/* Sub-phase 1 - Do SCSI command phase 0. */
x54x_log("%s: Callback: Process SCSI request\n", dev->name);
x54x_scsi_cmd(dev);
/* Go to notify phase. */
dev->callback_sub_phase = 2;
cb_period = 20.0;
break;
case 2:
/* Sub-phase 2 - Notify. */
case 2:
/* Sub-phase 2 - Do SCSI command phase 1. */
x54x_log("%s: Callback: Process SCSI request\n", dev->name);
x54x_scsi_cmd_phase1(dev);
break;
case 3:
/* Sub-phase 3 - Request sense. */
x54x_log("%s: Callback: Process SCSI request\n", dev->name);
x54x_request_sense(dev);
break;
case 4:
/* Sub-phase 4 - Notify. */
x54x_log("%s: Callback: Send incoming mailbox\n", dev->name);
x54x_notify(dev);
@@ -1260,7 +1291,7 @@ x54x_cmd_callback(void *priv)
}
period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period);
timer_on(&dev->timer, dev->media_period + period + cb_period, 0);
timer_on(&dev->timer, dev->media_period + period + 10.0, 0);
x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period);
}

View File

@@ -381,13 +381,15 @@ typedef struct {
uint8_t callback_phase :4,
callback_sub_phase :4,
scsi_cmd_phase, pad,
sync,
parity, shram_mode,
Geometry, Control,
Command, CmdParam,
BusOnTime, BusOffTime,
ATBusSpeed, setup_info_len,
max_id, pci_slot;
max_id, pci_slot,
temp_cdb[12];
volatile uint8_t /* for multi-threading, keep */
Status, Interrupt, /* these volatile */
@@ -418,7 +420,8 @@ typedef struct {
/* 16 + 20 + 52 = 88 bytes */
volatile int
MailboxOutInterrupts,
PendingInterrupt, Lock;
PendingInterrupt, Lock,
target_data_len, pad0;
uint32_t Base, rom_addr, /* address of BIOS ROM */
CmdParamLeft, Outgoing,