diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..5eebc68f
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+github: akuker
diff --git a/.github/workflows/rpi_image_creation.yml b/.github/workflows/rpi_image_creation.yml
index 748d77ae..873223d9 100644
--- a/.github/workflows/rpi_image_creation.yml
+++ b/.github/workflows/rpi_image_creation.yml
@@ -1,6 +1,4 @@
-# This is a basic workflow to help you get started with Actions
-
-name: CI
+name: Generate a RaSCSI OS image, based upon the official Rapsberry Pi OS
# Controls when the workflow will run
on:
@@ -21,16 +19,51 @@ jobs:
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
+ # TODO: I don't think this step is needed....
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
+ - name: Checkout RaSCSI
+ uses: actions/checkout@v2
+ with:
+ path: RASCSI
+
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - name: Checkout RaSCSI
+ uses: actions/checkout@v2
+ with:
+ repository: akuker/pi-gen
+ path: pi-gen
+
+ - name: Install Raspberry Pi build toolchain
+ run: sudo apt-get install coreutils quilt parted qemu-user-static debootstrap zerofree zip dosfstools libarchive-tools libcap2-bin grep rsync xz-utils file git curl bc qemu-utils kpartx
- # Runs a single command using the runners shell
- - name: Run a one-line script
- run: echo Hello, world!
-
- # Runs a set of commands using the runners shell
- - name: Run a multi-line script
+ - name: Configure the build
run: |
- echo Add other actions to build,
- echo test, and deploy your project.
+ echo -----------------------------------------------------
+ echo "IMG_NAME=RaSCSI-$GITHUB_RUN_ID" > config
+ echo "TARGET_HOSTNAME=rascsi" >> config
+ echo "ENABLE_SSH=1" >> config
+ echo "LOCALE_DEFAULT=en_US.UTF-8" >> config
+ echo "KEYBOARD_KEYMAP=us" >> config
+ echo "KEYBOARD_LAYOUT=\"English (US)\"" >> config
+ echo -----------------------------------------------------
+ cat config
+ working-directory: pi-gen
+
+ - name: Run the Raspberry Pi build generation tool
+ run: sudo ./build.sh
+ working-directory: pi-gen
+
+ - name: List the files in the deploy directory
+ run: |
+ echo -----------------------------------------------------
+ ls -alh pi-gen/deploy/
+ echo -----------------------------------------------------
+
+ - name: Archive the build artifacts
+ uses: actions/upload-artifact@v2.2.4
+ with:
+ # Artifact name
+ name: raspberry-pi-image
+ # A file, directory or wildcard pattern that describes what to upload
+ path: pi-gen/deploy/*
diff --git a/.gitignore b/.gitignore
index e17ba71f..a9d4c876 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,8 @@ core
*.swp
__pycache__
src/web/current
+src/web/rascsi_interface_pb2.py
src/oled_monitor/current
+src/oled_monitor/rascsi_interface_pb2.py
+src/raspberrypi/hfdisk/
+*~
diff --git a/LICENSE b/LICENSE
index ffef9a2f..3960dd7b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -2,7 +2,8 @@ BSD 3-Clause License
Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp)
Copyright (C) 2014-2020 GIMONS
-Copyright (c) 2020, akuker
+Copyright (c) 2020-2021 akuker
+Copyright (c) RaSCSI project contributors (github.com/akuker/rascsi)
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/RASCSI_webpage_translated.pdf b/RASCSI_webpage_translated.pdf
deleted file mode 100644
index d7ec3d69..00000000
Binary files a/RASCSI_webpage_translated.pdf and /dev/null differ
diff --git a/README.md b/README.md
index 5652d747..63e62676 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,5 @@
-![C/C++ CI](https://github.com/akuker/RASCSI/workflows/C/C++%20CI/badge.svg) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/akuker/RASCSI/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/akuker/RASCSI/?branch=master)
-
-
-
-
# What is RaSCSI?
-RaSCSI is a virtual SCSI device emulator that runs on a Raspberry Pi. It runs in userspace, and can emulate several SCSI devices at one time. There is a control interface to attach / detach drives during runtime, as well as insert and eject removable media. This project is aimed at users of vintage Macintosh computers from the 1980's and 1990's.
+RaSCSI is a virtual SCSI device emulator that runs on a Raspberry Pi. It runs in userspace, and can emulate several SCSI devices at one time. There is a control interface to attach / detach drives during runtime, as well as insert and eject removable media. This project is aimed at users of vintage Macintosh computers and more (see [compatibility list](https://github.com/akuker/RASCSI/wiki/Compatibility)) from the 1980's and 1990's.
Please check out the full story with much more detail on the [wiki](https://github.com/akuker/RASCSI/wiki)!
diff --git a/doc/converter.txt b/doc/converter.txt
deleted file mode 100644
index 25ea42a7..00000000
--- a/doc/converter.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-------------------------------------------------------------------------------
-
- SCSI Target Emulator RaSCSI for Raspberry Pi
-
- Powered by XM6 TypeG Technology.
- Copyright (C) 2016-2020 GIMONS
-
-------------------------------------------------------------------------------
-
-□変換基板の必要性について
- SCSIはTTLレベルで5Vを220Ωと330Ωで分圧(パッシブターミネータの場合)する
- ことで各信号線に3V弱の電圧がかかった状態が定常状態(信号的にはネゲート)に
- なっています。
-
- イニシエータ側もしくはターゲット側が信号をアサートする(=0V)にしようと
- すると両端のターミネータから合わせて5000÷220×2=45mAの電流が流れることに
- なります(X68000のSCSIコントローラであるMB89352のデータシートを見ればシンク
- 電流としてIol48mAとなっています)。
-
- RPIのGPIOはこのような大きなシンク電流は吸収できません。電気的に安全な接続
- を行うためには汎用ロジックIC等で変換基板を作る必要があります。汎用ロジック
- ICで48mAものシンク電流に耐えるのは74LS06とか07といったオープンコレクタで
- ハイパワータイプのものを使用します。
-
- 作者は74HC541×3,74HC126×1,74HC04×1で基本的なSCSIの方向制御を行い更に
- 74LS07×3を使ってバスをドライブする回路を組んでみたところ問題なく動作する
- ことを確認しました。
-
- 他にも74LS641の派生版である74LS641-1を使用すると回路はシンプルに構成できる
- でしょう。ノーマル品と違ってシンク電流が48mA対応なので74LS07を使用する必要
- はありません。しかし入手性はそれほど良くありません。
-
-□変換基板の回路図案
- 同じフォルダに回路図案を入れています。
-
- ・target.png
- SCSIのターゲットモードを使用するための変換基板回路図です。基本機能である
- HDDやMOのエミュレーションを行うのであればこの回路図相当の物を作れば良い
- でしょう。使用するGPIOピンも最も少ない構成になります。
-
- ピンアサインを変更しなければRaSCSIのstandardディレクトリに含まれる
- バイナリを使用することが可能です。
-
- ・fullspec.png
- SCSIのターゲットモード、イニシエータモードを利用できる変換基板回路図です。
- 全ての74LS641-1の方向制御をRaSCSIから行いますのでGPIOピンを三つ余分に使用
- してしまいます。
-
- ピンアサインのカスタマイズで、PIN_TAD,PIN_IND,PIN_DTDにそれぞれ標準
- では6,7,8を設定してコンパイルする必要があります。ピンアサインの
- カスタマイズを参照してください。
-
-□既存のものを手に入れる方法
- 最近では主にTwitter界隈を通じてRaSCSI用の変換基板を作成していただいて
- いる方々がいらっしゃいます。直ぐに見つかると思いますのでここでの紹介
- は省略します。時期は未定ですが公式版の有償頒布を計画しています。
-
-□ピンアサインのカスタマイズ
- GPIOの信号制御論理やピンアサインはgpiobus.hに定義があります。
-
- カスタマイズ例としてgpiobus.hに下記の二つの変換基板用定義例を用意しました。
- 配布物の中にはコンパイル済みバイナリも含まれています。
-
- ・あいぼむ版
- ・GAMERnium版
-
-□カスタマイズ方法
- ・RaSCSI起動時のメッセージです。
- CONNECT_DESC
-
- ・信号制御モードを選択します。
- SIGNAL_CONTROL_MODE
-
- 0:SCSI論理仕様
- 直結またはHPに公開した74LS641-1等を使用する変換基板
- アーサート:0V
- ネゲート :オープンコレクタ出力(バスから切り離す)
-
- 1:負論理仕様(負論理->SCSI論理への変換基板を使用する場合)
- 現時点でこの仕様による変換基板は存在しません
- アーサート:0V -> (CONVERT) -> 0V
- ネゲート :3.3V -> (CONVERT) -> オープンコレクタ出力
-
- 2:正論理仕様(正論理->SCSI論理への変換基板を使用する場合)
- RaSCSI Adapter Rev.C @132sync等
-
- アーサート:3.3V -> (CONVERT) -> 0V
- ネゲート :0V -> (CONVERT) -> オープンコレクタ出力
-
- ・制御信号ピンアサイン
- PIN_ACT:SCSIコマンドを処理中の状態を示す信号のピン番号。
- PIN_ENB:起動から終了の間の有効信号を示す信号のピン番号。
- PIN_TAD:ターゲット信号(BSY,IO,CD,MSG,REG)の入出力方向を示す信号のピン番号。
- PIN_IND:イニシーエータ信号(SEL,ATN,RST,ACK)の入出力方向を示す信号のピン番号。
- PIN_DTD:データ信号(DT0...DT7,DP)の入出力方向を示す信号のピン番号。
-
- ・制御信号出力論理
- 0V:FALSE 3.3V:TRUEで指定します。
-
- ACT_ON:PIN_ACT信号の論理です。
- ENB_ON:PIN_ENB信号の論理です。
- TAD_IN:PIN_TAD入力方向時の論理です。
- IND_IN:PIN_ENB入力方向時の論理です。
- DTD_IN:PIN_ENB入力方向時の論理です。
-
- ・SCSI信号ピンアサイン
- PIN_DT0~PIN_SEL:それぞれSCSI信号のピン番号です。
-
-□コンパイル方法
-
- ・実行ファイル(rascsi,rasctl)
- gpiobus.hを修正
- make clean
- make
-
-[EOF]
diff --git a/doc/converter_en.txt b/doc/converter_en.txt
deleted file mode 100644
index 2b7a01cc..00000000
--- a/doc/converter_en.txt
+++ /dev/null
@@ -1,116 +0,0 @@
--------------------------------------------------- ----------------------------
-
- SCSI Target Emulator RaSCSI for Raspberry Pi
-
- Powered by XM6 TypeG Technology.
- Copyright (C) 2016-2020 GIMONS
-
--------------------------------------------------- ----------------------------
-
-□ Necessity of conversion board
- SCSI divides 5V at 220Ω and 330Ω at TTL level (in the case of passive terminator)
- As a result, the state where a voltage of less than 3 V is applied to each signal line becomes a steady state (signal-wise negate)
- It has become.
-
- Initiator side or target side tries to assert signal (=0V)
- Then, a total current of 5000÷220×2=45mA flows from both terminators.
- If you look at the data sheet of MB89352 which is the SCSI controller of X68000,
- The current is Iol48mA).
-
- The RPI GPIO cannot absorb such a large sink current. Electrically secure connection
- To do this, it is necessary to make a conversion board with a general-purpose logic IC. General logic
- It is an open collector such as 74LS06 or 07 that can withstand a sink current of 48 mA with IC.
- Use the high power type.
-
- The author does basic SCSI direction control with 74HC541×3,74HC126×1,74HC04×1
- I tried to build a circuit to drive the bus using 74LS07 × 3 and it works without problems
- I confirmed that.
-
- If you use 74LS641-1 which is a derivative of 74LS641, you can configure the circuit simply.
- Would be Unlike normal products, the sink current is compatible with 48 mA, so it is necessary to use 74LS07
- there is no. But availability is not so good.
-
-□ Circuit board of conversion board
- The circuit design is put in the same folder.
-
- ・Target.png
- Conversion board circuit diagram for using SCSI target mode. It is a basic function
- If you want to emulate HDD or MO, you can make something equivalent to this circuit diagram.
- Would be It also uses the fewest GPIO pins.
-
- If you do not change the pin assignment, it will be included in the standard directory of RaSCSI
- It is possible to use the binary.
-
- ・Fullspec.png
- It is a conversion board circuit diagram that can use SCSI target mode and initiator mode.
- All 74LS641-1 direction control is performed from RaSCSI, so use 3 extra GPIO pins
- I will do it.
-
- Customize pin assignments to PIN_TAD, PIN_IND, PIN_DTD respectively
- Now you need to set 6,7,8 and compile. Pin assigned
- See Customization.
-
-□ How to get existing ones
- Recently, you have created a conversion board for RaSCSI mainly through the Twitter area.
- There are people who are. Introducing here
- Is omitted. The timing is undecided, but we plan to distribute the official version for a fee.
-
-□ Customize pin assignment
- The signal control logic and pin assignment of GPIO are defined in gpiobus.h.
-
- As a customization example, the following two conversion board definition examples are prepared in gpiobus.h.
- Compiled binaries are also included in the distribution.
-
- ・Aibomu version
- ・GAMERnium version
-
-□ How to customize
- -This is a message when starting up RaSCSI.
- CONNECT_DESC
-
- ・Select the signal control mode.
- SIGNAL_CONTROL_MODE
-
- 0: SCSI logical specification
- Conversion board using 74LS641-1 etc. directly connected or published on HP
- Arthurt: 0V
- Negative: Open collector output (disconnect from bus)
-
- 1: Negative logic specification (when using the conversion board for negative logic -> SCSI logic)
- There are no conversion boards with this specification at this time
- Arthurt: 0V -> (CONVERT) -> 0V
- Negative: 3.3V -> (CONVERT) -> Open collector output
-
- 2: Positive logic specification (when using the conversion board for positive logic -> SCSI logic)
- RaSCSI Adapter Rev.C @132sync etc.
-
- Arthurt: 3.3V -> (CONVERT) -> 0V
- Negative: 0V -> (CONVERT) -> Open collector output
-
- ・Control signal pin assignment
- PIN_ACT: The pin number of the signal that indicates the status that the SCSI command is being processed.
- PIN_ENB: Pin number of the signal that indicates the valid signal from start to finish.
- PIN_TAD: Pin number of the signal that indicates the input/output direction of the target signal (BSY,IO,CD,MSG,REG).
- PIN_IND: Pin number of the signal indicating the input/output direction of the initiator signal (SEL, ATN, RST, ACK).
- PIN_DTD: Pin number of the signal that indicates the input/output direction of the data signal (DT0...DT7,DP).
-
- ・Control signal output logic
- 0V:FALSE Specify with 3.3V:TRUE.
-
- ACT_ON: PIN_ACT signal logic.
- ENB_ON: Logic of PIN_ENB signal.
- TAD_IN:PIN_TAD This is the logic in the input direction.
- IND_IN:PIN_ENB Logic in the input direction.
- DTD_IN:PIN_ENB Logic in the input direction.
-
- ・ SCSI signal pin assignment
- PIN_DT0 to PIN_SEL: Each is the pin number of the SCSI signal.
-
-□ How to compile
-
- ・Executable files (rascsi, rasctl)
- Fix gpiobus.h
- make clean
- make
-
-[EOF]
\ No newline at end of file
diff --git a/doc/fullspec.png b/doc/fullspec.png
deleted file mode 100644
index b80fee28..00000000
Binary files a/doc/fullspec.png and /dev/null differ
diff --git a/doc/pinassign.png b/doc/pinassign.png
deleted file mode 100644
index a334ade7..00000000
Binary files a/doc/pinassign.png and /dev/null differ
diff --git a/doc/rascsi.1 b/doc/rascsi.1
index 07ab3e05..e8c8e1f4 100644
--- a/doc/rascsi.1
+++ b/doc/rascsi.1
@@ -3,19 +3,28 @@
rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins
.SH SYNOPSIS
.B rascsi
-[\fB\-IDn\fR \fIfile\fR]
-[\fB\-HDn\fR \fIfile\fR]...
+[\fB\-F\f® \fIFOLDER\fR]
+[\fB\-L\f® \fILOG_LEVEL\fR]
+[\fB\-h\fR]
+[\fB\-n\fR \fIVENDOR:PRODUCT:REVISION\fR]
+[\fB\-p\f® \fIPORT\fR]
+[\fB\-r\fR \fIRESERVED_IDS\fR]
+[\fB\-n\fR \fITYPE\fR]
+[\fB\-v\fR]
+[\fB\-IDn:[u]\fR \fIFILE\fR]
+[\fB\-HDn[:u]\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.
+In the arguments to RaSCSI, one or more SCSI (-IDn[:u]) or SASI (-HDn[:u]) devices can be specified.
+The number (n) after the ID or HD identifier specifies the ID number for that device. The optional number (u) specifies the LUN (logical unit) for that device. The default LUN is 0.
+For SCSI: The ID is limited from 0-7. However, typically SCSI ID 7 is reserved for the "initiator" (the host computer). The LUN is limited from 0-31. 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.
+RaSCSI will determine 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)
+ hds: SCSI Hard Disk image (generic, non-removable)
+ hdr: SCSI Hard Disk image (generic, removable)
hdn: SCSI Hard Disk image (NEC GENUINE)
hdi: SCSI Hard Disk image (Anex86 HD image)
nhd: SCSI Hard Disk image (T98Next HD image)
@@ -26,37 +35,69 @@ RaSCSI will determin the type of device based upon the file extension of the FIL
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 starts, it will open a socket (default port is 6868) to allow external management commands.
+If another process is using the rascsi port, 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)
+.BR \-b\fI " " \fIBLOCK_SIZE
+The optional block size. For SCSI drives 512, 1024, 2048 or 4096 bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default is 256 bytes.
+.TP
+.BR \-F\fI " " \fIFOLDER
+The default folder for image files. For files in this folder no absolute path needs to be specified. The initial default folder is '~/images'.
+.TP
+.BR \-L\fI " " \fILOG_LEVEL
+The rascsi log level (trace, debug, info, warn, err, critical, off). The default log level is 'info'.
+.TP
+.BR \-h\fI " " \fI
+Show a help page.
+.TP
+.BR \-n\fI " " \fIVENDOR:PRODUCT:REVISION
+Set the vendor, product and revision for the device, to be returned with the INQUIRY data. A complete set of name components must be provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up to 4 characters. Padding with blanks to the maxium length is automatically applied. Once set the name of a device cannot be changed.
+.TP
+.BR \-p\fI " " \fIPORT
+The rascsi server port, default is 6868.
+.TP
+.BR \-r\fI " " \fIRESERVED_IDS
+Comma-separated list of IDs to reserve.
+.BR \-p\fI " " \fITYPE
+The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP). If no type is specified for devices that support an image file, rascsi tries to derive the type from the file extension.
+.TP
+.BR \-v\fI " " \fI
+Display the rascsi version.
+.TP
+.BR \-ID\fIn[:u] " " \fIFILE
+n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0.
.IP
-FILE is the name of the image file to attach to that ID.
+FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP) a dummy name must be provided.
.TP
-.BR \-HD\fIn " " \fIFILE
-n is the SASI ID number (0-15)
+.BR \-HD\fIn[:u] " " \fIFILE
+n is the SASI ID number (0-15). The effective SASI ID is calculated as n/2, the effective SASI LUN is calculated is the remainder of n/2. Alternatively the n:u syntax can be used, where ns is the SASI ID (0-7) and u the LUN (0-1).
.IP
-FILE is the name of the image file to attach to that ID.
+FILE is the name of the image file to use for the SASI device.
.IP
-Note: SASI usage is rare, and is typically limited to early Sharp X68000 systems.
+Note: SASI usage is rare, and is typically limited to early Unix workstations and 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
+Launch RaSCSI with an Apple hard drive image as ID 0 and a CD-ROM as ID 2
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
+Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw device file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter as ID 6:
+ rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME
+
To create an empty, 100MB HD image, use the following command:
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
+In case the fallocate command is available a much faster alternative to the dd command is:
+ fallocate -l 104857600 /path/to/newimage.hda
+
.SH SEE ALSO
-rasctl(1), scsimon(1)
+rasctl(1), scsimon(1), rasdump(1), sasidump(1)
Full documentation is available at:
diff --git a/doc/rascsi.txt b/doc/rascsi.txt
deleted file mode 100644
index 6b1c6d90..00000000
--- a/doc/rascsi.txt
+++ /dev/null
@@ -1,335 +0,0 @@
-------------------------------------------------------------------------------
-
- SCSI Target Emulator RaSCSI (*^..^*)
- for Raspberry Pi
-
- Powered by XM6 TypeG Technology.
- Copyright (C) 2016-2020 GIMONS
-
-------------------------------------------------------------------------------
-□RaSCSIとは
- RaSCSIはRaspberry Piで動作するSCSIデバイス(ハードディスク,MO,CD-ROM)を
- 仮想的に再現するエミュレータです。SCSIを採用したSHARPのX68000で使用する
- ことを目的として開発しました。RaSCSIを導入したRaspberry PiをX68000のSCSI
- コネクタに接続するだけで物理的なSCSIデバイスとして認識されます。
-
- X68000以外にもSCSIを採用したFM TOWNSやPC98等のレトロPCでも使用できるかも
- しれません。作者はFM TOWNSとPC9821Ceで動作するところまでは確認しています。
-
- RaSCSIはSCSIデバイスをエミュレートするソフトウェアに加えてRaspberry Piの
- GPIOコネクタをSCSIコネクタに変換する機構の総称を指します。
-
-□動作環境
- (1)Raspberry Pi
- Raspberry Pi Zero
- Raspberry Pi Zero W
- Raspberry Pi Zero WH
- Raspberry Pi 2 Model B
- Raspberry Pi 3 Model B(推奨)
- Raspberry Pi 3 Model A+
- Raspberry Pi 3 Model B+
- Raspberry Pi 4 Model B
-
- Zero/Zero W/Zero WHでは性能的に少し不安定かもしれません。
-
- 3 Model A+/3 Model B+/4 Model Bは高性能ですが熱の影響でCPUクロックが
- 変動することがありますので対策が必要でしょう。
-
- (2)OS
- RASPBIAN BUSTERで開発およびテストしています。
- RaSCSIはSCSI信号をGPIOを利用して制御しているので可能な限り低レイテンシー
- の状態で使用する必要があります。したがってCUIモードで利用することを推奨
- します。
-
-□SCSIコネクタとの接続方法
- 状況が複雑になってきましたのでRaSCSIのホームページ上で情報提供しています。
- このドキュメントの最後にある公式ホームページを参考にして下さい。
-
-□配布物
- 配布するアーカイブには実行ファイル、ドキュメント、ソースコードのそれぞれが
- ディレクトリで分かれて含まれています。
-
- bin/ ・・・ 実行ファイル
- raspberrypi/ ・・・ RPI用のプログラム
- rascsi.tar.gz ・・・ 実行ファイルをtar+gzipしたもの。
-
- x68k/ ・・・ X68000用の専用ドライバ
- RASDRIVER.XDF・・・ 二つのドライバを含むフロッピーイメージ
- RASDRIVER.HDS・・・ 二つのドライバを含むSCSI HDイメージ
- RASDRIVER.HDF・・・ 二つのドライバを含むSASI HDイメージ
-
- doc/ ・・・ ドキュメント
- rascsi.txt ・・・ 当ドキュメント
- x68k.txt ・・・ X68000固有機能の説明
- converter.txt ・・・ 変換基板の説明
- pinassign.png ・・・ ピンアサイン図
- target.png ・・・ 変換基板回路図案(ターゲットモード)
- fullspec.png ・・・ 変換基板回路図案(フルスペック)
-
- src/ ・・・ ソースコード
- raspberrypi/ ・・・ RPI用のプログラムソース一式
- x68k/ ・・・ X68000用のプログラム一式
-
-
- RPIで使用するプログラムはrascsi.tar.gzですのでRPI上に転送してから解凍して
- 下さい。パーミッション等を維持するためにRPI上で解凍することを推奨します。
-
- rascsi.tar.gzにはstandard,fullspec,aibom,gamerniumのディレクトリが含まれ
- ています。
-
- 直結ケーブルや直結基板を使用する場合はstandardディレクトリの実行ファイル
- を使用して下さい。
-
- 同様にフルスペック版と説明された変換基板の場合はfullspecのディレクトリの
- ものを使用します(直結でも動くと思います)。
-
- aibom,gamerniumディレクトリのものは"あいぼむ版","GAMERnium版"の変換基板を
- 使用する時のものです。
-
- X68000用のドライバはRASDRIVER.XDFもしくはRASDRIVER.HDSの中に次の二つが含ま
- れています。
- RASDRV.SYS ・・・ ホストドライブドライバ
- RASETHER.SYS ・・・ イーサネットドライバ
-
-□RASCI本体の使用方法(rascsi)
-
- ID指定の場合
- rascsi [-IDn FILE] ...
- n:0~7
-
- HD指定の場合(X68000 SASI機のHD指定互換)
- rascsi [-HDn FILE] ...
- n:0~15
-
- ルート権限が必要ですのでsudo等で起動する必要があります。
- オプションに-hを付けると簡単なHELPが表示されます
-
- Usage: rascsi [-IDn FILE] ...
-
- n is SCSI identification number(0-7).
- FILE is disk image file.
-
- Usage: rascsi [-HDn FILE] ...
-
- n is X68000 SASI HD number(0-15).
- FILE is disk image file.
-
- Image type is detected based on file extension.
- hdf : SASI HD image(XM6 SASI HD image)
- hds : SCSI HD image(XM6 SCSI HD image)
- hdn : SCSI HD image(NEC GENUINE)
- hdi : SCSI HD image(Anex86 HD image)
- nhd : SCSI HD image(T98Next HD image)
- hda : SCSI HD image(APPLE GENUINE)
- mos : SCSI MO image(XM6 SCSI MO image)
- iso : SCSI CD image(ISO 9660 image)
-
- 引数では-IDnもしくは-HDnとFILEの一組で一つのSCSI(SASI)デバイスを指定できます。
- -IDの後ろの番号はSCSI(SASI) IDです。IDは0-7を指定できますが通常レトロPC本体
- がイニシエータとしてID7等を使用していると思います。その場合は0-6を指定する
- ことになります。
-
- FILEは仮想ディスクイメージのファイルパスです。イメージファイル名には拡張子
- が必要です。拡張子によってHD,MO,CDの種別を判定しています。
-
- 例)SCSI ID0にHDIMAGE0.HDS,ID1にHDIMAGE1.HDSを指定して起動する場合、
- sudo rascsi -ID0 HDIMAGE0.HDS -ID1 HDIMAGE1.HDS
-
- 終了する場合はCTRL+Cで停止します。
- バックグラウンドで起動した場合にはkillコマンド該当プロセスにINTシグナルか
- HUPシグナルを送ることで終了します。
-
- rascsiは起動後にソケット(6868ポート)を開いて外部からの管理コマンドを受け
- 付ける状態になります。したがって既に別プロセスとしてrascsiが起動している
- 場合はエラーメッセージとともに起動を中断します。
-
-□管理ツールの使用方法(rasctl)
- バージョン1.10からrasctlという管理ツールを提供します。これはrascsiプロセス
- がバックグラウンドで起動(6868ポートで接続待ちの状態)している場合にディスク
- 操作のコマンドを発行することが可能となります。コマンドラインは下記の通り。
-
- rasctl -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE]
-
- ID : SCSI ID(0~7)
- UNIT : ユニット番号(0または1)
- CMD : 操作コマンド
- attach : ディスクを取り付ける
- detach : ディスクを取り外す
- insert : メディアを挿入する(MOまたはCDのみ)
- eject : メディアを取り出す(MOまたはCDのみ)
- protect : メディアを書き込み禁止にする(MOのみ)
- TYPE : ディスク種別
- hd : ハードディスク(SASI/SCSI)
- mo : MO(光磁気ディスク)
- cd : CDROM(CDROMドライブ)
- bridge : ブリッジデバイス
- FILE : ディスクイメージファイルのパス
-
- IDは必須です。UNITは省略時は0です(SCSIの場合は0を基本とします)。
- CMDは省略時はattachと解釈します。TYPEはコマンドがattachの場合にはFILEの拡張子
- から自動判定します。FILEはTYPEを明示的に指定している場合は拡張子が異なっても
- 構いません。基本的CMD,TYPEの解釈は大文字小文字を無視します。最初の1文字でのみ
- 判定しています。
-
- コマンド例
- rasctl -i 0 -f HDIMAGE0.HDS
-
- の場合はSCSI IDは0。CMDはデフォルトでattachでありTYPEは拡張子HDSから判断
- するのでhdと推測することになりrascsi起動時のオプション指定と同等です。
-
- 現在の状態を確認するにために-lオプションのみを指定するとデバイス一覧が表示
- されます。コマンドラインは下記の通り。
-
- rasctl -l
-
- rasctl自体の起動にはルート権限は必要ありません。
-
-□ディスクダンプツールの使用方法(rasdump)
- 直結もしくは直結基板、またはフルスペック基板向けのサンプルプログラムです。
-
- 名前の通りSCSI HDDやMOのイメージをダンプ(オプションでリストア)します。
- 自身のIDはBIDで指定して下さい。省略時は7を使用します。
-
- rasdump -i ID [-b BID] -f FILE [-r]
- ID : ターゲットデバイスのSCSI ID
- BID : RaSCSI自身のSCSI ID
- FILE : ダンプファイル名
- -r : リストアモード
-
- サンプルなので必要最低限の処理しか実装していませんので改造するなりして
- ご使用下さい。
-
-□SASI専用ディスクダンプツールの使用方法(sasidump)
- rasdumpをベースにSASI専用に作成したダンプツールです。
- SASI HDイメージをダンプ(オプションでリストア)します。
-
- sasidump -i ID [-u UT] [-b BSIZE] -c COUNT -f FILE [-r]
- ID : ターゲットデバイスのSASI ID
- UT : ターゲットデバイスのUNIT ID
- BSIZE: ブロックサイズ(デフォルトは512)
- COUNT: ブロック数
- FILE : ダンプファイル名
- -r : リストアモード
-
-□ソースから実行ファイルをコンパイルする場合
- スタンダード版
- make CONNECT_TYPE=STANDARD
-
- フルスペック版
- make CONNECT_TYPE=FULLSPEC
-
- あいぼむ版
- make CONNECT_TYPE=AIBOM
-
- GAMERnium版
- make CONNECT_TYPE=GAMERNIUM
-
-□サポートするディスクイメージ
- (1)SCSI ハードディスク
- HDSファイル形式 (拡張子HDS/HDN/HDI/NHD/HDA)
- ファイルサイズは10MB以上4095MB以下の範囲で任意のサイズ(但し512バイト単位)
-
- 拡張子が"HDN"の場合はNEC純正55ボード(PC-9801-55)向けの純正ハードディスク
- エミュレーションを行います。INQUIRYで返却される情報やMODE SENSEのサイズに
- に違いがあります。
-
- 拡張子が"HDI","NHD"の場合はそれぞれPC98エミュレータであるAnex86及びT98Next
- のSCSIハードディスクイメージを使用するものです。HDNの時と同様に一部の情報
- がNEC用に変換されます。
-
- 拡張子が"HDA"の場合はAPPLE純正ハードディスクエミュレーションを行います。
- INQUIRY及びMODE SENSEで返却される情報に違いがあります。
-
- (2)SASI ハードディスク
- HDFファイル形式 (拡張子HDF)
- ファイルサイズは10441728バイト、20748288バイト、41496576バイトのいずれか
- (それぞれ10MBドライブ、20MBドライブ、40MBドライブに対応)を推奨します。
- 256バイト単位であれば10M~512Mの任意のファイルサイズがマウント可能です。
-
- Version1.46から22437888バイトのイメージはMZ-2500/MZ-2800 MZ-1F23専用の
- 20MBイメージとして認識します(ブロックサイズが1024という特殊イメージ)。
-
- (3)SCSI 光磁気(MO)ディスク
- MOSファイル形式 (拡張子MOS)
- ファイルサイズは次の4種類のいずれか:
- 128MBタイプ (127398912バイト)
- 230MBタイプ (228518400バイト)
- 540MBタイプ (533248000バイト)
- 640MBタイプ (635600896バイト)
- 128MB,230MB,540MBは512バイト/セクタ、640MBは2048バイト/セクタになります。
-
- (4)SCSI CD-ROMディスク
- ISOファイル形式 (拡張子ISO、ISO9660ベタイメージ)
- モード1(2048バイト/セクタ)で、データのみ格納されたファイルとRAW形式で記録
- されたファイルの両方に対応しています。
-
-□ディスクイメージの作成
- RaSCSI自体がX68000エミュレータであるXM6 TypeGの派生物です。従ってディスク
- イメージの作成はXM6 TypeGの「ツール」メニューから行うことを前提としています。
- もちろん先に説明した仕様に従えばdd等で空のイメージファイルを作成することも
- 可能です。
-
- 例)100MBのHDSイメージ(空ファイル)を作る場合
-
- dd if=/dev/zero of=HARDDISK.HDS bs=512 count=204800
-
-□動作実績
- 作者の開発環境であるX68000 PRO(内蔵SASI/純正SCSIボード)、X68030 内蔵SCSI、
- XVI Compact 内蔵SCSIで動作確認しています。Mach-2でも動作しました。
-
- 他にも初代X68000,ACE,EXPERT,XVI,PRO2,SUPER等で動作報告がありましたので、
- X68000シリーズはほぼ問題ないでしょう。
-
- その他のレトロPCではFM TOWNSシリーズ、Apple Macintosh、MSX(MEGA-SCSI利用)
- で動作報告があります。PC98シリーズは動作したという報告も多数ありますが、
- SCSIボードによっては全く動作しないという報告もあります。
-
-□活用方法
- XM6等のX68000エミュレータを使用している場合はエミュレータで環境構築したHDD
- イメージをFTP等でRaspberry Piに転送することでX68000の実機に接続できます。
- またその逆も然りで実機上に存在するファイルを格納したHDDイメージをPCにFTP等
- で転送することでエミュレータで活用することができます。
-
-□ライセンス
- RaSCSIはあるがまま"AS IS"で配布されるソフトウェアです。
-
- つまり使用者が受けたあらゆる損害に対して一切責任を持ちません。またソフト
- ウェアに不備もしくは不具合があったとしてもそれを修正する責任もありません。
-
- RaSCSIを利用することでRaspberry PiやレトロPCが故障するリスクがあります。
- あくまで自己責任でチャレンジしてください。
-
- XM6 TypeG同様に実験成果公開という性質上私のHP以外での配布を認めておりません。
-
- XM6のライセンス条項を継承していますので雑誌/書籍での紹介事前の許諾が必要です。
- そもそも2019年にもなってSCSIに反応するのは限られた人だけだと思います。
-
-□変換基板の頒布について
- 変換基板を有償で頒布する場合は下記の条件に従う限り作者に許諾を得る必要は
- ありません。重要なことは基板を購入したユーザーに十分な情報を提供することと
- 心得て下さい。
-
- 1.頒布価格
- 基板製作費 + パーツ費用 + 運送費 +(社会通念上一般的な)手数料。
-
- 2.回路図
- 購入者に回路図を提供して下さい。基板頒布と同時もしくは別途ホームページから
- のダウンロード等手段は自由です。
-
- 3.動作検証
- X68000実機環境の動作検証は必須とします。実機が手に入らない場合はX68000
- ユーザーの方に検証の協力をお願いしてもよいでしょう。動作検証は起動確認以外
- に書き込みや負荷テストをお願いします。検証結果は使用した環境やと共に公開
- して下さい。
-
-□変換基板(公式版)について
- BOOTHで2019年3月以降配布しています(数に限りがありますので不定期です)。
-
-□公開ホームページ
- http://retropc.net/gimons/rascsi/
-
-□連絡先
- twitter https://twitter.com/kugimoto0715
- e-mail gimons.developer.works@gmail.com
-
-[EOF]
diff --git a/doc/rascsi_en.txt b/doc/rascsi_en.txt
deleted file mode 100644
index fa9a49cf..00000000
--- a/doc/rascsi_en.txt
+++ /dev/null
@@ -1,335 +0,0 @@
--------------------------------------------------- ----------------------------
-
- SCSI Target Emulator RaSCSI (*^..^*)
- for Raspberry Pi
-
- Powered by XM6 TypeG Technology.
- Copyright (C) 2016-2020 GIMONS
-
--------------------------------------------------- ----------------------------
-□ What is RaSCSI
- RaSCSI is a SCSI device (hard disk, MO, CD-ROM) that operates on the Raspberry Pi.
- It is a virtual emulator. Use with SHARP X68000 that adopts SCSI
- It was developed for that purpose. Raspberry Pi with RaSCSI installed on the X68000 SCSI
- Simply connect it to the connector and it will be recognized as a physical SCSI device.
-
- In addition to the X68000, it may be possible to use it with a retro PC such as FM TOWNS or PC 98 that adopted SCSI.
- May. The author has confirmed that it works with FM TOWNS and PC9821Ce.
-
- RaSCSI is a software that emulates SCSI devices plus Raspberry Pi
- Refers to the general term for the mechanism that converts a GPIO connector into a SCSI connector.
-
-□ Operating environment
- (1) Raspberry Pi
- Raspberry Pi Zero
- Raspberry Pi Zero W
- Raspberry Pi Zero WH
- Raspberry Pi 2 Model B
- Raspberry Pi 3 Model B (recommended)
- Raspberry Pi 3 Model A+
- Raspberry Pi 3 Model B+
- Raspberry Pi 4 Model B
-
- Performance may be a little unstable with Zero/Zero W/Zero WH.
-
- 3 Model A+/3 Model B+/4 Model B has high performance, but CPU clock is affected by heat.
- It may fluctuate, so it will be necessary to take measures.
-
- (2) OS
- Developed and tested by RASPBIAN BUSTER.
- RaSCSI uses GPIO to control SCSI signals, so latency is as low as possible.
- Must be used in the state of. Therefore, it is recommended to use it in CUI mode.
- To do.
-
-□ Connection method with SCSI connector
- Since the situation has become complicated, we provide information on the RaSCSI home page.
- Please refer to the official website at the end of this document.
-
-□ Handout
- The executable file, the document, and the source code are stored in the distributed archive.
- It is divided and included in the directory.
-
- bin/ ・・・ Executable file
- raspberrypi/ ・・・ RPI program
- rascsi.tar.gz ・・・ The tar+gzip of the executable file.
-
- x68k/ ・・・ Dedicated driver for X68000
- RASDRIVER.XDF... A floppy image containing two drivers
- RASDRIVER.HDS... A SCSI HD image containing two drivers
- RASDRIVER.HDF... SASI HD image containing two drivers
-
- doc/ ・・・Documents
- rascsi.txt ・・・ This document
- x68k.txt ・・・ Description of X68000 specific functions
- converter.txt ・・・ Description of converter board
- pinassign.png ・・・ Pin assignment diagram
- target.png ・・・ Conversion board circuit pattern (target mode)
- fullspec.png ・・・Conversion board circuit pattern (full spec)
-
- src/ ・・・ Source code
- raspberrypi/ ・・・ Set of program source for RPI
- x68k/ ・・・ Set of programs for X68000
-
-
- The program used in RPI is rascsi.tar.gz, so transfer it to RPI and decompress it.
- Please. It is recommended to unzip on RPI to maintain permissions etc.
-
- rascsi.tar.gz contains standard, fullspec, aibom and gamernium directories.
- I am.
-
- Executable file in the standard directory when using a direct connection cable or direct connection board
- Please use.
-
- Similarly, in the case of the conversion board described as the full spec version, in the fullspec directory
- I will use one (I think that it works even if it is directly connected).
-
- For the aibom and gamernium directories, use the conversion boards of "Aibomu version" and "GAMERnium version".
- It is when using.
-
- The driver for X68000 includes the following two in RASDRIVER.XDF or RASDRIVER.HDS
- It is
- RASDRV.SYS ・・・ Host drive driver
- RASETHER.SYS ・・・ Ethernet driver
-
-□ How to use RASCI main unit (rascsi)
-
- When ID is specified
- rascsi [-IDn FILE] ...
- n:0 ~ 7
-
- When specifying HD (compatible with HD specification of X68000 SASI machine)
- rascsi [-HDn FILE] ...
- n: 0 ~ 15
-
- Since root authority is required, it is necessary to start with sudo etc.
- If you add -h to the option, a simple HELP will be displayed
-
- Usage: rascsi [-IDn FILE] ...
-
- n is SCSI identification number(0-7).
- FILE is disk image file.
-
- Usage: rascsi [-HDn FILE] ...
-
- n is X68000 SASI HD number(0-15).
- FILE is disk image file.
-
- Image type is detected based on file extension.
- hdf: SASI HD image(XM6 SASI HD image)
- hds: SCSI HD image(XM6 SCSI HD image)
- hdn: SCSI HD image (NEC GENUINE)
- hdi: SCSI HD image(Anex86 HD image)
- nhd: SCSI HD image(T98Next HD image)
- hda: SCSI HD image(APPLE GENUINE)
- mos: SCSI MO image(XM6 SCSI MO image)
- iso: SCSI CD image (ISO 9660 image)
-
- In the argument, one SCSI (SASI) device can be specified by a pair of -IDn or -HDn and FILE.
- -The number after the ID is the SCSI (SASI) ID. You can specify 0-7 as the ID, but usually the retro PC body
- I think you are using ID7 etc. as the initiator. In that case, specify 0-6
- It will be.
-
- FILE is the file path of the virtual disk image. The image file name has an extension
- Is required. The type of HD, MO, CD is determined by the extension.
-
- Example) When you specify HDIMAGE0.HDS for SCSI ID0 and HDIMAGE1.HDS for ID1 and start up,
- sudo rascsi -ID0 HDIMAGE0.HDS -ID1 HDIMAGE1.HDS
-
- When you finish, press CTRL+C to stop.
- If it is started in the background, is the kill command an INT signal to the relevant process?
- It ends by sending a HUP signal.
-
- After starting, rascsi opens a socket (6868 port) and receives external management commands.
- It is ready to be attached. Therefore, rascsi has already started as another process.
- If so, the boot will abort with an error message.
-
-□ How to use the management tool (rasctl)
- We provide a management tool called rasctl from version 1.10. This is the rascsi process
- Disk is running in the background (waiting for connection on port 6868)
- It is possible to issue operation commands. The command line is as follows.
-
- rasctl -i ID [-u UNIT] [-c CMD] [-t TYPE] [-f FILE]
-
- ID: SCSI ID (0 to 7)
- UNIT: Unit number (0 or 1)
- CMD: Operation command
- attach: attach disk
- detach: detach disk
- insert: insert media (MO or CD only)
- eject: Eject media (MO or CD only)
- protect: Write protect the media (MO only)
- TYPE: Disc type
- hd: Hard disk (SASI/SCSI)
- mo: MO (magneto-optical disk)
- cd: CDROM (CDROM drive)
- bridge: Bridge device
- FILE: Path of disk image file
-
- ID is required. UNIT defaults to 0 (default is 0 for SCSI).
- CMD is interpreted as attach when omitted. TYPE is the extension of FILE when the command is attach
- It will automatically judge from. FILE has a different extension if TYPE is explicitly specified.
- does not matter. Basic interpretation of CMD and TYPE is case insensitive. Only the first letter
- Judging.
-
- Command example
- rasctl -i 0 -f HDIMAGE0.HDS
-
- Is 0, the SCSI ID is 0. CMD is attach by default and TYPE is determined from the extension HDS
- Therefore, it is supposed to be hd and it is equivalent to the option specification when starting rascsi.
-
- If only -l option is specified to check the current status, the device list is displayed.
- Will be done. The command line is as follows.
-
- rasctl -l
-
- You do not need root privileges to start rasctl itself.
-
-□ How to use Disk Dump Tool (rasdump)
- Sample program for direct connection or direct connection board, or full-spec board.
-
- As the name suggests, it dumps (optionally restores) the image of SCSI HDD or MO.
- Specify your own ID as BID. If omitted, 7 is used.
-
- rasdump -i ID [-b BID] -f FILE [-r]
- ID: SCSI ID of the target device
- BID: RaSCSI's own SCSI ID
- FILE: dump file name
- -r: Restore mode
-
- Since it is a sample, only the minimum necessary processing is implemented, so do not modify it
- Please use.
-
-□ How to use SASI dedicated disk dump tool (sasidump)
- A dump tool created for SASI based on rasdump.
- Dump (optionally restore) the SASI HD image.
-
- sasidump -i ID [-u UT] [-b BSIZE] -c COUNT -f FILE [-r]
- ID: SASI ID of the target device
- UT: UNIT ID of the target device
- BSIZE: Block size (default 512)
- COUNT: Number of blocks
- FILE: dump file name
- -r: Restore mode
-
-□ When compiling the executable file from the source
- Standard edition
- make CONNECT_TYPE=STANDARD
-
- Full spec version
- make CONNECT_TYPE=FULLSPEC
-
- Aibomu version
- make CONNECT_TYPE=AIBOM
-
- GAMERnium version
- make CONNECT_TYPE=GAMERNIUM
-
-□ Supported disk images
- (1) SCSI hard disk
- HDS file format (extension HDS/HDN/HDI/NHD/HDA)
- The file size can be any size within the range of 10MB to 4095MB (in 512-byte units)
-
- If the extension is "HDN", a genuine hard disk for NEC genuine 55 board (PC-9801-55)
- Perform emulation. For information returned by INQUIRY and MODE SENSE size
- There is a difference.
-
- If the extension is "HDI" or "NHD", the PC98 emulator is Annex86 or T98Next.
- It is intended to use a SCSI hard disk image. Some information as in HDN
- Is converted for NEC.
-
- If the extension is "HDA", APPLE genuine hard disk emulation is performed.
- There is a difference in the information returned by INQUIRY and MODE SENSE.
-
- (2) SASI hard disk
- HDF file format (extension HDF)
- File size is either 10441728 bytes, 20748288 bytes, or 41496576 bytes
- We recommend 10MB drive, 20MB drive and 40MB drive respectively.
- Any file size from 10M to 512M can be mounted in 256-byte units.
-
- Images from version 1.46 to 22437888 bytes are for MZ-2500/MZ-2800 MZ-1F23
- Recognized as a 20MB image (special image with a block size of 1024).
-
- (3) SCSI magneto-optical (MO) disk
- MOS file format (extension MOS)
- File size is one of the following four types:
- 128MB type (127398912 bytes)
- 230MB type (228518400 bytes)
- 540MB type (533248000 bytes)
- 640MB type (635600896 bytes)
- 128MB, 230MB, 540MB is 512 bytes/sector and 640MB is 2048 bytes/sector.
-
- (4) SCSI CD-ROM disk
- ISO file format (extension ISO, ISO9660 solid image)
- Record in a file containing only data and in RAW format in mode 1 (2048 bytes/sector)
- Both files are supported.
-
-□ Disk image creation
- RaSCSI itself is a derivative of the XM6 TypeG, an X68000 emulator. Therefore the disc
- It is assumed that the image is created from the "Tools" menu of XM6 TypeG.
- Of course, you can also create an empty image file with dd etc. according to the specifications explained above.
- Is possible.
-
- Example) When creating a 100 MB HDS image (empty file)
-
- dd if=/dev/zero of=HARDDISK.HDS bs=512 count=204800
-
-□ Operation record
- The author's development environment X68000 PRO (built-in SASI/genuine SCSI board), X68030 built-in SCSI,
- We have confirmed the operation with the XVI Compact built-in SCSI. It also worked on Mach-2.
-
- Since there were other operation reports on the first generation X68000, ACE, EXPERT, XVI, PRO2, SUPER, etc.,
- The X68000 series should be fine.
-
- For other retro PCs, FM TOWNS series, Apple Macintosh, MSX (using MEGA-SCSI)
- There is an operation report in. There are many reports that the PC98 series worked, but
- Some SCSI boards do not even work at all.
-
-□ How to use
- If you are using an X68000 emulator such as XM6, HDD that is built by the emulator
- You can connect to the actual X68000 machine by transferring the image to the Raspberry Pi by FTP etc.
- The reverse is also true, and the HDD image that stores the files that exist on the actual machine is FTPed to the PC, etc.
- You can use it in the emulator by transferring with.
-
-□ License
- RaSCSI is software distributed as is "AS IS".
-
- That is, we do not take any responsibility for any damages that the user receives. Soft again
- We are not responsible for fixing any defects or defects in the software.
-
- There is a risk that the Raspberry Pi and retro PC will break down by using RaSCSI.
- Please challenge at your own risk.
-
- As with XM6 TypeG, we are not allowed to distribute it on other than my HP due to the nature of experimental results disclosure.
-
- As it inherits the license terms of XM6, introduction in magazines/books requires prior permission.
- In the first place, I think only a limited number of people will respond to SCSI in 2019.
-
-□About distribution of conversion boards
- If you want to distribute the conversion board for a fee, it is not necessary to obtain permission from the author as long as you follow the conditions below.
- There is none. It is important to provide enough information to the user who purchased the board.
- Please understand.
-
- 1.Distribution price
- Board production cost + parts cost + transportation cost + (general social convention) fee.
-
- 2. Schematic
- Please provide the buyer with the schematic. Simultaneously with board distribution or separately from homepage
- There are no restrictions on the means of downloading.
-
- 3. Operation verification
- Operation verification of the X68000 actual machine environment is mandatory. If you can not get the real machine X68000
- You may ask the user to cooperate with the verification. Operation verification is other than startup confirmation
- Please write and load test. Verification results are published together with the environment in which they were used
- please do it.
-
-□ About conversion board (official version)
- It has been distributed on BOOTH since March 2019 (it is irregular because the number is limited).
-
-□ Public homepage
- http://retropc.net/gimons/rascsi/
-
-□ Contact information
- twitter https://twitter.com/kugimoto0715
- e-mail gimons.developer.works@gmail.com
-
-[EOF]
\ No newline at end of file
diff --git a/doc/rascsi_man_page.txt b/doc/rascsi_man_page.txt
index de2f98f8..ca6b25cc 100644
--- a/doc/rascsi_man_page.txt
+++ b/doc/rascsi_man_page.txt
@@ -2,65 +2,136 @@
!! ------ The native file is rascsi.1. Re-run 'make docs' after updating
-rascsi(1) General Commands Manual rascsi(1)
+rascsi(1) General Commands Manual rascsi(1)
NAME
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
SYNOPSIS
- rascsi [-IDn file] [-HDn file]...
+ rascsi [-F[u00AE] FOLDER] [-L[u00AE] LOG_LEVEL] [-h] [-n VENDOR:PROD‐
+ UCT:REVISION] [-p[u00AE] PORT] [-r RESERVED_IDS] [-n TYPE] [-v]
+ [-IDn:[u] FILE] [-HDn[:u] 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 com‐
- puters.
+ In the arguments to RaSCSI, one or more SCSI (-IDn[:u]) or SASI
+ (-HDn[:u]) devices can be specified. The number (n) after the ID or HD
+ identifier specifies the ID number for that device. The optional number
+ (u) specifies the LUN (logical unit) for that device. The default LUN
+ is 0. For SCSI: The ID is limited from 0-7. However, typically SCSI ID
+ 7 is reserved for the "initiator" (the host computer). The LUN is lim‐
+ ited from 0-31. 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)
+ RaSCSI will determine 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 (generic, non-removable)
+ hdr: SCSI Hard Disk image (generic, removable)
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)
+ 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:
+ 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 in‐
- stance of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used to send commands.
+ Once RaSCSI starts, it will open a socket (default port is 6868) to al‐
+ low external management commands. If another process is using the
+ rascsi port, 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.
+ 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)
+ -b BLOCK_SIZE
+ The optional block size. For SCSI drives 512, 1024, 2048 or 4096
+ bytes, default size is 512 bytes. For SASI drives 256 or 1024
+ bytes, default is 256 bytes.
- FILE is the name of the image file to attach to that ID.
+ -F FOLDER
+ The default folder for image files. For files in this folder no
+ absolute path needs to be specified. The initial default folder
+ is '~/images'.
- -HDn FILE
- n is the SASI ID number (0-15)
+ -L LOG_LEVEL
+ The rascsi log level (trace, debug, info, warn, err, critical,
+ off). The default log level is 'info'.
- FILE is the name of the image file to attach to that ID.
+ -h Show a help page.
- Note: SASI usage is rare, and is typically limited to early Sharp X68000 systems.
+ -n VENDOR:PRODUCT:REVISION
+ Set the vendor, product and revision for the device, to be re‐
+ turned with the INQUIRY data. A complete set of name components
+ must be provided. VENDOR may have up to 8, PRODUCT up to 16, RE‐
+ VISION up to 4 characters. Padding with blanks to the maxium
+ length is automatically applied. Once set the name of a device
+ cannot be changed.
+
+ -p PORT
+ The rascsi server port, default is 6868.
+
+ -r RESERVED_IDS
+ Comma-separated list of IDs to reserve. -p TYPE The optional
+ case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO,
+ SCBR, SCDP). If no type is specified for devices that support an
+ image file, rascsi tries to derive the type from the file exten‐
+ sion.
+
+ -v Display the rascsi version.
+
+ -IDn[:u] FILE
+ n is the SCSI ID number (0-7). u (0-31) is the optional LUN
+ (logical unit). The default LUN is 0.
+
+ FILE is the name of the image file to use for the SCSI device.
+ For devices that do not support an image file (SCBR, SCDP) a
+ dummy name must be provided.
+
+ -HDn[:u] FILE
+ n is the SASI ID number (0-15). The effective SASI ID is calcu‐
+ lated as n/2, the effective SASI LUN is calculated is the re‐
+ mainder of n/2. Alternatively the n:u syntax can be used, where
+ ns is the SASI ID (0-7) and u the LUN (0-1).
+
+ FILE is the name of the image file to use for the SASI device.
+
+ Note: SASI usage is rare, and is typically limited to early Unix
+ workstations and 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
+ Launch RaSCSI with an Apple hard drive image as ID 0 and a CD-ROM as ID
+ 2
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
+ Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de‐
+ vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter
+ as ID 6:
+ rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME
+
To create an empty, 100MB HD image, use the following command:
dd if=/dev/zero of=/path/to/newimage.hda bs=512 count=204800
+ In case the fallocate command is available a much faster alternative to
+ the dd command is:
+ fallocate -l 104857600 /path/to/newimage.hda
+
SEE ALSO
- rasctl(1), scsimon(1)
+ rasctl(1), scsimon(1), rasdump(1), sasidump(1)
- Full documentation is available at:
+ Full documentation is available at:
+
- rascsi(1)
+ rascsi(1)
diff --git a/doc/rasctl.1 b/doc/rasctl.1
index 1533a182..71cdd7c8 100644
--- a/doc/rasctl.1
+++ b/doc/rasctl.1
@@ -3,12 +3,33 @@
rasctl \- Sends management commands to the rascsi process
.SH SYNOPSIS
.B rasctl
+\fB\-e\fR |
\fB\-l\fR |
-\fB\-i\fR \fIID\fR
-[\fB\-u\fR \fIUNIT\fR]
+\fB\-m\fR |
+\fB\-s\fR |
+\fB\-v\fR |
+\fB\-D\fR |
+\fB\-I\fR |
+\fB\-L\fR |
+\fB\-O\fR |
+\fB\-T\fR |
+\fB\-V\fR |
+\fB\-X\fR |
+[\fB\-C\fR \fIFILENAME:FILESIZE\fR]
+[\fB\-E\fR \fIFILENAME\fR]
+[\fB\-F\fR \fIIMAGE_FOLDER\fR]
+[\fB\-R\fR \fICURRENT_NAME:NEW_NAME\fR]
[\fB\-c\fR \fICMD\fR]
+[\fB\-f\fR \fIFILE|PARAM\fR]
+[\fB\-g\fR \fILOG_LEVEL\fR]
+[\fB\-h\fR \fIHOST\fR]
+[\fB\-i\fR \fIID\fR
+[\fB\-n\fR \fINAME\fR]
+[\fB\-p\fR \fIPORT\fR]
+[\fB\-r\fR \fIRESERVED_IDS\fR]
[\fB\-t\fR \fITYPE\fR]
-[\fB\-f\fR \fIFILE\fR]
+[\fB\-u\fR \fIUNIT\fR]
+[\fB\-x\fR \fICURRENT_NAME:NEW_NAME\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.
@@ -17,55 +38,128 @@ 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.
+Note: The command and type arguments are case insensitive. Only the first letter of the command/type is evaluated by the tool.
.SH OPTIONS
.TP
+.BR \-C\fI " "\fIFILENAME:FILESIZE
+Create an image file in the default image folder with the specified name and size in bytes.
+.TP
+.BR \-D\fI
+Detach all devices.
+.TP
+.BR \-E\fI " " \fIFILENAME
+Display information on an image file.
+.TP
+.BR \-F\fI " "\fIIMAGE_FOLDER
+Set the default image folder.
+.TP
+.BR \-I\fI
+Gets the list of reserved device IDs.
+.TP
+.BR \-L\fI " "\fILOG_LEVEL
+Set the rascsi log level (trace, debug, info, warn, err, critical, off).
+.TP
+.BR \-h\fI " " \fIHOST
+The rascsi host to connect to, default is 'localhost'.
+.TP
+.BR \-e\fI
+List all images files in the default image folder.
+.TP
+.BR \-N\fI
+Lists all available network interfaces provided that they are up.
+.TP
+.BR \-O\fI
+Display the available rascsi server log levels and the current log level.
+.TP
.BR \-l\fI
List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
.TP
+.BR \-m\fI
+List all file extensions recognized by RaSCSI and the device types they map to.
+.TP
+.BR \-R\fI " "\fICURRENT_NAME:NEW_NAME
+Rename an image file in the default image folder.
+.TP
+.BR \-p\fI " " \fIPORT
+The rascsi port to connect to, default is 6868.
+.TP
+.BR \-r\fI " " \fIRESERVED_IDS
+Comma-separated list of IDs to reserve.
+.TP
+.BR \-s\fI
+Display server-side settings like available images or supported device types.
+.TP
+.BR \-T\fI
+Display all device types and their properties.
+.TP
+.BR \-v\fI " " \fI
+Display the rascsi server version.
+.TP
+.BR \-V\fI " " \fI
+Display the rasctl version.
+.TP
+.BR \-X\fI " " \fI
+Shut down the rascsi process.
+.TP
+.BR \-d\fI " "\fIFILENAME
+Delete an image file in the default image folder.
+.TP
+.BR \-x\fI " "\fICURRENT_NAME:NEW_NAME
+Copy an image file in the default image folder.
+.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)
+Command is the operation being requested. Options are:
+ a(ttach): Attach disk
+ d(etach): Detach disk
+ i(nsert): Insert media (removable media devices only)
+ e(ject): Eject media (removable media devices only)
+ p(rotect): Write protect the medium (not for CD-ROMs, which are always read-only)
+ u(nprotect): Remove write protection from the medium (not for CD-ROMs, which are always read-only)
+ s(how): Display device information
.IP
-When the command is omited, rasctl will default to the 'attach' command
+eject, protect and unprotect are idempotent.
+.TP
+.BR \-b\fI " " \fIBLOCK_SIZE
+The optional block size. For SCSI drives 512, 1024, 2048 or 4096 bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default is 256 bytes.
+.TP
+.BR \-f\fI " " \fIFILE|PARAM
+Device-specific: Either a path to a disk image file, or a parameter for a non-disk device. See the rascsi(1) man page for permitted file types.
.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)
+Specifies the device type. This type overrides the type derived from the file extension of the specified image. See the rascsi(1) man page for the available device types. For some types there are shortcuts (only the first letter is required):
+ hd: SCSI hard disk drive
+ rm: SCSI removable media drive
cd: CD-ROM
- bridge: Bridge device (This is only applicable to the Sharp X68000)
+ mo: Magneto-Optical disk
+ bridge: Bridge device (Only applicable to the Sharp X68000)
+ daynaport: DaynaPORT network adapter
.TP
-.BR \-f\fI " " \fIFILE
-Path to the disk image file. See the rascsi(1) man page for allowable file types.
+.BR \-n\fI " " \fIVENDOR:PRODUCT:REVISION
+The vendor, product and revision for the device, to be returned with the INQUIRY data. A complete set of name components must be provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up to 4 characters. Padding with blanks to the maxium length is automatically applied. Once set the name of a device cannot be changed.
+.TP
+.BR \-u\fI " " \fIUNIT
+Unit number (0-31). 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)
.SH EXAMPLES
-Show a listing of all of the SCSI devices and their current status
+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
- +----+----+------+-------------------------------------
+ +----+-----+------+-------------------------------------
+ | ID | LUN | TYPE | IMAGE FILE
+ +----+-----+------+-------------------------------------
+ | 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) scsimon(1)
+rascsi(1), scsimon(1), rasdump(1), sasidump(1)
Full documentation is available at:
diff --git a/doc/rasctl_man_page.txt b/doc/rasctl_man_page.txt
index 2b0498a8..138c16a5 100644
--- a/doc/rasctl_man_page.txt
+++ b/doc/rasctl_man_page.txt
@@ -2,67 +2,160 @@
!! ------ The native file is rasctl.1. Re-run 'make docs' after updating
-rascsi(1) General Commands Manual rascsi(1)
+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]
+ rasctl -e | -l | -m | -s | -v | -D | -I | -L | -O | -T | -V | -X | [-C
+ FILENAME:FILESIZE] [-E FILENAME] [-F IMAGE_FOLDER] [-R CUR‐
+ RENT_NAME:NEW_NAME] [-c CMD] [-f FILE|PARAM] [-g LOG_LEVEL] [-h HOST]
+ [-i ID [-n NAME] [-p PORT] [-r RESERVED_IDS] [-t TYPE] [-u UNIT] [-x
+ CURRENT_NAME:NEW_NAME]
DESCRIPTION
- rasctl Sends commands to the rascsi process to make configuration adjustments at runtime or to check the status of the devices.
+ rasctl Sends commands to the rascsi process to make configuration ad‐
+ justments 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.
+ Note: The command and type arguments are case insensitive. Only the
+ first letter of the command/type is evaluated by the tool.
OPTIONS
- -l List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
+ -C FILENAME:FILESIZE
+ Create an image file in the default image folder with the speci‐
+ fied name and size in bytes.
+
+ -D Detach all devices.
+
+ -E FILENAME
+ Display information on an image file.
+
+ -F IMAGE_FOLDER
+ Set the default image folder.
+
+ -I Gets the list of reserved device IDs.
+
+ -L LOG_LEVEL
+ Set the rascsi log level (trace, debug, info, warn, err, criti‐
+ cal, off).
+
+ -h HOST
+ The rascsi host to connect to, default is 'localhost'.
+
+ -e List all images files in the default image folder.
+
+ -N Lists all available network interfaces provided that they are
+ up.
+
+ -O Display the available rascsi server log levels and the current
+ log level.
+
+ -l List all of the devices that are currently being emulated by
+ RaSCSI, as well as their current status.
+
+ -m List all file extensions recognized by RaSCSI and the device
+ types they map to.
+
+ -R CURRENT_NAME:NEW_NAME
+ Rename an image file in the default image folder.
+
+ -p PORT
+ The rascsi port to connect to, default is 6868.
+
+ -r RESERVED_IDS
+ Comma-separated list of IDs to reserve.
+
+ -s Display server-side settings like available images or supported
+ device types.
+
+ -T Display all device types and their properties.
+
+ -v Display the rascsi server version.
+
+ -V Display the rasctl version.
+
+ -X Shut down the rascsi process.
+
+ -d FILENAME
+ Delete an image file in the default image folder.
+
+ -x CURRENT_NAME:NEW_NAME
+ Copy an image file in the default image folder.
-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:
+ a(ttach): Attach disk
+ d(etach): Detach disk
+ i(nsert): Insert media (removable media devices only)
+ e(ject): Eject media (removable media devices only)
+ p(rotect): Write protect the medium (not for CD-ROMs, which
+ are always read-only)
+ u(nprotect): Remove write protection from the medium (not for
+ CD-ROMs, which are always read-only)
+ s(how): Display device information
- -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)
+ eject, protect and unprotect are idempotent.
- When the command is omited, rasctl will default to the 'attach' command
+ -b BLOCK_SIZE
+ The optional block size. For SCSI drives 512, 1024, 2048 or 4096
+ bytes, default size is 512 bytes. For SASI drives 256 or 1024
+ bytes, default is 256 bytes.
+
+ -f FILE|PARAM
+ Device-specific: Either a path to a disk image file, or a param‐
+ eter for a non-disk device. See the rascsi(1) man page for per‐
+ mitted file types.
-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)
+ Specifies the device type. This type overrides the type derived
+ from the file extension of the specified image. See the
+ rascsi(1) man page for the available device types. For some
+ types there are shortcuts (only the first letter is required):
+ hd: SCSI hard disk drive
+ rm: SCSI removable media drive
cd: CD-ROM
- bridge: Bridge device (This is only applicable to the Sharp X68000)
+ mo: Magneto-Optical disk
+ bridge: Bridge device (Only applicable to the Sharp X68000)
+ daynaport: DaynaPORT network adapter
- -f FILE
- Path to the disk image file. See the rascsi(1) man page for allowable file types.
+ -n VENDOR:PRODUCT:REVISION
+ The vendor, product and revision for the device, to be returned
+ with the INQUIRY data. A complete set of name components must be
+ provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up
+ to 4 characters. Padding with blanks to the maxium length is au‐
+ tomatically applied. Once set the name of a device cannot be
+ changed.
+
+ -u UNIT
+ Unit number (0-31). This will default to 0. This option is only
+ used when there are multiple SCSI devices on a shared SCSI con‐
+ troller. (This is not common)
EXAMPLES
- Show a listing of all of the SCSI devices and their current status
+ 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
- +----+----+------+-------------------------------------
+ +----+-----+------+-------------------------------------
+ | ID | LUN | TYPE | IMAGE FILE
+ +----+-----+------+-------------------------------------
+ | 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".
+ 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) scsimon(1)
+ rascsi(1), scsimon(1), rasdump(1), sasidump(1)
- Full documentation is available at:
+ Full documentation is available at:
+
- rascsi(1)
+ rascsi(1)
diff --git a/doc/rasdump.1 b/doc/rasdump.1
new file mode 100644
index 00000000..43d38e1d
--- /dev/null
+++ b/doc/rasdump.1
@@ -0,0 +1,35 @@
+.TH rasdump 1
+.SH NAME
+rasdump \- SCSI disk dumping tool for RaSCSI
+.SH SYNOPSIS
+.B rasdump
+\fB\-i\fR \fIID\fR
+[\fB\-b\fR \fIBID\fR]
+\fB\-f\fR \fIFILE\fR
+[\fB\-r\fR]
+.SH DESCRIPTION
+.B rasdump
+Samples the data on physical SCSI storage media, including hard drives and MO drives, and stores it to an image file. It can also restore from a dumped file onto physical SCSI storage media. Can be connected directly, through a STANDARD RaSCSI board, or a FULLSPEC RaSCSI board.
+
+Set its own ID with the BID option. Defaults to 7 if ommitted.
+
+.SH OPTIONS
+.TP
+.BR \-i\fI " "\fIID
+SCSI ID of the target device
+.TP
+.BR \-b\fI " "\fIBID
+SCSI ID of the RaSCSI device
+.TP
+.BR \-f\fI " "\fIFILE
+Path to the dump file
+.TP
+.BR \-r\fI
+Restoration mode
+
+.SH EXAMPLES
+
+.SH SEE ALSO
+rasctl(1), rascsi(1), scsimon(1), sasidump(1)
+
+Full documentation is available at:
diff --git a/doc/sasidump.1 b/doc/sasidump.1
new file mode 100644
index 00000000..ce6df31c
--- /dev/null
+++ b/doc/sasidump.1
@@ -0,0 +1,41 @@
+.TH sasidump 1
+.SH NAME
+sasidump \- SASI disk dumping tool for RaSCSI
+.SH SYNOPSIS
+.B sasidump
+\fB\-i\fR \fIID\fR
+[\fB\-u\fR \fIUT\fR]
+[\fB\-b\fR \fIBSIZE\fR]
+\fB\-c\fR \fICOUNT\fR
+\fB\-f\fR \fIFILE\fR
+[\fB\-r\fR]
+.SH DESCRIPTION
+.B sasidump
+Samples the data on physical SASI storage media, and stores it to an image file. It can also restore from a dumped file onto physical SASI storage media.
+
+.SH OPTIONS
+.TP
+.BR \-i\fI " "\fIID
+SASI ID of the target device
+.TP
+.BR \-u\fI " "\fIUD
+Unit ID of the target device
+.TP
+.BR \-b\fI " "\fIBSIZE
+Block size (default is 512)
+.TP
+.BR \-c\fI " "\fICOUNT
+Block count
+.TP
+.BR \-f\fI " "\fIFILE
+Path to the dump file
+.TP
+.BR \-r\fI
+Restoration mode
+
+.SH EXAMPLES
+
+.SH SEE ALSO
+rasctl(1), rascsi(1), scsimon(1), rasdump(1)
+
+Full documentation is available at:
diff --git a/doc/scsimon.1 b/doc/scsimon.1
index 670c2103..454894b0 100644
--- a/doc/scsimon.1
+++ b/doc/scsimon.1
@@ -9,7 +9,7 @@ Monitors all of the traffic on the SCSI bus, using a RaSCSI device. The data is
.PP
The logged data is stored in a file called "log.vcd" in the current working directory from where scsimon was launched.
-Currently, scsimon doesn't accept any agruments.
+Currently, scsimon doesn't accept any arguments.
To quit scsimon, press Control + C.
@@ -22,6 +22,6 @@ Launch scsimon to capture all SCSI traffic available to the RaSCSI hardware:
scsimon
.SH SEE ALSO
-rasctl(1), rascsi(1)
+rasctl(1), rascsi(1), rasdump(1), sasidump(1)
Full documentation is available at:
diff --git a/doc/scsimon_man_page.txt b/doc/scsimon_man_page.txt
index 0e7db3de..39c5f469 100644
--- a/doc/scsimon_man_page.txt
+++ b/doc/scsimon_man_page.txt
@@ -2,21 +2,26 @@
!! ------ The native file is scsimon.1. Re-run 'make docs' after updating
-scsimon(1) General Commands Manual scsimon(1)
+scsimon(1) General Commands Manual scsimon(1)
NAME
- scsimon - Acts as a data capture tool for all traffic on the SCSI bus. Data is stored in a Value Change Dump (VCD) file.
+ scsimon - Acts as a data capture tool for all traffic on the SCSI bus.
+ Data is stored in a Value Change Dump (VCD) file.
SYNOPSIS
scsimon
DESCRIPTION
- scsimon Monitors all of the traffic on the SCSI bus, using a RaSCSI device. The data is cached in memory while the tool is running. A circular buffer is used so that only the most recent 1,000,000
- transactions are stored. The tool will continue to run until the user presses CTRL-C, or the process receives a SIGINT signal.
+ scsimon Monitors all of the traffic on the SCSI bus, using a RaSCSI de‐
+ vice. The data is cached in memory while the tool is running. A circu‐
+ lar buffer is used so that only the most recent 1,000,000 transactions
+ are stored. The tool will continue to run until the user presses CTRL-
+ C, or the process receives a SIGINT signal.
- The logged data is stored in a file called "log.vcd" in the current working directory from where scsimon was launched.
+ The logged data is stored in a file called "log.vcd" in the current
+ working directory from where scsimon was launched.
- Currently, scsimon doesn't accept any agruments.
+ Currently, scsimon doesn't accept any arguments.
To quit scsimon, press Control + C.
@@ -24,12 +29,14 @@ OPTIONS
None
EXAMPLES
- Launch scsimon to capture all SCSI traffic available to the RaSCSI hardware:
+ Launch scsimon to capture all SCSI traffic available to the RaSCSI
+ hardware:
scsimon
SEE ALSO
- rasctl(1), rascsi(1)
+ rasctl(1), rascsi(1), rasdump(1), sasidump(1)
- Full documentation is available at:
+ Full documentation is available at:
+
- scsimon(1)
+ scsimon(1)
diff --git a/doc/target.png b/doc/target.png
deleted file mode 100644
index b25e1049..00000000
Binary files a/doc/target.png and /dev/null differ
diff --git a/doc/x68k.txt b/doc/x68k.txt
deleted file mode 100644
index de40ac49..00000000
--- a/doc/x68k.txt
+++ /dev/null
@@ -1,114 +0,0 @@
-------------------------------------------------------------------------------
-
- SCSI Target Emulator RaSCSII (*^..^*)
- for Raspberry Pi
-
- Powered by XM6 TypeG Technology.
- Copyright (C) 2016-2020 GIMONS
-
-------------------------------------------------------------------------------
-□X68000固有の機能について
- RaSCSIにはブリッジデバイスという仮想的なSCSIデバイスが実装されておりX68000と
- ホストであるRaspberry Piの橋渡しを行うことができます。このブリッジデバイスと
- X68000用の専用ドライバを使用して下記の機能を提供します。
-
- ・イーサーネット
- Neptune-Xと同様のイーサーネット機能を提供します。SCSI接続のイーサーネット
- BOXのようにRaSCSIが振舞います。Raspberry PiのTAPデバイスにパケットを中継
- することで実現しています。Ether+と似たものです。
-
- ・ホストファイルシステム
- X68000のエミュレーターでは標準的な機能であるWindrv相当の機能を提供します。
- Raspberry Pi上のファイルシステムをリモートドライブとしてマウントすること
- ができます。
-
-□ブジッジデバイスの起動方法
- RaSCSI起動時にファイル名として"BRIDGE"というキーワードを設定するとそのIDに
- 対してブジッリデバイスを生成します。
-
- ex)
- sudo rascsi -ID0 HDIMAGE0.HDS -ID6 BRIDGE
-
-□専用ドライバ
- 配布物に含まれるRASDRIVER.XDFもしくはRASDRIVER.HDSに二つのドライバが含まれ
- ています。RaSCSIでRASDRIVER.HDSをマウントし適宜コピーした方が実機への転送が
- 簡単でしょう。
-
-□イーサーネット接続
- イーサネットドライバ(RASETHER.SYS)がブリッジデバイスと連携してイーサーネット
- のパケット送受信を行うことができます。
-
- 以下、Raspberry Piの仮想アダプタ(TAP)のIPアドレスを「192.168.68.1」として、
- X68000側を「192.168.68.3」とするケースで説明します。
-
- ・X68000の設定
- RASETHER.SYSはNeptune-X用ドライバを改造して作ったものですので使用方法は
- 全く同じです。X68000をネット接続するためには他に環境設定を行う必要があり
- ます。設定方法は自力で調べていただくようお願いします。
-
- 以下実際に使用しているCONFIG.SYSとAUTOEXEC.BATの抜粋です。
-
- [CONFIG.SYS抜粋]
- PROCESS = 3 10 10
- DEVICE = \NETWORK\RASETHER.SYS
-
- [AUTOEXEC.BAT抜粋]
- SET SYSROOT=A:/NETWORK/
- SET temp=A:\
- SET tmp=A:\
- SET HOME=A:/NETWORK/ETC/
- SET HOST=X68000
- XIP.X
- IFCONFIG.X lp0 up
- IFCONFIG.X en0 192.168.68.3 netmask 255.255.255.0 up
- INETDCONF.X +router 192.168.68.1 -rip
- INETDCONF.X
-
- ・Raspberry Piの設定
- TAPデバイスというものを利用していますのでTAPを有効にしてください。恐らく
- 最近のJessieであれば最初から有効なはずです。確認方法は/dev/net/tunという
- ファイルが存在すれば有効となっていると判断できます。
-
- 仮想アダプタの作成方法は次の様に行います。
-
- [/etc/rc.local等から設定]
- ip tuntap add ras0 mode tap user root
- ip link set ras0 up
- ifconfig ras0 inet 192.168.68.1/8 up
- route add -net 192.168.68.0 netmask 255.255.255.0 dev ras0
-
- 上記によってRaspberry Pi(192.168.68.1)とX68000(192.168.68.3)の間で通信が
- 可能になります。
-
- インターネット等と接続する場合はRaspberry Pi側でブリッジやルーティングの
- 設定が必要になります。ご自身の環境に合わせて設定してください。無線LANの
- 場合にブリッジ構成するには色々と課題があるようなのでフォワーディングと
- NAT構成等もお勧めです。作者はrc.localで次のような設定で使用しています。
-
- echo 1 > /proc/sys/net/ipv4/ip_forward
- iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
-
-□ホストファイルシステム連携
- X68000エミュレータでよく利用されるWindrvやWindrvXMと同等の機能を提供します。
- 専用のRASDRV.SYSというデバイスドライバを組み込めばRaspberri Piのファイル
- システムがX68000側のドライブに見えて操作できるということです。
-
- デバイスドライバの登録は簡単です。
- 例えば
-
- DEVICE = \SYS\RASDRV.SYS
-
- この場合はデフォルトでRaspberry Piのルートディレクトリをマウントします。
- デバイスドライバ起動時にどのドライブにマウントされたか表示されます。
- ルートを以外をマウントする場合はディレクトリを指定して下さい。/home/pi等を
- マウントするには
-
- DEVICE = \SYS\RASDRV.SYS /home/pi
-
- と指定します。複数のディレクトリを指定すれば別々のドライブとしてマウントする
- ことが可能です。
-
- SUSIEをご利用の方はSUSIEより先にRASDRV.SYSを組み込んで下さい。後に組み込むと
- 正しく認識できなくなると報告があります。
-
-[EOF]
diff --git a/doc/x68k_en.txt b/doc/x68k_en.txt
deleted file mode 100644
index d536fdef..00000000
--- a/doc/x68k_en.txt
+++ /dev/null
@@ -1,114 +0,0 @@
--------------------------------------------------- ----------------------------
-
- SCSI Target Emulator RaSCSII (*^..^*)
- for Raspberry Pi
-
- Powered by XM6 TypeG Technology.
- Copyright (C) 2016-2020 GIMONS
-
--------------------------------------------------- ----------------------------
-□ Regarding the functions unique to the X68000
- RaSCSI is equipped with a virtual SCSI device called a bridge device,
- You can bridge the host Raspberry Pi. With this bridge device
- The following functions are provided by using the dedicated driver for X68000.
-
- ・Ethernet
- It provides the same Ethernet function as Neptune-X. SCSI-connected Ethernet
- RaSCSI behaves like a BOX. Relay packets to the Raspberry Pi TAP device
- It is realized by doing. Similar to Ether+.
-
- ・Host file system
- The emulator of X68000 provides a standard function equivalent to Windrv.
- Mount the file system on the Raspberry Pi as a remote drive
- I can.
-
-□ How to activate the Bridge Device
- If you set the keyword "BRIDGE" as the file name when RaSCSI starts up, it will be assigned to that ID.
- Generate a Buzzilli device for it.
-
- ex)
- sudo rascsi -ID0 HDIMAGE0.HDS -ID6 BRIDGE
-
-□ Dedicated driver
- Two drivers are included in RASDRIVER.XDF or RASDRIVER.HDS included in the distribution
- I am. It is better to mount RASDRIVER.HDS with RaSCSI and copy it appropriately to transfer to the actual device
- It will be easy.
-
-□ Ethernet connection
- Ethernet driver (RASETHER.SYS) works with bridge device to connect to Ethernet
- You can send and receive packets.
-
- Below, the IP address of the virtual adapter (TAP) of Raspberry Pi is "192.168.68.1",
- The case where the X68000 side is set to "192.168.68.3" will be explained.
-
- -X68000 settings
- RASETHER.SYS is made by modifying the driver for Neptune-X.
- Exactly the same. In order to connect the X68000 to the internet, it is necessary to set other environment settings.
- I will. Please check the setting method by yourself.
-
- Below is an excerpt of CONFIG.SYS and AUTOEXEC.BAT that are actually used.
-
- [Excerpt from CONFIG.SYS]
- PROCESS = 3 10 10
- DEVICE = \NETWORK\RASETHER.SYS
-
- [Excerpt from AUTOEXEC.BAT]
- SET SYSROOT=A:/NETWORK/
- SET temp=A:\
- SET tmp=A:\
- SET HOME=A:/NETWORK/ETC/
- SET HOST=X68000
- XIP.X
- IFCONFIG.X lp0 up
- IFCONFIG.X en0 192.168.68.3 netmask 255.255.255.0 up
- INETDCONF.X +router 192.168.68.1 -rip
- INETDCONF.X
-
- ・Raspberry Pi settings
- I am using a TAP device, so please enable TAP. perhaps
- If you're using Jessie these days, it should work from the beginning. The confirmation method is /dev/net/tun
- If the file exists, it can be determined that it is valid.
-
- The method of creating a virtual adapter is as follows.
-
- [Set from /etc/rc.local etc.]
- ip tuntap add ras0 mode tap user root
- ip link set ras0 up
- ifconfig ras0 inet 192.168.68.1/8 up
- route add -net 192.168.68.0 netmask 255.255.255.0 dev ras0
-
- By the above, communication between Raspberry Pi (192.168.68.1) and X68000 (192.168.68.3)
- It will be possible.
-
- When connecting to the Internet etc., bridge and routing on the Raspberry Pi side
- Settings are required. Please set according to your environment. Wifi
- In this case, there seem to be various problems in constructing a bridge.
- NAT configuration is also recommended. The author uses it in rc.local with the following settings.
-
- echo 1 >/proc/sys/net/ipv4/ip_forward
- iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
-
-□ Host file system cooperation
- It provides the same functions as Windrv and WindrvXM that are often used in the X68000 emulator.
- Raspberri Pi files if you include a dedicated device driver called RASDRV.SYS
- It means that the system can be seen and operated as a drive on the X68000 side.
-
- Registering a device driver is easy.
- For example
-
- DEVICE = \SYS\RASDRV.SYS
-
- In this case, mount the root directory of Raspberry Pi by default.
- The drive mounted when the device driver is started is displayed.
- If you want to mount other than root, please specify the directory. /home/pi etc.
- To mount
-
- DEVICE = \SYS\RASDRV.SYS /home/pi
-
- Specify. If you specify multiple directories, they will be mounted as separate drives.
- It is possible.
-
- If you are using SUSIE, please install RASDRV.SYS before SUSIE. When incorporated later
- There are reports that it can not be recognized correctly.
-
-[EOF]
\ No newline at end of file
diff --git a/easyinstall.sh b/easyinstall.sh
index 66728bdc..53a36c69 100755
--- a/easyinstall.sh
+++ b/easyinstall.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# BSD 3-Clause License
# Author @sonique6784
@@ -20,11 +20,43 @@ logo="""
echo -e $logo
}
-VIRTUAL_DRIVER_PATH=/home/pi/images
+function showMacNetworkWired(){
+logo="""
+ .-~-.-~~~-.~-.\n
+ ╔═══════╗ .( )\n
+ ║|¯¯¯¯¯|║ / \`.\n
+ ║|_____|║>--------------<~ . )\n
+ ║ . __ ║ ( :'-'\n
+ ╚╦═════╦╝ ~-.________.:'\n
+ ¯¯¯¯¯¯¯\n
+"""
+echo -e $logo
+}
+
+function showMacNetworkWireless(){
+logo="""
+ .-~-.-~~~-.~-.\n
+ ╔═══════╗ .( .( )\n
+ ║|¯¯¯¯¯|║ .( .( / \`.\n
+ ║|_____|║ .o o ~ . )\n
+ ║ . __ ║ '( '( ( :'-'\n
+ ╚╦═════╦╝ '( ~-.________.:'\n
+ ¯¯¯¯¯¯¯\n
+"""
+echo -e $logo
+}
+
+BASE="$HOME/RASCSI"
+VIRTUAL_DRIVER_PATH="$HOME/images"
+CFG_PATH="$HOME/.config/rascsi"
+WEBINSTDIR="$BASE/src/web"
HFS_FORMAT=/usr/bin/hformat
HFDISK_BIN=/usr/bin/hfdisk
-LIDO_DRIVER=~/RASCSI/lido-driver.img
+LIDO_DRIVER=$BASE/lido-driver.img
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+GIT_REMOTE=${GIT_REMOTE:-origin}
+
+set -e
function initialChecks() {
currentUser=$(whoami)
@@ -33,30 +65,36 @@ function initialChecks() {
exit 1
fi
- if [ ! -d ~/RASCSI ]; then
- echo "You must checkout RASCSI repo into /home/pi/RASCSI"
+ if [ ! -d "$BASE" ]; then
+ echo "You must checkout RASCSI repo into $BASE"
echo "$ git clone git@github.com:akuker/RASCSI.git"
exit 2
fi
}
+# install all dependency packages for RaSCSI Service
function installPackages() {
- sudo apt-get update && sudo apt install git libspdlog-dev genisoimage python3 python3-venv nginx bridge-utils -y
+ sudo apt-get update && sudo apt-get install git libspdlog-dev libpcap-dev genisoimage python3 python3-venv nginx libpcap-dev protobuf-compiler bridge-utils python3-dev libev-dev libevdev2 -y > /etc/sudoers'
+ else
+ echo "The sudoers file is already modified for rascsi-web."
fi
+ sudo systemctl daemon-reload
sudo systemctl restart rsyslog
sudo systemctl enable rascsi # optional - start rascsi at boot
sudo systemctl start rascsi
+
+ startRaScsiScreen
+}
+
+# install everything required to run an HTTP server (Nginx + Python Flask App)
+function installRaScsiWebInterface() {
+ if [ -f "$WEBINSTDIR/rascsi_interface_pb2.py" ]; then
+ rm "$WEBINSTDIR/rascsi_interface_pb2.py"
+ echo "Deleting old Python protobuf library rascsi_interface_pb2.py"
+ fi
+ echo "Compiling the Python protobuf library rascsi_interface_pb2.py..."
+ protoc -I="$BASE/src/raspberrypi/" --python_out="$WEBINSTDIR" rascsi_interface.proto
+
+ sudo cp -f "$BASE/src/web/service-infra/nginx-default.conf" /etc/nginx/sites-available/default
+ sudo cp -f "$BASE/src/web/service-infra/502.html" /var/www/html/502.html
+
+ sudo usermod -a -G pi www-data
+
+ sudo systemctl reload nginx || true
+
+ echo "Installing the rascsi-web.service configuration..."
+ sudo cp -f "$BASE/src/web/service-infra/rascsi-web.service" /etc/systemd/system/rascsi-web.service
+
+ sudo systemctl daemon-reload
+ sudo systemctl enable rascsi-web
+ sudo systemctl start rascsi-web
+}
+
+function installRaScsiScreen() {
+ echo "IMPORTANT: This configuration requires a OLED screen to be installed onto your RaSCSI board."
+ echo "See wiki for more information: https://github.com/akuker/RASCSI/wiki/OLED-Status-Display-(Optional)"
+ echo ""
+ echo "Do you want to use the recommended screen rotation (180 degrees)?"
+ echo "Press Y/n and Enter, or CTRL-C to exit"
+ read REPLY
+
+ if [ "$REPLY" == "N" ] || [ "$REPLY" == "n" ]; then
+ echo "Proceeding with 0 degrees rotation."
+ ROTATION="0"
+ else
+ echo "Proceeding with 180 degrees rotation."
+ ROTATION="180"
+ fi
+
+ stopRaScsiScreen
+ updateRaScsiGit
+
+ sudo apt-get update && sudo apt-get install python3-dev python3-pip python3-venv libjpeg-dev libpng-dev libopenjp2-7-dev i2c-tools raspi-config -y /dev/null; echo $?)
if [ "$APACHE_STATUS" -eq 0 ] ; then
echo "Stopping old Apache2 RaSCSI Web..."
@@ -80,61 +227,63 @@ function stopOldWebInterface() {
fi
}
-# install everything required to run an HTTP server (Nginx + Python Flask App)
-function installRaScsiWebInterface() {
- stopOldWebInterface
- installPackages
-
- sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default
- sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html
-
- mkdir -p $VIRTUAL_DRIVER_PATH
- chmod -R 775 $VIRTUAL_DRIVER_PATH
- groups www-data
- sudo usermod -a -G pi www-data
- groups www-data
-
- sudo systemctl reload nginx
-
- sudo cp ~/RASCSI/src/web/service-infra/rascsi-web.service /etc/systemd/system/rascsi-web.service
- sudo systemctl daemon-reload
- sudo systemctl enable rascsi-web
- sudo systemctl start rascsi-web
-}
-
function updateRaScsiGit() {
- echo "Updating checked out branch $GIT_BRANCH"
- cd ~/RASCSI
- git fetch origin
- git stash
- git rebase origin/$GIT_BRANCH
- git stash apply
+ cd "$BASE" || exit 1
+ stashed=0
+ if [[ $(git diff --stat) != '' ]]; then
+ echo "There are local changes to the RaSCSI code; we will stash and reapply them."
+ git -c user.name="${GIT_COMMITTER_NAME-rascsi}" -c user.email="${GIT_COMMITTER_EMAIL-rascsi@rascsi.com}" stash
+ stashed=1
+ fi
+
+ if [[ `git for-each-ref --format='%(upstream:short)' "$(git symbolic-ref -q HEAD)"` != "" ]]; then
+ echo "Updating checked out git branch $GIT_REMOTE/$GIT_BRANCH"
+ git pull --ff-only
+ else
+ echo "Detected a local git working branch; skipping the remote update step."
+ fi
+
+ if [ $stashed -eq 1 ]; then
+ echo "Reapplying local changes..."
+ git stash apply
+ fi
}
-function updateRaScsi() {
- updateRaScsiGit
- installPackages
- sudo systemctl stop rascsi
-
- cd ~/RASCSI/src/raspberrypi
-
- make clean
- make all CONNECT_TYPE=FULLSPEC
- sudo make install CONNECT_TYPE=FULLSPEC
- sudo systemctl start rascsi
+function stopRaScsi() {
+ if [[ `systemctl list-units | grep -c rascsi.service` -ge 1 ]]; then
+ sudo systemctl stop rascsi.service
+ fi
}
-function updateRaScsiWebInterface() {
- stopOldWebInterface
- updateRaScsiGit
- sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default
- sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html
- sudo systemctl restart rascsi-web
- sudo systemctl restart nginx
+function stopRaScsiWeb() {
+ if [[ `systemctl list-units | grep -c rascsi-web.service` -ge 1 ]]; then
+ sudo systemctl stop rascsi-web.service
+ fi
+}
+
+function stopRaScsiScreen() {
+ if [[ `systemctl list-units | grep -c monitor_rascsi.service` -ge 1 ]]; then
+ sudo systemctl stop monitor_rascsi.service
+ fi
+}
+
+function startRaScsiScreen() {
+ if [[ -f "/etc/systemd/system/monitor_rascsi.service" ]]; then
+ sudo systemctl start monitor_rascsi.service
+ showRaScsiScreenStatus
+ fi
}
function showRaScsiStatus() {
- sudo systemctl status rascsi
+ sudo systemctl status rascsi | tee
+}
+
+function showRaScsiWebStatus() {
+ sudo systemctl status rascsi-web | tee
+}
+
+function showRaScsiScreenStatus() {
+ sudo systemctl status monitor_rascsi | tee
}
function createDrive600MB() {
@@ -151,7 +300,7 @@ function createDriveCustom() {
read driveName
done
- createDrive $driveSize "$driveName"
+ createDrive "$driveSize" "$driveName"
}
function formatDrive() {
@@ -160,30 +309,46 @@ function formatDrive() {
if [ ! -x $HFS_FORMAT ]; then
# Install hfsutils to have hformat to format HFS
- sudo apt-get install hfsutils
+ sudo apt-get install hfsutils --assume-yes > /etc/dhcpcd.conf'
+ echo "Modified /etc/dhcpcd.conf"
+
+ # default config file is made for eth0, this will set the right net interface
+ sudo bash -c 'sed s/eth0/'"$LAN_INTERFACE"'/g '"$BASE"'/src/raspberrypi/os_integration/rascsi_bridge > /etc/network/interfaces.d/rascsi_bridge'
+ echo "Modified /etc/network/interfaces.d/rascsi_bridge"
+
+ echo "Configuration completed!"
+ echo "Please make sure you attach a DaynaPORT network adapter to your RaSCSI configuration."
+ echo "Either use the Web UI, or do this on the command line (assuming SCSI ID 6):"
+ echo "rasctl -i 6 -c attach -t scdp -f $LAN_INTERFACE"
+ echo ""
+ echo "We need to reboot your Pi"
+ echo "Press Enter to reboot or CTRL-C to exit"
+ read
+
+ echo "Rebooting..."
+ sleep 3
+ sudo reboot
+}
+
+function setupWirelessNetworking() {
+ NETWORK="10.10.20"
+ IP=$NETWORK.2 # Macintosh or Device IP
+ NETWORK_MASK="255.255.255.0"
+ CIDR="24"
+ ROUTER_IP=$NETWORK.1
+ ROUTING_ADDRESS=$NETWORK.0/$CIDR
+ WLAN_INTERFACE="wlan0"
+
+ echo "$WLAN_INTERFACE will be configured for network forwarding with static IP assignment."
+ echo "Configure your Macintosh or other device with the following:"
+ echo "IP Address (static): $IP"
+ echo "Router Address: $ROUTER_IP"
+ echo "Subnet Mask: $NETWORK_MASK"
+ echo "DNS Server: Any public DNS server"
+ echo ""
+ echo "Do you want to proceed with network configuration using the default settings? Y/n"
+ read REPLY
+
+ if [ "$REPLY" == "N" ] || [ "$REPLY" == "n" ]; then
+ echo "Available wireless interfaces on this system:"
+ echo `ip -o addr show scope link | awk '{split($0, a); print $2}' | grep wlan`
+ echo "Please type the wireless interface you want to use and press Enter:"
+ read -r WLAN_INTERFACE
+ echo "Base IP address (ex. 10.10.20):"
+ read -r NETWORK
+ echo "CIDR for Subnet Mask (ex. '24' for 255.255.255.0):"
+ read -r CIDR
+ ROUTER_IP=$NETWORK.1
+ ROUTING_ADDRESS=$NETWORK.0/$CIDR
+ fi
+
+
+ if [ "$(grep -c "^net.ipv4.ip_forward=1" /etc/sysctl.conf)" -ge 1 ]; then
+ echo "WARNING: Network forwarding may already have been configured. Proceeding will overwrite the configuration."
+ echo "Press enter to continue or CTRL-C to exit"
+ read REPLY
+ else
+ sudo bash -c 'echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf'
+ echo "Modified /etc/sysctl.conf"
+ fi
+
+ sudo iptables --flush
+ sudo iptables -t nat -F
+ sudo iptables -X
+ sudo iptables -Z
+ sudo iptables -P INPUT ACCEPT
+ sudo iptables -P OUTPUT ACCEPT
+ sudo iptables -P FORWARD ACCEPT
+ sudo iptables -t nat -A POSTROUTING -o "$WLAN_INTERFACE" -s "$ROUTING_ADDRESS" -j MASQUERADE
+
+ # Check if iptables-persistent is installed
+ if [ `apt-cache policy iptables-persistent | grep Installed | grep -c "(none)"` -eq 0 ]; then
+ echo "iptables-persistent is already installed"
+ sudo iptables-save --file /etc/iptables/rules.v4
+ else
+ sudo apt-get install iptables-persistent --assume-yes > ./config/AppleVolumes.default.tmpl
+
+ echo "ATALKD_RUN=yes" >> ./config/netatalk.conf
+ echo "\"RaSCSI-Pi\" -transall -uamlist uams_guest.so,uams_clrtxt.so,uams_dhx.so -defaultvol /etc/netatalk/AppleVolumes.default -systemvol /etc/netatalk/AppleVolumes.system -nosavepassword -nouservol -guestname \"nobody\" -setuplog \"default log_maxdebug /var/log/afpd.log\"" >> ./config/afpd.conf.tmpl
+
+ ( sudo apt-get update && sudo apt-get install libssl-dev libdb-dev libcups2-dev autotools-dev automake libtool --assume-yes ) 1:
+ if str(argv[1]) == "0":
+ rotation = 0
+ elif str(argv[1]) == "180":
+ rotation = 2
+ else:
+ exit("Only 0 and 180 are valid arguments for screen rotation.")
+else:
+ print("Defaulting to 180 degrees screen rotation.")
+ rotation = 2
+
# Clear display.
+oled.rotation = rotation
oled.fill(0)
oled.show()
@@ -74,57 +123,219 @@ draw.rectangle((0,0,WIDTH,HEIGHT), outline=0, fill=0)
# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
-padding = -2
+padding = 0
top = padding
bottom = HEIGHT-padding
# Move left to right keeping track of the current x position for drawing shapes.
x = 0
# Load default font.
-font = ImageFont.load_default()
+#font = ImageFont.load_default()
# Alternatively load a TTF font. Make sure the .ttf font file is in the same directory as the python script!
+# When using other fonds, you may need to adjust padding, font size, and line spacing
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
-# font = ImageFont.truetype('Minecraftia.ttf', 8)
+font = ImageFont.truetype('type_writer.ttf', 8)
-while True:
- # Draw a black filled box to clear the image.
- draw.rectangle((0,0,WIDTH,HEIGHT), outline=0, fill=0)
-
- cmd = "rasctl -l"
- rascsi_list = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding)
+def device_list():
+ """
+ Sends a DEVICES_INFO command to the server.
+ Returns a list of dicts with info on all attached devices.
+ """
+ command = proto.PbCommand()
+ command.operation = proto.PbOperation.DEVICES_INFO
+ data = send_pb_command(command.SerializeToString())
+ result = proto.PbResult()
+ result.ParseFromString(data)
- y_pos = top
- # Draw all of the meaningful data to the 'image'
- #
- # Example rascstl -l output:
- # pi@rascsi:~ $ rasctl -l
- #
- # +----+----+------+-------------------------------------
- # | ID | UN | TYPE | DEVICE STATUS
- # +----+----+------+-------------------------------------
- # | 1 | 0 | SCHD | /home/pi/harddisk.hda
- # | 6 | 0 | SCCD | NO MEDIA
- # +----+----+------+-------------------------------------
- # pi@rascsi:~ $
- for line in rascsi_list.split('\n'):
- # Skip empty strings, divider lines and the header line...
- if (len(line) == 0) or line.startswith("+---") or line.startswith("| ID | UN"):
- continue
- else:
- if line.startswith("| "):
- fields = line.split('|')
- output = str.strip(fields[1]) + " " + str.strip(fields[3]) + " " + os.path.basename(str.strip(fields[4]))
- else:
- output = "No image mounted!"
- draw.text((x, y_pos), output, font=font, fill=255)
- y_pos += 8
+ device_list = []
+ n = 0
- # If there is still room on the screen, we'll display the time. If there's not room it will just be clipped
- draw.text((x, y_pos), datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S"), font=font, fill=255)
+ while n < len(result.devices_info.devices):
+ did = result.devices_info.devices[n].id
+ dtype = proto.PbDeviceType.Name(result.devices_info.devices[n].type)
+ dstat = result.devices_info.devices[n].status
+ dprop = result.devices_info.devices[n].properties
- # Display image.
- oled.image(image)
+ # Building the status string
+ dstat_msg = []
+ if dstat.protected == True and dprop.protectable == True:
+ dstat_msg.append("Write-Protected")
+ if dstat.removed == True and dprop.removable == True:
+ dstat_msg.append("No Media")
+ if dstat.locked == True and dprop.lockable == True:
+ dstat_msg.append("Locked")
+
+ dfile = path.basename(result.devices_info.devices[n].file.name)
+ dven = result.devices_info.devices[n].vendor
+ dprod = result.devices_info.devices[n].product
+
+ device_list.append(
+ {
+ "id": did,
+ "device_type": dtype,
+ "status": ", ".join(dstat_msg),
+ "file": dfile,
+ "vendor": dven,
+ "product": dprod,
+ }
+ )
+ n += 1
+
+ return device_list
+
+def get_ip_and_host():
+ host = socket.gethostname()
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ try:
+ # mock ip address; doesn't have to be reachable
+ s.connect(('10.255.255.255', 1))
+ ip = s.getsockname()[0]
+ except Exception:
+ ip = '127.0.0.1'
+ finally:
+ s.close()
+ return ip, host
+
+def send_pb_command(payload):
+ """
+ Takes a str containing a serialized protobuf as argument.
+ Establishes a socket connection with RaSCSI.
+ """
+ # Host and port number where rascsi is listening for socket connections
+ HOST = 'localhost'
+ PORT = 6868
+
+ counter = 0
+ tries = 100
+ error_msg = ""
+
+ while counter < tries:
+ try:
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+ s.connect((HOST, PORT))
+ return send_over_socket(s, payload)
+ except socket.error as error:
+ counter += 1
+ print("The RaSCSI service is not responding - attempt " + \
+ str(counter) + "/" + str(tries))
+ error_msg = str(error)
+
+ exit(error_msg)
+
+
+def send_over_socket(s, payload):
+ """
+ Takes a socket object and str payload with serialized protobuf.
+ Sends payload to RaSCSI over socket and captures the response.
+ Tries to extract and interpret the protobuf header to get response size.
+ Reads data from socket in 2048 bytes chunks until all data is received.
+ """
+
+ # Sending the magic word "RASCSI" to authenticate with the server
+ s.send(b"RASCSI")
+ # Prepending a little endian 32bit header with the message size
+ s.send(pack("= 4:
+ # Extracting the response header to get the length of the response message
+ response_length = unpack(" 5:
+ output.rotate(-1)
+
+ # Display image.
+ oled.image(image)
+ oled.show()
+ sleep(1000/delay_time_ms)
+
+ snapshot = formatted_output()
+
+ if h.interrupted:
+ stop_splash()
+ exit("Shutting down the OLED display...")
diff --git a/src/oled_monitor/requirements.txt b/src/oled_monitor/requirements.txt
index 57c38c4c..be07f39f 100644
--- a/src/oled_monitor/requirements.txt
+++ b/src/oled_monitor/requirements.txt
@@ -1,14 +1,15 @@
-Adafruit-Blinka==6.3.2
-adafruit-circuitpython-busdevice==5.0.6
-adafruit-circuitpython-framebuf==1.4.6
-adafruit-circuitpython-ssd1306==2.11.1
-Adafruit-PlatformDetect==3.2.0
-Adafruit-PureIO==1.1.8
-Pillow==8.2.0
+Adafruit-Blinka==6.15.0
+adafruit-circuitpython-busdevice==5.1.0
+adafruit-circuitpython-framebuf==1.4.7
+adafruit-circuitpython-ssd1306==2.12.2
+Adafruit-PlatformDetect==3.13.0
+Adafruit-PureIO==1.1.9
+Pillow==8.4.0
pkg-resources==0.0.0
-pyftdi==0.52.9
+pyftdi==0.53.3
pyserial==3.5
-pyusb==1.1.1
-rpi-ws281x==4.2.5
+pyusb==1.2.1
+rpi-ws281x==4.3.0
RPi.GPIO==0.7.0
sysv-ipc==1.1.0
+protobuf==3.17.3
diff --git a/src/oled_monitor/splash_start.bmp b/src/oled_monitor/splash_start.bmp
new file mode 100644
index 00000000..bd749374
Binary files /dev/null and b/src/oled_monitor/splash_start.bmp differ
diff --git a/src/oled_monitor/splash_stop.bmp b/src/oled_monitor/splash_stop.bmp
new file mode 100644
index 00000000..3dde1c7f
Binary files /dev/null and b/src/oled_monitor/splash_stop.bmp differ
diff --git a/src/oled_monitor/start.sh b/src/oled_monitor/start.sh
index f0a37013..e48b63df 100755
--- a/src/oled_monitor/start.sh
+++ b/src/oled_monitor/start.sh
@@ -2,7 +2,7 @@
set -e
# set -x # Uncomment to Debug
-cd $(dirname $0)
+cd "$(dirname "$0")"
# verify packages installed
ERROR=0
if ! command -v dpkg -l i2c-tools &> /dev/null ; then
@@ -15,6 +15,11 @@ if ! command -v python3 &> /dev/null ; then
echo "Run 'sudo apt install python3' to fix."
ERROR=1
fi
+if ! python3 -m venv --help &> /dev/null ; then
+ echo "venv could not be found"
+ echo "Run 'sudo apt install python3-venv' to fix."
+ ERROR=1
+fi
# Dep to build Pillow
if ! dpkg -l python3-dev &> /dev/null; then
echo "python3-dev could not be found"
@@ -31,10 +36,9 @@ if ! dpkg -l libpng-dev &> /dev/null; then
echo "Run 'sudo apt install libpng-dev' to fix."
ERROR=1
fi
-# Dep to build Pollow
-if ! python3 -m venv --help &> /dev/null ; then
- echo "venv could not be found"
- echo "Run 'sudo apt install python3-venv' to fix."
+if ! dpkg -l libopenjp2-7-dev &> /dev/null; then
+ echo "libopenjp2-7-dev could not be found"
+ echo "Run 'sudo apt install libopenjp2-7-dev' to fix."
ERROR=1
fi
if [ $ERROR = 1 ] ; then
@@ -43,6 +47,12 @@ if [ $ERROR = 1 ] ; then
exit 1
fi
+if pgrep -f "python3 rascsi_oled_monitor.py" &> /dev/null; then
+ echo "Detected active rascsi_oled_monitor.py process"
+ echo "Terminating before launching a new one."
+ sudo pkill -f "python3 rascsi_oled_monitor.py"
+fi
+
if ! i2cdetect -y 1 &> /dev/null ; then
echo "i2cdetect -y 1 did not find a screen."
exit 2
@@ -53,6 +63,7 @@ if ! test -e venv; then
echo "Activating venv"
source venv/bin/activate
echo "Installing requirements.txt"
+ pip install wheel
pip install -r requirements.txt
git rev-parse HEAD > current
fi
@@ -65,12 +76,34 @@ if ! test -e current; then
else
if [ "$(cat current)" != "$(git rev-parse HEAD)" ]; then
echo "New version detected, updating requirements.txt"
- echo " This may take some time..."
- pip install wheel
pip install -r requirements.txt
git rev-parse HEAD > current
fi
fi
-echo "Starting OLED Screen..."
-python3 rascsi_oled_monitor.py
+# parse arguments
+while [ "$1" != "" ]; do
+ PARAM=$(echo "$1" | awk -F= '{print $1}')
+ VALUE=$(echo "$1" | awk -F= '{print $2}')
+ case $PARAM in
+ -r | --rotation)
+ ROTATION=$VALUE
+ ;;
+ *)
+ echo "ERROR: unknown parameter \"$PARAM\""
+ exit 1
+ ;;
+ esac
+ case $VALUE in
+ 0 | 180 )
+ ;;
+ *)
+ echo "ERROR: invalid option \"$VALUE\""
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+echo "Starting OLED Screen with $ROTATION degrees rotation..."
+python3 rascsi_oled_monitor.py "${ROTATION}"
diff --git a/src/oled_monitor/type_writer.ttf b/src/oled_monitor/type_writer.ttf
new file mode 100644
index 00000000..a8e88ccd
Binary files /dev/null and b/src/oled_monitor/type_writer.ttf differ
diff --git a/src/raspberrypi/.gitignore b/src/raspberrypi/.gitignore
index b3172ad3..d81380e1 100644
--- a/src/raspberrypi/.gitignore
+++ b/src/raspberrypi/.gitignore
@@ -12,3 +12,8 @@ sasidump
rasdump
obj
bin
+/rascsi_interface.pb.cpp
+/rascsi_interface.pb.h
+.project
+.cproject
+.settings
diff --git a/src/raspberrypi/.vscode/launch.json b/src/raspberrypi/.vscode/launch.json
index 4ac5ab4b..e3cd4037 100644
--- a/src/raspberrypi/.vscode/launch.json
+++ b/src/raspberrypi/.vscode/launch.json
@@ -8,13 +8,15 @@
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
- "program": "${workspaceFolder}/bin/rascsi",
+ "program": "${workspaceFolder}/bin/fullspec/rascsi",
"args": [],
"stopAtEntry": true,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
+ "targetArchitecture": "arm",
+ "miDebuggerPath": "${workspaceFolder}/launch_sudo.sh",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
@@ -24,4 +26,4 @@
]
}
]
-}
\ No newline at end of file
+}
diff --git a/src/raspberrypi/.vscode/tasks.json b/src/raspberrypi/.vscode/tasks.json
index eeedfe8a..6105ee09 100644
--- a/src/raspberrypi/.vscode/tasks.json
+++ b/src/raspberrypi/.vscode/tasks.json
@@ -5,7 +5,7 @@
"type": "shell",
"label": "g++ build active file",
"command": "make",
- "args": ["all", "DEBUG=1"],
+ "args": ["all", "DEBUG=1", "-j4"],
"options": {
"cwd": "${workspaceFolder}/"
},
@@ -16,4 +16,4 @@
}
}
]
- }
\ No newline at end of file
+ }
diff --git a/src/raspberrypi/Makefile b/src/raspberrypi/Makefile
index 34d421a4..20b5f27a 100644
--- a/src/raspberrypi/Makefile
+++ b/src/raspberrypi/Makefile
@@ -1,18 +1,14 @@
.DEFAULT_GOAL: all
## Optional build flags:
-## ARCH=arm : Specify which target platform you're compiling
-## for. This will default to arm, which is typical
-## on a Raspberry Pi.
## CROSS_COMPILE=arm-linux-gnueabihf- : Specify which compiler
## toolchain to use. This will default to arm-linux-
## gnueabihf-, which is typical on a Raspberry Pi.
## To cross compile on a x86_64 system set these to:
## ARM=x86_64 CROSS_COMPILE=x86_64-linux-gnu-cpp
-ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabihf-
-CC = $(CROSS_COMPILE)gcc
+CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
## DEBUG=1 : A Debug build includes the debugger symbols
@@ -21,8 +17,8 @@ CXX = $(CROSS_COMPILE)g++
DEBUG ?= 0
ifeq ($(DEBUG), 1)
# Debug CFLAGS
- CFLAGS += -DDISK_LOG -O0 -g -Wall -DDEBUG
- CXXFLAGS += -DDISK_LOG -O0 -g -Wall -DDEBUG
+ CFLAGS += -O0 -g -Wall -DDEBUG
+ CXXFLAGS += -O0 -g -Wall -DDEBUG
BUILD_TYPE = Debug
else
# Release CFLAGS
@@ -30,19 +26,23 @@ else
CXXFLAGS += -O3 -Wall -Werror -DNDEBUG
BUILD_TYPE = Release
endif
-CFLAGS += -iquote . -MD -MP
-CXXFLAGS += -std=c++14 -iquote . -MD -MP
+CFLAGS += -iquote . -D_FILE_OFFSET_BITS=64 -MD -MP
+CXXFLAGS += -std=c++17 -Wno-psabi -iquote . -D_FILE_OFFSET_BITS=64 -MD -MP
-## CONNECT_TYPE=STANDARD : Specify the type of RaSCSI board type
+## EXTRA_FLAGS : Can be used to pass special purpose flags
+CFLAGS += $(EXTRA_FLAGS)
+CXXFLAGS += $(EXTRA_FLAGS)
+
+## CONNECT_TYPE=FULLSPEC : Specify the type of RaSCSI board type
## that you are using. The typical options are
-## STANDARD or FULLSPEC. The default is STANDARD
+## STANDARD or FULLSPEC. The default is FULLSPEC
## * THIS IS TYPICALLY THE ONLY COMPILE OPTION YOU
## * NEED TO SPECIFY
# If its not specified, build for FULLSPEC configuration
CONNECT_TYPE ?= FULLSPEC
ifdef CONNECT_TYPE
-CFLAGS += -DCONNECT_TYPE_$(CONNECT_TYPE)
+CFLAGS += -DCONNECT_TYPE_$(CONNECT_TYPE)
CXXFLAGS += -DCONNECT_TYPE_$(CONNECT_TYPE)
endif
@@ -64,10 +64,18 @@ OS_FILES = ./os_integration
OBJDIR := ./obj/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]')
BINDIR := ./bin/$(shell echo $(CONNECT_TYPE) | tr '[:upper:]' '[:lower:]')
-#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 = $(BINDIR)/$(RASCSI) $(BINDIR)/$(RASCTL) $(BINDIR)/$(SCSIMON)
+BIN_ALL = \
+ $(BINDIR)/$(RASCSI) \
+ $(BINDIR)/$(RASCTL) \
+ $(BINDIR)/$(SCSIMON) \
+ $(BINDIR)/$(RASDUMP) \
+ $(BINDIR)/$(SASIDUMP)
+
+SRC_PROTOC = \
+ rascsi_interface.proto
+
+SRC_PROTOBUF = \
+ rascsi_interface.pb.cpp
SRC_RASCSI = \
rascsi.cpp \
@@ -75,29 +83,31 @@ SRC_RASCSI = \
gpiobus.cpp \
filepath.cpp \
fileio.cpp\
- rascsi_version.cpp
-# os.cpp
-# rasctl_command.cpp
-# rascsi_mgr.cpp
-# command_thread.cpp
+ rascsi_version.cpp \
+ rascsi_image.cpp \
+ rascsi_response.cpp \
+ rasutil.cpp \
+ protobuf_util.cpp
SRC_RASCSI += $(shell find ./controllers -name '*.cpp')
SRC_RASCSI += $(shell find ./devices -name '*.cpp')
+SRC_RASCSI += $(SRC_PROTOBUF)
SRC_SCSIMON = \
scsimon.cpp \
scsi.cpp \
gpiobus.cpp \
filepath.cpp \
- fileio.cpp\
+ fileio.cpp \
rascsi_version.cpp
-SRC_SCSIMON += $(shell find ./controllers -name '*.cpp')
-SRC_SCSIMON += $(shell find ./devices -name '*.cpp')
-
SRC_RASCTL = \
rasctl.cpp\
- rascsi_version.cpp
-# rasctl_command.cpp
+ rasctl_commands.cpp \
+ rasctl_display.cpp \
+ rascsi_version.cpp \
+ rasutil.cpp \
+ protobuf_util.cpp
+SRC_RASCTL += $(SRC_PROTOBUF)
SRC_RASDUMP = \
rasdump.cpp \
@@ -125,9 +135,9 @@ OBJ_RASCSI := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCSI:%.cpp=%.o)))
OBJ_RASCTL := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASCTL:%.cpp=%.o)))
OBJ_RASDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_RASDUMP:%.cpp=%.o)))
OBJ_SASIDUMP := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SASIDUMP:%.cpp=%.o)))
-OBJ_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(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_SCSIMON := $(addprefix $(OBJDIR)/,$(notdir $(SRC_SCSIMON:%.cpp=%.o)))
+
+GEN_PROTOBUF := $(SRC_PROTOBUF) rascsi_interface.pb.h
# The following will include all of the auto-generated dependency files (*.d)
@@ -142,6 +152,11 @@ $(OBJDIR) $(BINDIR):
$(OBJDIR)/%.o: %.cpp | $(OBJDIR)
$(CXX) $(CXXFLAGS) -c $< -o $@
+$(SRC_PROTOBUF): $(SRC_PROTOC)
+ echo "-- Generating protobuf-based source files"
+ protoc --cpp_out=. $(SRC_PROTOC)
+ mv rascsi_interface.pb.cc $@
+
## Build Targets:
## all : Rebuild all of the executable files and re-generate
## the text versions of the manpages
@@ -153,11 +168,11 @@ ALL: all
docs: $(DOC_DIR)/rascsi_man_page.txt $(DOC_DIR)/rasctl_man_page.txt $(DOC_DIR)/scsimon_man_page.txt
-$(BINDIR)/$(RASCSI): $(OBJ_RASCSI) | $(BINDIR)
- $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread
+$(BINDIR)/$(RASCSI): $(SRC_PROTOBUF) $(OBJ_RASCSI) | $(BINDIR)
+ $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCSI) -lpthread -lz -lpcap -lprotobuf -lstdc++fs
-$(BINDIR)/$(RASCTL): $(OBJ_RASCTL) | $(BINDIR)
- $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL)
+$(BINDIR)/$(RASCTL): $(SRC_PROTOBUF) $(OBJ_RASCTL) | $(BINDIR)
+ $(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASCTL) -lprotobuf -lstdc++fs
$(BINDIR)/$(RASDUMP): $(OBJ_RASDUMP) | $(BINDIR)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ_RASDUMP)
@@ -172,7 +187,7 @@ $(BINDIR)/$(SCSIMON): $(OBJ_SCSIMON) | $(BINDIR)
## compiler files and executable files
.PHONY: clean
clean:
- rm -rf $(OBJDIR) $(BINDIR)
+ rm -rf $(OBJDIR) $(BINDIR) $(GEN_PROTOBUF)
## run : Launches RaSCSI using some pre-defined drive
## images. Useful for debugging when you're building
@@ -194,7 +209,20 @@ run:
## * sudo systemctl enable rascsi
## * sudo systemctl start rascsi
.PHONY: install
-install: $(MAN_PAGE_DIR)/rascsi.1 $(MAN_PAGE_DIR)/rasctl.1 $(MAN_PAGE_DIR)/scsimon.1 $(USR_LOCAL_BIN)/$(RASCTL) $(USR_LOCAL_BIN)/$(RASCSI) $(USR_LOCAL_BIN)/$(SCSIMON) $(SYSTEMD_CONF) $(RSYSLOG_CONF) $(RSYSLOG_LOG)
+install: \
+ $(MAN_PAGE_DIR)/rascsi.1 \
+ $(MAN_PAGE_DIR)/rasctl.1 \
+ $(MAN_PAGE_DIR)/scsimon.1 \
+ $(MAN_PAGE_DIR)/rasdump.1 \
+ $(MAN_PAGE_DIR)/sasidump.1 \
+ $(USR_LOCAL_BIN)/$(RASCTL) \
+ $(USR_LOCAL_BIN)/$(RASCSI) \
+ $(USR_LOCAL_BIN)/$(SCSIMON) \
+ $(USR_LOCAL_BIN)/$(RASDUMP) \
+ $(USR_LOCAL_BIN)/$(SASIDUMP) \
+ $(SYSTEMD_CONF) \
+ $(RSYSLOG_CONF) \
+ $(RSYSLOG_LOG)
@echo "-- Done installing!"
$(USR_LOCAL_BIN)% : $(BINDIR)/%
diff --git a/src/raspberrypi/controllers/sasidev_ctrl.cpp b/src/raspberrypi/controllers/sasidev_ctrl.cpp
index 5e50e67a..89276f0d 100644
--- a/src/raspberrypi/controllers/sasidev_ctrl.cpp
+++ b/src/raspberrypi/controllers/sasidev_ctrl.cpp
@@ -17,6 +17,8 @@
#include "filepath.h"
#include "gpiobus.h"
#include "devices/scsi_host_bridge.h"
+#include "devices/scsi_daynaport.h"
+#include
//===========================================================================
//
@@ -29,39 +31,29 @@
// Constructor
//
//---------------------------------------------------------------------------
-#ifdef RASCSI
SASIDEV::SASIDEV()
-#else
-SASIDEV::SASIDEV(Device *dev)
-#endif // RASCSI
{
- int i;
-
- #ifndef RASCSI
- // Remember host device
- host = dev;
- #endif // RASCSI
-
// Work initialization
ctrl.phase = BUS::busfree;
- ctrl.id = -1;
+ ctrl.m_scsi_id = UNKNOWN_SCSI_ID;
ctrl.bus = NULL;
memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd));
ctrl.status = 0x00;
ctrl.message = 0x00;
- #ifdef RASCSI
ctrl.execstart = 0;
- #endif // RASCSI
- ctrl.bufsize = 0x800;
+ // The initial buffer size will default to either the default buffer size OR
+ // the size of an Ethernet message, whichever is larger.
+ ctrl.bufsize = std::max(DEFAULT_BUFFER_SIZE, ETH_FRAME_LEN + 16 + ETH_FCS_LEN);
ctrl.buffer = (BYTE *)malloc(ctrl.bufsize);
memset(ctrl.buffer, 0x00, ctrl.bufsize);
ctrl.blocks = 0;
ctrl.next = 0;
ctrl.offset = 0;
ctrl.length = 0;
+ ctrl.lun = -1;
// Logical unit initialization
- for (i = 0; i < UnitMax; i++) {
+ for (int i = 0; i < UnitMax; i++) {
ctrl.unit[i] = NULL;
}
}
@@ -85,20 +77,14 @@ SASIDEV::~SASIDEV()
// Device reset
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Reset()
+void SASIDEV::Reset()
{
- int i;
-
- ASSERT(this);
-
// Work initialization
memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd));
ctrl.phase = BUS::busfree;
ctrl.status = 0x00;
ctrl.message = 0x00;
- #ifdef RASCSI
ctrl.execstart = 0;
- #endif // RASCSI
memset(ctrl.buffer, 0x00, ctrl.bufsize);
ctrl.blocks = 0;
ctrl.next = 0;
@@ -106,126 +92,31 @@ void FASTCALL SASIDEV::Reset()
ctrl.length = 0;
// Unit initialization
- for (i = 0; i < UnitMax; i++) {
+ for (int i = 0; i < UnitMax; i++) {
if (ctrl.unit[i]) {
ctrl.unit[i]->Reset();
}
}
}
-#ifndef RASCSI
-//---------------------------------------------------------------------------
-//
-// Save
-//
-//---------------------------------------------------------------------------
-BOOL FASTCALL SASIDEV::Save(Fileio *fio, int /*ver*/)
-{
- DWORD sz;
-
- 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);
- PROP_EXPORT(fio, ctrl.status);
- PROP_EXPORT(fio, ctrl.message);
- if (!fio->Write(ctrl.buffer, 0x800)) {
- return FALSE;
- }
- PROP_EXPORT(fio, ctrl.blocks);
- PROP_EXPORT(fio, ctrl.next);
- PROP_EXPORT(fio, ctrl.offset);
- PROP_EXPORT(fio, ctrl.length);
-
- return TRUE;
-}
-
-//---------------------------------------------------------------------------
-//
-// Load
-//
-//---------------------------------------------------------------------------
-BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver)
-{
- DWORD sz;
-
- ASSERT(this);
- ASSERT(fio);
-
- // 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;
- }
- if (sz != 2120) {
- return FALSE;
- }
-
- // Load the entity
- PROP_IMPORT(fio, ctrl.phase);
- PROP_IMPORT(fio, ctrl.id);
- PROP_IMPORT(fio, ctrl.cmd);
- PROP_IMPORT(fio, ctrl.status);
- PROP_IMPORT(fio, ctrl.message);
- if (!fio->Read(ctrl.buffer, 0x800)) {
- return FALSE;
- }
- PROP_IMPORT(fio, ctrl.blocks);
- PROP_IMPORT(fio, ctrl.next);
- PROP_IMPORT(fio, ctrl.offset);
- PROP_IMPORT(fio, ctrl.length);
-
- return TRUE;
-}
-#endif // RASCSI
-
//---------------------------------------------------------------------------
//
// Connect the controller
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Connect(int id, BUS *bus)
+void SASIDEV::Connect(int id, BUS *bus)
{
- ASSERT(this);
-
- ctrl.id = id;
+ ctrl.m_scsi_id = id;
ctrl.bus = bus;
}
-//---------------------------------------------------------------------------
-//
-// Get the logical unit
-//
-//---------------------------------------------------------------------------
-Disk* FASTCALL SASIDEV::GetUnit(int no)
-{
- ASSERT(this);
- ASSERT(no < UnitMax);
-
- return ctrl.unit[no];
-}
-
//---------------------------------------------------------------------------
//
// Set the logical unit
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::SetUnit(int no, Disk *dev)
+void SASIDEV::SetUnit(int no, Disk *dev)
{
- ASSERT(this);
ASSERT(no < UnitMax);
ctrl.unit[no] = dev;
@@ -233,52 +124,18 @@ void FASTCALL SASIDEV::SetUnit(int no, Disk *dev)
//---------------------------------------------------------------------------
//
-// Check to see if this has a valid logical unit
+// Check to see if this has a valid LUN
//
//---------------------------------------------------------------------------
-BOOL FASTCALL SASIDEV::HasUnit()
+bool SASIDEV::HasUnit()
{
- int i;
-
- ASSERT(this);
-
- for (i = 0; i < UnitMax; i++) {
+ for (int i = 0; i < UnitMax; i++) {
if (ctrl.unit[i]) {
- return TRUE;
+ return true;
}
}
- return FALSE;
-}
-
-//---------------------------------------------------------------------------
-//
-// Get internal data
-//
-//---------------------------------------------------------------------------
-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()
-{
- DWORD lun;
-
- ASSERT(this);
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- return ctrl.unit[lun];
+ return false;
}
//---------------------------------------------------------------------------
@@ -286,12 +143,10 @@ Disk* FASTCALL SASIDEV::GetBusyUnit()
// Run
//
//---------------------------------------------------------------------------
-BUS::phase_t FASTCALL SASIDEV::Process()
+BUS::phase_t SASIDEV::Process()
{
- ASSERT(this);
-
// Do nothing if not connected
- if (ctrl.id < 0 || ctrl.bus == NULL) {
+ if (ctrl.m_scsi_id < 0 || ctrl.bus == NULL) {
return ctrl.phase;
}
@@ -301,9 +156,7 @@ BUS::phase_t FASTCALL SASIDEV::Process()
// 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, "SASI - RESET signal received");
- #endif // DISK_LOG
+ LOGINFO("RESET signal received");
// Reset the controller
Reset();
@@ -364,16 +217,11 @@ BUS::phase_t FASTCALL SASIDEV::Process()
// Bus free phase
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::BusFree()
+void SASIDEV::BusFree()
{
- ASSERT(this);
-
// Phase change
if (ctrl.phase != BUS::busfree) {
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Bus free phase");
- #endif // DISK_LOG
+ LOGTRACE("%s Bus free phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::busfree;
@@ -383,11 +231,14 @@ void FASTCALL SASIDEV::BusFree()
ctrl.bus->SetMSG(FALSE);
ctrl.bus->SetCD(FALSE);
ctrl.bus->SetIO(FALSE);
- ctrl.bus->SetBSY(FALSE);
+ ctrl.bus->SetBSY(false);
// Initialize status and message
ctrl.status = 0x00;
ctrl.message = 0x00;
+
+ ctrl.lun = -1;
+
return;
}
@@ -402,34 +253,28 @@ void FASTCALL SASIDEV::BusFree()
// Selection phase
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Selection()
+void SASIDEV::Selection()
{
- DWORD id;
-
- ASSERT(this);
-
// Phase change
if (ctrl.phase != BUS::selection) {
// Invalid if IDs do not match
- id = 1 << ctrl.id;
+ DWORD id = 1 << ctrl.m_scsi_id;
if ((ctrl.bus->GetDAT() & id) == 0) {
return;
}
- // Return if there is no unit
+ // Return if there is no valid LUN
if (!HasUnit()) {
return;
}
- #if defined(DISK_LOG)
- Log(Log::Normal,"SASI - Selection Phase ID=%d (with device)", ctrl.id);
- #endif // DISK_LOG
+ LOGTRACE("%s Selection Phase ID=%d (with device)", __PRETTY_FUNCTION__, (int)ctrl.m_scsi_id);
// Phase change
ctrl.phase = BUS::selection;
// Raiase BSY and respond
- ctrl.bus->SetBSY(TRUE);
+ ctrl.bus->SetBSY(true);
return;
}
@@ -441,24 +286,14 @@ void FASTCALL SASIDEV::Selection()
//---------------------------------------------------------------------------
//
-// Command phase
+// Command phase (used by SASI and SCSI)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Command()
+void SASIDEV::Command()
{
- #ifdef RASCSI
- int count;
- int i;
- #endif // RASCSI
-
- ASSERT(this);
-
// Phase change
if (ctrl.phase != BUS::command) {
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Command Phase");
- #endif // DISK_LOG
+ LOGTRACE("%s Command Phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::command;
@@ -473,20 +308,14 @@ void FASTCALL SASIDEV::Command()
ctrl.length = 6;
ctrl.blocks = 1;
- #ifdef RASCSI
- // Command reception handshake (10 bytes are automatically received at the first command)
- count = ctrl.bus->CommandHandShake(ctrl.buffer);
-
// If no byte can be received move to the status phase
- if (count == 0) {
+ int count = ctrl.bus->CommandHandShake(ctrl.buffer);
+ if (!count) {
Error();
return;
}
- // Check 10-byte CDB
- if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) {
- ctrl.length = 10;
- }
+ ctrl.length = GPIOBUS::GetCommandByteCount(ctrl.buffer[0]);
// If not able to receive all, move to the status phase
if (count != (int)ctrl.length) {
@@ -495,8 +324,9 @@ void FASTCALL SASIDEV::Command()
}
// Command data transfer
- for (i = 0; i < (int)ctrl.length; i++) {
+ for (int i = 0; i < (int)ctrl.length; i++) {
ctrl.cmd[i] = (DWORD)ctrl.buffer[i];
+ LOGTRACE("%s Command Byte %d: $%02X",__PRETTY_FUNCTION__, i, ctrl.cmd[i]);
}
// Clear length and block
@@ -505,26 +335,7 @@ void FASTCALL SASIDEV::Command()
// Execution Phase
Execute();
- #else
- // Request the command
- ctrl.bus->SetREQ(TRUE);
- return;
- #endif // RASCSI
}
- #ifndef RASCSI
- // 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
}
//---------------------------------------------------------------------------
@@ -532,13 +343,9 @@ void FASTCALL SASIDEV::Command()
// Execution Phase
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Execute()
+void SASIDEV::Execute()
{
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Execution Phase Command %02X", ctrl.cmd[0]);
- #endif // DISK_LOG
+ LOGTRACE("%s Execution Phase Command %02X", __PRETTY_FUNCTION__, (WORD)ctrl.cmd[0]);
// Phase Setting
ctrl.phase = BUS::execute;
@@ -546,82 +353,97 @@ void FASTCALL SASIDEV::Execute()
// Initialization for data transfer
ctrl.offset = 0;
ctrl.blocks = 1;
- #ifdef RASCSI
ctrl.execstart = SysTimer::GetTimerLow();
- #endif // RASCSI
+
+ // Discard pending sense data from the previous command if the current command is not REQUEST SENSE
+ if ((SASIDEV::sasi_command)ctrl.cmd[0] != SASIDEV::eCmdRequestSense) {
+ ctrl.status = 0;
+ ctrl.device->SetStatusCode(0);
+ }
// Process by command
- switch (ctrl.cmd[0]) {
+ // TODO This code does not belong here. Each device type needs such a dispatcher, which the controller has to call.
+ switch ((SASIDEV::sasi_command)ctrl.cmd[0]) {
// TEST UNIT READY
- case 0x00:
+ case SASIDEV::eCmdTestUnitReady:
CmdTestUnitReady();
return;
// REZERO UNIT
- case 0x01:
+ case SASIDEV::eCmdRezero:
CmdRezero();
return;
// REQUEST SENSE
- case 0x03:
+ case SASIDEV::eCmdRequestSense:
CmdRequestSense();
return;
- // FORMAT UNIT
- case 0x04:
- CmdFormat();
- return;
-
- // FORMAT UNIT
- case 0x06:
+ // FORMAT
+ case SASIDEV::eCmdFormat:
CmdFormat();
return;
// REASSIGN BLOCKS
- case 0x07:
- CmdReassign();
+ case SASIDEV::eCmdReassign:
+ CmdReassignBlocks();
return;
// READ(6)
- case 0x08:
+ case SASIDEV::eCmdRead6:
CmdRead6();
return;
// WRITE(6)
- case 0x0a:
+ case SASIDEV::eCmdWrite6:
CmdWrite6();
return;
// SEEK(6)
- case 0x0b:
+ case SASIDEV::eCmdSeek6:
CmdSeek6();
return;
- // ASSIGN(SASIのみ)
- case 0x0e:
+ // ASSIGN (SASI only)
+ // This doesn't exist in the SCSI Spec, but was in the original RaSCSI code.
+ // leaving it here for now....
+ case SASIDEV::eCmdSasiCmdAssign:
CmdAssign();
return;
// RESERVE UNIT(16)
- case 0x16:
+ case SASIDEV::eCmdReserve6:
CmdReserveUnit();
return;
// RELEASE UNIT(17)
- case 0x17:
+ case eCmdRelease6:
CmdReleaseUnit();
return;
- // SPECIFY(SASIのみ)
- case 0xc2:
+ // SPECIFY (SASI only)
+ // This doesn't exist in the SCSI Spec, but was in the original RaSCSI code.
+ // leaving it here for now....
+ case SASIDEV::eCmdInvalid:
CmdSpecify();
return;
+ default:
+ break;
}
// Unsupported command
- Log(Log::Warning, "SASI - Unsupported command $%02X", ctrl.cmd[0]);
- CmdInvalid();
+ LOGTRACE("%s ID %d received unsupported command: $%02X", __PRETTY_FUNCTION__, GetSCSIID(), (BYTE)ctrl.cmd[0]);
+
+ // Logical Unit
+ DWORD lun = GetEffectiveLun();
+ if (ctrl.unit[lun]) {
+ // Command processing on drive
+ ctrl.unit[lun]->SetStatusCode(STATUS_INVALIDCMD);
+ }
+
+ // Failure (Error)
+ Error();
}
//---------------------------------------------------------------------------
@@ -629,23 +451,14 @@ void FASTCALL SASIDEV::Execute()
// Status phase
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Status()
+void SASIDEV::Status()
{
- #ifdef RASCSI
- DWORD min_exec_time;
- DWORD time;
- #endif // RASCSI
-
- ASSERT(this);
-
// Phase change
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;
+ DWORD min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
+ DWORD time = SysTimer::GetTimerLow() - ctrl.execstart;
if (time < min_exec_time) {
SysTimer::SleepUsec(min_exec_time - time);
}
@@ -653,11 +466,8 @@ void FASTCALL SASIDEV::Status()
} else {
SysTimer::SleepUsec(5);
}
- #endif // RASCSI
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Status phase");
- #endif // DISK_LOG
+ LOGTRACE("%s Status phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::status;
@@ -673,52 +483,25 @@ void FASTCALL SASIDEV::Status()
ctrl.blocks = 1;
ctrl.buffer[0] = (BYTE)ctrl.status;
- #ifndef RASCSI
- // Request status
- ctrl.bus->SetDAT(ctrl.buffer[0]);
- ctrl.bus->SetREQ(TRUE);
+ LOGTRACE( "%s Status Phase $%02X",__PRETTY_FUNCTION__, (unsigned int)ctrl.status);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - 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();
- }
- }
- #endif // RASCSI
}
//---------------------------------------------------------------------------
//
-// Message in phase
+// Message in phase (used by SASI and SCSI)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::MsgIn()
+void SASIDEV::MsgIn()
{
- ASSERT(this);
-
// Phase change
if (ctrl.phase != BUS::msgin) {
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Message in phase");
- #endif // DISK_LOG
+ LOGTRACE("%s Starting Message in phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::msgin;
@@ -732,67 +515,34 @@ void FASTCALL SASIDEV::MsgIn()
ASSERT(ctrl.length > 0);
ASSERT(ctrl.blocks > 0);
ctrl.offset = 0;
-
- #ifndef RASCSI
- // Request message
- ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
- ctrl.bus->SetREQ(TRUE);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Message in phase $%02X", ctrl.buffer[ctrl.offset]);
- #endif // DISK_LOG
- #endif // RASCSI
return;
}
- #ifdef RASCSI
//Send
+ LOGTRACE("%s Transitioning to Send()", __PRETTY_FUNCTION__);
Send();
- #else
- // Requesting
- if (ctrl.bus->GetREQ()) {
- // Initator received
- if (ctrl.bus->GetACK()) {
- SendNext();
- }
- } else {
- // Initiator requests next
- if (!ctrl.bus->GetACK()) {
- Send();
- }
- }
- #endif // RASCSI
}
//---------------------------------------------------------------------------
//
-// Data-in Phase
+// Data-in Phase (used by SASI and SCSI)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::DataIn()
+void SASIDEV::DataIn()
{
- #ifdef RASCSI
- DWORD min_exec_time;
- DWORD time;
- #endif // RASCSI
-
- ASSERT(this);
ASSERT(ctrl.length >= 0);
// Phase change
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;
+ DWORD min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
+ DWORD time = SysTimer::GetTimerLow() - ctrl.execstart;
if (time < min_exec_time) {
SysTimer::SleepUsec(min_exec_time - time);
}
ctrl.execstart = 0;
}
- #endif // RASCSI
// If the length is 0, go to the status phase
if (ctrl.length == 0) {
@@ -800,10 +550,7 @@ void FASTCALL SASIDEV::DataIn()
return;
}
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Data-in Phase");
- #endif // DISK_LOG
-
+ LOGTRACE("%s Going into Data-in Phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::datain;
@@ -817,64 +564,33 @@ void FASTCALL SASIDEV::DataIn()
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();
- }
- }
- #endif // RASCSI
}
//---------------------------------------------------------------------------
//
-// Data out phase
+// Data out phase (used by SASI and SCSI)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::DataOut()
+void SASIDEV::DataOut()
{
- #ifdef RASCSI
- DWORD min_exec_time;
- DWORD time;
- #endif // RASCSI
-
- ASSERT(this);
ASSERT(ctrl.length >= 0);
// Phase change
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;
+ DWORD min_exec_time = IsSASI() ? min_exec_time_sasi : min_exec_time_scsi;
+ DWORD time = SysTimer::GetTimerLow() - ctrl.execstart;
if (time < min_exec_time) {
SysTimer::SleepUsec(min_exec_time - time);
}
ctrl.execstart = 0;
}
- #endif // RASCSI
// If the length is 0, go to the status phase
if (ctrl.length == 0) {
@@ -882,9 +598,7 @@ void FASTCALL SASIDEV::DataOut()
return;
}
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Data out phase");
- #endif // DISK_LOG
+ LOGTRACE("%s Data out phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::dataout;
@@ -898,31 +612,11 @@ void FASTCALL SASIDEV::DataOut()
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
- 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
}
//---------------------------------------------------------------------------
@@ -930,12 +624,8 @@ void FASTCALL SASIDEV::DataOut()
// Error
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Error()
+void SASIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc)
{
- DWORD lun;
-
- ASSERT(this);
-
// Get bus information
((GPIOBUS*)ctrl.bus)->Aquire();
@@ -955,12 +645,8 @@ void FASTCALL SASIDEV::Error()
return;
}
- #if defined(DISK_LOG)
- Log(Log::Warning, "SASI - Error occured (going to status phase)");
- #endif // DISK_LOG
-
// Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
+ DWORD lun = GetEffectiveLun();
// Set status and message(CHECK CONDITION)
ctrl.status = (lun << 5) | 0x02;
@@ -974,34 +660,12 @@ void FASTCALL SASIDEV::Error()
// TEST UNIT READY
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdTestUnitReady()
+void SASIDEV::CmdTestUnitReady()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - TEST UNIT READY Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE("%s TEST UNIT READY Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->TestUnitReady(ctrl.cmd);
- if (!status) {
- // Failure (Error)
- Error();
- return;
- }
-
- // status phase
- Status();
+ ctrl.device->TestUnitReady(this);
}
//---------------------------------------------------------------------------
@@ -1009,34 +673,12 @@ void FASTCALL SASIDEV::CmdTestUnitReady()
// REZERO UNIT
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdRezero()
+void SASIDEV::CmdRezero()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - REZERO UNIT Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE( "%s REZERO UNIT Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->Rezero(ctrl.cmd);
- if (!status) {
- // Failure (Error)
- Error();
- return;
- }
-
- // status phase
- Status();
+ ctrl.device->Rezero(this);
}
//---------------------------------------------------------------------------
@@ -1044,33 +686,12 @@ void FASTCALL SASIDEV::CmdRezero()
// REQUEST SENSE
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdRequestSense()
+void SASIDEV::CmdRequestSense()
{
- DWORD lun;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - REQUEST SENSE Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE( "%s REQUEST SENSE Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer);
- ASSERT(ctrl.length > 0);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Sense key $%02X", ctrl.buffer[2]);
- #endif // DISK_LOG
-
- // Read phase
- DataIn();
+ ctrl.device->RequestSense(this);
}
//---------------------------------------------------------------------------
@@ -1078,34 +699,12 @@ void FASTCALL SASIDEV::CmdRequestSense()
// FORMAT UNIT
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdFormat()
+void SASIDEV::CmdFormat()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - FORMAT UNIT Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE( "%s FORMAT UNIT Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->Format(ctrl.cmd);
- if (!status) {
- // Failure (Error)
- Error();
- return;
- }
-
- // status phase
- Status();
+ ctrl.device->FormatUnit(this);
}
//---------------------------------------------------------------------------
@@ -1113,70 +712,48 @@ void FASTCALL SASIDEV::CmdFormat()
// REASSIGN BLOCKS
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdReassign()
+void SASIDEV::CmdReassignBlocks()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - REASSIGN BLOCKS Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE("%s REASSIGN BLOCKS Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->Reassign(ctrl.cmd);
- if (!status) {
- // Failure (Error)
- Error();
- return;
- }
-
- // status phase
- Status();
+ ctrl.device->ReassignBlocks(this);
}
-// The following commands RESERVE UNIT and RELEASE UNIT are not properly implemented.
-// These commands are used in multi-initator environments which this project is not targeted at.
-// For now, we simply reply with an OK. -phrax 2021-03-06
-
//---------------------------------------------------------------------------
//
// RESERVE UNIT(16)
//
+// The reserve/release commands are only used in multi-initiator
+// environments. RaSCSI doesn't support this use case. However, some old
+// versions of Solaris will issue the reserve/release commands. We will
+// just respond with an OK status.
+//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdReserveUnit()
+void SASIDEV::CmdReserveUnit()
{
- ASSERT(this);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - RESERVE UNIT Command");
- #endif // DISK_LOG
+ LOGTRACE( "%s Reserve(6) Command", __PRETTY_FUNCTION__);
// status phase
- Status();
+ Status();
}
//---------------------------------------------------------------------------
//
// RELEASE UNIT(17)
//
+// The reserve/release commands are only used in multi-initiator
+// environments. RaSCSI doesn't support this use case. However, some old
+// versions of Solaris will issue the reserve/release commands. We will
+// just respond with an OK status.
+//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdReleaseUnit()
+void SASIDEV::CmdReleaseUnit()
{
- ASSERT(this);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - RELEASE UNIT Command");
- #endif // DISK_LOG
+ LOGTRACE( "%s Release(6) Command", __PRETTY_FUNCTION__);
// status phase
- Status();
+ Status();
}
//---------------------------------------------------------------------------
@@ -1184,22 +761,10 @@ void FASTCALL SASIDEV::CmdReleaseUnit()
// READ(6)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdRead6()
+void SASIDEV::CmdRead6()
{
- DWORD lun;
- 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[1] & 0x1f;
+ DWORD record = ctrl.cmd[1] & 0x1f;
record <<= 8;
record |= ctrl.cmd[2];
record <<= 8;
@@ -1209,18 +774,16 @@ void FASTCALL SASIDEV::CmdRead6()
ctrl.blocks = 0x100;
}
- #if defined(DISK_LOG)
- Log(Log::Normal,"SASI - READ(6) command record=%06X blocks=%d", record, ctrl.blocks);
- #endif // DISK_LOG
+ LOGTRACE("%s READ(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (unsigned int)record, (int)ctrl.blocks);
// Command processing on drive
- ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record);
+ ctrl.length = ctrl.device->Read(ctrl.cmd, ctrl.buffer, record);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
return;
}
-
+
// Set next block
ctrl.next = record + 1;
@@ -1233,22 +796,10 @@ void FASTCALL SASIDEV::CmdRead6()
// WRITE(6)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdWrite6()
+void SASIDEV::CmdWrite6()
{
- DWORD lun;
- 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[1] & 0x1f;
+ DWORD record = ctrl.cmd[1] & 0x1f;
record <<= 8;
record |= ctrl.cmd[2];
record <<= 8;
@@ -1258,12 +809,10 @@ void FASTCALL SASIDEV::CmdWrite6()
ctrl.blocks = 0x100;
}
- #if defined(DISK_LOG)
- Log(Log::Normal,"SASI - WRITE(6) command record=%06X blocks=%d", record, ctrl.blocks);
- #endif // DISK_LOG
+ LOGTRACE("%s WRITE(6) command record=%d blocks=%d", __PRETTY_FUNCTION__, (WORD)record, (WORD)ctrl.blocks);
// Command processing on drive
- ctrl.length = ctrl.unit[lun]->WriteCheck(record);
+ ctrl.length = ctrl.device->WriteCheck(record);
if (ctrl.length <= 0) {
// Failure (Error)
Error();
@@ -1282,34 +831,12 @@ void FASTCALL SASIDEV::CmdWrite6()
// SEEK(6)
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdSeek6()
+void SASIDEV::CmdSeek6()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - SEEK(6) Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE("%s SEEK(6) Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->Seek(ctrl.cmd);
- if (!status) {
- // Failure (Error)
- Error();
- return;
- }
-
- // status phase
- Status();
+ ctrl.device->Seek6(this);
}
//---------------------------------------------------------------------------
@@ -1317,26 +844,12 @@ void FASTCALL SASIDEV::CmdSeek6()
// ASSIGN
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdAssign()
+void SASIDEV::CmdAssign()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - ASSIGN Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE("%s ASSIGN Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->Assign(ctrl.cmd);
+ bool status = ctrl.device->CheckReady();
if (!status) {
// Failure (Error)
Error();
@@ -1355,26 +868,12 @@ void FASTCALL SASIDEV::CmdAssign()
// SPECIFY
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdSpecify()
+void SASIDEV::CmdSpecify()
{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - SPECIFY Command ");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (!ctrl.unit[lun]) {
- Error();
- return;
- }
+ LOGTRACE("%s SPECIFY Command ", __PRETTY_FUNCTION__);
// Command processing on drive
- status = ctrl.unit[lun]->Assign(ctrl.cmd);
+ bool status = ctrl.device->CheckReady();
if (!status) {
// Failure (Error)
Error();
@@ -1388,32 +887,6 @@ void FASTCALL SASIDEV::CmdSpecify()
DataOut();
}
-//---------------------------------------------------------------------------
-//
-// Unsupported command
-//
-//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::CmdInvalid()
-{
- DWORD lun;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SASI - Command not supported");
- #endif // DISK_LOG
-
- // Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
- if (ctrl.unit[lun]) {
- // Command processing on drive
- ctrl.unit[lun]->InvalidCmd();
- }
-
- // Failure (Error)
- Error();
-}
-
//===========================================================================
//
// Data transfer
@@ -1425,25 +898,19 @@ void FASTCALL SASIDEV::CmdInvalid()
// Data transmission
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Send()
+void SASIDEV::Send()
{
- #ifdef RASCSI
- int len;
- #endif // RASCSI
- BOOL result;
-
- ASSERT(this);
ASSERT(!ctrl.bus->GetREQ());
ASSERT(ctrl.bus->GetIO());
- #ifdef RASCSI
// Check that the length isn't 0
if (ctrl.length != 0) {
- len = ctrl.bus->SendHandShake(
- &ctrl.buffer[ctrl.offset], ctrl.length);
+ int len = ctrl.bus->SendHandShake(
+ &ctrl.buffer[ctrl.offset], ctrl.length, BUS::SEND_NO_DELAY);
// If you can not send it all, move on to the status phase
if (len != (int)ctrl.length) {
+ LOGERROR("%s ctrl.length (%d) did not match the amount of data sent (%d)",__PRETTY_FUNCTION__, (int)ctrl.length, len);
Error();
return;
}
@@ -1453,40 +920,27 @@ void FASTCALL SASIDEV::Send()
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;
+ else{
+ LOGINFO("%s ctrl.length was 0", __PRETTY_FUNCTION__);
}
- #endif // RASCSI
// Remove block and initialize the result
ctrl.blocks--;
- result = TRUE;
+ bool result = true;
// Process 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);
- //** printf("xfer in: %d \n",result);
-
- #ifndef RASCSI
- ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
- #endif // RASCSI
+ LOGTRACE("%s xfer in: %d",__PRETTY_FUNCTION__, result);
+ LOGTRACE("%s processing after data collection", __PRETTY_FUNCTION__);
}
}
// If result FALSE, move to the status phase
if (!result) {
+ LOGERROR("%s Send result was false", __PRETTY_FUNCTION__);
Error();
return;
}
@@ -1495,10 +949,6 @@ void FASTCALL SASIDEV::Send()
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;
}
@@ -1532,115 +982,23 @@ void FASTCALL SASIDEV::Send()
}
}
-#ifndef RASCSI
-//---------------------------------------------------------------------------
-//
-// Continue sending data
-//
-//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::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 SASIDEV::Receive()
+void SASIDEV::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, "SASI - 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 byte CDB
- ctrl.length = 10;
- }
- }
- 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 SASIDEV::Receive()
-#else
-//---------------------------------------------------------------------------
-//
-// Continue receiving data
-//
-//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::ReceiveNext()
-#endif // RASCSI
-{
- #ifdef RASCSI
- int len;
- #endif // RASCSI
- BOOL result;
-
- 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(
+ int len = ctrl.bus->ReceiveHandShake(
&ctrl.buffer[ctrl.offset], ctrl.length);
+ LOGDEBUG("%s Received %d bytes", __PRETTY_FUNCTION__, len);
// If not able to receive all, move to status phase
if (len != (int)ctrl.length) {
@@ -1653,32 +1011,23 @@ void FASTCALL SASIDEV::ReceiveNext()
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;
+ else
+ {
+ LOGDEBUG("%s ctrl.length was 0", __PRETTY_FUNCTION__);
}
- #endif // RASCSI
// Remove the control block and initialize the result
ctrl.blocks--;
- result = TRUE;
+ bool result = true;
// Process the data out phase
if (ctrl.phase == BUS::dataout) {
if (ctrl.blocks == 0) {
// End with this buffer
- result = XferOut(FALSE);
+ result = XferOut(false);
} else {
// Continue to next buffer (set offset, length)
- result = XferOut(TRUE);
+ result = XferOut(true);
}
}
@@ -1692,25 +1041,14 @@ void FASTCALL SASIDEV::ReceiveNext()
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 the next phase
switch (ctrl.phase) {
- #ifndef RASCSI
- // Command phase
- case BUS::command:
- // Execution Phase
- Execute();
- break;
- #endif // RASCSI
-
// Data out phase
case BUS::dataout:
+ LOGTRACE("%s transitioning to FlushUnit()",__PRETTY_FUNCTION__);
// Flush
FlushUnit();
@@ -1731,33 +1069,30 @@ void FASTCALL SASIDEV::ReceiveNext()
// *Reset offset and length
//
//---------------------------------------------------------------------------
-BOOL FASTCALL SASIDEV::XferIn(BYTE *buf)
+bool SASIDEV::XferIn(BYTE *buf)
{
- DWORD lun;
-
- ASSERT(this);
ASSERT(ctrl.phase == BUS::datain);
+ LOGTRACE("%s ctrl.cmd[0]=%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl.cmd[0]);
// Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
+ DWORD lun = GetEffectiveLun();
if (!ctrl.unit[lun]) {
- return FALSE;
+ return false;
}
// Limited to read commands
switch (ctrl.cmd[0]) {
- // READ(6)
- case 0x08:
- // READ(10)
- case 0x28:
+ case eCmdRead6:
+ case eCmdRead10:
+ case eCmdRead16:
// Read from disk
- ctrl.length = ctrl.unit[lun]->Read(buf, ctrl.next);
+ ctrl.length = ctrl.unit[lun]->Read(ctrl.cmd, buf, ctrl.next);
ctrl.next++;
// If there is an error, go to the status phase
if (ctrl.length <= 0) {
// Cancel data-in
- return FALSE;
+ return false;
}
// If things are normal, work setting
@@ -1767,11 +1102,11 @@ BOOL FASTCALL SASIDEV::XferIn(BYTE *buf)
// Other (impossible)
default:
ASSERT(FALSE);
- return FALSE;
+ return false;
}
// Succeeded in setting the buffer
- return TRUE;
+ return true;
}
//---------------------------------------------------------------------------
@@ -1780,43 +1115,37 @@ BOOL FASTCALL SASIDEV::XferIn(BYTE *buf)
// *If cont=true, reset the offset and length
//
//---------------------------------------------------------------------------
-BOOL FASTCALL SASIDEV::XferOut(BOOL cont)
+bool SASIDEV::XferOut(bool cont)
{
- DWORD lun;
- SCSIBR *bridge;
-
- ASSERT(this);
ASSERT(ctrl.phase == BUS::dataout);
// Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
+ DWORD lun = GetEffectiveLun();
if (!ctrl.unit[lun]) {
- return FALSE;
+ return false;
}
+ Disk *device = ctrl.unit[lun];
- // MODE SELECT or WRITE system
switch (ctrl.cmd[0]) {
- // MODE SELECT
- case 0x15:
- // MODE SELECT(10)
- case 0x55:
- if (!ctrl.unit[lun]->ModeSelect(
- ctrl.cmd, ctrl.buffer, ctrl.offset)) {
+ case SASIDEV::eCmdModeSelect6:
+ case SASIDEV::eCmdModeSelect10:
+ if (!device->ModeSelect(ctrl.cmd, ctrl.buffer, ctrl.offset)) {
// MODE SELECT failed
- return FALSE;
+ return false;
}
break;
- // WRITE(6)
- case 0x0a:
- // WRITE(10)
- case 0x2a:
- // 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)) {
+ case SASIDEV::eCmdWrite6:
+ case SASIDEV::eCmdWrite10:
+ case SASIDEV::eCmdWrite16:
+ case SASIDEV::eCmdVerify10:
+ case SASIDEV::eCmdVerify16:
+ // If we're a host bridge, use the host bridge's SendMessage10 function
+ // TODO This class must not know about SCSIBR
+ if (device->IsBridge()) {
+ if (!((SCSIBR*)device)->SendMessage10(ctrl.cmd, ctrl.buffer)) {
// write failed
- return FALSE;
+ return false;
}
// If normal, work setting
@@ -1824,12 +1153,23 @@ BOOL FASTCALL SASIDEV::XferOut(BOOL cont)
break;
}
- // WRITE AND VERIFY
- case 0x2e:
- // Write
- if (!ctrl.unit[lun]->Write(ctrl.buffer, ctrl.next - 1)) {
+ // Special case Write function for DaynaPort
+ // TODO This class must not know about DaynaPort
+ if (device->IsDaynaPort()) {
+ if (!device->Write(ctrl.cmd, ctrl.buffer, ctrl.length)) {
+ // write failed
+ return false;
+ }
+
+ // If normal, work setting
+ ctrl.offset = 0;
+ ctrl.blocks = 0;
+ break;
+ }
+
+ if (!device->Write(ctrl.cmd, ctrl.buffer, ctrl.next - 1)) {
// Write failed
- return FALSE;
+ return false;
}
// If you do not need the next block, end here
@@ -1839,10 +1179,10 @@ BOOL FASTCALL SASIDEV::XferOut(BOOL cont)
}
// Check the next block
- ctrl.length = ctrl.unit[lun]->WriteCheck(ctrl.next - 1);
+ ctrl.length = device->WriteCheck(ctrl.next - 1);
if (ctrl.length <= 0) {
// Cannot write
- return FALSE;
+ return false;
}
// If normal, work setting
@@ -1850,16 +1190,21 @@ BOOL FASTCALL SASIDEV::XferOut(BOOL cont)
break;
// SPECIFY(SASI only)
- case 0xc2:
+ case SASIDEV::eCmdInvalid:
+ break;
+
+ case SASIDEV::eCmdSetMcastAddr:
+ LOGTRACE("%s Done with DaynaPort Set Multicast Address", __PRETTY_FUNCTION__);
break;
default:
+ LOGWARN("Received an unexpected command (%02X) in %s", (WORD)ctrl.cmd[0] , __PRETTY_FUNCTION__)
ASSERT(FALSE);
break;
}
// Buffer saved successfully
- return TRUE;
+ return true;
}
//---------------------------------------------------------------------------
@@ -1867,175 +1212,65 @@ BOOL FASTCALL SASIDEV::XferOut(BOOL cont)
// Logical unit flush
//
//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::FlushUnit()
+void SASIDEV::FlushUnit()
{
- DWORD lun;
-
- ASSERT(this);
ASSERT(ctrl.phase == BUS::dataout);
// Logical Unit
- lun = (ctrl.cmd[1] >> 5) & 0x07;
+ DWORD lun = GetEffectiveLun();
if (!ctrl.unit[lun]) {
return;
}
+ Disk *device = ctrl.unit[lun];
// WRITE system only
- switch (ctrl.cmd[0]) {
- // WRITE(6)
- case 0x0a:
- // WRITE(10)
- case 0x2a:
- // WRITE AND VERIFY
- case 0x2e:
- // Flush
- if (!ctrl.unit[lun]->IsCacheWB()) {
- ctrl.unit[lun]->Flush();
- }
+ switch ((SASIDEV::sasi_command)ctrl.cmd[0]) {
+ case SASIDEV::eCmdWrite6:
+ case SASIDEV::eCmdWrite10:
+ case SASIDEV::eCmdWrite16:
+ case SASIDEV::eCmdVerify10:
+ case SASIDEV::eCmdVerify16:
break;
- // Mode Select (6)
- case 0x15:
- // MODE SELECT(10)
- case 0x55:
- // Debug code related to Issue #2 on github, where we get an unhandled Model select when
+
+ case SASIDEV::eCmdModeSelect6:
+ case SASIDEV::eCmdModeSelect10:
+ // Debug code related to Issue #2 on github, where we get an unhandled Mode Select when
// the mac is rebooted
// https://github.com/akuker/RASCSI/issues/2
- Log(Log::Warning, "SASI - Received \'Mode Select\'\n");
- Log(Log::Warning, " Operation Code: [%02X]\n", ctrl.cmd[0]);
- Log(Log::Warning, " Logical Unit %01X, PF %01X, SP %01X [%02X]\n", ctrl.cmd[1] >> 5, 1 & (ctrl.cmd[1] >> 4), ctrl.cmd[1] & 1, ctrl.cmd[1]);
- Log(Log::Warning, " Reserved: %02X\n", ctrl.cmd[2]);
- Log(Log::Warning, " Reserved: %02X\n", ctrl.cmd[3]);
- Log(Log::Warning, " Parameter List Len %02X\n", ctrl.cmd[4]);
- Log(Log::Warning, " Reserved: %02X\n", ctrl.cmd[5]);
- Log(Log::Warning, " Ctrl Len: %08X\n",ctrl.length);
+ LOGWARN("Received \'Mode Select\'\n");
+ LOGWARN(" Operation Code: [%02X]\n", (WORD)ctrl.cmd[0]);
+ LOGWARN(" Logical Unit %01X, PF %01X, SP %01X [%02X]\n",\
+ (WORD)ctrl.cmd[1] >> 5, 1 & ((WORD)ctrl.cmd[1] >> 4), \
+ (WORD)ctrl.cmd[1] & 1, (WORD)ctrl.cmd[1]);
+ LOGWARN(" Reserved: %02X\n", (WORD)ctrl.cmd[2]);
+ LOGWARN(" Reserved: %02X\n", (WORD)ctrl.cmd[3]);
+ LOGWARN(" Parameter List Len %02X\n", (WORD)ctrl.cmd[4]);
+ LOGWARN(" Reserved: %02X\n",(WORD)ctrl.cmd[5]);
+ LOGWARN(" Ctrl Len: %08X\n",(WORD)ctrl.length);
- if (!ctrl.unit[lun]->ModeSelect(
+ if (!device->ModeSelect(
ctrl.cmd, ctrl.buffer, ctrl.offset)) {
// MODE SELECT failed
- Log(Log::Warning, "SASI - Error occured while processing Mode Select command %02X\n", (unsigned char)ctrl.cmd[0]);
+ LOGWARN("Error occured while processing Mode Select command %02X\n", (unsigned char)ctrl.cmd[0]);
return;
}
break;
+ case SASIDEV::eCmdSetMcastAddr:
+ // TODO: Eventually, we should store off the multicast address configuration data here...
+ break;
+
default:
- Log(Log::Warning, "SASI - Received an invalid flush command %02X!!!!!\n",ctrl.cmd[0]);
- ASSERT(FALSE);
+ LOGWARN("Received an unexpected flush command %02X!!!!!\n",(WORD)ctrl.cmd[0]);
+ // The following statement makes debugging a huge pain. You can un-comment it
+ // if you're not trying to add new devices....
+ // ASSERT(FALSE);
break;
}
}
-#ifdef DISK_LOG
-//---------------------------------------------------------------------------
-//
-// Get the current phase as a string
-//
-//---------------------------------------------------------------------------
-void SASIDEV::GetPhaseStr(char *str)
+int SASIDEV::GetEffectiveLun() const
{
- 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;
- }
+ return ctrl.lun != -1 ? ctrl.lun : (ctrl.cmd[1] >> 5) & 0x07;
}
-#endif
-//---------------------------------------------------------------------------
-//
-// Log output
-//
-// TODO: This function needs some cleanup. Its very kludgey
-//---------------------------------------------------------------------------
-void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...)
-{
- #if !defined(BAREMETAL)
- #ifdef DISK_LOG
- char buffer[0x200];
- char buffer2[0x250];
- char buffer3[0x250];
- char phase_str[20];
- #endif
- va_list args;
- va_start(args, format);
-
- if(this->GetID() != 6)
- {
- return;
- }
-
- #ifdef RASCSI
- #ifndef DISK_LOG
- if (level == Log::Warning) {
- return;
- }
- #endif // DISK_LOG
- #endif // RASCSI
-
- #ifdef DISK_LOG
- // 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", buffer2);
- #else
- host->GetVM()->GetLog()->Format(level, host, buffer);
- #endif // RASCSI
- #endif // BAREMETAL
- #endif // DISK_LOG
-}
diff --git a/src/raspberrypi/controllers/sasidev_ctrl.h b/src/raspberrypi/controllers/sasidev_ctrl.h
index 120f050f..db41ccd5 100644
--- a/src/raspberrypi/controllers/sasidev_ctrl.h
+++ b/src/raspberrypi/controllers/sasidev_ctrl.h
@@ -15,12 +15,11 @@
//---------------------------------------------------------------------------
#pragma once
+#include "../rascsi.h"
#include "os.h"
#include "scsi.h"
#include "fileio.h"
-#include "devices/disk.h"
#include "log.h"
-#include "xm6.h"
//===========================================================================
@@ -30,141 +29,171 @@
//===========================================================================
class SASIDEV
{
-public:
- enum {
- UnitMax = 8 // Maximum number of logical units
+protected:
+ enum scsi_message_code : BYTE {
+ eMsgCodeAbort = 0x06,
+ eMsgCodeAbortTag = 0x0D,
+ eMsgCodeBusDeviceReset = 0x0C,
+ eMsgCodeClearQueue = 0x0E,
+ eMsgCodeCommandComplete = 0x00,
+ eMsgCodeDisconnect = 0x04,
+ eMsgCodeIdentify = 0x80,
+ eMsgCodeIgnoreWideResidue = 0x23, // (Two Bytes)
+ eMsgCodeInitiateRecovery = 0x0F,
+ eMsgCodeInitiatorDetectedError = 0x05,
+ eMsgCodeLinkedCommandComplete = 0x0A,
+ eMsgCodeLinkedCommandCompleteWithFlag = 0x0B,
+ eMsgCodeMessageParityError = 0x09,
+ eMsgCodeMessageReject = 0x07,
+ eMsgCodeNoOperation = 0x08,
+ eMsgCodeHeadOfQueueTag = 0x21,
+ eMsgCodeOrderedQueueTag = 0x22,
+ eMsgCodeSimpleQueueTag = 0x20,
+ eMsgCodeReleaseRecovery = 0x10,
+ eMsgCodeRestorePointers = 0x03,
+ eMsgCodeSaveDataPointer = 0x02,
+ eMsgCodeTerminateIOProcess = 0x11
};
- #ifdef RASCSI
+private:
+ enum sasi_command : int {
+ eCmdTestUnitReady = 0x00,
+ eCmdRezero = 0x01,
+ eCmdRequestSense = 0x03,
+ eCmdFormat = 0x06,
+ eCmdReassign = 0x07,
+ eCmdRead6 = 0x08,
+ eCmdWrite6 = 0x0A,
+ eCmdSeek6 = 0x0B,
+ eCmdSetMcastAddr = 0x0D, // DaynaPort specific command
+ eCmdModeSelect6 = 0x15,
+ eCmdReserve6 = 0x16,
+ eCmdRelease6 = 0x17,
+ eCmdRead10 = 0x28,
+ eCmdWrite10 = 0x2A,
+ eCmdVerify10 = 0x2E,
+ eCmdVerify = 0x2F,
+ eCmdModeSelect10 = 0x55,
+ eCmdRead16 = 0x88,
+ eCmdWrite16 = 0x8A,
+ eCmdVerify16 = 0x8F,
+ eCmdInvalid = 0xC2,
+ eCmdSasiCmdAssign = 0x0E
+ };
+
+public:
+ enum {
+ UnitMax = 32 // Maximum number of logical units
+ };
+
+ const int UNKNOWN_SCSI_ID = -1;
+ const int DEFAULT_BUFFER_SIZE = 0x1000;
+ // TODO Remove this duplicate
+ const int DAYNAPORT_BUFFER_SIZE = 0x1000000;
+
// For timing adjustments
enum {
min_exec_time_sasi = 100, // SASI BOOT/FORMAT 30:NG 35:OK
min_exec_time_scsi = 50
};
- #endif // RASCSI
// Internal data definition
typedef struct {
- // 全般
+ // General
BUS::phase_t phase; // Transition phase
- int id; // Controller ID (0-7)
- BUS *bus; // Bus
+ int m_scsi_id; // Controller ID (0-7)
+ BUS *bus; // Bus
// commands
- DWORD cmd[10]; // Command data
+ DWORD cmd[16]; // Command data
DWORD status; // Status data
DWORD message; // Message data
- #ifdef RASCSI
// Run
DWORD execstart; // Execution start time
- #endif // RASCSI
// Transfer
BYTE *buffer; // Transfer data buffer
int bufsize; // Transfer data buffer size
- DWORD blocks; // Number of transfer block
- DWORD next; // Next record
+ uint32_t blocks; // Number of transfer block
+ DWORD next; // Next record
DWORD offset; // Transfer offset
DWORD length; // Transfer remaining length
// Logical unit
- Disk *unit[UnitMax]; // Logical Unit
+ Disk *unit[UnitMax];
+
+ // The current device
+ Disk *device;
+
+ // The LUN from the IDENTIFY message
+ int lun;
} ctrl_t;
public:
// Basic Functions
- #ifdef RASCSI
SASIDEV();
- #else
-
- SASIDEV(Device *dev); // Constructor
-
- #endif //RASCSI
virtual ~SASIDEV(); // Destructor
- virtual void FASTCALL Reset(); // Device Reset
-
- #ifndef RASCSI
- virtual BOOL FASTCALL Save(Fileio *fio, int ver); // Save
- virtual BOOL FASTCALL Load(Fileio *fio, int ver); // Load
- #endif //RASCSI
+ virtual void Reset(); // Device Reset
// External API
- virtual BUS::phase_t FASTCALL Process(); // Run
+ virtual BUS::phase_t Process(); // Run
// Connect
- void FASTCALL Connect(int id, BUS *sbus); // Controller connection
- Disk* FASTCALL GetUnit(int no); // Get logical unit
- void FASTCALL SetUnit(int no, Disk *dev); // Logical unit setting
- BOOL FASTCALL HasUnit(); // Has a valid logical unit
+ void Connect(int id, BUS *sbus); // Controller connection
+ Disk* GetUnit(int no); // Get logical unit
+ void SetUnit(int no, Disk *dev); // Logical unit setting
+ bool HasUnit(); // Has a valid logical unit
// Other
- BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} // Get the phase
- #ifdef DISK_LOG
+ BUS::phase_t GetPhase() {return ctrl.phase;} // Get the phase
- // Function to get the current phase as a String.
- void FASTCALL GetPhaseStr(char *str);
- #endif
+ int GetSCSIID() {return ctrl.m_scsi_id;} // Get the ID
+ ctrl_t* GetCtrl() { return &ctrl; } // Get the internal information address
+ virtual bool IsSASI() const { return true; } // SASI Check
+ virtual bool IsSCSI() const { return false; } // SCSI check
- int FASTCALL GetID() {return ctrl.id;} // Get the ID
- void FASTCALL GetCTRL(ctrl_t *buffer); // Get the internal information
- ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; } // Get the internal information address
- virtual BOOL FASTCALL IsSASI() const {return TRUE;} // SASI Check
- virtual BOOL FASTCALL IsSCSI() const {return FALSE;} // SCSI check
- Disk* FASTCALL GetBusyUnit(); // Get the busy unit
+public:
+ void DataIn(); // Data in phase
+ void Status(); // Status phase
+ void MsgIn(); // Message in phase
+ void DataOut(); // Data out phase
+
+ int GetEffectiveLun() const;
+
+ virtual void Error(ERROR_CODES::sense_key sense_key = ERROR_CODES::sense_key::NO_SENSE,
+ ERROR_CODES::asc = ERROR_CODES::asc::NO_ADDITIONAL_SENSE_INFORMATION); // Common error handling
protected:
// Phase processing
- virtual void FASTCALL BusFree(); // Bus free phase
- virtual void FASTCALL Selection(); // Selection phase
- virtual void FASTCALL Command(); // Command phase
- virtual void FASTCALL Execute(); // Execution phase
- void FASTCALL Status(); // Status phase
- void FASTCALL MsgIn(); // Message in phase
- void FASTCALL DataIn(); // Data in phase
- void FASTCALL DataOut(); // Data out phase
- virtual void FASTCALL Error(); // Common error handling
+ virtual void BusFree(); // Bus free phase
+ virtual void Selection(); // Selection phase
+ virtual void Command(); // Command phase
+ virtual void Execute(); // Execution phase
- // commands
- void FASTCALL CmdTestUnitReady(); // TEST UNIT READY command
- void FASTCALL CmdRezero(); // REZERO UNIT command
- void FASTCALL CmdRequestSense(); // REQUEST SENSE command
- void FASTCALL CmdFormat(); // FORMAT command
- void FASTCALL CmdReassign(); // REASSIGN BLOCKS command
- void FASTCALL CmdReserveUnit(); // RESERVE UNIT command
- void FASTCALL CmdReleaseUnit(); // RELEASE UNIT command
- void FASTCALL CmdRead6(); // READ(6) command
- void FASTCALL CmdWrite6(); // WRITE(6) command
- void FASTCALL CmdSeek6(); // SEEK(6) command
- void FASTCALL CmdAssign(); // ASSIGN command
- void FASTCALL CmdSpecify(); // SPECIFY command
- void FASTCALL CmdInvalid(); // Unsupported command
+ // Commands
+ void CmdTestUnitReady(); // TEST UNIT READY command
+ void CmdRezero(); // REZERO UNIT command
+ void CmdRequestSense(); // REQUEST SENSE command
+ void CmdFormat(); // FORMAT command
+ void CmdReassignBlocks(); // REASSIGN BLOCKS command
+ void CmdReserveUnit(); // RESERVE UNIT command
+ void CmdReleaseUnit(); // RELEASE UNIT command
+ void CmdRead6(); // READ(6) command
+ void CmdWrite6(); // WRITE(6) command
+ void CmdSeek6(); // SEEK(6) command
+ void CmdAssign(); // ASSIGN command
+ void CmdSpecify(); // SPECIFY command
- // データ転送
- virtual void FASTCALL Send(); // Send data
+ // Data transfer
+ virtual void Send(); // Send data
+ virtual void Receive(); // Receive data
- #ifndef RASCSI
- virtual void FASTCALL SendNext(); // Continue sending data
- #endif // RASCSI
-
- virtual void FASTCALL Receive(); // Receive data
-
- #ifndef RASCSI
- virtual void FASTCALL ReceiveNext(); // Continue receiving data
- #endif // RASCSI
-
- BOOL FASTCALL XferIn(BYTE* buf); // Data transfer IN
- BOOL FASTCALL XferOut(BOOL cont); // Data transfer OUT
+ bool XferIn(BYTE* buf); // Data transfer IN
+ bool XferOut(bool cont); // Data transfer OUT
// Special operations
- void FASTCALL FlushUnit(); // Flush the logical unit
+ void FlushUnit(); // Flush the logical unit
- // Log
- void FASTCALL Log(Log::loglevel level, const char *format, ...); // Log output
-
-protected:
- #ifndef RASCSI
- Device *host; // Host device
- #endif // RASCSI
ctrl_t ctrl; // Internal data
};
diff --git a/src/raspberrypi/controllers/scsidev_ctrl.cpp b/src/raspberrypi/controllers/scsidev_ctrl.cpp
index 50a0e2ea..c07d35b6 100644
--- a/src/raspberrypi/controllers/scsidev_ctrl.cpp
+++ b/src/raspberrypi/controllers/scsidev_ctrl.cpp
@@ -13,10 +13,11 @@
// [ SCSI device controller ]
//
//---------------------------------------------------------------------------
+#include "log.h"
#include "controllers/scsidev_ctrl.h"
#include "gpiobus.h"
-#include "devices/scsi_host_bridge.h"
-#include "rascsi_version.h"
+#include "devices/scsi_daynaport.h"
+#include
//===========================================================================
//
@@ -29,32 +30,30 @@
// Constructor
//
//---------------------------------------------------------------------------
-#ifdef RASCSI
SCSIDEV::SCSIDEV() : SASIDEV()
-#else
-SCSIDEV::SCSIDEV(Device *dev) : SASIDEV(dev)
-#endif
{
// Synchronous transfer work initialization
scsi.syncenable = FALSE;
scsi.syncperiod = 50;
scsi.syncoffset = 0;
- scsi.atnmsg = FALSE;
+ scsi.atnmsg = false;
scsi.msc = 0;
memset(scsi.msb, 0x00, sizeof(scsi.msb));
}
+SCSIDEV::~SCSIDEV()
+{
+}
+
//---------------------------------------------------------------------------
//
// Device reset
//
//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::Reset()
+void SCSIDEV::Reset()
{
- ASSERT(this);
-
// Work initialization
- scsi.atnmsg = FALSE;
+ scsi.atnmsg = false;
scsi.msc = 0;
memset(scsi.msb, 0x00, sizeof(scsi.msb));
@@ -67,23 +66,19 @@ void FASTCALL SCSIDEV::Reset()
// Process
//
//---------------------------------------------------------------------------
-BUS::phase_t FASTCALL SCSIDEV::Process()
+BUS::phase_t SCSIDEV::Process()
{
- ASSERT(this);
-
// Do nothing if not connected
- if (ctrl.id < 0 || ctrl.bus == NULL) {
+ if (ctrl.m_scsi_id < 0 || ctrl.bus == NULL) {
return ctrl.phase;
}
// Get bus information
((GPIOBUS*)ctrl.bus)->Aquire();
- // Reset
+ // Check to see if the reset signal was asserted
if (ctrl.bus->GetRST()) {
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - RESET信号受信");
- #endif // DISK_LOG
+ LOGWARN("RESET signal received!");
// Reset the controller
Reset();
@@ -100,7 +95,7 @@ BUS::phase_t FASTCALL SCSIDEV::Process()
BusFree();
break;
- // Selection phase
+ // Selection
case BUS::selection:
Selection();
break;
@@ -144,44 +139,36 @@ BUS::phase_t FASTCALL SCSIDEV::Process()
return ctrl.phase;
}
-//---------------------------------------------------------------------------
-//
-// Phaes
-//
-//---------------------------------------------------------------------------
-
//---------------------------------------------------------------------------
//
// Bus free phase
//
//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::BusFree()
+void SCSIDEV::BusFree()
{
- ASSERT(this);
-
// Phase change
if (ctrl.phase != BUS::busfree) {
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - Bus free phase");
- #endif // DISK_LOG
+ LOGTRACE("%s Bus free phase", __PRETTY_FUNCTION__);
// Phase setting
ctrl.phase = BUS::busfree;
- // Signal line
+ // Set Signal lines
ctrl.bus->SetREQ(FALSE);
ctrl.bus->SetMSG(FALSE);
ctrl.bus->SetCD(FALSE);
ctrl.bus->SetIO(FALSE);
- ctrl.bus->SetBSY(FALSE);
+ ctrl.bus->SetBSY(false);
// Initialize status and message
ctrl.status = 0x00;
ctrl.message = 0x00;
// Initialize ATN message reception status
- scsi.atnmsg = FALSE;
+ scsi.atnmsg = false;
+
+ ctrl.lun = -1;
+
return;
}
@@ -196,34 +183,28 @@ void FASTCALL SCSIDEV::BusFree()
// Selection Phase
//
//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::Selection()
+void SCSIDEV::Selection()
{
- DWORD id;
-
- ASSERT(this);
-
// Phase change
if (ctrl.phase != BUS::selection) {
// invalid if IDs do not match
- id = 1 << ctrl.id;
+ DWORD id = 1 << ctrl.m_scsi_id;
if ((ctrl.bus->GetDAT() & id) == 0) {
return;
}
- // End if there is no valid unit
+ // Return if there is no valid LUN
if (!HasUnit()) {
return;
}
- #if defined(DISK_LOG)
- Log(Log::Normal,"SCSI - Selection Phase ID=%d (with device)", ctrl.id);
- #endif // DISK_LOG
+ LOGTRACE("%s Selection Phase ID=%d (with device)", __PRETTY_FUNCTION__, (int)ctrl.m_scsi_id);
// Phase setting
ctrl.phase = BUS::selection;
// Raise BSY and respond
- ctrl.bus->SetBSY(TRUE);
+ ctrl.bus->SetBSY(true);
return;
}
@@ -243,13 +224,9 @@ void FASTCALL SCSIDEV::Selection()
// Execution Phase
//
//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::Execute()
+void SCSIDEV::Execute()
{
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - Execution phase command $%02X", ctrl.cmd[0]);
- #endif // DISK_LOG
+ LOGTRACE("%s Execution phase command $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl.cmd[0]);
// Phase Setting
ctrl.phase = BUS::execute;
@@ -257,182 +234,53 @@ void FASTCALL SCSIDEV::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;
-
- // RESERVE(6)
- case 0x16:
- CmdReserve6();
- return;
-
- // RESERVE(10)
- case 0x56:
- CmdReserve10();
- return;
-
- // RELEASE(6)
- case 0x17:
- CmdRelease6();
- return;
-
- // RELEASE(10)
- case 0x57:
- CmdRelease10();
- 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;
+ // Discard pending sense data from the previous command if the current command is not REQUEST SENSE
+ if ((SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
+ ctrl.status = 0;
}
- // No other support
- Log(Log::Normal, "SCSI - Unsupported command received: $%02X", ctrl.cmd[0]);
- CmdInvalid();
+ LOGDEBUG("++++ CMD ++++ %s Executing command $%02X", __PRETTY_FUNCTION__, (unsigned int)ctrl.cmd[0]);
+
+ int lun = GetEffectiveLun();
+ if (!ctrl.unit[lun]) {
+ if ((SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdInquiry && (SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
+ LOGDEBUG("Invalid LUN %d for ID %d", lun, GetSCSIID());
+
+ Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_LUN);
+ return;
+ }
+ // Use LUN 0 for INQUIRY and REQUEST SENSE because LUN0 is assumed to be always available.
+ // INQUIRY and REQUEST SENSE have a special LUN handling of their own, required by the SCSI standard.
+ else {
+ assert(ctrl.unit[0]);
+
+ lun = 0;
+ }
+ }
+
+ ctrl.device = ctrl.unit[lun];
+
+ // Discard pending sense data from the previous command if the current command is not REQUEST SENSE
+ if ((SCSIDEV::scsi_command)ctrl.cmd[0] != eCmdRequestSense) {
+ ctrl.device->SetStatusCode(0);
+ }
+
+ if (!ctrl.device->Dispatch(this)) {
+ LOGTRACE("ID %d LUN %d received unsupported command: $%02X", GetSCSIID(), lun, (BYTE)ctrl.cmd[0]);
+
+ Error(ERROR_CODES::sense_key::ILLEGAL_REQUEST, ERROR_CODES::asc::INVALID_COMMAND_OPERATION_CODE);
+ }
+
+ // SCSI-2 p.104 4.4.3 Incorrect logical unit handling
+ if ((SCSIDEV::scsi_command)ctrl.cmd[0] == eCmdInquiry && !ctrl.unit[lun]) {
+ lun = GetEffectiveLun();
+
+ LOGDEBUG("Reporting LUN %d for device ID %d as not supported", lun, ctrl.device->GetId());
+
+ ctrl.buffer[0] = 0x7f;
+ }
}
//---------------------------------------------------------------------------
@@ -440,20 +288,17 @@ void FASTCALL SCSIDEV::Execute()
// Message out phase
//
//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::MsgOut()
+void SCSIDEV::MsgOut()
{
- ASSERT(this);
+ LOGTRACE("%s ID %d",__PRETTY_FUNCTION__, GetSCSIID());
// Phase change
if (ctrl.phase != BUS::msgout) {
+ LOGTRACE("Message Out Phase");
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - Message Out Phase"); // Message out phase after selection
- #endif // DISK_LOG
-
- // process the IDENTIFY message
+ // process the IDENTIFY message
if (ctrl.phase == BUS::selection) {
- scsi.atnmsg = TRUE;
+ scsi.atnmsg = true;
scsi.msc = 0;
memset(scsi.msb, 0x00, sizeof(scsi.msb));
}
@@ -471,31 +316,11 @@ void FASTCALL SCSIDEV::MsgOut()
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
}
//---------------------------------------------------------------------------
@@ -503,10 +328,8 @@ void FASTCALL SCSIDEV::MsgOut()
// Common Error Handling
//
//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::Error()
+void SCSIDEV::Error(ERROR_CODES::sense_key sense_key, ERROR_CODES::asc asc)
{
- ASSERT(this);
-
// Get bus information
((GPIOBUS*)ctrl.bus)->Aquire();
@@ -526,970 +349,53 @@ void FASTCALL SCSIDEV::Error()
return;
}
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - Error (to status phase)");
- #endif // DISK_LOG
+ DWORD lun = (ctrl.cmd[1] >> 5) & 0x07;
+ if (!ctrl.unit[lun] || asc == ERROR_CODES::INVALID_LUN) {
+ lun = 0;
+ }
+
+ if (sense_key || asc) {
+ // Set Sense Key and ASC for a subsequent REQUEST SENSE
+ ctrl.unit[lun]->SetStatusCode((sense_key << 16) | (asc << 8));
+ }
- // Set status and message(CHECK CONDITION)
ctrl.status = 0x02;
ctrl.message = 0x00;
- // status phase
+ LOGTRACE("%s Error (to status phase)", __PRETTY_FUNCTION__);
+
Status();
}
-//---------------------------------------------------------------------------
-//
-// Command
-//
-//---------------------------------------------------------------------------
-
-//---------------------------------------------------------------------------
-//
-// INQUIRY
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdInquiry()
-{
- Disk *disk;
- int lun;
- DWORD major;
- DWORD minor;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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) {
- major = (DWORD)rascsi_major_version;
- minor = (DWORD)rascsi_minor_version;
- 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 SCSIDEV::CmdModeSelect()
-{
- DWORD lun;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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();
-}
-
-// The following commands RESERVE(6), RESERVE(10), RELEASE(6) and RELEASE(10)
-// are not properly implemented. These commands are used in multi-initator environments
-// which this project is not targeted at. For now, we simply reply with an OK.
-// -phrax 2021-03-06
-
-//---------------------------------------------------------------------------
-//
-// RESERVE(6)
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdReserve6()
-{
- ASSERT(this);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - RESERVE(6) Command");
- #endif // DISK_LOG
-
- // status phase
- Status();
-}
-
-//---------------------------------------------------------------------------
-//
-// RESERVE(10)
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdReserve10()
-{
- ASSERT(this);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - RESERVE(10) Command");
- #endif // DISK_LOG
-
- // status phase
- Status();
-}
-
-//---------------------------------------------------------------------------
-//
-// RELEASE(6)
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdRelease6()
-{
- ASSERT(this);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - RELEASE(6) Command");
- #endif // DISK_LOG
-
- // status phase
- Status();
-}
-
-//---------------------------------------------------------------------------
-//
-// RELEASE(10)
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdRelease10()
-{
- ASSERT(this);
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - RELEASE(10) Command");
- #endif // DISK_LOG
-
- // status phase
- Status();
-}
-
-//---------------------------------------------------------------------------
-//
-// MODE SENSE
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdModeSense()
-{
- DWORD lun;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - MODE SENSE 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]->ModeSense(ctrl.cmd, ctrl.buffer);
- ASSERT(ctrl.length >= 0);
- if (ctrl.length == 0) {
- Log(Log::Warning,"SCSI - Not supported MODE SENSE page $%02X", ctrl.cmd[2]);
-
- // Failure (Error)
- Error();
- return;
- }
-
- // Data-in Phase
- DataIn();
-}
-
-//---------------------------------------------------------------------------
-//
-// START STOP UNIT
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::CmdStartStop()
-{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::CmdSendDiag()
-{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::CmdRemoval()
-{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::CmdReadCapacity()
-{
- DWORD lun;
- int length;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::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, "SCSI - 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 SCSIDEV::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,"SCSI - 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 SCSIDEV::CmdSeek10()
-{
- DWORD lun;
- BOOL status;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::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,"SCSI - 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 SCSIDEV::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 SCSIDEV::CmdReadDefectData10()
-{
- DWORD lun;
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::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 SCSIDEV::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 SCSIDEV::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 SCSIDEV::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 SCSIDEV::CmdModeSelect10()
-{
- DWORD lun;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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 SCSIDEV::CmdModeSense10()
-{
- DWORD lun;
-
- ASSERT(this);
-
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - 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,"SCSI - Not supported MODE SENSE(10) page $%02X", ctrl.cmd[2]);
-
- // Failure (Error)
- Error();
- return;
- }
-
- // Data-in Phase
- DataIn();
-}
-
-//---------------------------------------------------------------------------
-//
-// GET MESSAGE(10)
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::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 SCSIDEV::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 SCSIDEV::Send()
+void SCSIDEV::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);
+ ostringstream s;
+ s << __PRETTY_FUNCTION__ << " sending handhake with offset " << ctrl.offset << ", length " << ctrl.length;
+ LOGTRACE("%s", s.str().c_str());
+
+ // TODO Get rid of Daynaport specific code in this class
+ // The Daynaport needs to have a delay after the size/flags field
+ // of the read response. In the MacOS driver, it looks like the
+ // driver is doing two "READ" system calls.
+ int len;
+ if (ctrl.unit[0] && ctrl.unit[0]->IsDaynaPort()) {
+ len = ((GPIOBUS*)ctrl.bus)->SendHandShake(
+ &ctrl.buffer[ctrl.offset], ctrl.length, SCSIDaynaPort::DAYNAPORT_READ_HEADER_SZ);
+ }
+ else
+ {
+ len = ctrl.bus->SendHandShake(&ctrl.buffer[ctrl.offset], ctrl.length, BUS::SEND_NO_DELAY);
+ }
// If you cannot send all, move to status phase
if (len != (int)ctrl.length) {
@@ -1502,33 +408,19 @@ void FASTCALL SCSIDEV::Send()
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;
+ bool 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
+ ostringstream s;
+ s << __PRETTY_FUNCTION__ << " Processing after data collection. Blocks: " << ctrl.blocks;
+ LOGTRACE("%s", s.str().c_str());
}
}
@@ -1540,23 +432,23 @@ void FASTCALL SCSIDEV::Send()
// Continue sending if block !=0
if (ctrl.blocks != 0){
+ ostringstream s;
+ s << __PRETTY_FUNCTION__ << " Continuing to send. Blocks: " << ctrl.blocks;
+ LOGTRACE("%s", s.str().c_str());
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
+ LOGTRACE("%s Move to next phase %s (%d)", __PRETTY_FUNCTION__, BUS::GetPhaseStrRaw(ctrl.phase), ctrl.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;
+ scsi.atnmsg = false;
// command phase
Command();
@@ -1588,167 +480,57 @@ void FASTCALL SCSIDEV::Send()
}
}
-#ifndef RASCSI
-//---------------------------------------------------------------------------
-//
-// Continue data transmission.....
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::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 SCSIDEV::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, "SCSI - 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, "SCSI - 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 SCSIDEV::Receive()
-#else
-
-//---------------------------------------------------------------------------
-//
-// Continue receiving data
-//
-//---------------------------------------------------------------------------
-void FASTCALL SCSIDEV::ReceiveNext()
-#endif // RASCSI
+void SCSIDEV::Receive()
{
- #ifdef RASCSI
int len;
- #endif // RASCSI
- BOOL result;
- int i;
BYTE data;
- ASSERT(this);
+ LOGTRACE("%s",__PRETTY_FUNCTION__);
// REQ is low
ASSERT(!ctrl.bus->GetREQ());
ASSERT(!ctrl.bus->GetIO());
- #ifdef RASCSI
// Length != 0 if received
if (ctrl.length != 0) {
+ LOGTRACE("%s length was != 0", __PRETTY_FUNCTION__);
// Receive
- len = ctrl.bus->ReceiveHandShake(
- &ctrl.buffer[ctrl.offset], ctrl.length);
+ 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) {
+ LOGERROR("%s Not able to receive all data. Going to error",__PRETTY_FUNCTION__);
Error();
return;
}
// Offset and Length
ctrl.offset += ctrl.length;
- ctrl.length = 0;;
+ 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;
+ bool result = true;
// Processing after receiving data (by phase)
+ LOGTRACE("%s ctrl.phase: %d (%s)",__PRETTY_FUNCTION__, (int)ctrl.phase, BUS::GetPhaseStrRaw(ctrl.phase));
switch (ctrl.phase) {
// Data out phase
case BUS::dataout:
if (ctrl.blocks == 0) {
// End with this buffer
- result = XferOut(FALSE);
+ result = XferOut(false);
} else {
// Continue to next buffer (set offset, length)
- result = XferOut(TRUE);
+ result = XferOut(true);
}
break;
@@ -1779,10 +561,6 @@ void FASTCALL SCSIDEV::ReceiveNext()
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;
}
@@ -1790,20 +568,12 @@ void FASTCALL SCSIDEV::ReceiveNext()
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++) {
+ len = GPIOBUS::GetCommandByteCount(ctrl.buffer[0]);
+
+ for (int i = 0; i < len; i++) {
ctrl.cmd[i] = (DWORD)ctrl.buffer[i];
- #if defined(DISK_LOG)
- Log(Log::Normal, "SCSI - Command $%02X", ctrl.cmd[i]);
- #endif // DISK_LOG
+ LOGTRACE("%s Command Byte %d: $%02X",__PRETTY_FUNCTION__, i, ctrl.cmd[i]);
}
- #endif // RASCSI
// Execution Phase
Execute();
@@ -1817,34 +587,26 @@ void FASTCALL SCSIDEV::ReceiveNext()
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;
+ int i = 0;
while (i < scsi.msc) {
// Message type
data = scsi.msb[i];
// ABORT
if (data == 0x06) {
- #if defined(DISK_LOG)
- Log(Log::Normal,"SCSI - Message code ABORT $%02X", data);
- #endif // DISK_LOG
+ LOGTRACE("Message code ABORT $%02X", (int)data);
BusFree();
return;
}
// BUS DEVICE RESET
if (data == 0x0C) {
- #if defined(DISK_LOG)
- Log(Log::Normal,"SCSI - Message code BUS DEVICE RESET $%02X", data);
- #endif // DISK_LOG
+ LOGTRACE("Message code BUS DEVICE RESET $%02X", (int)data);
scsi.syncoffset = 0;
BusFree();
return;
@@ -1852,16 +614,13 @@ void FASTCALL SCSIDEV::ReceiveNext()
// IDENTIFY
if (data >= 0x80) {
- #if defined(DISK_LOG)
- Log(Log::Normal,"SCSI - Message code IDENTIFY $%02X", data);
- #endif // DISK_LOG
+ ctrl.lun = data & 0x1F;
+ LOGTRACE("Message code IDENTIFY $%02X, LUN %d selected", data, ctrl.lun);
}
// Extended Message
if (data == 0x01) {
- #if defined(DISK_LOG)
- Log(Log::Normal,"SCSI - Message code EXTENDED MESSAGE $%02X", data);
- #endif // DISK_LOG
+ LOGTRACE("Message code EXTENDED MESSAGE $%02X", (int)data);
// Check only when synchronous transfer is possible
if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) {
@@ -1902,7 +661,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
}
// Initialize ATN message reception status
- scsi.atnmsg = FALSE;
+ scsi.atnmsg = false;
// Command phase
Command();
@@ -1929,9 +688,8 @@ void FASTCALL SCSIDEV::ReceiveNext()
// Transfer MSG
//
//---------------------------------------------------------------------------
-BOOL FASTCALL SCSIDEV::XferMsg(DWORD msg)
+bool SCSIDEV::XferMsg(DWORD msg)
{
- ASSERT(this);
ASSERT(ctrl.phase == BUS::msgout);
// Save message out data
@@ -1941,5 +699,5 @@ BOOL FASTCALL SCSIDEV::XferMsg(DWORD msg)
scsi.msc %= 256;
}
- return TRUE;
+ return true;
}
diff --git a/src/raspberrypi/controllers/scsidev_ctrl.h b/src/raspberrypi/controllers/scsidev_ctrl.h
index 8beec1df..c0ce8db6 100644
--- a/src/raspberrypi/controllers/scsidev_ctrl.h
+++ b/src/raspberrypi/controllers/scsidev_ctrl.h
@@ -14,7 +14,9 @@
//
//---------------------------------------------------------------------------
#pragma once
+
#include "controllers/sasidev_ctrl.h"
+#include