おことわり
実用性は全く追求していません。
内容は個人的活動の成果をもとにしていて、所属する組織とは特に関係ありません。
はじまり
できそうなんだけど誰もやらないんだよなー(そりゃそうだろう)と思うこと数年。
気まぐれでやってみました。
使い方
いるもの
- X68030
- メモリ12MByteまで増設済み + MC68030 + MC68882
- それなりに容量のあるHDD
当然ながら実機である必要はありません。
わたしはXM6 Type Gを使いました。
事前の用意
カーネル以外にルートファイルシステムの入ったHDDが必要なので用意します。
と言ってもX68030用のルートファイルシステムは存在しないので、他のm68kシステムのイメージを借りてくるか、自力で作ってください。
出来上がったイメージはHDDに書き込みます。
手順はこんな感じ
- Human68kのFORMAT.Xで領域確保
起動用のHuman68k / ルートファイルシステム用 / swap用
くらいに分けてください - ルートファイルシステム用のパーティションにイメージを書き込む
ddコマンドで書くのが速いです。が、Human68kから書きたい人もいるかもしれないということでimgwrt というユーティリティを用意しました。何も考えずに書けますが遅いです。
カーネルのビルド
X68k対応linux kernelのソースは
https://scm.osdn.net/gitroot/uclinux-h8/linux.git
のx68kブランチにあります。
微妙に古いのは、そのへんが最新だった頃に作り始めてその後更新していないだけです。
素直に最新をマージできるくらいの古さだと思うので、誰か挑戦してみてください。
ビルド手順は他と同じく
$ make menuconfig
$ make vmlinux.bin.gz
でできます。
x68kdefconfigを入れてあるので、それを下敷きにして構成してください。
vmlinux.bin.gzができたら、X68030環境のHuman68k領域に持っていきます。そのままだとHuman68kで扱えないので、適宜リネームするかTwentyOne.xに頼ってください。
ブートローダーの用意
まじめにIPLから起動できるブートローダーを用意する気力が足りなかったので、Human68kから起動します。
loadlin68k なるものを用意したので、これをビルドしてください。
gcc + libc環境であればmake出来るはず。
ハードウエア構成をbuild_bootinfoで設定しているので、実際の環境に合わせて適宜修正してください。
loadlin.xができたら同じくHuman68k領域に置いてください。
起動してみる
COMMAND.Xのプロンプトから、こんな感じで起動できます。
A>loadlin <カーネルファイル名> video=x68kfb root=/dev/sda2
ものすごく遅いので気長に待ってください。
おまけ
起動している様子
技術的なこととか
ここから本編です
きっかけ
上にも書きましたが、Personal Workstationを名乗っていてNetBSDが動いているならLinuxくらい動かなきゃいかんだろうという、どうでもいいような理由だけで作ってます。
技術は無駄遣いしないと面白くない主義なもので。
方針
動かすことに意義があるので、それなりに見れそうな最低限のところだけ作ることにします。
なので
必須
- シリアルポート
- タイマー
なくても動くけど、使えないと悲しいので作る
- 画面(最低限)
- キーボード
- SCSI HDD
作らない
- それ以外(音・マウスなど)
という感じでざっくりと対応範囲を決めます。
資料集め
ハードウエア周りの情報は便利な本 があるのでこれで足ります。
X68030固有の部分は触らなかったのでこっち は不要。
あとはarch/m68kの下をざっと眺めた結果、Atari STが比較的近い構成のようなのですが、Atariの資料は手に入らないので、検索してなんとかします。
68030なんだからTTのほうじゃないのかと思う人もいるかもしれませんが、困ったことにMPU以外は68000時代なままなのでSTのほうが近いのです。
と言ってもそこまで似ているわけではなく、強烈な個性を持ったハードウエアが多すぎるだけです。
開発環境
ということで必要な情報は揃ったので開発環境を用意します。
ハードウエアは前世紀のものですが、近代技術を使って出来る限り快適な開発環境を目指します。
X68030のエミュレーターはWindows用なので、素直に環境を作るのであればWindowsになるのですが、Linux kernelをWindowsでビルドするのはものすごく面倒くさいのでLinux環境で開発したいという面倒な状況です。
結局エミュレーター二階建てなこのようなややこしい構成で開発することにしました。
こうすると、Linux環境の/homeをHuman68kから読み書きできるようになるので、ビルドしたkernelを簡単に試せるために試行錯誤を繰り返すときのダメージが減ります。
調査
歴史的経緯なのか他のアーキテクチャと微妙に構造が違いますが、arch/m68kの下はこうなっています。
arch/m68k
├── 68000
├── amiga
├── apollo
├── atari
├── bvme6000
├── coldfire
├── configs
├── emu
├── fpsp040
├── hp300
├── ifpsp060
├── include
├── kernel
(略)
ということで、arch/m68k/x68kディレクトリを作って、その中にX68030依存部を入れてしまえばよいということになります。
依存部分の作り方の参考にatariの下を覗くとこんな感じ。
❯ ls arch/m68k/atari
Makefile atakeyb.c config.c nvram.c stram.c
ataints.c atasound.c debug.c stdma.c time.c
ファイル名でなんとなく想像できますが、ataints / timeあたりを作ればとりあえずは良さそう。
configの用途がよくわからないので中身を確認すると機種依存部分(初期化とか)のコードが詰まっていたので、これも必要です。
書いてみる
最低限シリアルポートとタイマが動いていて、そこから割り込みを受け取ることができていれば、initramfsをマウントしてinitを起動するところまでは動くので、最初のステップとしてそこまで作ります
タイマ
X68030のタイマはMFP(MC68901)で、ハードウエア的に用途が限定されていないものが2CHあります(Timer-C / D)。
で、ユーザーが自由に使っていいのはTimer-Dなので、こちらを使います。Clock Event Deviceとして登録するだけなので特に変わったことをする必要はありません。
シリアルポート
こちらはSCC(Z85C30)です。有名なチップなのでドライバがあるはず…と思って探してみると
❯ grep -l 85C30 drivers/tty/serial/*.c
drivers/tty/serial/pmac_zilog.c
drivers/tty/serial/zs.c
なぜか2個見つかるという…(これに引っかからなかったけどもう一個ありました)zs.cの方は使い方がいまいちわからないので、今はなきモトローラつながりでpmac_zilogの方を使います。
X68030依存部でplatform_deviceにSCCのアドレスを設定するだけで動くようになりました。今どきはDeviceTreeで書いておけばいいんですが、古いのでそんな便利な機能はないのですね。
割り込み
割り込みコントローラーの制御をしないといけないのですが、X68030にはPICのような割り込みコントローラーというものがない(エンコーダー入ってますが、ソフトウエア的にやることがない)ので、割り込みベクタだけ設定します。
起動させる
ということで最低限必要な部分が出来たので起動させてみます。
というところでどうやって起動すればいいのか調べてなかったことに気がついたので調べます。
arch/m68k/kernel/vmlinux-std.ldsがリンカスクリプトで、それを見ると0x1000にvmlinuxをロードして_startに飛べば良さそうです。
が、0x1000あたりはHuman68kが使っていたような気がするので、一回別の場所に読み込んだあとでこちらに移動→_startにジャンプしないといけません。
あとはカーネルコマンドラインの渡し方とかも確認します。
arch/m68k/kernel/head.Sに_startがあるので眺めてみます。なにやらvmlinuxの最後尾にbootinfoなる構造体を埋めておけば良いようです。
bootinfoには機種名/CPU/FPU/メモリサイズ/コマンドラインをいれます。今どきのやり方ならDeviceTree以下略
ということで、調べた結果をもとにHuman68kでvmlinuxをロード・再配置・_startにジャンプするだけのブートローダーをつくります。
で、このへん調べたときに見落としていたのですが、head.Sでは機種依存の透過変換を設定しないといけないようで、I/O用に0xFF000000以降を透過変換するように設定します。
ここまでできるとシリアルコンソールでinitを起動するあたりまで動いていることが確認できるので、頑張ってinitがないpanicメッセージにたどり着けるよう直します。
続書いてみる
initを起動するくらいまで動けばほぼ問題なく動きそうな雰囲気なので、残りの必須じゃないドライバ類を用意します。
ちなみに普段は触らないところばかりなので完全に未知の世界です。
画面(フレームバッファ)
当然ながらドライバはないので新しく用意しないといけません。
参考にできそうなものが全部パックドピクセルだったため、(遅くなるのを覚悟の上で)何も考えずグラフィック画面をフレームバッファにします。Atariのドライバがプレーンタイプなので読み取ってみようと思ったのですが、仕様が見当たらなくて断念。
あと、グラフィック画面だけを使うために画面モードを再設定しないといけないのですが、自力でビデオ周りを再設定するのも面倒なので、IOCSを使えるうちにブートローダー側に設定してもらうことにして、ドライバはVRAMを見せることだけに注力しています。
キーボード
こちらも同じく。といってもUSBじゃないキーボードはどこでも同じくキーボードとシリアル通信しているだけなので、ドライバは簡単です。
X68030の場合はMFPのUARTにキーボードのデータが届くので、それを受け取って上位のドライバに渡すと良きに計らってくれます。
あとはキーボードの送ってくるデータを内部で扱う共通のコードに変換するテーブルを書く必要があります。
が、X68030のキーボードは個性的なのでどう割り当てるべきかとても悩ましいところが…ということでアルファベット以外は適当にすませます。
アルファベットと一部記号がちゃんと入力できればなんとか操作できるでしょう。
ハードディスク
X68030のハードディスクはSCSIなので、SCSIホストインタフェースのドライバを書けば読み書きできるようになります。
で、ホストインタフェースは富士通のMB89352ということで国内ではそこそこ使われていたはずですが、海外では無名なので当然ながらドライバは標準では入っていません。一応古いkernel用のドライバは入手できるようですが、古すぎてそのままでは使えず…ということなので諦めて書きます。
今はなき(ないよね)AHA-1520のドライバが近そうな気がするということで、検索したら出てきたデータシートを読みつつMB89352用に直します。
で、正しく作るのであればデータの転送はDMACにまかせるべきなのですが、X68030の構造的にCPUでも転送できそうということで、CPUに頑張ってもらっています。そういう使い方を想定しているわけではないと思うので実ハードウエアで問題ないのか若干疑問ですが(XM6のソースを見ても何もしていないような気がする)、まあ大丈夫でしょう。
Human68kとの同居
ハードディスクはこれで読み書きできるのですが、このままではHuman68kと同居できないので、起動用のドライブとrootfsを置くドライブを分けないといけません。
それはそれで面倒くさいのでHuman68kと同居できるようX68000のパーティションを扱えるようにして、何も考えずに同居できるようにします。
パーティションの考え方は一般的なものと全く同じなので、ディスク上にFORMAT.Xが書いてくれた情報を読んできて、パーティションの一覧表を返すだけです。
ということで
これくらい作ってそれなりに動くようになりました。
手抜きが激しいので、もうちょっとまじめに作りたいなーという思いもありますが、優先順位がI/Oコントローラーの割り込みと同じくらいなので、気が向いたらになると思います。
がソースを一式公開してあるので、元気な若者(いるのか?)に頑張って欲しいなあと思います。