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

                                     



                              


                              
                                          
                                                                            

                                          
                                                                            
 
                                          

       
                                                                                                        
 


                                                                                                                                         
 
                                           
 
                                            
                                           
                                            














                                             
                                      

                                       
                                                  
 

                                
 



                                                        
          

                                                                                                                          


                                                                                                       
 

















                                              
                                          
































                                           

                                           


                                       
                                       












                                      
                                    



                                 
                               




                                    
                                   




























                                                   
                                                    










                                          
                                                    



                                          

                                                    





                                           



                                                                                  
                          






                                        

                         
 





                                
                                                      
                                            







                                     
          
                          

        

                                

                                    




                                      
 

                                  

                                       

  
                                              

       
                                                                                                          
 
                                                    
 
                                       
 

                                                           






                                                                                                                            

                                                               













                                                                                                         
                                                    
 








                                                                   



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

#pragma once

#include "machine/nscsi_bus.h"

#define MCFG_NCR5390_IRQ_HANDLER(_devcb) \
	downcast<ncr5390_device &>(*device).set_irq_handler(DEVCB_##_devcb);

#define MCFG_NCR5390_DRQ_HANDLER(_devcb) \
	downcast<ncr5390_device &>(*device).set_drq_handler(DEVCB_##_devcb);

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

	// configuration helpers
	template <class Object> devcb_base &set_irq_handler(Object &&cb) { return m_irq_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_drq_handler(Object &&cb) { return m_drq_handler.set_callback(std::forward<Object>(cb)); }

	virtual void map(address_map &map);

	DECLARE_READ8_MEMBER(tcounter_lo_r);
	DECLARE_WRITE8_MEMBER(tcount_lo_w);
	DECLARE_READ8_MEMBER(tcounter_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(test_w);
	DECLARE_WRITE8_MEMBER(clock_w);

	virtual void scsi_ctrl_changed() override;

	uint8_t dma_r();
	void dma_w(uint8_t val);

	// memory mapped wrappers for dma read/write
	DECLARE_READ8_MEMBER(mdma_r) { return dma_r(); }
	DECLARE_WRITE8_MEMBER(mdma_w) { dma_w(data); }

protected:
	ncr5390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	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;

	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_INIT,
		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_FUNCTION_COMPLETE,
		INIT_XFR_BUS_COMPLETE,
		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,
		CD_SELECT_ATN3     = 0x46, // 53c90a
		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,
		CT_ABORT_DMA       = 0x04, // 53c90a
		CI_XFER            = 0x10,
		CI_COMPLETE        = 0x11,
		CI_MSG_ACCEPT      = 0x12,
		CI_PAD             = 0x18,
		CI_SET_ATN         = 0x1a,
		CI_RESET_ATN       = 0x1b, // 53c90a
	};

	enum { DMA_NONE, DMA_IN, DMA_OUT };

	emu_timer *tm;

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

	int dma_dir;

	bool irq, drq;
	bool dma_command;
	bool test_mode;

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

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

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

protected:
	void reset_soft();

private:
	void reset_disconnect();

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

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

	void decrement_tcounter();

	devcb_write_line m_irq_handler;
	devcb_write_line m_drq_handler;
};

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

	virtual void map(address_map &map) override;

	DECLARE_READ8_MEMBER(status_r);

	DECLARE_READ8_MEMBER(conf2_r) { return config2; };
	DECLARE_WRITE8_MEMBER(conf2_w) { config2 = data; };

protected:
	ncr53c90a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	virtual void device_start() override;
	void reset_soft();

	virtual bool check_valid_command(uint8_t cmd) override;

	// 53c90a uses a previously reserved bit as an interrupt flag
	enum {
		S_INTERRUPT = 0x80,
	};

private:
	u8 config2;
};

class ncr53c94_device : public ncr53c90a_device
{
public:
	ncr53c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	virtual void map(address_map &map) override;

	DECLARE_READ8_MEMBER(conf3_r) { return config3; };
	DECLARE_WRITE8_MEMBER(conf3_w) { config3 = data; };
	DECLARE_WRITE8_MEMBER(fifo_align_w) { fifo_align = data; };

protected:
	virtual void device_start() override;
	void reset_soft();

private:
	u8 config3;
	u8 fifo_align;
};

DECLARE_DEVICE_TYPE(NCR5390, ncr5390_device)
DECLARE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device)
DECLARE_DEVICE_TYPE(NCR53C94, ncr53c94_device)

#endif // MAME_MACHINE_NCR5390_H