diff options
Diffstat (limited to 'src/emu/machine/nscsi_bus.h')
-rw-r--r-- | src/emu/machine/nscsi_bus.h | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/src/emu/machine/nscsi_bus.h b/src/emu/machine/nscsi_bus.h new file mode 100644 index 00000000000..ea34ad0cbe9 --- /dev/null +++ b/src/emu/machine/nscsi_bus.h @@ -0,0 +1,353 @@ +#ifndef __NSCSI_BUS_H__ +#define __NSCSI_BUS_H__ + +#include "emu.h" + +#define MCFG_NSCSI_BUS_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, NSCSI_BUS, 0) + +#define MCFG_NSCSI_DEVICE_ADD(_tag, _subtag, _type, _clock) \ + MCFG_DEVICE_ADD(_tag, NSCSI_CONNECTOR, 0) \ + downcast<nscsi_connector *>(device)->set_fixed_device(_subtag); \ + MCFG_DEVICE_ADD(_tag ":" _subtag, _type, _clock) + +#define MCFG_NSCSI_FULL_DEVICE_ADD(_tag, _subtag, _type, _clock) \ + MCFG_NSCSI_DEVICE_ADD(_tag, _subtag, _type, _clock) + +#define MCFG_NSCSI_ADD(_tag, _slot_intf, _def_slot, _def_inp) \ + MCFG_DEVICE_ADD(_tag, NSCSI_CONNECTOR, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _def_inp) + +class nscsi_device; + +class nscsi_bus_device : public device_t +{ +public: + nscsi_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + void ctrl_w(int refid, UINT32 lines, UINT32 mask); + void data_w(int refid, UINT32 lines); + void ctrl_wait(int refid, UINT32 lines, UINT32 mask); + + UINT32 ctrl_r() const; + UINT32 data_r() const; + +protected: + virtual void device_start(); + virtual void device_reset(); + virtual void device_config_complete(); + +private: + struct dev_t { + nscsi_device *dev; + UINT32 ctrl, wait_ctrl; + UINT32 data; + }; + + dev_t dev[16]; + int devcnt; + + UINT32 data, ctrl; + + void regen_data(); + void regen_ctrl(int refid); +}; + +class nscsi_connector: public device_t, + public device_slot_interface +{ +public: + nscsi_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual ~nscsi_connector(); + + nscsi_device *get_device(); + void set_fixed_device(const char *subtag); + +protected: + virtual void device_start(); + +private: + const char *fixed_subtag; +}; + +class nscsi_device : public device_t, + public device_slot_card_interface +{ +public: + // Here because the biggest users are the devices, not the bus + enum { + S_INP = 0x0001, + S_CTL = 0x0002, + S_MSG = 0x0004, + S_BSY = 0x0008, + S_SEL = 0x0010, + S_REQ = 0x0020, + S_ACK = 0x0040, + S_ATN = 0x0080, + S_RST = 0x0100, + S_ALL = 0x01ff, + + S_PHASE_DATA_OUT = 0, + S_PHASE_DATA_IN = S_INP, + S_PHASE_COMMAND = S_CTL, + S_PHASE_STATUS = S_CTL|S_INP, + S_PHASE_MSG_OUT = S_MSG|S_CTL, + S_PHASE_MSG_IN = S_MSG|S_CTL|S_INP, + S_PHASE_MASK = S_MSG|S_CTL|S_INP, + }; + + nscsi_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock); + + void connect_to_bus(nscsi_bus_device *bus, int refid, int default_scsi_id); + virtual void scsi_ctrl_changed(); +protected: + int scsi_id; + int scsi_refid; + nscsi_bus_device *scsi_bus; +}; + +class nscsi_full_device : public nscsi_device +{ +public: + nscsi_full_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock); + + virtual void scsi_ctrl_changed(); +protected: + enum { SCSI_TIMER = 100 }; + + // SCSI status returns + enum { + SS_GOOD = 0x00, + SS_CHECK_CONDITION = 0x02, + SS_CONDITION_MET = 0x04, + SS_BUSY = 0x08, + SS_INT_GOOD = 0x10, + SS_INT_CONDITION_MET = 0x14, + SS_RESV_CONFLICT = 0x18, + SS_TERMINATED = 0x22, + SS_QUEUE_FULL = 0x28, + }; + + // SCSI commands + enum { + SC_TEST_UNIT_READY = 0x00, + SC_REZERO = 0x01, + SC_REQUEST_SENSE = 0x03, + SC_FORMAT_UNIT = 0x04, + SC_REASSIGN_BLOCKS = 0x07, + SC_READ = 0x08, + SC_WRITE = 0x0a, + SC_SEEK = 0x0b, + SC_INQUIRY = 0x12, + SC_MODE_SELECT_6 = 0x15, + SC_RESERVE_6 = 0x16, + SC_RELEASE_6 = 0x17, + SC_MODE_SENSE_6 = 0x1a, + SC_START_STOP_UNIT = 0x1b, + SC_RECIEVE_DIAG_RES = 0x1c, + SC_SEND_DIAGNOSTICS = 0x1d, + SC_READ_CAPACITY = 0x25, + SC_READ_EXTENDED = 0x28, + SC_WRITE_EXTENDED = 0x2a, + SC_SEEK_EXTENDED = 0x2b, + SC_WRITE_VERIFY = 0x2e, + SC_VERIFY = 0x2f, + SC_SYNC_CACHE = 0x35, + SC_READ_DEFECT_DATA = 0x37, + SC_READ_DATA_BUFFER = 0x3c, + SC_READ_LONG = 0x3e, + SC_WRITE_LONG = 0x3f, + SC_CHANGE_DEFINITION = 0x40, + SC_LOG_SELECT = 0x4c, + SC_LOG_SENSE = 0x4d, + SC_MODE_SELECT_10 = 0x55, + SC_RESERVE_10 = 0x56, + SC_RELEASE_10 = 0x57, + SC_MODE_SENSE_10 = 0x5a, + }; + + // SCSI Messages + enum { + SM_COMMAND_COMPLETE = 0x00, + SM_EXTENDED_MSG = 0x01, + SM_SAVE_DATA_PTR = 0x02, + SM_RESTORE_PTR = 0x03, + SM_DISCONNECT = 0x04, + SM_INITIATOR_ERROR = 0x05, + SM_ABORT = 0x06, + SM_MSG_REJECT = 0x07, + SM_NOP = 0x08, + SM_MSG_PARITY = 0x09, + SM_LCMD_COMPLETE = 0x0a, + SM_LCMD_COMPLETE_F = 0x0b, + SM_BUS_DEVICE_RESET = 0x0c, + SM_ABORT_TAG = 0x0d, + SM_CLEAR_QUEUE = 0x0e, + SM_INIT_RECOVERY = 0x0f, + SM_RELEASE_RECOVERY = 0x10, + SM_TERMINATE_IO = 0x11, + SM_SIMPLE_QUEUE = 0x20, + SM_HEAD_QUEUE = 0x21, + SM_ORDERED_QUEUE = 0x22, + SM_IGNORE_WIDE_RES = 0x23, + }; + + enum { + SBUF_MAIN, + SBUF_SENSE, + }; + + UINT8 scsi_cmdbuf[4096], scsi_sense_buffer[8]; + int scsi_cmdsize; + UINT8 scsi_identify; + + virtual void device_start(); + virtual void device_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + virtual void scsi_message(); + virtual void scsi_command(); + + void scsi_unknown_command(); + void scsi_status_complete(UINT8 st); + void scsi_data_in(int buf, int size); + void scsi_data_out(int buf, int size); + + void sense(bool deferred, UINT8 key); + int get_lun(int def = 0); + void bad_lun(); + + virtual UINT8 scsi_get_data(int buf, int offset); + + // Default delays: + + // Arbitration delay (2.4us) + virtual attotime scsi_arbitation_delay(); + + // Assertion period (90ns) + virtual attotime scsi_assertion_period(); + + // Bus clear delay (800ns) + virtual attotime scsi_bus_clear_delay(); + + // Bus free delay (800ns) + virtual attotime scsi_bus_free_delay(); + + // Bus set delay (1.8us) + virtual attotime scsi_bus_set_delay(); + + // Bus settle delay (400ns) + virtual attotime scsi_bus_settle_delay(); + + // Cable skew delay (10ns) + virtual attotime scsi_cable_skew_delay(); + + // Data release delay (400ns) + virtual attotime scsi_data_release_delay(); + + // Deskew delay (45ns) + virtual attotime scsi_deskew_delay(); + + // Disconnection delay (200us) + virtual attotime scsi_disconnection_delay(); + + // Hold time (45ns) + virtual attotime scsi_hold_time(); + + // Negation period (90ns) + virtual attotime scsi_negation_period(); + + // Reset hold time (25us) + virtual attotime scsi_reset_hold_time(); + + // Selection abort time (200us) + virtual attotime scsi_selection_abort_time(); + + // Selection timeout delay (250ms) + virtual attotime scsi_selection_timeout_delay(); + + // Fast assertion period (30ns) + virtual attotime scsi_fast_assertion_period(); + + // Fast cable skew delay (5ns) + virtual attotime scsi_fast_cable_skew_delay(); + + // Fast deskew delay (20ns) + virtual attotime scsi_fast_deskew_delay(); + + // Fast hold time (10ns) + virtual attotime scsi_fast_hold_time(); + + // Fast negation period (30ns) + virtual attotime scsi_fast_negation_period(); + +private: + enum { + IDLE, + }; + + enum { + TARGET_SELECT_WAIT_BUS_SETTLE = 1, + TARGET_SELECT_WAIT_SEL_0, + + TARGET_NEXT_CONTROL, + TARGET_WAIT_MSG_BYTE, + TARGET_WAIT_CMD_BYTE, + TARGET_WAIT_DATA_IN_BYTE, + }; + + enum { + RECV_BYTE_T_WAIT_ACK_0 = 1, + RECV_BYTE_T_WAIT_ACK_1, + SEND_BYTE_T_WAIT_ACK_0, + SEND_BYTE_T_WAIT_ACK_1, + }; + + enum { + STATE_MASK = 0x00ff, + SUB_SHIFT = 8, + SUB_MASK = 0xff00, + }; + + enum { + BC_MSG_OR_COMMAND, + BC_STATUS, + BC_MESSAGE_1, + BC_MESSAGE_2, + BC_DATA_IN, + BC_DATA_OUT, + BC_BUS_FREE, + }; + + struct control { + int action; + int param1, param2; + }; + + emu_timer *scsi_timer; + + int scsi_state, scsi_substate; + int scsi_initiator_id; + int data_buffer_id, data_buffer_size, data_buffer_pos; + + control buf_control[32]; + int buf_control_rpos; + int buf_control_wpos; + + control *buf_control_push(); + control *buf_control_pop(); + + void step(bool timeout); + void target_recv_byte(); + void target_send_byte(UINT8 val); + void received(UINT8 val); + void target_send_buffer_byte(); + bool command_done(); +}; + + +extern const device_type NSCSI_BUS; +extern const device_type NSCSI_CONNECTOR; + +#endif + |