diff --git a/src/raspberrypi/command_thread.cpp b/src/raspberrypi/command_thread.cpp index c2d6913..bfe2ec4 100644 --- a/src/raspberrypi/command_thread.cpp +++ b/src/raspberrypi/command_thread.cpp @@ -536,7 +536,9 @@ BOOL Command_Thread::ExecuteCommand(FILE *fp, Rasctl_Command *incoming_command) -BOOL Command_Thread::DoShutdown(FILE *fp, Rasctl_Command *incoming_command){return FALSE;} +BOOL Command_Thread::DoShutdown(FILE *fp, Rasctl_Command *incoming_command){ + m_running = FALSE; +} BOOL Command_Thread::DoList(FILE *fp, Rasctl_Command *incoming_command){ Rascsi_Manager::GetInstance()->ListDevice(fp); @@ -554,97 +556,70 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){ // } - // Create a new drive, based upon type - switch (incoming_command->type) { - case rasctl_dev_sasi_hd: // HDF - pUnit = new SASIHD(); - break; - case rasctl_dev_scsi_hd: // HDS/HDN/HDI/NHD/HDA - pUnit = new SCSIHD(); - break; - case rasctl_dev_scsi_hd_appl: - pUnit = new SCSIHD_APPLE(); - break; - case rasctl_dev_scsi_hd_nec: - pUnit = new SCSIHD_NEC(); - break; - case rasctl_dev_mo: - pUnit = new SCSIMO(); - break; - case rasctl_dev_cd: - pUnit = new SCSICD(); - break; - case rasctl_dev_br: - pUnit = new SCSIBR(); - break; - default: - FPRT(fp, "Error : Invalid device type\n"); - return FALSE; - } - - // drive checks files - switch(incoming_command->type){ - case rasctl_dev_mo: - case rasctl_dev_scsi_hd_nec: - case rasctl_dev_sasi_hd: - case rasctl_dev_scsi_hd: - case rasctl_dev_cd: - case rasctl_dev_scsi_hd_appl: - // Set the Path - filepath.SetPath(incoming_command->file); - - // Open the file path - if (!pUnit->Open(filepath)) { - FPRT(fp, "Error : File open error [%s]\n", incoming_command->file); - delete pUnit; - return FALSE; - } + // Create a new drive, based upon type + switch (incoming_command->type) { + case rasctl_dev_sasi_hd: // HDF + pUnit = new SASIHD(); break; - case rasctl_dev_br: - case rasctl_dev_invalid: - // Do nothing + case rasctl_dev_scsi_hd: // HDS/HDN/HDI/NHD/HDA + pUnit = new SCSIHD(); break; + case rasctl_dev_scsi_hd_appl: + pUnit = new SCSIHD_APPLE(); + break; + case rasctl_dev_scsi_hd_nec: + pUnit = new SCSIHD_NEC(); + break; + case rasctl_dev_mo: + pUnit = new SCSIMO(); + break; + case rasctl_dev_cd: + pUnit = new SCSICD(); + break; + case rasctl_dev_br: + pUnit = new SCSIBR(); + break; + default: + FPRT(fp, "Error : Invalid device type\n"); + return FALSE; + } + + // drive checks files + switch(incoming_command->type){ + case rasctl_dev_mo: + case rasctl_dev_scsi_hd_nec: + case rasctl_dev_sasi_hd: + case rasctl_dev_scsi_hd: + case rasctl_dev_cd: + case rasctl_dev_scsi_hd_appl: + // Set the Path + filepath.SetPath(incoming_command->file); + + // Open the file path + if (!pUnit->Open(filepath)) { + FPRT(fp, "Error : File open error [%s]\n", incoming_command->file); + delete pUnit; + return FALSE; } + break; + case rasctl_dev_br: + case rasctl_dev_invalid: + // Do nothing + break; + } - // Set the cache to write-through - pUnit->SetCacheWB(FALSE); + // Set the cache to write-through + pUnit->SetCacheWB(FALSE); -// // Replace with the newly created unit -// map[id * Rascsi_Manager::GetInstance()->UnitNum + un] = pUnit; - - // Map the controller - Rascsi_Manager::GetInstance()->MapControler(fp, map); - return TRUE; + // Map the controller + return Rascsi_Manager::GetInstance()->AttachDevice(fp, pUnit, incoming_command->id, incoming_command->un); - - return FALSE;} +} BOOL Command_Thread::DoDetach(FILE *fp, Rasctl_Command *incoming_command){ + return Rascsi_Manager::GetInstance()->DetachDevice(fp, incoming_command->id, incoming_command->un); +} -// // Does the controller exist? -// if (Rascsi_Manager::GetInstance()->m_ctrl[id] == NULL) { -// FPRT(fp, "Error : No such device\n"); -// return FALSE; -// } - -// // Does the unit exist? -// pUnit = Rascsi_Manager::GetInstance()->m_disk[id * Rascsi_Manager::GetInstance()->UnitNum + un]; -// if (pUnit == NULL) { -// FPRT(fp, "Error : No such device\n"); -// return FALSE; -// } - - // // Disconnect Command -// if (cmd == 1) { // DETACH -// // Free the existing unit -// map[id * Rascsi_Manager::GetInstance()->UnitNum + un] = NULL; - -// // Re-map the controller -// Rascsi_Manager::GetInstance()->MapControler(fp, map); -// return TRUE; -// } - - return FALSE;} BOOL Command_Thread::DoInsert(FILE *fp, Rasctl_Command *incoming_command){ diff --git a/src/raspberrypi/disks/disk.cpp b/src/raspberrypi/disks/disk.cpp index 64827ee..a05f27a 100644 --- a/src/raspberrypi/disks/disk.cpp +++ b/src/raspberrypi/disks/disk.cpp @@ -989,6 +989,18 @@ BOOL FASTCALL Disk::IsSASI() const return FALSE; } +//--------------------------------------------------------------------------- +// +// SCSI Check +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::IsSCSI() const +{ + ASSERT(this); + // If this isn't SASI, then it must be SCSI. + return (this->IsSASI()) ? FALSE : TRUE; +} + //--------------------------------------------------------------------------- // // Open diff --git a/src/raspberrypi/disks/disk.h b/src/raspberrypi/disks/disk.h index f31c9ff..725880f 100644 --- a/src/raspberrypi/disks/disk.h +++ b/src/raspberrypi/disks/disk.h @@ -239,6 +239,8 @@ public: // NULL check BOOL FASTCALL IsSASI() const; // SASI Check + BOOL FASTCALL IsSCSI() const; + // SASI Check // Media Operations virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); diff --git a/src/raspberrypi/fileio.cpp b/src/raspberrypi/fileio.cpp index db320cc..040c765 100644 --- a/src/raspberrypi/fileio.cpp +++ b/src/raspberrypi/fileio.cpp @@ -124,6 +124,8 @@ BOOL FASTCALL Fileio::Open(LPCTSTR fname, OpenMode mode, BOOL directIO) #ifndef __APPLE__ // デフォルトモード omode = directIO ? O_DIRECT : 0; +#else + omode = 0; #endif // ifndef __APPLE__ // モード別 diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 05731ab..48438f0 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -48,6 +48,10 @@ FATFS fatfs; // FatFS #endif // BAREMETAL Rascsi_Manager *mgr; +#ifndef CONNECT_DESC +#define CONNECT_DESC "UNKNOWN" +#endif + #ifndef BAREMETAL //--------------------------------------------------------------------------- // diff --git a/src/raspberrypi/rascsi_mgr.cpp b/src/raspberrypi/rascsi_mgr.cpp index ef4c312..30e844c 100644 --- a/src/raspberrypi/rascsi_mgr.cpp +++ b/src/raspberrypi/rascsi_mgr.cpp @@ -25,238 +25,121 @@ Rascsi_Manager* Rascsi_Manager::GetInstance(){ return m_instance; } +BOOL Rascsi_Manager::AttachDevice(FILE *fp, Disk *disk, int id, int unit_num){ + BOOL result; + m_locked.lock(); + result = AttachDevicePrivate(fp, disk, id, unit_num); + m_locked.unlock(); + return result; +} -void Rascsi_Manager::AttachDevice(FILE *fp, Disk *disk, int id, int unit_num){ +BOOL Rascsi_Manager::DetachDevice(FILE *fp, int id, int unit_num){ + BOOL result; + m_locked.lock(); + result = DetachDevicePrivate(fp, id, unit_num); + m_locked.unlock(); + return result; +} + +BOOL Rascsi_Manager::AttachDevicePrivate(FILE *fp, Disk *disk, int id, int unit_num) +{ + Rascsi_Device_Mode_e cur_mode = GetCurrentDeviceMode(); int unitno = (id * UnitNum) + unit_num; - // Get the lock - m_locked.lock(); + if((disk->IsSASI() && (cur_mode == rascsi_device_scsi_mode)) || + (!disk->IsSCSI() && (cur_mode == rascsi_device_sasi_mode))){ + FPRT(fp, "Warning: Can't mix SASI and SCSI devices!\n"); + return FALSE; + } // Check if something already exists at that SCSI ID / Unit Number if (m_disk[unitno]) { - // Disconnect it from the controller - if (m_ctrl[i]) { - m_ctrl[i]->SetUnit(j, NULL); - }else{ - printf("Warning: A controller was not connected to the drive at id %d un %d\n",id, unit_num); - } - - // Free the Unit - delete m_disk[unitno]; + DetachDevice(fp,id,unit_num); } // Add the new unit m_disk[unitno] = disk; - - // Reconfigure all of the controllers - for (i = 0; i < CtrlMax; i++) { - // Examine the unit configuration - sasi_num = 0; - scsi_num = 0; - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - // branch by unit type - if (m_disk[unitno]) { - if (m_disk[unitno]->IsSASI()) { - // Drive is SASI, so increment SASI count - sasi_num++; - } else { - // Drive is SCSI, so increment SCSI count - scsi_num++; - } - } - - // Remove the unit - if (m_ctrl[i]) { - m_ctrl[i]->SetUnit(j, NULL); - } - } - - // If there are no units connected - if (sasi_num == 0 && scsi_num == 0) { - if (m_ctrl[i]) { - delete m_ctrl[i]; - m_ctrl[i] = NULL; - continue; - } - } - - // Mixture of SCSI and SASI - if (sasi_num > 0 && scsi_num > 0) { - FPRT(fp, "Error : SASI and SCSI can't be mixed\n"); - continue; - } - - if (sasi_num > 0) { - // Only SASI Unit(s) - - // Release the controller if it is not SASI - if (m_ctrl[i] && !m_ctrl[i]->IsSASI()) { - delete m_ctrl[i]; - m_ctrl[i] = NULL; - } - - // Create a new SASI controller - if (!m_ctrl[i]) { - m_ctrl[i] = new SASIDEV(); - m_ctrl[i]->Connect(i, m_bus); - } - } else { - // Only SCSI Unit(s) - - // Release the controller if it is not SCSI - if (m_ctrl[i] && !m_ctrl[i]->IsSCSI()) { - delete m_ctrl[i]; - m_ctrl[i] = NULL; - } - - // Create a new SCSI controller - if (!m_ctrl[i]) { - m_ctrl[i] = new SCSIDEV(); - m_ctrl[i]->Connect(i, m_bus); - } - } - - // connect all units - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - if (m_disk[unitno]) { - // Add the unit connection - m_ctrl[i]->SetUnit(j, m_disk[unitno]); - } + + // If the controllder doesn't already exist, create it. + if (m_ctrl[id] == nullptr){ + // We need to create a new controller + if(disk->IsSASI()){ + m_ctrl[id] = new SASIDEV(); + }else{ + m_ctrl[id] = new SCSIDEV(); } + m_ctrl[id]->Connect(id, m_bus); } - - - } - void Rascsi_Manager::DetachDevice(FILE *fp, Disk *map, int id, int ui) - { - return; - } - Disk* Rascsi_Manager::GetDevice(FILE *fp, int id, int ui) - { - return nullptr; - - } - - - -//--------------------------------------------------------------------------- -// -// Controller Mapping -// -//--------------------------------------------------------------------------- -void Rascsi_Manager::MapControler(FILE *fp, Disk **map) -{ - int i; - int j; - int unitno; - int sasi_num; - int scsi_num; - - // Replace the changed unit - for (i = 0; i < CtrlMax; i++) { - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - if (m_disk[unitno] != map[unitno]) { - // Check if the original unit exists - if (m_disk[unitno]) { - // Disconnect it from the controller - if (m_ctrl[i]) { - m_ctrl[i]->SetUnit(j, NULL); - } - - // Free the Unit - delete m_disk[unitno]; - } - - // Setup a new unit - m_disk[unitno] = map[unitno]; - } - } - } - - // Reconfigure all of the controllers - for (i = 0; i < CtrlMax; i++) { - // Examine the unit configuration - sasi_num = 0; - scsi_num = 0; - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - // branch by unit type - if (m_disk[unitno]) { - if (m_disk[unitno]->IsSASI()) { - // Drive is SASI, so increment SASI count - sasi_num++; - } else { - // Drive is SCSI, so increment SCSI count - scsi_num++; - } - } - - // Remove the unit - if (m_ctrl[i]) { - m_ctrl[i]->SetUnit(j, NULL); - } - } - - // If there are no units connected - if (sasi_num == 0 && scsi_num == 0) { - if (m_ctrl[i]) { - delete m_ctrl[i]; - m_ctrl[i] = NULL; - continue; - } - } - - // Mixture of SCSI and SASI - if (sasi_num > 0 && scsi_num > 0) { - FPRT(fp, "Error : SASI and SCSI can't be mixed\n"); - continue; - } - - if (sasi_num > 0) { - // Only SASI Unit(s) - - // Release the controller if it is not SASI - if (m_ctrl[i] && !m_ctrl[i]->IsSASI()) { - delete m_ctrl[i]; - m_ctrl[i] = NULL; - } - - // Create a new SASI controller - if (!m_ctrl[i]) { - m_ctrl[i] = new SASIDEV(); - m_ctrl[i]->Connect(i, m_bus); - } - } else { - // Only SCSI Unit(s) - - // Release the controller if it is not SCSI - if (m_ctrl[i] && !m_ctrl[i]->IsSCSI()) { - delete m_ctrl[i]; - m_ctrl[i] = NULL; - } - - // Create a new SCSI controller - if (!m_ctrl[i]) { - m_ctrl[i] = new SCSIDEV(); - m_ctrl[i]->Connect(i, m_bus); - } - } - - // connect all units - for (j = 0; j < UnitNum; j++) { - unitno = i * UnitNum + j; - if (m_disk[unitno]) { - // Add the unit connection - m_ctrl[i]->SetUnit(j, m_disk[unitno]); - } - } - } + // Add the disk to the controller + m_ctrl[id]->SetUnit(unit_num, disk); } +BOOL Rascsi_Manager::DetachDevicePrivate(FILE *fp, int id, int unit_num) +{ + int unitno = (id * UnitNum) + unit_num; + + // Disconnect it from the controller + if (m_ctrl[id]) { + m_ctrl[id]->SetUnit(unit_num, NULL); + // Free the Unit + delete m_disk[unitno]; + m_disk[unitno] = nullptr; + }else{ + fprintf(fp, "Warning: A controller was not connected to the drive at id %d un %d\n",id, unit_num); + fprintf(fp, "This is some sort of internal error, since you can't have a device without a controller.\n"); + return FALSE; + } + + // If there are no longer any units connected to this controller, delete it + if(!m_ctrl[id]->HasUnit()){ + delete m_ctrl[id]; + m_ctrl[id] = nullptr; + } + + return TRUE; +} + +Disk* Rascsi_Manager::GetDevice(FILE *fp, int id, int unit_num) +{ + int unitno = (id * UnitNum) + unit_num; + return m_disk[unitno]; +} + +//--------------------------------------------------------------------------- +// +// GetCurrentDeviceMode +// +// Loop through all of the controllers and check if we have SCSI or SASI +// controllers already created. (Note: We can't have a mix of them) +// +//--------------------------------------------------------------------------- +Rascsi_Device_Mode_e Rascsi_Manager::GetCurrentDeviceMode(){ + + Rascsi_Device_Mode_e mode = rascsi_device_unknown_mode; + for(int i =0; i < CtrlMax; i++){ + if(m_ctrl[i] != nullptr){ + if(m_ctrl[i]->IsSASI()){ + if(mode == rascsi_device_unknown_mode){ + mode = rascsi_device_sasi_mode; + }else if(mode == rascsi_device_scsi_mode){ + mode = rascsi_device_invalid_mode; + printf("Error: Mix of SCSI and SASI devices. This isn't allowed. Device %d was SASI, but expecting SCSI\n", i); + } + }else { // This is SCSI + if(mode == rascsi_device_unknown_mode){ + mode = rascsi_device_scsi_mode; + }else if(mode == rascsi_device_sasi_mode){ + mode = rascsi_device_invalid_mode; + printf("Error: Mix of SCSI and SASI devices. This isn't allowed. Device %d was SCSI, but expecting SASI\n", i); + } + } + } + } + return mode; +} + + //--------------------------------------------------------------------------- // diff --git a/src/raspberrypi/rascsi_mgr.h b/src/raspberrypi/rascsi_mgr.h index d8bf734..2140acb 100644 --- a/src/raspberrypi/rascsi_mgr.h +++ b/src/raspberrypi/rascsi_mgr.h @@ -27,18 +27,28 @@ #include "sasidev_ctrl.h" #include +enum Rascsi_Device_Mode_e{ + rascsi_device_unknown_mode, + rascsi_device_sasi_mode, + rascsi_device_scsi_mode, + rascsi_device_invalid_mode, +}; + class Rascsi_Manager{ public: static Rascsi_Manager* GetInstance(); void MapControler(FILE *fp, Disk **map); - void AttachDevice(FILE *fp, Disk *disk, int id, int ui); - void DetachDevice(FILE *fp, Disk *disk, int id, int ui); + + + BOOL AttachDevice(FILE *fp, Disk *disk, int id, int ui); + BOOL DetachDevice(FILE *fp, int id, int ui); Disk* GetDevice(FILE *fp, int id, int ui); void ListDevice(FILE *fp); BOOL Init(); void Close(); void Reset(); BOOL Step(); + Rascsi_Device_Mode_e GetCurrentDeviceMode(); static const int CtrlMax = 8; // Maximum number of SCSI controllers static const int UnitNum=2; // Number of units around controller @@ -62,6 +72,9 @@ class Rascsi_Manager{ static BOOL m_active; static BOOL m_running; + BOOL AttachDevicePrivate(FILE *fp, Disk *disk, int id, int ui); + BOOL DetachDevicePrivate(FILE *fp, int id, int ui); + // Any PUBLIC functions should lock this before accessing the m_ctrl // m_disk or m_bus data structures. The Public functions could be // called from a different thread.