Fixed CD-ROM temporary buffer freeing and made the SCSI phase and SCSI status variable per-SCSI-device rather than two single global variables.

This commit is contained in:
OBattler
2018-01-06 22:47:41 +01:00
parent 2173f14ec0
commit 444fa519a7
9 changed files with 187 additions and 205 deletions

View File

@@ -9,11 +9,11 @@
* Implementation of the CD-ROM drive with SCSI(-like)
* commands, for both ATAPI and SCSI usage.
*
* Version: @(#)cdrom.c 1.0.25 2017/12/10
* Version: @(#)cdrom.c 1.0.26 2018/01/06
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016,2017 Miran Grca.
* Copyright 2016,2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
@@ -1406,9 +1406,20 @@ static void cdrom_sense_clear(int id, int command)
cdrom_sense_key = cdrom_asc = cdrom_ascq = 0;
}
static void cdrom_set_phase(uint8_t id, uint8_t phase)
{
uint8_t scsi_id = cdrom_drives[id].scsi_device_id;
uint8_t scsi_lun = cdrom_drives[id].scsi_device_lun;
if (cdrom_drives[id].bus_type != CDROM_BUS_SCSI)
return;
SCSIDevices[scsi_id][scsi_lun].Phase = phase;
}
static void cdrom_cmd_error(uint8_t id)
{
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
cdrom[id].error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR;
if (cdrom[id].unit_attention)
cdrom[id].error |= MCR_ERR;
@@ -1422,7 +1433,7 @@ static void cdrom_cmd_error(uint8_t id)
static void cdrom_unit_attention(uint8_t id)
{
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
cdrom[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR;
if (cdrom[id].unit_attention)
cdrom[id].error |= MCR_ERR;
@@ -2130,17 +2141,15 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
msf = cdb[1] & 2;
cdrom[id].sector_len = 0;
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
/* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */
if (cdrom_pre_execution_check(id, cdb) == 0)
return;
cdrom_buf_free(id);
switch (cdb[0]) {
case GPCMD_TEST_UNIT_READY:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
cdrom_command_complete(id);
break;
@@ -2149,13 +2158,13 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
cdrom_drives[id].handler->stop(id);
cdrom[id].sector_pos = cdrom[id].sector_len = 0;
cdrom_seek(id, 0);
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
break;
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. */
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
max_len = cdb[4];
cdrom_buf_alloc(id, 256);
cdrom_set_buf_len(id, BufLen, &max_len);
@@ -2165,12 +2174,12 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_SET_SPEED:
case GPCMD_SET_SPEED_ALT:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
cdrom_command_complete(id);
break;
case GPCMD_MECHANISM_STATUS:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
cdrom_buf_alloc(id, 8);
@@ -2186,7 +2195,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
case GPCMD_READ_TOC_PMA_ATIP:
cdrom[id].toctimes++;
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
max_len = cdb[7];
max_len <<= 8;
@@ -2197,7 +2206,6 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdrom_drives[id].handler->pass_through) {
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret) {
/* return; */
cdrom_sense_key = cdrom_asc = cdrom_ascq = 0;
goto cdrom_readtoc_fallback;
}
@@ -2228,6 +2236,7 @@ cdrom_readtoc_fallback:
break;
default:
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
}
@@ -2252,7 +2261,7 @@ cdrom_readtoc_fallback:
case GPCMD_READ_12:
case GPCMD_READ_CD:
case GPCMD_READ_CD_MSF:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
alloc_length = 2048;
switch(cdb[0]) {
@@ -2294,7 +2303,7 @@ cdrom_readtoc_fallback:
}
if (!cdrom[id].sector_len) {
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
/* cdrom_log("CD-ROM %i: All done - callback set\n", id); */
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].callback = 20LL * CDROM_TIME;
@@ -2311,8 +2320,10 @@ cdrom_readtoc_fallback:
cdrom_buf_alloc(id, cdrom[id].packet_len);
ret = cdrom_read_blocks(id, &alloc_length, 1);
if (ret <= 0)
if (ret <= 0) {
cdrom_buf_free(id);
return;
}
cdrom[id].requested_blocks = max_len;
cdrom[id].packet_len = alloc_length;
@@ -2329,15 +2340,17 @@ cdrom_readtoc_fallback:
return;
case GPCMD_READ_HEADER:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
alloc_length = ((cdb[7] << 8) | cdb[8]);
cdrom_buf_alloc(id, 8);
if (cdrom_drives[id].handler->pass_through) {
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
if (!ret) {
cdrom_buf_free(id);
return;
}
} else {
cdrom[id].sector_len = 1;
cdrom[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5];
@@ -2364,7 +2377,7 @@ cdrom_readtoc_fallback:
case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI)
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
@@ -2383,6 +2396,7 @@ cdrom_readtoc_fallback:
if (!(cdrom_mode_sense_page_flags[id] & (1LL << cdrom[id].current_page_code))) {
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
@@ -2417,7 +2431,7 @@ cdrom_readtoc_fallback:
case GPCMD_MODE_SELECT_6:
case GPCMD_MODE_SELECT_10:
SCSIPhase = SCSI_PHASE_DATA_OUT;
cdrom_set_phase(id, SCSI_PHASE_DATA_OUT);
if (cdb[0] == GPCMD_MODE_SELECT_6) {
len = cdb[4];
@@ -2434,7 +2448,7 @@ cdrom_readtoc_fallback:
return;
case GPCMD_GET_CONFIGURATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
/* XXX: could result in alignment problems in some architectures */
feature = (cdb[2] << 8) | cdb[3];
@@ -2443,6 +2457,7 @@ cdrom_readtoc_fallback:
/* only feature 0 is supported */
if ((cdb[2] != 0) || (cdb[3] > 2)) {
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
@@ -2530,7 +2545,7 @@ cdrom_readtoc_fallback:
break;
case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
cdrom_buf_alloc(id, 8 + sizeof(gesn_event_header));
@@ -2542,6 +2557,7 @@ cdrom_readtoc_fallback:
/* asynchronous mode */
/* Only polling is supported, asynchronous mode is not. */
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
@@ -2591,7 +2607,7 @@ cdrom_readtoc_fallback:
break;
case GPCMD_READ_DISC_INFORMATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
max_len = cdb[7];
max_len <<= 8;
@@ -2601,8 +2617,10 @@ cdrom_readtoc_fallback:
if (cdrom_drives[id].handler->pass_through) {
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
if (!ret) {
cdrom_buf_free(id);
return;
}
alloc_length = cdbufferb[0];
alloc_length <<= 8;
alloc_length |= cdbufferb[1];
@@ -2627,7 +2645,7 @@ cdrom_readtoc_fallback:
break;
case GPCMD_READ_TRACK_INFORMATION:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
max_len = cdb[7];
max_len <<= 8;
@@ -2642,8 +2660,10 @@ cdrom_readtoc_fallback:
if (cdrom_drives[id].handler->pass_through) {
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
if (!ret) {
cdrom_buf_free(id);
return;
}
alloc_length = cdbufferb[0];
alloc_length <<= 8;
alloc_length |= cdbufferb[1];
@@ -2652,6 +2672,7 @@ cdrom_readtoc_fallback:
} else {
if (((cdb[1] & 0x03) != 1) || (track != 1)) {
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
@@ -2686,7 +2707,7 @@ cdrom_readtoc_fallback:
case GPCMD_PLAY_AUDIO_12:
case GPCMD_PLAY_AUDIO_MSF:
case GPCMD_PLAY_AUDIO_TRACK_INDEX:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
switch(cdb[0]) {
case GPCMD_PLAY_AUDIO_10:
@@ -2729,7 +2750,7 @@ cdrom_readtoc_fallback:
break;
case GPCMD_READ_SUBCHANNEL:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
max_len = cdb[7];
max_len <<= 8;
@@ -2741,8 +2762,10 @@ cdrom_readtoc_fallback:
cdrom_log("CD-ROM %i: Getting page %i (%s)\n", id, cdb[3], msf ? "MSF" : "LBA");
if ((cdrom_drives[id].handler->pass_through) && (cdb[3] != 1)) {
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret)
if (!ret) {
cdrom_buf_free(id);
return;
}
switch(cdrom[id].cd_status) {
case CD_STATUS_PLAYING:
cdbufferb[1] = 0x11;
@@ -2776,6 +2799,7 @@ cdrom_readtoc_fallback:
if (cdb[3] > 3) {
/* cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", id, cdb[3]); */
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
@@ -2826,7 +2850,7 @@ cdrom_readtoc_fallback:
break;
case GPCMD_READ_DVD_STRUCTURE:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
alloc_length = (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]);
@@ -2835,6 +2859,7 @@ cdrom_readtoc_fallback:
if (cdrom_drives[id].handler->pass_through) {
ret = cdrom_pass_through(id, &len, cdrom[id].current_cdb, cdbufferb);
if (!ret) {
cdrom_buf_free(id);
return;
} else {
if (cdrom_drives[id].bus_type == CDROM_BUS_SCSI) {
@@ -2852,6 +2877,7 @@ cdrom_readtoc_fallback:
if (cdb[7] < 0xc0) {
if (len <= CD_MAX_SECTORS) {
cdrom_incompatible_format(id);
cdrom_buf_free(id);
return;
}
}
@@ -2879,10 +2905,11 @@ cdrom_readtoc_fallback:
if (cdb[1] == 0) {
ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb);
cdrom_set_buf_len(id, BufLen, &alloc_length);
if (ret)
if (ret) {
cdrom_set_buf_len(id, BufLen, &alloc_length);
cdrom_data_command_finish(id, alloc_length, alloc_length, len, 0);
} else
cdrom_buf_free(id);
return;
}
/* TODO: BD support, fall through for now */
@@ -2896,13 +2923,14 @@ cdrom_readtoc_fallback:
case 0xc0: /* TODO: Write protection status */
default:
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
}
break;
case GPCMD_START_STOP_UNIT:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
switch(cdb[4] & 3) {
case 0: /* Stop the disc. */
@@ -2926,7 +2954,7 @@ cdrom_readtoc_fallback:
break;
case GPCMD_INQUIRY:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
max_len = cdb[3];
max_len <<= 8;
@@ -2952,6 +2980,7 @@ cdrom_readtoc_fallback:
case 0x83:
if (idx + 24 > max_len) {
cdrom_data_phase_error(id);
cdrom_buf_free(id);
return;
}
@@ -2978,6 +3007,7 @@ cdrom_readtoc_fallback:
default:
cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]);
cdrom_invalid_field(id);
cdrom_buf_free(id);
return;
}
} else {
@@ -3017,13 +3047,13 @@ atapi_out:
break;
case GPCMD_PREVENT_REMOVAL:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
cdrom_command_complete(id);
break;
case GPCMD_PAUSE_RESUME_ALT:
case GPCMD_PAUSE_RESUME:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
if (cdb[8] & 1) {
if (cdrom_drives[id].handler->resume)
@@ -3045,7 +3075,7 @@ atapi_out:
case GPCMD_SEEK_6:
case GPCMD_SEEK_10:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
switch(cdb[0]) {
case GPCMD_SEEK_6:
@@ -3060,12 +3090,14 @@ atapi_out:
break;
case GPCMD_READ_CDROM_CAPACITY:
SCSIPhase = SCSI_PHASE_DATA_IN;
cdrom_set_phase(id, SCSI_PHASE_DATA_IN);
cdrom_buf_alloc(id, 8);
if (cdrom_read_capacity(id, cdrom[id].current_cdb, cdbufferb, &len) == 0)
if (cdrom_read_capacity(id, cdrom[id].current_cdb, cdbufferb, &len) == 0) {
cdrom_buf_free(id);
return;
}
cdrom_set_buf_len(id, BufLen, &len);
@@ -3073,7 +3105,7 @@ atapi_out:
break;
case GPCMD_STOP_PLAY_SCAN:
SCSIPhase = SCSI_PHASE_STATUS;
cdrom_set_phase(id, SCSI_PHASE_STATUS);
if (cdrom_drives[id].handler->stop)
cdrom_drives[id].handler->stop(id);
@@ -3090,6 +3122,9 @@ atapi_out:
}
/* cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", cdrom[id].phase, cdrom[id].request_length); */
if (cdrom_atapi_phase_to_scsi(id) == SCSI_PHASE_STATUS)
cdrom_buf_free(id);
}
/* This is the general ATAPI callback. */
@@ -3110,6 +3145,7 @@ void cdrom_callback(uint8_t id) /* Callback for non-Read CD commands */
cdrom[id].pos = cdrom[id].request_pos = 0;
cdrom_command_complete(id);
cdrom_buf_free(id);
} else {
cdrom_log("CD-ROM %i: %i bytes read, %i bytes are still left\n", id, cdrom[id].pos, cdrom[id].packet_len - cdrom[id].pos);
@@ -3132,6 +3168,7 @@ int cdrom_mode_select_return(uint8_t id, int ret)
case -6:
/* Attempted to write to a non-existent CD-ROM drive (should never occur, but you never know). */
cdrom_invalid_field_pl(id);
cdrom_buf_free(id);
return -2;
case 1:
/* Successful, more data needed. */
@@ -3149,10 +3186,11 @@ int cdrom_mode_select_return(uint8_t id, int ret)
case -4:
/* Unknown phase. */
cdrom_illegal_opcode(id);
cdrom_buf_free(id);
return -2;
case -5:
/* Command terminated successfully. */
/* cdrom_command_complete(id); */
cdrom_buf_free(id);
return -1;
default:
return -15;
@@ -3317,7 +3355,6 @@ void cdrom_phase_callback(uint8_t id)
cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id);
cdrom[id].status = BUSY_STAT | (cdrom[id].status &ERR_STAT);
memcpy(cdrom[id].atapi_cdb, cdbufferb, cdrom[id].cdb_len);
cdrom_buf_free(id);
cdrom_command(id, cdrom[id].atapi_cdb);
return;
case CDROM_PHASE_COMPLETE:
@@ -3325,7 +3362,6 @@ void cdrom_phase_callback(uint8_t id)
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
cdrom[id].packet_status = 0xFF;
cdrom_buf_free(id);
ui_sb_update_icon(SB_CDROM | id, 0);
cdrom_irq_raise(id);
return;
@@ -3338,6 +3374,7 @@ void cdrom_phase_callback(uint8_t id)
case CDROM_PHASE_DATA_OUT_DMA:
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id);
cdrom_read_from_dma(id);
cdrom_buf_free(id);
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
@@ -3353,6 +3390,7 @@ void cdrom_phase_callback(uint8_t id)
case CDROM_PHASE_DATA_IN_DMA:
cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id);
cdrom_write_to_dma(id);
cdrom_buf_free(id);
cdrom[id].packet_status = CDROM_PHASE_COMPLETE;
cdrom[id].status = READY_STAT;
cdrom[id].phase = 3;
@@ -3363,7 +3401,6 @@ void cdrom_phase_callback(uint8_t id)
cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id);
cdrom[id].status = READY_STAT | ERR_STAT;
cdrom[id].phase = 3;
cdrom_buf_free(id);
cdrom_irq_raise(id);
ui_sb_update_icon(SB_CDROM | id, 0);
return;

View File

@@ -42,8 +42,8 @@
scsi_device_t SCSIDevices[SCSI_ID_MAX][SCSI_LUN_MAX];
uint8_t SCSIPhase = 0xff;
uint8_t SCSIStatus = SCSI_STATUS_OK;
// uint8_t SCSIPhase = 0xff;
// uint8_t SCSIStatus = SCSI_STATUS_OK;
uint8_t scsi_cdrom_id = 3; /*common setting*/
char scsi_fn[SCSI_NUM][512];
uint16_t scsi_hd_location[SCSI_NUM];

View File

@@ -8,15 +8,15 @@
*
* SCSI controller handler header.
*
* Version: @(#)scsi_h 1.0.8 2017/10/15
* Version: @(#)scsi_h 1.0.9 2018/01/06
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2017 TheCollector1995.
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
* Copyright 2016,2018 TheCollector1995.
* Copyright 2016,2018 Miran Grca.
* Copyright 2018 Fred N. van Kempen.
*/
#ifndef EMU_SCSI_H
#define EMU_SCSI_H
@@ -215,8 +215,6 @@ extern uint8_t page_current;
#define PAGE_CHANGEABLE 1
#define PAGE_CHANGED 2
extern uint8_t SCSIStatus;
extern uint8_t SCSIPhase;
extern uint8_t scsi_cdrom_id;
struct _scsisense_ {
@@ -267,6 +265,8 @@ typedef struct {
uint8_t *CmdBuffer;
int LunType;
int32_t BufferLength;
uint8_t Status;
uint8_t Phase;
} scsi_device_t;

View File

@@ -8,7 +8,7 @@
*
* The generic SCSI bus operations handler.
*
* Version: @(#)scsi_bus.c 1.0.5 2017/12/09
* Version: @(#)scsi_bus.c 1.0.6 2018/01/06
*
* NOTES: For now ported from PCem with some modifications
* but at least it's a start.
@@ -159,16 +159,16 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert)
get_cmd_len(bus->command[0]),
bus->command);
scsi_bus_log("(%02X:%02X): Command %02X: Buffer Length %i, SCSI Phase %02X\n", bus->dev_id, lun, bus->command[0], dev->BufferLength, SCSIPhase);
scsi_bus_log("(%02X:%02X): Command %02X: Buffer Length %i, SCSI Phase %02X\n", bus->dev_id, lun, bus->command[0], dev->BufferLength, dev->Phase);
if ((SCSIPhase == SCSI_PHASE_DATA_IN) ||
(SCSIPhase == SCSI_PHASE_DATA_OUT)) {
if ((dev->Phase == SCSI_PHASE_DATA_IN) ||
(dev->Phase == SCSI_PHASE_DATA_OUT)) {
scsi_bus_log("dev->CmdBuffer = %08X\n", dev->CmdBuffer);
dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength);
scsi_bus_log("dev->CmdBuffer = %08X\n", dev->CmdBuffer);
}
if (SCSIPhase == SCSI_PHASE_DATA_OUT) {
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. */
scsi_bus_log("Next state is data out\n");
@@ -176,8 +176,8 @@ scsi_bus_update(scsi_bus_t *bus, int bus_assert)
bus->clear_req = 0;
} else {
/* Other command - execute immediately. */
bus->new_state = SCSIPhase;
if (SCSIPhase == SCSI_PHASE_DATA_IN) {
bus->new_state = dev->Phase;
if (dev->Phase == SCSI_PHASE_DATA_IN) {
scsi_device_command_phase1(bus->dev_id, lun);
}
@@ -324,11 +324,14 @@ scsi_bus_read(scsi_bus_t *bus)
break;
case SCSI_PHASE_STATUS:
lun = (bus->command[1] >> 5) & 7;
dev = &SCSIDevices[bus->dev_id][lun];
scsi_bus_log("Phase status\n");
bus->state = STATE_STATUS;
bus->bus_out |= BUS_REQ;
bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(SCSIStatus) | BUS_DBP;
/* scsi_bus_log("SCSI Status (command %02X): %02X (%08X)\n", bus->command[0], SCSIStatus, bus->bus_out); */
bus->bus_out = (bus->bus_out & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP;
/* scsi_bus_log("SCSI Status (command %02X): %02X (%08X)\n", bus->command[0], dev->Status, bus->bus_out); */
break;
case SCSI_PHASE_MESSAGE_IN:

View File

@@ -11,7 +11,7 @@
* 1 - BT-545S ISA;
* 2 - BT-958D PCI
*
* Version: @(#)scsi_buslogic.c 1.0.33 2018/01/02
* Version: @(#)scsi_buslogic.c 1.0.34 2018/01/06
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -599,7 +599,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId);
SCSIStatus = SCSI_STATUS_OK;
SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status = SCSI_STATUS_OK;
if (!scsi_device_present(ESCSICmd->TargetId, 0)) {
buslogic_log("SCSI Target ID %i has no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit);
@@ -639,7 +639,7 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].BufferLength = ESCSICmd->DataLength;
scsi_device_command_phase0(ESCSICmd->TargetId, ESCSICmd->LogicalUnit, ESCSICmd->CDBLength, temp_cdb);
phase = SCSIPhase;
phase = SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Phase;
if (phase != SCSI_PHASE_STATUS) {
if (phase == SCSI_PHASE_DATA_IN)
scsi_device_command_phase1(ESCSICmd->TargetId, ESCSICmd->LogicalUnit);
@@ -652,10 +652,10 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u
buslogic_log("BIOS Request complete\n");
if (SCSIStatus == SCSI_STATUS_OK) {
if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_OK) {
DataInBuf[2] = CCB_COMPLETE;
DataInBuf[3] = SCSI_STATUS_OK;
} else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) {
} else if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].Status == SCSI_STATUS_CHECK_CONDITION) {
DataInBuf[2] = CCB_COMPLETE;
DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION;
}

View File

@@ -8,13 +8,13 @@
*
* The generic SCSI device command handler.
*
* Version: @(#)scsi_device.c 1.0.9 2017/11/04
* Version: @(#)scsi_device.c 1.0.10 2018/01/06
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016,2017 Miran Grca.
* Copyright 2017 Fred N. van Kempen.
* Copyright 2016,2018 Miran Grca.
* Copyright 2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
@@ -31,41 +31,21 @@
static uint8_t scsi_null_device_sense[14] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0 };
static void scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
static uint8_t scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb)
{
if (lun_type == SCSI_DISK)
{
SCSIPhase = SCSI_PHASE_COMMAND;
scsi_hd_command(id, cdb);
SCSIStatus = scsi_hd_err_stat_to_scsi(id);
return scsi_hd_err_stat_to_scsi(id);
}
else if (lun_type == SCSI_CDROM)
{
SCSIPhase = SCSI_PHASE_COMMAND;
cdrom_command(id, cdb);
SCSIStatus = cdrom_CDROM_PHASE_to_scsi(id);
return cdrom_CDROM_PHASE_to_scsi(id);
}
else
{
SCSIPhase = SCSI_PHASE_STATUS;
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
}
}
static int scsi_device_target_phase_to_scsi(int lun_type, uint8_t id)
{
if (lun_type == SCSI_DISK)
{
return scsi_hd_phase_to_scsi(id);
}
else if (lun_type == SCSI_CDROM)
{
return cdrom_atapi_phase_to_scsi(id);
}
else
{
return 0;
return SCSI_STATUS_CHECK_CONDITION;
}
}
@@ -281,7 +261,6 @@ int scsi_device_block_shift(uint8_t scsi_id, uint8_t scsi_lun)
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;
uint8_t id = 0;
@@ -296,8 +275,8 @@ void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len,
break;
default:
id = 0;
SCSIPhase = SCSI_PHASE_STATUS;
SCSIStatus = SCSI_STATUS_CHECK_CONDITION;
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_STATUS;
SCSIDevices[scsi_id][scsi_lun].Status = SCSI_STATUS_CHECK_CONDITION;
return;
}
@@ -317,26 +296,14 @@ void scsi_device_command_phase0(uint8_t scsi_id, uint8_t scsi_lun, int cdb_len,
}
/* Finally, execute the SCSI command immediately and get the transfer length. */
scsi_device_target_command(lun_type, id, cdb);
if (SCSIStatus == SCSI_STATUS_OK) {
phase = scsi_device_target_phase_to_scsi(lun_type, id);
if (phase == 2) {
/* Command completed - call the phase callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
} else {
/* Command first phase complete - call the callback to execute the second phase. */
if (SCSIPhase == SCSI_PHASE_STATUS)
{
scsi_device_target_phase_callback(lun_type, id);
SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id);
/* Command second phase complete - call the callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
}
}
} else {
/* Error (Check Condition) - call the phase callback to complete the command. */
SCSIDevices[scsi_id][scsi_lun].Phase = SCSI_PHASE_COMMAND;
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_command(lun_type, id, cdb);
if (SCSIDevices[scsi_id][scsi_lun].Phase == SCSI_PHASE_STATUS) {
/* Command completed (either OK or error) - call the phase callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
}
/* If the phase is DATA IN or DATA OUT, finish this here. */
}
void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
@@ -358,8 +325,9 @@ void scsi_device_command_phase1(uint8_t scsi_id, uint8_t scsi_lun)
return;
}
/* Call the second phase. */
scsi_device_target_phase_callback(lun_type, id);
SCSIStatus = scsi_device_target_err_stat_to_scsi(lun_type, id);
SCSIDevices[scsi_id][scsi_lun].Status = scsi_device_target_err_stat_to_scsi(lun_type, id);
/* Command second phase complete - call the callback to complete the command. */
scsi_device_target_phase_callback(lun_type, id);
}

View File

@@ -6,11 +6,11 @@
*
* Emulation of SCSI fixed and removable disks.
*
* Version: @(#)scsi_disk.c 1.0.11 2017/12/09
* Version: @(#)scsi_disk.c 1.0.12 2018/01/06
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2017 Miran Grca.
* Copyright 2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
@@ -490,40 +490,6 @@ int scsi_hd_err_stat_to_scsi(uint8_t id)
}
/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */
int scsi_hd_phase_to_scsi(uint8_t id)
{
if (shdc[id].status & 8)
{
switch (shdc[id].phase & 3)
{
case 0:
return 0;
case 1:
return 2;
case 2:
return 1;
case 3:
return 7;
}
}
else
{
if ((shdc[id].phase & 3) == 3)
{
return 3;
}
else
{
/* Translate reserved ATAPI phase to reserved SCSI phase. */
return 4;
}
}
return 0;
}
int find_hdd_for_scsi_id(uint8_t scsi_id, uint8_t scsi_lun)
{
uint8_t i = 0;
@@ -1095,9 +1061,21 @@ static void scsi_hd_sense_clear(int id, int command)
}
static void scsi_hd_set_phase(uint8_t id, uint8_t phase)
{
uint8_t scsi_id = hdd[id].scsi_id;
uint8_t scsi_lun = hdd[id].scsi_lun;
if ((hdd[id].bus != HDD_BUS_SCSI) && (hdd[id].bus != HDD_BUS_SCSI_REMOVABLE))
return;
SCSIDevices[scsi_id][scsi_lun].Phase = phase;
}
static void scsi_hd_cmd_error(uint8_t id)
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
shdc[id].error = ((scsi_hd_sense_key & 0xf) << 4) | ABRT_ERR;
if (shdc[id].unit_attention & 3)
{
@@ -1113,7 +1091,7 @@ static void scsi_hd_cmd_error(uint8_t id)
static void scsi_hd_unit_attention(uint8_t id)
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
shdc[id].error = (SENSE_NOT_READY << 4) | ABRT_ERR;
if (shdc[id].unit_attention & 3)
{
@@ -1150,7 +1128,7 @@ static void scsi_hd_invalid_lun(uint8_t id)
scsi_hd_sense_key = SENSE_ILLEGAL_REQUEST;
scsi_hd_asc = ASC_INV_LUN;
scsi_hd_ascq = 0;
SCSIPhase = BUS_CD | BUS_IO;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
scsi_hd_cmd_error(id);
}
@@ -1461,7 +1439,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
shdc[id].sector_len = 0;
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
/* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */
if (scsi_hd_pre_execution_check(id, cdb) == 0)
@@ -1473,14 +1451,14 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
{
case GPCMD_TEST_UNIT_READY:
case GPCMD_FORMAT_UNIT:
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
scsi_hd_command_complete(id);
break;
case GPCMD_REZERO_UNIT:
shdc[id].sector_pos = shdc[id].sector_len = 0;
scsi_hd_seek(id, 0);
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
break;
case GPCMD_REQUEST_SENSE:
@@ -1496,7 +1474,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
cdb[4] = *BufLen;
}
SCSIPhase = SCSI_PHASE_DATA_IN;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN);
scsi_hd_data_command_finish(id, 18, 18, cdb[4], 0);
break;
@@ -1508,7 +1486,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
*BufLen = len;
}
SCSIPhase = SCSI_PHASE_DATA_IN;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN);
scsi_hd_data_command_finish(id, 8, 8, len, 0);
break;
@@ -1539,7 +1517,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
if ((!shdc[id].sector_len) || (*BufLen == 0))
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
scsi_hd_log("SCSI HD %i: All done - callback set\n", id);
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
@@ -1557,7 +1535,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
*BufLen = alloc_length;
}
SCSIPhase = SCSI_PHASE_DATA_IN;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN);
if (shdc[id].requested_blocks > 1)
{
@@ -1575,7 +1553,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case GPCMD_VERIFY_10:
case GPCMD_VERIFY_12:
if (!(cdb[1] & 2)) {
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
scsi_hd_command_complete(id);
break;
}
@@ -1621,7 +1599,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
if ((!shdc[id].sector_len) || (*BufLen == 0))
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
scsi_hd_log("SCSI HD %i: All done - callback set\n", id);
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
@@ -1639,7 +1617,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
*BufLen = alloc_length;
}
SCSIPhase = SCSI_PHASE_DATA_OUT;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT);
if (shdc[id].requested_blocks > 1)
{
@@ -1678,7 +1656,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
if ((!shdc[id].sector_len) || (*BufLen == 0))
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
scsi_hd_log("SCSI HD %i: All done - callback set\n", id);
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
@@ -1696,7 +1674,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
*BufLen = alloc_length;
}
SCSIPhase = SCSI_PHASE_DATA_OUT;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT);
if (shdc[id].requested_blocks > 1)
{
@@ -1712,7 +1690,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
SCSIPhase = SCSI_PHASE_DATA_IN;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN);
block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1;
@@ -1792,7 +1770,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
case GPCMD_MODE_SELECT_6:
case GPCMD_MODE_SELECT_10:
SCSIPhase = SCSI_PHASE_DATA_OUT;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_OUT);
if (cdb[0] == GPCMD_MODE_SELECT_6)
{
@@ -1833,7 +1811,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
break;
}
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
scsi_hd_command_complete(id);
break;
@@ -1844,7 +1822,7 @@ void scsi_hd_command(uint8_t id, uint8_t *cdb)
if ((!max_len) || (*BufLen == 0))
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
/* scsi_hd_log("SCSI HD %i: All done - callback set\n", id); */
shdc[id].packet_status = CDROM_PHASE_COMPLETE;
shdc[id].callback = 20 * SCSI_TIME;
@@ -1962,12 +1940,12 @@ atapi_out:
len = *BufLen;
}
SCSIPhase = SCSI_PHASE_DATA_IN;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN);
scsi_hd_data_command_finish(id, len, len, max_len, 0);
break;
case GPCMD_PREVENT_REMOVAL:
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
scsi_hd_command_complete(id);
break;
@@ -1984,7 +1962,7 @@ atapi_out:
}
scsi_hd_seek(id, pos);
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
scsi_hd_command_complete(id);
break;
@@ -1993,7 +1971,7 @@ atapi_out:
if (scsi_hd_read_capacity(id, shdc[id].current_cdb, shdc[id].temp_buffer, &len) == 0)
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
return;
}
@@ -2002,7 +1980,7 @@ atapi_out:
*BufLen = len;
}
SCSIPhase = SCSI_PHASE_DATA_IN;
scsi_hd_set_phase(id, SCSI_PHASE_DATA_IN);
scsi_hd_data_command_finish(id, len, len, len, 0);
break;
@@ -2061,7 +2039,7 @@ void scsi_hd_phase_data_in(uint8_t id)
if (!*BufLen)
{
scsi_hd_log("scsi_hd_phase_data_in(): Buffer length is 0\n");
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
@@ -2109,7 +2087,7 @@ void scsi_hd_phase_data_in(uint8_t id)
break;
}
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
}
@@ -2130,7 +2108,7 @@ void scsi_hd_phase_data_out(uint8_t id)
if (!*BufLen)
{
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
return;
@@ -2211,7 +2189,7 @@ void scsi_hd_phase_data_out(uint8_t id)
break;
}
SCSIPhase = SCSI_PHASE_STATUS;
scsi_hd_set_phase(id, SCSI_PHASE_STATUS);
ui_sb_update_icon((hdd[id].bus == HDD_BUS_SCSI_REMOVABLE) ? (SB_RDISK | id) : (SB_HDD | HDD_BUS_SCSI), 0);
}

