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:
@@ -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;
|
||||
|
@@ -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];
|
||||
|
@@ -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;
|
||||
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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)) {
|
||||
|
Reference in New Issue
Block a user