Start to back out some changes. Just include command processing changes

This commit is contained in:
akuker
2020-08-28 11:56:28 -05:00
parent 66a4a7337c
commit a8ed8ef7c4
5 changed files with 386 additions and 533 deletions

View File

@@ -54,7 +54,6 @@ SRC_RASCSI = \
gpiobus.cpp \ gpiobus.cpp \
filepath.cpp \ filepath.cpp \
fileio.cpp\ fileio.cpp\
rascsi_mgr.cpp\
command_thread.cpp\ command_thread.cpp\
os.cpp\ os.cpp\
rasctl_command.cpp rasctl_command.cpp

View File

@@ -21,7 +21,6 @@
#include "os.h" #include "os.h"
#include "rasctl_command.h" #include "rasctl_command.h"
#include "rascsi_mgr.h"
#include "sasihd.h" #include "sasihd.h"
#include "scsihd.h" #include "scsihd.h"
#include "scsihd_nec.h" #include "scsihd_nec.h"

View File

@@ -5,8 +5,6 @@
// //
// Powered by XM6 TypeG Technology. // Powered by XM6 TypeG Technology.
// Copyright (C) 2016-2020 GIMONS // Copyright (C) 2016-2020 GIMONS
// Copyright (C) akuker
//
// [ RaSCSI main ] // [ RaSCSI main ]
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@@ -27,41 +25,35 @@
#include "controllers/sasidev_ctrl.h" #include "controllers/sasidev_ctrl.h"
#include "gpiobus.h" #include "gpiobus.h"
#include "command_thread.h" #include "command_thread.h"
#include "rascsi_mgr.h"
#include "sasidev_ctrl.h"
#include "scsidev_ctrl.h"
#include "sasihd.h"
#include "scsihd.h"
#include "scsihd_apple.h"
#include "scsihd_nec.h"
#include "scsicd.h"
#include "scsimo.h"
#include "scsi_host_bridge.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Constant declarations // Constant declarations
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#define CtrlMax 8 // Maximum number of SCSI controllers
#define UnitNum 2 // Number of units around controller
#ifdef BAREMETAL
#define FPRT(fp, ...) printf( __VA_ARGS__ )
#else
#define FPRT(fp, ...) fprintf(fp, __VA_ARGS__ )
#endif // BAREMETAL
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Variable declarations // Variable declarations
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static volatile BOOL running; // Running flag
static volatile BOOL active; // Processing flag
SASIDEV *ctrl[CtrlMax]; // Controller
Disk *disk[CtrlMax * UnitNum]; // Disk
GPIOBUS *bus; // GPIO Bus
#ifdef BAREMETAL #ifdef BAREMETAL
FATFS fatfs; // FatFS FATFS fatfs; // FatFS
#else #else
#endif // BAREMETAL #endif // BAREMETAL
#ifndef CONNECT_DESC
#define CONNECT_DESC "UNKNOWN"
#endif
#ifndef BAREMETAL #ifndef BAREMETAL
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
@@ -71,7 +63,7 @@ FATFS fatfs; // FatFS
void KillHandler(int sig) void KillHandler(int sig)
{ {
// Stop instruction // Stop instruction
Rascsi_Manager::Stop(); running = FALSE;
} }
#endif // BAREMETAL #endif // BAREMETAL
@@ -93,7 +85,6 @@ void Banner(int argc, char* argv[])
FPRT(stdout,"Powered by XM6 TypeG Technology / "); FPRT(stdout,"Powered by XM6 TypeG Technology / ");
FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n"); FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n");
FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); FPRT(stdout,"Connect type : %s\n", CONNECT_DESC);
FPRT(stdout,"Build on %s at %s\n", __DATE__, __TIME__);
if ((argc > 1 && strcmp(argv[1], "-h") == 0) || if ((argc > 1 && strcmp(argv[1], "-h") == 0) ||
(argc > 1 && strcmp(argv[1], "--help") == 0)){ (argc > 1 && strcmp(argv[1], "--help") == 0)){
@@ -127,17 +118,9 @@ void Banner(int argc, char* argv[])
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
BOOL Init() BOOL Init()
{ {
printf("Rascsi_Manager Init\n"); int i;
if(!Rascsi_Manager::Init()){
printf("\tRascsi_Manager FAILED!!\n");
return FALSE;
}
printf("Command_Thread Init\n"); #ifndef BAREMETAL
if(!Command_Thread::Init()){
printf("\tCommand_Thread FAILED!!\n");
return FALSE;
}
// Interrupt handler settings // Interrupt handler settings
if (signal(SIGINT, KillHandler) == SIG_ERR) { if (signal(SIGINT, KillHandler) == SIG_ERR) {
@@ -149,6 +132,38 @@ BOOL Init()
if (signal(SIGTERM, KillHandler) == SIG_ERR) { if (signal(SIGTERM, KillHandler) == SIG_ERR) {
return FALSE; return FALSE;
} }
#endif // BAREMETAL
// GPIOBUS creation
bus = new GPIOBUS();
// GPIO Initialization
if (!bus->Init()) {
return FALSE;
}
// Bus Reset
bus->Reset();
// Controller initialization
for (i = 0; i < CtrlMax; i++) {
ctrl[i] = NULL;
}
// Disk Initialization
for (i = 0; i < CtrlMax; i++) {
disk[i] = NULL;
}
// Other
running = FALSE;
active = FALSE;
printf("Command_Thread Init\n");
if(!Command_Thread::Init()){
printf("\tCommand_Thread FAILED!!\n");
return FALSE;
}
return TRUE; return TRUE;
} }
@@ -160,13 +175,243 @@ BOOL Init()
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void Cleanup() void Cleanup()
{ {
Rascsi_Manager::Close(); int i;
// Delete the disks
for (i = 0; i < CtrlMax * UnitNum; i++) {
if (disk[i]) {
delete disk[i];
disk[i] = NULL;
}
}
// Delete the Controllers
for (i = 0; i < CtrlMax; i++) {
if (ctrl[i]) {
delete ctrl[i];
ctrl[i] = NULL;
}
}
// Cleanup the Bus
bus->Cleanup();
// Discard the GPIOBUS object
delete bus;
#ifndef BAREMETAL #ifndef BAREMETAL
// Close the command socket
Command_Thread::Close(); Command_Thread::Close();
#endif // BAREMETAL #endif // BAREMETAL
} }
//---------------------------------------------------------------------------
//
// Reset
//
//---------------------------------------------------------------------------
void Reset()
{
int i;
// Reset all of the controllers
for (i = 0; i < CtrlMax; i++) {
if (ctrl[i]) {
ctrl[i]->Reset();
}
}
// Reset the bus
bus->Reset();
}
//---------------------------------------------------------------------------
//
// List Devices
//
//---------------------------------------------------------------------------
void ListDevice(FILE *fp)
{
int i;
int id;
int un;
Disk *pUnit;
Filepath filepath;
BOOL find;
char type[5];
find = FALSE;
type[4] = 0;
for (i = 0; i < CtrlMax * UnitNum; i++) {
// Initialize ID and unit number
id = i / UnitNum;
un = i % UnitNum;
pUnit = disk[i];
// skip if unit does not exist or null disk
if (pUnit == NULL || pUnit->IsNULL()) {
continue;
}
// Output the header
if (!find) {
FPRT(fp, "\n");
FPRT(fp, "+----+----+------+-------------------------------------\n");
FPRT(fp, "| ID | UN | TYPE | DEVICE STATUS\n");
FPRT(fp, "+----+----+------+-------------------------------------\n");
find = TRUE;
}
// ID,UNIT,Type,Device Status
type[0] = (char)(pUnit->GetID() >> 24);
type[1] = (char)(pUnit->GetID() >> 16);
type[2] = (char)(pUnit->GetID() >> 8);
type[3] = (char)(pUnit->GetID());
FPRT(fp, "| %d | %d | %s | ", id, un, type);
// mount status output
if (pUnit->GetID() == MAKEID('S', 'C', 'B', 'R')) {
FPRT(fp, "%s", "HOST BRIDGE");
} else {
pUnit->GetPath(filepath);
FPRT(fp, "%s",
(pUnit->IsRemovable() && !pUnit->IsReady()) ?
"NO MEDIA" : filepath.GetPath());
}
// Write protection status
if (pUnit->IsRemovable() && pUnit->IsReady() && pUnit->IsWriteP()) {
FPRT(fp, "(WRITEPROTECT)");
}
// Goto the next line
FPRT(fp, "\n");
}
// If there is no controller, find will be null
if (!find) {
FPRT(fp, "No device is installed.\n");
return;
}
FPRT(fp, "+----+----+------+-------------------------------------\n");
}
//---------------------------------------------------------------------------
//
// Controller Mapping
//
//---------------------------------------------------------------------------
void 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 (disk[unitno] != map[unitno]) {
// Check if the original unit exists
if (disk[unitno]) {
// Disconnect it from the controller
if (ctrl[i]) {
ctrl[i]->SetUnit(j, NULL);
}
// Free the Unit
delete disk[unitno];
}
// Setup a new unit
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 (disk[unitno]) {
if (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 (ctrl[i]) {
ctrl[i]->SetUnit(j, NULL);
}
}
// If there are no units connected
if (sasi_num == 0 && scsi_num == 0) {
if (ctrl[i]) {
delete ctrl[i];
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 (ctrl[i] && !ctrl[i]->IsSASI()) {
delete ctrl[i];
ctrl[i] = NULL;
}
// Create a new SASI controller
if (!ctrl[i]) {
ctrl[i] = new SASIDEV();
ctrl[i]->Connect(i, bus);
}
} else {
// Only SCSI Unit(s)
// Release the controller if it is not SCSI
if (ctrl[i] && !ctrl[i]->IsSCSI()) {
delete ctrl[i];
ctrl[i] = NULL;
}
// Create a new SCSI controller
if (!ctrl[i]) {
ctrl[i] = new SCSIDEV();
ctrl[i]->Connect(i, bus);
}
}
// connect all units
for (j = 0; j < UnitNum; j++) {
unitno = i * UnitNum + j;
if (disk[unitno]) {
// Add the unit connection
ctrl[i]->SetUnit(j, disk[unitno]);
}
}
}
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Main processing // Main processing
@@ -181,9 +426,13 @@ int startrascsi(void)
#else #else
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
int i=0;
#endif // BAREMETAL #endif // BAREMETAL
int i;
int ret; int ret;
int actid;
DWORD now;
BUS::phase_t phase;
BYTE data;
#ifndef BAREMETAL #ifndef BAREMETAL
struct sched_param schparam; struct sched_param schparam;
#endif // BAREMETAL #endif // BAREMETAL
@@ -198,24 +447,23 @@ int main(int argc, char* argv[])
goto init_exit; goto init_exit;
} }
// Reset
Reset();
#ifdef BAREMETAL #ifdef BAREMETAL
// BUSY assert (to hold the host side) // BUSY assert (to hold the host side)
Rascsi_Manager::m_bus->SetBSY(TRUE); bus->SetBSY(TRUE);
// Argument parsing // Argument parsing
if (!Command_Thread::ParseConfig(argc, argv)) { if (!Command_Thread::ParseConfig(argc, argv)) {
ret = EINVAL; ret = EINVAL;
goto err_exit; goto err_exit;
} }
// Release the busy signal // Release the busy signal
Rascsi_Manager::m_bus->SetBSY(FALSE); bus->SetBSY(FALSE);
#endif #endif
// For non-baremetal versions, we won't process the startup arguments... yet
printf("Here1\n");
#ifndef BAREMETAL #ifndef BAREMETAL
// Set the affinity to a specific processor core // Set the affinity to a specific processor core
FixCpu(3); FixCpu(3);
@@ -227,11 +475,105 @@ int main(int argc, char* argv[])
#endif // USE_SEL_EVENT_ENABLE #endif // USE_SEL_EVENT_ENABLE
#endif // BAREMETAL #endif // BAREMETAL
printf("entering main loop \n"); // Start execution
running = TRUE;
// Main Loop // Main Loop
while (Rascsi_Manager::IsRunning()) { while (running) {
printf("step %d\n", i++); // Work initialization
Rascsi_Manager::Step(); actid = -1;
phase = BUS::busfree;
#ifdef USE_SEL_EVENT_ENABLE
// SEL signal polling
if (bus->PollSelectEvent() < 0) {
// Stop on interrupt
if (errno == EINTR) {
break;
}
continue;
}
// Get the bus
bus->Aquire();
#else
bus->Aquire();
if (!bus->GetSEL()) {
#if !defined(BAREMETAL)
usleep(0);
#endif // !BAREMETAL
continue;
}
#endif // USE_SEL_EVENT_ENABLE
// Wait until BSY is released as there is a possibility for the
// initiator to assert it while setting the ID (for up to 3 seconds)
if (bus->GetBSY()) {
now = SysTimer::GetTimerLow();
while ((SysTimer::GetTimerLow() - now) < 3 * 1000 * 1000) {
bus->Aquire();
if (!bus->GetBSY()) {
break;
}
}
}
// Stop because it the bus is busy or another device responded
if (bus->GetBSY() || !bus->GetSEL()) {
continue;
}
// Notify all controllers
data = bus->GetDAT();
for (i = 0; i < CtrlMax; i++) {
if (!ctrl[i] || (data & (1 << i)) == 0) {
continue;
}
// Find the target that has moved to the selection phase
if (ctrl[i]->Process() == BUS::selection) {
// Get the target ID
actid = i;
// Bus Selection phase
phase = BUS::selection;
break;
}
}
// Return to bus monitoring if the selection phase has not started
if (phase != BUS::selection) {
continue;
}
// Start target device
active = TRUE;
#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL)
// Scheduling policy setting (highest priority)
schparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &schparam);
#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL
// Loop until the bus is free
while (running) {
// Target drive
phase = ctrl[actid]->Process();
// End when the bus is free
if (phase == BUS::busfree) {
break;
}
}
#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL)
// Set the scheduling priority back to normal
schparam.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &schparam);
#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL
// End the target travel
active = FALSE;
} }
printf("Exited main loop\n"); printf("Exited main loop\n");

View File

@@ -1,403 +0,0 @@
#include "rascsi_mgr.h"
#include "log.h"
#include "sasidev_ctrl.h"
#include "scsidev_ctrl.h"
SASIDEV *Rascsi_Manager::m_ctrl[CtrlMax]; // Controller
Disk *Rascsi_Manager::m_disk[CtrlMax * UnitNum]; // Disk
GPIOBUS *Rascsi_Manager::m_bus;
int Rascsi_Manager::m_actid = -1;
BUS::phase_t Rascsi_Manager::m_phase = BUS::busfree;
BYTE Rascsi_Manager::m_data = 0;
DWORD Rascsi_Manager::m_now = 0;
BOOL Rascsi_Manager::m_active = FALSE;
BOOL Rascsi_Manager::m_running = FALSE;
std::timed_mutex Rascsi_Manager::m_locked;
BOOL Rascsi_Manager::m_initialized = FALSE;
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;
}
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;
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]) {
DetachDevicePrivate(fp,id,unit_num);
}
// Add the new unit
m_disk[unitno] = disk;
// 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);
}
// Add the disk to the controller
m_ctrl[id]->SetUnit(unit_num, disk);
return TRUE;
}
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;
}
//---------------------------------------------------------------------------
//
// Reset
//
//---------------------------------------------------------------------------
void Rascsi_Manager::Reset()
{
int i;
// Reset all of the controllers
for (i = 0; i < CtrlMax; i++) {
if (m_ctrl[i]) {
m_ctrl[i]->Reset();
}
}
// Reset the bus
m_bus->Reset();
}
//---------------------------------------------------------------------------
//
// List Devices
//
//---------------------------------------------------------------------------
void Rascsi_Manager::ListDevice(FILE *fp)
{
int i;
int id;
int un;
Disk *pUnit;
Filepath filepath;
BOOL find;
char type[5];
find = FALSE;
type[4] = 0;
for (i = 0; i < CtrlMax * UnitNum; i++) {
// Initialize ID and unit number
id = i / UnitNum;
un = i % UnitNum;
pUnit = m_disk[i];
// skip if unit does not exist or null disk
if (pUnit == NULL || pUnit->IsNULL()) {
continue;
}
// Output the header
if (!find) {
FPRT(fp, "\n");
FPRT(fp, "+----+----+------+-------------------------------------\n");
FPRT(fp, "| ID | UN | TYPE | DEVICE STATUS\n");
FPRT(fp, "+----+----+------+-------------------------------------\n");
find = TRUE;
}
// ID,UNIT,Type,Device Status
type[0] = (char)(pUnit->GetID() >> 24);
type[1] = (char)(pUnit->GetID() >> 16);
type[2] = (char)(pUnit->GetID() >> 8);
type[3] = (char)(pUnit->GetID());
FPRT(fp, "| %d | %d | %s | ", id, un, type);
// mount status output
if (pUnit->GetID() == MAKEID('S', 'C', 'B', 'R')) {
FPRT(fp, "%s", "HOST BRIDGE");
} else {
pUnit->GetPath(filepath);
FPRT(fp, "%s",
(pUnit->IsRemovable() && !pUnit->IsReady()) ?
"NO MEDIA" : filepath.GetPath());
}
// Write protection status
if (pUnit->IsRemovable() && pUnit->IsReady() && pUnit->IsWriteP()) {
FPRT(fp, "(WRITEPROTECT)");
}
// Goto the next line
FPRT(fp, "\n");
}
// If there is no controller, find will be null
if (!find) {
FPRT(fp, "No device is installed.\n");
return;
}
FPRT(fp, "+----+----+------+-------------------------------------\n");
}
void Rascsi_Manager::Close(){
// Delete the disks
for (int i = 0; i < (CtrlMax * UnitNum); i++) {
if (m_disk[i]) {
delete m_disk[i];
m_disk[i] = NULL;
}
}
// Delete the Controllers
for (int i = 0; i < CtrlMax; i++) {
if (m_ctrl[i]) {
delete m_ctrl[i];
m_ctrl[i] = NULL;
}
}
// Cleanup the Bus
m_bus->Cleanup();
// Discard the GPIOBUS object
delete m_bus;
}
BOOL Rascsi_Manager::Init(){
if(m_initialized != FALSE){
printf("Can not initialize Rascsi_Manager twice!!!\n");
return FALSE;
}
m_initialized = TRUE;
// GPIOBUS creation
m_bus = new GPIOBUS();
// GPIO Initialization
if (!m_bus->Init()) {
return FALSE;
}
// Bus Reset
m_bus->Reset();
// Controller initialization
for (int i = 0; i < CtrlMax; i++) {
m_ctrl[i] = NULL;
}
// Disk Initialization
for (int i = 0; i < CtrlMax; i++) {
m_disk[i] = NULL;
}
// Reset
Reset();
m_running = TRUE;
return TRUE;
}
BOOL Rascsi_Manager::Step()
{
// Work initialization
m_actid = -1;
m_phase = BUS::busfree;
#ifdef USE_SEL_EVENT_ENABLE
// SEL signal polling
if (m_bus->PollSelectEvent() < 0) {
// Stop on interrupt
if (errno == EINTR) {
m_locked.unlock();
return FALSE;
}
return FALSE;
}
// Get the bus
m_bus->Aquire();
#else
m_bus->Aquire();
if (!m_bus->GetSEL()) {
#if !defined(BAREMETAL)
usleep(0);
#endif // !BAREMETAL
return FALSE;
}
#endif // USE_SEL_EVENT_ENABLE
// Wait until BSY is released as there is a possibility for the
// initiator to assert it while setting the ID (for up to 3 seconds)
if (m_bus->GetBSY()) {
m_now = SysTimer::GetTimerLow();
while ((SysTimer::GetTimerLow() - m_now) < 3 * 1000 * 1000) {
m_bus->Aquire();
if (!m_bus->GetBSY()) {
break;
}
}
}
// Stop because it the bus is busy or another device responded
if (m_bus->GetBSY() || !m_bus->GetSEL()) {
return FALSE;
}
m_locked.lock();
// Notify all controllers
m_data = m_bus->GetDAT();
for (int i = 0; i < CtrlMax; i++) {
if (!m_ctrl[i] || (m_data & (1 << i)) == 0) {
continue;
}
// Find the target that has moved to the selection phase
if (m_ctrl[i]->Process() == BUS::selection) {
// Get the target ID
m_actid = i;
// Bus Selection phase
m_phase = BUS::selection;
break;
}
}
// Return to bus monitoring if the selection phase has not started
if (m_phase != BUS::selection) {
m_locked.unlock();
return FALSE;
}
// Start target device
m_active = TRUE;
#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL)
// Scheduling policy setting (highest priority)
schparam.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &schparam);
#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL
// Loop until the bus is free
while (m_running) {
// Target drive
m_phase = m_ctrl[m_actid]->Process();
// End when the bus is free
if (m_phase == BUS::busfree) {
break;
}
}
#if !defined(USE_SEL_EVENT_ENABLE) && !defined(BAREMETAL)
// Set the scheduling priority back to normal
schparam.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &schparam);
#endif // !USE_SEL_EVENT_ENABLE && !BAREMETAL
// End the target travel
m_active = FALSE;
m_locked.unlock();
return TRUE;
}
void Rascsi_Manager::Stop(){
m_running = FALSE;
}
BOOL Rascsi_Manager::IsRunning(){
return (m_running == TRUE);
}

