1 // license:BSD-3-Clause
2 // copyright-holders:Patrick Mackinlay
3 
4 #ifndef MAME_MACHINE_CXD1185_H
5 #define MAME_MACHINE_CXD1185_H
6 
7 #pragma once
8 
9 #include "machine/nscsi_bus.h"
10 
11 class cxd1185_device
12 	: public nscsi_device
13 	, public nscsi_slot_card_interface
14 {
15 public:
16 	cxd1185_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
17 
18 	// device configuration
irq_out_cb()19 	auto irq_out_cb() { return m_irq_out_cb.bind(); }
drq_out_cb()20 	auto drq_out_cb() { return m_drq_out_cb.bind(); }
port_out_cb()21 	auto port_out_cb() { return m_port_out_cb.bind(); }
22 
23 	void map(address_map &map);
24 
25 	// dma and port handlers
26 	u8 dma_r();
27 	void dma_w(u8 data);
28 	void port_w(u8 data);
29 
30 protected:
31 	// device_t overrides
32 	virtual void device_start() override;
33 	virtual void device_reset() override;
34 
35 	// ncsci_device overrides
36 	virtual void scsi_ctrl_changed() override;
37 
38 	// register handlers
39 	u8 status_r();
40 	u8 scsi_data_r();
41 	template <unsigned Register> u8 int_req_r();
42 	u8 scsi_ctrl_monitor_r();
43 	u8 fifo_status_r();
scsi_id_r()44 	u8 scsi_id_r() { return m_scsi_id; }
count_r()45 	template <unsigned Byte> u8 count_r() { return u8(m_count >> (Byte * 8)); }
int_auth_r()46 	template <unsigned Register> u8 int_auth_r() { return m_int_auth[Register]; }
mode_r()47 	u8 mode_r() { return m_mode; }
sync_ctrl_r()48 	u8 sync_ctrl_r() { return m_sync_ctrl; }
scsi_ctrl_r()49 	u8 scsi_ctrl_r() { return m_scsi_ctrl; }
ioport_r()50 	u8 ioport_r() { return m_ioport; }
51 
52 	void command_w(u8 data);
53 	void scsi_data_w(u8 data);
54 	void environ_w(u8 data);
55 	void timer_w(u8 data);
scsi_id_w(u8 data)56 	void scsi_id_w(u8 data) { m_scsi_id = data; }
count_w(u8 data)57 	template <unsigned Byte> void count_w(u8 data) { m_count &= ~(0xffU << (Byte * 8)); m_count |= u32(data) << (Byte * 8); }
58 	template <unsigned Register> void int_auth_w(u8 data);
mode_w(u8 data)59 	void mode_w(u8 data) { m_mode = data; }
sync_ctrl_w(u8 data)60 	void sync_ctrl_w(u8 data) { m_sync_ctrl = data; }
61 	void scsi_ctrl_w(u8 data);
62 	void ioport_w(u8 data);
63 
64 	// state machine
65 	void state_timer(void *ptr, s32 param);
66 	int state_step();
67 
68 	// other logic
69 	void reset_chip();
70 	void reset_fifo();
71 	void int_check();
72 	void set_drq(bool asserted);
73 
74 private:
75 	devcb_write_line m_irq_out_cb;
76 	devcb_write_line m_drq_out_cb;
77 	devcb_write8 m_port_out_cb;
78 
79 	emu_timer *m_state_timer;
80 	enum state : unsigned
81 	{
82 		IDLE,
83 
84 		// arbitration
85 		ARB_BUS_FREE,
86 		ARB_START,
87 		ARB_EVALUATE,
88 
89 		// selection
90 		SEL_START,
91 		SEL_DELAY,
92 		SEL_WAIT_BSY,
93 		SEL_COMPLETE,
94 
95 		// information transfer
96 		XFR_INFO,
97 		XFR_IN,
98 		XFR_IN_NEXT,
99 		XFR_IN_REQ,
100 		XFR_IN_DRAIN,
101 		XFR_OUT,
102 		XFR_OUT_NEXT,
103 		XFR_OUT_REQ,
104 		XFR_INFO_DONE,
105 
106 		// scsi bus reset
107 		BUS_RESET,
108 		BUS_RESET_DONE,
109 
110 		COMPLETE,
111 	}
112 	m_state;
113 
114 	// internal state
115 	bool m_irq_asserted;
116 	bool m_drq_asserted;
117 	util::fifo <u8, 16> m_fifo;
118 	bool m_pio_data_mode;
119 	bool m_pio_ctrl_mode;
120 	u32 m_scsi_ctrl_state;
121 
122 	enum status_mask : u8
123 	{
124 		CIP  = 0x01, // command in progress
125 		MIRQ = 0x02, // monitor irq
126 		TRBZ = 0x04, // transfer byte count zero
127 		TARG = 0x08, // target
128 		INIT = 0x10, // initiator
129 
130 		MDBP = 0x40, // monitor scsi bus DBP
131 		MRST = 0x80, // monitor scsi bus RST
132 	};
133 	enum command_mask : u8
134 	{
135 		CMD  = 0x0f, // command code
136 		TRBE = 0x10, // transfer byte counter enable
137 		DMA  = 0x20, // dma mode
138 		CAT  = 0xc0, // command category
139 
140 		CMD_RESET   = 0x01,
141 		CMD_SEL_ATN = 0x42,
142 		CMD_XFR_PAD = 0xc1,
143 	};
144 	enum int_req1 : u8
145 	{
146 		ARBF = 0x01, // arbitration fail
147 		SWOA = 0x02, // selection without atn
148 		SWA  = 0x04, // selection with atn
149 		RSL  = 0x08, // reselected
150 		STO  = 0x10, // selection time over
151 	};
152 	enum int_req2 : u8
153 	{
154 		RMSG = 0x01, // req in message phase
155 		SPE  = 0x02, // scsi bus parity error
156 		DPE  = 0x04, // data bus parity error
157 		DATN = 0x08, // drive atn
158 		PHC  = 0x10, // phase change
159 		SRST = 0x20, // scsi reset
160 		DCNT = 0x40, // disconnected
161 		FNC  = 0x80, // function complete
162 	};
163 	enum fifo_status_mask : u8
164 	{
165 		FC  = 0x0f, // fifo count
166 		FIF = 0x10, // fifo is full
167 
168 		FIE = 0x80, // fifo is empty
169 	};
170 	enum environ_mask : u8
171 	{
172 		FS0  = 0x01,
173 		FS1  = 0x02,
174 		FS   = 0x03, // clock division ratio
175 
176 		SIRM = 0x10, // irq active low
177 		DPEN = 0x20, // data bus parity enable
178 		SDPM = 0x40, // data bus parity even
179 		DIFE = 0x80, // differential mode
180 	};
181 	enum scsi_ctrl_monitor_mask : u8
182 	{
183 		MATN = 0x01,
184 		MACK = 0x02,
185 		MREQ = 0x04,
186 		MIO  = 0x08,
187 		MCD  = 0x10,
188 		MMSG = 0x20,
189 		MSEL = 0x40,
190 		MBSY = 0x80,
191 	};
192 	enum scsi_id_mask : u8
193 	{
194 		OID  = 0x07, // owner id
195 		SMOD = 0x10, // single initiator mode
196 		SID  = 0xe0, // selecting id
197 		TID  = 0xe0, // target id
198 	};
199 	enum mode_mask : u8
200 	{
201 		BDMA = 0x01, // burst dma mode
202 		SSPE = 0x04, // ignore selection scsi parity error
203 		SPHI = 0x08, // scsi phase change ignore
204 		TMSL = 0x10, // scsi reset timer enable
205 		HATN = 0x20, // halt on atn
206 		HSPE = 0x40, // halt on scsi parity error
207 		HDPE = 0x80, // halt on data bus parity error
208 	};
209 	enum sync_ctrl_mask : u8
210 	{
211 		TOF = 0x0f, // transfer offset
212 		TPD = 0xf0, // transfer cycle
213 	};
214 	enum io_port_mask : u8
215 	{
216 		PRT = 0x0f, // i/o port data
217 		PCN = 0xf0, // i/o port control
218 	};
219 	enum scsi_ctrl_mask : u8
220 	{
221 		AATN = 0x01,
222 		AACK = 0x02,
223 		AREQ = 0x04,
224 		AIO  = 0x08,
225 		ACD  = 0x10,
226 		AMSG = 0x20,
227 		ASEL = 0x40,
228 		ABSY = 0x80,
229 	};
230 
231 	// registers
232 	u8 m_status;
233 	u8 m_command;
234 	u8 m_int_req[2];
235 	u8 m_environ;
236 	unsigned m_sel_time;
237 	unsigned m_rst_time;
238 	u8 m_scsi_id;
239 	u8 m_int_auth[2];
240 	u8 m_mode;
241 	u32 m_count;
242 	u8 m_sync_ctrl;
243 	u8 m_scsi_ctrl;
244 	u8 m_ioport;
245 };
246 
247 DECLARE_DEVICE_TYPE(CXD1185, cxd1185_device)
248 
249 #endif // MAME_MACHINE_CXD1185_H
250