デバイスドライバってどうやって作るの?
- (by K, 2008.03.01)
- 発展課題のページ(全部読む前にここを読むのは混乱するのでおすすめじゃないです)
- 読者の人と話す機会があったのですが(OSC2008東京春)、なにやらデバイスドライバを作りたいと思っても何をどうしていいか分からないそうです。うーん、そんなに難しいかなあ。難しく考えすぎなんじゃないかなあ、なんて思っていたら帰りのバスで分かりやすそうな方法を思いついたので紹介しておきます。他のOSがどんな風にデバイスドライバを用意しているのかは知りませんが(いや少し知っているけどそんなことはどうでもいい)、わざわざ難しい方法をここで紹介してもしょうがないので、とにかく簡単に楽しくやってみます。
- まずデバイスドライバを作るってなんでしょうか。そもそも今の「はりぼてOS」だってデバイスドライバはあるんです。キーボードドライバとかですね。でもここで言っているのはそういうことじゃなくて、OSの中には入っていないデバイスドライバを作りたいわけです。アプリみたいにOSとデバイスドライバを分けたいわけです。まあここまではいいです。
- でもどうして分けたいのでしょうか。それを考えてみたことがある人がどれだけいるか分かりませんが、他のOSでは分かれているから自分のOSでも分けてみたい、なんていう理由はさすがにあんまりです。そんな理由ではやる気が出ません。・・・たとえばOSとデバイスドライバが分かれていると、デバイスドライバのバグを直すときに、OSをmakeしなおす必要がありません。またデバイスドライバを交換するだけで(OSをmakeしなおさなくても)、デバイスの制御方法を変えることができます。
- つまり何が言いたいのかというと、デバイスドライバの開発をやり直してバグを取らなきゃいけないとか、もしくは複数のデバイスドライバがあってそれを交換できるようにする予定が無い限り、以下の改造はやる意味がないです。というかデバイスドライバをOSから切り離せばそれだけ仕組みが複雑になるのは避けられないので、今までどおりの使い方しかないのなら、以下の改造はOSが遅くて大きくなるだけです。それは「進化」ではなく「退化」です。そのような退化を繰り返せば、ただ大きくて使わない機能ばかりあるどこぞのOSに近づくだけです。だから自分がどんなOSにしたいのかをよく考えてくださいね。
仕組み
- さてそれではやってみます。OSと別々にコンパイルして実行するためにはどうしたらいいのかというと、結局アプリと同じような仕組みにするのがいいのではないかと筆者は考えました。これなら説明も要りませんしね。それにアプリの仕組みを考えた時だって、OSとは別々にmakeできるようにするためにはどうしたらいいかって考えて決めたのですから、同じ目的のために同じ方法を使うのは理にかなっていると思います。
- ただ完全に同じだとOSからみてそのファイルがアプリなのかドライバなのか区別できなくて、そうなると人間の操作ミスで一気におかしくなるかもしれません、でもそんなのはいやです。ってことで、拡張子を.HDVにして、ファイルのフォーマットの中のマークは"HrDv"にすることにします。これでドライバファイルを間違って実行してしまうことはないはずです。
- アプリではAPIを作ってそれを呼び出していました。ドライバでも似たような仕組みが無いとOSとやり取りできないのでドライバとしての仕事ができません。でもドライバはウィンドウを出したり文字を書いたりすることは重要ではなくて、むしろもっと特別な機能が必要だと考えました。それをAPIに追加してももちろんいいのですが、そうするとアプリがこれらの特別な機能を間違って呼び出して混乱しそうなので、あえて分けることにします。INT 0x41を使うことにしましょう。これはアプリケーション・プログラム・インターフェースというよりは、ドライバ・プログラム・インターフェースというほうが近いと思うので、DPIと呼ぶことにします(註:多分こんな言い方は一般的ではない)。
- ドライバはアプリみたいに保護するといろいろできないことが出てきて不満かもしれないので、OSと同じセグメント属性にしようと最初は思いました。でもそうすると、harib18dのときみたいな改造が必要になりそうで、なんかめんどくさくなったのでやめました。ドライバもアプリモードで動いてもらいます。ただこれだとIN命令やOUT命令やSTIやCLIが実行できなくなってドライバが作りにくそうなので、ドライバが起動するときのEFLAGSの値を変更して、アプリモードでもI/O命令を実行できるように特別に設定します(IOPLを11にする。p.89参照)。
- DPIはこんな感じで作ります。とりあえず3つあればいいかな。
- EDX = 1 : IRQ処理関数登録
- EAX = 関数の番地、ECX = IRQの番号、EBX = 割り込み処理用のESP
- EDX = 2 : FIFOにデータを送信
- EAX = データ、ECX = FIFOの番地
- (実際に送るときは+256される:api_getkeyで-256されるため)
- EDX = 3 : 自分のFIFOの番地を知る
- EDX = 4 : キー入力をOSに通知
- EDX = 5 : マウス入力をOSに通知
bim2hdv
OS側の改造
- 長くなったのでページを分けました。 → advance/driver/01
- 長くなったのは難しいからじゃなくて、アプリと似たような処理を書いたら長くなっただけです。
- 共通化できる部分をまとめたほうがいいとは思いますが、それをやると変更箇所が分散してさらに説明が面倒になるので今回はやめました。興味がある人は各自いろいろやってください。
キーボードドライバの作成
注意?
- この方法でキーボードドライバを作ってしまうと、OS起動時にキーボードドライバが組み込まれていないことになるので、キー入力ができません。だったらどうやってキーボードドライバを起動するのさ!(笑)。
- ということでadvance/startupも組み込んでおいて、起動時にキーボードドライバをncstで起動するようにしてください。
こめんと欄
- USBドライバも掲載おねがいします -- aaa 2008-03-04 (火) 17:26:24
- advance/driver/01のint.cのstart_appの下にあるload_ldtrはstore_ldtrの間違いだと思います。load_ldtrは引数を指定しないと思います。 -- Triangle Ld. 2009-09-14 (月) 15:40:15
- あの、aaaさん。Kさんは、ここでは簡単なデバイスドライバの作り方(OS側)を教えていて、キーボードドライバはテスト用に、作ってみようということで作ったものです。そのほかの、USBドライバとかは、自分で調べて作るものです。 -- Triangle Ld. 2009-09-14 (月) 15:43:39
- driver/02で dpilib.hが出るのにこれも apilib.hに似ているんでしょうか? -- Kor_Lee_Hee_Rak 2009-09-15 (火) 13:27:23
- 形は同じです。api_???がdpi_???になったくらいで、やっぱり作った関数をそのまま並べれば簡単です。 -- Triangle_Ld. 2009-09-16 (水) 19:29:50
|