View File

@@ -1,84 +0,0 @@
//---------------------------------------------------------------------------
//
// 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.
//
// [ RaSCSI Manager ]
//
// Any meaningful logic should be included in this file so that it can be
// tested using unit tests. The main "rascsi.cpp" file should contain very
// little functional code.
//---------------------------------------------------------------------------
#pragma once
#include "os.h"
#include "scsi.h"
#include "fileio.h"
#include "disk.h"
#include "log.h"
#include "xm6.h"
#include "gpiobus.h"
#include "sasidev_ctrl.h"
#include <mutex>
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();
static void MapControler(FILE *fp, Disk **map);
static void Stop();
static BOOL IsRunning();
static BOOL AttachDevice(FILE *fp, Disk *disk, int id, int ui);
static BOOL DetachDevice(FILE *fp, int id, int ui);
static Disk* GetDevice(FILE *fp, int id, int ui);
static void ListDevice(FILE *fp);
static BOOL Init();
static void Close();
static void Reset();
static BOOL Step();
static 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
// TODO: These need to be made private. All of the functionality that is using
// them directly should be updated to be issolated.
// The Command_Thread class is WAAAAY too tightly coupled to this class.
//
static SASIDEV *m_ctrl[CtrlMax]; // Controller
static Disk *m_disk[CtrlMax * UnitNum]; // Disk
static GPIOBUS *m_bus; // GPIO Bus
private:
static int m_actid;
static BUS::phase_t m_phase;
static BYTE m_data;
static DWORD m_now;
static BOOL m_active;
static BOOL m_running;
static BOOL m_initialized;
static BOOL AttachDevicePrivate(FILE *fp, Disk *disk, int id, int ui);
static 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.
static std::timed_mutex m_locked;
};