2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
17 void SCSI_DEV::initialize()
19 buffer = new FIFO(SCSI_BUFFER_SIZE);
20 phase = SCSI_PHASE_BUS_FREE;
23 void SCSI_DEV::release()
29 void SCSI_DEV::reset()
32 sel_status = atn_status = ack_status = rst_status = false;
33 selected = atn_pending = false;
35 event_sel = event_phase = event_req = -1;
36 set_phase(SCSI_PHASE_BUS_FREE);
39 void SCSI_DEV::write_signal(int id, uint32_t data, uint32_t mask)
43 data_bus = data & mask;
48 bool prev_status = sel_status;
49 sel_status = ((data & mask) != 0);
51 if(phase != SCSI_PHASE_BUS_FREE) {
52 // this device is already selected
53 } else if(!prev_status && sel_status) {
55 #ifdef SCSI_DEV_IMMEDIATE_SELECT
56 event_callback(EVENT_SEL, 0);
59 cancel_event(this, event_sel);
61 register_event(this, EVENT_SEL, 20.0, false, &event_sel);
63 } else if(prev_status && !sel_status) {
66 cancel_event(this, event_sel);
71 // change to message out phase
73 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
74 // set_phase(SCSI_PHASE_MESSAGE_OUT);
76 // change to command phase
77 memset(command, 0, sizeof(command));
79 set_phase_delay(SCSI_PHASE_COMMAND, 10.0);
80 // set_phase(SCSI_PHASE_COMMAND);
89 bool prev_status = atn_status;
90 atn_status = ((data & mask) != 0);
92 if(phase == SCSI_PHASE_BUS_FREE) {
93 // this device is not selected
94 } else if(!prev_status && atn_status) {
96 #ifdef _SCSI_DEBUG_LOG
97 this->out_debug_log(_T("[SCSI_DEV:ID=%d] ATN signal raised\n"), scsi_id);
100 // wait until ack=off
103 // change to message out phase
106 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
115 initiator ---> device
128 initiator <--- device
141 bool prev_status = ack_status;
142 ack_status = ((data & mask) != 0);
144 if(phase == SCSI_PHASE_BUS_FREE) {
145 // this device is not selected
146 } else if(!prev_status & ack_status) {
149 case SCSI_PHASE_DATA_OUT:
150 buffer->write(data_bus);
152 // check defect list length in format unit data
153 if(command[0] == SCSI_CMD_FORMAT) {
154 if(buffer->count() == 4) {
155 remain += buffer->read_not_remove(2) * 256 + buffer->read_not_remove(3);
160 case SCSI_PHASE_COMMAND:
161 command[command_index++] = data_bus;
164 case SCSI_PHASE_MESSAGE_OUT:
165 buffer->write(data_bus);
169 } else if(prev_status && !ack_status) {
172 // change to message out phase
175 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
178 case SCSI_PHASE_DATA_OUT:
182 write_buffer(buffer->count());
184 // request to write next data
186 case SCSI_CMD_WRITE6:
187 case SCSI_CMD_WRITE10:
188 case SCSI_CMD_WRITE12:
190 next_req_usec += 1000000.0 / bytes_per_sec;
191 double usec = next_req_usec - get_passed_usec(first_req_clock);
192 set_req_delay(1, (usec > 1.0) ? usec : 1.0);
195 set_req_delay(1, 1.0);
200 if(!buffer->empty()) {
201 write_buffer(buffer->count());
203 // change to status phase
204 set_dat(SCSI_STATUS_GOOD);
205 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
209 case SCSI_PHASE_DATA_IN:
212 if(buffer->count() == 0) {
213 if(remain > SCSI_BUFFER_SIZE) {
214 read_buffer(SCSI_BUFFER_SIZE);
216 read_buffer((int)remain);
219 // request to read next data
220 set_dat(buffer->read());
223 case SCSI_CMD_READ10:
224 case SCSI_CMD_READ12:
226 next_req_usec += 1000000.0 / bytes_per_sec;
227 double usec = next_req_usec - get_passed_usec(first_req_clock);
228 set_req_delay(1, (usec > 1.0) ? usec : 1.0);
232 set_req_delay(1, 1.0);
236 // change to status phase
237 set_dat(SCSI_STATUS_GOOD);
238 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
242 case SCSI_PHASE_COMMAND:
243 if(command_index < get_command_length(command[0])) {
244 // request next command
245 set_req_delay(1, 1.0);
252 case SCSI_PHASE_STATUS:
253 // create message data table
256 buffer->write(0x00); // command complete message
257 // change to message in phase
258 set_dat(buffer->read());
259 set_phase_delay(SCSI_PHASE_MESSAGE_IN, 1.0);
262 case SCSI_PHASE_MESSAGE_OUT:
263 if((buffer->read() & 0xb8) == 0x80) {
264 // identify, change to command phase
265 memset(command, 0, sizeof(command));
267 set_phase_delay(SCSI_PHASE_COMMAND, 10.0);
269 // abort, change to bus free phase
270 set_phase_delay(SCSI_PHASE_BUS_FREE, 10.0);
274 case SCSI_PHASE_MESSAGE_IN:
276 // request to read next data
277 set_dat(buffer->read());
278 set_req_delay(1, 1.0);
280 // change to bus free phase
281 set_phase_delay(SCSI_PHASE_BUS_FREE, 1.0);
292 bool prev_status = rst_status;
293 rst_status = ((data & mask) != 0);
295 if(!prev_status & rst_status) {
297 #ifdef _SCSI_DEBUG_LOG
298 this->out_debug_log(_T("[SCSI_DEV:ID=%d] RST signal raised\n"), scsi_id);
301 set_phase(SCSI_PHASE_BUS_FREE);
308 void SCSI_DEV::event_callback(int event_id, int err)
313 if((data_bus & 0x7f) == (1 << scsi_id)) {
314 // this device is selected!
315 #ifdef _SCSI_DEBUG_LOG
316 this->out_debug_log(_T("[SCSI_DEV:ID=%d] This device is selected\n"), scsi_id);
325 set_phase(next_phase);
335 void SCSI_DEV::set_phase(int value)
337 #ifdef _SCSI_DEBUG_LOG
338 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Phase %s -> %s\n"), scsi_id, scsi_phase_name[phase], scsi_phase_name[value]);
340 if(event_phase != -1) {
341 cancel_event(this, event_phase);
348 if(value == SCSI_PHASE_BUS_FREE) {
355 set_req_delay(1, 10.0);
360 void SCSI_DEV::set_phase_delay(int value, double usec)
365 if(event_phase != -1) {
366 cancel_event(this, event_phase);
369 register_event(this, EVENT_PHASE, usec, false, &event_phase);
374 void SCSI_DEV::set_dat(int value)
376 #ifdef _SCSI_DEBUG_LOG
377 // emu->force_out_debug_log(_T("[SCSI_DEV:ID=%d] DATA = %02x\n"), scsi_id, value);
379 write_signals(&outputs_dat, value);
382 void SCSI_DEV::set_bsy(int value)
384 #ifdef _SCSI_DEBUG_LOG
385 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] BUSY = %d\n"), scsi_id, value ? 1 : 0);
387 write_signals(&outputs_bsy, value ? 0xffffffff : 0);
390 void SCSI_DEV::set_cd(int value)
392 #ifdef _SCSI_DEBUG_LOG
393 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] C/D = %d\n"), scsi_id, value ? 1 : 0);
395 write_signals(&outputs_cd, value ? 0xffffffff : 0);
398 void SCSI_DEV::set_io(int value)
400 #ifdef _SCSI_DEBUG_LOG
401 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] I/O = %d\n"), scsi_id, value ? 1 : 0);
403 write_signals(&outputs_io, value ? 0xffffffff : 0);
406 void SCSI_DEV::set_msg(int value)
408 #ifdef _SCSI_DEBUG_LOG
409 // this->out_debug_log(_T("[SCSI_DEV:ID=%d] MSG = %d\n"), scsi_id, value ? 1 : 0);
411 write_signals(&outputs_msg, value ? 0xffffffff : 0);
414 void SCSI_DEV::set_req(int value)
416 #ifdef _SCSI_DEBUG_LOG
417 this->out_debug_log(_T("[SCSI_DEV:ID=%d] REQ = %d\n"), scsi_id, value ? 1 : 0);
419 if(event_req != -1) {
420 cancel_event(this, event_req);
423 if(value && first_req_clock == 0) {
424 first_req_clock = get_current_clock();
427 write_signals(&outputs_req, value ? 0xffffffff : 0);
430 void SCSI_DEV::set_req_delay(int value, double usec)
435 if(event_req != -1) {
436 cancel_event(this, event_req);
439 register_event(this, EVENT_REQ, usec, false, &event_req);
444 int SCSI_DEV::get_command_length(int value)
446 switch((value >> 5) & 7) {
461 void SCSI_DEV::start_command()
464 case SCSI_CMD_TST_U_RDY:
465 #ifdef _SCSI_DEBUG_LOG
466 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Test Unit Ready\n"), scsi_id);
468 // change to status phase
469 set_dat(is_device_ready() ? SCSI_STATUS_GOOD : SCSI_STATUS_CHKCOND);
470 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
473 case SCSI_CMD_REQ_SENSE:
474 #ifdef _SCSI_DEBUG_LOG
475 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Request Sense\n"), scsi_id);
478 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
479 position *= physical_block_size;
482 // create sense data table
484 buffer->write(SCSI_SERROR_CURRENT);
486 buffer->write(is_device_ready() ? SCSI_KEY_NOSENSE : SCSI_KEY_UNITATT);
500 // change to data in phase
501 set_dat(buffer->read());
502 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
505 case SCSI_CMD_INQUIRY:
506 #ifdef _SCSI_DEBUG_LOG
507 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Inquiry\n"), scsi_id);
510 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
511 position *= physical_block_size;
514 // create inquiry data table
516 buffer->write(device_type);
517 buffer->write(is_removable ? 0x80 : 0x00);
518 buffer->write(0x02); // ANSI SCSI2
519 buffer->write(0x01); // ANSI-CCS
524 for(int i = 0; i < (int)strlen(vendor_id) && i < 8; i++) {
525 buffer->write(vendor_id[i]);
527 for(int i = strlen(vendor_id); i < 8; i++) {
530 for(int i = 0; i < (int)strlen(product_id) && i < 16; i++) {
531 buffer->write(vendor_id[i]);
533 for(int i = strlen(product_id); i < 16; i++) {
536 // change to data in phase
537 set_dat(buffer->read());
538 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
541 case SCSI_CMD_RD_CAPAC:
542 #ifdef _SCSI_DEBUG_LOG
543 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read Capacity\n"), scsi_id);
545 // initialize max logical block address
546 initialize_max_logical_block_addr();
548 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
549 position *= physical_block_size;
552 // create capacity data table
554 buffer->write((max_logical_block_addr >> 24) & 0xff);
555 buffer->write((max_logical_block_addr >> 16) & 0xff);
556 buffer->write((max_logical_block_addr >> 8) & 0xff);
557 buffer->write((max_logical_block_addr >> 0) & 0xff);
558 buffer->write(( logical_block_size >> 24) & 0xff);
559 buffer->write(( logical_block_size >> 16) & 0xff);
560 buffer->write(( logical_block_size >> 8) & 0xff);
561 buffer->write(( logical_block_size >> 0) & 0xff);
562 // change to data in phase
563 set_dat(buffer->read());
564 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
567 case SCSI_CMD_FORMAT:
568 #ifdef _SCSI_DEBUG_LOG
569 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Format Unit\n"), scsi_id);
571 if(command[1] & 0x10) {
572 // change to data out phase for extra bytes
574 set_phase_delay(SCSI_PHASE_DATA_OUT, 10.0);
576 // no extra bytes, change to status phase
577 set_dat(SCSI_STATUS_GOOD);
578 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
582 case SCSI_CMD_RD_DEFECT:
583 #ifdef _SCSI_DEBUG_LOG
584 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read Defect Data\n"), scsi_id);
588 // create detect data table
591 buffer->write(command[2]);
592 buffer->write(0x00); // msb of defect list length
593 buffer->write(0x00); // lsb of defect list length
594 // change to data in phase
595 set_dat(buffer->read());
596 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
600 #ifdef _SCSI_DEBUG_LOG
601 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 6-byte\n"), scsi_id);
604 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
605 position *= physical_block_size;
607 remain = command[4] * logical_block_size;
611 if(remain > SCSI_BUFFER_SIZE) {
612 read_buffer(SCSI_BUFFER_SIZE);
614 read_buffer((int)remain);
616 // change to data in phase
617 set_dat(buffer->read());
618 set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
620 // transfer length is zero, change to status phase
621 set_dat(SCSI_STATUS_GOOD);
622 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
626 case SCSI_CMD_WRITE6:
627 #ifdef _SCSI_DEBUG_LOG
628 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write 6-Byte\n"), scsi_id);
631 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
632 position *= physical_block_size;
634 remain = command[4] * logical_block_size;
638 // change to data in phase
639 set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
641 // transfer length is zero, change to status phase
642 set_dat(SCSI_STATUS_GOOD);
643 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
647 case SCSI_CMD_READ10:
648 #ifdef _SCSI_DEBUG_LOG
649 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 10-byte\n"), scsi_id);
652 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
653 position *= physical_block_size;
655 remain = command[7] * 0x100 + command[8];
656 remain *= logical_block_size;
660 if(remain > SCSI_BUFFER_SIZE) {
661 read_buffer(SCSI_BUFFER_SIZE);
663 read_buffer((int)remain);
665 // change to data in phase
666 set_dat(buffer->read());
667 set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
669 // transfer length is zero, change to status phase
670 set_dat(SCSI_STATUS_GOOD);
671 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
675 case SCSI_CMD_WRITE10:
676 #ifdef _SCSI_DEBUG_LOG
677 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write 10-Byte\n"), scsi_id);
680 case SCSI_CMD_WRT_VERIFY:
681 #ifdef _SCSI_DEBUG_LOG
682 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write and Verify\n"), scsi_id);
686 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
687 position *= physical_block_size;
689 remain = command[7] * 0x100 + command[8];
690 remain *= logical_block_size;
694 // change to data in phase
695 set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
697 // transfer length is zero, change to status phase
698 set_dat(SCSI_STATUS_GOOD);
699 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
703 case SCSI_CMD_READ12:
704 #ifdef _SCSI_DEBUG_LOG
705 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 12-byte\n"), scsi_id);
708 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
709 position *= physical_block_size;
711 remain = command[6] * 0x1000000 + command[7] * 0x10000 + command[8] * 0x100 + command[9];
712 remain *= logical_block_size;
716 if(remain > SCSI_BUFFER_SIZE) {
717 read_buffer(SCSI_BUFFER_SIZE);
719 read_buffer((int)remain);
721 // change to data in phase
722 set_dat(buffer->read());
723 set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
725 // transfer length is zero, change to status phase
726 set_dat(SCSI_STATUS_GOOD);
727 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
731 case SCSI_CMD_WRITE12:
732 #ifdef _SCSI_DEBUG_LOG
733 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Write 12-Byte\n"), scsi_id);
736 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
737 position *= physical_block_size;
739 remain = command[6] * 0x1000000 + command[7] * 0x10000 + command[8] * 0x100 + command[9];
740 remain *= logical_block_size;
744 // change to data in phase
745 set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
747 // transfer length is zero, change to status phase
748 set_dat(SCSI_STATUS_GOOD);
749 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
754 #ifdef _SCSI_DEBUG_LOG
755 this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Unknown %02X\n"), scsi_id, command[0]);
757 set_dat(SCSI_STATUS_GOOD);
758 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
762 void SCSI_DEV::read_buffer(int length)
764 for(int i = 0; i < length; i++) {
770 void SCSI_DEV::write_buffer(int length)
772 for(int i = 0; i < length; i++) {
778 #define STATE_VERSION 1
780 void SCSI_DEV::save_state(FILEIO* state_fio)
782 state_fio->FputUint32(STATE_VERSION);
783 state_fio->FputInt32(this_device_id);
785 state_fio->FputUint32(data_bus);
786 state_fio->FputBool(sel_status);
787 state_fio->FputBool(atn_status);
788 state_fio->FputBool(ack_status);
789 state_fio->FputBool(rst_status);
790 state_fio->FputBool(selected);
791 state_fio->FputBool(atn_pending);
792 state_fio->FputInt32(phase);
793 state_fio->FputInt32(next_phase);
794 state_fio->FputInt32(next_req);
795 state_fio->FputInt32(event_sel);
796 state_fio->FputInt32(event_phase);
797 state_fio->FputInt32(event_req);
798 state_fio->FputUint32(first_req_clock);
799 state_fio->FputDouble(next_req_usec);
800 state_fio->Fwrite(command, sizeof(command), 1);
801 state_fio->FputInt32(command_index);
802 buffer->save_state((void *)state_fio);
803 state_fio->FputUint64(position);
804 state_fio->FputUint64(remain);
807 bool SCSI_DEV::load_state(FILEIO* state_fio)
809 if(state_fio->FgetUint32() != STATE_VERSION) {
812 if(state_fio->FgetInt32() != this_device_id) {
815 data_bus = state_fio->FgetUint32();
816 sel_status = state_fio->FgetBool();
817 atn_status = state_fio->FgetBool();
818 ack_status = state_fio->FgetBool();
819 rst_status = state_fio->FgetBool();
820 selected = state_fio->FgetBool();
821 atn_pending = state_fio->FgetBool();
822 phase = state_fio->FgetInt32();
823 next_phase = state_fio->FgetInt32();
824 next_req = state_fio->FgetInt32();
825 event_sel = state_fio->FgetInt32();
826 event_phase = state_fio->FgetInt32();
827 event_req = state_fio->FgetInt32();
828 first_req_clock = state_fio->FgetUint32();
829 next_req_usec = state_fio->FgetDouble();
830 state_fio->Fread(command, sizeof(command), 1);
831 command_index = state_fio->FgetInt32();
832 if(!buffer->load_state((void *)state_fio)) {
835 position = state_fio->FgetUint64();
836 remain = state_fio->FgetUint64();