From c86764c6e7cb66f144efc34251bca53b517db8b9 Mon Sep 17 00:00:00 2001 From: akuker Date: Mon, 6 Jul 2020 19:23:54 -0500 Subject: [PATCH 01/16] Debug code for cd-rom integration --- src/raspberrypi/Makefile | 11 +- src/raspberrypi/disk.cpp | 515 ++++++++++++++++++++++++--------------- src/raspberrypi/disk.h | 3 + 3 files changed, 326 insertions(+), 203 deletions(-) diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index 97d7b13..f2adee5 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -1,7 +1,10 @@ CC = gcc -CFLAGS = -DNDEBUG -O3 -Wall +CFLAGS = -DDISK_LOG -O0 -g -Wall CXX = g++ -CXXFLAGS = -DNDEBUG -O3 -Wall +CXXFLAGS = -DDISK_LOG -O0 -g -Wall + +# If its not specified, build for STANDARD configuration +CONNECT_TYPE ?= STANDARD ifdef CONNECT_TYPE CFLAGS += -DCONNECT_TYPE_$(CONNECT_TYPE) @@ -13,6 +16,7 @@ RASCTL = rasctl RASDUMP = rasdump SASIDUMP = sasidump + BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) SRC_RASCSI = \ @@ -67,3 +71,6 @@ $(SASIDUMP): $(OBJ_SASIDUMP) clean: rm -f $(OBJ_ALL) $(BIN_ALL) + +run: + sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK.HDA -ID6 /home/pi/marathon.iso diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index dbe3d34..217e6d1 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -45,7 +45,7 @@ //#define DISK_LOG #ifdef RASCSI -#define BENDER_SIGNATURE "RaSCSI" +#define BENDER_SIGNATURE "SONY " #else #define BENDER_SIGNATURE "XM6" #endif @@ -1346,16 +1346,20 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Get changeable flag if ((cdb[2] & 0xc0) == 0x40) { + printf("MODESENSE: Change = TRUE\n"); change = TRUE; } else { + printf("MODESENSE: Change = FALSE\n"); change = FALSE; } // Get page code (0x00 is valid from the beginning) page = cdb[2] & 0x3f; if (page == 0x00) { + printf("MODESENSE: Page code: OK %02X\n", cdb[2]); valid = TRUE; } else { + printf("MODESENSE: Invalid page code received %02X\n", cdb[2]); valid = FALSE; } @@ -1369,6 +1373,7 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // DEVICE SPECIFIC PARAMETER if (disk.writep) { + printf("MODESENSE: Write protect\n"); buf[2] = 0x80; } @@ -1379,6 +1384,7 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Only if ready if (disk.ready) { + printf("MODESENSE: Disk is ready\n"); // Block descriptor (number of blocks) buf[5] = (BYTE)(disk.blocks >> 16); buf[6] = (BYTE)(disk.blocks >> 8); @@ -1455,10 +1461,13 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Unsupported page if (!valid) { + printf("MODESENSE: Something was invalid...\n"); disk.code = DISK_INVALIDCDB; return 0; } + printf("MODESENSE: mode sense length is %d\n",length); + // MODE SENSE success disk.code = DISK_NOERROR; return length; @@ -2820,7 +2829,7 @@ BOOL FASTCALL SCSIHD_NEC::Open(const Filepath& path, BOOL /*attn*/) cylinders = (int)(size >> 9); cylinders >>= 3; cylinders /= 25; - } else if (xstrcasecmp(ext, _T(".HDI")) == 0) { // Anex86 HD image? + } else if (xstrcasecmp(ext, _T(".HDI")) == 0) { // Anex86 HD image? imgoffset = getDwordLE(&hdr[4 + 4]); imgsize = getDwordLE(&hdr[4 + 4 + 4]); sectorsize = getDwordLE(&hdr[4 + 4 + 4 + 4]); @@ -2944,7 +2953,7 @@ int FASTCALL SCSIHD_NEC::AddFormat(BOOL change, BYTE *buf) // 1ゾーンのトラック数を設定(PC-9801-55はこの値を見ているようだ) buf[0x2] = (BYTE)(heads >> 8); buf[0x3] = (BYTE)heads; - + // 1トラックのセクタ数を設定 buf[0xa] = (BYTE)(sectors >> 8); buf[0xb] = (BYTE)sectors; @@ -2987,7 +2996,7 @@ int FASTCALL SCSIHD_NEC::AddDrive(BOOL change, BYTE *buf) buf[0x2] = (BYTE)(cylinders >> 16); buf[0x3] = (BYTE)(cylinders >> 8); buf[0x4] = (BYTE)cylinders; - + // ヘッド数を設定 buf[0x5] = (BYTE)heads; } @@ -3401,29 +3410,29 @@ int FASTCALL SCSIMO::AddVendor(int page, BOOL change, BYTE *buf) mode page code 20h - Vendor Unique Format Page format mode XXh type 0 information: http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-lpg28560-1.pdf - + offset description 02h format mode 03h type of format (0) 04~07h size of user band (total sectors?) 08~09h size of spare band (spare sectors?) 0A~0Bh number of bands - + actual value of each 3.5inches optical medium (grabbed by Fujitsu M2513EL) - + 128M 230M 540M 640M --------------------------------------------------- size of user band 3CBFAh 6CF75h FE45Ch 4BC50h size of spare band 0400h 0401h 08CAh 08C4h number of bands 0001h 000Ah 0012h 000Bh - + further information: http://r2089.blog36.fc2.com/blog-entry-177.html */ if (disk.ready) { unsigned spare = 0; unsigned bands = 0; - + if (disk.size == 9) switch (disk.blocks) { // 128MB case 248826: @@ -4126,7 +4135,7 @@ int FASTCALL SCSICD::Inquiry( buf[1] = 0x80; buf[2] = 0x02; buf[3] = 0x02; - buf[4] = 36 - 5; // 必須 + buf[4] = 42; // Required // Fill with blanks memset(&buf[8], 0x20, buf[4] - 3); @@ -4135,12 +4144,16 @@ int FASTCALL SCSICD::Inquiry( memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); // Product name - memcpy(&buf[16], "CD-ROM CDU-55S", 14); + memcpy(&buf[16], "CD-ROM CDU-8003A", 16); // Revision (XM6 version number) - sprintf(rev, "0%01d%01d%01d", - (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); - memcpy(&buf[32], rev, 4); +// sprintf(rev, "1.9a", + // (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], "1.9a", 4); + + //strcpy(&buf[35],"A1.9a"); + buf[36]=0x20; + memcpy(&buf[37],"1999/01/01",10); // Size of data that can be returned size = (buf[4] + 5); @@ -4989,7 +5002,7 @@ void FASTCALL SCSIBR::FS_CheckDir(BYTE *buf) pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->CheckDir(nUnit, pNamests); } @@ -5013,10 +5026,10 @@ void FASTCALL SCSIBR::FS_MakeDir(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->MakeDir(nUnit, pNamests); } @@ -5040,10 +5053,10 @@ void FASTCALL SCSIBR::FS_RemoveDir(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->RemoveDir(nUnit, pNamests); } @@ -5068,13 +5081,13 @@ void FASTCALL SCSIBR::FS_Rename(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); pNamestsNew = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->Rename(nUnit, pNamests, pNamestsNew); } @@ -5098,10 +5111,10 @@ void FASTCALL SCSIBR::FS_Delete(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->Delete(nUnit, pNamests); } @@ -5126,14 +5139,14 @@ void FASTCALL SCSIBR::FS_Attribute(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); dp = (DWORD*)&buf[i]; nHumanAttribute = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->Attribute(nUnit, pNamests, nHumanAttribute); } @@ -5163,7 +5176,7 @@ void FASTCALL SCSIBR::FS_Files(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); @@ -5270,7 +5283,7 @@ void FASTCALL SCSIBR::FS_Create(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); @@ -5332,7 +5345,7 @@ void FASTCALL SCSIBR::FS_Open(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); @@ -5385,7 +5398,7 @@ void FASTCALL SCSIBR::FS_Close(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5434,7 +5447,7 @@ void FASTCALL SCSIBR::FS_Read(BYTE *buf) pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); - + dp = (DWORD*)&buf[i]; nSize = ntohl(*dp); i += sizeof(DWORD); @@ -5483,7 +5496,7 @@ void FASTCALL SCSIBR::FS_Write(BYTE *buf) dp = (DWORD*)buf; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5535,7 +5548,7 @@ void FASTCALL SCSIBR::FS_Seek(BYTE *buf) dp = (DWORD*)buf; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5594,7 +5607,7 @@ void FASTCALL SCSIBR::FS_TimeStamp(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5675,10 +5688,10 @@ void FASTCALL SCSIBR::FS_CtrlDrive(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i]; i += sizeof(Human68k::ctrldrive_t); - + fsresult = fs->CtrlDrive(nUnit, pCtrlDrive); memcpy(fsout, pCtrlDrive, sizeof(Human68k::ctrldrive_t)); @@ -5705,7 +5718,7 @@ void FASTCALL SCSIBR::FS_GetDPB(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->GetDPB(nUnit, &dpb); dpb.sector_size = htons(dpb.sector_size); @@ -5748,7 +5761,7 @@ void FASTCALL SCSIBR::FS_DiskRead(BYTE *buf) dp = (DWORD*)&buf[i]; nSize = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->DiskRead(nUnit, fsout, nSector, nSize); fsoutlen = 0x200; } @@ -5772,7 +5785,7 @@ void FASTCALL SCSIBR::FS_DiskWrite(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->DiskWrite(nUnit); } @@ -5849,7 +5862,7 @@ void FASTCALL SCSIBR::FS_Flush(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->Flush(nUnit); } @@ -5872,7 +5885,7 @@ void FASTCALL SCSIBR::FS_CheckMedia(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->CheckMedia(nUnit); } @@ -5895,7 +5908,7 @@ void FASTCALL SCSIBR::FS_Lock(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->Lock(nUnit); } @@ -6021,11 +6034,11 @@ SASIDEV::SASIDEV(Device *dev) int i; #ifndef RASCSI - // ホストデバイスを記憶 + // Remember host device host = dev; #endif // RASCSI - // ワーク初期化 + // Work initialization ctrl.phase = BUS::busfree; ctrl.id = -1; ctrl.bus = NULL; @@ -6043,7 +6056,7 @@ SASIDEV::SASIDEV(Device *dev) ctrl.offset = 0; ctrl.length = 0; - // 論理ユニット初期化 + // Logical unit initialization for (i = 0; i < UnitMax; i++) { ctrl.unit[i] = NULL; } @@ -6056,7 +6069,7 @@ SASIDEV::SASIDEV(Device *dev) //--------------------------------------------------------------------------- SASIDEV::~SASIDEV() { - // バッファを開放 + // Free the buffer if (ctrl.buffer) { free(ctrl.buffer); ctrl.buffer = NULL; @@ -6065,7 +6078,7 @@ SASIDEV::~SASIDEV() //--------------------------------------------------------------------------- // -// デバイスリセット +// Device reset // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Reset() @@ -6074,7 +6087,7 @@ void FASTCALL SASIDEV::Reset() ASSERT(this); - // ワーク初期化 + // Work initialization memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd)); ctrl.phase = BUS::busfree; ctrl.status = 0x00; @@ -6088,7 +6101,7 @@ void FASTCALL SASIDEV::Reset() ctrl.offset = 0; ctrl.length = 0; - // ユニット初期化 + // Unit initialization for (i = 0; i < UnitMax; i++) { if (ctrl.unit[i]) { ctrl.unit[i]->Reset(); @@ -6099,7 +6112,7 @@ void FASTCALL SASIDEV::Reset() #ifndef RASCSI //--------------------------------------------------------------------------- // -// セーブ +// Save // //--------------------------------------------------------------------------- BOOL FASTCALL SASIDEV::Save(Fileio *fio, int /*ver*/) @@ -6109,13 +6122,13 @@ BOOL FASTCALL SASIDEV::Save(Fileio *fio, int /*ver*/) ASSERT(this); ASSERT(fio); - // サイズをセーブ + // Save size sz = 2120; if (!fio->Write(&sz, sizeof(sz))) { return FALSE; } - // 実体をセーブ + // Save entity PROP_EXPORT(fio, ctrl.phase); PROP_EXPORT(fio, ctrl.id); PROP_EXPORT(fio, ctrl.cmd); @@ -6134,7 +6147,7 @@ BOOL FASTCALL SASIDEV::Save(Fileio *fio, int /*ver*/) //--------------------------------------------------------------------------- // -// ロード +// Load // //--------------------------------------------------------------------------- BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver) @@ -6144,12 +6157,12 @@ BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver) ASSERT(this); ASSERT(fio); - // version3.11より前はセーブしていない + // Not saved before version 3.11 if (ver <= 0x0311) { return TRUE; } - // サイズをロード、照合 + // Load size and check if the size matches if (!fio->Read(&sz, sizeof(sz))) { return FALSE; } @@ -6157,7 +6170,7 @@ BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver) return FALSE; } - // 実体をロード + // Load the entity PROP_IMPORT(fio, ctrl.phase); PROP_IMPORT(fio, ctrl.id); PROP_IMPORT(fio, ctrl.cmd); @@ -6177,7 +6190,7 @@ BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver) //--------------------------------------------------------------------------- // -// コントローラ接続 +// Connect the controller // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Connect(int id, BUS *bus) @@ -6190,7 +6203,7 @@ void FASTCALL SASIDEV::Connect(int id, BUS *bus) //--------------------------------------------------------------------------- // -// 論理ユニット取得 +// Get the logical unit // //--------------------------------------------------------------------------- Disk* FASTCALL SASIDEV::GetUnit(int no) @@ -6203,7 +6216,7 @@ Disk* FASTCALL SASIDEV::GetUnit(int no) //--------------------------------------------------------------------------- // -// 論理ユニット設定 +// Set the logical unit // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::SetUnit(int no, Disk *dev) @@ -6216,7 +6229,7 @@ void FASTCALL SASIDEV::SetUnit(int no, Disk *dev) //--------------------------------------------------------------------------- // -// 有効な論理ユニットを持っているか返す +// Check to see if this has a valid logical unit // //--------------------------------------------------------------------------- BOOL FASTCALL SASIDEV::HasUnit() @@ -6236,7 +6249,7 @@ BOOL FASTCALL SASIDEV::HasUnit() //--------------------------------------------------------------------------- // -// 内部データ取得 +// Get internal data // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::GetCTRL(ctrl_t *buffer) @@ -6244,13 +6257,13 @@ void FASTCALL SASIDEV::GetCTRL(ctrl_t *buffer) ASSERT(this); ASSERT(buffer); - // 内部ワークをコピー + // reference the internal structure *buffer = ctrl; } //--------------------------------------------------------------------------- // -// ビジー状態のユニットを取得 +// Get a busy unit // //--------------------------------------------------------------------------- Disk* FASTCALL SASIDEV::GetBusyUnit() @@ -6266,14 +6279,14 @@ Disk* FASTCALL SASIDEV::GetBusyUnit() //--------------------------------------------------------------------------- // -// 実行 +// Run // //--------------------------------------------------------------------------- BUS::phase_t FASTCALL SASIDEV::Process() { ASSERT(this); - // 未接続なら何もしない + // Do nothing if not connected if (ctrl.id < 0 || ctrl.bus == NULL) { return ctrl.phase; } @@ -6284,7 +6297,7 @@ BUS::phase_t FASTCALL SASIDEV::Process() // Reset if (ctrl.bus->GetRST()) { #if defined(DISK_LOG) - Log(Log::Normal, "RESET信号受信"); + Log(Log::Normal, "RESET signal received"); #endif // DISK_LOG // Reset the controller @@ -6295,39 +6308,39 @@ BUS::phase_t FASTCALL SASIDEV::Process() return ctrl.phase; } - // フェーズ処理 + // Phase processing switch (ctrl.phase) { - // バスフリー + // Bus free case BUS::busfree: BusFree(); break; - // セレクション + // Selection case BUS::selection: Selection(); break; - // データアウト(MCI=000) + // Data out (MCI=000) case BUS::dataout: DataOut(); break; - // データイン(MCI=001) + // Data in (MCI=001) case BUS::datain: DataIn(); break; - // コマンド(MCI=010) + // Command (MCI=010) case BUS::command: Command(); break; - // ステータス(MCI=011) + // Status (MCI=011) case BUS::status: Status(); break; - // メッセージイン(MCI=111) + // Msg in (MCI=111) case BUS::msgin: MsgIn(); break; @@ -6367,13 +6380,13 @@ void FASTCALL SASIDEV::BusFree() ctrl.bus->SetIO(FALSE); ctrl.bus->SetBSY(FALSE); - // ステータスとメッセージを初期化 + // Initialize status and message ctrl.status = 0x00; ctrl.message = 0x00; return; } - // セレクションフェーズに移行 + // Move to selection phase if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { Selection(); } @@ -6381,7 +6394,7 @@ void FASTCALL SASIDEV::BusFree() //--------------------------------------------------------------------------- // -// セレクションフェーズ +// Selection phase // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Selection() @@ -6392,31 +6405,31 @@ void FASTCALL SASIDEV::Selection() // Phase change if (ctrl.phase != BUS::selection) { - // IDが一致していなければ無効 + // Invalid if IDs do not match id = 1 << ctrl.id; if ((ctrl.bus->GetDAT() & id) == 0) { return; } - // 有効なユニットが無ければ終了 + // Return if there is no unit if (!HasUnit()) { return; } #if defined(DISK_LOG) Log(Log::Normal, - "セレクションフェーズ ID=%d (デバイスあり)", ctrl.id); + "Selection Phase ID=%d (with device)", ctrl.id); #endif // DISK_LOG // Phase change ctrl.phase = BUS::selection; - // BSYを上げて応答 + // Raiase BSY and respond ctrl.bus->SetBSY(TRUE); return; } - // セレクション完了でコマンドフェーズ移行 + // Command phase shifts when selection is completed if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { Command(); } @@ -6424,7 +6437,7 @@ void FASTCALL SASIDEV::Selection() //--------------------------------------------------------------------------- // -// コマンドフェーズ +// Command phase // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Command() @@ -6440,7 +6453,7 @@ void FASTCALL SASIDEV::Command() if (ctrl.phase != BUS::command) { #if defined(DISK_LOG) - Log(Log::Normal, "コマンドフェーズ"); + Log(Log::Normal, "Command Phase"); #endif // DISK_LOG // Phase Setting @@ -6451,45 +6464,51 @@ void FASTCALL SASIDEV::Command() ctrl.bus->SetCD(TRUE); ctrl.bus->SetIO(FALSE); - // データ転送は6バイトx1ブロック + // Data transfer is 6 bytes x 1 block ctrl.offset = 0; ctrl.length = 6; ctrl.blocks = 1; #ifdef RASCSI - // コマンド受信ハンドシェイク(最初のコマンドで自動で10バイト受信する) + // Command reception handshake (10 bytes are automatically received at the first command) count = ctrl.bus->CommandHandShake(ctrl.buffer); - - // 1バイトも受信できなければステータスフェーズへ移行 + printf("Command received: " ); + for(int i=0; i< count; i++) + { + printf("%02X ", ctrl.buffer[i]); + } + printf("\n"); + + // If no byte can be received move to the status phase if (count == 0) { Error(); return; } - - // 10バイトCDBのチェック + + // Check 10-byte CDB if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { ctrl.length = 10; } - - // 全て受信できなければステータスフェーズへ移行 + + // If not able to receive all, move to the status phase if (count != (int)ctrl.length) { Error(); return; } - + // Command data transfer for (i = 0; i < (int)ctrl.length; i++) { ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; } - - // レングスとブロックをクリア + + // Clear length and block ctrl.length = 0; ctrl.blocks = 0; - + // Execution Phase Execute(); #else - // コマンドを要求 + // Request the command ctrl.bus->SetREQ(TRUE); return; #endif // RASCSI @@ -6520,13 +6539,13 @@ void FASTCALL SASIDEV::Execute() ASSERT(this); #if defined(DISK_LOG) - Log(Log::Normal, "Execution Phase コマンド$%02X", ctrl.cmd[0]); + Log(Log::Normal, "Execution Phase Command %02X", ctrl.cmd[0]); #endif // DISK_LOG // Phase Setting ctrl.phase = BUS::execute; - // データ転送のための初期化 + // Initialization for data transfer ctrl.offset = 0; ctrl.blocks = 1; #ifdef RASCSI @@ -6591,8 +6610,8 @@ void FASTCALL SASIDEV::Execute() return; } - // それ以外は対応していない - Log(Log::Warning, "未対応コマンド $%02X", ctrl.cmd[0]); + // Unsupported command + Log(Log::Warning, "Unsupported command $%02X", ctrl.cmd[0]); CmdInvalid(); } @@ -6614,7 +6633,7 @@ void FASTCALL SASIDEV::Status() if (ctrl.phase != BUS::status) { #ifdef RASCSI - // 最小実行時間 + // Minimum execution time if (ctrl.execstart > 0) { min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi; time = SysTimer::GetTimerLow() - ctrl.execstart; @@ -6628,7 +6647,7 @@ void FASTCALL SASIDEV::Status() #endif // RASCSI #if defined(DISK_LOG) - Log(Log::Normal, "ステータスフェーズ"); + Log(Log::Normal, "Status phase"); #endif // DISK_LOG // Phase Setting @@ -6646,29 +6665,29 @@ void FASTCALL SASIDEV::Status() ctrl.buffer[0] = (BYTE)ctrl.status; #ifndef RASCSI - // ステータスを要求 + // Request status ctrl.bus->SetDAT(ctrl.buffer[0]); ctrl.bus->SetREQ(TRUE); #if defined(DISK_LOG) - Log(Log::Normal, "ステータスフェーズ $%02X", ctrl.status); + Log(Log::Normal, "Status Phase $%02X", ctrl.status); #endif // DISK_LOG #endif // RASCSI return; } #ifdef RASCSI - // 送信 + // Send Send(); #else // Requesting if (ctrl.bus->GetREQ()) { - // イニシエータが受信した + // Initiator received if (ctrl.bus->GetACK()) { SendNext(); } } else { - // イニシエータが次を要求 + // Initiator requests next if (!ctrl.bus->GetACK()) { Send(); } @@ -6700,7 +6719,7 @@ void FASTCALL SASIDEV::MsgIn() ctrl.bus->SetCD(TRUE); ctrl.bus->SetIO(TRUE); - // length, blocksは設定済み + // length, blocks are already set ASSERT(ctrl.length > 0); ASSERT(ctrl.blocks > 0); ctrl.offset = 0; @@ -6718,17 +6737,17 @@ void FASTCALL SASIDEV::MsgIn() } #ifdef RASCSI - // 送信 + //Send Send(); #else // Requesting if (ctrl.bus->GetREQ()) { - // イニシエータが受信した + // Initator received if (ctrl.bus->GetACK()) { SendNext(); } } else { - // イニシエータが次を要求 + // Initiator requests next if (!ctrl.bus->GetACK()) { Send(); } @@ -6755,7 +6774,7 @@ void FASTCALL SASIDEV::DataIn() if (ctrl.phase != BUS::datain) { #ifdef RASCSI - // 最小実行時間 + // Minimum execution time if (ctrl.execstart > 0) { min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi; time = SysTimer::GetTimerLow() - ctrl.execstart; @@ -6766,7 +6785,7 @@ void FASTCALL SASIDEV::DataIn() } #endif // RASCSI - // レングス0なら、ステータスフェーズへ + // If the length is 0, go to the status phase if (ctrl.length == 0) { Status(); return; @@ -6784,33 +6803,33 @@ void FASTCALL SASIDEV::DataIn() ctrl.bus->SetCD(FALSE); ctrl.bus->SetIO(TRUE); - // length, blocksは設定済み + // length, blocks are already set ASSERT(ctrl.length > 0); ASSERT(ctrl.blocks > 0); ctrl.offset = 0; #ifndef RASCSI - // データを設定 + // Assert the DAT signal ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); - // データを要求 + // Request data ctrl.bus->SetREQ(TRUE); #endif // RASCSI return; } #ifdef RASCSI - // 送信 + // Send Send(); #else // Requesting if (ctrl.bus->GetREQ()) { - // イニシエータが受信した + // Initator received if (ctrl.bus->GetACK()) { SendNext(); } } else { - // イニシエータが次を要求 + // Initiator requests next if (!ctrl.bus->GetACK()) { Send(); } @@ -6820,7 +6839,7 @@ void FASTCALL SASIDEV::DataIn() //--------------------------------------------------------------------------- // -// データアウトフェーズ +// Data out phase // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::DataOut() @@ -6837,7 +6856,7 @@ void FASTCALL SASIDEV::DataOut() if (ctrl.phase != BUS::dataout) { #ifdef RASCSI - // 最小実行時間 + // Minimum execution time if (ctrl.execstart > 0) { min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi; time = SysTimer::GetTimerLow() - ctrl.execstart; @@ -6848,14 +6867,14 @@ void FASTCALL SASIDEV::DataOut() } #endif // RASCSI - // レングス0なら、ステータスフェーズへ + // If the length is 0, go to the status phase if (ctrl.length == 0) { Status(); return; } #if defined(DISK_LOG) - Log(Log::Normal, "データアウトフェーズ"); + Log(Log::Normal, "Data out phase"); #endif // DISK_LOG // Phase Setting @@ -6866,20 +6885,20 @@ void FASTCALL SASIDEV::DataOut() ctrl.bus->SetCD(FALSE); ctrl.bus->SetIO(FALSE); - // length, blocksは設定済み + // length, blocks are already calculated ASSERT(ctrl.length > 0); ASSERT(ctrl.blocks > 0); ctrl.offset = 0; #ifndef RASCSI - // データを要求 + // Request data ctrl.bus->SetREQ(TRUE); #endif // RASCSI return; } #ifdef RASCSI - // 受信 + // Receive Receive(); #else // Requesting @@ -6899,7 +6918,7 @@ void FASTCALL SASIDEV::DataOut() //--------------------------------------------------------------------------- // -// 共通エラー +// Error // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Error() @@ -6921,14 +6940,14 @@ void FASTCALL SASIDEV::Error() return; } - // ステータスフェーズ、メッセージインフェーズはバスフリー + // Bus free for status phase and message in phase if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { BusFree(); return; } #if defined(DISK_LOG) - Log(Log::Warning, "エラー(ステータスフェーズへ)"); + Log(Log::Warning, "Error occured (going to status phase)"); #endif // DISK_LOG // Logical Unit @@ -7038,10 +7057,10 @@ void FASTCALL SASIDEV::CmdRequestSense() ASSERT(ctrl.length > 0); #if defined(DISK_LOG) - Log(Log::Normal, "センスキー $%02X", ctrl.buffer[2]); + Log(Log::Normal, "Sense key $%02X", ctrl.buffer[2]); #endif // DISK_LOG - // リードフェーズ + // Read phase DataIn(); } @@ -7147,7 +7166,7 @@ void FASTCALL SASIDEV::CmdRead6() #if defined(DISK_LOG) Log(Log::Normal, - "READ(6)コマンド レコード=%06X ブロック=%d", record, ctrl.blocks); + "READ(6) command record=%06X blocks=%d", record, ctrl.blocks); #endif // DISK_LOG // Command processing on drive @@ -7161,7 +7180,7 @@ void FASTCALL SASIDEV::CmdRead6() // Set next block ctrl.next = record + 1; - // リードフェーズ + // Read phase DataIn(); } @@ -7197,7 +7216,7 @@ void FASTCALL SASIDEV::CmdWrite6() #if defined(DISK_LOG) Log(Log::Normal, - "WRITE(6)コマンド レコード=%06X ブロック=%d", record, ctrl.blocks); + "WRITE(6) command record=%06X blocks=%d", record, ctrl.blocks); #endif // DISK_LOG // Command processing on drive @@ -7211,7 +7230,7 @@ void FASTCALL SASIDEV::CmdWrite6() // Set next block ctrl.next = record + 1; - // ライトフェーズ + // Write phase DataOut(); } @@ -7281,10 +7300,10 @@ void FASTCALL SASIDEV::CmdAssign() return; } - // 4バイトのデータをリクエスト + // 4Request 4 bytes of data ctrl.length = 4; - // ライトフェーズ + // Write phase DataOut(); } @@ -7319,16 +7338,16 @@ void FASTCALL SASIDEV::CmdSpecify() return; } - // 10バイトのデータをリクエスト + // Request 10 bytes of data ctrl.length = 10; - // ライトフェーズ + // Write phase DataOut(); } //--------------------------------------------------------------------------- // -// サポートしていないコマンド +// Unsupported command // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::CmdInvalid() @@ -7338,7 +7357,7 @@ void FASTCALL SASIDEV::CmdInvalid() ASSERT(this); #if defined(DISK_LOG) - Log(Log::Normal, "サポートしていない Command "); + Log(Log::Normal, "Command not supported"); #endif // DISK_LOG // Logical Unit @@ -7360,7 +7379,7 @@ void FASTCALL SASIDEV::CmdInvalid() //--------------------------------------------------------------------------- // -// データ送信 +// Data transmission // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Send() @@ -7375,12 +7394,12 @@ void FASTCALL SASIDEV::Send() ASSERT(ctrl.bus->GetIO()); #ifdef RASCSI - // レングス!=0なら送信 + // Check that the length isn't 0 if (ctrl.length != 0) { len = ctrl.bus->SendHandShake( &ctrl.buffer[ctrl.offset], ctrl.length); - // 全て送信できなければステータスフェーズへ移行 + // If you can not send it all, move on to the status phase if (len != (int)ctrl.length) { Error(); return; @@ -7397,7 +7416,8 @@ void FASTCALL SASIDEV::Send() ctrl.offset++; ctrl.length--; - // ACKアサート直後にSendNextでデータ設定済みならリクエストを上げる + // Immediately after ACK is asserted, if the data + // has been set by SendNext, raise the request if (ctrl.length != 0) { // Signal line operated by the target ctrl.bus->SetREQ(TRUE); @@ -7405,28 +7425,30 @@ void FASTCALL SASIDEV::Send() } #endif // RASCSI - // ブロック減算、リザルト初期化 + // Remove block and initialize the result ctrl.blocks--; result = TRUE; - // データ引き取り後の処理(リード/データインのみ) + // Process after data collection (read/data-in only) if (ctrl.phase == BUS::datain) { if (ctrl.blocks != 0) { - // 次のバッファを設定(offset, lengthをセットすること) + // Set next buffer (set offset, length) result = XferIn(ctrl.buffer); + printf("xfer in: %d \n",result); + #ifndef RASCSI ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); #endif // RASCSI } } - // リザルトFALSEなら、ステータスフェーズへ移行 + // If result FALSE, move to the status phase if (!result) { Error(); return; } - // ブロック!=0なら送信継続 + // Continue sending if block != 0 if (ctrl.blocks != 0){ ASSERT(ctrl.length > 0); ASSERT(ctrl.offset == 0); @@ -7437,7 +7459,7 @@ void FASTCALL SASIDEV::Send() return; } - // 次フェーズに移動 + // Move to the next phase switch (ctrl.phase) { // Message in phase case BUS::msgin: @@ -7451,7 +7473,7 @@ void FASTCALL SASIDEV::Send() Status(); break; - // ステータスフェーズ + // Status phase case BUS::status: // Message in phase ctrl.length = 1; @@ -7470,7 +7492,7 @@ void FASTCALL SASIDEV::Send() #ifndef RASCSI //--------------------------------------------------------------------------- // -// データ送信継続 +// Continue sending data // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::SendNext() @@ -7484,7 +7506,7 @@ void FASTCALL SASIDEV::SendNext() // Signal line operated by the target ctrl.bus->SetREQ(FALSE); - // バッファにデータがあれば先に設定する + // If there is data in the buffer, set it first. if (ctrl.length > 1) { ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset + 1]); } @@ -7494,7 +7516,7 @@ void FASTCALL SASIDEV::SendNext() #ifndef RASCSI //--------------------------------------------------------------------------- // -// データ受信 +// Receive data // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Receive() @@ -7518,13 +7540,13 @@ void FASTCALL SASIDEV::Receive() case BUS::command: ctrl.cmd[ctrl.offset] = data; #if defined(DISK_LOG) - Log(Log::Normal, "コマンドフェーズ $%02X", data); + Log(Log::Normal, "Command phase $%02X", data); #endif // DISK_LOG // Set the length again with the first data (offset 0) if (ctrl.offset == 0) { if (ctrl.cmd[0] >= 0x20 && ctrl.cmd[0] <= 0x7D) { - // 10バイトCDB + // 10 byte CDB ctrl.length = 10; } } @@ -7546,14 +7568,14 @@ void FASTCALL SASIDEV::Receive() #ifdef RASCSI //--------------------------------------------------------------------------- // -// データ受信 +// Receive data // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Receive() #else //--------------------------------------------------------------------------- // -// データ受信継続 +// Continue receiving data // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::ReceiveNext() @@ -7571,13 +7593,13 @@ void FASTCALL SASIDEV::ReceiveNext() ASSERT(!ctrl.bus->GetIO()); #ifdef RASCSI - // レングス!=0なら受信 + // Length != 0 if received if (ctrl.length != 0) { - // 受信 + // Receive len = ctrl.bus->ReceiveHandShake( &ctrl.buffer[ctrl.offset], ctrl.length); - // 全て受信できなければステータスフェーズへ移行 + // If not able to receive all, move to status phase if (len != (int)ctrl.length) { Error(); return; @@ -7594,7 +7616,7 @@ void FASTCALL SASIDEV::ReceiveNext() ctrl.offset++; ctrl.length--; - // レングス!=0なら、再びreqをセット + // If length != 0, set req again if (ctrl.length != 0) { // Signal line operated by the target ctrl.bus->SetREQ(TRUE); @@ -7602,11 +7624,11 @@ void FASTCALL SASIDEV::ReceiveNext() } #endif // RASCSI - // ブロック減算、リザルト初期化 + // Remove the control block and initialize the result ctrl.blocks--; result = TRUE; - // データアウトフェーズの処理 + // Process the data out phase if (ctrl.phase == BUS::dataout) { if (ctrl.blocks == 0) { // End with this buffer @@ -7617,13 +7639,13 @@ void FASTCALL SASIDEV::ReceiveNext() } } - // リザルトFALSEなら、ステータスフェーズへ移行 + // If result is false, move to the status phase if (!result) { Error(); return; } - // ブロック!=0なら受信継続 + // Continue to receive is block != 0 if (ctrl.blocks != 0){ ASSERT(ctrl.length > 0); ASSERT(ctrl.offset == 0); @@ -7634,7 +7656,7 @@ void FASTCALL SASIDEV::ReceiveNext() return; } - // 次フェーズに移動 + // Move to the next phase switch (ctrl.phase) { #ifndef RASCSI // Command phase @@ -7646,7 +7668,7 @@ void FASTCALL SASIDEV::ReceiveNext() // Data out phase case BUS::dataout: - // フラッシュ + // Flush FlushUnit(); // status phase @@ -7662,8 +7684,8 @@ void FASTCALL SASIDEV::ReceiveNext() //--------------------------------------------------------------------------- // -// データ転送IN -// ※offset, lengthを再設定すること +// Data transfer IN +// *Reset offset and length // //--------------------------------------------------------------------------- BOOL FASTCALL SASIDEV::XferIn(BYTE *buf) @@ -7679,23 +7701,30 @@ BOOL FASTCALL SASIDEV::XferIn(BYTE *buf) return FALSE; } - // READ系コマンドに限る + // Limited to read commands switch (ctrl.cmd[0]) { // READ(6) case 0x08: // READ(10) case 0x28: - // ディスクから読み取りを行う + // Read from disk ctrl.length = ctrl.unit[lun]->Read(buf, ctrl.next); ctrl.next++; - // エラーなら、ステータスフェーズへ + printf("XferIn read data from disk: "); + for (int i=0; iModeSelect( ctrl.cmd, ctrl.buffer, ctrl.offset)) { - // MODE SELECTに失敗 + // MODE SELECT failed return FALSE; } break; @@ -7746,45 +7775,45 @@ BOOL FASTCALL SASIDEV::XferOut(BOOL cont) case 0x0a: // WRITE(10) case 0x2a: - // ホストブリッジはSEND MESSAGE10に差し替える + // Replace the host bridge with SEND MESSAGE 10 if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { bridge = (SCSIBR*)ctrl.unit[lun]; if (!bridge->SendMessage10(ctrl.cmd, ctrl.buffer)) { - // 書き込み失敗 + // write failed return FALSE; } - // 正常なら、ワーク設定 + // If normal, work setting ctrl.offset = 0; break; } // WRITE AND VERIFY case 0x2e: - // 書き込みを行う + // Write if (!ctrl.unit[lun]->Write(ctrl.buffer, ctrl.next - 1)) { - // 書き込み失敗 + // Write failed return FALSE; } - // 次のブロックが必要ないならここまで + // If you do not need the next block, end here ctrl.next++; if (!cont) { break; } - // 次のブロックをチェック + // Check the next block ctrl.length = ctrl.unit[lun]->WriteCheck(ctrl.next - 1); if (ctrl.length <= 0) { - // 書き込みできない + // Cannot write return FALSE; } - // 正常なら、ワーク設定 + // If normal, work setting ctrl.offset = 0; break; - // SPECIFY(SASIのみ) + // SPECIFY(SASI only) case 0xc2: break; @@ -7793,13 +7822,13 @@ BOOL FASTCALL SASIDEV::XferOut(BOOL cont) break; } - // バッファ保存に成功した + // Buffer saved successfully return TRUE; } //--------------------------------------------------------------------------- // -// 論理ユニットフラッシュ +// Logical unit flush // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::FlushUnit() @@ -7815,7 +7844,7 @@ void FASTCALL SASIDEV::FlushUnit() return; } - // WRITE系のみ + // WRITE system only switch (ctrl.cmd[0]) { // WRITE(6) case 0x0a: @@ -7823,7 +7852,7 @@ void FASTCALL SASIDEV::FlushUnit() case 0x2a: // WRITE AND VERIFY case 0x2e: - // フラッシュ + // Flush if (!ctrl.unit[lun]->IsCacheWB()) { ctrl.unit[lun]->Flush(); } @@ -7836,16 +7865,72 @@ void FASTCALL SASIDEV::FlushUnit() //--------------------------------------------------------------------------- // -// ログ出力 +// Get the current phase as a string +// +//--------------------------------------------------------------------------- +void SASIDEV::GetPhaseStr(char *str) +{ + switch(this->GetPhase()) + { + case BUS::busfree: + strcpy(str,"busfree "); + break; + case BUS::arbitration: + strcpy(str,"arbitration"); + break; + case BUS::selection: + strcpy(str,"selection "); + break; + case BUS::reselection: + strcpy(str,"reselection"); + break; + case BUS::command: + strcpy(str,"command "); + break; + case BUS::execute: + strcpy(str,"execute "); + break; + case BUS::datain: + strcpy(str,"datain "); + break; + case BUS::dataout: + strcpy(str,"dataout "); + break; + case BUS::status: + strcpy(str,"status "); + break; + case BUS::msgin: + strcpy(str,"msgin "); + break; + case BUS::msgout: + strcpy(str,"msgout "); + break; + case BUS::reserved: + strcpy(str,"reserved "); + break; + } +} + +//--------------------------------------------------------------------------- +// +// Log output // //--------------------------------------------------------------------------- void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...) { #if !defined(BAREMETAL) char buffer[0x200]; + char buffer2[0x250]; + char buffer3[0x250]; + char phase_str[20]; va_list args; va_start(args, format); + if(this->GetID() != 6) + { + return; + } + #ifdef RASCSI #ifndef DISK_LOG if (level == Log::Warning) { @@ -7854,15 +7939,35 @@ void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...) #endif // DISK_LOG #endif // RASCSI - // フォーマット + // format vsprintf(buffer, format, args); - // 可変長引数終了 + // end variable length argument va_end(args); - // ログ出力 + // Add the date/timestamp + // current date/time based on current system + time_t now = time(0); + // convert now to string form + char* dt = ctime(&now); + + + strcpy(buffer2, "["); + strcat(buffer2, dt); + // Get rid of the carriage return + buffer2[strlen(buffer2)-1] = '\0'; + strcat(buffer2, "] "); + + // Get the phase + this->GetPhaseStr(phase_str); + sprintf(buffer3, "[%d][%s] ", this->GetID(), phase_str); + strcat(buffer2,buffer3); + strcat(buffer2, buffer); + + + // Log output #ifdef RASCSI - printf("%s\n", buffer); + printf("%s\n", buffer2); #else host->GetVM()->GetLog()->Format(level, host, buffer); #endif // RASCSI @@ -8259,10 +8364,11 @@ void FASTCALL SCSIDEV::Execute() case 0xc2: CmdInvalid(); return; + } // No other support - Log(Log::Normal, "未対応コマンド $%02X", ctrl.cmd[0]); + Log(Log::Normal, "Unsupported command received: $%02X", ctrl.cmd[0]); CmdInvalid(); } @@ -8480,6 +8586,13 @@ void FASTCALL SCSIDEV::CmdModeSense() Log(Log::Normal, "MODE SENSE Command "); #endif // DISK_LOG + printf("Received a Mode Sense command. Contents...."); + for(int i=0; i<10; i++) + { + printf("%08X ", ctrl.cmd[i]); + } + printf("\n"); + // Logical Unit lun = (ctrl.cmd[1] >> 5) & 0x07; if (!ctrl.unit[lun]) { diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h index 40cb35e..69dc47a 100644 --- a/src/raspberrypi/disk.h +++ b/src/raspberrypi/disk.h @@ -920,6 +920,9 @@ public: // Other BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} // Get the phase + + void FASTCALL GetPhaseStr(char *str); + int FASTCALL GetID() {return ctrl.id;} // Get the ID void FASTCALL GetCTRL(ctrl_t *buffer); From 6fd6fdcc05cf7584cb818584b8bc2064dc7f3192 Mon Sep 17 00:00:00 2001 From: akuker Date: Tue, 7 Jul 2020 14:16:02 -0500 Subject: [PATCH 02/16] Failed attempt at monitoring the SCSI traffic. --- src/raspberrypi/Makefile | 34 +++- src/raspberrypi/disk.cpp | 346 ++++++++++++++++++++++++++++++------ src/raspberrypi/disk.h | 177 ++++++++++++++++++ src/raspberrypi/gpiobus.cpp | 106 +++++++++-- src/raspberrypi/rascsi.cpp | 14 +- 5 files changed, 602 insertions(+), 75 deletions(-) diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index f2adee5..96ea2bc 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -1,8 +1,13 @@ +.DEFAULT_GOAL: all + CC = gcc -CFLAGS = -DDISK_LOG -O0 -g -Wall CXX = g++ + +CFLAGS = -DDISK_LOG -O0 -g -Wall CXXFLAGS = -DDISK_LOG -O0 -g -Wall + + # If its not specified, build for STANDARD configuration CONNECT_TYPE ?= STANDARD @@ -15,9 +20,13 @@ RASCSI = rascsi RASCTL = rasctl RASDUMP = rasdump SASIDUMP = sasidump +SCSIMON = scsimon +#BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON) +# Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed +# for my specific use case. If you need them - add them back in! +BIN_ALL = $(RASCSI) $(RASCTL) $(SCSIMON) -BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) SRC_RASCSI = \ rascsi.cpp \ @@ -46,16 +55,29 @@ SRC_SASIDUMP = \ filepath.cpp \ fileio.cpp +SRC_SCSIMON = \ + scsimon.cpp \ + scsi.cpp \ + disk.cpp \ + gpiobus.cpp \ + ctapdriver.cpp \ + cfilesystem.cpp \ + filepath.cpp \ + fileio.cpp \ + scsimondev.cpp + OBJ_RASCSI := $(SRC_RASCSI:%.cpp=%.o) OBJ_RASCTL := $(SRC_RASCTL:%.cpp=%.o) OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=%.o) OBJ_SASIDUMP := $(SRC_SASIDUMP:%.cpp=%.o) -OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) +OBJ_SCSIMON := $(SRC_SCSIMON:%.cpp=%.o) +OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON) %.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ ALL: $(BIN_ALL) +all: $(BIN_ALL) $(RASCSI): $(OBJ_RASCSI) $(CXX) -o $@ $(OBJ_RASCSI) -lpthread @@ -69,8 +91,14 @@ $(RASDUMP): $(OBJ_RASDUMP) $(SASIDUMP): $(OBJ_SASIDUMP) $(CXX) -o $@ $(OBJ_SASIDUMP) +$(SCSIMON): $(OBJ_SCSIMON) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ_SCSIMON) -lpthread + clean: rm -f $(OBJ_ALL) $(BIN_ALL) run: sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK.HDA -ID6 /home/pi/marathon.iso + +.PHONY: Debug +Debug: scsimon diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index 217e6d1..23678f6 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -4534,6 +4534,248 @@ void FASTCALL SCSICD::GetBuf( ASSERT(this); } + + +//=========================================================================== +// +// SCSI Monitor Device +// This will monitor all of the traffic to this SCSI ID and dump it to +// STDOUT +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// Constructor +// +//--------------------------------------------------------------------------- +MONITORHD::MONITORHD() : Disk() +{ + // SCSI Monitor + disk.id = MAKEID('S', 'M', 'O', 'N'); +} + +//--------------------------------------------------------------------------- +// +// Reset +// +//--------------------------------------------------------------------------- +void FASTCALL MONITORHD::Reset() +{ +// // Unlock and release attention +// disk.lock = FALSE; +// disk.attn = FALSE; +// +// // No reset, clear code +// disk.reset = FALSE; +// disk.code = 0x00; +} + +//--------------------------------------------------------------------------- +// +// Open +// +//--------------------------------------------------------------------------- +BOOL FASTCALL MONITORHD::Open(const Filepath& path, BOOL /*attn*/) +{ +// Fileio fio; +// off64_t size; +// +// ASSERT(this); +// ASSERT(!disk.ready); +// +// // read open required +// if (!fio.Open(path, Fileio::ReadOnly)) { +// return FALSE; +// } +// +// // Get file size +// size = fio.GetFileSize(); +// fio.Close(); +// +// // Must be 512 bytes +// if (size & 0x1ff) { +// return FALSE; +// } +// +// // 10MB or more +// if (size < 0x9f5400) { +// return FALSE; +// } +// // 2TB according to xm6i +// // There is a similar one in wxw/wxw_cfg.cpp +// if (size > 2LL * 1024 * 1024 * 1024 * 1024) { +// return FALSE; +// } +// +// // sector size and number of blocks +// disk.size = 9; +// disk.blocks = (DWORD)(size >> 9); +// +// // Call base class +// return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL MONITORHD::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ +//////// char vendor[32]; +//////// char product[32]; +//////// char rev[32]; + int size = 0; +//////// +//////// ASSERT(this); +//////// ASSERT(cdb); +//////// ASSERT(buf); +//////// ASSERT(cdb[0] == 0x12); +//////// +//////// // EVPD check +//////// if (cdb[1] & 0x01) { +//////// disk.code = DISK_INVALIDCDB; +//////// return 0; +//////// } +//////// +//////// // Ready check (Error if no image file) +//////// if (!disk.ready) { +//////// disk.code = DISK_NOTREADY; +//////// return 0; +//////// } +//////// +//////// // Basic data +//////// // buf[0] ... Direct Access Device +//////// // buf[2] ... SCSI-2 compliant command system +//////// // buf[3] ... SCSI-2 compliant Inquiry response +//////// // buf[4] ... Inquiry additional data +//////// memset(buf, 0, 8); +//////// +//////// // SCSI-2 p.104 4.4.3 Incorrect logical unit handling +//////// if (((cdb[1] >> 5) & 0x07) != disk.lun) { +//////// buf[0] = 0x7f; +//////// } +//////// +//////// buf[2] = 0x02; +//////// buf[3] = 0x02; +//////// buf[4] = 122 + 3; // Value close to real HDD +//////// +//////// // Fill with blanks +//////// memset(&buf[8], 0x20, buf[4] - 3); +//////// +//////// // Determine vendor name/product name +//////// sprintf(vendor, BENDER_SIGNATURE); +//////// size = disk.blocks >> 11; +//////// if (size < 300) +//////// sprintf(product, "PRODRIVE LPS%dS", size); +//////// else if (size < 600) +//////// sprintf(product, "MAVERICK%dS", size); +//////// else if (size < 800) +//////// sprintf(product, "LIGHTNING%dS", size); +//////// else if (size < 1000) +//////// sprintf(product, "TRAILBRAZER%dS", size); +//////// else if (size < 2000) +//////// sprintf(product, "FIREBALL%dS", size); +//////// else +//////// sprintf(product, "FBSE%d.%dS", size / 1000, (size % 1000) / 100); +//////// +//////// // Vendor name +//////// memcpy(&buf[8], vendor, strlen(vendor)); +//////// +//////// // Product name +//////// memcpy(&buf[16], product, strlen(product)); +//////// +//////// // Revision +//////// sprintf(rev, "0%01d%01d%01d", +//////// (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); +//////// memcpy(&buf[32], rev, 4); +//////// +//////// // Size of data that can be returned +//////// size = (buf[4] + 5); +//////// +//////// // Limit if the other buffer is small +//////// if (size > (int)cdb[4]) { +//////// size = (int)cdb[4]; +//////// } +//////// +//////// // Success +//////// disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// *Not affected by disk.code +// +//--------------------------------------------------------------------------- +BOOL FASTCALL MONITORHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ +// int page; +// int size; +// +// ASSERT(this); +// ASSERT(buf); +// ASSERT(length >= 0); +// +// // PF +// if (cdb[1] & 0x10) { +// // Mode Parameter header +// if (length >= 12) { +// // Check the block length bytes +// size = 1 << disk.size; +// if (buf[9] != (BYTE)(size >> 16) || +// buf[10] != (BYTE)(size >> 8) || +// buf[11] != (BYTE)size) { +// // currently does not allow changing sector length +// disk.code = DISK_INVALIDPRM; +// return FALSE; +// } +// buf += 12; +// length -= 12; +// } +// +// // Parsing the page +// while (length > 0) { +// // Get page +// page = buf[0]; +// +// switch (page) { +// // format device +// case 0x03: +// // check the number of bytes in the physical sector +// size = 1 << disk.size; +// if (buf[0xc] != (BYTE)(size >> 8) || +// buf[0xd] != (BYTE)size) { +// // currently does not allow changing sector length +// disk.code = DISK_INVALIDPRM; +// return FALSE; +// } +// break; +// +// // Other page +// default: +// break; +// } +// +// // Advance to the next page +// size = buf[1] + 2; +// length -= size; +// buf += size; +// } +// } +// +// // Do not generate an error for the time being (MINIX) +// disk.code = DISK_NOERROR; + + return TRUE; +} + + + + //=========================================================================== // // SCSI Host Bridge @@ -6294,19 +6536,20 @@ BUS::phase_t FASTCALL SASIDEV::Process() // Get bus information ctrl.bus->Aquire(); - // Reset - if (ctrl.bus->GetRST()) { -#if defined(DISK_LOG) - Log(Log::Normal, "RESET signal received"); -#endif // DISK_LOG - - // Reset the controller - Reset(); - - // Reset the bus - ctrl.bus->Reset(); - return ctrl.phase; - } + // For the monitor tool, we shouldn't need to reset. We're just logging information +//////// // Reset +//////// if (ctrl.bus->GetRST()) { +////////#if defined(DISK_LOG) +//////// Log(Log::Normal, "RESET signal received"); +////////#endif // DISK_LOG +//////// +//////// // Reset the controller +//////// Reset(); +//////// +//////// // Reset the bus +//////// ctrl.bus->Reset(); +//////// return ctrl.phase; +//////// } // Phase processing switch (ctrl.phase) { @@ -6373,12 +6616,12 @@ void FASTCALL SASIDEV::BusFree() // Phase Setting ctrl.phase = BUS::busfree; - // 信号線 - ctrl.bus->SetREQ(FALSE); - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(FALSE); - ctrl.bus->SetIO(FALSE); - ctrl.bus->SetBSY(FALSE); +// // Set Signal lines +// ctrl.bus->SetREQ(FALSE); +// ctrl.bus->SetMSG(FALSE); +// ctrl.bus->SetCD(FALSE); +// ctrl.bus->SetIO(FALSE); +// ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -6459,10 +6702,10 @@ void FASTCALL SASIDEV::Command() // Phase Setting ctrl.phase = BUS::command; - // Signal line operated by the target - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(TRUE); - ctrl.bus->SetIO(FALSE); +// // Signal line operated by the target +// ctrl.bus->SetMSG(FALSE); +// ctrl.bus->SetCD(TRUE); +// ctrl.bus->SetIO(FALSE); // Data transfer is 6 bytes x 1 block ctrl.offset = 0; @@ -6653,10 +6896,10 @@ void FASTCALL SASIDEV::Status() // Phase Setting ctrl.phase = BUS::status; - // Signal line operated by the target - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(TRUE); - ctrl.bus->SetIO(TRUE); +//////// // Signal line operated by the target +//////// ctrl.bus->SetMSG(FALSE); +//////// ctrl.bus->SetCD(TRUE); +//////// ctrl.bus->SetIO(TRUE); // Data transfer is 1 byte x 1 block ctrl.offset = 0; @@ -6666,8 +6909,8 @@ void FASTCALL SASIDEV::Status() #ifndef RASCSI // Request status - ctrl.bus->SetDAT(ctrl.buffer[0]); - ctrl.bus->SetREQ(TRUE); +// ctrl.bus->SetDAT(ctrl.buffer[0]); +// ctrl.bus->SetREQ(TRUE); #if defined(DISK_LOG) Log(Log::Normal, "Status Phase $%02X", ctrl.status); @@ -6714,10 +6957,10 @@ void FASTCALL SASIDEV::MsgIn() // Phase Setting ctrl.phase = BUS::msgin; - // Signal line operated by the target - ctrl.bus->SetMSG(TRUE); - ctrl.bus->SetCD(TRUE); - ctrl.bus->SetIO(TRUE); +////////// // Signal line operated by the target +////////// ctrl.bus->SetMSG(TRUE); +////////// ctrl.bus->SetCD(TRUE); +////////// ctrl.bus->SetIO(TRUE); // length, blocks are already set ASSERT(ctrl.length > 0); @@ -6798,10 +7041,10 @@ void FASTCALL SASIDEV::DataIn() // Phase Setting ctrl.phase = BUS::datain; - // Signal line operated by the target - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(FALSE); - ctrl.bus->SetIO(TRUE); +//////// // Signal line operated by the target +//////// ctrl.bus->SetMSG(FALSE); +//////// ctrl.bus->SetCD(FALSE); +//////// ctrl.bus->SetIO(TRUE); // length, blocks are already set ASSERT(ctrl.length > 0); @@ -6880,10 +7123,10 @@ void FASTCALL SASIDEV::DataOut() // Phase Setting ctrl.phase = BUS::dataout; - // Signal line operated by the target - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(FALSE); - ctrl.bus->SetIO(FALSE); +//////// // Signal line operated by the target +//////// ctrl.bus->SetMSG(FALSE); +//////// ctrl.bus->SetCD(FALSE); +//////// ctrl.bus->SetIO(FALSE); // length, blocks are already calculated ASSERT(ctrl.length > 0); @@ -8026,6 +8269,7 @@ void FASTCALL SCSIDEV::Reset() BUS::phase_t FASTCALL SCSIDEV::Process() { ASSERT(this); + printf("SCSIDEV::Process() %d\n", ctrl.id); // Do nothing if not connected if (ctrl.id < 0 || ctrl.bus == NULL) { @@ -8125,12 +8369,12 @@ void FASTCALL SCSIDEV::BusFree() // Phase setting ctrl.phase = BUS::busfree; - // Signal line - ctrl.bus->SetREQ(FALSE); - ctrl.bus->SetMSG(FALSE); - ctrl.bus->SetCD(FALSE); - ctrl.bus->SetIO(FALSE); - ctrl.bus->SetBSY(FALSE); +//////// // Signal line +//////// ctrl.bus->SetREQ(FALSE); +//////// ctrl.bus->SetMSG(FALSE); +//////// ctrl.bus->SetCD(FALSE); +//////// ctrl.bus->SetIO(FALSE); +//////// ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -8399,10 +8643,10 @@ void FASTCALL SCSIDEV::MsgOut() // Phase Setting ctrl.phase = BUS::msgout; - // Signal line operated by the target - ctrl.bus->SetMSG(TRUE); - ctrl.bus->SetCD(TRUE); - ctrl.bus->SetIO(FALSE); +//////// // Signal line operated by the target +//////// ctrl.bus->SetMSG(TRUE); +//////// ctrl.bus->SetCD(TRUE); +//////// ctrl.bus->SetIO(FALSE); // Data transfer is 1 byte x 1 block ctrl.offset = 0; diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h index 69dc47a..d6dff79 100644 --- a/src/raspberrypi/disk.h +++ b/src/raspberrypi/disk.h @@ -229,6 +229,8 @@ public: // NULL check BOOL FASTCALL IsSASI() const; // SASI Check + virtual BOOL FASTCALL IsMonitor() const {return FALSE;} + // Check if this is a monitor device // Media Operations virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); @@ -399,6 +401,26 @@ public: // MODE SELECT(6) command }; +class MONITORHD : public Disk +{ +public: + // Basic Functions + MONITORHD(); + // Constructor + void FASTCALL Reset(); + // Reset + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // Open + + // commands + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY command + BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT(6) command + BOOL FASTCALL IsMonitor() const {return TRUE;} +}; + //=========================================================================== // // SCSI hard disk (PC-9801-55 NEC genuine /Anex86/T98Next) @@ -701,6 +723,31 @@ private: #endif }; + +//////////=========================================================================== +////////// +////////// SCSI Monitor Device (Interits SCSI device) +////////// +//////////=========================================================================== +////////class SCSIMONDEV : public Disk +////////{ +////////public: +//////// // Basic Functions +//////// SCSIMONDEV(); +//////// // Constructor +//////// void FASTCALL Reset(); +//////// // Reset +//////// BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); +//////// // Open +//////// +//////// // commands +//////// int FASTCALL Inquiry( +//////// const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); +//////// // INQUIRY command +//////// BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); +//////// // MODE SELECT(6) command +////////}; + //=========================================================================== // // SCSI Host Bridge @@ -933,6 +980,8 @@ public: // SASI Check virtual BOOL FASTCALL IsSCSI() const {return FALSE;} // SCSI check + virtual BOOL FASTCALL IsMonitor() const {return FALSE;} + // Check to see if this is a monitor device Disk* FASTCALL GetBusyUnit(); // Get the busy unit @@ -1141,4 +1190,132 @@ private: // Internal data }; +//=========================================================================== +// +// SCSI Device (Interits SASI device) +// +//=========================================================================== +class SCSIMONDEV : public SASIDEV +{ +public: + // Internal data definition + typedef struct { + // Synchronous transfer + BOOL syncenable; // Synchronous transfer possible + int syncperiod; // Synchronous transfer period + int syncoffset; // Synchronous transfer offset + int syncack; // Number of synchronous transfer ACKs + + // ATN message + BOOL atnmsg; + int msc; + BYTE msb[256]; + } scsi_t; + + BOOL FASTCALL IsMonitor() const {return TRUE;} + +public: + // Basic Functions +#ifdef RASCSI + SCSIMONDEV(); +#else + SCSIMONDEV(Device *dev); +#endif // RASCSI + // Constructor + + void FASTCALL Reset(); + // Device Reset + + // 外部API + BUS::phase_t FASTCALL Process(); + // Run + + void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } + // Synchronouse transfer enable setting + + // Other + BOOL FASTCALL IsSASI() const {return FALSE;} + // SASI Check + BOOL FASTCALL IsSCSI() const {return TRUE;} + // SCSI check + +private: + // Phase + void FASTCALL BusFree(); + // Bus free phase + void FASTCALL Selection(); + // Selection phase + void FASTCALL Execute(); + // Execution phase + void FASTCALL MsgOut(); + // Message out phase + void FASTCALL Error(); + // Common erorr handling + + // commands + void FASTCALL CmdInquiry(); + // INQUIRY command + void FASTCALL CmdModeSelect(); + // MODE SELECT command + void FASTCALL CmdModeSense(); + // MODE SENSE command + void FASTCALL CmdStartStop(); + // START STOP UNIT command + void FASTCALL CmdSendDiag(); + // SEND DIAGNOSTIC command + void FASTCALL CmdRemoval(); + // PREVENT/ALLOW MEDIUM REMOVAL command + void FASTCALL CmdReadCapacity(); + // READ CAPACITY command + void FASTCALL CmdRead10(); + // READ(10) command + void FASTCALL CmdWrite10(); + // WRITE(10) command + void FASTCALL CmdSeek10(); + // SEEK(10) command + void FASTCALL CmdVerify(); + // VERIFY command + void FASTCALL CmdSynchronizeCache(); + // SYNCHRONIZE CACHE command + void FASTCALL CmdReadDefectData10(); + // READ DEFECT DATA(10) command + void FASTCALL CmdReadToc(); + // READ TOC command + void FASTCALL CmdPlayAudio10(); + // PLAY AUDIO(10) command + void FASTCALL CmdPlayAudioMSF(); + // PLAY AUDIO MSF command + void FASTCALL CmdPlayAudioTrack(); + // PLAY AUDIO TRACK INDEX command + void FASTCALL CmdModeSelect10(); + // MODE SELECT(10) command + void FASTCALL CmdModeSense10(); + // MODE SENSE(10) command + void FASTCALL CmdGetMessage10(); + // GET MESSAGE(10) command + void FASTCALL CmdSendMessage10(); + // SEND MESSAGE(10) command + + // データ転送 + void FASTCALL Send(); + // Send data +#ifndef RASCSI + void FASTCALL SendNext(); + // Continue sending data +#endif // RASCSI + void FASTCALL Receive(); + // Receive data +#ifndef RASCSI + void FASTCALL ReceiveNext(); + // Continue receiving data +#endif // RASCSI + BOOL FASTCALL XferMsg(DWORD msg); + // Data transfer message + + scsi_t scsi; + // Internal data +}; + + + #endif // disk_h diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp index e0b8386..a8cd7a3 100644 --- a/src/raspberrypi/gpiobus.cpp +++ b/src/raspberrypi/gpiobus.cpp @@ -65,7 +65,7 @@ DWORD bcm_host_get_peripheral_address(void) char buf[1024]; size_t len = sizeof(buf); DWORD address; - + if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf) { // Failed to get CPU model || Not BCM2835 @@ -88,7 +88,7 @@ extern uint32_t RPi_IO_Base_Addr; // Core frequency extern uint32_t RPi_Core_Freq; -#ifdef USE_SEL_EVENT_ENABLE +#ifdef USE_SEL_EVENT_ENABLE //--------------------------------------------------------------------------- // // Interrupt control function @@ -169,6 +169,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode) // Open /dev/mem fd = open("/dev/mem", O_RDWR | O_SYNC); if (fd == -1) { + printf("Error: Unable to open /dev/mem. Are you running as root?\n"); return FALSE; } @@ -274,6 +275,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode) PinConfig(PIN_DTD, GPIO_OUTPUT); // Set the ENABLE signal + // This is used to show that the application is running PinSetSignal(PIN_ENB, ENB_OFF); PinConfig(PIN_ENB, GPIO_OUTPUT); @@ -373,6 +375,7 @@ BOOL FASTCALL GPIOBUS::Init(mode_e mode) MakeTable(); // Finally, enable ENABLE + // Show the user that this app is running SetControl(PIN_ENB, ENB_ON); return TRUE; @@ -518,7 +521,7 @@ DWORD FASTCALL GPIOBUS::Aquire() // Invert if negative logic (internal processing is unified to positive logic) signals = ~signals; #endif // SIGNAL_CONTROL_MODE - + return signals; } @@ -549,9 +552,15 @@ BOOL FASTCALL GPIOBUS::GetBSY() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetBSY(BOOL ast) { - // Set BSY signal - SetSignal(PIN_BSY, ast); - + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET BSY IN MONITOR MODE"); + } + else + { + // Set BSY signal + SetSignal(PIN_BSY, ast); + } if (actmode == TARGET) { if (ast) { // Turn on ACTIVE signal @@ -603,8 +612,14 @@ void FASTCALL GPIOBUS::SetSEL(BOOL ast) SetControl(PIN_ACT, ACT_ON); } - // Set SEL signal - SetSignal(PIN_SEL, ast); + if (actmode != MONITOR) + { + // Set SEL signal + SetSignal(PIN_SEL, ast); + } + else{ + printf("WARNING!!! SOMEONE TRIED TO SET SEL IN MONITOR MODE"); +} } //--------------------------------------------------------------------------- @@ -624,7 +639,14 @@ BOOL FASTCALL GPIOBUS::GetATN() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetATN(BOOL ast) { - SetSignal(PIN_ATN, ast); + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET ATN IN MONITOR MODE"); + } + else + { + SetSignal(PIN_ATN, ast); + } } //--------------------------------------------------------------------------- @@ -644,7 +666,14 @@ BOOL FASTCALL GPIOBUS::GetACK() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetACK(BOOL ast) { + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET ACK IN MONITOR MODE"); + } + else + { SetSignal(PIN_ACK, ast); + } } //--------------------------------------------------------------------------- @@ -664,7 +693,14 @@ BOOL FASTCALL GPIOBUS::GetRST() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetRST(BOOL ast) { + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET RST IN MONITOR MODE"); + } + else + { SetSignal(PIN_RST, ast); + } } //--------------------------------------------------------------------------- @@ -684,7 +720,13 @@ BOOL FASTCALL GPIOBUS::GetMSG() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetMSG(BOOL ast) { - SetSignal(PIN_MSG, ast); + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET MSG IN MONITOR MODE"); + } + else{ + SetSignal(PIN_MSG, ast); + } } //--------------------------------------------------------------------------- @@ -704,7 +746,14 @@ BOOL FASTCALL GPIOBUS::GetCD() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetCD(BOOL ast) { - SetSignal(PIN_CD, ast); + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET CD IN MONITOR MODE"); + } + else + { + SetSignal(PIN_CD, ast); + } } //--------------------------------------------------------------------------- @@ -754,6 +803,21 @@ BOOL FASTCALL GPIOBUS::GetIO() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetIO(BOOL ast) { + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET IO IN MONITOR MODE"); + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } + SetSignal(PIN_IO, ast); if (actmode == TARGET) { @@ -802,6 +866,12 @@ BOOL FASTCALL GPIOBUS::GetREQ() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetREQ(BOOL ast) { + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET REQ IN MONITOR MODE"); + return; + } + SetSignal(PIN_REQ, ast); } @@ -835,6 +905,14 @@ BYTE FASTCALL GPIOBUS::GetDAT() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetDAT(BYTE dat) { + + + if(actmode == MONITOR) + { + printf("WARNING!!! SOMEONE TRIED TO SET Data IN MONITOR MODE"); + return; + } + // Write to port #if SIGNAL_CONTROL_MODE == 0 DWORD fsel; @@ -1152,7 +1230,7 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count) } // Already waiting for REQ assertion - + // Assert the ACK signal SetSignal(PIN_ACK, ON); @@ -1396,7 +1474,7 @@ void FASTCALL GPIOBUS::SetMode(int pin, int mode) gpio[index] = data; gpfsel[index] = data; } - + //--------------------------------------------------------------------------- // // Get input signal value @@ -1406,7 +1484,7 @@ BOOL FASTCALL GPIOBUS::GetSignal(int pin) { return (signals >> pin) & 1; } - + //--------------------------------------------------------------------------- // // Set output signal value diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 4e55f00..c12ac06 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -153,9 +153,9 @@ BOOL Init() // GPIOBUS creation bus = new GPIOBUS(); - + // GPIO Initialization - if (!bus->Init()) { + if (!bus->Init(BUS::TARGET)) { return FALSE; } @@ -206,7 +206,7 @@ void Cleanup() // Cleanup the Bus bus->Cleanup(); - + // Discard the GPIOBUS object delete bus; @@ -306,7 +306,7 @@ void ListDevice(FILE *fp) FPRT(fp, "No device is installed.\n"); return; } - + FPRT(fp, "+----+----+------+-------------------------------------\n"); } @@ -862,7 +862,7 @@ static void *MonThread(void *param) { struct sched_param schedparam; struct sockaddr_in client; - socklen_t len; + socklen_t len; int fd; FILE *fp; char buf[BUFSIZ]; @@ -892,8 +892,8 @@ static void *MonThread(void *param) while (1) { // Wait for connection - memset(&client, 0, sizeof(client)); - len = sizeof(client); + memset(&client, 0, sizeof(client)); + len = sizeof(client); fd = accept(monsocket, (struct sockaddr*)&client, &len); if (fd < 0) { break; From 6815f758368f531ef1ac8c23a3eb2733d0d68508 Mon Sep 17 00:00:00 2001 From: akuker Date: Tue, 7 Jul 2020 14:17:16 -0500 Subject: [PATCH 03/16] Failed attempt at monitoring the SCSI traffic. --- src/raspberrypi/.gitignore | 2 + src/raspberrypi/scsimon.cpp | 1174 ++++++++++++++++++++ src/raspberrypi/scsimondev.cpp | 1902 ++++++++++++++++++++++++++++++++ 3 files changed, 3078 insertions(+) create mode 100644 src/raspberrypi/.gitignore create mode 100644 src/raspberrypi/scsimon.cpp create mode 100644 src/raspberrypi/scsimondev.cpp diff --git a/src/raspberrypi/.gitignore b/src/raspberrypi/.gitignore new file mode 100644 index 0000000..02c03f1 --- /dev/null +++ b/src/raspberrypi/.gitignore @@ -0,0 +1,2 @@ +*.o +*.bak diff --git a/src/raspberrypi/scsimon.cpp b/src/raspberrypi/scsimon.cpp new file mode 100644 index 0000000..3bdf95b --- /dev/null +++ b/src/raspberrypi/scsimon.cpp @@ -0,0 +1,1174 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2020 GIMONS +// [ RaSCSI main ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "filepath.h" +#include "fileio.h" +#include "disk.h" +#include "gpiobus.h" + +//--------------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------------- +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 +FATFS fatfs; // FatFS +#else +int monsocket; // Monitor Socket +pthread_t monthread; // Monitor Thread +static void *MonThread(void *param); +#endif // BAREMETAL + +#ifndef BAREMETAL +//--------------------------------------------------------------------------- +// +// Signal Processing +// +//--------------------------------------------------------------------------- +void KillHandler(int sig) +{ + // Stop instruction + running = FALSE; +} +#endif // BAREMETAL + +//--------------------------------------------------------------------------- +// +// Banner Output +// +//--------------------------------------------------------------------------- +void Banner(int argc, char* argv[]) +{ + FPRT(stdout,"SCSI Target Emulator RaSCSI(*^..^*) "); + FPRT(stdout,"version %01d.%01d%01d(%s, %s)\n", + (int)((VERSION >> 8) & 0xf), + (int)((VERSION >> 4) & 0xf), + (int)((VERSION ) & 0xf), + __DATE__, + __TIME__); + FPRT(stdout,"Powered by XM6 TypeG Technology / "); + FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n"); + FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); + + if (argc > 1 && strcmp(argv[1], "-h") == 0) { + FPRT(stdout,"\n"); + FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); + FPRT(stdout," n is SCSI identification number(0-7).\n"); + FPRT(stdout," FILE is disk image file.\n\n"); + FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]); + FPRT(stdout," n is X68000 SASI HD number(0-15).\n"); + FPRT(stdout," FILE is disk image file.\n\n"); + FPRT(stdout," Image type is detected based on file extension.\n"); + FPRT(stdout," hdf : SASI HD image(XM6 SASI HD image)\n"); + FPRT(stdout," hds : SCSI HD image(XM6 SCSI HD image)\n"); + FPRT(stdout," hdn : SCSI HD image(NEC GENUINE)\n"); + FPRT(stdout," hdi : SCSI HD image(Anex86 HD image)\n"); + FPRT(stdout," nhd : SCSI HD image(T98Next HD image)\n"); + FPRT(stdout," hda : SCSI HD image(APPLE GENUINE)\n"); + FPRT(stdout," mos : SCSI MO image(XM6 SCSI MO image)\n"); + FPRT(stdout," iso : SCSI CD image(ISO 9660 image)\n"); + +#ifndef BAREMETAL + exit(0); +#endif // BAREMETAL + } +} + +//--------------------------------------------------------------------------- +// +// Initialization +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + int i; + +#ifndef BAREMETAL + struct sockaddr_in server; + int yes; + + // Create socket for monitor + monsocket = socket(PF_INET, SOCK_STREAM, 0); + memset(&server, 0, sizeof(server)); + server.sin_family = PF_INET; + server.sin_port = htons(6868); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + // allow address reuse + yes = 1; + if (setsockopt( + monsocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0){ + return FALSE; + } + + // Bind + if (bind(monsocket, (struct sockaddr *)&server, + sizeof(struct sockaddr_in)) < 0) { + FPRT(stderr, "Error : Already running?\n"); + return FALSE; + } + + // Create Monitor Thread + pthread_create(&monthread, NULL, MonThread, NULL); + + // Interrupt handler settings + if (signal(SIGINT, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGHUP, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGTERM, KillHandler) == SIG_ERR) { + return FALSE; + } +#endif // BAREMETAL + + // GPIOBUS creation + bus = new GPIOBUS(); + + // GPIO Initialization + if (!bus->Init(BUS::MONITOR)) { + return FALSE; + } + + // Bus Reset + bus->Reset(); + bus->SetIO(FALSE); + + // 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; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// Cleanup +// +//--------------------------------------------------------------------------- +void Cleanup() +{ + 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 + // Close the monitor socket + if (monsocket >= 0) { + close(monsocket); + } +#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; + BOOL is_monitor; + + // 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]) { + // Check to see if we need a standard SCSI controller + // or if we are creating a "monitor" controller + is_monitor = FALSE; + for (j = 0; j < UnitNum; j++) + { + unitno = i * UnitNum + j; + if( disk[unitno] && disk[unitno]->IsMonitor()) + { + is_monitor = TRUE; + break; + } + } + if(is_monitor == TRUE) + { + ctrl[i] = new SCSIMONDEV(); + } + else + { + 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]); + } + } + } +} + +//--------------------------------------------------------------------------- +// +// Command Processing +// +//--------------------------------------------------------------------------- +BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file) +{ + Disk *map[CtrlMax * UnitNum]; + int len; + char *ext; + Filepath filepath; + Disk *pUnit; + + // Copy the Unit List + memcpy(map, disk, sizeof(disk)); + + // Check the Controller Number + if (id < 0 || id >= CtrlMax) { + FPRT(fp, "Error : Invalid ID\n"); + return FALSE; + } + + // Check the Unit Number + if (un < 0 || un >= UnitNum) { + FPRT(fp, "Error : Invalid unit number\n"); + return FALSE; + } + + // Connect Command + if (cmd == 0) { // ATTACH + // Distinguish between SASI and SCSI + ext = NULL; + pUnit = NULL; + 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; + } + } + + // Create a new drive, based upon type + switch (type) { + case 0: // HDF + pUnit = new SASIHD(); + break; + case 1: // HDS/HDN/HDI/NHD/HDA + if (ext == NULL) { + break; + } + if (xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0) { + pUnit = new SCSIHD_NEC(); + } else if (xstrcasecmp(ext, "hda") == 0) { + pUnit = new SCSIHD_APPLE(); + } else { + pUnit = new SCSIHD(); + } + break; + case 2: // MO + pUnit = new SCSIMO(); + break; + case 3: // CD + pUnit = new SCSICD(); + break; + case 4: // BRIDGE + pUnit = new SCSIBR(); + break; + case 5: // Logger/Monitor device + pUnit = new MONITORHD(); + break; + default: + FPRT(fp, "Error : Invalid device type\n"); + return FALSE; + } + + // drive checks files + if (type <= 1 || (type <= 3 && xstrcasecmp(file, "-") != 0)) { + // Set the Path + filepath.SetPath(file); + + // Open the file path + if (!pUnit->Open(filepath)) { + FPRT(fp, "Error : File open error [%s]\n", file); + delete pUnit; + return FALSE; + } + } + + // Set the cache to write-through + pUnit->SetCacheWB(FALSE); + + // Replace with the newly created unit + map[id * UnitNum + un] = pUnit; + + // Re-map the controller + MapControler(fp, map); + return TRUE; + } + + // Is this a valid command? + if (cmd > 4) { + FPRT(fp, "Error : Invalid command\n"); + return FALSE; + } + + // Does the controller exist? + if (ctrl[id] == NULL) { + FPRT(fp, "Error : No such device\n"); + return FALSE; + } + + // Does the unit exist? + pUnit = disk[id * 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 * UnitNum + un] = NULL; + + // Re-map the controller + MapControler(fp, map); + return TRUE; + } + + // Valid only for MO or CD + if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O') && + pUnit->GetID() != MAKEID('S', 'C', 'C', 'D')) { + FPRT(fp, "Error : Operation denied(Deveice isn't removable)\n"); + return FALSE; + } + + switch (cmd) { + case 2: // INSERT + // Set the file path + filepath.SetPath(file); + + // Open the file + if (pUnit->Open(filepath)) { + FPRT(fp, "Error : File open error [%s]\n", file); + return FALSE; + } + break; + + case 3: // EJECT + pUnit->Eject(TRUE); + break; + + case 4: // PROTECT + if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O')) { + FPRT(fp, "Error : Operation denied(Deveice isn't MO)\n"); + return FALSE; + } + pUnit->WriteP(!pUnit->IsWriteP()); + break; + default: + ASSERT(FALSE); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// Argument Parsing +// +//--------------------------------------------------------------------------- +BOOL ParseArgument(int argc, char* argv[]) +{ +#ifdef BAREMETAL + FRESULT fr; + FIL fp; + char line[512]; +#else + int i; +#endif // BAREMETAL + int id; + int un; + int type; + char *argID; + char *argPath; + int len; + char *ext; + +#ifdef BAREMETAL + // Mount the SD card + fr = f_mount(&fatfs, "", 1); + if (fr != FR_OK) { + FPRT(stderr, "Error : SD card mount failed.\n"); + return FALSE; + } + + // If there is no setting file, the processing is interrupted + fr = f_open(&fp, "rascsi.ini", FA_READ); + if (fr != FR_OK) { + return FALSE; + } +#else + // If the ID and path are not specified, the processing is interrupted + if (argc < 3) { + return TRUE; + } + i = 1; + argc--; +#endif // BAREMETAL + + // Start Decoding + + while (TRUE) { +#ifdef BAREMETAL + // Get one Line + memset(line, 0x00, sizeof(line)); + if (f_gets(line, sizeof(line) -1, &fp) == NULL) { + break; + } + + // Delete the CR/LF + len = strlen(line); + while (len > 0) { + if (line[len - 1] != '\r' && line[len - 1] != '\n') { + break; + } + line[len - 1] = '\0'; + len--; + } +#else + if (argc < 2) { + break; + } + + argc -= 2; +#endif // BAREMETAL + + // Get the ID and Path +#ifdef BAREMETAL + argID = &line[0]; + argPath = &line[4]; + line[3] = '\0'; + + // Check if the line is an empty string + if (argID[0] == '\0' || argPath[0] == '\0') { + continue; + } +#else + argID = argv[i++]; + argPath = argv[i++]; + + // Check if the argument is invalid + if (argID[0] != '-') { + FPRT(stderr, + "Error : Invalid argument(-IDn or -HDn) [%s]\n", argID); + goto parse_error; + } + argID++; +#endif // BAREMETAL + + if (strlen(argID) == 3 && xstrncasecmp(argID, "id", 2) == 0) { + // ID or ID Format + + // Check that the ID number is valid (0-7) + if (argID[2] < '0' || argID[2] > '7') { + FPRT(stderr, + "Error : Invalid argument(IDn n=0-7) [%c]\n", argID[2]); + goto parse_error; + } + + // The ID unit is good + id = argID[2] - '0'; + un = 0; + } else if (xstrncasecmp(argID, "hd", 2) == 0) { + // HD or HD format + + if (strlen(argID) == 3) { + // Check that the HD number is valid (0-9) + if (argID[2] < '0' || argID[2] > '9') { + FPRT(stderr, + "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); + goto parse_error; + } + + // ID was confirmed + id = (argID[2] - '0') / UnitNum; + un = (argID[2] - '0') % UnitNum; + } else if (strlen(argID) == 4) { + // Check that the HD number is valid (10-15) + if (argID[2] != '1' || argID[3] < '0' || argID[3] > '5') { + FPRT(stderr, + "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); + goto parse_error; + } + + // The ID unit is good - create the id and unit number + id = ((argID[3] - '0') + 10) / UnitNum; + un = ((argID[3] - '0') + 10) % UnitNum; +#ifdef BAREMETAL + argPath++; +#endif // BAREMETAL + } else { + FPRT(stderr, + "Error : Invalid argument(IDn or HDn) [%s]\n", argID); + goto parse_error; + } + } else { + FPRT(stderr, + "Error : Invalid argument(IDn or HDn) [%s]\n", argID); + goto parse_error; + } + + // Skip if there is already an active device + if (disk[id * UnitNum + un] && + !disk[id * UnitNum + un]->IsNULL()) { + continue; + } + + // Initialize device type + type = -1; + + // Check ethernet and host bridge + if (xstrcasecmp(argPath, "bridge") == 0) { + type = 4; + } else if (xstrcasecmp(argPath, "monitor") == 0){ + type = 5; + } else { + // Check the path length + len = strlen(argPath); + if (len < 5) { + FPRT(stderr, + "Error : Invalid argument(File path is short) [%s]\n", + argPath); + goto parse_error; + } + + // Does the file have an extension? + if (argPath[len - 4] != '.') { + FPRT(stderr, + "Error : Invalid argument(No extension) [%s]\n", argPath); + goto parse_error; + } + + // Figure out what the type is + ext = &argPath[len - 3]; + if (xstrcasecmp(ext, "hdf") == 0 || + xstrcasecmp(ext, "hds") == 0 || + xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 || + xstrcasecmp(ext, "hda") == 0) { + // HD(SASI/SCSI) + type = 0; + } else if (strcasecmp(ext, "mos") == 0) { + // MO + type = 2; + } else if (strcasecmp(ext, "iso") == 0) { + // CD + type = 3; + } else { + // Cannot determine the file type + FPRT(stderr, + "Error : Invalid argument(file type) [%s]\n", ext); + goto parse_error; + } + } + + // Execute the command + if (!ProcessCmd(stderr, id, un, 0, type, argPath)) { + goto parse_error; + } + } + +#ifdef BAREMETAL + // Close the configuration file + f_close(&fp); +#endif // BAREMETAL + + // Display the device list + ListDevice(stdout); + + return TRUE; + +parse_error: + +#ifdef BAREMETAL + // Close the configuration file + f_close(&fp); +#endif // BAREMETAL + + return FALSE; +} + +#ifndef BAREMETAL +//--------------------------------------------------------------------------- +// +// Pin the thread to a specific CPU +// +//--------------------------------------------------------------------------- +void FixCpu(int cpu) +{ + cpu_set_t cpuset; + int cpus; + + // Get the number of CPUs + CPU_ZERO(&cpuset); + sched_getaffinity(0, sizeof(cpu_set_t), &cpuset); + cpus = CPU_COUNT(&cpuset); + + // Set the thread affinity + if (cpu < cpus) { + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); + } +} + +//--------------------------------------------------------------------------- +// +// Monitor Thread +// +//--------------------------------------------------------------------------- +static void *MonThread(void *param) +{ + struct sched_param schedparam; + struct sockaddr_in client; + socklen_t len; + int fd; + FILE *fp; + char buf[BUFSIZ]; + char *p; + int i; + char *argv[5]; + int id; + int un; + int cmd; + int type; + char *file; + + // Scheduler Settings + schedparam.sched_priority = 0; + sched_setscheduler(0, SCHED_IDLE, &schedparam); + + // Set the affinity to a specific processor core + FixCpu(2); + + // Wait for the execution to start + while (!running) { + usleep(1); + } + + // Setup the monitor socket to receive commands + listen(monsocket, 1); + + while (1) { + // Wait for connection + memset(&client, 0, sizeof(client)); + len = sizeof(client); + fd = accept(monsocket, (struct sockaddr*)&client, &len); + if (fd < 0) { + break; + } + + // Fetch the command + fp = fdopen(fd, "r+"); + p = fgets(buf, BUFSIZ, fp); + + // Failed to get the command + if (!p) { + goto next; + } + + // Remove the newline character + p[strlen(p) - 1] = 0; + + // List all of the devices + if (xstrncasecmp(p, "list", 4) == 0) { + ListDevice(fp); + goto next; + } + + // Parameter separation + argv[0] = p; + for (i = 1; i < 5; i++) { + // Skip parameter values + while (*p && (*p != ' ')) { + p++; + } + + // Replace spaces with null characters + while (*p && (*p == ' ')) { + *p++ = 0; + } + + // The parameters were lost + if (!*p) { + break; + } + + // Recognized as a parameter + argv[i] = p; + } + + // Failed to get all parameters + if (i < 5) { + goto next; + } + + // ID, unit, command, type, file + id = atoi(argv[0]); + un = atoi(argv[1]); + cmd = atoi(argv[2]); + type = atoi(argv[3]); + file = argv[4]; + + // Wait until we becom idle + while (active) { + usleep(500 * 1000); + } + + // Execute the command + ProcessCmd(fp, id, un, cmd, type, file); + +next: + // Release the connection + fclose(fp); + close(fd); + } + + return NULL; +} +#endif // BAREMETAL + +//--------------------------------------------------------------------------- +// +// Main processing +// +//--------------------------------------------------------------------------- +#ifdef BAREMETAL +extern "C" +int startrascsi(void) +{ + int argc = 0; + char** argv = NULL; +#else +int main(int argc, char* argv[]) +{ +#endif // BAREMETAL + int i; + int ret; + int actid; + DWORD now; + BUS::phase_t phase; + BYTE data; +#ifndef BAREMETAL + struct sched_param schparam; +#endif // BAREMETAL + + // Output the Banner + Banner(argc, argv); + + // Initialize + ret = 0; + if (!Init()) { + ret = EPERM; + goto init_exit; + } + + // Reset + Reset(); + +#ifdef BAREMETAL + // BUSY assert (to hold the host side) + bus->SetBSY(TRUE); +#endif + + // Argument parsing + if (!ParseArgument(argc, argv)) { + ret = EINVAL; + goto err_exit; + } + +#ifdef BAREMETAL + // Release the busy signal + bus->SetBSY(FALSE); +#endif + +#ifndef BAREMETAL + // Set the affinity to a specific processor core + FixCpu(3); + +#ifdef USE_SEL_EVENT_ENABLE + // 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 +#endif // BAREMETAL + + // Start execution + running = TRUE; + + // Main Loop + while (running) { + // Work initialization + 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; + } + +err_exit: + // Cleanup + Cleanup(); + +init_exit: +#if !defined(BAREMETAL) + exit(ret); +#else + return ret; +#endif // BAREMETAL +} diff --git a/src/raspberrypi/scsimondev.cpp b/src/raspberrypi/scsimondev.cpp new file mode 100644 index 0000000..c6185fb --- /dev/null +++ b/src/raspberrypi/scsimondev.cpp @@ -0,0 +1,1902 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2020 GIMONS +// +// XM6i +// Copyright (C) 2010-2015 isaki@NetBSD.org +// Copyright (C) 2010 Y.Sugahara +// +// Imported sava's Anex86/T98Next image and MO format support patch. +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// Comments translated to english by akuker. +// +// [ SCSI Monitor Device] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "filepath.h" +#include "fileio.h" +#ifdef RASCSI +#include "gpiobus.h" +#ifndef BAREMETAL +#include "ctapdriver.h" +#endif // BAREMETAL +#include "cfilesystem.h" +#include "disk.h" +#else +#include "vm.h" +#include "disk.h" +#include "windrv.h" +#include "ctapdriver.h" +#include "mfc_com.h" +#include "mfc_host.h" +#endif // RASCSI + +// Temporary? Trick to make the ID understand that RASCSI is set +#ifndef RASCSI +#define RASCSI +#endif // RASCSI + +//=========================================================================== +// +// SCSI Device +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// Constructor +// +//--------------------------------------------------------------------------- +#ifdef RASCSI +SCSIMONDEV::SCSIMONDEV() : SASIDEV() +#else +SCSIMONDEV::SCSIMONDEV(Device *dev) : SASIDEV(dev) +#endif +{ + // Synchronous transfer work initialization + scsi.syncenable = FALSE; + scsi.syncperiod = 50; + scsi.syncoffset = 0; + scsi.atnmsg = FALSE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); +} + +//--------------------------------------------------------------------------- +// +// Device reset +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Reset() +{ + ASSERT(this); + + // Work initialization + scsi.atnmsg = FALSE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); + + // Base class + SASIDEV::Reset(); +} + +//--------------------------------------------------------------------------- +// +// Process +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL SCSIMONDEV::Process() +{ + ASSERT(this); + printf("SCSIMONDEV::Process() %d\n", ctrl.id); + + // Do nothing if not connected + if (ctrl.id < 0 || ctrl.bus == NULL) { + return ctrl.phase; + } + + // Get bus information + ctrl.bus->Aquire(); + + // Reset + if (ctrl.bus->GetRST()) { +#if defined(DISK_LOG) + Log(Log::Normal, "RESET信号受信"); +#endif // DISK_LOG + + // Reset the controller + Reset(); + + // Reset the bus + ctrl.bus->Reset(); + return ctrl.phase; + } + + // Phase processing + switch (ctrl.phase) { + // Bus free phase + case BUS::busfree: + BusFree(); + break; + + // Selection phase + case BUS::selection: + Selection(); + break; + + // Data out (MCI=000) + case BUS::dataout: + DataOut(); + break; + + // Data in (MCI=001) + case BUS::datain: + DataIn(); + break; + + // Command (MCI=010) + case BUS::command: + Command(); + break; + + // Status (MCI=011) + case BUS::status: + Status(); + break; + + // Message out (MCI=110) + case BUS::msgout: + MsgOut(); + break; + + // Message in (MCI=111) + case BUS::msgin: + MsgIn(); + break; + + // Other + default: + ASSERT(FALSE); + break; + } + + return ctrl.phase; +} + +//--------------------------------------------------------------------------- +// +// Phaes +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// Bus free phase +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::BusFree() +{ + ASSERT(this); + + // Phase change + if (ctrl.phase != BUS::busfree) { + +#if defined(DISK_LOG) + Log(Log::Normal, "Bus free phase"); +#endif // DISK_LOG + + // Phase setting + ctrl.phase = BUS::busfree; + +//////// // Signal line +//////// ctrl.bus->SetREQ(FALSE); +//////// ctrl.bus->SetMSG(FALSE); +//////// ctrl.bus->SetCD(FALSE); +//////// ctrl.bus->SetIO(FALSE); +//////// ctrl.bus->SetBSY(FALSE); + + // Initialize status and message + ctrl.status = 0x00; + ctrl.message = 0x00; + + // Initialize ATN message reception status + scsi.atnmsg = FALSE; + return; + } + + // Move to selection phase + if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { + Selection(); + } +} + +//--------------------------------------------------------------------------- +// +// Selection Phase +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Selection() +{ + DWORD id; + + ASSERT(this); + + // Phase change + if (ctrl.phase != BUS::selection) { + // invalid if IDs do not match + id = 1 << ctrl.id; + if ((ctrl.bus->GetDAT() & id) == 0) { + return; + } + + // End if there is no valid unit + if (!HasUnit()) { + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, + "Selection Phase ID=%d (with device)", ctrl.id); +#endif // DISK_LOG + + // Phase setting + ctrl.phase = BUS::selection; + + // Raise BSY and respond + ctrl.bus->SetBSY(TRUE); + return; + } + + // Selection completed + if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { + // Message out phase if ATN=1, otherwise command phase + if (ctrl.bus->GetATN()) { + MsgOut(); + } else { + Command(); + } + } +} + +//--------------------------------------------------------------------------- +// +// Execution Phase +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Execute() +{ + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "Execution phase command $%02X", ctrl.cmd[0]); +#endif // DISK_LOG + + // Phase Setting + ctrl.phase = BUS::execute; + + // Initialization for data transfer + ctrl.offset = 0; + ctrl.blocks = 1; +#ifdef RASCSI + ctrl.execstart = SysTimer::GetTimerLow(); +#endif // RASCSI + + // Process by command + switch (ctrl.cmd[0]) { + // TEST UNIT READY + case 0x00: + CmdTestUnitReady(); + return; + + // REZERO + case 0x01: + CmdRezero(); + return; + + // REQUEST SENSE + case 0x03: + CmdRequestSense(); + return; + + // FORMAT UNIT + case 0x04: + CmdFormat(); + return; + + // REASSIGN BLOCKS + case 0x07: + CmdReassign(); + return; + + // READ(6) + case 0x08: + CmdRead6(); + return; + + // WRITE(6) + case 0x0a: + CmdWrite6(); + return; + + // SEEK(6) + case 0x0b: + CmdSeek6(); + return; + + // INQUIRY + case 0x12: + CmdInquiry(); + return; + + // MODE SELECT + case 0x15: + CmdModeSelect(); + return; + + // MDOE SENSE + case 0x1a: + CmdModeSense(); + return; + + // START STOP UNIT + case 0x1b: + CmdStartStop(); + return; + + // SEND DIAGNOSTIC + case 0x1d: + CmdSendDiag(); + return; + + // PREVENT/ALLOW MEDIUM REMOVAL + case 0x1e: + CmdRemoval(); + return; + + // READ CAPACITY + case 0x25: + CmdReadCapacity(); + return; + + // READ(10) + case 0x28: + CmdRead10(); + return; + + // WRITE(10) + case 0x2a: + CmdWrite10(); + return; + + // SEEK(10) + case 0x2b: + CmdSeek10(); + return; + + // WRITE and VERIFY + case 0x2e: + CmdWrite10(); + return; + + // VERIFY + case 0x2f: + CmdVerify(); + return; + + // SYNCHRONIZE CACHE + case 0x35: + CmdSynchronizeCache(); + return; + + // READ DEFECT DATA(10) + case 0x37: + CmdReadDefectData10(); + return; + + // READ TOC + case 0x43: + CmdReadToc(); + return; + + // PLAY AUDIO(10) + case 0x45: + CmdPlayAudio10(); + return; + + // PLAY AUDIO MSF + case 0x47: + CmdPlayAudioMSF(); + return; + + // PLAY AUDIO TRACK + case 0x48: + CmdPlayAudioTrack(); + return; + + // MODE SELECT(10) + case 0x55: + CmdModeSelect10(); + return; + + // MDOE SENSE(10) + case 0x5a: + CmdModeSense10(); + return; + + // SPECIFY (SASI only/Suppress warning when using SxSI) + case 0xc2: + CmdInvalid(); + return; + + } + + // No other support + Log(Log::Normal, "Unsupported command received: $%02X", ctrl.cmd[0]); + CmdInvalid(); +} + +//--------------------------------------------------------------------------- +// +// Message out phase +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::MsgOut() +{ + ASSERT(this); + + // Phase change + if (ctrl.phase != BUS::msgout) { + +#if defined(DISK_LOG) + Log(Log::Normal, "Message Out Phase"); +#endif // DISK_LOG + + // Message out phase after selection + // process the IDENTIFY message + if (ctrl.phase == BUS::selection) { + scsi.atnmsg = TRUE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); + } + + // Phase Setting + ctrl.phase = BUS::msgout; + +//////// // Signal line operated by the target +//////// ctrl.bus->SetMSG(TRUE); +//////// ctrl.bus->SetCD(TRUE); +//////// ctrl.bus->SetIO(FALSE); + + // Data transfer is 1 byte x 1 block + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + +#ifndef RASCSI + // Request message + ctrl.bus->SetREQ(TRUE); +#endif // RASCSI + return; + } + +#ifdef RASCSI + // Receive + Receive(); +#else + // Requesting + if (ctrl.bus->GetREQ()) { + // Sent by the initiator + if (ctrl.bus->GetACK()) { + Receive(); + } + } else { + // Request the initator to + if (!ctrl.bus->GetACK()) { + ReceiveNext(); + } + } +#endif // RASCSI +} + +//--------------------------------------------------------------------------- +// +// Common Error Handling +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Error() +{ + ASSERT(this); + + // Get bus information + ctrl.bus->Aquire(); + + // Reset check + if (ctrl.bus->GetRST()) { + // Reset the controller + Reset(); + + // Reset the bus + ctrl.bus->Reset(); + return; + } + + // Bus free for status phase and message in phase + if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { + BusFree(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "Error (to status phase)"); +#endif // DISK_LOG + + // Set status and message(CHECK CONDITION) + ctrl.status = 0x02; + ctrl.message = 0x00; + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// Command +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdInquiry() +{ + Disk *disk; + int lun; + DWORD major; + DWORD minor; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "INQUIRY Command"); +#endif // DISK_LOG + + // Find a valid unit + disk = NULL; + for (lun = 0; lun < UnitMax; lun++) { + if (ctrl.unit[lun]) { + disk = ctrl.unit[lun]; + break; + } + } + + // Processed on the disk side (it is originally processed by the controller) + if (disk) { +#ifdef RASCSI + major = (DWORD)(RASCSI >> 8); + minor = (DWORD)(RASCSI & 0xff); +#else + host->GetVM()->GetVersion(major, minor); +#endif // RASCSI + ctrl.length = + ctrl.unit[lun]->Inquiry(ctrl.cmd, ctrl.buffer, major, minor); + } else { + ctrl.length = 0; + } + + if (ctrl.length <= 0) { + // failure (error) + Error(); + return; + } + + // Add synchronous transfer support information + if (scsi.syncenable) { + ctrl.buffer[7] |= (1 << 4); + } + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdModeSelect() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SELECT Command"); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->SelectCheck(ctrl.cmd); + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Data out phase + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdModeSense() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SENSE Command "); +#endif // DISK_LOG + + printf("Received a Mode Sense command. Contents...."); + for(int i=0; i<10; i++) + { + printf("%08X ", ctrl.cmd[i]); + } + printf("\n"); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->ModeSense(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + if (ctrl.length == 0) { + Log(Log::Warning, + "Not supported MODE SENSE page $%02X", ctrl.cmd[2]); + + // Failure (Error) + Error(); + return; + } + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// START STOP UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdStartStop() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "START STOP UNIT Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->StartStop(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// SEND DIAGNOSTIC +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdSendDiag() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEND DIAGNOSTIC Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->SendDiag(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// PREVENT/ALLOW MEDIUM REMOVAL +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdRemoval() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "PREVENT/ALLOW MEDIUM REMOVAL Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->Removal(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdReadCapacity() +{ + DWORD lun; + int length; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "READ CAPACITY Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + length = ctrl.unit[lun]->ReadCapacity(ctrl.cmd, ctrl.buffer); + ASSERT(length >= 0); + if (length <= 0) { + Error(); + return; + } + + // Length setting + ctrl.length = length; + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// READ(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdRead10() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Receive message if host bridge + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + CmdGetMessage10(); + return; + } + + // Get record number and block number + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "READ(10) command record=%08X block=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // Do not process 0 blocks + if (ctrl.blocks == 0) { + Status(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Set next block + ctrl.next = record + 1; + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// WRITE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdWrite10() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Receive message with host bridge + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + CmdSendMessage10(); + return; + } + + // Get record number and block number + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, + "WRTIE(10) command record=%08X blocks=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // Do not process 0 blocks + if (ctrl.blocks == 0) { + Status(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->WriteCheck(record); + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Set next block + ctrl.next = record + 1; + + // Data out phase + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SEEK(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdSeek10() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEEK(10) Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// VERIFY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdVerify() +{ + DWORD lun; + BOOL status; + DWORD record; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Get record number and block number + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, + "VERIFY command record=%08X blocks=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // Do not process 0 blocks + if (ctrl.blocks == 0) { + Status(); + return; + } + + // if BytChk=0 + if ((ctrl.cmd[1] & 0x02) == 0) { + // Command processing on drive + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); + return; + } + + // Test loading + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Set next block + ctrl.next = record + 1; + + // Data out phase + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SYNCHRONIZE CACHE +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdSynchronizeCache() +{ + DWORD lun; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Make it do something (not implemented)... + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ DEFECT DATA(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdReadDefectData10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "READ DEFECT DATA(10) Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->ReadDefectData10(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + + if (ctrl.length <= 4) { + Error(); + return; + } + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdReadToc() +{ + DWORD lun; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->ReadToc(ctrl.cmd, ctrl.buffer); + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdPlayAudio10() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->PlayAudio(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdPlayAudioMSF() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->PlayAudioMSF(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdPlayAudioTrack() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + status = ctrl.unit[lun]->PlayAudioTrack(ctrl.cmd); + if (!status) { + // Failure (Error) + Error(); + return; + } + + // status phase + Status(); +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT10 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdModeSelect10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SELECT10 Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->SelectCheck10(ctrl.cmd); + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Data out phase + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdModeSense10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SENSE(10) Command "); +#endif // DISK_LOG + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Command processing on drive + ctrl.length = ctrl.unit[lun]->ModeSense10(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + if (ctrl.length == 0) { + Log(Log::Warning, + "Not supported MODE SENSE(10) page $%02X", ctrl.cmd[2]); + + // Failure (Error) + Error(); + return; + } + + // Data-in Phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// GET MESSAGE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdGetMessage10() +{ + DWORD lun; + SCSIBR *bridge; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Error if not a host bridge + if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { + Error(); + return; + } + + // Reallocate buffer (because it is not transfer for each block) + if (ctrl.bufsize < 0x1000000) { + free(ctrl.buffer); + ctrl.bufsize = 0x1000000; + ctrl.buffer = (BYTE *)malloc(ctrl.bufsize); + } + + // Process with drive + bridge = (SCSIBR*)ctrl.unit[lun]; + ctrl.length = bridge->GetMessage10(ctrl.cmd, ctrl.buffer); + + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Set next block + ctrl.blocks = 1; + ctrl.next = 1; + + // Data in phase + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// SEND MESSAGE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::CmdSendMessage10() +{ + DWORD lun; + + ASSERT(this); + + // Logical Unit + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // Error if not a host bridge + if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { + Error(); + return; + } + + // Reallocate buffer (because it is not transfer for each block) + if (ctrl.bufsize < 0x1000000) { + free(ctrl.buffer); + ctrl.bufsize = 0x1000000; + ctrl.buffer = (BYTE *)malloc(ctrl.bufsize); + } + + // Set transfer amount + ctrl.length = ctrl.cmd[6]; + ctrl.length <<= 8; + ctrl.length |= ctrl.cmd[7]; + ctrl.length <<= 8; + ctrl.length |= ctrl.cmd[8]; + + if (ctrl.length <= 0) { + // Failure (Error) + Error(); + return; + } + + // Set next block + ctrl.blocks = 1; + ctrl.next = 1; + + // Light phase + DataOut(); +} + +//=========================================================================== +// +// Data Transfer +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// Send data +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Send() +{ +#ifdef RASCSI + int len; +#endif // RASCSI + BOOL result; + + ASSERT(this); + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(ctrl.bus->GetIO()); + +#ifdef RASCSI + //if Length! = 0, send + if (ctrl.length != 0) { + len = ctrl.bus->SendHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // If you cannot send all, move to status phase + if (len != (int)ctrl.length) { + Error(); + return; + } + + // offset and length + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } +#else + // offset and length + ASSERT(ctrl.length >= 1); + ctrl.offset++; + ctrl.length--; + + // Immediately after ACK is asserted, if the data has been + // set by SendNext, raise the request + if (ctrl.length != 0) { + // Signal line operated by the target + ctrl.bus->SetREQ(TRUE); + return; + } +#endif // RASCSI + + // Block subtraction, result initialization + ctrl.blocks--; + result = TRUE; + + // Processing after data collection (read/data-in only) + if (ctrl.phase == BUS::datain) { + if (ctrl.blocks != 0) { + // // set next buffer (set offset, length) + result = XferIn(ctrl.buffer); +#ifndef RASCSI + ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); +#endif // RASCSI + } + } + + // If result FALSE, move to status phase + if (!result) { + Error(); + return; + } + + // Continue sending if block !=0 + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); +#ifndef RASCSI + // Signal line operated by the target + ctrl.bus->SetREQ(TRUE); +#endif // RASCSI + return; + } + + // Move to next phase + switch (ctrl.phase) { + // Message in phase + case BUS::msgin: + // Completed sending response to extended message of IDENTIFY message + if (scsi.atnmsg) { + // flag off + scsi.atnmsg = FALSE; + + // command phase + Command(); + } else { + // Bus free phase + BusFree(); + } + break; + + // Data-in Phase + case BUS::datain: + // status phase + Status(); + break; + + // status phase + case BUS::status: + // Message in phase + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = (BYTE)ctrl.message; + MsgIn(); + break; + + // Other (impossible) + default: + ASSERT(FALSE); + break; + } +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// Continue data transmission..... +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::SendNext() +{ + ASSERT(this); + + // REQ is up + ASSERT(ctrl.bus->GetREQ()); + ASSERT(ctrl.bus->GetIO()); + + // Signal line operated by the target + ctrl.bus->SetREQ(FALSE); + + // If there is data in the buffer, set it first + if (ctrl.length > 1) { + ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset + 1]); + } +} +#endif // RASCSI + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// Receive data +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Receive() +{ + DWORD data; + + ASSERT(this); + + // Req is up + ASSERT(ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetIO()); + + // Get data + data = (DWORD)ctrl.bus->GetDAT(); + + // Signal line operated by the target + ctrl.bus->SetREQ(FALSE); + + switch (ctrl.phase) { + // Command phase + case BUS::command: + ctrl.cmd[ctrl.offset] = data; +#if defined(DISK_LOG) + Log(Log::Normal, "Command phase $%02X", data); +#endif // DISK_LOG + + // Set the length again with the first data (offset 0) + if (ctrl.offset == 0) { + if (ctrl.cmd[0] >= 0x20) { + // 10バイトCDB + ctrl.length = 10; + } + } + break; + + // Message out phase + case BUS::msgout: + ctrl.message = data; +#if defined(DISK_LOG) + Log(Log::Normal, "Message out phase $%02X", data); +#endif // DISK_LOG + break; + + // Data out phase + case BUS::dataout: + ctrl.buffer[ctrl.offset] = (BYTE)data; + break; + + // Other (impossible) + default: + ASSERT(FALSE); + break; + } +} +#endif // RASCSI + +#ifdef RASCSI +//--------------------------------------------------------------------------- +// +// Receive Data +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::Receive() +#else +//--------------------------------------------------------------------------- +// +// Continue receiving data +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIMONDEV::ReceiveNext() +#endif // RASCSI +{ +#ifdef RASCSI + int len; +#endif // RASCSI + BOOL result; + int i; + BYTE data; + + ASSERT(this); + + // REQ is low + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetIO()); + +#ifdef RASCSI + // Length != 0 if received + if (ctrl.length != 0) { + // Receive + len = ctrl.bus->ReceiveHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // If not able to receive all, move to status phase + if (len != (int)ctrl.length) { + Error(); + return; + } + + // Offset and Length + ctrl.offset += ctrl.length; + ctrl.length = 0;; + return; + } +#else + // Offset and Length + ASSERT(ctrl.length >= 1); + ctrl.offset++; + ctrl.length--; + + // If length!=0, set req again + if (ctrl.length != 0) { + // Signal line operated by the target + ctrl.bus->SetREQ(TRUE); + return; + } +#endif // RASCSI + + // Block subtraction, result initialization + ctrl.blocks--; + result = TRUE; + + // Processing after receiving data (by phase) + switch (ctrl.phase) { + + // Data out phase + case BUS::dataout: + if (ctrl.blocks == 0) { + // End with this buffer + result = XferOut(FALSE); + } else { + // Continue to next buffer (set offset, length) + result = XferOut(TRUE); + } + break; + + // Message out phase + case BUS::msgout: + ctrl.message = ctrl.buffer[0]; + if (!XferMsg(ctrl.message)) { + // Immediately free the bus if message output fails + BusFree(); + return; + } + + // Clear message data in preparation for message-in + ctrl.message = 0x00; + break; + + default: + break; + } + + // If result FALSE, move to status phase + if (!result) { + Error(); + return; + } + + // Continue to receive if block !=0 + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); +#ifndef RASCSI + // Signal line operated by the target + ctrl.bus->SetREQ(TRUE); +#endif // RASCSI + return; + } + + // Move to next phase + switch (ctrl.phase) { + // Command phase + case BUS::command: +#ifdef RASCSI + // Command data transfer + len = 6; + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10 byte CDB + len = 10; + } + for (i = 0; i < len; i++) { + ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; +#if defined(DISK_LOG) + Log(Log::Normal, "Command $%02X", ctrl.cmd[i]); +#endif // DISK_LOG + } +#endif // RASCSI + + // Execution Phase + Execute(); + break; + + // Message out phase + case BUS::msgout: + // Continue message out phase as long as ATN keeps asserting + if (ctrl.bus->GetATN()) { + // Data transfer is 1 byte x 1 block + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; +#ifndef RASCSI + // Request message + ctrl.bus->SetREQ(TRUE); +#endif // RASCSI + return; + } + + // Parsing messages sent by ATN + if (scsi.atnmsg) { + i = 0; + while (i < scsi.msc) { + // Message type + data = scsi.msb[i]; + + // ABORT + if (data == 0x06) { +#if defined(DISK_LOG) + Log(Log::Normal, + "Message code ABORT $%02X", data); +#endif // DISK_LOG + BusFree(); + return; + } + + // BUS DEVICE RESET + if (data == 0x0C) { +#if defined(DISK_LOG) + Log(Log::Normal, + "Message code BUS DEVICE RESET $%02X", data); +#endif // DISK_LOG + scsi.syncoffset = 0; + BusFree(); + return; + } + + // IDENTIFY + if (data >= 0x80) { +#if defined(DISK_LOG) + Log(Log::Normal, + "Message code IDENTIFY $%02X", data); +#endif // DISK_LOG + } + + // Extended Message + if (data == 0x01) { +#if defined(DISK_LOG) + Log(Log::Normal, + "Message code EXTENDED MESSAGE $%02X", data); +#endif // DISK_LOG + + // Check only when synchronous transfer is possible + if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = 0x07; + MsgIn(); + return; + } + + // Transfer period factor (limited to 50 x 4 = 200ns) + scsi.syncperiod = scsi.msb[i + 3]; + if (scsi.syncperiod > 50) { + scsi.syncoffset = 50; + } + + // REQ/ACK offset(limited to 16) + scsi.syncoffset = scsi.msb[i + 4]; + if (scsi.syncoffset > 16) { + scsi.syncoffset = 16; + } + + // STDR response message generation + ctrl.length = 5; + ctrl.blocks = 1; + ctrl.buffer[0] = 0x01; + ctrl.buffer[1] = 0x03; + ctrl.buffer[2] = 0x01; + ctrl.buffer[3] = (BYTE)scsi.syncperiod; + ctrl.buffer[4] = (BYTE)scsi.syncoffset; + MsgIn(); + return; + } + + // next + i++; + } + } + + // Initialize ATN message reception status + scsi.atnmsg = FALSE; + + // Command phase + Command(); + break; + + // Data out phase + case BUS::dataout: + // Flush unit + FlushUnit(); + + // status phase + Status(); + break; + + // Other (impossible) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// Transfer MSG +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMONDEV::XferMsg(DWORD msg) +{ + ASSERT(this); + ASSERT(ctrl.phase == BUS::msgout); + + // Save message out data + if (scsi.atnmsg) { + scsi.msb[scsi.msc] = (BYTE)msg; + scsi.msc++; + scsi.msc %= 256; + } + + return TRUE; +} From 64c621d36b794ff475f1e12f7ddbcebf344279e9 Mon Sep 17 00:00:00 2001 From: akuker Date: Tue, 7 Jul 2020 16:41:12 -0500 Subject: [PATCH 04/16] Cleanup failed stuff.... --- src/raspberrypi/disk.cpp | 339 ++++++------------------------------- src/raspberrypi/disk.h | 171 ------------------- src/raspberrypi/rascsi.cpp | 2 +- 3 files changed, 50 insertions(+), 462 deletions(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index 23678f6..48cb38d 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -4535,247 +4535,6 @@ void FASTCALL SCSICD::GetBuf( } - -//=========================================================================== -// -// SCSI Monitor Device -// This will monitor all of the traffic to this SCSI ID and dump it to -// STDOUT -// -//=========================================================================== - -//--------------------------------------------------------------------------- -// -// Constructor -// -//--------------------------------------------------------------------------- -MONITORHD::MONITORHD() : Disk() -{ - // SCSI Monitor - disk.id = MAKEID('S', 'M', 'O', 'N'); -} - -//--------------------------------------------------------------------------- -// -// Reset -// -//--------------------------------------------------------------------------- -void FASTCALL MONITORHD::Reset() -{ -// // Unlock and release attention -// disk.lock = FALSE; -// disk.attn = FALSE; -// -// // No reset, clear code -// disk.reset = FALSE; -// disk.code = 0x00; -} - -//--------------------------------------------------------------------------- -// -// Open -// -//--------------------------------------------------------------------------- -BOOL FASTCALL MONITORHD::Open(const Filepath& path, BOOL /*attn*/) -{ -// Fileio fio; -// off64_t size; -// -// ASSERT(this); -// ASSERT(!disk.ready); -// -// // read open required -// if (!fio.Open(path, Fileio::ReadOnly)) { -// return FALSE; -// } -// -// // Get file size -// size = fio.GetFileSize(); -// fio.Close(); -// -// // Must be 512 bytes -// if (size & 0x1ff) { -// return FALSE; -// } -// -// // 10MB or more -// if (size < 0x9f5400) { -// return FALSE; -// } -// // 2TB according to xm6i -// // There is a similar one in wxw/wxw_cfg.cpp -// if (size > 2LL * 1024 * 1024 * 1024 * 1024) { -// return FALSE; -// } -// -// // sector size and number of blocks -// disk.size = 9; -// disk.blocks = (DWORD)(size >> 9); -// -// // Call base class -// return Disk::Open(path); -} - -//--------------------------------------------------------------------------- -// -// INQUIRY -// -//--------------------------------------------------------------------------- -int FASTCALL MONITORHD::Inquiry( - const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) -{ -//////// char vendor[32]; -//////// char product[32]; -//////// char rev[32]; - int size = 0; -//////// -//////// ASSERT(this); -//////// ASSERT(cdb); -//////// ASSERT(buf); -//////// ASSERT(cdb[0] == 0x12); -//////// -//////// // EVPD check -//////// if (cdb[1] & 0x01) { -//////// disk.code = DISK_INVALIDCDB; -//////// return 0; -//////// } -//////// -//////// // Ready check (Error if no image file) -//////// if (!disk.ready) { -//////// disk.code = DISK_NOTREADY; -//////// return 0; -//////// } -//////// -//////// // Basic data -//////// // buf[0] ... Direct Access Device -//////// // buf[2] ... SCSI-2 compliant command system -//////// // buf[3] ... SCSI-2 compliant Inquiry response -//////// // buf[4] ... Inquiry additional data -//////// memset(buf, 0, 8); -//////// -//////// // SCSI-2 p.104 4.4.3 Incorrect logical unit handling -//////// if (((cdb[1] >> 5) & 0x07) != disk.lun) { -//////// buf[0] = 0x7f; -//////// } -//////// -//////// buf[2] = 0x02; -//////// buf[3] = 0x02; -//////// buf[4] = 122 + 3; // Value close to real HDD -//////// -//////// // Fill with blanks -//////// memset(&buf[8], 0x20, buf[4] - 3); -//////// -//////// // Determine vendor name/product name -//////// sprintf(vendor, BENDER_SIGNATURE); -//////// size = disk.blocks >> 11; -//////// if (size < 300) -//////// sprintf(product, "PRODRIVE LPS%dS", size); -//////// else if (size < 600) -//////// sprintf(product, "MAVERICK%dS", size); -//////// else if (size < 800) -//////// sprintf(product, "LIGHTNING%dS", size); -//////// else if (size < 1000) -//////// sprintf(product, "TRAILBRAZER%dS", size); -//////// else if (size < 2000) -//////// sprintf(product, "FIREBALL%dS", size); -//////// else -//////// sprintf(product, "FBSE%d.%dS", size / 1000, (size % 1000) / 100); -//////// -//////// // Vendor name -//////// memcpy(&buf[8], vendor, strlen(vendor)); -//////// -//////// // Product name -//////// memcpy(&buf[16], product, strlen(product)); -//////// -//////// // Revision -//////// sprintf(rev, "0%01d%01d%01d", -//////// (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); -//////// memcpy(&buf[32], rev, 4); -//////// -//////// // Size of data that can be returned -//////// size = (buf[4] + 5); -//////// -//////// // Limit if the other buffer is small -//////// if (size > (int)cdb[4]) { -//////// size = (int)cdb[4]; -//////// } -//////// -//////// // Success -//////// disk.code = DISK_NOERROR; - return size; -} - -//--------------------------------------------------------------------------- -// -// MODE SELECT -// *Not affected by disk.code -// -//--------------------------------------------------------------------------- -BOOL FASTCALL MONITORHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) -{ -// int page; -// int size; -// -// ASSERT(this); -// ASSERT(buf); -// ASSERT(length >= 0); -// -// // PF -// if (cdb[1] & 0x10) { -// // Mode Parameter header -// if (length >= 12) { -// // Check the block length bytes -// size = 1 << disk.size; -// if (buf[9] != (BYTE)(size >> 16) || -// buf[10] != (BYTE)(size >> 8) || -// buf[11] != (BYTE)size) { -// // currently does not allow changing sector length -// disk.code = DISK_INVALIDPRM; -// return FALSE; -// } -// buf += 12; -// length -= 12; -// } -// -// // Parsing the page -// while (length > 0) { -// // Get page -// page = buf[0]; -// -// switch (page) { -// // format device -// case 0x03: -// // check the number of bytes in the physical sector -// size = 1 << disk.size; -// if (buf[0xc] != (BYTE)(size >> 8) || -// buf[0xd] != (BYTE)size) { -// // currently does not allow changing sector length -// disk.code = DISK_INVALIDPRM; -// return FALSE; -// } -// break; -// -// // Other page -// default: -// break; -// } -// -// // Advance to the next page -// size = buf[1] + 2; -// length -= size; -// buf += size; -// } -// } -// -// // Do not generate an error for the time being (MINIX) -// disk.code = DISK_NOERROR; - - return TRUE; -} - - - - //=========================================================================== // // SCSI Host Bridge @@ -6537,19 +6296,19 @@ BUS::phase_t FASTCALL SASIDEV::Process() ctrl.bus->Aquire(); // For the monitor tool, we shouldn't need to reset. We're just logging information -//////// // Reset -//////// if (ctrl.bus->GetRST()) { -////////#if defined(DISK_LOG) -//////// Log(Log::Normal, "RESET signal received"); -////////#endif // DISK_LOG -//////// -//////// // Reset the controller -//////// Reset(); -//////// -//////// // Reset the bus -//////// ctrl.bus->Reset(); -//////// return ctrl.phase; -//////// } + // Reset + if (ctrl.bus->GetRST()) { +#if defined(DISK_LOG) + Log(Log::Normal, "RESET signal received"); +#endif // DISK_LOG + + // Reset the controller + Reset(); + + // Reset the bus + ctrl.bus->Reset(); + return ctrl.phase; + } // Phase processing switch (ctrl.phase) { @@ -6616,12 +6375,12 @@ void FASTCALL SASIDEV::BusFree() // Phase Setting ctrl.phase = BUS::busfree; -// // Set Signal lines -// ctrl.bus->SetREQ(FALSE); -// ctrl.bus->SetMSG(FALSE); -// ctrl.bus->SetCD(FALSE); -// ctrl.bus->SetIO(FALSE); -// ctrl.bus->SetBSY(FALSE); + Set Signal lines + ctrl.bus->SetREQ(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -6702,10 +6461,10 @@ void FASTCALL SASIDEV::Command() // Phase Setting ctrl.phase = BUS::command; -// // Signal line operated by the target -// ctrl.bus->SetMSG(FALSE); -// ctrl.bus->SetCD(TRUE); -// ctrl.bus->SetIO(FALSE); + // Signal line operated by the target + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); // Data transfer is 6 bytes x 1 block ctrl.offset = 0; @@ -6896,10 +6655,10 @@ void FASTCALL SASIDEV::Status() // Phase Setting ctrl.phase = BUS::status; -//////// // Signal line operated by the target -//////// ctrl.bus->SetMSG(FALSE); -//////// ctrl.bus->SetCD(TRUE); -//////// ctrl.bus->SetIO(TRUE); + // Signal line operated by the target + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(TRUE); // Data transfer is 1 byte x 1 block ctrl.offset = 0; @@ -6957,10 +6716,10 @@ void FASTCALL SASIDEV::MsgIn() // Phase Setting ctrl.phase = BUS::msgin; -////////// // Signal line operated by the target -////////// ctrl.bus->SetMSG(TRUE); -////////// ctrl.bus->SetCD(TRUE); -////////// ctrl.bus->SetIO(TRUE); + // Signal line operated by the target + ctrl.bus->SetMSG(TRUE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(TRUE); // length, blocks are already set ASSERT(ctrl.length > 0); @@ -7041,10 +6800,10 @@ void FASTCALL SASIDEV::DataIn() // Phase Setting ctrl.phase = BUS::datain; -//////// // Signal line operated by the target -//////// ctrl.bus->SetMSG(FALSE); -//////// ctrl.bus->SetCD(FALSE); -//////// ctrl.bus->SetIO(TRUE); + // Signal line operated by the target + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(TRUE); // length, blocks are already set ASSERT(ctrl.length > 0); @@ -7123,10 +6882,10 @@ void FASTCALL SASIDEV::DataOut() // Phase Setting ctrl.phase = BUS::dataout; -//////// // Signal line operated by the target -//////// ctrl.bus->SetMSG(FALSE); -//////// ctrl.bus->SetCD(FALSE); -//////// ctrl.bus->SetIO(FALSE); + // Signal line operated by the target + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); // length, blocks are already calculated ASSERT(ctrl.length > 0); @@ -8369,12 +8128,12 @@ void FASTCALL SCSIDEV::BusFree() // Phase setting ctrl.phase = BUS::busfree; -//////// // Signal line -//////// ctrl.bus->SetREQ(FALSE); -//////// ctrl.bus->SetMSG(FALSE); -//////// ctrl.bus->SetCD(FALSE); -//////// ctrl.bus->SetIO(FALSE); -//////// ctrl.bus->SetBSY(FALSE); + // Signal line + ctrl.bus->SetREQ(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetBSY(FALSE); // Initialize status and message ctrl.status = 0x00; @@ -8643,10 +8402,10 @@ void FASTCALL SCSIDEV::MsgOut() // Phase Setting ctrl.phase = BUS::msgout; -//////// // Signal line operated by the target -//////// ctrl.bus->SetMSG(TRUE); -//////// ctrl.bus->SetCD(TRUE); -//////// ctrl.bus->SetIO(FALSE); + // Signal line operated by the target + ctrl.bus->SetMSG(TRUE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); // Data transfer is 1 byte x 1 block ctrl.offset = 0; diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h index d6dff79..0299d3c 100644 --- a/src/raspberrypi/disk.h +++ b/src/raspberrypi/disk.h @@ -401,26 +401,6 @@ public: // MODE SELECT(6) command }; -class MONITORHD : public Disk -{ -public: - // Basic Functions - MONITORHD(); - // Constructor - void FASTCALL Reset(); - // Reset - BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); - // Open - - // commands - int FASTCALL Inquiry( - const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); - // INQUIRY command - BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); - // MODE SELECT(6) command - BOOL FASTCALL IsMonitor() const {return TRUE;} -}; - //=========================================================================== // // SCSI hard disk (PC-9801-55 NEC genuine /Anex86/T98Next) @@ -723,31 +703,6 @@ private: #endif }; - -//////////=========================================================================== -////////// -////////// SCSI Monitor Device (Interits SCSI device) -////////// -//////////=========================================================================== -////////class SCSIMONDEV : public Disk -////////{ -////////public: -//////// // Basic Functions -//////// SCSIMONDEV(); -//////// // Constructor -//////// void FASTCALL Reset(); -//////// // Reset -//////// BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); -//////// // Open -//////// -//////// // commands -//////// int FASTCALL Inquiry( -//////// const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); -//////// // INQUIRY command -//////// BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); -//////// // MODE SELECT(6) command -////////}; - //=========================================================================== // // SCSI Host Bridge @@ -1190,132 +1145,6 @@ private: // Internal data }; -//=========================================================================== -// -// SCSI Device (Interits SASI device) -// -//=========================================================================== -class SCSIMONDEV : public SASIDEV -{ -public: - // Internal data definition - typedef struct { - // Synchronous transfer - BOOL syncenable; // Synchronous transfer possible - int syncperiod; // Synchronous transfer period - int syncoffset; // Synchronous transfer offset - int syncack; // Number of synchronous transfer ACKs - - // ATN message - BOOL atnmsg; - int msc; - BYTE msb[256]; - } scsi_t; - - BOOL FASTCALL IsMonitor() const {return TRUE;} - -public: - // Basic Functions -#ifdef RASCSI - SCSIMONDEV(); -#else - SCSIMONDEV(Device *dev); -#endif // RASCSI - // Constructor - - void FASTCALL Reset(); - // Device Reset - - // 外部API - BUS::phase_t FASTCALL Process(); - // Run - - void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } - // Synchronouse transfer enable setting - - // Other - BOOL FASTCALL IsSASI() const {return FALSE;} - // SASI Check - BOOL FASTCALL IsSCSI() const {return TRUE;} - // SCSI check - -private: - // Phase - void FASTCALL BusFree(); - // Bus free phase - void FASTCALL Selection(); - // Selection phase - void FASTCALL Execute(); - // Execution phase - void FASTCALL MsgOut(); - // Message out phase - void FASTCALL Error(); - // Common erorr handling - - // commands - void FASTCALL CmdInquiry(); - // INQUIRY command - void FASTCALL CmdModeSelect(); - // MODE SELECT command - void FASTCALL CmdModeSense(); - // MODE SENSE command - void FASTCALL CmdStartStop(); - // START STOP UNIT command - void FASTCALL CmdSendDiag(); - // SEND DIAGNOSTIC command - void FASTCALL CmdRemoval(); - // PREVENT/ALLOW MEDIUM REMOVAL command - void FASTCALL CmdReadCapacity(); - // READ CAPACITY command - void FASTCALL CmdRead10(); - // READ(10) command - void FASTCALL CmdWrite10(); - // WRITE(10) command - void FASTCALL CmdSeek10(); - // SEEK(10) command - void FASTCALL CmdVerify(); - // VERIFY command - void FASTCALL CmdSynchronizeCache(); - // SYNCHRONIZE CACHE command - void FASTCALL CmdReadDefectData10(); - // READ DEFECT DATA(10) command - void FASTCALL CmdReadToc(); - // READ TOC command - void FASTCALL CmdPlayAudio10(); - // PLAY AUDIO(10) command - void FASTCALL CmdPlayAudioMSF(); - // PLAY AUDIO MSF command - void FASTCALL CmdPlayAudioTrack(); - // PLAY AUDIO TRACK INDEX command - void FASTCALL CmdModeSelect10(); - // MODE SELECT(10) command - void FASTCALL CmdModeSense10(); - // MODE SENSE(10) command - void FASTCALL CmdGetMessage10(); - // GET MESSAGE(10) command - void FASTCALL CmdSendMessage10(); - // SEND MESSAGE(10) command - - // データ転送 - void FASTCALL Send(); - // Send data -#ifndef RASCSI - void FASTCALL SendNext(); - // Continue sending data -#endif // RASCSI - void FASTCALL Receive(); - // Receive data -#ifndef RASCSI - void FASTCALL ReceiveNext(); - // Continue receiving data -#endif // RASCSI - BOOL FASTCALL XferMsg(DWORD msg); - // Data transfer message - - scsi_t scsi; - // Internal data -}; - #endif // disk_h diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index c12ac06..dadf76e 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -155,7 +155,7 @@ BOOL Init() bus = new GPIOBUS(); // GPIO Initialization - if (!bus->Init(BUS::TARGET)) { + if (!bus->Init()) { return FALSE; } From da101dea19dc469bc46789180fa487bc485cdffd Mon Sep 17 00:00:00 2001 From: akuker Date: Tue, 7 Jul 2020 16:49:36 -0500 Subject: [PATCH 05/16] Fix typo --- src/raspberrypi/disk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index 48cb38d..676c166 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -6375,7 +6375,7 @@ void FASTCALL SASIDEV::BusFree() // Phase Setting ctrl.phase = BUS::busfree; - Set Signal lines + // Set Signal lines ctrl.bus->SetREQ(FALSE); ctrl.bus->SetMSG(FALSE); ctrl.bus->SetCD(FALSE); From 1d588d1120c45a008db65a0e212d03e748f81111 Mon Sep 17 00:00:00 2001 From: akuker Date: Wed, 8 Jul 2020 19:45:34 -0500 Subject: [PATCH 06/16] Create skeleton man pages --- src/raspberrypi/rascsi.1 | 14 ++++++++++++++ src/raspberrypi/rasctl.1 | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/raspberrypi/rascsi.1 create mode 100644 src/raspberrypi/rasctl.1 diff --git a/src/raspberrypi/rascsi.1 b/src/raspberrypi/rascsi.1 new file mode 100644 index 0000000..b29a702 --- /dev/null +++ b/src/raspberrypi/rascsi.1 @@ -0,0 +1,14 @@ +.TH rascsi 1 +.SH NAME +rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins +.SH SYNOPSIS +.B rascsi +[\fB\-HDn\fR \fIfile\fR]... +.SH DESCRIPTION +.B rascsi +Emulates SCSI devices using the Raspberry Pi GPIO pins. +.SH OPTIONS +.TP +.BR \-n ", " \-\-bits = \fIBITS\R +Default is one bit. + diff --git a/src/raspberrypi/rasctl.1 b/src/raspberrypi/rasctl.1 new file mode 100644 index 0000000..b29a702 --- /dev/null +++ b/src/raspberrypi/rasctl.1 @@ -0,0 +1,14 @@ +.TH rascsi 1 +.SH NAME +rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins +.SH SYNOPSIS +.B rascsi +[\fB\-HDn\fR \fIfile\fR]... +.SH DESCRIPTION +.B rascsi +Emulates SCSI devices using the Raspberry Pi GPIO pins. +.SH OPTIONS +.TP +.BR \-n ", " \-\-bits = \fIBITS\R +Default is one bit. + From 78eb315917c392e48b042e741446a786f26d2816 Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 12:24:47 -0500 Subject: [PATCH 07/16] Updated rascsi man page --- src/raspberrypi/rascsi.1 | 52 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/raspberrypi/rascsi.1 b/src/raspberrypi/rascsi.1 index b29a702..13f20f8 100644 --- a/src/raspberrypi/rascsi.1 +++ b/src/raspberrypi/rascsi.1 @@ -3,12 +3,60 @@ rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins .SH SYNOPSIS .B rascsi +[\fB\-IDn\fR \fIfile\fR]... [\fB\-HDn\fR \fIfile\fR]... .SH DESCRIPTION .B rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins. +.PP +In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. +The number (n) after the ID or HD idnetifier specifies the ID number for that device. +For SCSI: The ID is limited from 0-7. However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered rare and only used on very early Sharp X68000 computers. +.PP +RaSCSI will determin the type of device based upon the file extension of the FILE argument. + hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used with X68000) + hds: SCSI Hard Disk image (XM6 SCSI HD image - typically only used with X68000) + hdn: SCSI Hard Disk image (NEC GENUINE) + hdi: SCSI Hard Disk image (Anex86 HD image) + nhd: SCSI Hard Disk image (T98Next HD image) + hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac SCSI emulation) + mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only used with X68000) + iso: SCSI CD-ROM image (ISO 9660 image) + +For example, if you want to specify an Apple-compatible HD image on ID 0, you can use the following command: + sudo rascsi -ID0 /path/to/drive/hdimage.hda + +Once RaSCSI starts, it will open a socket (port 6868) to allow external management commands. +If another process is using port 6868, RaSCSI will terminate, since it is likely another instance of RaSCSI. +Once RaSCSI has initialized, the rasctl utility can be used to send commands. + +To quit RaSCSI, press Control + C. If it is running in the background, you can kill it using an INT signal. + .SH OPTIONS .TP -.BR \-n ", " \-\-bits = \fIBITS\R -Default is one bit. +.BR\-\-ID\fIn " " \fIFILE +n is the SCSI ID number (0-7)\n +.IP +FILE is the name of the image file to attach to that ID. +.TP +.BR\-\-HD\fIn " " \fIFILE +n is the SASI ID number (0-15)\n +.IP +FILE is the name of the image file to attach to that ID. +.IP +Note: SASI usage is rare, and is typically limited to early Sharp X68000 systems. +.SH EXAMPLES +Launch RaSCSI with no emulated drives attached: + rascsi + +Launch RaSCSI with an Apple hard drive image as ID0 and a CD-ROM as ID 2 + rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso + +To create an empty, 100MB HD image, use the following command: + dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800 + +.SH SEE ALSO +rasctl(1), scsidump(1) + +Full documentation is available at: From 5c604eb1eabcce510bac9d127a2b875770b19b87 Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:00:06 -0500 Subject: [PATCH 08/16] Updated man pages --- src/raspberrypi/rascsi.1 | 4 +-- src/raspberrypi/rasctl.1 | 71 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/raspberrypi/rascsi.1 b/src/raspberrypi/rascsi.1 index 13f20f8..32933a6 100644 --- a/src/raspberrypi/rascsi.1 +++ b/src/raspberrypi/rascsi.1 @@ -3,7 +3,7 @@ rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins .SH SYNOPSIS .B rascsi -[\fB\-IDn\fR \fIfile\fR]... +[\fB\-IDn\fR \fIfile\fR] [\fB\-HDn\fR \fIfile\fR]... .SH DESCRIPTION .B rascsi @@ -59,4 +59,4 @@ To create an empty, 100MB HD image, use the following command: .SH SEE ALSO rasctl(1), scsidump(1) -Full documentation is available at: +Full documentation is available at: diff --git a/src/raspberrypi/rasctl.1 b/src/raspberrypi/rasctl.1 index b29a702..6364d58 100644 --- a/src/raspberrypi/rasctl.1 +++ b/src/raspberrypi/rasctl.1 @@ -1,14 +1,71 @@ .TH rascsi 1 .SH NAME -rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins +rasctl \- Sends management commands to the rascsi process .SH SYNOPSIS -.B rascsi -[\fB\-HDn\fR \fIfile\fR]... +.B rasctl +\fB\-l\fR | +\fB\-i\fR \fIID\fR +[\fB\-u\fR \fIUNIT\fR] +[\fB\-c\fR \fICMD\fR] +[\fB\-t\fR \fITYPE\fR] +[\fB\-f\fR \fIFILE\fR] .SH DESCRIPTION -.B rascsi -Emulates SCSI devices using the Raspberry Pi GPIO pins. +.B rasctl +Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices. + +Either the -i or -l option should be specified at one time. Not both. + +You do NOT need root privileges to use rasctl. + +Note: The command and type arguments are case insensitive. Only the first letter of the command/type are evaluated by the tool. + .SH OPTIONS .TP -.BR \-n ", " \-\-bits = \fIBITS\R -Default is one bit. +.BR\-\-l\fI +List all of the devices that are currently being emulated by RaSCSI, as well as their current status. \n +.TP +.BR\-\-i\fI " " \fIID +ID is the SCSI ID that you want to control. (0-7)\n +.TP +.BR\-\-u\fI " " \fIUNIT +Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI devices on a shared SCSI controller. (This is not common)\n +.TP +.BR\-\-c\fI " " \fICMD +Command is the operation being requested. options are: + attach: attach disk + detach: detach disk + insert: insert media (Magneto-Optical and CD only) + eject: eject media (Magneto-Optical and CD only) + protect: Write protect the media (Magneto-Optical only) +.IP +When the command is omited, rasctl will default to the 'attach' command +.TP +.BR\-\-t\fI " " \fITYPE +Specifies the type of disk. If this disagrees with the file extension of the specified image, the TYPE argument is ignored. Available drive types are: + hd: Hard disk (SCSI or SASI) + mo: Magneto-Optical disk) + cd: CD-ROM + bridge: Bridge device (This is only applicable to the Sharp X68000) +.TP +.BR\-\-f\fI " " \fIFILE +Path to the disk image file. See the rascsi(1) man page for allowable file types. +.SH EXAMPLES +Show a listing of all of the SCSI devices and their current status + rasctl -l + + +Example output: + +----+----+------+------------------------------------- + | ID | UN | TYPE | DEVICE STATUS + +----+----+------+------------------------------------- + | 0 | 1 | SCHD | /home/pi/harddisk.hda + +----+----+------+------------------------------------- + +Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image "HDIIMAGE0.HDS". + rasctl -i 0 -f HDIIMAGE0.HDS + +.SH SEE ALSO +rascsi(1) + +Full documentation is available at: From 79ac158eb0a3c2063fbeb18dbd2477e7e4b230b6 Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:21:15 -0500 Subject: [PATCH 09/16] Updated man pages and generated text version of the doc --- doc/rascsi.1 | 62 +++++++++++++++++++++++++++++++++++ doc/rascsi_man_page.txt | 64 +++++++++++++++++++++++++++++++++++++ doc/rasctl.1 | 71 +++++++++++++++++++++++++++++++++++++++++ doc/rasctl_man_page.txt | 69 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 266 insertions(+) create mode 100644 doc/rascsi.1 create mode 100644 doc/rascsi_man_page.txt create mode 100644 doc/rasctl.1 create mode 100644 doc/rasctl_man_page.txt diff --git a/doc/rascsi.1 b/doc/rascsi.1 new file mode 100644 index 0000000..d08cf86 --- /dev/null +++ b/doc/rascsi.1 @@ -0,0 +1,62 @@ +.TH rascsi 1 +.SH NAME +rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins +.SH SYNOPSIS +.B rascsi +[\fB\-IDn\fR \fIfile\fR] +[\fB\-HDn\fR \fIfile\fR]... +.SH DESCRIPTION +.B rascsi +Emulates SCSI devices using the Raspberry Pi GPIO pins. +.PP +In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. +The number (n) after the ID or HD idnetifier specifies the ID number for that device. +For SCSI: The ID is limited from 0-7. However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered rare and only used on very early Sharp X68000 computers. +.PP +RaSCSI will determin the type of device based upon the file extension of the FILE argument. + hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used with X68000) + hds: SCSI Hard Disk image (XM6 SCSI HD image - typically only used with X68000) + hdn: SCSI Hard Disk image (NEC GENUINE) + hdi: SCSI Hard Disk image (Anex86 HD image) + nhd: SCSI Hard Disk image (T98Next HD image) + hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac SCSI emulation) + mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only used with X68000) + iso: SCSI CD-ROM image (ISO 9660 image) + +For example, if you want to specify an Apple-compatible HD image on ID 0, you can use the following command: + sudo rascsi -ID0 /path/to/drive/hdimage.hda + +Once RaSCSI starts, it will open a socket (port 6868) to allow external management commands. +If another process is using port 6868, RaSCSI will terminate, since it is likely another instance of RaSCSI. +Once RaSCSI has initialized, the rasctl utility can be used to send commands. + +To quit RaSCSI, press Control + C. If it is running in the background, you can kill it using an INT signal. + +.SH OPTIONS +.TP +.BR \-ID\fIn " " \fIFILE +n is the SCSI ID number (0-7) +.IP +FILE is the name of the image file to attach to that ID. +.TP +.BR \-HD\fIn " " \fIFILE +n is the SASI ID number (0-15) +.IP +FILE is the name of the image file to attach to that ID. +.IP +Note: SASI usage is rare, and is typically limited to early Sharp X68000 systems. + +.SH EXAMPLES +Launch RaSCSI with no emulated drives attached: + rascsi + +Launch RaSCSI with an Apple hard drive image as ID0 and a CD-ROM as ID 2 + rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso + +To create an empty, 100MB HD image, use the following command: + dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800 + +.SH SEE ALSO +rasctl(1), scsidump(1) + +Full documentation is available at: diff --git a/doc/rascsi_man_page.txt b/doc/rascsi_man_page.txt new file mode 100644 index 0000000..998e7e4 --- /dev/null +++ b/doc/rascsi_man_page.txt @@ -0,0 +1,64 @@ +rascsi(1) General Commands Manual rascsi(1) + +NAME + rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins + +SYNOPSIS + rascsi [-IDn file] [-HDn file]... + +DESCRIPTION + rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins. + + In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. The number (n) + after the ID or HD idnetifier specifies the ID number for that device. For SCSI: The ID is limited from 0-7. + However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered + rare and only used on very early Sharp X68000 computers. + + RaSCSI will determin the type of device based upon the file extension of the FILE argument. + hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used with X68000) + hds: SCSI Hard Disk image (XM6 SCSI HD image - typically only used with X68000) + hdn: SCSI Hard Disk image (NEC GENUINE) + hdi: SCSI Hard Disk image (Anex86 HD image) + nhd: SCSI Hard Disk image (T98Next HD image) + hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac SCSI emulation) + mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only used with X68000) + iso: SCSI CD-ROM image (ISO 9660 image) + + For example, if you want to specify an Apple-compatible HD image on ID 0, you can use the following command: + sudo rascsi -ID0 /path/to/drive/hdimage.hda + + Once RaSCSI starts, it will open a socket (port 6868) to allow external management commands. If another + process is using port 6868, RaSCSI will terminate, since it is likely another instance of RaSCSI. Once + RaSCSI has initialized, the rasctl utility can be used to send commands. + + To quit RaSCSI, press Control + C. If it is running in the background, you can kill it using an INT signal. + +OPTIONS + -IDn FILE + n is the SCSI ID number (0-7) + + FILE is the name of the image file to attach to that ID. + + -HDn FILE + n is the SASI ID number (0-15) + + FILE is the name of the image file to attach to that ID. + + Note: SASI usage is rare, and is typically limited to early Sharp X68000 systems. + +EXAMPLES + Launch RaSCSI with no emulated drives attached: + rascsi + + Launch RaSCSI with an Apple hard drive image as ID0 and a CD-ROM as ID 2 + rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso + + To create an empty, 100MB HD image, use the following command: + dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800 + +SEE ALSO + rasctl(1), scsidump(1) + + Full documentation is available at: + + rascsi(1) diff --git a/doc/rasctl.1 b/doc/rasctl.1 new file mode 100644 index 0000000..be65b17 --- /dev/null +++ b/doc/rasctl.1 @@ -0,0 +1,71 @@ +.TH rascsi 1 +.SH NAME +rasctl \- Sends management commands to the rascsi process +.SH SYNOPSIS +.B rasctl +\fB\-l\fR | +\fB\-i\fR \fIID\fR +[\fB\-u\fR \fIUNIT\fR] +[\fB\-c\fR \fICMD\fR] +[\fB\-t\fR \fITYPE\fR] +[\fB\-f\fR \fIFILE\fR] +.SH DESCRIPTION +.B rasctl +Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices. + +Either the -i or -l option should be specified at one time. Not both. + +You do NOT need root privileges to use rasctl. + +Note: The command and type arguments are case insensitive. Only the first letter of the command/type are evaluated by the tool. + +.SH OPTIONS +.TP +.BR \-l\fI +List all of the devices that are currently being emulated by RaSCSI, as well as their current status. +.TP +.BR \-i\fI " " \fIID +ID is the SCSI ID that you want to control. (0-7) +.TP +.BR \-u\fI " " \fIUNIT +Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI devices on a shared SCSI controller. (This is not common) +.TP +.BR \-c\fI " " \fICMD +Command is the operation being requested. options are: + attach: attach disk + detach: detach disk + insert: insert media (Magneto-Optical and CD only) + eject: eject media (Magneto-Optical and CD only) + protect: Write protect the media (Magneto-Optical only) +.IP +When the command is omited, rasctl will default to the 'attach' command +.TP +.BR \-t\fI " " \fITYPE +Specifies the type of disk. If this disagrees with the file extension of the specified image, the TYPE argument is ignored. Available drive types are: + hd: Hard disk (SCSI or SASI) + mo: Magneto-Optical disk) + cd: CD-ROM + bridge: Bridge device (This is only applicable to the Sharp X68000) +.TP +.BR \-f\fI " " \fIFILE +Path to the disk image file. See the rascsi(1) man page for allowable file types. + +.SH EXAMPLES +Show a listing of all of the SCSI devices and their current status + rasctl -l + + +Example output: + +----+----+------+------------------------------------- + | ID | UN | TYPE | DEVICE STATUS + +----+----+------+------------------------------------- + | 0 | 1 | SCHD | /home/pi/harddisk.hda + +----+----+------+------------------------------------- + +Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image "HDIIMAGE0.HDS". + rasctl -i 0 -f HDIIMAGE0.HDS + +.SH SEE ALSO +rascsi(1) + +Full documentation is available at: diff --git a/doc/rasctl_man_page.txt b/doc/rasctl_man_page.txt new file mode 100644 index 0000000..b79f409 --- /dev/null +++ b/doc/rasctl_man_page.txt @@ -0,0 +1,69 @@ +rascsi(1) General Commands Manual rascsi(1) + +NAME + rasctl - Sends management commands to the rascsi process + +SYNOPSIS + rasctl -l | -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE] + +DESCRIPTION + rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the sta‐ + tus of the devices. + + Either the -i or -l option should be specified at one time. Not both. + + You do NOT need root privileges to use rasctl. + + Note: The command and type arguments are case insensitive. Only the first letter of the command/type are + evaluated by the tool. + +OPTIONS + -l List all of the devices that are currently being emulated by RaSCSI, as well as their current status. + + -i ID ID is the SCSI ID that you want to control. (0-7) + + -u UNIT + Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI + devices on a shared SCSI controller. (This is not common) + + -c CMD Command is the operation being requested. options are: + attach: attach disk + detach: detach disk + insert: insert media (Magneto-Optical and CD only) + eject: eject media (Magneto-Optical and CD only) + protect: Write protect the media (Magneto-Optical only) + + When the command is omited, rasctl will default to the 'attach' command + + -t TYPE + Specifies the type of disk. If this disagrees with the file extension of the specified image, the TYPE + argument is ignored. Available drive types are: + hd: Hard disk (SCSI or SASI) + mo: Magneto-Optical disk) + cd: CD-ROM + bridge: Bridge device (This is only applicable to the Sharp X68000) + + -f FILE + Path to the disk image file. See the rascsi(1) man page for allowable file types. + +EXAMPLES + Show a listing of all of the SCSI devices and their current status + rasctl -l + + Example output: + +----+----+------+------------------------------------- + | ID | UN | TYPE | DEVICE STATUS + +----+----+------+------------------------------------- + | 0 | 1 | SCHD | /home/pi/harddisk.hda + +----+----+------+------------------------------------- + + Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image + "HDIIMAGE0.HDS". + rasctl -i 0 -f HDIIMAGE0.HDS + +SEE ALSO + rascsi(1) + + Full documentation is available at: + + rascsi(1) From 35d2b838112dc8cc7da3ac7be1498b7b093d8e74 Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:21:59 -0500 Subject: [PATCH 10/16] Updated makefile to auto-generate man pages text files --- src/raspberrypi/Makefile | 35 ++++++++++++++++---- src/raspberrypi/rascsi.1 | 62 ----------------------------------- src/raspberrypi/rasctl.1 | 71 ---------------------------------------- 3 files changed, 28 insertions(+), 140 deletions(-) delete mode 100644 src/raspberrypi/rascsi.1 delete mode 100644 src/raspberrypi/rasctl.1 diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index 96ea2bc..4b59e0f 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -3,8 +3,12 @@ CC = gcc CXX = g++ -CFLAGS = -DDISK_LOG -O0 -g -Wall -CXXFLAGS = -DDISK_LOG -O0 -g -Wall +# Debug CFLAGS +#CFLAGS = -DDISK_LOG -O0 -g -Wall +#CFLAGS = -DDISK_LOG -O0 -g -Wall +# Release CFLAGS +CXXFLAGS = -O3 -Wall +CXXFLAGS = -O3 -Wall @@ -22,10 +26,14 @@ RASDUMP = rasdump SASIDUMP = sasidump SCSIMON = scsimon +USR_LOCAL_BIN = /usr/local/bin +MAN_PAGE_DIR = /usr/share/man/man1 +DOC_DIR = ../../doc + #BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) $(SASIDUMP) $(SCSIMON) # Temporarily remove the RASDUMP and RASDUMP tools, since they're not needed # for my specific use case. If you need them - add them back in! -BIN_ALL = $(RASCSI) $(RASCTL) $(SCSIMON) +BIN_ALL = $(RASCSI) $(RASCTL) SRC_RASCSI = \ @@ -71,13 +79,16 @@ OBJ_RASCTL := $(SRC_RASCTL:%.cpp=%.o) OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=%.o) OBJ_SASIDUMP := $(SRC_SASIDUMP:%.cpp=%.o) OBJ_SCSIMON := $(SRC_SCSIMON:%.cpp=%.o) -OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON) +#OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) $(OBJ_SCSIMON) +OBJ_ALL := $(OBJ_RASCSI) $(OBJ_RASCTL) $(OBJ_RASDUMP) $(OBJ_SASIDUMP) %.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ -ALL: $(BIN_ALL) -all: $(BIN_ALL) +docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt + +ALL: $(BIN_ALL) docs +all: $(BIN_ALL) docs $(RASCSI): $(OBJ_RASCSI) $(CXX) -o $@ $(OBJ_RASCSI) -lpthread @@ -98,7 +109,17 @@ clean: rm -f $(OBJ_ALL) $(BIN_ALL) run: - sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK.HDA -ID6 /home/pi/marathon.iso + sudo ./$(RASCSI) -ID1 /home/pi/HARDDISK2.hda -ID6 /home/pi/marathon.iso + +install: $(MAN_PAGE_DIR)/rascsi.1 $(MAN_PAGE_DIR)/rasctl.1 + sudo cp $(RASCTL) $(USR_LOCAL_BIN) + sudo cp $(RASCSI) $(USR_LOCAL_BIN) + +$(MAN_PAGE_DIR)/%.1 : $(DOC_DIR)/%.1 + sudo cp $< $@ + +$(DOC_DIR)/%_man_page.txt : $(DOC_DIR)/%.1 + man -l $< | col -bx > $@ .PHONY: Debug Debug: scsimon diff --git a/src/raspberrypi/rascsi.1 b/src/raspberrypi/rascsi.1 deleted file mode 100644 index 32933a6..0000000 --- a/src/raspberrypi/rascsi.1 +++ /dev/null @@ -1,62 +0,0 @@ -.TH rascsi 1 -.SH NAME -rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins -.SH SYNOPSIS -.B rascsi -[\fB\-IDn\fR \fIfile\fR] -[\fB\-HDn\fR \fIfile\fR]... -.SH DESCRIPTION -.B rascsi -Emulates SCSI devices using the Raspberry Pi GPIO pins. -.PP -In the arguments to RaSCSI, one or more SCSI (-IDn) or SASI (-HDn) devices can be specified. -The number (n) after the ID or HD idnetifier specifies the ID number for that device. -For SCSI: The ID is limited from 0-7. However, typically SCSI ID 7 is reserved for the "initiator" (the host computer).Note that SASI is considered rare and only used on very early Sharp X68000 computers. -.PP -RaSCSI will determin the type of device based upon the file extension of the FILE argument. - hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used with X68000) - hds: SCSI Hard Disk image (XM6 SCSI HD image - typically only used with X68000) - hdn: SCSI Hard Disk image (NEC GENUINE) - hdi: SCSI Hard Disk image (Anex86 HD image) - nhd: SCSI Hard Disk image (T98Next HD image) - hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac SCSI emulation) - mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only used with X68000) - iso: SCSI CD-ROM image (ISO 9660 image) - -For example, if you want to specify an Apple-compatible HD image on ID 0, you can use the following command: - sudo rascsi -ID0 /path/to/drive/hdimage.hda - -Once RaSCSI starts, it will open a socket (port 6868) to allow external management commands. -If another process is using port 6868, RaSCSI will terminate, since it is likely another instance of RaSCSI. -Once RaSCSI has initialized, the rasctl utility can be used to send commands. - -To quit RaSCSI, press Control + C. If it is running in the background, you can kill it using an INT signal. - -.SH OPTIONS -.TP -.BR\-\-ID\fIn " " \fIFILE -n is the SCSI ID number (0-7)\n -.IP -FILE is the name of the image file to attach to that ID. -.TP -.BR\-\-HD\fIn " " \fIFILE -n is the SASI ID number (0-15)\n -.IP -FILE is the name of the image file to attach to that ID. -.IP -Note: SASI usage is rare, and is typically limited to early Sharp X68000 systems. - -.SH EXAMPLES -Launch RaSCSI with no emulated drives attached: - rascsi - -Launch RaSCSI with an Apple hard drive image as ID0 and a CD-ROM as ID 2 - rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso - -To create an empty, 100MB HD image, use the following command: - dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800 - -.SH SEE ALSO -rasctl(1), scsidump(1) - -Full documentation is available at: diff --git a/src/raspberrypi/rasctl.1 b/src/raspberrypi/rasctl.1 deleted file mode 100644 index 6364d58..0000000 --- a/src/raspberrypi/rasctl.1 +++ /dev/null @@ -1,71 +0,0 @@ -.TH rascsi 1 -.SH NAME -rasctl \- Sends management commands to the rascsi process -.SH SYNOPSIS -.B rasctl -\fB\-l\fR | -\fB\-i\fR \fIID\fR -[\fB\-u\fR \fIUNIT\fR] -[\fB\-c\fR \fICMD\fR] -[\fB\-t\fR \fITYPE\fR] -[\fB\-f\fR \fIFILE\fR] -.SH DESCRIPTION -.B rasctl -Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices. - -Either the -i or -l option should be specified at one time. Not both. - -You do NOT need root privileges to use rasctl. - -Note: The command and type arguments are case insensitive. Only the first letter of the command/type are evaluated by the tool. - -.SH OPTIONS -.TP -.BR\-\-l\fI -List all of the devices that are currently being emulated by RaSCSI, as well as their current status. \n -.TP -.BR\-\-i\fI " " \fIID -ID is the SCSI ID that you want to control. (0-7)\n -.TP -.BR\-\-u\fI " " \fIUNIT -Unit number (0 or 1). This will default to 0. This option is only used when there are multiple SCSI devices on a shared SCSI controller. (This is not common)\n -.TP -.BR\-\-c\fI " " \fICMD -Command is the operation being requested. options are: - attach: attach disk - detach: detach disk - insert: insert media (Magneto-Optical and CD only) - eject: eject media (Magneto-Optical and CD only) - protect: Write protect the media (Magneto-Optical only) -.IP -When the command is omited, rasctl will default to the 'attach' command -.TP -.BR\-\-t\fI " " \fITYPE -Specifies the type of disk. If this disagrees with the file extension of the specified image, the TYPE argument is ignored. Available drive types are: - hd: Hard disk (SCSI or SASI) - mo: Magneto-Optical disk) - cd: CD-ROM - bridge: Bridge device (This is only applicable to the Sharp X68000) -.TP -.BR\-\-f\fI " " \fIFILE -Path to the disk image file. See the rascsi(1) man page for allowable file types. - -.SH EXAMPLES -Show a listing of all of the SCSI devices and their current status - rasctl -l - - -Example output: - +----+----+------+------------------------------------- - | ID | UN | TYPE | DEVICE STATUS - +----+----+------+------------------------------------- - | 0 | 1 | SCHD | /home/pi/harddisk.hda - +----+----+------+------------------------------------- - -Request the RaSCSI process to attach a disk (assumed) to SCSI ID 0 with the contents of the file system image "HDIIMAGE0.HDS". - rasctl -i 0 -f HDIIMAGE0.HDS - -.SH SEE ALSO -rascsi(1) - -Full documentation is available at: From 1c45f8e33c8f6ec578ff18ad8349b320c443a9f8 Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:28:17 -0500 Subject: [PATCH 11/16] Added warning at the top of the page to not manualy update --- doc/rascsi_man_page.txt | 4 ++++ doc/rasctl_man_page.txt | 4 ++++ src/raspberrypi/Makefile | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/rascsi_man_page.txt b/doc/rascsi_man_page.txt index 998e7e4..d7a2622 100644 --- a/doc/rascsi_man_page.txt +++ b/doc/rascsi_man_page.txt @@ -1,3 +1,7 @@ +!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!! +!! ------ The native file is rascsi.1. Re-run 'make docs' after updating + + rascsi(1) General Commands Manual rascsi(1) NAME diff --git a/doc/rasctl_man_page.txt b/doc/rasctl_man_page.txt index b79f409..9f2d564 100644 --- a/doc/rasctl_man_page.txt +++ b/doc/rasctl_man_page.txt @@ -1,3 +1,7 @@ +!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!! +!! ------ The native file is rasctl.1. Re-run 'make docs' after updating + + rascsi(1) General Commands Manual rascsi(1) NAME diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index 4b59e0f..883e8a0 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -119,7 +119,9 @@ $(MAN_PAGE_DIR)/%.1 : $(DOC_DIR)/%.1 sudo cp $< $@ $(DOC_DIR)/%_man_page.txt : $(DOC_DIR)/%.1 - man -l $< | col -bx > $@ + @echo "!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!" > $@ + @echo "!! ------ The native file is $(notdir $<). Re-run 'make docs' after updating\n\n" >> $@ + man -l $< | col -bx >> $@ .PHONY: Debug Debug: scsimon From 13cafbc97864c6020039d33be558080520b2af3f Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:32:18 -0500 Subject: [PATCH 12/16] Added ability to use --help as well as -h to show usage info --- src/raspberrypi/rascsi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index dadf76e..87b76a8 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -78,7 +78,8 @@ void Banner(int argc, char* argv[]) FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n"); FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); - if (argc > 1 && strcmp(argv[1], "-h") == 0) { + if ((argc > 1 && strcmp(argv[1], "-h") == 0) || + (argc > 1 && strcmp(argv[1], "--help") == 0){ FPRT(stdout,"\n"); FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); FPRT(stdout," n is SCSI identification number(0-7).\n"); From bd707885127bd00f3ca2458238866713c69ee97f Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:33:57 -0500 Subject: [PATCH 13/16] Added ability to use --help as well as -h to show usage info --- src/raspberrypi/rascsi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 87b76a8..5c538f3 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -79,7 +79,7 @@ void Banner(int argc, char* argv[]) FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); if ((argc > 1 && strcmp(argv[1], "-h") == 0) || - (argc > 1 && strcmp(argv[1], "--help") == 0){ + (argc > 1 && strcmp(argv[1], "--help") == 0)){ FPRT(stdout,"\n"); FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); FPRT(stdout," n is SCSI identification number(0-7).\n"); From f263dd03b36a86cfdce0e7fab8fb1e768e4ec58c Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:36:25 -0500 Subject: [PATCH 14/16] Removed extraneous debug printfs, removed scsimon --- src/raspberrypi/.gitignore | 6 + src/raspberrypi/Makefile | 11 - src/raspberrypi/disk.cpp | 57 +- src/raspberrypi/scsimon.cpp | 1174 -------------------- src/raspberrypi/scsimondev.cpp | 1902 -------------------------------- 5 files changed, 35 insertions(+), 3115 deletions(-) delete mode 100644 src/raspberrypi/scsimon.cpp delete mode 100644 src/raspberrypi/scsimondev.cpp diff --git a/src/raspberrypi/.gitignore b/src/raspberrypi/.gitignore index 02c03f1..659c642 100644 --- a/src/raspberrypi/.gitignore +++ b/src/raspberrypi/.gitignore @@ -1,2 +1,8 @@ *.o *.bak +*.HDA +*.save +*.cbp +*.layout +*.log + diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile index 883e8a0..8163221 100644 --- a/src/raspberrypi/Makefile +++ b/src/raspberrypi/Makefile @@ -63,17 +63,6 @@ SRC_SASIDUMP = \ filepath.cpp \ fileio.cpp -SRC_SCSIMON = \ - scsimon.cpp \ - scsi.cpp \ - disk.cpp \ - gpiobus.cpp \ - ctapdriver.cpp \ - cfilesystem.cpp \ - filepath.cpp \ - fileio.cpp \ - scsimondev.cpp - OBJ_RASCSI := $(SRC_RASCSI:%.cpp=%.o) OBJ_RASCTL := $(SRC_RASCTL:%.cpp=%.o) OBJ_RASDUMP := $(SRC_RASDUMP:%.cpp=%.o) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index 676c166..793a95e 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -1346,20 +1346,20 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Get changeable flag if ((cdb[2] & 0xc0) == 0x40) { - printf("MODESENSE: Change = TRUE\n"); + //** printf("MODESENSE: Change = TRUE\n"); change = TRUE; } else { - printf("MODESENSE: Change = FALSE\n"); + //** printf("MODESENSE: Change = FALSE\n"); change = FALSE; } // Get page code (0x00 is valid from the beginning) page = cdb[2] & 0x3f; if (page == 0x00) { - printf("MODESENSE: Page code: OK %02X\n", cdb[2]); + //** printf("MODESENSE: Page code: OK %02X\n", cdb[2]); valid = TRUE; } else { - printf("MODESENSE: Invalid page code received %02X\n", cdb[2]); + //** printf("MODESENSE: Invalid page code received %02X\n", cdb[2]); valid = FALSE; } @@ -1373,7 +1373,7 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // DEVICE SPECIFIC PARAMETER if (disk.writep) { - printf("MODESENSE: Write protect\n"); + //** printf("MODESENSE: Write protect\n"); buf[2] = 0x80; } @@ -1384,7 +1384,7 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Only if ready if (disk.ready) { - printf("MODESENSE: Disk is ready\n"); + //** printf("MODESENSE: Disk is ready\n"); // Block descriptor (number of blocks) buf[5] = (BYTE)(disk.blocks >> 16); buf[6] = (BYTE)(disk.blocks >> 8); @@ -1461,12 +1461,12 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Unsupported page if (!valid) { - printf("MODESENSE: Something was invalid...\n"); + //** printf("MODESENSE: Something was invalid...\n"); disk.code = DISK_INVALIDCDB; return 0; } - printf("MODESENSE: mode sense length is %d\n",length); + //** printf("MODESENSE: mode sense length is %d\n",length); // MODE SENSE success disk.code = DISK_NOERROR; @@ -6474,12 +6474,12 @@ void FASTCALL SASIDEV::Command() #ifdef RASCSI // Command reception handshake (10 bytes are automatically received at the first command) count = ctrl.bus->CommandHandShake(ctrl.buffer); - printf("Command received: " ); - for(int i=0; i< count; i++) - { - printf("%02X ", ctrl.buffer[i]); - } - printf("\n"); + //** printf("Command received: " ); + //** for(int i=0; i< count; i++) + //** { + //** printf("%02X ", ctrl.buffer[i]); + //** } + //** printf("\n"); // If no byte can be received move to the status phase if (count == 0) { @@ -7436,7 +7436,7 @@ void FASTCALL SASIDEV::Send() if (ctrl.blocks != 0) { // Set next buffer (set offset, length) result = XferIn(ctrl.buffer); - printf("xfer in: %d \n",result); + //** printf("xfer in: %d \n",result); #ifndef RASCSI ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); @@ -7713,12 +7713,12 @@ BOOL FASTCALL SASIDEV::XferIn(BYTE *buf) ctrl.length = ctrl.unit[lun]->Read(buf, ctrl.next); ctrl.next++; - printf("XferIn read data from disk: "); - for (int i=0; i> 5) & 0x07; diff --git a/src/raspberrypi/scsimon.cpp b/src/raspberrypi/scsimon.cpp deleted file mode 100644 index 3bdf95b..0000000 --- a/src/raspberrypi/scsimon.cpp +++ /dev/null @@ -1,1174 +0,0 @@ -//--------------------------------------------------------------------------- -// -// SCSI Target Emulator RaSCSI (*^..^*) -// for Raspberry Pi -// -// Powered by XM6 TypeG Technology. -// Copyright (C) 2016-2020 GIMONS -// [ RaSCSI main ] -// -//--------------------------------------------------------------------------- - -#include "os.h" -#include "xm6.h" -#include "filepath.h" -#include "fileio.h" -#include "disk.h" -#include "gpiobus.h" - -//--------------------------------------------------------------------------- -// -// 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 -// -//--------------------------------------------------------------------------- -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 -FATFS fatfs; // FatFS -#else -int monsocket; // Monitor Socket -pthread_t monthread; // Monitor Thread -static void *MonThread(void *param); -#endif // BAREMETAL - -#ifndef BAREMETAL -//--------------------------------------------------------------------------- -// -// Signal Processing -// -//--------------------------------------------------------------------------- -void KillHandler(int sig) -{ - // Stop instruction - running = FALSE; -} -#endif // BAREMETAL - -//--------------------------------------------------------------------------- -// -// Banner Output -// -//--------------------------------------------------------------------------- -void Banner(int argc, char* argv[]) -{ - FPRT(stdout,"SCSI Target Emulator RaSCSI(*^..^*) "); - FPRT(stdout,"version %01d.%01d%01d(%s, %s)\n", - (int)((VERSION >> 8) & 0xf), - (int)((VERSION >> 4) & 0xf), - (int)((VERSION ) & 0xf), - __DATE__, - __TIME__); - FPRT(stdout,"Powered by XM6 TypeG Technology / "); - FPRT(stdout,"Copyright (C) 2016-2020 GIMONS\n"); - FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); - - if (argc > 1 && strcmp(argv[1], "-h") == 0) { - FPRT(stdout,"\n"); - FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); - FPRT(stdout," n is SCSI identification number(0-7).\n"); - FPRT(stdout," FILE is disk image file.\n\n"); - FPRT(stdout,"Usage: %s [-HDn FILE] ...\n\n", argv[0]); - FPRT(stdout," n is X68000 SASI HD number(0-15).\n"); - FPRT(stdout," FILE is disk image file.\n\n"); - FPRT(stdout," Image type is detected based on file extension.\n"); - FPRT(stdout," hdf : SASI HD image(XM6 SASI HD image)\n"); - FPRT(stdout," hds : SCSI HD image(XM6 SCSI HD image)\n"); - FPRT(stdout," hdn : SCSI HD image(NEC GENUINE)\n"); - FPRT(stdout," hdi : SCSI HD image(Anex86 HD image)\n"); - FPRT(stdout," nhd : SCSI HD image(T98Next HD image)\n"); - FPRT(stdout," hda : SCSI HD image(APPLE GENUINE)\n"); - FPRT(stdout," mos : SCSI MO image(XM6 SCSI MO image)\n"); - FPRT(stdout," iso : SCSI CD image(ISO 9660 image)\n"); - -#ifndef BAREMETAL - exit(0); -#endif // BAREMETAL - } -} - -//--------------------------------------------------------------------------- -// -// Initialization -// -//--------------------------------------------------------------------------- -BOOL Init() -{ - int i; - -#ifndef BAREMETAL - struct sockaddr_in server; - int yes; - - // Create socket for monitor - monsocket = socket(PF_INET, SOCK_STREAM, 0); - memset(&server, 0, sizeof(server)); - server.sin_family = PF_INET; - server.sin_port = htons(6868); - server.sin_addr.s_addr = htonl(INADDR_ANY); - - // allow address reuse - yes = 1; - if (setsockopt( - monsocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0){ - return FALSE; - } - - // Bind - if (bind(monsocket, (struct sockaddr *)&server, - sizeof(struct sockaddr_in)) < 0) { - FPRT(stderr, "Error : Already running?\n"); - return FALSE; - } - - // Create Monitor Thread - pthread_create(&monthread, NULL, MonThread, NULL); - - // Interrupt handler settings - if (signal(SIGINT, KillHandler) == SIG_ERR) { - return FALSE; - } - if (signal(SIGHUP, KillHandler) == SIG_ERR) { - return FALSE; - } - if (signal(SIGTERM, KillHandler) == SIG_ERR) { - return FALSE; - } -#endif // BAREMETAL - - // GPIOBUS creation - bus = new GPIOBUS(); - - // GPIO Initialization - if (!bus->Init(BUS::MONITOR)) { - return FALSE; - } - - // Bus Reset - bus->Reset(); - bus->SetIO(FALSE); - - // 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; - - return TRUE; -} - -//--------------------------------------------------------------------------- -// -// Cleanup -// -//--------------------------------------------------------------------------- -void Cleanup() -{ - 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 - // Close the monitor socket - if (monsocket >= 0) { - close(monsocket); - } -#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; - BOOL is_monitor; - - // 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]) { - // Check to see if we need a standard SCSI controller - // or if we are creating a "monitor" controller - is_monitor = FALSE; - for (j = 0; j < UnitNum; j++) - { - unitno = i * UnitNum + j; - if( disk[unitno] && disk[unitno]->IsMonitor()) - { - is_monitor = TRUE; - break; - } - } - if(is_monitor == TRUE) - { - ctrl[i] = new SCSIMONDEV(); - } - else - { - 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]); - } - } - } -} - -//--------------------------------------------------------------------------- -// -// Command Processing -// -//--------------------------------------------------------------------------- -BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file) -{ - Disk *map[CtrlMax * UnitNum]; - int len; - char *ext; - Filepath filepath; - Disk *pUnit; - - // Copy the Unit List - memcpy(map, disk, sizeof(disk)); - - // Check the Controller Number - if (id < 0 || id >= CtrlMax) { - FPRT(fp, "Error : Invalid ID\n"); - return FALSE; - } - - // Check the Unit Number - if (un < 0 || un >= UnitNum) { - FPRT(fp, "Error : Invalid unit number\n"); - return FALSE; - } - - // Connect Command - if (cmd == 0) { // ATTACH - // Distinguish between SASI and SCSI - ext = NULL; - pUnit = NULL; - 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; - } - } - - // Create a new drive, based upon type - switch (type) { - case 0: // HDF - pUnit = new SASIHD(); - break; - case 1: // HDS/HDN/HDI/NHD/HDA - if (ext == NULL) { - break; - } - if (xstrcasecmp(ext, "hdn") == 0 || - xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0) { - pUnit = new SCSIHD_NEC(); - } else if (xstrcasecmp(ext, "hda") == 0) { - pUnit = new SCSIHD_APPLE(); - } else { - pUnit = new SCSIHD(); - } - break; - case 2: // MO - pUnit = new SCSIMO(); - break; - case 3: // CD - pUnit = new SCSICD(); - break; - case 4: // BRIDGE - pUnit = new SCSIBR(); - break; - case 5: // Logger/Monitor device - pUnit = new MONITORHD(); - break; - default: - FPRT(fp, "Error : Invalid device type\n"); - return FALSE; - } - - // drive checks files - if (type <= 1 || (type <= 3 && xstrcasecmp(file, "-") != 0)) { - // Set the Path - filepath.SetPath(file); - - // Open the file path - if (!pUnit->Open(filepath)) { - FPRT(fp, "Error : File open error [%s]\n", file); - delete pUnit; - return FALSE; - } - } - - // Set the cache to write-through - pUnit->SetCacheWB(FALSE); - - // Replace with the newly created unit - map[id * UnitNum + un] = pUnit; - - // Re-map the controller - MapControler(fp, map); - return TRUE; - } - - // Is this a valid command? - if (cmd > 4) { - FPRT(fp, "Error : Invalid command\n"); - return FALSE; - } - - // Does the controller exist? - if (ctrl[id] == NULL) { - FPRT(fp, "Error : No such device\n"); - return FALSE; - } - - // Does the unit exist? - pUnit = disk[id * 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 * UnitNum + un] = NULL; - - // Re-map the controller - MapControler(fp, map); - return TRUE; - } - - // Valid only for MO or CD - if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O') && - pUnit->GetID() != MAKEID('S', 'C', 'C', 'D')) { - FPRT(fp, "Error : Operation denied(Deveice isn't removable)\n"); - return FALSE; - } - - switch (cmd) { - case 2: // INSERT - // Set the file path - filepath.SetPath(file); - - // Open the file - if (pUnit->Open(filepath)) { - FPRT(fp, "Error : File open error [%s]\n", file); - return FALSE; - } - break; - - case 3: // EJECT - pUnit->Eject(TRUE); - break; - - case 4: // PROTECT - if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O')) { - FPRT(fp, "Error : Operation denied(Deveice isn't MO)\n"); - return FALSE; - } - pUnit->WriteP(!pUnit->IsWriteP()); - break; - default: - ASSERT(FALSE); - return FALSE; - } - - return TRUE; -} - -//--------------------------------------------------------------------------- -// -// Argument Parsing -// -//--------------------------------------------------------------------------- -BOOL ParseArgument(int argc, char* argv[]) -{ -#ifdef BAREMETAL - FRESULT fr; - FIL fp; - char line[512]; -#else - int i; -#endif // BAREMETAL - int id; - int un; - int type; - char *argID; - char *argPath; - int len; - char *ext; - -#ifdef BAREMETAL - // Mount the SD card - fr = f_mount(&fatfs, "", 1); - if (fr != FR_OK) { - FPRT(stderr, "Error : SD card mount failed.\n"); - return FALSE; - } - - // If there is no setting file, the processing is interrupted - fr = f_open(&fp, "rascsi.ini", FA_READ); - if (fr != FR_OK) { - return FALSE; - } -#else - // If the ID and path are not specified, the processing is interrupted - if (argc < 3) { - return TRUE; - } - i = 1; - argc--; -#endif // BAREMETAL - - // Start Decoding - - while (TRUE) { -#ifdef BAREMETAL - // Get one Line - memset(line, 0x00, sizeof(line)); - if (f_gets(line, sizeof(line) -1, &fp) == NULL) { - break; - } - - // Delete the CR/LF - len = strlen(line); - while (len > 0) { - if (line[len - 1] != '\r' && line[len - 1] != '\n') { - break; - } - line[len - 1] = '\0'; - len--; - } -#else - if (argc < 2) { - break; - } - - argc -= 2; -#endif // BAREMETAL - - // Get the ID and Path -#ifdef BAREMETAL - argID = &line[0]; - argPath = &line[4]; - line[3] = '\0'; - - // Check if the line is an empty string - if (argID[0] == '\0' || argPath[0] == '\0') { - continue; - } -#else - argID = argv[i++]; - argPath = argv[i++]; - - // Check if the argument is invalid - if (argID[0] != '-') { - FPRT(stderr, - "Error : Invalid argument(-IDn or -HDn) [%s]\n", argID); - goto parse_error; - } - argID++; -#endif // BAREMETAL - - if (strlen(argID) == 3 && xstrncasecmp(argID, "id", 2) == 0) { - // ID or ID Format - - // Check that the ID number is valid (0-7) - if (argID[2] < '0' || argID[2] > '7') { - FPRT(stderr, - "Error : Invalid argument(IDn n=0-7) [%c]\n", argID[2]); - goto parse_error; - } - - // The ID unit is good - id = argID[2] - '0'; - un = 0; - } else if (xstrncasecmp(argID, "hd", 2) == 0) { - // HD or HD format - - if (strlen(argID) == 3) { - // Check that the HD number is valid (0-9) - if (argID[2] < '0' || argID[2] > '9') { - FPRT(stderr, - "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); - goto parse_error; - } - - // ID was confirmed - id = (argID[2] - '0') / UnitNum; - un = (argID[2] - '0') % UnitNum; - } else if (strlen(argID) == 4) { - // Check that the HD number is valid (10-15) - if (argID[2] != '1' || argID[3] < '0' || argID[3] > '5') { - FPRT(stderr, - "Error : Invalid argument(HDn n=0-15) [%c]\n", argID[2]); - goto parse_error; - } - - // The ID unit is good - create the id and unit number - id = ((argID[3] - '0') + 10) / UnitNum; - un = ((argID[3] - '0') + 10) % UnitNum; -#ifdef BAREMETAL - argPath++; -#endif // BAREMETAL - } else { - FPRT(stderr, - "Error : Invalid argument(IDn or HDn) [%s]\n", argID); - goto parse_error; - } - } else { - FPRT(stderr, - "Error : Invalid argument(IDn or HDn) [%s]\n", argID); - goto parse_error; - } - - // Skip if there is already an active device - if (disk[id * UnitNum + un] && - !disk[id * UnitNum + un]->IsNULL()) { - continue; - } - - // Initialize device type - type = -1; - - // Check ethernet and host bridge - if (xstrcasecmp(argPath, "bridge") == 0) { - type = 4; - } else if (xstrcasecmp(argPath, "monitor") == 0){ - type = 5; - } else { - // Check the path length - len = strlen(argPath); - if (len < 5) { - FPRT(stderr, - "Error : Invalid argument(File path is short) [%s]\n", - argPath); - goto parse_error; - } - - // Does the file have an extension? - if (argPath[len - 4] != '.') { - FPRT(stderr, - "Error : Invalid argument(No extension) [%s]\n", argPath); - goto parse_error; - } - - // Figure out what the type is - ext = &argPath[len - 3]; - if (xstrcasecmp(ext, "hdf") == 0 || - xstrcasecmp(ext, "hds") == 0 || - xstrcasecmp(ext, "hdn") == 0 || - xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 || - xstrcasecmp(ext, "hda") == 0) { - // HD(SASI/SCSI) - type = 0; - } else if (strcasecmp(ext, "mos") == 0) { - // MO - type = 2; - } else if (strcasecmp(ext, "iso") == 0) { - // CD - type = 3; - } else { - // Cannot determine the file type - FPRT(stderr, - "Error : Invalid argument(file type) [%s]\n", ext); - goto parse_error; - } - } - - // Execute the command - if (!ProcessCmd(stderr, id, un, 0, type, argPath)) { - goto parse_error; - } - } - -#ifdef BAREMETAL - // Close the configuration file - f_close(&fp); -#endif // BAREMETAL - - // Display the device list - ListDevice(stdout); - - return TRUE; - -parse_error: - -#ifdef BAREMETAL - // Close the configuration file - f_close(&fp); -#endif // BAREMETAL - - return FALSE; -} - -#ifndef BAREMETAL -//--------------------------------------------------------------------------- -// -// Pin the thread to a specific CPU -// -//--------------------------------------------------------------------------- -void FixCpu(int cpu) -{ - cpu_set_t cpuset; - int cpus; - - // Get the number of CPUs - CPU_ZERO(&cpuset); - sched_getaffinity(0, sizeof(cpu_set_t), &cpuset); - cpus = CPU_COUNT(&cpuset); - - // Set the thread affinity - if (cpu < cpus) { - CPU_ZERO(&cpuset); - CPU_SET(cpu, &cpuset); - sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); - } -} - -//--------------------------------------------------------------------------- -// -// Monitor Thread -// -//--------------------------------------------------------------------------- -static void *MonThread(void *param) -{ - struct sched_param schedparam; - struct sockaddr_in client; - socklen_t len; - int fd; - FILE *fp; - char buf[BUFSIZ]; - char *p; - int i; - char *argv[5]; - int id; - int un; - int cmd; - int type; - char *file; - - // Scheduler Settings - schedparam.sched_priority = 0; - sched_setscheduler(0, SCHED_IDLE, &schedparam); - - // Set the affinity to a specific processor core - FixCpu(2); - - // Wait for the execution to start - while (!running) { - usleep(1); - } - - // Setup the monitor socket to receive commands - listen(monsocket, 1); - - while (1) { - // Wait for connection - memset(&client, 0, sizeof(client)); - len = sizeof(client); - fd = accept(monsocket, (struct sockaddr*)&client, &len); - if (fd < 0) { - break; - } - - // Fetch the command - fp = fdopen(fd, "r+"); - p = fgets(buf, BUFSIZ, fp); - - // Failed to get the command - if (!p) { - goto next; - } - - // Remove the newline character - p[strlen(p) - 1] = 0; - - // List all of the devices - if (xstrncasecmp(p, "list", 4) == 0) { - ListDevice(fp); - goto next; - } - - // Parameter separation - argv[0] = p; - for (i = 1; i < 5; i++) { - // Skip parameter values - while (*p && (*p != ' ')) { - p++; - } - - // Replace spaces with null characters - while (*p && (*p == ' ')) { - *p++ = 0; - } - - // The parameters were lost - if (!*p) { - break; - } - - // Recognized as a parameter - argv[i] = p; - } - - // Failed to get all parameters - if (i < 5) { - goto next; - } - - // ID, unit, command, type, file - id = atoi(argv[0]); - un = atoi(argv[1]); - cmd = atoi(argv[2]); - type = atoi(argv[3]); - file = argv[4]; - - // Wait until we becom idle - while (active) { - usleep(500 * 1000); - } - - // Execute the command - ProcessCmd(fp, id, un, cmd, type, file); - -next: - // Release the connection - fclose(fp); - close(fd); - } - - return NULL; -} -#endif // BAREMETAL - -//--------------------------------------------------------------------------- -// -// Main processing -// -//--------------------------------------------------------------------------- -#ifdef BAREMETAL -extern "C" -int startrascsi(void) -{ - int argc = 0; - char** argv = NULL; -#else -int main(int argc, char* argv[]) -{ -#endif // BAREMETAL - int i; - int ret; - int actid; - DWORD now; - BUS::phase_t phase; - BYTE data; -#ifndef BAREMETAL - struct sched_param schparam; -#endif // BAREMETAL - - // Output the Banner - Banner(argc, argv); - - // Initialize - ret = 0; - if (!Init()) { - ret = EPERM; - goto init_exit; - } - - // Reset - Reset(); - -#ifdef BAREMETAL - // BUSY assert (to hold the host side) - bus->SetBSY(TRUE); -#endif - - // Argument parsing - if (!ParseArgument(argc, argv)) { - ret = EINVAL; - goto err_exit; - } - -#ifdef BAREMETAL - // Release the busy signal - bus->SetBSY(FALSE); -#endif - -#ifndef BAREMETAL - // Set the affinity to a specific processor core - FixCpu(3); - -#ifdef USE_SEL_EVENT_ENABLE - // 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 -#endif // BAREMETAL - - // Start execution - running = TRUE; - - // Main Loop - while (running) { - // Work initialization - 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; - } - -err_exit: - // Cleanup - Cleanup(); - -init_exit: -#if !defined(BAREMETAL) - exit(ret); -#else - return ret; -#endif // BAREMETAL -} diff --git a/src/raspberrypi/scsimondev.cpp b/src/raspberrypi/scsimondev.cpp deleted file mode 100644 index c6185fb..0000000 --- a/src/raspberrypi/scsimondev.cpp +++ /dev/null @@ -1,1902 +0,0 @@ -//--------------------------------------------------------------------------- -// -// X68000 EMULATOR "XM6" -// -// Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) -// Copyright (C) 2014-2020 GIMONS -// -// XM6i -// Copyright (C) 2010-2015 isaki@NetBSD.org -// Copyright (C) 2010 Y.Sugahara -// -// Imported sava's Anex86/T98Next image and MO format support patch. -// Imported NetBSD support and some optimisation patch by Rin Okuyama. -// Comments translated to english by akuker. -// -// [ SCSI Monitor Device] -// -//--------------------------------------------------------------------------- - -#include "os.h" -#include "xm6.h" -#include "filepath.h" -#include "fileio.h" -#ifdef RASCSI -#include "gpiobus.h" -#ifndef BAREMETAL -#include "ctapdriver.h" -#endif // BAREMETAL -#include "cfilesystem.h" -#include "disk.h" -#else -#include "vm.h" -#include "disk.h" -#include "windrv.h" -#include "ctapdriver.h" -#include "mfc_com.h" -#include "mfc_host.h" -#endif // RASCSI - -// Temporary? Trick to make the ID understand that RASCSI is set -#ifndef RASCSI -#define RASCSI -#endif // RASCSI - -//=========================================================================== -// -// SCSI Device -// -//=========================================================================== - -//--------------------------------------------------------------------------- -// -// Constructor -// -//--------------------------------------------------------------------------- -#ifdef RASCSI -SCSIMONDEV::SCSIMONDEV() : SASIDEV() -#else -SCSIMONDEV::SCSIMONDEV(Device *dev) : SASIDEV(dev) -#endif -{ - // Synchronous transfer work initialization - scsi.syncenable = FALSE; - scsi.syncperiod = 50; - scsi.syncoffset = 0; - scsi.atnmsg = FALSE; - scsi.msc = 0; - memset(scsi.msb, 0x00, sizeof(scsi.msb)); -} - -//--------------------------------------------------------------------------- -// -// Device reset -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Reset() -{ - ASSERT(this); - - // Work initialization - scsi.atnmsg = FALSE; - scsi.msc = 0; - memset(scsi.msb, 0x00, sizeof(scsi.msb)); - - // Base class - SASIDEV::Reset(); -} - -//--------------------------------------------------------------------------- -// -// Process -// -//--------------------------------------------------------------------------- -BUS::phase_t FASTCALL SCSIMONDEV::Process() -{ - ASSERT(this); - printf("SCSIMONDEV::Process() %d\n", ctrl.id); - - // Do nothing if not connected - if (ctrl.id < 0 || ctrl.bus == NULL) { - return ctrl.phase; - } - - // Get bus information - ctrl.bus->Aquire(); - - // Reset - if (ctrl.bus->GetRST()) { -#if defined(DISK_LOG) - Log(Log::Normal, "RESET信号受信"); -#endif // DISK_LOG - - // Reset the controller - Reset(); - - // Reset the bus - ctrl.bus->Reset(); - return ctrl.phase; - } - - // Phase processing - switch (ctrl.phase) { - // Bus free phase - case BUS::busfree: - BusFree(); - break; - - // Selection phase - case BUS::selection: - Selection(); - break; - - // Data out (MCI=000) - case BUS::dataout: - DataOut(); - break; - - // Data in (MCI=001) - case BUS::datain: - DataIn(); - break; - - // Command (MCI=010) - case BUS::command: - Command(); - break; - - // Status (MCI=011) - case BUS::status: - Status(); - break; - - // Message out (MCI=110) - case BUS::msgout: - MsgOut(); - break; - - // Message in (MCI=111) - case BUS::msgin: - MsgIn(); - break; - - // Other - default: - ASSERT(FALSE); - break; - } - - return ctrl.phase; -} - -//--------------------------------------------------------------------------- -// -// Phaes -// -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// -// Bus free phase -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::BusFree() -{ - ASSERT(this); - - // Phase change - if (ctrl.phase != BUS::busfree) { - -#if defined(DISK_LOG) - Log(Log::Normal, "Bus free phase"); -#endif // DISK_LOG - - // Phase setting - ctrl.phase = BUS::busfree; - -//////// // Signal line -//////// ctrl.bus->SetREQ(FALSE); -//////// ctrl.bus->SetMSG(FALSE); -//////// ctrl.bus->SetCD(FALSE); -//////// ctrl.bus->SetIO(FALSE); -//////// ctrl.bus->SetBSY(FALSE); - - // Initialize status and message - ctrl.status = 0x00; - ctrl.message = 0x00; - - // Initialize ATN message reception status - scsi.atnmsg = FALSE; - return; - } - - // Move to selection phase - if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { - Selection(); - } -} - -//--------------------------------------------------------------------------- -// -// Selection Phase -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Selection() -{ - DWORD id; - - ASSERT(this); - - // Phase change - if (ctrl.phase != BUS::selection) { - // invalid if IDs do not match - id = 1 << ctrl.id; - if ((ctrl.bus->GetDAT() & id) == 0) { - return; - } - - // End if there is no valid unit - if (!HasUnit()) { - return; - } - -#if defined(DISK_LOG) - Log(Log::Normal, - "Selection Phase ID=%d (with device)", ctrl.id); -#endif // DISK_LOG - - // Phase setting - ctrl.phase = BUS::selection; - - // Raise BSY and respond - ctrl.bus->SetBSY(TRUE); - return; - } - - // Selection completed - if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { - // Message out phase if ATN=1, otherwise command phase - if (ctrl.bus->GetATN()) { - MsgOut(); - } else { - Command(); - } - } -} - -//--------------------------------------------------------------------------- -// -// Execution Phase -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Execute() -{ - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "Execution phase command $%02X", ctrl.cmd[0]); -#endif // DISK_LOG - - // Phase Setting - ctrl.phase = BUS::execute; - - // Initialization for data transfer - ctrl.offset = 0; - ctrl.blocks = 1; -#ifdef RASCSI - ctrl.execstart = SysTimer::GetTimerLow(); -#endif // RASCSI - - // Process by command - switch (ctrl.cmd[0]) { - // TEST UNIT READY - case 0x00: - CmdTestUnitReady(); - return; - - // REZERO - case 0x01: - CmdRezero(); - return; - - // REQUEST SENSE - case 0x03: - CmdRequestSense(); - return; - - // FORMAT UNIT - case 0x04: - CmdFormat(); - return; - - // REASSIGN BLOCKS - case 0x07: - CmdReassign(); - return; - - // READ(6) - case 0x08: - CmdRead6(); - return; - - // WRITE(6) - case 0x0a: - CmdWrite6(); - return; - - // SEEK(6) - case 0x0b: - CmdSeek6(); - return; - - // INQUIRY - case 0x12: - CmdInquiry(); - return; - - // MODE SELECT - case 0x15: - CmdModeSelect(); - return; - - // MDOE SENSE - case 0x1a: - CmdModeSense(); - return; - - // START STOP UNIT - case 0x1b: - CmdStartStop(); - return; - - // SEND DIAGNOSTIC - case 0x1d: - CmdSendDiag(); - return; - - // PREVENT/ALLOW MEDIUM REMOVAL - case 0x1e: - CmdRemoval(); - return; - - // READ CAPACITY - case 0x25: - CmdReadCapacity(); - return; - - // READ(10) - case 0x28: - CmdRead10(); - return; - - // WRITE(10) - case 0x2a: - CmdWrite10(); - return; - - // SEEK(10) - case 0x2b: - CmdSeek10(); - return; - - // WRITE and VERIFY - case 0x2e: - CmdWrite10(); - return; - - // VERIFY - case 0x2f: - CmdVerify(); - return; - - // SYNCHRONIZE CACHE - case 0x35: - CmdSynchronizeCache(); - return; - - // READ DEFECT DATA(10) - case 0x37: - CmdReadDefectData10(); - return; - - // READ TOC - case 0x43: - CmdReadToc(); - return; - - // PLAY AUDIO(10) - case 0x45: - CmdPlayAudio10(); - return; - - // PLAY AUDIO MSF - case 0x47: - CmdPlayAudioMSF(); - return; - - // PLAY AUDIO TRACK - case 0x48: - CmdPlayAudioTrack(); - return; - - // MODE SELECT(10) - case 0x55: - CmdModeSelect10(); - return; - - // MDOE SENSE(10) - case 0x5a: - CmdModeSense10(); - return; - - // SPECIFY (SASI only/Suppress warning when using SxSI) - case 0xc2: - CmdInvalid(); - return; - - } - - // No other support - Log(Log::Normal, "Unsupported command received: $%02X", ctrl.cmd[0]); - CmdInvalid(); -} - -//--------------------------------------------------------------------------- -// -// Message out phase -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::MsgOut() -{ - ASSERT(this); - - // Phase change - if (ctrl.phase != BUS::msgout) { - -#if defined(DISK_LOG) - Log(Log::Normal, "Message Out Phase"); -#endif // DISK_LOG - - // Message out phase after selection - // process the IDENTIFY message - if (ctrl.phase == BUS::selection) { - scsi.atnmsg = TRUE; - scsi.msc = 0; - memset(scsi.msb, 0x00, sizeof(scsi.msb)); - } - - // Phase Setting - ctrl.phase = BUS::msgout; - -//////// // Signal line operated by the target -//////// ctrl.bus->SetMSG(TRUE); -//////// ctrl.bus->SetCD(TRUE); -//////// ctrl.bus->SetIO(FALSE); - - // Data transfer is 1 byte x 1 block - ctrl.offset = 0; - ctrl.length = 1; - ctrl.blocks = 1; - -#ifndef RASCSI - // Request message - ctrl.bus->SetREQ(TRUE); -#endif // RASCSI - return; - } - -#ifdef RASCSI - // Receive - Receive(); -#else - // Requesting - if (ctrl.bus->GetREQ()) { - // Sent by the initiator - if (ctrl.bus->GetACK()) { - Receive(); - } - } else { - // Request the initator to - if (!ctrl.bus->GetACK()) { - ReceiveNext(); - } - } -#endif // RASCSI -} - -//--------------------------------------------------------------------------- -// -// Common Error Handling -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Error() -{ - ASSERT(this); - - // Get bus information - ctrl.bus->Aquire(); - - // Reset check - if (ctrl.bus->GetRST()) { - // Reset the controller - Reset(); - - // Reset the bus - ctrl.bus->Reset(); - return; - } - - // Bus free for status phase and message in phase - if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { - BusFree(); - return; - } - -#if defined(DISK_LOG) - Log(Log::Normal, "Error (to status phase)"); -#endif // DISK_LOG - - // Set status and message(CHECK CONDITION) - ctrl.status = 0x02; - ctrl.message = 0x00; - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// Command -// -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// -// INQUIRY -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdInquiry() -{ - Disk *disk; - int lun; - DWORD major; - DWORD minor; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "INQUIRY Command"); -#endif // DISK_LOG - - // Find a valid unit - disk = NULL; - for (lun = 0; lun < UnitMax; lun++) { - if (ctrl.unit[lun]) { - disk = ctrl.unit[lun]; - break; - } - } - - // Processed on the disk side (it is originally processed by the controller) - if (disk) { -#ifdef RASCSI - major = (DWORD)(RASCSI >> 8); - minor = (DWORD)(RASCSI & 0xff); -#else - host->GetVM()->GetVersion(major, minor); -#endif // RASCSI - ctrl.length = - ctrl.unit[lun]->Inquiry(ctrl.cmd, ctrl.buffer, major, minor); - } else { - ctrl.length = 0; - } - - if (ctrl.length <= 0) { - // failure (error) - Error(); - return; - } - - // Add synchronous transfer support information - if (scsi.syncenable) { - ctrl.buffer[7] |= (1 << 4); - } - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// MODE SELECT -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdModeSelect() -{ - DWORD lun; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "MODE SELECT Command"); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->SelectCheck(ctrl.cmd); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Data out phase - DataOut(); -} - -//--------------------------------------------------------------------------- -// -// MODE SENSE -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdModeSense() -{ - DWORD lun; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "MODE SENSE Command "); -#endif // DISK_LOG - - printf("Received a Mode Sense command. Contents...."); - for(int i=0; i<10; i++) - { - printf("%08X ", ctrl.cmd[i]); - } - printf("\n"); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->ModeSense(ctrl.cmd, ctrl.buffer); - ASSERT(ctrl.length >= 0); - if (ctrl.length == 0) { - Log(Log::Warning, - "Not supported MODE SENSE page $%02X", ctrl.cmd[2]); - - // Failure (Error) - Error(); - return; - } - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// START STOP UNIT -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdStartStop() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "START STOP UNIT Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->StartStop(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// SEND DIAGNOSTIC -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdSendDiag() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "SEND DIAGNOSTIC Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->SendDiag(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// PREVENT/ALLOW MEDIUM REMOVAL -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdRemoval() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "PREVENT/ALLOW MEDIUM REMOVAL Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->Removal(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// READ CAPACITY -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdReadCapacity() -{ - DWORD lun; - int length; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "READ CAPACITY Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - length = ctrl.unit[lun]->ReadCapacity(ctrl.cmd, ctrl.buffer); - ASSERT(length >= 0); - if (length <= 0) { - Error(); - return; - } - - // Length setting - ctrl.length = length; - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// READ(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdRead10() -{ - DWORD lun; - DWORD record; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Receive message if host bridge - if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { - CmdGetMessage10(); - return; - } - - // Get record number and block number - record = ctrl.cmd[2]; - record <<= 8; - record |= ctrl.cmd[3]; - record <<= 8; - record |= ctrl.cmd[4]; - record <<= 8; - record |= ctrl.cmd[5]; - ctrl.blocks = ctrl.cmd[7]; - ctrl.blocks <<= 8; - ctrl.blocks |= ctrl.cmd[8]; - -#if defined(DISK_LOG) - Log(Log::Normal, "READ(10) command record=%08X block=%d", record, ctrl.blocks); -#endif // DISK_LOG - - // Do not process 0 blocks - if (ctrl.blocks == 0) { - Status(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.next = record + 1; - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// WRITE(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdWrite10() -{ - DWORD lun; - DWORD record; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Receive message with host bridge - if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { - CmdSendMessage10(); - return; - } - - // Get record number and block number - record = ctrl.cmd[2]; - record <<= 8; - record |= ctrl.cmd[3]; - record <<= 8; - record |= ctrl.cmd[4]; - record <<= 8; - record |= ctrl.cmd[5]; - ctrl.blocks = ctrl.cmd[7]; - ctrl.blocks <<= 8; - ctrl.blocks |= ctrl.cmd[8]; - -#if defined(DISK_LOG) - Log(Log::Normal, - "WRTIE(10) command record=%08X blocks=%d", record, ctrl.blocks); -#endif // DISK_LOG - - // Do not process 0 blocks - if (ctrl.blocks == 0) { - Status(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->WriteCheck(record); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.next = record + 1; - - // Data out phase - DataOut(); -} - -//--------------------------------------------------------------------------- -// -// SEEK(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdSeek10() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "SEEK(10) Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->Seek(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// VERIFY -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdVerify() -{ - DWORD lun; - BOOL status; - DWORD record; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Get record number and block number - record = ctrl.cmd[2]; - record <<= 8; - record |= ctrl.cmd[3]; - record <<= 8; - record |= ctrl.cmd[4]; - record <<= 8; - record |= ctrl.cmd[5]; - ctrl.blocks = ctrl.cmd[7]; - ctrl.blocks <<= 8; - ctrl.blocks |= ctrl.cmd[8]; - -#if defined(DISK_LOG) - Log(Log::Normal, - "VERIFY command record=%08X blocks=%d", record, ctrl.blocks); -#endif // DISK_LOG - - // Do not process 0 blocks - if (ctrl.blocks == 0) { - Status(); - return; - } - - // if BytChk=0 - if ((ctrl.cmd[1] & 0x02) == 0) { - // Command processing on drive - status = ctrl.unit[lun]->Seek(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); - return; - } - - // Test loading - ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.next = record + 1; - - // Data out phase - DataOut(); -} - -//--------------------------------------------------------------------------- -// -// SYNCHRONIZE CACHE -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdSynchronizeCache() -{ - DWORD lun; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Make it do something (not implemented)... - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// READ DEFECT DATA(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdReadDefectData10() -{ - DWORD lun; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "READ DEFECT DATA(10) Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->ReadDefectData10(ctrl.cmd, ctrl.buffer); - ASSERT(ctrl.length >= 0); - - if (ctrl.length <= 4) { - Error(); - return; - } - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// READ TOC -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdReadToc() -{ - DWORD lun; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->ReadToc(ctrl.cmd, ctrl.buffer); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// PLAY AUDIO(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdPlayAudio10() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->PlayAudio(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// PLAY AUDIO MSF -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdPlayAudioMSF() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->PlayAudioMSF(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// PLAY AUDIO TRACK -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdPlayAudioTrack() -{ - DWORD lun; - BOOL status; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - status = ctrl.unit[lun]->PlayAudioTrack(ctrl.cmd); - if (!status) { - // Failure (Error) - Error(); - return; - } - - // status phase - Status(); -} - -//--------------------------------------------------------------------------- -// -// MODE SELECT10 -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdModeSelect10() -{ - DWORD lun; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "MODE SELECT10 Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->SelectCheck10(ctrl.cmd); - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Data out phase - DataOut(); -} - -//--------------------------------------------------------------------------- -// -// MODE SENSE(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdModeSense10() -{ - DWORD lun; - - ASSERT(this); - -#if defined(DISK_LOG) - Log(Log::Normal, "MODE SENSE(10) Command "); -#endif // DISK_LOG - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Command processing on drive - ctrl.length = ctrl.unit[lun]->ModeSense10(ctrl.cmd, ctrl.buffer); - ASSERT(ctrl.length >= 0); - if (ctrl.length == 0) { - Log(Log::Warning, - "Not supported MODE SENSE(10) page $%02X", ctrl.cmd[2]); - - // Failure (Error) - Error(); - return; - } - - // Data-in Phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// GET MESSAGE(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdGetMessage10() -{ - DWORD lun; - SCSIBR *bridge; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Error if not a host bridge - if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { - Error(); - return; - } - - // Reallocate buffer (because it is not transfer for each block) - if (ctrl.bufsize < 0x1000000) { - free(ctrl.buffer); - ctrl.bufsize = 0x1000000; - ctrl.buffer = (BYTE *)malloc(ctrl.bufsize); - } - - // Process with drive - bridge = (SCSIBR*)ctrl.unit[lun]; - ctrl.length = bridge->GetMessage10(ctrl.cmd, ctrl.buffer); - - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.blocks = 1; - ctrl.next = 1; - - // Data in phase - DataIn(); -} - -//--------------------------------------------------------------------------- -// -// SEND MESSAGE(10) -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::CmdSendMessage10() -{ - DWORD lun; - - ASSERT(this); - - // Logical Unit - lun = (ctrl.cmd[1] >> 5) & 0x07; - if (!ctrl.unit[lun]) { - Error(); - return; - } - - // Error if not a host bridge - if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { - Error(); - return; - } - - // Reallocate buffer (because it is not transfer for each block) - if (ctrl.bufsize < 0x1000000) { - free(ctrl.buffer); - ctrl.bufsize = 0x1000000; - ctrl.buffer = (BYTE *)malloc(ctrl.bufsize); - } - - // Set transfer amount - ctrl.length = ctrl.cmd[6]; - ctrl.length <<= 8; - ctrl.length |= ctrl.cmd[7]; - ctrl.length <<= 8; - ctrl.length |= ctrl.cmd[8]; - - if (ctrl.length <= 0) { - // Failure (Error) - Error(); - return; - } - - // Set next block - ctrl.blocks = 1; - ctrl.next = 1; - - // Light phase - DataOut(); -} - -//=========================================================================== -// -// Data Transfer -// -//=========================================================================== - -//--------------------------------------------------------------------------- -// -// Send data -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Send() -{ -#ifdef RASCSI - int len; -#endif // RASCSI - BOOL result; - - ASSERT(this); - ASSERT(!ctrl.bus->GetREQ()); - ASSERT(ctrl.bus->GetIO()); - -#ifdef RASCSI - //if Length! = 0, send - if (ctrl.length != 0) { - len = ctrl.bus->SendHandShake( - &ctrl.buffer[ctrl.offset], ctrl.length); - - // If you cannot send all, move to status phase - if (len != (int)ctrl.length) { - Error(); - return; - } - - // offset and length - ctrl.offset += ctrl.length; - ctrl.length = 0; - return; - } -#else - // offset and length - ASSERT(ctrl.length >= 1); - ctrl.offset++; - ctrl.length--; - - // Immediately after ACK is asserted, if the data has been - // set by SendNext, raise the request - if (ctrl.length != 0) { - // Signal line operated by the target - ctrl.bus->SetREQ(TRUE); - return; - } -#endif // RASCSI - - // Block subtraction, result initialization - ctrl.blocks--; - result = TRUE; - - // Processing after data collection (read/data-in only) - if (ctrl.phase == BUS::datain) { - if (ctrl.blocks != 0) { - // // set next buffer (set offset, length) - result = XferIn(ctrl.buffer); -#ifndef RASCSI - ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]); -#endif // RASCSI - } - } - - // If result FALSE, move to status phase - if (!result) { - Error(); - return; - } - - // Continue sending if block !=0 - if (ctrl.blocks != 0){ - ASSERT(ctrl.length > 0); - ASSERT(ctrl.offset == 0); -#ifndef RASCSI - // Signal line operated by the target - ctrl.bus->SetREQ(TRUE); -#endif // RASCSI - return; - } - - // Move to next phase - switch (ctrl.phase) { - // Message in phase - case BUS::msgin: - // Completed sending response to extended message of IDENTIFY message - if (scsi.atnmsg) { - // flag off - scsi.atnmsg = FALSE; - - // command phase - Command(); - } else { - // Bus free phase - BusFree(); - } - break; - - // Data-in Phase - case BUS::datain: - // status phase - Status(); - break; - - // status phase - case BUS::status: - // Message in phase - ctrl.length = 1; - ctrl.blocks = 1; - ctrl.buffer[0] = (BYTE)ctrl.message; - MsgIn(); - break; - - // Other (impossible) - default: - ASSERT(FALSE); - break; - } -} - -#ifndef RASCSI -//--------------------------------------------------------------------------- -// -// Continue data transmission..... -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::SendNext() -{ - ASSERT(this); - - // REQ is up - ASSERT(ctrl.bus->GetREQ()); - ASSERT(ctrl.bus->GetIO()); - - // Signal line operated by the target - ctrl.bus->SetREQ(FALSE); - - // If there is data in the buffer, set it first - if (ctrl.length > 1) { - ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset + 1]); - } -} -#endif // RASCSI - -#ifndef RASCSI -//--------------------------------------------------------------------------- -// -// Receive data -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Receive() -{ - DWORD data; - - ASSERT(this); - - // Req is up - ASSERT(ctrl.bus->GetREQ()); - ASSERT(!ctrl.bus->GetIO()); - - // Get data - data = (DWORD)ctrl.bus->GetDAT(); - - // Signal line operated by the target - ctrl.bus->SetREQ(FALSE); - - switch (ctrl.phase) { - // Command phase - case BUS::command: - ctrl.cmd[ctrl.offset] = data; -#if defined(DISK_LOG) - Log(Log::Normal, "Command phase $%02X", data); -#endif // DISK_LOG - - // Set the length again with the first data (offset 0) - if (ctrl.offset == 0) { - if (ctrl.cmd[0] >= 0x20) { - // 10バイトCDB - ctrl.length = 10; - } - } - break; - - // Message out phase - case BUS::msgout: - ctrl.message = data; -#if defined(DISK_LOG) - Log(Log::Normal, "Message out phase $%02X", data); -#endif // DISK_LOG - break; - - // Data out phase - case BUS::dataout: - ctrl.buffer[ctrl.offset] = (BYTE)data; - break; - - // Other (impossible) - default: - ASSERT(FALSE); - break; - } -} -#endif // RASCSI - -#ifdef RASCSI -//--------------------------------------------------------------------------- -// -// Receive Data -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::Receive() -#else -//--------------------------------------------------------------------------- -// -// Continue receiving data -// -//--------------------------------------------------------------------------- -void FASTCALL SCSIMONDEV::ReceiveNext() -#endif // RASCSI -{ -#ifdef RASCSI - int len; -#endif // RASCSI - BOOL result; - int i; - BYTE data; - - ASSERT(this); - - // REQ is low - ASSERT(!ctrl.bus->GetREQ()); - ASSERT(!ctrl.bus->GetIO()); - -#ifdef RASCSI - // Length != 0 if received - if (ctrl.length != 0) { - // Receive - len = ctrl.bus->ReceiveHandShake( - &ctrl.buffer[ctrl.offset], ctrl.length); - - // If not able to receive all, move to status phase - if (len != (int)ctrl.length) { - Error(); - return; - } - - // Offset and Length - ctrl.offset += ctrl.length; - ctrl.length = 0;; - return; - } -#else - // Offset and Length - ASSERT(ctrl.length >= 1); - ctrl.offset++; - ctrl.length--; - - // If length!=0, set req again - if (ctrl.length != 0) { - // Signal line operated by the target - ctrl.bus->SetREQ(TRUE); - return; - } -#endif // RASCSI - - // Block subtraction, result initialization - ctrl.blocks--; - result = TRUE; - - // Processing after receiving data (by phase) - switch (ctrl.phase) { - - // Data out phase - case BUS::dataout: - if (ctrl.blocks == 0) { - // End with this buffer - result = XferOut(FALSE); - } else { - // Continue to next buffer (set offset, length) - result = XferOut(TRUE); - } - break; - - // Message out phase - case BUS::msgout: - ctrl.message = ctrl.buffer[0]; - if (!XferMsg(ctrl.message)) { - // Immediately free the bus if message output fails - BusFree(); - return; - } - - // Clear message data in preparation for message-in - ctrl.message = 0x00; - break; - - default: - break; - } - - // If result FALSE, move to status phase - if (!result) { - Error(); - return; - } - - // Continue to receive if block !=0 - if (ctrl.blocks != 0){ - ASSERT(ctrl.length > 0); - ASSERT(ctrl.offset == 0); -#ifndef RASCSI - // Signal line operated by the target - ctrl.bus->SetREQ(TRUE); -#endif // RASCSI - return; - } - - // Move to next phase - switch (ctrl.phase) { - // Command phase - case BUS::command: -#ifdef RASCSI - // Command data transfer - len = 6; - if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { - // 10 byte CDB - len = 10; - } - for (i = 0; i < len; i++) { - ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; -#if defined(DISK_LOG) - Log(Log::Normal, "Command $%02X", ctrl.cmd[i]); -#endif // DISK_LOG - } -#endif // RASCSI - - // Execution Phase - Execute(); - break; - - // Message out phase - case BUS::msgout: - // Continue message out phase as long as ATN keeps asserting - if (ctrl.bus->GetATN()) { - // Data transfer is 1 byte x 1 block - ctrl.offset = 0; - ctrl.length = 1; - ctrl.blocks = 1; -#ifndef RASCSI - // Request message - ctrl.bus->SetREQ(TRUE); -#endif // RASCSI - return; - } - - // Parsing messages sent by ATN - if (scsi.atnmsg) { - i = 0; - while (i < scsi.msc) { - // Message type - data = scsi.msb[i]; - - // ABORT - if (data == 0x06) { -#if defined(DISK_LOG) - Log(Log::Normal, - "Message code ABORT $%02X", data); -#endif // DISK_LOG - BusFree(); - return; - } - - // BUS DEVICE RESET - if (data == 0x0C) { -#if defined(DISK_LOG) - Log(Log::Normal, - "Message code BUS DEVICE RESET $%02X", data); -#endif // DISK_LOG - scsi.syncoffset = 0; - BusFree(); - return; - } - - // IDENTIFY - if (data >= 0x80) { -#if defined(DISK_LOG) - Log(Log::Normal, - "Message code IDENTIFY $%02X", data); -#endif // DISK_LOG - } - - // Extended Message - if (data == 0x01) { -#if defined(DISK_LOG) - Log(Log::Normal, - "Message code EXTENDED MESSAGE $%02X", data); -#endif // DISK_LOG - - // Check only when synchronous transfer is possible - if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { - ctrl.length = 1; - ctrl.blocks = 1; - ctrl.buffer[0] = 0x07; - MsgIn(); - return; - } - - // Transfer period factor (limited to 50 x 4 = 200ns) - scsi.syncperiod = scsi.msb[i + 3]; - if (scsi.syncperiod > 50) { - scsi.syncoffset = 50; - } - - // REQ/ACK offset(limited to 16) - scsi.syncoffset = scsi.msb[i + 4]; - if (scsi.syncoffset > 16) { - scsi.syncoffset = 16; - } - - // STDR response message generation - ctrl.length = 5; - ctrl.blocks = 1; - ctrl.buffer[0] = 0x01; - ctrl.buffer[1] = 0x03; - ctrl.buffer[2] = 0x01; - ctrl.buffer[3] = (BYTE)scsi.syncperiod; - ctrl.buffer[4] = (BYTE)scsi.syncoffset; - MsgIn(); - return; - } - - // next - i++; - } - } - - // Initialize ATN message reception status - scsi.atnmsg = FALSE; - - // Command phase - Command(); - break; - - // Data out phase - case BUS::dataout: - // Flush unit - FlushUnit(); - - // status phase - Status(); - break; - - // Other (impossible) - default: - ASSERT(FALSE); - break; - } -} - -//--------------------------------------------------------------------------- -// -// Transfer MSG -// -//--------------------------------------------------------------------------- -BOOL FASTCALL SCSIMONDEV::XferMsg(DWORD msg) -{ - ASSERT(this); - ASSERT(ctrl.phase == BUS::msgout); - - // Save message out data - if (scsi.atnmsg) { - scsi.msb[scsi.msc] = (BYTE)msg; - scsi.msc++; - scsi.msc %= 256; - } - - return TRUE; -} From 15bd9d7dd4de961263c2b307616d196cfe1ded27 Mon Sep 17 00:00:00 2001 From: akuker Date: Thu, 9 Jul 2020 13:38:00 -0500 Subject: [PATCH 15/16] Ignore the binaries - don't check them into git --- src/raspberrypi/.gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/raspberrypi/.gitignore b/src/raspberrypi/.gitignore index 659c642..c5fb48a 100644 --- a/src/raspberrypi/.gitignore +++ b/src/raspberrypi/.gitignore @@ -5,4 +5,8 @@ *.cbp *.layout *.log - +rascsi +scsimon +rasctl +sasidump +rasdump From 6bdb841dfc7e961a36d995055b125b897bdb1f2f Mon Sep 17 00:00:00 2001 From: Tony Kuker Date: Thu, 9 Jul 2020 15:34:29 -0500 Subject: [PATCH 16/16] Cleanup to merge in with main branch --- src/raspberrypi/disk.cpp | 158 +++++++++++++++++------------------- src/raspberrypi/disk.h | 8 +- src/raspberrypi/gpiobus.cpp | 103 ++++------------------- src/raspberrypi/rascsi.cpp | 14 ++-- 4 files changed, 100 insertions(+), 183 deletions(-) diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp index 793a95e..cd55480 100644 --- a/src/raspberrypi/disk.cpp +++ b/src/raspberrypi/disk.cpp @@ -45,7 +45,9 @@ //#define DISK_LOG #ifdef RASCSI -#define BENDER_SIGNATURE "SONY " +#define BENDER_SIGNATURE "RaSCSI" +// The following line was to mimic Apple's CDROM ID +// #define BENDER_SIGNATURE "SONY " #else #define BENDER_SIGNATURE "XM6" #endif @@ -1346,20 +1348,16 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Get changeable flag if ((cdb[2] & 0xc0) == 0x40) { - //** printf("MODESENSE: Change = TRUE\n"); change = TRUE; } else { - //** printf("MODESENSE: Change = FALSE\n"); change = FALSE; } // Get page code (0x00 is valid from the beginning) page = cdb[2] & 0x3f; if (page == 0x00) { - //** printf("MODESENSE: Page code: OK %02X\n", cdb[2]); valid = TRUE; } else { - //** printf("MODESENSE: Invalid page code received %02X\n", cdb[2]); valid = FALSE; } @@ -1373,7 +1371,6 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // DEVICE SPECIFIC PARAMETER if (disk.writep) { - //** printf("MODESENSE: Write protect\n"); buf[2] = 0x80; } @@ -1384,7 +1381,6 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Only if ready if (disk.ready) { - //** printf("MODESENSE: Disk is ready\n"); // Block descriptor (number of blocks) buf[5] = (BYTE)(disk.blocks >> 16); buf[6] = (BYTE)(disk.blocks >> 8); @@ -1461,13 +1457,10 @@ int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) // Unsupported page if (!valid) { - //** printf("MODESENSE: Something was invalid...\n"); disk.code = DISK_INVALIDCDB; return 0; } - //** printf("MODESENSE: mode sense length is %d\n",length); - // MODE SENSE success disk.code = DISK_NOERROR; return length; @@ -2829,7 +2822,7 @@ BOOL FASTCALL SCSIHD_NEC::Open(const Filepath& path, BOOL /*attn*/) cylinders = (int)(size >> 9); cylinders >>= 3; cylinders /= 25; - } else if (xstrcasecmp(ext, _T(".HDI")) == 0) { // Anex86 HD image? + } else if (xstrcasecmp(ext, _T(".HDI")) == 0) { // Anex86 HD image? imgoffset = getDwordLE(&hdr[4 + 4]); imgsize = getDwordLE(&hdr[4 + 4 + 4]); sectorsize = getDwordLE(&hdr[4 + 4 + 4 + 4]); @@ -2953,7 +2946,7 @@ int FASTCALL SCSIHD_NEC::AddFormat(BOOL change, BYTE *buf) // 1ゾーンのトラック数を設定(PC-9801-55はこの値を見ているようだ) buf[0x2] = (BYTE)(heads >> 8); buf[0x3] = (BYTE)heads; - + // 1トラックのセクタ数を設定 buf[0xa] = (BYTE)(sectors >> 8); buf[0xb] = (BYTE)sectors; @@ -2996,7 +2989,7 @@ int FASTCALL SCSIHD_NEC::AddDrive(BOOL change, BYTE *buf) buf[0x2] = (BYTE)(cylinders >> 16); buf[0x3] = (BYTE)(cylinders >> 8); buf[0x4] = (BYTE)cylinders; - + // ヘッド数を設定 buf[0x5] = (BYTE)heads; } @@ -3410,29 +3403,29 @@ int FASTCALL SCSIMO::AddVendor(int page, BOOL change, BYTE *buf) mode page code 20h - Vendor Unique Format Page format mode XXh type 0 information: http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-lpg28560-1.pdf - + offset description 02h format mode 03h type of format (0) 04~07h size of user band (total sectors?) 08~09h size of spare band (spare sectors?) 0A~0Bh number of bands - + actual value of each 3.5inches optical medium (grabbed by Fujitsu M2513EL) - + 128M 230M 540M 640M --------------------------------------------------- size of user band 3CBFAh 6CF75h FE45Ch 4BC50h size of spare band 0400h 0401h 08CAh 08C4h number of bands 0001h 000Ah 0012h 000Bh - + further information: http://r2089.blog36.fc2.com/blog-entry-177.html */ if (disk.ready) { unsigned spare = 0; unsigned bands = 0; - + if (disk.size == 9) switch (disk.blocks) { // 128MB case 248826: @@ -4135,7 +4128,7 @@ int FASTCALL SCSICD::Inquiry( buf[1] = 0x80; buf[2] = 0x02; buf[3] = 0x02; - buf[4] = 42; // Required + buf[4] = 36 - 5; // Required // Fill with blanks memset(&buf[8], 0x20, buf[4] - 3); @@ -4144,16 +4137,34 @@ int FASTCALL SCSICD::Inquiry( memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); // Product name - memcpy(&buf[16], "CD-ROM CDU-8003A", 16); + memcpy(&buf[16], "CD-ROM CDU-55S", 14); // Revision (XM6 version number) -// sprintf(rev, "1.9a", - // (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); - memcpy(&buf[32], "1.9a", 4); - - //strcpy(&buf[35],"A1.9a"); - buf[36]=0x20; - memcpy(&buf[37],"1999/01/01",10); + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); +// +// The following code worked with the modified Apple CD-ROM drivers. Need to +// test with the original code to see if it works as well.... +// buf[4] = 42; // Required +// +// // Fill with blanks +// memset(&buf[8], 0x20, buf[4] - 3); +// +// // Vendor name +// memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); +// +// // Product name +// memcpy(&buf[16], "CD-ROM CDU-8003A", 16); +// +// // Revision (XM6 version number) +//// sprintf(rev, "1.9a", +// //// (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); +// memcpy(&buf[32], "1.9a", 4); +// +// //strcpy(&buf[35],"A1.9a"); +// buf[36]=0x20; +// memcpy(&buf[37],"1999/01/01",10); // Size of data that can be returned size = (buf[4] + 5); @@ -4534,7 +4545,6 @@ void FASTCALL SCSICD::GetBuf( ASSERT(this); } - //=========================================================================== // // SCSI Host Bridge @@ -5003,7 +5013,7 @@ void FASTCALL SCSIBR::FS_CheckDir(BYTE *buf) pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->CheckDir(nUnit, pNamests); } @@ -5027,10 +5037,10 @@ void FASTCALL SCSIBR::FS_MakeDir(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->MakeDir(nUnit, pNamests); } @@ -5054,10 +5064,10 @@ void FASTCALL SCSIBR::FS_RemoveDir(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->RemoveDir(nUnit, pNamests); } @@ -5082,13 +5092,13 @@ void FASTCALL SCSIBR::FS_Rename(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); pNamestsNew = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->Rename(nUnit, pNamests, pNamestsNew); } @@ -5112,10 +5122,10 @@ void FASTCALL SCSIBR::FS_Delete(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); - + fsresult = fs->Delete(nUnit, pNamests); } @@ -5140,14 +5150,14 @@ void FASTCALL SCSIBR::FS_Attribute(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); dp = (DWORD*)&buf[i]; nHumanAttribute = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->Attribute(nUnit, pNamests, nHumanAttribute); } @@ -5177,7 +5187,7 @@ void FASTCALL SCSIBR::FS_Files(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); @@ -5284,7 +5294,7 @@ void FASTCALL SCSIBR::FS_Create(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); @@ -5346,7 +5356,7 @@ void FASTCALL SCSIBR::FS_Open(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pNamests = (Human68k::namests_t*)&buf[i]; i += sizeof(Human68k::namests_t); @@ -5399,7 +5409,7 @@ void FASTCALL SCSIBR::FS_Close(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5448,7 +5458,7 @@ void FASTCALL SCSIBR::FS_Read(BYTE *buf) pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); - + dp = (DWORD*)&buf[i]; nSize = ntohl(*dp); i += sizeof(DWORD); @@ -5497,7 +5507,7 @@ void FASTCALL SCSIBR::FS_Write(BYTE *buf) dp = (DWORD*)buf; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5549,7 +5559,7 @@ void FASTCALL SCSIBR::FS_Seek(BYTE *buf) dp = (DWORD*)buf; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5608,7 +5618,7 @@ void FASTCALL SCSIBR::FS_TimeStamp(BYTE *buf) dp = (DWORD*)&buf[i]; nKey = ntohl(*dp); i += sizeof(DWORD); - + pFcb = (Human68k::fcb_t*)&buf[i]; i += sizeof(Human68k::fcb_t); @@ -5689,10 +5699,10 @@ void FASTCALL SCSIBR::FS_CtrlDrive(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i]; i += sizeof(Human68k::ctrldrive_t); - + fsresult = fs->CtrlDrive(nUnit, pCtrlDrive); memcpy(fsout, pCtrlDrive, sizeof(Human68k::ctrldrive_t)); @@ -5719,7 +5729,7 @@ void FASTCALL SCSIBR::FS_GetDPB(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->GetDPB(nUnit, &dpb); dpb.sector_size = htons(dpb.sector_size); @@ -5762,7 +5772,7 @@ void FASTCALL SCSIBR::FS_DiskRead(BYTE *buf) dp = (DWORD*)&buf[i]; nSize = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->DiskRead(nUnit, fsout, nSector, nSize); fsoutlen = 0x200; } @@ -5786,7 +5796,7 @@ void FASTCALL SCSIBR::FS_DiskWrite(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->DiskWrite(nUnit); } @@ -5863,7 +5873,7 @@ void FASTCALL SCSIBR::FS_Flush(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->Flush(nUnit); } @@ -5886,7 +5896,7 @@ void FASTCALL SCSIBR::FS_CheckMedia(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->CheckMedia(nUnit); } @@ -5909,7 +5919,7 @@ void FASTCALL SCSIBR::FS_Lock(BYTE *buf) dp = (DWORD*)buf; nUnit = ntohl(*dp); i += sizeof(DWORD); - + fsresult = fs->Lock(nUnit); } @@ -6474,13 +6484,7 @@ void FASTCALL SASIDEV::Command() #ifdef RASCSI // Command reception handshake (10 bytes are automatically received at the first command) count = ctrl.bus->CommandHandShake(ctrl.buffer); - //** printf("Command received: " ); - //** for(int i=0; i< count; i++) - //** { - //** printf("%02X ", ctrl.buffer[i]); - //** } - //** printf("\n"); - + // If no byte can be received move to the status phase if (count == 0) { Error(); @@ -6668,8 +6672,8 @@ void FASTCALL SASIDEV::Status() #ifndef RASCSI // Request status -// ctrl.bus->SetDAT(ctrl.buffer[0]); -// ctrl.bus->SetREQ(TRUE); + ctrl.bus->SetDAT(ctrl.buffer[0]); + ctrl.bus->SetREQ(TRUE); #if defined(DISK_LOG) Log(Log::Normal, "Status Phase $%02X", ctrl.status); @@ -7302,7 +7306,7 @@ void FASTCALL SASIDEV::CmdAssign() return; } - // 4Request 4 bytes of data + // Request 4 bytes of data ctrl.length = 4; // Write phase @@ -7712,14 +7716,7 @@ BOOL FASTCALL SASIDEV::XferIn(BYTE *buf) // Read from disk ctrl.length = ctrl.unit[lun]->Read(buf, ctrl.next); ctrl.next++; - - //** printf("XferIn read data from disk: "); - //** for (int i=0; iGetVM()->GetLog()->Format(level, host, buffer); #endif // RASCSI #endif // BAREMETAL +#endif // DISK_LOG } //=========================================================================== @@ -8029,7 +8031,6 @@ void FASTCALL SCSIDEV::Reset() BUS::phase_t FASTCALL SCSIDEV::Process() { ASSERT(this); - //** printf("SCSIDEV::Process() %d\n", ctrl.id); // Do nothing if not connected if (ctrl.id < 0 || ctrl.bus == NULL) { @@ -8590,13 +8591,6 @@ void FASTCALL SCSIDEV::CmdModeSense() Log(Log::Normal, "MODE SENSE Command "); #endif // DISK_LOG - //** printf("Received a Mode Sense command. Contents...."); - //** for(int i=0; i<10; i++) - //** { - //** printf("%08X ", ctrl.cmd[i]); - //** } - //** printf("\n"); - // Logical Unit lun = (ctrl.cmd[1] >> 5) & 0x07; if (!ctrl.unit[lun]) { diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h index 0299d3c..10593e6 100644 --- a/src/raspberrypi/disk.h +++ b/src/raspberrypi/disk.h @@ -229,8 +229,6 @@ public: // NULL check BOOL FASTCALL IsSASI() const; // SASI Check - virtual BOOL FASTCALL IsMonitor() const {return FALSE;} - // Check if this is a monitor device // Media Operations virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); @@ -922,8 +920,10 @@ public: // Other BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} // Get the phase - +#ifdef DISK_LOG + // Function to get the current phase as a String. void FASTCALL GetPhaseStr(char *str); +#endif int FASTCALL GetID() {return ctrl.id;} // Get the ID @@ -935,8 +935,6 @@ public: // SASI Check virtual BOOL FASTCALL IsSCSI() const {return FALSE;} // SCSI check - virtual BOOL FASTCALL IsMonitor() const {return FALSE;} - // Check to see if this is a monitor device Disk* FASTCALL GetBusyUnit(); // Get the busy unit diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp index a8cd7a3..31d6acf 100644 --- a/src/raspberrypi/gpiobus.cpp +++ b/src/raspberrypi/gpiobus.cpp @@ -65,7 +65,7 @@ DWORD bcm_host_get_peripheral_address(void) char buf[1024]; size_t len = sizeof(buf); DWORD address; - + if (sysctlbyname("hw.model", buf, &len, NULL, 0) || strstr(buf, "ARM1176JZ-S") != buf) { // Failed to get CPU model || Not BCM2835 @@ -88,7 +88,7 @@ extern uint32_t RPi_IO_Base_Addr; // Core frequency extern uint32_t RPi_Core_Freq; -#ifdef USE_SEL_EVENT_ENABLE +#ifdef USE_SEL_EVENT_ENABLE //--------------------------------------------------------------------------- // // Interrupt control function @@ -521,7 +521,7 @@ DWORD FASTCALL GPIOBUS::Aquire() // Invert if negative logic (internal processing is unified to positive logic) signals = ~signals; #endif // SIGNAL_CONTROL_MODE - + return signals; } @@ -552,15 +552,9 @@ BOOL FASTCALL GPIOBUS::GetBSY() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetBSY(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET BSY IN MONITOR MODE"); - } - else - { - // Set BSY signal - SetSignal(PIN_BSY, ast); - } + // Set BSY signal + SetSignal(PIN_BSY, ast); + if (actmode == TARGET) { if (ast) { // Turn on ACTIVE signal @@ -612,14 +606,8 @@ void FASTCALL GPIOBUS::SetSEL(BOOL ast) SetControl(PIN_ACT, ACT_ON); } - if (actmode != MONITOR) - { - // Set SEL signal - SetSignal(PIN_SEL, ast); - } - else{ - printf("WARNING!!! SOMEONE TRIED TO SET SEL IN MONITOR MODE"); -} + // Set SEL signal + SetSignal(PIN_SEL, ast); } //--------------------------------------------------------------------------- @@ -639,14 +627,7 @@ BOOL FASTCALL GPIOBUS::GetATN() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetATN(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET ATN IN MONITOR MODE"); - } - else - { - SetSignal(PIN_ATN, ast); - } + SetSignal(PIN_ATN, ast); } //--------------------------------------------------------------------------- @@ -666,14 +647,7 @@ BOOL FASTCALL GPIOBUS::GetACK() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetACK(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET ACK IN MONITOR MODE"); - } - else - { SetSignal(PIN_ACK, ast); - } } //--------------------------------------------------------------------------- @@ -693,14 +667,7 @@ BOOL FASTCALL GPIOBUS::GetRST() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetRST(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET RST IN MONITOR MODE"); - } - else - { SetSignal(PIN_RST, ast); - } } //--------------------------------------------------------------------------- @@ -720,13 +687,7 @@ BOOL FASTCALL GPIOBUS::GetMSG() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetMSG(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET MSG IN MONITOR MODE"); - } - else{ - SetSignal(PIN_MSG, ast); - } + SetSignal(PIN_MSG, ast); } //--------------------------------------------------------------------------- @@ -746,14 +707,7 @@ BOOL FASTCALL GPIOBUS::GetCD() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetCD(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET CD IN MONITOR MODE"); - } - else - { - SetSignal(PIN_CD, ast); - } + SetSignal(PIN_CD, ast); } //--------------------------------------------------------------------------- @@ -803,21 +757,6 @@ BOOL FASTCALL GPIOBUS::GetIO() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetIO(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET IO IN MONITOR MODE"); - SetControl(PIN_DTD, DTD_IN); - SetMode(PIN_DT0, IN); - SetMode(PIN_DT1, IN); - SetMode(PIN_DT2, IN); - SetMode(PIN_DT3, IN); - SetMode(PIN_DT4, IN); - SetMode(PIN_DT5, IN); - SetMode(PIN_DT6, IN); - SetMode(PIN_DT7, IN); - SetMode(PIN_DP, IN); - } - SetSignal(PIN_IO, ast); if (actmode == TARGET) { @@ -866,12 +805,6 @@ BOOL FASTCALL GPIOBUS::GetREQ() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetREQ(BOOL ast) { - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET REQ IN MONITOR MODE"); - return; - } - SetSignal(PIN_REQ, ast); } @@ -905,14 +838,6 @@ BYTE FASTCALL GPIOBUS::GetDAT() //--------------------------------------------------------------------------- void FASTCALL GPIOBUS::SetDAT(BYTE dat) { - - - if(actmode == MONITOR) - { - printf("WARNING!!! SOMEONE TRIED TO SET Data IN MONITOR MODE"); - return; - } - // Write to port #if SIGNAL_CONTROL_MODE == 0 DWORD fsel; @@ -1230,7 +1155,7 @@ int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count) } // Already waiting for REQ assertion - + // Assert the ACK signal SetSignal(PIN_ACK, ON); @@ -1474,7 +1399,7 @@ void FASTCALL GPIOBUS::SetMode(int pin, int mode) gpio[index] = data; gpfsel[index] = data; } - + //--------------------------------------------------------------------------- // // Get input signal value @@ -1484,7 +1409,7 @@ BOOL FASTCALL GPIOBUS::GetSignal(int pin) { return (signals >> pin) & 1; } - + //--------------------------------------------------------------------------- // // Set output signal value diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp index 5c538f3..5f64feb 100644 --- a/src/raspberrypi/rascsi.cpp +++ b/src/raspberrypi/rascsi.cpp @@ -79,7 +79,7 @@ void Banner(int argc, char* argv[]) FPRT(stdout,"Connect type : %s\n", CONNECT_DESC); if ((argc > 1 && strcmp(argv[1], "-h") == 0) || - (argc > 1 && strcmp(argv[1], "--help") == 0)){ + (argc > 1 && strcmp(argv[1], "--help") == 0)){ FPRT(stdout,"\n"); FPRT(stdout,"Usage: %s [-IDn FILE] ...\n\n", argv[0]); FPRT(stdout," n is SCSI identification number(0-7).\n"); @@ -154,7 +154,7 @@ BOOL Init() // GPIOBUS creation bus = new GPIOBUS(); - + // GPIO Initialization if (!bus->Init()) { return FALSE; @@ -207,7 +207,7 @@ void Cleanup() // Cleanup the Bus bus->Cleanup(); - + // Discard the GPIOBUS object delete bus; @@ -307,7 +307,7 @@ void ListDevice(FILE *fp) FPRT(fp, "No device is installed.\n"); return; } - + FPRT(fp, "+----+----+------+-------------------------------------\n"); } @@ -863,7 +863,7 @@ static void *MonThread(void *param) { struct sched_param schedparam; struct sockaddr_in client; - socklen_t len; + socklen_t len; int fd; FILE *fp; char buf[BUFSIZ]; @@ -893,8 +893,8 @@ static void *MonThread(void *param) while (1) { // Wait for connection - memset(&client, 0, sizeof(client)); - len = sizeof(client); + memset(&client, 0, sizeof(client)); + len = sizeof(client); fd = accept(monsocket, (struct sockaddr*)&client, &len); if (fd < 0) { break;