diff options
Diffstat (limited to 'src/devices/machine/nscsi_bus.cpp')
-rw-r--r-- | src/devices/machine/nscsi_bus.cpp | 311 |
1 files changed, 255 insertions, 56 deletions
diff --git a/src/devices/machine/nscsi_bus.cpp b/src/devices/machine/nscsi_bus.cpp index c2274f49c95..d1fa9a1265d 100644 --- a/src/devices/machine/nscsi_bus.cpp +++ b/src/devices/machine/nscsi_bus.cpp @@ -3,15 +3,19 @@ #include "emu.h" #include "nscsi_bus.h" -#define LOG_GENERAL (1U << 0) +#include "util/multibyte.h" + +#include <cassert> +#include <cstring> + #define LOG_UNSUPPORTED (1U << 1) #define LOG_STATE (1U << 2) #define LOG_CONTROL (1U << 3) #define LOG_DATA (1U << 4) #define LOG_DATA_SENT (1U << 5) -//#define VERBOSE (LOG_GENERAL | LOG_STATE | LOG_CONTROL | LOG_DATA) #define VERBOSE (LOG_UNSUPPORTED) +//#define LOG_OUTPUT_FUNC osd_printf_info #include "logmacro.h" @@ -76,16 +80,16 @@ void nscsi_bus_device::regen_ctrl(int refid) data); for(int i=0; i<devcnt; i++) if(dev[i].ctrl) { - LOGMASKED(LOG_CONTROL, "%d=%s%s%s%s%s%s%s%s%s\n", i, + LOGMASKED(LOG_CONTROL, "dev%d=%s%s%s%s%s%s%s%s%s\n", i, dev[i].ctrl & nscsi_device::S_RST ? "R" : "", dev[i].ctrl & nscsi_device::S_ATN ? "A" : "", dev[i].ctrl & nscsi_device::S_ACK ? "K" : "", dev[i].ctrl & nscsi_device::S_REQ ? "Q" : "", + dev[i].ctrl & nscsi_device::S_SEL ? "S" : "", + dev[i].ctrl & nscsi_device::S_BSY ? "B" : "", dev[i].ctrl & nscsi_device::S_MSG ? "M" : "", - dev[i].ctrl & nscsi_device::S_INP ? "I" : "", dev[i].ctrl & nscsi_device::S_CTL ? "C" : "", - dev[i].ctrl & nscsi_device::S_SEL ? "S" : "", - dev[i].ctrl & nscsi_device::S_BSY ? "B" : ""); + dev[i].ctrl & nscsi_device::S_INP ? "I" : ""); } } @@ -128,7 +132,7 @@ void nscsi_bus_device::ctrl_wait(int refid, uint32_t lines, uint32_t mask) void nscsi_bus_device::device_resolve_objects() { for(int i=0; i<16; i++) { - device_t *subdev = subdevice(string_format("%d", i).c_str()); + device_t *subdev = subdevice(string_format("%d", i)); nscsi_device *sdev = subdev ? downcast<nscsi_connector &>(*subdev).get_device() : nullptr; if(sdev) { int rid = devcnt++; @@ -141,7 +145,7 @@ void nscsi_bus_device::device_resolve_objects() nscsi_connector::nscsi_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, NSCSI_CONNECTOR, tag, owner, clock), - device_slot_interface(mconfig, *this) + device_single_card_slot_interface<nscsi_slot_card_interface>(mconfig, *this) { } @@ -149,20 +153,13 @@ nscsi_connector::~nscsi_connector() { } -void nscsi_connector::device_validity_check(validity_checker &valid) const -{ - device_t *const carddev = get_card_device(); - if (carddev && !dynamic_cast<nscsi_slot_card_interface *>(carddev)) - osd_printf_error("Card device %s (%s) does not implement nscsi_slot_card_interface\n", carddev->tag(), carddev->name()); -} - void nscsi_connector::device_start() { } nscsi_device *nscsi_connector::get_device() { - nscsi_slot_card_interface *connected = dynamic_cast<nscsi_slot_card_interface *>(get_card_device()); + nscsi_slot_card_interface *const connected = get_card_device(); if (connected) return connected->device().subdevice<nscsi_device>(connected->m_nscsi.finder_tag()); else @@ -170,7 +167,7 @@ nscsi_device *nscsi_connector::get_device() } nscsi_slot_card_interface::nscsi_slot_card_interface(const machine_config &mconfig, device_t &device, const char *nscsi_tag) : - device_slot_card_interface(mconfig, device), + device_interface(device, "nscsi"), m_nscsi(device, nscsi_tag) { } @@ -206,27 +203,27 @@ nscsi_full_device::nscsi_full_device(const machine_config &mconfig, device_type } const char *const nscsi_full_device::command_names[256] = { - /* 00 */ "TEST_UNIT_READY", "REZERO", "?", "REQUEST_SENSE", "FORMAT_UNIT", "?", "?", "REASSIGN_BLOCKS", - /* 08 */ "READ_6/RECIEVE", "?", "WRITE_6/SEND", "SEEK", "?", "?", "?", "?", - /* 10 */ "?", "?", "INQUIRY", "?", "?", "MODE_SELECT_6", "RESERVE_6", "RELEASE_6", - /* 18 */ "?", "?", "MODE_SENSE_6", "START_STOP_UNIT", "RECIEVE_DIAG_RES", "SEND_DIAGNOSTICS", "PREVENT_ALLOW_MEDIUM_REMOVAL", "?", - /* 20 */ "?", "?", "?", "READ_FORMAT_CAPACITIES", "?", "READ_CAPACITY", "?", "?", - - /* 28 */ "READ_10", "READ_GENERATION", "WRITE_10", "SEEK_10", "ERASE_10", "READ_UPDATED_BLOCK_10", "WRITE_VERIFY", "VERIFY", - /* 30 */ "SEARCH_DATA_HIGH_10", "SEARCH_DATA_EQUAL_10", "SEARCH_DATA_LOW_10", "SET_LIMITS_10", "PREFETCH", "SYNC_CACHE", "LOCK_UNLOCK_CACHE", "READ_DEFECT_DATA", - /* 38 */ "MEDIUM_SCAN", "COMPARE", "COPY_AND_VERIFY", "WRITE_BUFFER", "READ_DATA_BUFFER", "UPDATE_BLOCK", "READ_LONG", "WRITE_LONG", + /* 00 */ "TEST_UNIT_READY", "REWIND/REZERO_UNIT", "REQUEST_BLOCK_ADDRESS", "REQUEST_SENSE", "FORMAT/FORMAT_UNIT", "READ_BLOCK_LIMITS", "?", "INITIALIZE_ELEMENT_STATUS/REASSIGN_BLOCKS", + /* 08 */ "GET_MESSAGE_6/READ_6/RECEIVE", "?", "PRINT/SEND_MESSAGE_6/SEND_6/WRITE_6", "SEEK_6/SLEW_AND_PRINT", "SEEK_BLOCK", "?", "?", "READ_REVERSE", + /* 10 */ "SYNCHRONIZE_BUFFER/WRITE_FILEMARKS", "SPACE", "INQUIRY", "VERIFY_6", "RECOVER_BUFFERED_DATA", "MODE_SELECT_6", "RESERVE_6/RESERVE_UNIT", "RELEASE_6/RELEASE_UNIT", + /* 18 */ "COPY", "ERASE", "MODE_SENSE_6", "LOAD_UNLOAD/SCAN/STOP_PRINT/START_STOP_UNIT", "RECEIVE_DIAGNOSTIC_RESULTS", "SEND_DIAGNOSTIC", "PREVENT_ALLOW_MEDIUM_REMOVAL", "?", + /* 20 */ "?", "?", "?", "READ_FORMAT_CAPACITIES", "SET_WINDOW", "GET_WINDOW/READ_CAPACITY/READ_CD_RECORDED_CAPACITY", "?", "?", + + /* 28 */ "GET_MESSAGE_10/READ_10", "READ_GENERATION", "SEND_MESSAGE_10/SEND_10/WRITE_10", "LOCATE/POSITION_TO_ELEMENT/SEEK_10", "ERASE_10", "READ_UPDATED_BLOCK", "WRITE_AND_VERIFY_10", "VERIFY_10", + /* 30 */ "SEARCH_DATA_HIGH_10", "OBJECT_POSITION/SEARCH_DATA_EQUAL_10", "SEARCH_DATA_LOW_10", "SET_LIMITS_10", "PREFETCH/READ_POSITION", "SYNCHRONIZE_CACHE", "LOCK_UNLOCK_CACHE", "READ_DEFECT_DATA_10", + /* 38 */ "MEDIUM_SCAN", "COMPARE", "COPY_AND_VERIFY", "WRITE_BUFFER", "READ_BUFFER", "UPDATE_BLOCK", "READ_LONG", "WRITE_LONG", /* 40 */ "CHANGE_DEFINITION", "WRITE_SAME", "READ_SUB_CHANNEL", "READ_TOC_PMA_ATIP", "READ_HEADER", "PLAY_AUDIO_10", "GET_CONFIGURATION", "PLAY_AUDIO_MSF", - /* 48 */ "PLAY_AUDIO_TRACK_INDEX", "PLAY_RELATIVE_10", "GET_EVENT_STATUS_NOTIFICATION", "PAUSE_RESUME", "LOG_SELECT", "LOG_SENSE", "STOP_PLAY_SCAN", "?", + /* 48 */ "PLAY_AUDIO_TRACK_INDEX", "PLAY_TRACK_RELATIVE_10", "GET_EVENT_STATUS_NOTIFICATION", "PAUSE_RESUME", "LOG_SELECT", "LOG_SENSE", "STOP_PLAY_SCAN", "?", /* 50 */ "XDWRITE", "READ_DISC_INFORMATION/XPWRITE", "READ_TRACK_INFORMATION/XDREAD", "RESERVE_TRACK", "SEND_OPC_INFORMATION", "MODE_SELECT_10", "RESERVE_10", "RELEASE_10", /* 58 */ "REPAIR_TRACK", "READ_MASTER_CUE", "MODE_SENSE_10", "CLOSE_TRACK_SESSION", "READ_BUFFER_CAPACITY", "SEND_CUE_SHEET", "PERSISTENT_RESERVE_IN", "PERSISTENT_RESERVE_OUT", /* 80 */ "XDWRITE_EXTENDED", "REBUILD", "REGENERATE", "EXTENDED_COPY", "RECEIVE_COPY_RESULTS", "?", "?", "?", - /* 88 */ "?", "?", "?", "?", "?", "?", "?", "?", - /* 90 */ "?", "?", "?", "?", "?", "?", "?", "?", - /* 98 */ "?", "?", "?", "?", "?", "?", "?", "?", + /* 88 */ "?", "?", "WRITE_16", "?", "?", "?", "?", "?", + /* 90 */ "?", "SYNCHRONIZE_CACHE_16", "?", "WRITE_SAME_16", "?", "?", "?", "?", + /* 98 */ "?", "?", "?", "?", "?", "?", "READ_CAPACITY_166/READ_LONG_16", "WRITE_LONG_16", /* a0 */ "REPORT_LUNS", "BLANK", "SEND_EVENT", "REPORT_DEVICE_IDENTIFIER/SEND_KEY", "SET_DEVICE_IDENTIFIER/REPORT_KEY", "PLAY_AUDIO_12", "LOAD_UNLOAD_MEDIUM", "MOVE_MEDIUM_ATTACHED/SET_READ_AHEAD", /* a8 */ "READ_12", "PLAY_RELATIVE_12", "WRITE_12", "?", "ERASE_12/GET_PERFORMANCE", "READ_DVD_STRUCTURE", "WRITE_AND_VERIFY_12", "VERIFY_12", /* b0 */ "SEARCH_DATA_HIGH_12", "SEARCH_DATA_EQUAL_12", "SEARCH_DATA_LOW_12", "SET_LIMITS_12", "READ_ELEMENT_STATUS_ATTACHED", "?", "SET_STREAMING", "READ_DEFECT_DATA_12", - /* b8 */ "?", "READ_CD_MSF", "SCAN_MMC", "SET_CD_SPEED", "PLAY_CD", "MECHANISM_STATUS", "READ_CD", "SEND_DVD_STRUCTURE", + /* b8 */ "?", "READ_CD_MSF", "SCAN_MMC", "SET_CD_SPEED", "PLAY_CD/SPARE_IN", "MECHANISM_STATUS/SPARE_OUT", "READ_CD", "SEND_DVD_STRUCTURE", /* c0 */ "?", "?", "?", "?", "?", "?", "?", "?", /* c8 */ "?", "?", "?", "?", "?", "?", "?", "?", /* d0 */ "?", "?", "?", "?", "?", "?", "?", "?", @@ -240,7 +237,7 @@ const char *const nscsi_full_device::command_names[256] = { void nscsi_full_device::device_start() { nscsi_device::device_start(); - scsi_timer = timer_alloc(SCSI_TIMER); + scsi_timer = timer_alloc(FUNC(nscsi_full_device::update_tick), this); save_item(NAME(scsi_cmdbuf)); save_item(NAME(scsi_sense_buffer)); save_item(NAME(scsi_cmdsize)); @@ -270,15 +267,12 @@ void nscsi_full_device::device_reset() scsi_bus->data_w(scsi_refid, 0); scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); + sense(false, SK_NO_SENSE); } -void nscsi_full_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nscsi_full_device::update_tick) { - if(id != SCSI_TIMER) - return; - - step(true); - + step(param); } void nscsi_full_device::scsi_ctrl_changed() @@ -295,6 +289,11 @@ void nscsi_full_device::step(bool timeout) scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); scsi_state = IDLE; LOG("scsi bus reset\n"); + scsi_state = scsi_substate = IDLE; + buf_control_rpos = buf_control_wpos = 0; + scsi_identify = 0; + data_buffer_size = 0; + data_buffer_pos = 0; return; } @@ -309,7 +308,7 @@ void nscsi_full_device::step(bool timeout) if(scsi_initiator_id == 16) scsi_initiator_id = -1; scsi_state = TARGET_SELECT_WAIT_BUS_SETTLE; - scsi_timer->adjust(scsi_bus_settle_delay()); + scsi_timer->adjust(scsi_bus_settle_delay(), true); } break; @@ -341,7 +340,12 @@ void nscsi_full_device::step(bool timeout) if(!(ctrl & S_ACK)) { scsi_state &= STATE_MASK; scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK); - step(false); + attotime delay = scsi_data_byte_period(); + if (delay == attotime::zero) { + step(false); + } else { + scsi_timer->adjust(delay, false); + } } break; @@ -357,7 +361,12 @@ void nscsi_full_device::step(bool timeout) if(!(ctrl & S_ACK)) { scsi_state &= STATE_MASK; scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK); - step(false); + attotime delay = scsi_data_byte_period(); + if (delay == attotime::zero) { + step(false); + } else { + scsi_timer->adjust(delay, false); + } } break; @@ -465,7 +474,12 @@ void nscsi_full_device::step(bool timeout) scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK); scsi_command(); scsi_state = TARGET_NEXT_CONTROL; - step(false); + attotime delay = scsi_data_command_delay(); + if (delay == attotime::zero) { + step(false); + } else { + scsi_timer->adjust(delay, false); + } } else target_recv_byte(); break; @@ -518,7 +532,7 @@ void nscsi_full_device::scsi_put_data(int id, int pos, uint8_t data) scsi_sense_buffer[pos] = data; break; default: - fatalerror("nscsi_full_device::scsi_put_data - unknown id\n"); + fatalerror("nscsi_full_device::scsi_put_data - unknown id %d\n", id); } } @@ -539,14 +553,16 @@ bool nscsi_full_device::scsi_command_done(uint8_t command, uint8_t length) case 4: return true; case 5: return length == 12; case 6: return true; - case 7: return true; + case 7: return length == 32; + case 8: return length == 16; + case 9: return length == 16; } return true; } nscsi_full_device::control *nscsi_full_device::buf_control_push() { - if(buf_control_wpos == int(ARRAY_LENGTH(buf_control))) + if(buf_control_wpos == int(std::size(buf_control))) throw emu_fatalerror("%s: buf_control overflow\n", tag()); control *c = buf_control + buf_control_wpos; @@ -608,16 +624,171 @@ void nscsi_full_device::scsi_data_out(int buf, int size) c->param2 = size; } +////////////////////////////////////////////////////////////////////////////// + +void nscsi_full_device::set_sense_data(const u8 sense_key, const u16 sense_key_code, const sense_data *data) +{ + assert(sizeof(scsi_sense_buffer) >= 18); + assert(sense_key <= 0x0f); + memset(scsi_sense_buffer, 0, 18); + if (data) { + scsi_sense_buffer[0] = (data->invalid ? 0 : 0x80) // even though SCSI-2 section 8.2.14 implies valid bit should always be set, other sections such as 10.2.12 disagree! + | (data->deferred ? 0x71 : 0x70); + scsi_sense_buffer[2] = (data->filemark ? 0x80 : 0) + | (data->eom ? 0x40 : 0) + | (data->bad_len ? 0x20 : 0); // "incorrect length indicator" + put_s32be(&scsi_sense_buffer[3], data->info); + } + else + scsi_sense_buffer[0] = 0xf0; + scsi_sense_buffer[2] |= sense_key; + scsi_sense_buffer[7] = 10; // additional sense length + put_u16be(&scsi_sense_buffer[12], sense_key_code); +} + void nscsi_full_device::sense(bool deferred, uint8_t key, uint8_t asc, uint8_t ascq) { - memset(scsi_sense_buffer, 0, sizeof(scsi_sense_buffer)); - scsi_sense_buffer[0] = deferred ? 0x71 : 0x70; - scsi_sense_buffer[2] = key; - scsi_sense_buffer[7] = sizeof(scsi_sense_buffer) - 8; - scsi_sense_buffer[12] = asc; - scsi_sense_buffer[13] = ascq; + sense_data s; + s.deferred = deferred; + set_sense_data(key, (asc << 8) | ascq, &s); } +void nscsi_full_device::report_condition(const u8 sense_key, const u16 sense_key_code, const sense_data *data) +{ + set_sense_data(sense_key, sense_key_code, data); + scsi_status_complete(SS_CHECK_CONDITION); +} + +void nscsi_full_device::report_bad_lun(const u8 cmd, const u8 lun) +{ + LOG("%s (0x%02x) lun=%d\n *** BAD LUN\n", command_names[cmd], cmd, lun); + report_condition(SK_ILLEGAL_REQUEST, SKC_LOGICAL_UNIT_NOT_SUPPORTED); +} + +void nscsi_full_device::report_bad_cmd(const u8 cmd) +{ + LOG("%s (0x%02x)\n *** BAD COMMAND\n", command_names[cmd], cmd); + report_condition(SK_ILLEGAL_REQUEST, SKC_INVALID_COMMAND_OPERATION_CODE); +} + +void nscsi_full_device::report_filemark(const s32 info, const bool eom) +{ + LOG(" *** FILEMARK info=%d\n", info); + sense_data s; + s.filemark = true; + s.eom = eom; + s.info = info; + report_condition(SK_NO_SENSE, SKC_FILEMARK_DETECTED, &s); +} + +void nscsi_full_device::report_bom(const s32 info) +{ + LOG(" *** BOM info=%d\n", info); + sense_data s; + s.eom = true; + s.info = info; + report_condition(SK_NO_SENSE, SKC_BEGINNING_OF_PARTITION_MEDIUM_DETECTED, &s); +} + +void nscsi_full_device::report_ew(const s32 info) +{ + LOG(" EW info=%d\n", info); + sense_data s; + s.eom = true; + s.info = info; + report_condition(SK_NO_SENSE, SKC_END_OF_PARTITION_MEDIUM_DETECTED, &s); +} + +void nscsi_full_device::report_eod(const s32 info, const bool eom) +{ + LOG(" *** EOD info=%d\n", info); + sense_data s; + s.eom = eom; + s.info = info; + report_condition(SK_BLANK_CHECK, SKC_END_OF_DATA_DETECTED, &s); +} + +void nscsi_full_device::report_eom(const bool write, const s32 info, const bool invalid) +{ + LOG(" *** EOM info=%d invalid=%d\n", info, invalid); + sense_data s; + s.invalid = invalid; + s.eom = true; + s.info = info; + report_condition(write ? SK_VOLUME_OVERFLOW : SK_MEDIUM_ERROR, SKC_END_OF_PARTITION_MEDIUM_DETECTED, &s); +} + +void nscsi_full_device::report_bad_len(const bool over, const s32 info) +{ + LOG(" *** %sLENGTH BLOCK info=%d\n", over ? "OVER" : "UNDER", info); + sense_data s; + s.bad_len = true; + s.info = info; + report_condition(SK_ILLEGAL_REQUEST, SKC_NO_ADDITIONAL_SENSE_INFORMATION, &s); +} + +void nscsi_full_device::report_bad_cdb_field() +{ + LOG(" *** BAD CDB FIELD\n"); + report_condition(SK_ILLEGAL_REQUEST, SKC_INVALID_FIELD_IN_CDB); +} + +void nscsi_full_device::report_bad_pl_field() +{ + LOG(" *** BAD PARAMETER LIST FIELD\n"); + report_condition(SK_ILLEGAL_REQUEST, SKC_INVALID_FIELD_IN_PARAMETER_LIST); +} + +void nscsi_full_device::report_bad_pl_len() +{ + LOG(" *** BAD PARAMETER LIST LENGTH\n"); + report_condition(SK_ILLEGAL_REQUEST, SKC_PARAMETER_LIST_LENGTH_ERROR); +} + +void nscsi_full_device::report_no_saving_params() +{ + LOG(" *** NO SAVING PARAMETERS\n"); + report_condition(SK_ILLEGAL_REQUEST, SKC_SAVING_PARAMETERS_NOT_SUPPORTED); +} + +void nscsi_full_device::report_no_medium() +{ + LOG(" *** NO MEDIUM\n"); + report_condition(SK_NOT_READY, SKC_MEDIUM_NOT_PRESENT); +} + +void nscsi_full_device::report_medium_changed() +{ + LOG(" MEDIUM CHANGED\n"); + report_condition(SK_UNIT_ATTENTION, SKC_NOT_READY_TO_READY_TRANSITION_MEDIUM_MAY_HAVE_CHANGED); +} + +void nscsi_full_device::report_read_only() +{ + LOG(" *** READ ONLY\n"); + report_condition(SK_DATA_PROTECT, SKC_WRITE_PROTECTED); +} + +void nscsi_full_device::report_read_failure() +{ + LOG(" *** READ FAILURE\n"); + report_condition(SK_MEDIUM_ERROR, SKC_UNRECOVERED_READ_ERROR); +} + +void nscsi_full_device::report_write_failure() +{ + LOG(" *** WRITE FAILURE\n"); + report_condition(SK_MEDIUM_ERROR, SKC_WRITE_ERROR); +} + +void nscsi_full_device::report_erase_failure() +{ + LOG(" *** ERASE FAILURE\n"); + report_condition(SK_MEDIUM_ERROR, SKC_ERASE_FAILURE); +} + +////////////////////////////////////////////////////////////////////////////// + void nscsi_full_device::scsi_unknown_command() { std::string txt = util::string_format("Unhandled command %s (%d):", command_names[scsi_cmdbuf[0]], scsi_cmdsize); @@ -631,18 +802,34 @@ void nscsi_full_device::scsi_unknown_command() void nscsi_full_device::scsi_command() { - switch(scsi_cmdbuf[0]) { - case SC_REQUEST_SENSE: - LOG("command REQUEST SENSE alloc=%d\n", scsi_cmdbuf[4]); - scsi_data_in(SBUF_SENSE, scsi_cmdbuf[4] ? std::min(scsi_cmdbuf[4], u8(sizeof(scsi_sense_buffer))) : 4); + const u8 cmd = scsi_cmdbuf[0]; + const u8 lun = get_lun(scsi_cmdbuf[1] >> 5); // LUN may be overridden by IDENTIFY, per SCSI-2 section 7.2.2 + switch(cmd) { + case SC_REZERO_UNIT: + LOG("command REZERO UNIT\n"); scsi_status_complete(SS_GOOD); break; + case SC_REQUEST_SENSE: + handle_request_sense(lun); + break; default: scsi_unknown_command(); break; } } +void nscsi_full_device::handle_request_sense(const u8 lun) // mandatory; SCSI-2 section 8.2.14 +{ + const u8 alloc_len = scsi_cmdbuf[4]; // allocation length + LOG("command REQUEST SENSE lun=%d alloc_len=%d\n", lun, alloc_len); + if ((scsi_cmdbuf[1] & 0x1f) || scsi_cmdbuf[2] || scsi_cmdbuf[3]) // error: reserved bits set + return report_bad_cdb_field(); + + assert(sizeof(scsi_sense_buffer) >= 18); + scsi_data_in(SBUF_SENSE, std::min(18, (const int)alloc_len)); + scsi_status_complete(SS_GOOD); +} + void nscsi_full_device::scsi_message() { if(scsi_cmdbuf[0] & 0x80) { @@ -715,7 +902,7 @@ attotime nscsi_full_device::scsi_cable_skew_delay() // Data release delay (400ns) attotime nscsi_full_device::scsi_data_release_delay() { - return attotime::from_nsec(40); + return attotime::from_nsec(400); } // Deskew delay (45ns) @@ -789,3 +976,15 @@ attotime nscsi_full_device::scsi_fast_negation_period() { return attotime::from_nsec(30); } + +// Byte transfer rate (immediate) +attotime nscsi_full_device::scsi_data_byte_period() +{ + return attotime::zero; +} + +// Command execution delay (immediate) +attotime nscsi_full_device::scsi_data_command_delay() +{ + return attotime::zero; +} |