2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ SCSI hard disk drive ]
13 void SCSI_HDD::initialize_max_logical_block_addr()
15 if(max_logical_block_addr == 0) {
16 FILEIO* fio = new FILEIO();
17 uint32_t file_size = 0;
19 if(default_drive_size == 0) {
20 default_drive_size = 0x2800000; // 40MB
22 if(FILEIO::IsFileExisting(create_local_path(_T("SCSI%d.DAT"), scsi_id))) {
23 if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_READ_WRITE_BINARY)) {
24 if((file_size = fio->FileLength()) == 0) {
25 uint32_t remain = (file_size = default_drive_size);
26 void *tmp = calloc(1, SCSI_BUFFER_SIZE);
28 uint32_t length = min(remain, (uint32_t)SCSI_BUFFER_SIZE);
29 fio->Fwrite(tmp, length, 1);
37 if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_WRITE_BINARY)) {
38 uint32_t remain = (file_size = default_drive_size);
39 void *tmp = calloc(1, SCSI_BUFFER_SIZE);
41 uint32_t length = min(remain, (uint32_t)SCSI_BUFFER_SIZE);
42 fio->Fwrite(tmp, length, 1);
50 max_logical_block_addr = (file_size / logical_block_size) - 1;
56 void SCSI_HDD::start_command()
59 case SCSI_CMD_INQUIRY:
60 #ifdef _SCSI_DEBUG_LOG
61 emu->out_debug_log(_T("[SCSI_HDD:ID=%d] Command: Inquiry\n"), scsi_id);
64 position = ((command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3]) * logical_block_size;
67 // create sense data table
71 buffer->write(0x02); // ANSI SCSI2
72 buffer->write(0x01); // ANSI-CCS
77 for(int i = 0; i < (int)strlen(vendor_id) && i < 8; i++) {
78 buffer->write(vendor_id[i]);
80 for(int i = strlen(vendor_id); i < 8; i++) {
83 for(int i = 0; i < (int)strlen(product_id) && i < 16; i++) {
84 buffer->write(vendor_id[i]);
86 for(int i = strlen(product_id); i < 16; i++) {
90 set_dat(buffer->read());
91 // change to data in phase
92 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
95 case SCSI_CMD_RD_CAPAC:
96 #ifdef _SCSI_DEBUG_LOG
97 emu->out_debug_log(_T("[SCSI_HDD:ID=%d] Command: Read Capacity\n"), scsi_id);
99 // initialize max logical block address
100 initialize_max_logical_block_addr();
102 position = (command[2] * 0x1000000 + command[3] * 0x10000 + command[4] * 0x100 + command[5]) * logical_block_size;
105 // create capacity data table
107 buffer->write((max_logical_block_addr >> 24) & 0xff);
108 buffer->write((max_logical_block_addr >> 16) & 0xff);
109 buffer->write((max_logical_block_addr >> 8) & 0xff);
110 buffer->write((max_logical_block_addr >> 0) & 0xff);
111 buffer->write(( logical_block_size >> 24) & 0xff);
112 buffer->write(( logical_block_size >> 16) & 0xff);
113 buffer->write(( logical_block_size >> 8) & 0xff);
114 buffer->write(( logical_block_size >> 0) & 0xff);
116 set_dat(buffer->read());
117 // change to data in phase
118 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
122 SCSI_DEV::start_command();
127 void SCSI_HDD::read_buffer(int length)
129 // make sure drive size is not zero
130 initialize_max_logical_block_addr();
133 FILEIO* fio = new FILEIO();
134 if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_READ_BINARY)) {
135 // FIXME: consider the case that disk size is bigger than MAX_LONG
136 fio->Fseek((long)position, FILEIO_SEEK_SET);
138 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
139 int tmp_length = min(length, (int)sizeof(tmp_buffer));
141 fio->Fread(tmp_buffer, tmp_length, 1);
142 for(int i = 0; i < tmp_length; i++) {
143 buffer->write(tmp_buffer[i]);
145 length -= tmp_length;
146 position += tmp_length;
153 void SCSI_HDD::write_buffer(int length)
155 // make sure drive size is not zero
156 initialize_max_logical_block_addr();
159 FILEIO* fio = new FILEIO();
160 if(fio->Fopen(create_local_path(_T("SCSI%d.DAT"), scsi_id), FILEIO_READ_WRITE_BINARY)) {
161 // FIXME: consider the case that disk size is bigger than MAX_LONG
162 fio->Fseek((long)position, FILEIO_SEEK_SET);
164 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
165 int tmp_length = min(length, (int)sizeof(tmp_buffer));
167 for(int i = 0; i < tmp_length; i++) {
168 tmp_buffer[i] = buffer->read();
170 fio->Fwrite(tmp_buffer, tmp_length, 1);
171 length -= tmp_length;
172 position += tmp_length;