Various fixes, resulting from (more) Linux work.

Upstream commits applied.
This commit is contained in:
waltje
2018-10-08 02:27:07 -04:00
parent 6a6f23fe68
commit 5d6b369df8
15 changed files with 343 additions and 214 deletions

View File

@@ -11,7 +11,7 @@
*
* NOTE: This code now only supports targets at LUN=0 !!
*
* Version: @(#)scsi_ncr5380.c 1.0.8 2018/10/05
* Version: @(#)scsi_ncr5380.c 1.0.9 2018/10/07
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -216,13 +216,15 @@ get_dev_id(uint8_t data)
static int
get_cmd_len(int cbyte)
{
int len;
int len = 12;
int group;
group = (cbyte>>5) & 7;
group = (cbyte >> 5) & 7;
if (group == 0) len = 6;
if (group == 1 || group == 2) len = 10;
if (group == 0)
len = 6;
if (group == 1 || group == 2)
len = 10;
return(len);
}
@@ -881,6 +883,7 @@ ncr_callback(void *priv)
ncr5380_t *ncr_dev = (ncr5380_t *)priv;
ncr_t *ncr = &ncr_dev->ncr;
scsi_device_t *dev = &SCSIDevices[ncr->target_id][ncr->target_lun];
int64_t p;
int c = 0;
DEBUG("DMA mode=%d\n", ncr->dma_mode);
@@ -928,79 +931,71 @@ ncr_callback(void *priv)
}
}
} else if (ncr->state == STATE_COMMAND) {
int64_t p;
/*Command phase, make sure the ICR ACK bit is set to keep on,
because the device must be acknowledged by ICR*/
DEBUG("NCR ICR for Command=%02x\n", ncr->bus_host & BUS_ACK);
if (ncr->bus_host & BUS_ACK) {
/*Write command byte to the output data register*/
ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host);
if (ncr->command_pos < get_cmd_len(ncr->command[0])) {
/*Write command byte to the output data register*/
ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host);
ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN;
ncr->clear_req = 3;
DEBUG("Current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ);
ncr->cur_bus &= ~BUS_REQ;
ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN;
ncr->clear_req = 3;
DEBUG("NCR: current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ);
ncr->cur_bus &= ~BUS_REQ;
DEBUG("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host));
if (get_cmd_len(ncr->command[0]) == ncr->command_pos) {
/*Reset data position to default*/
ncr->data_pos = 0;
dev = &SCSIDevices[ncr->target_id][ncr->target_lun];
DEBUG("NCR: Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host));
if (get_cmd_len(ncr->command[0]) == ncr->command_pos) {
/*Reset data position to default*/
ncr->data_pos = 0;
DEBUG("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status);
dev = &SCSIDevices[ncr->target_id][ncr->target_lun];
dev->BufferLength = -1;
DEBUG("NCR: SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status);
/*Now, execute the given SCSI command*/
scsi_device_command_phase0(ncr->target_id, ncr->target_lun, ncr->command);
dev->BufferLength = -1;
DEBUG("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase);
/*Now, execute the given SCSI command*/
scsi_device_command_phase0(ncr->target_id, ncr->target_lun, ncr->command);
DEBUG("NCR: SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase);
if (dev->Status != SCSI_STATUS_OK)
ncr_dev->is_non_data_mode = 1;
if (ncr_dev->is_non_data_mode) {
ncr_dev->is_non_data_mode = 0;
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
return;
}
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) {
dev->CmdBuffer = (uint8_t *)mem_alloc(dev->BufferLength);
p = scsi_device_get_callback(ncr->target_id, ncr->target_lun);
if (p <= 0LL) {
ncr_dev->temp_period = (int64_t)(dev->BufferLength);
ncr_dev->media_period = 0;
ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, ncr_dev->temp_period));
if (dev->Status != SCSI_STATUS_OK)
ncr_dev->is_non_data_mode = 1;
if (ncr_dev->is_non_data_mode) {
ncr_dev->is_non_data_mode = 0;
ncr->new_phase = SCSI_PHASE_STATUS;
ncr->wait_data = 4;
return;
}
/*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/
if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) {
dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength);
p = scsi_device_get_callback(ncr->target_id, ncr->target_lun);
if (p <= 0LL) {
ncr_dev->temp_period = (int64_t)(dev->BufferLength);
ncr_dev->media_period = 0;
ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) MIN(64, ncr_dev->temp_period));
} else {
ncr_dev->media_period += p;
ncr_dev->temp_period = dev->BufferLength;
ncr_dev->period = (p / ((double) ncr_dev->temp_period)) * ((double) MIN(64, ncr_dev->temp_period));
}
}
if (dev->Phase == SCSI_PHASE_DATA_OUT) {
/* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */
DEBUG("NCR: Next state is data out\n");
ncr->new_phase = SCSI_PHASE_DATA_OUT;
ncr->wait_data = 4;
ncr->clear_req = 4;
} else {
ncr_dev->media_period += p;
ncr_dev->temp_period = dev->BufferLength;
ncr_dev->period = (p / ((double) ncr_dev->temp_period)) * ((double) MIN(64, ncr_dev->temp_period));
/* Other command - execute immediately. */
ncr->new_phase = dev->Phase;
if (ncr->new_phase == SCSI_PHASE_DATA_IN)
scsi_device_command_phase1(ncr->target_id, ncr->target_lun);
ncr->wait_data = 4;
}
}
if (dev->Phase == SCSI_PHASE_DATA_OUT) {
/* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */
DEBUG("Next state is data out\n");
ncr->new_phase = SCSI_PHASE_DATA_OUT;
ncr->wait_data = 4;
ncr->clear_req = 4;
} else {
/* Other command - execute immediately. */
ncr->new_phase = dev->Phase;
if (ncr->new_phase == SCSI_PHASE_DATA_IN) {
scsi_device_command_phase1(ncr->target_id, ncr->target_lun);
}
ncr->wait_data = 4;
}
}
}
}
} else if (ncr->state == STATE_DATAIN) {
dev = &SCSIDevices[ncr->target_id][ncr->target_lun];