View File

@@ -10,16 +10,16 @@
* NCR and later Symbios and LSI. This controller was designed
* for the PCI bus.
*
* Version: @(#)scsi_ncr53c810.c 1.0.5 2017/12/25
* Version: @(#)scsi_ncr53c810.c 1.0.6 2018/01/06
*
* Authors: Paul Brook (QEMU)
* Artyom Tarasenko (QEMU)
* TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2006-2017 Paul Brook.
* Copyright 2009-2017 Artyom Tarasenko.
* Copyright 2017 Miran Grca.
* Copyright 2006-2018 Paul Brook.
* Copyright 2009-2018 Artyom Tarasenko.
* Copyright 2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
@@ -623,7 +623,7 @@ ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id)
free(sd->CmdBuffer);
sd->CmdBuffer = NULL;
}
ncr53c810_command_complete(dev, SCSIStatus);
ncr53c810_command_complete(dev, sd->Status);
} else {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command);
dev->sstop = 0;
@@ -687,14 +687,14 @@ ncr53c810_do_command(ncr53c810_t *dev, uint8_t id)
dev->current->dma_len = sd->BufferLength;
}
if ((SCSIPhase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) {
if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DI);
} else if ((SCSIPhase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) {
} else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) {
ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, dev->current_lun, buf[0]);
ncr53c810_set_phase(dev, PHASE_DO);
} else
ncr53c810_command_complete(dev, SCSIStatus);
ncr53c810_command_complete(dev, sd->Status);
}

