1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert
3 #include "emu.h"
4 #include "nscsi_bus.h"
5 
6 #define LOG_GENERAL     (1U << 0)
7 #define LOG_UNSUPPORTED (1U << 1)
8 #define LOG_STATE       (1U << 2)
9 #define LOG_CONTROL     (1U << 3)
10 #define LOG_DATA        (1U << 4)
11 #define LOG_DATA_SENT   (1U << 5)
12 
13 //#define VERBOSE (LOG_GENERAL | LOG_STATE | LOG_CONTROL | LOG_DATA)
14 #define VERBOSE (LOG_UNSUPPORTED)
15 
16 #include "logmacro.h"
17 
18 DEFINE_DEVICE_TYPE(NSCSI_BUS,       nscsi_bus_device, "nscsi_bus",       "SCSI Bus (new)")
19 DEFINE_DEVICE_TYPE(NSCSI_CONNECTOR, nscsi_connector,  "nscsi_connector", "SCSI Connector Abstraction (new)")
20 
21 
nscsi_bus_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)22 nscsi_bus_device::nscsi_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
23 	device_t(mconfig, NSCSI_BUS, tag, owner, clock), data(0), ctrl(0)
24 {
25 	devcnt = 0;
26 	std::fill(std::begin(dev), std::end(dev), dev_t{ nullptr, 0, 0, 0 });
27 }
28 
device_start()29 void nscsi_bus_device::device_start()
30 {
31 	data = 0;
32 	ctrl = 0;
33 	save_item(NAME(data));
34 	save_item(NAME(ctrl));
35 	for(int i=0; i<devcnt; i++) {
36 		save_item(NAME(dev[i].data), i);
37 		save_item(NAME(dev[i].ctrl), i);
38 		save_item(NAME(dev[i].wait_ctrl), i);
39 	}
40 }
41 
device_reset()42 void nscsi_bus_device::device_reset()
43 {
44 }
45 
regen_data()46 void nscsi_bus_device::regen_data()
47 {
48 	data = 0;
49 	for(int i=0; i<devcnt; i++)
50 		data |= dev[i].data;
51 }
52 
regen_ctrl(int refid)53 void nscsi_bus_device::regen_ctrl(int refid)
54 {
55 	static char const *const phase[8] = {
56 		"dout", "din ", "cmd ", "stat", "4   ", "5   ", "mout", "min "
57 	};
58 
59 	uint32_t octrl = ctrl;
60 	ctrl = 0;
61 	for(int i=0; i<devcnt; i++)
62 		ctrl |= dev[i].ctrl;
63 
64 	if(VERBOSE & LOG_CONTROL) {
65 		LOGMASKED(LOG_CONTROL, "ctrl %c%c%c%c%c%c%c%c%c %s %04x\n",
66 					ctrl & nscsi_device::S_RST ? 'R' : '.',
67 					ctrl & nscsi_device::S_ATN ? 'A' : '.',
68 					ctrl & nscsi_device::S_ACK ? 'K' : '.',
69 					ctrl & nscsi_device::S_REQ ? 'Q' : '.',
70 					ctrl & nscsi_device::S_SEL ? 'S' : '.',
71 					ctrl & nscsi_device::S_BSY ? 'B' : '.',
72 					ctrl & nscsi_device::S_MSG ? 'M' : '.',
73 					ctrl & nscsi_device::S_CTL ? 'C' : '.',
74 					ctrl & nscsi_device::S_INP ? 'I' : '.',
75 					phase[ctrl & 7],
76 					data);
77 		for(int i=0; i<devcnt; i++)
78 			if(dev[i].ctrl) {
79 				LOGMASKED(LOG_CONTROL, "%d=%s%s%s%s%s%s%s%s%s\n", i,
80 							dev[i].ctrl & nscsi_device::S_RST ? "R" : "",
81 							dev[i].ctrl & nscsi_device::S_ATN ? "A" : "",
82 							dev[i].ctrl & nscsi_device::S_ACK ? "K" : "",
83 							dev[i].ctrl & nscsi_device::S_REQ ? "Q" : "",
84 							dev[i].ctrl & nscsi_device::S_MSG ? "M" : "",
85 							dev[i].ctrl & nscsi_device::S_INP ? "I" : "",
86 							dev[i].ctrl & nscsi_device::S_CTL ? "C" : "",
87 							dev[i].ctrl & nscsi_device::S_SEL ? "S" : "",
88 							dev[i].ctrl & nscsi_device::S_BSY ? "B" : "");
89 			}
90 	}
91 
92 	octrl = octrl ^ ctrl;
93 	if(octrl)
94 		for(int i=0; i<devcnt; i++)
95 			if(i != refid && (dev[i].wait_ctrl & octrl))
96 				dev[i].dev->scsi_ctrl_changed();
97 }
98 
data_r() const99 uint32_t nscsi_bus_device::data_r() const
100 {
101 	return data;
102 }
103 
ctrl_r() const104 uint32_t nscsi_bus_device::ctrl_r() const
105 {
106 	return ctrl;
107 }
108 
ctrl_w(int refid,uint32_t lines,uint32_t mask)109 void nscsi_bus_device::ctrl_w(int refid, uint32_t lines, uint32_t mask)
110 {
111 	uint32_t c = dev[refid].ctrl;
112 	dev[refid].ctrl = (c & ~mask) | (lines & mask);
113 	regen_ctrl(refid);
114 }
115 
data_w(int refid,uint32_t lines)116 void nscsi_bus_device::data_w(int refid, uint32_t lines)
117 {
118 	dev[refid].data = lines;
119 	regen_data();
120 }
121 
ctrl_wait(int refid,uint32_t lines,uint32_t mask)122 void nscsi_bus_device::ctrl_wait(int refid, uint32_t lines, uint32_t mask)
123 {
124 	uint32_t w = dev[refid].wait_ctrl;
125 	dev[refid].wait_ctrl = (w & ~mask) | (lines & mask);
126 }
127 
device_resolve_objects()128 void nscsi_bus_device::device_resolve_objects()
129 {
130 	for(int i=0; i<16; i++) {
131 		device_t *subdev = subdevice(string_format("%d", i).c_str());
132 		nscsi_device *sdev = subdev ? downcast<nscsi_connector &>(*subdev).get_device() : nullptr;
133 		if(sdev) {
134 			int rid = devcnt++;
135 			dev[rid].dev = sdev;
136 			sdev->connect_to_bus(this, rid, i);
137 		}
138 	}
139 }
140 
141 
nscsi_connector(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)142 nscsi_connector::nscsi_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
143 	device_t(mconfig, NSCSI_CONNECTOR, tag, owner, clock),
144 	device_single_card_slot_interface<nscsi_slot_card_interface>(mconfig, *this)
145 {
146 }
147 
~nscsi_connector()148 nscsi_connector::~nscsi_connector()
149 {
150 }
151 
device_start()152 void nscsi_connector::device_start()
153 {
154 }
155 
get_device()156 nscsi_device *nscsi_connector::get_device()
157 {
158 	nscsi_slot_card_interface *const connected = get_card_device();
159 	if (connected)
160 		return connected->device().subdevice<nscsi_device>(connected->m_nscsi.finder_tag());
161 	else
162 		return nullptr;
163 }
164 
nscsi_slot_card_interface(const machine_config & mconfig,device_t & device,const char * nscsi_tag)165 nscsi_slot_card_interface::nscsi_slot_card_interface(const machine_config &mconfig, device_t &device, const char *nscsi_tag) :
166 	device_interface(device, "nscsi"),
167 	m_nscsi(device, nscsi_tag)
168 {
169 }
170 
nscsi_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)171 nscsi_device::nscsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
172 	device_t(mconfig, type, tag, owner, clock)
173 {
174 	scsi_id = scsi_refid = -1;
175 	scsi_bus = nullptr;
176 }
177 
connect_to_bus(nscsi_bus_device * bus,int refid,int default_scsi_id)178 void nscsi_device::connect_to_bus(nscsi_bus_device *bus, int refid, int default_scsi_id)
179 {
180 	scsi_bus = bus;
181 	scsi_refid = refid;
182 	scsi_id = default_scsi_id;
183 }
184 
scsi_ctrl_changed()185 void nscsi_device::scsi_ctrl_changed()
186 {
187 }
188 
device_start()189 void nscsi_device::device_start()
190 {
191 	save_item(NAME(scsi_id));
192 }
193 
194 
nscsi_full_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)195 nscsi_full_device::nscsi_full_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
196 	nscsi_device(mconfig, type, tag, owner, clock),
197 	nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF)
198 {
199 }
200 
201 const char *const nscsi_full_device::command_names[256] = {
202 	/* 00 */ "TEST_UNIT_READY", "REZERO", "?", "REQUEST_SENSE", "FORMAT_UNIT", "?", "?", "REASSIGN_BLOCKS",
203 	/* 08 */ "READ_6/RECIEVE", "?", "WRITE_6/SEND", "SEEK", "?", "?", "?", "?",
204 	/* 10 */ "?", "?", "INQUIRY", "?", "?", "MODE_SELECT_6", "RESERVE_6", "RELEASE_6",
205 	/* 18 */ "?", "?", "MODE_SENSE_6", "START_STOP_UNIT", "RECIEVE_DIAG_RES", "SEND_DIAGNOSTICS", "PREVENT_ALLOW_MEDIUM_REMOVAL", "?",
206 	/* 20 */ "?", "?", "?", "READ_FORMAT_CAPACITIES", "?", "READ_CAPACITY", "?", "?",
207 
208 	/* 28 */ "READ_10", "READ_GENERATION", "WRITE_10", "SEEK_10", "ERASE_10", "READ_UPDATED_BLOCK_10", "WRITE_VERIFY", "VERIFY",
209 	/* 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",
210 	/* 38 */ "MEDIUM_SCAN", "COMPARE", "COPY_AND_VERIFY", "WRITE_BUFFER", "READ_DATA_BUFFER", "UPDATE_BLOCK", "READ_LONG", "WRITE_LONG",
211 	/* 40 */ "CHANGE_DEFINITION", "WRITE_SAME", "READ_SUB_CHANNEL", "READ_TOC_PMA_ATIP", "READ_HEADER", "PLAY_AUDIO_10", "GET_CONFIGURATION", "PLAY_AUDIO_MSF",
212 	/* 48 */ "PLAY_AUDIO_TRACK_INDEX", "PLAY_RELATIVE_10", "GET_EVENT_STATUS_NOTIFICATION", "PAUSE_RESUME", "LOG_SELECT", "LOG_SENSE", "STOP_PLAY_SCAN", "?",
213 	/* 50 */ "XDWRITE", "READ_DISC_INFORMATION/XPWRITE", "READ_TRACK_INFORMATION/XDREAD", "RESERVE_TRACK", "SEND_OPC_INFORMATION", "MODE_SELECT_10", "RESERVE_10", "RELEASE_10",
214 	/* 58 */ "REPAIR_TRACK", "READ_MASTER_CUE", "MODE_SENSE_10", "CLOSE_TRACK_SESSION", "READ_BUFFER_CAPACITY", "SEND_CUE_SHEET", "PERSISTENT_RESERVE_IN", "PERSISTENT_RESERVE_OUT",
215 	/* 80 */ "XDWRITE_EXTENDED", "REBUILD", "REGENERATE", "EXTENDED_COPY", "RECEIVE_COPY_RESULTS", "?", "?", "?",
216 	/* 88 */ "?", "?", "?", "?", "?", "?", "?", "?",
217 	/* 90 */ "?", "?", "?", "?", "?", "?", "?", "?",
218 	/* 98 */ "?", "?", "?", "?", "?", "?", "?", "?",
219 	/* 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",
220 	/* a8 */ "READ_12", "PLAY_RELATIVE_12", "WRITE_12", "?", "ERASE_12/GET_PERFORMANCE", "READ_DVD_STRUCTURE", "WRITE_AND_VERIFY_12", "VERIFY_12",
221 	/* 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",
222 	/* b8 */ "?", "READ_CD_MSF", "SCAN_MMC", "SET_CD_SPEED", "PLAY_CD", "MECHANISM_STATUS", "READ_CD", "SEND_DVD_STRUCTURE",
223 	/* c0 */ "?", "?", "?", "?", "?", "?", "?", "?",
224 	/* c8 */ "?", "?", "?", "?", "?", "?", "?", "?",
225 	/* d0 */ "?", "?", "?", "?", "?", "?", "?", "?",
226 	/* d8 */ "?", "?", "?", "?", "?", "?", "?", "?",
227 	/* e0 */ "?", "?", "?", "?", "?", "?", "?", "?",
228 	/* e8 */ "?", "?", "?", "?", "?", "?", "?", "?",
229 	/* f0 */ "?", "?", "?", "?", "?", "?", "?", "?",
230 	/* f8 */ "?", "?", "?", "?", "?", "?", "?", "?",
231 };
232 
device_start()233 void nscsi_full_device::device_start()
234 {
235 	nscsi_device::device_start();
236 	scsi_timer = timer_alloc(SCSI_TIMER);
237 	save_item(NAME(scsi_cmdbuf));
238 	save_item(NAME(scsi_sense_buffer));
239 	save_item(NAME(scsi_cmdsize));
240 	save_item(NAME(scsi_identify));
241 	save_item(NAME(scsi_state));
242 	save_item(NAME(scsi_substate));
243 	save_item(NAME(scsi_initiator_id));
244 	save_item(NAME(data_buffer_id));
245 	save_item(NAME(data_buffer_size));
246 	save_item(NAME(data_buffer_pos));
247 	save_item(NAME(buf_control_rpos));
248 	save_item(NAME(buf_control_wpos));
249 	for(int i=0; i<32; i++) {
250 		save_item(NAME(buf_control[i].action), i);
251 		save_item(NAME(buf_control[i].param1), i);
252 		save_item(NAME(buf_control[i].param2), i);
253 	}
254 }
255 
device_reset()256 void nscsi_full_device::device_reset()
257 {
258 	scsi_state = scsi_substate = IDLE;
259 	buf_control_rpos = buf_control_wpos = 0;
260 	scsi_identify = 0;
261 	data_buffer_size = 0;
262 	data_buffer_pos = 0;
263 	scsi_bus->data_w(scsi_refid, 0);
264 	scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
265 	scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
266 }
267 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)268 void nscsi_full_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
269 {
270 	if(id != SCSI_TIMER)
271 		return;
272 
273 	step(true);
274 
275 }
276 
scsi_ctrl_changed()277 void nscsi_full_device::scsi_ctrl_changed()
278 {
279 	step(false);
280 }
281 
step(bool timeout)282 void nscsi_full_device::step(bool timeout)
283 {
284 	uint32_t ctrl = scsi_bus->ctrl_r();
285 	uint32_t data = scsi_bus->data_r();
286 	if(ctrl & S_RST) {
287 		scsi_bus->data_w(scsi_refid, 0);
288 		scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
289 		scsi_state = IDLE;
290 		LOG("scsi bus reset\n");
291 		scsi_state = scsi_substate = IDLE;
292 		buf_control_rpos = buf_control_wpos = 0;
293 		scsi_identify = 0;
294 		data_buffer_size = 0;
295 		data_buffer_pos = 0;
296 		return;
297 	}
298 
299 	LOGMASKED(LOG_STATE, "state=%d.%d %s\n",
300 		scsi_state & STATE_MASK, (scsi_state & SUB_MASK) >> SUB_SHIFT,
301 		timeout ? "timeout" : "change");
302 
303 	switch(scsi_state & SUB_MASK ? scsi_state & SUB_MASK : scsi_state & STATE_MASK) {
304 	case IDLE:
305 		if(((ctrl & (S_SEL|S_BSY)) == S_SEL) && (scsi_id != -1) && ((data & (1 << scsi_id)) != 0)) {
306 			for(scsi_initiator_id = 0; scsi_initiator_id != 16 && (scsi_initiator_id == scsi_id || (data & (1 << scsi_initiator_id))); scsi_initiator_id++) {};
307 			if(scsi_initiator_id == 16)
308 				scsi_initiator_id = -1;
309 			scsi_state = TARGET_SELECT_WAIT_BUS_SETTLE;
310 			scsi_timer->adjust(scsi_bus_settle_delay());
311 		}
312 		break;
313 
314 	case TARGET_SELECT_WAIT_BUS_SETTLE:
315 		if((ctrl & (S_SEL|S_BSY)) == S_SEL) {
316 			scsi_state = TARGET_SELECT_WAIT_SEL_0;
317 			scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
318 		} else
319 			scsi_state = IDLE;
320 		break;
321 
322 	case TARGET_SELECT_WAIT_SEL_0:
323 		if(ctrl & S_SEL)
324 			break;
325 		buf_control_push()->action = BC_MSG_OR_COMMAND;
326 		scsi_state = TARGET_NEXT_CONTROL;
327 		step(false);
328 		break;
329 
330 	case RECV_BYTE_T_WAIT_ACK_1 << SUB_SHIFT:
331 		if(ctrl & S_ACK) {
332 			scsi_put_data(data_buffer_id, data_buffer_pos++, scsi_bus->data_r());
333 			scsi_state = (scsi_state & STATE_MASK) | (RECV_BYTE_T_WAIT_ACK_0 << SUB_SHIFT);
334 			scsi_bus->ctrl_w(scsi_refid, 0, S_REQ);
335 		}
336 		break;
337 
338 	case RECV_BYTE_T_WAIT_ACK_0 << SUB_SHIFT:
339 		if(!(ctrl & S_ACK)) {
340 			scsi_state &= STATE_MASK;
341 			scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK);
342 			step(false);
343 		}
344 		break;
345 
346 	case SEND_BYTE_T_WAIT_ACK_1 << SUB_SHIFT:
347 		if(ctrl & S_ACK) {
348 			scsi_state = (scsi_state & STATE_MASK) | (SEND_BYTE_T_WAIT_ACK_0 << SUB_SHIFT);
349 			scsi_bus->data_w(scsi_refid, 0);
350 			scsi_bus->ctrl_w(scsi_refid, 0, S_REQ);
351 		}
352 		break;
353 
354 	case SEND_BYTE_T_WAIT_ACK_0 << SUB_SHIFT:
355 		if(!(ctrl & S_ACK)) {
356 			scsi_state &= STATE_MASK;
357 			scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK);
358 			step(false);
359 		}
360 		break;
361 
362 	case TARGET_NEXT_CONTROL: {
363 		control *ctl = buf_control_pop();
364 		switch(ctl->action) {
365 		case BC_MSG_OR_COMMAND:
366 			data_buffer_id = SBUF_MAIN;
367 			data_buffer_pos = 0;
368 			if(ctrl & S_ATN) {
369 				scsi_state = TARGET_WAIT_MSG_BYTE;
370 				scsi_bus->ctrl_w(scsi_refid, S_PHASE_MSG_OUT, S_PHASE_MASK);
371 			} else {
372 				scsi_state = TARGET_WAIT_CMD_BYTE;
373 				scsi_bus->ctrl_w(scsi_refid, S_PHASE_COMMAND, S_PHASE_MASK);
374 			}
375 			target_recv_byte();
376 			break;
377 
378 		case BC_STATUS:
379 			scsi_bus->ctrl_w(scsi_refid, S_PHASE_STATUS, S_PHASE_MASK);
380 			target_send_byte(ctl->param1);
381 			break;
382 
383 		case BC_DATA_IN:
384 			scsi_bus->ctrl_w(scsi_refid, S_PHASE_DATA_IN, S_PHASE_MASK);
385 			data_buffer_id = ctl->param1;
386 			data_buffer_size = ctl->param2;
387 			data_buffer_pos = 0;
388 			if (data_buffer_size > 0) {
389 				scsi_state = TARGET_WAIT_DATA_IN_BYTE;
390 			}
391 			else {
392 				scsi_state = TARGET_NEXT_CONTROL;
393 			}
394 			step(false);
395 			break;
396 
397 		case BC_DATA_OUT:
398 			scsi_bus->ctrl_w(scsi_refid, S_PHASE_DATA_OUT, S_PHASE_MASK);
399 			data_buffer_id = ctl->param1;
400 			data_buffer_size = ctl->param2;
401 			data_buffer_pos = 0;
402 			if (data_buffer_size > 0) {
403 				scsi_state = TARGET_WAIT_DATA_OUT_BYTE;
404 			}
405 			else {
406 				scsi_state = TARGET_NEXT_CONTROL;
407 			}
408 			step(false);
409 			break;
410 
411 		case BC_MESSAGE_1:
412 			scsi_bus->ctrl_w(scsi_refid, S_PHASE_MSG_IN, S_PHASE_MASK);
413 			target_send_byte(ctl->param1);
414 			break;
415 
416 		case BC_BUS_FREE:
417 			scsi_bus->data_w(scsi_refid, 0);
418 			scsi_bus->ctrl_wait(scsi_refid, S_BSY|S_SEL|S_RST, S_ALL);
419 			scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
420 			scsi_state = IDLE;
421 			break;
422 		};
423 		break;
424 	}
425 
426 	case TARGET_WAIT_DATA_IN_BYTE:
427 		if(data_buffer_pos == data_buffer_size-1)
428 			scsi_state = TARGET_NEXT_CONTROL;
429 		target_send_buffer_byte();
430 		break;
431 
432 	case TARGET_WAIT_DATA_OUT_BYTE:
433 		if(data_buffer_pos == data_buffer_size-1)
434 			scsi_state = TARGET_NEXT_CONTROL;
435 		target_recv_byte();
436 		break;
437 
438 	case TARGET_WAIT_MSG_BYTE:
439 		if(ctrl & S_SEL)
440 			return;
441 		if(!(ctrl & S_ATN)) {
442 			scsi_cmdsize = data_buffer_pos;
443 			scsi_message();
444 			data_buffer_id = SBUF_MAIN;
445 			data_buffer_pos = 0;
446 			scsi_state = TARGET_WAIT_CMD_BYTE;
447 			scsi_bus->ctrl_w(scsi_refid, S_PHASE_COMMAND, S_PHASE_MASK);
448 		}
449 		target_recv_byte();
450 		break;
451 
452 	case TARGET_WAIT_CMD_BYTE:
453 		if(ctrl & S_SEL)
454 			return;
455 		if(ctrl & S_ATN) {
456 			LOG("Parity error? Say what?\n");
457 			scsi_state = IDLE;
458 			break;
459 		}
460 
461 		if(scsi_command_done(scsi_cmdbuf[0], data_buffer_pos)) {
462 			scsi_cmdsize = data_buffer_pos;
463 			scsi_bus->ctrl_wait(scsi_refid, 0, S_ACK);
464 			scsi_command();
465 			scsi_state = TARGET_NEXT_CONTROL;
466 			step(false);
467 		} else
468 			target_recv_byte();
469 		break;
470 
471 	default:
472 		LOG("step() unexpected state %d.%d\n",
473 			scsi_state & STATE_MASK, (scsi_state & SUB_MASK) >> SUB_SHIFT);
474 		exit(0);
475 	}
476 }
477 
target_recv_byte()478 void nscsi_full_device::target_recv_byte()
479 {
480 	scsi_bus->ctrl_wait(scsi_refid, S_ACK, S_ACK);
481 	scsi_state = (scsi_state & STATE_MASK) | (RECV_BYTE_T_WAIT_ACK_1 << SUB_SHIFT);
482 	scsi_bus->ctrl_w(scsi_refid, S_REQ, S_REQ);
483 	step(false);
484 }
485 
target_send_byte(uint8_t val)486 void nscsi_full_device::target_send_byte(uint8_t val)
487 {
488 	scsi_bus->ctrl_wait(scsi_refid, S_ACK, S_ACK);
489 	scsi_state = (scsi_state & STATE_MASK) | (SEND_BYTE_T_WAIT_ACK_1 << SUB_SHIFT);
490 	scsi_bus->data_w(scsi_refid, val);
491 	scsi_bus->ctrl_w(scsi_refid, S_REQ, S_REQ);
492 	step(false);
493 }
494 
scsi_get_data(int id,int pos)495 uint8_t nscsi_full_device::scsi_get_data(int id, int pos)
496 {
497 	switch(id) {
498 	case SBUF_MAIN:
499 		LOGMASKED(LOG_DATA, "scsi_get_data MAIN, id:%d pos:%d data:%02x %c\n", id, pos, scsi_cmdbuf[pos], scsi_cmdbuf[pos] >= 0x20 && scsi_cmdbuf[pos] < 0x7f ? (char)scsi_cmdbuf[pos] : ' ');
500 		return scsi_cmdbuf[pos];
501 	case SBUF_SENSE:
502 		return scsi_sense_buffer[pos];
503 	default:
504 		fatalerror("nscsi_full_device::scsi_get_data - unknown id\n");
505 	}
506 }
507 
scsi_put_data(int id,int pos,uint8_t data)508 void nscsi_full_device::scsi_put_data(int id, int pos, uint8_t data)
509 {
510 	switch(id) {
511 	case SBUF_MAIN:
512 		LOGMASKED(LOG_DATA, "nscsi_bus: scsi_put_data MAIN, id:%d pos:%d data:%02x %c\n", id, pos, data, data >= 0x20 && data < 0x7f ? (char)data : ' ');
513 		scsi_cmdbuf[pos] = data;
514 		break;
515 	case SBUF_SENSE:
516 		scsi_sense_buffer[pos] = data;
517 		break;
518 	default:
519 		fatalerror("nscsi_full_device::scsi_put_data - unknown id\n");
520 	}
521 }
522 
target_send_buffer_byte()523 void nscsi_full_device::target_send_buffer_byte()
524 {
525 	target_send_byte(scsi_get_data(data_buffer_id, data_buffer_pos++));
526 }
527 
scsi_command_done(uint8_t command,uint8_t length)528 bool nscsi_full_device::scsi_command_done(uint8_t command, uint8_t length)
529 {
530 	if(!length)
531 		return false;
532 	switch(command >> 5) {
533 	case 0: return length == 6;
534 	case 1: return length == 10;
535 	case 2: return length == 10;
536 	case 3: return true;
537 	case 4: return true;
538 	case 5: return length == 12;
539 	case 6: return true;
540 	case 7: return true;
541 	}
542 	return true;
543 }
544 
buf_control_push()545 nscsi_full_device::control *nscsi_full_device::buf_control_push()
546 {
547 	if(buf_control_wpos == int(ARRAY_LENGTH(buf_control)))
548 		throw emu_fatalerror("%s: buf_control overflow\n", tag());
549 
550 	control *c = buf_control + buf_control_wpos;
551 	buf_control_wpos++;
552 	return c;
553 }
554 
buf_control_pop()555 nscsi_full_device::control *nscsi_full_device::buf_control_pop()
556 {
557 	if(buf_control_rpos == buf_control_wpos)
558 		throw emu_fatalerror("%s: buf_control underflow\n", tag());
559 
560 	control *c = buf_control + buf_control_rpos;
561 	buf_control_rpos++;
562 	if(buf_control_rpos == buf_control_wpos)
563 		buf_control_rpos = buf_control_wpos = 0;
564 	return c;
565 }
566 
scsi_status_complete(uint8_t st)567 void nscsi_full_device::scsi_status_complete(uint8_t st)
568 {
569 	control *c;
570 	c = buf_control_push();
571 	c->action = BC_STATUS;
572 	c->param1 = st;
573 	c = buf_control_push();
574 	c->action = BC_MESSAGE_1;
575 	c->param1 = SM_COMMAND_COMPLETE;
576 	c = buf_control_push();
577 	c->action = BC_BUS_FREE;
578 }
579 
scsi_data_in(int buf,int size)580 void nscsi_full_device::scsi_data_in(int buf, int size)
581 {
582 	if((VERBOSE & LOG_DATA_SENT) && buf == 0) {
583 		std::string dt = "";
584 		int sz = size;
585 		if(sz > 50)
586 			sz = 50;
587 		for(int i=0; i<sz; i++)
588 			dt += util::string_format(" %02x", scsi_cmdbuf[i]);
589 		if(size > sz)
590 			dt += " ...";
591 		LOGMASKED(LOG_DATA_SENT, "Sending data (%d)%s\n", size, dt);
592 	}
593 	control *c;
594 	c = buf_control_push();
595 	c->action = BC_DATA_IN;
596 	c->param1 = buf;
597 	c->param2 = size;
598 }
599 
scsi_data_out(int buf,int size)600 void nscsi_full_device::scsi_data_out(int buf, int size)
601 {
602 	control *c;
603 	c = buf_control_push();
604 	c->action = BC_DATA_OUT;
605 	c->param1 = buf;
606 	c->param2 = size;
607 }
608 
sense(bool deferred,uint8_t key,uint8_t asc,uint8_t ascq)609 void nscsi_full_device::sense(bool deferred, uint8_t key, uint8_t asc, uint8_t ascq)
610 {
611 	memset(scsi_sense_buffer, 0, sizeof(scsi_sense_buffer));
612 	scsi_sense_buffer[0] = deferred ? 0x71 : 0x70;
613 	scsi_sense_buffer[2] = key;
614 	scsi_sense_buffer[7] = sizeof(scsi_sense_buffer) - 8;
615 	scsi_sense_buffer[12] = asc;
616 	scsi_sense_buffer[13] = ascq;
617 }
618 
scsi_unknown_command()619 void nscsi_full_device::scsi_unknown_command()
620 {
621 	std::string txt = util::string_format("Unhandled command %s (%d):", command_names[scsi_cmdbuf[0]], scsi_cmdsize);
622 	for(int i=0; i != scsi_cmdsize; i++)
623 		txt += util::string_format(" %02x", scsi_cmdbuf[i]);
624 	LOGMASKED(LOG_UNSUPPORTED, "%s\n", txt);
625 
626 	scsi_status_complete(SS_CHECK_CONDITION);
627 	sense(false, SK_ILLEGAL_REQUEST);
628 }
629 
scsi_command()630 void nscsi_full_device::scsi_command()
631 {
632 	switch(scsi_cmdbuf[0]) {
633 	case SC_REZERO:
634 		LOG("command REZERO\n");
635 		scsi_status_complete(SS_GOOD);
636 		break;
637 	case SC_REQUEST_SENSE:
638 		LOG("command REQUEST SENSE alloc=%d\n", scsi_cmdbuf[4]);
639 		scsi_data_in(SBUF_SENSE, scsi_cmdbuf[4] ? std::min(scsi_cmdbuf[4], u8(sizeof(scsi_sense_buffer))) : 4);
640 		scsi_status_complete(SS_GOOD);
641 		break;
642 	default:
643 		scsi_unknown_command();
644 		break;
645 	}
646 }
647 
scsi_message()648 void nscsi_full_device::scsi_message()
649 {
650 	if(scsi_cmdbuf[0] & 0x80) {
651 		scsi_identify = scsi_cmdbuf[0];
652 		return;
653 	}
654 
655 	std::string txt = "Unknown message";
656 	for(int i=0; i != scsi_cmdsize; i++)
657 		txt += util::string_format(" %02x", scsi_cmdbuf[i]);
658 	LOGMASKED(LOG_UNSUPPORTED, "%s\n", txt);
659 }
660 
get_lun(int def)661 int nscsi_full_device::get_lun(int def)
662 {
663 	if(scsi_identify & 0x80)
664 		// lower 3 bits contain LUNTRN
665 		return scsi_identify & 0x07;
666 	return def;
667 }
668 
bad_lun()669 void nscsi_full_device::bad_lun()
670 {
671 	scsi_status_complete(SS_CHECK_CONDITION);
672 	sense(false, SK_ILLEGAL_REQUEST, SK_ASC_LOGICAL_UNIT_NOT_SUPPORTED);
673 }
674 
675 // Arbitration delay (2.4us)
scsi_arbitation_delay()676 attotime nscsi_full_device::scsi_arbitation_delay()
677 {
678 	return attotime::from_nsec(2400);
679 }
680 
681 // Assertion period (90ns)
scsi_assertion_period()682 attotime nscsi_full_device::scsi_assertion_period()
683 {
684 	return attotime::from_nsec(90);
685 }
686 
687 // Bus clear delay (800ns)
scsi_bus_clear_delay()688 attotime nscsi_full_device::scsi_bus_clear_delay()
689 {
690 	return attotime::from_nsec(800);
691 }
692 
693 // Bus free delay (800ns)
scsi_bus_free_delay()694 attotime nscsi_full_device::scsi_bus_free_delay()
695 {
696 	return attotime::from_nsec(800);
697 }
698 
699 // Bus set delay (1.8us)
scsi_bus_set_delay()700 attotime nscsi_full_device::scsi_bus_set_delay()
701 {
702 	return attotime::from_nsec(1800);
703 }
704 
705 // Bus settle delay (400ns)
scsi_bus_settle_delay()706 attotime nscsi_full_device::scsi_bus_settle_delay()
707 {
708 	return attotime::from_nsec(400);
709 }
710 
711 // Cable skew delay (10ns)
scsi_cable_skew_delay()712 attotime nscsi_full_device::scsi_cable_skew_delay()
713 {
714 	return attotime::from_nsec(10);
715 }
716 
717 // Data release delay (400ns)
scsi_data_release_delay()718 attotime nscsi_full_device::scsi_data_release_delay()
719 {
720 	return attotime::from_nsec(40);
721 }
722 
723 // Deskew delay (45ns)
scsi_deskew_delay()724 attotime nscsi_full_device::scsi_deskew_delay()
725 {
726 	return attotime::from_nsec(45);
727 }
728 
729 // Disconnection delay (200us)
scsi_disconnection_delay()730 attotime nscsi_full_device::scsi_disconnection_delay()
731 {
732 	return attotime::from_usec(200);
733 }
734 
735 // Hold time (45ns)
scsi_hold_time()736 attotime nscsi_full_device::scsi_hold_time()
737 {
738 	return attotime::from_nsec(45);
739 }
740 
741 // Negation period (90ns)
scsi_negation_period()742 attotime nscsi_full_device::scsi_negation_period()
743 {
744 	return attotime::from_nsec(90);
745 }
746 
747 // Reset hold time (25us)
scsi_reset_hold_time()748 attotime nscsi_full_device::scsi_reset_hold_time()
749 {
750 	return attotime::from_usec(25);
751 }
752 
753 // Selection abort time (200us)
scsi_selection_abort_time()754 attotime nscsi_full_device::scsi_selection_abort_time()
755 {
756 	return attotime::from_usec(200);
757 }
758 
759 // Selection timeout delay (250ms)
scsi_selection_timeout_delay()760 attotime nscsi_full_device::scsi_selection_timeout_delay()
761 {
762 	return attotime::from_msec(250);
763 }
764 
765 // Fast assertion period (30ns)
scsi_fast_assertion_period()766 attotime nscsi_full_device::scsi_fast_assertion_period()
767 {
768 	return attotime::from_nsec(30);
769 }
770 
771 // Fast cable skew delay (5ns)
scsi_fast_cable_skew_delay()772 attotime nscsi_full_device::scsi_fast_cable_skew_delay()
773 {
774 	return attotime::from_nsec(5);
775 }
776 
777 // Fast deskew delay (20ns)
scsi_fast_deskew_delay()778 attotime nscsi_full_device::scsi_fast_deskew_delay()
779 {
780 	return attotime::from_nsec(20);
781 }
782 
783 // Fast hold time (10ns)
scsi_fast_hold_time()784 attotime nscsi_full_device::scsi_fast_hold_time()
785 {
786 	return attotime::from_nsec(10);
787 }
788 
789 // Fast negation period (30ns)
scsi_fast_negation_period()790 attotime nscsi_full_device::scsi_fast_negation_period()
791 {
792 	return attotime::from_nsec(30);
793 }
794