PIC(Programmable Interrupt Controller)とは、通常CPUでは割込みを1つしか扱うことができないので、(すなわちCPUの一つのピンに一つの装置しかつなげないということ)
それを解決するために付加した補助チップであり、「設定可能な割込みコントローラー」。
PICには8つのIRQを扱うことが出来る。またIRQ2にはスレーブにつながって計15個の装置を観測できる。
PIC0はマスターPIC、PIC1はスレーブPIC。
IMR(Interrupt Mask Register)はPIC内の割込み目隠しレジスタと呼ばれる8ビットレジスタ。
それぞれのビットがIRQ信号のそれぞれのピンに対応している。IMRが1になっているビットは対応するIRQ信号を無視する。
これはつながってない装置のIRQを無視したり、割り込みに関する設定をいじるときに反応する。
ICW(Initial Control Word)は初期化制御データ。ICW1とICW4はPICの基板上の配置、割込み信号の電気特性について。
ICW3はマスタとスレーブ間の接続についての設定。マスタに対しては何番のIRQにスレーブがつながっているかを示す。ここでは2番につながっているので00000100がセットされる。
スレーブの方はマスタの何番につながっているかを示す。
ICW2はよくわからん。IRQをどの割込み番号としてCPUに通知するかを決める???
割込み発生時に行う処理が記述されている。まずはアセンブラ側の記述から見ていく。
レジスタの内容をスタックに格納しておき、割込みハンドラをコールする。割込みハンドラはC言語で記述。
harib03eのキーボード割込みは左上に黒い枠を作成し、そこに文字列を記述する。マウスも同様なはずなのだが…
ちなみにinit_gtdidt内で作成した割込みハンドラをIDTに登録しておくことを忘れない。
inthandler21のio_out8(PIC0_OCW2, 0x61)というのはIRQ1が発生したことをPICを通知する処理を行う。
基本的にOCW2に0x60+IRQ番号をoutしてやればよい。通知してやるとPICは装置の変化を再び監視する。逆に言うとこの通知をしないとPICは装置の変化を無視した状態になってしまい、ユーザには入力を受け付けていないように見える。
次に装置番号0x0060から8ビットを入力する。これがキーコードであり、現時点ではこれをスクリーンに表示する。
割込み処理中は他の割込みが受け付けられないので、素早く行う必要がある。
現状では割込み処理中にVRAMにデータを128回書き込みを行っている。これは非常に時間のかかる処理である。次にmainへ。
main内の無限ループないではとりあえずcliで割込み処理禁止フラグを立てる。そしてキーコード用バッファのフラグをチェック。
フラグが立っていない場合は割込み許可フラグをセットしHLTする。ちなみHLT中はCPUが休眠してる状態であるが、割り込みが発生するとCPUは動作を開始、すなわちループを回していくことになる。
そしてまたもやCLIを行うわけだ。
キーコードバッファフラグが立っている場合は、ローカル変数にkeybufのデータを入れてkeybufのフラグをおろす。
そして割込み許可フラグを立てる。そしてharib04a同様キーコードを表示する。
そこで割込み処理中ではキーコードを変数に格納するだけにとどめて、描写はmainで行うように処理を変更する。
とりあえずchar型のデータ、フラグ、計1バイトのバッファを用意。割込み処理中ではバッファにキーコードを入れておき、フラグを立てる。
右CtrlキーのキーコードはE0 1D(ちなみに左Ctrlは1Dの1バイト)なのだが、本プログラムでは2バイト目が読み捨てられてしまう。
前節の問題点を解消するため、バッファのデータを拡張。取り出し側ではずらしながらとりだす。
疑問点は2バイトのデータがデバイスから入力される割込み発生時、どのように動くのか?
ずらし方式は処理が重いのでループ方式をつかいまつ。
マウスは比較的新しいデバイス。CPUとデバイスの間にマウス制御回路が仲介する。
しかし初期状態はデバイスも制御回路も機能していないので、有効化命令を発する必要がある。まずは制御回路から有効化する。
マウス制御回路はキーボード制御回路の中に存在する。
キーボード制御回路の初期化。まずはキーボードコントローラーが送信可能になるまで待機。
まずはキーボードコントローラにモード設定し、マウス制御回路を起動する。
次にマウスを有効化する。マウスへデータを送信する準備を行い、次にマウスの有効化命令を送信する。