View File

@@ -11,7 +11,7 @@
* series of SCSI Host Adapters made by Mylex.
* These controllers were designed for various buses.
*
* Version: @(#)scsi_x54x.c 1.0.10 2018/01/02
* Version: @(#)scsi_x54x.c 1.0.11 2018/01/06
*
* Authors: TheCollector1995, <mariogplayer@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -363,10 +363,6 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
dev->CmdBuffer = (uint8_t *)malloc(14);
memset(dev->CmdBuffer, 0x00, 14);
#if 0
SCSIStatus = x54x_bios_command_08(cmd->id, cmd->lun, dev->CmdBuffer) ? SCSI_STATUS_OK : SCSI_STATUS_CHECK_CONDITION;
#endif
if (sector_len > 0) {
x54x_log("BIOS DMA: Reading 14 bytes at %08X\n",
dma_address);
@@ -402,7 +398,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba)
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
if (SCSIPhase == SCSI_PHASE_STATUS)
if (dev->Phase == SCSI_PHASE_STATUS)
goto skip_read_phase1;
scsi_device_command_phase1(cmd->id, cmd->lun);
@@ -442,7 +438,7 @@ skip_read_phase1:
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
if (SCSIPhase == SCSI_PHASE_STATUS)
if (dev->Phase == SCSI_PHASE_STATUS)
goto skip_write_phase1;
if (sector_len > 0) {
@@ -532,7 +528,7 @@ skip_write_phase1:
scsi_device_command_phase0(cmd->id, cmd->lun, 12, cdb);
return((SCSIStatus == SCSI_STATUS_OK) ? 1 : 0);
return((dev->Status == SCSI_STATUS_OK) ? 1 : 0);
case 0x0d: /* Alternate Disk Reset, in practice it's a nop */
//FIXME: add a longer delay here --FvK
@@ -997,7 +993,7 @@ x54x_scsi_cmd(x54x_t *dev)
scsi_device_command_phase0(id, lun, req->CmdBlock.common.CdbLength, temp_cdb);
phase = SCSIPhase;
phase = SCSIDevices[id][lun].Phase;
x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03));
@@ -1007,7 +1003,7 @@ x54x_scsi_cmd(x54x_t *dev)
*BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength);
x54x_buf_alloc(id, lun, *BufLen);
scsi_device_command_phase1(id, lun);
if ((SCSIStatus != SCSI_STATUS_OK) && (*BufLen > 0)) {
if ((SCSIDevices[id][lun].Status != SCSI_STATUS_OK) && (*BufLen > 0)) {
SenseBufferAddress = SenseBufferPointer(req);
DMAPageWrite(SenseBufferAddress, SCSIDevices[id][lun].CmdBuffer, *BufLen);
}
@@ -1019,10 +1015,10 @@ x54x_scsi_cmd(x54x_t *dev)
if (phase == SCSI_PHASE_DATA_IN)
x54x_buf_dma_transfer(req, bit24, target_data_len, 0);
SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK));
SenseBufferFree(req, (SCSIDevices[id][lun].Status != SCSI_STATUS_OK));
}
} else
SenseBufferFree(req, (SCSIStatus != SCSI_STATUS_OK));
SenseBufferFree(req, (SCSIDevices[id][lun].Status != SCSI_STATUS_OK));
x54x_set_residue(req, target_data_len);
@@ -1030,15 +1026,15 @@ x54x_scsi_cmd(x54x_t *dev)
x54x_log("Request complete\n");
if (SCSIStatus == SCSI_STATUS_OK) {
if (SCSIDevices[id][lun].Status == SCSI_STATUS_OK) {
x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock,
CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS);
} else if (SCSIStatus == SCSI_STATUS_CHECK_CONDITION) {
} else if (SCSIDevices[id][lun].Status == SCSI_STATUS_CHECK_CONDITION) {
x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock,
CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR);
}
x54x_log("SCSIStatus = %02X\n", SCSIStatus);
x54x_log("SCSIDevices[%02i][%02i].Status = %02X\n", id, lun, SCSIDevices[id][lun].Status);
if (temp_cdb[0] == 0x42) {
thread_wait_event((event_t *) evt, 10);
@@ -1084,7 +1080,7 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32)
x54x_log("Scanning SCSI Target ID %i\n", id);
SCSIStatus = SCSI_STATUS_OK;
SCSIDevices[id][lun].Status = SCSI_STATUS_OK;
/* If there is no device at ID:0, timeout the selection - the LUN is then checked later. */
if (! scsi_device_present(id, 0)) {