summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/machine/ncr5390.h
blob: 7dfac6f5681b98f9c5da1838d3cae3f818e62b6b (plain) (tree)
1
2
3
4
5
6
7
8
9

                                     




                              
                                          
                                                                          

                                          
                                                                          
 
                                          

       
                                                                                                      
 
                                       

                                                                                                                                                                                      
 





















                                             
                                                  




                              


                                                                                                       























































                                              
                                       












                                      
                                    



                                 
                               




                                    
                                   











































                                                   
                                         

















                                                                                

























                                            
 

                                       




                                 
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#ifndef NCR5390_H
#define NCR5390_H

#include "machine/nscsi_bus.h"

#define MCFG_NCR5390_IRQ_HANDLER(_devcb) \
	devcb = &ncr5390_device::set_irq_handler(*device, DEVCB_##_devcb);

#define MCFG_NCR5390_DRQ_HANDLER(_devcb) \
	devcb = &ncr5390_device::set_drq_handler(*device, DEVCB_##_devcb);

class ncr5390_device : public nscsi_device
{
public:
	ncr5390_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	// static configuration helpers
	template<class _Object> static devcb_base &set_irq_handler(device_t &device, _Object object) { return downcast<ncr5390_device &>(device).m_irq_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_drq_handler(device_t &device, _Object object) { return downcast<ncr5390_device &>(device).m_drq_handler.set_callback(object); }

	DECLARE_ADDRESS_MAP(map, 8);

	DECLARE_READ8_MEMBER(tcount_lo_r);
	DECLARE_WRITE8_MEMBER(tcount_lo_w);
	DECLARE_READ8_MEMBER(tcount_hi_r);
	DECLARE_WRITE8_MEMBER(tcount_hi_w);
	DECLARE_READ8_MEMBER(fifo_r);
	DECLARE_WRITE8_MEMBER(fifo_w);
	DECLARE_READ8_MEMBER(command_r);
	DECLARE_WRITE8_MEMBER(command_w);
	DECLARE_READ8_MEMBER(status_r);
	DECLARE_WRITE8_MEMBER(bus_id_w);
	DECLARE_READ8_MEMBER(istatus_r);
	DECLARE_WRITE8_MEMBER(timeout_w);
	DECLARE_READ8_MEMBER(seq_step_r);
	DECLARE_WRITE8_MEMBER(sync_period_w);
	DECLARE_READ8_MEMBER(fifo_flags_r);
	DECLARE_WRITE8_MEMBER(sync_offset_w);
	DECLARE_READ8_MEMBER(conf_r);
	DECLARE_WRITE8_MEMBER(conf_w);
	DECLARE_WRITE8_MEMBER(clock_w);

	virtual void scsi_ctrl_changed() override;

	UINT8 dma_r();
	void dma_w(UINT8 val);

protected:
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

private:
	enum { MODE_D, MODE_T, MODE_I };
	enum { IDLE };

	enum {
		// Bus initiated sequences
		BUSINIT_SETTLE_DELAY = 1,
		BUSINIT_ASSERT_BUS_SEL,
		BUSINIT_MSG_OUT,
		BUSINIT_RECV_BYTE,
		BUSINIT_ASSERT_BUS_RESEL,
		BUSINIT_WAIT_REQ,
		BUSINIT_RECV_BYTE_NACK,

		// Bus SCSI Reset
		BUSRESET_WAIT_INT,
		BUSRESET_RESET_BOARD,

		// Disconnected state commands
		DISC_SEL_ARBITRATION,
		DISC_SEL_ATN_WAIT_REQ,
		DISC_SEL_ATN_SEND_BYTE,
		DISC_SEL_WAIT_REQ,
		DISC_SEL_SEND_BYTE,
		DISC_REC_ARBITRATION,
		DISC_REC_MSG_IN,
		DISC_REC_SEND_BYTE,
		DISC_RESET,

		// Command sequence
		CMDSEQ_CMD_PHASE,
		CMDSEQ_RECV_BYTE,

		// Target commands
		TARGET_SEND_BYTE,
		TARGET_CMD_RECV_BYTE,
		TARGET_MSG_RECV_BYTE,
		TARGET_MSG_RECV_PAD,
		TARGET_DISC_SEND_BYTE,
		TARGET_DISC_MSG_IN,
		TARGET_DISC_SEND_BYTE_2,

		// Initiator commands
		INIT_MSG_WAIT_REQ,
		INIT_XFR,
		INIT_XFR_SEND_BYTE,
		INIT_XFR_SEND_PAD_WAIT_REQ,
		INIT_XFR_SEND_PAD,
		INIT_XFR_RECV_PAD_WAIT_REQ,
		INIT_XFR_RECV_PAD,
		INIT_XFR_RECV_BYTE_ACK,
		INIT_XFR_RECV_BYTE_NACK,
		INIT_XFR_WAIT_REQ,
		INIT_CPT_RECV_BYTE_ACK,
		INIT_CPT_RECV_WAIT_REQ,
		INIT_CPT_RECV_BYTE_NACK
	};

	enum {
		// Arbitration
		ARB_WAIT_BUS_FREE = 1,
		ARB_COMPLETE,
		ARB_ASSERT_SEL,
		ARB_SET_DEST,
		ARB_RELEASE_BUSY,
		ARB_TIMEOUT_BUSY,
		ARB_TIMEOUT_ABORT,
		ARB_DESKEW_WAIT,

		// Send/receive byte
		SEND_WAIT_SETTLE,
		SEND_WAIT_REQ_0,
		RECV_WAIT_REQ_1,
		RECV_WAIT_SETTLE,
		RECV_WAIT_REQ_0
	};

	enum {
		STATE_MASK = 0x00ff,
		SUB_SHIFT  = 8,
		SUB_MASK   = 0xff00
	};

	enum { BUS_BUSY, BUS_FREE_WAIT, BUS_FREE };

	enum {
		S_GROSS_ERROR     = 0x40,
		S_PARITY          = 0x20,
		S_TC0             = 0x10,
		S_TCC             = 0x08,

		I_SCSI_RESET      = 0x80,
		I_ILLEGAL         = 0x40,
		I_DISCONNECT      = 0x20,
		I_BUS             = 0x10,
		I_FUNCTION        = 0x08,
		I_RESELECTED      = 0x04,
		I_SELECT_ATN      = 0x02,
		I_SELECTED        = 0x01,

		CM_NOP             = 0x00,
		CM_FLUSH_FIFO      = 0x01,
		CM_RESET           = 0x02,
		CM_RESET_BUS       = 0x03,
		CD_RESELECT        = 0x40,
		CD_SELECT          = 0x41,
		CD_SELECT_ATN      = 0x42,
		CD_SELECT_ATN_STOP = 0x43,
		CD_ENABLE_SEL      = 0x44,
		CD_DISABLE_SEL     = 0x45,
		CT_SEND_MSG        = 0x20,
		CT_SEND_STATUS     = 0x21,
		CT_SEND_DATA       = 0x22,
		CT_DISCONNECT_SEQ  = 0x23,
		CT_TERMINATE       = 0x24,
		CT_COMPLETE        = 0x25,
		CT_DISCONNECT      = 0x27,
		CT_RECV_MSG        = 0x28,
		CT_RECV_CMD        = 0x29,
		CT_RECV_DATA       = 0x2a,
		CT_RECV_CMD_SEQ    = 0x2b,
		CI_XFER            = 0x10,
		CI_COMPLETE        = 0x11,
		CI_MSG_ACCEPT      = 0x12,
		CI_PAD             = 0x18,
		CI_SET_ATN         = 0x1a
	};

	enum { DMA_NONE, DMA_IN, DMA_OUT };

	emu_timer *tm;

	UINT8 command[2], config, status, istatus;
	UINT8 clock_conv, sync_offset, sync_period, bus_id, select_timeout, seq;
	UINT8 fifo[16];
	UINT16 tcount;
	int mode, fifo_pos, command_pos;
	int state, xfr_phase;
	int command_length;

	int dma_dir;

	bool irq, drq;

	void dma_set(int dir);
	void drq_set();
	void drq_clear();

	void start_command();
	void step(bool timeout);
	bool check_valid_command(UINT8 cmd);
	int derive_msg_size(UINT8 msg_id);
	void function_complete();
	void function_bus_complete();
	void bus_complete();

	void arbitrate();
	void command_pop_and_chain();
	void check_irq();

	void reset_soft();
	void reset_disconnect();

	UINT8 fifo_pop();
	void fifo_push(UINT8 val);
	void send_byte();
	void recv_byte();

	void delay(int cycles);
	void delay_cycles(int cycles);

	devcb_write_line m_irq_handler;
	devcb_write_line m_drq_handler;
};

extern const device_type NCR5390;

#endif