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