Additional changes.... command interface works?

This commit is contained in:
akuker
2020-08-16 16:20:29 -05:00
parent c08024dd78
commit 1cf635be02
8 changed files with 197 additions and 225 deletions

View File

@@ -1,7 +1,26 @@
#include "os.h" //---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2014-2020 GIMONS
// Copyright (C) akuker
//
// Licensed under the BSD 3-Clause License.
// See LICENSE file in the project root folder.
//
// [ Command thread ]
//
// This is a background thread that runs, listening for commands on port
// 6868 for commands from the rasctl utility. This also includes the logic
// for handling the initialization commands that are specified at startup.
//
//---------------------------------------------------------------------------
#include "rasctl_command.h"
#include "command_thread.h" #include "command_thread.h"
#include "os.h"
#include "rasctl_command.h"
#include "rascsi_mgr.h" #include "rascsi_mgr.h"
#include "sasihd.h" #include "sasihd.h"
#include "scsihd.h" #include "scsihd.h"
@@ -11,23 +30,9 @@
#include "scsimo.h" #include "scsimo.h"
#include "scsi_host_bridge.h" #include "scsi_host_bridge.h"
BOOL Command_Thread::m_running = FALSE;
int Command_Thread::m_monsocket = -1; // Monitor Socket int Command_Thread::m_monsocket = -1; // Monitor Socket
pthread_t Command_Thread::m_monthread; // Monitor Thread pthread_t Command_Thread::m_monthread; // Monitor Thread
void Command_Thread::Start(){
m_running = TRUE;
}
void Command_Thread::Stop(){
m_running = FALSE;
}
BOOL Command_Thread::IsRunning(){
return m_running;
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Initialization // Initialization
@@ -44,7 +49,7 @@ BOOL Command_Thread::Init()
m_monsocket = socket(PF_INET, SOCK_STREAM, 0); m_monsocket = socket(PF_INET, SOCK_STREAM, 0);
memset(&server, 0, sizeof(server)); memset(&server, 0, sizeof(server));
server.sin_family = PF_INET; server.sin_family = PF_INET;
server.sin_port = htons(6868); server.sin_port = htons(Rasctl_Command::PortNumber);
server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_addr.s_addr = htonl(INADDR_ANY);
// allow address reuse // allow address reuse
@@ -70,6 +75,11 @@ BOOL Command_Thread::Init()
return TRUE; return TRUE;
} }
//---------------------------------------------------------------------------
//
// Close/Cleanup the command thread
//
//---------------------------------------------------------------------------
void Command_Thread::Close(){ void Command_Thread::Close(){
// Close the monitor socket // Close the monitor socket
if (m_monsocket >= 0) { if (m_monsocket >= 0) {
@@ -292,15 +302,10 @@ void *Command_Thread::MonThread(void *param)
// Set the affinity to a specific processor core // Set the affinity to a specific processor core
FixCpu(2); FixCpu(2);
// Wait for the execution to start
while (!m_running) {
usleep(1);
}
// Setup the monitor socket to receive commands // Setup the monitor socket to receive commands
listen(m_monsocket, 1); listen(m_monsocket, 1);
while (1) { while (Rascsi_Manager::IsRunning()) {
// Wait for connection // Wait for connection
memset(&client, 0, sizeof(client)); memset(&client, 0, sizeof(client));
len = sizeof(client); len = sizeof(client);
@@ -316,16 +321,7 @@ void *Command_Thread::MonThread(void *param)
// If we received a command.... // If we received a command....
if (p) { if (p) {
// // Remove the newline character new_command = Rasctl_Command::DeSerialize(p,BUFSIZ);
// p[strlen(p) - 1] = 0;
// // List all of the devices
// if (xstrncasecmp(p, "list", 4) == 0) {
// Rascsi_Manager::GetInstance()->ListDevice(fp);
// goto next;
// }
new_command = Rasctl_Command::DeSerialize((BYTE*)p,BUFSIZ);
if(new_command != nullptr){ if(new_command != nullptr){
// Execute the command // Execute the command
@@ -377,22 +373,20 @@ BOOL Command_Thread::ExecuteCommand(FILE *fp, Rasctl_Command *incoming_command)
result = DoDetach(fp,incoming_command); result = DoDetach(fp,incoming_command);
break; break;
default: default:
printf("UNKNOWN COMMAND RECEIVED\n"); fprintf(fp, "UNKNOWN COMMAND RECEIVED\n");
} }
if(!result){
fputs("Unknown server error", fp);
}
return result; return result;
} }
BOOL Command_Thread::DoShutdown(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoShutdown(FILE *fp, Rasctl_Command *incoming_command){
m_running = FALSE; fprintf(fp, "Stopping the RaSCSI application\n");
Rascsi_Manager::Stop();
return TRUE; return TRUE;
} }
BOOL Command_Thread::DoList(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoList(FILE *fp, Rasctl_Command *incoming_command){
Rascsi_Manager::GetInstance()->ListDevice(fp); Rascsi_Manager::ListDevice(fp);
return TRUE; return TRUE;
} }
@@ -405,13 +399,13 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){
case rasctl_dev_sasi_hd: // HDF case rasctl_dev_sasi_hd: // HDF
pUnit = new SASIHD(); pUnit = new SASIHD();
break; break;
case rasctl_dev_scsi_hd: // HDS/HDN/HDI/NHD/HDA case rasctl_dev_scsi_hd: // HDS/HDI
pUnit = new SCSIHD(); pUnit = new SCSIHD();
break; break;
case rasctl_dev_scsi_hd_appl: case rasctl_dev_scsi_hd_appl: // HDA
pUnit = new SCSIHD_APPLE(); pUnit = new SCSIHD_APPLE();
break; break;
case rasctl_dev_scsi_hd_nec: case rasctl_dev_scsi_hd_nec: // HDN/NHD
pUnit = new SCSIHD_NEC(); pUnit = new SCSIHD_NEC();
break; break;
case rasctl_dev_mo: case rasctl_dev_mo:
@@ -436,6 +430,7 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){
case rasctl_dev_scsi_hd: case rasctl_dev_scsi_hd:
case rasctl_dev_cd: case rasctl_dev_cd:
case rasctl_dev_scsi_hd_appl: case rasctl_dev_scsi_hd_appl:
if((incoming_command->file != nullptr) && (strnlen(incoming_command->file,_MAX_PATH) > 0)){
// Set the Path // Set the Path
filepath.SetPath(incoming_command->file); filepath.SetPath(incoming_command->file);
@@ -445,6 +440,8 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){
delete pUnit; delete pUnit;
return FALSE; return FALSE;
} }
}
break; break;
case rasctl_dev_br: case rasctl_dev_br:
case rasctl_dev_invalid: case rasctl_dev_invalid:
@@ -457,17 +454,17 @@ BOOL Command_Thread::DoAttach(FILE *fp, Rasctl_Command *incoming_command){
pUnit->SetCacheWB(FALSE); pUnit->SetCacheWB(FALSE);
// Map the controller // Map the controller
return Rascsi_Manager::GetInstance()->AttachDevice(fp, pUnit, incoming_command->id, incoming_command->un); return Rascsi_Manager::AttachDevice(fp, pUnit, incoming_command->id, incoming_command->un);
} }
BOOL Command_Thread::DoDetach(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoDetach(FILE *fp, Rasctl_Command *incoming_command){
return Rascsi_Manager::GetInstance()->DetachDevice(fp, incoming_command->id, incoming_command->un); return Rascsi_Manager::DetachDevice(fp, incoming_command->id, incoming_command->un);
} }
BOOL Command_Thread::DoInsert(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoInsert(FILE *fp, Rasctl_Command *incoming_command){
Filepath filepath; Filepath filepath;
Disk *pUnit = Rascsi_Manager::GetInstance()->GetDevice(fp, incoming_command->id, incoming_command->un); Disk *pUnit = Rascsi_Manager::GetDevice(fp, incoming_command->id, incoming_command->un);
// Does the device exist? // Does the device exist?
@@ -495,7 +492,7 @@ BOOL Command_Thread::DoInsert(FILE *fp, Rasctl_Command *incoming_command){
return TRUE; return TRUE;
} }
BOOL Command_Thread::DoEject(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoEject(FILE *fp, Rasctl_Command *incoming_command){
Disk *pUnit = Rascsi_Manager::GetInstance()->GetDevice(fp, incoming_command->id, incoming_command->un); Disk *pUnit = Rascsi_Manager::GetDevice(fp, incoming_command->id, incoming_command->un);
// Does the device exist? // Does the device exist?
if (pUnit == nullptr) { if (pUnit == nullptr) {
@@ -515,7 +512,7 @@ BOOL Command_Thread::DoEject(FILE *fp, Rasctl_Command *incoming_command){
BOOL Command_Thread::DoProtect(FILE *fp, Rasctl_Command *incoming_command){ BOOL Command_Thread::DoProtect(FILE *fp, Rasctl_Command *incoming_command){
Disk *pUnit = Rascsi_Manager::GetInstance()->GetDevice(fp, incoming_command->id, incoming_command->un); Disk *pUnit = Rascsi_Manager::GetDevice(fp, incoming_command->id, incoming_command->un);
// Does the device exist? // Does the device exist?
if (pUnit == nullptr) { if (pUnit == nullptr) {

View File

@@ -26,9 +26,6 @@ class Command_Thread{
public: public:
static BOOL Init(); static BOOL Init();
static void Start();
static void Stop();
static BOOL IsRunning();
static void Close(); static void Close();
static void KillHandler(); static void KillHandler();
static BOOL ParseArgument(int argc, char* argv[]); static BOOL ParseArgument(int argc, char* argv[]);
@@ -40,7 +37,7 @@ class Command_Thread{
private: private:
static int m_monsocket; // Monitor Socket static int m_monsocket; // Monitor Socket
static pthread_t m_monthread; // Monitor Thread static pthread_t m_monthread; // Monitor Thread
static BOOL m_running; static uint16_t m_monitor_port_num; // Port number to listen for commands
static BOOL HasSuffix(const char* string, const char* suffix); static BOOL HasSuffix(const char* string, const char* suffix);
static BOOL DoShutdown(FILE *fp, Rasctl_Command *incoming_command); static BOOL DoShutdown(FILE *fp, Rasctl_Command *incoming_command);

View File

@@ -56,7 +56,6 @@
FATFS fatfs; // FatFS FATFS fatfs; // FatFS
#else #else
#endif // BAREMETAL #endif // BAREMETAL
Rascsi_Manager *mgr;
#ifndef CONNECT_DESC #ifndef CONNECT_DESC
#define CONNECT_DESC "UNKNOWN" #define CONNECT_DESC "UNKNOWN"
@@ -71,7 +70,7 @@ Rascsi_Manager *mgr;
void KillHandler(int sig) void KillHandler(int sig)
{ {
// Stop instruction // Stop instruction
Command_Thread::Stop(); Rascsi_Manager::Stop();
} }
#endif // BAREMETAL #endif // BAREMETAL
@@ -127,12 +126,11 @@ void Banner(int argc, char* argv[])
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
BOOL Init() BOOL Init()
{ {
if(!Command_Thread::Init()){ if(!Rascsi_Manager::Init()){
return FALSE; return FALSE;
} }
mgr = Rascsi_Manager::GetInstance(); if(!Command_Thread::Init()){
if(!mgr->Init()){
return FALSE; return FALSE;
} }
@@ -157,7 +155,7 @@ BOOL Init()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void Cleanup() void Cleanup()
{ {
mgr->Close(); Rascsi_Manager::Close();
#ifndef BAREMETAL #ifndef BAREMETAL
Command_Thread::Close(); Command_Thread::Close();
@@ -223,12 +221,9 @@ int main(int argc, char* argv[])
#endif // USE_SEL_EVENT_ENABLE #endif // USE_SEL_EVENT_ENABLE
#endif // BAREMETAL #endif // BAREMETAL
// Start execution
Command_Thread::Start();
// Main Loop // Main Loop
while (Command_Thread::IsRunning()) { while (Rascsi_Manager::IsRunning()) {
mgr->Step(); Rascsi_Manager::Step();
} }
#ifdef BAREMETAL #ifdef BAREMETAL
err_exit: err_exit:

View File

@@ -3,9 +3,6 @@
#include "sasidev_ctrl.h" #include "sasidev_ctrl.h"
#include "scsidev_ctrl.h" #include "scsidev_ctrl.h"
Rascsi_Manager *Rascsi_Manager::m_instance = (Rascsi_Manager*)nullptr;
SASIDEV *Rascsi_Manager::m_ctrl[CtrlMax]; // Controller SASIDEV *Rascsi_Manager::m_ctrl[CtrlMax]; // Controller
Disk *Rascsi_Manager::m_disk[CtrlMax * UnitNum]; // Disk Disk *Rascsi_Manager::m_disk[CtrlMax * UnitNum]; // Disk
GPIOBUS *Rascsi_Manager::m_bus; GPIOBUS *Rascsi_Manager::m_bus;
@@ -17,13 +14,7 @@ DWORD Rascsi_Manager::m_now = 0;
BOOL Rascsi_Manager::m_active = FALSE; BOOL Rascsi_Manager::m_active = FALSE;
BOOL Rascsi_Manager::m_running = FALSE; BOOL Rascsi_Manager::m_running = FALSE;
std::timed_mutex Rascsi_Manager::m_locked; std::timed_mutex Rascsi_Manager::m_locked;
BOOL Rascsi_Manager::m_initialized = FALSE;
Rascsi_Manager* Rascsi_Manager::GetInstance(){
if(m_instance != nullptr){
m_instance = new Rascsi_Manager();
}
return m_instance;
}
BOOL Rascsi_Manager::AttachDevice(FILE *fp, Disk *disk, int id, int unit_num){ BOOL Rascsi_Manager::AttachDevice(FILE *fp, Disk *disk, int id, int unit_num){
BOOL result; BOOL result;
@@ -54,7 +45,7 @@ BOOL Rascsi_Manager::AttachDevicePrivate(FILE *fp, Disk *disk, int id, int unit_
// Check if something already exists at that SCSI ID / Unit Number // Check if something already exists at that SCSI ID / Unit Number
if (m_disk[unitno]) { if (m_disk[unitno]) {
DetachDevice(fp,id,unit_num); DetachDevicePrivate(fp,id,unit_num);
} }
// Add the new unit // Add the new unit
@@ -260,12 +251,11 @@ void Rascsi_Manager::Close(){
BOOL Rascsi_Manager::Init(){ BOOL Rascsi_Manager::Init(){
if(m_instance != nullptr){ if(m_initialized != FALSE){
printf("Can not initialize Rascsi_Manager twice!!!\n"); printf("Can not initialize Rascsi_Manager twice!!!\n");
return FALSE; return FALSE;
} }
m_initialized = TRUE;
m_instance = new Rascsi_Manager();
// GPIOBUS creation // GPIOBUS creation
m_bus = new GPIOBUS(); m_bus = new GPIOBUS();
@@ -288,10 +278,11 @@ BOOL Rascsi_Manager::Init(){
m_disk[i] = NULL; m_disk[i] = NULL;
} }
// Reset // Reset
Reset(); Reset();
m_running = TRUE;
return TRUE; return TRUE;
} }
@@ -405,3 +396,11 @@ BOOL Rascsi_Manager::Step()
return TRUE; return TRUE;
} }
void Rascsi_Manager::Stop(){
m_running = FALSE;
}
BOOL Rascsi_Manager::IsRunning(){
return (m_running == TRUE);
}

View File

@@ -37,18 +37,20 @@ enum Rascsi_Device_Mode_e{
class Rascsi_Manager{ class Rascsi_Manager{
public: public:
static Rascsi_Manager* GetInstance(); static Rascsi_Manager* GetInstance();
void MapControler(FILE *fp, Disk **map); static void MapControler(FILE *fp, Disk **map);
static void Stop();
static BOOL IsRunning();
BOOL AttachDevice(FILE *fp, Disk *disk, int id, int ui); static BOOL AttachDevice(FILE *fp, Disk *disk, int id, int ui);
BOOL DetachDevice(FILE *fp, int id, int ui); static BOOL DetachDevice(FILE *fp, int id, int ui);
Disk* GetDevice(FILE *fp, int id, int ui); static Disk* GetDevice(FILE *fp, int id, int ui);
void ListDevice(FILE *fp); static void ListDevice(FILE *fp);
BOOL Init(); static BOOL Init();
void Close(); static void Close();
void Reset(); static void Reset();
BOOL Step(); static BOOL Step();
Rascsi_Device_Mode_e GetCurrentDeviceMode(); static Rascsi_Device_Mode_e GetCurrentDeviceMode();
static const int CtrlMax = 8; // Maximum number of SCSI controllers static const int CtrlMax = 8; // Maximum number of SCSI controllers
static const int UnitNum=2; // Number of units around controller static const int UnitNum=2; // Number of units around controller
@@ -68,12 +70,12 @@ class Rascsi_Manager{
static BUS::phase_t m_phase; static BUS::phase_t m_phase;
static BYTE m_data; static BYTE m_data;
static DWORD m_now; static DWORD m_now;
static Rascsi_Manager *m_instance;
static BOOL m_active; static BOOL m_active;
static BOOL m_running; static BOOL m_running;
static BOOL m_initialized;
BOOL AttachDevicePrivate(FILE *fp, Disk *disk, int id, int ui); static BOOL AttachDevicePrivate(FILE *fp, Disk *disk, int id, int ui);
BOOL DetachDevicePrivate(FILE *fp, int id, int ui); static BOOL DetachDevicePrivate(FILE *fp, int id, int ui);
// Any PUBLIC functions should lock this before accessing the m_ctrl // Any PUBLIC functions should lock this before accessing the m_ctrl
// m_disk or m_bus data structures. The Public functions could be // m_disk or m_bus data structures. The Public functions could be

View File

@@ -17,7 +17,7 @@
// Send Command // Send Command
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
BOOL SendCommand(BYTE *buf) BOOL SendCommand(char *buf)
{ {
int fd; int fd;
struct sockaddr_in server; struct sockaddr_in server;
@@ -27,7 +27,7 @@ BOOL SendCommand(BYTE *buf)
fd = socket(PF_INET, SOCK_STREAM, 0); fd = socket(PF_INET, SOCK_STREAM, 0);
memset(&server, 0, sizeof(server)); memset(&server, 0, sizeof(server));
server.sin_family = PF_INET; server.sin_family = PF_INET;
server.sin_port = htons(6868); server.sin_port = htons(Rasctl_Command::PortNumber);
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
// Connect // Connect
@@ -68,16 +68,14 @@ int main(int argc, char* argv[])
int id; int id;
int un; int un;
char *file; char *file;
int len; char buf[BUFSIZ];
char *ext;
BYTE buf[BUFSIZ];
rasctl_command cmd = rasctl_cmd_invalid; rasctl_command cmd = rasctl_cmd_invalid;
rasctl_dev_type type = rasctl_dev_invalid; rasctl_dev_type type = rasctl_dev_invalid;
Rasctl_Command *rasctl_cmd; Rasctl_Command *rasctl_cmd;
id = -1; id = -1;
un = 0; un = 0;
file = NULL; file = nullptr;
// Display help // Display help
if (argc < 2) { if (argc < 2) {
@@ -102,11 +100,11 @@ int main(int argc, char* argv[])
while ((opt = getopt(argc, argv, "i:u:c:t:f:l")) != -1) { while ((opt = getopt(argc, argv, "i:u:c:t:f:l")) != -1) {
switch (opt) { switch (opt) {
case 'i': case 'i':
id = optarg[0] - '0'; id = atoi((char*)optarg);
break; break;
case 'u': case 'u':
un = optarg[0] - '0'; un = atoi((char*)optarg);
break; break;
case 'c': case 'c':
@@ -175,13 +173,13 @@ int main(int argc, char* argv[])
// Check the ID number // Check the ID number
if (id < 0 || id > 7) { if (id < 0 || id > 7) {
fprintf(stderr, "Error : Invalid ID\n"); fprintf(stderr, "Error : Invalid SCSI/SASI ID number %d\n", id);
exit(EINVAL); exit(EINVAL);
} }
// Check the unit number // Check the unit number
if (un < 0 || un > 1) { if (un < 0 || un > 1) {
fprintf(stderr, "Error : Invalid UNIT\n"); fprintf(stderr, "Error : Invalid UNIT number %d\n", un);
exit(EINVAL); exit(EINVAL);
} }
@@ -190,33 +188,10 @@ int main(int argc, char* argv[])
cmd = rasctl_cmd_attach; // Default command is ATTATCH cmd = rasctl_cmd_attach; // Default command is ATTATCH
} }
// Type Check // If the device type is still "invalid" (unknown), try to figure it out
if (cmd == rasctl_cmd_attach && type == rasctl_dev_invalid) { // from the image file name.
if (cmd == rasctl_cmd_attach && type == rasctl_dev_invalid && file != nullptr) {
// Try to determine the file type from the extension type = Rasctl_Command::DeviceTypeFromFilename(stderr, file);
len = file ? strlen(file) : 0;
if (len > 4 && file[len - 4] == '.') {
ext = &file[len - 3];
if (xstrcasecmp(ext, "hdf") == 0){
type = rasctl_dev_sasi_hd;
}else if(xstrcasecmp(ext, "hds") == 0 ||
xstrcasecmp(ext, "hdi") == 0 ||
xstrcasecmp(ext, "nhd") == 0){
type = rasctl_dev_scsi_hd;
}else if(xstrcasecmp(ext, "hdn") == 0) {
// NEC HD(SASI/SCSI)
type = rasctl_dev_scsi_hd_appl;
}else if(xstrcasecmp(ext, "hda") == 0) {
// Apple HD(SASI/SCSI)
type = rasctl_dev_scsi_hd_appl;
}else if (xstrcasecmp(ext, "mos") == 0) {
// MO
type = rasctl_dev_mo;
}else if (xstrcasecmp(ext, "iso") == 0) {
// CD
type = rasctl_dev_cd;
}
}
if (type == rasctl_dev_invalid) { if (type == rasctl_dev_invalid) {
fprintf(stderr, "Error : Invalid type\n"); fprintf(stderr, "Error : Invalid type\n");
@@ -255,12 +230,14 @@ int main(int argc, char* argv[])
strncpy(rasctl_cmd->file,file,_MAX_PATH); strncpy(rasctl_cmd->file,file,_MAX_PATH);
} }
if(rasctl_cmd->IsValid(stderr)){
// Generate the command and send it // Generate the command and send it
rasctl_cmd->Serialize(buf,BUFSIZ); rasctl_cmd->Serialize(buf,BUFSIZ);
if (!SendCommand(buf)) { if (!SendCommand(buf)) {
exit(ENOTCONN); exit(ENOTCONN);
} }
}
// All done! // All done!
exit(0); exit(0);

View File

@@ -1,23 +1,41 @@
#include "rasctl_command.h" #include "rasctl_command.h"
#include "rascsi_mgr.h" #include "rascsi_mgr.h"
#include <string.h>
const char* Rasctl_Command::m_delimiter = "\x1E"; // Record separator charater // In the serialized string from rasctl
//const char* Rasctl_Command::m_delimiter = " "; // Record separator charater const char* Rasctl_Command::m_delimiter = "\x1E\n"; // Record separator charater
const char* Rasctl_Command::m_no_file = "----";
const uint16_t Rasctl_Command::PortNumber = 6868;
void Rasctl_Command::Serialize(BYTE *buff, int max_buff_size){ const char* Rasctl_Command::dev_type_lookup[] = {
snprintf((char*)buff, max_buff_size, "%d%s%d%s%d%s%d%s%s%s\n", "SASI Hard Drive", // rasctl_dev_sasi_hd = 0,
this->id, this->m_delimiter, "SCSI Hard Drive", // rasctl_dev_scsi_hd = 1,
this->un, this->m_delimiter, "Magneto Optical Drive", // rasctl_dev_mo = 2,
this->cmd, this->m_delimiter, "CD-ROM", // rasctl_dev_cd = 3,
this->type, this->m_delimiter, "Host Bridge", // rasctl_dev_br = 4,
this->file, this->m_delimiter); "Apple SCSI Hard Drive", // rasctl_dev_scsi_hd_appl = 5,
"NEC SCSI Hard DRive", // rasctl_dev_scsi_hd_nec = 6,
};
void Rasctl_Command::Serialize(char *buff, int max_buff_size){
// The filename string can't be empty. Otherwise, strtok will
// ignore the field on the receiving end.
if(strlen(this->file) < 1){
strcpy(this->file,m_no_file);
}
snprintf(buff, max_buff_size, "%d%c%d%c%d%c%d%c%s%c\n",
this->id, this->m_delimiter[0],
this->un, this->m_delimiter[0],
this->cmd, this->m_delimiter[0],
this->type, this->m_delimiter[0],
this->file, this->m_delimiter[0]);
} }
Rasctl_Command* Rasctl_Command::DeSerialize(BYTE* buff, int size){ Rasctl_Command* Rasctl_Command::DeSerialize(char* buff, int size){
Rasctl_Command *return_command = new Rasctl_Command(); Rasctl_Command *return_command = new Rasctl_Command();
char err_message[256]; char err_message[256];
char *cur_token; char *cur_token;
char *command = (char*)buff; char *command = buff;
serial_token_order cur_token_idx = serial_token_first_token; serial_token_order cur_token_idx = serial_token_first_token;
cur_token = strtok(command, m_delimiter); cur_token = strtok(command, m_delimiter);
@@ -31,7 +49,11 @@ Rasctl_Command* Rasctl_Command::DeSerialize(BYTE* buff, int size){
return_command->type = (rasctl_dev_type)atoi(cur_token); return_command->type = (rasctl_dev_type)atoi(cur_token);
break; break;
case serial_token_file_name: case serial_token_file_name:
if(strncmp(cur_token,m_no_file,strlen(m_no_file)) != 0){
strncpy(return_command->file,cur_token,_MAX_PATH); strncpy(return_command->file,cur_token,_MAX_PATH);
} else {
strncpy(return_command->file,"",_MAX_PATH);
}
break; break;
case serial_token_id: case serial_token_id:
return_command->id = atoi(cur_token); return_command->id = atoi(cur_token);
@@ -78,6 +100,7 @@ BOOL Rasctl_Command::rasctl_dev_is_hd(rasctl_dev_type type)
BOOL Rasctl_Command::IsValid(FILE *fp){ BOOL Rasctl_Command::IsValid(FILE *fp){
struct stat stat_buffer; struct stat stat_buffer;
rasctl_dev_type expected_type = rasctl_dev_invalid;
// If the command is "invalid" we can just return FALSE // If the command is "invalid" we can just return FALSE
if(cmd == rasctl_cmd_invalid){ if(cmd == rasctl_cmd_invalid){
@@ -117,7 +140,7 @@ BOOL Rasctl_Command::IsValid(FILE *fp){
return FALSE; return FALSE;
} }
// Check that the file exists if specified // Check that the file exists if specified
if(stat(file, &stat_buffer) == 0){ if(stat(file, &stat_buffer) != 0){
FPRT(fp, "File %s is not accessible", file); FPRT(fp, "File %s is not accessible", file);
return FALSE; return FALSE;
} }
@@ -128,74 +151,49 @@ BOOL Rasctl_Command::IsValid(FILE *fp){
} }
} }
// char* path = optarg; // Check if the filename extension matches the device type
// int type = -1; expected_type = DeviceTypeFromFilename(fp, file);
// if (HasSuffix(path, ".hdf") if(expected_type != rasctl_dev_invalid){
// || HasSuffix(path, ".hds") if((file != nullptr) && (type != expected_type)) {
// || HasSuffix(path, ".hdn") FPRT(fp, "Filename specified is for type %s. This isn't compatible with a %s device.",
// || HasSuffix(path, ".hdi") dev_type_lookup[expected_type], dev_type_lookup[type]);
// || HasSuffix(path, ".hda") return FALSE;
// || HasSuffix(path, ".nhd")) { }
// type = 0; }
// } else if (HasSuffix(path, ".mos")) {
// type = 2;
// } else if (HasSuffix(path, ".iso")) {
// type = 3;
// } else if (xstrcasecmp(path, "bridge") == 0) {
// type = 4;
// } else {
// // Cannot determine the file type
// fprintf(stderr,
// "%s: unknown file extension\n", path);
// return false;
// }
// int un = 0;
// if (is_sasi) {
// un = id % Rascsi_Manager::UnitNum;
// id /= Rascsi_Manager::UnitNum;
// }
// // Execute the command
// if (!ExecuteCommand(stderr, id, un, 0, type, path)) {
// return false;
// }
// id = -1;
// }
// // Display the device list
// Rascsi_Manager::GetInstance()->ListDevice(stdout);
// return true;
// }
// if (type == 0) {
// // Passed the check
// if (!file) {
// return FALSE;
// }
// // Check that command is at least 5 characters long
// len = strlen(file);
// if (len < 5) {
// return FALSE;
// }
// // Check the extension
// if (file[len - 4] != '.') {
// return FALSE;
// }
// // If the extension is not SASI type, replace with SCSI
// ext = &file[len - 3];
// if (xstrcasecmp(ext, "hdf") != 0) {
// type = 1;
// }
return FALSE;
// Everything appears to be OK
return TRUE;
} }
rasctl_dev_type Rasctl_Command::DeviceTypeFromFilename(FILE *fp, const char* filename){
const char *extension = strrchr(filename,'.');
rasctl_dev_type ret_type = rasctl_dev_invalid;
if(extension == nullptr){
fprintf(fp, "Missing file extension from %s",filename);
return rasctl_dev_invalid;
}
if(strcasecmp(extension,".hdf") == 0){
ret_type = rasctl_dev_sasi_hd;
}else if((strcasecmp(extension,".hds") == 0) ||
(strcasecmp(extension,".hdi") == 0) ||
(strcasecmp(extension,".nhd") == 0)){
ret_type = rasctl_dev_scsi_hd;
}else if(strcasecmp(extension,".hdn") == 0){
ret_type = rasctl_dev_scsi_hd_nec;
}else if(strcasecmp(extension,".hdi") == 0){
ret_type = rasctl_dev_scsi_hd_nec;
}else if(strcasecmp(extension,".hda") == 0){
ret_type = rasctl_dev_scsi_hd_appl;
}else if(strcasecmp(extension,".mos") == 0){
ret_type = rasctl_dev_mo;
}else if(strcasecmp(extension,".iso") == 0){
ret_type = rasctl_dev_cd;
}
return ret_type;
}

View File

@@ -40,8 +40,8 @@ enum rasctl_dev_type : int {
class Rasctl_Command{ class Rasctl_Command{
public: public:
void Serialize(BYTE *buff, int max_buff_size); void Serialize(char *buff, int max_buff_size);
static Rasctl_Command* DeSerialize(BYTE* buff, int size); static Rasctl_Command* DeSerialize(char* buff, int size);
BOOL IsValid(FILE *fp); BOOL IsValid(FILE *fp);
@@ -49,12 +49,17 @@ class Rasctl_Command{
rasctl_dev_type type = rasctl_dev_invalid; rasctl_dev_type type = rasctl_dev_invalid;
int id = -1; int id = -1;
int un = -1; int un = -1;
char file[_MAX_PATH]; char file[_MAX_PATH] = "";
static BOOL rasctl_dev_is_hd(rasctl_dev_type dev); static BOOL rasctl_dev_is_hd(rasctl_dev_type dev);
static const uint16_t PortNumber;
static rasctl_dev_type DeviceTypeFromFilename(FILE *fp, const char* filename);
private: private:
static const char* m_delimiter; // Record separator charater static const char* m_delimiter; // Record separator charater
static const char* m_no_file; // Special character sequence indicating an empty file name.
enum serial_token_order : int { enum serial_token_order : int {
serial_token_first_token = 0, serial_token_first_token = 0,
@@ -65,4 +70,6 @@ class Rasctl_Command{
serial_token_file_name = 4, serial_token_file_name = 4,
serial_token_last_token = 5, serial_token_last_token = 5,
}; };
static const char* dev_type_lookup[];
}; };