* PIC 8259Aのページ [#u6487e56]
-PICは「Programmable Interrupt Controller」の略
-つまり割り込みコントローラ。IRQ周りの大事なところ。
-AT互換機、TOWNS、PC-9801とも、2個ずつ入っている(98には一部例外があったかもしれない)。
-たいていこれらの機種にはIRQ0~IRQ15の16種(厳密には15種)の割り込みがあると思いますが、CPUはこれらの割り込み信号を直接には管理していません。CPUにはIRQ関係の信号線は1つしかなく、それが15もあるように見えるのは、このPICのおかげなのです。
-基本的にPICは、8つの割り込み信号を監視して1つの信号線にまとめる能力があります。しかし、これだとIRQ0-7までしか使えないことになって割り込み不足になるので、もう一つ子供のPICを用意して、その割り込み通知ピンを親のIRQピンにつないでいます。こういう接続の仕方をカスケード接続といいます。この方法をもっと押し進めれば最大で64個のIRQをサポートできますが(スレーブ8個)、そんなマシンは無いようです。また8259Aは3段重ねはサポートしていないようです。
CPU ---1本--- PIC(マスタ:IRQ0-7)
+------ IRQ
+------ IRQ
+------ IRQ
+------------ PIC(スレーブ:IRQ8-15)
+------ IRQ
+------ IRQ
+------ IRQ
+------ IRQ
(註)図の簡略化のため、PICからは4本のIRQ線しか書いていませんが、本当は8本です。
-このような仕組みのため、マスタに直接つながっている割り込みと、スレーブにつながっている割り込みとでは、いろいろ扱いが変わります。マスタにつながっているやつのほうが簡単です(マスタだけいじればいいので)。
* 関係するI/Oポートなど [#y73bdf76]
*** AT互換機 [#l114d49d]
|アドレス(hex)|wide|R/W|デバイス|説明|備考|
|0020|byte|R|PIC-0|IRR/ISR||
|0020|byte|W|PIC-0|OCW2/OCW3/ICW1||
|0021|byte|R|PIC-0|IMR||
|0021|byte|W|PIC-0|OCW1/ICW2/ICW3/ICW4||
|00A0|byte|R|PIC-1|IRR/ISR||
|00A0|byte|W|PIC-1|OCW2/OCW3/ICW1||
|00A1|byte|R|PIC-1|IMR||
|00A1|byte|W|PIC-1|OCW1/ICW2/ICW3/ICW4||
-PIC-0がマスタ(IRQ0-7)、PIC-1がスレーブ(IRQ8-15)
-基本的にエッジトリガモードで使用するように設計されている(PCIサポート以降では、チップセットで部分的にレベルトリガにもできるが、とにかくPICに対してはエッジトリガで設定する):ICW1参照
-割り込み番号表
|IRQ0|タイマ|
|IRQ1|キーボード|
|IRQ2|スレーブとのカスケード接続に使用|
|IRQ3|シリアルポート(COM2)|
|IRQ4|シリアルポート(COM1)|
|IRQ5|主にISA/PCI拡張デバイス用|
|IRQ6|FDC|
|IRQ7|パラレルポート|
|IRQ8|RTC|
|IRQ9|主にISA/PCI拡張デバイス用|
|IRQ10|主にISA/PCI拡張デバイス用|
|IRQ12|マウス|
|IRQ13|FPU(?)|
|IRQ14|ATA-0|
|IRQ15|ATA-1|
--DOS/BIOSでは、IRQ0~7は INT 0x08~0x0f に割り当て。
--DOS/BIOSでは、IRQ8~15は INT 0x70~0x77 に割り当て。
--(まだ未完成)
*** TOWNS [#d69d78a2]
|アドレス(hex)|wide|R/W|デバイス|説明|備考|
|0000|byte|R|PIC-0|IRR/ISR||
|0000|byte|W|PIC-0|OCW2/OCW3/ICW1||
|0002|byte|R|PIC-0|IMR||
|0002|byte|W|PIC-0|OCW1/ICW2/ICW3/ICW4||
|0010|byte|R|PIC-1|IRR/ISR||
|0010|byte|W|PIC-1|OCW2/OCW3/ICW1||
|0012|byte|R|PIC-1|IMR||
|0012|byte|W|PIC-1|OCW1/ICW2/ICW3/ICW4||
-PIC-0がマスタ(IRQ0-7)、PIC-1がスレーブ(IRQ8-15)
-基本的にレベルトリガモードで使用するように設計されている:ICW1参照
-割り込み番号表
|IRQ0|タイマ|
|IRQ1|キーボード|
|IRQ2|RS-232C|
|IRQ3|拡張RS-232C|
|IRQ4|拡張ボード用|
|IRQ5|拡張ボード用|
|IRQ6|FDC|
|IRQ7|スレーブとのカスケード接続に使用|
|IRQ8|SCSI|
|IRQ9|内蔵CD-ROMドライブコントローラ|
|IRQ10|拡張ボード用|
|IRQ11|VSYNC|
|IRQ12|プリンタ|
|IRQ13|FM音源&PCM音源(註:レベルトリガなので割り込みが共存できる)|
|IRQ14|拡張ボード用|
|IRQ15|リザーブ|
* 概要 [#nb4cfb4a]
-IRR:インタラプトリクエストレジスタ
--IRQピンの状態を表す。ポートを読んだときに、IRRになるかISRになるかは、OCW3で選択する。
--1になっているビットは、現在要求が来ている(もしくは処理中の)割り込み。
-ISR:インサービスレジスタ
--現在処理中の割り込みがどれであるかを示す。ポートを読んだときに、IRRになるかISRになるかは、OCW3で選択する。
--1になっているビットは、現在処理中の割り込み。処理中というのは、CPUに対してINT命令を発行したが、EOI(割り込み終了命令)を受け取ってはいない割り込み。
-IMR:インタラプトマスクレジスタ
--これが1になっている割り込みは、IRRが1になっていても、反応しない。
---スペシャルマスクモード(OCW3参照)になっているときは、IMRの設定はIRRに対するマスクにはならない。つまり割り込みをマスクできない。
-OCW1:動作コマンドワード1
--書き込んだ8ビットがそのままIMRに転送される。
-OCW2:動作コマンドワード2
--''主に、割り込み処理終了をPICに伝える。これをしないと次の割り込みは受けられないので注意(CPUに対してIRETしてもPICにはそんなこと分からない!)。''
---たぶんアセンブラ初心者は、なんて不便な仕様なんだ、CPUがIRET命令の実行をPICに伝えてくれて良さそうなものなのに、と思うでしょう。しかし実は割り込み処理以外でもIRETを使うことは(たまに)ありますし、割り込み処理が終わってもIRET以外の方法で処理する場合もあるのです。また、後述のように(必要なら)割り込み処理中にさらに別の割り込みを受けたりもでき、そうするとどのIRETがどの割り込みの終了を意味するのかわからないということもあります(CPUはもともとIRQ割り込みは一個しか考えていなくて、それをPICで増やしているに過ぎないということを忘れずに)。だから、この仕様でいいのです。
---割り込み終了をPICに送るのが面倒だという人は自動EOIモードというのをICW4で設定しておくこともできますが、スレーブには使えない方法ですし、ICW4を使うということはPICを全面的に再設定しなければいけないということなので、あまりおすすめしません(自動EOIモードについてはICW4参照)。割り込み処理を終わる前に同じIRQの割り込みを受け付けてしまうことも当然ありえて、それに対する配慮も必要です。その観点からも自動EOIは一長一短です。
--bit0-2:(終了させたい)割り込み番号
--bit3-4:常に00:むしろここが00だからOCW2であるとPICは判断している(参考:OCW3/ICW1)。
--bit5-7:コマンド
---000:自動EOIモードにおいて、割り込み優先順位の回転モードをオフ。このコマンドでは、bit0-2の割り込み番号は無視される。
---001:通常モードにおいて、現在処理中の最優先度の割り込みを終了させる(ISRをみてPICは判断する)。このコマンドでは、bit0-2の割り込み番号は無視される。もし割り込み優先順位の回転モードがオンになっていれば、これをオフにする。
---010:何もしない
---011:通常モードにおいて、指定された割り込みを終了させる。このコマンドでは、bit0-2の割り込み番号を参照する。もし割り込み優先順位の回転モードがオンになっていれば、これをオフにする。
---100:自動EOIモードにおいて、割り込み優先順位の回転モードをオン。このコマンドでは、bit0-2の割り込み番号は無視される。
---101:通常モードにおいて、現在処理中の最優先度の割り込みを終了させる(ISRをみてPICは判断する)。このコマンドでは、bit0-2の割り込み番号は無視される。もし割り込み優先順位の回転モードがオフになっていれば、これをオンにする。
---110:もし割り込み優先順位の回転モードがオフになっていれば、これをオンにして、指定された割り込みが最優先になるように設定する(もしかしたらもっとも優先度が低くなるんだったかもしれない)。このコマンドは、通常モードでも自動EOIモードでも使う。
---111:通常モードにおいて、指定された割り込みを終了させる。このコマンドでは、bit0-2の割り込み番号を参照する。もし割り込み優先順位の回転モードがオフになっていれば、これをオンにする。
--割り込みの優先順位について
---2つの割り込みが同時に来たとき(これはありえないと思うかもしれないが、CLI→STIしたときなどは、容易に起こり得る)、もしくは1つの割り込み処理中にもう一つの割り込みが来た場合など、PICはどうしたらいいのかを優先順位という考え方で解決している。
---優先順位には、どの割り込みがどの割り込みに対して優先するのかということが固定的に決まっている非回転モードと、割り込みを受け付けるたびに割り込み優先順位が回転していく回転モードがある。
---非回転モードの場合、割り込み番号が小さいほど優先順位は高い。つまりIRQ0がもっとも優先度の高い割り込みになる。たいていの機種ではIRQ0にタイマーがあり、IRQ1にキーボードがある。これにより、時刻を正確に管理できる(優先度が一番高いので割り込みをうけやすい)とか、異常事態でもキーボードからの指令を優先できるようになっている。この思想を生かすなら、たとえ割り込みルーチンであっても長い期間CLIしないようにして(つまり長くなるようならSTIして)、タイマやキーからのIRQをまめに拾えばいいだろ
う。
---一方、もし高優先度の割り込みが集中してしまうと、順位の低い割り込みは全く受け付けてもらえないことになり、これは困る場合があるかもしれない。それを解決するのが回転モードである。回転モードでは、たとえばIRQ1を受け付けたら、優先順位が23456701に変更され、もしIRQ2以降からの割り込み要求があれば、それを優先してくれるのである。同様にIRQ4を受け付けたら56701234になる。こうして、どのIRQもほぼ平等になる。
--割り込み終了を受け付けると、対応する割り込みのISRとIRRがクリアされる。
---割り込み終了コマンドでISRがクリアされるのは間違いないが、IRRがクリアされるタイミングには自信がない。もしかしたら、割り込みを受け付けてISRをセットするのと同時にIRRをクリアしていたかもしれない。これは現在確認中。
-OCW3:動作コマンドワード2
--その他の簡単な設定を行う。
--bit0-1:IRR/ISR読み出しポートの設定
---00:設定は変更しない
---01:設定は変更しない
---10:IRRに設定
---11:ISRに設定
--bit2:PICの動作モード(0:通常、1:ポールコマンドモード)
---ポールコマンドモードとは、PICがINT命令を一切発行しないモードで、つまり割り込みは起きない。CPUは常にCLI状態にある必要があり、PICをこまめにリードしてIRQ応対をする。使い方の詳細はよく分からないが、こんなモードを使う人はまずいないと思うので、詳細を調べる予定はない。
--bit3-4:常に01:むしろここが01だからOCW3であるとPICは判断している(参考:OCW2/ICW1)。
--bit5-6:スペシャルマスクモードに関する設定
---00:設定は変更しない
---01:設定は変更しない
---10:通常モード(IMRはIRRに対するマスクとして働く)
---11:スペシャルマスクモード(IMRはISRに対するマスクとして働く)
---スペシャルマスクモードになっているときは、IMRの設定はIRRに対するマスクにはならない。つまり割り込みをマスクできない。
---スペシャルマスクモードでは、IMRは割り込み優先順位解決の際のISRへのマスクとして働く。すなわち、IMRでマスクされた割り込みの処理中であっても、より下位の割り込みを妨げることはない。
---おそらく、スペシャルマスクモードでIMRを0xffにすると、自動EOIモードとよく似たことになる。
--bit7:常に0。
-ICW1:初期化コマンドワード1
--PICを初期化して、設定をやり直す。このコマンドを発行するときには、マザーボード上でPICがどのように接続されているかの知識が必要になるので、よく理解してから使うこと(間違えると誤動作ばかりではなく、故障の原因になりうる)。
--このコマンドを書いた時点で、IRRとISRはゼロクリアされ、フリーネステッドモードになり、IRR/ISRの選択はIRRになる。
--(まだ書いてない)
-ICW2:初期化コマンドワード2
--(まだ書いてない)
-ICW3:初期化コマンドワード3
--(まだ書いてない)
-ICW4:初期化コマンドワード4
--(まだ書いてない)
* ものぐさなあなたのために [#b09f8344]
-毎度の、超簡潔な説明です。要するに、どうすればいいのよ、ということで。例によってAT互換機限定。
-とにかく割り込み処理が終わったとPICに通知したい。
--IRQ0-7の場合:
AL = 割り込み番号 + 0x60; OUT(0x20, AL);
--IRQ8-15の場合:
AL = (割り込み番号 - 8) + 0x60; OUT(0xa0, AL); AL = 0x62; OUT(0x20, AL);
---ただしこの方法を使う場合、IRQ8-15の割り込み処理中に他の割り込みを受け付けないこと。
---他の割り込みを受け付けているかもしれないときにも対応したいなら、OUT(0xa0, AL);のあとでスレーブのISRをチェックして、これが0x00のときに限って、AL = 0x62; OUT(0x20, AL); するように細工する。
* こめんと欄 [#z8dea157]
-PICはなんとかつかえそうなのですが、APICの使い方が謎・・ -- [[名無しさん]] SIZE(10){2004-10-15 (金) 21:30:32}
-それは僕もまだわかりませんねえ。それはAPICを活用しているOS(もしくは活用予定のOS)をOS-Wikiに誘致しないと・・・。 -- [[K]] SIZE(10){2004-10-16 (土) 02:10:30}
-IRQ0をポート0x60に設定し、キーボード割り込みを0x61で受け付けています。一応キーは取得できるのですが、何故か2回連続でキーの割り込みハンドラーがコールされます。行き詰まり、このページに行き着いたのですが、もし原因がおわかりでしたら、ご教授ください。 -- ''OS勉強中'' SIZE(10){2005-11-12 (土) 22:27:21}
-OS勉強中さんへ。このサイト内の(AT)keyboardに書いてありましたが、 makeとbreakが原因なのだと思います。 -- [[名無しさん]] SIZE(10){2005-11-20 (日) 13:44:39}
-<br> -- [[名無しさん]] SIZE(10){2005-12-22 (木) 17:01:54}
-キーボード割り込みでは、mov al,0x61;out 0x20,alだけでなくキーボードからデータを受け取らないとキーボードが割り込み信号を出さない?。だからmov al,0x61でキーボードバッファからデータを取り出すことも必要。 -- ''take'' SIZE(10){2009-09-12 (土) 09:51:37}
-キーボードバッファからデータを取り出すのはin al,0x60でした。 -- ''take'' SIZE(10){2009-09-12 (土) 09:53:20}
-キーコードを受け取らないうちに入力がきても、割り込みは起きません。感覚的には既に読み取り待機中のキーコードさえ忙しくて受け取れていないのに、更に割り込みがきてもCPUが困るだろうと配慮している、なんてふうに思うといいかもしれません。 -- [[K]] SIZE(10){2009-09-12 (土) 23:30:16}
-ICW1が実行したら絶対に ICW2 -> ICW3 -> ICW4 っと実行しないといけません。 追記. インテルの場合は8259割り込みコントローラとやらを初期化してからじゃないとICW1をいけないのかな? -- 名無しさん SIZE(10){2021-10-27 (水) 18:36:57}
#comment