commit 35866cfb84ecb9657798a219f0572c97d9424c39 Author: Xavier Rey-Robert Date: Thu May 3 15:47:57 2018 +0200 first commit diff --git a/bin/raspberrypi/rascsi.tar.gz b/bin/raspberrypi/rascsi.tar.gz new file mode 100644 index 00000000..61b0b19e Binary files /dev/null and b/bin/raspberrypi/rascsi.tar.gz differ diff --git a/bin/x68k/RASDRV.SYS b/bin/x68k/RASDRV.SYS new file mode 100644 index 00000000..72700ab6 Binary files /dev/null and b/bin/x68k/RASDRV.SYS differ diff --git a/bin/x68k/RASETHER.SYS b/bin/x68k/RASETHER.SYS new file mode 100644 index 00000000..9e5fd2de Binary files /dev/null and b/bin/x68k/RASETHER.SYS differ diff --git a/doc/converter.txt b/doc/converter.txt new file mode 100644 index 00000000..b9b2fe42 --- /dev/null +++ b/doc/converter.txt @@ -0,0 +1,158 @@ +------------------------------------------------------------------------------ + + SCSI Target Emulator RaSCSI (*^..^*) + version 1.33 for Raspberry Pi + + Powered by XM6 TypeG Technology. + Copyright (C) 2016-2018 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ディレクトリに含まれる + バイナリを使用することが可能です。 + + ・initiator.png + SCSIのターゲットモードに加えイニシエータモードを使用するための変換基板 + 回路図です。基本機能に加えてRPIがイニシエータとなって物理HDDにコマンド + を発行することが可能になります。モードの制御に追加で一つGPIOピンを消費 + します。このイニシエータモードを使用したサンプルプログラムとしてrasdump + を用意しました。実HDDやMOからイメージファイルにダンプすることができます。 + オプションでリストア機能も使用できます。 + + ピンアサインのカスタマイズでPIN_INDに標準では7を設定してコンパイルする + 必要があります。ピンアサインのカスタマイズを参照してください。 + + ・fullspec.png + SCSIのターゲットモード、イニシエータモードに加えてSCSIの通信をモニター + することができる変換基板回路図です。SCSIプロトコロルを解析する等の特殊 + 要件がある場合はこの回路が最適です。全ての74LS641-1の方向制御をRaSCSI + から行いますのでGPIOピンを三つ余分に使用してしまいます。SCSIの開発に + 興味があればこの回路を組んでみてはどうでしょうか。特徴としてGPIOピン + を余分に使用する代わりに上のイニシエータモードが使用できる基板と比較 + して74LS86が必要にならないため基板がシンプルになるという恩恵があります。 + + ピンアサインのカスタマイズで、PIN_TAD,PIN_IND,PIN_DTDにそれぞれ標準 + では6,7,8を設定してコンパイルする必要があります。ピンアサインの + カスタマイズを参照してください。 + +□既存のものを手に入れる方法 + 最近では主にTwitter界隈を通じてRaSCSI用の変換基板を作成していただいて + いる方々がいらっしゃいます。 + + また秋葉原で委託販売されてます。 + + 家電のKENCHAN 同人ハード(キット)のページ等です。 + http://www.kadenken.com/shopbrand/ct76/" + + 現在のところ市販されているものとして + + ・BELさん開発のあいぼむ版 + ・tomcatさん開発のGAMERnium版 + + があります。 + +□ピンアサインのカスタマイズ + GPIOの信号制御論理やピンアサインはgpiobus.hとrascsidrv.cに定義があります。 + 定義が分かれているのはrascsidrv.cだけGPLなので敢えて分離しています。 + 御察し下さい。 + + カスタマイズ例としてgpiobus.hとrascsidrv.cに下記の二つの変換基板用定義例を + 用意しました。配布物の中にはコンパイル済みバイナリも含まれています。 + + ・BELさん開発のあいぼむ版 + ・tomcatさん開発の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 + + ・カーネルドライバ(rascsidrv.ko) + @OS最新化(必要あれば) + sudo apt-get update + sudo apt-get upgrade + sudo reboot + + Aカーネルヘッダー取得(必要あれば) + sudo apt-get install raspberrypi-kernel-headers + + Bコンパイル + cd kernelmodule + rascsidrv.cの修正 + make +[EOF] diff --git a/doc/fullspec.png b/doc/fullspec.png new file mode 100644 index 00000000..47692e59 Binary files /dev/null and b/doc/fullspec.png differ diff --git a/doc/initiator.png b/doc/initiator.png new file mode 100644 index 00000000..cabd0051 Binary files /dev/null and b/doc/initiator.png differ diff --git a/doc/pinassign.png b/doc/pinassign.png new file mode 100644 index 00000000..a334ade7 Binary files /dev/null and b/doc/pinassign.png differ diff --git a/doc/rascsi.txt b/doc/rascsi.txt new file mode 100644 index 00000000..c6c90190 --- /dev/null +++ b/doc/rascsi.txt @@ -0,0 +1,315 @@ +------------------------------------------------------------------------------ + + SCSI Target Emulator RaSCSI (*^..^*) + version 1.34 for Raspberry Pi + + Powered by XM6 TypeG Technology. + Copyright (C) 2016-2018 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 3 Model B を推奨します。 + + Raspberry Pi 2 Model BやZeroでも動作すると考えられます。 + ピンアサインを独自に変更しRaspberry Pi 1で動作させたという報告もあります。 + + (2)OS + RASPBIAN STRETCHで開発およびテストしています。 + sudo apt-get update及びsudo apt-get upgradeで最新にしています。 + このドキュメントを記述している時点で"Linux raspberrypi 4.14.34-v7+"です。 + + RaSCSIはSCSI信号をGPIOを利用して制御しているので可能な限り低レイテンシー + の状態で使用する必要があります。したがってCUIモードで利用することを推奨 + します。更に不要なサービスは極力停止して下さい。 + +□SCSIコネクタとの接続方法 + 状況が複雑になってきましたのでRaSCSIのホームページ上で情報提供しています。 + このドキュメントの最後にある公式ホームページを参考にして下さい。 + +□配布物 + 配布するアーカイブには実行ファイル、ドキュメント、ソースコードのそれぞれが + ディレクトリで分かれて含まれています。 + + bin/ ・・・ 実行ファイル + raspberrypi/ ・・・ RPI用のプログラム + rascsi.tar.gz ・・・ 実行ファイルとカーネルモジュールをtar+gzipしたもの。 + + x68k/ ・・・ X68000用のプログラム + RASDRV.SYS ・・・ ホストドライブドライバ + RASETHER.SYS ・・・ イーサネットドライバ + + doc/ ・・・ ドキュメント + rascsi.txt ・・・ 当ドキュメント + x68k.txt ・・・ X68000固有機能の説明 + converter.txt ・・・ 変換基板の説明 + pinassign.png ・・・ ピンアサイン図 + target.png ・・・ 変換基板回路図案(ターゲットモード) + initiator.png ・・・ 変換基板回路図案(イニシエータサポート) + fullspec.png ・・・ 変換基板回路図案(フルスペック) + + src/ ・・・ ソースコード + raspberrypi/ ・・・ RPI用のプログラムソース一式 + x68k/ ・・・ X68000用のプログラム一式 + + + RPIで使用するプログラムはrascsi.tar.gzですのでRPI上に転送してから解凍して + 下さい。パーミッション等を維持するためにRPI上で解凍することを推奨します。 + + rascsi.tar.gzにはstandard,fullspec,aibom,gamerniumのディレクトリが含まれ + ています。通常はstandardディレクトリにある実行ファイルを使用して下さい。 + + aibom,gamerniumディレクトリのものは"あいぼむ版","GAMERnium版"の変換基板を + 使用する時のものです。 + + fullspecディレクトリのものは公開したフルスペック版変換基板の回路図案で + 変換基板を作成した時に使用する時のものです。 + +□RASCI本体の使用方法(rascsi) + + sudo rascsi [-ID{01234567} FILE] ... + + ルート権限が必要ですのでsudo等で起動する必要があります。 + オプションに-hを付けると簡単なHELPが表示されます + + Usage: ./rascsi [-ID{0|1|2|3|4|5|6|7} FILE] ... + + ID is SCSI identification number. + FILE is disk image file. + + Detected images type 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) + + 引数では-ID{01234567}とFILEの一組で一つのSCSIデバイスを指定できます。 + + -IDの後ろの番号はSCSI IDです。SCSI 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 [-c CMD] [-t TYPE] [-f FILE] + + ID : SCSI ID + CMD : 操作コマンド + attach : ディスクを取り付ける + detatch : ディスクを取り外す + insert : メディアを挿入する(MOまたはCDのみ) + eject : メディアを取り出す(MOまたはCDのみ) + protect : メディアを書き込み禁止にする(MOのみ) + TYPE : ディスク種別 + hd : ハードディスク(SASI/SCSI) + mo : MO(光磁気ディスク) + cd : CDROM(CDROMドライブ) + bridge : ブリッジデバイス + FILE : ディスクイメージファイルのパス + + IDは必須です。CMDは省略時はattachと解釈します。TYPEはコマンドがattachの + 場合にはFILEの拡張子から自動判定します。FILEはTYPEを明示的に指定している + 場合は拡張子が異なっても構いません。基本的CMD,TYPEの解釈は大文字小文字を + 無視します。現在のところ最初の1文字でのみ判定しています。 + + コマンド例 + rascsi -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 : リストアモード + + サンプルなので必要最低限の処理しか実装していませんので改造するなりして + ご使用下さい。 + +□カーネルモジュールの導入方法(rascsidrv.ko) + version 1.24から安定化のためにGPIO制御の一部をカーネルモジュールで動作 + させる拡張を加えました。 + + カーネルモジュールを導入しなくても動作できますが、X68000シリーズのSASI + を使用する場合や純正SCSIボードを増設した場合はカーネルモジュールの導入 + を行っていないと動作が不安定になります。 + + カーネルモジュールを有効にするには + + sudo insmod rascsidrv.ko + + を実行してください。 + + カーネルモジュールの起動を確認するにはdmesgコマンドで出力されるログの + 最後に次のような表示がされている筈です。 + + "RaSCSI GPIO Driver Loaded(STANDARD)" + + 注意! + カーネルモジュールは使用中のOSのバージョンに依存します。 + + rascsiやrasctlと同じ階層にあるrascsidrv.koはRaspberry Pi 2/3用の + "Linux raspberrypi 4.14.34-v7+"でコンパイルしたモジュールになります。 + + 同じ階層のrpi1orZero/rascsidrv.koはRaspberry Pi 1/Zero用です。 + "Linux raspberrypi 4.14.34+"でコンパイルしたモジュールになります。 + + 自身でカーネルモジュールをコンパイルする手順を簡単に記しておきます。 + + ・OSの最新化 + sudo apt-get update + sudo apt-get upgrade + sudo reboot + + ・カーネルヘッダー取得 + sudo apt-get install raspberrypi-kernel-headers + + ・コンパイル + cd kernelmodule + make + +□サポートするディスクイメージ + (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ドライブに対応) + + (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シリーズ、PC98シリーズ、Apple Macintosh、 + MSX(MEGA-SCSI利用)で動作報告があります。 + + その他の機種でもちらほらと動作報告を頂いています。 + +□活用方法 + XM6等のX68000エミュレータを使用している場合はエミュレータで環境構築したHDD + イメージをFTP等でRaspberry Piに転送することでX68000の実機に接続できます。 + またその逆も然りで実機上に存在するファイルを格納したHDDイメージをPCにFTP等 + で転送することでエミュレータで活用することができます。 + +□ライセンス + RaSCSIはカーネルドライバを除きあるがまま"AS IS"で配布されるソフトウェアです。 + カーネルドライバのソースrascsidrv.cのみGPLです(御察っし下さい)。 + + つまり使用者が受けたあらゆる損害に対して一切責任を持ちません。またソフト + ウェアに不備もしくは不具合があったとしてもそれを修正する責任もありません。 + + RaSCSIを利用することでRaspberry PiやレトロPCが故障するリスクがあります。 + あくまで自己責任でチャレンジしてください。 + + XM6 TypeG同様に実験成果公開という性質上私のHP以外での配布を認めておりません。 + + XM6のライセンス条項を継承していますので雑誌/書籍での紹介事前の許諾が必要です。 + そもそも2017年にもなってSCSIに反応するのは限られた人だけだと思います。 + +□変換基板の頒布について + 変換基板の頒布については作者に許諾を得る必要はありません。 + 一応ご連絡いただければ何かとサポートできるかもしれません。 + + 但しレトロPCのSCSI環境改善を応援するという趣旨から、 + 有料の場合は + + 基板製作費 + パーツ費用 + 運送費 +(社会通念上一般的な)手数料 + + を大きく越えるような頒布についてはお止め下さい。 + +□公開ホームページ + http://www.geocities.jp/kugimoto0715/rascsi/index.html + +□連絡先 + twitter https://twitter.com/kugimoto0715 + e-mail kugimoto0715@yahoo.co.jp + +[EOF] diff --git a/doc/target.png b/doc/target.png new file mode 100644 index 00000000..52c28cc5 Binary files /dev/null and b/doc/target.png differ diff --git a/doc/x68k.txt b/doc/x68k.txt new file mode 100644 index 00000000..16bc9dec --- /dev/null +++ b/doc/x68k.txt @@ -0,0 +1,109 @@ +------------------------------------------------------------------------------ + + SCSI Target Emulator RaSCSI (*^..^*) + version 1.33 for Raspberry Pi + + Powered by XM6 TypeG Technology. + Copyright (C) 2016-2018 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 + +□イーサーネット接続 + 配布物に含まれる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/src/raspberrypi/Makefile b/src/raspberrypi/Makefile new file mode 100644 index 00000000..70eb4cef --- /dev/null +++ b/src/raspberrypi/Makefile @@ -0,0 +1,51 @@ +CC = gcc +CFLAGS = -DNDEBUG -O3 +CXX = g++ +CXXFLAGS = -DNDEBUG -O3 + +RASCSI = rascsi +RASCTL = rasctl +RASDUMP = rasdump + +BIN_ALL = $(RASCSI) $(RASCTL) $(RASDUMP) + +SRC_RASCSI = \ + rascsi.cpp \ + scsi.cpp \ + disk.cpp \ + gpiobus.cpp \ + ctapdriver.cpp \ + cfilesystem.cpp \ + filepath.cpp \ + fileio.cpp + +SRC_RASCTL = \ + rasctl.cpp + +SRC_RASDUMP = \ + rasdump.cpp \ + scsi.cpp \ + gpiobus.cpp \ + filepath.cpp \ + fileio.cpp + +OBJ_RASCSI := $(SRC_RASCSI:.cpp=.o) +OBJ_RASCTL := $(SRC_RASCTL:.c=.o) +OBJ_RASDUMP := $(SRC_RASDUMP:.c=.o) + +.cpp.o: + $(CXX) $(CXXFLAGS) -c $< + +ALL: $(BIN_ALL) + +$(RASCSI): $(OBJ_RASCSI) $ + $(CXX) -o $@ $(OBJ_RASCSI) -lpthread + +$(RASCTL): $(OBJ_RASCTL) $ + $(CXX) -o $@ $(OBJ_RASCTL) + +$(RASDUMP): $(OBJ_RASDUMP) $ + $(CXX) -o $@ $(OBJ_RASDUMP) + +clean: + rm -f *.o $(BIN_ALL) diff --git a/src/raspberrypi/cfilesystem.cpp b/src/raspberrypi/cfilesystem.cpp new file mode 100644 index 00000000..347814da --- /dev/null +++ b/src/raspberrypi/cfilesystem.cpp @@ -0,0 +1,4228 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "log.h" +#include "filepath.h" +#include "cfilesystem.h" + +//--------------------------------------------------------------------------- +// +// 貍「蟄励さ繝シ繝牙、画鋤 +// +//--------------------------------------------------------------------------- +#define IC_BUF_SIZE 1024 +static char convert_buf[IC_BUF_SIZE]; +#ifndef __NetBSD__ +// POSIX.1貅匁侠iconv(3)繧剃スソ逕ィ +#define CONVERT(src, dest, inbuf, outbuf, outsize) \ + convert(src, dest, (char *)inbuf, outbuf, outsize) +static void convert(char const *src, char const *dest, + char *inbuf, char *outbuf, size_t outsize) +#else +// NetBSD迚iconv(3)繧剃スソ逕ィ: 隨ャ2蠑墓焚縺ッconst char ** +#define CONVERT(src, dest, inbuf, outbuf, outsize) \ + convert(src, dest, inbuf, outbuf, outsize) +static void convert(char const *src, char const *dest, + const char *inbuf, char *outbuf, size_t outsize) +#endif +{ + iconv_t cd; + size_t in; + size_t out; + size_t ret; + + *outbuf = '\0'; + in = strlen(inbuf); + out = outsize - 1; + + cd = iconv_open(dest, src); + if (cd == (iconv_t)-1) { + return; + } + + ret = iconv(cd, &inbuf, &in, &outbuf, &out); + if (ret == (size_t)-1) { + return; + } + + iconv_close(cd); + *outbuf = '\0'; +} + +//--------------------------------------------------------------------------- +// +// SJIS->UTF8螟画鋤 +// +//--------------------------------------------------------------------------- +static char* SJIS2UTF8(const char *sjis, char *utf8, size_t bufsize) +{ + CONVERT("SJIS", "UTF-8", sjis, utf8, bufsize); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +// UTF8->SJIS螟画鋤 +// +//--------------------------------------------------------------------------- +static char* UTF82SJIS(const char *utf8, char *sjis, size_t bufsize) +{ + CONVERT("UTF-8", "SJIS", utf8, sjis, bufsize); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +// SJIS->UTF8螟画鋤(邁。譏鍋沿) +// +//--------------------------------------------------------------------------- +static char* S2U(const char *sjis) +{ + SJIS2UTF8(sjis, convert_buf, IC_BUF_SIZE); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +// UTF8->SJIS螟画鋤(邁。譏鍋沿) +// +//--------------------------------------------------------------------------- +static char* U2S(const char *utf8) +{ + UTF82SJIS(utf8, convert_buf, IC_BUF_SIZE); + return convert_buf; +} + +//--------------------------------------------------------------------------- +// +/// 繝代せ蜷榊叙蠕 +/// +/// Human68k逕ィnamests讒矩菴薙°繧峨?uman68k繝代せ蜷阪r蜿門セ励☆繧九 +/// 譖ク縺崎セシ縺ソ蜈医ヰ繝繝輔ぃ縺ッ66繝舌う繝亥ソ隕√ +// +//--------------------------------------------------------------------------- +void Human68k::namests_t::GetCopyPath(BYTE* szPath) const +{ + ASSERT(this); + ASSERT(szPath); + + BYTE* p = szPath; + for (size_t i = 0; i < 65; i++) { + BYTE c = path[i]; + if (c == '\0') + break; + if (c == 0x09) { + c = '/'; + } + *p++ = c; + } + + *p = '\0'; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷榊叙蠕 +/// +/// Human68k逕ィnamests讒矩菴薙°繧峨?uman68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ励☆繧九 +/// 譖ク縺崎セシ縺ソ蜈医ヰ繝繝輔ぃ縺ッ23繝舌う繝亥ソ隕√ +// +//--------------------------------------------------------------------------- +void Human68k::namests_t::GetCopyFilename(BYTE* szFilename) const +{ + ASSERT(this); + ASSERT(szFilename); + + size_t i; + BYTE* p = szFilename; + + // 繝輔ぃ繧、繝ォ蜷肴悽菴楢サ「騾 + for (i = 0; i < 8; i++) { + BYTE c = name[i]; + if (c == ' ') { + // 繝輔ぃ繧、繝ォ蜷堺クュ縺ォ繧ケ繝壹シ繧ケ縺悟コ迴セ縺励◆蝣エ蜷医∽サ・髯阪ョ繧ィ繝ウ繝医Μ縺檎カ壹>縺ヲ縺繧九°縺ゥ縺縺狗「コ隱 + /// @todo 8+3譁蟄励→TewntyOne莠呈鋤繝「繝シ繝峨〒蜍穂ス懊r螟峨∴繧九∋縺 + // add[0] 縺梧怏蜉ケ縺ェ譁蟄励↑繧臥カ壹¢繧 + if (add[0] != '\0') + goto next_name; + // name[i] 繧医j蠕後↓遨コ逋ス莉・螟悶ョ譁蟄励′蟄伜惠縺吶k縺ェ繧臥カ壹¢繧 + for (size_t j = i + 1; j < 8; j++) { + if (name[j] != ' ') + goto next_name; + } + // 繝輔ぃ繧、繝ォ蜷咲オらォッ縺ェ繧芽サ「騾∫オゆコ + break; + } + next_name: + *p++ = c; + } + // 蜈ィ縺ヲ縺ョ譁蟄励r隱ュ縺ソ霎シ繧縺ィ縲√%縺薙〒 i >= 8 縺ィ縺ェ繧 + + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′8譁蟄嶺サ・荳翫↑繧芽ソス蜉驛ィ蛻繧ょ刈縺医k + if (i >= 8) { + // 繝輔ぃ繧、繝ォ蜷崎ソス蜉驛ィ蛻霆「騾 + for (i = 0; i < 10; i++) { + BYTE c = add[i]; + if (c == '\0') + break; + *p++ = c; + } + // 蜈ィ縺ヲ縺ョ譁蟄励r隱ュ縺ソ霎シ繧縺ィ縲√%縺薙〒 i >= 10 縺ィ縺ェ繧 + } + + // 諡。蠑オ蟄舌′蟄伜惠縺吶k蝣エ蜷医ッ霆「騾 + if (ext[0] != ' ' || ext[1] != ' ' || ext[2] != ' ') { + *p++ = '.'; + for (i = 0; i < 3; i++) { + BYTE c = ext[i]; + if (c == ' ') { + // 諡。蠑オ蟄蝉クュ縺ォ繧ケ繝壹シ繧ケ縺悟コ迴セ縺励◆蝣エ蜷医∽サ・髯阪ョ繧ィ繝ウ繝医Μ縺檎カ壹>縺ヲ縺繧九°縺ゥ縺縺狗「コ隱 + /// @todo 8+3譁蟄励→TewntyOne莠呈鋤繝「繝シ繝峨〒蜍穂ス懊r螟峨∴繧九∋縺 + // ext[i] 繧医j蠕後↓遨コ逋ス莉・螟悶ョ譁蟄励′蟄伜惠縺吶k縺ェ繧臥カ壹¢繧 + for (size_t j = i + 1; j < 3; j++) { + if (ext[j] != ' ') + goto next_ext; + } + // 諡。蠑オ蟄千オらォッ縺ェ繧芽サ「騾∫オゆコ + break; + } + next_ext: + *p++ = c; + } + // 蜈ィ縺ヲ縺ョ譁蟄励r隱ュ縺ソ霎シ繧縺ィ縲√%縺薙〒 i >= 3 縺ィ縺ェ繧 + } + + // 逡ェ蜈オ霑ス蜉 + *p = '\0'; +} + +//=========================================================================== +// +// 繝帙せ繝亥エ繝峨Λ繧、繝 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostDrv::CHostDrv() +{ + // 蛻晄悄蛹 + m_bWriteProtect = FALSE; + m_bEnable = FALSE; + m_capCache.sectors = 0; + m_bVolumeCache = FALSE; + m_szVolumeCache[0] = _T('\0'); + m_szBase[0] = _T('\0'); + m_nRing = 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostDrv::~CHostDrv() +{ + CHostPath* p; + while ((p = (CHostPath*)m_cRing.Next()) != &m_cRing) { + delete p; + ASSERT(m_nRing); + m_nRing--; + } + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + ASSERT(m_nRing == 0); +} + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) +// +//--------------------------------------------------------------------------- +void CHostDrv::Init(const TCHAR* szBase, DWORD nFlag) +{ + ASSERT(this); + ASSERT(szBase); + ASSERT(strlen(szBase) < FILEPATH_MAX); + ASSERT(m_bWriteProtect == FALSE); + ASSERT(m_bEnable == FALSE); + ASSERT(m_capCache.sectors == 0); + ASSERT(m_bVolumeCache == FALSE); + ASSERT(m_szVolumeCache[0] == _T('\0')); + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + ASSERT(m_nRing == 0); + + // 繝代Λ繝。繝シ繧ソ繧貞女縺大叙繧 + if (nFlag & FSFLAG_WRITE_PROTECT) + m_bWriteProtect = TRUE; + strcpy(m_szBase, szBase); + + // 繝吶シ繧ケ繝代せ縺ョ譛蠕後ョ繝代せ蛹コ蛻繧翫槭シ繧ッ繧貞炎髯、縺吶k + /// @warning Unicode蛻ゥ逕ィ譎ゅッ菫ョ豁」縺悟ソ隕 + TCHAR* pClear = NULL; + TCHAR* p = m_szBase; + for (;;) { + TCHAR c = *p; + if (c == _T('\0')) + break; + if (c == _T('/') || c == _T('\\')) { + pClear = p; + } else { + pClear = NULL; + } + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + p++; + if (*p == _T('\0')) + break; + } + p++; + } + if (pClear) + *pClear = _T('\0'); + + // 迥カ諷区峩譁ー + m_bEnable = TRUE; +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::isMediaOffline() +{ + ASSERT(this); + + // 繧ェ繝輔Λ繧、繝ウ迥カ諷九メ繧ァ繝繧ッ + return m_bEnable == FALSE; +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝舌う繝医ョ蜿門セ +// +//--------------------------------------------------------------------------- +BYTE CHostDrv::GetMediaByte() const +{ + ASSERT(this); + + return Human68k::MEDIA_REMOTE; +} + +//--------------------------------------------------------------------------- +// +/// 繝峨Λ繧、繝也憾諷九ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostDrv::GetStatus() const +{ + ASSERT(this); + + return 0x40 | (m_bEnable ? (m_bWriteProtect ? 0x08 : 0) | 0x02 : 0); +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「迥カ諷玖ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostDrv::SetEnable(BOOL bEnable) +{ + ASSERT(this); + + m_bEnable = bEnable; + + if (bEnable == FALSE) { + // 繧ュ繝」繝繧キ繝・豸亥悉 + m_capCache.sectors = 0; + m_bVolumeCache = FALSE; + m_szVolumeCache[0] = _T('\0'); + } +} + +//--------------------------------------------------------------------------- +// +/// 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ +// +//--------------------------------------------------------------------------- +void CHostDrv::GetVolume(TCHAR* szLabel) +{ + ASSERT(this); + ASSERT(szLabel); + ASSERT(m_bEnable); + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ +#ifdef RASCSI + strcpy(m_szVolumeCache, m_szBase); +#else + m_szVolumeCache[0] = _T('\0'); +#endif + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_bVolumeCache = TRUE; + + // 蜀螳ケ繧定サ「騾 + strcpy(szLabel, m_szVolumeCache); +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 +/// +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺繧九懊Μ繝・繝シ繝繝ゥ繝吶Ν諠蝣ア繧定サ「騾√☆繧九 +/// 繧ュ繝」繝繧キ繝・蜀螳ケ縺梧怏蜉ケ縺ェ繧欝RUE繧偵∫┌蜉ケ縺ェ繧宇ALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::GetVolumeCache(TCHAR* szLabel) const +{ + ASSERT(this); + ASSERT(szLabel); + + // 蜀螳ケ繧定サ「騾 + strcpy(szLabel, m_szVolumeCache); + + return m_bVolumeCache; +} + +//--------------------------------------------------------------------------- +// +/// 螳ケ驥上ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostDrv::GetCapacity(Human68k::capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(pCapacity); + ASSERT(m_bEnable); + + DWORD nFree = 0x7FFF8000; + DWORD freearea; + DWORD clusters; + DWORD sectors; + + freearea = 0xFFFF; + clusters = 0xFFFF; + sectors = 64; + + // 繝代Λ繝。繝シ繧ソ遽蝗イ諠ウ螳 + ASSERT(freearea <= 0xFFFF); + ASSERT(clusters <= 0xFFFF); + ASSERT(sectors <= 64); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_capCache.freearea = (WORD)freearea; + m_capCache.clusters = (WORD)clusters; + m_capCache.sectors = (WORD)sectors; + m_capCache.bytes = 512; + + // 蜀螳ケ繧定サ「騾 + memcpy(pCapacity, &m_capCache, sizeof(m_capCache)); + + return nFree; +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i螳ケ驥上r蜿門セ +/// +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺繧句ョケ驥乗ュ蝣ア繧定サ「騾√☆繧九 +/// 繧ュ繝」繝繧キ繝・蜀螳ケ縺梧怏蜉ケ縺ェ繧欝RUE繧偵∫┌蜉ケ縺ェ繧宇ALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::GetCapacityCache(Human68k::capacity_t* pCapacity) const +{ + ASSERT(this); + ASSERT(pCapacity); + + // 蜀螳ケ繧定サ「騾 + memcpy(pCapacity, &m_capCache, sizeof(m_capCache)); + + return m_capCache.sectors != 0; +} + +//--------------------------------------------------------------------------- +// +/// 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::CleanCache() +{ + ASSERT(this); + + Lock(); + for (CHostPath* p = (CHostPath*)m_cRing.Next(); p != &m_cRing;) { + p->Release(); + p = (CHostPath*)p->Next(); + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::CleanCache(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + + Lock(); + CHostPath* p = FindCache(szHumanPath); + if (p) { + p->Restore(); + p->Release(); + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::CleanCacheChild(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + + Lock(); + CHostPath* p = (CHostPath*)m_cRing.Next(); + while (p != &m_cRing) { + if (p->isSameChild(szHumanPath)) + p->Release(); + p = (CHostPath*)p->Next(); + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k +// +//--------------------------------------------------------------------------- +void CHostDrv::DeleteCache(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + + Lock(); + CHostPath* p = FindCache(szHumanPath); + if (p) { + delete p; + ASSERT(m_nRing); + m_nRing--; + } + Unlock(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺後く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°讀懃エ「縺吶k +/// +/// 謇譛峨☆繧九く繝」繧キ繝・繝舌ャ繝輔ぃ縺ョ荳ュ縺九i螳悟ィ荳閾エ縺ァ讀懃エ「縺励∬ヲ九▽縺九l縺ー縺昴ョ蜷咲ァー繧定ソ斐☆縲 +/// 繝輔ぃ繧、繝ォ蜷阪r髯、螟悶@縺ヲ縺翫¥縺薙→縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +CHostPath* CHostDrv::FindCache(const BYTE* szHuman) +{ + ASSERT(this); + ASSERT(szHuman); + + // 謇謖√@縺ヲ縺繧句ィ縺ヲ縺ョ繝輔ぃ繧、繝ォ蜷阪ョ荳ュ縺九i螳悟ィ荳閾エ縺吶k繧ゅョ繧呈、懃エ「 + for (CHostPath* p = (CHostPath*)m_cRing.Next(); p != &m_cRing;) { + if (p->isSameHuman(szHuman)) + return p; + p = (CHostPath*)p->Next(); + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・諠蝣ア繧貞縺ォ縲√帙せ繝亥エ縺ョ蜷咲ァー繧堤佐蠕励☆繧 +/// +/// 繝代せ縺後く繝」繝繧キ繝・縺ォ縺ゅk縺狗「コ隱阪ゅ↑縺代l縺ー繧ィ繝ゥ繝シ縲 +/// 隕九▽縺九▲縺溘く繝」繝繧キ繝・縺ョ譖エ譁ー繝√ぉ繝繧ッ縲よ峩譁ー縺悟ソ隕√↑繧峨お繝ゥ繝シ縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +CHostPath* CHostDrv::CopyCache(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(strlen((const char*)pFiles->GetHumanPath()) < HUMAN68K_PATH_MAX); + + // 繧ュ繝」繝繧キ繝・讀懃エ「 + CHostPath* pPath = FindCache(pFiles->GetHumanPath()); + if (pPath == NULL) + return NULL; // 繧ィ繝ゥ繝シ: 繧ュ繝」繝繧キ繝・縺ェ縺 + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + pPath->Insert(&m_cRing); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー繝√ぉ繝繧ッ + if (pPath->isRefresh()) + return NULL; // 繧ィ繝ゥ繝シ: 繧ュ繝」繝繧キ繝・譖エ譁ー縺悟ソ隕 + + // 繝帙せ繝亥エ縺ョ繝代せ蜷阪r菫晏ュ + pFiles->SetResult(pPath->GetHost()); + + return pPath; +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー縺ョ讒狗ッ峨↓蠢隕√↑諠蝣ア繧偵☆縺ケ縺ヲ蜿門セ励☆繧 +/// +/// 繝輔ぃ繧、繝ォ蜷阪ッ逵∫払蜿ッ閭ス縲(譎ョ騾壹ッ謖螳壹@縺ェ縺) +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +/// 繝吶シ繧ケ繝代せ譛ォ蟆セ縺ォ繝代せ蛹コ蛻繧頑枚蟄励r縺、縺代↑縺繧医≧豕ィ諢上 +/// 繝輔ぃ繧、繝ォ繧「繧ッ繧サ繧ケ縺悟、夂匱縺吶k蜿ッ閭ス諤ァ縺後≠繧九→縺阪ッ縲〃M繧ケ繝ャ繝繝峨ョ蜍穂ス懊r髢句ァ九&縺帙k縲 +/// +/// 菴ソ縺縺九◆: +/// CopyCache()縺励※繧ィ繝ゥ繝シ縺ョ蝣エ蜷医ッMakeCache()縺吶k縲ょソ縺壽ュ」縺励>繝帙せ繝亥エ縺ョ繝代せ縺悟叙蠕励〒縺阪k縲 +/// +/// 繝輔ぃ繧、繝ォ蜷阪→繝代せ蜷阪r縺吶∋縺ヲ蛻髮「縺吶k縲 +/// 荳贋ス阪ョ繧」繝ャ繧ッ繝医Μ縺九i鬆縺ォ縲√く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°縺ゥ縺縺狗「コ隱阪 +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺繧後ー遐エ譽繝√ぉ繝繧ッ縲らエ譽縺励◆蝣エ蜷域悴繧ュ繝」繝繧キ繝・謇ア縺縺ィ縺ェ繧九 +/// 繧ュ繝」繝繧キ繝・縺輔l縺ヲ縺縺ェ縺代l縺ー繧ュ繝」繝繧キ繝・繧呈ァ狗ッ峨 +/// 鬆逡ェ縺ォ縺吶∋縺ヲ縺ョ繝繧」繝ャ繧ッ繝医Μ繝サ繝輔ぃ繧、繝ォ蜷阪↓蟇セ縺励※陦後↑縺邨ゆコ縲 +/// 繧ィ繝ゥ繝シ縺檎匱逕溘@縺溷エ蜷医ッNULL縺ィ縺ェ繧九 +// +//--------------------------------------------------------------------------- +CHostPath* CHostDrv::MakeCache(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(strlen((const char*)pFiles->GetHumanPath()) < HUMAN68K_PATH_MAX); + + ASSERT(m_szBase); + ASSERT(strlen(m_szBase) < FILEPATH_MAX); + + BYTE szHumanPath[HUMAN68K_PATH_MAX]; // 繝ォ繝シ繝医°繧蛾縺ォ繝代せ蜷阪′蜈・繧 + szHumanPath[0] = '\0'; + size_t nHumanPath = 0; + + TCHAR szHostPath[FILEPATH_MAX]; + strcpy(szHostPath, m_szBase); + size_t nHostPath = strlen(szHostPath); + + CHostPath* pPath; + const BYTE* p = pFiles->GetHumanPath(); + for (;;) { + // 繝代せ蛹コ蛻繧翫r霑ス蜉 + if (nHumanPath + 1 >= HUMAN68K_PATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: Human68k繝代せ縺碁聞縺吶℃繧 + szHumanPath[nHumanPath++] = '/'; + szHumanPath[nHumanPath] = '\0'; + if (nHostPath + 1 >= FILEPATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: 繝帙せ繝亥エ縺ョ繝代せ縺碁聞縺吶℃繧 + szHostPath[nHostPath++] = _T('/'); + szHostPath[nHostPath] = _T('\0'); + + // 繝輔ぃ繧、繝ォ縺縺」縺薙>繧後k + BYTE szHumanFilename[24]; // 繝輔ぃ繧、繝ォ蜷埼Κ蛻 + p = SeparateCopyFilename(p, szHumanFilename); + if (p == NULL) + return NULL; // 繧ィ繝ゥ繝シ: 繝輔ぃ繧、繝ォ蜷崎ェュ縺ソ霎シ縺ソ螟ア謨 + size_t n = strlen((const char*)szHumanFilename); + if (nHumanPath + n >= HUMAN68K_PATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: Human68k繝代せ縺碁聞縺吶℃繧 + + // 隧イ蠖薙ヱ繧ケ縺後く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°シ + pPath = FindCache(szHumanPath); + if (pPath == NULL) { + // 繧ュ繝」繝繧キ繝・譛螟ァ謨ー繝√ぉ繝繧ッ + if (m_nRing >= XM6_HOST_DIRENTRY_CACHE_MAX) { + // 譛繧ょ商縺繧ュ繝」繝繧キ繝・繧堤エ譽縺励※蜀榊茜逕ィ + pPath = (CHostPath*)m_cRing.Prev(); + pPath->Clean(); // 蜈ィ繝輔ぃ繧、繝ォ隗」謾セ 譖エ譁ー繝√ぉ繝繧ッ逕ィ繝上Φ繝峨Ν繧りァ」謾セ + } else { + // 譁ー隕冗匳骭イ + pPath = new CHostPath; + ASSERT(pPath); + m_nRing++; + } + pPath->SetHuman(szHumanPath); + pPath->SetHost(szHostPath); + + // 迥カ諷区峩譁ー + pPath->Refresh(); + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー繝√ぉ繝繧ッ + if (pPath->isRefresh()) { + // 迥カ諷区峩譁ー + pPath->Refresh(); + } + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク + pPath->Insert(&m_cRing); + + // 繝輔ぃ繧、繝ォ蜷阪′縺ェ縺代l縺ー縺薙%縺ァ邨ゆコ + if (n == 0) + break; + + // 谺。縺ョ繝代せ繧呈、懃エ「 + // 繝代せ縺ョ騾比クュ縺ェ繧峨ョ繧」繝ャ繧ッ繝医Μ縺九←縺縺狗「コ隱 + const CHostFilename* pFilename; + if (*p != '\0') + pFilename = pPath->FindFilename(szHumanFilename, Human68k::AT_DIRECTORY); + else + pFilename = pPath->FindFilename(szHumanFilename); + if (pFilename == NULL) + return NULL; // 繧ィ繝ゥ繝シ: 騾比クュ縺ョ繝代せ蜷/繝輔ぃ繧、繝ォ蜷阪′隕九▽縺九i縺ェ縺 + + // 繝代せ蜷阪r騾」邨 + strcpy((char*)szHumanPath + nHumanPath, (const char*)szHumanFilename); + nHumanPath += n; + + n = strlen(pFilename->GetHost()); + if (nHostPath + n >= FILEPATH_MAX) + return NULL; // 繧ィ繝ゥ繝シ: 繝帙せ繝亥エ縺ョ繝代せ縺碁聞縺吶℃繧 + strcpy(szHostPath + nHostPath, pFilename->GetHost()); + nHostPath += n; + + // PLEASE CONTINUE + if (*p == '\0') + break; + } + + // 繝帙せ繝亥エ縺ョ繝代せ蜷阪r菫晏ュ + pFiles->SetResult(szHostPath); + + return pPath; +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) +/// +/// 縺ゅi縺九§繧∝ィ縺ヲ縺ョHuman68k逕ィ繝代Λ繝。繝シ繧ソ繧定ィュ螳壹@縺ヲ縺翫¥縺薙→縲 +// +//--------------------------------------------------------------------------- +BOOL CHostDrv::Find(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + + // 謗剃サ門宛蠕。髢句ァ + Lock(); + + // 繝代せ蜷咲佐蠕励♀繧医ウ繧ュ繝」繝繧キ繝・讒狗ッ + CHostPath* pPath = CopyCache(pFiles); + if (pPath == NULL) { + pPath = MakeCache(pFiles); + if (pPath == NULL) { + Unlock(); + CleanCache(); + return FALSE; // 繧ィ繝ゥ繝シ: 繧ュ繝」繝繧キ繝・讒狗ッ牙、ア謨 + } + } + + // 繝帙せ繝亥エ縺ョ繝代せ蜷阪r菫晏ュ + pFiles->SetResult(pPath->GetHost()); + + // 繝代せ蜷阪ョ縺ソ縺ェ繧臥オゆコ + if (pFiles->isPathOnly()) { + Unlock(); + return TRUE; // 豁」蟶ク邨ゆコ: 繝代せ蜷阪ョ縺ソ + } + + // 繝輔ぃ繧、繝ォ蜷肴、懃エ「 + const CHostFilename* pFilename = pFiles->Find(pPath); + if (pFilename == NULL) { + Unlock(); + return FALSE; // 繧ィ繝ゥ繝シ: 繝輔ぃ繧、繝ォ蜷阪′迯イ蠕励〒縺阪∪縺帙s + } + + // Human68k蛛エ縺ョ讀懃エ「邨先棡菫晏ュ + pFiles->SetEntry(pFilename); + + // 繝帙せ繝亥エ縺ョ繝輔Ν繝代せ蜷堺ソ晏ュ + pFiles->AddResult(pFilename->GetHost()); + + // 謗剃サ門宛蠕。邨ゆコ + Unlock(); + + return TRUE; +} + +//=========================================================================== +// +// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝輔ぃ繧、繝ォ蜷 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostFilename::CHostFilename() +{ +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostFilename::SetHost(const TCHAR* szHost) +{ + ASSERT(this); + ASSERT(szHost); + ASSERT(strlen(szHost) < FILEPATH_MAX); + + strcpy(m_szHost, szHost); +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷崎ヲ∫エ繧偵さ繝斐シ +// +//--------------------------------------------------------------------------- +BYTE* CHostFilename::CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast) // static +{ + ASSERT(pWrite); + ASSERT(pFirst); + ASSERT(pLast); + + for (const BYTE* p = pFirst; p < pLast; p++) { + *pWrite++ = *p; + } + + return pWrite; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧貞、画鋤 +/// +/// 縺ゅi縺九§繧ヾetHost()繧貞ョ溯。後@縺ヲ縺翫¥縺薙→縲 +/// 18+3縺ョ蜻ス蜷崎ヲ丞援縺ォ蠕薙▲縺溷錐蜑榊、画鋤繧定。後↑縺縲 +/// 繝輔ぃ繧、繝ォ蜷榊磯ュ縺翫h縺ウ譛ォ蟆セ縺ョ遨コ逋ス縺ッ縲?uman68k縺ァ謇ア縺医↑縺縺溘a閾ェ蜍慕噪縺ォ蜑企勁縺輔l繧九 +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ蜷榊燕驛ィ蛻繧偵√ヵ繧。繧、繝ォ蜷榊、画鋤譎ゅョ諡。蠑オ蟄舌ョ菴咲スョ諠蝣ア繧剃スソ縺」縺ヲ逕滓舌☆繧九 +/// 縺昴ョ蠕後√ヵ繧。繧、繝ォ蜷阪ョ逡ー蟶ク蛻、螳壹r陦後↑縺縲(繧ケ繝壹シ繧ケ8譁蟄励□縺代ョ繝輔ぃ繧、繝ォ蜷阪↑縺ゥ) +/// 繝輔ぃ繧、繝ォ蜷阪ョ驥崎、蛻、螳壹ッ陦後↑繧上↑縺縺ョ縺ァ豕ィ諢上ゅ%繧後i縺ョ蛻、螳壹ッ荳贋ス阪け繝ゥ繧ケ縺ァ陦後↑縺縲 +/// TwentyOne version 1.36c modified +14 patchlevel9莉・髯阪ョ諡。蠑オ蟄占ヲ丞援縺ォ蟇セ蠢懊&縺帙k縲 +// +//--------------------------------------------------------------------------- +void CHostFilename::ConvertHuman(int nCount) +{ + char szHost[FILEPATH_MAX]; + + ASSERT(this); + + // 迚ケ谿翫ョ繧」繝ャ繧ッ繝医Μ蜷阪ョ蝣エ蜷医ッ螟画鋤縺励↑縺 + if (m_szHost[0] == _T('.') && + (m_szHost[1] == _T('\0') || (m_szHost[1] == _T('.') && m_szHost[2] == _T('\0')))) { + strcpy((char*)m_szHuman, m_szHost); /// @warning Unicode譎りヲ∽ソョ豁」 竊 貂 + + m_bCorrect = TRUE; + m_pszHumanLast = m_szHuman + strlen((const char*)m_szHuman); + m_pszHumanExt = m_pszHumanLast; + return; + } + + size_t nMax = 18; // 繝吶シ繧ケ驛ィ蛻(繝吶シ繧ケ蜷阪→諡。蠑オ蟄仙錐)縺ョ繝舌う繝域焚 + DWORD nOption = CFileSys::GetFileOption(); + if (nOption & WINDRV_OPT_CONVERT_LENGTH) + nMax = 8; + + // 繝吶シ繧ケ蜷埼Κ蛻縺ョ陬懈ュ」貅門y + BYTE szNumber[8]; + BYTE* pNumber = NULL; + if (nCount >= 0) { + pNumber = &szNumber[8]; + for (DWORD i = 0; i < 5; i++) { // 譛螟ァ5+1譯√∪縺ァ (繝吶シ繧ケ蜷榊磯ュ2繝舌う繝医ッ蠢縺壽ョ九☆) + int n = nCount % 36; + nMax--; + pNumber--; + *pNumber = (BYTE)(n + (n < 10 ? '0' : 'A' - 10)); + nCount /= 36; + if (nCount == 0) + break; + } + nMax--; + pNumber--; + BYTE c = (BYTE)((nOption >> 24) & 0x7F); + if (c == 0) + c = XM6_HOST_FILENAME_MARK; + *pNumber = c; + } + + // 譁蟄怜、画鋤 + /// @warning Unicode譛ェ蟇セ蠢懊ゅ>縺壹lUnicode縺ョ荳也阜縺ォ鬟ョ縺セ繧後◆譎ゅッ縺薙%縺ァ螟画鋤繧定。後↑縺 竊 貂 + BYTE szHuman[FILEPATH_MAX]; + const BYTE* pFirst = szHuman; + const BYTE* pLast; + const BYTE* pExt = NULL; + + { + strcpy(szHost, m_szHost); + const BYTE* pRead = (const BYTE*)szHost; + BYTE* pWrite = szHuman; + const BYTE* pPeriod = SeparateExt(pRead); + + for (bool bFirst = true;; bFirst = false) { + BYTE c = *pRead++; + switch (c) { + case ' ': + if (nOption & WINDRV_OPT_REDUCED_SPACE) + continue; + if (nOption & WINDRV_OPT_CONVERT_SPACE) + c = '_'; + else if (pWrite == szHuman) + continue; // 蜈磯ュ縺ョ遨コ逋ス縺ッ辟。隕 + break; + case '=': + case '+': + if (nOption & WINDRV_OPT_REDUCED_BADCHAR) + continue; + if (nOption & WINDRV_OPT_CONVERT_BADCHAR) + c = '_'; + break; + case '-': + if (bFirst) { + if (nOption & WINDRV_OPT_REDUCED_HYPHEN) + continue; + if (nOption & WINDRV_OPT_CONVERT_HYPHEN) + c = '_'; + break; + } + if (nOption & WINDRV_OPT_REDUCED_HYPHENS) + continue; + if (nOption & WINDRV_OPT_CONVERT_HYPHENS) + c = '_'; + break; + case '.': + if (pRead - 1 == pPeriod) { // Human68k諡。蠑オ蟄舌ッ萓句、悶→縺吶k + pExt = pWrite; + break; + } + if (bFirst) { + if (nOption & WINDRV_OPT_REDUCED_PERIOD) + continue; + if (nOption & WINDRV_OPT_CONVERT_PERIOD) + c = '_'; + break; + } + if (nOption & WINDRV_OPT_REDUCED_PERIODS) + continue; + if (nOption & WINDRV_OPT_CONVERT_PERIODS) + c = '_'; + break; + } + *pWrite++ = c; + if (c == '\0') + break; + } + + pLast = pWrite - 1; + } + + // 諡。蠑オ蟄占」懈ュ」 + if (pExt) { + // 譛ォ蟆セ縺ョ遨コ逋ス繧貞炎髯、縺吶k + while (pExt < pLast - 1 && *(pLast - 1) == ' ') { + pLast--; + BYTE* p = (BYTE*)pLast; + *p = '\0'; + } + + // 螟画鋤蠕後↓螳滉ス薙′縺ェ縺上↑縺」縺溷エ蜷医ッ蜑企勁 + if (pExt + 1 >= pLast) { + pLast = pExt; + BYTE* p = (BYTE*)pLast; + *p = '\0'; // 蠢オ縺ョ縺溘a + } + } else { + pExt = pLast; + } + + // 逋サ蝣エ莠コ迚ゥ邏ケ莉 + // + // pFirst: 菫コ縺ッ繝ェ繝シ繝繝シ縲ゅヵ繧。繧、繝ォ蜷榊磯ュ + // pCut: 騾夂ァー繝輔ぉ繧、繧ケ縲よ怙蛻昴ョ繝斐Μ繧ェ繝峨ョ蜃コ迴セ菴咲スョ 縺昴ョ蠕後吶シ繧ケ蜷咲オらォッ菴咲スョ縺ィ縺ェ繧 + // pSecond: 繧医♂縺翫∪縺。縺ゥ縺縲ゆソコ讒倥%縺昴槭シ繝峨ャ繧ッ縲よ僑蠑オ蟄仙錐縺ョ髢句ァ倶ス咲スョ縲ゅ□縺九i菴輔 + // pExt: B繝サA繝サ繝舌Λ繧ォ繧ケ縲Human68k諡。蠑オ蟄舌ョ螟ゥ謇阪□縲ゅ〒繧ゅ3譁蟄励h繧企聞縺蜷榊燕縺ッ蜍伜シ√↑縲 + // 譛蠕後ョ繝斐Μ繧ェ繝峨ョ蜃コ迴セ菴咲スョ 隧イ蠖薙@縺ェ縺代l縺ーpLast縺ィ蜷後§蛟、 + // + // 竊菟First 竊菟Stop 竊菟Second 竊 竊菟Ext + // T h i s _ i s _ a . V e r y . L o n g . F i l e n a m e . t x t \0 + // 竊叢Cut 竊 竊叢Cut蛻晄悄菴咲スョ 竊叢Last + // + // 荳願ィ倥ョ蝣エ蜷医∝、画鋤蠕後ッ This.Long.Filename.txt 縺ィ縺ェ繧 + + // 1譁蟄礼岼蛻、螳 + const BYTE* pCut = pFirst; + const BYTE* pStop = pExt - nMax; // 諡。蠑オ蟄仙錐縺ッ譛螟ァ17繝舌う繝医→縺吶k(繝吶シ繧ケ蜷阪r谿九☆) + if (pFirst < pExt) { + pCut++; // 蠢縺1繝舌う繝医ッ繝吶シ繧ケ蜷阪r菴ソ縺 + BYTE c = *pFirst; + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + pCut++; // 繝吶シ繧ケ蜷 譛蟆2繝舌う繝 + pStop++; // 諡。蠑オ蟄仙錐 譛螟ァ16繝舌う繝 + } + } + if (pStop < pFirst) + pStop = pFirst; + + // 繝吶シ繧ケ蜷榊愛螳 + pCut = (BYTE*)strchr((const char*)pCut, '.'); // SJIS2繝舌う繝育岼縺ッ蠢縺0x40莉・荳翫↑縺ョ縺ァ蝠城。後↑縺 + if (pCut == NULL) + pCut = pLast; + if ((size_t)(pCut - pFirst) > nMax) + pCut = pFirst + nMax; // 蠕後⊇縺ゥSJIS2繝舌う繝亥愛螳/陬懈ュ」繧定。後↑縺 縺薙%縺ァ蛻、螳壹@縺ヲ縺ッ縺縺代↑縺 + + // 諡。蠑オ蟄仙錐蛻、螳 + const BYTE* pSecond = pExt; + const BYTE* p; + for (p = pExt - 1; pStop < p; p--) { + if (*p == '.') + pSecond = p; // SJIS2繝舌う繝育岼縺ッ蠢縺0x40莉・荳翫↑縺ョ縺ァ蝠城。後↑縺 + } + + // 繝吶シ繧ケ蜷阪r遏ュ邵ョ + size_t nExt = pExt - pSecond; // 諡。蠑オ蟄仙錐驛ィ蛻縺ョ髟キ縺 + if ((size_t)(pCut - pFirst) + nExt > nMax) + pCut = pFirst + nMax - nExt; + // 2繝舌う繝域枚蟄励ョ騾比クュ縺ェ繧峨&繧峨↓遏ュ邵ョ + for (p = pFirst; p < pCut; p++) { + BYTE c = *p; + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + p++; + if (p >= pCut) { + pCut--; + break; + } + } + } + + // 蜷榊燕縺ョ邨仙粋 + BYTE* pWrite = m_szHuman; + pWrite = CopyName(pWrite, pFirst, pCut); // 繝吶シ繧ケ蜷阪r霆「騾 + if (pNumber) + pWrite = CopyName(pWrite, pNumber, &szNumber[8]); // 陬懈ュ」譁蟄励r霆「騾 + pWrite = CopyName(pWrite, pSecond, pExt); // 諡。蠑オ蟄仙錐繧定サ「騾 + m_pszHumanExt = pWrite; // 諡。蠑オ蟄蝉ス咲スョ菫晏ュ + pWrite = CopyName(pWrite, pExt, pLast); // Human68k諡。蠑オ蟄舌r霆「騾 + m_pszHumanLast = pWrite; // 邨らォッ菴咲スョ菫晏ュ + *pWrite = '\0'; + + // 螟画鋤邨先棡縺ョ遒コ隱 + m_bCorrect = TRUE; + + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′蟄伜惠縺励↑縺代l縺ー荳榊粋譬シ + if (m_pszHumanExt <= m_szHuman) + m_bCorrect = FALSE; + + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′1譁蟄嶺サ・荳翫〒縺九▽遨コ逋ス縺ァ邨ゆコ縺励※縺繧後ー荳榊粋譬シ + // 繝輔ぃ繧、繝ォ蜷肴悽菴薙′8譁蟄嶺サ・荳翫ョ蝣エ蜷医∫炊隲紋ク翫ッ遨コ逋ス縺ァ縺ョ邨ゆコ縺瑚。ィ迴セ蜿ッ + // 閭ス縺縺後?uman68k縺ァ縺ッ豁」縺励¥謇ア縺医↑縺縺溘a縲√%繧後b荳榊粋譬シ縺ィ縺吶k + else if (m_pszHumanExt[-1] == ' ') + m_bCorrect = FALSE; + + // 螟画鋤邨先棡縺檎音谿翫ョ繧」繝ャ繧ッ繝医Μ蜷阪→蜷後§縺ェ繧我ク榊粋譬シ + if (m_szHuman[0] == '.' && + (m_szHuman[1] == '\0' || (m_szHuman[1] == '.' && m_szHuman[2] == '\0'))) + m_bCorrect = FALSE; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧定、陬ス +/// +/// 繝輔ぃ繧、繝ォ蜷埼Κ蛻縺ョ諠蝣ア繧定、陬ス縺励,onvertHuman()逶ク蠖薙ョ蛻晄悄蛹門虚菴懊r陦後↑縺縲 +// +//--------------------------------------------------------------------------- +void CHostFilename::CopyHuman(const BYTE* szHuman) +{ + ASSERT(this); + ASSERT(szHuman); + ASSERT(strlen((const char*)szHuman) < 23); + + strcpy((char*)m_szHuman, (const char*)szHuman); + m_bCorrect = TRUE; + m_pszHumanLast = m_szHuman + strlen((const char*)m_szHuman); + m_pszHumanExt = (BYTE*)SeparateExt(m_szHuman); +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 +/// +/// ConvertHuman()縺ァ險ュ螳壽ク医∩縺ョ繝輔ぃ繧、繝ォ蜷阪r繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ォ蜿肴丐縺吶k縲 +// +//--------------------------------------------------------------------------- +void CHostFilename::SetEntryName() +{ + ASSERT(this); + + // 繝輔ぃ繧、繝ォ蜷崎ィュ螳 + BYTE* p = m_szHuman; + size_t i; + for (i = 0; i < 8; i++) { + if (p < m_pszHumanExt) + m_dirHuman.name[i] = *p++; + else + m_dirHuman.name[i] = ' '; + } + + for (i = 0; i < 10; i++) { + if (p < m_pszHumanExt) + m_dirHuman.add[i] = *p++; + else + m_dirHuman.add[i] = '\0'; + } + + if (*p == '.') + p++; + for (i = 0; i < 3; i++) { + BYTE c = *p; + if (c) + p++; + m_dirHuman.ext[i] = c; + } +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー縺悟刈蟾・縺輔l縺溘°隱ソ譟サ +// +//--------------------------------------------------------------------------- +BOOL CHostFilename::isReduce() const +{ + ASSERT(this); + + return strcmp((LPTSTR)m_szHost, (const char*)m_szHuman) != 0; /// @warning Unicode譎りヲ∽ソョ豁」 竊 貂 +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ螻樊ァ蛻、螳 +// +//--------------------------------------------------------------------------- +BOOL CHostFilename::CheckAttribute(DWORD nHumanAttribute) const +{ + ASSERT(this); + + BYTE nAttribute = m_dirHuman.attr; + if ((nAttribute & (Human68k::AT_ARCHIVE | Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) == 0) + nAttribute |= Human68k::AT_ARCHIVE; + + return nAttribute & nHumanAttribute; +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝輔ぃ繧、繝ォ蜷阪°繧画僑蠑オ蟄舌r蛻髮「 +// +//--------------------------------------------------------------------------- +const BYTE* CHostFilename::SeparateExt(const BYTE* szHuman) // static +{ + // 繝輔ぃ繧、繝ォ蜷阪ョ髟キ縺輔r迯イ蠕 + size_t nLength = strlen((const char*)szHuman); + const BYTE* pFirst = szHuman; + const BYTE* pLast = pFirst + nLength; + + // Human68k諡。蠑オ蟄舌ョ菴咲スョ繧堤「コ隱 + const BYTE* pExt = (BYTE*)strrchr((const char*)pFirst, '.'); // SJIS2繝舌う繝育岼縺ッ蠢縺0x40莉・荳翫↑縺ョ縺ァ蝠城。後↑縺 + if (pExt == NULL) + pExt = pLast; + // 繝輔ぃ繧、繝ォ蜷阪′20ス22譁蟄励°縺、19譁蟄礼岼縺'.'縺九▽'.'縺ァ邨ゆコ縺ィ縺縺繝代ち繝シ繝ウ繧堤音蛻・謇ア縺縺吶k + if (20 <= nLength && nLength <= 22 && pFirst[18] == '.' && pFirst[nLength - 1] == '.') + pExt = pFirst + 18; + // 諡。蠑オ蟄舌ョ譁蟄玲焚繧定ィ育ョ (-1:縺ェ縺 0:繝斐Μ繧ェ繝峨□縺 1ス3:Human68k諡。蠑オ蟄 4莉・荳:諡。蠑オ蟄仙錐) + size_t nExt = pLast - pExt - 1; + // '.' 縺梧枚蟄怜怜磯ュ莉・螟悶↓蟄伜惠縺励※縲√°縺、1ス3譁蟄励ョ蝣エ蜷医ョ縺ソ諡。蠑オ蟄舌→縺ソ縺ェ縺 + if (pExt == pFirst || nExt < 1 || nExt > 3) + pExt = pLast; + + return pExt; +} + +//=========================================================================== +// +// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝代せ蜷 +// +//=========================================================================== + +DWORD CHostPath::g_nId; ///< 隴伜挨ID逕滓千畑繧ォ繧ヲ繝ウ繧ソ + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostPath::CHostPath() +{ + m_bRefresh = TRUE; + +#ifdef _DEBUG + // 蠢縺壼、縺梧峩譁ー縺輔l繧九ョ縺ァ蛻晄悄蛹紋ク崎ヲ (繝繝舌ャ繧ー譎ゅョ蛻晄悄蜍穂ス懃「コ隱咲畑) + m_nId = 0; +#endif // _DEBUG +} + +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostPath::~CHostPath() +{ + Clean(); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷埼伜沺遒コ菫 +/// +/// 縺サ縺ィ繧薙←縺ョ繧ア繝シ繧ケ縺ァ縺ッ縲√帙せ繝亥エ繝輔ぃ繧、繝ォ蜷阪ョ髟キ縺輔ッ繝舌ャ繝輔ぃ譛螟ァ髟キ縺ォ +/// 豈斐∋縺ヲ髱槫クク縺ォ遏ュ縺縲ゅ&繧峨↓繝輔ぃ繧、繝ォ蜷阪ッ螟ァ驥上↓逕滓舌&繧後k蜿ッ閭ス諤ァ縺後≠繧九 +/// 縺昴ョ縺溘a譁蟄玲焚縺ォ蠢懊§縺溷庄螟蛾聞縺ァ遒コ菫昴☆繧九 +// +//--------------------------------------------------------------------------- +CHostPath::ring_t* CHostPath::Alloc(size_t nLength) // static +{ + ASSERT(nLength < FILEPATH_MAX); + + size_t n = offsetof(ring_t, f) + CHostFilename::Offset() + (nLength + 1) * sizeof(TCHAR); + ring_t* p = (ring_t*)malloc(n); + ASSERT(p); + + p->r.Init(); // 讎帛錐縺ッ螟ァ荳亥、ォ縺ァ縺呻シ + + return p; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ蜷埼伜沺隗」謾セ +// +//--------------------------------------------------------------------------- +void CHostPath::Free(ring_t* pRing) // static +{ + ASSERT(pRing); + + pRing->~ring_t(); + free(pRing); +} + +//--------------------------------------------------------------------------- +// +/// 蜀榊茜逕ィ縺ョ縺溘a縺ョ蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CHostPath::Clean() +{ + ASSERT(this); + + Release(); + + // 蜈ィ繝輔ぃ繧、繝ォ蜷阪r隗」謾セ + ring_t* p; + while ((p = (ring_t*)m_cRing.Next()) != (ring_t*)&m_cRing) { + Free(p); + } +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 +// +//--------------------------------------------------------------------------- +void CHostPath::SetHuman(const BYTE* szHuman) +{ + ASSERT(this); + ASSERT(szHuman); + ASSERT(strlen((const char*)szHuman) < HUMAN68K_PATH_MAX); + + strcpy((char*)m_szHuman, (const char*)szHuman); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 +// +//--------------------------------------------------------------------------- +void CHostPath::SetHost(const TCHAR* szHost) +{ + ASSERT(this); + ASSERT(szHost); + ASSERT(strlen(szHost) < FILEPATH_MAX); + + strcpy(m_szHost, szHost); +} + +//--------------------------------------------------------------------------- +// +/// 譁蟄怜玲ッ碑シ (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) +// +//--------------------------------------------------------------------------- +int CHostPath::Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast) +{ + ASSERT(pFirst); + ASSERT(pLast); + ASSERT(pBufFirst); + ASSERT(pBufLast); + + // 譁蟄玲ッ碑シ + BOOL bSkip0 = FALSE; + BOOL bSkip1 = FALSE; + for (const BYTE* p = pFirst; p < pLast; p++) { + // 1譁蟄苓ェュ縺ソ霎シ縺ソ + BYTE c = *p; + BYTE d = '\0'; + if (pBufFirst < pBufLast) + d = *pBufFirst++; + + // 豈碑シ縺ョ縺溘a縺ョ譁蟄苓」懈ュ」 + if (bSkip0 == FALSE) { + if (bSkip1 == FALSE) { // c繧E繧1繝舌う繝育岼 + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip0 = TRUE; + } + if ((0x80 <= d && d <= 0x9F) || 0xE0 <= d) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip1 = TRUE; + } + if (c == d) + continue; // 鬮倡「コ邇縺ァ蛻、螳壼ョ御コ縺吶k + if ((CFileSys::GetFileOption() & WINDRV_OPT_ALPHABET) == 0) { + if ('A' <= c && c <= 'Z') + c += 'a' - 'A'; // 蟆乗枚蟄怜喧 + if ('A' <= d && d <= 'Z') + d += 'a' - 'A'; // 蟆乗枚蟄怜喧 + } + } else { // c縺縺代′1繝舌う繝育岼 + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip0 = TRUE; + } + bSkip1 = FALSE; + } + } else { + if (bSkip1 == FALSE) { // d縺縺代′1繝舌う繝育岼 + bSkip0 = FALSE; + if ((0x80 <= d && d <= 0x9F) || 0xE0 <= d) { // 蜴ウ蟇縺ォ縺ッ 0x81ス0x9F 0xE0ス0xEF + bSkip1 = TRUE; + } + } else { // c繧E繧2繝舌う繝育岼 + bSkip0 = FALSE; + bSkip1 = FALSE; + } + } + + // 豈碑シ + if (c == d) + continue; + if (c == '?') + continue; + return 1; + } + if (pBufFirst < pBufLast) + return 2; + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k +// +//--------------------------------------------------------------------------- +BOOL CHostPath::isSameHuman(const BYTE* szHuman) const +{ + ASSERT(this); + ASSERT(szHuman); + + // 譁蟄玲焚險育ョ + size_t nLength = strlen((const char*)m_szHuman); + size_t n = strlen((const char*)szHuman); + + // 譁蟄玲焚繝√ぉ繝繧ッ + if (nLength != n) + return FALSE; + + // Human68k繝代せ蜷阪ョ豈碑シ + return Compare(m_szHuman, m_szHuman + nLength, szHuman, szHuman + n) == 0; +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k +// +//--------------------------------------------------------------------------- +BOOL CHostPath::isSameChild(const BYTE* szHuman) const +{ + ASSERT(this); + ASSERT(szHuman); + + // 譁蟄玲焚險育ョ + size_t nLength = strlen((const char*)m_szHuman); + size_t n = strlen((const char*)szHuman); + + // 譁蟄玲焚繝√ぉ繝繧ッ + if (nLength < n) + return FALSE; + + // Human68k繝代せ蜷阪ョ豈碑シ + return Compare(m_szHuman, m_szHuman + n, szHuman, szHuman + n) == 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 +/// +/// 謇譛峨☆繧九く繝」繧キ繝・繝舌ャ繝輔ぃ縺ョ荳ュ縺九i讀懃エ「縺励∬ヲ九▽縺九l縺ー縺昴ョ蜷咲ァー繧定ソ斐☆縲 +/// 繝代せ蜷阪r髯、螟悶@縺ヲ縺翫¥縺薙→縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +const CHostFilename* CHostPath::FindFilename(const BYTE* szHuman, DWORD nHumanAttribute) const +{ + ASSERT(this); + ASSERT(szHuman); + + // 譁蟄玲焚險育ョ + const BYTE* pFirst = szHuman; + size_t nLength = strlen((const char*)pFirst); + const BYTE* pLast = pFirst + nLength; + + // 謇謖√@縺ヲ縺繧句ィ縺ヲ縺ョ繝輔ぃ繧、繝ォ蜷阪ョ荳ュ縺九i螳悟ィ荳閾エ縺吶k繧ゅョ繧呈、懃エ「 + const ring_t* p = (ring_t*)m_cRing.Next(); + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + // 螻樊ァ繝√ぉ繝繧ッ + if (p->f.CheckAttribute(nHumanAttribute) == 0) + continue; + // 譁蟄玲焚險育ョ + const BYTE* pBufFirst = p->f.GetHuman(); + const BYTE* pBufLast = p->f.GetHumanLast(); + size_t nBufLength = pBufLast - pBufFirst; + // 譁蟄玲焚繝√ぉ繝繧ッ + if (nLength != nBufLength) + continue; + // 繝輔ぃ繧、繝ォ蜷阪メ繧ァ繝繧ッ + if (Compare(pFirst, pLast, pBufFirst, pBufLast) == 0) + return &p->f; + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) +/// +/// 謇譛峨☆繧九ヰ繝繝輔ぃ縺ョ荳ュ縺九i讀懃エ「縺励∬ヲ九▽縺九l縺ー縺昴ョ蜷咲ァー繧定ソ斐☆縲 +/// 繝代せ蜷阪r髯、螟悶@縺ヲ縺翫¥縺薙→縲 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +const CHostFilename* CHostPath::FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const +{ + ASSERT(this); + ASSERT(szHuman); + ASSERT(pFind); + + // 讀懃エ「繝輔ぃ繧、繝ォ蜷阪r譛ャ菴薙→Human68k諡。蠑オ蟄舌↓蛻縺代k + const BYTE* pFirst = szHuman; + const BYTE* pLast = pFirst + strlen((const char*)pFirst); + const BYTE* pExt = CHostFilename::SeparateExt(pFirst); + + // 髢句ァ句慍轤ケ縺ク遘サ蜍 + const ring_t* p = (ring_t*)m_cRing.Next(); + if (pFind->count > 0) { + if (pFind->id == m_nId) { + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺悟酔荳縺ェ繧峨∝燕蝗槭ョ菴咲スョ縺九i蜊ウ邯咏カ + p = pFind->pos; + } else { + // 髢句ァ句慍轤ケ繧偵ョ繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜀螳ケ縺九i讀懃エ「縺吶k + DWORD n = 0; + for (;; p = (ring_t*)p->r.Next()) { + if (p == (ring_t*)&m_cRing) { + // 蜷御ク繧ィ繝ウ繝医Μ縺瑚ヲ九▽縺九i縺ェ縺九▲縺溷エ蜷医∝屓謨ー縺九i謗ィ螳 (蠢オ縺ョ縺溘a) + p = (ring_t*)m_cRing.Next(); + n = 0; + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + if (n >= pFind->count) + break; + n++; + } + break; + } + if (p->f.isSameEntry(&pFind->entry)) { + // 蜷御ク繧ィ繝ウ繝医Μ繧堤匱隕 + pFind->count = n; + break; + } + n++; + } + } + } + + // 繝輔ぃ繧、繝ォ讀懃エ「 + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + pFind->count++; + + // 螻樊ァ繝√ぉ繝繧ッ + if (p->f.CheckAttribute(nHumanAttribute) == 0) + continue; + + // 繝輔ぃ繧、繝ォ蜷阪r譛ャ菴薙→Human68k諡。蠑オ蟄舌↓蛻縺代k + const BYTE* pBufFirst = p->f.GetHuman(); + const BYTE* pBufLast = p->f.GetHumanLast(); + const BYTE* pBufExt = p->f.GetHumanExt(); + + // 譛ャ菴捺ッ碑シ + if (Compare(pFirst, pExt, pBufFirst, pBufExt)) + continue; + + // Human68k諡。蠑オ蟄先ッ碑シ + // 諡。蠑オ蟄.???縺ョ蝣エ蜷医ッ縲?uman68k諡。蠑オ蟄舌ョ繝斐Μ繧ェ繝峨↑縺励↓繧ゅ槭ャ繝√&縺帙k + if (strcmp((const char*)pExt, ".???") == 0 || + Compare(pExt, pLast, pBufExt, pBufLast) == 0) { + // 谺。縺ョ蛟呵」懊ョ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜀螳ケ繧定ィ倬鹸 + const ring_t* pNext = (ring_t*)p->r.Next(); + pFind->id = m_nId; + pFind->pos = pNext; + if (pNext != (ring_t*)&m_cRing) + memcpy(&pFind->entry, pNext->f.GetEntry(), sizeof(pFind->entry)); + else + memset(&pFind->entry, 0, sizeof(pFind->entry)); + return &p->f; + } + } + + pFind->id = m_nId; + pFind->pos = p; + memset(&pFind->entry, 0, sizeof(pFind->entry)); + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ螟画峩縺瑚。後↑繧上l縺溘°遒コ隱 +// +//--------------------------------------------------------------------------- +BOOL CHostPath::isRefresh() +{ + ASSERT(this); + + return m_bRefresh; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜀肴ァ区 +/// +/// 縺薙%縺ァ蛻昴a縺ヲ縲√帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ隕ウ貂ャ縺瑚。後↑繧上l繧九 +/// 蠢縺壻ク贋ス阪〒謗剃サ門宛蠕。繧定。後↑縺縺薙→縲 +// +//--------------------------------------------------------------------------- +void CHostPath::Refresh() +{ + ASSERT(this); + ASSERT(strlen(m_szHost) + 22 < FILEPATH_MAX); + + // 繧ソ繧、繝繧ケ繧ソ繝ウ繝嶺ソ晏ュ + Backup(); + + TCHAR szPath[FILEPATH_MAX]; + strcpy(szPath, m_szHost); + + // 譖エ譁ー繝輔Λ繧ー螟画峩 + m_bRefresh = FALSE; + + // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ繧剃ソ晏ュ + CRing cRingBackup; + m_cRing.InsertRing(&cRingBackup); + + // 繝輔ぃ繧、繝ォ蜷咲匳骭イ + /// @todo 繝輔ぃ繧、繝ォ驥崎、蜃ヲ逅繧偵帙せ繝亥エAPI繧堤オ檎罰縺帙★縺ォ蜈ィ縺ヲ閾ェ蜑阪〒蜃ヲ逅縺吶k縲 + BOOL bUpdate = FALSE; + DIR* pd = NULL; + for (DWORD i = 0; i < XM6_HOST_DIRENTRY_FILE_MAX; i++) { + TCHAR szFilename[FILEPATH_MAX]; + if (pd == NULL) { + pd = opendir(S2U(szPath)); + if (pd == NULL) + break; + } + // 繝輔ぃ繧、繝ォ蜷阪r迯イ蠕 + struct dirent* pe = readdir(pd); + if (pe == NULL) + break; + strcpy(szFilename, U2S(pe->d_name)); + + // 繝輔ぃ繧、繝ォ蜷埼伜沺遒コ菫 + ring_t* pRing = Alloc(strlen(szFilename)); + CHostFilename* pFilename = &pRing->f; + pFilename->SetHost(szFilename); + + // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ縺ォ隧イ蠖薙☆繧九ヵ繧。繧、繝ォ蜷阪′縺ゅl縺ー縺昴ョHuman68k蜷咲ァー繧貞━蜈医☆繧 + ring_t* pCache = (ring_t*)cRingBackup.Next(); + for (;;) { + if (pCache == (ring_t*)&cRingBackup) { + pCache = NULL; // 隧イ蠖薙☆繧九お繝ウ繝医Μ縺ェ縺 + bUpdate = TRUE; // 譁ー隕上お繝ウ繝医Μ縺ィ遒コ螳 + pFilename->ConvertHuman(); + break; + } + if (strcmp(pFilename->GetHost(), pCache->f.GetHost()) == 0) { + pFilename->CopyHuman(pCache->f.GetHuman()); // Human68k蜷咲ァー縺ョ繧ウ繝斐シ + break; + } + pCache = (ring_t*)pCache->r.Next(); + } + + // 譁ー隕上お繝ウ繝医Μ縺ョ蝣エ蜷医ッ繝輔ぃ繧、繝ォ蜷埼崎、繧偵メ繧ァ繝繧ッ縺吶k + // 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷阪°繧牙、画峩縺後≠縺」縺溘°縲?uman68k縺ァ陦ィ迴セ縺ァ縺阪↑縺繝輔ぃ繧、繝ォ蜷阪ョ蝣エ蜷医ッ + // 莉・荳九ョ繝√ぉ繝繧ッ繧貞ィ縺ヲ繝代せ縺吶k繝輔ぃ繧、繝ォ蜷阪r譁ー縺溘↓逕滓舌☆繧 + // 繝サ豁」縺励>繝輔ぃ繧、繝ォ蜷阪〒縺ゅk縺薙→ + // 繝サ驕主悉縺ョ繧ィ繝ウ繝医Μ縺ォ蜷悟錐縺ョ繧ゅョ縺悟ュ伜惠縺励↑縺縺薙→ + // 繝サ蜷悟錐縺ョ螳溘ヵ繧。繧、繝ォ蜷阪′蟄伜惠縺励↑縺縺薙→ + if (pFilename->isReduce() || !pFilename->isCorrect()) { // 繝輔ぃ繧、繝ォ蜷榊、画峩縺悟ソ隕√°遒コ隱 + for (DWORD n = 0; n < XM6_HOST_FILENAME_PATTERN_MAX; n++) { + // 豁」縺励>繝輔ぃ繧、繝ォ蜷阪°縺ゥ縺縺狗「コ隱 + if (pFilename->isCorrect()) { + // 驕主悉縺ョ繧ィ繝ウ繝医Μ縺ィ荳閾エ縺吶k縺狗「コ隱 + const CHostFilename* pCheck = FindFilename(pFilename->GetHuman()); + if (pCheck == NULL) { + // 荳閾エ縺吶k繧ゅョ縺後↑縺代l縺ー縲∝ョ溘ヵ繧。繧、繝ォ縺悟ュ伜惠縺吶k縺狗「コ隱 + strcpy(szPath, m_szHost); + strcat(szPath, (const char*)pFilename->GetHuman()); /// @warning Unicode譎りヲ∽ソョ豁」 竊 貂 + struct stat sb; + if (stat(S2U(szPath), &sb)) + break; // 蛻ゥ逕ィ蜿ッ閭ス繝代ち繝シ繝ウ繧堤匱隕 + } + } + // 譁ー縺励>蜷榊燕繧堤函謌 + pFilename->ConvertHuman(n); + } + } + + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜷咲ァー + pFilename->SetEntryName(); + + // 諠蝣ア蜿門セ + strcpy(szPath, m_szHost); + strcat(szPath, U2S(pe->d_name)); + + struct stat sb; + if (stat(S2U(szPath), &sb)) + continue; + + // 螻樊ァ + BYTE nHumanAttribute = Human68k::AT_ARCHIVE; + if (S_ISDIR(sb.st_mode)) + nHumanAttribute = Human68k::AT_DIRECTORY; + if ((sb.st_mode & 0200) == 0) + nHumanAttribute |= Human68k::AT_READONLY; + pFilename->SetEntryAttribute(nHumanAttribute); + + // 繧オ繧、繧コ + DWORD nHumanSize = (DWORD)sb.st_size; + pFilename->SetEntrySize(nHumanSize); + + // 譌・莉俶凾蛻サ + WORD nHumanDate = 0; + WORD nHumanTime = 0; + struct tm* pt = localtime(&sb.st_mtime); + if (pt) { + nHumanDate = (WORD)(((pt->tm_year - 80) << 9) | ((pt->tm_mon + 1) << 5) | pt->tm_mday); + nHumanTime = (WORD)((pt->tm_hour << 11) | (pt->tm_min << 5) | (pt->tm_sec >> 1)); + } + pFilename->SetEntryDate(nHumanDate); + pFilename->SetEntryTime(nHumanTime); + + // 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ險ュ螳 + pFilename->SetEntryCluster(0); + + // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ縺ィ豈碑シ + if (pCache) { + if (pCache->f.isSameEntry(pFilename->GetEntry())) { + Free(pRing); // 莉雁屓菴懈舌@縺溘お繝ウ繝医Μ縺ッ遐エ譽縺 + pRing = pCache; // 莉・蜑阪ョ繧ュ繝」繝繧キ繝・蜀螳ケ繧剃スソ縺 + } else { + Free(pCache); // 谺。蝗槭ョ讀懃エ「蟇セ雎。縺九i髯、螟 + bUpdate = TRUE; // 荳閾エ縺励↑縺代l縺ー譖エ譁ー縺ゅj + } + } + + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク霑ス蜉 + pRing->r.InsertTail(&m_cRing); + } + + closedir(pd); + + // 谿句ュ倥☆繧九く繝」繝繧キ繝・蜀螳ケ繧貞炎髯、 + ring_t* p; + while ((p = (ring_t*)cRingBackup.Next()) != (ring_t*)&cRingBackup) { + bUpdate = TRUE; // 蜑企勁縺ォ繧医▲縺ヲ繧ィ繝ウ繝医Μ謨ー縺ョ貂帛ー代′蛻、譏 + Free(p); + } + + // 譖エ譁ー縺瑚。後↑繧上l縺溘i隴伜挨ID繧貞、画峩 + if (bUpdate) + m_nId = ++g_nId; + // ASSERT(m_nId); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r菫晏ュ +// +//--------------------------------------------------------------------------- +void CHostPath::Backup() +{ + ASSERT(this); + ASSERT(m_szHost); + ASSERT(strlen(m_szHost) < FILEPATH_MAX); + + TCHAR szPath[FILEPATH_MAX]; + strcpy(szPath, m_szHost); + size_t len = strlen(szPath); + + m_tBackup = 0; + if (len > 1) { // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蝣エ蜷医ッ菴輔b縺励↑縺 + len--; + ASSERT(szPath[len] == _T('/')); + szPath[len] = _T('\0'); + struct stat sb; + if (stat(S2U(szPath), &sb) == 0) + m_tBackup = sb.st_mtime; + } +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r蠕ゥ蜈 +// +//--------------------------------------------------------------------------- +void CHostPath::Restore() const +{ + ASSERT(this); + ASSERT(m_szHost); + ASSERT(strlen(m_szHost) < FILEPATH_MAX); + + TCHAR szPath[FILEPATH_MAX]; + strcpy(szPath, m_szHost); + size_t len = strlen(szPath); + + if (m_tBackup) { + ASSERT(len); + len--; + ASSERT(szPath[len] == _T('/')); + szPath[len] = _T('\0'); + + struct utimbuf ut; + ut.actime = m_tBackup; + ut.modtime = m_tBackup; + utime(szPath, &ut); + } +} + +//--------------------------------------------------------------------------- +// +/// 譖エ譁ー +// +//--------------------------------------------------------------------------- +void CHostPath::Release() +{ + ASSERT(this); + + m_bRefresh = TRUE; +} + +//=========================================================================== +// +// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ邂。逅 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CHostEntry::CHostEntry() +{ + for (size_t n = 0; n < DriveMax; n++) { + m_pDrv[n] = NULL; + } + + m_nTimeout = 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostEntry::~CHostEntry() +{ + Clean(); + +#ifdef _DEBUG + // 繧ェ繝悶ず繧ァ繧ッ繝育「コ隱 + for (size_t n = 0; n < DriveMax; n++) { + ASSERT(m_pDrv[n] == NULL); + } +#endif // _DEBUG +} + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) +// +//--------------------------------------------------------------------------- +void CHostEntry::Init() +{ + ASSERT(this); + +#ifdef _DEBUG + // 繧ェ繝悶ず繧ァ繧ッ繝育「コ隱 + for (size_t n = 0; n < DriveMax; n++) { + ASSERT(m_pDrv[n] == NULL); + } +#endif // _DEBUG +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) +// +//--------------------------------------------------------------------------- +void CHostEntry::Clean() +{ + ASSERT(this); + + // 繧ェ繝悶ず繧ァ繧ッ繝亥炎髯、 + for (size_t n = 0; n < DriveMax; n++) { + delete m_pDrv[n]; + m_pDrv[n] = NULL; + } +} + +//--------------------------------------------------------------------------- +// +/// 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCache() +{ + ASSERT(this); + + for (size_t i = 0; i < DriveMax; i++) { + if (m_pDrv[i]) + m_pDrv[i]->CleanCache(); + } + + CHostPath::InitId(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝ヲ繝九ャ繝医ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCache(DWORD nUnit) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->CleanCache(); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCache(DWORD nUnit, const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->CleanCache(szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->CleanCacheChild(szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k +// +//--------------------------------------------------------------------------- +void CHostEntry::DeleteCache(DWORD nUnit, const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->DeleteCache(szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::Find(DWORD nUnit, CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->Find(pFiles); +} + +void CHostEntry::ShellNotify(DWORD, const TCHAR*) {} + +//--------------------------------------------------------------------------- +// +/// 繝峨Λ繧、繝冶ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostEntry::SetDrv(DWORD nUnit, CHostDrv* pDrv) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit] == NULL); + + m_pDrv[nUnit] = pDrv; +} + +//--------------------------------------------------------------------------- +// +/// 譖ク縺崎セシ縺ソ遖∵ュ「縺具シ +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::isWriteProtect(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->isWriteProtect(); +} + +//--------------------------------------------------------------------------- +// +/// 繧「繧ッ繧サ繧ケ蜿ッ閭ス縺具シ +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::isEnable(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->isEnable(); +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::isMediaOffline(DWORD nUnit) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->isMediaOffline(); +} + +//--------------------------------------------------------------------------- +// +/// 繝。繝繧」繧「繝舌う繝医ョ蜿門セ +// +//--------------------------------------------------------------------------- +BYTE CHostEntry::GetMediaByte(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetMediaByte(); +} + +//--------------------------------------------------------------------------- +// +/// 繝峨Λ繧、繝也憾諷九ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostEntry::GetStatus(DWORD nUnit) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetStatus(); +} + +//--------------------------------------------------------------------------- +// +/// 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ +// +//--------------------------------------------------------------------------- +void CHostEntry::GetVolume(DWORD nUnit, TCHAR* szLabel) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + m_pDrv[nUnit]->GetVolume(szLabel); +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetVolumeCache(szLabel); +} + +//--------------------------------------------------------------------------- +// +/// 螳ケ驥上ョ蜿門セ +// +//--------------------------------------------------------------------------- +DWORD CHostEntry::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetCapacity(pCapacity); +} + +//--------------------------------------------------------------------------- +// +/// 繧ュ繝」繝繧キ繝・縺九i繧ッ繝ゥ繧ケ繧ソ繧オ繧、繧コ繧貞叙蠕 +// +//--------------------------------------------------------------------------- +BOOL CHostEntry::GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const +{ + ASSERT(this); + ASSERT(nUnit < DriveMax); + ASSERT(m_pDrv[nUnit]); + + return m_pDrv[nUnit]->GetCapacityCache(pCapacity); +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝輔Ν繝代せ蜷阪°繧牙磯ュ縺ョ隕∫エ繧貞髮「繝サ繧ウ繝斐シ +/// +/// Human68k繝輔Ν繝代せ蜷阪ョ蜈磯ュ縺ョ隕∫エ繧偵ヱ繧ケ蛹コ蛻繧頑枚蟄励r髯、螟悶@縺ヲ蜿門セ励☆繧九 +/// 譖ク縺崎セシ縺ソ蜈医ヰ繝繝輔ぃ縺ッ23繝舌う繝亥ソ隕√ +/// Human68k繝代せ縺ッ蠢縺/縺ァ髢句ァ九☆繧九%縺ィ縲 +/// 騾比クュ/縺2縺、莉・荳企」邯壹@縺ヲ蜃コ迴セ縺励◆蝣エ蜷医ッ繧ィ繝ゥ繝シ縺ィ縺吶k縲 +/// 譁蟄怜礼オらォッ縺/縺縺代ョ蝣エ蜷医ッ遨コ縺ョ譁蟄怜励→縺励※蜃ヲ逅縺励√お繝ゥ繝シ縺ォ縺ッ縺励↑縺縲 +// +//--------------------------------------------------------------------------- +const BYTE* CHostDrv::SeparateCopyFilename(const BYTE* szHuman, BYTE* szBuffer) // static +{ + ASSERT(szHuman); + ASSERT(szBuffer); + + const size_t nMax = 22; + const BYTE* p = szHuman; + + BYTE c = *p++; // 隱ュ縺ソ霎シ縺ソ + if (c != '/' && c != '\\') + return NULL; // 繧ィ繝ゥ繝シ: 荳肴ュ」縺ェ繝代せ蜷 + + // 繝輔ぃ繧、繝ォ縺縺」縺薙>繧後k + size_t i = 0; + for (;;) { + c = *p; // 隱ュ縺ソ霎シ縺ソ + if (c == '\0') + break; // 譁蟄怜礼オらォッ縺ェ繧臥オゆコ (邨らォッ菴咲スョ繧定ソ斐☆) + if (c == '/' || c == '\\') { + if (i == 0) + return NULL; // 繧ィ繝ゥ繝シ: 繝代せ蛹コ蛻繧頑枚蟄励′騾」邯壹@縺ヲ縺繧 + break; // 繝代せ縺ョ蛹コ蛻繧翫r隱ュ繧薙□繧臥オゆコ (譁蟄励ョ菴咲スョ繧定ソ斐☆) + } + p++; + + if (i >= nMax) + return NULL; // 繧ィ繝ゥ繝シ: 1繝舌う繝育岼縺後ヰ繝繝輔ぃ邨らォッ縺ォ縺九°繧 + szBuffer[i++] = c; // 譖ク縺崎セシ縺ソ + + if ((0x80 <= c && c <= 0x9F) || 0xE0 <= c) { // 蜴ウ蟇縺ォ縺ッ0x81ス0x9F縺ィ0xE0ス0xEF + c = *p++; // 隱ュ縺ソ霎シ縺ソ + if (c < 0x40) + return NULL; // 繧ィ繝ゥ繝シ: 荳肴ュ」縺ェSJIS2繝舌う繝育岼 + + if (i >= nMax) + return NULL; // 繧ィ繝ゥ繝シ: 2繝舌う繝育岼縺後ヰ繝繝輔ぃ邨らォッ縺ォ縺九°繧 + szBuffer[i++] = c; // 譖ク縺崎セシ縺ソ + } + } + szBuffer[i] = '\0'; // 譖ク縺崎セシ縺ソ + + return p; +} + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ讀懃エ「蜃ヲ逅 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CHostFiles::Init() +{ + ASSERT(this); +} + +//--------------------------------------------------------------------------- +// +/// 繝代せ蜷阪サ繝輔ぃ繧、繝ォ蜷阪r蜀驛ィ縺ァ逕滓 +// +//--------------------------------------------------------------------------- +void CHostFiles::SetPath(const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + pNamests->GetCopyPath(m_szHumanPath); + pNamests->GetCopyFilename(m_szHumanFilename); + m_nHumanWildcard = 0; + m_nHumanAttribute = Human68k::AT_ARCHIVE; + m_findNext.Clear(); +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ァ繝輔ぃ繧、繝ォ繧呈、懃エ「縺励帙せ繝亥エ縺ョ諠蝣ア繧堤函謌 +// +//--------------------------------------------------------------------------- +BOOL CHostFiles::Find(DWORD nUnit, CHostEntry* pEntry) +{ + ASSERT(this); + ASSERT(pEntry); + + return pEntry->Find(nUnit, this); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷肴、懃エ「 +// +//--------------------------------------------------------------------------- +const CHostFilename* CHostFiles::Find(CHostPath* pPath) +{ + ASSERT(this); + ASSERT(pPath); + + if (m_nHumanWildcard) + return pPath->FindFilenameWildcard(m_szHumanFilename, m_nHumanAttribute, &m_findNext); + + return pPath->FindFilename(m_szHumanFilename, m_nHumanAttribute); +} + +//--------------------------------------------------------------------------- +// +/// Human68k蛛エ縺ョ讀懃エ「邨先棡菫晏ュ +// +//--------------------------------------------------------------------------- +void CHostFiles::SetEntry(const CHostFilename* pFilename) +{ + ASSERT(this); + ASSERT(pFilename); + + // Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ菫晏ュ + memcpy(&m_dirHuman, pFilename->GetEntry(), sizeof(m_dirHuman)); + + // Human68k繝輔ぃ繧、繝ォ蜷堺ソ晏ュ + strcpy((char*)m_szHumanResult, (const char*)pFilename->GetHuman()); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 +// +//--------------------------------------------------------------------------- +void CHostFiles::SetResult(const TCHAR* szPath) +{ + ASSERT(this); + ASSERT(szPath); + ASSERT(strlen(szPath) < FILEPATH_MAX); + + strcpy(m_szHostResult, szPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォ繝輔ぃ繧、繝ォ蜷阪r霑ス蜉 +// +//--------------------------------------------------------------------------- +void CHostFiles::AddResult(const TCHAR* szPath) +{ + ASSERT(this); + ASSERT(szPath); + ASSERT(strlen(m_szHostResult) + strlen(szPath) < FILEPATH_MAX); + + strcat(m_szHostResult, szPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォHuman68k縺ョ譁ー隕上ヵ繧。繧、繝ォ蜷阪r霑ス蜉 +// +//--------------------------------------------------------------------------- +void CHostFiles::AddFilename() +{ + ASSERT(this); + ASSERT(strlen(m_szHostResult) + strlen((const char*)m_szHumanFilename) < FILEPATH_MAX); + + /// @warning Unicode譛ェ蟇セ蠢懊ゅ>縺壹lUnicode縺ョ荳也阜縺ォ鬟ョ縺セ繧後◆譎ゅッ縺薙%縺ァ螟画鋤繧定。後↑縺 竊 貂 + strcat(m_szHostResult, (const char*)m_szHumanFilename); +} + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== + +#ifdef _DEBUG +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostFilesManager::~CHostFilesManager() +{ + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); +} +#endif // _DEBUG + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) +// +//--------------------------------------------------------------------------- +void CHostFilesManager::Init() +{ + ASSERT(this); + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + + // 繝。繝「繝ェ遒コ菫 + for (DWORD i = 0; i < XM6_HOST_FILES_MAX; i++) { + ring_t* p = new ring_t; + ASSERT(p); + p->r.Insert(&m_cRing); + } +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) +// +//--------------------------------------------------------------------------- +void CHostFilesManager::Clean() +{ + ASSERT(this); + + // 繝。繝「繝ェ隗」謾セ + CRing* p; + while ((p = m_cRing.Next()) != &m_cRing) { + delete (ring_t*)p; + } +} + +//--------------------------------------------------------------------------- +// +/// 遒コ菫 +// +//--------------------------------------------------------------------------- +CHostFiles* CHostFilesManager::Alloc(DWORD nKey) +{ + ASSERT(this); + ASSERT(nKey); + + // 譛ォ蟆セ縺九i驕ク謚 + ring_t* p = (ring_t*)m_cRing.Prev(); + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + + // 繧ュ繝シ繧定ィュ螳 + p->f.SetKey(nKey); + + return &p->f; +} + +//--------------------------------------------------------------------------- +// +/// 讀懃エ「 +// +//--------------------------------------------------------------------------- +CHostFiles* CHostFilesManager::Search(DWORD nKey) +{ + ASSERT(this); + // ASSERT(nKey); // DPB遐エ謳阪↓繧医j讀懃エ「繧ュ繝シ縺0縺ォ縺ェ繧九%縺ィ繧ゅ≠繧 + + // 隧イ蠖薙☆繧九が繝悶ず繧ァ繧ッ繝医r讀懃エ「 + ring_t* p = (ring_t*)m_cRing.Next(); + for (; p != (ring_t*)&m_cRing; p = (ring_t*)p->r.Next()) { + if (p->f.isSameKey(nKey)) { + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + return &p->f; + } + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ +// +//--------------------------------------------------------------------------- +void CHostFilesManager::Free(CHostFiles* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + + // 隗」謾セ + pFiles->SetKey(0); + pFiles->Init(); + + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク遘サ蜍 + ring_t* p = (ring_t*)((size_t)pFiles - offsetof(ring_t, f)); + p->r.InsertTail(&m_cRing); +} + +//=========================================================================== +// +// FCB蜃ヲ逅 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CHostFcb::Init() +{ + ASSERT(this); + + m_bUpdate = FALSE; + m_pFile = NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝峨r險ュ螳 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::SetMode(DWORD nHumanMode) +{ + ASSERT(this); + + switch (nHumanMode & Human68k::OP_MASK) { + case Human68k::OP_READ: + m_pszMode = "rb"; + break; + case Human68k::OP_WRITE: + m_pszMode = "wb"; + break; + case Human68k::OP_FULL: + m_pszMode = "r+b"; + break; + default: + return FALSE; + } + + m_bFlag = (nHumanMode & Human68k::OP_SPECIAL) != 0; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蜷阪r險ュ螳 +// +//--------------------------------------------------------------------------- +void CHostFcb::SetFilename(const TCHAR* szFilename) +{ + ASSERT(this); + ASSERT(szFilename); + ASSERT(strlen(szFilename) < FILEPATH_MAX); + + strcpy(m_szFilename, szFilename); +} + +//--------------------------------------------------------------------------- +// +/// Human68k繝代せ蜷阪r險ュ螳 +// +//--------------------------------------------------------------------------- +void CHostFcb::SetHumanPath(const BYTE* szHumanPath) +{ + ASSERT(this); + ASSERT(szHumanPath); + ASSERT(strlen((const char*)szHumanPath) < HUMAN68K_PATH_MAX); + + strcpy((char*)m_szHumanPath, (const char*)szHumanPath); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ菴懈 +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Create(DWORD nHumanAttribute, BOOL bForce) +{ + ASSERT(this); + ASSERT((nHumanAttribute & (Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) == 0); + ASSERT(strlen(m_szFilename) > 0); + ASSERT(m_pFile == NULL); + + // 驥崎、繝√ぉ繝繧ッ + if (bForce == FALSE) { + struct stat sb; + if (stat(S2U(m_szFilename), &sb) == 0) + return FALSE; + } + + // 繝輔ぃ繧、繝ォ菴懈 + m_pFile = fopen(S2U(m_szFilename), "w+b"); /// @warning 逅諠ウ蜍穂ス懊ッ螻樊ァ縺斐→荳頑嶌縺 + + return m_pFile != NULL; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Open() +{ + struct stat st; + + ASSERT(this); + ASSERT(strlen(m_szFilename) > 0); + + // 繝繧」繝ャ繧ッ繝医Μ縺ェ繧牙、ア謨 + if (stat(S2U(m_szFilename), &st) == 0) { + if ((st.st_mode & S_IFMT) == S_IFDIR) { + return FALSE || m_bFlag; + } + } + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (m_pFile == NULL) + m_pFile = fopen(S2U(m_szFilename), m_pszMode); + + return m_pFile != NULL || m_bFlag; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Rewind(DWORD nOffset) +{ + ASSERT(this); + ASSERT(m_pFile); + + if (fseek(m_pFile, nOffset, SEEK_SET)) + return FALSE; + + return ftell(m_pFile) != -1L; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ +/// +/// 0繝舌う繝郁ェュ縺ソ霎シ縺ソ縺ァ繧よュ」蟶ク蜍穂ス懊→縺吶k縲 +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッ-1繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +DWORD CHostFcb::Read(BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(pBuffer); + ASSERT(m_pFile); + + size_t nResult = fread(pBuffer, sizeof(BYTE), nSize, m_pFile); + if (ferror(m_pFile)) + nResult = (size_t)-1; + + return (DWORD)nResult; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ +/// +/// 0繝舌う繝域嶌縺崎セシ縺ソ縺ァ繧よュ」蟶ク蜍穂ス懊→縺吶k縲 +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッ-1繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +DWORD CHostFcb::Write(const BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(pBuffer); + ASSERT(m_pFile); + + size_t nResult = fwrite(pBuffer, sizeof(BYTE), nSize, m_pFile); + if (ferror(m_pFile)) + nResult = (size_t)-1; + + return (DWORD)nResult; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ蛻繧願ゥー繧 +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Truncate() +{ + ASSERT(this); + ASSERT(m_pFile); + + return ftruncate(fileno(m_pFile), ftell(m_pFile)) == 0; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッ-1繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +DWORD CHostFcb::Seek(DWORD nOffset, DWORD nHumanSeek) +{ + ASSERT(this); + ASSERT(nHumanSeek == Human68k::SK_BEGIN || + nHumanSeek == Human68k::SK_CURRENT || nHumanSeek == Human68k::SK_END); + ASSERT(m_pFile); + + int nSeek; + switch (nHumanSeek) { + case Human68k::SK_BEGIN: + nSeek = SEEK_SET; + break; + case Human68k::SK_CURRENT: + nSeek = SEEK_CUR; + break; + // case SK_END: + default: + nSeek = SEEK_END; + break; + } + if (fseek(m_pFile, nOffset, nSeek)) + return (DWORD)-1; + + return (DWORD)ftell(m_pFile); +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ譎ょ綾險ュ螳 +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::TimeStamp(DWORD nHumanTime) +{ + ASSERT(this); + ASSERT(m_pFile || m_bFlag); + + struct tm t = { 0 }; + t.tm_year = (nHumanTime >> 25) + 80; + t.tm_mon = ((nHumanTime >> 21) - 1) & 15; + t.tm_mday = (nHumanTime >> 16) & 31; + t.tm_hour = (nHumanTime >> 11) & 15; + t.tm_min = (nHumanTime >> 5) & 63; + t.tm_sec = (nHumanTime & 31) << 1; + time_t ti = mktime(&t); + if (ti == (time_t)-1) + return FALSE; + struct utimbuf ut; + ut.actime = ti; + ut.modtime = ti; + + // 繧ッ繝ュ繝シ繧コ譎ゅ↓譖エ譁ー譎ょ綾縺御ク頑嶌縺阪&繧後k縺ョ繧帝亟豁「縺吶k縺溘a + // 繧ソ繧、繝繧ケ繧ソ繝ウ繝励ョ譖エ譁ー蜑阪↓繝輔Λ繝繧キ繝・縺励※蜷梧悄縺輔○繧 + fflush(m_pFile); + + return utime(S2U(m_szFilename), &ut) == 0 || m_bFlag; +} + +//--------------------------------------------------------------------------- +// +/// 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ +/// +/// 繧ィ繝ゥ繝シ縺ョ譎ゅッFALSE繧定ソ斐☆縲 +// +//--------------------------------------------------------------------------- +BOOL CHostFcb::Close() +{ + ASSERT(this); + + BOOL bResult = TRUE; + + // 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + // Close竊巽ree(蜀驛ィ縺ァ蜀榊コヲClose)縺ィ縺縺豬√l繧ゅ≠繧九ョ縺ァ蠢縺壼晄悄蛹悶☆繧九%縺ィ縲 + if (m_pFile) { + fclose(m_pFile); + m_pFile = NULL; + } + + return bResult; +} + +//=========================================================================== +// +// FCB蜃ヲ逅 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== + +#ifdef _DEBUG +//--------------------------------------------------------------------------- +// +/// 繝繧ケ繝医Λ繧ッ繧ソ final +// +//--------------------------------------------------------------------------- +CHostFcbManager::~CHostFcbManager() +{ + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); +} +#endif // _DEBUG + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) +// +//--------------------------------------------------------------------------- +void CHostFcbManager::Init() +{ + ASSERT(this); + + // 螳滉ス薙′蟄伜惠縺励↑縺縺薙→繧堤「コ隱 (蠢オ縺ョ縺溘a) + ASSERT(m_cRing.Next() == &m_cRing); + ASSERT(m_cRing.Prev() == &m_cRing); + + // 繝。繝「繝ェ遒コ菫 + for (DWORD i = 0; i < XM6_HOST_FCB_MAX; i++) { + ring_t* p = new ring_t; + ASSERT(p); + p->r.Insert(&m_cRing); + } +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) +// +//--------------------------------------------------------------------------- +void CHostFcbManager::Clean() +{ + ASSERT(this); + + // 繝。繝「繝ェ隗」謾セ + CRing* p; + while ((p = m_cRing.Next()) != &m_cRing) { + delete (ring_t*)p; + } +} + +//--------------------------------------------------------------------------- +// +/// 遒コ菫 +// +//--------------------------------------------------------------------------- +CHostFcb* CHostFcbManager::Alloc(DWORD nKey) +{ + ASSERT(this); + ASSERT(nKey); + + // 譛ォ蟆セ縺九i驕ク謚 + ring_t* p = (ring_t*)m_cRing.Prev(); + + // 菴ソ逕ィ荳ュ縺ェ繧峨お繝ゥ繝シ (蠢オ縺ョ縺溘a) + if (p->f.isSameKey(0) == FALSE) { + ASSERT(0); + return NULL; + } + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + + // 繧ュ繝シ繧定ィュ螳 + p->f.SetKey(nKey); + + return &p->f; +} + +//--------------------------------------------------------------------------- +// +/// 讀懃エ「 +// +//--------------------------------------------------------------------------- +CHostFcb* CHostFcbManager::Search(DWORD nKey) +{ + ASSERT(this); + ASSERT(nKey); + + // 隧イ蠖薙☆繧九が繝悶ず繧ァ繧ッ繝医r讀懃エ「 + ring_t* p = (ring_t*)m_cRing.Next(); + while (p != (ring_t*)&m_cRing) { + if (p->f.isSameKey(nKey)) { + // 繝ェ繝ウ繧ー蜈磯ュ縺ク遘サ蜍 + p->r.Insert(&m_cRing); + return &p->f; + } + p = (ring_t*)p->r.Next(); + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +/// 隗」謾セ +// +//--------------------------------------------------------------------------- +void CHostFcbManager::Free(CHostFcb* pFcb) +{ + ASSERT(this); + ASSERT(pFcb); + + // 隗」謾セ + pFcb->SetKey(0); + pFcb->Close(); + + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク遘サ蜍 + ring_t* p = (ring_t*)((size_t)pFcb - offsetof(ring_t, f)); + p->r.InsertTail(&m_cRing); +} + +//=========================================================================== +// +// 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝 +// +//=========================================================================== + +DWORD CFileSys::g_nOption; ///< 繝輔ぃ繧、繝ォ蜷榊、画鋤繝輔Λ繧ー + +//--------------------------------------------------------------------------- +// +/// 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CFileSys::CFileSys() +{ + // 繧ウ繝ウ繝輔ぅ繧ー繝繝シ繧ソ蛻晄悄蛹 + m_nDrives = 0; + + for (size_t n = 0; n < DriveMax; n++) { + m_nFlag[n] = 0; + m_szBase[n][0] = _T('\0'); + } + + // TwentyOne繧ェ繝励す繝ァ繝ウ逶」隕門晄悄蛹 + m_nKernel = 0; + m_nKernelSearch = 0; + + // 蜍穂ス懊ヵ繝ゥ繧ー蛻晄悄蛹 + m_nOptionDefault = 0; + m_nOption = 0; + ASSERT(g_nOption == 0); +} + +//--------------------------------------------------------------------------- +// +/// 繝ェ繧サ繝繝 (蜈ィ繧ッ繝ュ繝シ繧コ) +// +//--------------------------------------------------------------------------- +void CFileSys::Reset() +{ + ASSERT(this); + + // 莉ョ諠ウ繧サ繧ッ繧ソ鬆伜沺蛻晄悄蛹 + m_nHostSectorCount = 0; + memset(m_nHostSectorBuffer, 0, sizeof(m_nHostSectorBuffer)); + + // 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + m_cFiles.Clean(); + + // FCB謫堺ス憺伜沺 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + m_cFcb.Clean(); + + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + m_cEntry.Clean(); + + // TwentyOne繧ェ繝励す繝ァ繝ウ逶」隕門晄悄蛹 + m_nKernel = 0; + m_nKernelSearch = 0; + + // 蜍穂ス懊ヵ繝ゥ繧ー蛻晄悄蛹 + SetOption(m_nOptionDefault); +} + +//--------------------------------------------------------------------------- +// +/// 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) +// +//--------------------------------------------------------------------------- +void CFileSys::Init() +{ + ASSERT(this); + + // 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔サ繝ュ繝シ繝画凾) + m_cFiles.Init(); + + // FCB謫堺ス憺伜沺 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔サ繝ュ繝シ繝画凾) + m_cFcb.Init(); + + // 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔サ繝ュ繝シ繝画凾) + m_cEntry.Init(); + + // 繝代せ蛟句挨險ュ螳壹ョ譛臥┌繧貞愛螳 + DWORD nDrives = m_nDrives; + if (nDrives == 0) { + // 蛟句挨險ュ螳壹r菴ソ繧上★縺ォ繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ繧剃スソ逕ィ縺吶k + strcpy(m_szBase[0], _T("/")); + m_nFlag[0] = 0; + nDrives++; + } + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧堤匳骭イ + DWORD nUnit = 0; + for (DWORD n = 0; n < nDrives; n++) { + // 繝吶シ繧ケ繝代せ縺悟ュ伜惠縺励↑縺繧ィ繝ウ繝医Μ縺ッ逋サ骭イ縺励↑縺 + if (m_szBase[n][0] == _T('\0')) + continue; + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧1繝ヲ繝九ャ繝育函謌 + CHostDrv* p = new CHostDrv; // std::nothrow + if (p) { + m_cEntry.SetDrv(nUnit, p); + p->Init(m_szBase[n], m_nFlag[n]); + + // 谺。縺ョ繝ヲ繝九ャ繝医∈ + nUnit++; + } + } + + // 逋サ骭イ縺励◆繝峨Λ繧、繝匁焚繧剃ソ晏ュ + m_nUnits = nUnit; +} + +//--------------------------------------------------------------------------- +// +/// $40 - 繝繝舌う繧ケ襍キ蜍 +// +//--------------------------------------------------------------------------- +DWORD CFileSys::InitDevice(const Human68k::argument_t* pArgument) +{ + ASSERT(this); + + // 繧ェ繝励す繝ァ繝ウ蛻晄悄蛹 + InitOption(pArgument); + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝蛻晄悄蛹 + Init(); + + return m_nUnits; +} + +//--------------------------------------------------------------------------- +// +/// $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +int CFileSys::CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + if (f.isRootPath()) + return 0; + f.SetPathOnly(); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_DIRNOTFND; + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 +// +//--------------------------------------------------------------------------- +int CFileSys::MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetPathOnly(); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_INVALIDPATH; + f.AddFilename(); + + // 繝繧」繝ャ繧ッ繝医Μ菴懈 + if (mkdir(S2U(f.GetPath()), 0777)) + return FS_INVALIDPATH; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 +// +//--------------------------------------------------------------------------- +int CFileSys::RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_DIRECTORY); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_DIRNOTFND; + + // 繧ュ繝」繝繧キ繝・蜑企勁 + BYTE szHuman[HUMAN68K_PATH_MAX + 24]; + ASSERT(strlen((const char*)f.GetHumanPath()) + + strlen((const char*)f.GetHumanFilename()) < HUMAN68K_PATH_MAX + 24); + strcpy((char*)szHuman, (const char*)f.GetHumanPath()); + strcat((char*)szHuman, (const char*)f.GetHumanFilename()); + strcat((char*)szHuman, "/"); + m_cEntry.DeleteCache(nUnit, szHuman); + + // 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + if (rmdir(S2U(f.GetPath()))) + return FS_CANTDELETE; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 +// +//--------------------------------------------------------------------------- +int CFileSys::Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_ALL); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + CHostFiles fNew; + fNew.SetPath(pNamestsNew); + fNew.SetPathOnly(); + if (fNew.Find(nUnit, &m_cEntry) == FALSE) + return FS_INVALIDPATH; + fNew.AddFilename(); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + if (f.GetAttribute() & Human68k::AT_DIRECTORY) + m_cEntry.CleanCacheChild(nUnit, f.GetHumanPath()); + + // 繝輔ぃ繧、繝ォ蜷榊、画峩 + char szFrom[FILENAME_MAX]; + char szTo[FILENAME_MAX]; + SJIS2UTF8(f.GetPath(), szFrom, FILENAME_MAX); + SJIS2UTF8(fNew.GetPath(), szTo, FILENAME_MAX); + if (rename(szFrom, szTo)) { + return FS_FILENOTFND; + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + m_cEntry.CleanCache(nUnit, fNew.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $45 - 繝輔ぃ繧、繝ォ蜑企勁 +// +//--------------------------------------------------------------------------- +int CFileSys::Delete(DWORD nUnit, const Human68k::namests_t* pNamests) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + // 繝輔ぃ繧、繝ォ蜑企勁 + if (unlink(S2U(f.GetPath()))) + return FS_CANTDELETE; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 +// +//--------------------------------------------------------------------------- +int CFileSys::Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute) +{ + ASSERT(this); + ASSERT(pNamests); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_ALL); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + // 螻樊ァ蜿門セ励↑繧臥オゆコ + if (nHumanAttribute == 0xFF) + return f.GetAttribute(); + + // 螻樊ァ繝√ぉ繝繧ッ + if (nHumanAttribute & Human68k::AT_VOLUME) + return FS_CANTACCESS; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 螻樊ァ逕滓 + DWORD nAttribute = (nHumanAttribute & Human68k::AT_READONLY) | + (f.GetAttribute() & ~Human68k::AT_READONLY); + if (f.GetAttribute() != nAttribute) { + struct stat sb; + if (stat(S2U(f.GetPath()), &sb)) + return FS_FILENOTFND; + mode_t m = sb.st_mode & 0777; + if (nAttribute & Human68k::AT_READONLY) + m &= 0555; // ugo-w + else + m |= 0200; // u+w + + // 螻樊ァ險ュ螳 + if (chmod(S2U(f.GetPath()), m)) + return FS_FILENOTFND; + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + // 螟画峩蠕後ョ螻樊ァ蜿門セ + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + return f.GetAttribute(); +} + +//--------------------------------------------------------------------------- +// +/// $47 - 繝輔ぃ繧、繝ォ讀懃エ「 +// +//--------------------------------------------------------------------------- +int CFileSys::Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles) +{ + ASSERT(this); + ASSERT(pNamests); + ASSERT(nKey); + ASSERT(pFiles); + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後≠繧後ー隗」謾セ縺励※縺翫¥ + CHostFiles* pHostFiles = m_cFiles.Search(nKey); + if (pHostFiles != NULL) { + m_cFiles.Free(pHostFiles); + } + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ + /** @note + 逶エ蜑阪ョ繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ縺ァ豁」縺励¥繧ィ繝ゥ繝シ繧定ソ斐@縺ヲ縺繧九↓繧ゅ°縺九o繧 + 縺壹√懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ励r螳溯。後☆繧玖。悟о縺ョ謔ェ縺繧「繝励Μ縺ァ繝帙せ繝亥エ縺ョ + 繝ェ繝繝シ繝舌ヶ繝ォ繝。繝繧」繧「(CD-ROM繝峨Λ繧、繝也ュ)縺檎區蟶ッ繧貞コ縺吶ョ繧帝亟縺舌◆繧√ + 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ励ッ繝。繝繧」繧「繝√ぉ繝繧ッ繧偵○縺壹↓陦後↑縺莉墓ァ倥→縺励◆縲 + */ + if ((pFiles->fatr & (Human68k::AT_ARCHIVE | Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) + == Human68k::AT_VOLUME) { + // 繝代せ繝√ぉ繝繧ッ + CHostFiles f; + f.SetPath(pNamests); + if (f.isRootPath() == FALSE) + return FS_FILENOTFND; + + // 繝舌ャ繝輔ぃ繧堤「コ菫昴○縺壹√>縺阪↑繧顔オ先棡繧定ソ斐☆ + if (FilesVolume(nUnit, pFiles) == FALSE) + return FS_FILENOTFND; + return 0; + } + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繝舌ャ繝輔ぃ遒コ菫 + pHostFiles = m_cFiles.Alloc(nKey); + if (pHostFiles == NULL) + return FS_OUTOFMEM; + + // 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + pHostFiles->SetPath(pNamests); + if (pHostFiles->isRootPath() == FALSE) { + pHostFiles->SetPathOnly(); + if (pHostFiles->Find(nUnit, &m_cEntry) == FALSE) { + m_cFiles.Free(pHostFiles); + return FS_DIRNOTFND; + } + } + + // 繝ッ繧、繝ォ繝峨き繝シ繝我スソ逕ィ蜿ッ閭ス縺ォ險ュ螳 + pHostFiles->SetPathWildcard(); + pHostFiles->SetAttribute(pFiles->fatr); + + // 繝輔ぃ繧、繝ォ讀懃エ「 + if (pHostFiles->Find(nUnit, &m_cEntry) == FALSE) { + m_cFiles.Free(pHostFiles); + return FS_FILENOTFND; + } + + // 讀懃エ「邨先棡繧呈シ邏 + pFiles->attr = (BYTE)pHostFiles->GetAttribute(); + pFiles->date = pHostFiles->GetDate(); + pFiles->time = pHostFiles->GetTime(); + pFiles->size = pHostFiles->GetSize(); + strcpy((char*)pFiles->full, (const char*)pHostFiles->GetHumanResult()); + + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧呈欠螳 + pFiles->sector = nKey; + pFiles->offset = 0; + + // 繝輔ぃ繧、繝ォ蜷阪↓繝ッ繧、繝ォ繝峨き繝シ繝峨′縺ェ縺代l縺ー縲√%縺ョ譎らせ縺ァ繝舌ャ繝輔ぃ繧定ァ」謾セ蜿ッ閭ス + if (pNamests->wildcard == 0) { + // 縺励°縺励∽サョ諠ウ繧サ繧ッ繧ソ縺ョ繧ィ繝溘Η繝ャ繝シ繧キ繝ァ繝ウ縺ァ菴ソ縺蜿ッ閭ス諤ァ縺後≠繧九◆繧√√☆縺舌↓縺ッ隗」謾セ縺励↑縺 + // m_cFiles.Free(pHostFiles); + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 +// +//--------------------------------------------------------------------------- +int CFileSys::NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFiles); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繝舌ャ繝輔ぃ讀懃エ「 + CHostFiles* pHostFiles = m_cFiles.Search(nKey); + if (pHostFiles == NULL) + return FS_INVALIDPTR; + + // 繝輔ぃ繧、繝ォ讀懃エ「 + if (pHostFiles->Find(nUnit, &m_cEntry) == FALSE) { + m_cFiles.Free(pHostFiles); + return FS_FILENOTFND; + } + + ASSERT(pFiles->sector == nKey); + ASSERT(pFiles->offset == 0); + + // 讀懃エ「邨先棡繧呈シ邏 + pFiles->attr = (BYTE)pHostFiles->GetAttribute(); + pFiles->date = pHostFiles->GetDate(); + pFiles->time = pHostFiles->GetTime(); + pFiles->size = pHostFiles->GetSize(); + strcpy((char*)pFiles->full, (const char*)pHostFiles->GetHumanResult()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $49 - 繝輔ぃ繧、繝ォ譁ー隕丈ス懈 +// +//--------------------------------------------------------------------------- +int CFileSys::Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce) +{ + ASSERT(this); + ASSERT(pNamests); + ASSERT(nKey); + ASSERT(pFcb); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後≠繧後ー繧ィ繝ゥ繝シ縺ィ縺吶k + if (m_cFcb.Search(nKey) != NULL) + return FS_INVALIDPTR; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetPathOnly(); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_INVALIDPATH; + f.AddFilename(); + + // 螻樊ァ繝√ぉ繝繧ッ + if (nHumanAttribute & (Human68k::AT_DIRECTORY | Human68k::AT_VOLUME)) + return FS_CANTACCESS; + + // 繝代せ蜷堺ソ晏ュ + CHostFcb* pHostFcb = m_cFcb.Alloc(nKey); + if (pHostFcb == NULL) + return FS_OUTOFMEM; + pHostFcb->SetFilename(f.GetPath()); + pHostFcb->SetHumanPath(f.GetHumanPath()); + + // 繧ェ繝シ繝励Φ繝「繝シ繝芽ィュ螳 + pFcb->mode = (WORD)((pFcb->mode & ~Human68k::OP_MASK) | Human68k::OP_FULL); + if (pHostFcb->SetMode(pFcb->mode) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_ILLEGALMOD; + } + + // 繝輔ぃ繧、繝ォ菴懈 + if (pHostFcb->Create(nHumanAttribute, bForce) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_FILEEXIST; + } + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, f.GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +int CFileSys::Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb) +{ + ASSERT(this); + ASSERT(pNamests); + ASSERT(nKey); + ASSERT(pFcb); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + switch (pFcb->mode & Human68k::OP_MASK) { + case Human68k::OP_WRITE: + case Human68k::OP_FULL: + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + } + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後≠繧後ー繧ィ繝ゥ繝シ縺ィ縺吶k + if (m_cFcb.Search(nKey) != NULL) + return FS_INVALIDPRM; + + // 繝代せ蜷咲函謌 + CHostFiles f; + f.SetPath(pNamests); + f.SetAttribute(Human68k::AT_ALL); + if (f.Find(nUnit, &m_cEntry) == FALSE) + return FS_FILENOTFND; + + // 繧ソ繧、繝繧ケ繧ソ繝ウ繝 + pFcb->date = f.GetDate(); + pFcb->time = f.GetTime(); + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ + pFcb->size = f.GetSize(); + + // 繝代せ蜷堺ソ晏ュ + CHostFcb* pHostFcb = m_cFcb.Alloc(nKey); + if (pHostFcb == NULL) + return FS_OUTOFMEM; + pHostFcb->SetFilename(f.GetPath()); + pHostFcb->SetHumanPath(f.GetHumanPath()); + + // 繧ェ繝シ繝励Φ繝「繝シ繝芽ィュ螳 + if (pHostFcb->SetMode(pFcb->mode) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_ILLEGALMOD; + } + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (pHostFcb->Open() == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDPATH; + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +int CFileSys::Close(DWORD nUnit, DWORD nKey, Human68k::fcb_t* /* pFcb */) +{ + ASSERT(this); + ASSERT(nKey); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_INVALIDPRM; + + // 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ縺ィ鬆伜沺隗」謾セ + m_cFcb.Free(pHostFcb); + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + if (pHostFcb->isUpdate()) + m_cEntry.CleanCache(nUnit, pHostFcb->GetHumanPath()); + + /// @note 繧ッ繝ュ繝シ繧コ譎ゅョFCB縺ョ迥カ諷九r莉悶ョ繝繝舌う繧ケ縺ィ蜷医o縺帙◆縺 + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ +/// +/// 0繝舌う繝郁ェュ縺ソ霎シ縺ソ縺ァ繧よュ」蟶ク邨ゆコ縺吶k縲 +// +//--------------------------------------------------------------------------- +int CFileSys::Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFcb); + // ASSERT(pBuffer); // 蠢隕∵凾縺ョ縺ソ蛻、螳 + ASSERT(nSize <= 0xFFFFFF); // 繧ッ繝ェ繝繝玲ク + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + // 繝舌ャ繝輔ぃ蟄伜惠遒コ隱 + if (pBuffer == NULL) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDFUNC; + } + + // 隱ュ縺ソ霎シ縺ソ + DWORD nResult; + nResult = pHostFcb->Read(pBuffer, nSize); + if (nResult == (DWORD)-1) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDFUNC; /// @note 縺薙l縺ォ蜉縺医※繧ィ繝ゥ繝シ繧ウ繝シ繝10(隱ュ縺ソ霎シ縺ソ繧ィ繝ゥ繝シ)繧定ソ斐☆縺ケ縺 + } + ASSERT(nResult <= nSize); + + // 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ譖エ譁ー + pFcb->fileptr += nResult; /// @note 繧ェ繝シ繝舌シ繝輔Ο繝シ遒コ隱阪ッ蠢隕√§繧繧阪≧縺具シ + + return nResult; +} + +//--------------------------------------------------------------------------- +// +/// $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ +/// +/// 0繝舌う繝域嶌縺崎セシ縺ソ縺ョ蝣エ蜷医ッ繝輔ぃ繧、繝ォ繧貞繧願ゥー繧√k縲 +// +//--------------------------------------------------------------------------- +int CFileSys::Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pBuffer, DWORD nSize) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFcb); + // ASSERT(pBuffer); // 蠢隕∵凾縺ョ縺ソ蛻、螳 + ASSERT(nSize <= 0xFFFFFF); // 繧ッ繝ェ繝繝玲ク + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + DWORD nResult; + if (nSize == 0) { + // 蛻繧願ゥー繧 + if (pHostFcb->Truncate() == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_CANTSEEK; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ譖エ譁ー + pFcb->size = pFcb->fileptr; + + nResult = 0; + } else { + // 繝舌ャ繝輔ぃ蟄伜惠遒コ隱 + if (pBuffer == NULL) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDFUNC; + } + + // 譖ク縺崎セシ縺ソ + nResult = pHostFcb->Write(pBuffer, nSize); + if (nResult == (DWORD)-1) { + m_cFcb.Free(pHostFcb); + return FS_CANTWRITE; /// @note 縺薙l縺ォ蜉縺医※繧ィ繝ゥ繝シ繧ウ繝シ繝11(譖ク縺崎セシ縺ソ繧ィ繝ゥ繝シ)繧定ソ斐☆縺ケ縺 + } + ASSERT(nResult <= nSize); + + // 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ譖エ譁ー + pFcb->fileptr += nResult; /// @note 繧ェ繝シ繝舌シ繝輔Ο繝シ遒コ隱阪ッ蠢隕√§繧繧阪≧縺具シ + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ譖エ譁ー + if (pFcb->size < pFcb->fileptr) + pFcb->size = pFcb->fileptr; + } + + // 繝輔Λ繧ー譖エ譁ー + pHostFcb->SetUpdate(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +/// $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +// +//--------------------------------------------------------------------------- +int CFileSys::Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset) +{ + ASSERT(this); + ASSERT(pFcb); + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + // 繝代Λ繝。繝シ繧ソ繝√ぉ繝繧ッ + if (nSeek > Human68k::SK_END) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDPRM; + } + + // 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + DWORD nResult = pHostFcb->Seek(nOffset, nSeek); + if (nResult == (DWORD)-1) { + m_cFcb.Free(pHostFcb); + return FS_CANTSEEK; + } + + // 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ譖エ譁ー + pFcb->fileptr = nResult; + + return nResult; +} + +//--------------------------------------------------------------------------- +// +/// $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 +/// +/// 邨先棡縺ョ荳贋ス16Bit縺$FFFF縺縺ィ繧ィ繝ゥ繝シ縲 +// +//--------------------------------------------------------------------------- +DWORD CFileSys::TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime) +{ + ASSERT(this); + ASSERT(nKey); + ASSERT(pFcb); + + // 蜿門セ励ョ縺ソ + if (nHumanTime == 0) + return ((DWORD)pFcb->date << 16) | pFcb->time; + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 譌「縺ォ蜷後§繧ュ繝シ繧呈戟縺、鬆伜沺縺後↑縺代l縺ー繧ィ繝ゥ繝シ縺ィ縺吶k + CHostFcb* pHostFcb = m_cFcb.Search(nKey); + if (pHostFcb == NULL) + return FS_NOTOPENED; + + // 譎ょ綾險ュ螳 + if (pHostFcb->TimeStamp(nHumanTime) == FALSE) { + m_cFcb.Free(pHostFcb); + return FS_INVALIDPRM; + } + pFcb->date = (WORD)(nHumanTime >> 16); + pFcb->time = (WORD)nHumanTime; + + // 繧ュ繝」繝繧キ繝・譖エ譁ー + m_cEntry.CleanCache(nUnit, pHostFcb->GetHumanPath()); + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $50 - 螳ケ驥丞叙蠕 +// +//--------------------------------------------------------------------------- +int CFileSys::GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(pCapacity); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 螳ケ驥丞叙蠕 + return m_cEntry.GetCapacity(nUnit, pCapacity); +} + +//--------------------------------------------------------------------------- +// +/// $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 +// +//--------------------------------------------------------------------------- +int CFileSys::CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive) +{ + ASSERT(this); + ASSERT(pCtrlDrive); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + switch (pCtrlDrive->status) { + case 0: // 迥カ諷区、懈渊 + case 9: // 迥カ諷区、懈渊2 + pCtrlDrive->status = (BYTE)m_cEntry.GetStatus(nUnit); + return pCtrlDrive->status; + + case 1: // 繧、繧ク繧ァ繧ッ繝 + case 2: // 繧、繧ク繧ァ繧ッ繝育ヲ∵ュ「1 (譛ェ螳溯」) + case 3: // 繧、繧ク繧ァ繧ッ繝郁ィア蜿ッ1 (譛ェ螳溯」) + case 4: // 繝。繝繧」繧「譛ェ謖ソ蜈・譎ゅ↓LED轤ケ貊 (譛ェ螳溯」) + case 5: // 繝。繝繧」繧「譛ェ謖ソ蜈・譎ゅ↓LED豸育ッ (譛ェ螳溯」) + case 6: // 繧、繧ク繧ァ繧ッ繝育ヲ∵ュ「2 (譛ェ螳溯」) + case 7: // 繧、繧ク繧ァ繧ッ繝郁ィア蜿ッ2 (譛ェ螳溯」) + return 0; + + case 8: // 繧、繧ク繧ァ繧ッ繝域、懈渊 + return 1; + } + + return FS_INVALIDFUNC; +} + +//--------------------------------------------------------------------------- +// +/// $52 - DPB蜿門セ +/// +/// 繝ャ繧ク繝・繝シ繝蠕後↓DPB縺悟叙蠕励〒縺阪↑縺縺ィHuman68k蜀驛ィ縺ァ繝峨Λ繧、繝悶′豸域サ縺吶k縺溘a縲 +/// 遽蝗イ螟悶ョ繝ヲ繝九ャ繝医〒繧ゅ→縺ォ縺九¥豁」蟶ク邉サ縺ィ縺励※蜃ヲ逅縺吶k縲 +// +//--------------------------------------------------------------------------- +int CFileSys::GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb) +{ + ASSERT(this); + ASSERT(pDpb); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + + Human68k::capacity_t cap; + BYTE media = Human68k::MEDIA_REMOTE; + if (nUnit < m_nUnits) { + media = m_cEntry.GetMediaByte(nUnit); + + // 繧サ繧ッ繧ソ諠蝣ア迯イ蠕 + if (m_cEntry.GetCapacityCache(nUnit, &cap) == FALSE) { + // 謇句虚繧、繧ク繧ァ繧ッ繝医□縺ィ繝。繝繧」繧「繝√ぉ繝繧ッ繧偵☆繧頑栢縺代k縺溘a縺薙%縺ァ謐墓拷 + if (m_cEntry.isEnable(nUnit) == FALSE) + goto none; + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + goto none; + + // 繝峨Λ繧、繝也憾諷句叙蠕 + m_cEntry.GetCapacity(nUnit, &cap); + } + } else { + none: + cap.clusters = 4; // 縺セ縺」縺」縺溘¥蝠城。後↑縺繝繧ケ繧茨シ + cap.sectors = 64; + cap.bytes = 512; + } + + // 繧キ繝輔ヨ謨ー險育ョ + DWORD nSize = 1; + DWORD nShift = 0; + for (;;) { + if (nSize >= cap.sectors) + break; + nSize <<= 1; + nShift++; + } + + // 繧サ繧ッ繧ソ逡ェ蜿キ險育ョ + // + // 莉・荳九ョ鬆縺ォ荳ヲ縺ケ繧九 + // 繧ッ繝ゥ繧ケ繧ソ0: 譛ェ菴ソ逕ィ + // 繧ッ繝ゥ繧ケ繧ソ1: FAT + // 繧ッ繝ゥ繧ケ繧ソ2: 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ + // 繧ッ繝ゥ繧ケ繧ソ3: 繝繝シ繧ソ鬆伜沺(謫ャ莨シ繧サ繧ッ繧ソ) + DWORD nFat = cap.sectors; + DWORD nRoot = cap.sectors * 2; + DWORD nData = cap.sectors * 3; + + // DPB險ュ螳 + pDpb->sector_size = (WORD)cap.bytes; // 1繧サ繧ッ繧ソ蠖薙j縺ョ繝舌う繝域焚 + pDpb->cluster_size = + (BYTE)(cap.sectors - 1); // 1繧ッ繝ゥ繧ケ繧ソ蠖薙j縺ョ繧サ繧ッ繧ソ謨ー - 1 + pDpb->shift = (BYTE)nShift; // 繧ッ繝ゥ繧ケ繧ソ竊偵そ繧ッ繧ソ縺ョ繧キ繝輔ヨ謨ー + pDpb->fat_sector = (WORD)nFat; // FAT 縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + pDpb->fat_max = 1; // FAT 鬆伜沺縺ョ蛟区焚 + pDpb->fat_size = (BYTE)cap.sectors; // FAT 縺ョ蜊繧√k繧サ繧ッ繧ソ謨ー(隍蜀吝繧帝勁縺) + pDpb->file_max = + (WORD)(cap.sectors * cap.bytes / 0x20); // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ォ蜈・繧九ヵ繧。繧、繝ォ縺ョ蛟区焚 + pDpb->data_sector = (WORD)nData; // 繝繝シ繧ソ鬆伜沺縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + pDpb->cluster_max = (WORD)cap.clusters; // 邱上け繝ゥ繧ケ繧ソ謨ー + 1 + pDpb->root_sector = (WORD)nRoot; // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + pDpb->media = media; // 繝。繝繧」繧「繝舌う繝 + + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ +/// +/// 繧サ繧ッ繧ソ縺ッ逍台シシ逧縺ォ讒狗ッ峨@縺溘b縺ョ繧剃スソ逕ィ縺吶k縲 +/// 繝舌ャ繝輔ぃ繧オ繧、繧コ縺ッ$200繝舌う繝亥崋螳壹 +// +//--------------------------------------------------------------------------- +int CFileSys::DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize) +{ + ASSERT(this); + ASSERT(pBuffer); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝紋ク翫〒逋コ逕 + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 繧サ繧ッ繧ソ謨ー1莉・螟悶ョ蝣エ蜷医ッ繧ィ繝ゥ繝シ + if (nSize != 1) + return FS_INVALIDPRM; + + // 繧サ繧ッ繧ソ諠蝣ア迯イ蠕 + Human68k::capacity_t cap; + if (m_cEntry.GetCapacityCache(nUnit, &cap) == FALSE) { + // 繝峨Λ繧、繝也憾諷句叙蠕 + m_cEntry.GetCapacity(nUnit, &cap); + } + + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ク縺ョ繧「繧ッ繧サ繧ケ + CHostFiles* pHostFiles = m_cFiles.Search(nSector); + if (pHostFiles) { + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧堤函謌 + Human68k::dirent_t* dir = (Human68k::dirent_t*)pBuffer; + memcpy(pBuffer, pHostFiles->GetEntry(), sizeof(*dir)); + memset(pBuffer + sizeof(*dir), 0xE5, 0x200 - sizeof(*dir)); + + // 謫ャ莨シ繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ蜀縺ォ繝輔ぃ繧、繝ォ螳滉ス薙r謖縺呎闘莨シ繧サ繧ッ繧ソ逡ェ蜿キ繧定ィ倬鹸 + // 縺ェ縺翫〕zdsys縺ァ縺ッ莉・荳九ョ蠑上〒隱ュ縺ソ霎シ縺ソ繧サ繧ッ繧ソ逡ェ蜿キ繧堤ョ怜コ縺励※縺繧九 + // (dirent.cluster - 2) * (dpb.cluster_size + 1) + dpb.data_sector + /// @warning 繝ェ繝医Ν繧ィ繝ウ繝繧」繧「繝ウ蟆ら畑 + dir->cluster = (WORD)(m_nHostSectorCount + 2); // 謫ャ莨シ繧サ繧ッ繧ソ逡ェ蜿キ + m_nHostSectorBuffer[m_nHostSectorCount] = nSector; // 謫ャ莨シ繧サ繧ッ繧ソ縺ョ謖縺吝ョ滉ス + m_nHostSectorCount++; + m_nHostSectorCount %= XM6_HOST_PSEUDO_CLUSTER_MAX; + + return 0; + } + + // 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ縺九i繧サ繧ッ繧ソ逡ェ蜿キ繧堤ョ怜コ + DWORD n = nSector - (3 * cap.sectors); + DWORD nMod = 1; + if (cap.sectors) { + // 繝。繝繧」繧「縺悟ュ伜惠縺励↑縺蝣エ蜷医ッcap.sectors縺0縺ォ縺ェ繧九ョ縺ァ豕ィ諢 + nMod = n % cap.sectors; + n /= cap.sectors; + } + + // 繝輔ぃ繧、繝ォ螳滉ス薙∈縺ョ繧「繧ッ繧サ繧ケ + if (nMod == 0 && n < XM6_HOST_PSEUDO_CLUSTER_MAX) { + pHostFiles = m_cFiles.Search(m_nHostSectorBuffer[n]); // 螳滉ス薙r讀懃エ「 + if (pHostFiles) { + // 謫ャ莨シ繧サ繧ッ繧ソ繧堤函謌 + CHostFcb f; + f.SetFilename(pHostFiles->GetPath()); + f.SetMode(Human68k::OP_READ); + if (f.Open() == FALSE) + return FS_INVALIDPRM; + memset(pBuffer, 0, 0x200); + DWORD nResult = f.Read(pBuffer, 0x200); + f.Close(); + if (nResult == (DWORD)-1) + return FS_INVALIDPRM; + + return 0; + } + } + + return FS_INVALIDPRM; +} + +//--------------------------------------------------------------------------- +// +/// $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +int CFileSys::DiskWrite(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + if (m_cEntry.isWriteProtect(nUnit)) + return FS_FATAL_WRITEPROTECT; + + // 迴セ螳溘r遯√″縺、縺代k + return FS_INVALIDPRM; +} + +//--------------------------------------------------------------------------- +// +/// $55 - IOCTRL +// +//--------------------------------------------------------------------------- +int CFileSys::Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl) +{ + ASSERT(this); + ASSERT(pIoctrl); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + switch (nFunction) { + case 0: + // 繝。繝繧」繧「繝舌う繝医ョ迯イ蠕 + pIoctrl->media = m_cEntry.GetMediaByte(nUnit); + return 0; + + case 1: + // Human68k莠呈鋤縺ョ縺溘a縺ョ繝繝溘シ + pIoctrl->param = (unsigned long)-1; + return 0; + + case 2: + switch (pIoctrl->param) { + case -1: + // 繝。繝繧」繧「蜀崎ェ崎ュ + m_cEntry.isMediaOffline(nUnit); + return 0; + + case 0: + case 1: + // Human68k莠呈鋤縺ョ縺溘a縺ョ繝繝溘シ + return 0; + } + break; + + case -1: + // 蟶ク鬧仙愛螳 + memcpy(pIoctrl->buffer, "WindrvXM", 8); + return 0; + + case -2: + // 繧ェ繝励す繝ァ繝ウ險ュ螳 + SetOption(pIoctrl->param); + return 0; + + case -3: + // 繧ェ繝励す繝ァ繝ウ迯イ蠕 + pIoctrl->param = GetOption(); + return 0; + } + + return FS_NOTIOCTRL; +} + +//--------------------------------------------------------------------------- +// +/// $56 - 繝輔Λ繝繧キ繝・ +// +//--------------------------------------------------------------------------- +int CFileSys::Flush(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint縺九i繧ウ繝槭Φ繝峨r螳溯。後@謌サ繧区凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + // 蟶ク縺ォ謌仙粥 + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ +// +//--------------------------------------------------------------------------- +int CFileSys::CheckMedia(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + if (nUnit >= m_nUnits) + return FS_INVALIDFUNC; // 繝ャ繧ク繝・繝シ繝蠕後↓辟。蜉ケ縺ェ繝峨Λ繧、繝悶〒mint謫堺ス懈凾縺ォ逋ス蟶ッ繧貞コ縺輔↑縺繧医≧謾ケ濶ッ + + // 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + m_cEntry.CleanCache(nUnit); + return 0; +} + +//--------------------------------------------------------------------------- +// +/// $58 - 謗剃サ門宛蠕。 +// +//--------------------------------------------------------------------------- +int CFileSys::Lock(DWORD nUnit) +{ + ASSERT(this); + + // 繝ヲ繝九ャ繝医メ繧ァ繝繧ッ + if (nUnit >= DriveMax) + return FS_FATAL_INVALIDUNIT; + ASSERT(nUnit < m_nUnits); + if (nUnit >= m_nUnits) + return FS_FATAL_MEDIAOFFLINE; // 蠢オ縺ョ縺溘a + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FS_FATAL_MEDIAOFFLINE; + + // 蟶ク縺ォ謌仙粥 + return 0; +} + +//--------------------------------------------------------------------------- +// +/// 繧ェ繝励す繝ァ繝ウ險ュ螳 +// +//--------------------------------------------------------------------------- +void CFileSys::SetOption(DWORD nOption) +{ + ASSERT(this); + + // 繧ェ繝励す繝ァ繝ウ險ュ螳壼、画峩縺ァ繧ュ繝」繝繧キ繝・繧ッ繝ェ繧「 + if (m_nOption ^ nOption) + m_cEntry.CleanCache(); + + m_nOption = nOption; + g_nOption = nOption; +} + +//--------------------------------------------------------------------------- +// +/// 繧ェ繝励す繝ァ繝ウ蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void CFileSys::InitOption(const Human68k::argument_t* pArgument) +{ + ASSERT(this); + ASSERT(pArgument); + + // 繝峨Λ繧、繝匁焚繧貞晄悄蛹 + m_nDrives = 0; + + const BYTE* pp = pArgument->buf; + pp += strlen((const char*)pp) + 1; + + DWORD nOption = m_nOptionDefault; + for (;;) { + ASSERT(pp < pArgument->buf + sizeof(*pArgument)); + const BYTE* p = pp; + BYTE c = *p++; + if (c == '\0') + break; + + DWORD nMode; + if (c == '+') { + nMode = 1; + } else if (c == '-') { + nMode = 0; + } else if (c == '/') { + // 繝繝輔か繝ォ繝医吶シ繧ケ繝代せ縺ョ謖螳 + if (m_nDrives < DriveMax) { + p--; + strcpy(m_szBase[m_nDrives], (const char *)p); + m_nDrives++; + } + pp += strlen((const char*)pp) + 1; + continue; + } else { + // 繧ェ繝励す繝ァ繝ウ謖螳壹〒縺ッ縺ェ縺縺ョ縺ァ谺。縺ク + pp += strlen((const char*)pp) + 1; + continue; + } + + for (;;) { + c = *p++; + if (c == '\0') + break; + + DWORD nBit = 0; + switch (c) { + case 'A': case 'a': nBit = WINDRV_OPT_CONVERT_LENGTH; break; + case 'T': case 't': nBit = WINDRV_OPT_COMPARE_LENGTH; nMode ^= 1; break; + case 'C': case 'c': nBit = WINDRV_OPT_ALPHABET; break; + + case 'E': nBit = WINDRV_OPT_CONVERT_PERIOD; break; + case 'P': nBit = WINDRV_OPT_CONVERT_PERIODS; break; + case 'N': nBit = WINDRV_OPT_CONVERT_HYPHEN; break; + case 'H': nBit = WINDRV_OPT_CONVERT_HYPHENS; break; + case 'X': nBit = WINDRV_OPT_CONVERT_BADCHAR; break; + case 'S': nBit = WINDRV_OPT_CONVERT_SPACE; break; + + case 'e': nBit = WINDRV_OPT_REDUCED_PERIOD; break; + case 'p': nBit = WINDRV_OPT_REDUCED_PERIODS; break; + case 'n': nBit = WINDRV_OPT_REDUCED_HYPHEN; break; + case 'h': nBit = WINDRV_OPT_REDUCED_HYPHENS; break; + case 'x': nBit = WINDRV_OPT_REDUCED_BADCHAR; break; + case 's': nBit = WINDRV_OPT_REDUCED_SPACE; break; + } + + if (nMode) + nOption |= nBit; + else + nOption &= ~nBit; + } + + pp = p; + } + + // 繧ェ繝励す繝ァ繝ウ險ュ螳 + if (nOption != m_nOption) { + SetOption(nOption); + } +} + +//--------------------------------------------------------------------------- +// +/// 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL CFileSys::FilesVolume(DWORD nUnit, Human68k::files_t* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ + TCHAR szVolume[32]; + BOOL bResult = m_cEntry.GetVolumeCache(nUnit, szVolume); + if (bResult == FALSE) { + // 謇句虚繧、繧ク繧ァ繧ッ繝医□縺ィ繝。繝繧」繧「繝√ぉ繝繧ッ繧偵☆繧頑栢縺代k縺溘a縺薙%縺ァ謐墓拷 + if (m_cEntry.isEnable(nUnit) == FALSE) + return FALSE; + + // 繝。繝繧」繧「繝√ぉ繝繧ッ + if (m_cEntry.isMediaOffline(nUnit)) + return FALSE; + + // 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ + m_cEntry.GetVolume(nUnit, szVolume); + } + if (szVolume[0] == _T('\0')) + return FALSE; + + pFiles->attr = Human68k::AT_VOLUME; + pFiles->time = 0; + pFiles->date = 0; + pFiles->size = 0; + + CHostFilename fname; + fname.SetHost(szVolume); + fname.ConvertHuman(); + strcpy((char*)pFiles->full, (const char*)fname.GetHuman()); + + return TRUE; +} diff --git a/src/raspberrypi/cfilesystem.h b/src/raspberrypi/cfilesystem.h new file mode 100644 index 00000000..58dabe8e --- /dev/null +++ b/src/raspberrypi/cfilesystem.h @@ -0,0 +1,1157 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝 ] +// +//--------------------------------------------------------------------------- + +#ifndef cfilesystem_h +#define cfilesystem_h + +//--------------------------------------------------------------------------- +// +// 繧ケ繝繝シ繧ソ繧ケ繧ウ繝シ繝牙ョ夂セゥ +// +//--------------------------------------------------------------------------- +#define FS_INVALIDFUNC 0xFFFFFFFF ///< 辟。蜉ケ縺ェ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ繧ウ繝シ繝峨r螳溯。後@縺 +#define FS_FILENOTFND 0xFFFFFFFE ///< 謖螳壹@縺溘ヵ繧。繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺 +#define FS_DIRNOTFND 0xFFFFFFFD ///< 謖螳壹@縺溘ョ繧」繝ャ繧ッ繝医Μ縺瑚ヲ九▽縺九i縺ェ縺 +#define FS_OVEROPENED 0xFFFFFFFC ///< 繧ェ繝シ繝励Φ縺励※縺繧九ヵ繧。繧、繝ォ縺悟、壹☆縺弱k +#define FS_CANTACCESS 0xFFFFFFFB ///< 繝繧」繝ャ繧ッ繝医Μ繧繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ッ繧「繧ッ繧サ繧ケ荳榊庄 +#define FS_NOTOPENED 0xFFFFFFFA ///< 謖螳壹@縺溘ワ繝ウ繝峨Ν縺ッ繧ェ繝シ繝励Φ縺輔l縺ヲ縺縺ェ縺 +#define FS_INVALIDMEM 0xFFFFFFF9 ///< 繝。繝「繝ェ邂。逅鬆伜沺縺檎エ螢翫&繧後◆ +#define FS_OUTOFMEM 0xFFFFFFF8 ///< 螳溯。後↓蠢隕√↑繝。繝「繝ェ縺後↑縺 +#define FS_INVALIDPTR 0xFFFFFFF7 ///< 辟。蜉ケ縺ェ繝。繝「繝ェ邂。逅繝昴う繝ウ繧ソ繧呈欠螳壹@縺 +#define FS_INVALIDENV 0xFFFFFFF6 ///< 荳肴ュ」縺ェ迺ー蠅繧呈欠螳壹@縺 +#define FS_ILLEGALFMT 0xFFFFFFF5 ///< 螳溯。後ヵ繧。繧、繝ォ縺ョ繝輔か繝シ繝槭ャ繝医′逡ー蟶ク +#define FS_ILLEGALMOD 0xFFFFFFF4 ///< 繧ェ繝シ繝励Φ縺ョ繧「繧ッ繧サ繧ケ繝「繝シ繝峨′逡ー蟶ク +#define FS_INVALIDPATH 0xFFFFFFF3 ///< 繝輔ぃ繧、繝ォ蜷阪ョ謖螳壹↓隱、繧翫′縺ゅk +#define FS_INVALIDPRM 0xFFFFFFF2 ///< 辟。蜉ケ縺ェ繝代Λ繝。繝シ繧ソ縺ァ繧ウ繝シ繝ォ縺励◆ +#define FS_INVALIDDRV 0xFFFFFFF1 ///< 繝峨Λ繧、繝匁欠螳壹↓隱、繧翫′縺ゅk +#define FS_DELCURDIR 0xFFFFFFF0 ///< 繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ縺ッ蜑企勁縺ァ縺阪↑縺 +#define FS_NOTIOCTRL 0xFFFFFFEF ///< IOCTRL縺ァ縺阪↑縺繝繝舌う繧ケ +#define FS_LASTFILE 0xFFFFFFEE ///< 縺薙l莉・荳翫ヵ繧。繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺 +#define FS_CANTWRITE 0xFFFFFFED ///< 謖螳壹ョ繝輔ぃ繧、繝ォ縺ッ譖ク縺崎セシ縺ソ縺ァ縺阪↑縺 +#define FS_DIRALREADY 0xFFFFFFEC ///< 謖螳壹ョ繝繧」繝ャ繧ッ繝医Μ縺ッ譌「縺ォ逋サ骭イ縺輔l縺ヲ縺繧 +#define FS_CANTDELETE 0xFFFFFFEB ///< 繝輔ぃ繧、繝ォ縺後≠繧九ョ縺ァ蜑企勁縺ァ縺阪↑縺 +#define FS_CANTRENAME 0xFFFFFFEA ///< 繝輔ぃ繧、繝ォ縺後≠繧九ョ縺ァ繝ェ繝阪シ繝縺ァ縺阪↑縺 +#define FS_DISKFULL 0xFFFFFFE9 ///< 繝繧」繧ケ繧ッ縺御ク譚ッ縺ァ繝輔ぃ繧、繝ォ縺御ス懊l縺ェ縺 +#define FS_DIRFULL 0xFFFFFFE8 ///< 繝繧」繝ャ繧ッ繝医Μ縺御ク譚ッ縺ァ繝輔ぃ繧、繝ォ縺御ス懊l縺ェ縺 +#define FS_CANTSEEK 0xFFFFFFE7 ///< 謖螳壹ョ菴咲スョ縺ォ縺ッ繧キ繝シ繧ッ縺ァ縺阪↑縺 +#define FS_SUPERVISOR 0xFFFFFFE6 ///< 繧ケ繝シ繝代シ繝舌う繧カ迥カ諷九〒繧ケ繝シ繝代ヰ繧、繧カ謖螳壹@縺 +#define FS_THREADNAME 0xFFFFFFE5 ///< 蜷後§繧ケ繝ャ繝繝牙錐縺悟ュ伜惠縺吶k +#define FS_BUFWRITE 0xFFFFFFE4 ///< 繝励Ο繧サ繧ケ髢馴壻ソ。縺ョ繝舌ャ繝輔ぃ縺梧嶌霎シ縺ソ遖∵ュ「 +#define FS_BACKGROUND 0xFFFFFFE3 ///< 繝舌ャ繧ッ繧ー繝ゥ繧ヲ繝ウ繝峨励Ο繧サ繧ケ繧定オキ蜍輔〒縺阪↑縺 +#define FS_OUTOFLOCK 0xFFFFFFE0 ///< 繝ュ繝繧ッ鬆伜沺縺瑚カウ繧翫↑縺 +#define FS_LOCKED 0xFFFFFFDF ///< 繝ュ繝繧ッ縺輔l縺ヲ縺縺ヲ繧「繧ッ繧サ繧ケ縺ァ縺阪↑縺 +#define FS_DRIVEOPENED 0xFFFFFFDE ///< 謖螳壹ョ繝峨Λ繧、繝悶ッ繝上Φ繝峨Λ縺後が繝シ繝励Φ縺輔l縺ヲ縺繧 +#define FS_LINKOVER 0xFFFFFFDD ///< 繧キ繝ウ繝懊Μ繝繧ッ繝ェ繝ウ繧ッ繝阪せ繝医′16蝗槭r雜縺医◆ +#define FS_FILEEXIST 0xFFFFFFB0 ///< 繝輔ぃ繧、繝ォ縺悟ュ伜惠縺吶k + +#define FS_FATAL_MEDIAOFFLINE 0xFFFFFFA3 ///< 繝。繝繧」繧「縺悟・縺」縺ヲ縺縺ェ縺 +#define FS_FATAL_WRITEPROTECT 0xFFFFFFA2 ///< 譖ク縺崎セシ縺ソ遖∵ュ「驕募渚 +#define FS_FATAL_INVALIDCOMMAND 0xFFFFFFA1 ///< 荳肴ュ」縺ェ繧ウ繝槭Φ繝臥分蜿キ +#define FS_FATAL_INVALIDUNIT 0xFFFFFFA0 ///< 荳肴ュ」縺ェ繝ヲ繝九ャ繝育分蜿キ + +#define HUMAN68K_PATH_MAX 96 ///< Human68k縺ョ繝代せ譛螟ァ髟キ + +//=========================================================================== +// +/// Human68k 蜷榊燕遨コ髢 +// +//=========================================================================== +namespace Human68k { + /// 繝輔ぃ繧、繝ォ螻樊ァ繝薙ャ繝 + enum attribute_t { + AT_READONLY = 0x01, ///< 隱ュ縺ソ霎シ縺ソ蟆ら畑螻樊ァ + AT_HIDDEN = 0x02, ///< 髫縺怜ア樊ァ + AT_SYSTEM = 0x04, ///< 繧キ繧ケ繝繝螻樊ァ + AT_VOLUME = 0x08, ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν螻樊ァ + AT_DIRECTORY = 0x10, ///< 繝繧」繝ャ繧ッ繝医Μ螻樊ァ + AT_ARCHIVE = 0x20, ///< 繧「繝シ繧ォ繧、繝門ア樊ァ + AT_ALL = 0xFF, ///< 蜈ィ縺ヲ縺ョ螻樊ァ繝薙ャ繝医′1 + }; + + /// 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝 + enum open_t { + OP_READ = 0, ///< 隱ュ縺ソ霎シ縺ソ + OP_WRITE = 1, ///< 譖ク縺崎セシ縺ソ + OP_FULL = 2, ///< 隱ュ縺ソ譖ク縺 + OP_MASK = 0x0F, ///< 蛻、螳夂畑繝槭せ繧ッ + OP_SHARE_NONE = 0x10, ///< 蜈ア譛臥ヲ∵ュ「 + OP_SHARE_READ = 0x20, ///< 隱ュ縺ソ霎シ縺ソ蜈ア譛 + OP_SHARE_WRITE = 0x30, ///< 譖ク縺崎セシ縺ソ蜈ア譛 + OP_SHARE_FULL = 0x40, ///< 隱ュ縺ソ譖ク縺榊ア譛 + OP_SHARE_MASK = 0x70, ///< 蜈ア譛牙愛螳夂畑繝槭せ繧ッ + OP_SPECIAL = 0x100, ///< 霎樊嶌繧「繧ッ繧サ繧ケ + }; + + /// 繧キ繝シ繧ッ遞ョ鬘 + enum seek_t { + SK_BEGIN = 0, ///< 繝輔ぃ繧、繝ォ蜈磯ュ縺九i + SK_CURRENT = 1, ///< 迴セ蝨ィ菴咲スョ縺九i + SK_END = 2, ///< 繝輔ぃ繧、繝ォ譛ォ蟆セ縺九i + }; + + /// 繝。繝繧」繧「繝舌う繝 + enum media_t { + MEDIA_2DD_10 = 0xE0, ///< 2DD/10繧サ繧ッ繧ソ + MEDIA_1D_9 = 0xE5, ///< 1D/9繧サ繧ッ繧ソ + MEDIA_2D_9 = 0xE6, ///< 2D/9繧サ繧ッ繧ソ + MEDIA_1D_8 = 0xE7, ///< 1D/8繧サ繧ッ繧ソ + MEDIA_2D_8 = 0xE8, ///< 2D/8繧サ繧ッ繧ソ + MEDIA_2HT = 0xEA, ///< 2HT + MEDIA_2HS = 0xEB, ///< 2HS + MEDIA_2HDE = 0xEC, ///< 2DDE + MEDIA_1DD_9 = 0xEE, ///< 1DD/9繧サ繧ッ繧ソ + MEDIA_1DD_8 = 0xEF, ///< 1DD/8繧サ繧ッ繧ソ + MEDIA_MANUAL = 0xF1, ///< 繝ェ繝「繝シ繝医ラ繝ゥ繧、繝 (謇句虚繧、繧ク繧ァ繧ッ繝) + MEDIA_REMOVABLE = 0xF2, ///< 繝ェ繝「繝シ繝医ラ繝ゥ繧、繝 (繝ェ繝繝シ繝舌ヶ繝ォ) + MEDIA_REMOTE = 0xF3, ///< 繝ェ繝「繝シ繝医ラ繝ゥ繧、繝 + MEDIA_DAT = 0xF4, ///< SCSI-DAT + MEDIA_CDROM = 0xF5, ///< SCSI-CDROM + MEDIA_MO = 0xF6, ///< SCSI-MO + MEDIA_SCSI_HD = 0xF7, ///< SCSI-HD + MEDIA_SASI_HD = 0xF8, ///< SASI-HD + MEDIA_RAMDISK = 0xF9, ///< RAM繝繧」繧ケ繧ッ + MEDIA_2HQ = 0xFA, ///< 2HQ + MEDIA_2DD_8 = 0xFB, ///< 2DD/8繧サ繧ッ繧ソ + MEDIA_2DD_9 = 0xFC, ///< 2DD/9繧サ繧ッ繧ソ + MEDIA_2HC = 0xFD, ///< 2HC + MEDIA_2HD = 0xFE, ///< 2HD + }; + + /// namests讒矩菴 + struct namests_t { + BYTE wildcard; ///< 繝ッ繧、繝ォ繝峨き繝シ繝画枚蟄玲焚 + BYTE drive; ///< 繝峨Λ繧、繝也分蜿キ + BYTE path[65]; ///< 繝代せ(繧オ繝悶ョ繧」繝ャ繧ッ繝医Μ+/) + BYTE name[8]; ///< 繝輔ぃ繧、繝ォ蜷 (PADDING 0x20) + BYTE ext[3]; ///< 諡。蠑オ蟄 (PADDING 0x20) + BYTE add[10]; ///< 繝輔ぃ繧、繝ォ蜷崎ソス蜉 (PADDING 0x00) + + // 譁蟄怜怜叙蠕 + void FASTCALL GetCopyPath(BYTE* szPath) const; + ///< 繝代せ蜷榊叙蠕 + void FASTCALL GetCopyFilename(BYTE* szFilename) const; + ///< 繝輔ぃ繧、繝ォ蜷榊叙蠕 + }; + + /// files讒矩菴 + struct files_t { + BYTE fatr; ///< + 0 讀懃エ「縺吶k螻樊ァ 隱ュ霎シ蟆ら畑 + // BYTE drive; ///< + 1 繝峨Λ繧、繝也分蜿キ 隱ュ霎シ蟆ら畑 + DWORD sector; ///< + 2 繝繧」繝ャ繧ッ繝医Μ縺ョ繧サ繧ッ繧ソ DOS _FILES蜈磯ュ繧「繝峨Ξ繧ケ縺ァ莉」逕ィ + // WORD cluster; ///< + 6 繝繧」繝ャ繧ッ繝医Μ縺ョ繧ッ繝ゥ繧ケ繧ソ 隧ウ邏ー荳肴 (譛ェ菴ソ逕ィ) + WORD offset; ///< + 8 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 譖ク霎シ蟆ら畑 + // BYTE name[8]; ///< +10 菴懈・ュ逕ィ繝輔ぃ繧、繝ォ蜷 隱ュ霎シ蟆ら畑 (譛ェ菴ソ逕ィ) + // BYTE ext[3]; ///< +18 菴懈・ュ逕ィ諡。蠑オ蟄 隱ュ霎シ蟆ら畑 (譛ェ菴ソ逕ィ) + BYTE attr; ///< +21 繝輔ぃ繧、繝ォ螻樊ァ 譖ク霎シ蟆ら畑 + WORD time; ///< +22 譛邨ょ、画峩譎ょ綾 譖ク霎シ蟆ら畑 + WORD date; ///< +24 譛邨ょ、画峩譛域律 譖ク霎シ蟆ら畑 + DWORD size; ///< +26 繝輔ぃ繧、繝ォ繧オ繧、繧コ 譖ク霎シ蟆ら畑 + BYTE full[23]; ///< +30 繝輔Ν繝輔ぃ繧、繝ォ蜷 譖ク霎シ蟆ら畑 + }; + + /// FCB讒矩菴 + struct fcb_t { + // BYTE pad00[6]; ///< + 0ス+ 5 (譛ェ菴ソ逕ィ) + DWORD fileptr; ///< + 6ス+ 9 繝輔ぃ繧、繝ォ繝昴う繝ウ繧ソ + // BYTE pad01[4]; ///< +10ス+13 (譛ェ菴ソ逕ィ) + WORD mode; ///< +14ス+15 繧ェ繝シ繝励Φ繝「繝シ繝 + // BYTE pad02[16]; ///< +16ス+31 (譛ェ菴ソ逕ィ) + // DWORD zero; ///< +32ス+35 繧ェ繝シ繝励Φ縺ョ縺ィ縺0縺梧嶌縺崎セシ縺セ繧後※縺繧 (譛ェ菴ソ逕ィ) + // BYTE name[8]; ///< +36ス+43 繝輔ぃ繧、繝ォ蜷 (PADDING 0x20) (譛ェ菴ソ逕ィ) + // BYTE ext[3]; ///< +44ス+46 諡。蠑オ蟄 (PADDING 0x20) (譛ェ菴ソ逕ィ) + BYTE attr; ///< +47 繝輔ぃ繧、繝ォ螻樊ァ + // BYTE add[10]; ///< +48ス+57 繝輔ぃ繧、繝ォ蜷崎ソス蜉 (PADDING 0x00) (譛ェ菴ソ逕ィ) + WORD time; ///< +58ス+59 譛邨ょ、画峩譎ょ綾 + WORD date; ///< +60ス+61 譛邨ょ、画峩譛域律 + // WORD cluster; ///< +62ス+63 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ (譛ェ菴ソ逕ィ) + DWORD size; ///< +64ス+67 繝輔ぃ繧、繝ォ繧オ繧、繧コ + // BYTE pad03[28]; ///< +68ス+95 FAT繧ュ繝」繝繧キ繝・ (譛ェ菴ソ逕ィ) + }; + + /// capacity讒矩菴 + struct capacity_t { + WORD freearea; ///< + 0 菴ソ逕ィ蜿ッ閭ス縺ェ繧ッ繝ゥ繧ケ繧ソ謨ー + WORD clusters; ///< + 2 邱上け繝ゥ繧ケ繧ソ謨ー + WORD sectors; ///< + 4 繧ッ繝ゥ繧ケ繧ソ縺ゅ◆繧翫ョ繧サ繧ッ繧ソ謨ー + WORD bytes; ///< + 6 繧サ繧ッ繧ソ蠖薙◆繧翫ョ繝舌う繝域焚 + }; + + /// ctrldrive讒矩菴 + struct ctrldrive_t { + BYTE status; ///< +13 迥カ諷 + BYTE pad[3]; ///< Padding + }; + + /// DPB讒矩菴 + struct dpb_t { + WORD sector_size; ///< + 0 1繧サ繧ッ繧ソ蠖薙j縺ョ繝舌う繝域焚 + BYTE cluster_size; ///< + 2 1繧ッ繝ゥ繧ケ繧ソ蠖薙j縺ョ繧サ繧ッ繧ソ謨ー-1 + BYTE shift; ///< + 3 繧ッ繝ゥ繧ケ繧ソ竊偵そ繧ッ繧ソ縺ョ繧キ繝輔ヨ謨ー + WORD fat_sector; ///< + 4 FAT縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + BYTE fat_max; ///< + 6 FAT鬆伜沺縺ョ蛟区焚 + BYTE fat_size; ///< + 7 FAT縺ョ蜊繧√k繧サ繧ッ繧ソ謨ー(隍蜀吝繧帝勁縺) + WORD file_max; ///< + 8 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ォ蜈・繧九ヵ繧。繧、繝ォ縺ョ蛟区焚 + WORD data_sector; ///< +10 繝繝シ繧ソ鬆伜沺縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + WORD cluster_max; ///< +12 邱上け繝ゥ繧ケ繧ソ謨ー+1 + WORD root_sector; ///< +14 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蜈磯ュ繧サ繧ッ繧ソ逡ェ蜿キ + // DWORD driverentry; ///< +16 繝繝舌う繧ケ繝峨Λ繧、繝舌∈縺ョ繝昴う繝ウ繧ソ (譛ェ菴ソ逕ィ) + BYTE media; ///< +20 繝。繝繧」繧「隴伜挨蟄 + // BYTE flag; ///< +21 DPB菴ソ逕ィ繝輔Λ繧ー (譛ェ菴ソ逕ィ) + }; + + /// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ讒矩菴 + struct dirent_t { + BYTE name[8]; ///< + 0 繝輔ぃ繧、繝ォ蜷 (PADDING 0x20) + BYTE ext[3]; ///< + 8 諡。蠑オ蟄 (PADDING 0x20) + BYTE attr; ///< +11 繝輔ぃ繧、繝ォ螻樊ァ + BYTE add[10]; ///< +12 繝輔ぃ繧、繝ォ蜷崎ソス蜉 (PADDING 0x00) + WORD time; ///< +22 譛邨ょ、画峩譎ょ綾 + WORD date; ///< +24 譛邨ょ、画峩譛域律 + WORD cluster; ///< +26 繧ッ繝ゥ繧ケ繧ソ逡ェ蜿キ + DWORD size; ///< +28 繝輔ぃ繧、繝ォ繧オ繧、繧コ + }; + + /// IOCTRL繝代Λ繝。繝シ繧ソ蜈ア逕ィ菴 + union ioctrl_t { + BYTE buffer[8]; ///< 繝舌う繝亥腰菴阪〒縺ョ繧「繧ッ繧サ繧ケ + DWORD param; ///< 繝代Λ繝。繝シ繧ソ(蜈磯ュ4繝舌う繝) + WORD media; ///< 繝。繝繧」繧「繝舌う繝(蜈磯ュ2繝舌う繝) + }; + + /// 繧ウ繝槭Φ繝峨Λ繧、繝ウ蠑墓焚讒矩菴 + /** + 蜈磯ュ縺ォ繝峨Λ繧、繝占ェ霄ォ縺ョ繝代せ縺悟性縺セ繧後k縺溘aHUMAN68K_PATH_MAX莉・荳翫ョ繧オ繧、繧コ縺ォ縺吶k縲 + */ + struct argument_t { + BYTE buf[256]; ///< 繧ウ繝槭Φ繝峨Λ繧、繝ウ蠑墓焚 + }; +} + +/// FILES逕ィ繝舌ャ繝輔ぃ蛟区焚 +/** +騾壼クク縺ッ謨ー蛟九〒蜊∝縺縺後?uman68k縺ョ隍謨ー縺ョ繝励Ο繧サ繧ケ縺後槭Ν繝√ち繧ケ繧ッ縺ァ蜷梧凾縺ォ +豺ア縺髫主ア、縺ォ貂。縺」縺ヲ菴懈・ュ縺吶k譎ゅ↑縺ゥ縺ッ縺薙ョ蛟、繧貞「励d縺吝ソ隕√′縺ゅk縲 + +繝繝輔か繝ォ繝医ッ20蛟九 +*/ +#define XM6_HOST_FILES_MAX 20 + +/// FCB逕ィ繝舌ャ繝輔ぃ蛟区焚 +/** +蜷梧凾縺ォ繧ェ繝シ繝励Φ縺ァ縺阪k繝輔ぃ繧、繝ォ謨ー縺ッ縺薙l縺ァ豎コ縺セ繧九 + +繝繝輔か繝ォ繝医ッ100繝輔ぃ繧、繝ォ縲 +*/ +#define XM6_HOST_FCB_MAX 100 + +/// 莉ョ諠ウ繧サ繧ッ繧ソ/繧ッ繝ゥ繧ケ繧ソ 譛螟ァ蛟区焚 +/** +繝輔ぃ繧、繝ォ螳滉ス薙ョ蜈磯ュ繧サ繧ッ繧ソ縺ク縺ョ繧「繧ッ繧サ繧ケ縺ォ蟇セ蠢懊☆繧九◆繧√ョ莉ョ諠ウ繧サ繧ッ繧ソ縺ョ蛟区焚縲 +lzdsys縺ォ繧医k繧「繧ッ繧サ繧ケ繧定。後↑縺繧ケ繝ャ繝繝峨ョ謨ー繧医j螟壹a縺ォ遒コ菫昴☆繧九 + +繝繝輔か繝ォ繝医ッ10繧サ繧ッ繧ソ縲 +*/ +#define XM6_HOST_PSEUDO_CLUSTER_MAX 10 + +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繧ュ繝」繝繧キ繝・蛟区焚 +/** +Human68k縺ッ縲√し繝悶ョ繧」繝ャ繧ッ繝医Μ蜀縺ァ蜃ヲ逅繧定。後↑縺髫帙↓繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ +縺ョ繝√ぉ繝繧ッ繧貞、ァ驥上↓逋コ陦後☆繧九ゅ%縺ョ蠢懃ュ斐r鬮倬溷喧縺吶k縺溘a縺ョ邁。譏薙く繝」繝繧キ繝・ +縺ョ蛟区焚繧呈欠螳壹☆繧九ゅく繝」繝繧キ繝・縺ッ蜷繝峨Λ繧、繝匁ッ弱↓遒コ菫昴&繧後k縲 +螟壹>縺サ縺ゥ鬮倬溘↓縺ェ繧九′縲∝「励d縺励☆縺弱k縺ィ繝帙せ繝OS蛛エ縺ォ雋諡縺後°縺九k縺ョ縺ァ豕ィ諢上 + +繝繝輔か繝ォ繝医ッ16蛟九 +*/ +#define XM6_HOST_DIRENTRY_CACHE_MAX 16 + +/// 1繝繧」繝ャ繧ッ繝医Μ縺ォ蜿守エ阪〒縺阪k繧ィ繝ウ繝医Μ縺ョ譛螟ァ謨ー +/** +繝繧」繝ャ繧ッ繝医Μ蜀縺ォ繝輔ぃ繧、繝ォ縺悟、ァ驥上↓蟄伜惠縺吶k縺ィ縲∝ス捺凾縺ョ繧「繝励Μ繧ア繝シ繧キ繝ァ繝ウ縺 +諠ウ螳壹@縺ヲ縺縺ェ縺螟ァ驥上ョ繝繝シ繧ソ繧定ソ斐@縺ヲ縺励∪縺縺薙→縺ォ縺ェ繧九ゅい繝励Μ縺ォ繧医▲縺ヲ縺ッ +荳驛ィ縺励°隱崎ュ倥&繧後↑縺九▲縺溘j縲騾溷コヲ縺悟、ァ蟷縺ォ菴惹ク九@縺溘j縲√Γ繝「繝ェ荳崎カウ縺ァ蛛懈ュ「 +縺吶k縺ェ縺ゥ縺ョ蜊ア髯コ諤ァ縺悟ュ伜惠縺吶k縲ゅ%縺ョ縺溘a荳企剞繧定ィュ螳壹☆繧九%縺ィ縺ァ蟇セ蜃ヲ縺吶k縲 +萓九∴縺ー縺ィ縺ゅk繝輔ぃ繧、繝ゥ縺ョ蝣エ蜷医2560繝輔ぃ繧、繝ォ縺御ク企剞縺ィ縺ェ縺」縺ヲ縺繧九ゅ%縺ョ謨ー繧 +荳縺、縺ョ逶ョ螳峨→縺吶k縺ョ縺瑚憶縺縲 + +繝繝輔か繝ォ繝医ッ邏6荳繧ィ繝ウ繝医Μ縲(FAT縺ョ繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ァ縺ョ荳企剞蛟、) +*/ +#define XM6_HOST_DIRENTRY_FILE_MAX 65535 + +/// 繝輔ぃ繧、繝ォ蜷阪ョ驥崎、髯、螟悶ヱ繧ソ繝シ繝ウ縺ョ譛螟ァ謨ー +/** +Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷阪ッ縲√帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ蜷咲ァー繧偵b縺ィ縺ォ閾ェ +蜍慕函謌舌&繧後k縺後?uman68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷阪h繧翫b繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷阪ョ蜷 +遘ー縺ョ縺サ縺縺碁聞縺縺溘a縲∝酔蜷阪ョ繝輔ぃ繧、繝ォ蜷阪′逕滓舌&繧後※縺励∪縺蜿ッ閭ス諤ァ縺後≠繧九 +縺昴ョ譎ゅ?uman68k蛛エ縺九i繝輔ぃ繧、繝ォ蜷阪r蛹コ蛻・縺ァ縺阪k繧医≧縺ォ縺吶k縺溘a縲仝indrvXM +迢ャ閾ェ縺ョ蜻ス蜷崎ヲ丞援縺ォ蠕薙▲縺ヲ蛻・蜷阪r逕滓舌@縺ヲ隗」豎コ縺励※縺繧九 +逅隲紋ク翫ッ邏6蜊荳(36縺ョ5荵)騾壹j縺ョ蛻・蜷阪r逕滓舌〒縺阪k譁ケ蠑上r蜿悶▲縺ヲ縺繧九′縲∝ョ +髫帙↓縺ッ謨ー逋セ繝代ち繝シ繝ウ莉・荳翫ョ驥崎、蛻、螳壹′逋コ逕溘☆繧九→蜃ヲ逅縺ォ譎る俣縺後°縺九▲縺ヲ縺励∪ +縺縺溘a縲驥崎、縺ョ荳企剞繧定ィュ螳壹☆繧九%縺ィ縺ァ騾溷コヲ繧堤カュ謖√☆繧九ょクク隴倡噪縺ェ驕狗畑縺ァ縺ゅl +縺ー縲∽サ」譖ソ蜷阪ッ謨ー繝代ち繝シ繝ウ繧ゅ≠繧後ー蜊∝驕狗畑縺ァ縺阪k縺ッ縺壹〒縺ゅj縲√%縺ョ蛟、繧貞庄閭ス +縺ェ髯舌j蟆上&縺蛟、縺ォ縺吶k縺薙→縺ァ繝代ヵ繧ゥ繝シ繝槭Φ繧ケ縺ョ謾ケ蝟縺梧悄蠕縺ァ縺阪k縲 +縺薙ョ蛟区焚繧定カ縺医k繝輔ぃ繧、繝ォ蜷阪′驥崎、縺励※縺励∪縺」縺溷エ蜷医ッ縲∝酔蜷阪ョ繧ィ繝ウ繝医Μ縺 +隍謨ー逕滓舌&繧後k縲ゅ%縺ョ蝣エ蜷医√ヵ繧。繧、繝ォ荳隕ァ縺ァ縺ッ隕九∴繧九′繝輔ぃ繧、繝ォ蜷阪〒謖螳壹☆ +繧九→譛蛻昴ョ繧ィ繝ウ繝医Μ縺ョ縺ソ謇ア縺医k迥カ諷九→縺ェ繧九 + +繝繝輔か繝ォ繝医ッ36繝代ち繝シ繝ウ縲 +*/ +#define XM6_HOST_FILENAME_PATTERN_MAX 36 + +/// 繝輔ぃ繧、繝ォ蜷埼崎、髦イ豁「繝槭シ繧ッ +/** +繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷阪→Human68k蛛エ繝輔ぃ繧、繝ォ蜷阪ョ蜷咲ァー縺ョ蛹コ蛻・繧偵▽縺代k縺ィ縺阪↓ +菴ソ縺譁蟄励ゅさ繝槭Φ繝峨す繧ァ繝ォ遲峨ョ繧ィ繧ケ繧ア繝シ繝玲枚蟄励→驥阪↑繧峨↑縺繧ゅョ繧帝∈縺カ縺ィ蜷峨 + +繝繝輔か繝ォ繝医ッ縲掘縲阪 +*/ +#define XM6_HOST_FILENAME_MARK '@' + +/// WINDRV蜍穂ス懊ヵ繝ゥ繧ー +/** +騾壼クク縺ッ0縺ォ縺吶k縲ゅヵ繧。繧、繝ォ蜑企勁縺ォOS縺ョ縺斐∩邂ア讖溯ス繧貞茜逕ィ縺吶k蝣エ蜷医ッ1縺ォ縺吶k縲 +縺昴l莉・螟悶ョ蛟、縺ッ蟆譚・縺ョ縺溘a縺ョ莠育エ縺ィ縺吶k縲 +蜀驛ィ蜍穂ス懊ヵ繝ゥ繧ー縺ィ繝。繝繧」繧「繝舌う繝亥⊃陬縺ェ縺ゥ繧定ヲ玖カ翫@縺溷ー譚・縺ョ諡。蠑オ逕ィ縲 +*/ +enum { + WINDRV_OPT_REMOVE = 0x00000001, + ///< Bit 0: 繝輔ぃ繧、繝ォ蜑企勁蜃ヲ逅 0:逶エ謗・ 1:縺斐∩邂ア + WINDRV_OPT_ALPHABET = 0x00000020, + ///< Bit 5: 繝輔ぃ繧、繝ォ蜷肴ッ碑シ Alphabet蛹コ蛻・ 0:縺ェ縺 1:縺ゅj 0:-C 1:+C + WINDRV_OPT_COMPARE_LENGTH = 0x00000040, + ///< Bit 6: 繝輔ぃ繧、繝ォ蜷肴ッ碑シ 譁蟄玲焚(譛ェ螳溯」) 0:18+3 1:8+3 0:+T 1:-T + WINDRV_OPT_CONVERT_LENGTH = 0x00000080, + ///< Bit 7: 繝輔ぃ繧、繝ォ蜷榊、画鋤 譁蟄玲焚 0:18+3 1:8+3 0:-A 1:+A + + WINDRV_OPT_CONVERT_SPACE = 0x00000100, + ///< Bit 8: 繝輔ぃ繧、繝ォ蜷榊、画鋤 繧ケ繝壹シ繧ケ 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_BADCHAR = 0x00000200, + ///< Bit 9: 繝輔ぃ繧、繝ォ蜷榊、画鋤 辟。蜉ケ縺ェ譁蟄 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_HYPHENS = 0x00000400, + ///< Bit10: 繝輔ぃ繧、繝ォ蜷榊、画鋤 荳ュ髢薙ョ繝上う繝輔Φ 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_HYPHEN = 0x00000800, + ///< Bit11: 繝輔ぃ繧、繝ォ蜷榊、画鋤 蜈磯ュ縺ョ繝上う繝輔Φ 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_PERIODS = 0x00001000, + ///< Bit12: 繝輔ぃ繧、繝ォ蜷榊、画鋤 荳ュ髢薙ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:'_' + WINDRV_OPT_CONVERT_PERIOD = 0x00002000, + ///< Bit13: 繝輔ぃ繧、繝ォ蜷榊、画鋤 蜈磯ュ縺ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:'_' + + WINDRV_OPT_REDUCED_SPACE = 0x00010000, + ///< Bit16: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 繧ケ繝壹シ繧ケ 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_BADCHAR = 0x00020000, + ///< Bit17: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 辟。蜉ケ縺ェ譁蟄 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_HYPHENS = 0x00040000, + ///< Bit18: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 荳ュ髢薙ョ繝上う繝輔Φ 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_HYPHEN = 0x00080000, + ///< Bit19: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 蜈磯ュ縺ョ繝上う繝輔Φ 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_PERIODS = 0x00100000, + ///< Bit20: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 荳ュ髢薙ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:遏ュ邵ョ + WINDRV_OPT_REDUCED_PERIOD = 0x00200000, + ///< Bit21: 繝輔ぃ繧、繝ォ蜷咲洒邵ョ 蜈磯ュ縺ョ繝斐Μ繧ェ繝 0:縺ェ縺 1:遏ュ邵ョ + + // Bit24ス30 繝輔ぃ繧、繝ォ驥崎、髦イ豁「繝槭シ繧ッ 0:閾ェ蜍 1ス127:譁蟄 +}; + +/// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝蜍穂ス懊ヵ繝ゥ繧ー +/** +騾壼クク縺ッ0縺ォ縺吶k縲ゅΜ繝シ繝峨が繝ウ繝ェ繝シ縺ァ繝槭え繝ウ繝医@縺溘>繝峨Λ繧、繝悶ョ蝣エ蜷医ッ1縺ォ縺吶k縲 +縺昴l莉・螟悶ョ蛟、縺ッ蟆譚・縺ョ縺溘a縺ョ莠育エ縺ィ縺吶k縲 +蛻、螳壹′蝗ー髮」縺ェ繝繝舌う繧ケ(閾ェ菴弑SB繧ケ繝医Ξ繝シ繧ク縺ィ縺)縺ョ縺溘a縺ョ菫晞匱逕ィ縲 +*/ +enum { + FSFLAG_WRITE_PROTECT = 0x00000001, + ///< Bit0: 蠑キ蛻カ譖ク縺崎セシ縺ソ遖∵ュ「 + FSFLAG_REMOVABLE = 0x00000002, + ///< Bit1: 蠑キ蛻カ繝ェ繝繝シ繝舌ヶ繝ォ繝。繝繧」繧「 + FSFLAG_MANUAL = 0x00000004, + ///< Bit2: 蠑キ蛻カ謇句虚繧、繧ク繧ァ繧ッ繝 +}; + +//=========================================================================== +// +/// 縺セ繧九▲縺ィ繝ェ繝ウ繧ー繝ェ繧ケ繝 +/// +/// 蜈磯ュ(root.next)縺梧怙繧よ眠縺励>繧ェ繝悶ず繧ァ繧ッ繝医 +/// 譛ォ蟆セ(root.prev)縺梧怙繧ょ商縺/譛ェ菴ソ逕ィ繧ェ繝悶ず繧ァ繧ッ繝医 +/// 繧ウ繝シ繝牙柑邇霑ス豎ゅョ縺溘a縲‥elete譎ゅッ蠢縺壹昴う繝ウ繧ソ繧偵い繝繝励く繝」繧ケ繝医☆繧九%縺ィ縲 +// +//=========================================================================== +class CRing { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CRing() { Init(); } + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CRing() { Remove(); } + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init() { ASSERT(this); next = prev = this; } + ///< 蛻晄悄蛹 + + CRing* Next() const { ASSERT(this); return next; } + ///< 谺。縺ョ隕∫エ繧貞叙蠕 + CRing* Prev() const { ASSERT(this); return prev; } + ///< 蜑阪ョ隕∫エ繧貞叙蠕 + + void Insert(CRing* pRoot) + { + ASSERT(this); + // 隧イ蠖薙が繝悶ず繧ァ繧ッ繝医r蛻繧企屬縺 + ASSERT(next); + ASSERT(prev); + next->prev = prev; + prev->next = next; + // 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + ASSERT(pRoot); + ASSERT(pRoot->next); + next = pRoot->next; + prev = pRoot; + pRoot->next->prev = this; + pRoot->next = this; + } + ///< 繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 & 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + + void InsertTail(CRing* pRoot) + { + ASSERT(this); + // 隧イ蠖薙が繝悶ず繧ァ繧ッ繝医r蛻繧企屬縺 + ASSERT(next); + ASSERT(prev); + next->prev = prev; + prev->next = next; + // 繝ェ繝ウ繧ー譛ォ蟆セ縺ク謖ソ蜈・ + ASSERT(pRoot); + ASSERT(pRoot->prev); + next = pRoot; + prev = pRoot->prev; + pRoot->prev->next = this; + pRoot->prev = this; + } + ///< 繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 & 繝ェ繝ウ繧ー譛ォ蟆セ縺ク謖ソ蜈・ + + void InsertRing(CRing* pRoot) + { + ASSERT(this); + if (next == prev) return; + + // 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + ASSERT(pRoot); + ASSERT(pRoot->next); + pRoot->next->prev = prev; + prev->next = pRoot->next; + pRoot->next = next; + next->prev = pRoot; + + // 閾ェ蛻閾ェ霄ォ繧堤ゥコ縺ォ縺吶k + next = prev = this; + } + ///< 閾ェ蛻莉・螟悶ョ繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 & 繝ェ繝ウ繧ー蜈磯ュ縺ク謖ソ蜈・ + + void Remove() + { + ASSERT(this); + // 隧イ蠖薙が繝悶ず繧ァ繧ッ繝医r蛻繧企屬縺 + ASSERT(next); + ASSERT(prev); + next->prev = prev; + prev->next = next; + // 螳牙ィ縺ョ縺溘a閾ェ蛻閾ェ霄ォ繧呈欠縺励※縺翫¥ (菴募コヲ蛻繧企屬縺励※繧ょ撫鬘後↑縺) + next = prev = this; + } + ///< 繧ェ繝悶ず繧ァ繧ッ繝亥繧企屬縺 + +private: + CRing* next; ///< 谺。縺ョ隕∫エ + CRing* prev; ///< 蜑阪ョ隕∫エ +}; + +//=========================================================================== +// +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝輔ぃ繧、繝ォ蜷 +// +//=========================================================================== +class CHostFilename { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostFilename(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + static size_t Offset() { return offsetof(CHostFilename, m_szHost); } + ///< 繧ェ繝輔そ繝繝井ス咲スョ蜿門セ + + void SetHost(const TCHAR* szHost); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 + const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧貞叙蠕 + void ConvertHuman(int nCount = -1); + ///< Human68k蛛エ縺ョ蜷咲ァー繧貞、画鋤 + void CopyHuman(const BYTE* szHuman); + ///< Human68k蛛エ縺ョ蜷咲ァー繧定、陬ス + BOOL isReduce() const; + ///< Human68k蛛エ縺ョ蜷咲ァー縺悟刈蟾・縺輔l縺溘°隱ソ譟サ + BOOL isCorrect() const { ASSERT(this); return m_bCorrect; } + ///< Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷崎ヲ丞援縺ォ蜷郁エ縺励※縺繧九°隱ソ譟サ + const BYTE* GetHuman() const { ASSERT(this); return m_szHuman; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + const BYTE* GetHumanLast() const { ASSERT(this); return m_pszHumanLast; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + const BYTE* GetHumanExt() const { ASSERT(this); return m_pszHumanExt; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + void SetEntryName(); + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryAttribute(BYTE nHumanAttribute) + { ASSERT(this); m_dirHuman.attr = nHumanAttribute; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntrySize(DWORD nHumanSize) + { ASSERT(this); m_dirHuman.size = nHumanSize; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryDate(WORD nHumanDate) + { ASSERT(this); m_dirHuman.date = nHumanDate; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryTime(WORD nHumanTime) + { ASSERT(this); m_dirHuman.time = nHumanTime; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + void SetEntryCluster(WORD nHumanCluster) + { ASSERT(this); m_dirHuman.cluster = nHumanCluster; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧定ィュ螳 + const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧貞叙蠕 + BOOL CheckAttribute(DWORD nHumanAttribute) const; + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ螻樊ァ蛻、螳 + BOOL isSameEntry(const Human68k::dirent_t* pdirHuman) const + { ASSERT(this); ASSERT(pdirHuman); return memcmp(&m_dirHuman, pdirHuman, sizeof(m_dirHuman)) == 0; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ荳閾エ蛻、螳 + + // 繝代せ蜷肴桃菴 + static const BYTE* SeparateExt(const BYTE* szHuman); + ///< Human68k繝輔ぃ繧、繝ォ蜷阪°繧画僑蠑オ蟄舌r蛻髮「 + +private: + static BYTE* CopyName(BYTE* pWrite, const BYTE* pFirst, const BYTE* pLast); + ///< Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷崎ヲ∫エ繧偵さ繝斐シ + + const BYTE* m_pszHumanLast; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷阪ョ邨らォッ菴咲スョ + const BYTE* m_pszHumanExt; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷阪ョ諡。蠑オ蟄蝉ス咲スョ + BOOL m_bCorrect; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷阪′豁」縺励¢繧後ー逵 + BYTE m_szHuman[24]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷 + Human68k::dirent_t m_dirHuman; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜈ィ諠蝣ア + TCHAR m_szHost[FILEPATH_MAX]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョ繝帙せ繝亥エ縺ョ蜷咲ァー (蜿ッ螟蛾聞) +}; + +//=========================================================================== +// +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ 繝代せ蜷 +/// +/// Human68k蛛エ縺ョ繝代せ蜷阪ッ縲∝ソ縺壼磯ュ縺/縺ァ蟋九∪繧翫∵忰蟆セ縺/縺ァ邨ゅo繧九 +/// 繝ヲ繝九ャ繝育分蜿キ縺ッ謖√◆縺ェ縺縲 +/// 鬮倬溷喧縺ョ縺溘a縲√帙せ繝亥エ縺ョ蜷咲ァー縺ォ縺ッ繝吶シ繧ケ繝代せ驛ィ蛻繧ょ性繧縲 +// +//=========================================================================== +/** @note +縺サ縺ィ繧薙←縺ョHuman68k縺ョ繧「繝励Μ縺ッ縲√ヵ繧。繧、繝ォ縺ョ譖エ譁ー遲峨↓繧医▲縺ヲ繝繧」繝ャ繧ッ繝医Μ繧ィ +繝ウ繝医Μ縺ォ螟画峩縺檎函縺倥◆髫帙∬ヲェ繝繧」繝ャ繧ッ繝医Μ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励ッ螟牙喧縺励↑縺繧 +縺ョ縺ィ諠ウ螳壹@縺ヲ菴懊i繧後※縺繧九 +縺ィ縺薙m縺後帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ァ縺ッ隕ェ繝繧」繝ャ繧ッ繝医Μ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝 +繧ょ、牙喧縺励※縺励∪縺繧ゅョ縺御クサ豬√→縺ェ縺」縺ヲ縺励∪縺」縺ヲ縺繧九 + +縺薙ョ縺溘a縲√ョ繧」繝ャ繧ッ繝医Μ縺ョ繧ウ繝斐シ遲峨↓縺翫>縺ヲ縲√い繝励Μ蛛エ縺ッ豁」遒コ縺ォ繧ソ繧、繝繧ケ繧ソ +繝ウ繝玲ュ蝣ア縺ェ縺ゥ繧定ィュ螳壹@縺ヲ縺繧九↓繧ゅ°縺九o繧峨★縲∝ョ溯。檎オ先棡縺ァ縺ッ譎ょ綾諠蝣ア縺御ク頑嶌 +縺阪&繧後※縺励∪縺縺ィ縺縺諠ィ蜉縺瑚オキ縺阪※縺励∪縺縲 + +縺昴%縺ァ繝繧」繝ャ繧ッ繝医Μ繧ュ繝」繝繧キ繝・蜀縺ォFAT繧ソ繧、繝繧ケ繧ソ繝ウ繝励ョ繧ィ繝溘Η繝ャ繝シ繧キ繝ァ繝ウ +讖溯ス繧貞ョ溯」縺励◆縲ゅ帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ譖エ譁ー譎ゅ↓繧ソ繧、繝繧ケ繧ソ繝ウ繝玲ュ +蝣ア繧貞セゥ蜈縺吶k縺薙→縺ァHuman68k蛛エ縺ョ譛溷セ縺吶k邨先棡縺ィ荳閾エ縺輔○繧九 +*/ +class CHostPath: public CRing { + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostFilename f; ///< 螳滉ス + }; + +public: + /// 讀懃エ「逕ィ繝舌ャ繝輔ぃ + struct find_t { + DWORD count; ///< 讀懃エ「螳溯。悟屓謨ー + 1 (0縺ョ縺ィ縺阪ッ莉・荳九ョ蛟、縺ッ辟。蜉ケ) + DWORD id; ///< 谺。蝗樊、懃エ「繧堤カ夊。後☆繧九ヱ繧ケ縺ョ繧ィ繝ウ繝医Μ隴伜挨ID + const ring_t* pos; ///< 谺。蝗樊、懃エ「繧堤カ夊。後☆繧倶ス咲スョ (隴伜挨ID荳閾エ譎) + Human68k::dirent_t entry; ///< 谺。蝗樊、懃エ「繧堤カ夊。後☆繧九お繝ウ繝医Μ蜀螳ケ + + void Clear() { count = 0; } + ///< 蛻晄悄蛹 + }; + + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostPath(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostPath(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Clean(); + ///< 蜀榊茜逕ィ縺ョ縺溘a縺ョ蛻晄悄蛹 + + void SetHuman(const BYTE* szHuman); + ///< Human68k蛛エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 + void SetHost(const TCHAR* szHost); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧堤峩謗・謖螳壹☆繧 + BOOL isSameHuman(const BYTE* szHuman) const; + ///< Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k + BOOL isSameChild(const BYTE* szHuman) const; + ///< Human68k蛛エ縺ョ蜷咲ァー繧呈ッ碑シ縺吶k + const TCHAR* GetHost() const { ASSERT(this); return m_szHost; } + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ョ迯イ蠕 + const CHostFilename* FindFilename(const BYTE* szHuman, DWORD nHumanAttribute = Human68k::AT_ALL) const; + ///< 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 + const CHostFilename* FindFilenameWildcard(const BYTE* szHuman, DWORD nHumanAttribute, find_t* pFind) const; + ///< 繝輔ぃ繧、繝ォ蜷阪r讀懃エ「 (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) + BOOL isRefresh(); + ///< 繝輔ぃ繧、繝ォ螟画峩縺瑚。後↑繧上l縺溘°遒コ隱 + void Refresh(); + ///< 繝輔ぃ繧、繝ォ蜀肴ァ区 + void Backup(); + /// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r菫晏ュ + void Restore() const; + /// 繝帙せ繝亥エ縺ョ繧ソ繧、繝繧ケ繧ソ繝ウ繝励r蠕ゥ蜈 + void Release(); + ///< 譖エ譁ー + + // CHostEntry縺悟茜逕ィ縺吶k螟夜ΚAPI + static void InitId() { g_nId = 0; } + ///< 隴伜挨ID逕滓千畑繧ォ繧ヲ繝ウ繧ソ蛻晄悄蛹 + +private: + static ring_t* Alloc(size_t nLength); + ///< 繝輔ぃ繧、繝ォ蜷埼伜沺遒コ菫 + static void Free(ring_t* pRing); + ///< 繝輔ぃ繧、繝ォ蜷埼伜沺隗」謾セ + static int Compare(const BYTE* pFirst, const BYTE* pLast, const BYTE* pBufFirst, const BYTE* pBufLast); + ///< 譁蟄怜玲ッ碑シ (繝ッ繧、繝ォ繝峨き繝シ繝牙ッセ蠢) + + CRing m_cRing; ///< CHostFilename騾」邨千畑 + time_t m_tBackup; ///< 譎ょ綾蠕ゥ蜈逕ィ + BOOL m_bRefresh; ///< 譖エ譁ー繝輔Λ繧ー + DWORD m_nId; ///< 隴伜挨ID (蛟、縺悟、牙喧縺励◆蝣エ蜷医ッ譖エ譁ー繧呈э蜻ウ縺吶k) + BYTE m_szHuman[HUMAN68K_PATH_MAX]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョHuman68k蜀驛ィ蜷 + TCHAR m_szHost[FILEPATH_MAX]; ///< 隧イ蠖薙お繝ウ繝医Μ縺ョ繝帙せ繝亥エ縺ョ蜷咲ァー + + static DWORD g_nId; ///< 隴伜挨ID逕滓千畑繧ォ繧ヲ繝ウ繧ソ +}; + +//=========================================================================== +// +/// 繝輔ぃ繧、繝ォ讀懃エ「蜃ヲ逅 +/// +/// Human68k蛛エ縺ョ繝輔ぃ繧、繝ォ蜷阪r蜀驛ィUnicode縺ァ蜃ヲ逅縺吶k縺ョ縺ッ豁」逶エ繧ュ繝縺縲ゅ→ +/// 縺縺繧上¢縺ァ縲∝ィ縺ヲBYTE縺ォ螟画鋤縺励※蜃ヲ逅縺吶k縲ょ、画鋤蜃ヲ逅縺ッ繝繧」繝ャ繧ッ繝医Μ繧ィ +/// 繝ウ繝医Μ繧ュ繝」繝繧キ繝・縺御ク謇九↓諡縺縲仝INDRV蛛エ縺ッ縺吶∋縺ヲ繧キ繝輔ヨJIS縺ョ縺ソ縺ァ謇ア +/// 縺医k繧医≧縺ォ縺吶k縲 +/// 縺セ縺溘?uman68k蛛エ蜷咲ァー縺ッ縲∝ョ悟ィ縺ォ繝吶シ繧ケ繝代せ謖螳壹°繧臥峡遶九&縺帙k縲 +/// +/// 繝輔ぃ繧、繝ォ繧呈桶縺逶エ蜑阪↓縲√ョ繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ繧ュ繝」繝繧キ繝・繧堤函謌舌☆繧九 +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ縺ョ逕滓仙ヲ逅縺ッ鬮倥さ繧ケ繝医ョ縺溘a縲∽ク蠎ヲ逕滓舌@縺溘お繝ウ繝医Μ縺ッ +/// 蜿ッ閭ス縺ェ髯舌j邯ュ謖√@縺ヲ菴ソ縺蝗槭☆縲 +/// +/// 繝輔ぃ繧、繝ォ讀懃エ「縺ッ3譁ケ蠑上ゅ☆縺ケ縺ヲCHostFiles::Find()縺ァ蜃ヲ逅縺吶k縲 +/// 1. 繝代せ蜷阪ョ縺ソ讀懃エ「 螻樊ァ縺ッ繝繧」繝ャ繧ッ繝医Μ縺ョ縺ソ _CHKDIR _CREATE +/// 2. 繝代せ蜷+繝輔ぃ繧、繝ォ蜷+螻樊ァ縺ョ讀懃エ「 _OPEN +/// 3. 繝代せ蜷+繝ッ繧、繝ォ繝峨き繝シ繝+螻樊ァ縺ョ讀懃エ「 _FILES _NFILES +/// 讀懃エ「邨先棡縺ッ縲√ョ繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ諠蝣ア縺ィ縺励※菫晄戟縺励※縺翫¥縲 +// +//=========================================================================== +class CHostFiles { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostFiles() { SetKey(0); Init(); } + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + void Init(); + ///< 蛻晄悄蛹 + + void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } + ///< 讀懃エ「繧ュ繝シ險ュ螳 + BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } + ///< 讀懃エ「繧ュ繝シ豈碑シ + void SetPath(const Human68k::namests_t* pNamests); + ///< 繝代せ蜷阪サ繝輔ぃ繧、繝ォ蜷阪r蜀驛ィ縺ァ逕滓 + BOOL isRootPath() const { return m_szHumanPath[1] == '\0'; } + ///< 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ蛻、螳 + void SetPathWildcard() { m_nHumanWildcard = 1; } + ///< 繝ッ繧、繝ォ繝峨き繝シ繝峨↓繧医k繝輔ぃ繧、繝ォ讀懃エ「繧呈怏蜉ケ蛹 + void SetPathOnly() { m_nHumanWildcard = 0xFF; } + ///< 繝代せ蜷阪ョ縺ソ繧呈怏蜉ケ蛹 + BOOL isPathOnly() const { return m_nHumanWildcard == 0xFF; } + ///< 繝代せ蜷阪ョ縺ソ險ュ螳壹°蛻、螳 + void SetAttribute(DWORD nHumanAttribute) { m_nHumanAttribute = nHumanAttribute; } + ///< 讀懃エ「螻樊ァ繧定ィュ螳 + BOOL Find(DWORD nUnit, class CHostEntry* pEntry); + ///< Human68k蛛エ縺ァ繝輔ぃ繧、繝ォ繧呈、懃エ「縺励帙せ繝亥エ縺ョ諠蝣ア繧堤函謌 + const CHostFilename* Find(CHostPath* pPath); + ///< 繝輔ぃ繧、繝ォ蜷肴、懃エ「 + void SetEntry(const CHostFilename* pFilename); + ///< Human68k蛛エ縺ョ讀懃エ「邨先棡菫晏ュ + void SetResult(const TCHAR* szPath); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧定ィュ螳 + void AddResult(const TCHAR* szPath); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォ繝輔ぃ繧、繝ォ蜷阪r霑ス蜉 + void AddFilename(); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ォHuman68k縺ョ譁ー隕上ヵ繧。繧、繝ォ蜷阪r霑ス蜉 + + const TCHAR* GetPath() const { ASSERT(this); return m_szHostResult; } + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧貞叙蠕 + const Human68k::dirent_t* GetEntry() const { ASSERT(this); return &m_dirHuman; } + ///< Human68k繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ繧貞叙蠕 + DWORD GetAttribute() const { ASSERT(this); return m_dirHuman.attr; } + ///< Human68k螻樊ァ繧貞叙蠕 + WORD GetDate() const { ASSERT(this); return m_dirHuman.date; } + ///< Human68k譌・莉倥r蜿門セ + WORD GetTime() const { ASSERT(this); return m_dirHuman.time; } + ///< Human68k譎ょ綾繧貞叙蠕 + DWORD GetSize() const { ASSERT(this); return m_dirHuman.size; } + ///< Human68k繝輔ぃ繧、繝ォ繧オ繧、繧コ繧貞叙蠕 + const BYTE* GetHumanFilename() const { ASSERT(this); return m_szHumanFilename; } + ///< Human68k繝輔ぃ繧、繝ォ蜷阪r蜿門セ + const BYTE* GetHumanResult() const { ASSERT(this); return m_szHumanResult; } + ///< Human68k繝輔ぃ繧、繝ォ蜷肴、懃エ「邨先棡繧貞叙蠕 + const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; } + ///< Human68k繝代せ蜷阪r蜿門セ + +private: + DWORD m_nKey; ///< Human68k縺ョFILES繝舌ャ繝輔ぃ繧「繝峨Ξ繧ケ 0縺ェ繧画悴菴ソ逕ィ + DWORD m_nHumanWildcard; ///< Human68k縺ョ繝ッ繧、繝ォ繝峨き繝シ繝画ュ蝣ア + DWORD m_nHumanAttribute; ///< Human68k縺ョ讀懃エ「螻樊ァ + CHostPath::find_t m_findNext; ///< 谺。蝗樊、懃エ「菴咲スョ諠蝣ア + Human68k::dirent_t m_dirHuman; ///< 讀懃エ「邨先棡 Human68k繝輔ぃ繧、繝ォ諠蝣ア + BYTE m_szHumanFilename[24]; ///< Human68k縺ョ繝輔ぃ繧、繝ォ蜷 + BYTE m_szHumanResult[24]; ///< 讀懃エ「邨先棡 Human68k繝輔ぃ繧、繝ォ蜷 + BYTE m_szHumanPath[HUMAN68K_PATH_MAX]; + ///< Human68k縺ョ繝代せ蜷 + TCHAR m_szHostResult[FILEPATH_MAX]; ///< 讀懃エ「邨先棡 繝帙せ繝亥エ縺ョ繝輔Ν繝代せ蜷 +}; + +//=========================================================================== +// +/// 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== +class CHostFilesManager { +public: +#ifdef _DEBUG + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + ~CHostFilesManager(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final +#endif // _DEBUG + void Init(); + ///< 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) + void Clean(); + ///< 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + + CHostFiles* Alloc(DWORD nKey); + ///< 遒コ菫 + CHostFiles* Search(DWORD nKey); + ///< 讀懃エ「 + void Free(CHostFiles* pFiles); + ///< 隗」謾セ +private: + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostFiles f; ///< 螳滉ス + }; + + CRing m_cRing; ///< CHostFiles騾」邨千畑 +}; + +//=========================================================================== +// +/// FCB蜃ヲ逅 +// +//=========================================================================== +class CHostFcb { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostFcb() { SetKey(0); Init(); } + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostFcb() { Close(); } + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init(); + ///< 蛻晄悄蛹 + + void SetKey(DWORD nKey) { ASSERT(this); m_nKey = nKey; } + ///< 讀懃エ「繧ュ繝シ險ュ螳 + BOOL isSameKey(DWORD nKey) const { ASSERT(this); return m_nKey == nKey; } + ///< 讀懃エ「繧ュ繝シ豈碑シ + void SetUpdate() { ASSERT(this); m_bUpdate = TRUE; } + ///< 譖エ譁ー + BOOL isUpdate() const { ASSERT(this); return m_bUpdate; } + ///< 譖エ譁ー迥カ諷句叙蠕 + BOOL SetMode(DWORD nHumanMode); + ///< 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝峨r險ュ螳 + void SetFilename(const TCHAR* szFilename); + ///< 繝輔ぃ繧、繝ォ蜷阪r險ュ螳 + void SetHumanPath(const BYTE* szHumanPath); + ///< Human68k繝代せ蜷阪r險ュ螳 + const BYTE* GetHumanPath() const { ASSERT(this); return m_szHumanPath; } + ///< Human68k繝代せ蜷阪r蜿門セ + + BOOL Create(DWORD nHumanAttribute, BOOL bForce); + ///< 繝輔ぃ繧、繝ォ菴懈 + BOOL Open(); + ///< 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + BOOL Rewind(DWORD nOffset); + ///< 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + DWORD Read(BYTE* pBuffer, DWORD nSize); + ///< 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + DWORD Write(const BYTE* pBuffer, DWORD nSize); + ///< 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + BOOL Truncate(); + ///< 繝輔ぃ繧、繝ォ蛻繧願ゥー繧 + DWORD Seek(DWORD nOffset, DWORD nHumanSeek); + ///< 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + BOOL TimeStamp(DWORD nHumanTime); + ///< 繝輔ぃ繧、繝ォ譎ょ綾險ュ螳 + BOOL Close(); + ///< 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + +private: + DWORD m_nKey; ///< Human68k縺ョFCB繝舌ャ繝輔ぃ繧「繝峨Ξ繧ケ (0縺ェ繧画悴菴ソ逕ィ) + BOOL m_bUpdate; ///< 譖エ譁ー繝輔Λ繧ー + FILE* m_pFile; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧ェ繝悶ず繧ァ繧ッ繝 + const char* m_pszMode; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝「繝シ繝 + bool m_bFlag; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ繝輔Λ繧ー + BYTE m_szHumanPath[HUMAN68K_PATH_MAX]; + ///< Human68k縺ョ繝代せ蜷 + TCHAR m_szFilename[FILEPATH_MAX]; ///< 繝帙せ繝亥エ縺ョ繝輔ぃ繧、繝ォ蜷 +}; + +//=========================================================================== +// +/// FCB蜃ヲ逅 繝槭ロ繝シ繧ク繝」 +// +//=========================================================================== +class CHostFcbManager { +public: +#ifdef _DEBUG + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + ~CHostFcbManager(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final +#endif // _DEBUG + void Init(); + ///< 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) + void Clean(); + ///< 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + + CHostFcb* Alloc(DWORD nKey); + ///< 遒コ菫 + CHostFcb* Search(DWORD nKey); + ///< 讀懃エ「 + void Free(CHostFcb* p); + ///< 隗」謾セ + +private: + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostFcb f; ///< 螳滉ス + }; + + CRing m_cRing; ///< CHostFcb騾」邨千畑 +}; + +//=========================================================================== +// +/// 繝帙せ繝亥エ繝峨Λ繧、繝 +/// +/// 繝峨Λ繧、繝匁ッ弱↓蠢隕√↑諠蝣ア縺ョ菫晄戟縺ォ蟆ょソオ縺励∫ョ。逅縺ッCHostEntry縺ァ陦後↑縺縲 +// +//=========================================================================== +class CHostDrv +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostDrv(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostDrv(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init(const TCHAR* szBase, DWORD nFlag); + ///< 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) + + BOOL isWriteProtect() const { ASSERT(this); return m_bWriteProtect; } + ///< 譖ク縺崎セシ縺ソ遖∵ュ「縺具シ + BOOL isEnable() const { ASSERT(this); return m_bEnable; } + ///< 繧「繧ッ繧サ繧ケ蜿ッ閭ス縺具シ + BOOL isMediaOffline(); + ///< 繝。繝繧」繧「繝√ぉ繝繧ッ + BYTE GetMediaByte() const; + ///< 繝。繝繧」繧「繝舌う繝医ョ蜿門セ + DWORD GetStatus() const; + ///< 繝峨Λ繧、繝也憾諷九ョ蜿門セ + void SetEnable(BOOL bEnable); + ///< 繝。繝繧」繧「迥カ諷玖ィュ螳 + void GetVolume(TCHAR* szLabel); + ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ + BOOL GetVolumeCache(TCHAR* szLabel) const; + ///< 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 + DWORD GetCapacity(Human68k::capacity_t* pCapacity); + ///< 螳ケ驥上ョ蜿門セ + BOOL GetCapacityCache(Human68k::capacity_t* pCapacity) const; + ///< 繧ュ繝」繝繧キ繝・縺九i螳ケ驥上r蜿門セ + + // 繧ュ繝」繝繧キ繝・謫堺ス + void CleanCache(); + ///< 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCache(const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCacheChild(const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k + void DeleteCache(const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k + CHostPath* FindCache(const BYTE* szHuman); + ///< 謖螳壹&繧後◆繝代せ縺後く繝」繝繧キ繝・縺輔l縺ヲ縺繧九°讀懃エ「縺吶k + CHostPath* CopyCache(CHostFiles* pFiles); + ///< 繧ュ繝」繝繧キ繝・諠蝣ア繧貞縺ォ縲√帙せ繝亥エ縺ョ蜷咲ァー繧堤佐蠕励☆繧 + CHostPath* MakeCache(CHostFiles* pFiles); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー縺ョ讒狗ッ峨↓蠢隕√↑諠蝣ア繧偵☆縺ケ縺ヲ蜿門セ励☆繧 + BOOL Find(CHostFiles* pFiles); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) + +private: + // 繝代せ蜷肴桃菴 + static const BYTE* SeparateCopyFilename(const BYTE* szHuman, BYTE* szBuffer); + ///< Human68k繝輔Ν繝代せ蜷阪°繧牙磯ュ縺ョ隕∫エ繧貞髮「繝サ繧ウ繝斐シ + + // 謗剃サ門宛蠕。 + void Lock() {} + void Unlock() {} + + /// 繝。繝「繝ェ邂。逅逕ィ + struct ring_t { + CRing r; ///< 蜀迺ー + CHostPath f; ///< 螳滉ス + }; + + BOOL m_bWriteProtect; ///< 譖ク縺崎セシ縺ソ遖∵ュ「縺ェ繧欝RUE + BOOL m_bEnable; ///< 繝。繝繧」繧「縺悟茜逕ィ蜿ッ閭ス縺ェ繧欝RUE + DWORD m_nRing; ///< 繝代せ蜷堺ソ晄戟謨ー + CRing m_cRing; ///< CHostPath騾」邨千畑 + Human68k::capacity_t m_capCache; ///< 繧サ繧ッ繧ソ諠蝣ア繧ュ繝」繝繧キ繝・ sectors == 0 縺ェ繧画悴繧ュ繝」繝繧キ繝・ + BOOL m_bVolumeCache; ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν隱ュ縺ソ霎シ縺ソ貂医∩縺ェ繧欝RUE + TCHAR m_szVolumeCache[24]; ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧ュ繝」繝繧キ繝・ + TCHAR m_szBase[FILEPATH_MAX]; ///< 繝吶シ繧ケ繝代せ +}; + +//=========================================================================== +// +/// 繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ邂。逅 +// +//=========================================================================== +class CHostEntry { +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CHostEntry(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + ~CHostEntry(); + ///< 繝繧ケ繝医Λ繧ッ繧ソ final + void Init(); + ///< 蛻晄悄蛹 (繝峨Λ繧、繝千オ霎シ縺ソ譎) + void Clean(); + ///< 隗」謾セ (襍キ蜍輔サ繝ェ繧サ繝繝域凾) + + // 繧ュ繝」繝繧キ繝・謫堺ス + void CleanCache(); + ///< 蜈ィ縺ヲ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCache(DWORD nUnit); + ///< 謖螳壹&繧後◆繝ヲ繝九ャ繝医ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCache(DWORD nUnit, const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧呈峩譁ー縺吶k + void CleanCacheChild(DWORD nUnit, const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ莉・荳九ョ繧ュ繝」繝繧キ繝・繧貞ィ縺ヲ譖エ譁ー縺吶k + void DeleteCache(DWORD nUnit, const BYTE* szHumanPath); + ///< 謖螳壹&繧後◆繝代せ縺ョ繧ュ繝」繝繧キ繝・繧貞炎髯、縺吶k + BOOL Find(DWORD nUnit, CHostFiles* pFiles); + ///< 繝帙せ繝亥エ縺ョ蜷咲ァー繧呈、懃エ「 (繝代せ蜷+繝輔ぃ繧、繝ォ蜷(逵∫払蜿ッ)+螻樊ァ) + void ShellNotify(DWORD nEvent, const TCHAR* szPath); + ///< 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝迥カ諷句、牙喧騾夂衍 + + // 繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝域桃菴 + void SetDrv(DWORD nUnit, CHostDrv* pDrv); + ///< 繝峨Λ繧、繝冶ィュ螳 + BOOL isWriteProtect(DWORD nUnit) const; + ///< 譖ク縺崎セシ縺ソ遖∵ュ「縺具シ + BOOL isEnable(DWORD nUnit) const; + ///< 繧「繧ッ繧サ繧ケ蜿ッ閭ス縺具シ + BOOL isMediaOffline(DWORD nUnit); + ///< 繝。繝繧」繧「繝√ぉ繝繧ッ + BYTE GetMediaByte(DWORD nUnit) const; + ///< 繝。繝繧」繧「繝舌う繝医ョ蜿門セ + DWORD GetStatus(DWORD nUnit) const; + ///< 繝峨Λ繧、繝也憾諷九ョ蜿門セ + void GetVolume(DWORD nUnit, TCHAR* szLabel); + ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν縺ョ蜿門セ + BOOL GetVolumeCache(DWORD nUnit, TCHAR* szLabel) const; + ///< 繧ュ繝」繝繧キ繝・縺九i繝懊Μ繝・繝シ繝繝ゥ繝吶Ν繧貞叙蠕 + DWORD GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); + ///< 螳ケ驥上ョ蜿門セ + BOOL GetCapacityCache(DWORD nUnit, Human68k::capacity_t* pCapacity) const; + ///< 繧ュ繝」繝繧キ繝・縺九i繧ッ繝ゥ繧ケ繧ソ繧オ繧、繧コ繧貞叙蠕 + + /// 螳壽焚 + enum { + DriveMax = 10 ///< 繝峨Λ繧、繝匁怙螟ァ蛟呵」懈焚 + }; + +private: + CHostDrv* m_pDrv[DriveMax]; ///< 繝帙せ繝亥エ繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝 + DWORD m_nTimeout; ///< 譛蠕後↓繧ソ繧、繝繧「繧ヲ繝医メ繧ァ繝繧ッ繧定。後↑縺」縺滓凾蛻サ +}; + +//=========================================================================== +// +/// 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝 +// +//=========================================================================== +/** @note +迴セ蝨ィ縺ョ隕玖ァ」縲 + +XM6縺ョ險ュ險域晄Φ縺ィ縺ッ蜿阪☆繧九′縲…lass Windrv縺セ縺溘ッclass CWindrv縺ォ逶エ謗・ +class CFileSys縺ク縺ョ繝昴う繝ウ繧ソ繧呈戟縺溘○繧区婿豕輔r讓。邏「縺吶k縺ケ縺阪〒縺ゅk縲 +縺薙l縺ォ繧医j縲∽サ・荳九ョ繝。繝ェ繝繝医′蠕励i繧後k縲 + +繝。繝ェ繝繝医◎縺ョ1縲 +繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ縺ョ螟ァ驥上ョ繝。繧ス繝繝臥セ、繧剃ク繝カ謇縺ァ髮荳ュ邂。逅縺ァ縺阪k縲 +繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ縺ッ繝帙せ繝亥エ縺ョ莉墓ァ伜、画峩縺ェ縺ゥ縺ョ隕∝屏縺ォ繧医▲縺ヲ豼縺励¥螟牙喧縺吶k +蜿ッ閭ス諤ァ縺碁ォ倥>縺溘a縲√Γ繧ス繝繝峨ョ霑ス蜉蜑企勁繧蠑墓焚縺ョ螟画峩縺ェ縺ゥ縺ョ繝。繝ウ繝繝翫Φ繧ケ縺 +螟ァ蟷縺ォ讌ス縺ォ縺ェ繧九 + +繝。繝ェ繝繝医◎縺ョ2縲 +莉ョ諠ウ髢「謨ー縺ョ繝繝シ繝悶Ν逕滓舌サ蜿らァ蜃ヲ逅縺ォ髢「縺吶k蜃ヲ逅繧ウ繝シ繝峨r鬧騾舌〒縺阪k縲 +XM6縺ァ縺ッ隍謨ー縺ョ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧ェ繝悶ず繧ァ繧ッ繝医r蜷梧凾縺ォ菴ソ縺繧医≧縺ェ螳溯」縺ッ +縺ゅj縺医↑縺縲ゅ▽縺セ繧翫ヵ繧。繧、繝ォ繧キ繧ケ繝繝繧ェ繝悶ず繧ァ繧ッ繝医↓繝昴Μ繝「繝シ繝輔ぅ繧コ繝縺ッ +縺セ縺」縺溘¥蠢隕√↑縺縺ゥ縺薙m縺九√◆縺繧ッ繝ュ繝繧ッ縺ョ辟。鬧縺ィ縺ェ縺」縺ヲ縺繧九□縺代〒縺ゅk縲 + +隧ヲ縺励↓螟峨∴縺ヲ縺ソ縺溘ょョ滄圀蜉ケ邇荳翫′縺」縺溘 +windrv.h蜀縺ョFILESYS_FAST_STRUCTURE縺ョ蛟、繧貞、峨∴縺ヲ繧ウ繝ウ繝代う繝ゥ縺ョ蜷舌¥繧ス繝シ繧ケ +繧呈ッ碑シ縺吶l縺ー荳逶ョ迸ュ辟カ縲ゆス墓腐遘√′縺薙s縺ェ髟キ譁繧呈嶌縺薙≧縺ィ諤昴▲縺溘ョ縺九r逅隗」縺ァ +縺阪k縺ッ縺壹 + +荳譁ケ繝ュ繧キ繧「縺ッclass CWindrv蜀縺ォclass CFileSys繧堤峩謗・險ュ鄂ョ縺励◆縲 +(譛ャ蠖薙ッclass CHost繧貞サ豁「縺励※逶エ謗・鄂ョ縺阪◆縺窶ヲ窶ヲ濶ッ縺譁ケ豕輔ッ縺ェ縺繧ゅョ縺銀ヲ窶ヲ) +*/ +class CFileSys +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CFileSys(); + ///< 繝繝輔か繝ォ繝医さ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~CFileSys() {}; + ///< 繝繧ケ繝医Λ繧ッ繧ソ + + // 蛻晄悄蛹悶サ邨ゆコ + void Reset(); + ///< 繝ェ繧サ繝繝 (蜈ィ繧ッ繝ュ繝シ繧コ) + void Init(); + ///< 蛻晄悄蛹 (繝繝舌う繧ケ襍キ蜍輔→繝ュ繝シ繝) + + // 繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ + DWORD InitDevice(const Human68k::argument_t* pArgument); + ///< $40 - 繝繝舌う繧ケ襍キ蜍 + int CheckDir(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + int MakeDir(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 + int RemoveDir(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + int Rename(DWORD nUnit, const Human68k::namests_t* pNamests, const Human68k::namests_t* pNamestsNew); + ///< $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 + int Delete(DWORD nUnit, const Human68k::namests_t* pNamests); + ///< $45 - 繝輔ぃ繧、繝ォ蜑企勁 + int Attribute(DWORD nUnit, const Human68k::namests_t* pNamests, DWORD nHumanAttribute); + ///< $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 + int Files(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::files_t* pFiles); + ///< $47 - 繝輔ぃ繧、繝ォ讀懃エ「 + int NFiles(DWORD nUnit, DWORD nKey, Human68k::files_t* pFiles); + ///< $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 + int Create(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb, DWORD nHumanAttribute, BOOL bForce); + ///< $49 - 繝輔ぃ繧、繝ォ菴懈 + int Open(DWORD nUnit, DWORD nKey, const Human68k::namests_t* pNamests, Human68k::fcb_t* pFcb); + ///< $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + int Close(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb); + ///< $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + int Read(DWORD nKey, Human68k::fcb_t* pFcb, BYTE* pAddress, DWORD nSize); + ///< $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + int Write(DWORD nKey, Human68k::fcb_t* pFcb, const BYTE* pAddress, DWORD nSize); + ///< $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + int Seek(DWORD nKey, Human68k::fcb_t* pFcb, DWORD nSeek, int nOffset); + ///< $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + DWORD TimeStamp(DWORD nUnit, DWORD nKey, Human68k::fcb_t* pFcb, DWORD nHumanTime); + ///< $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 + int GetCapacity(DWORD nUnit, Human68k::capacity_t* pCapacity); + ///< $50 - 螳ケ驥丞叙蠕 + int CtrlDrive(DWORD nUnit, Human68k::ctrldrive_t* pCtrlDrive); + ///< $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 + int GetDPB(DWORD nUnit, Human68k::dpb_t* pDpb); + ///< $52 - DPB蜿門セ + int DiskRead(DWORD nUnit, BYTE* pBuffer, DWORD nSector, DWORD nSize); + ///< $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ + int DiskWrite(DWORD nUnit); + ///< $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ + int Ioctrl(DWORD nUnit, DWORD nFunction, Human68k::ioctrl_t* pIoctrl); + ///< $55 - IOCTRL + int Flush(DWORD nUnit); + ///< $56 - 繝輔Λ繝繧キ繝・ + int CheckMedia(DWORD nUnit); + ///< $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + int Lock(DWORD nUnit); + ///< $58 - 謗剃サ門宛蠕。 + + void SetOption(DWORD nOption); + ///< 繧ェ繝励す繝ァ繝ウ險ュ螳 + DWORD GetOption() const { ASSERT(this); return m_nOption; } + ///< 繧ェ繝励す繝ァ繝ウ蜿門セ + DWORD GetDefault() const { ASSERT(this); return m_nOptionDefault; } + ///< 繝繝輔か繝ォ繝医が繝励す繝ァ繝ウ蜿門セ + static DWORD GetFileOption() { return g_nOption; } + ///< 繝輔ぃ繧、繝ォ蜷榊、画鋤繧ェ繝励す繝ァ繝ウ蜿門セ + void ShellNotify(DWORD nEvent, const TCHAR* szPath) + { ASSERT(this); m_cEntry.ShellNotify(nEvent, szPath); } + ///< 繝帙せ繝亥エ繝輔ぃ繧、繝ォ繧キ繧ケ繝繝迥カ諷句、牙喧騾夂衍 + + /// 螳壽焚 + enum { + DriveMax = CHostEntry::DriveMax ///< 繝峨Λ繧、繝匁怙螟ァ蛟呵」懈焚 + }; + +private: + // 蜀驛ィ陬懷勧逕ィ + void InitOption(const Human68k::argument_t* pArgument); + ///< 繧ェ繝励す繝ァ繝ウ蛻晄悄蛹 + BOOL FilesVolume(DWORD nUnit, Human68k::files_t* pFiles); + ///< 繝懊Μ繝・繝シ繝繝ゥ繝吶Ν蜿門セ + + DWORD m_nUnits; ///< 迴セ蝨ィ縺ョ繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝域焚 (繝ャ繧ク繝・繝シ繝豈弱↓螟牙喧) + + DWORD m_nOption; ///< 迴セ蝨ィ縺ョ蜍穂ス懊ヵ繝ゥ繧ー + DWORD m_nOptionDefault; ///< 繝ェ繧サ繝繝域凾縺ョ蜍穂ス懊ヵ繝ゥ繧ー + + DWORD m_nDrives; ///< 繝吶シ繧ケ繝代せ迥カ諷句セゥ蜈逕ィ縺ョ蛟呵」懈焚 (0縺ェ繧画ッ主屓繧ケ繧ュ繝」繝ウ) + + DWORD m_nKernel; ///< 繧ォ繝シ繝阪Ν繝√ぉ繝繧ッ逕ィ繧ォ繧ヲ繝ウ繧ソ + DWORD m_nKernelSearch; ///< NUL繝繝舌う繧ケ縺ョ蜈磯ュ繧「繝峨Ξ繧ケ + + DWORD m_nHostSectorCount; ///< 謫ャ莨シ繧サ繧ッ繧ソ逡ェ蜿キ + + CHostFilesManager m_cFiles; ///< 繝輔ぃ繧、繝ォ讀懃エ「鬆伜沺 + CHostFcbManager m_cFcb; ///< FCB謫堺ス憺伜沺 + CHostEntry m_cEntry; ///< 繝峨Λ繧、繝悶が繝悶ず繧ァ繧ッ繝医→繝繧」繝ャ繧ッ繝医Μ繧ィ繝ウ繝医Μ + + DWORD m_nHostSectorBuffer[XM6_HOST_PSEUDO_CLUSTER_MAX]; + ///< 謫ャ莨シ繧サ繧ッ繧ソ縺ョ謖縺吶ヵ繧。繧、繝ォ螳滉ス + + DWORD m_nFlag[DriveMax]; ///< 繝吶シ繧ケ繝代せ迥カ諷句セゥ蜈逕ィ縺ョ蜍穂ス懊ヵ繝ゥ繧ー蛟呵」 + TCHAR m_szBase[DriveMax][FILEPATH_MAX]; + ///< 繝吶シ繧ケ繝代せ迥カ諷句セゥ蜈逕ィ縺ョ蛟呵」 + static DWORD g_nOption; ///< 繝輔ぃ繧、繝ォ蜷榊、画鋤繝輔Λ繧ー +}; + +#endif // cfilesystem_h diff --git a/src/raspberrypi/cqueue.h b/src/raspberrypi/cqueue.h new file mode 100644 index 00000000..27802a51 --- /dev/null +++ b/src/raspberrypi/cqueue.h @@ -0,0 +1,68 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2004 PI.(ytanaka@ipc-tokai.or.jp) +// [ MFC キュー ] +// +//--------------------------------------------------------------------------- + +#if !defined(queue_h) +#define queue_h + +//=========================================================================== +// +// キュー +// +//=========================================================================== +class CQueue +{ +public: + // 内部データ定義 + typedef struct _QUQUEINFO { + BYTE *pBuf; // バッファ + DWORD dwSize; // サイズ + DWORD dwMask; // マスク(サイズ-1) + DWORD dwRead; // Readポインタ + DWORD dwWrite; // Writeポインタ + DWORD dwNum; // 個数 + DWORD dwTotalRead; // 合計Read + DWORD dwTotalWrite; // 合計Write + } QUEUEINFO, *LPQUEUEINFO; + + // 基本ファンクション + CQueue(); + // コンストラクタ + virtual ~CQueue(); + // デストラクタ + BOOL FASTCALL Init(DWORD dwSize); + // 初期化 + + // API + void FASTCALL Clear(); + // クリア + BOOL FASTCALL IsEmpty() const { return (BOOL)(m_Queue.dwNum == 0); } + // キューが空かチェック + DWORD FASTCALL GetNum() const { return m_Queue.dwNum; } + // キューのデータ数を取得 + DWORD FASTCALL Get(BYTE *pDest); + // キュー内のデータをすべて取得 + DWORD FASTCALL Copy(BYTE *pDest) const; + // キュー内のデータをすべて取得(キュー進めない) + void FASTCALL Discard(DWORD dwNum); + // キューを進める + void FASTCALL Back(DWORD dwNum); + // キューを戻す + DWORD FASTCALL GetFree() const; + // キューの空き個数を取得 + BOOL FASTCALL Insert(const BYTE *pSrc, DWORD dwLength); + // キューに挿入 + void FASTCALL GetQueue(QUEUEINFO *pInfo) const; + // キュー情報取得 + +private: + QUEUEINFO m_Queue; + // 内部ワーク +}; + +#endif // queue_h diff --git a/src/raspberrypi/ctapdriver.cpp b/src/raspberrypi/ctapdriver.cpp new file mode 100644 index 00000000..fbcb3d44 --- /dev/null +++ b/src/raspberrypi/ctapdriver.cpp @@ -0,0 +1,209 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ TAP繝峨Λ繧、繝 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "ctapdriver.h" + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CTapDriver::CTapDriver() +{ + // 蛻晄悄蛹 + m_hTAP = -1; + memset(&m_MacAddr, 0, sizeof(m_MacAddr)); +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +#ifdef __linux__ +BOOL FASTCALL CTapDriver::Init() +{ + char dev[IFNAMSIZ] = "ras0"; + struct ifreq ifr; + int ret; + + ASSERT(this); + + // TAP繝繝舌う繧ケ蛻晄悄蛹 + if ((m_hTAP = open("/dev/net/tun", O_RDWR)) < 0) { + printf("Error: can't open tun\n"); + return FALSE; + } + + // IFF_NO_PI for no extra packet information + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + if ((ret = ioctl(m_hTAP, TUNSETIFF, (void *)&ifr)) < 0) { + printf("Error: can't ioctl TUNSETIFF\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ蜿門セ + ifr.ifr_addr.sa_family = AF_INET; + if ((ret = ioctl(m_hTAP, SIOCGIFHWADDR, &ifr)) < 0) { + printf("Error: can't ioctl SIOCGIFHWADDR\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ菫晏ュ + memcpy(m_MacAddr, ifr.ifr_hwaddr.sa_data, sizeof(m_MacAddr)); + return TRUE; +} +#endif // __linux__ + +#ifdef __NetBSD__ +BOOL FASTCALL CTapDriver::Init() +{ + struct ifreq ifr; + struct ifaddrs *ifa, *a; + + ASSERT(this); + + // TAP繝繝舌う繧ケ蛻晄悄蛹 + if ((m_hTAP = open("/dev/tap", O_RDWR)) < 0) { + printf("Error: can't open tap\n"); + return FALSE; + } + + // 繝繝舌う繧ケ蜷榊叙蠕 + if (ioctl(m_hTAP, TAPGIFNAME, (void *)&ifr) < 0) { + printf("Error: can't ioctl TAPGIFNAME\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ蜿門セ + if (getifaddrs(&ifa) == -1) { + printf("Error: can't getifaddrs\n"); + close(m_hTAP); + return FALSE; + } + for (a = ifa; a != NULL; a = a->ifa_next) + if (strcmp(ifr.ifr_name, a->ifa_name) == 0 && + a->ifa_addr->sa_family == AF_LINK) + break; + if (a == NULL) { + printf("Error: can't get MAC address\n"); + close(m_hTAP); + return FALSE; + } + + // MAC繧「繝峨Ξ繧ケ菫晏ュ + memcpy(m_MacAddr, LLADDR((struct sockaddr_dl *)a->ifa_addr), + sizeof(m_MacAddr)); + freeifaddrs(ifa); + + printf("Tap device : %s\n", ifr.ifr_name); + + return TRUE; +} +#endif // __NetBSD__ + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL CTapDriver::Cleanup() +{ + ASSERT(this); + + // TAP繝繝舌う繧ケ隗」謾セ + if (m_hTAP != -1) { + close(m_hTAP); + m_hTAP = -1; + } +} + +//--------------------------------------------------------------------------- +// +// MAC繧「繝峨Ξ繧ケ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL CTapDriver::GetMacAddr(BYTE *mac) +{ + ASSERT(this); + ASSERT(mac); + + memcpy(mac, m_MacAddr, sizeof(m_MacAddr)); +} + +//--------------------------------------------------------------------------- +// +// 蜿嶺ソ。 +// +//--------------------------------------------------------------------------- +int FASTCALL CTapDriver::Rx(BYTE *buf) +{ + struct pollfd fds; + DWORD dwReceived; + + ASSERT(this); + ASSERT(m_hTAP != -1); + + // 蜿嶺ソ。蜿ッ閭ス縺ェ繝繝シ繧ソ縺後≠繧九°隱ソ縺ケ繧 + fds.fd = m_hTAP; + fds.events = POLLIN | POLLERR; + fds.revents = 0; + poll(&fds, 1, 0); + if (!(fds.revents & POLLIN)) { + return 0; + } + + // 蜿嶺ソ。 + dwReceived = read(m_hTAP, buf, ETH_FRAME_LEN); + if (dwReceived == (DWORD)-1) { + return 0; + } + + // 蜿嶺ソ。縺梧怏蜉ケ縺ァ縺ゅl縺ー + if (dwReceived > 0) { + // FCS繧帝勁縺乗怙蟆上ヵ繝ャ繝シ繝繧オ繧、繧コ(60繝舌う繝)縺ォ繝代ョ繧」繝ウ繧ー + if (dwReceived < 60) { + memset(buf + dwReceived, 0, 60 - dwReceived); + dwReceived = 60; + } + + // 繝繝溘シ縺ョFCS繧剃サ伜刈縺吶k + memset(buf + dwReceived, 0, 4); + dwReceived += 4; + } + + // 繝舌う繝域焚繧定ソ泌唆 + return dwReceived; +} + +//--------------------------------------------------------------------------- +// +// 騾∽ソ。 +// +//--------------------------------------------------------------------------- +int FASTCALL CTapDriver::Tx(BYTE *buf, int len) +{ + ASSERT(this); + ASSERT(m_hTAP != -1); + + // 騾∽ソ。髢句ァ + return write(m_hTAP, buf, len); +} \ No newline at end of file diff --git a/src/raspberrypi/ctapdriver.h b/src/raspberrypi/ctapdriver.h new file mode 100644 index 00000000..9f7b3f44 --- /dev/null +++ b/src/raspberrypi/ctapdriver.h @@ -0,0 +1,53 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ TAP繝峨Λ繧、繝 ] +// +//--------------------------------------------------------------------------- + +#if !defined(ctapdriver_h) +#define ctapdriver_h + +#ifndef ETH_FRAME_LEN +#define ETH_FRAME_LEN 1514 +#endif + +//=========================================================================== +// +// Tap繝峨Λ繧、繝 +// +//=========================================================================== +class CTapDriver +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CTapDriver(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Init(); + // 蛻晄悄蛹 + void FASTCALL Cleanup(); + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + void FASTCALL GetMacAddr(BYTE *mac); + // MAC繧「繝峨Ξ繧ケ蜿門セ + int FASTCALL Rx(BYTE *buf); + // 蜿嶺ソ。 + int FASTCALL Tx(BYTE *buf, int len); + // 騾∽ソ。 + +private: + BYTE m_MacAddr[6]; + // MAC繧「繝峨Ξ繧ケ + BOOL m_bTxValid; + // 騾∽ソ。譛牙柑繝輔Λ繧ー + int m_hTAP; + // 繝繧」繧ケ繧ッ繝励Μ繧ソ +}; + +#endif // ctapdriver_h diff --git a/src/raspberrypi/disk.cpp b/src/raspberrypi/disk.cpp new file mode 100644 index 00000000..869e1284 --- /dev/null +++ b/src/raspberrypi/disk.cpp @@ -0,0 +1,9160 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// XM6i +// Copyright (C) 2010-2015 isaki@NetBSD.org +// Copyright (C) 2010 Y.Sugahara +// +// Imported sava's Anex86/T98Next image and MO format support patch. +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ 繝繧」繧ケ繧ッ ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "fileio.h" +#ifdef RASCSI +#include "filepath.h" +#include "ctapdriver.h" +#include "cfilesystem.h" +#include "disk.h" +#else +#include "vm.h" +#include "disk.h" +#include "windrv.h" +#include "ctapdriver.h" +#include "mfc_com.h" +#include "mfc_host.h" +#endif // RASCSI + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ +// +//=========================================================================== +//#define DISK_LOG + +#ifdef RASCSI +#define BENDER_SIGNATURE "RaSCSI" +#else +#define BENDER_SIGNATURE "XM6" +#endif + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繝医Λ繝繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskTrack::DiskTrack() +{ + // 蜀驛ィ諠蝣ア縺ョ蛻晄悄蛹 + dt.track = 0; + dt.size = 0; + dt.sectors = 0; + dt.raw = FALSE; + dt.init = FALSE; + dt.changed = FALSE; + dt.length = 0; + dt.buffer = NULL; + dt.maplen = 0; + dt.changemap = NULL; + dt.imgoffset = 0; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskTrack::~DiskTrack() +{ + // 繝。繝「繝ェ隗」謾セ縺ッ陦後≧縺後∬ェ蜍輔そ繝シ繝悶ッ縺励↑縺 + if (dt.buffer) { +#ifdef RASCSI + free(dt.buffer); +#else + delete[] dt.buffer; +#endif // RASCSI + dt.buffer = NULL; + } + if (dt.changemap) { + delete[] dt.changemap; + dt.changemap = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +void FASTCALL DiskTrack::Init( + int track, int size, int sectors, BOOL raw, off64_t imgoff) +{ + ASSERT(track >= 0); + ASSERT((size == 8) || (size == 9) || (size == 11)); + ASSERT((sectors > 0) && (sectors <= 0x100)); + ASSERT(imgoff >= 0); + + // 繝代Λ繝。繝シ繧ソ繧定ィュ螳 + dt.track = track; + dt.size = size; + dt.sectors = sectors; + dt.raw = raw; + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺(繝ュ繝シ繝峨☆繧句ソ隕√≠繧) + dt.init = FALSE; + + // 螟画峩縺輔l縺ヲ縺縺ェ縺 + dt.changed = FALSE; + + // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 + dt.imgoffset = imgoff; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Load(const Filepath& path) +{ + Fileio fio; + off64_t offset; + int i; + int length; + + ASSERT(this); + + // 譌「縺ォ繝ュ繝シ繝峨&繧後※縺繧後ー荳崎ヲ + if (dt.init) { + ASSERT(dt.buffer); + ASSERT(dt.changemap); + return TRUE; + } + + // 繧ェ繝輔そ繝繝医r險育ョ(縺薙l莉・蜑阪ョ繝医Λ繝繧ッ縺ッ256繧サ繧ッ繧ソ菫晄戟縺ィ縺ソ縺ェ縺) + offset = ((off64_t)dt.track << 8); + if (dt.raw) { + ASSERT(dt.size == 11); + offset *= 0x930; + offset += 0x10; + } else { + offset <<= dt.size; + } + + // 螳溘う繝。繝シ繧ク縺セ縺ァ縺ョ繧ェ繝輔そ繝繝医r霑ス蜉 + offset += dt.imgoffset; + + // 繝ャ繝ウ繧ー繧ケ繧定ィ育ョ(縺薙ョ繝医Λ繝繧ッ縺ョ繝繝シ繧ソ繧オ繧、繧コ) + length = dt.sectors << dt.size; + + // 繝舌ャ繝輔ぃ縺ョ繝。繝「繝ェ繧堤「コ菫 + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + try { + // 繝舌ャ繝輔ぃ髟キ縺檎焚縺ェ繧九↑繧芽ァ」謾セ + if (dt.length != (DWORD)length) { + if (dt.buffer) { +#ifdef RASCSI + free(dt.buffer); +#else + delete[] dt.buffer; +#endif // RASCSI + dt.buffer = NULL; + } + } + + // 繝舌ャ繝輔ぃ遒コ菫 + dt.length = length; + if (dt.buffer == NULL) { +#ifdef RASCSI + posix_memalign((void **)&dt.buffer, 512, ((dt.length + 511) / 512) * 512); +#else + dt.buffer = new BYTE[dt.length]; +#endif // RASCSI + } + } + catch (...) { + dt.length = 0; + dt.buffer = NULL; + return FALSE; + } + if (!dt.buffer) { + return FALSE; + } + + // 螟画峩繝槭ャ繝励ョ繝。繝「繝ェ繧堤「コ菫 + try { + // 繝舌ャ繝輔ぃ髟キ縺檎焚縺ェ繧九↑繧芽ァ」謾セ + if (dt.maplen != (DWORD)dt.sectors) { + if (dt.changemap) { + delete[] dt.changemap; + dt.changemap = NULL; + } + } + + // 繝舌ャ繝輔ぃ遒コ菫 + dt.maplen = dt.sectors; + if (dt.changemap == NULL) { + dt.changemap = new BOOL[dt.maplen]; + } + } + catch (...) { + dt.maplen = 0; + dt.changemap = NULL; + return FALSE; + } + if (!dt.changemap) { + return FALSE; + } + + // 螟画峩繝槭ャ繝励r繧ッ繝ェ繧「 + memset(dt.changemap, 0x00, dt.sectors * sizeof(BOOL)); + + // 繝輔ぃ繧、繝ォ縺九i隱ュ縺ソ霎シ繧 +#ifdef RASCSI + if (!fio.OpenDIO(path, Fileio::ReadOnly)) { +#else + if (!fio.Open(path, Fileio::ReadOnly)) { +#endif // RASCSI + return FALSE; + } + if (dt.raw) { + // 蛻蜑イ隱ュ縺ソ + for (i = 0; i < dt.sectors; i++) { + // 繧キ繝シ繧ッ + if (!fio.Seek(offset)) { + fio.Close(); + return FALSE; + } + + // 隱ュ縺ソ霎シ縺ソ + if (!fio.Read(&dt.buffer[i << dt.size], 1 << dt.size)) { + fio.Close(); + return FALSE; + } + + // 谺。縺ョ繧ェ繝輔そ繝繝 + offset += 0x930; + } + } else { + // 騾」邯夊ェュ縺ソ + if (!fio.Seek(offset)) { + fio.Close(); + return FALSE; + } + if (!fio.Read(dt.buffer, length)) { + fio.Close(); + return FALSE; + } + } + fio.Close(); + + // 繝輔Λ繧ー繧堤ォ九※縲∵ュ」蟶ク邨ゆコ + dt.init = TRUE; + dt.changed = FALSE; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Save(const Filepath& path) +{ + off64_t offset; + int i; + Fileio fio; + int length; + + ASSERT(this); + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺代l縺ー荳崎ヲ + if (!dt.init) { + return TRUE; + } + + // 螟画峩縺輔l縺ヲ縺縺ェ縺代l縺ー荳崎ヲ + if (!dt.changed) { + return TRUE; + } + + // 譖ク縺崎セシ繧蠢隕√′縺ゅk + ASSERT(dt.buffer); + ASSERT(dt.changemap); + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + + // RAW繝「繝シ繝峨〒縺ッ譖ク縺崎セシ縺ソ縺ッ縺ゅj縺医↑縺 + ASSERT(!dt.raw); + + // 繧ェ繝輔そ繝繝医r險育ョ(縺薙l莉・蜑阪ョ繝医Λ繝繧ッ縺ッ256繧サ繧ッ繧ソ菫晄戟縺ィ縺ソ縺ェ縺) + offset = ((off64_t)dt.track << 8); + offset <<= dt.size; + + // 螳溘う繝。繝シ繧ク縺セ縺ァ縺ョ繧ェ繝輔そ繝繝医r霑ス蜉 + offset += dt.imgoffset; + + // 繧サ繧ッ繧ソ縺ゅ◆繧翫ョ繝ャ繝ウ繧ー繧ケ繧定ィ育ョ + length = 1 << dt.size; + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (!fio.Open(path, Fileio::ReadWrite)) { + return FALSE; + } + + // 譖ク縺崎セシ縺ソ繝ォ繝シ繝 + for (i = 0; i < dt.sectors; i++) { + // 螟画峩縺輔l縺ヲ縺繧後ー + if (dt.changemap[i]) { + // 繧キ繝シ繧ッ縲∵嶌縺崎セシ縺ソ + if (!fio.Seek(offset + ((off64_t)i << dt.size))) { + fio.Close(); + return FALSE; + } + if (!fio.Write(&dt.buffer[i << dt.size], length)) { + fio.Close(); + return FALSE; + } + + // 螟画峩繝輔Λ繧ー繧定誠縺ィ縺 + dt.changemap[i] = FALSE; + } + } + + // 繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 螟画峩繝輔Λ繧ー繧定誠縺ィ縺励∫オゆコ + dt.changed = FALSE; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繝シ繝峨そ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Read(BYTE *buf, int sec) const +{ + ASSERT(this); + ASSERT(buf); + ASSERT((sec >= 0) & (sec < 0x100)); + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺代l縺ー繧ィ繝ゥ繝シ + if (!dt.init) { + return FALSE; + } + + // 繧サ繧ッ繧ソ縺梧怏蜉ケ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (sec >= dt.sectors) { + return FALSE; + } + + // 繧ウ繝斐シ + ASSERT(dt.buffer); + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + memcpy(buf, &dt.buffer[(off64_t)sec << dt.size], (off64_t)1 << dt.size); + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ゥ繧、繝医そ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskTrack::Write(const BYTE *buf, int sec) +{ + int offset; + int length; + + ASSERT(this); + ASSERT(buf); + ASSERT((sec >= 0) & (sec < 0x100)); + ASSERT(!dt.raw); + + // 蛻晄悄蛹悶&繧後※縺縺ェ縺代l縺ー繧ィ繝ゥ繝シ + if (!dt.init) { + return FALSE; + } + + // 繧サ繧ッ繧ソ縺梧怏蜉ケ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (sec >= dt.sectors) { + return FALSE; + } + + // 繧ェ繝輔そ繝繝医√Ξ繝ウ繧ー繧ケ繧定ィ育ョ + offset = sec << dt.size; + length = 1 << dt.size; + + // 豈碑シ + ASSERT(dt.buffer); + ASSERT((dt.size == 8) || (dt.size == 9) || (dt.size == 11)); + ASSERT((dt.sectors > 0) && (dt.sectors <= 0x100)); + if (memcmp(buf, &dt.buffer[offset], length) == 0) { + // 蜷後§繧ゅョ繧呈嶌縺崎セシ繧ゅ≧縺ィ縺励※縺繧九ョ縺ァ縲∵ュ」蟶ク邨ゆコ + return TRUE; + } + + // 繧ウ繝斐シ縲∝、画峩縺ゅj + memcpy(&dt.buffer[offset], buf, length); + dt.changemap[sec] = TRUE; + dt.changed = TRUE; + + // 謌仙粥 + return TRUE; +} + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskCache::DiskCache( + const Filepath& path, int size, int blocks, off64_t imgoff) +{ + int i; + + ASSERT((size == 8) || (size == 9) || (size == 11)); + ASSERT(blocks > 0); + ASSERT(imgoff >= 0); + + // 繧ュ繝」繝繧キ繝・繝ッ繝シ繧ッ + for (i = 0; i < CacheMax; i++) { + cache[i].disktrk = NULL; + cache[i].serial = 0; + } + + // 縺昴ョ莉 + serial = 0; + sec_path = path; + sec_size = size; + sec_blocks = blocks; + cd_raw = FALSE; + imgoffset = imgoff; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +DiskCache::~DiskCache() +{ + // 繝医Λ繝繧ッ繧偵け繝ェ繧「 + Clear(); +} + +//--------------------------------------------------------------------------- +// +// RAW繝「繝シ繝芽ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL DiskCache::SetRawMode(BOOL raw) +{ + ASSERT(this); + ASSERT(sec_size == 11); + + // 險ュ螳 + cd_raw = raw; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Save() +{ + int i; + + ASSERT(this); + + // 繝医Λ繝繧ッ繧剃ソ晏ュ + for (i = 0; i < CacheMax; i++) { + // 譛牙柑縺ェ繝医Λ繝繧ッ縺 + if (cache[i].disktrk) { + // 菫晏ュ + if (!cache[i].disktrk->Save(sec_path)) { + return FALSE; + } + } + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・諠蝣ア蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::GetCache(int index, int& track, DWORD& aserial) const +{ + ASSERT(this); + ASSERT((index >= 0) && (index < CacheMax)); + + // 譛ェ菴ソ逕ィ縺ェ繧宇ALSE + if (!cache[index].disktrk) { + return FALSE; + } + + // 繝医Λ繝繧ッ縺ィ繧キ繝ェ繧「繝ォ繧定ィュ螳 + track = cache[index].disktrk->GetTrack(); + aserial = cache[index].serial; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繧「 +// +//--------------------------------------------------------------------------- +void FASTCALL DiskCache::Clear() +{ + int i; + + ASSERT(this); + + // 繧ュ繝」繝繧キ繝・繝ッ繝シ繧ッ繧定ァ」謾セ + for (i = 0; i < CacheMax; i++) { + if (cache[i].disktrk) { + delete cache[i].disktrk; + cache[i].disktrk = NULL; + } + } +} + +//--------------------------------------------------------------------------- +// +// 繧サ繧ッ繧ソ繝ェ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Read(BYTE *buf, int block) +{ + int track; + DiskTrack *disktrk; + + ASSERT(this); + ASSERT(sec_size != 0); + + // 蜈医↓譖エ譁ー + Update(); + + // 繝医Λ繝繧ッ繧堤ョ怜コ(256繧サ繧ッ繧ソ/繝医Λ繝繧ッ縺ォ蝗コ螳) + track = block >> 8; + + // 縺昴ョ繝医Λ繝繧ッ繝繝シ繧ソ繧貞セ励k + disktrk = Assign(track); + if (!disktrk) { + return FALSE; + } + + // 繝医Λ繝繧ッ縺ォ莉サ縺帙k + return disktrk->Read(buf, (BYTE)block); +} + +//--------------------------------------------------------------------------- +// +// 繧サ繧ッ繧ソ繝ゥ繧、繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Write(const BYTE *buf, int block) +{ + int track; + DiskTrack *disktrk; + + ASSERT(this); + ASSERT(sec_size != 0); + + // 蜈医↓譖エ譁ー + Update(); + + // 繝医Λ繝繧ッ繧堤ョ怜コ(256繧サ繧ッ繧ソ/繝医Λ繝繧ッ縺ォ蝗コ螳) + track = block >> 8; + + // 縺昴ョ繝医Λ繝繧ッ繝繝シ繧ソ繧貞セ励k + disktrk = Assign(track); + if (!disktrk) { + return FALSE; + } + + // 繝医Λ繝繧ッ縺ォ莉サ縺帙k + return disktrk->Write(buf, (BYTE)block); +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ縺ョ蜑イ繧雁ス薙※ +// +//--------------------------------------------------------------------------- +DiskTrack* FASTCALL DiskCache::Assign(int track) +{ + int i; + int c; + DWORD s; + DiskTrack *disktrk; + + ASSERT(this); + ASSERT(sec_size != 0); + ASSERT(track >= 0); + + // 縺セ縺壹∵里縺ォ蜑イ繧雁ス薙※縺輔l縺ヲ縺縺ェ縺縺玖ェソ縺ケ繧 + for (i = 0; i < CacheMax; i++) { + if (cache[i].disktrk) { + if (cache[i].disktrk->GetTrack() == track) { + // 繝医Λ繝繧ッ縺御ク閾エ + cache[i].serial = serial; + return cache[i].disktrk; + } + } + } + + // 谺。縺ォ縲∫ゥコ縺縺ヲ縺繧九b縺ョ縺後↑縺縺玖ェソ縺ケ繧 + for (i = 0; i < CacheMax; i++) { + if (!cache[i].disktrk) { + // 繝ュ繝シ繝峨r隧ヲ縺ソ繧 + if (Load(i, track)) { + // 繝ュ繝シ繝画仙粥 + cache[i].serial = serial; + return cache[i].disktrk; + } + + // 繝ュ繝シ繝牙、ア謨 + return NULL; + } + } + + // 譛蠕後↓縲√す繝ェ繧「繝ォ逡ェ蜿キ縺ョ荳逡ェ闍・縺繧ゅョ繧呈爾縺励∝炎髯、縺吶k + + // 繧、繝ウ繝繝繧ッ繧ケ0繧貞呵」彡縺ィ縺吶k + s = cache[0].serial; + c = 0; + + // 蛟呵」懊→繧キ繝ェ繧「繝ォ繧呈ッ碑シ縺励√h繧雁ー上&縺繧ゅョ縺ク譖エ譁ー縺吶k + for (i = 0; i < CacheMax; i++) { + ASSERT(cache[i].disktrk); + + // 譌「縺ォ蟄伜惠縺吶k繧キ繝ェ繧「繝ォ縺ィ豈碑シ縲∵峩譁ー + if (cache[i].serial < s) { + s = cache[i].serial; + c = i; + } + } + + // 縺薙ョ繝医Λ繝繧ッ繧剃ソ晏ュ + if (!cache[c].disktrk->Save(sec_path)) { + return NULL; + } + + // 縺薙ョ繝医Λ繝繧ッ繧貞炎髯、 + disktrk = cache[c].disktrk; + cache[c].disktrk = NULL; + + // 繝ュ繝シ繝 + if (Load(c, track, disktrk)) { + // 繝ュ繝シ繝画仙粥 + cache[c].serial = serial; + return cache[c].disktrk; + } + + // 繝ュ繝シ繝牙、ア謨 + return NULL; +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ縺ョ繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL DiskCache::Load(int index, int track, DiskTrack *disktrk) +{ + int sectors; + + ASSERT(this); + ASSERT((index >= 0) && (index < CacheMax)); + ASSERT(track >= 0); + ASSERT(!cache[index].disktrk); + + // 縺薙ョ繝医Λ繝繧ッ縺ョ繧サ繧ッ繧ソ謨ー繧貞叙蠕 + sectors = sec_blocks - (track << 8); + ASSERT(sectors > 0); + if (sectors > 0x100) { + sectors = 0x100; + } + + // 繝繧」繧ケ繧ッ繝医Λ繝繧ッ繧剃ス懈 + if (disktrk == NULL) { + disktrk = new DiskTrack(); + } + + // 繝繧」繧ケ繧ッ繝医Λ繝繧ッ繧貞晄悄蛹 + disktrk->Init(track, sec_size, sectors, cd_raw, imgoffset); + + // 繝ュ繝シ繝峨r隧ヲ縺ソ繧 + if (!disktrk->Load(sec_path)) { + // 螟ア謨 + delete disktrk; + return FALSE; + } + + // 蜑イ繧雁ス薙※謌仙粥縲√Ρ繝シ繧ッ繧定ィュ螳 + cache[index].disktrk = disktrk; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝ェ繧「繝ォ逡ェ蜿キ縺ョ譖エ譁ー +// +//--------------------------------------------------------------------------- +void FASTCALL DiskCache::Update() +{ + int i; + + ASSERT(this); + + // 譖エ譁ー縺励※縲0莉・螟悶ッ菴輔b縺励↑縺 + serial++; + if (serial != 0) { + return; + } + + // 蜈ィ繧ュ繝」繝繧キ繝・縺ョ繧キ繝ェ繧「繝ォ繧偵け繝ェ繧「(32bit繝ォ繝シ繝励@縺ヲ縺繧) + for (i = 0; i < CacheMax; i++) { + cache[i].serial = 0; + } +} + + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Disk::Disk() +{ + // 繝ッ繝シ繧ッ蛻晄悄蛹 + disk.id = MAKEID('N', 'U', 'L', 'L'); + disk.ready = FALSE; + disk.writep = FALSE; + disk.readonly = FALSE; + disk.removable = FALSE; + disk.lock = FALSE; + disk.attn = FALSE; + disk.reset = FALSE; + disk.size = 0; + disk.blocks = 0; + disk.lun = 0; + disk.code = 0; + disk.dcache = NULL; + disk.imgoffset = 0; + + // 縺昴ョ莉 + cache_wb = TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Disk::~Disk() +{ + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ョ菫晏ュ + if (disk.ready) { + // 繝ャ繝繧」縺ョ蝣エ蜷医ョ縺ソ + if (disk.dcache) { + disk.dcache->Save(); + } + } + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ョ蜑企勁 + if (disk.dcache) { + delete disk.dcache; + disk.dcache = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::Reset() +{ + ASSERT(this); + + // 繝ュ繝繧ッ縺ェ縺励√い繝繝ウ繧キ繝ァ繝ウ縺ェ縺励√Μ繧サ繝繝医≠繧 + disk.lock = FALSE; + disk.attn = FALSE; + disk.reset = TRUE; +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Save(Fileio *fio, int ver) +{ + DWORD sz; + DWORD padding; + + ASSERT(this); + ASSERT(fio); + + // 繧オ繧、繧コ繧偵そ繝シ繝 + sz = 52; + if (!fio->Write(&sz, sizeof(sz))) { + return FALSE; + } + + // 螳滉ス薙r繧サ繝シ繝 + PROP_EXPORT(fio, disk.id); + PROP_EXPORT(fio, disk.ready); + PROP_EXPORT(fio, disk.writep); + PROP_EXPORT(fio, disk.readonly); + PROP_EXPORT(fio, disk.removable); + PROP_EXPORT(fio, disk.lock); + PROP_EXPORT(fio, disk.attn); + PROP_EXPORT(fio, disk.reset); + PROP_EXPORT(fio, disk.size); + PROP_EXPORT(fio, disk.blocks); + PROP_EXPORT(fio, disk.lun); + PROP_EXPORT(fio, disk.code); + PROP_EXPORT(fio, padding); + + // 繝代せ繧偵そ繝シ繝 + if (!diskpath.Save(fio, ver)) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Load(Fileio *fio, int ver) +{ + DWORD sz; + disk_t buf; + DWORD padding; + Filepath path; + + ASSERT(this); + ASSERT(fio); + + // version2.03繧医j蜑阪ッ縲√ョ繧」繧ケ繧ッ縺ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0202) { + return TRUE; + } + + // 迴セ蝨ィ縺ョ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧貞炎髯、 + if (disk.dcache) { + disk.dcache->Save(); + delete disk.dcache; + disk.dcache = NULL; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 52) { + return FALSE; + } + + // 繝舌ャ繝輔ぃ縺ク繝ュ繝シ繝 + PROP_IMPORT(fio, buf.id); + PROP_IMPORT(fio, buf.ready); + PROP_IMPORT(fio, buf.writep); + PROP_IMPORT(fio, buf.readonly); + PROP_IMPORT(fio, buf.removable); + PROP_IMPORT(fio, buf.lock); + PROP_IMPORT(fio, buf.attn); + PROP_IMPORT(fio, buf.reset); + PROP_IMPORT(fio, buf.size); + PROP_IMPORT(fio, buf.blocks); + PROP_IMPORT(fio, buf.lun); + PROP_IMPORT(fio, buf.code); + PROP_IMPORT(fio, padding); + + // 繝代せ繧偵Ο繝シ繝 + if (!path.Load(fio, ver)) { + return FALSE; + } + + // ID縺御ク閾エ縺励◆蝣エ蜷医ョ縺ソ縲∫ァサ蜍 + if (disk.id == buf.id) { + // NULL縺ェ繧我ス輔b縺励↑縺 + if (IsNULL()) { + return TRUE; + } + + // 繧サ繝シ繝悶@縺滓凾縺ィ蜷後§遞ョ鬘槭ョ繝繝舌う繧ケ + disk.ready = FALSE; + if (Open(path)) { + // Open蜀縺ァ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ッ菴懈舌&繧後※縺繧 + // 繝励Ο繝代ユ繧」縺ョ縺ソ遘サ蜍 + if (!disk.readonly) { + disk.writep = buf.writep; + } + disk.lock = buf.lock; + disk.attn = buf.attn; + disk.reset = buf.reset; + disk.lun = buf.lun; + disk.code = buf.code; + + // 豁」蟶ク縺ォ繝ュ繝シ繝峨〒縺阪◆ + return TRUE; + } + } + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・蜀堺ス懈 + if (!IsReady()) { + disk.dcache = NULL; + } else { + disk.dcache = new DiskCache(diskpath, disk.size, disk.blocks); + } + + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// NULL繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::IsNULL() const +{ + ASSERT(this); + + if (disk.id == MAKEID('N', 'U', 'L', 'L')) { + return TRUE; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// SASI繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::IsSASI() const +{ + ASSERT(this); + + if (disk.id == MAKEID('S', 'A', 'H', 'D')) { + return TRUE; + } + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// 窶サ豢セ逕溘け繝ゥ繧ケ縺ァ縲√が繝シ繝励Φ謌仙粥蠕後ョ蠕悟ヲ逅縺ィ縺励※蜻シ縺ウ蜃コ縺吶%縺ィ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Open(const Filepath& path, BOOL /*attn*/) +{ + Fileio fio; + + ASSERT(this); + ASSERT((disk.size == 8) || (disk.size == 9) || (disk.size == 11)); + ASSERT(disk.blocks > 0); + + // 繝ャ繝繧」 + disk.ready = TRUE; + + // 繧ュ繝」繝繧キ繝・蛻晄悄蛹 + ASSERT(!disk.dcache); + disk.dcache = new DiskCache( + path, disk.size, disk.blocks, disk.imgoffset); + + // 隱ュ縺ソ譖ク縺阪が繝シ繝励Φ蜿ッ閭ス縺 + if (fio.Open(path, Fileio::ReadWrite)) { + // 譖ク縺崎セシ縺ソ險ア蜿ッ縲√Μ繝シ繝峨が繝ウ繝ェ繝シ縺ァ縺ェ縺 + disk.writep = FALSE; + disk.readonly = FALSE; + fio.Close(); + } else { + // 譖ク縺崎セシ縺ソ遖∵ュ「縲√Μ繝シ繝峨が繝ウ繝ェ繝シ + disk.writep = TRUE; + disk.readonly = TRUE; + } + + // 繝ュ繝繧ッ縺輔l縺ヲ縺縺ェ縺 + disk.lock = FALSE; + + // 繝代せ菫晏ュ + diskpath = path; + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧、繧ク繧ァ繧ッ繝 +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::Eject(BOOL force) +{ + ASSERT(this); + + // 繝ェ繝繝シ繝舌ヶ繝ォ縺ァ縺ェ縺代l縺ー繧、繧ク繧ァ繧ッ繝医〒縺阪↑縺 + if (!disk.removable) { + return; + } + + // 繝ャ繝繧」縺ァ縺ェ縺代l縺ー繧、繧ク繧ァ繧ッ繝亥ソ隕√↑縺 + if (!disk.ready) { + return; + } + + // 蠑キ蛻カ繝輔Λ繧ー縺後↑縺蝣エ蜷医√Ο繝繧ッ縺輔l縺ヲ縺縺ェ縺縺薙→縺悟ソ隕 + if (!force) { + if (disk.lock) { + return; + } + } + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧貞炎髯、 + disk.dcache->Save(); + delete disk.dcache; + disk.dcache = NULL; + + // 繝弱ャ繝医Ξ繝繧」縲√い繝繝ウ繧キ繝ァ繝ウ縺ェ縺 + disk.ready = FALSE; + disk.writep = FALSE; + disk.readonly = FALSE; + disk.attn = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 譖ク縺崎セシ縺ソ遖∵ュ「 +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::WriteP(BOOL writep) +{ + ASSERT(this); + + // 繝ャ繝繧」縺ァ縺ゅk縺薙→ + if (!disk.ready) { + return; + } + + // Read Only縺ョ蝣エ蜷医ッ縲√励Ο繝繧ッ繝育憾諷九ョ縺ソ + if (disk.readonly) { + ASSERT(disk.writep); + return; + } + + // 繝輔Λ繧ー險ュ螳 + disk.writep = writep; +} + +//--------------------------------------------------------------------------- +// +// 蜀驛ィ繝ッ繝シ繧ッ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::GetDisk(disk_t *buffer) const +{ + ASSERT(this); + ASSERT(buffer); + + // 蜀驛ィ繝ッ繝シ繧ッ繧偵さ繝斐シ + *buffer = disk; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL Disk::GetPath(Filepath& path) const +{ + path = diskpath; +} + +//--------------------------------------------------------------------------- +// +// 繝輔Λ繝繧キ繝・ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Flush() +{ + ASSERT(this); + + // 繧ュ繝」繝繧キ繝・縺後↑縺代l縺ー菴輔b縺励↑縺 + if (!disk.dcache) { + return TRUE; + } + + // 繧ュ繝」繝繧キ繝・繧剃ソ晏ュ + return disk.dcache->Save(); +} + +//--------------------------------------------------------------------------- +// +// 繝ャ繝繧」繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::CheckReady() +{ + ASSERT(this); + + // 繝ェ繧サ繝繝医↑繧峨√せ繝繝シ繧ソ繧ケ繧定ソ斐☆ + if (disk.reset) { + disk.code = DISK_DEVRESET; + disk.reset = FALSE; + return FALSE; + } + + // 繧「繝繝ウ繧キ繝ァ繝ウ縺ェ繧峨√せ繝繝シ繧ソ繧ケ繧定ソ斐☆ + if (disk.attn) { + disk.code = DISK_ATTENTION; + disk.attn = FALSE; + return FALSE; + } + + // 繝弱ャ繝医Ξ繝繧」縺ェ繧峨√せ繝繝シ繧ソ繧ケ繧定ソ斐☆ + if (!disk.ready) { + disk.code = DISK_NOTREADY; + return FALSE; + } + + // 繧ィ繝ゥ繝シ縺ェ縺励↓蛻晄悄蛹 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// 窶サ蟶ク譎よ仙粥縺吶k蠢隕√′縺ゅk +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::Inquiry( + const DWORD* /*cdb*/, BYTE* /*buf*/, DWORD /*major*/, DWORD /*minor*/) +{ + ASSERT(this); + + // 繝繝輔か繝ォ繝医ッINQUIRY螟ア謨 + disk.code = DISK_INVALIDCMD; + return 0; +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE +// 窶サSASI縺ッ蛻・蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::RequestSense(const DWORD *cdb, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + + // 繧ィ繝ゥ繝シ縺後↑縺蝣エ蜷医↓髯舌j縲√ヮ繝繝医Ξ繝繧」繧偵メ繧ァ繝繧ッ + if (disk.code == DISK_NOERROR) { + if (!disk.ready) { + disk.code = DISK_NOTREADY; + } + } + + // 繧オ繧、繧コ豎コ螳(繧「繝ュ繧ア繝シ繧キ繝ァ繝ウ繝ャ繝ウ繧ー繧ケ縺ォ蠕薙≧) + size = (int)cdb[4]; + ASSERT((size >= 0) && (size < 0x100)); + + // SCSI-1縺ァ縺ッ縲√し繧、繧コ0縺ョ縺ィ縺阪↓4繝舌う繝郁サ「騾√☆繧(SCSI-2縺ァ縺ッ縺薙ョ莉墓ァ倥ッ蜑企勁) + if (size == 0) { + size = 4; + } + + // 繝舌ャ繝輔ぃ繧偵け繝ェ繧「 + memset(buf, 0, size); + + // 諡。蠑オ繧サ繝ウ繧ケ繝繝シ繧ソ繧貞性繧√◆縲18繝舌う繝医r險ュ螳 + buf[0] = 0x70; + buf[2] = (BYTE)(disk.code >> 16); + buf[7] = 10; + buf[12] = (BYTE)(disk.code >> 8); + buf[13] = (BYTE)disk.code; + + // 繧ウ繝シ繝峨r繧ッ繝ェ繧「 + disk.code = 0x00; + + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT繝√ぉ繝繧ッ +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::SelectCheck(const DWORD *cdb) +{ + int length; + + ASSERT(this); + ASSERT(cdb); + + // SCSIHD縺ァ縺ェ縺上そ繝シ繝悶ヱ繝ゥ繝。繝シ繧ソ縺瑚ィュ螳壹&繧後※縺繧後ー繧ィ繝ゥ繝シ + if (disk.id != MAKEID('S', 'C', 'H', 'D')) { + // 繧サ繝シ繝悶ヱ繝ゥ繝。繝シ繧ソ縺瑚ィュ螳壹&繧後※縺繧後ー繧ィ繝ゥ繝シ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 繝代Λ繝。繝シ繧ソ繝ャ繝ウ繧ー繧ケ縺ァ謖螳壹&繧後◆繝繝シ繧ソ繧貞女縺大叙繧 + length = (int)cdb[4]; + return length; +} + + +//--------------------------------------------------------------------------- +// +// MODE SELECT(10)繝√ぉ繝繧ッ +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::SelectCheck10(const DWORD *cdb) +{ + DWORD length; + + ASSERT(this); + ASSERT(cdb); + + // SCSIHD縺ァ縺ェ縺上そ繝シ繝悶ヱ繝ゥ繝。繝シ繧ソ縺瑚ィュ螳壹&繧後※縺繧後ー繧ィ繝ゥ繝シ + if (disk.id != MAKEID('S', 'C', 'H', 'D')) { + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 繝代Λ繝。繝シ繧ソ繝ャ繝ウ繧ー繧ケ縺ァ謖螳壹&繧後◆繝繝シ繧ソ繧貞女縺大叙繧 + length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + + return (int)length; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ + ASSERT(this); + ASSERT(buf); + ASSERT(length >= 0); + + // 險ュ螳壹〒縺阪↑縺 + disk.code = DISK_INVALIDPRM; + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ModeSense(const DWORD *cdb, BYTE *buf) +{ + int page; + int length; + int size; + BOOL valid; + BOOL change; + int ret; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x1a); + + // 繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = (int)cdb[4]; + ASSERT((length >= 0) && (length < 0x100)); + memset(buf, 0, length); + + // 螟画峩蜿ッ閭ス繝輔Λ繧ー蜿門セ + if ((cdb[2] & 0xc0) == 0x40) { + change = TRUE; + } else { + change = FALSE; + } + + // 繝壹シ繧ク繧ウ繝シ繝牙叙蠕(0x00縺ッ譛蛻昴°繧益alid) + page = cdb[2] & 0x3f; + if (page == 0x00) { + valid = TRUE; + } else { + valid = FALSE; + } + + // 蝓コ譛ャ諠蝣ア + size = 4; + + // MEDIUM TYPE + if (disk.id == MAKEID('S', 'C', 'M', 'O')) { + buf[1] = 0x03; // optical reversible or erasable + } + + // DEVICE SPECIFIC PARAMETER + if (disk.writep) { + buf[2] = 0x80; + } + + // DBD縺0縺ェ繧峨√ヶ繝ュ繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち繧定ソス蜉 + if ((cdb[1] & 0x08) == 0) { + // 繝「繝シ繝峨ヱ繝ゥ繝。繝シ繧ソ繝倥ャ繝 + buf[3] = 0x08; + + // 繝ャ繝繧」縺ョ蝣エ蜷医↓髯舌j + if (disk.ready) { + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ謨ー) + buf[5] = (BYTE)(disk.blocks >> 16); + buf[6] = (BYTE)(disk.blocks >> 8); + buf[7] = (BYTE)disk.blocks; + + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ) + size = 1 << disk.size; + buf[9] = (BYTE)(size >> 16); + buf[10] = (BYTE)(size >> 8); + buf[11] = (BYTE)size; + } + + // 繧オ繧、繧コ蜀崎ィュ螳 + size = 12; + } + + // 繝壹シ繧ク繧ウ繝シ繝1(read-write error recovery) + if ((page == 0x01) || (page == 0x3f)) { + size += AddError(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝3(format device) + if ((page == 0x03) || (page == 0x3f)) { + size += AddFormat(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝4(drive parameter) + if ((page == 0x04) || (page == 0x3f)) { + size += AddDrive(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝6(optical) + if (disk.id == MAKEID('S', 'C', 'M', 'O')) { + if ((page == 0x06) || (page == 0x3f)) { + size += AddOpt(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝8(caching) + if ((page == 0x08) || (page == 0x3f)) { + size += AddCache(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝13(CD-ROM) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0d) || (page == 0x3f)) { + size += AddCDROM(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝14(CD-DA) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0e) || (page == 0x3f)) { + size += AddCDDA(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク(繝吶Φ繝迚ケ谿) + ret = AddVendor(page, change, &buf[size]); + if (ret > 0) { + size += ret; + valid = TRUE; + } + + // 繝「繝シ繝峨ョ繝シ繧ソ繝ャ繝ウ繧ー繧ケ繧呈怙邨りィュ螳 + buf[0] = (BYTE)(size - 1); + + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繝壹シ繧ク縺 + if (!valid) { + disk.code = DISK_INVALIDCDB; + return 0; + } + + // MODE SENSE謌仙粥 + disk.code = DISK_NOERROR; + return length; +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE(10) +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ModeSense10(const DWORD *cdb, BYTE *buf) +{ + int page; + int length; + int size; + BOOL valid; + BOOL change; + int ret; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x5a); + + // 繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + ASSERT((length >= 0) && (length < 0x800)); + memset(buf, 0, length); + + // 螟画峩蜿ッ閭ス繝輔Λ繧ー蜿門セ + if ((cdb[2] & 0xc0) == 0x40) { + change = TRUE; + } else { + change = FALSE; + } + + // 繝壹シ繧ク繧ウ繝シ繝牙叙蠕(0x00縺ッ譛蛻昴°繧益alid) + page = cdb[2] & 0x3f; + if (page == 0x00) { + valid = TRUE; + } else { + valid = FALSE; + } + + // 蝓コ譛ャ諠蝣ア + size = 4; + if (disk.writep) { + buf[2] = 0x80; + } + + // DBD縺0縺ェ繧峨√ヶ繝ュ繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち繧定ソス蜉 + if ((cdb[1] & 0x08) == 0) { + // 繝「繝シ繝峨ヱ繝ゥ繝。繝シ繧ソ繝倥ャ繝 + buf[3] = 0x08; + + // 繝ャ繝繧」縺ョ蝣エ蜷医↓髯舌j + if (disk.ready) { + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ謨ー) + buf[5] = (BYTE)(disk.blocks >> 16); + buf[6] = (BYTE)(disk.blocks >> 8); + buf[7] = (BYTE)disk.blocks; + + // 繝悶Ο繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち(繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ) + size = 1 << disk.size; + buf[9] = (BYTE)(size >> 16); + buf[10] = (BYTE)(size >> 8); + buf[11] = (BYTE)size; + } + + // 繧オ繧、繧コ蜀崎ィュ螳 + size = 12; + } + + // 繝壹シ繧ク繧ウ繝シ繝1(read-write error recovery) + if ((page == 0x01) || (page == 0x3f)) { + size += AddError(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝3(format device) + if ((page == 0x03) || (page == 0x3f)) { + size += AddFormat(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝4(drive parameter) + if ((page == 0x04) || (page == 0x3f)) { + size += AddDrive(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝6(optical) + if (disk.id == MAKEID('S', 'C', 'M', 'O')) { + if ((page == 0x06) || (page == 0x3f)) { + size += AddOpt(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝8(caching) + if ((page == 0x08) || (page == 0x3f)) { + size += AddCache(change, &buf[size]); + valid = TRUE; + } + + // 繝壹シ繧ク繧ウ繝シ繝13(CD-ROM) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0d) || (page == 0x3f)) { + size += AddCDROM(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク繧ウ繝シ繝14(CD-DA) + if (disk.id == MAKEID('S', 'C', 'C', 'D')) { + if ((page == 0x0e) || (page == 0x3f)) { + size += AddCDDA(change, &buf[size]); + valid = TRUE; + } + } + + // 繝壹シ繧ク(繝吶Φ繝迚ケ谿) + ret = AddVendor(page, change, &buf[size]); + if (ret > 0) { + size += ret; + valid = TRUE; + } + + // 繝「繝シ繝峨ョ繝シ繧ソ繝ャ繝ウ繧ー繧ケ繧呈怙邨りィュ螳 + buf[0] = (BYTE)(size - 1); + + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繝壹シ繧ク縺 + if (!valid) { + disk.code = DISK_INVALIDCDB; + return 0; + } + + // MODE SENSE謌仙粥 + disk.code = DISK_NOERROR; + return length; +} + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddError(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x01; + buf[1] = 0x0a; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 12; + } + + // 繝ェ繝医Λ繧、繧ォ繧ヲ繝ウ繝医ッ0縲√Μ繝溘ャ繝医ち繧、繝縺ッ陬鄂ョ蜀驛ィ縺ョ繝繝輔か繝ォ繝亥、繧剃スソ逕ィ + return 12; +} + +//--------------------------------------------------------------------------- +// +// 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddFormat(BOOL change, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x80 | 0x03; + buf[1] = 0x16; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚縺ッ螟画峩蜿ッ閭ス縺ォ隕九○繧(螳滄圀縺ォ縺ッ螟画峩縺ァ縺阪↑縺縺) + if (change) { + buf[0xc] = 0xff; + buf[0xd] = 0xff; + return 24; + } + + if (disk.ready) { + // 1繧セ繝シ繝ウ縺ョ繝医Λ繝繧ッ謨ー繧8縺ォ險ュ螳(TODO) + buf[0x3] = 0x08; + + // 繧サ繧ッ繧ソ/繝医Λ繝繧ッ繧25縺ォ險ュ螳(TODO) + buf[0xa] = 0x00; + buf[0xb] = 0x19; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧定ィュ螳 + size = 1 << disk.size; + buf[0xc] = (BYTE)(size >> 8); + buf[0xd] = (BYTE)size; + } + + // 繝ェ繝繝シ繝舌ヶ繝ォ螻樊ァ繧定ィュ螳 + if (disk.removable) { + buf[20] = 0x20; + } + + return 24; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddDrive(BOOL change, BYTE *buf) +{ + DWORD cylinder; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x04; + buf[1] = 0x16; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 24; + } + + if (disk.ready) { + // 繧キ繝ェ繝ウ繝謨ー繧定ィュ螳(邱上ヶ繝ュ繝繧ッ謨ー繧25繧サ繧ッ繧ソ/繝医Λ繝繧ッ縺ィ8繝倥ャ繝峨〒髯、邂) + cylinder = disk.blocks; + cylinder >>= 3; + cylinder /= 25; + buf[0x2] = (BYTE)(cylinder >> 16); + buf[0x3] = (BYTE)(cylinder >> 8); + buf[0x4] = (BYTE)cylinder; + + // 繝倥ャ繝峨r8縺ァ蝗コ螳 + buf[0x5] = 0x8; + } + + return 24; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝励ユ繧」繧ォ繝ォ繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddOpt(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x06; + buf[1] = 0x02; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 4; + } + + // 譖エ譁ー繝悶Ο繝繧ッ縺ョ繝ャ繝昴シ繝医ッ陦後o縺ェ縺 + return 4; +} + +//--------------------------------------------------------------------------- +// +// 繧ュ繝」繝繧キ繝・繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddCache(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x08; + buf[1] = 0x0a; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 12; + } + + // 隱ュ縺ソ霎シ縺ソ繧ュ繝」繝繧キ繝・縺ョ縺ソ譛牙柑縲√励Μ繝輔ぉ繝繝√ッ陦後o縺ェ縺 + return 12; +} + +//--------------------------------------------------------------------------- +// +// CD-ROM繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddCDROM(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x0d; + buf[1] = 0x06; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 8; + } + + // 繧、繝ウ繧「繧ッ繝繧」繝悶ち繧、繝槭ッ2sec + buf[3] = 0x05; + + // MSF蛟肴焚縺ッ縺昴l縺槭l60, 75 + buf[5] = 60; + buf[7] = 75; + + return 8; +} + +//--------------------------------------------------------------------------- +// +// CD-DA繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddCDDA(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x0e; + buf[1] = 0x0e; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 16; + } + + // 繧ェ繝シ繝繧」繧ェ縺ッ謫堺ス懷ョ御コ繧貞セ縺。縲 隍謨ー繝医Λ繝繧ッ縺ォ縺セ縺溘′繧輝LAY繧定ィア蜿ッ縺吶k + return 16; +} + +//--------------------------------------------------------------------------- +// +// Vendor迚ケ谿翫壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::AddVendor(int page, BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + return 0; +} + +//--------------------------------------------------------------------------- +// +// READ DEFECT DATA(10) +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ReadDefectData10(const DWORD *cdb, BYTE *buf) +{ + DWORD length; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x37); + + // 繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = cdb[7]; + length <<= 8; + length |= cdb[8]; + if (length > 0x800) { + length = 0x800; + } + ASSERT((length >= 0) && (length < 0x800)); + memset(buf, 0, length); + + // P/G/FORMAT + buf[1] = (cdb[1] & 0x18) | 5; + buf[3] = 8; + + buf[4] = 0xff; + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + + buf[8] = 0xff; + buf[9] = 0xff; + buf[10] = 0xff; + buf[11] = 0xff; + + // 繝ェ繧ケ繝育┌縺 + disk.code = DISK_NODEFECT; + return 4; +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::TestUnitReady(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // TEST UNIT READY謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// REZERO UNIT +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Rezero(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // REZERO謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// FORMAT UNIT +// 窶サSASI縺ッ繧ェ繝壹さ繝シ繝$06縲ヾCSI縺ッ繧ェ繝壹さ繝シ繝$04 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Format(const DWORD *cdb) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // FMTDATA=1縺ッ繧オ繝昴シ繝医@縺ェ縺(菴縺優EFECT LIST縺檎┌縺縺ェ繧碓K) + if ((cdb[1] & 0x10) != 0 && cdb[4] != 0) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // FORMAT謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// REASSIGN BLOCKS +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Reassign(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // REASSIGN BLOCKS謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// READ +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::Read(BYTE *buf, DWORD block) +{ + ASSERT(this); + ASSERT(buf); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝医シ繧ソ繝ォ繝悶Ο繝繧ッ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (block >= disk.blocks) { + disk.code = DISK_INVALIDLBA; + return 0; + } + + // 繧ュ繝」繝繧キ繝・縺ォ莉サ縺帙k + if (!disk.dcache->Read(buf, block)) { + disk.code = DISK_READFAULT; + return 0; + } + + // 謌仙粥 + return (1 << disk.size); +} + +//--------------------------------------------------------------------------- +// +// WRITE繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::WriteCheck(DWORD block) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝医シ繧ソ繝ォ繝悶Ο繝繧ッ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (block >= disk.blocks) { + return 0; + } + + // 譖ク縺崎セシ縺ソ遖∵ュ「縺ェ繧峨お繝ゥ繝シ + if (disk.writep) { + disk.code = DISK_WRITEPROTECT; + return 0; + } + + // 謌仙粥 + return (1 << disk.size); +} + +//--------------------------------------------------------------------------- +// +// WRITE +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Write(const BYTE *buf, DWORD block) +{ + ASSERT(this); + ASSERT(buf); + + // 繝ャ繝繧」縺ァ縺ェ縺代l縺ー繧ィ繝ゥ繝シ + if (!disk.ready) { + disk.code = DISK_NOTREADY; + return FALSE; + } + + // 繝医シ繧ソ繝ォ繝悶Ο繝繧ッ謨ー繧定カ縺医※縺繧後ー繧ィ繝ゥ繝シ + if (block >= disk.blocks) { + disk.code = DISK_INVALIDLBA; + return FALSE; + } + + // 譖ク縺崎セシ縺ソ遖∵ュ「縺ェ繧峨お繝ゥ繝シ + if (disk.writep) { + disk.code = DISK_WRITEPROTECT; + return FALSE; + } + + // 繧ュ繝」繝繧キ繝・縺ォ莉サ縺帙k + if (!disk.dcache->Write(buf, block)) { + disk.code = DISK_WRITEFAULT; + return FALSE; + } + + // 繝ゥ繧、繝医せ繝ォ繝シ繧ュ繝」繝繧キ繝・ + if (!cache_wb) { + Flush(); + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// SEEK +// 窶サLBA縺ョ繝√ぉ繝繧ッ縺ッ陦後o縺ェ縺(SASI IOCS) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Seek(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // SEEK謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// ASSIGN +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Assign(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// SPECIFY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Specify(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// START STOP UNIT +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::StartStop(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x1b); + + // 繧、繧ク繧ァ繧ッ繝医ン繝繝医r隕九※縲∝ソ隕√↑繧峨う繧ク繧ァ繧ッ繝 + if (cdb[4] & 0x02) { + if (disk.lock) { + // 繝ュ繝繧ッ縺輔l縺ヲ縺繧九ョ縺ァ縲√う繧ク繧ァ繧ッ繝医〒縺阪↑縺 + disk.code = DISK_PREVENT; + return FALSE; + } + + // 繧、繧ク繧ァ繧ッ繝 + Eject(FALSE); + } + + // OK + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// SEND DIAGNOSTIC +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::SendDiag(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x1d); + + // PF繝薙ャ繝医ッ繧オ繝昴シ繝医@縺ェ縺 + if (cdb[1] & 0x10) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 繝代Λ繝。繝シ繧ソ繝ェ繧ケ繝医ッ繧オ繝昴シ繝医@縺ェ縺 + if ((cdb[3] != 0) || (cdb[4] != 0)) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蟶ク縺ォ謌仙粥 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// PREVENT/ALLOW MEDIUM REMOVAL +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Removal(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x1e); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return FALSE; + } + + // 繝ュ繝繧ッ繝輔Λ繧ー繧定ィュ螳 + if (cdb[4] & 0x01) { + disk.lock = TRUE; + } else { + disk.lock = FALSE; + } + + // REMOVAL謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ReadCapacity(const DWORD* /*cdb*/, BYTE *buf) +{ + DWORD blocks; + DWORD length; + + ASSERT(this); + ASSERT(buf); + + // 繝舌ャ繝輔ぃ繧ッ繝ェ繧「 + memset(buf, 0, 8); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 隲也炊繝悶Ο繝繧ッ繧「繝峨Ξ繧ケ縺ョ邨らォッ(disk.blocks - 1)繧剃ス懈 + ASSERT(disk.blocks > 0); + blocks = disk.blocks - 1; + buf[0] = (BYTE)(blocks >> 24); + buf[1] = (BYTE)(blocks >> 16); + buf[2] = (BYTE)(blocks >> 8); + buf[3] = (BYTE)blocks; + + // 繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ(1 << disk.size)繧剃ス懈 + length = 1 << disk.size; + buf[4] = (BYTE)(length >> 24); + buf[5] = (BYTE)(length >> 16); + buf[6] = (BYTE)(length >> 8); + buf[7] = (BYTE)length; + + // 霑秘√し繧、繧コ繧定ソ斐☆ + return 8; +} + +//--------------------------------------------------------------------------- +// +// VERIFY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::Verify(const DWORD *cdb) +{ + DWORD record; + DWORD blocks; + + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x2f); + + // 繝代Λ繝。繝シ繧ソ蜿門セ + record = cdb[2]; + record <<= 8; + record |= cdb[3]; + record <<= 8; + record |= cdb[4]; + record <<= 8; + record |= cdb[5]; + blocks = cdb[7]; + blocks <<= 8; + blocks |= cdb[8]; + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝代Λ繝。繝シ繧ソ繝√ぉ繝繧ッ + if (disk.blocks < (record + blocks)) { + disk.code = DISK_INVALIDLBA; + return FALSE; + } + + // 謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +int FASTCALL Disk::ReadToc(const DWORD *cdb, BYTE *buf) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x43); + ASSERT(buf); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::PlayAudio(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x45); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::PlayAudioMSF(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x47); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Disk::PlayAudioTrack(const DWORD *cdb) +{ + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x48); + + // 縺薙ョ繧ウ繝槭Φ繝峨ッ繧オ繝昴シ繝医@縺ェ縺 + disk.code = DISK_INVALIDCMD; + return FALSE; +} + +//=========================================================================== +// +// SASI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SASIHD::SASIHD() : Disk() +{ + // SASI 繝上シ繝峨ョ繧」繧ケ繧ッ + disk.id = MAKEID('S', 'A', 'H', 'D'); +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIHD::Reset() +{ + // 繝ュ繝繧ッ迥カ諷玖ァ」髯、縲√い繝繝ウ繧キ繝ァ繝ウ隗」髯、 + disk.lock = FALSE; + disk.attn = FALSE; + + // 繝ェ繧サ繝繝医↑縺励√さ繝シ繝峨r繧ッ繝ェ繧「 + disk.reset = FALSE; + disk.code = 0x00; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIHD::Open(const Filepath& path, BOOL /*attn*/) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + fio.Close(); + + // 10MB, 20MB, 40MB縺ョ縺ソ + switch (size) { + // 10MB + case 0x9f5400: + break; + + // 20MB + case 0x13c9800: + break; + + // 40MB + case 0x2793000: + break; + + // 縺昴ョ莉(繧オ繝昴シ繝医@縺ェ縺) + default: + return FALSE; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ縺ィ繝悶Ο繝繧ッ謨ー + disk.size = 8; + disk.blocks = (DWORD)(size >> 8); + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE +// +//--------------------------------------------------------------------------- +int FASTCALL SASIHD::RequestSense(const DWORD *cdb, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + + // 繧オ繧、繧コ豎コ螳 + size = (int)cdb[4]; + ASSERT((size >= 0) && (size < 0x100)); + + // SASI縺ッ髱樊僑蠑オ繝輔か繝シ繝槭ャ繝医↓蝗コ螳 + memset(buf, 0, size); + buf[0] = (BYTE)(disk.code >> 16); + buf[1] = (BYTE)(disk.lun << 5); + + // 繧ウ繝シ繝峨r繧ッ繝ェ繧「 + disk.code = 0x00; + + return size; +} + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIHD::SCSIHD() : Disk() +{ + // SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ + disk.id = MAKEID('S', 'C', 'H', 'D'); +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIHD::Reset() +{ + // 繝ュ繝繧ッ迥カ諷玖ァ」髯、縲√い繝繝ウ繧キ繝ァ繝ウ隗」髯、 + disk.lock = FALSE; + disk.attn = FALSE; + + // 繝ェ繧サ繝繝医↑縺励√さ繝シ繝峨r繧ッ繝ェ繧「 + disk.reset = FALSE; + disk.code = 0x00; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIHD::Open(const Filepath& path, BOOL /*attn*/) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + fio.Close(); + + // 512繝舌う繝亥腰菴阪〒縺ゅk縺薙→ + if (size & 0x1ff) { + return FALSE; + } + + // 10MB莉・荳 + if (size < 0x9f5400) { + return FALSE; + } + // xm6i縺ォ貅悶§縺ヲ2TB + // 繧医¥莨シ縺溘b縺ョ縺 wxw/wxw_cfg.cpp 縺ォ繧ゅ≠繧 + if (size > 2LL * 1024 * 1024 * 1024 * 1024) { + return FALSE; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ縺ィ繝悶Ο繝繧ッ謨ー + disk.size = 9; + disk.blocks = (DWORD)(size >> 9); + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + char vendor[32]; + char product[32]; + char rev[32]; + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return 0; + } + + // 繝ャ繝繧」繝√ぉ繝繧ッ(繧、繝。繝シ繧ク繝輔ぃ繧、繝ォ縺後↑縺蝣エ蜷医√お繝ゥ繝シ縺ィ縺吶k) + if (!disk.ready) { + disk.code = DISK_NOTREADY; + return 0; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... Direct Access Device + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 122 + 3; // 螳櫞DD縺ォ霑代>蛟、 + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝蜷/陬ス蜩∝錐繧呈アコ螳 + sprintf(vendor, BENDER_SIGNATURE); + size = disk.blocks >> 11; + if (size < 300) + sprintf(product, "PRODRIVE LPS%dS", size); + else if (size < 600) + sprintf(product, "MAVERICK%dS", size); + else if (size < 800) + sprintf(product, "LIGHTNING%dS", size); + else if (size < 1000) + sprintf(product, "TRAILBRAZER%dS", size); + else if (size < 2000) + sprintf(product, "FIREBALL%dS", size); + else + sprintf(product, "FBSE%d.%dS", size / 1000, (size % 1000) / 100); + + // 繝吶Φ繝蜷 + memcpy(&buf[8], vendor, strlen(vendor)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], product, strlen(product)); + + // 繝ェ繝薙ず繝ァ繝ウ + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIHD::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ + int page; + int size; + + ASSERT(this); + ASSERT(buf); + ASSERT(length >= 0); + + // PF + if (cdb[1] & 0x10) { + // Mode Parameter header + if (length >= 12) { + // 繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[9] != (BYTE)(size >> 16) || + buf[10] != (BYTE)(size >> 8) || buf[11] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + buf += 12; + length -= 12; + } + + // 繝壹シ繧ク縺ョ隗」譫 + while (length > 0) { + // 繝壹シ繧ク縺ョ蜿門セ + page = buf[0]; + + switch (page) { + // format device + case 0x03: + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[0xc] != (BYTE)(size >> 8) || buf[0xd] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + break; + + // 縺昴ョ莉悶壹シ繧ク + default: + break; + } + + // 谺。縺ョ繝壹シ繧ク縺ク + size = buf[1] + 2; + length -= size; + buf += size; + } + } + + // 縺ィ繧翫≠縺医★繧ィ繝ゥ繝シ縺ッ逋コ逕溘&縺帙↑縺(MINIX) + disk.code = DISK_NOERROR; + + return TRUE; +} + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(PC-9801-55 NEC邏疲ュ」/Anex86/T98Next) +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIHD_NEC::SCSIHD_NEC() : SCSIHD() +{ + // 繝ッ繝シ繧ッ蛻晄悄蛹 + cylinders = 0; + heads = 0; + sectors = 0; + sectorsize = 0; + imgoffset = 0; + imgsize = 0; +} + +static inline WORD getWordLE(const BYTE *b) +{ + return ((WORD)(b[1]) << 8) | b[0]; +} +static inline DWORD getDwordLE(const BYTE *b) +{ + return ((DWORD)(b[3]) << 24) | ((DWORD)(b[2]) << 16) | + ((DWORD)(b[1]) << 8) | b[0]; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIHD_NEC::Open(const Filepath& path, BOOL attn) +{ + Fileio fio; + off64_t size; + BYTE hdr[512]; + LPCTSTR ext; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + + // 繝倥ャ繝繝シ隱ュ縺ソ霎シ縺ソ + if (size >= sizeof(hdr)) { + if (!fio.Read(hdr, sizeof(hdr))) { + fio.Close(); + return FALSE; + } + } + fio.Close(); + + // 512繝舌う繝亥腰菴阪〒縺ゅk縺薙→ + if (size & 0x1ff) { + return FALSE; + } + + // 10MB莉・荳 + if (size < 0x9f5400) { + return FALSE; + } + // xm6i縺ォ貅悶§縺ヲ2TB + // 繧医¥莨シ縺溘b縺ョ縺 wxw/wxw_cfg.cpp 縺ォ繧ゅ≠繧 + if (size > 2LL * 1024 * 1024 * 1024 * 1024) { + return FALSE; + } + + // 諡。蠑オ蟄仙挨縺ォ繝代Λ繝。繝シ繧ソ繧呈アコ螳 + ext = path.GetFileExt(); + if (xstrcasecmp(ext, ".HDN") == 0) { + // 繝繝輔か繝ォ繝郁ィュ螳壹→縺励※繧サ繧ッ繧ソ繧オ繧、繧コ512,繧サ繧ッ繧ソ謨ー25,繝倥ャ繝画焚8繧呈Φ螳 + imgoffset = 0; + imgsize = size; + sectorsize = 512; + sectors = 25; + heads = 8; + cylinders = (int)(size >> 9); + cylinders >>= 3; + cylinders /= 25; + } else if (xstrcasecmp(ext, ".HDI") == 0) { // Anex86 HD image? + imgoffset = getDwordLE(&hdr[4 + 4]); + imgsize = getDwordLE(&hdr[4 + 4 + 4]); + sectorsize = getDwordLE(&hdr[4 + 4 + 4 + 4]); + sectors = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4]); + heads = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4 + 4]); + cylinders = getDwordLE(&hdr[4 + 4 + 4 + 4 + 4 + 4 + 4]); + } else if (xstrcasecmp(ext, ".NHD") == 0 && + memcmp(hdr, "T98HDDIMAGE.R0\0", 15) == 0) { // T98Next HD image? + imgoffset = getDwordLE(&hdr[0x10 + 0x100]); + cylinders = getDwordLE(&hdr[0x10 + 0x100 + 4]); + heads = getWordLE(&hdr[0x10 + 0x100 + 4 + 4]); + sectors = getWordLE(&hdr[0x10 + 0x100 + 4 + 4 + 2]); + sectorsize = getWordLE(&hdr[0x10 + 0x100 + 4 + 4 + 2 + 2]); + imgsize = (off64_t)cylinders * heads * sectors * sectorsize; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ縺ッ256縺セ縺溘ッ512繧偵し繝昴シ繝 + if (sectorsize != 256 && sectorsize != 512) { + return FALSE; + } + + // 繧、繝。繝シ繧ク繧オ繧、繧コ縺ョ謨エ蜷域ァ繝√ぉ繝繧ッ + if (imgoffset + imgsize > size || (imgsize % sectorsize != 0)) { + return FALSE; + } + + // 繧サ繧ッ繧ソ繧オ繧、繧コ + for(disk.size = 16; disk.size > 0; --(disk.size)) { + if ((1 << disk.size) == sectorsize) + break; + } + if (disk.size <= 0 || disk.size > 16) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー + disk.blocks = (DWORD)(imgsize >> disk.size); + disk.imgoffset = imgoffset; + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + return Disk::Open(path); +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + int size; + + // 蝓コ蠎輔け繝ゥ繧ケ + size = SCSIHD::Inquiry(cdb, buf, major, minor); + + // 蝓コ蠎輔け繝ゥ繧ケ縺ァ繧ィ繝ゥ繝シ縺ェ繧臥オゆコ + if (size == 0) { + return 0; + } + + // SCSI1逶ク蠖薙↓螟画峩 + buf[2] = 0x01; + buf[3] = 0x01; + + // 繝吶Φ繝繝シ蜷榊キョ縺玲崛縺 + buf[8] = 'N'; + buf[9] = 'E'; + buf[10] = 'C'; + + return size; +} + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::AddError(BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x01; + buf[1] = 0x06; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 8; + } + + // 繝ェ繝医Λ繧、繧ォ繧ヲ繝ウ繝医ッ0縲√Μ繝溘ャ繝医ち繧、繝縺ッ陬鄂ョ蜀驛ィ縺ョ繝繝輔か繝ォ繝亥、繧剃スソ逕ィ + return 8; +} + +//--------------------------------------------------------------------------- +// +// 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::AddFormat(BOOL change, BYTE *buf) +{ + int size; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x80 | 0x03; + buf[1] = 0x16; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚縺ッ螟画峩蜿ッ閭ス縺ォ隕九○繧(螳滄圀縺ォ縺ッ螟画峩縺ァ縺阪↑縺縺) + if (change) { + buf[0xc] = 0xff; + buf[0xd] = 0xff; + return 24; + } + + if (disk.ready) { + // 1繧セ繝シ繝ウ縺ョ繝医Λ繝繧ッ謨ー繧定ィュ螳(PC-9801-55縺ッ縺薙ョ蛟、繧定ヲ九※縺繧九h縺縺) + buf[0x2] = (BYTE)(heads >> 8); + buf[0x3] = (BYTE)heads; + + // 1繝医Λ繝繧ッ縺ョ繧サ繧ッ繧ソ謨ー繧定ィュ螳 + buf[0xa] = (BYTE)(sectors >> 8); + buf[0xb] = (BYTE)sectors; + + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧定ィュ螳 + size = 1 << disk.size; + buf[0xc] = (BYTE)(size >> 8); + buf[0xd] = (BYTE)size; + } + + // 繝ェ繝繝シ繝舌ヶ繝ォ螻樊ァ繧定ィュ螳(譏斐ョ蜷肴ョ) + if (disk.removable) { + buf[20] = 0x20; + } + + return 24; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_NEC::AddDrive(BOOL change, BYTE *buf) +{ + DWORD cylinder; + + ASSERT(this); + ASSERT(buf); + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x04; + buf[1] = 0x12; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 20; + } + + if (disk.ready) { + // 繧キ繝ェ繝ウ繝謨ー繧定ィュ螳 + buf[0x2] = (BYTE)(cylinders >> 16); + buf[0x3] = (BYTE)(cylinders >> 8); + buf[0x4] = (BYTE)cylinders; + + // 繝倥ャ繝画焚繧定ィュ螳 + buf[0x5] = (BYTE)heads; + } + + return 20; +} + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(Macintosh Apple邏疲ュ」) +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIHD_APPLE::SCSIHD_APPLE() : SCSIHD() +{ +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_APPLE::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + int size; + char vendor[32]; + char product[32]; + + // 蝓コ蠎輔け繝ゥ繧ケ + size = SCSIHD::Inquiry(cdb, buf, major, minor); + + // 蝓コ蠎輔け繝ゥ繧ケ縺ァ繧ィ繝ゥ繝シ縺ェ繧臥オゆコ + if (size == 0) { + return 0; + } + + // 繝吶Φ繝蜷 + sprintf(vendor, " SEAGATE"); + memcpy(&buf[8], vendor, strlen(vendor)); + + // 陬ス蜩∝錐 + sprintf(product, " ST225N"); + memcpy(&buf[16], product, strlen(product)); + + return size; +} + +//--------------------------------------------------------------------------- +// +// Vendor迚ケ谿翫壹シ繧ク霑ス蜉 +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIHD_APPLE::AddVendor(int page, BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繝壹シ繧ク繧ウ繝シ繝48 + if ((page != 0x30) && (page != 0x3f)) { + return 0; + } + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x30; + buf[1] = 0x1c; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 30; + } + + // APPLE COMPUTER, INC. + memcpy(&buf[0xa], "APPLE COMPUTER, INC.", 20); + + return 30; +} + +//=========================================================================== +// +// SCSI 蜈臥」∵ー励ョ繧」繧ケ繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIMO::SCSIMO() : Disk() +{ + // SCSI 蜈臥」∵ー励ョ繧」繧ケ繧ッ + disk.id = MAKEID('S', 'C', 'M', 'O'); + + // 繝ェ繝繝シ繝舌ヶ繝ォ + disk.removable = TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMO::Open(const Filepath& path, BOOL attn) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + ASSERT(!disk.ready); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + size = fio.GetFileSize(); + fio.Close(); + + switch (size) { + // 128MB + case 0x797f400: + disk.size = 9; + disk.blocks = 248826; + break; + + // 230MB + case 0xd9eea00: + disk.size = 9; + disk.blocks = 446325; + break; + + // 540MB + case 0x1fc8b800: + disk.size = 9; + disk.blocks = 1041500; + break; + + // 640MB + case 0x25e28000: + disk.size = 11; + disk.blocks = 310352; + break; + + // 縺昴ョ莉(繧ィ繝ゥ繝シ) + default: + return FALSE; + } + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + Disk::Open(path); + + // 繝ャ繝繧」縺ェ繧峨い繝繝ウ繧キ繝ァ繝ウ + if (disk.ready && attn) { + disk.attn = TRUE; + } + + return TRUE; +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMO::Load(Fileio *fio, int ver) +{ + DWORD sz; + disk_t buf; + DWORD padding; + Filepath path; + + ASSERT(this); + ASSERT(fio); + ASSERT(ver >= 0x0200); + + // version2.03繧医j蜑阪ッ縲√ョ繧」繧ケ繧ッ縺ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0202) { + return TRUE; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 52) { + return FALSE; + } + + // 繝舌ャ繝輔ぃ縺ク繝ュ繝シ繝 + PROP_IMPORT(fio, buf.id); + PROP_IMPORT(fio, buf.ready); + PROP_IMPORT(fio, buf.writep); + PROP_IMPORT(fio, buf.readonly); + PROP_IMPORT(fio, buf.removable); + PROP_IMPORT(fio, buf.lock); + PROP_IMPORT(fio, buf.attn); + PROP_IMPORT(fio, buf.reset); + PROP_IMPORT(fio, buf.size); + PROP_IMPORT(fio, buf.blocks); + PROP_IMPORT(fio, buf.lun); + PROP_IMPORT(fio, buf.code); + PROP_IMPORT(fio, padding); + + // 繝代せ繧偵Ο繝シ繝 + if (!path.Load(fio, ver)) { + return FALSE; + } + + // 蠢縺壹う繧ク繧ァ繧ッ繝 + Eject(TRUE); + + // ID縺御ク閾エ縺励◆蝣エ蜷医ョ縺ソ縲∫ァサ蜍 + if (disk.id != buf.id) { + // 繧サ繝シ繝匁凾縺ォMO縺ァ縺ェ縺九▲縺溘ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // 蜀阪が繝シ繝励Φ繧定ゥヲ縺ソ繧 + if (!Open(path, FALSE)) { + // 蜀阪が繝シ繝励Φ縺ァ縺阪↑縺縲ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // Open蜀縺ァ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ッ菴懈舌&繧後※縺繧九ゅ励Ο繝代ユ繧」縺ョ縺ソ遘サ蜍 + if (!disk.readonly) { + disk.writep = buf.writep; + } + disk.lock = buf.lock; + disk.attn = buf.attn; + disk.reset = buf.reset; + disk.lun = buf.lun; + disk.code = buf.code; + + // 豁」蟶ク縺ォ繝ュ繝シ繝峨〒縺阪◆ + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIMO::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + int size; + char rev[32]; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... Optical Memory Device + // buf[1] ... 繝ェ繝繝シ繝舌ヶ繝ォ + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + buf[0] = 0x07; + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[1] = 0x80; + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 36 - 5; // 蠢鬆 + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝 + memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], "M2513A", 6); + + // 繝ェ繝薙ず繝ァ繝ウ(XM6縺ョ繝舌シ繧ク繝ァ繝ウNo) + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// 窶サdisk.code縺ョ蠖ア髻ソ繧貞女縺代↑縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIMO::ModeSelect(const DWORD *cdb, const BYTE *buf, int length) +{ + int page; + int size; + + ASSERT(this); + ASSERT(buf); + ASSERT(length >= 0); + + // PF + if (cdb[1] & 0x10) { + // Mode Parameter header + if (length >= 12) { + // 繝悶Ο繝繧ッ繝ャ繝ウ繧ー繧ケ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[9] != (BYTE)(size >> 16) || + buf[10] != (BYTE)(size >> 8) || buf[11] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + buf += 12; + length -= 12; + } + + // 繝壹シ繧ク縺ョ隗」譫 + while (length > 0) { + // 繝壹シ繧ク縺ョ蜿門セ + page = buf[0]; + + switch (page) { + // format device + case 0x03: + // 迚ゥ逅繧サ繧ッ繧ソ縺ョ繝舌う繝域焚繧偵メ繧ァ繝繧ッ + size = 1 << disk.size; + if (buf[0xc] != (BYTE)(size >> 8) || buf[0xd] != (BYTE)size) { + // 莉翫ョ縺ィ縺薙m繧サ繧ッ繧ソ髟キ縺ョ螟画峩縺ッ險ア縺輔↑縺 + disk.code = DISK_INVALIDPRM; + return FALSE; + } + break; + // vendor unique format + case 0x20: + // just ignore, for now + break; + + // 縺昴ョ莉悶壹シ繧ク + default: + break; + } + + // 谺。縺ョ繝壹シ繧ク縺ク + size = buf[1] + 2; + length -= size; + buf += size; + } + } + + // 縺ィ繧翫≠縺医★繧ィ繝ゥ繝シ縺ッ逋コ逕溘&縺帙↑縺(MINIX) + disk.code = DISK_NOERROR; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// Vendor Unique Format Page 20h (MO) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIMO::AddVendor(int page, BOOL change, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + // 繝壹シ繧ク繧ウ繝シ繝20h + if ((page != 0x20) && (page != 0x3f)) { + return 0; + } + + // 繧ウ繝シ繝峨サ繝ャ繝ウ繧ー繧ケ繧定ィュ螳 + buf[0] = 0x20; + buf[1] = 0x0a; + + // 螟画峩蜿ッ閭ス鬆伜沺縺ッ縺ェ縺 + if (change) { + return 12; + } + + /* + mode page code 20h - Vendor Unique Format Page + format mode XXh type 0 + information: http://h20628.www2.hp.com/km-ext/kmcsdirect/emr_na-lpg28560-1.pdf + + offset description + 02h format mode + 03h type of format (0) + 04~07h size of user band (total sectors?) + 08~09h size of spare band (spare sectors?) + 0A~0Bh number of bands + + actual value of each 3.5inches optical medium (grabbed by Fujitsu M2513EL) + + 128M 230M 540M 640M + --------------------------------------------------- + size of user band 3CBFAh 6CF75h FE45Ch 4BC50h + size of spare band 0400h 0401h 08CAh 08C4h + number of bands 0001h 000Ah 0012h 000Bh + + further information: http://r2089.blog36.fc2.com/blog-entry-177.html + */ + + if (disk.ready) { + unsigned spare = 0; + unsigned bands = 0; + + if (disk.size == 9) switch (disk.blocks) { + // 128MB + case 248826: + spare = 1024; + bands = 1; + break; + + // 230MB + case 446325: + spare = 1025; + bands = 10; + break; + + // 540MB + case 1041500: + spare = 2250; + bands = 18; + break; + } + + if (disk.size == 11) switch (disk.blocks) { + // 640MB + case 310352: + spare = 2244; + bands = 11; + break; + + // 1.3GB (lpproj: not tested with real device) + case 605846: + spare = 4437; + bands = 18; + break; + } + + buf[2] = 0; // format mode + buf[3] = 0; // type of format + buf[4] = (BYTE)(disk.blocks >> 24); + buf[5] = (BYTE)(disk.blocks >> 16); + buf[6] = (BYTE)(disk.blocks >> 8); + buf[7] = (BYTE)disk.blocks; + buf[8] = (BYTE)(spare >> 8); + buf[9] = (BYTE)spare; + buf[10] = (BYTE)(bands >> 8); + buf[11] = (BYTE)bands; + } + + return 12; +} + +//=========================================================================== +// +// CD繝医Λ繝繧ッ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDTrack::CDTrack(SCSICD *scsicd) +{ + ASSERT(scsicd); + + // 隕ェ縺ィ縺ェ繧気D-ROM繝繝舌う繧ケ繧定ィュ螳 + cdrom = scsicd; + + // 繝医Λ繝繧ッ辟。蜉ケ + valid = FALSE; + + // 縺昴ョ莉悶ョ繝繝シ繧ソ繧貞晄悄蛹 + track_no = -1; + first_lba = 0; + last_lba = 0; + audio = FALSE; + raw = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDTrack::~CDTrack() +{ +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL CDTrack::Init(int track, DWORD first, DWORD last) +{ + ASSERT(this); + ASSERT(!valid); + ASSERT(track >= 1); + ASSERT(first < last); + + // 繝医Λ繝繧ッ逡ェ蜿キ繧定ィュ螳壹∵怏蜉ケ蛹 + track_no = track; + valid = TRUE; + + // LBA繧定ィ俶カ + first_lba = first; + last_lba = last; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL CDTrack::SetPath(BOOL cdda, const Filepath& path) +{ + ASSERT(this); + ASSERT(valid); + + // CD-DA縺九√ョ繝シ繧ソ縺 + audio = cdda; + + // 繝代せ險俶カ + imgpath = path; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL CDTrack::GetPath(Filepath& path) const +{ + ASSERT(this); + ASSERT(valid); + + // 繝代せ繧定ソ斐☆ + path = imgpath; +} + +//--------------------------------------------------------------------------- +// +// 繧、繝ウ繝繝繧ッ繧ケ霑ス蜉 +// +//--------------------------------------------------------------------------- +void FASTCALL CDTrack::AddIndex(int index, DWORD lba) +{ + ASSERT(this); + ASSERT(valid); + ASSERT(index > 0); + ASSERT(first_lba <= lba); + ASSERT(lba <= last_lba); + + // 迴セ蝨ィ縺ッ繧、繝ウ繝繝繧ッ繧ケ縺ッ繧オ繝昴シ繝医@縺ェ縺 + ASSERT(FALSE); +} + +//--------------------------------------------------------------------------- +// +// 髢句ァ記BA蜿門セ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL CDTrack::GetFirst() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(first_lba < last_lba); + + return first_lba; +} + +//--------------------------------------------------------------------------- +// +// 邨らォッLBA蜿門セ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL CDTrack::GetLast() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(first_lba < last_lba); + + return last_lba; +} + +//--------------------------------------------------------------------------- +// +// 繝悶Ο繝繧ッ謨ー蜿門セ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL CDTrack::GetBlocks() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(first_lba < last_lba); + + // 髢句ァ記BA縺ィ譛邨LBA縺九i邂怜コ + return (DWORD)(last_lba - first_lba + 1); +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ逡ェ蜿キ蜿門セ +// +//--------------------------------------------------------------------------- +int FASTCALL CDTrack::GetTrackNo() const +{ + ASSERT(this); + ASSERT(valid); + ASSERT(track_no >= 1); + + return track_no; +} + +//--------------------------------------------------------------------------- +// +// 譛牙柑縺ェ繝悶Ο繝繧ッ縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL CDTrack::IsValid(DWORD lba) const +{ + ASSERT(this); + + // 繝医Λ繝繧ッ閾ェ菴薙′辟。蜉ケ縺ェ繧峨:ALSE + if (!valid) { + return FALSE; + } + + // first繧医j蜑阪↑繧峨:ALSE + if (lba < first_lba) { + return FALSE; + } + + // last繧医j蠕後↑繧峨:ALSE + if (last_lba < lba) { + return FALSE; + } + + // 縺薙ョ繝医Λ繝繧ッ + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ縺 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL CDTrack::IsAudio() const +{ + ASSERT(this); + ASSERT(valid); + + return audio; +} + +//=========================================================================== +// +// CD-DA繝舌ャ繝輔ぃ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDDABuf::CDDABuf() +{ +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +CDDABuf::~CDDABuf() +{ +} + +//=========================================================================== +// +// SCSI CD-ROM +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSICD::SCSICD() : Disk() +{ + int i; + + // SCSI CD-ROM + disk.id = MAKEID('S', 'C', 'C', 'D'); + + // 繝ェ繝繝シ繝舌ヶ繝ォ縲∵嶌霎シ縺ソ遖∵ュ「 + disk.removable = TRUE; + disk.writep = TRUE; + + // RAW蠖「蠑上〒縺ェ縺 + rawfile = FALSE; + + // 繝輔Ξ繝シ繝蛻晄悄蛹 + frame = 0; + + // 繝医Λ繝繧ッ蛻晄悄蛹 + for (i = 0; i < TrackMax; i++) { + track[i] = NULL; + } + tracks = 0; + dataindex = -1; + audioindex = -1; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSICD::~SCSICD() +{ + // 繝医Λ繝繧ッ繧ッ繝ェ繧「 + ClearTrack(); +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::Load(Fileio *fio, int ver) +{ + DWORD sz; + disk_t buf; + DWORD padding; + Filepath path; + + ASSERT(this); + ASSERT(fio); + ASSERT(ver >= 0x0200); + + // version2.03繧医j蜑阪ッ縲√ョ繧」繧ケ繧ッ縺ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0202) { + return TRUE; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 52) { + return FALSE; + } + + // 繝舌ャ繝輔ぃ縺ク繝ュ繝シ繝 + PROP_IMPORT(fio, buf.id); + PROP_IMPORT(fio, buf.ready); + PROP_IMPORT(fio, buf.writep); + PROP_IMPORT(fio, buf.readonly); + PROP_IMPORT(fio, buf.removable); + PROP_IMPORT(fio, buf.lock); + PROP_IMPORT(fio, buf.attn); + PROP_IMPORT(fio, buf.reset); + PROP_IMPORT(fio, buf.size); + PROP_IMPORT(fio, buf.blocks); + PROP_IMPORT(fio, buf.lun); + PROP_IMPORT(fio, buf.code); + PROP_IMPORT(fio, padding); + + // 繝代せ繧偵Ο繝シ繝 + if (!path.Load(fio, ver)) { + return FALSE; + } + + // 蠢縺壹う繧ク繧ァ繧ッ繝 + Eject(TRUE); + + // ID縺御ク閾エ縺励◆蝣エ蜷医ョ縺ソ縲∫ァサ蜍 + if (disk.id != buf.id) { + // 繧サ繝シ繝匁凾縺ォCD-ROM縺ァ縺ェ縺九▲縺溘ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // 蜀阪が繝シ繝励Φ繧定ゥヲ縺ソ繧 + if (!Open(path, FALSE)) { + // 蜀阪が繝シ繝励Φ縺ァ縺阪↑縺縲ゅう繧ク繧ァ繧ッ繝育憾諷九r邯ュ謖 + return TRUE; + } + + // Open蜀縺ァ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・縺ッ菴懈舌&繧後※縺繧九ゅ励Ο繝代ユ繧」縺ョ縺ソ遘サ蜍 + if (!disk.readonly) { + disk.writep = buf.writep; + } + disk.lock = buf.lock; + disk.attn = buf.attn; + disk.reset = buf.reset; + disk.lun = buf.lun; + disk.code = buf.code; + + // 蜀榊コヲ縲√ョ繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧堤エ譽 + if (disk.dcache) { + delete disk.dcache; + disk.dcache = NULL; + } + disk.dcache = NULL; + + // 證ォ螳 + disk.blocks = track[0]->GetBlocks(); + if (disk.blocks > 0) { + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧剃ス懊j逶エ縺 + track[0]->GetPath(path); + disk.dcache = new DiskCache(path, disk.size, disk.blocks); + disk.dcache->SetRawMode(rawfile); + + // 繝繝シ繧ソ繧、繝ウ繝繝繧ッ繧ケ繧貞崎ィュ螳 + dataindex = 0; + } + + return TRUE; +} +#endif // RASCSI + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::Open(const Filepath& path, BOOL attn) +{ + Fileio fio; + off64_t size; + char file[5]; + + ASSERT(this); + ASSERT(!disk.ready); + + // 蛻晄悄蛹悶√ヨ繝ゥ繝繧ッ繧ッ繝ェ繧「 + disk.blocks = 0; + rawfile = FALSE; + ClearTrack(); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 迚ゥ逅CD繧「繧ッ繧サ繧ケ縺ェ繧峨け繝ュ繝シ繧コ縺励※蟋碑ュイ縺吶k + if (path.GetPath()[0] == _T('\\')) { + // 繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 迚ゥ逅CD繧ェ繝シ繝励Φ + if (!OpenPhysical(path)) { + return FALSE; + } + } else { + // 繧オ繧、繧コ蜿門セ + size = fio.GetFileSize(); + if (size <= 4) { + fio.Close(); + return FALSE; + } + + // CUE繧キ繝シ繝医°縲!SO繝輔ぃ繧、繝ォ縺九ョ蛻、螳壹r陦後≧ + fio.Read(file, 4); + file[4] = '\0'; + fio.Close(); + + // FILE縺ァ蟋九∪縺」縺ヲ縺繧後ー縲,UE繧キ繝シ繝医→縺ソ縺ェ縺 + if (xstrncasecmp(file, "FILE", 4) == 0) { + // CUE縺ィ縺励※繧ェ繝シ繝励Φ + if (!OpenCue(path)) { + return FALSE; + } + } else { + // ISO縺ィ縺励※繧ェ繝シ繝励Φ + if (!OpenIso(path)) { + return FALSE; + } + } + } + + // 繧ェ繝シ繝励Φ謌仙粥 + ASSERT(disk.blocks > 0); + disk.size = 11; + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + Disk::Open(path); + + // RAW繝輔Λ繧ー繧定ィュ螳 + ASSERT(disk.dcache); + disk.dcache->SetRawMode(rawfile); + + // ROM繝。繝繧」繧「縺ェ縺ョ縺ァ縲∵嶌縺崎セシ縺ソ縺ッ縺ァ縺阪↑縺 + disk.writep = TRUE; + + // 繝ャ繝繧」縺ェ繧峨い繝繝ウ繧キ繝ァ繝ウ + if (disk.ready && attn) { + disk.attn = TRUE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ(CUE) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::OpenCue(const Filepath& /*path*/) +{ + ASSERT(this); + + // 蟶ク縺ォ螟ア謨 + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ(ISO) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::OpenIso(const Filepath& path) +{ + Fileio fio; + off64_t size; + BYTE header[12]; + BYTE sync[12]; + + ASSERT(this); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繧オ繧、繧コ蜿門セ + size = fio.GetFileSize(); + if (size < 0x800) { + fio.Close(); + return FALSE; + } + + // 譛蛻昴ョ12繝舌う繝医r隱ュ縺ソ蜿悶▲縺ヲ縲√け繝ュ繝シ繧コ + if (!fio.Read(header, sizeof(header))) { + fio.Close(); + return FALSE; + } + + // RAW蠖「蠑上°繝√ぉ繝繧ッ + memset(sync, 0xff, sizeof(sync)); + sync[0] = 0x00; + sync[11] = 0x00; + rawfile = FALSE; + if (memcmp(header, sync, sizeof(sync)) == 0) { + // 00,FFx10,00縺ェ縺ョ縺ァ縲ヽAW蠖「蠑上→謗ィ螳壹&繧後k + if (!fio.Read(header, 4)) { + fio.Close(); + return FALSE; + } + + // MODE1/2048縺セ縺溘ッMODE1/2352縺ョ縺ソ繧オ繝昴シ繝 + if (header[3] != 0x01) { + // 繝「繝シ繝峨′驕輔≧ + fio.Close(); + return FALSE; + } + + // RAW繝輔ぃ繧、繝ォ縺ォ險ュ螳 + rawfile = TRUE; + } + fio.Close(); + + if (rawfile) { + // 繧オ繧、繧コ縺2536縺ョ蛟肴焚縺ァ縲700MB莉・荳九〒縺ゅk縺薙→ + if (size % 0x930) { + return FALSE; + } + if (size > 912579600) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー繧定ィュ螳 + disk.blocks = (DWORD)(size / 0x930); + } else { + // 繧オ繧、繧コ縺2048縺ョ蛟肴焚縺ァ縲700MB莉・荳九〒縺ゅk縺薙→ + if (size & 0x7ff) { + return FALSE; + } + if (size > 0x2bed5000) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー繧定ィュ螳 + disk.blocks = (DWORD)(size >> 11); + } + + // 繝繝シ繧ソ繝医Λ繝繧ッ1縺、縺ョ縺ソ菴懈 + ASSERT(!track[0]); + track[0] = new CDTrack(this); + track[0]->Init(1, 0, disk.blocks - 1); + track[0]->SetPath(FALSE, path); + tracks = 1; + dataindex = 0; + + // 繧ェ繝シ繝励Φ謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ(Physical) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::OpenPhysical(const Filepath& path) +{ + Fileio fio; + off64_t size; + + ASSERT(this); + + // 隱ュ縺ソ霎シ縺ソ繧ェ繝シ繝励Φ縺悟ソ隕 + if (!fio.Open(path, Fileio::ReadOnly)) { + return FALSE; + } + + // 繧オ繧、繧コ蜿門セ + size = fio.GetFileSize(); + if (size < 0x800) { + fio.Close(); + return FALSE; + } + + // 繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 繧オ繧、繧コ縺2048縺ョ蛟肴焚縺ァ縲700MB莉・荳九〒縺ゅk縺薙→ + if (size & 0x7ff) { + return FALSE; + } + if (size > 0x2bed5000) { + return FALSE; + } + + // 繝悶Ο繝繧ッ謨ー繧定ィュ螳 + disk.blocks = (DWORD)(size >> 11); + + // 繝繝シ繧ソ繝医Λ繝繧ッ1縺、縺ョ縺ソ菴懈 + ASSERT(!track[0]); + track[0] = new CDTrack(this); + track[0]->Init(1, 0, disk.blocks - 1); + track[0]->SetPath(FALSE, path); + tracks = 1; + dataindex = 0; + + // 繧ェ繝シ繝励Φ謌仙粥 + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + char rev[32]; + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... CD-ROM Device + // buf[1] ... 繝ェ繝繝シ繝舌ヶ繝ォ + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + buf[0] = 0x05; + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[1] = 0x80; + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 36 - 5; // 蠢鬆 + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝 + memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], "CD-ROM CDU-55S", 14); + + // 繝ェ繝薙ず繝ァ繝ウ(XM6縺ョ繝舌シ繧ク繝ァ繝ウNo) + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// READ +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::Read(BYTE *buf, DWORD block) +{ + int index; + Filepath path; + + ASSERT(this); + ASSERT(buf); + + // 迥カ諷九メ繧ァ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝医Λ繝繧ッ讀懃エ「 + index = SearchTrack(block); + + // 辟。蜉ケ縺ェ繧峨∫ッ蝗イ螟 + if (index < 0) { + disk.code = DISK_INVALIDLBA; + return 0; + } + ASSERT(track[index]); + + // 迴セ蝨ィ縺ョ繝繝シ繧ソ繝医Λ繝繧ッ縺ィ逡ー縺ェ縺」縺ヲ縺繧後ー + if (dataindex != index) { + // 迴セ蝨ィ縺ョ繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧貞炎髯、(Save縺ョ蠢隕√ッ縺ェ縺) + delete disk.dcache; + disk.dcache = NULL; + + // 繝悶Ο繝繧ッ謨ー繧貞崎ィュ螳 + disk.blocks = track[index]->GetBlocks(); + ASSERT(disk.blocks > 0); + + // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・繧剃ス懊j逶エ縺 + track[index]->GetPath(path); + disk.dcache = new DiskCache(path, disk.size, disk.blocks); + disk.dcache->SetRawMode(rawfile); + + // 繝繝シ繧ソ繧、繝ウ繝繝繧ッ繧ケ繧貞崎ィュ螳 + dataindex = index; + } + + // 蝓コ譛ャ繧ッ繝ゥ繧ケ + ASSERT(dataindex >= 0); + return Disk::Read(buf, block); +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::ReadToc(const DWORD *cdb, BYTE *buf) +{ + int last; + int index; + int length; + int loop; + int i; + BOOL msf; + DWORD lba; + + ASSERT(this); + ASSERT(cdb); + ASSERT(cdb[0] == 0x43); + ASSERT(buf); + + // 繝ャ繝繧」繝√ぉ繝繧ッ + if (!CheckReady()) { + return 0; + } + + // 繝ャ繝繧」縺ァ縺ゅk縺ェ繧峨√ヨ繝ゥ繝繧ッ縺梧怙菴1縺、莉・荳雁ュ伜惠縺吶k + ASSERT(tracks > 0); + ASSERT(track[0]); + + // 繧「繝ュ繧ア繝シ繧キ繝ァ繝ウ繝ャ繝ウ繧ー繧ケ蜿門セ励√ヰ繝繝輔ぃ繧ッ繝ェ繧「 + length = cdb[7] << 8; + length |= cdb[8]; + memset(buf, 0, length); + + // MSF繝輔Λ繧ー蜿門セ + if (cdb[1] & 0x02) { + msf = TRUE; + } else { + msf = FALSE; + } + + // 譛邨ゅヨ繝ゥ繝繧ッ逡ェ蜿キ繧貞叙蠕励√メ繧ァ繝繧ッ + last = track[tracks - 1]->GetTrackNo(); + if ((int)cdb[6] > last) { + // 縺溘□縺輸A縺ッ髯、螟 + if (cdb[6] != 0xaa) { + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 髢句ァ九う繝ウ繝繝繧ッ繧ケ繧偵メ繧ァ繝繧ッ + index = 0; + if (cdb[6] != 0x00) { + // 繝医Λ繝繧ッ逡ェ蜿キ縺御ク閾エ縺吶k縺セ縺ァ縲√ヨ繝ゥ繝繧ッ繧帝イ繧√k + while (track[index]) { + if ((int)cdb[6] == track[index]->GetTrackNo()) { + break; + } + index++; + } + + // 隕九▽縺九i縺ェ縺代l縺ーAA縺九∝驛ィ繧ィ繝ゥ繝シ + if (!track[index]) { + if (cdb[6] == 0xaa) { + // AA縺ェ縺ョ縺ァ縲∵怙邨LBA+1繧定ソ斐☆ + buf[0] = 0x00; + buf[1] = 0x0a; + buf[2] = (BYTE)track[0]->GetTrackNo(); + buf[3] = (BYTE)last; + buf[6] = 0xaa; + lba = track[tracks - 1]->GetLast() + 1; + if (msf) { + LBAtoMSF(lba, &buf[8]); + } else { + buf[10] = (BYTE)(lba >> 8); + buf[11] = (BYTE)lba; + } + return length; + } + + // 縺昴l莉・螟悶ッ繧ィ繝ゥ繝シ + disk.code = DISK_INVALIDCDB; + return 0; + } + } + + // 莉雁屓霑斐☆繝医Λ繝繧ッ繝繧」繧ケ繧ッ繝ェ繝励ち縺ョ蛟区焚(繝ォ繝シ繝玲焚) + loop = last - track[index]->GetTrackNo() + 1; + ASSERT(loop >= 1); + + // 繝倥ャ繝菴懈 + buf[0] = (BYTE)(((loop << 3) + 2) >> 8); + buf[1] = (BYTE)((loop << 3) + 2); + buf[2] = (BYTE)track[0]->GetTrackNo(); + buf[3] = (BYTE)last; + buf += 4; + + // 繝ォ繝シ繝 + for (i = 0; i < loop; i++) { + // ADR縺ィControl + if (track[index]->IsAudio()) { + // 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ + buf[1] = 0x10; + } else { + // 繝繝シ繧ソ繝医Λ繝繧ッ + buf[1] = 0x14; + } + + // 繝医Λ繝繧ッ逡ェ蜿キ + buf[2] = (BYTE)track[index]->GetTrackNo(); + + // 繝医Λ繝繧ッ繧「繝峨Ξ繧ケ + if (msf) { + LBAtoMSF(track[index]->GetFirst(), &buf[4]); + } else { + buf[6] = (BYTE)(track[index]->GetFirst() >> 8); + buf[7] = (BYTE)(track[index]->GetFirst()); + } + + // 繝舌ャ繝輔ぃ縺ィ繧、繝ウ繝繝繧ッ繧ケ繧帝イ繧√k + buf += 8; + index++; + } + + // 繧「繝ュ繧ア繝シ繧キ繝ァ繝ウ繝ャ繝ウ繧ー繧ケ縺縺大ソ縺夊ソ斐☆ + return length; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::PlayAudio(const DWORD* /*cdb*/) +{ + ASSERT(this); + + disk.code = DISK_INVALIDCDB; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::PlayAudioMSF(const DWORD* /*cdb*/) +{ + ASSERT(this); + + disk.code = DISK_INVALIDCDB; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::PlayAudioTrack(const DWORD* /*cdb*/) +{ + ASSERT(this); + + disk.code = DISK_INVALIDCDB; + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// LBA竊樽SF螟画鋤 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSICD::LBAtoMSF(DWORD lba, BYTE *msf) const +{ + DWORD m; + DWORD s; + DWORD f; + + ASSERT(this); + + // 75縲75*60縺ァ縺昴l縺槭l菴吶j繧貞コ縺 + m = lba / (75 * 60); + s = lba % (75 * 60); + f = s % 75; + s /= 75; + + // 蝓コ轤ケ縺ッM=0,S=2,F=0 + s += 2; + if (s >= 60) { + s -= 60; + m++; + } + + // 譬シ邏 + ASSERT(m < 0x100); + ASSERT(s < 60); + ASSERT(f < 75); + msf[0] = 0x00; + msf[1] = (BYTE)m; + msf[2] = (BYTE)s; + msf[3] = (BYTE)f; +} + +//--------------------------------------------------------------------------- +// +// MSF竊鱈BA螟画鋤 +// +//--------------------------------------------------------------------------- +DWORD FASTCALL SCSICD::MSFtoLBA(const BYTE *msf) const +{ + DWORD lba; + + ASSERT(this); + ASSERT(msf[2] < 60); + ASSERT(msf[3] < 75); + + // 1, 75, 75*60縺ョ蛟肴焚縺ァ蜷育ョ + lba = msf[1]; + lba *= 60; + lba += msf[2]; + lba *= 75; + lba += msf[3]; + + // 蝓コ轤ケ縺ッM=0,S=2,F=0縺ェ縺ョ縺ァ縲150繧貞シ輔¥ + lba -= 150; + + return lba; +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ繧ッ繝ェ繧「 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSICD::ClearTrack() +{ + int i; + + ASSERT(this); + + // 繝医Λ繝繧ッ繧ェ繝悶ず繧ァ繧ッ繝医r蜑企勁 + for (i = 0; i < TrackMax; i++) { + if (track[i]) { + delete track[i]; + track[i] = NULL; + } + } + + // 繝医Λ繝繧ッ謨ー0 + tracks = 0; + + // 繝繝シ繧ソ縲√が繝シ繝繧」繧ェ縺ィ繧りィュ螳壹↑縺 + dataindex = -1; + audioindex = -1; +} + +//--------------------------------------------------------------------------- +// +// 繝医Λ繝繧ッ讀懃エ「 +// 窶サ隕九▽縺九i縺ェ縺代l縺ー-1繧定ソ斐☆ +// +//--------------------------------------------------------------------------- +int FASTCALL SCSICD::SearchTrack(DWORD lba) const +{ + int i; + + ASSERT(this); + + // 繝医Λ繝繧ッ繝ォ繝シ繝 + for (i = 0; i < tracks; i++) { + // 繝医Λ繝繧ッ縺ォ閨槭¥ + ASSERT(track[i]); + if (track[i]->IsValid(lba)) { + return i; + } + } + + // 隕九▽縺九i縺ェ縺九▲縺 + return -1; +} + +//--------------------------------------------------------------------------- +// +// 繝輔Ξ繝シ繝騾夂衍 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSICD::NextFrame() +{ + ASSERT(this); + ASSERT((frame >= 0) && (frame < 75)); + + // 繝輔Ξ繝シ繝繧0ス74縺ョ遽蝗イ縺ァ險ュ螳 + frame = (frame + 1) % 75; + + // 1蜻ィ縺励◆繧宇ALSE + if (frame != 0) { + return TRUE; + } else { + return FALSE; + } +} + +//--------------------------------------------------------------------------- +// +// CD-DA繝舌ャ繝輔ぃ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSICD::GetBuf(DWORD* /*buffer*/, int /*samples*/, DWORD /*rate*/) +{ + ASSERT(this); +} + +//=========================================================================== +// +// SCSI 繝帙せ繝医ヶ繝ェ繝繧ク +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIBR::SCSIBR() : Disk() +{ + // 繝帙せ繝医ヶ繝ェ繝繧ク + disk.id = MAKEID('S', 'C', 'B', 'R'); + + // TAP繝峨Λ繧、繝千函謌 + tap = new CTapDriver(); + m_bTapEnable = tap->Init(); + + // MAC繧「繝峨Ξ繧ケ繧堤函謌 + memset(mac_addr, 0x00, 6); + if (m_bTapEnable) { + tap->GetMacAddr(mac_addr); + mac_addr[5]++; + } + + // 繝代こ繝繝亥女菫。繝輔Λ繧ー繧ェ繝 + packet_enable = FALSE; + + // 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝逕滓 + fs = new CFileSys(); + fs->Reset(); +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SCSIBR::~SCSIBR() +{ + // TAP繝峨Λ繧、繝占ァ」謾セ + if (tap) { + tap->Cleanup(); + delete tap; + } + + // 繝帙せ繝医ヵ繧。繧、繝ォ繧キ繧ケ繝繝隗」謾セ + if (fs) { + fs->Reset(); + delete fs; + } +} + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor) +{ + char rev[32]; + int size; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + ASSERT(cdb[0] == 0x12); + + // EVPD繝√ぉ繝繧ッ + if (cdb[1] & 0x01) { + disk.code = DISK_INVALIDCDB; + return FALSE; + } + + // 蝓コ譛ャ繝繝シ繧ソ + // buf[0] ... Communication Device + // buf[2] ... SCSI-2貅匁侠縺ョ繧ウ繝槭Φ繝我ス鍋ウサ + // buf[3] ... SCSI-2貅匁侠縺ョInquiry繝ャ繧ケ繝昴Φ繧ケ + // buf[4] ... Inquiry霑ス蜉繝繝シ繧ソ + memset(buf, 0, 8); + buf[0] = 0x09; + + // SCSI-2 譛ャ縺ョ p.104 4.4.3 荳榊ス薙↑繝ュ繧ク繧ォ繝ォ繝ヲ繝九ャ繝医ョ蜃ヲ逅 + if (((cdb[1] >> 5) & 0x07) != disk.lun) { + buf[0] = 0x7f; + } + + buf[2] = 0x02; + buf[3] = 0x02; + buf[4] = 36 - 5 + 8; // 蠢鬆 + 8繝舌う繝域僑蠑オ + + // 遨コ逋ス縺ァ蝓九a繧 + memset(&buf[8], 0x20, buf[4] - 3); + + // 繝吶Φ繝 + memcpy(&buf[8], BENDER_SIGNATURE, strlen(BENDER_SIGNATURE)); + + // 陬ス蜩∝錐 + memcpy(&buf[16], "RASCSI BRIDGE", 13); + + // 繝ェ繝薙ず繝ァ繝ウ(XM6縺ョ繝舌シ繧ク繝ァ繝ウNo) + sprintf(rev, "0%01d%01d%01d", + (int)major, (int)(minor >> 4), (int)(minor & 0x0f)); + memcpy(&buf[32], rev, 4); + + // 繧ェ繝励す繝ァ繝ウ讖溯ス譛牙柑繝輔Λ繧ー + buf[36] = '0'; + + // TAP譛牙柑 + if (m_bTapEnable) { + buf[37] = '1'; + } + + // CFileSys譛牙柑 + buf[38] = '1'; + + // 霑泌唆縺ァ縺阪k繝繝シ繧ソ縺ョ繧オ繧、繧コ + size = (buf[4] + 5); + + // 逶ク謇九ョ繝舌ャ繝輔ぃ縺悟ー代↑縺代l縺ー蛻カ髯舌☆繧 + if (size > (int)cdb[4]) { + size = (int)cdb[4]; + } + + // 謌仙粥 + disk.code = DISK_NOERROR; + return size; +} + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIBR::TestUnitReady(const DWORD* /*cdb*/) +{ + ASSERT(this); + + // TEST UNIT READY謌仙粥 + disk.code = DISK_NOERROR; + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// GET MESSAGE(10) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::GetMessage10(const DWORD *cdb, BYTE *buf) +{ + int type; + int func; + int phase; + int total_len; + int i; + + ASSERT(this); + + // 繧ソ繧、繝 + type = cdb[2]; + + // 讖溯ス逡ェ蜿キ + func = cdb[3]; + + // 繝輔ぉ繝シ繧コ + phase = cdb[9]; + + switch (type) { + case 1: // 繧、繝シ繧オ繝阪ャ繝 + // TAP辟。蜉ケ縺ェ繧牙ヲ逅縺励↑縺 + if (!m_bTapEnable) { + return 0; + } + + switch (func) { + case 0: // MAC繧「繝峨Ξ繧ケ蜿門セ + return GetMacAddr(buf); + + case 1: // 蜿嶺ソ。繝代こ繝繝亥叙蠕(繧オ繧、繧コ/繝舌ャ繝輔ぃ蛻・) + if (phase == 0) { + // 繝代こ繝繝医し繧、繧コ蜿門セ + ReceivePacket(); + buf[0] = (BYTE)(packet_len >> 8); + buf[1] = (BYTE)packet_len; + return 2; + } else { + // 繝代こ繝繝医ョ繝シ繧ソ蜿門セ + GetPacketBuf(buf); + return packet_len; + } + + case 2: // 蜿嶺ソ。繝代こ繝繝亥叙蠕(繧オ繧、繧コシ九ヰ繝繝輔ぃ蜷梧凾) + ReceivePacket(); + buf[0] = (BYTE)(packet_len >> 8); + buf[1] = (BYTE)packet_len; + GetPacketBuf(&buf[2]); + return packet_len + 2; + + case 3: // 隍謨ー繝代こ繝繝亥酔譎ょ叙蠕(繧オ繧、繧コシ九ヰ繝繝輔ぃ蜷梧凾) + // 繝代こ繝繝域焚縺ョ荳企剞縺ッ迴セ迥カ10蛟九↓豎コ繧∵遠縺。 + // 縺薙l莉・荳雁「励d縺励※繧ゅ≠縺セ繧企溘¥縺ェ繧峨↑縺? + total_len = 0; + for (i = 0; i < 10; i++) { + ReceivePacket(); + *buf++ = (BYTE)(packet_len >> 8); + *buf++ = (BYTE)packet_len; + total_len += 2; + if (packet_len == 0) + break; + GetPacketBuf(buf); + buf += packet_len; + total_len += packet_len; + } + return total_len; + } + break; + + case 2: // 繝帙せ繝医ラ繝ゥ繧、繝 + switch (phase) { + case 0: // 邨先棡繧ウ繝シ繝牙叙蠕 + return ReadFsResult(buf); + + case 1: // 霑泌唆繝繝シ繧ソ蜿門セ + return ReadFsOut(buf); + + case 2: // 霑泌唆霑ス蜉繝繝シ繧ソ蜿門セ + return ReadFsOpt(buf); + } + break; + } + + // 繧ィ繝ゥ繝シ + ASSERT(FALSE); + return 0; +} + +//--------------------------------------------------------------------------- +// +// SEND MESSAGE(10) +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIBR::SendMessage10(const DWORD *cdb, BYTE *buf) +{ + int type; + int func; + int phase; + int len; + + ASSERT(this); + ASSERT(cdb); + ASSERT(buf); + + // 繧ソ繧、繝 + type = cdb[2]; + + // 讖溯ス逡ェ蜿キ + func = cdb[3]; + + // 繝輔ぉ繝シ繧コ + phase = cdb[9]; + + // 繝ゥ繧、繝域焚繧貞叙蠕 + len = cdb[6]; + len <<= 8; + len |= cdb[7]; + len <<= 8; + len |= cdb[8]; + + switch (type) { + case 1: // 繧、繝シ繧オ繝阪ャ繝 + // TAP辟。蜉ケ縺ェ繧牙ヲ逅縺励↑縺 + if (!m_bTapEnable) { + return FALSE; + } + + switch (func) { + case 0: // MAC繧「繝峨Ξ繧ケ險ュ螳 + SetMacAddr(buf); + return TRUE; + + case 1: // 繝代こ繝繝磯∽ソ。 + SendPacket(buf, len); + return TRUE; + } + break; + + case 2: // 繝帙せ繝医ラ繝ゥ繧、繝 + switch (phase) { + case 0: // 繧ウ繝槭Φ繝臥匱陦 + WriteFs(func, buf); + return TRUE; + + case 1: // 霑ス蜉繝繝シ繧ソ譖ク縺崎セシ縺ソ + WriteFsOpt(buf, len); + return TRUE; + } + break; + } + + // 繧ィ繝ゥ繝シ + ASSERT(FALSE); + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// MAC繧「繝峨Ξ繧ケ蜿門セ +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::GetMacAddr(BYTE *mac) +{ + ASSERT(this); + ASSERT(mac); + + memcpy(mac, mac_addr, 6); + return 6; +} + +//--------------------------------------------------------------------------- +// +// MAC繧「繝峨Ξ繧ケ險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::SetMacAddr(BYTE *mac) +{ + ASSERT(this); + ASSERT(mac); + + memcpy(mac_addr, mac, 6); +} + +//--------------------------------------------------------------------------- +// +// 繝代こ繝繝亥女菫。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::ReceivePacket() +{ + static const BYTE bcast_addr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + BYTE buf[0x1000]; + + ASSERT(this); + ASSERT(tap); + + // 蜑阪ョ繝代こ繝繝医′蜿嶺ソ。縺輔l縺ヲ縺縺ェ縺 + if (packet_enable) { + return; + } + + // 繝代こ繝繝亥女菫。 + packet_len = tap->Rx(packet_buf); + + // 蜿嶺ソ。繝代こ繝繝医°讀懈渊 + if (memcmp(packet_buf, mac_addr, 6) != 0) { + if (memcmp(packet_buf, bcast_addr, 6) != 0) { + packet_len = 0; + return; + } + } + + // 繝舌ャ繝輔ぃ繧オ繧、繧コ繧定カ翫∴縺溘i謐ィ縺ヲ繧 + if (packet_len > 2048) { + packet_len = 0; + return; + } + + // 蜿嶺ソ。繝舌ャ繝輔ぃ縺ォ譬シ邏 + if (packet_len > 0) { + packet_enable = TRUE; + } +} + +//--------------------------------------------------------------------------- +// +// 繝代こ繝繝亥叙蠕 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::GetPacketBuf(BYTE *buf) +{ + int len; + + ASSERT(this); + ASSERT(tap); + ASSERT(buf); + + // 繧オ繧、繧コ蛻カ髯 + len = packet_len; + if (len > 2048) { + len = 2048; + } + + // 繧ウ繝斐シ + memcpy(buf, packet_buf, len); + + // 蜿嶺ソ。貂医∩ + packet_enable = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝代こ繝繝磯∽ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::SendPacket(BYTE *buf, int len) +{ + ASSERT(this); + ASSERT(tap); + ASSERT(buf); + + tap->Tx(buf, len); +} + +//--------------------------------------------------------------------------- +// +// $40 - 繝繝舌う繧ケ襍キ蜍 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_InitDevice(BYTE *buf) +{ + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + fs->Reset(); + fsresult = fs->InitDevice((Human68k::argument_t*)buf); +} + +//--------------------------------------------------------------------------- +// +// $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_CheckDir(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->CheckDir(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_MakeDir(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->MakeDir(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_RemoveDir(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->RemoveDir(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Rename(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + Human68k::namests_t* pNamestsNew; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + pNamestsNew = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->Rename(nUnit, pNamests, pNamestsNew); +} + +//--------------------------------------------------------------------------- +// +// $45 - 繝輔ぃ繧、繝ォ蜑企勁 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Delete(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + fsresult = fs->Delete(nUnit, pNamests); +} + +//--------------------------------------------------------------------------- +// +// $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Attribute(BYTE *buf) +{ + DWORD nUnit; + Human68k::namests_t *pNamests; + DWORD nHumanAttribute; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + dp = (DWORD*)&buf[i]; + nHumanAttribute = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->Attribute(nUnit, pNamests, nHumanAttribute); +} + +//--------------------------------------------------------------------------- +// +// $47 - 繝輔ぃ繧、繝ォ讀懃エ「 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Files(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::namests_t *pNamests; + Human68k::files_t *files; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + files = (Human68k::files_t*)&buf[i]; + i += sizeof(Human68k::files_t); + + files->sector = ntohl(files->sector); + files->offset = ntohs(files->offset); + files->time = ntohs(files->time); + files->date = ntohs(files->date); + files->size = ntohl(files->size); + + fsresult = fs->Files(nUnit, nKey, pNamests, files); + + files->sector = htonl(files->sector); + files->offset = htons(files->offset); + files->time = htons(files->time); + files->date = htons(files->date); + files->size = htonl(files->size); + + i = 0; + memcpy(&fsout[i], files, sizeof(Human68k::files_t)); + i += sizeof(Human68k::files_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_NFiles(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::files_t *files; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + files = (Human68k::files_t*)&buf[i]; + i += sizeof(Human68k::files_t); + + files->sector = ntohl(files->sector); + files->offset = ntohs(files->offset); + files->time = ntohs(files->time); + files->date = ntohs(files->date); + files->size = ntohl(files->size); + + fsresult = fs->NFiles(nUnit, nKey, files); + + files->sector = htonl(files->sector); + files->offset = htons(files->offset); + files->time = htons(files->time); + files->date = htons(files->date); + files->size = htonl(files->size); + + i = 0; + memcpy(&fsout[i], files, sizeof(Human68k::files_t)); + i += sizeof(Human68k::files_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $49 - 繝輔ぃ繧、繝ォ菴懈 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Create(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::namests_t *pNamests; + Human68k::fcb_t *pFcb; + DWORD nAttribute; + BOOL bForce; + DWORD *dp; + BOOL *bp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nAttribute = ntohl(*dp); + i += sizeof(DWORD); + + bp = (BOOL*)&buf[i]; + bForce = ntohl(*bp); + i += sizeof(BOOL); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Create(nUnit, nKey, pNamests, pFcb, nAttribute, bForce); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Open(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::namests_t *pNamests; + Human68k::fcb_t *pFcb; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pNamests = (Human68k::namests_t*)&buf[i]; + i += sizeof(Human68k::namests_t); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Open(nUnit, nKey, pNamests, pFcb); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Close(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Close(nUnit, nKey, pFcb); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Read(BYTE *buf) +{ + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nSize; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nSize = ntohl(*dp); + i += sizeof(DWORD); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Read(nKey, pFcb, fsopt, nSize); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; + + fsoptlen = fsresult; +} + +//--------------------------------------------------------------------------- +// +// $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Write(BYTE *buf) +{ + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nSize; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nSize = ntohl(*dp); + i += sizeof(DWORD); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Write(nKey, pFcb, fsopt, nSize); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Seek(BYTE *buf) +{ + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nMode; + int nOffset; + DWORD *dp; + int *ip; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nMode = ntohl(*dp); + i += sizeof(DWORD); + + ip = (int*)&buf[i]; + nOffset = ntohl(*ip); + i += sizeof(int); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->Seek(nKey, pFcb, nMode, nOffset); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_TimeStamp(BYTE *buf) +{ + DWORD nUnit; + DWORD nKey; + Human68k::fcb_t *pFcb; + DWORD nHumanTime; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nKey = ntohl(*dp); + i += sizeof(DWORD); + + pFcb = (Human68k::fcb_t*)&buf[i]; + i += sizeof(Human68k::fcb_t); + + dp = (DWORD*)&buf[i]; + nHumanTime = ntohl(*dp); + i += sizeof(DWORD); + + pFcb->fileptr = ntohl(pFcb->fileptr); + pFcb->mode = ntohs(pFcb->mode); + pFcb->time = ntohs(pFcb->time); + pFcb->date = ntohs(pFcb->date); + pFcb->size = ntohl(pFcb->size); + + fsresult = fs->TimeStamp(nUnit, nKey, pFcb, nHumanTime); + + pFcb->fileptr = htonl(pFcb->fileptr); + pFcb->mode = htons(pFcb->mode); + pFcb->time = htons(pFcb->time); + pFcb->date = htons(pFcb->date); + pFcb->size = htonl(pFcb->size); + + i = 0; + memcpy(&fsout[i], pFcb, sizeof(Human68k::fcb_t)); + i += sizeof(Human68k::fcb_t); + + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $50 - 螳ケ驥丞叙蠕 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_GetCapacity(BYTE *buf) +{ + DWORD nUnit; + Human68k::capacity_t cap; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->GetCapacity(nUnit, &cap); + + cap.freearea = htons(cap.freearea); + cap.clusters = htons(cap.clusters); + cap.sectors = htons(cap.sectors); + cap.bytes = htons(cap.bytes); + + memcpy(fsout, &cap, sizeof(Human68k::capacity_t)); + fsoutlen = sizeof(Human68k::capacity_t); +} + +//--------------------------------------------------------------------------- +// +// $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_CtrlDrive(BYTE *buf) +{ + DWORD nUnit; + Human68k::ctrldrive_t *pCtrlDrive; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + pCtrlDrive = (Human68k::ctrldrive_t*)&buf[i]; + i += sizeof(Human68k::ctrldrive_t); + + fsresult = fs->CtrlDrive(nUnit, pCtrlDrive); + + memcpy(fsout, pCtrlDrive, sizeof(Human68k::ctrldrive_t)); + fsoutlen = sizeof(Human68k::ctrldrive_t); +} + +//--------------------------------------------------------------------------- +// +// $52 - DPB蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_GetDPB(BYTE *buf) +{ + DWORD nUnit; + Human68k::dpb_t dpb; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->GetDPB(nUnit, &dpb); + + dpb.sector_size = htons(dpb.sector_size); + dpb.fat_sector = htons(dpb.fat_sector); + dpb.file_max = htons(dpb.file_max); + dpb.data_sector = htons(dpb.data_sector); + dpb.cluster_max = htons(dpb.cluster_max); + dpb.root_sector = htons(dpb.root_sector); + + memcpy(fsout, &dpb, sizeof(Human68k::dpb_t)); + fsoutlen = sizeof(Human68k::dpb_t); +} + +//--------------------------------------------------------------------------- +// +// $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_DiskRead(BYTE *buf) +{ + DWORD nUnit; + DWORD nSector; + DWORD nSize; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nSector = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nSize = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->DiskRead(nUnit, fsout, nSector, nSize); + fsoutlen = 0x200; +} + +//--------------------------------------------------------------------------- +// +// $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_DiskWrite(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->DiskWrite(nUnit); +} + +//--------------------------------------------------------------------------- +// +// $55 - IOCTRL +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Ioctrl(BYTE *buf) +{ + DWORD nUnit; + DWORD nFunction; + Human68k::ioctrl_t *pIoctrl; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + nFunction = ntohl(*dp); + i += sizeof(DWORD); + + pIoctrl = (Human68k::ioctrl_t*)&buf[i]; + i += sizeof(Human68k::ioctrl_t); + + switch (nFunction) { + case 2: + case -2: + pIoctrl->param = htonl(pIoctrl->param); + break; + } + + fsresult = fs->Ioctrl(nUnit, nFunction, pIoctrl); + + switch (nFunction) { + case 0: + pIoctrl->media = htons(pIoctrl->media); + break; + case 1: + case -3: + pIoctrl->param = htonl(pIoctrl->param); + break; + } + + i = 0; + memcpy(&fsout[i], pIoctrl, sizeof(Human68k::ioctrl_t)); + i += sizeof(Human68k::ioctrl_t); + fsoutlen = i; +} + +//--------------------------------------------------------------------------- +// +// $56 - 繝輔Λ繝繧キ繝・ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Flush(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->Flush(nUnit); +} + +//--------------------------------------------------------------------------- +// +// $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_CheckMedia(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->CheckMedia(nUnit); +} + +//--------------------------------------------------------------------------- +// +// $58 - 謗剃サ門宛蠕。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::FS_Lock(BYTE *buf) +{ + DWORD nUnit; + DWORD *dp; + int i; + + ASSERT(this); + ASSERT(fs); + ASSERT(buf); + + i = 0; + dp = (DWORD*)buf; + nUnit = ntohl(*dp); + i += sizeof(DWORD); + + fsresult = fs->Lock(nUnit); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(邨先棡繧ウ繝シ繝) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::ReadFsResult(BYTE *buf) +{ + DWORD *dp; + + ASSERT(this); + ASSERT(buf); + + dp = (DWORD*)buf; + *dp = htonl(fsresult); + return sizeof(DWORD); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(霑泌唆繝繝シ繧ソ) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::ReadFsOut(BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + memcpy(buf, fsout, fsoutlen); + return fsoutlen; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(霑泌唆繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ) +// +//--------------------------------------------------------------------------- +int FASTCALL SCSIBR::ReadFsOpt(BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + memcpy(buf, fsopt, fsoptlen); + return fsoptlen; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::WriteFs(int func, BYTE *buf) +{ + ASSERT(this); + ASSERT(buf); + + fsresult = FS_FATAL_INVALIDCOMMAND; + fsoutlen = 0; + fsoptlen = 0; + + // 繧ウ繝槭Φ繝牙蟯 + func &= 0x1f; + switch (func) { + case 0x00: return FS_InitDevice(buf); // $40 - 繝繝舌う繧ケ襍キ蜍 + case 0x01: return FS_CheckDir(buf); // $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + case 0x02: return FS_MakeDir(buf); // $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 + case 0x03: return FS_RemoveDir(buf); // $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + case 0x04: return FS_Rename(buf); // $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 + case 0x05: return FS_Delete(buf); // $45 - 繝輔ぃ繧、繝ォ蜑企勁 + case 0x06: return FS_Attribute(buf); // $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 + case 0x07: return FS_Files(buf); // $47 - 繝輔ぃ繧、繝ォ讀懃エ「 + case 0x08: return FS_NFiles(buf); // $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 + case 0x09: return FS_Create(buf); // $49 - 繝輔ぃ繧、繝ォ菴懈 + case 0x0A: return FS_Open(buf); // $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + case 0x0B: return FS_Close(buf); // $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + case 0x0C: return FS_Read(buf); // $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + case 0x0D: return FS_Write(buf); // $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + case 0x0E: return FS_Seek(buf); // $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + case 0x0F: return FS_TimeStamp(buf); // $4F - 繝輔ぃ繧、繝ォ譖エ譁ー譎ょ綾縺ョ蜿門セ/險ュ螳 + case 0x10: return FS_GetCapacity(buf); // $50 - 螳ケ驥丞叙蠕 + case 0x11: return FS_CtrlDrive(buf); // $51 - 繝峨Λ繧、繝門宛蠕。/迥カ諷区、懈渊 + case 0x12: return FS_GetDPB(buf); // $52 - DPB蜿門セ + case 0x13: return FS_DiskRead(buf); // $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ + case 0x14: return FS_DiskWrite(buf); // $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ + case 0x15: return FS_Ioctrl(buf); // $55 - IOCTRL + case 0x16: return FS_Flush(buf); // $56 - 繝輔Λ繝繧キ繝・ + case 0x17: return FS_CheckMedia(buf); // $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + case 0x18: return FS_Lock(buf); // $58 - 謗剃サ門宛蠕。 + } +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ(蜈・蜉帙が繝励す繝ァ繝ウ繝繝シ繧ソ) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIBR::WriteFsOpt(BYTE *buf, int num) +{ + ASSERT(this); + + memcpy(fsopt, buf, num); +} + +//=========================================================================== +// +// SASI 繝繝舌う繧ケ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +#ifdef RASCSI +SASIDEV::SASIDEV() +#else +SASIDEV::SASIDEV(Device *dev) +#endif // RASCSI +{ + int i; + +#ifndef RASCSI + // 繝帙せ繝医ョ繝舌う繧ケ繧定ィ俶カ + host = dev; +#endif // RASCSI + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + ctrl.phase = BUS::busfree; + ctrl.id = -1; + ctrl.bus = NULL; + memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd)); + ctrl.status = 0x00; + ctrl.message = 0x00; + ctrl.bufsize = 0x800; + ctrl.buffer = new BYTE[ctrl.bufsize]; + memset(ctrl.buffer, 0x00, ctrl.bufsize); + ctrl.blocks = 0; + ctrl.next = 0; + ctrl.offset = 0; + ctrl.length = 0; + + // 隲也炊繝ヲ繝九ャ繝亥晄悄蛹 + for (i = 0; i < UnitMax; i++) { + ctrl.unit[i] = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +SASIDEV::~SASIDEV() +{ + // 繝舌ャ繝輔ぃ繧帝幕謾セ + if (ctrl.buffer) { + delete ctrl.buffer; + ctrl.buffer = NULL; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝舌う繧ケ繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Reset() +{ + int i; + + ASSERT(this); + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + memset(ctrl.cmd, 0x00, sizeof(ctrl.cmd)); + ctrl.phase = BUS::busfree; + ctrl.status = 0x00; + ctrl.message = 0x00; + memset(ctrl.buffer, 0x00, ctrl.bufsize); + ctrl.blocks = 0; + ctrl.next = 0; + ctrl.offset = 0; + ctrl.length = 0; + + // 繝ヲ繝九ャ繝亥晄悄蛹 + for (i = 0; i < UnitMax; i++) { + if (ctrl.unit[i]) { + ctrl.unit[i]->Reset(); + } + } +} + +#ifndef RASCSI +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::Save(Fileio *fio, int /*ver*/) +{ + DWORD sz; + + ASSERT(this); + ASSERT(fio); + + // 繧オ繧、繧コ繧偵そ繝シ繝 + sz = 2120; + if (!fio->Write(&sz, sizeof(sz))) { + return FALSE; + } + + // 螳滉ス薙r繧サ繝シ繝 + 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; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::Load(Fileio *fio, int ver) +{ + DWORD sz; + + ASSERT(this); + ASSERT(fio); + + // version3.11繧医j蜑阪ッ繧サ繝シ繝悶@縺ヲ縺縺ェ縺 + if (ver <= 0x0311) { + return TRUE; + } + + // 繧オ繧、繧コ繧偵Ο繝シ繝峨∫ァ蜷 + if (!fio->Read(&sz, sizeof(sz))) { + return FALSE; + } + if (sz != 2120) { + return FALSE; + } + + // 螳滉ス薙r繝ュ繝シ繝 + 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 + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繝医Ο繝シ繝ゥ謗・邯 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Connect(int id, BUS *bus) +{ + ASSERT(this); + + ctrl.id = id; + ctrl.bus = bus; +} + +//--------------------------------------------------------------------------- +// +// 隲也炊繝ヲ繝九ャ繝亥叙蠕 +// +//--------------------------------------------------------------------------- +Disk* FASTCALL SASIDEV::GetUnit(int no) +{ + ASSERT(this); + ASSERT(no < UnitMax); + + return ctrl.unit[no]; +} + +//--------------------------------------------------------------------------- +// +// 隲也炊繝ヲ繝九ャ繝郁ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::SetUnit(int no, Disk *dev) +{ + ASSERT(this); + ASSERT(no < UnitMax); + + ctrl.unit[no] = dev; +} + +//--------------------------------------------------------------------------- +// +// 譛牙柑縺ェ隲也炊繝ヲ繝九ャ繝医r謖√▲縺ヲ縺繧九°霑斐☆ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::HasUnit() +{ + int i; + + ASSERT(this); + + for (i = 0; i < UnitMax; i++) { + if (ctrl.unit[i]) { + return TRUE; + } + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 蜀驛ィ繝繝シ繧ソ蜿門セ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::GetCTRL(ctrl_t *buffer) +{ + ASSERT(this); + ASSERT(buffer); + + // 蜀驛ィ繝ッ繝シ繧ッ繧偵さ繝斐シ + *buffer = ctrl; +} + +//--------------------------------------------------------------------------- +// +// 繝薙ず繝シ迥カ諷九ョ繝ヲ繝九ャ繝医r蜿門セ +// +//--------------------------------------------------------------------------- +Disk* FASTCALL SASIDEV::GetBusyUnit() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + return ctrl.unit[lun]; +} + +//--------------------------------------------------------------------------- +// +// 螳溯。 +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL SASIDEV::Process() +{ + ASSERT(this); + + // 譛ェ謗・邯壹↑繧我ス輔b縺励↑縺 + if (ctrl.id < 0 || ctrl.bus == NULL) { + return ctrl.phase; + } + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝 + if (ctrl.bus->GetRST()) { +#if defined(DISK_LOG) + Log(Log::Normal, "RESET菫。蜿キ蜿嶺ソ。"); +#endif // DISK_LOG + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return ctrl.phase; + } + + // 繝輔ぉ繝シ繧コ蜃ヲ逅 + switch (ctrl.phase) { + // 繝舌せ繝輔Μ繝シ + case BUS::busfree: + BusFree(); + break; + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ + case BUS::selection: + Selection(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝(MCI=000) + case BUS::dataout: + DataOut(); + break; + + // 繝繝シ繧ソ繧、繝ウ(MCI=001) + case BUS::datain: + DataIn(); + break; + + // 繧ウ繝槭Φ繝(MCI=010) + case BUS::command: + Command(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ(MCI=011) + case BUS::status: + Status(); + break; + + // 繝。繝繧サ繝シ繧ク繧、繝ウ(MCI=111) + case BUS::msgin: + MsgIn(); + break; + + // 縺昴ョ莉 + default: + ASSERT(FALSE); + break; + } + + return ctrl.phase; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::BusFree() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::busfree) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::busfree; + + // 菫。蜿キ邱 + ctrl.bus->SetBSY(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetREQ(FALSE); + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧貞晄悄蛹 + ctrl.status = 0x00; + ctrl.message = 0x00; + + // 繝舌せ繧ッ繝ェ繧「繝繧」繝ャ繧、 + ctrl.bus->SleepNsec(Time_phase_bsy); + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺ォ遘サ陦 + if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { + Selection(); + } +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Selection() +{ + DWORD id; + + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::selection) { + // ID縺御ク閾エ縺励※縺縺ェ縺代l縺ー辟。蜉ケ + id = 1 << ctrl.id; + if ((ctrl.bus->GetDAT() & id) == 0) { + return; + } + + // 譛牙柑縺ェ繝ヲ繝九ャ繝医′辟。縺代l縺ー邨ゆコ + if (!HasUnit()) { + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ ID=%d (繝繝舌う繧ケ縺ゅj)", ctrl.id); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + ctrl.phase = BUS::selection; + + // BSY繧剃ク翫£縺ヲ蠢懃ュ + ctrl.bus->SetBSY(TRUE); + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ螳御コ縺ァ繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ遘サ陦 + if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { + Command(); + } +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Command() +{ + BYTE data; + int count; + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::command) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::command; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // 繝繝シ繧ソ霆「騾√ッ6繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 6; + ctrl.blocks = 1; + + // 譛蛻昴ョ1繝舌う繝医r蜿門セ(蜻ス莉、髟キ險育ョ励ョ縺溘a) + count = ctrl.bus->ReceiveHandShake(&data, 1); + ctrl.buffer[ctrl.offset] = data; + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (count != 1) { + Error(); + return; + } + + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10繝舌う繝CDB + ctrl.length = 10; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset++; + ctrl.length--; + return; + } + + // 蜿嶺ソ。 + Receive(); +} + +//--------------------------------------------------------------------------- +// +// 螳溯。後ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Execute() +{ + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "螳溯。後ヵ繧ァ繝シ繧コ 繧ウ繝槭Φ繝$%02X", ctrl.cmd[0]); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::execute; + + // 繝繝シ繧ソ霆「騾√ョ縺溘a縺ョ蛻晄悄蛹 + ctrl.offset = 0; + ctrl.blocks = 1; + + // 繧ウ繝槭Φ繝牙挨蜃ヲ逅 + switch (ctrl.cmd[0]) { + // TEST UNIT READY + case 0x00: + CmdTestUnitReady(); + return; + + // REZERO UNIT + case 0x01: + CmdRezero(); + return; + + // REQUEST SENSE + case 0x03: + CmdRequestSense(); + return; + + // FORMAT UNIT + case 0x04: + CmdFormat(); + return; + + // FORMAT UNIT + case 0x06: + 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; + + // ASSIGN(SASI縺ョ縺ソ) + case 0x0e: + CmdAssign(); + return; + + // SPECIFY(SASI縺ョ縺ソ) + case 0xc2: + CmdSpecify(); + return; + } + + // 縺昴l莉・螟悶ッ蟇セ蠢懊@縺ヲ縺縺ェ縺 + Log(Log::Warning, "譛ェ蟇セ蠢懊さ繝槭Φ繝 $%02X", ctrl.cmd[0]); + CmdInvalid(); +} + +//--------------------------------------------------------------------------- +// +// 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Status() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::status) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::status; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(TRUE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after_status); + + // 繝繝シ繧ソ霆「騾√ッ1繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = (BYTE)ctrl.status; + return; + } + + // 騾∽ソ。 + Send(); +} + +//--------------------------------------------------------------------------- +// +// 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::MsgIn() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::msgin) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::msgin; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(TRUE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(TRUE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // length, blocks縺ッ險ュ螳壽ク医∩ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.blocks > 0); + ctrl.offset = 0; + return; + } + + // 騾∽ソ。 + Send(); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::DataIn() +{ + ASSERT(this); + ASSERT(ctrl.length >= 0); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::datain) { + // 繝ャ繝ウ繧ー繧ケ0縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク + if (ctrl.length == 0) { + Status(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before_data); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::datain; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(TRUE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // length, blocks縺ッ險ュ螳壽ク医∩ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.blocks > 0); + ctrl.offset = 0; + return; + } + + // 騾∽ソ。 + Send(); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::DataOut() +{ + ASSERT(this); + ASSERT(ctrl.length >= 0); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::dataout) { + // 繝ャ繝ウ繧ー繧ケ0縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク + if (ctrl.length == 0) { + Status(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before_data); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::dataout; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // length, blocks縺ッ險ュ螳壽ク医∩ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.blocks > 0); + ctrl.offset = 0; + return; + } + + // 蜿嶺ソ。 + Receive(); +} + +//--------------------------------------------------------------------------- +// +// 蜈ア騾壹お繝ゥ繝シ +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Error() +{ + DWORD lun; + + ASSERT(this); + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝医メ繧ァ繝繧ッ + if (ctrl.bus->GetRST()) { + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縲√Γ繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ縺ッ繝舌せ繝輔Μ繝シ + if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { + BusFree(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Warning, "繧ィ繝ゥ繝シ(繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク)"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧定ィュ螳(CHECK CONDITION) + ctrl.status = (lun << 5) | 0x02; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdTestUnitReady() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "TEST UNIT READY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->TestUnitReady(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// REZERO UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdRezero() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "REZERO UNIT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Rezero(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdRequestSense() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "REQUEST SENSE繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->RequestSense(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length > 0); + +#if defined(DISK_LOG) + Log(Log::Normal, "繧サ繝ウ繧ケ繧ュ繝シ $%02X", ctrl.buffer[2]); +#endif // DISK_LOG + + // 繝ェ繝シ繝峨ヵ繧ァ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// FORMAT UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdFormat() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "FORMAT UNIT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Format(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// REASSIGN BLOCKS +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdReassign() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "REASSIGN BLOCKS繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Reassign(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ(6) +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdRead6() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[1] & 0x1f; + record <<= 8; + record |= ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + ctrl.blocks = ctrl.cmd[4]; + if (ctrl.blocks == 0) { + ctrl.blocks = 0x100; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "READ(6)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%06X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝ェ繝シ繝峨ヵ繧ァ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// WRITE(6) +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdWrite6() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[1] & 0x1f; + record <<= 8; + record |= ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + ctrl.blocks = ctrl.cmd[4]; + if (ctrl.blocks == 0) { + ctrl.blocks = 0x100; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "WRITE(6)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%06X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->WriteCheck(record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SEEK(6) +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdSeek6() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEEK(6)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// ASSIGN +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdAssign() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "ASSIGN繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Assign(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 4繝舌う繝医ョ繝繝シ繧ソ繧偵Μ繧ッ繧ィ繧ケ繝 + ctrl.length = 4; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SPECIFY +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdSpecify() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SPECIFY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Assign(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 10繝舌う繝医ョ繝繝シ繧ソ繧偵Μ繧ッ繧ィ繧ケ繝 + ctrl.length = 10; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::CmdInvalid() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (ctrl.unit[lun]) { + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.unit[lun]->InvalidCmd(); + } + + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); +} + +//=========================================================================== +// +// 繝繝シ繧ソ霆「騾 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ騾∽ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Send() +{ + int len; + BOOL result; + + ASSERT(this); + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧蛾∽ソ。 + if (ctrl.length != 0) { + len = ctrl.bus->SendHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ騾∽ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ蠑輔″蜿悶j蠕後ョ蜃ヲ逅(繝ェ繝シ繝/繝繝シ繧ソ繧、繝ウ縺ョ縺ソ) + if (ctrl.phase == BUS::datain) { + if (ctrl.blocks != 0) { + // 谺。縺ョ繝舌ャ繝輔ぃ繧定ィュ螳(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferIn(ctrl.buffer); + } + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧蛾∽ソ。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::msgin: + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + BusFree(); + break; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::datain: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + case BUS::status: + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = ctrl.message; + MsgIn(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿嶺ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Receive() +{ + BOOL result; + int i; + int len; + + ASSERT(this); + + // REQ,ACK縺御ク九′縺」縺ヲ縺繧九%縺ィ + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(!ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧牙女菫。 + if (ctrl.length != 0) { + // 蜿嶺ソ。 + len = ctrl.bus->ReceiveHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ蜿嶺ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ縺ョ蜃ヲ逅 + if (ctrl.phase == BUS::dataout) { + if (ctrl.blocks == 0) { + // 縺薙ョ繝舌ャ繝輔ぃ縺ァ邨ゆコ + result = XferOut(FALSE); + } else { + // 谺。縺ョ繝舌ャ繝輔ぃ縺ォ邯壹¥(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferOut(TRUE); + } + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧牙女菫。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + case BUS::command: + // 繧ウ繝槭Φ繝峨ョ繝シ繧ソ霆「騾 + len = 6; + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10繝舌う繝CDB + len = 10; + } + for (i = 0; i < len; i++) { + ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; +#if defined(DISK_LOG) + Log(Log::Normal, "繧ウ繝槭Φ繝 $%02X", ctrl.cmd[i]); +#endif // DISK_LOG + } + + // 螳溯。後ヵ繧ァ繝シ繧コ + Execute(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::dataout: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ霆「騾!N +// 窶サoffset, length繧貞崎ィュ螳壹☆繧九%縺ィ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::XferIn(BYTE *buf) +{ + DWORD lun; + + ASSERT(this); + ASSERT(ctrl.phase == BUS::datain); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + return FALSE; + } + + // READ邉サ繧ウ繝槭Φ繝峨↓髯舌k + switch (ctrl.cmd[0]) { + // READ(6) + case 0x08: + // READ(10) + case 0x28: + // 繝繧」繧ケ繧ッ縺九i隱ュ縺ソ蜿悶j繧定。後≧ + ctrl.length = ctrl.unit[lun]->Read(buf, ctrl.next); + ctrl.next++; + + // 繧ィ繝ゥ繝シ縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク + if (ctrl.length <= 0) { + // 繝繝シ繧ソ繧、繝ウ荳ュ豁「 + return FALSE; + } + + // 豁」蟶ク縺ェ繧峨√Ρ繝シ繧ッ險ュ螳 + ctrl.offset = 0; + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + return FALSE; + } + + // 繝舌ャ繝輔ぃ險ュ螳壹↓謌仙粥縺励◆ + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ霆「騾^UT +// 窶サcont=TRUE縺ョ蝣エ蜷医{ffset, length繧貞崎ィュ螳壹☆繧九%縺ィ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SASIDEV::XferOut(BOOL cont) +{ + DWORD lun; + SCSIBR *bridge; + + ASSERT(this); + ASSERT(ctrl.phase == BUS::dataout); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + return FALSE; + } + + // MODE SELECT縺セ縺溘ッ縲仝RITE邉サ + switch (ctrl.cmd[0]) { + // MODE SELECT + case 0x15: + // MODE SELECT(10) + case 0x55: + if (!ctrl.unit[lun]->ModeSelect(ctrl.cmd, ctrl.buffer, ctrl.offset)) { + // MODE SELECT縺ォ螟ア謨 + return FALSE; + } + break; + + // WRITE(6) + case 0x0a: + // WRITE(10) + case 0x2a: + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ッSEND MESSAGE10縺ォ蟾ョ縺玲崛縺医k + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + bridge = (SCSIBR*)ctrl.unit[lun]; + if (!bridge->SendMessage10(ctrl.cmd, ctrl.buffer)) { + // 譖ク縺崎セシ縺ソ螟ア謨 + return FALSE; + } + + // 豁」蟶ク縺ェ繧峨√Ρ繝シ繧ッ險ュ螳 + ctrl.offset = 0; + break; + } + + // WRITE AND VERIFY + case 0x2e: + // 譖ク縺崎セシ縺ソ繧定。後≧ + if (!ctrl.unit[lun]->Write(ctrl.buffer, ctrl.next - 1)) { + // 譖ク縺崎セシ縺ソ螟ア謨 + return FALSE; + } + + // 谺。縺ョ繝悶Ο繝繧ッ縺悟ソ隕√↑縺縺ェ繧峨%縺薙∪縺ァ + ctrl.next++; + if (!cont) { + break; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧偵メ繧ァ繝繧ッ + ctrl.length = ctrl.unit[lun]->WriteCheck(ctrl.next); + if (ctrl.length <= 0) { + // 譖ク縺崎セシ縺ソ縺ァ縺阪↑縺 + return FALSE; + } + + // 豁」蟶ク縺ェ繧峨√Ρ繝シ繧ッ險ュ螳 + ctrl.offset = 0; + break; + + default: + ASSERT(FALSE); + break; + } + + // 繝舌ャ繝輔ぃ菫晏ュ倥↓謌仙粥縺励◆ + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繧ー蜃コ蜉 +// +//--------------------------------------------------------------------------- +void FASTCALL SASIDEV::Log(Log::loglevel level, const char *format, ...) +{ + char buffer[0x200]; + va_list args; + va_start(args, format); + +#ifdef RASCSI +#ifndef DISK_LOG + if (level == Log::Warning) { + return; + } +#endif // DISK_LOG +#endif // RASCSI + + // 繝輔か繝シ繝槭ャ繝 + vsprintf(buffer, format, args); + + // 蜿ッ螟蛾聞蠑墓焚邨ゆコ + va_end(args); + + // 繝ュ繧ー蜃コ蜉 +#ifdef RASCSI + printf("%s\n", buffer); +#else + host->GetVM()->GetLog()->Format(level, host, buffer); +#endif // RASCSI +} + +//=========================================================================== +// +// SCSI 繝繝舌う繧ケ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +#ifdef RASCSI +SCSIDEV::SCSIDEV() : SASIDEV() +#else +SCSIDEV::SCSIDEV(Device *dev) : SASIDEV(dev) +#endif +{ + // 蜷梧悄霆「騾√Ρ繝シ繧ッ蛻晄悄蛹 + scsi.syncenable = FALSE; + scsi.syncperiod = 50; + scsi.syncoffset = 0; + scsi.atnmsg = FALSE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); +} + +//--------------------------------------------------------------------------- +// +// 繝繝舌う繧ケ繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Reset() +{ + ASSERT(this); + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + scsi.atnmsg = FALSE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); + + // 蝓コ蠎輔け繝ゥ繧ケ + SASIDEV::Reset(); +} + +//--------------------------------------------------------------------------- +// +// 螳溯。 +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL SCSIDEV::Process() +{ + ASSERT(this); + + // 譛ェ謗・邯壹↑繧我ス輔b縺励↑縺 + if (ctrl.id < 0 || ctrl.bus == NULL) { + return ctrl.phase; + } + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝 + if (ctrl.bus->GetRST()) { +#if defined(DISK_LOG) + Log(Log::Normal, "RESET菫。蜿キ蜿嶺ソ。"); +#endif // DISK_LOG + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return ctrl.phase; + } + + // 繝輔ぉ繝シ繧コ蜃ヲ逅 + switch (ctrl.phase) { + + // 繝舌せ繝輔Μ繝シ + case BUS::busfree: + BusFree(); + break; + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + case BUS::selection: + Selection(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝(MCI=000) + case BUS::dataout: + DataOut(); + break; + + // 繝繝シ繧ソ繧、繝ウ(MCI=001) + case BUS::datain: + DataIn(); + break; + + // 繧ウ繝槭Φ繝(MCI=010) + case BUS::command: + Command(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ(MCI=011) + case BUS::status: + Status(); + break; + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝(MCI=110) + case BUS::msgout: + MsgOut(); + break; + + // 繝。繝繧サ繝シ繧ク繧、繝ウ(MCI=111) + case BUS::msgin: + MsgIn(); + break; + + // 縺昴ョ莉 + default: + ASSERT(FALSE); + break; + } + + return ctrl.phase; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::BusFree() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::busfree) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ"); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::busfree; + + // 菫。蜿キ邱 + ctrl.bus->SetBSY(FALSE); + ctrl.bus->SetMSG(FALSE); + ctrl.bus->SetCD(FALSE); + ctrl.bus->SetIO(FALSE); + ctrl.bus->SetREQ(FALSE); + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧貞晄悄蛹 + ctrl.status = 0x00; + ctrl.message = 0x00; + + // ATN繝。繝繧サ繝シ繧ク蜿嶺ソ。繧ケ繧ソ繝シ繧ソ繧ケ蛻晄悄蛹 + scsi.atnmsg = FALSE; + + // 繝舌せ繧ッ繝ェ繧「繝繧」繝ャ繧、 + ctrl.bus->SleepNsec(Time_phase_bsy); + + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺ォ遘サ陦 + if (ctrl.bus->GetSEL() && !ctrl.bus->GetBSY()) { + Selection(); + } +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Selection() +{ + DWORD id; + + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::selection) { + // ID縺御ク閾エ縺励※縺縺ェ縺代l縺ー辟。蜉ケ + id = 1 << ctrl.id; + if ((ctrl.bus->GetDAT() & id) == 0) { + return; + } + + // 譛牙柑縺ェ繝ヲ繝九ャ繝医′辟。縺代l縺ー邨ゆコ + if (!HasUnit()) { + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ ID=%d (繝繝舌う繧ケ縺ゅj)", ctrl.id); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::selection; + + // BSY繧剃ク翫£縺ヲ蠢懃ュ + ctrl.bus->SetBSY(TRUE); + return; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ螳御コ + if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) { + // ATN=1縺ェ繧峨Γ繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ縲√◎縺縺ァ縺ェ縺代l縺ー繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + if (ctrl.bus->GetATN()) { + MsgOut(); + } else { + Command(); + } + } +} + +//--------------------------------------------------------------------------- +// +// 螳溯。後ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Execute() +{ + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "螳溯。後ヵ繧ァ繝シ繧コ 繧ウ繝槭Φ繝$%02X", ctrl.cmd[0]); +#endif // DISK_LOG + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::execute; + + // 繝繝シ繧ソ霆「騾√ョ縺溘a縺ョ蛻晄悄蛹 + ctrl.offset = 0; + ctrl.blocks = 1; + + // 蜃ヲ逅譎る俣縺ョ繝繧」繝ャ繧、 + ctrl.bus->SleepNsec(100 * 1000); + + // 繧ウ繝槭Φ繝牙挨蜃ヲ逅 + switch (ctrl.cmd[0]) { + // TEST UNIT READY + case 0x00: + CmdTestUnitReady(); + return; + + // REZERO + case 0x01: + CmdRezero(); + return; + + // REQUEST SENSE + case 0x03: + CmdRequestSense(); + return; + + // FORMAT UNIT + case 0x04: + CmdFormat(); + return; + + // REASSIGN BLOCKS + case 0x07: + CmdReassign(); + return; + + // READ(6) + case 0x08: + CmdRead6(); + return; + + // WRITE(6) + case 0x0a: + CmdWrite6(); + return; + + // SEEK(6) + case 0x0b: + CmdSeek6(); + return; + + // INQUIRY + case 0x12: + CmdInquiry(); + return; + + // MODE SELECT + case 0x15: + CmdModeSelect(); + return; + + // MDOE SENSE + case 0x1a: + CmdModeSense(); + return; + + // START STOP UNIT + case 0x1b: + CmdStartStop(); + return; + + // SEND DIAGNOSTIC + case 0x1d: + CmdSendDiag(); + return; + + // PREVENT/ALLOW MEDIUM REMOVAL + case 0x1e: + CmdRemoval(); + return; + + // READ CAPACITY + case 0x25: + CmdReadCapacity(); + return; + + // READ(10) + case 0x28: + CmdRead10(); + return; + + // WRITE(10) + case 0x2a: + CmdWrite10(); + return; + + // SEEK(10) + case 0x2b: + CmdSeek10(); + return; + + // WRITE and VERIFY + case 0x2e: + CmdWrite10(); + return; + + // VERIFY + case 0x2f: + CmdVerify(); + return; + + // SYNCHRONIZE CACHE + case 0x35: + CmdSynchronizeCache(); + return; + + // READ DEFECT DATA(10) + case 0x37: + CmdReadDefectData10(); + return; + + // READ TOC + case 0x43: + CmdReadToc(); + return; + + // PLAY AUDIO(10) + case 0x45: + CmdPlayAudio10(); + return; + + // PLAY AUDIO MSF + case 0x47: + CmdPlayAudioMSF(); + return; + + // PLAY AUDIO TRACK + case 0x48: + CmdPlayAudioTrack(); + return; + + // MODE SELECT(10) + case 0x55: + CmdModeSelect10(); + return; + + // MDOE SENSE(10) + case 0x5a: + CmdModeSense10(); + return; + } + + // 縺昴l莉・螟悶ッ蟇セ蠢懊@縺ヲ縺縺ェ縺 + Log(Log::Normal, "譛ェ蟇セ蠢懊さ繝槭Φ繝 $%02X", ctrl.cmd[0]); + CmdInvalid(); +} + +//--------------------------------------------------------------------------- +// +// 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::MsgOut() +{ + ASSERT(this); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク + if (ctrl.phase != BUS::msgout) { + +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ"); +#endif // DISK_LOG + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ蠕後ョ繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ縺ッIDENTIFY繝。繝繧サ繝シ繧ク縺ョ蜃ヲ逅 + if (ctrl.phase == BUS::selection) { + scsi.atnmsg = TRUE; + scsi.msc = 0; + memset(scsi.msb, 0x00, sizeof(scsi.msb)); + } + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蜑阪ョ繧ヲ繧ァ繧、繝 + ctrl.bus->SleepNsec(Time_phase_before); + + // 繝輔ぉ繝シ繧コ險ュ螳 + ctrl.phase = BUS::msgout; + + // 繧ソ繝シ繧イ繝繝医′謫堺ス懊☆繧倶ソ。蜿キ邱 + ctrl.bus->SetMSG(TRUE); + ctrl.bus->SetCD(TRUE); + ctrl.bus->SetIO(FALSE); + + // 繝輔ぉ繝シ繧コ繝√ぉ繝ウ繧ク蠕後ョ莠亥相譎る俣 + ctrl.bus->SleepNsec(Time_phase_after); + + // 繝繝シ繧ソ霆「騾√ッ1繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + return; + } + + // 蜿嶺ソ。 + Receive(); +} + +//--------------------------------------------------------------------------- +// +// 蜈ア騾壹お繝ゥ繝シ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Error() +{ + ASSERT(this); + + // 繝舌せ諠蝣ア縺ョ蜿悶j霎シ縺ソ + ctrl.bus->Aquire(); + + // 繝ェ繧サ繝繝医メ繧ァ繝繧ッ + if (ctrl.bus->GetRST()) { + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧偵Μ繧サ繝繝 + Reset(); + + // 繝舌せ繧ゅΜ繧サ繝繝 + ctrl.bus->Reset(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縲√Γ繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ縺ッ繝舌せ繝輔Μ繝シ + if (ctrl.phase == BUS::status || ctrl.phase == BUS::msgin) { + BusFree(); + return; + } + +#if defined(DISK_LOG) + Log(Log::Normal, "繧ィ繝ゥ繝シ(繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク)"); +#endif // DISK_LOG + + // 繧ケ繝繝シ繧ソ繧ケ縺ィ繝。繝繧サ繝シ繧ク繧定ィュ螳(CHECK CONDITION) + ctrl.status = 0x02; + ctrl.message = 0x00; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// INQUIRY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdInquiry() +{ + Disk *disk; + int lun; + DWORD major; + DWORD minor; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "INQUIRY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 譛牙柑縺ェ繝ヲ繝九ャ繝医r謗「縺 + disk = NULL; + for (lun = 0; lun < UnitMax; lun++) { + if (ctrl.unit[lun]) { + disk = ctrl.unit[lun]; + break; + } + } + + // 繝繧」繧ケ繧ッ蛛エ縺ァ蜃ヲ逅(譛ャ譚・縺ッ繧ウ繝ウ繝医Ο繝シ繝ゥ縺ァ蜃ヲ逅縺輔l繧) + if (disk) { +#ifdef RASCSI + major = (DWORD)(RASCSI >> 8); + minor = (DWORD)(RASCSI & 0xff); +#else + host->GetVM()->GetVersion(major, minor); +#endif // RASCSI + ctrl.length = ctrl.unit[lun]->Inquiry(ctrl.cmd, ctrl.buffer, major, minor); + } else { + ctrl.length = 0; + } + + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 蜷梧悄霆「騾√し繝昴シ繝域ュ蝣ア縺ョ霑ス蜉 + if (scsi.syncenable) { + ctrl.buffer[7] |= (1 << 4); + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSelect() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SELECT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->SelectCheck(ctrl.cmd); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSense() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SENSE繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ModeSense(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + if (ctrl.length == 0) { + Log(Log::Warning, "繧オ繝昴シ繝医@縺ヲ縺縺ェ縺МODE SENSE繝壹シ繧ク $%02X", ctrl.cmd[2]); + + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// START STOP UNIT +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdStartStop() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "START STOP UNIT繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->StartStop(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// SEND DIAGNOSTIC +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSendDiag() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEND DIAGNOSTIC繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->SendDiag(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// PREVENT/ALLOW MEDIUM REMOVAL +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdRemoval() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "PREVENT/ALLOW MEDIUM REMOVAL繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Removal(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdReadCapacity() +{ + DWORD lun; + int length; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "READ CAPACITY繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + length = ctrl.unit[lun]->ReadCapacity(ctrl.cmd, ctrl.buffer); + ASSERT(length >= 0); + if (length <= 0) { + Error(); + return; + } + + // 繝ャ繝ウ繧ー繧ケ險ュ螳 + ctrl.length = length; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// READ(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdRead10() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ェ繧峨Γ繝繧サ繝シ繧ク蜿嶺ソ。 + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + CmdGetMessage10(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "READ(10)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%08X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝悶Ο繝繧ッ謨ー0縺ッ蜃ヲ逅縺励↑縺 + if (ctrl.blocks == 0) { + Status(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// WRITE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdWrite10() +{ + DWORD lun; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ェ繧峨Γ繝繧サ繝シ繧ク蜿嶺ソ。 + if (ctrl.unit[lun]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + CmdSendMessage10(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "WRTIE(10)繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%08X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝悶Ο繝繧ッ謨ー0縺ッ蜃ヲ逅縺励↑縺 + if (ctrl.blocks == 0) { + Status(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->WriteCheck(record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SEEK(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSeek10() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "SEEK(10)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// VERIFY +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdVerify() +{ + DWORD lun; + BOOL status; + DWORD record; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝ャ繧ウ繝シ繝臥分蜿キ縺ィ繝悶Ο繝繧ッ謨ー繧貞叙蠕 + record = ctrl.cmd[2]; + record <<= 8; + record |= ctrl.cmd[3]; + record <<= 8; + record |= ctrl.cmd[4]; + record <<= 8; + record |= ctrl.cmd[5]; + ctrl.blocks = ctrl.cmd[7]; + ctrl.blocks <<= 8; + ctrl.blocks |= ctrl.cmd[8]; + +#if defined(DISK_LOG) + Log(Log::Normal, "VERIFY繧ウ繝槭Φ繝 繝ャ繧ウ繝シ繝=%08X 繝悶Ο繝繧ッ=%d", record, ctrl.blocks); +#endif // DISK_LOG + + // 繝悶Ο繝繧ッ謨ー0縺ッ蜃ヲ逅縺励↑縺 + if (ctrl.blocks == 0) { + Status(); + return; + } + + // BytChk=0縺ェ繧 + if ((ctrl.cmd[1] & 0x02) == 0) { + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->Seek(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + return; + } + + // 繝繧ケ繝郁ェュ縺ソ霎シ縺ソ + ctrl.length = ctrl.unit[lun]->Read(ctrl.buffer, record); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.next = record + 1; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// SYNCHRONIZE CACHE +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSynchronizeCache() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 謌仙粥縺励◆縺薙→縺ォ縺吶k(譛ェ螳溯」) + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// READ DEFECT DATA(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdReadDefectData10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "READ DEFECT DATA(10)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ReadDefectData10(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + + if (ctrl.length <= 4) { + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// READ TOC +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdReadToc() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ReadToc(ctrl.cmd, ctrl.buffer); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdPlayAudio10() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->PlayAudio(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO MSF +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdPlayAudioMSF() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->PlayAudioMSF(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// PLAY AUDIO TRACK +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdPlayAudioTrack() +{ + DWORD lun; + BOOL status; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + status = ctrl.unit[lun]->PlayAudioTrack(ctrl.cmd); + if (!status) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); +} + +//--------------------------------------------------------------------------- +// +// MODE SELECT10 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSelect10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SELECT10繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->SelectCheck10(ctrl.cmd); + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdModeSense10() +{ + DWORD lun; + + ASSERT(this); + +#if defined(DISK_LOG) + Log(Log::Normal, "MODE SENSE(10)繧ウ繝槭Φ繝"); +#endif // DISK_LOG + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝峨Λ繧、繝悶〒繧ウ繝槭Φ繝牙ヲ逅 + ctrl.length = ctrl.unit[lun]->ModeSense10(ctrl.cmd, ctrl.buffer); + ASSERT(ctrl.length >= 0); + if (ctrl.length == 0) { + Log(Log::Warning, "繧オ繝昴シ繝医@縺ヲ縺縺ェ縺МODE SENSE(10)繝壹シ繧ク $%02X", ctrl.cmd[2]); + + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// GET MESSAGE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdGetMessage10() +{ + DWORD lun; + SCSIBR *bridge; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ァ縺ェ縺縺ェ繧峨お繝ゥ繝シ + if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { + Error(); + return; + } + + // 繝舌ャ繝輔ぃ縺ョ蜀咲「コ菫(繝悶Ο繝繧ッ豈弱ョ霆「騾√〒縺ッ縺ェ縺縺溘a) + if (ctrl.bufsize < 0x1000000) { + delete ctrl.buffer; + ctrl.bufsize = 0x1000000; + ctrl.buffer = new BYTE[ctrl.bufsize]; + } + + // 繝峨Λ繧、繝悶〒蜃ヲ逅縺吶k + bridge = (SCSIBR*)ctrl.unit[lun]; + ctrl.length = bridge->GetMessage10(ctrl.cmd, ctrl.buffer); + + if (ctrl.length <= 0) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.blocks = 1; + ctrl.next = 1; + + // 繝ェ繝シ繝峨ヵ繧ァ繝シ繧コ + DataIn(); +} + +//--------------------------------------------------------------------------- +// +// SEND MESSAGE(10) +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::CmdSendMessage10() +{ + DWORD lun; + + ASSERT(this); + + // 隲也炊繝ヲ繝九ャ繝 + lun = (ctrl.cmd[1] >> 5) & 0x07; + if (!ctrl.unit[lun]) { + Error(); + return; + } + + // 繝帙せ繝医ヶ繝ェ繝繧ク縺ァ縺ェ縺縺ェ繧峨お繝ゥ繝シ + if (ctrl.unit[lun]->GetID() != MAKEID('S', 'C', 'B', 'R')) { + Error(); + return; + } + + // 繝舌ャ繝輔ぃ縺ョ蜀咲「コ菫(繝悶Ο繝繧ッ豈弱ョ霆「騾√〒縺ッ縺ェ縺縺溘a) + if (ctrl.bufsize < 0x1000000) { + delete ctrl.buffer; + ctrl.bufsize = 0x1000000; + ctrl.buffer = new BYTE[ctrl.bufsize]; + } + + // 霆「騾驥上r險ュ螳 + 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) { + // 螟ア謨(繧ィ繝ゥ繝シ) + Error(); + return; + } + + // 谺。縺ョ繝悶Ο繝繧ッ繧定ィュ螳 + ctrl.blocks = 1; + ctrl.next = 1; + + // 繝ゥ繧、繝医ヵ繧ァ繝シ繧コ + DataOut(); +} + +//=========================================================================== +// +// 繝繝シ繧ソ霆「騾 +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ騾∽ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Send() +{ + int len; + BOOL result; + + ASSERT(this); + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧蛾∽ソ。 + if (ctrl.length != 0) { + len = ctrl.bus->SendHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ騾∽ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ蠑輔″蜿悶j蠕後ョ蜃ヲ逅(繝ェ繝シ繝/繝繝シ繧ソ繧、繝ウ縺ョ縺ソ) + if (ctrl.phase == BUS::datain) { + if (ctrl.blocks != 0) { + // 谺。縺ョ繝舌ャ繝輔ぃ繧定ィュ螳(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferIn(ctrl.buffer); + } + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧蛾∽ソ。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::msgin: + // IDENTIFY繝。繝繧サ繝シ繧ク縺ョ諡。蠑オ繝。繝繧サ繝シ繧ク縺ォ蟇セ縺吶k蠢懃ュ秘∽ソ。螳御コ + if (scsi.atnmsg) { + // 繝輔Λ繧ー繧ェ繝 + scsi.atnmsg = FALSE; + + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + Command(); + } else { + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + BusFree(); + } + break; + + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + case BUS::datain: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + case BUS::status: + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = ctrl.message; + MsgIn(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿嶺ソ。 +// +//--------------------------------------------------------------------------- +void FASTCALL SCSIDEV::Receive() +{ + BYTE data; + BOOL result; + int i; + int len; + + ASSERT(this); + + // REQ,ACK縺御ク九′縺」縺ヲ縺繧九%縺ィ + ASSERT(!ctrl.bus->GetREQ()); + ASSERT(!ctrl.bus->GetACK()); + ASSERT(!ctrl.bus->GetIO()); + + // 繝ャ繝ウ繧ー繧ケ!=0縺ェ繧牙女菫。 + if (ctrl.length != 0) { + // 蜿嶺ソ。 + len = ctrl.bus->ReceiveHandShake( + &ctrl.buffer[ctrl.offset], ctrl.length); + + // 蜈ィ縺ヲ蜿嶺ソ。縺ァ縺阪↑縺代l縺ー繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (len != ctrl.length) { + Error(); + return; + } + + // 繧ェ繝輔そ繝繝医→繝ャ繝ウ繧ー繧ケ + ctrl.offset += ctrl.length; + ctrl.length = 0;; + return; + } + + // 繝悶Ο繝繧ッ貂帷ョ励√Μ繧カ繝ォ繝亥晄悄蛹 + ctrl.blocks--; + result = TRUE; + + // 繝繝シ繧ソ蜿礼炊蠕後ョ蜃ヲ逅(繝輔ぉ繝シ繧コ蛻・) + switch (ctrl.phase) { + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::dataout: + if (ctrl.blocks == 0) { + // 縺薙ョ繝舌ャ繝輔ぃ縺ァ邨ゆコ + result = XferOut(FALSE); + } else { + // 谺。縺ョ繝舌ャ繝輔ぃ縺ォ邯壹¥(offset, length繧偵そ繝繝医☆繧九%縺ィ) + result = XferOut(TRUE); + } + break; + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::msgout: + ctrl.message = ctrl.buffer[0]; + if (!XferMsg(ctrl.message)) { + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医↓螟ア謨励@縺溘i縲∝叉蠎ァ縺ォ繝舌せ繝輔Μ繝シ + BusFree(); + return; + } + + // 繝。繝繧サ繝シ繧ク繧、繝ウ縺ォ蛯吶∴縲√Γ繝繧サ繝シ繧ク繝繝シ繧ソ繧偵け繝ェ繧「縺励※縺翫¥ + ctrl.message = 0x00; + break; + + default: + break; + } + + // 繝ェ繧カ繝ォ繝FALSE縺ェ繧峨√せ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ縺ク遘サ陦 + if (!result) { + Error(); + return; + } + + // 繝悶Ο繝繧ッ!=0縺ェ繧牙女菫。邯咏カ + if (ctrl.blocks != 0){ + ASSERT(ctrl.length > 0); + ASSERT(ctrl.offset == 0); + return; + } + + // 谺。繝輔ぉ繝シ繧コ縺ォ遘サ蜍 + switch (ctrl.phase) { + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + case BUS::command: + // 繧ウ繝槭Φ繝峨ョ繝シ繧ソ霆「騾 + len = 6; + if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) { + // 10繝舌う繝CDB + len = 10; + } + for (i = 0; i < len; i++) { + ctrl.cmd[i] = (DWORD)ctrl.buffer[i]; +#if defined(DISK_LOG) + Log(Log::Normal, "繧ウ繝槭Φ繝 $%02X", ctrl.cmd[i]); +#endif // DISK_LOG + } + + // 螳溯。後ヵ繧ァ繝シ繧コ + Execute(); + break; + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::msgout: + // ATN縺後い繧オ繝シ繝医@邯壹¢繧矩剞繧翫Γ繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ繧堤カ咏カ + if (ctrl.bus->GetATN()) { + // 繝繝シ繧ソ霆「騾√ッ1繝舌う繝x1繝悶Ο繝繧ッ + ctrl.offset = 0; + ctrl.length = 1; + ctrl.blocks = 1; + return; + } + + // ATN縺ァ騾∽ソ。縺輔l縺溘Γ繝繧サ繝シ繧ク縺ョ隗」譫 + if (scsi.atnmsg) { + i = 0; + while (i < scsi.msc) { + // 繝。繝繧サ繝シ繧ク縺ョ遞ョ鬘 + data = scsi.msb[i]; + + // ABORT + if (data == 0x06) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 ABORT $%02X", data); +#endif // DISK_LOG + BusFree(); + return; + } + + // BUS DEVICE RESET + if (data == 0x0C) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 BUS DEVICE RESET $%02X", data); +#endif // DISK_LOG + scsi.syncoffset = 0; + BusFree(); + return; + } + + // IDENTIFY + if (data >= 0x80) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 IDENTIFY $%02X", data); +#endif // DISK_LOG + } + + // 諡。蠑オ繝。繝繧サ繝シ繧ク + if (data == 0x01) { +#if defined(DISK_LOG) + Log(Log::Normal, "繝。繝繧サ繝シ繧ク繧ウ繝シ繝 EXTENDED MESSAGE $%02X", data); +#endif // DISK_LOG + + // 蜷梧悄霆「騾√′蜿ッ閭ス縺ェ譎ゅ□縺代メ繧ァ繝繧ッ + if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) { + ctrl.length = 1; + ctrl.blocks = 1; + ctrl.buffer[0] = 0x07; + MsgIn(); + return; + } + + // Transfer period factor(50 x 4 = 200ns縺ォ蛻カ髯) + scsi.syncperiod = scsi.msb[i + 3]; + if (scsi.syncperiod > 50) { + scsi.syncoffset = 50; + } + + // REQ/ACK offset(16縺ォ蛻カ髯) + scsi.syncoffset = scsi.msb[i + 4]; + if (scsi.syncoffset > 16) { + scsi.syncoffset = 16; + } + + // STDR蠢懃ュ斐Γ繝繧サ繝シ繧ク逕滓 + ctrl.length = 5; + ctrl.blocks = 1; + ctrl.buffer[0] = 0x01; + ctrl.buffer[1] = 0x03; + ctrl.buffer[2] = 0x01; + ctrl.buffer[3] = scsi.syncperiod; + ctrl.buffer[4] = scsi.syncoffset; + MsgIn(); + return; + } + + // 谺。縺ク + i++; + } + } + + // ATN繝。繝繧サ繝シ繧ク蜿嶺ソ。繧ケ繧ソ繝シ繧ソ繧ケ蛻晄悄蛹 + scsi.atnmsg = FALSE; + + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + Command(); + break; + + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + case BUS::dataout: + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + Status(); + break; + + // 縺昴ョ莉(縺ゅj縺医↑縺) + default: + ASSERT(FALSE); + break; + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ霆「騾`SG +// +//--------------------------------------------------------------------------- +BOOL FASTCALL SCSIDEV::XferMsg(DWORD msg) +{ + ASSERT(this); + ASSERT(ctrl.phase == BUS::msgout); + + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ョ繝シ繧ソ縺ョ菫晏ュ + if (scsi.atnmsg) { + scsi.msb[scsi.msc] = msg; + scsi.msc++; + scsi.msc %= 256; + } + + return TRUE; +} diff --git a/src/raspberrypi/disk.h b/src/raspberrypi/disk.h new file mode 100644 index 00000000..0d440890 --- /dev/null +++ b/src/raspberrypi/disk.h @@ -0,0 +1,1108 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// XM6i +// Copyright (C) 2010-2015 isaki@NetBSD.org +// +// Imported sava's Anex86/T98Next image and MO format support patch. +// +// [ 繝繧」繧ケ繧ッ ] +// +//--------------------------------------------------------------------------- + +#if !defined(disk_h) +#define disk_h + +#include "log.h" +#include "scsi.h" + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ゥ繝シ螳夂セゥ(REQUEST SENSE縺ァ霑斐&繧後k繧サ繝ウ繧ケ繧ウ繝シ繝) +// +// MSB 莠育エ(0x00) +// 繧サ繝ウ繧ケ繧ュ繝シ +// 諡。蠑オ繧サ繝ウ繧ケ繧ウ繝シ繝(ASC) +// LSB 諡。蠑オ繧サ繝ウ繧ケ繧ウ繝シ繝峨け繧ゥ繝ェ繝輔ぃ繧、繧「(ASCQ) +// +//--------------------------------------------------------------------------- +#define DISK_NOERROR 0x00000000 // NO ADDITIONAL SENSE INFO. +#define DISK_DEVRESET 0x00062900 // POWER ON OR RESET OCCURED +#define DISK_NOTREADY 0x00023a00 // MEDIUM NOT PRESENT +#define DISK_ATTENTION 0x00062800 // MEDIUM MAY HAVE CHANGED +#define DISK_PREVENT 0x00045302 // MEDIUM REMOVAL PREVENTED +#define DISK_READFAULT 0x00031100 // UNRECOVERED READ ERROR +#define DISK_WRITEFAULT 0x00030300 // PERIPHERAL DEVICE WRITE FAULT +#define DISK_WRITEPROTECT 0x00042700 // WRITE PROTECTED +#define DISK_MISCOMPARE 0x000e1d00 // MISCOMPARE DURING VERIFY +#define DISK_INVALIDCMD 0x00052000 // INVALID COMMAND OPERATION CODE +#define DISK_INVALIDLBA 0x00052100 // LOGICAL BLOCK ADDR. OUT OF RANGE +#define DISK_INVALIDCDB 0x00052400 // INVALID FIELD IN CDB +#define DISK_INVALIDLUN 0x00052500 // LOGICAL UNIT NOT SUPPORTED +#define DISK_INVALIDPRM 0x00052600 // INVALID FIELD IN PARAMETER LIST +#define DISK_INVALIDMSG 0x00054900 // INVALID MESSAGE ERROR +#define DISK_PARAMLEN 0x00051a00 // PARAMETERS LIST LENGTH ERROR +#define DISK_PARAMNOT 0x00052601 // PARAMETERS NOT SUPPORTED +#define DISK_PARAMVALUE 0x00052602 // PARAMETERS VALUE INVALID +#define DISK_PARAMSAVE 0x00053900 // SAVING PARAMETERS NOT SUPPORTED +#define DISK_NODEFECT 0x00010000 // DEFECT LIST NOT FOUND + +#if 0 +#define DISK_AUDIOPROGRESS 0x00??0011 // AUDIO PLAY IN PROGRESS +#define DISK_AUDIOPAUSED 0x00??0012 // AUDIO PLAY PAUSED +#define DISK_AUDIOSTOPPED 0x00??0014 // AUDIO PLAY STOPPED DUE TO ERROR +#define DISK_AUDIOCOMPLETE 0x00??0013 // AUDIO PLAY SUCCESSFULLY COMPLETED +#endif + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繝医Λ繝繧ッ +// +//=========================================================================== +class DiskTrack +{ +public: + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + int track; // 繝医Λ繝繧ッ繝翫Φ繝舌シ + int size; // 繧サ繧ッ繧ソ繧オ繧、繧コ(8 or 9) + int sectors; // 繧サ繧ッ繧ソ謨ー(<=0x100) + DWORD length; // 繝繝シ繧ソ繝舌ャ繝輔ぃ髟キ + BYTE *buffer; // 繝繝シ繧ソ繝舌ャ繝輔ぃ + BOOL init; // 繝ュ繝シ繝画ク医∩縺 + BOOL changed; // 螟画峩貂医∩繝輔Λ繧ー + DWORD maplen; // 螟画峩貂医∩繝槭ャ繝鈴聞 + BOOL *changemap; // 螟画峩貂医∩繝槭ャ繝 + BOOL raw; // RAW繝「繝シ繝 + off64_t imgoffset; // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 + } disktrk_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + DiskTrack(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~DiskTrack(); + // 繝繧ケ繝医Λ繧ッ繧ソ + void FASTCALL Init(int track, int size, int sectors, BOOL raw = FALSE, + off64_t imgoff = 0); + // 蛻晄悄蛹 + BOOL FASTCALL Load(const Filepath& path); + // 繝ュ繝シ繝 + BOOL FASTCALL Save(const Filepath& path); + // 繧サ繝シ繝 + + // 繝ェ繝シ繝峨サ繝ゥ繧、繝 + BOOL FASTCALL Read(BYTE *buf, int sec) const; + // 繧サ繧ッ繧ソ繝ェ繝シ繝 + BOOL FASTCALL Write(const BYTE *buf, int sec); + // 繧サ繧ッ繧ソ繝ゥ繧、繝 + + // 縺昴ョ莉 + int FASTCALL GetTrack() const { return dt.track; } + // 繝医Λ繝繧ッ蜿門セ + BOOL FASTCALL IsChanged() const { return dt.changed; } + // 螟画峩繝輔Λ繧ー繝√ぉ繝繧ッ + +private: + // 蜀驛ィ繝繝シ繧ソ + disktrk_t dt; + // 蜀驛ィ繝繝シ繧ソ +}; + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・ +// +//=========================================================================== +class DiskCache +{ +public: + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + DiskTrack *disktrk; // 蜑イ繧雁ス薙※繝医Λ繝繧ッ + DWORD serial; // 譛邨ゅす繝ェ繧「繝ォ + } cache_t; + + // 繧ュ繝」繝繧キ繝・謨ー + enum { + CacheMax = 16 // 繧ュ繝」繝繧キ繝・縺吶k繝医Λ繝繧ッ謨ー + }; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + DiskCache(const Filepath& path, int size, int blocks, + off64_t imgoff = 0); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~DiskCache(); + // 繝繧ケ繝医Λ繧ッ繧ソ + void FASTCALL SetRawMode(BOOL raw); + // CD-ROM raw繝「繝シ繝芽ィュ螳 + + // 繧「繧ッ繧サ繧ケ + BOOL FASTCALL Save(); + // 蜈ィ繧サ繝シ繝厄シ隗」謾セ + BOOL FASTCALL Read(BYTE *buf, int block); + // 繧サ繧ッ繧ソ繝ェ繝シ繝 + BOOL FASTCALL Write(const BYTE *buf, int block); + // 繧サ繧ッ繧ソ繝ゥ繧、繝 + BOOL FASTCALL GetCache(int index, int& track, DWORD& serial) const; + // 繧ュ繝」繝繧キ繝・諠蝣ア蜿門セ + +private: + // 蜀驛ィ邂。逅 + void FASTCALL Clear(); + // 繝医Λ繝繧ッ繧偵☆縺ケ縺ヲ繧ッ繝ェ繧「 + DiskTrack* FASTCALL Assign(int track); + // 繝医Λ繝繧ッ縺ョ繝ュ繝シ繝 + BOOL FASTCALL Load(int index, int track, DiskTrack *disktrk = NULL); + // 繝医Λ繝繧ッ縺ョ繝ュ繝シ繝 + void FASTCALL Update(); + // 繧キ繝ェ繧「繝ォ逡ェ蜿キ譖エ譁ー + + // 蜀驛ィ繝繝シ繧ソ + cache_t cache[CacheMax]; + // 繧ュ繝」繝繧キ繝・邂。逅 + DWORD serial; + // 譛邨ゅい繧ッ繧サ繧ケ繧キ繝ェ繧「繝ォ繝翫Φ繝 + Filepath sec_path; + // 繝代せ + int sec_size; + // 繧サ繧ッ繧ソ繧オ繧、繧コ(8 or 9 or 11) + int sec_blocks; + // 繧サ繧ッ繧ソ繝悶Ο繝繧ッ謨ー + BOOL cd_raw; + // CD-ROM RAW繝「繝シ繝 + off64_t imgoffset; + // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 +}; + +//=========================================================================== +// +// 繝繧」繧ケ繧ッ +// +//=========================================================================== +class Disk +{ +public: + // 蜀驛ィ繝ッ繝シ繧ッ + typedef struct { + DWORD id; // 繝。繝繧」繧「ID + BOOL ready; // 譛牙柑縺ェ繝繧」繧ケ繧ッ + BOOL writep; // 譖ク縺崎セシ縺ソ遖∵ュ「 + BOOL readonly; // 隱ュ縺ソ霎シ縺ソ蟆ら畑 + BOOL removable; // 蜿悶j螟悶@ + BOOL lock; // 繝ュ繝繧ッ + BOOL attn; // 繧「繝繝ウ繧キ繝ァ繝ウ + BOOL reset; // 繝ェ繧サ繝繝 + int size; // 繧サ繧ッ繧ソ繧オ繧、繧コ + DWORD blocks; // 邱上そ繧ッ繧ソ謨ー + DWORD lun; // LUN + DWORD code; // 繧ケ繝繝シ繧ソ繧ケ繧ウ繝シ繝 + DiskCache *dcache; // 繝繧」繧ケ繧ッ繧ュ繝」繝繧キ繝・ + off64_t imgoffset; // 螳溘ョ繝シ繧ソ縺セ縺ァ縺ョ繧ェ繝輔そ繝繝 + } disk_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + Disk(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~Disk(); + // 繝繧ケ繝医Λ繧ッ繧ソ + virtual void FASTCALL Reset(); + // 繝繝舌う繧ケ繝ェ繧サ繝繝 +#ifndef RASCSI + virtual BOOL FASTCALL Save(Fileio *fio, int ver); + // 繧サ繝シ繝 + virtual BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif // RASCSI + + // ID + DWORD FASTCALL GetID() const { return disk.id; } + // 繝。繝繧」繧「ID蜿門セ + BOOL FASTCALL IsNULL() const; + // NULL繝√ぉ繝繧ッ + BOOL FASTCALL IsSASI() const; + // SASI繝√ぉ繝繧ッ + + // 繝。繝繧」繧「謫堺ス + virtual BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + void FASTCALL GetPath(Filepath& path) const; + // 繝代せ蜿門セ + void FASTCALL Eject(BOOL force); + // 繧、繧ク繧ァ繧ッ繝 + BOOL FASTCALL IsReady() const { return disk.ready; } + // Ready繝√ぉ繝繧ッ + void FASTCALL WriteP(BOOL flag); + // 譖ク縺崎セシ縺ソ遖∵ュ「 + BOOL FASTCALL IsWriteP() const { return disk.writep; } + // 譖ク縺崎セシ縺ソ遖∵ュ「繝√ぉ繝繧ッ + BOOL FASTCALL IsReadOnly() const { return disk.readonly; } + // Read Only繝√ぉ繝繧ッ + BOOL FASTCALL IsRemovable() const { return disk.removable; } + // 繝ェ繝繝シ繝舌ヶ繝ォ繝√ぉ繝繧ッ + BOOL FASTCALL IsLocked() const { return disk.lock; } + // 繝ュ繝繧ッ繝√ぉ繝繧ッ + BOOL FASTCALL IsAttn() const { return disk.attn; } + // 莠、謠帙メ繧ァ繝繧ッ + BOOL FASTCALL Flush(); + // 繧ュ繝」繝繧キ繝・繝輔Λ繝繧キ繝・ + void FASTCALL GetDisk(disk_t *buffer) const; + // 蜀驛ィ繝ッ繝シ繧ッ蜿門セ + + // 繝励Ο繝代ユ繧」 + void FASTCALL SetLUN(DWORD lun) { disk.lun = lun; } + // LUN繧サ繝繝 + DWORD FASTCALL GetLUN() { return disk.lun; } + // LUN蜿門セ + // 繧ウ繝槭Φ繝 + virtual int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + virtual int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); + // REQUEST SENSE繧ウ繝槭Φ繝 + int FASTCALL SelectCheck(const DWORD *cdb); + // SELECT繝√ぉ繝繧ッ + int FASTCALL SelectCheck10(const DWORD *cdb); + // SELECT(10)繝√ぉ繝繧ッ + virtual BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT繧ウ繝槭Φ繝 + virtual int FASTCALL ModeSense(const DWORD *cdb, BYTE *buf); + // MODE SENSE繧ウ繝槭Φ繝 + virtual int FASTCALL ModeSense10(const DWORD *cdb, BYTE *buf); + // MODE SENSE(10)繧ウ繝槭Φ繝 + int FASTCALL ReadDefectData10(const DWORD *cdb, BYTE *buf); + // READ DEFECT DATA(10)繧ウ繝槭Φ繝 + virtual BOOL FASTCALL TestUnitReady(const DWORD *cdb); + // TEST UNIT READY繧ウ繝槭Φ繝 + BOOL FASTCALL Rezero(const DWORD *cdb); + // REZERO繧ウ繝槭Φ繝 + BOOL FASTCALL Format(const DWORD *cdb); + // FORMAT UNIT繧ウ繝槭Φ繝 + BOOL FASTCALL Reassign(const DWORD *cdb); + // REASSIGN UNIT繧ウ繝槭Φ繝 + virtual int FASTCALL Read(BYTE *buf, DWORD block); + // READ繧ウ繝槭Φ繝 + int FASTCALL WriteCheck(DWORD block); + // WRITE繝√ぉ繝繧ッ + BOOL FASTCALL Write(const BYTE *buf, DWORD block); + // WRITE繧ウ繝槭Φ繝 + BOOL FASTCALL Seek(const DWORD *cdb); + // SEEK繧ウ繝槭Φ繝 + BOOL FASTCALL Assign(const DWORD *cdb); + // ASSIGN繧ウ繝槭Φ繝 + BOOL FASTCALL Specify(const DWORD *cdb); + // SPECIFY繧ウ繝槭Φ繝 + BOOL FASTCALL StartStop(const DWORD *cdb); + // START STOP UNIT繧ウ繝槭Φ繝 + BOOL FASTCALL SendDiag(const DWORD *cdb); + // SEND DIAGNOSTIC繧ウ繝槭Φ繝 + BOOL FASTCALL Removal(const DWORD *cdb); + // PREVENT/ALLOW MEDIUM REMOVAL繧ウ繝槭Φ繝 + int FASTCALL ReadCapacity(const DWORD *cdb, BYTE *buf); + // READ CAPACITY繧ウ繝槭Φ繝 + BOOL FASTCALL Verify(const DWORD *cdb); + // VERIFY繧ウ繝槭Φ繝 + virtual int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); + // READ TOC繧ウ繝槭Φ繝 + virtual BOOL FASTCALL PlayAudio(const DWORD *cdb); + // PLAY AUDIO繧ウ繝槭Φ繝 + virtual BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); + // PLAY AUDIO MSF繧ウ繝槭Φ繝 + virtual BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); + // PLAY AUDIO TRACK繧ウ繝槭Φ繝 + void FASTCALL InvalidCmd() { disk.code = DISK_INVALIDCMD; } + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝 + + // 縺昴ョ莉 + void SetCacheWB(BOOL enable) { cache_wb = enable; } + // 繧ュ繝」繝繧キ繝・繝「繝シ繝芽ィュ螳 + +protected: + // 繧オ繝門ヲ逅 + virtual int FASTCALL AddError(BOOL change, BYTE *buf); + // 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 + virtual int FASTCALL AddFormat(BOOL change, BYTE *buf); + // 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 + virtual int FASTCALL AddDrive(BOOL change, BYTE *buf); + // 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 + int FASTCALL AddOpt(BOOL change, BYTE *buf); + // 繧ェ繝励ユ繧」繧ォ繝ォ繝壹シ繧ク霑ス蜉 + int FASTCALL AddCache(BOOL change, BYTE *buf); + // 繧ュ繝」繝繧キ繝・繝壹シ繧ク霑ス蜉 + int FASTCALL AddCDROM(BOOL change, BYTE *buf); + // CD-ROM繝壹シ繧ク霑ス蜉 + int FASTCALL AddCDDA(BOOL change, BYTE *buf); + // CD-DA繝壹シ繧ク霑ス蜉 + virtual int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); + // 繝吶Φ繝迚ケ谿翫壹シ繧ク霑ス蜉 + BOOL FASTCALL CheckReady(); + // 繝ャ繝繧」繝√ぉ繝繧ッ + + // 蜀驛ィ繝繝シ繧ソ + disk_t disk; + // 繝繧」繧ケ繧ッ蜀驛ィ繝繝シ繧ソ + Filepath diskpath; + // 繝代せ(GetPath逕ィ) + BOOL cache_wb; + // 繧ュ繝」繝繧キ繝・繝「繝シ繝 +}; + +//=========================================================================== +// +// SASI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== +class SASIHD : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SASIHD(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + void FASTCALL Reset(); + // 繝ェ繧サ繝繝 + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + // 繧ウ繝槭Φ繝 + int FASTCALL RequestSense(const DWORD *cdb, BYTE *buf); + // REQUEST SENSE繧ウ繝槭Φ繝 +}; + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ +// +//=========================================================================== +class SCSIHD : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIHD(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + void FASTCALL Reset(); + // 繝ェ繧サ繝繝 + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT(6)繧ウ繝槭Φ繝 +}; + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(PC-9801-55 NEC邏疲ュ」/Anex86/T98Next) +// +//=========================================================================== +class SCSIHD_NEC : public SCSIHD +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIHD_NEC(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + + // 繧オ繝門ヲ逅 + int FASTCALL AddError(BOOL change, BYTE *buf); + // 繧ィ繝ゥ繝シ繝壹シ繧ク霑ス蜉 + int FASTCALL AddFormat(BOOL change, BYTE *buf); + // 繝輔か繝シ繝槭ャ繝医壹シ繧ク霑ス蜉 + int FASTCALL AddDrive(BOOL change, BYTE *buf); + // 繝峨Λ繧、繝悶壹シ繧ク霑ス蜉 + +private: + int cylinders; + // 繧キ繝ェ繝ウ繝謨ー + int heads; + // 繝倥ャ繝画焚 + int sectors; + // 繧サ繧ッ繧ソ謨ー + int sectorsize; + // 繧サ繧ッ繧ソ繧オ繧、繧コ + off64_t imgoffset; + // 繧、繝。繝シ繧ク繧ェ繝輔そ繝繝 + off64_t imgsize; + // 繧、繝。繝シ繧ク繧オ繧、繧コ +}; + +//=========================================================================== +// +// SCSI 繝上シ繝峨ョ繧」繧ケ繧ッ(Macintosh Apple邏疲ュ」) +// +//=========================================================================== +class SCSIHD_APPLE : public SCSIHD +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIHD_APPLE(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry( + const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + + // 繧オ繝門ヲ逅 + int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); + // 繝吶Φ繝迚ケ谿翫壹シ繧ク霑ス蜉 +}; + +//=========================================================================== +// +// SCSI 蜈臥」∵ー励ョ繧」繧ケ繧ッ +// +//=========================================================================== +class SCSIMO : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIMO(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ +#ifndef RASCSI + BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif // RASCSI + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + BOOL FASTCALL ModeSelect(const DWORD *cdb, const BYTE *buf, int length); + // MODE SELECT(6)繧ウ繝槭Φ繝 + + // 繧オ繝門ヲ逅 + int FASTCALL AddVendor(int page, BOOL change, BYTE *buf); + // 繝吶Φ繝迚ケ谿翫壹シ繧ク霑ス蜉 +}; + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ゥ繧ケ蜈郁。悟ョ夂セゥ +// +//--------------------------------------------------------------------------- +class SCSICD; + +//=========================================================================== +// +// CD-ROM 繝医Λ繝繧ッ +// +//=========================================================================== +class CDTrack +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CDTrack(SCSICD *scsicd); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~CDTrack(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Init(int track, DWORD first, DWORD last); + // 蛻晄悄蛹 + + // 繝励Ο繝代ユ繧」 + void FASTCALL SetPath(BOOL cdda, const Filepath& path); + // 繝代せ險ュ螳 + void FASTCALL GetPath(Filepath& path) const; + // 繝代せ蜿門セ + void FASTCALL AddIndex(int index, DWORD lba); + // 繧、繝ウ繝繝繧ッ繧ケ霑ス蜉 + DWORD FASTCALL GetFirst() const; + // 髢句ァ記BA蜿門セ + DWORD FASTCALL GetLast() const; + // 邨らォッLBA蜿門セ + DWORD FASTCALL GetBlocks() const; + // 繝悶Ο繝繧ッ謨ー蜿門セ + int FASTCALL GetTrackNo() const; + // 繝医Λ繝繧ッ逡ェ蜿キ蜿門セ + BOOL FASTCALL IsValid(DWORD lba) const; + // 譛牙柑縺ェLBA縺 + BOOL FASTCALL IsAudio() const; + // 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ縺 + +private: + SCSICD *cdrom; + // 隕ェ繝繝舌う繧ケ + BOOL valid; + // 譛牙柑縺ェ繝医Λ繝繧ッ + int track_no; + // 繝医Λ繝繧ッ逡ェ蜿キ + DWORD first_lba; + // 髢句ァ記BA + DWORD last_lba; + // 邨ゆコLBA + BOOL audio; + // 繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ繝輔Λ繧ー + BOOL raw; + // RAW繝繝シ繧ソ繝輔Λ繧ー + Filepath imgpath; + // 繧、繝。繝シ繧ク繝輔ぃ繧、繝ォ繝代せ +}; + +//=========================================================================== +// +// CD-DA 繝舌ャ繝輔ぃ +// +//=========================================================================== +class CDDABuf +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + CDDABuf(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~CDDABuf(); + // 繝繧ケ繝医Λ繧ッ繧ソ +#if 0 + BOOL Init(); + // 蛻晄悄蛹 + BOOL FASTCALL Load(const Filepath& path); + // 繝ュ繝シ繝 + BOOL FASTCALL Save(const Filepath& path); + // 繧サ繝シ繝 + + // API + void FASTCALL Clear(); + // 繝舌ャ繝輔ぃ繧ッ繝ェ繧「 + BOOL FASTCALL Open(Filepath& path); + // 繝輔ぃ繧、繝ォ謖螳 + BOOL FASTCALL GetBuf(DWORD *buffer, int frames); + // 繝舌ャ繝輔ぃ蜿門セ + BOOL FASTCALL IsValid(); + // 譛牙柑繝√ぉ繝繧ッ + BOOL FASTCALL ReadReq(); + // 隱ュ縺ソ霎シ縺ソ隕∵ア + BOOL FASTCALL IsEnd() const; + // 邨ゆコ繝√ぉ繝繧ッ + +private: + Filepath wavepath; + // Wave繝代せ + BOOL valid; + // 繧ェ繝シ繝励Φ邨先棡 + DWORD *buf; + // 繝繝シ繧ソ繝舌ャ繝輔ぃ + DWORD read; + // Read繝昴う繝ウ繧ソ + DWORD write; + // Write繝昴う繝ウ繧ソ + DWORD num; + // 繝繝シ繧ソ譛牙柑謨ー + DWORD rest; + // 繝輔ぃ繧、繝ォ谿九j繧オ繧、繧コ +#endif +}; + +//=========================================================================== +// +// SCSI CD-ROM +// +//=========================================================================== +class SCSICD : public Disk +{ +public: + // 繝医Λ繝繧ッ謨ー + enum { + TrackMax = 96 // 繝医Λ繝繧ッ譛螟ァ謨ー + }; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSICD(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~SCSICD(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Open(const Filepath& path, BOOL attn = TRUE); + // 繧ェ繝シ繝励Φ +#ifndef RASCSI + BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif // RASCSI + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + int FASTCALL Read(BYTE *buf, DWORD block); + // READ繧ウ繝槭Φ繝 + int FASTCALL ReadToc(const DWORD *cdb, BYTE *buf); + // READ TOC繧ウ繝槭Φ繝 + BOOL FASTCALL PlayAudio(const DWORD *cdb); + // PLAY AUDIO繧ウ繝槭Φ繝 + BOOL FASTCALL PlayAudioMSF(const DWORD *cdb); + // PLAY AUDIO MSF繧ウ繝槭Φ繝 + BOOL FASTCALL PlayAudioTrack(const DWORD *cdb); + // PLAY AUDIO TRACK繧ウ繝槭Φ繝 + + // CD-DA + BOOL FASTCALL NextFrame(); + // 繝輔Ξ繝シ繝騾夂衍 + void FASTCALL GetBuf(DWORD *buffer, int samples, DWORD rate); + // CD-DA繝舌ャ繝輔ぃ蜿門セ + + // LBA-MSF螟画鋤 + void FASTCALL LBAtoMSF(DWORD lba, BYTE *msf) const; + // LBA竊樽SF螟画鋤 + DWORD FASTCALL MSFtoLBA(const BYTE *msf) const; + // MSF竊鱈BA螟画鋤 + +private: + // 繧ェ繝シ繝励Φ + BOOL FASTCALL OpenCue(const Filepath& path); + // 繧ェ繝シ繝励Φ(CUE) + BOOL FASTCALL OpenIso(const Filepath& path); + // 繧ェ繝シ繝励Φ(ISO) + BOOL FASTCALL OpenPhysical(const Filepath& path); + // 繧ェ繝シ繝励Φ(Physical) + BOOL rawfile; + // RAW繝輔Λ繧ー + + // 繝医Λ繝繧ッ邂。逅 + void FASTCALL ClearTrack(); + // 繝医Λ繝繧ッ繧ッ繝ェ繧「 + int FASTCALL SearchTrack(DWORD lba) const; + // 繝医Λ繝繧ッ讀懃エ「 + CDTrack* track[TrackMax]; + // 繝医Λ繝繧ッ繧ェ繝悶ず繧ァ繧ッ繝 + int tracks; + // 繝医Λ繝繧ッ繧ェ繝悶ず繧ァ繧ッ繝域怏蜉ケ謨ー + int dataindex; + // 迴セ蝨ィ縺ョ繝繝シ繧ソ繝医Λ繝繧ッ + int audioindex; + // 迴セ蝨ィ縺ョ繧ェ繝シ繝繧」繧ェ繝医Λ繝繧ッ + + int frame; + // 繝輔Ξ繝シ繝逡ェ蜿キ + +#if 0 + CDDABuf da_buf; + // CD-DA繝舌ャ繝輔ぃ + int da_num; + // CD-DA繝医Λ繝繧ッ謨ー + int da_cur; + // CD-DA繧ォ繝ャ繝ウ繝医ヨ繝ゥ繝繧ッ + int da_next; + // CD-DA繝阪け繧ケ繝医ヨ繝ゥ繝繧ッ + BOOL da_req; + // CD-DA繝繝シ繧ソ隕∵ア +#endif +}; + +//=========================================================================== +// +// SCSI 繝帙せ繝医ヶ繝ェ繝繧ク +// +//=========================================================================== +class CTapDriver; +class CFileSys; +class SCSIBR : public Disk +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + SCSIBR(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~SCSIBR(); + // 繝繧ケ繝医Λ繧ッ繧ソ + + // 繧ウ繝槭Φ繝 + int FASTCALL Inquiry(const DWORD *cdb, BYTE *buf, DWORD major, DWORD minor); + // INQUIRY繧ウ繝槭Φ繝 + BOOL FASTCALL TestUnitReady(const DWORD *cdb); + // TEST UNIT READY繧ウ繝槭Φ繝 + int FASTCALL GetMessage10(const DWORD *cdb, BYTE *buf); + // GET MESSAGE10繧ウ繝槭Φ繝 + BOOL FASTCALL SendMessage10(const DWORD *cdb, BYTE *buf); + // SEND MESSAGE10繧ウ繝槭Φ繝 + +private: + int FASTCALL GetMacAddr(BYTE *buf); + // MAC繧「繝峨Ξ繧ケ蜿門セ + void FASTCALL SetMacAddr(BYTE *buf); + // MAC繧「繝峨Ξ繧ケ險ュ螳 + void FASTCALL ReceivePacket(); + // 繝代こ繝繝亥女菫。 + void FASTCALL GetPacketBuf(BYTE *buf); + // 繝代こ繝繝亥叙蠕 + void FASTCALL SendPacket(BYTE *buf, int len); + // 繝代こ繝繝磯∽ソ。 + + CTapDriver *tap; + // TAP繝峨Λ繧、繝 + BOOL m_bTapEnable; + // TAP譛牙柑繝輔Λ繧ー + BYTE mac_addr[6]; + // MAC繧「繝峨Ξ繧ケ + int packet_len; + // 蜿嶺ソ。繝代こ繝繝医し繧、繧コ + BYTE packet_buf[0x1000]; + // 蜿嶺ソ。繝代こ繝繝医ヰ繝繝輔ぃ + BOOL packet_enable; + // 蜿嶺ソ。繝代こ繝繝域怏蜉ケ + + + int FASTCALL ReadFsResult(BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(邨先棡繧ウ繝シ繝) + int FASTCALL ReadFsOut(BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(霑泌唆繝繝シ繧ソ) + int FASTCALL ReadFsOpt(BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝隱ュ縺ソ霎シ縺ソ(繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ) + void FASTCALL WriteFs(int func, BYTE *buf); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ(螳溯。) + void FASTCALL WriteFsOpt(BYTE *buf, int len); + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝譖ク縺崎セシ縺ソ(繧ェ繝励す繝ァ繝ウ繝繝シ繧ソ) + + // 繧ウ繝槭Φ繝峨ワ繝ウ繝峨Λ + void FASTCALL FS_InitDevice(BYTE *buf); + // $40 - 繝繝舌う繧ケ襍キ蜍 + void FASTCALL FS_CheckDir(BYTE *buf); + // $41 - 繝繧」繝ャ繧ッ繝医Μ繝√ぉ繝繧ッ + void FASTCALL FS_MakeDir(BYTE *buf); + // $42 - 繝繧」繝ャ繧ッ繝医Μ菴懈 + void FASTCALL FS_RemoveDir(BYTE *buf); + // $43 - 繝繧」繝ャ繧ッ繝医Μ蜑企勁 + void FASTCALL FS_Rename(BYTE *buf); + // $44 - 繝輔ぃ繧、繝ォ蜷榊、画峩 + void FASTCALL FS_Delete(BYTE *buf); + // $45 - 繝輔ぃ繧、繝ォ蜑企勁 + void FASTCALL FS_Attribute(BYTE *buf); + // $46 - 繝輔ぃ繧、繝ォ螻樊ァ蜿門セ/險ュ螳 + void FASTCALL FS_Files(BYTE *buf); + // $47 - 繝輔ぃ繧、繝ォ讀懃エ「 + void FASTCALL FS_NFiles(BYTE *buf); + // $48 - 繝輔ぃ繧、繝ォ谺。讀懃エ「 + void FASTCALL FS_Create(BYTE *buf); + // $49 - 繝輔ぃ繧、繝ォ菴懈 + void FASTCALL FS_Open(BYTE *buf); + // $4A - 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + void FASTCALL FS_Close(BYTE *buf); + // $4B - 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + void FASTCALL FS_Read(BYTE *buf); + // $4C - 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + void FASTCALL FS_Write(BYTE *buf); + // $4D - 繝輔ぃ繧、繝ォ譖ク縺崎セシ縺ソ + void FASTCALL FS_Seek(BYTE *buf); + // $4E - 繝輔ぃ繧、繝ォ繧キ繝シ繧ッ + void FASTCALL FS_TimeStamp(BYTE *buf); + // $4F - 繝輔ぃ繧、繝ォ譎ょ綾蜿門セ/險ュ螳 + void FASTCALL FS_GetCapacity(BYTE *buf); + // $50 - 螳ケ驥丞叙蠕 + void FASTCALL FS_CtrlDrive(BYTE *buf); + // $51 - 繝峨Λ繧、繝也憾諷区、懈渊/蛻カ蠕。 + void FASTCALL FS_GetDPB(BYTE *buf); + // $52 - DPB蜿門セ + void FASTCALL FS_DiskRead(BYTE *buf); + // $53 - 繧サ繧ッ繧ソ隱ュ縺ソ霎シ縺ソ + void FASTCALL FS_DiskWrite(BYTE *buf); + // $54 - 繧サ繧ッ繧ソ譖ク縺崎セシ縺ソ + void FASTCALL FS_Ioctrl(BYTE *buf); + // $55 - IOCTRL + void FASTCALL FS_Flush(BYTE *buf); + // $56 - 繝輔Λ繝繧キ繝・ + void FASTCALL FS_CheckMedia(BYTE *buf); + // $57 - 繝。繝繧」繧「莠、謠帙メ繧ァ繝繧ッ + void FASTCALL FS_Lock(BYTE *buf); + // $58 - 謗剃サ門宛蠕。 + + CFileSys *fs; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繝繧オ繝シ + DWORD fsresult; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ邨先棡繧ウ繝シ繝 + BYTE fsout[0x800]; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ邨先棡繝舌ャ繝輔ぃ + DWORD fsoutlen; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ邨先棡繝舌ャ繝輔ぃ繧オ繧、繧コ + BYTE fsopt[0x1000000]; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ繝舌ャ繝輔ぃ + DWORD fsoptlen; + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝繧「繧ッ繧サ繧ケ繝舌ャ繝輔ぃ繧オ繧、繧コ +}; + +//=========================================================================== +// +// SASI 繧ウ繝ウ繝医Ο繝シ繝ゥ +// +//=========================================================================== +class SASIDEV +{ +public: + // 隲也炊繝ヲ繝九ャ繝域怙螟ァ謨ー + enum { + UnitMax = 8 + }; + + // 繝輔ぉ繝シ繧コ繧ソ繧、繝溘Φ繧ー(隱ソ謨エ逕ィ) + enum { + Time_phase_bsy = 800, + Time_phase_before = 6000, // min 4000ns + Time_phase_before_data = 60000, // min 40000ns + Time_phase_after = 6000, // min 4000ns + Time_phase_after_status = 12000, // min 9000ns + }; + + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + // 蜈ィ闊ャ + BUS::phase_t phase; // 驕キ遘サ繝輔ぉ繝シ繧コ + int id; // 繧ウ繝ウ繝医Ο繝シ繝ゥID(0-7) + BUS *bus; // 繝舌せ + + // 繧ウ繝槭Φ繝 + DWORD cmd[10]; // 繧ウ繝槭Φ繝峨ョ繝シ繧ソ + DWORD status; // 繧ケ繝繝シ繧ソ繧ケ繝繝シ繧ソ + DWORD message; // 繝。繝繧サ繝シ繧ク繝繝シ繧ソ + + // 霆「騾 + BYTE *buffer; // 霆「騾√ヰ繝繝輔ぃ + int bufsize; // 霆「騾√ヰ繝繝輔ぃ繧オ繧、繧コ + DWORD blocks; // 霆「騾√ヶ繝ュ繝繧ッ謨ー + DWORD next; // 谺。縺ョ繝ャ繧ウ繝シ繝 + DWORD offset; // 霆「騾√が繝輔そ繝繝 + DWORD length; // 霆「騾∵ョ九j髟キ縺 + + // 隲也炊繝ヲ繝九ャ繝 + Disk *unit[UnitMax]; + // 隲也炊繝ヲ繝九ャ繝 + } ctrl_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ +#ifdef RASCSI + SASIDEV(); +#else + SASIDEV(Device *dev); +#endif //RASCSI + + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~SASIDEV(); + // 繝繧ケ繝医Λ繧ッ繧ソ + virtual void FASTCALL Reset(); + // 繝繝舌う繧ケ繝ェ繧サ繝繝 +#ifndef RASCSI + virtual BOOL FASTCALL Save(Fileio *fio, int ver); + // 繧サ繝シ繝 + virtual BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 +#endif //RASCSI + + // 螟夜ΚAPI + virtual BUS::phase_t FASTCALL Process(); + // 螳溯。 + + // 謗・邯 + void FASTCALL Connect(int id, BUS *sbus); + // 繧ウ繝ウ繝医Ο繝シ繝ゥ謗・邯 + Disk* FASTCALL GetUnit(int no); + // 隲也炊繝ヲ繝九ャ繝亥叙蠕 + void FASTCALL SetUnit(int no, Disk *dev); + // 隲也炊繝ヲ繝九ャ繝郁ィュ螳 + BOOL FASTCALL HasUnit(); + // 譛牙柑縺ェ隲也炊繝ヲ繝九ャ繝医r謖√▲縺ヲ縺繧九°霑斐☆ + + // 縺昴ョ莉 + BUS::phase_t FASTCALL GetPhase() {return ctrl.phase;} + // 繝輔ぉ繝シ繧コ蜿門セ + int FASTCALL GetID() {return ctrl.id;} + // ID蜿門セ + void FASTCALL GetCTRL(ctrl_t *buffer); + // 蜀驛ィ諠蝣ア蜿門セ + ctrl_t* FASTCALL GetWorkAddr() { return &ctrl; } + // 蜀驛ィ諠蝣ア繧「繝峨Ξ繧ケ蜿門セ + virtual BOOL FASTCALL IsSASI() const {return TRUE;} + // SASI繝√ぉ繝繧ッ + Disk* FASTCALL GetBusyUnit(); + // 繝薙ず繝シ迥カ諷九ョ繝ヲ繝九ャ繝医r蜿門セ + +protected: + // 繝輔ぉ繝シ繧コ蜃ヲ逅 + virtual void FASTCALL BusFree(); + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + virtual void FASTCALL Selection(); + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + virtual void FASTCALL Command(); + // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + virtual void FASTCALL Execute(); + // 螳溯。後ヵ繧ァ繝シ繧コ + void FASTCALL Status(); + // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + void FASTCALL MsgIn(); + // 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ + void FASTCALL DataIn(); + // 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ + void FASTCALL DataOut(); + // 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + virtual void FASTCALL Error(); + // 蜈ア騾壹お繝ゥ繝シ蜃ヲ逅 + + // 繧ウ繝槭Φ繝 + void FASTCALL CmdTestUnitReady(); + // TEST UNIT READY繧ウ繝槭Φ繝 + void FASTCALL CmdRezero(); + // REZERO UNIT繧ウ繝槭Φ繝 + void FASTCALL CmdRequestSense(); + // REQUEST SENSE繧ウ繝槭Φ繝 + void FASTCALL CmdFormat(); + // FORMAT繧ウ繝槭Φ繝 + void FASTCALL CmdReassign(); + // REASSIGN BLOCKS繧ウ繝槭Φ繝 + void FASTCALL CmdRead6(); + // READ(6)繧ウ繝槭Φ繝 + void FASTCALL CmdWrite6(); + // WRITE(6)繧ウ繝槭Φ繝 + void FASTCALL CmdSeek6(); + // SEEK(6)繧ウ繝槭Φ繝 + void FASTCALL CmdAssign(); + // ASSIGN繧ウ繝槭Φ繝 + void FASTCALL CmdSpecify(); + // SPECIFY繧ウ繝槭Φ繝 + void FASTCALL CmdInvalid(); + // 繧オ繝昴シ繝医@縺ヲ縺縺ェ縺繧ウ繝槭Φ繝 + + // 繝繝シ繧ソ霆「騾 + virtual void FASTCALL Send(); + // 繝繝シ繧ソ騾∽ソ。 + virtual void FASTCALL Receive(); + // 繝繝シ繧ソ蜿嶺ソ。 + BOOL FASTCALL XferIn(BYTE* buf); + // 繝繝シ繧ソ霆「騾!N + BOOL FASTCALL XferOut(BOOL cont); + // 繝繝シ繧ソ霆「騾^UT + + // 繝ュ繧ー + void FASTCALL Log(Log::loglevel level, const char *format, ...); + // 繝ュ繧ー蜃コ蜉 + +protected: +#ifndef RASCSI + Device *host; + // 繝帙せ繝医ョ繝舌う繧ケ +#endif // RASCSI + + ctrl_t ctrl; + // 蜀驛ィ繝繝シ繧ソ +}; + +//=========================================================================== +// +// SCSI 繝繝舌う繧ケ(SASI 繝繝舌う繧ケ繧堤カ呎価) +// +//=========================================================================== +class SCSIDEV : public SASIDEV +{ +public: + // 蜀驛ィ繝繝シ繧ソ螳夂セゥ + typedef struct { + // 蜷梧悄霆「騾 + BOOL syncenable; // 蜷梧悄霆「騾∝庄閭ス + int syncperiod; // 蜷梧悄霆「騾√ヴ繝ェ繧ェ繝 + int syncoffset; // 蜷梧悄霆「騾√が繝輔そ繝繝 + int syncack; // 蜷梧悄霆「騾、CK謨ー + + // ATN繝。繝繧サ繝シ繧ク + BOOL atnmsg; + int msc; + BOOL msb[256]; + } scsi_t; + +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ +#ifdef RASCSI + SCSIDEV(); +#else + SCSIDEV(Device *dev); +#endif // RASCSI + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + + void FASTCALL Reset(); + // 繝繝舌う繧ケ繝ェ繧サ繝繝 + + // 螟夜ΚAPI + BUS::phase_t FASTCALL Process(); + // 螳溯。 + + void FASTCALL SyncTransfer(BOOL enable) { scsi.syncenable = enable; } + // 蜷梧悄霆「騾∝庄閭ス險ュ螳 + + // 縺昴ョ莉 + BOOL FASTCALL IsSASI() const {return FALSE;} + // SASI繝√ぉ繝繧ッ + +private: + // 繝輔ぉ繝シ繧コ + void FASTCALL BusFree(); + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + void FASTCALL Selection(); + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + void FASTCALL Execute(); + // 螳溯。後ヵ繧ァ繝シ繧コ + void FASTCALL MsgOut(); + // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + void FASTCALL Error(); + // 蜈ア騾壹お繝ゥ繝シ蜃ヲ逅 + + // 繧ウ繝槭Φ繝 + void FASTCALL CmdInquiry(); + // INQUIRY繧ウ繝槭Φ繝 + void FASTCALL CmdModeSelect(); + // MODE SELECT繧ウ繝槭Φ繝 + void FASTCALL CmdModeSense(); + // MODE SENSE繧ウ繝槭Φ繝 + void FASTCALL CmdStartStop(); + // START STOP UNIT繧ウ繝槭Φ繝 + void FASTCALL CmdSendDiag(); + // SEND DIAGNOSTIC繧ウ繝槭Φ繝 + void FASTCALL CmdRemoval(); + // PREVENT/ALLOW MEDIUM REMOVAL繧ウ繝槭Φ繝 + void FASTCALL CmdReadCapacity(); + // READ CAPACITY繧ウ繝槭Φ繝 + void FASTCALL CmdRead10(); + // READ(10)繧ウ繝槭Φ繝 + void FASTCALL CmdWrite10(); + // WRITE(10)繧ウ繝槭Φ繝 + void FASTCALL CmdSeek10(); + // SEEK(10)繧ウ繝槭Φ繝 + void FASTCALL CmdVerify(); + // VERIFY繧ウ繝槭Φ繝 + void FASTCALL CmdSynchronizeCache(); + // SYNCHRONIZE CACHE 繧ウ繝槭Φ繝 + void FASTCALL CmdReadDefectData10(); + // READ DEFECT DATA(10) 繧ウ繝槭Φ繝 + void FASTCALL CmdReadToc(); + // READ TOC繧ウ繝槭Φ繝 + void FASTCALL CmdPlayAudio10(); + // PLAY AUDIO(10)繧ウ繝槭Φ繝 + void FASTCALL CmdPlayAudioMSF(); + // PLAY AUDIO MSF繧ウ繝槭Φ繝 + void FASTCALL CmdPlayAudioTrack(); + // PLAY AUDIO TRACK INDEX繧ウ繝槭Φ繝 + void FASTCALL CmdModeSelect10(); + // MODE SELECT(10)繧ウ繝槭Φ繝 + void FASTCALL CmdModeSense10(); + // MODE SENSE(10)繧ウ繝槭Φ繝 + void FASTCALL CmdGetMessage10(); + // GET MESSAGE(10)繧ウ繝槭Φ繝 + void FASTCALL CmdSendMessage10(); + // SEND MESSAGE(10)繧ウ繝槭Φ繝 + + // 繝繝シ繧ソ霆「騾 + void FASTCALL Send(); + // 繝繝シ繧ソ騾∽ソ。 + void FASTCALL Receive(); + // 繝繝シ繧ソ蜿嶺ソ。 + BOOL FASTCALL XferMsg(DWORD msg); + // 繝繝シ繧ソ霆「騾`SG + + scsi_t scsi; + // 蜀驛ィ繝繝シ繧ソ +}; + +#endif // disk_h diff --git a/src/raspberrypi/fileio.cpp b/src/raspberrypi/fileio.cpp new file mode 100644 index 00000000..c72c4c4c --- /dev/null +++ b/src/raspberrypi/fileio.cpp @@ -0,0 +1,367 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2010-2018 GIMONS +// [ 繝輔ぃ繧、繝ォI/O(RaSCSI逕ィ繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "filepath.h" +#include "fileio.h" + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォI/O +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Fileio::Fileio() +{ + // 繝ッ繝シ繧ッ蛻晄悄蛹 + handle = -1; +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Fileio::~Fileio() +{ + ASSERT(handle == -1); + + // Release縺ァ縺ョ螳牙ィ遲 + Close(); +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Load(const Filepath& path, void *buffer, int size) +{ + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle < 0); + + // 繧ェ繝シ繝励Φ + if (!Open(path, ReadOnly)) { + return FALSE; + } + + // 隱ュ縺ソ霎シ縺ソ + if (!Read(buffer, size)) { + Close(); + return FALSE; + } + + // 繧ッ繝ュ繝シ繧コ + Close(); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Save(const Filepath& path, void *buffer, int size) +{ + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle < 0); + + // 繧ェ繝シ繝励Φ + if (!Open(path, WriteOnly)) { + return FALSE; + } + + // 隱ュ縺ソ霎シ縺ソ + if (!Write(buffer, size)) { + Close(); + return FALSE; + } + + // 繧ッ繝ュ繝シ繧コ + Close(); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Open(LPCTSTR fname, OpenMode mode) +{ + ASSERT(this); + ASSERT(fname); + ASSERT(handle < 0); + + // 繝後Ν譁蟄怜励°繧峨ョ隱ュ縺ソ霎シ縺ソ縺ッ蠢縺壼、ア謨励&縺帙k + if (fname[0] == _T('\0')) { + handle = -1; + return FALSE; + } + + // 繝「繝シ繝牙挨 + switch (mode) { + // 隱ュ縺ソ霎シ縺ソ縺ョ縺ソ + case ReadOnly: + handle = open(fname, O_RDONLY); + break; + + // 譖ク縺崎セシ縺ソ縺ョ縺ソ + case WriteOnly: + handle = open(fname, O_CREAT | O_WRONLY | O_TRUNC, 0666); + break; + + // 隱ュ縺ソ譖ク縺堺ク。譁ケ + case ReadWrite: + // CD-ROM縺九i縺ョ隱ュ縺ソ霎シ縺ソ縺ッRW縺梧仙粥縺励※縺励∪縺 + if (access(fname, 0x06) != 0) { + return FALSE; + } + handle = open(fname, O_RDWR); + break; + + // 繧「繝壹Φ繝 + case Append: + handle = open(fname, O_CREAT | O_WRONLY | O_APPEND, 0666); + break; + + // 縺昴l莉・螟 + default: + ASSERT(FALSE); + break; + } + + // 邨先棡隧穂セ。 + if (handle == -1) { + return FALSE; + } + ASSERT(handle >= 0); + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::OpenDIO(LPCTSTR fname, OpenMode mode) +{ + ASSERT(this); + ASSERT(fname); + ASSERT(handle < 0); + + // 繝後Ν譁蟄怜励°繧峨ョ隱ュ縺ソ霎シ縺ソ縺ッ蠢縺壼、ア謨励&縺帙k + if (fname[0] == _T('\0')) { + handle = -1; + return FALSE; + } + + // 繝「繝シ繝牙挨 + switch (mode) { + // 隱ュ縺ソ霎シ縺ソ縺ョ縺ソ + case ReadOnly: + handle = open(fname, O_RDONLY | O_DIRECT); + break; + + // 譖ク縺崎セシ縺ソ縺ョ縺ソ + case WriteOnly: + handle = open(fname, O_CREAT | O_WRONLY | O_TRUNC | O_DIRECT, 0666); + break; + + // 隱ュ縺ソ譖ク縺堺ク。譁ケ + case ReadWrite: + // CD-ROM縺九i縺ョ隱ュ縺ソ霎シ縺ソ縺ッRW縺梧仙粥縺励※縺励∪縺 + if (access(fname, 0x06) != 0) { + return FALSE; + } + handle = open(fname, O_RDWR | O_DIRECT); + break; + + // 繧「繝壹Φ繝 + case Append: + handle = open(fname, O_CREAT | O_WRONLY | O_APPEND | O_DIRECT, 0666); + break; + + // 縺昴l莉・螟 + default: + ASSERT(FALSE); + break; + } + + // 邨先棡隧穂セ。 + if (handle == -1) { + return FALSE; + } + ASSERT(handle >= 0); + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Open(const Filepath& path, OpenMode mode) +{ + ASSERT(this); + + return Open(path.GetPath(), mode); +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::OpenDIO(const Filepath& path, OpenMode mode) +{ + ASSERT(this); + + return OpenDIO(path.GetPath(), mode); +} + +//--------------------------------------------------------------------------- +// +// 隱ュ縺ソ霎シ縺ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Read(void *buffer, int size) +{ + int count; + + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle >= 0); + + // 隱ュ縺ソ霎シ縺ソ + count = read(handle, buffer, size); + if (count != size) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 譖ク縺崎セシ縺ソ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Write(const void *buffer, int size) +{ + int count; + + ASSERT(this); + ASSERT(buffer); + ASSERT(size > 0); + ASSERT(handle >= 0); + + // 隱ュ縺ソ霎シ縺ソ + count = write(handle, buffer, size); + if (count != size) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝シ繧ッ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Fileio::Seek(off64_t offset, BOOL relative) +{ + ASSERT(this); + ASSERT(handle >= 0); + ASSERT(offset >= 0); + + // 逶ク蟇セ繧キ繝シ繧ッ縺ェ繧峨が繝輔そ繝繝医↓迴セ蝨ィ蛟、繧定ソス蜉 + if (relative) { + offset += GetFilePos(); + } + + if (lseek(handle, offset, SEEK_SET) != offset) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ繧オ繧、繧コ蜿門セ +// +//--------------------------------------------------------------------------- +off64_t FASTCALL Fileio::GetFileSize() +{ + off64_t cur; + off64_t end; + + ASSERT(this); + ASSERT(handle >= 0); + + // 繝輔ぃ繧、繝ォ菴咲スョ繧64bit縺ァ蜿門セ + cur = GetFilePos(); + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ繧64bit縺ァ蜿門セ + end = lseek(handle, 0, SEEK_END); + + // 菴咲スョ繧貞縺ォ謌サ縺 + Seek(cur); + + return end; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ菴咲スョ蜿門セ +// +//--------------------------------------------------------------------------- +off64_t FASTCALL Fileio::GetFilePos() const +{ + off64_t pos; + + ASSERT(this); + ASSERT(handle >= 0); + + // 繝輔ぃ繧、繝ォ菴咲スョ繧64bit縺ァ蜿門セ + pos = lseek(handle, 0, SEEK_CUR); + return pos; + +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +void FASTCALL Fileio::Close() +{ + ASSERT(this); + + if (handle != -1) { + close(handle); + handle = -1; + } +} diff --git a/src/raspberrypi/fileio.h b/src/raspberrypi/fileio.h new file mode 100644 index 00000000..22f02ac9 --- /dev/null +++ b/src/raspberrypi/fileio.h @@ -0,0 +1,83 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2005 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2013-2018 GIMONS +// [ 繝輔ぃ繧、繝ォI/O(RaSCSI逕ィ繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#if !defined(fileio_h) +#define fileio_h + +//=========================================================================== +// +// 繝槭け繝ュ(Load,Save逕ィ) +// +//=========================================================================== +#define PROP_IMPORT(f, p) \ + if (!f->Read(&(p), sizeof(p))) {\ + return FALSE;\ + }\ + +#define PROP_EXPORT(f, p) \ + if (!f->Write(&(p), sizeof(p))) {\ + return FALSE;\ + }\ + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォI/O +// +//=========================================================================== +class Fileio +{ +public: + enum OpenMode { + ReadOnly, // 隱ュ縺ソ霎シ縺ソ縺ョ縺ソ + WriteOnly, // 譖ク縺崎セシ縺ソ縺ョ縺ソ + ReadWrite, // 隱ュ縺ソ譖ク縺堺ク。譁ケ + Append // 繧「繝壹Φ繝 + }; + +public: + Fileio(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~Fileio(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Load(const Filepath& path, void *buffer, int size); + // ROM,RAM繝ュ繝シ繝 + BOOL FASTCALL Save(const Filepath& path, void *buffer, int size); + // RAM繧サ繝シ繝 + + BOOL FASTCALL Open(LPCTSTR fname, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL OpenDIO(LPCTSTR fname, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL Open(const Filepath& path, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL OpenDIO(const Filepath& path, OpenMode mode); + // 繧ェ繝シ繝励Φ + BOOL FASTCALL Seek(off64_t offset, BOOL relative = FALSE); + // 繧キ繝シ繧ッ + BOOL FASTCALL Read(void *buffer, int size); + // 隱ュ縺ソ霎シ縺ソ + BOOL FASTCALL Write(const void *buffer, int size); + // 譖ク縺崎セシ縺ソ + off64_t FASTCALL GetFileSize(); + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ蜿門セ + off64_t FASTCALL GetFilePos() const; + // 繝輔ぃ繧、繝ォ菴咲スョ蜿門セ + void FASTCALL Close(); + // 繧ッ繝ュ繝シ繧コ + BOOL FASTCALL IsValid() const { return (BOOL)(handle != -1); } + // 譛牙柑繝√ぉ繝繧ッ + int FASTCALL GetHandle() const { return handle; } + // 繝上Φ繝峨Ν蜿門セ + +private: + int handle; // 繝輔ぃ繧、繝ォ繝上Φ繝峨Ν +}; + +#endif // fileio_h diff --git a/src/raspberrypi/filepath.cpp b/src/raspberrypi/filepath.cpp new file mode 100644 index 00000000..43d2e410 --- /dev/null +++ b/src/raspberrypi/filepath.cpp @@ -0,0 +1,273 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2012-2018 GIMONS +// [ 繝輔ぃ繧、繝ォ繝代せ(繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "filepath.h" +#include "fileio.h" + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ繝代せ +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Filepath::Filepath() +{ + // 繧ッ繝ェ繧「 + Clear(); +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +Filepath::~Filepath() +{ +} + +//--------------------------------------------------------------------------- +// +// 莉」蜈・貍皮ョ怜ュ +// +//--------------------------------------------------------------------------- +Filepath& Filepath::operator=(const Filepath& path) +{ + // 繝代せ險ュ螳(蜀驛ィ縺ァSplit縺輔l繧) + SetPath(path.GetPath()); + + return *this; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繧「 +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::Clear() +{ + ASSERT(this); + + // 繝代せ縺翫h縺ウ蜷驛ィ蛻繧偵け繝ェ繧「 + m_szPath[0] = _T('\0'); + m_szDir[0] = _T('\0'); + m_szFile[0] = _T('\0'); + m_szExt[0] = _T('\0'); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ險ュ螳(繝ヲ繝シ繧カ) MBCS逕ィ +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::SetPath(LPCSTR path) +{ + ASSERT(this); + ASSERT(path); + ASSERT(strlen(path) < _MAX_PATH); + + // 繝代せ蜷阪さ繝斐シ + strcpy(m_szPath, (LPTSTR)path); + + // 蛻髮「 + Split(); +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蛻髮「 +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::Split() +{ + LPTSTR pDir; + LPTSTR pDirName; + LPTSTR pBase; + LPTSTR pBaseName; + LPTSTR pExtName; + + ASSERT(this); + + // 繝代シ繝繧貞晄悄蛹 + m_szDir[0] = _T('\0'); + m_szFile[0] = _T('\0'); + m_szExt[0] = _T('\0'); + + // 蛻髮「 + pDir = strdup(m_szPath); + pDirName = dirname(pDir); + pBase = strdup(m_szPath); + pBaseName = basename(pBase); + pExtName = strrchr(pBaseName, '.'); + + // 霆「騾 + if (pDirName) { + strcpy(m_szDir, pDirName); + strcat(m_szDir, "/"); + } + + if (pExtName) { + strcpy(m_szExt, pExtName); + *pExtName = 0; + } + + if (pBaseName) { + strcpy(m_szFile, pBaseName); + } + + // 隗」謾セ + free(pDir); + free(pBase); +} + +//--------------------------------------------------------------------------- +// +// 繝代せ蜷域 +// +//--------------------------------------------------------------------------- +void FASTCALL Filepath::Make() +{ + ASSERT(this); + + // 繝代せ蛻晄悄蛹 + m_szPath[0] = _T('\0'); + + // 蜷域 + strcat(m_szPath, m_szDir); + strcat(m_szPath, m_szFile); + strcat(m_szPath, m_szExt); +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繧「縺輔l縺ヲ縺繧九° +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::IsClear() const +{ + // Clear()縺ョ騾 + if ((m_szPath[0] == _T('\0')) && + (m_szDir[0] == _T('\0')) && + (m_szFile[0] == _T('\0')) && + (m_szExt[0] == _T('\0'))) { + // 遒コ縺九↓縲√け繝ェ繧「縺輔l縺ヲ縺繧 + return TRUE; + } + + // 繧ッ繝ェ繧「縺輔l縺ヲ縺縺ェ縺 + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝ァ繝シ繝亥錐蜿門セ +// 窶サ霑斐&繧後k繝昴う繝ウ繧ソ縺ッ荳譎ら噪縺ェ繧ゅョ縲ゅ☆縺舌さ繝斐シ縺吶k縺薙→ +// 窶サFDIDisk縺ョdisk.name縺ィ縺ョ髢「菫ゅ〒縲∵枚蟄怜励ッ譛螟ァ59譁蟄+邨らォッ縺ィ縺吶k縺薙→ +// +//--------------------------------------------------------------------------- +const char* FASTCALL Filepath::GetShort() const +{ + char szFile[_MAX_FNAME]; + char szExt[_MAX_EXT]; + + ASSERT(this); + + // TCHAR譁蟄怜励°繧営har譁蟄怜励∈螟画鋤 + strcpy(szFile, m_szFile); + strcpy(szExt, m_szExt); + + // 蝗コ螳壹ヰ繝繝輔ぃ縺ク蜷域 + strcpy(ShortName, szFile); + strcat(ShortName, szExt); + + // strlen縺ァ隱ソ縺ケ縺溘→縺阪∵怙螟ァ59縺ォ縺ェ繧九h縺縺ォ邏ー蟾・ + ShortName[59] = '\0'; + + // const char縺ィ縺励※霑斐☆ + return (const char*)ShortName; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ蜷搾シ区僑蠑オ蟄仙叙蠕 +// 窶サ霑斐&繧後k繝昴う繝ウ繧ソ縺ッ荳譎ら噪縺ェ繧ゅョ縲ゅ☆縺舌さ繝斐シ縺吶k縺薙→ +// +//--------------------------------------------------------------------------- +LPCTSTR FASTCALL Filepath::GetFileExt() const +{ + ASSERT(this); + + // 蝗コ螳壹ヰ繝繝輔ぃ縺ク蜷域 + strcpy(FileExt, m_szExt); + + // LPCTSTR縺ィ縺励※霑斐☆ + return (LPCTSTR)FileExt; +} + +//--------------------------------------------------------------------------- +// +// 繝代せ豈碑シ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::CmpPath(const Filepath& path) const +{ + // 繝代せ縺悟ョ悟ィ荳閾エ縺励※縺繧後ーTRUE + if (strcmp(path.GetPath(), GetPath()) == 0) { + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::Save(Fileio *fio, int /*ver*/) +{ + ASSERT(this); + ASSERT(fio); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝ュ繝シ繝 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL Filepath::Load(Fileio *fio, int /*ver*/) +{ + ASSERT(this); + ASSERT(fio); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧キ繝ァ繝シ繝亥錐 +// +//--------------------------------------------------------------------------- +char Filepath::ShortName[_MAX_FNAME + _MAX_DIR]; + +//--------------------------------------------------------------------------- +// +// 繝輔ぃ繧、繝ォ蜷搾シ区僑蠑オ蟄 +// +//--------------------------------------------------------------------------- +TCHAR Filepath::FileExt[_MAX_FNAME + _MAX_DIR]; \ No newline at end of file diff --git a/src/raspberrypi/filepath.h b/src/raspberrypi/filepath.h new file mode 100644 index 00000000..1817a429 --- /dev/null +++ b/src/raspberrypi/filepath.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2012-2018 GIMONS +// [ 繝輔ぃ繧、繝ォ繝代せ(繧オ繝悶そ繝繝) ] +// +//--------------------------------------------------------------------------- + +#if !defined(filepath_h) +#define filepath_h + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳夂セゥ +// +//--------------------------------------------------------------------------- +#define FILEPATH_MAX _MAX_PATH + +//=========================================================================== +// +// 繝輔ぃ繧、繝ォ繝代せ +// 窶サ莉」蜈・貍皮ョ怜ュ舌r逕ィ諢上☆繧九%縺ィ +// +//=========================================================================== +class Filepath +{ +public: + Filepath(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~Filepath(); + // 繝繧ケ繝医Λ繧ッ繧ソ + Filepath& operator=(const Filepath& path); + // 莉」蜈・ + + void FASTCALL Clear(); + // 繧ッ繝ェ繧「 + void FASTCALL SetPath(LPCSTR path); + // 繝輔ぃ繧、繝ォ險ュ螳(繝ヲ繝シ繧カ) MBCS逕ィ + BOOL FASTCALL IsClear() const; + // 繧ッ繝ェ繧「縺輔l縺ヲ縺繧九° + LPCTSTR FASTCALL GetPath() const { return m_szPath; } + // 繝代せ蜷榊叙蠕 + const char* FASTCALL GetShort() const; + // 繧キ繝ァ繝シ繝亥錐蜿門セ(const char*) + LPCTSTR FASTCALL GetFileExt() const; + // 繧キ繝ァ繝シ繝亥錐蜿門セ(LPCTSTR) + BOOL FASTCALL CmpPath(const Filepath& path) const; + // 繝代せ豈碑シ + + BOOL FASTCALL Save(Fileio *fio, int ver); + // 繧サ繝シ繝 + BOOL FASTCALL Load(Fileio *fio, int ver); + // 繝ュ繝シ繝 + +private: + void FASTCALL Split(); + // 繝代せ蛻蜑イ + void FASTCALL Make(); + // 繝代せ蜷域 + void FASTCALL SetCurDir(); + // 繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ險ュ螳 + TCHAR m_szPath[_MAX_PATH]; + // 繝輔ぃ繧、繝ォ繝代せ + TCHAR m_szDrive[_MAX_DRIVE]; + // 繝峨Λ繧、繝 + TCHAR m_szDir[_MAX_DIR]; + // 繝繧」繝ャ繧ッ繝医Μ + TCHAR m_szFile[_MAX_FNAME]; + // 繝輔ぃ繧、繝ォ + TCHAR m_szExt[_MAX_EXT]; + // 諡。蠑オ蟄 + + static char ShortName[_MAX_FNAME + _MAX_DIR]; + // 繧キ繝ァ繝シ繝亥錐(char) + static TCHAR FileExt[_MAX_FNAME + _MAX_DIR]; + // 繧キ繝ァ繝シ繝亥錐(TCHAR) +}; + +#endif // filepath_h diff --git a/src/raspberrypi/gpiobus.cpp b/src/raspberrypi/gpiobus.cpp new file mode 100644 index 00000000..792f8070 --- /dev/null +++ b/src/raspberrypi/gpiobus.cpp @@ -0,0 +1,1192 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ GPIO-SCSI繝舌せ ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "gpiobus.h" + +#ifdef __linux__ +//--------------------------------------------------------------------------- +// +// imported from bcm_host.c +// +//--------------------------------------------------------------------------- +static DWORD get_dt_ranges(const char *filename, DWORD offset) +{ + DWORD address; + FILE *fp; + BYTE buf[4]; + + address = ~0; + fp = fopen(filename, "rb"); + if (fp) { + fseek(fp, offset, SEEK_SET); + if (fread(buf, 1, sizeof buf, fp) == sizeof buf) { + address = + buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0; + } + fclose(fp); + } + return address; +} + +DWORD bcm_host_get_peripheral_address(void) +{ + DWORD address; + + address = get_dt_ranges("/proc/device-tree/soc/ranges", 4); + return address == (DWORD)~0 ? 0x20000000 : address; +} +#endif // __linux__ + +#ifdef __NetBSD__ +// Raspberry Pi繧キ繝ェ繝シ繧コ繧剃サョ螳壹@縺ヲCPU縺九i繧「繝峨Ξ繧ケ繧呈耳螳 +DWORD bcm_host_get_peripheral_address(void) +{ + char buf[1024]; + size_t len = sizeof(buf); + DWORD address; + + if (sysctlbyname("hw.model", buf, &len, NULL, 0) || + strstr(buf, "ARM1176JZ-S") != buf) { + // CPU繝「繝繝ォ縺ョ蜿門セ励↓螟ア謨 || BCM2835縺ァ縺ッ縺ェ縺 + // BCM283[67]縺ョ繧「繝峨Ξ繧ケ繧剃スソ逕ィ + address = 0x3f000000; + } else { + // BCM2835縺ョ繧「繝峨Ξ繧ケ繧剃スソ逕ィ + address = 0x20000000; + } + printf("Peripheral address : 0x%lx\n", address); + return address; +} +#endif + +//--------------------------------------------------------------------------- +// +// 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +GPIOBUS::GPIOBUS() +{ +} + +//--------------------------------------------------------------------------- +// +// 繝繧ケ繝医Λ繧ッ繧ソ +// +//--------------------------------------------------------------------------- +GPIOBUS::~GPIOBUS() +{ +} + +//--------------------------------------------------------------------------- +// +// 繝斐Φ讖溯ス險ュ螳(蜈・蜃コ蜉幄ィュ螳) +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::PinConfig(int pin, int mode) +{ + int index; + DWORD mask; + + // 譛ェ菴ソ逕ィ縺ェ繧臥┌蜉ケ + if (pin < 0) { + return; + } + + index = pin / 10; + mask = ~(0x7 << ((pin % 10) * 3)); + gpio[index] = (gpio[index] & mask) | ((mode & 0x7) << ((pin % 10) * 3)); +} + +//--------------------------------------------------------------------------- +// +// 繝斐Φ讖溯ス險ュ螳(繝励Ν繧「繝繝/繝繧ヲ繝ウ) +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::PullConfig(int pin, int mode) +{ + // 譛ェ菴ソ逕ィ縺ェ繧臥┌蜉ケ + if (pin < 0) { + return; + } + + gpio[GPIO_PUD] = mode & 0x3; + usleep(1); + gpio[GPIO_CLK_0] = 0x1 << pin; + usleep(1); + gpio[GPIO_PUD] = 0; + gpio[GPIO_CLK_0] = 0; +} + +//--------------------------------------------------------------------------- +// +// Drive Strength險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::DrvConfig(DWORD drive) +{ + DWORD data; + + // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌′縺ゅl縺ーIOCTL縺ァ萓晞シ縺吶k + if (drvfd >= 0) { + ioctl(drvfd, IOCTL_PADS, (DWORD)drive); + } else { + data = pads[PAD_0_27]; + pads[PAD_0_27] = (0xFFFFFFF8 & data) | drive | 0x5a000000; + } +} + +//--------------------------------------------------------------------------- +// +// 繝斐Φ蜃コ蜉幄ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::PinSetSignal(int pin, BOOL ast) +{ + // 譛ェ菴ソ逕ィ縺ェ繧臥┌蜉ケ + if (pin < 0) { + return; + } + + if (ast) { + gpio[GPIO_SET_0] = 0x1 << pin; + } else { + gpio[GPIO_CLR_0] = 0x1 << pin; + } +} + +//--------------------------------------------------------------------------- +// +// 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::MakeTable(void) +{ + const int pintbl[] = { + PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, PIN_DT4, + PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP + }; + + int i; + int j; + BOOL tblParity[256]; + DWORD bits; + DWORD parity; +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; +#else + DWORD gpclr; + DWORD gpset; +#endif + + // 繝代Μ繝繧」繝繝シ繝悶Ν菴懈 + for (i = 0; i < 0x100; i++) { + bits = (DWORD)i; + parity = 0; + for (j = 0; j < 8; j++) { + parity ^= bits & 1; + bits >>= 1; + } + parity = ~parity; + tblParity[i] = parity & 1; + } + +#if SIGNAL_CONTROL_MODE == 0 + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0xff, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + + // 繝薙ャ繝域、懈渊 + for (j = 0; j < 9; j++) { + // 繧、繝ウ繝繝繧ッ繧ケ縺ィ繧キ繝輔ヨ驥剰ィ育ョ + index = pintbl[j] / 10; + shift = (pintbl[j] % 10) * 3; + + // 繝槭せ繧ッ繝繝シ繧ソ + tblDatMsk[index][i] &= ~(0x7 << shift); + + // 險ュ螳壹ョ繝シ繧ソ + if (bits & 1) { + tblDatSet[index][i] |= (1 << shift); + } + + bits >>= 1; + } + } +#else + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0x00, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + +#if SIGNAL_CONTROL_MODE == 1 + // 雋隲也炊縺ッ蜿崎サ「 + bits = ~bits; +#endif + + // GPIO繝ャ繧ク繧ケ繧ソ諠蝣ア縺ョ菴懈 + gpclr = 0; + gpset = 0; + for (j = 0; j < 9; j++) { + if (bits & 1) { + gpset |= (1 << pintbl[j]); + } else { + gpclr |= (1 << pintbl[j]); + } + bits >>= 1; + } + + tblDatMsk[i] = gpclr; + tblDatSet[i] = gpset; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::Init(mode_e mode) +{ + DWORD base; + DWORD addr; + int fd; + void *map; + int i; + int j; + int pullmode; + + // 蜍穂ス懊Δ繝シ繝峨ョ菫晏ュ + actmode = mode; + + // 繝吶シ繧ケ繧「繝峨Ξ繧ケ縺ョ蜿門セ + base = (DWORD)bcm_host_get_peripheral_address(); + + // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌が繝シ繝励Φ + drvfd = open(DRIVER_PATH, O_RDWR); + if (drvfd >= 0) { + printf("Activated RaSCSI GPIO Driver.\n"); + ioctl(drvfd, IOCTL_INIT, base); + ioctl(drvfd, IOCTL_MODE, (DWORD)actmode); + } + + // /dev/mem,/dev/gpiomem縺ョ鬆縺ォ繧ェ繝シ繝励Φ繧定ゥヲ縺ソ繧 + addr = base + GPIO_OFFSET; + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + // /dev/gpiomem繧偵が繝シ繝励Φ + addr = 0; + fd = open("/dev/gpiomem", O_RDWR | O_SYNC); + if (fd == -1) { + return FALSE; + } + } + + // GPIO縺ョI/O繝昴シ繝医r繝槭ャ繝励☆繧 + map = mmap(NULL, 164, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr); + if (map == MAP_FAILED) { + close(fd); + return FALSE; + } + + // GPIO縺ョI/O繝昴シ繝医い繝峨Ξ繧ケ遒コ菫 + gpio = (DWORD *)map; + level = &gpio[GPIO_LEV_0]; + + // PADS縺ョ蜃ヲ逅縺ッ繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌′辟。縺譎ゅ□縺(sudo縺悟ソ隕√→縺ェ繧) + if (drvfd < 0) { + // /dev/mem繧偵が繝シ繝励Φ + fd = open("/dev/mem", O_RDWR | O_SYNC); + if (fd == -1) { + return FALSE; + } + + // PADS縺ョI/O繝昴シ繝医r繝槭ャ繝励☆繧 + map = mmap(NULL, 56, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, base + PADS_OFFSET); + close(fd); + if (map == MAP_FAILED) { + return FALSE; + } + + // PADS縺ョI/O繝昴シ繝医い繝峨Ξ繧ケ遒コ菫 + pads = (DWORD *)map; + } + + // Drive Strength繧16mA縺ォ險ュ螳 + DrvConfig(7); + + // 繝励Ν繧「繝繝/繝励Ν繝繧ヲ繝ウ繧定ィュ螳 +#if SIGNAL_CONTROL_MODE == 0 + pullmode = GPIO_PULLNONE; +#elif SIGNAL_CONTROL_MODE == 1 + pullmode = GPIO_PULLUP; +#else + pullmode = GPIO_PULLDOWN; +#endif + + // 蜈ィ菫。蜿キ蛻晄悄蛹 + for (i = 0; SignalTable[i] >= 0; i++) { + j = SignalTable[i]; + PinSetSignal(j, FALSE); + PinConfig(j, GPIO_INPUT); + PullConfig(j, pullmode); + } + + // 蛻カ蠕。菫。蜿キ繧定ィュ螳 + PinSetSignal(PIN_ACT, FALSE); + PinSetSignal(PIN_TAD, FALSE); + PinSetSignal(PIN_IND, FALSE); + PinSetSignal(PIN_DTD, FALSE); + PinConfig(PIN_ACT, GPIO_OUTPUT); + PinConfig(PIN_TAD, GPIO_OUTPUT); + PinConfig(PIN_IND, GPIO_OUTPUT); + PinConfig(PIN_DTD, GPIO_OUTPUT); + + // 譛牙柑菫。蜿キ繧定ィュ螳 + PinSetSignal(PIN_ENB, ENB_ON); + PinConfig(PIN_ENB, GPIO_OUTPUT); + + // GPFSEL繝舌ャ繧ッ繧「繝繝 + gpfsel[0] = gpio[GPIO_FSEL_0]; + gpfsel[1] = gpio[GPIO_FSEL_1]; + gpfsel[2] = gpio[GPIO_FSEL_2]; + gpfsel[3] = gpio[GPIO_FSEL_3]; + + // 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 + MakeTable(); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::Cleanup() +{ + int i; + int j; + + // 蛻カ蠕。菫。蜿キ繧定ィュ螳 + PinSetSignal(PIN_ENB, FALSE); + PinSetSignal(PIN_ACT, FALSE); + PinSetSignal(PIN_TAD, FALSE); + PinSetSignal(PIN_IND, FALSE); + PinSetSignal(PIN_DTD, FALSE); + PinConfig(PIN_ACT, GPIO_INPUT); + PinConfig(PIN_TAD, GPIO_INPUT); + PinConfig(PIN_IND, GPIO_INPUT); + PinConfig(PIN_DTD, GPIO_INPUT); + + // 蜈ィ菫。蜿キ蛻晄悄蛹 + for (i = 0; SignalTable[i] >= 0; i++) { + j = SignalTable[i]; + PinSetSignal(j, FALSE); + PinConfig(j, GPIO_INPUT); + PullConfig(j, GPIO_PULLNONE); + } + + // Drive Strength繧8mA縺ォ險ュ螳 + DrvConfig(3); + + // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝 + if (drvfd >= 0) { + close(drvfd); + drvfd = -1; + } +} + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetControl(int pin, BOOL ast) +{ + PinSetSignal(pin, ast); +} + +//--------------------------------------------------------------------------- +// +// 蜈・蜃コ蜉帙Δ繝シ繝芽ィュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetMode(int pin, int mode) +{ + int index; + int shift; + DWORD data; + +#if SIGNAL_CONTROL_MODE == 0 + if (mode == OUT) { + return; + } +#endif + + index = pin / 10; + shift = (pin % 10) * 3; + data = gpfsel[index]; + data &= ~(0x7 << shift); + if (mode == OUT) { + data |= (1 << shift); + } + gpio[index] = data; + gpfsel[index] = data; +} + +//--------------------------------------------------------------------------- +// +// 蜈・蜉帑ソ。蜿キ蛟、蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetSignal(int pin) +{ + return (signals >> pin) & 1; +} + +//--------------------------------------------------------------------------- +// +// 蜃コ蜉帑ソ。蜿キ蛟、險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetSignal(int pin, BOOL ast) +{ +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; + DWORD data; + + index = pin / 10; + shift = (pin % 10) * 3; + data = gpfsel[index]; + data &= ~(0x7 << shift); + if (ast) { + data |= (1 << shift); + } + gpio[index] = data; + gpfsel[index] = data; +#elif SIGNAL_CONTROL_MODE == 1 + if (ast) { + gpio[GPIO_CLR_0] = 0x1 << pin; + } else { + gpio[GPIO_SET_0] = 0x1 << pin; + } +#elif SIGNAL_CONTROL_MODE == 2 + if (ast) { + gpio[GPIO_SET_0] = 0x1 << pin; + } else { + gpio[GPIO_CLR_0] = 0x1 << pin; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SleepNsec(DWORD nsec) +{ + DWORD count; + + count = (nsec + 8 - 1) / 8; + while (count--) { + gpio[GPIO_PUD] = 0; + } +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::Reset() +{ + int i; + int j; + + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝 + SetControl(PIN_ACT, ACT_OFF); + + // 蜈ィ菫。蜿キ繧偵ロ繧イ繝シ繝医↓險ュ螳 + for (i = 0;; i++) { + j = SignalTable[i]; + if (j < 0) { + break; + } + + SetSignal(j, OFF); + } + + if (actmode == TARGET) { + // 繧ソ繝シ繧イ繝繝医Δ繝シ繝 + + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_IN); + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + + // 繧、繝九す繧ィ繝シ繧ソ菫。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_IND, IND_IN); + SetMode(PIN_SEL, IN); + SetMode(PIN_ATN, IN); + SetMode(PIN_ACK, IN); + SetMode(PIN_RST, IN); + + // 繝繝シ繧ソ繝舌せ菫。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } else { + // 繧、繝九す繧ィ繝シ繧ソ繝「繝シ繝 + + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_IN); + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + + // 繧、繝九す繧ィ繝シ繧ソ菫。蜿キ繧貞コ蜉帙↓險ュ螳 + SetControl(PIN_IND, IND_OUT); + SetMode(PIN_SEL, OUT); + SetMode(PIN_ATN, OUT); + SetMode(PIN_ACK, OUT); + SetMode(PIN_RST, OUT); + + // 繝繝シ繧ソ繝舌せ菫。蜿キ繧貞コ蜉帙↓險ュ螳 + SetControl(PIN_DTD, DTD_OUT); + SetMode(PIN_DT0, OUT); + SetMode(PIN_DT1, OUT); + SetMode(PIN_DT2, OUT); + SetMode(PIN_DT3, OUT); + SetMode(PIN_DT4, OUT); + SetMode(PIN_DT5, OUT); + SetMode(PIN_DT6, OUT); + SetMode(PIN_DT7, OUT); + SetMode(PIN_DP, OUT); + } + + // 蜈ィ菫。蜿キ蛻晄悄蛹 + signals = 0; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ菫。蜿キ蜿悶j霎シ縺ソ +// +//--------------------------------------------------------------------------- +DWORD FASTCALL GPIOBUS::Aquire() +{ + signals = *level; + +#if SIGNAL_CONTROL_MODE < 2 + // 雋隲也炊縺ェ繧牙渚霆「縺吶k(蜀驛ィ蜃ヲ逅縺ッ豁」隲也炊縺ォ邨ア荳) + signals = ~signals; +#endif + + return signals; +} + +//--------------------------------------------------------------------------- +// +// BSY繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetBSY() +{ + return GetSignal(PIN_BSY); +} + +//--------------------------------------------------------------------------- +// +// BSY繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetBSY(BOOL ast) +{ + if (actmode == TARGET) { + if (ast) { + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝ウ + SetControl(PIN_ACT, ACT_ON); + + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞コ蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_OUT); + SetMode(PIN_BSY, OUT); + SetMode(PIN_MSG, OUT); + SetMode(PIN_CD, OUT); + SetMode(PIN_REQ, OUT); + SetMode(PIN_IO, OUT); + } else { + // 繧ソ繝シ繧イ繝繝井ソ。蜿キ繧貞・蜉帙↓險ュ螳 + SetControl(PIN_TAD, TAD_IN); + SetMode(PIN_BSY, IN); + SetMode(PIN_MSG, IN); + SetMode(PIN_CD, IN); + SetMode(PIN_REQ, IN); + SetMode(PIN_IO, IN); + + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝 + SetControl(PIN_ACT, ACT_OFF); + } + } + + // BSY菫。蜿キ繧定ィュ螳 + SetSignal(PIN_BSY, ast); +} + +//--------------------------------------------------------------------------- +// +// SEL繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetSEL() +{ + return GetSignal(PIN_SEL); +} + +//--------------------------------------------------------------------------- +// +// SEL繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetSEL(BOOL ast) +{ + if (actmode == INITIATOR && ast) { + // 繧「繧ッ繝繧」繝紋ソ。蜿キ繧偵が繝ウ + SetControl(PIN_ACT, ACT_ON); + } + + // SEL菫。蜿キ繧定ィュ螳 + SetSignal(PIN_SEL, ast); +} + +//--------------------------------------------------------------------------- +// +// ATN繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetATN() +{ + return GetSignal(PIN_ATN); +} + +//--------------------------------------------------------------------------- +// +// ATN繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetATN(BOOL ast) +{ + SetSignal(PIN_ATN, ast); +} + +//--------------------------------------------------------------------------- +// +// ACK繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetACK() +{ + return GetSignal(PIN_ACK); +} + +//--------------------------------------------------------------------------- +// +// ACK繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetACK(BOOL ast) +{ + SetSignal(PIN_ACK, ast); +} + +//--------------------------------------------------------------------------- +// +// RST繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetRST() +{ + return GetSignal(PIN_RST); +} + +//--------------------------------------------------------------------------- +// +// RST繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetRST(BOOL ast) +{ + SetSignal(PIN_RST, ast); +} + +//--------------------------------------------------------------------------- +// +// MSG繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetMSG() +{ + return GetSignal(PIN_MSG); +} + +//--------------------------------------------------------------------------- +// +// MSG繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetMSG(BOOL ast) +{ + SetSignal(PIN_MSG, ast); +} + +//--------------------------------------------------------------------------- +// +// CD繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetCD() +{ + return GetSignal(PIN_CD); +} + +//--------------------------------------------------------------------------- +// +// CD繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetCD(BOOL ast) +{ + SetSignal(PIN_CD, ast); +} + +//--------------------------------------------------------------------------- +// +// IO繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetIO() +{ + BOOL ast; + ast = GetSignal(PIN_IO); + + if (actmode == INITIATOR) { + // IO菫。蜿キ縺ォ繧医▲縺ヲ繝繝シ繧ソ縺ョ蜈・蜃コ蜉帶婿蜷代r螟画峩 + if (ast) { + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } else { + SetControl(PIN_DTD, DTD_OUT); + SetMode(PIN_DT0, OUT); + SetMode(PIN_DT1, OUT); + SetMode(PIN_DT2, OUT); + SetMode(PIN_DT3, OUT); + SetMode(PIN_DT4, OUT); + SetMode(PIN_DT5, OUT); + SetMode(PIN_DT6, OUT); + SetMode(PIN_DT7, OUT); + SetMode(PIN_DP, OUT); + } + } + + return ast; +} + +//--------------------------------------------------------------------------- +// +// IO繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetIO(BOOL ast) +{ + SetSignal(PIN_IO, ast); + + if (actmode == TARGET) { + // IO菫。蜿キ縺ォ繧医▲縺ヲ繝繝シ繧ソ縺ョ蜈・蜃コ蜉帶婿蜷代r螟画峩 + if (ast) { + SetControl(PIN_DTD, DTD_OUT); + SetMode(PIN_DT0, OUT); + SetMode(PIN_DT1, OUT); + SetMode(PIN_DT2, OUT); + SetMode(PIN_DT3, OUT); + SetMode(PIN_DT4, OUT); + SetMode(PIN_DT5, OUT); + SetMode(PIN_DT6, OUT); + SetMode(PIN_DT7, OUT); + SetMode(PIN_DP, OUT); + } else { + SetControl(PIN_DTD, DTD_IN); + SetMode(PIN_DT0, IN); + SetMode(PIN_DT1, IN); + SetMode(PIN_DT2, IN); + SetMode(PIN_DT3, IN); + SetMode(PIN_DT4, IN); + SetMode(PIN_DT5, IN); + SetMode(PIN_DT6, IN); + SetMode(PIN_DT7, IN); + SetMode(PIN_DP, IN); + } + } +} + +//--------------------------------------------------------------------------- +// +// REQ繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BOOL FASTCALL GPIOBUS::GetREQ() +{ + return GetSignal(PIN_REQ); +} + +//--------------------------------------------------------------------------- +// +// REQ繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetREQ(BOOL ast) +{ + SetSignal(PIN_REQ, ast); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧キ繧ー繝翫Ν蜿門セ +// +//--------------------------------------------------------------------------- +BYTE FASTCALL GPIOBUS::GetDAT() +{ + DWORD data; + + data = Aquire(); + data = + ((data >> (PIN_DT0 - 0)) & (1 << 0)) | + ((data >> (PIN_DT1 - 1)) & (1 << 1)) | + ((data >> (PIN_DT2 - 2)) & (1 << 2)) | + ((data >> (PIN_DT3 - 3)) & (1 << 3)) | + ((data >> (PIN_DT4 - 4)) & (1 << 4)) | + ((data >> (PIN_DT5 - 5)) & (1 << 5)) | + ((data >> (PIN_DT6 - 6)) & (1 << 6)) | + ((data >> (PIN_DT7 - 7)) & (1 << 7)); + + return (BYTE)data; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +void FASTCALL GPIOBUS::SetDAT(BYTE dat) +{ + // 繝昴シ繝医∈譖ク縺崎セシ縺ソ +#if SIGNAL_CONTROL_MODE == 0 + gpfsel[0] &= tblDatMsk[0][dat]; + gpfsel[0] |= tblDatSet[0][dat]; + gpio[GPIO_FSEL_0] = gpfsel[0]; + + gpfsel[1] &= tblDatMsk[1][dat]; + gpfsel[1] |= tblDatSet[1][dat]; + gpio[GPIO_FSEL_1] = gpfsel[1]; + + gpfsel[2] &= tblDatMsk[2][dat]; + gpfsel[2] |= tblDatSet[2][dat]; + gpio[GPIO_FSEL_2] = gpfsel[2]; +#else + gpio[GPIO_CLR_0] = tblDatMsk[dat]; + gpio[GPIO_SET_0] = tblDatSet[dat]; +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿嶺ソ。繝上Φ繝峨す繧ァ繧、繧ッ +// +//--------------------------------------------------------------------------- +int FASTCALL GPIOBUS::ReceiveHandShake(BYTE *buf, int count) +{ + int i; + DWORD loop; + DWORD phase; + + if (drvfd >= 0) { + return read(drvfd, buf, count); + } else { + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, ON); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // 繝繝シ繧ソ蜿門セ + *buf = GetDAT(); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, OFF); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // 蜿嶺ソ。謨ー繧定ソ泌唆 + return i; + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ蜿門セ + *buf = GetDAT(); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, ON); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, OFF); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // 蜿嶺ソ。謨ー繧定ソ泌唆 + return i; + } + } +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ騾∽ソ。繝上Φ繝峨す繧ァ繧、繧ッ +// +//--------------------------------------------------------------------------- +int FASTCALL GPIOBUS::SendHandShake(BYTE *buf, int count) +{ + int i; + DWORD loop; + DWORD phase; + + if (drvfd >= 0) { + return write(drvfd, buf, count); + } else { + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // 繝繝シ繧ソ險ュ螳 + SetDAT(*buf); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, ON); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, OFF); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // 騾∽ソ。謨ー繧定ソ泌唆 + return i; + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ險ュ螳 + SetDAT(*buf); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, ON); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, OFF); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + + // 騾∽ソ。謨ー繧定ソ泌唆 + return i; + } + } +} + +//--------------------------------------------------------------------------- +// +// 菫。蜿キ繝繝シ繝悶Ν +// +//--------------------------------------------------------------------------- +const int GPIOBUS::SignalTable[19] = { + PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, + PIN_DT4, PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP, + PIN_SEL,PIN_ATN, PIN_RST, PIN_ACK, + PIN_BSY, PIN_MSG, PIN_CD, PIN_IO, PIN_REQ, + -1 +}; diff --git a/src/raspberrypi/gpiobus.h b/src/raspberrypi/gpiobus.h new file mode 100644 index 00000000..82f556f6 --- /dev/null +++ b/src/raspberrypi/gpiobus.h @@ -0,0 +1,479 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ GPIO-SCSI繝舌せ ] +// +//--------------------------------------------------------------------------- + +#if !defined(gpiobus_h) +#define gpiobus_h + +#include "scsi.h" + +//--------------------------------------------------------------------------- +// +// 謗・邯壽婿豕募ョ夂セゥ縺ョ驕ク謚 +// +//--------------------------------------------------------------------------- +#define CONNECT_TYPE_STANDARD // 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_FULLSPEC // 繝輔Ν繧ケ繝壹ャ繧ッ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_AIBOM // AIBOM迚(豁」隲也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_GAMERNIUM // GAMERnium.com迚(讓呎コ冶ォ也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) + +//--------------------------------------------------------------------------- +// +// 菫。蜿キ蛻カ蠕。隲也炊蜿翫ウ繝斐Φ繧「繧オ繧、繝ウ繧ォ繧ケ繧ソ繝槭う繧コ +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// SIGNAL_CONTROL_MODE:菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +// Version1.22縺九i菫。蜿キ蛻カ蠕。縺ョ隲也炊繧偵き繧ケ繧ソ繝槭う繧コ縺ァ縺阪∪縺吶 +// +// 0:SCSI隲也炊莉墓ァ +// 逶エ邨舌∪縺溘ッHP縺ォ蜈ャ髢九@縺74LS641-1遲峨r菴ソ逕ィ縺吶k螟画鋤蝓コ譚ソ +// 繧「繝シ繧オ繝シ繝:0V +// 繝阪ご繝シ繝 :繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉(繝舌せ縺九i蛻繧企屬縺) +// +// 1:雋隲也炊莉墓ァ(雋隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// 迴セ譎らせ縺ァ縺薙ョ莉墓ァ倥↓繧医k螟画鋤蝓コ譚ソ縺ッ蟄伜惠縺励∪縺帙s +// 繧「繝シ繧オ繝シ繝:0V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :3.3V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +// 2:豁」隲也炊莉墓ァ(豁」隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// RaSCSI Adapter Rev.C @132sync遲 +// +// 繧「繝シ繧オ繝シ繝:3.3V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :0V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// 蛻カ蠕。菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// +// 蛻カ蠕。菫。蜿キ +// PIN_ACT +// SCSI繧ウ繝槭Φ繝峨r蜃ヲ逅荳ュ縺ョ迥カ諷九r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_ENB +// 襍キ蜍輔°繧臥オゆコ縺ョ髢薙ョ譛牙柑菫。蜿キ繧堤、コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_TAD +// 繧ソ繝シ繧イ繝繝井ソ。蜿キ(BSY,IO,CD,MSG,REG)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_IND +// 繧、繝九す繝シ繧ィ繝シ繧ソ菫。蜿キ(SEL,ATN,RST,ACK)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_DTD +// 繝繝シ繧ソ菫。蜿キ(DT0...DT7,DP)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +// 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菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// SCSI縺ョ菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// PIN_DT0ス霸IN_SEL +// +//--------------------------------------------------------------------------- + +#ifdef CONNECT_TYPE_STANDARD +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "STANDARD" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND -1 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD -1 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_FULLSPEC +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "FULLSPEC" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND 6 // INITIATOR CTRL DIRECTION +#define PIN_TAD 7 // TARGET CTRL DIRECTION +#define PIN_DTD 8 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_AIBOM +// +// RaSCSI Adapter 縺ゅ>縺シ繧迚 +// + +#define CONNECT_DESC "AIBOM PRODUCTS version" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 2 // SCSI豁」隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN FALSE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 17 // ENABLE +#define PIN_IND 27 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD 18 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 6 // 繝繝シ繧ソ0 +#define PIN_DT1 12 // 繝繝シ繧ソ1 +#define PIN_DT2 13 // 繝繝シ繧ソ2 +#define PIN_DT3 16 // 繝繝シ繧ソ3 +#define PIN_DT4 19 // 繝繝シ繧ソ4 +#define PIN_DT5 20 // 繝繝シ繧ソ5 +#define PIN_DT6 26 // 繝繝シ繧ソ6 +#define PIN_DT7 21 // 繝繝シ繧ソ7 +#define PIN_DP 5 // 繝代Μ繝繧」 +#define PIN_ATN 22 // ATN +#define PIN_RST 25 // RST +#define PIN_ACK 10 // ACK +#define PIN_REQ 7 // REQ +#define PIN_MSG 9 // MSG +#define PIN_CD 11 // CD +#define PIN_IO 23 // IO +#define PIN_BSY 24 // BSY +#define PIN_SEL 8 // SEL +#endif + +#ifdef CONNECT_TYPE_GAMERNIUM +// +// RaSCSI Adapter GAMERnium.com迚 +// + +#define CONNECT_DESC "GAMERnium.com version"// 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 14 // ACTIVE +#define PIN_ENB 6 // ENABLE +#define PIN_IND 7 // INITIATOR CTRL DIRECTION +#define PIN_TAD 8 // TARGET CTRL DIRECTION +#define PIN_DTD 5 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 21 // 繝繝シ繧ソ0 +#define PIN_DT1 26 // 繝繝シ繧ソ1 +#define PIN_DT2 20 // 繝繝シ繧ソ2 +#define PIN_DT3 19 // 繝繝シ繧ソ3 +#define PIN_DT4 16 // 繝繝シ繧ソ4 +#define PIN_DT5 13 // 繝繝シ繧ソ5 +#define PIN_DT6 12 // 繝繝シ繧ソ6 +#define PIN_DT7 11 // 繝繝シ繧ソ7 +#define PIN_DP 25 // 繝代Μ繝繧」 +#define PIN_ATN 10 // ATN +#define PIN_RST 22 // RST +#define PIN_ACK 24 // ACK +#define PIN_REQ 15 // REQ +#define PIN_MSG 17 // MSG +#define PIN_CD 18 // CD +#define PIN_IO 4 // IO +#define PIN_BSY 27 // BSY +#define PIN_SEL 23 // SEL +#endif + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(GPIO) +// +//--------------------------------------------------------------------------- +#define GPIO_OFFSET 0x200000 +#define PADS_OFFSET 0x100000 +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 +#define GPIO_PULLNONE 0 +#define GPIO_PULLDOWN 1 +#define GPIO_PULLUP 2 +#define GPIO_FSEL_0 0 +#define GPIO_FSEL_1 1 +#define GPIO_FSEL_2 2 +#define GPIO_FSEL_3 3 +#define GPIO_SET_0 7 +#define GPIO_CLR_0 10 +#define GPIO_LEV_0 13 +#define GPIO_EDS_0 16 +#define GPIO_REN_0 19 +#define GPIO_FEN_0 22 +#define GPIO_HEN_0 25 +#define GPIO_LEN_0 28 +#define GPIO_AREN_0 31 +#define GPIO_AFEN_0 34 +#define GPIO_PUD 37 +#define GPIO_CLK_0 38 +#define PAD_0_27 11 + +#define GPIO_INEDGE ((1 << PIN_BSY) | \ + (1 << PIN_SEL) | \ + (1 << PIN_ATN) | \ + (1 << PIN_ACK) | \ + (1 << PIN_RST)) + +#define GPIO_MCI ((1 << PIN_MSG) | \ + (1 << PIN_CD) | \ + (1 << PIN_IO)) + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(蛻カ蠕。菫。蜿キ) +// +//--------------------------------------------------------------------------- +#define ACT_OFF !ACT_ON +#define ENB_OFF !ENB_ON +#define TAD_OUT !TAD_IN +#define IND_OUT !IND_IN +#define DTD_OUT !DTD_IN + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(SCSI) +// +//--------------------------------------------------------------------------- +#define IN GPIO_INPUT +#define OUT GPIO_OUTPUT +#define ON TRUE +#define OFF FALSE + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(繝峨Λ繧、繝) +// +//--------------------------------------------------------------------------- +#define DEVICE_NAME "rascsidrv" +#define DRIVER_PATH "/dev/" DEVICE_NAME +#define IOCTL_INIT 0x100 +#define IOCTL_MODE 0x101 +#define IOCTL_PADS 0x102 + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ゥ繧ケ螳夂セゥ +// +//--------------------------------------------------------------------------- +class GPIOBUS : public BUS +{ +public: + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + GPIOBUS(); + // 繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ + virtual ~GPIOBUS(); + // 繝繧ケ繝医Λ繧ッ繧ソ + BOOL FASTCALL Init(mode_e mode = TARGET); + // 蛻晄悄蛹 + void FASTCALL Reset(); + // 繝ェ繧サ繝繝 + void FASTCALL Cleanup(); + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + + DWORD FASTCALL Aquire(); + // 菫。蜿キ蜿悶j霎シ縺ソ + + BOOL FASTCALL GetBSY(); + // BSY繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetBSY(BOOL ast); + // BSY繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetSEL(); + // SEL繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetSEL(BOOL ast); + // SEL繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetATN(); + // ATN繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetATN(BOOL ast); + // ATN繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetACK(); + // ACK繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetACK(BOOL ast); + // ACK繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetRST(); + // RST繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetRST(BOOL ast); + // RST繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetMSG(); + // MSG繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetMSG(BOOL ast); + // MSG繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetCD(); + // CD繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetCD(BOOL ast); + // CD繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetIO(); + // IO繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetIO(BOOL ast); + // IO繧キ繧ー繝翫Ν險ュ螳 + + BOOL FASTCALL GetREQ(); + // REQ繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetREQ(BOOL ast); + // REQ繧キ繧ー繝翫Ν險ュ螳 + + BYTE FASTCALL GetDAT(); + // 繝繝シ繧ソ繧キ繧ー繝翫Ν蜿門セ + void FASTCALL SetDAT(BYTE dat); + // 繝繝シ繧ソ繧キ繧ー繝翫Ν險ュ螳 + int FASTCALL ReceiveHandShake(BYTE *buf, int count); + // 繝繝シ繧ソ蜿嶺ソ。繝上Φ繝峨す繧ァ繧、繧ッ + int FASTCALL SendHandShake(BYTE *buf, int count); + // 繝繝シ繧ソ騾∽ソ。繝上Φ繝峨す繧ァ繧、繧ッ + + // 繧ソ繧、繝樣未菫 + void FASTCALL SleepNsec(DWORD nsec); + // 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 + +private: + void FASTCALL DrvConfig(DWORD drive); + // GPIO繝峨Λ繧、繝冶ス蜉幄ィュ螳 + void FASTCALL PinConfig(int pin, int mode); + // GPIO繝斐Φ讖溯ス險ュ螳(蜈・蜃コ蜉幄ィュ螳) + void FASTCALL PullConfig(int pin, int mode); + // GPIO繝斐Φ讖溯ス險ュ螳(繝励Ν繧「繝繝/繝繧ヲ繝ウ) + void FASTCALL PinSetSignal(int pin, BOOL ast); + // GPIO繝斐Φ蜃コ蜉帑ソ。蜿キ險ュ螳 + void FASTCALL MakeTable(); + // 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 + void FASTCALL SetControl(int pin, BOOL ast); + // 蛻カ蠕。菫。蜿キ險ュ螳 + void FASTCALL SetMode(int pin, int mode); + // SCSI蜈・蜃コ蜉帙Δ繝シ繝芽ィュ螳 + BOOL FASTCALL GetSignal(int pin); + // SCSI蜈・蜉帑ソ。蜿キ蛟、蜿門セ + void FASTCALL SetSignal(int pin, BOOL ast); + // SCSI蜃コ蜉帑ソ。蜿キ蛟、險ュ螳 + + mode_e actmode; // 蜍穂ス懊Δ繝シ繝 + + volatile DWORD *gpio; // GPIO繝ャ繧ク繧ケ繧ソ + + volatile DWORD *pads; // PADS繝ャ繧ク繧ケ繧ソ + + volatile DWORD *level; // GPIO蜈・蜉帙Ξ繝吶Ν + + DWORD gpfsel[4]; // GPFSEL0-4繝舌ャ繧ッ繧「繝繝 + + DWORD signals; // 繝舌せ蜈ィ菫。蜿キ + +#if SIGNAL_CONTROL_MODE == 0 + DWORD tblDatMsk[3][256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν + + DWORD tblDatSet[3][256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#else + DWORD tblDatMsk[256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν + + DWORD tblDatSet[256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#endif + + int drvfd; // 繧ォ繝シ繝阪Ν繝峨Λ繧、繝舌ヵ繧。繧、繝ォ繝繧」繧ケ繧ッ繝励Μ繧ソ + + static const int SignalTable[19]; // 繧キ繧ー繝翫Ν繝繝シ繝悶Ν +}; + +#endif // gpiobus_h diff --git a/src/raspberrypi/kernelmodule/Makefile b/src/raspberrypi/kernelmodule/Makefile new file mode 100644 index 00000000..5ed61fdc --- /dev/null +++ b/src/raspberrypi/kernelmodule/Makefile @@ -0,0 +1,9 @@ +KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build +obj-m := rascsidrv.o +ccflags-y := -O3 + +all: + $(MAKE) -C $(KERNEL_HEADERS) M=$(PWD) modules + +clean: + $(MAKE) -C $(KERNEL_HEADERS) M=$(PWD) clean diff --git a/src/raspberrypi/kernelmodule/rascsidrv.c b/src/raspberrypi/kernelmodule/rascsidrv.c new file mode 100644 index 00000000..9dd239f9 --- /dev/null +++ b/src/raspberrypi/kernelmodule/rascsidrv.c @@ -0,0 +1,1122 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ GPIO繝峨Λ繧、繝 ] +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +// +// 蝓コ譛ャ蝙句ョ夂セゥ +// +//--------------------------------------------------------------------------- +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; + +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +//--------------------------------------------------------------------------- +// +// 謗・邯壽婿豕募ョ夂セゥ縺ョ驕ク謚 +// +//--------------------------------------------------------------------------- +#define CONNECT_TYPE_STANDARD // 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_FULLSPEC // 繝輔Ν繧ケ繝壹ャ繧ッ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_AIBOM // AIBOM迚(豁」隲也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) +//#define CONNECT_TYPE_GAMERNIUM // GAMERnium.com迚(讓呎コ冶ォ也炊,蝗コ譛峨ヴ繝ウ繧「繧オ繧、繝ウ) + +//--------------------------------------------------------------------------- +// +// 菫。蜿キ蛻カ蠕。隲也炊蜿翫ウ繝斐Φ繧「繧オ繧、繝ウ繧ォ繧ケ繧ソ繝槭う繧コ +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// SIGNAL_CONTROL_MODE:菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +// Version1.22縺九i菫。蜿キ蛻カ蠕。縺ョ隲也炊繧偵き繧ケ繧ソ繝槭う繧コ縺ァ縺阪∪縺吶 +// +// 0:SCSI隲也炊莉墓ァ +// 逶エ邨舌∪縺溘ッHP縺ォ蜈ャ髢九@縺74LS641-1遲峨r菴ソ逕ィ縺吶k螟画鋤蝓コ譚ソ +// 繧「繝シ繧オ繝シ繝:0V +// 繝阪ご繝シ繝 :繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉(繝舌せ縺九i蛻繧企屬縺) +// +// 1:雋隲也炊莉墓ァ(雋隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// 迴セ譎らせ縺ァ縺薙ョ莉墓ァ倥↓繧医k螟画鋤蝓コ譚ソ縺ッ蟄伜惠縺励∪縺帙s +// 繧「繝シ繧オ繝シ繝:0V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :3.3V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +// 2:豁」隲也炊莉墓ァ(豁」隲也炊->SCSI隲也炊縺ク縺ョ螟画鋤蝓コ譚ソ繧剃スソ逕ィ縺吶k蝣エ蜷) +// RaSCSI Adapter Rev.C @132sync遲 +// +// 繧「繝シ繧オ繝シ繝:3.3V -> (CONVERT) -> 0V +// 繝阪ご繝シ繝 :0V -> (CONVERT) -> 繧ェ繝シ繝励Φ繧ウ繝ャ繧ッ繧ソ蜃コ蜉 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// 蛻カ蠕。菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// +// 蛻カ蠕。菫。蜿キ +// PIN_ACT +// SCSI繧ウ繝槭Φ繝峨r蜃ヲ逅荳ュ縺ョ迥カ諷九r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_ENB +// 襍キ蜍輔°繧臥オゆコ縺ョ髢薙ョ譛牙柑菫。蜿キ繧堤、コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_TAD +// 繧ソ繝シ繧イ繝繝井ソ。蜿キ(BSY,IO,CD,MSG,REG)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_IND +// 繧、繝九す繝シ繧ィ繝シ繧ソ菫。蜿キ(SEL,ATN,RST,ACK)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// PIN_DTD +// 繝繝シ繧ソ菫。蜿キ(DT0...DT7,DP)縺ョ蜈・蜃コ蜉帶婿蜷代r遉コ縺吩ソ。蜿キ縺ョ繝斐Φ逡ェ蜿キ縲 +// +//--------------------------------------------------------------------------- + +//--------------------------------------------------------------------------- +// +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +// 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菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ險ュ螳 +// SCSI縺ョ菫。蜿キ縺ォ蟇セ縺吶kGPIO繝斐Φ縺ョ繝槭ャ繝斐Φ繧ー繝繝シ繝悶Ν縺ァ縺吶 +// PIN_DT0ス霸IN_SEL +// +//--------------------------------------------------------------------------- + +#ifdef CONNECT_TYPE_STANDARD +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "STANDARD" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND -1 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD -1 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_FULLSPEC +// +// RaSCSI 讓呎コ(SCSI隲也炊,讓呎コ悶ヴ繝ウ繧「繧オ繧、繝ウ) +// +#define CONNECT_DESC "FULLSPEC" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 5 // ENABLE +#define PIN_IND 6 // INITIATOR CTRL DIRECTION +#define PIN_TAD 7 // TARGET CTRL DIRECTION +#define PIN_DTD 8 // DATA DIRECTION + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 10 // 繝繝シ繧ソ0 +#define PIN_DT1 11 // 繝繝シ繧ソ1 +#define PIN_DT2 12 // 繝繝シ繧ソ2 +#define PIN_DT3 13 // 繝繝シ繧ソ3 +#define PIN_DT4 14 // 繝繝シ繧ソ4 +#define PIN_DT5 15 // 繝繝シ繧ソ5 +#define PIN_DT6 16 // 繝繝シ繧ソ6 +#define PIN_DT7 17 // 繝繝シ繧ソ7 +#define PIN_DP 18 // 繝代Μ繝繧」 +#define PIN_ATN 19 // ATN +#define PIN_RST 20 // RST +#define PIN_ACK 21 // ACK +#define PIN_REQ 22 // REQ +#define PIN_MSG 23 // MSG +#define PIN_CD 24 // CD +#define PIN_IO 25 // IO +#define PIN_BSY 26 // BSY +#define PIN_SEL 27 // SEL +#endif + +#ifdef CONNECT_TYPE_AIBOM +// +// RaSCSI Adapter 縺ゅ>縺シ繧迚 +// + +#define CONNECT_DESC "AIBOM PRODUCTS version" // 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 2 // SCSI豁」隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN FALSE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 4 // ACTIVE +#define PIN_ENB 17 // ENABLE +#define PIN_IND 27 // INITIATOR CTRL DIRECTION +#define PIN_TAD -1 // TARGET CTRL DIRECTION +#define PIN_DTD 18 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 6 // 繝繝シ繧ソ0 +#define PIN_DT1 12 // 繝繝シ繧ソ1 +#define PIN_DT2 13 // 繝繝シ繧ソ2 +#define PIN_DT3 16 // 繝繝シ繧ソ3 +#define PIN_DT4 19 // 繝繝シ繧ソ4 +#define PIN_DT5 20 // 繝繝シ繧ソ5 +#define PIN_DT6 26 // 繝繝シ繧ソ6 +#define PIN_DT7 21 // 繝繝シ繧ソ7 +#define PIN_DP 5 // 繝代Μ繝繧」 +#define PIN_ATN 22 // ATN +#define PIN_RST 25 // RST +#define PIN_ACK 10 // ACK +#define PIN_REQ 7 // REQ +#define PIN_MSG 9 // MSG +#define PIN_CD 11 // CD +#define PIN_IO 23 // IO +#define PIN_BSY 24 // BSY +#define PIN_SEL 8 // SEL +#endif + +#ifdef CONNECT_TYPE_GAMERNIUM +// +// RaSCSI Adapter GAMERnium.com迚 +// + +#define CONNECT_DESC "GAMERnium.com version"// 襍キ蜍墓凾繝。繝繧サ繝シ繧ク + +// 菫。蜿キ蛻カ蠕。繝「繝シ繝蛾∈謚 +#define SIGNAL_CONTROL_MODE 0 // SCSI隲也炊莉墓ァ + +// 蛻カ蠕。菫。蜿キ蜃コ蜉幄ォ也炊 +#define ACT_ON TRUE // ACTIVE SIGNAL ON +#define ENB_ON TRUE // ENABLE SIGNAL ON +#define IND_IN FALSE // INITIATOR SIGNAL INPUT +#define TAD_IN FALSE // TARGET SIGNAL INPUT +#define DTD_IN TRUE // DATA SIGNAL INPUT + +// 蛻カ蠕。菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ(-1縺ョ蝣エ蜷医ッ蛻カ蠕。辟。縺) +#define PIN_ACT 14 // ACTIVE +#define PIN_ENB 6 // ENABLE +#define PIN_IND 7 // INITIATOR CTRL DIRECTION +#define PIN_TAD 8 // TARGET CTRL DIRECTION +#define PIN_DTD 5 // DATA DIRECTION + +// SCSI菫。蜿キ繝斐Φ繧「繧オ繧、繝ウ +#define PIN_DT0 21 // 繝繝シ繧ソ0 +#define PIN_DT1 26 // 繝繝シ繧ソ1 +#define PIN_DT2 20 // 繝繝シ繧ソ2 +#define PIN_DT3 19 // 繝繝シ繧ソ3 +#define PIN_DT4 16 // 繝繝シ繧ソ4 +#define PIN_DT5 13 // 繝繝シ繧ソ5 +#define PIN_DT6 12 // 繝繝シ繧ソ6 +#define PIN_DT7 11 // 繝繝シ繧ソ7 +#define PIN_DP 25 // 繝代Μ繝繧」 +#define PIN_ATN 10 // ATN +#define PIN_RST 22 // RST +#define PIN_ACK 24 // ACK +#define PIN_REQ 15 // REQ +#define PIN_MSG 17 // MSG +#define PIN_CD 18 // CD +#define PIN_IO 4 // IO +#define PIN_BSY 27 // BSY +#define PIN_SEL 23 // SEL +#endif + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(GPIO) +// +//--------------------------------------------------------------------------- +#define GPIO_OFFSET 0x200000 +#define PADS_OFFSET 0x100000 +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 +#define GPIO_PULLNONE 0 +#define GPIO_PULLDOWN 1 +#define GPIO_PULLUP 2 +#define GPIO_FSEL_0 0 +#define GPIO_FSEL_1 1 +#define GPIO_FSEL_2 2 +#define GPIO_FSEL_3 3 +#define GPIO_SET_0 7 +#define GPIO_CLR_0 10 +#define GPIO_LEV_0 13 +#define GPIO_EDS_0 16 +#define GPIO_REN_0 19 +#define GPIO_FEN_0 22 +#define GPIO_HEN_0 25 +#define GPIO_LEN_0 28 +#define GPIO_AREN_0 31 +#define GPIO_AFEN_0 34 +#define GPIO_PUD 37 +#define GPIO_CLK_0 38 +#define PAD_0_27 11 + +#define GPIO_INEDGE ((1 << PIN_BSY) | \ + (1 << PIN_SEL) | \ + (1 << PIN_ATN) | \ + (1 << PIN_ACK) | \ + (1 << PIN_RST)) + +#define GPIO_MCI ((1 << PIN_MSG) | \ + (1 << PIN_CD) | \ + (1 << PIN_IO)) + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(蛻カ蠕。菫。蜿キ) +// +//--------------------------------------------------------------------------- +#define ACT_OFF !ACT_ON +#define ENB_OFF !ENB_ON +#define TAD_OUT !TAD_IN +#define IND_OUT !IND_IN +#define DTD_OUT !DTD_IN + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(SCSI) +// +//--------------------------------------------------------------------------- +#define IN GPIO_INPUT +#define OUT GPIO_OUTPUT +#define ON TRUE +#define OFF FALSE + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險(繝峨Λ繧、繝) +// +//--------------------------------------------------------------------------- +#define DEVICE_NAME "rascsidrv" +#define DRIVER_PATH "/dev/" DEVICE_NAME +#define IOCTL_INIT 0x100 +#define IOCTL_MODE 0x101 +#define IOCTL_PADS 0x102 + +//--------------------------------------------------------------------------- +// +// 蜍穂ス懊Δ繝シ繝 +// +//--------------------------------------------------------------------------- +enum mode_e { + TARGET = 0, + INITIATOR = 1, + MONITOR = 2, +}; + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝宣未謨ー螳」險 +// +//--------------------------------------------------------------------------- +static int drv_init(void); +static void drv_exit(void); + +//--------------------------------------------------------------------------- +// +// 繧ィ繝ウ繝医Μ繝昴う繝ウ繝亥ョ」險 +// +//--------------------------------------------------------------------------- +int drv_open(struct inode *inode, struct file *file); +int drv_close(struct inode *inode, struct file *file); +long drv_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +ssize_t drv_read( + struct file *file, char __user *buf, size_t count, loff_t *fops); +ssize_t drv_write( + struct file *file, const char __user *buf, size_t count, loff_t *fops); +struct file_operations drv_fops = { + .open = drv_open, + .release = drv_close, + .unlocked_ioctl = drv_ioctl, + .read = drv_read, + .write = drv_write, +}; + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險(繝峨Λ繧、繝千匳骭イ) +// +//--------------------------------------------------------------------------- +static dev_t drv_dev; +static dev_t drv_devno; +static struct cdev drv_cdev; +static struct class *drv_class; + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險(GPIO蛻カ蠕。) +// +//--------------------------------------------------------------------------- +static DWORD baseaddr; // BASE繧「繝峨Ξ繧ケ +static volatile DWORD *gpio; // GPIO繝ャ繧ク繧ケ繧ソ +static volatile DWORD *level; // GPIO繝ャ繧ク繧ケ繧ソ(繝ャ繝吶Ν) +static volatile DWORD *pads; // PADS繝ャ繧ク繧ケ繧ソ + +#if SIGNAL_CONTROL_MODE == 0 +static DWORD gpfsel[4]; // FSEL繝舌ャ繧ッ繧「繝繝 +#endif + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險(SCSI蛻カ蠕。) +// +//--------------------------------------------------------------------------- +static enum mode_e actmode; // 蜍穂ス懊Δ繝シ繝 +static DWORD signals; // SCSI蜈ィ菫。蜿キ + +static BOOL tblParity[256]; +#if SIGNAL_CONTROL_MODE == 0 +static DWORD tblDatMsk[3][256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν +static DWORD tblDatSet[3][256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#else +static DWORD tblDatMsk[256]; // 繝繝シ繧ソ繝槭せ繧ッ逕ィ繝繝シ繝悶Ν +static DWORD tblDatSet[256]; // 繝繝シ繧ソ險ュ螳夂畑繝繝シ繝悶Ν +#endif + +//--------------------------------------------------------------------------- +// +// 繝ッ繝シ繧ッ繝繝シ繝悶Ν菴懈 +// +//--------------------------------------------------------------------------- +void MakeTable(void) +{ + const int pintbl[] = { + PIN_DT0, PIN_DT1, PIN_DT2, PIN_DT3, PIN_DT4, + PIN_DT5, PIN_DT6, PIN_DT7, PIN_DP + }; + + int i; + int j; + DWORD bits; + DWORD parity; +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; +#else + DWORD gpclr; + DWORD gpset; +#endif + + // 繝代Μ繝繧」繝繝シ繝悶Ν菴懈 + for (i = 0; i < 0x100; i++) { + bits = (DWORD)i; + parity = 0; + for (j = 0; j < 8; j++) { + parity ^= bits & 1; + bits >>= 1; + } + parity = ~parity; + tblParity[i] = parity & 1; + } + +#if SIGNAL_CONTROL_MODE == 0 + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0xff, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + + // 繝薙ャ繝域、懈渊 + for (j = 0; j < 9; j++) { + // 繧、繝ウ繝繝繧ッ繧ケ縺ィ繧キ繝輔ヨ驥剰ィ育ョ + index = pintbl[j] / 10; + shift = (pintbl[j] % 10) * 3; + + // 繝槭せ繧ッ繝繝シ繧ソ + tblDatMsk[index][i] &= ~(0x7 << shift); + + // 險ュ螳壹ョ繝シ繧ソ + if (bits & 1) { + tblDatSet[index][i] |= (1 << shift); + } + + bits >>= 1; + } + } +#else + // 繝槭せ繧ッ縺ィ險ュ螳壹ョ繝シ繧ソ逕滓 + memset(tblDatMsk, 0x00, sizeof(tblDatMsk)); + memset(tblDatSet, 0x00, sizeof(tblDatSet)); + for (i = 0; i < 0x100; i++) { + // 讀懈渊逕ィ繝薙ャ繝亥 + bits = (DWORD)i; + + // 繝代Μ繝繧」蜿門セ + if (tblParity[i]) { + bits |= (1 << 8); + } + +#if SIGNAL_CONTROL_MODE == 1 + // 雋隲也炊縺ッ蜿崎サ「 + bits = ~bits; +#endif + + // GPIO繝ャ繧ク繧ケ繧ソ諠蝣ア縺ョ菴懈 + gpclr = 0; + gpset = 0; + for (j = 0; j < 9; j++) { + if (bits & 1) { + gpset |= (1 << pintbl[j]); + } else { + gpclr |= (1 << pintbl[j]); + } + bits >>= 1; + } + + tblDatMsk[i] = gpclr; + tblDatSet[i] = gpset; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝仙晄悄蛹 +// +//--------------------------------------------------------------------------- +static int drv_init(void) +{ + printk(KERN_INFO "RaSCSI GPIO Driver Loaded(%s)\n", CONNECT_DESC); + + // 繝繝舌う繧ケ逡ェ蜿キ蜿門セ + if (alloc_chrdev_region( + &drv_dev, + 0, + 1, + DEVICE_NAME) < 0) { + printk(KERN_DEBUG "Failed to allocate region\n"); + goto init_error; + } + + // 繧ッ繝ゥ繧ケ逋サ骭イ + if ((drv_class = class_create( + THIS_MODULE, + DEVICE_NAME)) == NULL) { + printk(KERN_DEBUG "Failed to create class\n"); + goto init_error; + } + + // 繝繝舌う繧ケ蛻晄悄蛹 + cdev_init(&drv_cdev, &drv_fops); + drv_cdev.owner = THIS_MODULE; + if (cdev_add(&drv_cdev, drv_dev, 1) < 0) { + printk(KERN_ALERT "Failed to add device\n"); + goto init_error; + } + + // 繝繝舌う繧ケ菴懈 + drv_devno = MKDEV(MAJOR(drv_dev), MINOR(drv_dev)); + if (device_create( + drv_class, + NULL, + drv_devno, + NULL, + DEVICE_NAME) == NULL) { + printk(KERN_DEBUG "Failed to create device\n"); + goto init_error; + } + + // 繝ッ繝シ繧ッ繝繝シ繝悶Ν逕滓 + MakeTable(); + + // 繝ッ繝シ繧ッ繧ッ繝ェ繧「 + baseaddr = ~0; + gpio = NULL; + level = NULL; + pads = NULL; + + return 0; + +init_error: + drv_exit(); + return -1; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝占ァ」謾セ +// +//--------------------------------------------------------------------------- +static void drv_exit(void) +{ + // 繧ッ繝ゥ繧ケ逋サ骭イ隗」髯、 + if (drv_class) { + device_destroy(drv_class, drv_devno); + class_destroy(drv_class); + drv_class = NULL; + } + + // 繝繝舌う繧ケ逋サ骭イ隗」髯、 + if (drv_dev){ + unregister_chrdev_region(drv_dev, 1); + drv_dev = 0; + } + + printk(KERN_INFO "RaSCSI GPIO Driver Unloaded\n"); +} + +//--------------------------------------------------------------------------- +// +// 繧ェ繝シ繝励Φ +// +//--------------------------------------------------------------------------- +int drv_open(struct inode *inode, struct file *file) +{ + // 蜍穂ス懊Δ繝シ繝牙晄悄蛹 + actmode = TARGET; + + return 0; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ュ繝シ繧コ +// +//--------------------------------------------------------------------------- +int drv_close(struct inode *inode, struct file *file) +{ + // 繧「繝ウ繝槭ャ繝 + if (gpio) { + iounmap(gpio); + gpio = NULL; + } + + if (pads) { + iounmap(pads); + pads = NULL; + } + + // 繝吶シ繧ケ繧「繝峨Ξ繧ケ繧ッ繝ェ繧「 + baseaddr = ~0; + + return 0; +} + +//--------------------------------------------------------------------------- +// +// 繝峨Λ繧、繝 IOCTL +// +//--------------------------------------------------------------------------- +long drv_ioctl( + struct file *file, unsigned int cmd, unsigned long arg) +{ + DWORD data; + DWORD drive; + + switch (cmd) { + case IOCTL_INIT: + // 蛻晄悄蛹悶ッ繧ェ繝シ繝励Φ蠕後↓1蝗樣剞繧 + if (baseaddr != ~0) { + break; + } + + // 繝吶シ繧ケ繧「繝峨Ξ繧ケ + baseaddr = arg; + + // GPIO繝ャ繧ク繧ケ繧ソ繧偵槭ャ繝 + gpio = (DWORD *)ioremap_nocache(baseaddr + GPIO_OFFSET, 164); + level = &gpio[GPIO_LEV_0]; + + // PADS繝ャ繧ク繧ケ繧ソ繧偵槭ャ繝 + pads = (DWORD *)ioremap_nocache(baseaddr + PADS_OFFSET, 56); + break; + + case IOCTL_MODE: + // 蜍穂ス懊Δ繝シ繝牙、画峩 + actmode = (enum mode_e)arg; + break; + + case IOCTL_PADS: + // DriveStrength螟画峩 + if (!pads) { + return -1; + } + + data = pads[PAD_0_27]; + drive = arg; + pads[PAD_0_27] = (0xFFFFFFF8 & data) | drive | 0x5a000000; + break; + + default: + break; + } + + return 0; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ菫。蜿キ蜿悶j霎シ縺ソ +// +//--------------------------------------------------------------------------- +static inline DWORD Aquire(void) +{ + signals = *level; + +#if SIGNAL_CONTROL_MODE < 2 + // 雋隲也炊縺ェ繧牙渚霆「縺吶k(蜀驛ィ蜃ヲ逅縺ッ豁」隲也炊縺ォ邨ア荳) + signals = ~signals; +#endif + + return signals; +} + +//--------------------------------------------------------------------------- +// +// 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 +// +// GPIO髢「菫ゅョ繝ャ繧ク繧ケ繧ソ縺ッ繧ウ繧「繧ッ繝ュ繝繧ッ縺400縺ョ譎ゅ↓險域クャ縺励◆騾溷コヲ繧貞盾閠縺ォ縺励◆縲 +// 繝ェ繝シ繝:48ns +// 繝ゥ繧、繝: 8ns +// +//--------------------------------------------------------------------------- +static inline void SleepNsec(DWORD nsec) +{ + DWORD count; + + count = (nsec + 8 - 1) / 8; + while (count--) { + gpio[GPIO_PUD] = 0; + } +} + +//--------------------------------------------------------------------------- +// +// 繧キ繧ー繝翫Ν險ュ螳 +// +//--------------------------------------------------------------------------- +static inline void SetSignal(int pin, BOOL ast) +{ +#if SIGNAL_CONTROL_MODE == 0 + int index; + int shift; + DWORD data; + + index = pin / 10; + shift = (pin % 10) * 3; + data = gpfsel[index]; + data &= ~(0x7 << shift); + if (ast) { + data |= (1 << shift); + } + gpio[GPIO_FSEL_0 + index] = data; + gpfsel[index] = data; +#elif SIGNAL_CONTROL_MODE == 1 + if (ast) { + gpio[GPIO_CLR_0] = 0x1 << pin; + } else { + gpio[GPIO_SET_0] = 0x1 << pin; + } +#elif SIGNAL_CONTROL_MODE == 2 + if (ast) { + gpio[GPIO_SET_0] = 0x1 << pin; + } else { + gpio[GPIO_CLR_0] = 0x1 << pin; + } +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ蜿門セ +// +//--------------------------------------------------------------------------- +static inline BYTE GetDAT(void) +{ + DWORD data; + + data = Aquire(); + data = + ((data >> (PIN_DT0 - 0)) & (1 << 0)) | + ((data >> (PIN_DT1 - 1)) & (1 << 1)) | + ((data >> (PIN_DT2 - 2)) & (1 << 2)) | + ((data >> (PIN_DT3 - 3)) & (1 << 3)) | + ((data >> (PIN_DT4 - 4)) & (1 << 4)) | + ((data >> (PIN_DT5 - 5)) & (1 << 5)) | + ((data >> (PIN_DT6 - 6)) & (1 << 6)) | + ((data >> (PIN_DT7 - 7)) & (1 << 7)); + + return (BYTE)data; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ險ュ螳 +// +//--------------------------------------------------------------------------- +static inline void SetDAT(BYTE dat) +{ + // 繝昴シ繝医∈譖ク縺崎セシ縺ソ +#if SIGNAL_CONTROL_MODE == 0 + gpfsel[0] &= tblDatMsk[0][dat]; + gpfsel[0] |= tblDatSet[0][dat]; + gpio[GPIO_FSEL_0] = gpfsel[0]; + + gpfsel[1] &= tblDatMsk[1][dat]; + gpfsel[1] |= tblDatSet[1][dat]; + gpio[GPIO_FSEL_1] = gpfsel[1]; + + gpfsel[2] &= tblDatMsk[2][dat]; + gpfsel[2] |= tblDatSet[2][dat]; + gpio[GPIO_FSEL_2] = gpfsel[2]; +#else + gpio[GPIO_CLR_0] = tblDatMsk[dat]; + gpio[GPIO_SET_0] = tblDatSet[dat]; +#endif +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繝シ繝 +// +//--------------------------------------------------------------------------- +ssize_t drv_read( + struct file *file, char __user *buf, size_t count, loff_t *fops) +{ + ssize_t i; + BYTE data; + DWORD loop; + DWORD phase; + +#if SIGNAL_CONTROL_MODE == 0 + // FSEL莠句燕蜿門セ + gpfsel[0] = gpio[GPIO_FSEL_0]; + gpfsel[1] = gpio[GPIO_FSEL_1]; + gpfsel[2] = gpio[GPIO_FSEL_2]; +#endif + + // 蜑イ繧願セシ縺ソ遖∵ュ「 + local_irq_disable(); + local_fiq_disable(); + + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, TRUE); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // 繝繝シ繧ソ蜿門セ + data = GetDAT(); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, FALSE); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 繝繝シ繧ソ霑泌唆 + if (copy_to_user(buf, (unsigned char *)&data, 1)) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + Aquire(); + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ蜿門セ + data = GetDAT(); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, TRUE); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = 30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, FALSE); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ霑泌唆 + if (copy_to_user(buf, (unsigned char *)&data, 1)) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + } + + // 蜑イ繧願セシ縺ソ遖∵ュ「隗」髯、 + local_fiq_enable(); + local_irq_enable(); + + return i; +} + +//--------------------------------------------------------------------------- +// +// 繝ゥ繧、繝 +// +//--------------------------------------------------------------------------- +ssize_t drv_write( + struct file *file, const char __user *buf, size_t count, loff_t *fops) +{ + size_t i; + BYTE data; + DWORD loop; + DWORD phase; + + // 蜑イ繧願セシ縺ソ遖∵ュ「 + local_irq_disable(); + local_fiq_disable(); + +#if SIGNAL_CONTROL_MODE == 0 + // FSEL莠句燕蜿門セ + gpfsel[0] = gpio[GPIO_FSEL_0]; + gpfsel[1] = gpio[GPIO_FSEL_1]; + gpfsel[2] = gpio[GPIO_FSEL_2]; +#endif + + if (actmode == TARGET) { + for (i = 0; i < count; i++) { + // 繝繝シ繧ソ蜿悶j霎シ縺ソ + if (copy_from_user((unsigned char *)&data, buf, 1)) { + break; + } + + // 繝繝シ繧ソ險ュ螳 + SetDAT(data); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // ACK繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // REQ繧「繧オ繝シ繝 + SetSignal(PIN_REQ, TRUE); + + // ACK繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + + // REQ繝阪ご繝シ繝 + SetSignal(PIN_REQ, FALSE); + + // ACK繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & (1 << PIN_RST))) { + break; + } + + // 谺。繝繝シ繧ソ + buf++; + }; + + // ACK繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_ACK)) && + !(signals & (1 << PIN_RST)) && loop > 0); + } else { + // 繝輔ぉ繝シ繧コ蜿門セ + Aquire(); + phase = signals & GPIO_MCI; + + for (i = 0; i < count; i++) { + // 繝繝シ繧ソ蜿悶j霎シ縺ソ + if (copy_from_user((unsigned char *)&data, buf, 1)) { + break; + } + + // REQ繧「繧オ繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while (!(signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // REQ繧「繧オ繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 繝繝シ繧ソ險ュ螳 + SetDAT(data); + + // 菫。蜿キ邱壹′螳牙ョ壹☆繧九∪縺ァ繧ヲ繧ァ繧、繝 + SleepNsec(150); + + // ACK繧「繧オ繝シ繝 + SetSignal(PIN_ACK, TRUE); + + // REQ繝阪ご繝シ繝亥セ縺。 + loop = (DWORD)30000000; + do { + Aquire(); + loop--; + } while ((signals & (1 << PIN_REQ)) && + ((signals & GPIO_MCI) == phase) && loop > 0); + + // ACK繝阪ご繝シ繝 + SetSignal(PIN_ACK, FALSE); + + // REQ繝阪ご繝シ繝亥セ縺。縺ァ繧ソ繧、繝繧「繧ヲ繝 + if (loop == 0 || (signals & GPIO_MCI) != phase) { + break; + } + + // 谺。繝繝シ繧ソ縺ク + buf++; + } + } + + // 蜑イ繧願セシ縺ソ遖∵ュ「隗」髯、 + local_fiq_enable(); + local_irq_enable(); + + return i; +} + +module_init(drv_init); +module_exit(drv_exit); + +MODULE_DESCRIPTION("RASCSI GPIO Driver"); +MODULE_VERSION("1.0"); +MODULE_AUTHOR("GIMONS"); +MODULE_LICENSE("GPL"); diff --git a/src/raspberrypi/log.h b/src/raspberrypi/log.h new file mode 100644 index 00000000..4448418f --- /dev/null +++ b/src/raspberrypi/log.h @@ -0,0 +1,31 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 繝ュ繧ー ] +// +//--------------------------------------------------------------------------- + +#if !defined(log_h) +#define log_h + +//=========================================================================== +// +// 繝ュ繧ー +// +//=========================================================================== +class Log +{ +public: + enum loglevel { + Detail, // 隧ウ邏ー繝ャ繝吶Ν + Normal, // 騾壼クク繝ャ繝吶Ν + Warning, // 隴ヲ蜻翫Ξ繝吶Ν + Debug // 繝繝舌ャ繧ー繝ャ繝吶Ν + }; +}; + +#endif // log_h diff --git a/src/raspberrypi/os.h b/src/raspberrypi/os.h new file mode 100644 index 00000000..d2d043e9 --- /dev/null +++ b/src/raspberrypi/os.h @@ -0,0 +1,145 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// Imported NetBSD support and some optimisation patch by Rin Okuyama. +// +// [ OS蝗コ譛 ] +// +//--------------------------------------------------------------------------- + +#if !defined(os_h) +#define os_h + +//--------------------------------------------------------------------------- +// +// #define +// +//--------------------------------------------------------------------------- +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +//--------------------------------------------------------------------------- +// +// #include +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) +#include +#include +#elif defined(__NetBSD__) +#include +#include +#include +#include +#include +#include +#else +#error unsupported platform +#endif + +//--------------------------------------------------------------------------- +// +// 蝓コ譛ャ繝槭け繝ュ +// +//--------------------------------------------------------------------------- +#undef FASTCALL +#define FASTCALL + +#undef CDECL +#define CDECL + +#undef INLINE +#define INLINE + +#if !defined(ASSERT) +#if !defined(NDEBUG) +#define ASSERT(cond) assert(cond) +#else +#define ASSERT(cond) ((void)0) +#endif // NDEBUG +#endif // ASSERT + +#if !defined(ASSERT_DIAG) +#if !defined(NDEBUG) +#define ASSERT_DIAG() AssertDiag() +#else +#define ASSERT_DIAG() ((void)0) +#endif // NDEBUG +#endif // ASSERT_DIAG + +//--------------------------------------------------------------------------- +// +// 蝓コ譛ャ蝙句ョ夂セゥ +// +//--------------------------------------------------------------------------- +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; +typedef char TCHAR; +typedef char *LPTSTR; +typedef const char *LPCTSTR; +typedef const char *LPCSTR; + +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +#if !defined(_T) +#define _T(x) x +#endif + +#define _MAX_PATH 260 +#define _MAX_DRIVE 3 +#define _MAX_DIR 256 +#define _MAX_FNAME 256 +#define _MAX_EXT 256 + +#define off64_t off_t + +#define xstrcasecmp strcasecmp +#define xstrncasecmp strncasecmp + +#endif // os_h diff --git a/src/raspberrypi/rascsi.cpp b/src/raspberrypi/rascsi.cpp new file mode 100644 index 00000000..a697f101 --- /dev/null +++ b/src/raspberrypi/rascsi.cpp @@ -0,0 +1,758 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 繝。繧、繝ウ ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "fileio.h" +#include "filepath.h" +#include "disk.h" +#include "gpiobus.h" + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險 +// +//--------------------------------------------------------------------------- +enum { + CtrlMax = 8, // 譛螟ァSCSI繧ウ繝ウ繝医Ο繝シ繝ゥ謨ー +}; + +SASIDEV *ctrl[CtrlMax]; // 繧ウ繝ウ繝医Ο繝シ繝ゥ +Disk *disk[CtrlMax]; // 繝繧」繧ケ繧ッ +Filepath image[CtrlMax]; // 繧、繝。繝シ繧ク繝輔ぃ繧、繝ォ繝代せ +GPIOBUS bus; // 繝舌せ +BUS::phase_t phase; // 繝輔ぉ繝シ繧コ +int actid; // 繧「繧ッ繝繧」繝悶↑繧ウ繝ウ繝医Ο繝シ繝ゥID +volatile BOOL bRun; // 螳溯。御クュ繝輔Λ繧ー + +BOOL bServer; // 繧オ繝シ繝舌シ繝「繝シ繝峨ヵ繝ゥ繧ー +int monfd; // 繝「繝九ち繝シ逕ィ繧ス繧ア繝繝FD +pthread_t monthread; // 繝「繝九ち繝シ繧ケ繝ャ繝繝 +static void *MonThread(void *param); + +//--------------------------------------------------------------------------- +// +// 繧キ繧ー繝翫Ν蜃ヲ逅 +// +//--------------------------------------------------------------------------- +void KillHandler(int sig) +{ + // 蛛懈ュ「謖遉コ + bRun = FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝舌リ繝シ蜃コ蜉 +// +//--------------------------------------------------------------------------- +BOOL Banner(int argc, char* argv[]) +{ + printf("SCSI Target Emulator RaSCSI(*^..^*) "); + printf("version %01d.%01d%01d\n", + (int)((VERSION >> 8) & 0xf), + (int)((VERSION >> 4) & 0xf), + (int)((VERSION ) & 0xf)); + printf("Powered by XM6 TypeG Technology / "); + printf("Copyright (C) 2016-2018 GIMONS\n"); + printf("Connect type : %s\n", CONNECT_DESC); + + if (argc > 1 && strcmp(argv[1], "-h") == 0) { + printf("\n"); + printf("Usage: %s [-ID{0|1|2|3|4|5|6|7} FILE] ...\n\n", argv[0]); + printf(" IDn is SCSI identification number.\n"); + printf(" FILE is disk image file.\n\n"); + printf(" Detected images type based on file extension.\n"); + printf(" hdf : SASI HD image(XM6 SASI HD image)\n"); + printf(" hds : SCSI HD image(XM6 SCSI HD image)\n"); + printf(" hdn : SCSI HD image(NEC GENUINE)\n"); + printf(" hdi : SCSI HD image(Anex86 HD image)\n"); + printf(" nhd : SCSI HD image(T98Next HD image)\n"); + printf(" hda : SCSI HD image(APPLE GENUINE)\n"); + printf(" mos : SCSI MO image(XM6 SCSI MO image)\n"); + printf(" iso : SCSI CD image(ISO 9660 image)\n"); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + int i; + struct sockaddr_in server; + + // 繝「繝九ち繝シ逕ィ繧ス繧ア繝繝育函謌 + monfd = socket(PF_INET, SOCK_STREAM, 0); + memset(&server, 0, sizeof(server)); + server.sin_family = PF_INET; + server.sin_port = htons(6868); + server.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(monfd, (struct sockaddr *)&server, + sizeof(struct sockaddr_in)) < 0) { + if (errno != EADDRINUSE) { + return FALSE; + } + bServer = FALSE; + return TRUE; + } else { + bServer = TRUE; + } + + // 蜑イ繧願セシ縺ソ繝上Φ繝峨Λ險ュ螳 + if (signal(SIGINT, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGHUP, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGTERM, KillHandler) == SIG_ERR) { + return FALSE; + } + + // GPIO蛻晄悄蛹 + if (!bus.Init()) { + return FALSE; + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ蛻晄悄蛹 + for (i = 0; i < CtrlMax; i++) { + ctrl[i] = NULL; + } + + // 繝繧」繧ケ繧ッ蛻晄悄蛹 + for (i = 0; i < CtrlMax; i++) { + disk[i] = NULL; + } + + // 繧、繝。繝シ繧ク繝代せ蛻晄悄蛹 + for (i = 0; i < CtrlMax; i++) { + image[i].Clear(); + } + + // 繧「繧ッ繝繧」繝蜂D蛻晄悄蛹 + actid = -1; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void Cleanup() +{ + int i; + + // 繝繧」繧ケ繧ッ蜑企勁 + for (i = 0; i < CtrlMax; i++) { + if (disk[i]) { + delete disk[i]; + disk[i] = NULL; + } + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ蜑企勁 + for (i = 0; i < CtrlMax; i++) { + if (ctrl[i]) { + delete ctrl[i]; + ctrl[i] = NULL; + } + } + + // 繝舌せ繧偵け繝ェ繝シ繝ウ繧「繝繝 + bus.Cleanup(); + + // 繝「繝九ち繝シ逕ィ繧ス繧ア繝繝医け繝ュ繝シ繧コ + if (monfd >= 0) { + close(monfd); + } +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void Reset() +{ + int i; + + // 繧「繧ッ繝繧」繝蜂D蛻晄悄蛹 + actid = -1; + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繝ェ繧サ繝繝 + for (i = 0; i < CtrlMax; i++) { + if (ctrl[i]) { + ctrl[i]->Reset(); + } + } + + // 繝舌せ菫。蜿キ邱壹r繝ェ繧サ繝繝 + bus.Reset(); +} + +//--------------------------------------------------------------------------- +// +// 繝繝舌う繧ケ荳隕ァ陦ィ遉コ +// +//--------------------------------------------------------------------------- +void ListDevice(FILE *fp) +{ + int i; + Filepath filepath; + BOOL find; + char type[5]; + + find = FALSE; + type[4] = 0; + for (i = 0; i < 8; i++) { + if (disk[i] == NULL) { + continue; + } + + // 繝倥ャ繝繝シ蜃コ蜉 + if (!find) { + fprintf(fp, "\n"); + fprintf(fp, "---+------+---------------------------------------\n"); + fprintf(fp, "ID | TYPE | DEVICE STATUS\n"); + fprintf(fp, "---+------+---------------------------------------\n"); + find = TRUE; + } + + // ID,繧ソ繧、繝怜コ蜉 + type[0] = (char)(disk[i]->GetID() >> 24); + type[1] = (char)(disk[i]->GetID() >> 16); + type[2] = (char)(disk[i]->GetID() >> 8); + type[3] = (char)(disk[i]->GetID()); + fprintf(fp, " %d | %s | ", i, type); + + // 繝槭え繝ウ繝育憾諷句コ蜉 + if (disk[i]->GetID() == MAKEID('S', 'C', 'B', 'R')) { + fprintf(fp, "%s", "RaSCSI BRIDGE"); + } else { + disk[i]->GetPath(filepath); + fprintf(fp, "%s", + (disk[i]->IsRemovable() && !disk[i]->IsReady()) ? + "NO MEDIA" : filepath.GetPath()); + } + + // 繝ゥ繧、繝医励Ο繝繧ッ繝育憾諷句コ蜉 + if (disk[i]->IsRemovable() && disk[i]->IsReady() && disk[i]->IsWriteP()) { + fprintf(fp, "(WRITEPROTECT)"); + } + + // 谺。縺ョ陦後∈ + fprintf(fp, "\n"); + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ縺檎┌縺蝣エ蜷 + if (!find) { + fprintf(fp, "No device is installed.\n"); + return; + } + + fprintf(fp, "---+------+---------------------------------------\n"); +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝牙ヲ逅 +// +//--------------------------------------------------------------------------- +BOOL ProcessCmd(FILE *fp, int id, int cmd, int type, char *file) +{ + int len; + char *ext; + Filepath filepath; + + // ID繝√ぉ繝繧ッ + if (id < 0 || id > 7) { + fprintf(fp, "Error : Invalid ID\n"); + return FALSE; + } + + // 謗・邯壹さ繝槭Φ繝 + if (cmd == 0) { // ATTACH + // 繧ウ繝ウ繝医Ο繝シ繝ゥ繧定ァ」謾セ + if (ctrl[id]) { + ctrl[id]->SetUnit(0, NULL); + delete ctrl[id]; + ctrl[id] = NULL; + } + + // 繝繧」繧ケ繧ッ繧定ァ」謾セ + if (disk[id]) { + delete disk[id]; + disk[id] = NULL; + } + + // SASI縺ィSCSI繧定ヲ句縺代k + if (type == 0) { + // 繝代せ繝√ぉ繝繧ッ + if (!file) { + return FALSE; + } + + // 譛菴5譁蟄 + len = strlen(file); + if (len < 5) { + return FALSE; + } + + // 諡。蠑オ蟄舌メ繧ァ繝繧ッ + if (file[len - 4] != '.') { + return FALSE; + } + + // 諡。蠑オ蟄舌′SASI繧ソ繧、繝励〒辟。縺代l縺ーSCSI縺ォ蟾ョ縺玲崛縺 + ext = &file[len - 3]; + if (xstrcasecmp(ext, "hdf") != 0) { + type = 1; + } + } + + // 繧ソ繧、繝怜挨縺ョ繧、繝ウ繧ケ繧ソ繝ウ繧ケ繧堤函謌 + switch (type) { + case 0: // HDF + disk[id] = new SASIHD(); + break; + case 1: // HDS/HDN/HDI/NHD/HDA + if (xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0) { + disk[id] = new SCSIHD_NEC(); + } else if (xstrcasecmp(ext, "hda") == 0) { + disk[id] = new SCSIHD_APPLE(); + } else { + disk[id] = new SCSIHD(); + } + break; + case 2: // MO + disk[id] = new SCSIMO(); + break; + case 3: // CD + disk[id] = new SCSICD(); + break; + case 4: // BRIDGE + disk[id] = new SCSIBR(); + break; + default: + fprintf(fp, "Error : Invalid device type\n"); + return FALSE; + } + + // 繧ソ繧、繝励↓蜷医o縺帙※繧ウ繝ウ繝医Ο繝シ繝ゥ繧剃ス懊k + if (type == 0) { + ctrl[id] = new SASIDEV(); + } else { + ctrl[id] = new SCSIDEV(); + } + + // 繝峨Λ繧、繝悶ッ繝輔ぃ繧、繝ォ縺ョ遒コ隱阪r陦後≧ + if (type <= 1 || (type <= 3 && xstrcasecmp(file, "-") != 0)) { + // 繝代せ繧定ィュ螳 + filepath.SetPath(file); + + // 繧ェ繝シ繝励Φ + if (!disk[id]->Open(filepath)) { + fprintf(fp, "Error : File open error [%s]\n", file); + delete disk[id]; + disk[id] = NULL; + delete ctrl[id]; + ctrl[id] = NULL; + return FALSE; + } + } + + // 繝ゥ繧、繝医せ繝ォ繝シ縺ォ險ュ螳 + disk[id]->SetCacheWB(FALSE); + + // 譁ー縺溘↑繝繧」繧ケ繧ッ繧呈磁邯 + ctrl[id]->Connect(id, &bus); + ctrl[id]->SetUnit(0, disk[id]); + return TRUE; + } + + // 譛牙柑縺ェ繧ウ繝槭Φ繝峨° + if (cmd > 4) { + fprintf(fp, "Error : Invalid command\n"); + return FALSE; + } + + // 繧ウ繝ウ繝医Ο繝シ繝ゥ縺悟ュ伜惠縺吶k縺 + if (ctrl[id] == NULL) { + fprintf(fp, "Error : No such device\n"); + return FALSE; + } + + // 繝繧」繧ケ繧ッ縺悟ュ伜惠縺吶k縺 + if (disk[id] == NULL) { + fprintf(fp, "Error : No such device\n"); + return FALSE; + } + + // 蛻譁ュ繧ウ繝槭Φ繝 + if (cmd == 1) { // DETACH + ctrl[id]->SetUnit(0, NULL); + delete disk[id]; + disk[id] = NULL; + delete ctrl[id]; + ctrl[id] = NULL; + return TRUE; + } + + // MO縺気D縺ョ蝣エ蜷医□縺第怏蜉ケ + if (disk[id]->GetID() != MAKEID('S', 'C', 'M', 'O') && + disk[id]->GetID() != MAKEID('S', 'C', 'C', 'D')) { + fprintf(fp, "Error : Operation denied(Deveice isn't MO or CD)\n"); + return FALSE; + } + + switch (cmd) { + case 2: // INSERT + // 繝代せ繧定ィュ螳 + filepath.SetPath(file); + + // 繧ェ繝シ繝励Φ + if (!disk[id]->Open(filepath)) { + fprintf(fp, "Error : File open error [%s]\n", file); + return FALSE; + } + break; + + case 3: // EJECT + disk[id]->Eject(TRUE); + break; + + case 4: // PROTECT + if (disk[id]->GetID() != MAKEID('S', 'C', 'M', 'O')) { + fprintf(fp, "Error : Operation denied(Deveice isn't MO)\n"); + return FALSE; + } + disk[id]->WriteP(!disk[id]->IsWriteP()); + break; + default: + ASSERT(FALSE); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 蠑墓焚蜃ヲ逅 +// +//--------------------------------------------------------------------------- +BOOL ParseArgument(int argc, char* argv[]) +{ + int i; + int id; + int type; + char *argID; + char *argPath; + int len; + char *ext; + + // ID縺ィ繝代せ謖螳壹′縺ェ縺代l縺ー蜃ヲ逅繧剃クュ譁ュ + if (argc < 3) { + return TRUE; + } + + // 蠑墓焚縺ョ隗」隱ュ髢句ァ + i = 1; + argc--; + + // ID縺ィ繝代せ繧貞叙蠕 + while (argc >= 2) { + argc -= 2; + argID = argv[i++]; + argPath = argv[i++]; + + // -ID or -id縺ョ蠖「蠑上r繝√ぉ繝繧ッ + if (strlen(argID) != 4 || xstrncasecmp(argID, "-id", 3) != 0) { + fprintf(stderr, + "Error : Invalid argument(-IDn) [%s]\n", argID); + return FALSE; + } + + // ID逡ェ蜿キ繧偵メ繧ァ繝繧ッ(0-7) + if (argID[3] < '0' || argID[3] > '7') { + fprintf(stderr, + "Error : Invalid argument(-IDn n=0-7) [%c]\n", argID[3]); + return FALSE; + } + + // ID遒コ螳 + id = argID[3] - '0'; + + // 縺吶〒縺ォ繧「繧ッ繝繧」繝悶↑繝繝舌う繧ケ縺後≠繧九↑繧峨せ繧ュ繝繝 + if (disk[id]) { + continue; + } + + // 繝繝舌う繧ケ繧ソ繧、繝励r蛻晄悄蛹 + type = -1; + + // 繧、繝シ繧オ繝阪ャ繝医→繝帙せ繝医ヶ繝ェ繝繧ク縺ョ繝√ぉ繝繧ッ + if (xstrcasecmp(argPath, "bridge") == 0) { + type = 4; + } else { + // 繝代せ縺ョ髟キ縺輔r繝√ぉ繝繧ッ + len = strlen(argPath); + if (len < 5) { + fprintf(stderr, + "Error : Invalid argument(File path is short) [%s]\n", + argPath); + return FALSE; + } + + // 諡。蠑オ蟄舌r謖√▲縺ヲ縺繧九°シ + if (argPath[len - 4] != '.') { + fprintf(stderr, + "Error : Invalid argument(No extension) [%s]\n", argPath); + return FALSE; + } + + // 繧ソ繧、繝励r豎コ繧√k + ext = &argPath[len - 3]; + if (xstrcasecmp(ext, "hdf") == 0 || + xstrcasecmp(ext, "hds") == 0 || + xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || xstrcasecmp(ext, "nhd") == 0 || + xstrcasecmp(ext, "hda") == 0) { + // HD(SASI/SCSI) + type = 0; + } else if (strcasecmp(ext, "mos") == 0) { + // MO + type = 2; + } else if (strcasecmp(ext, "iso") == 0) { + // CD + type = 3; + } else { + // 繧ソ繧、繝励′蛻、蛻・縺ァ縺阪↑縺 + fprintf(stderr, + "Error : Invalid argument(file type) [%s]\n", ext); + return FALSE; + } + } + + // 繧ウ繝槭Φ繝牙ョ溯。 + if (!ProcessCmd(stderr, id, 0, type, argPath)) { + return FALSE; + } + } + + // 繝繝舌う繧ケ繝ェ繧ケ繝郁。ィ遉コ + ListDevice(stdout); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝「繝九ち繝シ繧ケ繝ャ繝繝 +// +//--------------------------------------------------------------------------- +static void *MonThread(void *param) +{ + struct sockaddr_in client; + socklen_t len; + int fd; + FILE *fp; + BYTE buf[BUFSIZ]; + int id; + int cmd; + int type; + char *file; + BOOL list; + + // 逶」隕匁コ門y + listen(monfd, 1); + + while (1) { + // 謗・邯壼セ縺。 + memset(&client, 0, sizeof(client)); + len = sizeof(client); + fd = accept(monfd, (struct sockaddr*)&client, &len); + if (fd < 0) { + break; + } + + // 繧ウ繝槭Φ繝牙叙蠕 + fp = fdopen(fd, "r+"); + fgets((char *)buf, BUFSIZ, fp); + buf[strlen((const char*)buf) - 1] = 0; + + // 繝繝舌う繧ケ繝ェ繧ケ繝郁。ィ遉コ縺ェ縺ョ縺句宛蠕。繧ウ繝槭Φ繝峨°繧貞愛譁ュ + if (strncasecmp((char*)buf, "list", 4) == 0) { + list = TRUE; + } else { + list = FALSE; + id = (int)(buf[0] - '0'); + cmd = (int)(buf[2] - '0'); + type = (int)(buf[4] - '0'); + file = (char*)&buf[6]; + } + + // 繝舌せ繝輔Μ繝シ縺ョ繧ソ繧、繝溘Φ繧ー縺セ縺ァ蠕縺、 + while (phase != BUS::busfree) { + usleep(500 * 1000); + } + + if (list) { + // 繝ェ繧ケ繝郁。ィ遉コ + ListDevice(fp); + } else { + // 繧ウ繝槭Φ繝牙ョ溯。 + ProcessCmd(fp, id, cmd, type, file); + } + + // 謗・邯夊ァ」謾セ + fclose(fp); + close(fd); + } + + return NULL; +} + +//--------------------------------------------------------------------------- +// +// 荳サ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + int i; + DWORD dwBusBak; + DWORD dwBusIn; + struct sched_param schparam; + + // 繝舌リ繝シ蜃コ蜉 + if (!Banner(argc, argv)) { + exit(0); + } + + // 蛻晄悄蛹 + if (!Init()) { + fprintf(stderr, "Error : Initializing\n"); + + // 諱舌i縺俊oot縺ァ縺ッ辟。縺シ + exit(EPERM); + } + + // 譌「縺ォ襍キ蜍輔@縺ヲ縺繧具シ + if (!bServer) { + fprintf(stderr, "Error : Already running RaSCSI\n"); + exit(0); + } + + // 讒狗ッ + if (!ParseArgument(argc, argv)) { + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 蠑墓焚繧ィ繝ゥ繝シ縺ァ邨ゆコ + exit(EINVAL); + } + + // 繝「繝九ち繝シ繧ケ繝ャ繝繝臥函謌 + bRun = TRUE; + pthread_create(&monthread, NULL, MonThread, NULL); + + // 繝ェ繧サ繝繝 + Reset(); + + // 繝。繧、繝ウ繝ォ繝シ繝玲コ門y + phase = BUS::busfree; + dwBusBak = bus.Aquire(); + + // 繝。繧、繝ウ繝ォ繝シ繝 + while(bRun) { + // 繝舌せ縺ョ蜈・蜉帑ソ。蜿キ螟牙喧讀懷コ + dwBusIn = bus.Aquire(); + + // 蜈・蜉帑ソ。蜿キ螟牙喧讀懷コ + if ((dwBusIn & GPIO_INEDGE) == (dwBusBak & GPIO_INEDGE)) { + usleep(0); + continue; + } + + // 繝舌せ縺ョ蜈・蜉帑ソ。蜿キ繧剃ソ晏ュ + dwBusBak = dwBusIn; + + // 縺昴b縺昴b繧サ繝ャ繧ッ繧キ繝ァ繝ウ菫。蜿キ縺檎┌縺代l縺ー辟。隕 + if (!bus.GetSEL() || bus.GetBSY()) { + continue; + } + + // 蜈ィ繧ウ繝ウ繝医Ο繝シ繝ゥ縺ォ騾夂衍 + for (i = 0; i < CtrlMax; i++) { + if (!ctrl[i]) { + continue; + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺ォ遘サ陦後@縺溘ち繝シ繧イ繝繝医r謗「縺 + if (ctrl[i]->Process() == BUS::selection) { + // 繧ソ繝シ繧イ繝繝医ョID繧貞叙蠕 + actid = i; + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + phase = BUS::selection; + break; + } + } + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ縺碁幕蟋九&繧後※縺縺ェ縺代l縺ー繝舌せ縺ョ逶」隕悶∈謌サ繧 + if (phase != BUS::selection) { + continue; + } + + // 繧ソ繝シ繧イ繝繝郁オー陦碁幕蟋 + + // 繧ケ繧ア繧ク繝・繝シ繝ェ繝ウ繧ー繝昴Μ繧キ繝シ險ュ螳(譛蜆ェ蜈) + schparam.sched_priority = sched_get_priority_max(SCHED_FIFO); + sched_setscheduler(0, SCHED_FIFO, &schparam); + + // 繝舌せ繝輔Μ繝シ縺ォ縺ェ繧九∪縺ァ繝ォ繝シ繝 + while (bRun) { + // 繧ソ繝シ繧イ繝繝磯ァ蜍 + phase = ctrl[actid]->Process(); + + // 繝舌せ繝輔Μ繝シ縺ォ縺ェ縺」縺溘i邨ゆコ + if (phase == BUS::busfree) { + break; + } + } + + // 繝舌せ繝輔Μ繝シ縺ァ繧サ繝繧キ繝ァ繝ウ邨ゆコ + actid = -1; + phase = BUS::busfree; + bus.Reset(); + dwBusBak = bus.Aquire(); + + // 繧ケ繧ア繧ク繝・繝シ繝ェ繝ウ繧ー繝昴Μ繧キ繝シ險ュ螳(繝弱シ繝槭Ν) + schparam.sched_priority = 0; + sched_setscheduler(0, SCHED_OTHER, &schparam); + } + + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 邨ゆコ + exit(0); +} diff --git a/src/raspberrypi/rasctl.cpp b/src/raspberrypi/rasctl.cpp new file mode 100644 index 00000000..3759ce8d --- /dev/null +++ b/src/raspberrypi/rasctl.cpp @@ -0,0 +1,247 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ 蛻カ蠕。繧ウ繝槭Φ繝蛾∽ソ。 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝蛾∽ソ。 +// +//--------------------------------------------------------------------------- +BOOL SendCommand(char *buf) +{ + int fd; + struct sockaddr_in server; + FILE *fp; + + // 繧ウ繝槭Φ繝臥畑繧ス繧ア繝繝育函謌 + fd = socket(PF_INET, SOCK_STREAM, 0); + memset(&server, 0, sizeof(server)); + server.sin_family = PF_INET; + server.sin_port = htons(6868); + server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + // 謗・邯 + if (connect(fd, (struct sockaddr *)&server, + sizeof(struct sockaddr_in)) < 0) { + fprintf(stderr, "Error : Can't connect to rascsi process\n"); + return FALSE; + } + + // 騾∽ソ。 + fp = fdopen(fd, "r+"); + setvbuf(fp, NULL, _IONBF, 0); + fprintf(fp, buf); + + // 繝。繝繧サ繝シ繧ク蜿嶺ソ。 + while (1) { + if (fgets((char *)buf, BUFSIZ, fp) == NULL) { + break; + } + printf("%s", buf); + } + + // 繧ス繧ア繝繝医r髢峨§繧 + fclose(fp); + close(fd); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 荳サ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + int opt; + int id; + int cmd; + int type; + char *file; + BOOL list; + int len; + char *ext; + char buf[BUFSIZ]; + + id = -1; + cmd = -1; + type = -1; + file = NULL; + list = FALSE; + + // 繝倥Ν繝励ョ陦ィ遉コ + if (argc < 2) { + fprintf(stderr, "SCSI Target Emulator RaSCSI Controller\n"); + fprintf(stderr, + "Usage: %s -i ID [-c CMD] [-t TYPE] [-f FILE]\n", + argv[0]); + fprintf(stderr, " where ID := {0|1|2|3|4|5|6|7}\n"); + fprintf(stderr, " CMD := {attach|detatch|insert|eject|protect}\n"); + fprintf(stderr, " TYPE := {hd|mo|cd|bridge}\n"); + fprintf(stderr, " FILE := image file path\n"); + fprintf(stderr, " CMD is 'attach' or 'insert' and FILE parameter is required.\n"); + fprintf(stderr, "Usage: %s -l\n", argv[0]); + fprintf(stderr, " Print device list.\n"); + exit(0); + } + + // 蠑墓焚隗」譫 + opterr = 0; + while ((opt = getopt(argc, argv, "i:c:t:f:l")) != -1) { + switch (opt) { + case 'i': + id = optarg[0] - '0'; + break; + + case 'c': + switch (optarg[0]) { + case 'a': // ATTACH + case 'A': + cmd = 0; + break; + case 'd': // DETACH + case 'D': + cmd = 1; + break; + case 'i': // INSERT + case 'I': + cmd = 2; + break; + case 'e': // EJECT + case 'E': + cmd = 3; + break; + case 'p': // PROTECT + case 'P': + cmd = 4; + break; + } + break; + + case 't': + switch (optarg[0]) { + case 's': // HD(SASI) + case 'S': + case 'h': // HD(SCSI) + case 'H': + type = 0; + break; + case 'm': // MO + case 'M': + type = 2; + break; + case 'c': // CD + case 'C': + type = 3; + break; + case 'b': // BRIDGE + case 'B': + type = 4; + break; + } + break; + + case 'f': + file = optarg; + break; + + case 'l': + list = TRUE; + break; + } + } + + // 繝ェ繧ケ繝郁。ィ遉コ縺ョ縺ソ + if (id < 0 && cmd < 0 && type < 0 && file == NULL && list) { + sprintf(buf, "list\n"); + SendCommand(buf); + exit(0); + } + + // ID繝√ぉ繝繧ッ + if (id < 0 || id > 7) { + fprintf(stderr, "Error : Invalid ID\n"); + exit(EINVAL); + } + + // 繧ウ繝槭Φ繝峨メ繧ァ繝繧ッ + if (cmd < 0) { + cmd = 0; // 繝繝輔か繝ォ繝医ッATTATCH縺ィ縺吶k + } + + // 繧ソ繧、繝励メ繧ァ繝繧ッ + if (cmd == 0 && type < 0) { + + // 諡。蠑オ蟄舌°繧峨ち繧、繝怜愛蛻・繧定ゥヲ縺ソ繧 + len = file ? strlen(file) : 0; + if (len > 4 && file[len - 4] == '.') { + ext = &file[len - 3]; + if (xstrcasecmp(ext, "hdf") == 0 || + xstrcasecmp(ext, "hds") == 0 || + xstrcasecmp(ext, "hdn") == 0 || + xstrcasecmp(ext, "hdi") == 0 || + xstrcasecmp(ext, "nhd") == 0 || + xstrcasecmp(ext, "hda") == 0) { + // HD(SASI/SCSI) + type = 0; + } else if (xstrcasecmp(ext, "mos") == 0) { + // MO + type = 2; + } else if (xstrcasecmp(ext, "iso") == 0) { + // CD + type = 3; + } + } + + if (type < 0) { + fprintf(stderr, "Error : Invalid type\n"); + exit(EINVAL); + } + } + + // 繝輔ぃ繧、繝ォ繝√ぉ繝繧ッ(繧ウ繝槭Φ繝峨ッATTACH縺ァ繧ソ繧、繝励ッHD) + if (cmd == 0 && type >= 0 && type <= 1) { + if (!file) { + fprintf(stderr, "Error : Invalid file path\n"); + exit(EINVAL); + } + } + + // 繝輔ぃ繧、繝ォ繝√ぉ繝繧ッ(繧ウ繝槭Φ繝峨ッINSERT) + if (cmd == 2) { + if (!file) { + fprintf(stderr, "Error : Invalid file path\n"); + exit(EINVAL); + } + } + + // 蠢隕√〒縺ェ縺дype縺ッ0縺ィ縺励※縺翫¥ + if (type < 0) { + type = 0; + } + + // 騾∽ソ。繧ウ繝槭Φ繝臥函謌 + sprintf(buf, "%d %d %d %s\n", id, cmd, type, file ? file : "-"); + if (!SendCommand(buf)) { + exit(ENOTCONN); + } + + // 繝ェ繧ケ繝郁。ィ遉コ + if (list) { + sprintf(buf, "list\n"); + SendCommand(buf); + } + + // 邨ゆコ + exit(0); +} diff --git a/src/raspberrypi/rasdump.cpp b/src/raspberrypi/rasdump.cpp new file mode 100644 index 00000000..c1ceef53 --- /dev/null +++ b/src/raspberrypi/rasdump.cpp @@ -0,0 +1,1006 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// [ HDD繝繝ウ繝励Θ繝シ繝繧」繝ェ繝繧」(繧、繝九す繝シ繧ィ繧ソ繝「繝シ繝) ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "fileio.h" +#include "filepath.h" +#include "gpiobus.h" + +//--------------------------------------------------------------------------- +// +// 螳壽焚螳」險 +// +//--------------------------------------------------------------------------- +#define BUFSIZE 1024 * 64 // 64KB縺舌i縺縺九↑縺 + +//--------------------------------------------------------------------------- +// +// 螟画焚螳」險 +// +//--------------------------------------------------------------------------- +GPIOBUS bus; // 繝舌せ +int targetid; // 繧ソ繝シ繧イ繝繝医ョ繝舌う繧ケID +int boardid; // 繝懊シ繝迂D(閾ェ霄ォ縺ョID) +Filepath hdsfile; // HDS繝輔ぃ繧、繝ォ +BOOL restore; // 繝ェ繧ケ繝医い繝輔Λ繧ー +BYTE buffer[BUFSIZE]; // 繝ッ繝シ繧ッ繝舌ャ繝輔ぃ +int result; // 邨先棡繧ウ繝シ繝 + +//--------------------------------------------------------------------------- +// +// 髢「謨ー螳」險 +// +//--------------------------------------------------------------------------- +void Cleanup(); + +//--------------------------------------------------------------------------- +// +// 繧キ繧ー繝翫Ν蜃ヲ逅 +// +//--------------------------------------------------------------------------- +void KillHandler(int sig) +{ + // 蛛懈ュ「謖遉コ + Cleanup(); + exit(0); +} + +//--------------------------------------------------------------------------- +// +// 繝舌リ繝シ蜃コ蜉 +// +//--------------------------------------------------------------------------- +BOOL Banner(int argc, char* argv[]) +{ + printf("RaSCSI hard disk dump utility "); + printf("version %01d.%01d%01d\n", + (int)((VERSION >> 8) & 0xf), + (int)((VERSION >> 4) & 0xf), + (int)((VERSION ) & 0xf)); + + if (argc < 2 || strcmp(argv[1], "-h") == 0) { + printf("Usage: %s -i ID [-b BID] -f FILE [-r]\n", argv[0]); + printf(" ID is target device SCSI ID {0|1|2|3|4|5|6|7}.\n"); + printf(" BID is rascsi board SCSI ID {0|1|2|3|4|5|6|7}. Default is 7.\n"); + printf(" FILE is HDS file path.\n"); + printf(" -r is restore operation.\n"); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 蛻晄悄蛹 +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + // 蜑イ繧願セシ縺ソ繝上Φ繝峨Λ險ュ螳 + if (signal(SIGINT, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGHUP, KillHandler) == SIG_ERR) { + return FALSE; + } + if (signal(SIGTERM, KillHandler) == SIG_ERR) { + return FALSE; + } + + // GPIO蛻晄悄蛹 + if (!bus.Init(BUS::INITIATOR)) { + return FALSE; + } + + // 繝ッ繝シ繧ッ蛻晄悄蛹 + targetid = -1; + boardid = 7; + restore = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ェ繝シ繝ウ繧「繝繝 +// +//--------------------------------------------------------------------------- +void Cleanup() +{ + // 繝舌せ繧偵け繝ェ繝シ繝ウ繧「繝繝 + bus.Cleanup(); +} + +//--------------------------------------------------------------------------- +// +// 繝ェ繧サ繝繝 +// +//--------------------------------------------------------------------------- +void Reset() +{ + // 繝舌せ菫。蜿キ邱壹r繝ェ繧サ繝繝 + bus.Reset(); +} + +//--------------------------------------------------------------------------- +// +// 蠑墓焚蜃ヲ逅 +// +//--------------------------------------------------------------------------- +BOOL ParseArgument(int argc, char* argv[]) +{ + int opt; + char *file; + + // 蛻晄悄蛹 + file = NULL; + + // 蠑墓焚隗」譫 + opterr = 0; + while ((opt = getopt(argc, argv, "i:b:f:r")) != -1) { + switch (opt) { + case 'i': + targetid = optarg[0] - '0'; + break; + + case 'b': + boardid = optarg[0] - '0'; + break; + + case 'f': + file = optarg; + break; + + case 'r': + restore = TRUE; + break; + } + } + + // TARGET ID繝√ぉ繝繧ッ + if (targetid < 0 || targetid > 7) { + fprintf(stderr, + "Error : Invalid target id range\n"); + return FALSE; + } + + // BOARD ID繝√ぉ繝繧ッ + if (boardid < 0 || boardid > 7) { + fprintf(stderr, + "Error : Invalid board id range\n"); + return FALSE; + } + + // TARGET縺ィBOARD縺ョID驥崎、繝√ぉ繝繧ッ + if (targetid == boardid) { + fprintf(stderr, + "Error : Invalid target or board id\n"); + return FALSE; + } + + // 繝輔ぃ繧、繝ォ繝√ぉ繝繧ッ + if (!file) { + fprintf(stderr, + "Error : Invalid file path\n"); + return FALSE; + } + + hdsfile.SetPath(file); + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ蠕縺。 +// +//--------------------------------------------------------------------------- +BOOL WaitPhase(BUS::phase_t phase) +{ + int count; + + // REQ繧貞セ縺、(6遘) + count = 30000; + do { + usleep(200); + bus.Aquire(); + if (bus.GetREQ()) { + break; + } + } while (count--); + + // 繝輔ぉ繝シ繧コ縺御ク閾エ縺吶l縺ーOK + bus.Aquire(); + if (bus.GetPhase() == phase) { + return TRUE; + } + + // 繝輔ぉ繝シ繧コ縺御ク閾エ縺吶l縺ーOK(繝ェ繝医Λ繧、) + usleep(1000 * 1000); + bus.Aquire(); + if (bus.GetPhase() == phase) { + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +void BusFree() +{ + bus.Reset(); +} + +//--------------------------------------------------------------------------- +// +// 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +BOOL Selection(int id) +{ + BYTE data; + int count; + + // ID險ュ螳壹→SEL繧「繧オ繝シ繝 + data = 0; + data |= (1 << boardid); + data |= (1 << id); + bus.SetDAT(data); + bus.SetSEL(TRUE); + + // BSY繧貞セ縺、 + count = 10000; + do { + usleep(20); + bus.Aquire(); + if (bus.GetBSY()) { + break; + } + } while (count--); + + // SEL繝阪ご繝シ繝 + bus.SetSEL(FALSE); + + // 繧ソ繝シ繧イ繝繝医′繝薙ず繝シ迥カ諷九↑繧画仙粥 + return bus.GetBSY(); +} + +//--------------------------------------------------------------------------- +// +// 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +BOOL Command(BYTE *buf, int length) +{ + int count; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::command)) { + return FALSE; + } + + // 繧ウ繝槭Φ繝蛾∽ソ。 + count = bus.SendHandShake(buf, length); + + // 騾∽ソ。邨先棡縺御セ晞シ謨ー縺ィ蜷後§縺ェ繧画仙粥 + if (count == length) { + return TRUE; + } + + // 騾∽ソ。繧ィ繝ゥ繝シ + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧、繝ウ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int DataIn(BYTE *buf, int length) +{ + int count; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::datain)) { + return -1; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + return bus.ReceiveHandShake(buf, length); +} + +//--------------------------------------------------------------------------- +// +// 繝繝シ繧ソ繧「繧ヲ繝医ヵ繧ァ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int DataOut(BYTE *buf, int length) +{ + int count; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::dataout)) { + return -1; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + return bus.SendHandShake(buf, length); +} + +//--------------------------------------------------------------------------- +// +// 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int Status() +{ + BYTE buf[256]; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::status)) { + return -2; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + if (bus.ReceiveHandShake(buf, 1) == 1) { + return (int)buf[0]; + } + + // 蜿嶺ソ。繧ィ繝ゥ繝シ + return -1; +} + +//--------------------------------------------------------------------------- +// +// 繝。繝繧サ繝シ繧ク繧、繝ウ繝輔ぉ繝シ繧コ螳溯。 +// +//--------------------------------------------------------------------------- +int MessageIn() +{ + BYTE buf[256]; + + // 繝輔ぉ繝シ繧コ蠕縺。 + if (!WaitPhase(BUS::msgin)) { + return -2; + } + + // 繝繝シ繧ソ蜿嶺ソ。 + if (bus.ReceiveHandShake(buf, 1) == 1) { + return (int)buf[0]; + } + + // 蜿嶺ソ。繧ィ繝ゥ繝シ + return -1; +} + +//--------------------------------------------------------------------------- +// +// TEST UNIT READY螳溯。 +// +//--------------------------------------------------------------------------- +int TestUnitReady(int id) +{ + BYTE cmd[256]; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x00; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + return result; +} + +//--------------------------------------------------------------------------- +// +// REQUEST SENSE螳溯。 +// +//--------------------------------------------------------------------------- +int RequestSense(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x03; + cmd[4] = 0xff; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 256); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// MODE SENSE螳溯。 +// +//--------------------------------------------------------------------------- +int ModeSense(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x1a; + cmd[2] = 0x3f; + cmd[4] = 0xff; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 256); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// INQUIRY螳溯。 +// +//--------------------------------------------------------------------------- +int Inquiry(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 6); + cmd[0] = 0x12; + cmd[4] = 0xff; + if (!Command(cmd, 6)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 255); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// READ CAPACITY螳溯。 +// +//--------------------------------------------------------------------------- +int ReadCapacity(int id, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 10); + cmd[0] = 0x25; + if (!Command(cmd, 10)) { + result = -2; + goto exit; + } + + // DATAIN + memset(buf, 0x00, sizeof(buf)); + count = DataIn(buf, 8); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// READ10螳溯。 +// +//--------------------------------------------------------------------------- +int Read10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 10); + cmd[0] = 0x28; + cmd[2] = (BYTE)(bstart >> 24); + cmd[3] = (BYTE)(bstart >> 16); + cmd[4] = (BYTE)(bstart >> 8); + cmd[5] = (BYTE)bstart; + cmd[7] = (BYTE)(blength >> 8); + cmd[8] = (BYTE)blength; + if (!Command(cmd, 10)) { + result = -2; + goto exit; + } + + // DATAIN + count = DataIn(buf, length); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// WRITE10螳溯。 +// +//--------------------------------------------------------------------------- +int Write10(int id, DWORD bstart, DWORD blength, DWORD length, BYTE *buf) +{ + BYTE cmd[256]; + int count; + + // 邨先棡繧ウ繝シ繝牙晄悄蛹 + result = 0; + + // SELECTION + if (!Selection(id)) { + result = -1; + goto exit; + } + + // COMMAND + memset(cmd, 0x00, 10); + cmd[0] = 0x2a; + cmd[2] = (BYTE)(bstart >> 24); + cmd[3] = (BYTE)(bstart >> 16); + cmd[4] = (BYTE)(bstart >> 8); + cmd[5] = (BYTE)bstart; + cmd[7] = (BYTE)(blength >> 8); + cmd[8] = (BYTE)blength; + if (!Command(cmd, 10)) { + result = -2; + goto exit; + } + + // DATAOUT + count = DataOut(buf, length); + if (count <= 0) { + result = -3; + goto exit; + } + + // STATUS + if (Status() < 0) { + result = -4; + goto exit; + } + + // MESSAGE IN + if (MessageIn() < 0) { + result = -5; + goto exit; + } + +exit: + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // 謌仙粥縺ァ縺ゅl縺ー霆「騾∵焚繧定ソ斐☆ + if (result == 0) { + return count; + } + + return result; +} + +//--------------------------------------------------------------------------- +// +// 荳サ蜃ヲ逅 +// +//--------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + int i; + int count; + char str[32]; + DWORD bsiz; + DWORD bnum; + DWORD duni; + DWORD dsiz; + DWORD dnum; + DWORD rest; + Fileio fio; + Fileio::OpenMode omode; + off64_t size; + + // 繝舌リ繝シ蜃コ蜉 + if (!Banner(argc, argv)) { + exit(0); + } + + // 蛻晄悄蛹 + if (!Init()) { + fprintf(stderr, "Error : Initializing\n"); + + // 諱舌i縺俊oot縺ァ縺ッ辟。縺シ + exit(EPERM); + } + + // 讒狗ッ + if (!ParseArgument(argc, argv)) { + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 蠑墓焚繧ィ繝ゥ繝シ縺ァ邨ゆコ + exit(EINVAL); + } + + // 繝ェ繧サ繝繝 + Reset(); + + // 繝輔ぃ繧、繝ォ繧ェ繝シ繝励Φ + if (restore) { + omode = Fileio::ReadOnly; + } else { + omode = Fileio::WriteOnly; + } + if (!fio.Open(hdsfile.GetPath(), omode)) { + fprintf(stderr, "Error : Can't open hds file\n"); + + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + exit(EPERM); + } + + // 繝舌せ繝輔Μ繝シ + BusFree(); + + // RESET繧キ繧ー繝翫Ν逋コ陦 + bus.SetRST(TRUE); + usleep(1000); + bus.SetRST(FALSE); + + // 繝繝ウ繝鈴幕蟋 + printf("TARGET ID : %d\n", targetid); + printf("BORAD ID : %d\n", boardid); + + // TEST UNIT READY + count = TestUnitReady(targetid); + if (count < 0) { + fprintf(stderr, "TEST UNIT READY ERROR %d\n", count); + goto cleanup_exit; + } + + // REQUEST SENSE(for CHECK CONDITION) + count = RequestSense(targetid, buffer); + if (count < 0) { + fprintf(stderr, "REQUEST SENSE ERROR %d\n", count); + goto cleanup_exit; + } + + // INQUIRY + count = Inquiry(targetid, buffer); + if (count < 0) { + fprintf(stderr, "INQUIRY ERROR %d\n", count); + goto cleanup_exit; + } + + // INQUIRY縺ョ諠蝣ア繧定。ィ遉コ + memset(str, 0x00, sizeof(str)); + memcpy(str, &buffer[8], 8); + printf("Vendor : %s\n", str); + memset(str, 0x00, sizeof(str)); + memcpy(str, &buffer[16], 16); + printf("Product : %s\n", str); + memset(str, 0x00, sizeof(str)); + memcpy(str, &buffer[32], 4); + printf("Revison : %s\n", str); + + // 螳ケ驥丞叙蠕 + count = ReadCapacity(targetid, buffer); + if (count < 0) { + fprintf(stderr, "READ CAPACITY ERROR %d\n", count); + goto cleanup_exit; + } + + // 繝悶Ο繝繧ッ繧オ繧、繧コ縺ィ繝悶Ο繝繧ッ謨ー縺ョ陦ィ遉コ + bsiz = + (buffer[4] << 24) | (buffer[5] << 16) | + (buffer[6] << 8) | buffer[7]; + bnum = + (buffer[0] << 24) | (buffer[1] << 16) | + (buffer[2] << 8) | buffer[3]; + bnum++; + printf("Number of blocks : %d Blocks\n", bnum); + printf("Block length : %d Bytes\n", bsiz); + printf("Unit Capacity : %d MBytes %d Bytes\n", + bsiz * bnum / 1024 / 1024, + bsiz * bnum); + + // 繝ェ繧ケ繝医い繝輔ぃ繧、繝ォ繧オ繧、繧コ縺ョ蜿門セ + if (restore) { + size = fio.GetFileSize(); + printf("Restore file size : %d bytes", (int)size); + if (size != (off64_t)(bsiz * bnum)) { + printf("(WARNING : File size isn't equal to disk size)"); + } + printf("\n"); + } + + // 繝舌ャ繝輔ぃ繧オ繧、繧コ豈弱↓繝繝ウ繝励☆繧 + duni = BUFSIZE; + duni /= bsiz; + dsiz = BUFSIZE; + dnum = bnum * bsiz; + dnum /= BUFSIZE; + + if (restore) { + printf("Restore progress : "); + } else { + printf("Dump progress : "); + } + + for (i = 0; i < dnum; i++) { + if (i > 0) { + printf("\033[21D"); + printf("\033[0K"); + } + printf("%3d\%(%7d/%7d)", (i + 1) * 100 / dnum, i * duni, bnum); + fflush(stdout); + + if (restore) { + if (fio.Read(buffer, dsiz)) { + if (Write10(targetid, i * duni, duni, dsiz, buffer) >= 0) { + continue; + } + } + } else { + if (Read10(targetid, i * duni, duni, dsiz, buffer) >= 0) { + if (fio.Write(buffer, dsiz)) { + continue; + } + } + } + + printf("\n"); + printf("Error occured and aborted... %d\n", result); + goto cleanup_exit; + } + + // 螳ケ驥丈ク翫ョ遶ッ謨ー蜃ヲ逅 + dnum = bnum % duni; + dsiz = dnum * bsiz; + if (dnum > 0) { + if (restore) { + if (fio.Read(buffer, dsiz)) { + Write10(targetid, i * duni, duni, dsiz, buffer); + } + } else { + if (Read10(targetid, i * duni, dnum, dsiz, buffer) >= 0) { + fio.Write(buffer, dsiz); + } + } + } + + // 螳御コ繝。繝繧サ繝シ繧ク + printf("\033[21D"); + printf("\033[0K"); + printf("%3d\%(%7d/%7d)\n", 100, bnum, bnum); + +cleanup_exit: + // 繝輔ぃ繧、繝ォ繧ッ繝ュ繝シ繧コ + fio.Close(); + + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + Cleanup(); + + // 邨ゆコ + exit(0); +} diff --git a/src/raspberrypi/scsi.cpp b/src/raspberrypi/scsi.cpp new file mode 100644 index 00000000..b74e5aa6 --- /dev/null +++ b/src/raspberrypi/scsi.cpp @@ -0,0 +1,58 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// [ SCSI蜈ア騾 ] +// +//--------------------------------------------------------------------------- + +#include "os.h" +#include "xm6.h" +#include "scsi.h" + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ蜿門セ +// +//--------------------------------------------------------------------------- +BUS::phase_t FASTCALL BUS::GetPhase() +{ + DWORD mci; + + ASSERT(this); + + // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + if (GetSEL()) { + return selection; + } + + // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + if (!GetBSY()) { + return busfree; + } + + // 繝舌せ縺ョ菫。蜿キ邱壹°繧峨ち繝シ繧イ繝繝医ョ繝輔ぉ繝シ繧コ繧貞叙蠕 + mci = GetMSG() ? 0x04 : 0x00; + mci |= GetCD() ? 0x02 : 0x00; + mci |= GetIO() ? 0x01 : 0x00; + return GetPhase(mci); +} + +//--------------------------------------------------------------------------- +// +// 繝輔ぉ繝シ繧コ繝繝シ繝悶Ν +// +//--------------------------------------------------------------------------- +const BUS::phase_t BUS::phase_table[8] = { + dataout, + datain, + command, + status, + reserved, + reserved, + msgout, + msgin +}; diff --git a/src/raspberrypi/scsi.h b/src/raspberrypi/scsi.h new file mode 100644 index 00000000..5bed1f73 --- /dev/null +++ b/src/raspberrypi/scsi.h @@ -0,0 +1,128 @@ +//--------------------------------------------------------------------------- +// +// X68000 EMULATOR "XM6" +// +// Copyright (C) 2001-2006 シーシゥシ(ytanaka@ipc-tokai.or.jp) +// Copyright (C) 2014-2018 GIMONS +// +// [ SCSI蜈ア騾 ] +// +//--------------------------------------------------------------------------- + +#if !defined(scsi_h) +#define scsi_h + +//=========================================================================== +// +// SASI/SCSI 繝舌せ +// +//=========================================================================== +class BUS +{ +public: + // 蜍穂ス懊Δ繝シ繝牙ョ夂セゥ + enum mode_e { + TARGET = 0, + INITIATOR = 1, + MONITOR = 2, + }; + + // 繝輔ぉ繝シ繧コ螳夂セゥ + enum phase_t { + busfree, // 繝舌せ繝輔Μ繝シ繝輔ぉ繝シ繧コ + arbitration, // 繧「繝シ繝薙ヨ繝ャ繝シ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + selection, // 繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + reselection, // 繝ェ繧サ繝ャ繧ッ繧キ繝ァ繝ウ繝輔ぉ繝シ繧コ + command, // 繧ウ繝槭Φ繝峨ヵ繧ァ繝シ繧コ + execute, // 螳溯。後ヵ繧ァ繝シ繧コ + datain, // 繝繝シ繧ソ繧、繝ウ + dataout, // 繝繝シ繧ソ繧「繧ヲ繝 + status, // 繧ケ繝繝シ繧ソ繧ケ繝輔ぉ繝シ繧コ + msgin, // 繝。繝繧サ繝シ繧ク繝輔ぉ繝シ繧コ + msgout, // 繝。繝繧サ繝シ繧ク繧「繧ヲ繝医ヵ繧ァ繝シ繧コ + reserved // 譛ェ菴ソ逕ィ/繝ェ繧カ繝シ繝 + }; + + // 蝓コ譛ャ繝輔ぃ繝ウ繧ッ繧キ繝ァ繝ウ + virtual BOOL FASTCALL Init(mode_e mode) = 0; + // 蛻晄悄蛹 + virtual void FASTCALL Reset() = 0; + // 繝ェ繧サ繝繝 + virtual void FASTCALL Cleanup() = 0; + // 繧ッ繝ェ繝シ繝ウ繧「繝繝 + phase_t FASTCALL GetPhase(); + // 繝輔ぉ繝シ繧コ蜿門セ + + static phase_t FASTCALL GetPhase(DWORD mci) + { + return phase_table[mci]; + } + // 繝輔ぉ繝シ繧コ蜿門セ + + virtual DWORD FASTCALL Aquire() = 0; + // 菫。蜿キ蜿悶j霎シ縺ソ + + virtual BOOL FASTCALL GetBSY() = 0; + // BSY繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetBSY(BOOL ast) = 0; + // BSY繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetSEL() = 0; + // SEL繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetSEL(BOOL ast) = 0; + // SEL繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetATN() = 0; + // ATN繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetATN(BOOL ast) = 0; + // ATN繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetACK() = 0; + // ACK繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetACK(BOOL ast) = 0; + // ACK繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetRST() = 0; + // RST繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetRST(BOOL ast) = 0; + // RST繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetMSG() = 0; + // MSG繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetMSG(BOOL ast) = 0; + // MSG繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetCD() = 0; + // CD繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetCD(BOOL ast) = 0; + // CD繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetIO() = 0; + // IO繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetIO(BOOL ast) = 0; + // IO繧キ繧ー繝翫Ν險ュ螳 + + virtual BOOL FASTCALL GetREQ() = 0; + // REQ繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetREQ(BOOL ast) = 0; + // REQ繧キ繧ー繝翫Ν險ュ螳 + + virtual BYTE FASTCALL GetDAT() = 0; + // 繝繝シ繧ソ繧キ繧ー繝翫Ν蜿門セ + virtual void FASTCALL SetDAT(BYTE dat) = 0; + // 繝繝シ繧ソ繧キ繧ー繝翫Ν險ュ螳 + + virtual int FASTCALL ReceiveHandShake(BYTE *buf, int count) = 0; + // 繝繝シ繧ソ蜿嶺ソ。繝上Φ繝峨す繧ァ繧、繧ッ + virtual int FASTCALL SendHandShake(BYTE *buf, int count) = 0; + // 繝繝シ繧ソ騾∽ソ。繝上Φ繝峨す繧ァ繧、繧ッ + + virtual void FASTCALL SleepNsec(DWORD nsec) = 0; + // 繝翫ヮ遘貞腰菴阪ョ繧ケ繝ェ繝シ繝 + +private: + static const phase_t phase_table[8]; + // 繝輔ぉ繝シ繧コ繝繝シ繝悶Ν +}; + +#endif // scsi_h diff --git a/src/raspberrypi/xm6.h b/src/raspberrypi/xm6.h new file mode 100644 index 00000000..cdd09a2c --- /dev/null +++ b/src/raspberrypi/xm6.h @@ -0,0 +1,49 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technology. +// Copyright (C) 2016-2018 GIMONS +// +// [ 蜈ア騾壼ョ夂セゥ ] +// +//--------------------------------------------------------------------------- + +#if !defined(xm6_h) +#define xm6_h + +//--------------------------------------------------------------------------- +// +// VERSION +// +//--------------------------------------------------------------------------- +#define VERSION 0x0134 + +//--------------------------------------------------------------------------- +// +// RaSCSI +// +//--------------------------------------------------------------------------- +#define RASCSI VERSION + +//--------------------------------------------------------------------------- +// +// ID繝槭け繝ュ +// +//--------------------------------------------------------------------------- +#define MAKEID(a, b, c, d) ((DWORD)((a<<24) | (b<<16) | (c<<8) | d)) + +//--------------------------------------------------------------------------- +// +// 繧ッ繝ゥ繧ケ螳」險 +// +//--------------------------------------------------------------------------- +class Fileio; + // 繝輔ぃ繧、繝ォ蜈・蜃コ蜉 +class Disk; + // SASI/SCSI繝繧」繧ケ繧ッ +class Filepath; + // 繝輔ぃ繧、繝ォ繝代せ + +#endif // xm6_h diff --git a/src/x68k/RASDRV/BRIDGE.C b/src/x68k/RASDRV/BRIDGE.C new file mode 100644 index 00000000..cf0f9918 --- /dev/null +++ b/src/x68k/RASDRV/BRIDGE.C @@ -0,0 +1,2414 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ ホストファイルシステム ブリッジドライバ ] +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include "bridge.h" + +//--------------------------------------------------------------------------- +// +// 変数宣言 +// +//--------------------------------------------------------------------------- +volatile BYTE *request; // リクエストヘッダアドレス +DWORD command; // コマンド番号 +DWORD unit; // ユニット番号 + +//=========================================================================== +// +/// ファイルシステム(SCSI連携) +// +//=========================================================================== +typedef struct +{ + char DeviceType; + char RMB; + char ANSI_Ver; + char RDF; + char AddLen; + char RESV0; + char RESV1; + char OptFunc; + char VendorID[8]; + char ProductID[16]; + char FirmRev[4]; +} INQUIRY_T; + +int scsiid; // SCSI ID + +//--------------------------------------------------------------------------- +// +// 初期化 +// +//--------------------------------------------------------------------------- +BOOL SCSI_Init(void) +{ + int i; + INQUIRY_T inq; + + // SCSI ID未定 + scsiid = -1; + + for (i = 0; i <= 7; i++) { + if (S_INQUIRY(sizeof(INQUIRY_T) , i, (struct INQUIRY*)&inq) < 0) { + continue; + } + + if (memcmp(&(inq.ProductID), "RASCSI BRIDGE", 13) != 0) { + continue; + } + + // SCSI ID確定 + scsiid = i; + return TRUE; + } + + return FALSE; +} + +//--------------------------------------------------------------------------- +// +// コマンド送信 +// +//--------------------------------------------------------------------------- +int SCSI_SendCmd(BYTE *buf, int len) +{ + int ret; + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + BYTE retbuf[4]; + + ret = FS_FATAL_MEDIAOFFLINE; + + cmdbuf[0] = 0x2a; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAOUT_P(len, buf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = 0; + cmdbuf[7] = 0; + cmdbuf[8] = 4; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAIN_P(4, retbuf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + ret = *(int*)retbuf; + return ret; +} + +//--------------------------------------------------------------------------- +// +// コマンド呼び出し +// +//--------------------------------------------------------------------------- +int SCSI_CalCmd(BYTE *buf, int len, BYTE *outbuf, int outlen) +{ + int ret; + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + BYTE retbuf[4]; + + ret = FS_FATAL_MEDIAOFFLINE; + + cmdbuf[0] = 0x2a; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAOUT_P(len, buf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = 0; + cmdbuf[7] = 0; + cmdbuf[8] = 4; + cmdbuf[9] = 0; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAIN_P(4, retbuf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + // エラーなら返却データの受信を止める + ret = *(int*)retbuf; + if (ret < 0) { + return ret; + } + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(outlen >> 16); + cmdbuf[7] = (BYTE)(outlen >> 8); + cmdbuf[8] = (BYTE)outlen; + cmdbuf[9] = 1; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return ret; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return ret; + } + + if (S_DATAIN_P(outlen, outbuf) != 0) { + return ret; + } + + if (S_STSIN(&sts) != 0) { + return ret; + } + + if (S_MSGIN(&msg) != 0) { + return ret; + } + + ret = *(int*)retbuf; + return ret; +} + +//--------------------------------------------------------------------------- +// +// オプションデータ取得 +// +//--------------------------------------------------------------------------- +BOOL SCSI_ReadOpt(BYTE *buf, int len) +{ + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + + cmdbuf[0] = 0x28; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 2; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return FALSE; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return FALSE; + } + + if (S_DATAIN_P(len, buf) != 0) { + return FALSE; + } + + if (S_STSIN(&sts) != 0) { + return FALSE; + } + + if (S_MSGIN(&msg) != 0) { + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- +// +// オプションデータ書き込み +// +//--------------------------------------------------------------------------- +BOOL SCSI_WriteOpt(BYTE *buf, int len) +{ + BYTE cmdbuf[10]; + BYTE sts; + BYTE msg; + + cmdbuf[0] = 0x2a; + cmdbuf[1] = 0; + cmdbuf[2] = 2; + cmdbuf[3] = command; + cmdbuf[4] = 0; + cmdbuf[5] = 0; + cmdbuf[6] = (BYTE)(len >> 16); + cmdbuf[7] = (BYTE)(len >> 8); + cmdbuf[8] = (BYTE)len; + cmdbuf[9] = 1; + + // セレクトがタイムアウトする時には再試行 + if (S_SELECT(scsiid) != 0) { + S_RESET(); + if (S_SELECT(scsiid) != 0) { + return FALSE; + } + } + + if (S_CMDOUT(10, cmdbuf) != 0) { + return FALSE; + } + + if (S_DATAOUT_P(len, buf) != 0) { + return FALSE; + } + + if (S_STSIN(&sts) != 0) { + return FALSE; + } + + if (S_MSGIN(&msg) != 0) { + return FALSE; + } + + return TRUE; +} + +//=========================================================================== +// +/// ファイルシステム +// +//=========================================================================== + +//--------------------------------------------------------------------------- +// +// $40 - デバイス起動 +// +//--------------------------------------------------------------------------- +DWORD FS_InitDevice(const argument_t* pArgument) +{ + return (DWORD)SCSI_SendCmd((BYTE*)pArgument, sizeof(argument_t)); +} + +//--------------------------------------------------------------------------- +// +// $41 - ディレクトリチェック +// +//--------------------------------------------------------------------------- +int FS_CheckDir(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $42 - ディレクトリ作成 +// +//--------------------------------------------------------------------------- +int FS_MakeDir(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $43 - ディレクトリ削除 +// +//--------------------------------------------------------------------------- +int FS_RemoveDir(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $44 - ファイル名変更 +// +//--------------------------------------------------------------------------- +int FS_Rename(const namests_t* pNamests, const namests_t* pNamestsNew) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], pNamestsNew, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $45 - ファイル削除 +// +//--------------------------------------------------------------------------- +int FS_Delete(const namests_t* pNamests) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $46 - ファイル属性取得/設定 +// +//--------------------------------------------------------------------------- +int FS_Attribute(const namests_t* pNamests, DWORD nHumanAttribute) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + dp = (DWORD*)&buf[i]; + *dp = nHumanAttribute; + i += sizeof(DWORD); + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $47 - ファイル検索 +// +//--------------------------------------------------------------------------- +int FS_Files(DWORD nKey, + const namests_t* pNamests, files_t* info) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], info, sizeof(files_t)); + i += sizeof(files_t); + + return SCSI_CalCmd(buf, i, (BYTE*)info, sizeof(files_t)); +} + +//--------------------------------------------------------------------------- +// +// $48 - ファイル次検索 +// +//--------------------------------------------------------------------------- +int FS_NFiles(DWORD nKey, files_t* info) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], info, sizeof(files_t)); + i += sizeof(files_t); + + return SCSI_CalCmd(buf, i, (BYTE*)info, sizeof(files_t)); +} + +//--------------------------------------------------------------------------- +// +// $49 - ファイル作成 +// +//--------------------------------------------------------------------------- +int FS_Create(DWORD nKey, + const namests_t* pNamests, fcb_t* pFcb, DWORD nAttribute, BOOL bForce) +{ + BYTE buf[256]; + DWORD *dp; + BOOL *bp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nAttribute; + i += sizeof(DWORD); + + bp = (BOOL*)&buf[i]; + *bp = bForce; + i += sizeof(BOOL); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4A - ファイルオープン +// +//--------------------------------------------------------------------------- +int FS_Open(DWORD nKey, + const namests_t* pNamests, fcb_t* pFcb) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pNamests, sizeof(namests_t)); + i += sizeof(namests_t); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4B - ファイルクローズ +// +//--------------------------------------------------------------------------- +int FS_Close(DWORD nKey, fcb_t* pFcb) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4C - ファイル読み込み +// +//--------------------------------------------------------------------------- +int FS_Read(DWORD nKey, fcb_t* pFcb, BYTE* pAddress, DWORD nSize) +{ + BYTE buf[256]; + DWORD *dp; + int i; + int nResult; + + i = 0; + dp = (DWORD*)buf; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nSize; + i += sizeof(DWORD); + + nResult = SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); + + if (nResult > 0) { + SCSI_ReadOpt(pAddress, nResult); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4D - ファイル書き込み +// +//--------------------------------------------------------------------------- +int FS_Write(DWORD nKey, fcb_t* pFcb, BYTE* pAddress, DWORD nSize) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nSize; + i += sizeof(DWORD); + + if (nSize != 0) { + if (!SCSI_WriteOpt(pAddress, nSize)) { + return FS_FATAL_MEDIAOFFLINE; + } + } + + return SCSI_SendCmd(buf, i); +} + +//--------------------------------------------------------------------------- +// +// $4E - ファイルシーク +// +//--------------------------------------------------------------------------- +int FS_Seek(DWORD nKey, fcb_t* pFcb, DWORD nMode, int nOffset) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nMode; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nOffset; + i += sizeof(int); + + return SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $4F - ファイル時刻取得/設定 +// +//--------------------------------------------------------------------------- +DWORD FS_TimeStamp(DWORD nKey, + fcb_t* pFcb, DWORD nHumanTime) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nKey; + i += sizeof(DWORD); + + memcpy(&buf[i], pFcb, sizeof(fcb_t)); + i += sizeof(fcb_t); + + dp = (DWORD*)&buf[i]; + *dp = nHumanTime; + i += sizeof(DWORD); + + return (DWORD)SCSI_CalCmd(buf, i, (BYTE*)pFcb, sizeof(fcb_t)); +} + +//--------------------------------------------------------------------------- +// +// $50 - 容量取得 +// +//--------------------------------------------------------------------------- +int FS_GetCapacity(capacity_t* cap) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + return SCSI_CalCmd(buf, i, (BYTE*)cap, sizeof(capacity_t)); +} + +//--------------------------------------------------------------------------- +// +// $51 - ドライブ状態検査/制御 +// +//--------------------------------------------------------------------------- +int FS_CtrlDrive(ctrldrive_t* pCtrlDrive) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + memcpy(&buf[i], pCtrlDrive, sizeof(ctrldrive_t)); + i += sizeof(ctrldrive_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pCtrlDrive, sizeof(ctrldrive_t)); +} + +//--------------------------------------------------------------------------- +// +// $52 - DPB取得 +// +//--------------------------------------------------------------------------- +int FS_GetDPB(dpb_t* pDpb) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + return SCSI_CalCmd(buf, i, (BYTE*)pDpb, sizeof(dpb_t)); +} + +//--------------------------------------------------------------------------- +// +// $53 - セクタ読み込み +// +//--------------------------------------------------------------------------- +int FS_DiskRead(BYTE* pBuffer, DWORD nSector, DWORD nSize) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nSector; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nSize; + i += sizeof(DWORD); + + return SCSI_CalCmd(buf, i, (BYTE*)pBuffer, 0x200); +} + +//--------------------------------------------------------------------------- +// +// $54 - セクタ書き込み +// +//--------------------------------------------------------------------------- +int FS_DiskWrite() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//--------------------------------------------------------------------------- +// +// $55 - IOCTRL +// +//--------------------------------------------------------------------------- +int FS_Ioctrl(DWORD nFunction, ioctrl_t* pIoctrl) +{ + BYTE buf[256]; + DWORD *dp; + int i; + + i = 0; + dp = (DWORD*)buf; + *dp = unit; + i += sizeof(DWORD); + + dp = (DWORD*)&buf[i]; + *dp = nFunction; + i += sizeof(DWORD); + + memcpy(&buf[i], pIoctrl, sizeof(ioctrl_t)); + i += sizeof(ioctrl_t); + + return SCSI_CalCmd(buf, i, (BYTE*)pIoctrl, sizeof(ioctrl_t)); +} + +//--------------------------------------------------------------------------- +// +// $56 - フラッシュ +// +//--------------------------------------------------------------------------- +int FS_Flush() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//--------------------------------------------------------------------------- +// +// $57 - メディア交換チェック +// +//--------------------------------------------------------------------------- +int FS_CheckMedia() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//--------------------------------------------------------------------------- +// +// $58 - 排他制御 +// +//--------------------------------------------------------------------------- +int FS_Lock() +{ + BYTE buf[256]; + DWORD *dp; + + dp = (DWORD*)buf; + *dp = unit; + + return SCSI_SendCmd(buf, 4); +} + +//=========================================================================== +// +// コマンドハンドラ +// +//=========================================================================== +#define GetReqByte(a) (request[a]) +#define SetReqByte(a,d) (request[a] = (d)) +#define GetReqWord(a) (*((WORD*)&request[a])) +#define SetReqWord(a,d) (*((WORD*)&request[a]) = (d)) +#define GetReqLong(a) (*((DWORD*)&request[a])) +#define SetReqLong(a,d) (*((DWORD*)&request[a]) = (d)) +#define GetReqAddr(a) ((BYTE*)((*((DWORD*)&request[a])) & 0x00ffffff)) + +//--------------------------------------------------------------------------- +// +// NAMESTS読み込み +// +//--------------------------------------------------------------------------- +void GetNameStsPath(BYTE *addr, namests_t* pNamests) +{ + DWORD i; + + ASSERT(this); + ASSERT(pNamests); + + // ワイルドカード情報 + pNamests->wildcard = *addr; + + // ドライブ番号 + pNamests->drive = addr[1]; + + // パス名 + for (i = 0; i < sizeof(pNamests->path); i++) { + pNamests->path[i] = addr[2 + i]; + } + + // ファイル名1 + memset(pNamests->name, 0x20, sizeof(pNamests->name)); + + // 拡張子 + memset(pNamests->ext, 0x20, sizeof(pNamests->ext)); + + // ファイル名2 + memset(pNamests->add, 0, sizeof(pNamests->add)); +} + +//--------------------------------------------------------------------------- +// +// NAMESTS読み込み +// +//--------------------------------------------------------------------------- +void GetNameSts(BYTE *addr, namests_t* pNamests) +{ + DWORD i; + + ASSERT(this); + ASSERT(pNamests); + ASSERT(addr <= 0xFFFFFF); + + // ワイルドカード情報 + pNamests->wildcard = *addr; + + // ドライブ番号 + pNamests->drive = addr[1]; + + // パス名 + for (i = 0; i < sizeof(pNamests->path); i++) { + pNamests->path[i] = addr[2 + i]; + } + + // ファイル名1 + for (i = 0; i < sizeof(pNamests->name); i++) { + pNamests->name[i] = addr[67 + i]; + } + + // 拡張子 + for (i = 0; i < sizeof(pNamests->ext); i++) { + pNamests->ext[i] = addr[75 + i]; + } + + // ファイル名2 + for (i = 0; i < sizeof(pNamests->add); i++) { + pNamests->add[i] = addr[78 + i]; + } +} + +//--------------------------------------------------------------------------- +// +// FILES読み込み +// +//--------------------------------------------------------------------------- +void GetFiles(BYTE *addr, files_t* pFiles) +{ + ASSERT(this); + ASSERT(pFiles); + ASSERT(addr <= 0xFFFFFF); + + // 検索情報 + pFiles->fatr = *addr; + pFiles->sector = *((DWORD*)&addr[2]); + pFiles->offset = *((WORD*)&addr[8]);; + + pFiles->attr = 0; + pFiles->time = 0; + pFiles->date = 0; + pFiles->size = 0; + memset(pFiles->full, 0, sizeof(pFiles->full)); +} + +//--------------------------------------------------------------------------- +// +// FILES書き込み +// +//--------------------------------------------------------------------------- +void SetFiles(BYTE *addr, const files_t* pFiles) +{ + DWORD i; + + ASSERT(this); + ASSERT(pFiles); + + *((DWORD*)&addr[2]) = pFiles->sector; + *((WORD*)&addr[8]) = pFiles->offset; + + // ファイル情報 + addr[21] = pFiles->attr; + *((WORD*)&addr[22]) = pFiles->time; + *((WORD*)&addr[24]) = pFiles->date; + *((DWORD*)&addr[26]) = pFiles->size; + + // フルファイル名 + addr += 30; + for (i = 0; i < sizeof(pFiles->full); i++) { + *addr = pFiles->full[i]; + addr++; + } +} + +//--------------------------------------------------------------------------- +// +// FCB読み込み +// +//--------------------------------------------------------------------------- +void GetFcb(BYTE *addr, fcb_t* pFcb) +{ + ASSERT(this); + ASSERT(pFcb); + + // FCB情報 + pFcb->fileptr = *((DWORD*)&addr[6]); + pFcb->mode = *((WORD*)&addr[14]); + + // 属性 + pFcb->attr = addr[47]; + + // FCB情報 + pFcb->time = *((WORD*)&addr[58]); + pFcb->date = *((WORD*)&addr[60]); + pFcb->size = *((DWORD*)&addr[64]); +} + +//--------------------------------------------------------------------------- +// +// FCB書き込み +// +//--------------------------------------------------------------------------- +void SetFcb(BYTE *addr, const fcb_t* pFcb) +{ + ASSERT(this); + ASSERT(pFcb); + + // FCB情報 + *((DWORD*)&addr[6]) = pFcb->fileptr; + *((WORD*)&addr[14]) = pFcb->mode; + + // 属性 + addr[47] = pFcb->attr; + + // FCB情報 + *((WORD*)&addr[58]) = pFcb->time; + *((WORD*)&addr[60]) = pFcb->date; + *((DWORD*)&addr[64]) = pFcb->size; +} + +//--------------------------------------------------------------------------- +// +// CAPACITY書き込み +// +//--------------------------------------------------------------------------- +void SetCapacity(BYTE *addr, const capacity_t* pCapacity) +{ + ASSERT(this); + ASSERT(pCapacity); + + *((WORD*)&addr[0]) = pCapacity->freearea; + *((WORD*)&addr[2]) = pCapacity->clusters; + *((WORD*)&addr[4]) = pCapacity->sectors; + *((WORD*)&addr[6]) = pCapacity->bytes; +} + +//--------------------------------------------------------------------------- +// +// DPB書き込み +// +//--------------------------------------------------------------------------- +void SetDpb(BYTE *addr, const dpb_t* pDpb) +{ + ASSERT(this); + ASSERT(pDpb); + + // DPB情報 + *((WORD*)&addr[0]) = pDpb->sector_size; + addr[2] = pDpb->cluster_size; + addr[3] = pDpb->shift; + *((WORD*)&addr[4]) = pDpb->fat_sector; + addr[6] = pDpb->fat_max; + addr[7] = pDpb->fat_size; + *((WORD*)&addr[8]) = pDpb->file_max; + *((WORD*)&addr[10]) = pDpb->data_sector; + *((WORD*)&addr[12]) = pDpb->cluster_max; + *((WORD*)&addr[14]) = pDpb->root_sector; + addr[20] = pDpb->media; +} + +//--------------------------------------------------------------------------- +// +// IOCTRL読み込み +// +//--------------------------------------------------------------------------- +void GetIoctrl(DWORD param, DWORD func, ioctrl_t* pIoctrl) +{ + DWORD *lp; + + ASSERT(this); + ASSERT(pIoctrl); + + switch (func) { + case 2: + // メディア再認識 + pIoctrl->param = param; + return; + + case -2: + // オプション設定 + lp = (DWORD*)param; + pIoctrl->param = *lp; + return; + } +} + +//--------------------------------------------------------------------------- +// +// IOCTRL書き込み +// +//--------------------------------------------------------------------------- +void SetIoctrl(DWORD param, DWORD func, ioctrl_t* pIoctrl) +{ + DWORD i; + BYTE *bp; + WORD *wp; + DWORD *lp; + + ASSERT(this); + ASSERT(pIoctrl); + + switch (func) { + case 0: + // メディアIDの獲得 + wp = (WORD*)param; + *wp = pIoctrl->media; + return; + + case 1: + // Human68k互換のためのダミー + lp = (DWORD*)param; + *lp = pIoctrl->param; + return; + + case -1: + // 常駐判定 + bp = (BYTE*)param; + for (i = 0; i < 8; i++) { + *bp = pIoctrl->buffer[i]; + bp++; + } + return; + + case -3: + // オプション獲得 + lp = (DWORD*)param; + *lp = pIoctrl->param; + return; + } +} + +//--------------------------------------------------------------------------- +// +// ARGUMENT読み込み +// +// バッファサイズよりも長い場合は転送を打ち切って必ず終端する。 +// +//--------------------------------------------------------------------------- +void GetArgument(BYTE *addr, argument_t* pArgument) +{ + BOOL bMode; + BYTE *p; + DWORD i; + BYTE c; + + ASSERT(this); + ASSERT(pArgument); + + bMode = FALSE; + p = pArgument->buf; + for (i = 0; i < sizeof(pArgument->buf) - 2; i++) { + c = addr[i]; + *p++ = c; + if (bMode == 0) { + if (c == '\0') + return; + bMode = TRUE; + } else { + if (c == '\0') + bMode = FALSE; + } + } + + *p++ = '\0'; + *p = '\0'; +} + +//--------------------------------------------------------------------------- +// +// 終了値書き込み +// +//--------------------------------------------------------------------------- +void SetResult(DWORD nResult) +{ + DWORD code; + + ASSERT(this); + + // 致命的エラー判定 + switch (nResult) { + case FS_FATAL_INVALIDUNIT: + code = 0x5001; + goto fatal; + case FS_FATAL_INVALIDCOMMAND: + code = 0x5003; + goto fatal; + case FS_FATAL_WRITEPROTECT: + code = 0x700D; + goto fatal; + case FS_FATAL_MEDIAOFFLINE: + code = 0x7002; + fatal: + SetReqByte(3, (BYTE)code); + SetReqByte(4, code >> 8); + // @note リトライ可能を返すときは、(a5 + 18)を書き換えてはいけない。 + // その後白帯で Retry を選択した場合、書き換えた値を読み込んで誤動作してしまう。 + if (code & 0x2000) + break; + nResult = FS_INVALIDFUNC; + default: + SetReqLong(18, nResult); + break; + } +} + +//--------------------------------------------------------------------------- +// +// $40 - デバイス起動 +// +// in (offset size) +// 0 1.b 定数(22) +// 2 1.b コマンド($40/$c0) +// 18 1.l パラメータアドレス +// 22 1.b ドライブ番号 +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 13 1.b ユニット数 +// 14 1.l デバイスドライバの終了アドレス + 1 +// +// ローカルドライブのコマンド 0 と同様に組み込み時に呼ばれるが、BPB 及 +// びそのポインタの配列を用意する必要はない. +// 他のコマンドと違い、このコマンドだけa5 + 1には有効な値が入っていない +// (0初期化なども期待してはいけない)ので注意すること。 +// +//--------------------------------------------------------------------------- +DWORD InitDevice(void) +{ + argument_t arg; + DWORD units; + + ASSERT(this); + ASSERT(fs); + + // オプション内容を獲得 + GetArgument(GetReqAddr(18), &arg); + + // Human68k側で利用可能なドライブ数の範囲で、ファイルシステムを構築 + units = FS_InitDevice(&arg); + + // ドライブ数を返信 + SetReqByte(13, units); + + return 0; +} + +//--------------------------------------------------------------------------- +// +// $41 - ディレクトリチェック +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD CheckDir(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameStsPath(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_CheckDir(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $42 - ディレクトリ作成 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD MakeDir(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_MakeDir(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $43 - ディレクトリ削除 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD RemoveDir(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_RemoveDir(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $44 - ファイル名変更 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス 旧ファイル名 +// 18 1.L NAMESTS構造体アドレス 新ファイル名 +// +//--------------------------------------------------------------------------- +DWORD Rename(void) +{ + namests_t ns; + namests_t ns_new; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + GetNameSts(GetReqAddr(18), &ns_new); + + // ファイルシステム呼び出し + nResult = FS_Rename(&ns, &ns_new); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $45 - ファイル削除 +// +// in (offset size) +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Delete(void) +{ + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_Delete(&ns); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $46 - ファイル属性取得/設定 +// +// in (offset size) +// 12 1.B 読み出し時に0x01になるので注意 +// 13 1.B 属性 $FFだと読み出し +// 14 1.L NAMESTS構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Attribute(void) +{ + namests_t ns; + DWORD attr; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // 対象属性 + attr = GetReqByte(13); + + // ファイルシステム呼び出し + nResult = FS_Attribute(&ns, attr); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $47 - ファイル検索 +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($47/$c7) +// 13 1.b 検索属性 (WindrvXMでは未使用。検索バッファに値が書かれている) +// 14 1.l ファイル名バッファ(namests 形式) +// 18 1.l 検索バッファ(files 形式) このバッファに検索途中情報と検索結果を書き込む +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// ディレクトリから指定ファイルを検索する. DOS _FILES から呼び出される. +// 検索に失敗した場合、若しくは検索に成功してもワイルドカードが使われて +// いない場合は、次回検索時に必ず失敗させる為に検索バッファのオフセットに +// -1 を書き込む. 検索が成功した場合は見つかったファイルの情報を設定する +// と共に、次検索用の情報のセクタ番号、オフセット、ルートディレクトリの場 +// 合は更に残りセクタ数を設定する. 検索ドライブ・属性、パス名は DOS コー +// ル処理内で設定されるので書き込む必要はない. +// +// +// (offset size) +// 0 1.b NAMWLD 0:ワイルドカードなし -1:ファイル指定なし +// (ワイルドカードの文字数) +// 1 1.b NAMDRV ドライブ番号(A=0,B=1,…,Z=25) +// 2 65.b NAMPTH パス('\'+あればサブディレクトリ名+'\') +// 67 8.b NAMNM1 ファイル名(先頭 8 文字) +// 75 3.b NAMEXT 拡張子 +// 78 10.b NAMNM2 ファイル名(残りの 10 文字) +// +// パス区切り文字は0x2F(/)や0x5C(\)ではなく0x09(TAB)を使っているので注意。 +// +//--------------------------------------------------------------------------- +DWORD Files(void) +{ + BYTE *files; + files_t info; + namests_t ns; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 検索途中経過格納領域 + files = GetReqAddr(18); + GetFiles(files, &info); + + // 検索対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // ファイルシステム呼び出し + nResult = FS_Files((DWORD)files, &ns, &info); + + // 検索結果の反映 + if (nResult >= 0) { + SetFiles(files, &info); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $48 - ファイル次検索 +// +// in (offset size) +// 18 1.L FILES構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD NFiles(void) +{ + BYTE *files; + files_t info; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ワーク領域の読み込み + files = GetReqAddr(18); + GetFiles(files, &info); + + // ファイルシステム呼び出し + nResult = FS_NFiles((DWORD)files, &info); + + // 検索結果の反映 + if (nResult >= 0) { + SetFiles(files, &info); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $49 - ファイル作成(Create) +// +// in (offset size) +// 1 1.B ユニット番号 +// 13 1.B 属性 +// 14 1.L NAMESTS構造体アドレス +// 18 1.L モード (0:_NEWFILE 1:_CREATE) +// 22 1.L FCB構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Create(void) +{ + namests_t ns; + BYTE *pFcb; + fcb_t fcb; + DWORD attr; + BOOL force; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 属性 + attr = GetReqByte(13); + + // 強制上書きモード + force = (BOOL)GetReqLong(18); + + // ファイルシステム呼び出し + nResult = FS_Create((DWORD)pFcb, &ns, &fcb, attr, force); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4A - ファイルオープン +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L NAMESTS構造体アドレス +// 22 1.L FCB構造体アドレス +// 既にFCBにはほとんどのパラメータが設定済み +// 時刻・日付はオープンした瞬間のものになってるので上書き +// サイズは0になっているので上書き +// +//--------------------------------------------------------------------------- +DWORD Open(void) +{ + namests_t ns; + BYTE *pFcb; + fcb_t fcb; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // 対象ファイル名獲得 + GetNameSts(GetReqAddr(14), &ns); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // ファイルシステム呼び出し + nResult = FS_Open((DWORD)pFcb, &ns, &fcb); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4B - ファイルクローズ +// +// in (offset size) +// 22 1.L FCB構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Close(void) +{ + BYTE *pFcb; + fcb_t fcb; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // ファイルシステム呼び出し + nResult = FS_Close((DWORD)pFcb, &fcb); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4C - ファイル読み込み +// +// in (offset size) +// 14 1.L 読み込みバッファ ここにファイル内容を読み込む +// 18 1.L サイズ 16MBを超える値が指定される可能性もあり +// 22 1.L FCB構造体アドレス +// +// バスエラーが発生するアドレスを指定した場合の動作は保証しない。 +// +// 20世紀のアプリは「負の数だとファイルを全部読む」という作法で書かれている +// 可能性が微レ存。あれれー?このファイル16MB超えてるよー?(CV.高山みなみ) +// +// むしろ4〜12MBくらいの当時のプログラマーから見た実質的な「∞」の値で +// クリップするような配慮こそが現代では必要なのではなかろうか。 +// または、末尾が12MBと16MB位置を超えたらサイズをクリップすると良いかも。 +// +//--------------------------------------------------------------------------- +DWORD Read(void) +{ + BYTE *pFcb; + fcb_t fcb; + BYTE *pAddress; + DWORD nSize; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 読み込みバッファ + pAddress = GetReqAddr(14); + + // 読み込みサイズ + nSize = GetReqLong(18); + + // クリッピング + if (nSize >= WINDRV_CLIPSIZE_MAX) { + nSize = WINDRV_CLIPSIZE_MAX; + } + + // ファイルシステム呼び出し + nResult = FS_Read((DWORD)pFcb, &fcb, pAddress, nSize); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4D - ファイル書き込み +// +// in (offset size) +// 14 1.L 書き込みバッファ ここにファイル内容を書き込む +// 18 1.L サイズ 負の数ならファイルサイズを指定したのと同じ +// 22 1.L FCB構造体アドレス +// +// バスエラーが発生するアドレスを指定した場合の動作は保証しない。 +// +//--------------------------------------------------------------------------- +DWORD Write(void) +{ + BYTE *pFcb; + fcb_t fcb; + BYTE *pAddress; + DWORD nSize; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 書き込みバッファ + pAddress = GetReqAddr(14); + + // 書き込みサイズ + nSize = GetReqLong(18); + + // クリッピング + if (nSize >= WINDRV_CLIPSIZE_MAX) { + nSize = WINDRV_CLIPSIZE_MAX; + } + + // ファイルシステム呼び出し + nResult = FS_Write((DWORD)pFcb, &fcb, pAddress, nSize); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4E - ファイルシーク +// +// in (offset size) +// 12 1.B 0x2B になってるときがある 0のときもある +// 13 1.B モード +// 18 1.L オフセット +// 22 1.L FCB構造体アドレス +// +//--------------------------------------------------------------------------- +DWORD Seek(void) +{ + BYTE *pFcb; + fcb_t fcb; + DWORD nMode; + DWORD nOffset; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // シークモード + nMode = GetReqByte(13); + + // シークオフセット + nOffset = GetReqLong(18); + + // ファイルシステム呼び出し + nResult = FS_Seek((DWORD)pFcb, &fcb, nMode, nOffset); + + // 結果の反映 + if (nResult >= 0) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $4F - ファイル時刻取得/設定 +// +// in (offset size) +// 18 1.W DATE +// 20 1.W TIME +// 22 1.L FCB構造体アドレス +// +// FCBが読み込みモードで開かれた状態でも設定変更が可能。 +// FCBだけでは書き込み禁止の判定ができないので注意。 +// +//--------------------------------------------------------------------------- +DWORD TimeStamp(void) +{ + BYTE *pFcb; + fcb_t fcb; + DWORD nTime; + DWORD nResult; + + ASSERT(this); + ASSERT(fs); + + // FCB獲得 + pFcb = GetReqAddr(22); + GetFcb(pFcb, &fcb); + + // 時刻獲得 + nTime = GetReqLong(18); + + // ファイルシステム呼び出し + nResult = FS_TimeStamp((DWORD)pFcb, &fcb, nTime); + + // 結果の反映 + if (nResult < 0xFFFF0000) { + SetFcb(pFcb, &fcb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $50 - 容量取得 +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($50/$d0) +// 14 1.l バッファアドレス +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// メディアの総容量/空き容量、クラスタ/セクタサイズを収得する. バッファ +// に書き込む内容は以下の通り. リザルトステータスとして使用可能なバイト数 +// を返すこと. +// +// (offset size) +// 0 1.w 使用可能なクラスタ数 +// 2 1.w 総クラスタ数 +// 4 1.w 1 クラスタ当りのセクタ数 +// 6 1.w 1 セクタ当りのバイト数 +// +//--------------------------------------------------------------------------- +DWORD GetCapacity(void) +{ + BYTE *pCapacity; + capacity_t cap; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // バッファ取得 + pCapacity = GetReqAddr(14); + +#if 0 + // ファイルシステム呼び出し + nResult = FS_GetCapacity(&cap); +#else + // いつも同じ内容が返ってくるのでスキップしてみる + cap.freearea = 0xFFFF; + cap.clusters = 0xFFFF; + cap.sectors = 64; + cap.bytes = 512; + nResult = 0x7FFF8000; +#endif + + // 結果の反映 + if (nResult >= 0) { + SetCapacity(pCapacity, &cap); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $51 - ドライブ状態検査/制御 +// +// in (offset size) +// 1 1.B ユニット番号 +// 13 1.B 状態 0: 状態検査 1: イジェクト +// +//--------------------------------------------------------------------------- +DWORD CtrlDrive(void) +{ + ctrldrive_t ctrl; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ドライブ状態取得 + ctrl.status = GetReqByte(13); + + // ファイルシステム呼び出し + nResult = FS_CtrlDrive(&ctrl); + + // 結果の反映 + if (nResult >= 0) { + SetReqByte(13, ctrl.status); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $52 - DPB取得 +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($52/$d2) +// 14 1.l バッファアドレス(先頭アドレス + 2 を指す) +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// 指定メディアの情報を v1 形式 DPB で返す. このコマンドで設定する必要 +// がある情報は以下の通り(括弧内は DOS コールが設定する). ただし、バッフ +// ァアドレスはオフセット 2 を指したアドレスが渡されるので注意すること. +// +// (offset size) +// 0 1.b (ドライブ番号) +// 1 1.b (ユニット番号) +// 2 1.w 1 セクタ当りのバイト数 +// 4 1.b 1 クラスタ当りのセクタ数 - 1 +// 5 1.b クラスタ→セクタのシフト数 +// bit 7 = 1 で MS-DOS 形式 FAT(16bit Intel 配列) +// 6 1.w FAT の先頭セクタ番号 +// 8 1.b FAT 領域の個数 +// 9 1.b FAT の占めるセクタ数(複写分を除く) +// 10 1.w ルートディレクトリに入るファイルの個数 +// 12 1.w データ領域の先頭セクタ番号 +// 14 1.w 総クラスタ数 + 1 +// 16 1.w ルートディレクトリの先頭セクタ番号 +// 18 1.l (ドライバヘッダのアドレス) +// 22 1.b (小文字の物理ドライブ名) +// 23 1.b (DPB 使用フラグ:常に 0) +// 24 1.l (次の DPB のアドレス) +// 28 1.w (カレントディレクトリのクラスタ番号:常に 0) +// 30 64.b (カレントディレクトリ名) +// +//--------------------------------------------------------------------------- +DWORD GetDPB(void) +{ + BYTE *pDpb; + dpb_t dpb; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // DPB取得 + pDpb = GetReqAddr(14); + + // ファイルシステム呼び出し + nResult = FS_GetDPB(&dpb); + + // 結果の反映 + if (nResult >= 0) { + SetDpb(pDpb, &dpb); + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $53 - セクタ読み込み +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L バッファアドレス +// 18 1.L セクタ数 +// 22 1.L セクタ番号 +// +//--------------------------------------------------------------------------- +DWORD DiskRead(void) +{ + BYTE *pAddress; + DWORD nSize; + DWORD nSector; + BYTE buffer[0x200]; + int nResult; + int i; + + ASSERT(this); + ASSERT(fs); + + pAddress = GetReqAddr(14); // アドレス (上位ビットが拡張フラグ) + nSize = GetReqLong(18); // セクタ数 + nSector = GetReqLong(22); // セクタ番号 + + // ファイルシステム呼び出し + nResult = FS_DiskRead(buffer, nSector, nSize); + + // 結果の反映 + if (nResult >= 0) { + for (i = 0; i < sizeof(buffer); i++) { + *pAddress = buffer[i]; + pAddress++; + } + } + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $54 - セクタ書き込み +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L バッファアドレス +// 18 1.L セクタ数 +// 22 1.L セクタ番号 +// +//--------------------------------------------------------------------------- +DWORD DiskWrite(void) +{ + BYTE *pAddress; + DWORD nSize; + DWORD nSector; + int nResult; + + ASSERT(this); + ASSERT(fs); + + pAddress = GetReqAddr(14); // アドレス(上位ビットが拡張フラグ) + nSize = GetReqLong(18); // セクタ数 + nSector = GetReqLong(22); // セクタ番号 + + // ファイルシステム呼び出し + nResult = FS_DiskWrite(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $55 - IOCTRL +// +// in (offset size) +// 1 1.B ユニット番号 +// 14 1.L パラメータ +// 18 1.W 機能番号 +// +//--------------------------------------------------------------------------- +DWORD Ioctrl(void) +{ + DWORD param; + DWORD func; + ioctrl_t ioctrl; + int nResult; + + ASSERT(this); + ASSERT(fs); + + // IOCTRL取得 + param = GetReqLong(14); // パラメータ + func = GetReqWord(18); // 機能番号 + GetIoctrl(param, func, &ioctrl); + + // ファイルシステム呼び出し + nResult = FS_Ioctrl(func, &ioctrl); + + // 結果の反映 + if (nResult >= 0) + SetIoctrl(param, func, &ioctrl); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $56 - フラッシュ +// +// in (offset size) +// 1 1.B ユニット番号 +// +//--------------------------------------------------------------------------- +DWORD Flush(void) +{ + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ファイルシステム呼び出し + nResult = FS_Flush(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $57 - メディア交換チェック +// +// in (offset size) +// 0 1.b 定数(26) +// 1 1.b ユニット番号 +// 2 1.b コマンド($57/$d7) +// out (offset size) +// 3 1.b エラーコード(下位) +// 4 1.b 〃 (上位) +// 18 1.l リザルトステータス +// +// メディアが交換されたか否かを調べる. 交換されていた場合のフォーマット +// 確認はこのコマンド内で行うこと. +// +//--------------------------------------------------------------------------- +DWORD CheckMedia(void) +{ +#if 1 + static DWORD last = 0; + DWORD now; +#endif + int nResult; + + ASSERT(this); + ASSERT(fs); + +#if 1 + // 連続で呼び出されるの回避する + now = TIMEGET(); + if ((now - last) < 3) { + return 0; + } else { + last = now; + } +#endif + + // ファイルシステム呼び出し + nResult = FS_CheckMedia(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// $58 - 排他制御 +// +// in (offset size) +// 1 1.B ユニット番号 +// +//--------------------------------------------------------------------------- +DWORD Lock(void) +{ + int nResult; + + ASSERT(this); + ASSERT(fs); + + // ファイルシステム呼び出し + nResult = FS_Lock(); + + return nResult; +} + +//--------------------------------------------------------------------------- +// +// コマンド実行 +// +//--------------------------------------------------------------------------- +DWORD ExecuteCommand() +{ + ASSERT(this); + + // エラー情報クリア + SetReqByte(3, 0); + SetReqByte(4, 0); + + // コマンド番号 + command = (DWORD)GetReqByte(2); // ビット7はベリファイフラグ + + // ユニット番号 + unit = GetReqByte(1); + + // コマンド分岐 + switch (command & 0x7F) { + case 0x40: return InitDevice(); // $40 - デバイス起動 + case 0x41: return CheckDir(); // $41 - ディレクトリチェック + case 0x42: return MakeDir(); // $42 - ディレクトリ作成 + case 0x43: return RemoveDir(); // $43 - ディレクトリ削除 + case 0x44: return Rename(); // $44 - ファイル名変更 + case 0x45: return Delete(); // $45 - ファイル削除 + case 0x46: return Attribute(); // $46 - ファイル属性取得/設定 + case 0x47: return Files(); // $47 - ファイル検索 + case 0x48: return NFiles(); // $48 - ファイル次検索 + case 0x49: return Create(); // $49 - ファイル作成 + case 0x4A: return Open(); // $4A - ファイルオープン + case 0x4B: return Close(); // $4B - ファイルクローズ + case 0x4C: return Read(); // $4C - ファイル読み込み + case 0x4D: return Write(); // $4D - ファイル書き込み + case 0x4E: return Seek(); // $4E - ファイルシーク + case 0x4F: return TimeStamp(); // $4F - ファイル更新時刻の取得/設定 + case 0x50: return GetCapacity();// $50 - 容量取得 + case 0x51: return CtrlDrive(); // $51 - ドライブ制御/状態検査 + case 0x52: return GetDPB(); // $52 - DPB取得 + case 0x53: return DiskRead(); // $53 - セクタ読み込み + case 0x54: return DiskWrite(); // $54 - セクタ書き込み + case 0x55: return Ioctrl(); // $55 - IOCTRL +#if 0 + case 0x56: return Flush(); // $56 - フラッシュ +#else + case 0x56: return 0; // $56 - フラッシュ +#endif + case 0x57: return CheckMedia(); // $57 - メディア交換チェック +#if 0 + case 0x58: return Lock(); // $58 - 排他制御 +#else + case 0x58: return 0; // $58 - 排他制御 +#endif + } + + return FS_FATAL_INVALIDCOMMAND; +} + +//--------------------------------------------------------------------------- +// +// 初期化 +// +//--------------------------------------------------------------------------- +BOOL Init() +{ + ASSERT(this); + + return SCSI_Init(); +} + +//--------------------------------------------------------------------------- +// +// 実行 +// +//--------------------------------------------------------------------------- +void Process(DWORD nA5) +{ + ASSERT(this); + ASSERT(nA5 <= 0xFFFFFF); + ASSERT(m_bAlloc); + ASSERT(m_bFree); + + // リクエストヘッダのアドレス + request = (BYTE*)nA5; + + // コマンド実行 + SetResult(ExecuteCommand()); +} diff --git a/src/x68k/RASDRV/BRIDGE.H b/src/x68k/RASDRV/BRIDGE.H new file mode 100644 index 00000000..b59c642d --- /dev/null +++ b/src/x68k/RASDRV/BRIDGE.H @@ -0,0 +1,256 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ ホストファイルシステム ブリッジドライバ ] +// +//--------------------------------------------------------------------------- + +#ifndef bridge_h +#define bridge_h + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef int BOOL; + +#if !defined(FALSE) +#define FALSE 0 +#endif + +#if !defined(TRUE) +#define TRUE 1 +#endif + +#define FASTCALL +#define ASSERT(x) + +//--------------------------------------------------------------------------- +// +// 定数定義 +// +//--------------------------------------------------------------------------- +#define FILEPATH_MAX _MAX_PATH +#define WINDRV_CLIPSIZE_MAX 0xC00000 + +//--------------------------------------------------------------------------- +// +// ステータスコード定義 +// +//--------------------------------------------------------------------------- +#define FS_INVALIDFUNC 0xFFFFFFFF // 無効なファンクションコードを実行した +#define FS_FILENOTFND 0xFFFFFFFE // 指定したファイルが見つからない +#define FS_DIRNOTFND 0xFFFFFFFD // 指定したディレクトリが見つからない +#define FS_OVEROPENED 0xFFFFFFFC // オープンしているファイルが多すぎる +#define FS_CANTACCESS 0xFFFFFFFB // ディレクトリやボリュームラベルはアクセス不可 +#define FS_NOTOPENED 0xFFFFFFFA // 指定したハンドルはオープンされていない +#define FS_INVALIDMEM 0xFFFFFFF9 // メモリ管理領域が破壊された +#define FS_OUTOFMEM 0xFFFFFFF8 // 実行に必要なメモリがない +#define FS_INVALIDPTR 0xFFFFFFF7 // 無効なメモリ管理ポインタを指定した +#define FS_INVALIDENV 0xFFFFFFF6 // 不正な環境を指定した +#define FS_ILLEGALFMT 0xFFFFFFF5 // 実行ファイルのフォーマットが異常 +#define FS_ILLEGALMOD 0xFFFFFFF4 // オープンのアクセスモードが異常 +#define FS_INVALIDPATH 0xFFFFFFF3 // ファイル名の指定に誤りがある +#define FS_INVALIDPRM 0xFFFFFFF2 // 無効なパラメータでコールした +#define FS_INVALIDDRV 0xFFFFFFF1 // ドライブ指定に誤りがある +#define FS_DELCURDIR 0xFFFFFFF0 // カレントディレクトリは削除できない +#define FS_NOTIOCTRL 0xFFFFFFEF // IOCTRLできないデバイス +#define FS_LASTFILE 0xFFFFFFEE // これ以上ファイルが見つからない +#define FS_CANTWRITE 0xFFFFFFED // 指定のファイルは書き込みできない +#define FS_DIRALREADY 0xFFFFFFEC // 指定のディレクトリは既に登録されている +#define FS_CANTDELETE 0xFFFFFFEB // ファイルがあるので削除できない +#define FS_CANTRENAME 0xFFFFFFEA // ファイルがあるのでリネームできない +#define FS_DISKFULL 0xFFFFFFE9 // ディスクが一杯でファイルが作れない +#define FS_DIRFULL 0xFFFFFFE8 // ディレクトリが一杯でファイルが作れない +#define FS_CANTSEEK 0xFFFFFFE7 // 指定の位置にはシークできない +#define FS_SUPERVISOR 0xFFFFFFE6 // スーパーバイザ状態でスーパバイザ指定した +#define FS_THREADNAME 0xFFFFFFE5 // 同じスレッド名が存在する +#define FS_BUFWRITE 0xFFFFFFE4 // プロセス間通信のバッファが書込み禁止 +#define FS_BACKGROUND 0xFFFFFFE3 // バックグラウンドプロセスを起動できない +#define FS_OUTOFLOCK 0xFFFFFFE0 // ロック領域が足りない +#define FS_LOCKED 0xFFFFFFDF // ロックされていてアクセスできない +#define FS_DRIVEOPENED 0xFFFFFFDE // 指定のドライブはハンドラがオープンされている +#define FS_LINKOVER 0xFFFFFFDD // シンボリックリンクネストが16回を超えた +#define FS_FILEEXIST 0xFFFFFFB0 // ファイルが存在する + +#define FS_FATAL_MEDIAOFFLINE 0xFFFFFFA3 // メディアが入っていない +#define FS_FATAL_WRITEPROTECT 0xFFFFFFA2 // 書き込み禁止違反 +#define FS_FATAL_INVALIDCOMMAND 0xFFFFFFA1 // 不正なコマンド番号 +#define FS_FATAL_INVALIDUNIT 0xFFFFFFA0 // 不正なユニット番号 + +#define HUMAN68K_PATH_MAX 96 // Human68kのパス最大長 + +//=========================================================================== +// +/// Human68k 名前空間 +// +//=========================================================================== +/// ファイル属性ビット +enum attribute_t { + AT_READONLY = 0x01, // 読み込み専用属性 + AT_HIDDEN = 0x02, // 隠し属性 + AT_SYSTEM = 0x04, // システム属性 + AT_VOLUME = 0x08, // ボリュームラベル属性 + AT_DIRECTORY= 0x10, // ディレクトリ属性 + AT_ARCHIVE = 0x20, // アーカイブ属性 + AT_ALL = 0xFF, // 全ての属性ビットが1 +}; + +/// ファイルオープンモード +enum open_t { + OP_READ = 0, // 読み込み + OP_WRITE = 1, // 書き込み + OP_FULL = 2, // 読み書き + OP_MASK = 0x0F, // 判定用マスク + OP_SHARE_NONE = 0x10, // 共有禁止 + OP_SHARE_READ = 0x20, // 読み込み共有 + OP_SHARE_WRITE = 0x30, // 書き込み共有 + OP_SHARE_FULL = 0x40, // 読み書き共有 + OP_SHARE_MASK = 0x70, // 共有判定用マスク + OP_SPECIAL = 0x100,// 辞書アクセス +}; + +/// シーク種類 +enum seek_t { + SK_BEGIN = 0, // ファイル先頭から + SK_CURRENT = 1, // 現在位置から + SK_END = 2, // ファイル末尾から +}; + +/// メディアバイト +enum media_t { + MEDIA_2DD_10 = 0xE0, // 2DD/10セクタ + MEDIA_1D_9 = 0xE5, // 1D/9セクタ + MEDIA_2D_9 = 0xE6, // 2D/9セクタ + MEDIA_1D_8 = 0xE7, // 1D/8セクタ + MEDIA_2D_8 = 0xE8, // 2D/8セクタ + MEDIA_2HT = 0xEA, // 2HT + MEDIA_2HS = 0xEB, // 2HS + MEDIA_2HDE = 0xEC, // 2DDE + MEDIA_1DD_9 = 0xEE, // 1DD/9セクタ + MEDIA_1DD_8 = 0xEF, // 1DD/8セクタ + MEDIA_MANUAL = 0xF1, // リモートドライブ (手動イジェクト) + MEDIA_REMOVABLE = 0xF2, // リモートドライブ (リムーバブル) + MEDIA_REMOTE = 0xF3, // リモートドライブ + MEDIA_DAT = 0xF4, // SCSI-DAT + MEDIA_CDROM = 0xF5, // SCSI-CDROM + MEDIA_MO = 0xF6, // SCSI-MO + MEDIA_SCSI_HD = 0xF7, // SCSI-HD + MEDIA_SASI_HD = 0xF8, // SASI-HD + MEDIA_RAMDISK = 0xF9, // RAMディスク + MEDIA_2HQ = 0xFA, // 2HQ + MEDIA_2DD_8 = 0xFB, // 2DD/8セクタ + MEDIA_2DD_9 = 0xFC, // 2DD/9セクタ + MEDIA_2HC = 0xFD, // 2HC + MEDIA_2HD = 0xFE, // 2HD +}; + +/// namests構造体 +typedef struct { + BYTE wildcard; // ワイルドカード文字数 + BYTE drive; // ドライブ番号 + BYTE path[65]; // パス(サブディレクトリ+/) + BYTE name[8]; // ファイル名 (PADDING 0x20) + BYTE ext[3]; // 拡張子 (PADDING 0x20) + BYTE add[10]; // ファイル名追加 (PADDING 0x00) +} namests_t; + +/// files構造体 +typedef struct { + BYTE fatr; // + 0 検索する属性 読込専用 + BYTE pad1[3]; // padding +// BYTE drive; // + 1 ドライブ番号 読込専用 + DWORD sector; // + 2 ディレクトリのセクタ DOS _FILES先頭アドレスで代用 +// WORD cluster; // + 6 ディレクトリのクラスタ 詳細不明 (未使用) + WORD offset; // + 8 ディレクトリエントリ 書込専用 +// BYTE name[8]; // +10 作業用ファイル名 読込専用 (未使用) +// BYTE ext[3]; // +18 作業用拡張子 読込専用 (未使用) + BYTE attr; // +21 ファイル属性 書込専用 + BYTE pad2; // padding + WORD time; // +22 最終変更時刻 書込専用 + WORD date; // +24 最終変更月日 書込専用 + DWORD size; // +26 ファイルサイズ 書込専用 + BYTE full[23]; // +30 フルファイル名 書込専用 + BYTE pad3; // padding +} files_t; + +/// FCB構造体 +typedef struct { +// BYTE pad00[6]; // + 0〜+ 5 (未使用) + DWORD fileptr; // + 6〜+ 9 ファイルポインタ +// BYTE pad01[4]; // +10〜+13 (未使用) + WORD mode; // +14〜+15 オープンモード +// BYTE pad02[16]; // +16〜+31 (未使用) +// DWORD zero; // +32〜+35 オープンのとき0が書き込まれている (未使用) +// BYTE name[8]; // +36〜+43 ファイル名 (PADDING 0x20) (未使用) +// BYTE ext[3]; // +44〜+46 拡張子 (PADDING 0x20) (未使用) + BYTE attr; // +47 ファイル属性 + BYTE pad; // padding +// BYTE add[10]; // +48〜+57 ファイル名追加 (PADDING 0x00) (未使用) + WORD time; // +58〜+59 最終変更時刻 + WORD date; // +60〜+61 最終変更月日 +// WORD cluster; // +62〜+63 クラスタ番号 (未使用) + DWORD size; // +64〜+67 ファイルサイズ +// BYTE pad03[28]; // +68〜+95 FATキャッシュ (未使用) +} fcb_t; + +/// capacity構造体 +typedef struct { + WORD freearea; // + 0 使用可能なクラスタ数 + WORD clusters; // + 2 総クラスタ数 + WORD sectors; // + 4 クラスタあたりのセクタ数 + WORD bytes; // + 6 セクタ当たりのバイト数 +} capacity_t; + +/// ctrldrive構造体 +typedef struct { + BYTE status; // +13 状態 + BYTE pad[3]; // padding +} ctrldrive_t; + +/// DPB構造体 +typedef struct { + WORD sector_size; // + 0 1セクタ当りのバイト数 + BYTE cluster_size; // + 2 1クラスタ当りのセクタ数-1 + BYTE shift; // + 3 クラスタ→セクタのシフト数 + WORD fat_sector; // + 4 FATの先頭セクタ番号 + BYTE fat_max; // + 6 FAT領域の個数 + BYTE fat_size; // + 7 FATの占めるセクタ数(複写分を除く) + WORD file_max; // + 8 ルートディレクトリに入るファイルの個数 + WORD data_sector; // +10 データ領域の先頭セクタ番号 + WORD cluster_max; // +12 総クラスタ数+1 + WORD root_sector; // +14 ルートディレクトリの先頭セクタ番号 +// DWORD driverentry; // +16 デバイスドライバへのポインタ (未使用) + BYTE media; // +20 メディア識別子 +// BYTE flag; // +21 DPB使用フラグ (未使用) + BYTE pad; // padding +} dpb_t; + +/// ディレクトリエントリ構造体 +typedef struct { + BYTE name[8]; // + 0 ファイル名 (PADDING 0x20) + BYTE ext[3]; // + 8 拡張子 (PADDING 0x20) + BYTE attr; // +11 ファイル属性 + BYTE add[10]; // +12 ファイル名追加 (PADDING 0x00) + WORD time; // +22 最終変更時刻 + WORD date; // +24 最終変更月日 + WORD cluster; // +26 クラスタ番号 + DWORD size; // +28 ファイルサイズ +} dirent_t; + +/// IOCTRLパラメータ共用体 +typedef union { + BYTE buffer[8]; // バイト単位でのアクセス + DWORD param; // パラメータ(先頭4バイト) + WORD media; // メディアバイト(先頭2バイト) +} ioctrl_t; + +/// コマンドライン引数構造体 +typedef struct { + BYTE buf[256]; // コマンドライン引数 +} argument_t; + +#endif // bridge_h diff --git a/src/x68k/RASDRV/Makefile b/src/x68k/RASDRV/Makefile new file mode 100644 index 00000000..4a449de3 --- /dev/null +++ b/src/x68k/RASDRV/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for RASDRV.SYS +# + +CC = gcc -O2 -Wall -fomit-frame-pointer +AS = has +LK = hlk -l -x + +RASDRV.SYS : RASDRV.o BRIDGE.o + $(LK) -o $@ $^ libc.a libiocs.a libscsi.a + +RASDRV.o : RASDRV.S + $(AS) $^ + +BRIDGE.o : BRIDGE.C + $(CC) -c -o $@ $^ + \ No newline at end of file diff --git a/src/x68k/RASDRV/RASDRV.S b/src/x68k/RASDRV/RASDRV.S new file mode 100644 index 00000000..4bd36f1e --- /dev/null +++ b/src/x68k/RASDRV/RASDRV.S @@ -0,0 +1,193 @@ +*--------------------------------------------------------------------------- +* +* SCSI Target Emulator RaSCSI (*^..^*) +* for Raspberry Pi +* +* Powered by XM6 TypeG Technorogy. +* Copyright (C) 2016-2017 GIMONS +* [ ホストファイルシステム ブリッジドライバ ] +* +* Based on +* X68k Emulator Host Filesystem Driver version 0.27 +* Programmed By co +* +*--------------------------------------------------------------------------- + + CPU 68010 + + INCLUDE DOSCALL.MAC + INCLUDE IOCSCALL.MAC + +.XREF _Init, _Process ;bridge.c + +COMMAND EQU 2 コマンド番号 +ERRLOW EQU 3 エラーコード下位8ビット +ERRHIGH EQU 4 エラーコード上位8ビット +MXUNIT EQU 13 ユニット数 +DEVEND EQU 14 ドライバ終了アドレス +BDEVNO EQU 22 ベースドライブ番号 + +DDHEADER: + DC.L -1 +$00 リンクポインタ + DC.W $2040 +$04 デバイス属性 + DC.L DDSTRATEGY +$06 + DC.L DDENTRY_FIRST +$0A + DC.B '*EMUHOST' +$0E デバイス名 + +DDREQUEST: + DC.L 0 + +DDSTRATEGY: + MOVE.L A5,DDREQUEST + RTS + +*デバイスドライバエントリ +DDENTRY: + MOVE.L SP,(STACK_BUFF) + LEA (DEF_STACK),SP + MOVEM.L D1-D3/A0-A2,-(SP) + MOVEM.L DDREQUEST(PC),D0 D0.L: リクエストヘッダアドレス + MOVE.L D0,-(SP) + BSR _Process + ADDQ.L #4,SP + MOVEM.L (SP)+,D1-D3/A0-A2 + MOVEA.L (STACK_BUFF),SP + RTS + +KEEP_HERE: + +*初回のみのデバイスドライバエントリ +DDENTRY_FIRST: + MOVEM.L D1-D3/A0-A2/A5,-(SP) + MOVEA.L DDREQUEST(PC),A5 A5.L: リクエストヘッダアドレス +* CMPI.B #$40,COMMAND(A5) 現行のHuman68kではチェック不要 +* BNE UNSUPPORTED エラー: 未対応 + +*タイトル表示 + PEA MESSAGE_TITLE(PC) + DOS _PRINT + ADDQ.L #4,SP + +*デバイスチェック +DEVICE_CHECK: + BSR _Init + + TST.L D0 + BEQ NOTFOUND エラー: デバイスが存在しません + +*常駐開始 + LEA DDENTRY(PC),A1 + + LEA DDHEADER+$0A(PC),A0 + MOVE.L A1,(A0) ドライバエントリを設定 + MOVE.L #PROG_END,DEVEND(A5) 常駐終了アドレスを設定 + + ST.B MXUNIT(A5) ポート未実装の判定のため負の値を設定しておく + JSR (A1) ドライバエントリを実行 + + TST.B MXUNIT(A5) ユニット数確認 + BLE NODRIVE エラー: ドライブがありません + + MOVE.B BDEVNO(A5),D0 + MOVE.B MXUNIT(A5),D1 + LEA FIRSTDRIVE(PC),A0 + ADD.B D0,(A0) 開始ドライブ名書き換え + ADD.B D1,D0 終了ドライブ名書き換え + ADD.B D0,LASTDRIVE-FIRSTDRIVE(A0) + + PEA MESSAGE_DRIVENAME(PC) 正常: ドライブA: + DOS _PRINT + + PEA MESSAGE_DRIVENAME2(PC) 正常: からZ: + SUBQ.B #2,D1 + BCS @F + DOS _PRINT +@@ ADDQ.L #8,SP + + PEA MESSAGE_DRIVENAME3(PC) 正常: を登録しました + BRA QUIT + +NOTFOUND: + PEA MESSAGE_NOTFOUND(PC) エラー: デバイスが存在しません + BRA ABORT + +UNSUPPORTED: + PEA MESSAGE_UNSUPPORTED(PC) エラー: 未対応 + BRA ABORT + +NODRIVE: + PEA MESSAGE_NODRIVE(PC) エラー: ドライブがありません + +ABORT: + MOVE.B #$0D,ERRLOW(A5) + MOVE.B #$70,ERRHIGH(A5) + +QUIT: + DOS _PRINT + ADDQ.L #4,SP + + MOVEM.L (SP)+,D1-D3/A0-A2/A5 + RTS + +SECRET: + PEA MESSAGE_TITLE2(PC) + DOS _PRINT + PEA CREDIT(PC) + DOS _PRINT + ADDQ.L #8,SP + DOS _EXIT + + DATA + +*エラーメッセージ +MESSAGE_NOTFOUND: + DC.B 'デバイスが存在しません',$0D,$0A,0 + +MESSAGE_UNSUPPORTED: + DC.B '未対応',$0D,$0A,0 + +MESSAGE_NODRIVE: + DC.B 'ドライブがありません',$0D,$0A,0 + +*登録メッセージ +MESSAGE_DRIVENAME: + DC.B 'ドライブ' +FIRSTDRIVE: + DC.B 'A:',0 +MESSAGE_DRIVENAME2: + DC.B 'から' +LASTDRIVE: + DC.B '@:',0 +MESSAGE_DRIVENAME3: + DC.B 'を登録しました',$0D,$0A,0 + +*タイトル +MESSAGE_TITLE: + DC.B $0D,$0A +MESSAGE_TITLE2: + DC.B 'RaSCSI FileSystem Driver version 1.21',$0D,$0A,0 + +*ありがとう! +CREDIT: + DC.B 'Coded by GIMONS',$0D,$0A + DC.B 'Special thanks to',$0D,$0A + DC.B 9,'co',$0D,$0A + DC.B 9,'PI.',$0D,$0A + DC.B 9,'立花@桑島技研',$0D,$0A + DC.B 0 + + BSS + QUAD + +STACK_BUFF: + .DS.L 1 + + STACK + QUAD + + .DS.B 1024*2 +DEF_STACK: + + +PROG_END: + END SECRET diff --git a/src/x68k/RASDRV/RASDRV.TXT b/src/x68k/RASDRV/RASDRV.TXT new file mode 100644 index 00000000..cbb094e2 --- /dev/null +++ b/src/x68k/RASDRV/RASDRV.TXT @@ -0,0 +1,29 @@ +RaSCSI ファイルシステムドライバ +RASDRV version 1.21 + +■概要 + + 本プログラムはX68000実機で動作しているHuman68kからRaSCSIのブリッジデバイスを + 通してRaspberry Pi側のファイルシステムを直接操作するためのデバイスドライバです。 + X68000エミュレータであるXM6及びXM6改ならびにTypeGのWindrvXMと同等の機能を提供 + します。 + +■解説 + + 利用するにはRaspberry PiのRaSCSIでブリッジデバイスを有効にする必要があります。 + 例えばSCSI ID6にブリッジデバイスを有効にする場合はrascsi -ID6 BRIDGEといった + 指定が必要です。 + + 次にデバイスドライバRASCSI.SYSを実機の環境にコピーします。あとはCONFIG.SYSの + 後半部分に以下のように記述してください。 + + DEVICE = \SYS\RASDRV.SYS + + 起動オプションを指定しない場合はRaspberry Piのルートディレクトリ配下をマウント + します。引数にディレクトリ名を指定することでそのディレクトリをマウントできます。 + 例えば/home/pi/appと/home/pi/dataというディレクトリをマウントする場合は + + DEVICE = \SYS\RASDRV.SYS /home/pi/app /home/pi/data + + と記述することで二つのディレクトリを別々のドライブとしてマウント可能です。 + その他のオプションとしてWindrvXMのものが指定可能です。 diff --git a/src/x68k/RASETHER/Makefile b/src/x68k/RASETHER/Makefile new file mode 100644 index 00000000..92557b33 --- /dev/null +++ b/src/x68k/RASETHER/Makefile @@ -0,0 +1,33 @@ +# +# Makefile for RASETHER.SYS +# + +TARGET = RASETHER.SYS + +OBJS = re.o asmsub.o main.o scsictl.o +LIBS = libc.a libgnu.a libscsi.a + +CC = gcc -O2 -Wall -fomit-frame-pointer +CFLAGS = -D__DOS_INLINE__ -D__IOCS_INLINE__ +#CFLAGS = -D__DOS_INLINE__ -D__IOCS_INLINE__ -DUSE_DMA + +AS = has +ASFLAGS = +LD = hlk +LDFLAGS = -l -x + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(LD) $(LDFLAGS) -o $@ $^ $(LIBS) + +scsictl.o: scsictl.c scsictl.h + $(COMPILE.c) $< + +main.o: main.c main.h scsictl.h + $(COMPILE.c) $< + +asmsub.o: asmsub.s + +# EOF + \ No newline at end of file diff --git a/src/x68k/RASETHER/RASETHER.DOC b/src/x68k/RASETHER/RASETHER.DOC new file mode 100644 index 00000000..5e37f13c --- /dev/null +++ b/src/x68k/RASETHER/RASETHER.DOC @@ -0,0 +1,42 @@ +RaSCSI用 Ethernetドライバ +RASETHER version 1.20 + +Based on + Neptune-X board driver for Human-68k(ESP-X) version 0.03 + Programed 1996-7 by Shi-MAD. + Special thanks to Niggle, FIRST, yamapu ... + +● このプログラムは + + Shi-MAD さんの作られた Ethernet 用 ISA バスブリッジ "Neptune-X" 用デバ + イスドライバ ether_ne.sys を改造した ether_ne.sys ver0.03 +M01 +1 +L12を + 参考にして開発したRaSCSI用のイーサーネット通信ドライバです。 + +● 使い方 + + 基本的にはオリジナルのドライバと同じようにデバイスドライバとしてCONFIG.SYS + で組み込んで下さい。 + + 例) + DEVICE = \SYS\RASETHER.SYS + + 以下のオプションが指定可能です。 + -tx [xは数字] : 使用するtrapを指定します。xは0から6が指定可能です。 + ただし、指定したtrapが使用中である場合は、trap #0から + 空いている所を自動探索し、見つかった空きtrapを利用し + ます。 + -n : APIにtrapを使用しません。 + + RASETHERで拡張したオプションは以下のとおりです。 + -px [xは数字] : パケット受信のポーリング間隔を指定します1がデフォルトです。 + 1の場合は約16ms毎にポーリングします。2,3・・・8まで指定が可能 + です。数字が一つ増えるごとに16ms間隔が大きくなります。 + + -ix [xは数字] : ポーリングに使用する割り込みのタイプを指定します。 + デフォルトは0でMFPのGPIP割り込み(V-DISP)を利用します。 + 1を指定するとTimer-A割り込みを使用します。 + + +● このドライバについて + オリジナルのether_ne.sys及び改造版のether_ne.sys ver0.03 +M01 +1 +L12の + 利用規定に従います。 diff --git a/src/x68k/RASETHER/asmsub.s b/src/x68k/RASETHER/asmsub.s new file mode 100644 index 00000000..87d85957 --- /dev/null +++ b/src/x68k/RASETHER/asmsub.s @@ -0,0 +1,22 @@ +* asmsub.s + + .xdef _DI, _EI * ne2000.c nagai. + + .text + .even + + + +_DI: + move.w sr,sendp_sr + ori.w #$700,sr + rts +_EI: + move.w sendp_sr,sr + rts + +sendp_sr: + .ds.w 1 + + + .even diff --git a/src/x68k/RASETHER/main.c b/src/x68k/RASETHER/main.c new file mode 100644 index 00000000..a6b6bb4a --- /dev/null +++ b/src/x68k/RASETHER/main.c @@ -0,0 +1,282 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット メイン ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include "main.h" +#include "scsictl.h" + +unsigned int scsiid; +int trap_no; +int num_of_prt; +struct prt PRT_LIST[NPRT]; + +// マルチキャスト(未対応) +#ifdef MULTICAST +int num_of_multicast; +struct eaddr multicast_array[NMULTICAST]; +#endif + +/************************************************ + * * + ************************************************/ +static int sprint_eaddr(unsigned char* dst, void* e) +{ + unsigned char* p = e; + + return sprintf( + dst, + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + p[0], p[1], p[2], p[3], p[4], p[5]); +} + +/************************************************ + * TRAP nが使用可能か調べる * + ************************************************/ +static int is_valid_trap(int trap_no) +{ + unsigned int addr; + + if (trap_no < 0 || 7 < trap_no) { + return 0; + } + + // 使用中かどうかチェック + addr = (unsigned int)_dos_intvcg(TRAP_VECNO(trap_no)); + + // 処理アドレスの最上位バイトにベクタ番号が入っていれば未使用 + if (addr & 0xff000000) { + return -1; + } + + return 0; +} + +/************************************************ + * 未使用のTRAP nを検索 * + ************************************************/ +static int search_trap_no(int def) +{ + int i; + + // もしdefが使用可能ならそれに決定 + if (is_valid_trap(def)) { + return def; + } + + for (i = 0; i <= 6; i++) { + if (is_valid_trap(i)) { + return i; + } + } + + return -1; +} + +/************************************************ + * vector set * + ************************************************/ +static void* trap_vector(int trap_no, void *func) +{ + return _dos_intvcs(TRAP_VECNO(trap_no), func); +} + +/************************************************ + 初期化関数(ne.sイニシャライズで呼びます) * + ************************************************/ +int Initialize(void) +{ + unsigned char buff[128]; + unsigned char buff2[32]; + struct eaddr ether_addr; + + if (SearchRaSCSI()) + { + Print("RaSCSI Ether Adapter の存在を確認できませんでした\r\n"); + return -1; + } + + if (InitList(NPRT) + || InitRaSCSI()) + { + Print("RaSCSI Ether Adapter Driver の初期化に失敗しました\r\n"); + return -1; + } + + memset(ðer_addr, 0x00, sizeof(ether_addr)); + GetMacAddr(ðer_addr); + + // 未使用trap番号を調べる(指定番号優先) + if (trap_no >= 0) { + trap_no = search_trap_no(trap_no); + } + + if (trap_no >= 0) { + // trapをフックする + trap_vector(trap_no, (void*)trap_entry); + sprintf(buff, " API trap number:%d ", trap_no); + } else { + sprintf(buff, " API trap number:n/a "); + } + Print(buff); + + sprintf(buff, "SCSI ID:%d ", scsiid); + Print(buff); + + sprint_eaddr(buff2, ether_addr.eaddr); + sprintf(buff, "MAC Addr:%s\r\n", buff2); + Print(buff); + + // ポーリング開始 + RegisterIntProcess(poll_interval); + + return 0; +} + +/************************************************ + * プロトコルリスト初期化 * + ************************************************/ +int InitList(int n) +{ + struct prt* p; + int i; + + p = &PRT_LIST[0]; + for (i = 0; i < NPRT; i++, p++) { + p->type = -1; + p->func = 0; + p->malloc = (malloc_func)-1; + } + num_of_prt = 0; + +#ifdef MULTICAST + num_of_multicast = 0; +#endif + + return 0; +} + +/************************************************ + * 受信ハンドラ(プロトコル)追加 * + ************************************************/ +int AddList(int type, int_handler handler) +{ + struct prt* p; + int i, result; + + if (type == -1) { + return -1; + } + + result = -1; + + // overwrite if alreay exist + p = &PRT_LIST[0]; + for (i = 0; i < NPRT; i++, p++) { + if ((p->type == type && p->malloc != (malloc_func)-1) + || p->type == -1) + { + if (p->type == -1) + num_of_prt++; + + p->type = type; + p->func = handler; + p->malloc = (malloc_func)-1; + i++; + p++; + result = 0; + break; + } + } + + // clear if exist more + for (; i < NPRT; i++, p++) { + if (p->type == type && p->malloc != (malloc_func)-1) { + p->type = -1; + } + } + + return result; +} + +/************************************************ + * 受信ハンドラ(プロトコル)削除 * + ************************************************/ +int DeleteList(int type) +{ + struct prt* p; + int i, result; + + if (type == -1) { + return -1; + } + + result = -1; + for (i = 0, p = &PRT_LIST[0]; i < NPRT; i++, p++) { + if (p->type == type && p->malloc != (malloc_func)-1) { + p->type = -1; + result = 0; + num_of_prt--; + } + } + + return result; +} + +/************************************************ + * 受信ハンドラ(プロトコル)サーチ * + ************************************************/ +int_handler SearchList(int type) +{ + struct prt* p; + int i; + + if (type == -1) { + return 0; + } + + for (i = 0, p = &PRT_LIST[0]; i < NPRT; i++, p++) { + if (p->type == type) { + return p->func; + } + } + + return 0; +} + + +/************************************************ + * 受信ハンドラ(プロトコル)サーチ * + ************************************************/ +int_handler SearchList2(int type, int n) +{ + struct prt *p; + int i, cur; + + if (type == -1) { + return NULL; + } + + cur = 0; + for (i = 0, p = &PRT_LIST[0]; i < NPRT; i++, p++) { + if (p->type == type && cur++ == n) { + return p->func; + } + } + + return NULL; +} diff --git a/src/x68k/RASETHER/main.h b/src/x68k/RASETHER/main.h new file mode 100644 index 00000000..fa481a06 --- /dev/null +++ b/src/x68k/RASETHER/main.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット メイン ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#ifndef main_h +#define main_h + +#define ID_EN0 (('e'<<24)+('n'<<16)+('0'<<8)) +#undef MULTICAST + +// number of protocol type we can handle **EDIT this** +#define NPRT (16) + +// number of multicast address we can handle **EDIT this** +#define NMULTICAST (64) +/* ただし、まだマルチキャストには対応していない */ + +struct eaddr { + unsigned char eaddr [6]; +}; + +typedef void (*int_handler) (int, void*, int); +typedef void (*malloc_func) (unsigned int*); + +struct prt { + int type; + int_handler func; + malloc_func malloc; +}; + + +// グローバル変数 +extern unsigned int scsiid; +extern int trap_no; +extern int num_of_prt; +extern struct prt PRT_LIST [NPRT]; + +#ifdef MULTICAST +extern int num_of_multicast; +extern struct eaddr multicast_array [NMULTICAST]; +#endif + + +// プロトタイプ宣言 +extern int Initialize (void); +extern int InitList (int); +extern int AddList (int, int_handler); +extern int DeleteList (int); +extern int_handler SearchList (int); +extern int_handler SearchList2 (int, int); +extern malloc_func GetMallocFunc (int, int); + +#ifdef MULTICAST +extern int AddMulticastArray (struct eaddr*); +extern void DelMulticastArray (struct eaddr*); +extern void MakeMulticastTable (unsigned char*); +#endif + + +// ne.s 内関数 +extern void trap_entry (void); + + +#include +#define Print _iocs_b_print + +#define TRAP_VECNO(n) (0x20 + n) + +#endif // main_h diff --git a/src/x68k/RASETHER/re.s b/src/x68k/RASETHER/re.s new file mode 100644 index 00000000..2eba98a8 --- /dev/null +++ b/src/x68k/RASETHER/re.s @@ -0,0 +1,574 @@ +**--------------------------------------------------------------------------- +** +** SCSI Target Emulator RaSCSI (*^..^*) +** for Raspberry Pi +** +** Powered by XM6 TypeG Technorogy. +** Copyright (C) 2016-2017 GIMONS +** [ RaSCSI イーサーネット ドライバ ] +** +** Based on +** Neptune-X board driver for Human-68k(ESP-X) version 0.03 +** Programed 1996-7 by Shi-MAD. +** Special thanks to Niggle, FIRST, yamapu ... +** +**--------------------------------------------------------------------------- + +* Include Files ----------------------- * + + .include doscall.mac + .include iocscall.mac + + +* Global Symbols ---------------------- * + +* +* C言語用 外部宣言 +* + .xref _Initialize, _AddList, _SearchList, _DeleteList ;main.c + .xref _GetMacAddr, _SetMacAddr ;scsictl.c + .xref _SendPacket, _SetPacketReception ;scsictl.c +* .xref _AddMulticastAddr, _DelMulticastAddr ;未実装 + +* +* C言語用 外部変数 +* + .xref _num_of_prt ;main.c 登録プロトコル数 + .xref _trap_no ;使用trapナンバー + .xref _trans_counter ;scsictl.c 送信/受信バイト数 + .xref _intr_type ;scsictl.c 割り込み種別 + .xref _poll_interval ;scsictl.c ポーリング間隔 + + +* Text Section -------------------------------- * + + .cpu 68000 + .text + + +* +* デバイスヘッダー +* +device_header: + .dc.l -1 ;リンクポインター + .dc $8000 ;device att. + .dc.l strategy_entry ;stategy entry + .dc.l interupt_entry ;interupt entry + .dc.b '/dev/en0' ;device name + .dc.b 'EthD' ;for etherlib.a + .dc.b 'RASC' ;driver name (この後にエントリーを置く) + +* 'RASC' から superjsr_entry の間には何も置かないこと + +* +* イーサドライバ 関数 エントリー ( for DOS _SUPERJSR ) +* in: d0: command number +* a0: args +* +superjsr_entry: + movem.l d1-d7/a1-a7,-(sp) + +* move.l d0,-(sp) +* pea (mes11,pc) +* DOS _PRINT +* addq.l #4,sp +* move.l (sp)+,d0 +* .data +*mes11: .dc.b 'en0:spjEntry',13,10,0 +* .text + + bsr do_command + movem.l (sp)+,d1-d7/a1-a7 + rts ;普通のリターン + + +* +* イーサドライバ 関数 エントリー ( for trap #n ) +* in: d0: command number +* a0: args +* +_trap_entry:: + movem.l d1-d7/a1-a7,-(sp) + +* move.l d0,-(sp) +* pea (mes10,pc) +* DOS _PRINT +* addq.l #4,sp +* move.l (sp)+,d0 +* .data +*mes10: .dc.b 'en0:trapEntry',13,10,0 +* .text + + bsr do_command + movem.l (sp)+,d1-d7/a1-a7 + rte ;割り込みリターン + + +* +* 各処理ふりわけ +* +do_command: + moveq #FUNC_MIN,d1 + cmp.l d0,d1 + bgt error ;d0<-2 なら未対応コマンド番号 + moveq #FUNC_MAX,d1 + cmp.l d1,d0 + bgt error ;9 + bsr _SetPacketReception ;割り込み許可 ... scsictl.c + addq.l #4,sp + +* moveq #0,d0 ;SetPacketReception() で常に 0 が返るので省略 +set_int_addr_rts: + rts + + +* +* コマンド 06: 割り込みハンドラのアドレス取得 +* return: interupt address +* +get_int_addr: +* pea (mes07,pc) +* DOS _PRINT +* addq.l #4,sp +* .data +*mes07: .dc.b 'GetIntAddr',13,10,0 +* .text + + pea (a0) + bsr _SearchList + addq.l #4,sp + rts + + +* +* コマンド 07: 割り込みハンドラの削除 +* return: 0 (if no errors) +* +del_int_addr: +* pea (mes06,pc) +* DOS _PRINT +* addq.l #4,sp +* .data +*mes06: .dc.b 'DelIntAddr',13,10,0 +* .text + + pea (a0) + bsr _DeleteList ;main.c 関数 + move.l d0,(sp)+ + bmi del_int_addr_ret ;削除失敗 + + tst.l (_num_of_prt) ;ハンドラが一つもなくなれば割り込みを禁止する + bne del_int_addr_ret + + clr.l -(sp) ;0=<禁止> + bsr _SetPacketReception ;割り込み禁止 ... scsictl.c + addq.l #4,sp + +* moveq #0,d0 ;SetPacketReception() で常に 0 が返るので省略 +del_int_addr_ret: + rts + + +* +* コマンド 08: マルチキャストアドレスの設定 +* +set_multicast_addr: +* pea (mes08,pc) +* .data +* DOS _PRINT +* addq.l #4,sp +*mes08: .dc.b 'SetMulticastAddr',13,10,0 +* .text + + moveq #0,d0 + rts + + +* +* コマンド 09: 統計読み出し +* +get_statistics: +* pea (mes09,pc) +* DOS _PRINT +* addq.l #4,sp +* .data +*mes09: .dc.b 'GetStatistics',13,10,0 +* .text + + moveq #0,d0 + rts + +* +* デバイスドライバエントリー +* +strategy_entry: + move.l a5,(request_buffer) + rts + + +interupt_entry: + move.l sp,(stack_buff) ;自前のスタックエリアを使う + lea (def_stack),sp ; + + movem.l d1-d7/a0-a5,-(sp) + movea.l (request_buffer,pc),a5 + tst.b (2,a5) + bne errorret + + pea (mestitle,pc) + DOS _PRINT + addq.l #4,sp + movea.l (18,a5),a4 +@@: + tst.b (a4)+ + bne @b + + moveq #0,d0 + move.l d0,(_trap_no) + move.l d0,(_intr_type) + moveq #1,d0 + move.l d0,(_poll_interval) + +arg_loop: + move.b (a4)+,d0 + beq arg_end + cmpi.b #'-',d0 + beq @f + cmpi.b #'/',d0 + bne param_errret +@@: + move.b (a4)+,d0 + beq param_errret +opt_loop: + andi.b #$df,d0 + cmpi.b #'I',d0 + beq opt_i + cmpi.b #'P',d0 + beq opt_p + cmpi.b #'T',d0 + beq opt_t + cmpi.b #'N',d0 + beq opt_n + bra param_errret + +opt_n: + moveq #-1,d0 + move.l d0,(_trap_no) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +opt_t: + bsr get_num + tst.b d0 + bne param_errret + cmpi #6,d2 + bgt param_errret + move.l d2,(_trap_no) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +opt_p: + bsr get_num + tst.b d0 + bne param_errret + cmpi #1,d2 + blt param_errret + cmpi #8,d2 + bgt param_errret + move.l d2,(_poll_interval) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +opt_i: + bsr get_num + tst.b d0 + bne param_errret + cmpi #1,d2 + bgt param_errret + move.l d2,(_intr_type) + move.b (a4)+,d0 + beq arg_loop + bra opt_loop + +arg_end: + bsr _Initialize ;main.c 関数 + ;I/Oアドレス設定 + ;MACアドレス取得 + ;プロトコルリスト初期化 + ;SCSICTL初期化 + ;割り込みハンドラ(ベクタ設定) + ;trapサービス(ベクタ設定) + tst.l d0 + bne errorret + +* moveq #0,d0 + move.l #prog_end,(14,a5) + bra intret + + +param_errret: + pea (mesparam_err,pc) + DOS _PRINT + addq.l #4,sp +errorret: + move #$5003,d0 +intret: + move.b d0,(4,a5) + lsr #8,d0 + move.b d0,(3,a5) + movem.l (sp)+,d1-d7/a0-a5 + + movea.l (stack_buff,pc),sp ;スタックポインタを元にもどす + rts + +get_num: + moveq #1,d0 + moveq #0,d1 + moveq #0,d2 +@@: + move.b (a4),d1 + subi.b #'0',d1 + bcs @f + cmpi.b #9,d1 + bgt @f + move.b #0,d0 + andi #$f,d1 + mulu #10,d2 + add d1,d2 + addq.l #1,a4 + bra @b +@@: + rts + + +* Data Section ------------------------ * + + .data +mestitle: + .dc.b 13,10 + .dc.b 'RaSCSI Ethernet Driver version 1.20 / Based on ether_ne.sys+M01L12',13,10 + .dc.b 0 +mesparam_err: + .dc.b 'パラメータが異常です',13,10,0 + .even + + +* BSS --------------------------------- * + + .bss + .quad + +stack_buff: + .ds.l 1 +request_buffer: + .ds.l 1 +stack_buff_i: + .ds.l 1 + + +* Stack Section ----------------------- * + + .stack + .quad + +* +* スタックエリア +* + .ds.b 1024*8 +def_stack: + +prog_end: + .end + + +* EOF --------------------------------- * diff --git a/src/x68k/RASETHER/scsictl.c b/src/x68k/RASETHER/scsictl.c new file mode 100644 index 00000000..8d30dc6d --- /dev/null +++ b/src/x68k/RASETHER/scsictl.c @@ -0,0 +1,537 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット SCSI制御部 ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include "main.h" +#include "scsictl.h" + +typedef struct +{ + char DeviceType; + char RMB; + char ANSI_Ver; + char RDF; + char AddLen; + char RESV0; + char RESV1; + char OptFunc; + char VendorID[8]; + char ProductID[16]; + char FirmRev[4]; +} INQUIRY_T; + +typedef struct +{ + INQUIRY_T info; + char options[8]; +} INQUIRYOPT_T; + +#define MFP_AEB 0xe88003 +#define MFP_IERB 0xe88009 +#define MFP_IMRB 0xe88015 + +// asmsub.s 内のサブルーチン +extern void DI(); +extern void EI(); + +volatile short* iocsexec = (short*)0xa0e; // IOCS実行中ワーク +struct trans_counter trans_counter; // 送受信カウンタ +unsigned char rx_buff[2048]; // 受信バッファ +int imr; // 割り込み許可フラグ +int scsistop; // SCSI停止中フラグ +int intr_type; // 割り込み種別(0:V-DISP 1:TimerA) +int poll_interval; // ポーリング間隔(設定) +int poll_current; // ポーリング間隔(現在) +int idle; // アイドルカウンタ + +#define POLLING_SLEEP 255 // 4-5s + +/************************************************ + * MACアドレス取得命令発行 * + ************************************************/ +int SCSI_GETMACADDR(unsigned char *mac) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x28; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 0; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 6; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + if (S_DATAIN(6, mac) != 0) { +#else + if (S_DATAIN_P(6, mac) != 0) { +#endif + return 0; + } + + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * MACアドレス設定命令発行 * + ************************************************/ +int SCSI_SETMACADDR(const unsigned char *mac) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x2a; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 0; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 6; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + S_DATAOUT(6, mac); +#else + S_DATAOUT_P(6, mac); +#endif + + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * パケット受信サイズ取得命令発行 * + ************************************************/ +int SCSI_GETPACKETLEN(int *len) +{ + unsigned char cmd[10]; + unsigned char buf[2]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x28; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 1; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = 0; + cmd[7] = 0; + cmd[8] = 2; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + if (S_DATAIN(2, buf) != 0) { +#else + if (S_DATAIN_P(2, buf) != 0) { +#endif + return 0; + } + + S_STSIN(&sts); + S_MSGIN(&msg); + + *len = (int)(buf[0] << 8) + (int)(buf[1]); + + return 1; +} + +/************************************************ + * パケット受信命令発行 * + ************************************************/ +int SCSI_GETPACKETBUF(unsigned char *buf, int len) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x28; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 1; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = (unsigned char)(len >> 16); + cmd[7] = (unsigned char)(len >> 8); + cmd[8] = (unsigned char)len; + cmd[9] = 1; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + if (S_DATAIN(len, buf) != 0) { +#else + if (S_DATAIN_P(len, buf) != 0) { +#endif + return 0; + } + + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * パケット送信命令発行 * + ************************************************/ +int SCSI_SENDPACKET(const unsigned char *buf, int len) +{ + unsigned char cmd[10]; + unsigned char sts; + unsigned char msg; + + if (S_SELECT(scsiid) != 0) { + return 0; + } + + cmd[0] = 0x2a; + cmd[1] = 0; + cmd[2] = 1; + cmd[3] = 1; + cmd[4] = 0; + cmd[5] = 0; + cmd[6] = (unsigned char)(len >> 16); + cmd[7] = (unsigned char)(len >> 8); + cmd[8] = (unsigned char)len; + cmd[9] = 0; + if (S_CMDOUT(10, cmd) != 0) { + return 0; + } + +#ifdef USE_DMA + S_DATAOUT(len, buf); +#else + S_DATAOUT_P(len, buf); +#endif + S_STSIN(&sts); + S_MSGIN(&msg); + + return 1; +} + +/************************************************ + * MACアドレス取得 * + ************************************************/ +int GetMacAddr(struct eaddr* buf) +{ + if (SCSI_GETMACADDR(buf->eaddr) != 0) { + return 0; + } else { + return -1; + } +} + +/************************************************ + * MACアドレス設定 * + ************************************************/ +int SetMacAddr(const struct eaddr* data) +{ + if (SCSI_SETMACADDR(data->eaddr) != 0) { + return 0; + } else { + return -1; + } +} + +/************************************************ + * RaSCSI検索 * + ************************************************/ +int SearchRaSCSI() +{ + int i; + INQUIRYOPT_T inq; + + for (i = 0; i <= 7; i++) { + // BRIDGEデバイス検索 + if (S_INQUIRY(sizeof(INQUIRY_T) , i, (struct INQUIRY*)&inq) < 0) { + continue; + } + + if (memcmp(&(inq.info.ProductID), "RASCSI BRIDGE", 13) != 0) { + continue; + } + + // TAP初期化状態を取得 + if (S_INQUIRY(sizeof(INQUIRYOPT_T) , i, (struct INQUIRY*)&inq) < 0) { + continue; + } + + if (inq.options[1] != '1') { + continue; + } + + // SCSI ID確定 + scsiid = i; + return 0; + } + + return -1; +} + +/************************************************ + * RaSCSI初期化 関数 * + ************************************************/ +int InitRaSCSI(void) +{ +#ifdef MULTICAST + unsigned char multicast_table[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +#endif + + imr = 0; + scsistop = 0; + poll_current = -1; + idle = 0; + + return 0; +} + +/************************************************ + * RaSCSI 割り込み処理 関数(ポーリング) * + ************************************************/ +void interrupt IntProcess(void) +{ + unsigned char phase; + unsigned int len; + int type; + int_handler func; + int i; + + // V-DISP GPIP割り込みはアイドルカウンタで制御 + if (intr_type == 0) { + // アイドル加算 + idle++; + + // 次回の処理予定に到達していないならスキップ + if (idle < poll_current) { + return; + } + + // アイドルカウンタをクリア + idle = 0; + } + + // 割り込み開始 + + // 割り込み許可の時だけ + if (imr == 0) { + return; + } + + // IOCS実行中ならばスキップ + if (*iocsexec != -1) { + return; + } + + // 受信処理中は割り込み禁止 + DI (); + + // バスフリーの時だけ + phase = S_PHASE(); + if (phase != 0) { + // 終了 + goto ei_exit; + } + + // 受信処理 + if (SCSI_GETPACKETLEN(&len) == 0) { + // RaSCSI停止中 + scsistop = 1; + + // ポーリング間隔の再設定(寝る) + UpdateIntProcess(POLLING_SLEEP); + + // 終了 + goto ei_exit; + } + + // RaSCSIは動作中 + if (scsistop) { + scsistop = 0; + + // ポーリング間隔の再設定(急ぐ) + UpdateIntProcess(poll_interval); + } + + // パケットは到着してなかった + if (len == 0) { + // 終了 + goto ei_exit; + } + + // 受信バッファメモリへパケット転送 + if (SCSI_GETPACKETBUF(rx_buff, len) == 0) { + // 失敗 + goto ei_exit; + } + + // 割り込み許可 + EI (); + + // パケットタイプでデータ分別 + type = rx_buff[12] * 256 + rx_buff[13]; + i = 0; + while ((func = SearchList2(type, i))) { + i++; + func(len, (void*)&rx_buff, ID_EN0); + } + trans_counter.recv_byte += len; + return; + +ei_exit: + // 割り込み許可 + EI (); +} + +/************************************************ + * RaSCSI パケット送信 関数 (ne.sから) * + ************************************************/ +int SendPacket(int len, const unsigned char* data) +{ + if (len < 1) { + return 0; + } + + if (len > 1514) { // 6 + 6 + 2 + 1500 + return -1; // エラー + } + + // RaSCSI停止中のようならエラー + if (scsistop) { + return -1; + } + + // 送信処理中は割り込み禁止 + DI (); + + // 送信処理と送信フラグアップ + if (SCSI_SENDPACKET(data, len) == 0) { + // 割り込み許可 + EI (); + return -1; + } + + // 割り込み許可 + EI (); + + // 送信依頼済み + trans_counter.send_byte += len; + + return 0; +} + +/************************************************ + * RaSCSI 割り込み許可、不許可設定 関数 * + ************************************************/ +int SetPacketReception(int i) +{ + imr = i; + return 0; +} + +/************************************************ + * RaSCSI 割り込み処理登録 * + ************************************************/ +void RegisterIntProcess(int n) +{ + volatile unsigned char *p; + + // ポーリング間隔(現在)の更新とアイドルカウンタクリア + poll_current = n; + idle = 0; + + if (intr_type == 0) { + // V-DISP GPIP割り込みベクタを書き換えて + // 割り込みを有効にする + B_INTVCS(0x46, (int)IntProcess); + p = (unsigned char *)MFP_AEB; + *p = *p | 0x10; + p = (unsigned char *)MFP_IERB; + *p = *p | 0x40; + p = (unsigned char *)MFP_IMRB; + *p = *p | 0x40; + } else if (intr_type == 1) { + // TimerAはカウントモードを設定 + VDISPST(NULL, 0, 0); + VDISPST(IntProcess, 0, poll_current); + } +} + +/************************************************ + * RaSCSI 割り込み処理変更 * + ************************************************/ +void UpdateIntProcess(int n) +{ + // ポーリング間隔(現在)と同じなら更新しない + if (n == poll_current) { + return; + } + + // ポーリング間隔(現在)の更新とアイドルカウンタクリア + poll_current = n; + idle = 0; + + if (intr_type == 1) { + // TimerAは再登録必要 + VDISPST(NULL, 0, 0); + VDISPST(IntProcess, 0, poll_current); + } +} + +// EOF diff --git a/src/x68k/RASETHER/scsictl.h b/src/x68k/RASETHER/scsictl.h new file mode 100644 index 00000000..ae6bf477 --- /dev/null +++ b/src/x68k/RASETHER/scsictl.h @@ -0,0 +1,40 @@ +//--------------------------------------------------------------------------- +// +// SCSI Target Emulator RaSCSI (*^..^*) +// for Raspberry Pi +// +// Powered by XM6 TypeG Technorogy. +// Copyright (C) 2016-2017 GIMONS +// [ RaSCSI イーサーネット SCSI制御部 ] +// +// Based on +// Neptune-X board driver for Human-68k(ESP-X) version 0.03 +// Programed 1996-7 by Shi-MAD. +// Special thanks to Niggle, FIRST, yamapu ... +// +//--------------------------------------------------------------------------- + +#ifndef scsictl_h +#define scsictl_h + +// グローバル変数 +extern int intr_type; +extern int poll_interval; + +// 送受信カウンタ +struct trans_counter { + unsigned int send_byte; + unsigned int recv_byte; +}; +extern struct trans_counter trans_counter; + +extern int SearchRaSCSI(); +extern int InitRaSCSI(void); +extern int GetMacAddr(struct eaddr* buf); +extern int SetMacAddr(const struct eaddr* data); +extern int SetPacketReception(int i); +extern int SendPacket(int len, const unsigned char* data); +extern void RegisterIntProcess(int n); +extern void UpdateIntProcess(int n); + +#endif // scsictl_h