2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
7 [ SCSI/SASI hard disk drive ]
14 void SCSI_HDD::release()
16 for(int i = 0; i < 8; i++) {
25 void SCSI_HDD::reset()
27 if(!is_hot_swappable) {
28 for(int drv = 0; drv < 8; drv++) {
29 if(disk[drv] != NULL) {
30 if(image_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(image_path[drv])) {
31 disk[drv]->open(image_path[drv], sector_size[drv]);
41 void SCSI_HDD::open(int drv, const _TCHAR* file_path, int default_sector_size)
43 if(drv < 8 && disk[drv] != NULL) {
44 if(!is_hot_swappable) {
45 my_tcscpy_s(image_path[drv], _MAX_PATH, file_path);
46 sector_size[drv] = default_sector_size;
48 disk[drv]->open(file_path, default_sector_size);
53 void SCSI_HDD::close(int drv)
55 if(drv < 8 && disk[drv] != NULL) {
56 if(!is_hot_swappable) {
57 image_path[drv][0] = _T('\0');
64 bool SCSI_HDD::mounted(int drv)
66 if(drv < 8 && disk[drv] != NULL) {
67 if(!is_hot_swappable) {
68 return (image_path[drv][0] != _T('\0'));
70 return disk[drv]->mounted();
76 bool SCSI_HDD::accessed(int drv)
78 if(drv < 8 && disk[drv] != NULL) {
79 return disk[drv]->accessed();
84 bool SCSI_HDD::is_device_existing()
86 for(int i = 0; i < 8; i++) {
87 if(disk[i] != NULL && disk[i]->mounted()) {
94 uint32_t SCSI_HDD::physical_block_size()
96 HARDDISK *unit = disk[get_logical_unit_number()];
98 if(unit != NULL && unit->mounted()) {
99 return unit->sector_size;
104 uint32_t SCSI_HDD::logical_block_size()
106 HARDDISK *unit = disk[get_logical_unit_number()];
108 if(unit != NULL && unit->mounted()) {
109 return unit->sector_size;
114 uint32_t SCSI_HDD::max_logical_block_addr()
116 HARDDISK *unit = disk[get_logical_unit_number()];
118 if(unit != NULL && unit->mounted() && unit->sector_num > 0) {
119 return unit->sector_num - 1;
124 bool SCSI_HDD::read_buffer(int length)
126 if(!(command[0] == SCSI_CMD_READ6 || command[0] == SCSI_CMD_READ10 || command[0] == SCSI_CMD_READ12)) {
127 for(int i = 0; i < length; i++) {
131 set_sense_code(SCSI_SENSE_NOSENSE);
134 HARDDISK *unit = disk[get_logical_unit_number()];
136 if(!(unit != NULL && unit->mounted())) {
137 set_sense_code(SCSI_SENSE_NOTREADY);
141 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
142 int tmp_length = min(length, (int)sizeof(tmp_buffer));
144 if(!unit->read_buffer((long)position, tmp_length, tmp_buffer)) {
145 set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
148 for(int i = 0; i < tmp_length; i++) {
149 buffer->write(tmp_buffer[i]);
151 length -= tmp_length;
152 position += tmp_length;
154 set_sense_code(SCSI_SENSE_NOSENSE);
158 bool SCSI_HDD::write_buffer(int length)
160 if(!(command[0] == SCSI_CMD_WRITE6 || command[0] == SCSI_CMD_WRITE10 || command[0] == SCSI_CMD_WRITE12)) {
161 for(int i = 0; i < length; i++) {
165 set_sense_code(SCSI_SENSE_NOSENSE);
168 HARDDISK *unit = disk[get_logical_unit_number()];
170 if(!(unit != NULL && unit->mounted())) {
171 set_sense_code(SCSI_SENSE_NOTREADY);
175 uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
176 int tmp_length = min(length, (int)sizeof(tmp_buffer));
178 for(int i = 0; i < tmp_length; i++) {
179 tmp_buffer[i] = buffer->read();
181 if(!unit->write_buffer((long)position, tmp_length, tmp_buffer)) {
182 set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
185 length -= tmp_length;
186 position += tmp_length;
188 set_sense_code(SCSI_SENSE_NOSENSE);
192 #define STATE_VERSION 3
194 bool SCSI_HDD::process_state(FILEIO* state_fio, bool loading)
196 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
199 if(!state_fio->StateCheckInt32(this_device_id)) {
203 for(int drv = 0; drv < 8; drv++) {
204 if(disk[drv] != NULL) {
205 if(!disk[drv]->process_state(state_fio, loading)) {
211 state_fio->StateArray(&image_path[0][0], sizeof(image_path), 1);
212 state_fio->StateArray(sector_size, sizeof(sector_size), 1);
213 return SCSI_DEV::process_state(state_fio, loading);
216 // SASI hard disk drive
218 void SASI_HDD::start_command()
221 case SCSI_CMD_REQ_SENSE:
222 #ifdef _SCSI_DEBUG_LOG
223 this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: Request Sense\n"), scsi_id);
226 position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
227 position *= physical_block_size();
230 // create sense data table
232 buffer->write(get_sense_code());
233 buffer->write(((max_logical_block_addr() >> 16) & 0x1f) | (get_logical_unit_number() << 5));
234 buffer->write(((max_logical_block_addr() >> 8) & 0xff));
235 buffer->write(((max_logical_block_addr() >> 0) & 0xff));
236 // change to data in phase
237 set_dat(buffer->read());
238 set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
239 set_sense_code(SCSI_SENSE_NOSENSE);
243 #ifdef _SCSI_DEBUG_LOG
244 this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: SASI Command 0xC2\n"), scsi_id);
247 remain = 10; // DTC
\8cn (
\83g
\83\89\83\93\83W
\83X
\83^
\8bZ
\8fpSPECIAL No.27, P.88)
250 // change to data in phase
251 set_phase_delay(SCSI_PHASE_DATA_OUT, 1.0);
254 // start standard command
255 SCSI_HDD::start_command();