2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
17 void SCSI_DEV::initialize()
20 buffer = new FIFO(SCSI_BUFFER_SIZE);
21 phase = SCSI_PHASE_BUS_FREE;
24 void SCSI_DEV::release()
30 void SCSI_DEV::reset()
33 sel_status = atn_status = ack_status = rst_status = false;
34 selected = atn_pending = false;
37 event_sel = event_phase = event_req = -1;
38 set_phase(SCSI_PHASE_BUS_FREE);
41 void SCSI_DEV::write_signal(int id, uint32_t data, uint32_t mask)
45 data_bus = data & mask;
50 bool prev_status = sel_status;
51 sel_status = ((data & mask) != 0);
53 if(phase != SCSI_PHASE_BUS_FREE) {
54 // this device is already selected
55 } else if(!prev_status && sel_status) {
57 #ifdef SCSI_DEV_IMMEDIATE_SELECT
58 event_callback(EVENT_SEL, 0);
61 cancel_event(this, event_sel);
63 register_event(this, EVENT_SEL, 20.0, false, &event_sel);
65 } else if(prev_status && !sel_status) {
68 cancel_event(this, event_sel);
73 // change to message out phase
75 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
76 // set_phase(SCSI_PHASE_MESSAGE_OUT);
78 // change to command phase
79 memset(command, 0, sizeof(command));
81 set_phase_delay(SCSI_PHASE_COMMAND, 10.0);
82 // set_phase(SCSI_PHASE_COMMAND);
91 bool prev_status = atn_status;
92 atn_status = ((data & mask) != 0);
94 if(phase == SCSI_PHASE_BUS_FREE) {
95 // this device is not selected
96 } else if(!prev_status && atn_status) {
98 #ifdef _SCSI_DEBUG_LOG
99 this->out_debug_log(_T("[SCSI_DEV:ID=%d] ATN signal raised\n"), scsi_id);
102 // wait until ack=off
105 // change to message out phase
108 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
117 initiator ---> device
130 initiator <--- device
143 bool prev_status = ack_status;
144 ack_status = ((data & mask) != 0);
146 if(phase == SCSI_PHASE_BUS_FREE) {
147 // this device is not selected
148 } else if(!prev_status & ack_status) {
151 case SCSI_PHASE_DATA_OUT:
152 buffer->write(data_bus);
154 // check defect list length in format unit data
155 if(command[0] == SCSI_CMD_FORMAT) {
156 if(buffer->count() == 4) {
157 remain += buffer->read_not_remove(2) * 256 + buffer->read_not_remove(3);
162 case SCSI_PHASE_COMMAND:
163 command[command_index++] = data_bus;
166 case SCSI_PHASE_MESSAGE_OUT:
167 buffer->write(data_bus);
171 } else if(prev_status && !ack_status) {
174 // change to message out phase
177 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
180 case SCSI_PHASE_DATA_OUT:
184 write_buffer(buffer->count());
186 // request to write next data
188 case SCSI_CMD_WRITE6:
189 case SCSI_CMD_WRITE10:
190 case SCSI_CMD_WRITE12:
192 next_req_usec += 1000000.0 / bytes_per_sec;
193 double usec = next_req_usec - get_passed_usec(first_req_clock);
194 set_req_delay(1, (usec > 1.0) ? usec : 1.0);
197 set_req_delay(1, 1.0);
202 if(!buffer->empty()) {
203 write_buffer(buffer->count());
205 // change to status phase
206 set_dat(SCSI_STATUS_GOOD);
207 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
211 case SCSI_PHASE_DATA_IN:
214 if(buffer->count() == 0) {
215 if(remain > SCSI_BUFFER_SIZE) {
216 read_buffer(SCSI_BUFFER_SIZE);
218 read_buffer((int)remain);
221 // request to read next data
222 set_dat(buffer->read());
225 case SCSI_CMD_READ10:
226 case SCSI_CMD_READ12:
228 next_req_usec += 1000000.0 / bytes_per_sec;
229 double usec = next_req_usec - get_passed_usec(first_req_clock);
230 set_req_delay(1, (usec > 1.0) ? usec : 1.0);
234 set_req_delay(1, 1.0);
238 // change to status phase
239 set_dat(SCSI_STATUS_GOOD);
240 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
244 case SCSI_PHASE_COMMAND:
245 if(command_index < get_command_length(command[0])) {
246 // request next command
247 set_req_delay(1, 1.0);
254 case SCSI_PHASE_STATUS:
255 // create message data table
258 buffer->write(0x00); // command complete message
259 // change to message in phase
260 set_dat(buffer->read());
261 set_phase_delay(SCSI_PHASE_MESSAGE_IN, 1.0);
264 case SCSI_PHASE_MESSAGE_OUT:
265 if((buffer->read() & 0xb8) == 0x80) {
266 // identify, change to command phase
267 memset(command, 0, sizeof(command));
269 set_phase_delay(SCSI_PHASE_COMMAND, 10.0);
271 // abort, change to bus free phase
272 set_phase_delay(SCSI_PHASE_BUS_FREE, 10.0);
276 case SCSI_PHASE_MESSAGE_IN:
278 // request to read next data
279 set_dat(buffer->read());
280 set_req_delay(1, 1.0);
282 // change to bus free phase
283 set_phase_delay(SCSI_PHASE_BUS_FREE, 1.0);
294 bool prev_status = rst_status;
295 rst_status = ((data & mask) != 0);
297 if(!prev_status & rst_status) {
299 #ifdef _SCSI_DEBUG_LOG
300 this->out_debug_log(_T("[SCSI_DEV:ID=%d] RST signal raised\n"), scsi_id);
303 set_phase(SCSI_PHASE_BUS_FREE);
310 uint32_t SCSI_DEV::read_signal(int id)
312 uint32_t stat = access ? 1 : 0;
317 void SCSI_DEV::event_callback(int event_id, int err)
322 if((data_bus & 0x7f) == (1 << scsi_id)) {
323 // this device is selected!
324 #ifdef _SCSI_DEBUG_LOG
325 this->out_debug_log(_T("[SCSI_DEV:ID=%d] This device is selected\n"), scsi_id);
334 set_phase(next_phase);
344 void SCSI_DEV::set_phase(int value)
346 #ifdef _SCSI_DEBUG_LOG
347 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Phase %s -> %s\n"), scsi_id, scsi_phase_name[phase], scsi_phase_name[value]);
349 if(event_phase != -1) {
350 cancel_event(this, event_phase);
357 if(value == SCSI_PHASE_BUS_FREE) {
364 set_req_delay(1, 10.0);
369 void SCSI_DEV::set_phase_delay(int value, double usec)
374 if(event_phase != -1) {
375 cancel_event(this, event_phase);
378 register_event(this, EVENT_PHASE, usec, false, &event_phase);
383 void SCSI_DEV::set_dat(int value)
385 #ifdef _SCSI_DEBUG_LOG
386 // emu->force_out_debug_log(_T("[SCSI_DEV:ID=%d] DATA = %02x\n"), scsi_id, value);
388 write_signals(&outputs_dat, value);
391 void SCSI_DEV::set_bsy(int value)
393 #ifdef _SCSI_DEBUG_LOG
394 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] BUSY = %d\n"), scsi_id, value ? 1 : 0);
396 write_signals(&outputs_bsy, value ? 0xffffffff : 0);
399 void SCSI_DEV::set_cd(int value)
401 #ifdef _SCSI_DEBUG_LOG
402 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] C/D = %d\n"), scsi_id, value ? 1 : 0);
404 write_signals(&outputs_cd, value ? 0xffffffff : 0);
407 void SCSI_DEV::set_io(int value)
409 #ifdef _SCSI_DEBUG_LOG
410 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] I/O = %d\n"), scsi_id, value ? 1 : 0);
412 write_signals(&outputs_io, value ? 0xffffffff : 0);
415 void SCSI_DEV::set_msg(int value)
417 #ifdef _SCSI_DEBUG_LOG
418 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] MSG = %d\n"), scsi_id, value ? 1 : 0);
420 write_signals(&outputs_msg, value ? 0xffffffff : 0);
423 void SCSI_DEV::set_req(int value)
425 #ifdef _SCSI_DEBUG_LOG
426 this->out_debug_log(_T("[SCSI_DEV:ID=%d] REQ = %d\n"), scsi_id, value ? 1 : 0);
428 if(event_req != -1) {
429 cancel_event(this, event_req);
432 if(value && first_req_clock == 0) {
433 first_req_clock = get_current_clock();
436 write_signals(&outputs_req, value ? 0xffffffff : 0);
439 void SCSI_DEV::set_req_delay(int value, double usec)
444 if(event_req != -1) {
445 cancel_event(this, event_req);
448 register_event(this, EVENT_REQ, usec, false, &event_req);
453 int SCSI_DEV::get_command_length(int value)
455 switch((value >> 5) & 7) {
470 void SCSI_DEV::start_command()
473 case SCSI_CMD_TST_U_RDY:
474 #ifdef _SCSI_DEBUG_LOG
475 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Test Unit Ready\n"), scsi_id);
477 // change to status phase
478 set_dat(is_device_ready() ? SCSI_STATUS_GOOD : SCSI_STATUS_CHKCOND);
479 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
482 case SCSI_CMD_REQ_SENSE:
483 #ifdef _SCSI_DEBUG_LOG
484 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Request Sense\n"), scsi_id);
487 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
488 position *= physical_block_size;
491 // create sense data table
493 buffer->write(SCSI_SERROR_CURRENT);
495 buffer->write(is_device_ready() ? SCSI_KEY_NOSENSE : SCSI_KEY_UNITATT);
509 // change to data in phase
510 set_dat(buffer->read());
511 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
514 case SCSI_CMD_INQUIRY:
515 #ifdef _SCSI_DEBUG_LOG
516 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Inquiry\n"), scsi_id);
519 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
520 position *= physical_block_size;
523 // create inquiry data table
525 buffer->write(device_type);
526 buffer->write(is_removable ? 0x80 : 0x00);
527 buffer->write(0x02); // ANSI SCSI2
528 buffer->write(0x01); // ANSI-CCS
533 for(int i = 0; i < (int)strlen(vendor_id) && i < 8; i++) {
534 buffer->write(vendor_id[i]);
536 for(int i = strlen(vendor_id); i < 8; i++) {
539 for(int i = 0; i < (int)strlen(product_id) && i < 16; i++) {
540 buffer->write(vendor_id[i]);
542 for(int i = strlen(product_id); i < 16; i++) {
545 // change to data in phase
546 set_dat(buffer->read());
547 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
550 case SCSI_CMD_RD_CAPAC:
551 #ifdef _SCSI_DEBUG_LOG
552 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read Capacity\n"), scsi_id);
554 // initialize max logical block address
555 initialize_max_logical_block_addr();
557 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
558 position *= physical_block_size;
561 // create capacity data table
563 buffer->write((max_logical_block_addr >> 24) & 0xff);
564 buffer->write((max_logical_block_addr >> 16) & 0xff);
565 buffer->write((max_logical_block_addr >> 8) & 0xff);
566 buffer->write((max_logical_block_addr >> 0) & 0xff);
567 buffer->write(( logical_block_size >> 24) & 0xff);
568 buffer->write(( logical_block_size >> 16) & 0xff);
569 buffer->write(( logical_block_size >> 8) & 0xff);
570 buffer->write(( logical_block_size >> 0) & 0xff);
571 // change to data in phase
572 set_dat(buffer->read());
573 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
576 case SCSI_CMD_FORMAT:
577 #ifdef _SCSI_DEBUG_LOG
578 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Format Unit\n"), scsi_id);
580 if(command[1] & 0x10) {
581 // change to data out phase for extra bytes
583 set_phase_delay(SCSI_PHASE_DATA_OUT, 10.0);
585 // no extra bytes, change to status phase
586 set_dat(SCSI_STATUS_GOOD);
587 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
591 case SCSI_CMD_RD_DEFECT:
592 #ifdef _SCSI_DEBUG_LOG
593 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read Defect Data\n"), scsi_id);
597 // create detect data table
600 buffer->write(command[2]);
601 buffer->write(0x00); // msb of defect list length
602 buffer->write(0x00); // lsb of defect list length
603 // change to data in phase
604 set_dat(buffer->read());
605 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
609 #ifdef _SCSI_DEBUG_LOG
610 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 6-byte\n"), scsi_id);
613 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
614 position *= physical_block_size;
616 remain = command[4] * logical_block_size;
620 if(remain > SCSI_BUFFER_SIZE) {
621 read_buffer(SCSI_BUFFER_SIZE);
623 read_buffer((int)remain);
625 // change to data in phase
626 set_dat(buffer->read());
627 set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
629 // transfer length is zero, change to status phase
630 set_dat(SCSI_STATUS_GOOD);
631 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
635 case SCSI_CMD_WRITE6:
636 #ifdef _SCSI_DEBUG_LOG
637 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write 6-Byte\n"), scsi_id);
640 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
641 position *= physical_block_size;
643 remain = command[4] * logical_block_size;
647 // change to data in phase
648 set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
650 // transfer length is zero, change to status phase
651 set_dat(SCSI_STATUS_GOOD);
652 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
656 case SCSI_CMD_READ10:
657 #ifdef _SCSI_DEBUG_LOG
658 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 10-byte\n"), scsi_id);
661 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
662 position *= physical_block_size;
664 remain = command[7] * 0x100 + command[8];
665 remain *= logical_block_size;
669 if(remain > SCSI_BUFFER_SIZE) {
670 read_buffer(SCSI_BUFFER_SIZE);
672 read_buffer((int)remain);
674 // change to data in phase
675 set_dat(buffer->read());
676 set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
678 // transfer length is zero, change to status phase
679 set_dat(SCSI_STATUS_GOOD);
680 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
684 case SCSI_CMD_WRITE10:
685 #ifdef _SCSI_DEBUG_LOG
686 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write 10-Byte\n"), scsi_id);
689 case SCSI_CMD_WRT_VERIFY:
690 #ifdef _SCSI_DEBUG_LOG
691 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write and Verify\n"), scsi_id);
695 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
696 position *= physical_block_size;
698 remain = command[7] * 0x100 + command[8];
699 remain *= logical_block_size;
703 // change to data in phase
704 set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
706 // transfer length is zero, change to status phase
707 set_dat(SCSI_STATUS_GOOD);
708 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
712 case SCSI_CMD_READ12:
713 #ifdef _SCSI_DEBUG_LOG
714 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 12-byte\n"), scsi_id);
717 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
718 position *= physical_block_size;
720 remain = command[6] * 0x1000000 + command[7] * 0x10000 + command[8] * 0x100 + command[9];
721 remain *= logical_block_size;
725 if(remain > SCSI_BUFFER_SIZE) {
726 read_buffer(SCSI_BUFFER_SIZE);
728 read_buffer((int)remain);
730 // change to data in phase
731 set_dat(buffer->read());
732 set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
734 // transfer length is zero, change to status phase
735 set_dat(SCSI_STATUS_GOOD);
736 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
740 case SCSI_CMD_WRITE12:
741 #ifdef _SCSI_DEBUG_LOG
742 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write 12-Byte\n"), scsi_id);
745 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
746 position *= physical_block_size;
748 remain = command[6] * 0x1000000 + command[7] * 0x10000 + command[8] * 0x100 + command[9];
749 remain *= logical_block_size;
753 // change to data in phase
754 set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
756 // transfer length is zero, change to status phase
757 set_dat(SCSI_STATUS_GOOD);
758 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
763 #ifdef _SCSI_DEBUG_LOG
764 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Unknown %02X\n"), scsi_id, command[0]);
766 set_dat(SCSI_STATUS_GOOD);
767 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
771 void SCSI_DEV::read_buffer(int length)
773 for(int i = 0; i < length; i++) {
779 void SCSI_DEV::write_buffer(int length)
781 for(int i = 0; i < length; i++) {
787 #define STATE_VERSION 1
789 void SCSI_DEV::save_state(FILEIO* state_fio)
791 state_fio->FputUint32(STATE_VERSION);
792 state_fio->FputInt32(this_device_id);
794 state_fio->FputUint32(data_bus);
795 state_fio->FputBool(sel_status);
796 state_fio->FputBool(atn_status);
797 state_fio->FputBool(ack_status);
798 state_fio->FputBool(rst_status);
799 state_fio->FputBool(selected);
800 state_fio->FputBool(atn_pending);
801 state_fio->FputInt32(phase);
802 state_fio->FputInt32(next_phase);
803 state_fio->FputInt32(next_req);
804 state_fio->FputInt32(event_sel);
805 state_fio->FputInt32(event_phase);
806 state_fio->FputInt32(event_req);
807 state_fio->FputUint32(first_req_clock);
808 state_fio->FputDouble(next_req_usec);
809 state_fio->Fwrite(command, sizeof(command), 1);
810 state_fio->FputInt32(command_index);
811 buffer->save_state((void *)state_fio);
812 state_fio->FputUint64(position);
813 state_fio->FputUint64(remain);
816 bool SCSI_DEV::load_state(FILEIO* state_fio)
818 if(state_fio->FgetUint32() != STATE_VERSION) {
821 if(state_fio->FgetInt32() != this_device_id) {
824 data_bus = state_fio->FgetUint32();
825 sel_status = state_fio->FgetBool();
826 atn_status = state_fio->FgetBool();
827 ack_status = state_fio->FgetBool();
828 rst_status = state_fio->FgetBool();
829 selected = state_fio->FgetBool();
830 atn_pending = state_fio->FgetBool();
831 phase = state_fio->FgetInt32();
832 next_phase = state_fio->FgetInt32();
833 next_req = state_fio->FgetInt32();
834 event_sel = state_fio->FgetInt32();
835 event_phase = state_fio->FgetInt32();
836 event_req = state_fio->FgetInt32();
837 first_req_clock = state_fio->FgetUint32();
838 next_req_usec = state_fio->FgetDouble();
839 state_fio->Fread(command, sizeof(command), 1);
840 command_index = state_fio->FgetInt32();
841 if(!buffer->load_state((void *)state_fio)) {
844 position = state_fio->FgetUint64();
845 remain = state_fio->FgetUint64();