Skip to content

Instantly share code, notes, and snippets.

@lpproj
Created January 4, 2021 13:36
Show Gist options
  • Save lpproj/e2888a801dcf39bf28b603858254c614 to your computer and use it in GitHub Desktop.
Save lpproj/e2888a801dcf39bf28b603858254c614 to your computer and use it in GitHub Desktop.
patch against RaSCSI 1.47
to (minimal) support of Old 5.25" 650M double-sided MO drive (NEC PC-OD101)
usage:
rasctl -i 1 -c attach -t mo650
rasctl -i 1 -c insert -f /home/pi/single_sided_mo_flat_image
size of image: 305135616 bytes (297984sectors * 1024bytes)
revision:
* 2020-12-12 lpproj initial patch
* 2021-01-02 lpproj enable to mount the medium on 3.5" MO drive (for convenience)
diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp
--- a/src/raspberrypi/disk.cpp
+++ b/src/raspberrypi/disk.cpp
@@ -3132,6 +3132,12 @@ BOOL FASTCALL SCSIMO::Open(const Filepath& path, BOOL attn)
disk.blocks = 310352;
break;
+ // 300MB (single side of 5.25inch 650M medium, for convenience)
+ case 0x12300000:
+ disk.size = 10;
+ disk.blocks = 297984;
+ break;
+
// その他(エラー)
default:
return FALSE;
@@ -3467,6 +3473,205 @@ int FASTCALL SCSIMO::AddVendor(int page, BOOL change, BYTE *buf)
return 12;
}
+
+//===========================================================================
+//
+// SCSI MO drive - NEC PC-OD101 specific, for NEC PC-98 series
+// (Old 5.25" double-sided 650M drive as WORM)
+//
+//===========================================================================
+
+//---------------------------------------------------------------------------
+//
+// コンストラクタ
+//
+//---------------------------------------------------------------------------
+SCSIMO_WORM650::SCSIMO_WORM650() : SCSIMO()
+{
+ // SCSI 光磁気ディスク
+ disk.id = MAKEID('S', 'C', 'M', 'W');
+
+ // リムーバブル
+ disk.removable = TRUE;
+}
+
+//---------------------------------------------------------------------------
+//
+// オープン
+//
+//---------------------------------------------------------------------------
+BOOL FASTCALL SCSIMO_WORM650::Open(const Filepath& path, BOOL attn)
+{
+ Fileio fio;
+ off64_t size;
+
+ ASSERT(this);
+ ASSERT(!disk.ready);
+
+ // 読み込みオープンが必要
+ if (!fio.Open(path, Fileio::ReadOnly)) {
+ return FALSE;
+ }
+
+ // ファイルサイズの取得
+ size = fio.GetFileSize();
+ fio.Close();
+
+ switch (size) {
+ // 300MB (single-side of '650M' medium)
+ case 305135616:
+ disk.size = 10;
+ disk.blocks = 297984;
+ break;
+
+ // その他(エラー)
+ default:
+ return FALSE;
+ }
+
+ // 基本クラス
+ Disk::Open(path);
+
+ // レディならアテンション
+ if (disk.ready && attn) {
+ disk.attn = TRUE;
+ }
+
+ return TRUE;
+}
+
+#ifndef RASCSI
+//---------------------------------------------------------------------------
+//
+// ロード
+//
+//---------------------------------------------------------------------------
+// BOOL FASTCALL SCSIMO_WORM650::Load(Fileio *fio, int ver)
+#endif // RASCSI
+
+//---------------------------------------------------------------------------
+//
+// INQUIRY
+//
+//---------------------------------------------------------------------------
+int FASTCALL SCSIMO_WORM650::Inquiry(
+ const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor)
+{
+ const char VENDOR_ID[] = "NEC";
+ const char PRODUCT_ID[] = "ODC141 -151";
+ // const char REVISION_LEVEL[] = "0001";
+ int size;
+ char rev[32];
+
+ ASSERT(this);
+ ASSERT(cdb);
+ ASSERT(buf);
+ ASSERT(cdb[0] == 0x12);
+
+ // EVPDチェック
+ if (cdb[1] & 0x01) {
+ disk.code = DISK_INVALIDCDB;
+ return FALSE;
+ }
+
+ // 基本データ
+ // NEC PC-OD101
+ // thanks to UME-3 for the report (https://twitter.com/ume3fmp/status/1337035804737032194)
+ // buf[0] ... 0x84 (WORM, Vendor-specific)
+ // buf[1] ... 0x80 (Removable)
+ // buf[2] ... 0x01 (SCSI-1)
+ // buf[3] ... 0x01 (SCSI-1 CCS)
+ // buf[4] ... 0x1f (Additional length)
+ memset(buf, 0, 8);
+ buf[0] = 0x84;
+ buf[1] = 0x80;
+ buf[2] = 0x01;
+ buf[3] = 0x01;
+ buf[4] = 36 - 5; // 必須
+
+ // 空白で埋める
+ memset(&buf[8], 0x20, buf[4] - 3);
+
+ // ベンダ
+ memcpy(&buf[8], VENDOR_ID, strlen(VENDOR_ID));
+
+ // 製品名
+ memcpy(&buf[16], PRODUCT_ID, strlen(PRODUCT_ID));
+
+ // リビジョン(XM6のバージョンNo)
+ sprintf(rev, "0%01d%01d%01d",
+ (int)major, (int)(minor >> 4), (int)(minor & 0x0f));
+ memcpy(&buf[32], rev, 4);
+
+ // 返却できるデータのサイズ
+ size = (buf[4] + 5);
+
+ // 相手のバッファが少なければ制限する
+ if (size > (int)cdb[4]) {
+ size = (int)cdb[4];
+ }
+
+ // 成功
+ disk.code = DISK_NOERROR;
+ return size;
+}
+
+//---------------------------------------------------------------------------
+//
+// MODE SELECT
+//
+//---------------------------------------------------------------------------
+BOOL FASTCALL SCSIMO_WORM650::ModeSelect(const DWORD *cdb, const BYTE *buf, int length)
+{
+// int page;
+// int size;
+
+ ASSERT(this);
+ ASSERT(buf);
+ ASSERT(length >= 0);
+
+ disk.code = DISK_INVALIDCMD;
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+//
+// Vendor Unique Format Page 20h (MO)
+//
+//---------------------------------------------------------------------------
+int FASTCALL SCSIMO_WORM650::AddVendor(int page, BOOL change, BYTE *buf)
+{
+ ASSERT(this);
+ ASSERT(buf);
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+//
+// MODE SENSE
+//
+//---------------------------------------------------------------------------
+int FASTCALL SCSIMO_WORM650::ModeSense(const DWORD *cdb, BYTE *buf)
+{
+ ASSERT(this);
+ ASSERT(buf);
+ ASSERT(length >= 0);
+
+ disk.code = DISK_INVALIDCMD;
+ return FALSE;
+}
+
+int FASTCALL SCSIMO_WORM650::ModeSense10(const DWORD *cdb, BYTE *buf)
+{
+ ASSERT(this);
+ ASSERT(buf);
+ ASSERT(length >= 0);
+
+ disk.code = DISK_INVALIDCMD;
+ return FALSE;
+}
+
//===========================================================================
//
// CDトラック
diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h
--- a/src/raspberrypi/disk.h
+++ b/src/raspberrypi/disk.h
@@ -491,6 +491,41 @@ public:
// ベンダ特殊ページ追加
};
+
+//===========================================================================
+//
+// SCSI 光磁気ディスク - Old 5.25" 650M MO drive (as WORM)
+//
+//===========================================================================
+class SCSIMO_WORM650 : public SCSIMO
+{
+public:
+ // 基本ファンクション
+ SCSIMO_WORM650();
+ // コンストラクタ
+ BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE);
+ // オープン
+#ifndef RASCSI
+ BOOL FASTCALL Load(Fileio *fio, int ver);
+ // ロード
+#endif // RASCSI
+
+ // コマンド
+ int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor);
+ // INQUIRYコマンド
+ BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length);
+ // MODE SELECT(6)コマンド
+ virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf);
+ // MODE SENSEコマンド
+ virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf);
+ // MODE SENSE(10)コマンド
+
+ // サブ処理
+ int FASTCALL AddVendor(int page, BOOL change, BYTE *buf);
+ // ベンダ特殊ページ追加
+};
+
+
//---------------------------------------------------------------------------
//
// クラス先行定義
diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp
--- a/src/raspberrypi/rascsi.cpp
+++ b/src/raspberrypi/rascsi.cpp
@@ -503,6 +503,9 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
case 2: // MO
pUnit = new SCSIMO();
break;
+ case 0x82: // Old 5.25" 650M MO, single-sided (as WORM)
+ pUnit = new SCSIMO_WORM650();
+ break;
case 3: // CD
pUnit = new SCSICD();
break;
@@ -569,6 +572,7 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
// MOかCDの場合だけ有効
if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O') &&
+ pUnit->GetID() != MAKEID('S', 'C', 'M', 'W') &&
pUnit->GetID() != MAKEID('S', 'C', 'C', 'D')) {
FPRT(fp, "Error : Operation denied(Deveice isn't removable)\n");
return FALSE;
@@ -580,7 +584,7 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
filepath.SetPath(file);
// オープン
- if (pUnit->Open(filepath)) {
+ if (!pUnit->Open(filepath)) {
FPRT(fp, "Error : File open error [%s]\n", file);
return FALSE;
}
@@ -591,7 +595,8 @@ BOOL ProcessCmd(FILE *fp, int id, int un, int cmd, int type, char *file)
break;
case 4: // PROTECT
- if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O')) {
+ if (pUnit->GetID() != MAKEID('S', 'C', 'M', 'O') &&
+ pUnit->GetID() != MAKEID('S', 'C', 'M', 'W')) {
FPRT(fp, "Error : Operation denied(Deveice isn't MO)\n");
return FALSE;
}
@@ -792,6 +797,9 @@ BOOL ParseArgument(int argc, char* argv[])
} else if (strcasecmp(ext, "mos") == 0) {
// MO
type = 2;
+ } else if (strcasecmp(ext, "mow") == 0) {
+ // Old 5.25" 650M MO, single-sided
+ type = 0x82;
} else if (strcasecmp(ext, "iso") == 0) {
// CD
type = 3;
diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp
--- a/src/raspberrypi/rasctl.cpp
+++ b/src/raspberrypi/rasctl.cpp
@@ -90,7 +90,7 @@ int main(int argc, char* argv[])
fprintf(stderr, " where ID := {0|1|2|3|4|5|6|7}\n");
fprintf(stderr, " UNIT := {0|1} default setting is 0.\n");
fprintf(stderr, " CMD := {attach|detach|insert|eject|protect}\n");
- fprintf(stderr, " TYPE := {hd|mo|cd|bridge}\n");
+ fprintf(stderr, " TYPE := {hd|mo|mo650|cd|bridge}\n");
fprintf(stderr, " FILE := image file path\n");
fprintf(stderr, " CMD is 'attach' or 'insert' and FILE parameter is required.\n");
fprintf(stderr, "Usage: %s -l\n", argv[0]);
@@ -146,6 +146,11 @@ int main(int argc, char* argv[])
case 'm': // MO
case 'M':
type = 2;
+ if (xstrcasecmp(optarg, "mo5")==0 ||
+ xstrcasecmp(optarg, "mo650")==0 ||
+ xstrcasecmp(optarg, "mow")==0) {
+ type = 0x82; // Old 5.25" 650M MO, single-sided
+ }
break;
case 'c': // CD
case 'C':
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment