Skip to content

Commit

Permalink
Add documents
Browse files Browse the repository at this point in the history
  • Loading branch information
yunkya2 committed Mar 4, 2024
1 parent ade40e3 commit d199ef3
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
34 changes: 34 additions & 0 deletions Internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
ループバックデバイスドライバの内部処理について
=========================================

## ディスクI/Oドライバ処理の修正

Human68k の通常のファイルアクセスは、DOS コールの処理ルーチンがファイルシステムの解釈を行い、ディスクI/Oドライバを通してセクタをの読み書きを行います。
ディスクI/OドライバはI/Oバッファキャッシュの管理も行っていて(CONFIG.SYSのBUFFERS=で指定した数のバッファがここで管理されます)、既にデータがバッファ上にあればそれを利用し、なければブロックデバイスドライバを呼んで、ディスクドライブなどのデータの読み書きを行います (下図の青点線)。

ループバックデバイスの原理はシンプルで、ディスクI/Oドライバからのデータ要求に対してデバイスをアクセスする代わりに、他のドライブのファイルシステム上にあるファイルをアクセスしているだけです。
デバイスドライバの中からはDOS _SEEK, _READ, _WRITEといったDOSコールが呼び出され、既にオープンされているイメージファイルの内容をディスクのセクタに見立てて読み書きを行います (下図の赤点線)。

ここで問題になるのが、ループバックデバイスのアクセスによって、ディスクI/Oドライバのデータ読み書き処理の中から再帰的に同じディスクI/Oドライバが呼び出されてしまうことです。
ディスクI/OドライバはI/Oバッファキャッシュを双方向リンクリストで管理しているのですが、アクセスの最中にリストの繋ぎ変えが発生するため、再帰的に呼び出されることで繋ぎ変え途中のリンクリストが書き換えられ、結果としてバッファのリンクリストが壊れてしまいます。

loopdrv.sys ではこのような事態を防ぐため、Human68k オリジナルのディスクI/Oドライバの一部を差し替えて、再帰呼び出し時にも正常に動作するようにしています。
FASTIO.X のようなディスクI/Oドライバはこの処理を丸ごと外部のものと差し替えてしまうため、loopdrv.sys との共存ができないわけです。

![loopdrv](images/loopdrv.png)

## イメージファイルのファイルディスクリプタ

ループバックマウントしたイメージファイルは、マウントされている間ずっとファイルがオープンされたままになっています。
loopdrv.sys 自身はファイルのオープンを行わず、ただ与えられたファイルディスクリプタへのアクセスを行うのみで、ファイルオープンは losetup.x が行います。

通常、プロセスがオープンしたファイルはそのプロセスが終了する際にすべてクローズされてしまいますが、losetup.x はそれを避けるため、終了前に自身のプロセス管理ポインタ (PSP) に格納されている「プロセスのファイルハンドラの使用状況」ビットを0に落とすことで、プロセス終了後もファイルがオープンされたままになるようにしています。

Human68k はファイルハンドラの使用状況を各プロセスごとだけでなくOS全体でも別途管理しているため、オープンされたままのディスクリプタが他のファイルオープンによって使われることはありません。
ただし、Human68kはシングルタスクOSでプロセス間のファイルハンドラの保護も特に行っていないため、ディスクリプタ値を直接指定することで他のプロセスがオープン中したファイルを勝手に読み書きやクローズすることもできてしまうので、注意が必要です。

## 参考文献

* [ぷにぐらま~ずまにゅある](https://github.com/kg68k/puni) by 立花@桑島技研 氏
* [fs_ospatch.txt](https://github.com/kg68k/puni/blob/main/fs_ospatch.txt)
* [oswork.txt](https://github.com/kg68k/puni/blob/main/oswork.txt)
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
X680x0 ループバックデバイスドライバ loopdrv
=========================================

## 概要

ループバックデバイスは、ファイルシステム上にある通常のファイルをディスクドライブのようなブロックデバイスに見せかけるための仕組みです。
Linux などの OS がこの機能をサポートしていますが、本ドライバはこの機能を X680x0 の Human68k 上で実現するためのものです。

# 使用方法

本ドライバは、Human68k に組み込むドライバ本体 loopdrv.sys と、ループバックデバイスを操作するためのコマンド losetup.x からなります。

## デバイスドライバのインストール

まず、CONFIG.SYS に以下の記述を追加して loopdrv.sys を組み込みます。

```
DEVICE = LOOPDRV.SYS [/u<ユニット数>] [/r]
```
* `/u<ユニット数>` には、ループバックデバイスのために予約するドライブのユニット数を 1~8 の値で指定します。省略した場合はユニット数 1 となります。
* `/r` は、ループバックデバイスのマウント時のデフォルトを読み込み専用にします。
(読み込み専用/読み書き可能はlosetupコマンドで切り替えられます)。

loopdrv.sys を組み込んで起動すると、以下のメッセージが出てループバックデバイスが利用できるようになります。

```
Loopback device driver for X680x0 version xxxxxxxx
ドライブX:でループバックデバイスが利用可能です
```

## losetup コマンドによるループバックデバイスの操作

ループバックデバイスの操作は losetup コマンドで行います。

* losetup
* ループバックデバイスの現在の設定状態を表示します。
* losetup -h
* コマンドの使い方を表示します。
* losetup -D
* マウントされているすべてのループバックデバイスをアンマウントします。
* losetup -d <ドライブ名>
* `<ドライブ名>` で指定したループバックデバイスをアンマウントします。
* losetup [-r][-w] <ドライブ名>
* `<ドライブ名>` で指定したループバックデバイスの状態を変更します。
* `-r` : ドライブを読み込み専用にします
* `-w` : ドライブを読み書き可能にします
* losetup [-r][-w] <ドライブ名> <イメージファイル名>
* `<ドライブ名>` で指定したループバックデバイスに `<イメージファイル名>` のファイルをマウントします。
* `-r` : 読み込み専用でマウントします。
* `-w` : 読み書き可能でマウントします。
* イメージファイルのヘッダやファイルサイズ等から判断して、以下のいずれかのデバイスとしてマウントします。
* フロッピーディスク
* 2HD (1232kB)
* 2HC (1200kB)
* 2HQ (1440kB)
* 2DD (640kB)
* 2DD (720kB)
* イメージファイルはベタイメージ(XDFファイル)、DIMファイル、D88/D68ファイルに対応しています。
* SASIハードディスク (HDFファイル)
* SCSIハードディスク (HDSファイル)/MOディスク (MOSファイル)

# 制約と注意事項

* Human68k v3.02 専用です。他のバージョンでは使用できません。
* FASTIO.X のような、Human68kのディスクI/Oバッファ処理を変更するドライバとは共存できません。
* loopdrv.sys は自分自身以外のドライバがバッファI/O処理を差し替えていることを検出すると、安全のためすべてのループバックデバイスへの操作を無効にします。
* ハードディスクのイメージファイルに複数のパーティションが切られている場合、最初のパーティションのみがマウントされます。
* ループバックマウントしたドライブをフォーマットする際は、FORMAT.X に必ず `/C` オプションを付けて論理フォーマットのみを行うようにしてください。
* FORMAT.X は、メディアバイトがフロッピーディスクであるドライブに対して通常のフォーマットを行うと、そのドライブのユニット番号と同じ番号のディスクドライブに対して物理フォーマットを行ってしまうようです。
* つまり、LOOPDRV.SYS で用意された最初のドライブ(ユニット番号0)をフォーマットすると、フロッピーディスクドライブ0 が物理フォーマットされてしまうということです。たまたまその時ドライブにディスクが入っていると、そのままディスクが物理フォーマットされてしまいます。
* 事故を防ぐため、ループバックデバイスに対してのフォーマット操作はできるだけ避けて、エミュレータ等で作成したフォーマット済みのイメージファイルを使用することをお勧めします。

# 謝辞

Human68k のディスクI/Oバッファの仕組みについては、ぷにぐらま~ずマニュアル https://github.com/kg68k/puni (立花@桑島技研 さん作) の [fs_ospatch.txt](https://github.com/kg68k/puni/blob/main/fs_ospatch.txt) が参考になりました。感謝します。
Binary file added images/loopdrv.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d199ef3

Please sign in to comment.