OSDN Git Service

[VM][DEVICE] You should add "DECVICE::initialize()" to top of initialize().
[csp-qt/common_source_project-fm7.git] / source / src / vm / scsi_dev.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2016.03.01-
6
7         [ SCSI base device ]
8 */
9
10 #include "scsi_dev.h"
11 #include "../fifo.h"
12
13 #define EVENT_SEL       0
14 #define EVENT_PHASE     1
15 #define EVENT_REQ       2
16
17 void SCSI_DEV::initialize()
18 {
19         DEVICE::initialize();
20         buffer = new FIFO(SCSI_BUFFER_SIZE);
21         phase = SCSI_PHASE_BUS_FREE;
22 }
23
24 void SCSI_DEV::release()
25 {
26         buffer->release();
27         delete buffer;
28 }
29
30 void SCSI_DEV::reset()
31 {
32         data_bus = 0;
33         sel_status = atn_status = ack_status = rst_status = false;
34         selected = atn_pending = false;
35         access = false;
36         
37         event_sel = event_phase = event_req = -1;
38         set_phase(SCSI_PHASE_BUS_FREE);
39 }
40
41 void SCSI_DEV::write_signal(int id, uint32_t data, uint32_t mask)
42 {
43         switch(id) {
44         case SIG_SCSI_DAT:
45                 data_bus = data & mask;
46                 break;
47                 
48         case SIG_SCSI_SEL:
49                 {
50                         bool prev_status = sel_status;
51                         sel_status = ((data & mask) != 0);
52                         
53                         if(phase != SCSI_PHASE_BUS_FREE) {
54                                 // this device is already selected
55                         } else if(!prev_status && sel_status) {
56                                 // L -> H
57 #ifdef SCSI_DEV_IMMEDIATE_SELECT
58                                 event_callback(EVENT_SEL, 0);
59 #else
60                                 if(event_sel != -1) {
61                                         cancel_event(this, event_sel);
62                                 }
63                                 register_event(this, EVENT_SEL, 20.0, false, &event_sel);
64 #endif
65                         } else if(prev_status && !sel_status) {
66                                 // H -> L
67                                 if(event_sel != -1) {
68                                         cancel_event(this, event_sel);
69                                         event_sel = -1;
70                                 }
71                                 if(selected) {
72                                         if(atn_status) {
73                                                 // change to message out phase
74                                                 buffer->clear();
75                                                 set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
76 //                                              set_phase(SCSI_PHASE_MESSAGE_OUT);
77                                         } else {
78                                                 // change to command phase
79                                                 memset(command, 0, sizeof(command));
80                                                 command_index = 0;
81                                                 set_phase_delay(SCSI_PHASE_COMMAND, 10.0);
82 //                                              set_phase(SCSI_PHASE_COMMAND);
83                                         }
84                                 }
85                         }
86                 }
87                 break;
88                 
89         case SIG_SCSI_ATN:
90                 {
91                         bool prev_status = atn_status;
92                         atn_status = ((data & mask) != 0);
93                         
94                         if(phase == SCSI_PHASE_BUS_FREE) {
95                                 // this device is not selected
96                         } else if(!prev_status && atn_status) {
97                                 // L -> H
98                                 #ifdef _SCSI_DEBUG_LOG
99                                         this->out_debug_log(_T("[SCSI_DEV:ID=%d] ATN signal raised\n"), scsi_id);
100                                 #endif
101                                 if(ack_status) {
102                                         // wait until ack=off
103                                         atn_pending = true;
104                                 } else {
105                                         // change to message out phase
106                                         atn_pending = false;
107                                         buffer->clear();
108                                         set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
109                                 }
110                         }
111                 }
112                 break;
113                 
114         case SIG_SCSI_ACK:
115                 {
116 /*
117                         initiator --->  device
118
119                         wait req=on
120                                         set req=on
121                                         wait ack=on
122                         write data
123                         set ack=on
124                         wait req=off
125                                         read data
126                                         set req=off
127                                         wait ack=off
128                         set ack=off
129
130                         initiator <---  device
131
132                         wait req=on
133                                         write data
134                                         set req=on
135                                         wait ack=on
136                         read data
137                         set ack=on
138                         wait req=off
139                                         set req=off
140                                         wait ack=off
141                         set ack=off
142 */
143                         bool prev_status = ack_status;
144                         ack_status = ((data & mask) != 0);
145                         
146                         if(phase == SCSI_PHASE_BUS_FREE) {
147                                 // this device is not selected
148                         } else if(!prev_status & ack_status) {
149                                 // L -> H
150                                 switch(phase) {
151                                 case SCSI_PHASE_DATA_OUT:
152                                         buffer->write(data_bus);
153                                         
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);
158                                                 }
159                                         }
160                                         break;
161                                         
162                                 case SCSI_PHASE_COMMAND:
163                                         command[command_index++] = data_bus;
164                                         break;
165                                         
166                                 case SCSI_PHASE_MESSAGE_OUT:
167                                         buffer->write(data_bus);
168                                         break;
169                                 }
170                                 set_req(0);
171                         } else if(prev_status && !ack_status) {
172                                 // H -> L
173                                 if(atn_pending) {
174                                         // change to message out phase
175                                         atn_pending = false;
176                                         buffer->clear();
177                                         set_phase_delay(SCSI_PHASE_MESSAGE_OUT, 10.0);
178                                 } else {
179                                         switch(phase) {
180                                         case SCSI_PHASE_DATA_OUT:
181                                                 if(--remain > 0) {
182                                                         // flush buffer
183                                                         if(buffer->full()) {
184                                                                 write_buffer(buffer->count());
185                                                         }
186                                                         // request to write next data
187                                                         switch(command[0]) {
188                                                         case SCSI_CMD_WRITE6:
189                                                         case SCSI_CMD_WRITE10:
190                                                         case SCSI_CMD_WRITE12:
191                                                                 {
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);
195                                                                 }
196                                                         default:
197                                                                 set_req_delay(1, 1.0);
198                                                                 break;
199                                                         }
200                                                 } else {
201                                                         // flush buffer
202                                                         if(!buffer->empty()) {
203                                                                 write_buffer(buffer->count());
204                                                         }
205                                                         // change to status phase
206                                                         set_dat(SCSI_STATUS_GOOD);
207                                                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
208                                                 }
209                                                 break;
210                                                 
211                                         case SCSI_PHASE_DATA_IN:
212                                                 if(--remain > 0) {
213                                                         // update buffer
214                                                         if(buffer->count() == 0) {
215                                                                 if(remain > SCSI_BUFFER_SIZE) {
216                                                                         read_buffer(SCSI_BUFFER_SIZE);
217                                                                 } else {
218                                                                         read_buffer((int)remain);
219                                                                 }
220                                                         }
221                                                         // request to read next data
222                                                         set_dat(buffer->read());
223                                                         switch(command[0]) {
224                                                         case SCSI_CMD_READ6:
225                                                         case SCSI_CMD_READ10:
226                                                         case SCSI_CMD_READ12:
227                                                                 {
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);
231                                                                 }
232                                                                 break;
233                                                         default:
234                                                                 set_req_delay(1, 1.0);
235                                                                 break;
236                                                         }
237                                                 } else {
238                                                         // change to status phase
239                                                         set_dat(SCSI_STATUS_GOOD);
240                                                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
241                                                 }
242                                                 break;
243                                                 
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);
248                                                 } else {
249                                                         // start command
250                                                         start_command();
251                                                 }
252                                                 break;
253                                                 
254                                         case SCSI_PHASE_STATUS:
255                                                 // create message data table
256                                                 remain = 1;
257                                                 buffer->clear();
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);
262                                                 break;
263                                                 
264                                         case SCSI_PHASE_MESSAGE_OUT:
265                                                 if((buffer->read() & 0xb8) == 0x80) {
266                                                         // identify, change to command phase
267                                                         memset(command, 0, sizeof(command));
268                                                         command_index = 0;
269                                                         set_phase_delay(SCSI_PHASE_COMMAND, 10.0);
270                                                 } else {
271                                                         // abort, change to bus free phase
272                                                         set_phase_delay(SCSI_PHASE_BUS_FREE, 10.0);
273                                                 }
274                                                 break;
275                                                 
276                                         case SCSI_PHASE_MESSAGE_IN:
277                                                 if(--remain > 0) {
278                                                         // request to read next data
279                                                         set_dat(buffer->read());
280                                                         set_req_delay(1, 1.0);
281                                                 } else {
282                                                         // change to bus free phase
283                                                         set_phase_delay(SCSI_PHASE_BUS_FREE, 1.0);
284                                                 }
285                                                 break;
286                                         }
287                                 }
288                         }
289                 }
290                 break;
291                 
292         case SIG_SCSI_RST:
293                 {
294                         bool prev_status = rst_status;
295                         rst_status = ((data & mask) != 0);
296                         
297                         if(!prev_status & rst_status) {
298                                 // L -> H
299                                 #ifdef _SCSI_DEBUG_LOG
300                                         this->out_debug_log(_T("[SCSI_DEV:ID=%d] RST signal raised\n"), scsi_id);
301                                 #endif
302                                 reset_device();
303                                 set_phase(SCSI_PHASE_BUS_FREE);
304                         }
305                 }
306                 break;
307         }
308 }
309
310 uint32_t SCSI_DEV::read_signal(int id)
311 {
312         uint32_t stat = access ? 1 : 0;
313         access = false;
314         return stat;
315 }
316
317 void SCSI_DEV::event_callback(int event_id, int err)
318 {
319         switch(event_id) {
320         case EVENT_SEL:
321                 event_sel = -1;
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);
326                         #endif
327                         set_bsy(true);
328                         selected = true;
329                 }
330                 break;
331                 
332         case EVENT_PHASE:
333                 event_phase = -1;
334                 set_phase(next_phase);
335                 break;
336                 
337         case EVENT_REQ:
338                 event_req = -1;
339                 set_req(next_req);
340                 break;
341         }
342 }
343
344 void SCSI_DEV::set_phase(int value)
345 {
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]);
348         #endif
349         if(event_phase != -1) {
350                 cancel_event(this, event_phase);
351                 event_phase = -1;
352         }
353         set_io (value & 1);
354         set_msg(value & 2);
355         set_cd (value & 4);
356         
357         if(value == SCSI_PHASE_BUS_FREE) {
358                 set_bsy(false);
359                 set_req(0);
360                 selected = false;
361         } else {
362                 first_req_clock = 0;
363 //              set_bsy(true);
364                 set_req_delay(1, 10.0);
365         }
366         phase = value;
367 }
368
369 void SCSI_DEV::set_phase_delay(int value, double usec)
370 {
371         if(usec <= 0.0) {
372                 set_phase(value);
373         } else {
374                 if(event_phase != -1) {
375                         cancel_event(this, event_phase);
376                         event_phase = -1;
377                 }
378                 register_event(this, EVENT_PHASE, usec, false, &event_phase);
379                 next_phase = value;
380         }
381 }
382
383 void SCSI_DEV::set_dat(int value)
384 {
385         #ifdef _SCSI_DEBUG_LOG
386 //              emu->force_out_debug_log(_T("[SCSI_DEV:ID=%d] DATA = %02x\n"), scsi_id, value);
387         #endif
388         write_signals(&outputs_dat, value);
389 }
390
391 void SCSI_DEV::set_bsy(int value)
392 {
393         #ifdef _SCSI_DEBUG_LOG
394 //              this->out_debug_log(_T("[SCSI_DEV:ID=%d] BUSY = %d\n"), scsi_id, value ? 1 : 0);
395         #endif
396         write_signals(&outputs_bsy, value ? 0xffffffff : 0);
397 }
398
399 void SCSI_DEV::set_cd(int value)
400 {
401         #ifdef _SCSI_DEBUG_LOG
402 //              this->out_debug_log(_T("[SCSI_DEV:ID=%d] C/D = %d\n"), scsi_id, value ? 1 : 0);
403         #endif
404         write_signals(&outputs_cd,  value ? 0xffffffff : 0);
405 }
406
407 void SCSI_DEV::set_io(int value)
408 {
409         #ifdef _SCSI_DEBUG_LOG
410 //              this->out_debug_log(_T("[SCSI_DEV:ID=%d] I/O = %d\n"), scsi_id, value ? 1 : 0);
411         #endif
412         write_signals(&outputs_io,  value ? 0xffffffff : 0);
413 }
414
415 void SCSI_DEV::set_msg(int value)
416 {
417         #ifdef _SCSI_DEBUG_LOG
418 //              this->out_debug_log(_T("[SCSI_DEV:ID=%d] MSG = %d\n"), scsi_id, value ? 1 : 0);
419         #endif
420         write_signals(&outputs_msg, value ? 0xffffffff : 0);
421 }
422
423 void SCSI_DEV::set_req(int value)
424 {
425         #ifdef _SCSI_DEBUG_LOG
426                 this->out_debug_log(_T("[SCSI_DEV:ID=%d] REQ = %d\n"), scsi_id, value ? 1 : 0);
427         #endif
428         if(event_req != -1) {
429                 cancel_event(this, event_req);
430                 event_req = -1;
431         }
432         if(value && first_req_clock == 0) {
433                 first_req_clock = get_current_clock();
434                 next_req_usec = 0.0;
435         }
436         write_signals(&outputs_req, value ? 0xffffffff : 0);
437 }
438
439 void SCSI_DEV::set_req_delay(int value, double usec)
440 {
441         if(usec <= 0.0) {
442                 set_req(value);
443         } else {
444                 if(event_req != -1) {
445                         cancel_event(this, event_req);
446                         event_req = -1;
447                 }
448                 register_event(this, EVENT_REQ, usec, false, &event_req);
449                 next_req = value;
450         }
451 }
452
453 int SCSI_DEV::get_command_length(int value)
454 {
455         switch((value >> 5) & 7) {
456         case 0:
457         case 3:
458         case 6:
459         case 7:
460                 return 6;
461         case 1:
462         case 2:
463                 return 10;
464         case 5:
465                 return 12;
466         }
467         return 6;
468 }
469
470 void SCSI_DEV::start_command()
471 {
472         switch(command[0]) {
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);
476                 #endif
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);
480                 break;
481                 
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);
485                 #endif
486                 // start position
487                 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
488                 position *= physical_block_size;
489                 // transfer length
490                 remain = 16;
491                 // create sense data table
492                 buffer->clear();
493                 buffer->write(SCSI_SERROR_CURRENT);
494                 buffer->write(0x00);
495                 buffer->write(is_device_ready() ? SCSI_KEY_NOSENSE : SCSI_KEY_UNITATT);
496                 buffer->write(0x00);
497                 buffer->write(0x00);
498                 buffer->write(0x00);
499                 buffer->write(0x00);
500                 buffer->write(0x08);
501                 buffer->write(0x00);
502                 buffer->write(0x00);
503                 buffer->write(0x00);
504                 buffer->write(0x00);
505                 buffer->write(0x00);
506                 buffer->write(0x00);
507                 buffer->write(0x00);
508                 buffer->write(0x00);
509                 // change to data in phase
510                 set_dat(buffer->read());
511                 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
512                 break;
513                 
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);
517                 #endif
518                 // start position
519                 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
520                 position *= physical_block_size;
521                 // transfer length
522                 remain = 32;
523                 // create inquiry data table
524                 buffer->clear();
525                 buffer->write(device_type);
526                 buffer->write(is_removable ? 0x80 : 0x00);
527                 buffer->write(0x02); // ANSI SCSI2
528                 buffer->write(0x01); // ANSI-CCS
529                 buffer->write(0x10);
530                 buffer->write(0x00);
531                 buffer->write(0x00);
532                 buffer->write(0x18);
533                 for(int i = 0; i < (int)strlen(vendor_id) && i < 8; i++) {
534                         buffer->write(vendor_id[i]);
535                 }
536                 for(int i = strlen(vendor_id); i < 8; i++) {
537                         buffer->write(0x20);
538                 }
539                 for(int i = 0; i < (int)strlen(product_id) && i < 16; i++) {
540                         buffer->write(vendor_id[i]);
541                 }
542                 for(int i = strlen(product_id); i < 16; i++) {
543                         buffer->write(0x20);
544                 }
545                 // change to data in phase
546                 set_dat(buffer->read());
547                 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
548                 break;
549                 
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);
553                 #endif
554                 // initialize max logical block address
555                 initialize_max_logical_block_addr();
556                 // start position
557                 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
558                 position *= physical_block_size;
559                 // transfer length
560                 remain = 8;
561                 // create capacity data table
562                 buffer->clear();
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);
574                 break;
575                 
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);
579                 #endif
580                 if(command[1] & 0x10) {
581                         // change to data out phase for extra bytes
582                         remain = 4;
583                         set_phase_delay(SCSI_PHASE_DATA_OUT, 10.0);
584                 } else {
585                         // no extra bytes, change to status phase
586                         set_dat(SCSI_STATUS_GOOD);
587                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
588                 }
589                 break;
590                 
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);
594                 #endif
595                 // transfer length
596                 remain = 4;
597                 // create detect data table
598                 buffer->clear();
599                 buffer->write(0x00);
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);
606                 break;
607                 
608         case SCSI_CMD_READ6:
609                 #ifdef _SCSI_DEBUG_LOG
610                         this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Read 6-byte\n"), scsi_id);
611                 #endif
612                 // start position
613                 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
614                 position *= physical_block_size;
615                 // transfer length
616                 remain = command[4] * logical_block_size;
617                 if(remain != 0) {
618                         // read data buffer
619                         buffer->clear();
620                         if(remain > SCSI_BUFFER_SIZE) {
621                                 read_buffer(SCSI_BUFFER_SIZE);
622                         } else {
623                                 read_buffer((int)remain);
624                         }
625                         // change to data in phase
626                         set_dat(buffer->read());
627                         set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
628                 } else {
629                         // transfer length is zero, change to status phase
630                         set_dat(SCSI_STATUS_GOOD);
631                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
632                 }
633                 break;
634                 
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);
638                 #endif
639                 // start position
640                 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
641                 position *= physical_block_size;
642                 // transfer length
643                 remain = command[4] * logical_block_size;
644                 if(remain != 0) {
645                         // clear data buffer
646                         buffer->clear();
647                         // change to data in phase
648                         set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
649                 } else {
650                         // transfer length is zero, change to status phase
651                         set_dat(SCSI_STATUS_GOOD);
652                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
653                 }
654                 break;
655                 
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);
659                 #endif
660                 // start position
661                 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
662                 position *= physical_block_size;
663                 // transfer length
664                 remain = command[7] * 0x100 + command[8];
665                 remain *= logical_block_size;
666                 if(remain != 0) {
667                         // read data buffer
668                         buffer->clear();
669                         if(remain > SCSI_BUFFER_SIZE) {
670                                 read_buffer(SCSI_BUFFER_SIZE);
671                         } else {
672                                 read_buffer((int)remain);
673                         }
674                         // change to data in phase
675                         set_dat(buffer->read());
676                         set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
677                 } else {
678                         // transfer length is zero, change to status phase
679                         set_dat(SCSI_STATUS_GOOD);
680                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
681                 }
682                 break;
683                 
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);
687                 #endif
688                 goto WRITE10;
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);
692                 #endif
693         WRITE10:
694                 // start position
695                 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
696                 position *= physical_block_size;
697                 // transfer length
698                 remain = command[7] * 0x100 + command[8];
699                 remain *= logical_block_size;
700                 if(remain != 0) {
701                         // clear data buffer
702                         buffer->clear();
703                         // change to data in phase
704                         set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
705                 } else {
706                         // transfer length is zero, change to status phase
707                         set_dat(SCSI_STATUS_GOOD);
708                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
709                 }
710                 break;
711                 
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);
715                 #endif
716                 // start position
717                 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
718                 position *= physical_block_size;
719                 // transfer length
720                 remain = command[6] * 0x1000000 + command[7] * 0x10000 + command[8] * 0x100 + command[9];
721                 remain *= logical_block_size;
722                 if(remain != 0) {
723                         // read data buffer
724                         buffer->clear();
725                         if(remain > SCSI_BUFFER_SIZE) {
726                                 read_buffer(SCSI_BUFFER_SIZE);
727                         } else {
728                                 read_buffer((int)remain);
729                         }
730                         // change to data in phase
731                         set_dat(buffer->read());
732                         set_phase_delay(SCSI_PHASE_DATA_IN, seek_time);
733                 } else {
734                         // transfer length is zero, change to status phase
735                         set_dat(SCSI_STATUS_GOOD);
736                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
737                 }
738                 break;
739                 
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);
743                 #endif
744                 // start position
745                 position = command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5];
746                 position *= physical_block_size;
747                 // transfer length
748                 remain = command[6] * 0x1000000 + command[7] * 0x10000 + command[8] * 0x100 + command[9];
749                 remain *= logical_block_size;
750                 if(remain != 0) {
751                         // clear data buffer
752                         buffer->clear();
753                         // change to data in phase
754                         set_phase_delay(SCSI_PHASE_DATA_OUT, seek_time);
755                 } else {
756                         // transfer length is zero, change to status phase
757                         set_dat(SCSI_STATUS_GOOD);
758                         set_phase_delay(SCSI_PHASE_STATUS, 10.0);
759                 }
760                 break;
761                 
762         default:
763                 #ifdef _SCSI_DEBUG_LOG
764                         this->out_debug_log(_T("[SCSI_DEV:ID=%d] Command: Unknown %02X\n"), scsi_id, command[0]);
765                 #endif
766                 set_dat(SCSI_STATUS_GOOD);
767                 set_phase_delay(SCSI_PHASE_STATUS, 10.0);
768         }
769 }
770
771 void SCSI_DEV::read_buffer(int length)
772 {
773         for(int i = 0; i < length; i++) {
774                 buffer->write(0);
775                 position++;
776         }
777 }
778
779 void SCSI_DEV::write_buffer(int length)
780 {
781         for(int i = 0; i < length; i++) {
782                 buffer->read();
783                 position++;
784         }
785 }
786
787 #define STATE_VERSION   1
788
789 void SCSI_DEV::save_state(FILEIO* state_fio)
790 {
791         state_fio->FputUint32(STATE_VERSION);
792         state_fio->FputInt32(this_device_id);
793         
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);
814 }
815
816 bool SCSI_DEV::load_state(FILEIO* state_fio)
817 {
818         if(state_fio->FgetUint32() != STATE_VERSION) {
819                 return false;
820         }
821         if(state_fio->FgetInt32() != this_device_id) {
822                 return false;
823         }
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)) {
842                 return false;
843         }
844         position = state_fio->FgetUint64();
845         remain = state_fio->FgetUint64();
846         return true;
847 }
848