Author : Takeda.Toshiya
Date : 2016.03.01-
- [ SCSI hard disk drive ]
+ [ SCSI/SASI hard disk drive ]
*/
#include "scsi_hdd.h"
SCSI_DEV::release();
}
+void SCSI_HDD::reset()
+{
+ if(!is_hot_swappable) {
+ for(int drv = 0; drv < 8; drv++) {
+ if(disk[drv] != NULL) {
+ if(image_path[drv][0] != _T('\0') && FILEIO::IsFileExisting(image_path[drv])) {
+ disk[drv]->open(image_path[drv], sector_size[drv]);
+ } else {
+ disk[drv]->close();
+ }
+ }
+ }
+ }
+ SCSI_DEV::reset();
+}
+
+void SCSI_HDD::open(int drv, const _TCHAR* file_path, int default_sector_size)
+{
+ if(drv < 8 && disk[drv] != NULL) {
+ if(!is_hot_swappable) {
+ my_tcscpy_s(image_path[drv], _MAX_PATH, file_path);
+ sector_size[drv] = default_sector_size;
+ } else {
+ disk[drv]->open(file_path, default_sector_size);
+ }
+ }
+}
+
+void SCSI_HDD::close(int drv)
+{
+ if(drv < 8 && disk[drv] != NULL) {
+ if(!is_hot_swappable) {
+ image_path[drv][0] = _T('\0');
+ } else {
+ disk[drv]->close();
+ }
+ }
+}
+
+bool SCSI_HDD::mounted(int drv)
+{
+ if(drv < 8 && disk[drv] != NULL) {
+ if(!is_hot_swappable) {
+ return (image_path[drv][0] != _T('\0'));
+ } else {
+ return disk[drv]->mounted();
+ }
+ }
+ return false;
+}
+
+bool SCSI_HDD::accessed(int drv)
+{
+ if(drv < 8 && disk[drv] != NULL) {
+ return disk[drv]->accessed();
+ }
+ return false;
+}
+
bool SCSI_HDD::is_device_existing()
{
for(int i = 0; i < 8; i++) {
if(unit != NULL && unit->mounted()) {
return unit->sector_size;
}
- return 512;
+ return 0;// 512;
}
uint32_t SCSI_HDD::logical_block_size()
if(unit != NULL && unit->mounted()) {
return unit->sector_size;
}
- return 512;
+ return 0;// 512;
}
uint32_t SCSI_HDD::max_logical_block_addr()
{
HARDDISK *unit = disk[get_logical_unit_number()];
- if(unit != NULL && unit->mounted()) {
- return unit->cylinders * unit->surfaces * unit->sectors;
+ if(unit != NULL && unit->mounted() && unit->sector_num > 0) {
+ return unit->sector_num - 1;
}
return 0;
}
-void SCSI_HDD::read_buffer(int length)
+bool SCSI_HDD::read_buffer(int length)
{
+ if(!(command[0] == SCSI_CMD_READ6 || command[0] == SCSI_CMD_READ10 || command[0] == SCSI_CMD_READ12)) {
+ for(int i = 0; i < length; i++) {
+ buffer->write(0);
+ position++;
+ }
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return true;
+ }
HARDDISK *unit = disk[get_logical_unit_number()];
- if(unit != NULL && unit->mounted()) {
- while(length > 0) {
- uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
- int tmp_length = min(length, (int)sizeof(tmp_buffer));
-
- unit->read_buffer((long)position, tmp_length, tmp_buffer);
- for(int i = 0; i < tmp_length; i++) {
- buffer->write(tmp_buffer[i]);
- }
- length -= tmp_length;
- position += tmp_length;
- }
+ if(!(unit != NULL && unit->mounted())) {
+ set_sense_code(SCSI_SENSE_NOTREADY);
+ return false;
}
+ while(length > 0) {
+ uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
+ int tmp_length = min(length, (int)sizeof(tmp_buffer));
+
+ if(!unit->read_buffer((long)position, tmp_length, tmp_buffer)) {
+ set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
+ return false;
+ }
+ for(int i = 0; i < tmp_length; i++) {
+ buffer->write(tmp_buffer[i]);
+ }
+ length -= tmp_length;
+ position += tmp_length;
+ }
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return true;
}
-void SCSI_HDD::write_buffer(int length)
+bool SCSI_HDD::write_buffer(int length)
{
+ if(!(command[0] == SCSI_CMD_WRITE6 || command[0] == SCSI_CMD_WRITE10 || command[0] == SCSI_CMD_WRITE12)) {
+ for(int i = 0; i < length; i++) {
+ buffer->read();
+ position++;
+ }
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return true;
+ }
HARDDISK *unit = disk[get_logical_unit_number()];
- if(unit != NULL && unit->mounted()) {
- while(length > 0) {
- uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
- int tmp_length = min(length, (int)sizeof(tmp_buffer));
-
- for(int i = 0; i < tmp_length; i++) {
- tmp_buffer[i] = buffer->read();
- }
- unit->write_buffer((long)position, tmp_length, tmp_buffer);
- length -= tmp_length;
- position += tmp_length;
- }
+ if(!(unit != NULL && unit->mounted())) {
+ set_sense_code(SCSI_SENSE_NOTREADY);
+ return false;
}
+ while(length > 0) {
+ uint8_t tmp_buffer[SCSI_BUFFER_SIZE];
+ int tmp_length = min(length, (int)sizeof(tmp_buffer));
+
+ for(int i = 0; i < tmp_length; i++) {
+ tmp_buffer[i] = buffer->read();
+ }
+ if(!unit->write_buffer((long)position, tmp_length, tmp_buffer)) {
+ set_sense_code(SCSI_SENSE_ILLGLBLKADDR); //SCSI_SENSE_NORECORDFND
+ return false;
+ }
+ length -= tmp_length;
+ position += tmp_length;
+ }
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return true;
}
-#define STATE_VERSION 1
-
-#include "../statesub.h"
+#define STATE_VERSION 3
-void SCSI_HDD::decl_state()
+bool SCSI_HDD::process_state(FILEIO* state_fio, bool loading)
{
- enter_decl_state(STATE_VERSION);
-
- SCSI_DEV::decl_state();
-
- leave_decl_state();
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ /*
+ for(int drv = 0; drv < 8; drv++) {
+ if(disk[drv] != NULL) {
+ if(!disk[drv]->process_state(state_fio, loading)) {
+ return false;
+ }
+ }
+ }
+ */
+ state_fio->StateArray(&image_path[0][0], sizeof(image_path), 1);
+ state_fio->StateArray(sector_size, sizeof(sector_size), 1);
+ return SCSI_DEV::process_state(state_fio, loading);
}
-void SCSI_HDD::save_state(FILEIO* state_fio)
-{
-// state_fio->FputUint32(STATE_VERSION);
-// state_fio->FputInt32(this_device_id);
-/*
- for(int i = 0; i < 8; i++) {
- if(disk[i] != NULL) {
- disk[i]->save_state(state_fio);
- }
- }
-*/
- SCSI_DEV::save_state(state_fio);
-}
+// SASI hard disk drive
-bool SCSI_HDD::load_state(FILEIO* state_fio)
+void SASI_HDD::start_command()
{
-// if(state_fio->FgetUint32() != STATE_VERSION) {
-// return false;
-// }
-// if(state_fio->FgetInt32() != this_device_id) {
-// return false;
-// }
-/*
- for(int i = 0; i < 8; i++) {
- if(disk[i] != NULL) {
- if(!disk[i]->load_state(state_fio)) {
- return false;
- }
- }
+ switch(command[0]) {
+ case SCSI_CMD_REQ_SENSE:
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: Request Sense\n"), scsi_id);
+ #endif
+ // start position
+ position = (command[1] & 0x1f) * 0x10000 + command[2] * 0x100 + command[3];
+ position *= physical_block_size();
+ // transfer length
+ remain = 4;
+ // create sense data table
+ buffer->clear();
+ buffer->write(get_sense_code());
+ buffer->write(((max_logical_block_addr() >> 16) & 0x1f) | (get_logical_unit_number() << 5));
+ buffer->write(((max_logical_block_addr() >> 8) & 0xff));
+ buffer->write(((max_logical_block_addr() >> 0) & 0xff));
+ // change to data in phase
+ set_dat(buffer->read());
+ set_phase_delay(SCSI_PHASE_DATA_IN, 10.0);
+ set_sense_code(SCSI_SENSE_NOSENSE);
+ return;
+
+ case 0xc2:
+ #ifdef _SCSI_DEBUG_LOG
+ this->out_debug_log(_T("[SASI_HDD:ID=%d] Command: SASI Command 0xC2\n"), scsi_id);
+ #endif
+ // transfer length
+ remain = 10; // DTC\8cn (\83g\83\89\83\93\83W\83X\83^\8bZ\8fpSPECIAL No.27, P.88)
+ // clear data buffer
+ buffer->clear();
+ // change to data in phase
+ set_phase_delay(SCSI_PHASE_DATA_OUT, 1.0);
+ return;
}
-*/
- return SCSI_DEV::load_state(state_fio);
+ // start standard command
+ SCSI_HDD::start_command();
}
-