AT互換機のPS/2キーボードコントローラ

  • コントローラは8042
  • I/Oポート
    アドレス(hex)wideR/Wデバイス説明備考
    0060byteRKBCKBCデータポート/キーボードデータ
    0060byteWKBCKBCデータ出力
    0064byteRKBCステータスレジスタ
    0064byteWKBCKBC制御コマンド出力
  • ステータスレジスタについて
    • I/Oポート0064をバイトリードすると読める
    • bit0:1==データポートにキーデータが来ている
      • このbitが1になっていたら速やかに0060を読んでデータを受け取ること
      • IRQ-1は、ここが0→1になると発生すると考えてよい
    • bit1:0==キーボードコントローラに送信データを送ってよい
    • bit2:システムフラグ(起動後に0になる)
    • bit3:キーボードへ送信中のデータは、1==コマンド、0==データ
      • これは、0064に書き込むと自動的に1になり、0060に書き込むと自動的に0になる
    • bit4:1==キーボードは入力可能状態(enable)になっている
    • bit5:1==データ送信エラー
      • データポートにキーデータが来ているのに、受け取らないでいて、さらに次のキーコードがきてしまうとこれになる
    • bit6:1==データ受信エラー
    • bit7:パリティビットなので基本的に気にしなくてよいと思う
      • 0==奇数パリティ、1==偶数パリティ
  • キーコード
    • 基本:0060から読み取った値の、bit0-6がキーコード、bit7がメイク・ブレイク種別(0:メイク、1:ブレイク)
    • 以下に見るとおり、Aを押したらAの文字コードが送信されてくるわけではない。PCからみると、キーボードはただのスイッチボタンのかたまりであって、何番のボタンを押した(メイク)か、離した(ブレイク)か、が知らされるに過ぎない。ShiftやCtrlやAltなどとの組み合わせの管理や、NumLockやCapsLockの状態の管理、把握も全部やらなければいけない。
      • まあ逆にいえば、キー配置を変える(たとえばShiftとCtrlを入れ替えるなど)は、ソフトウェアで好きなようにできるということでもある。
    • 一般キーコード
      00:割り当てなし(これはこないはず)10:Q20:D
      01:ESC11:W21:F
      02:フルキーの112:E22:G
      03:フルキーの213:R23:H
      04:フルキーの314:T24:J
      05:フルキーの415:Y25:K
      06:フルキーの516:U26:L
      07:フルキーの617:I27:;
      08:フルキーの718:O28::(英語キーボードでは')
      09:フルキーの819:P29:全角・半角(英語キーボードでは`)
      0A:フルキーの91A:@(英語キーボードでは[)2A:左Shift
      0B:フルキーの01B:[(英語キーボードでは])2B:](英語キーボードではバックスラッシュ)
      0C:フルキーの-1C:フルキーのEnter2C:Z
      0D:フルキーの^(英語キーボードでは=)1D:左Ctrl2D:X
      0E:バックスペース1E:A2E:C
      0F:タブキー1F:S2F:V
      30:B40:F650:テンキーの260:リザーブ70:ひらがな
      31:N41:F751:テンキーの361:リザーブ?71:リザーブ?
      32:M42:F852:テンキーの062:リザーブ?72:リザーブ?
      33:,43:F953:テンキーの.63:リザーブ?73:_
      34:.44:F1054:SysReq64:リザーブ?74:リザーブ?
      35:/45:NumLock55:リザーブ?65:リザーブ?75:リザーブ?
      36:右Shift46:ScrollLock56:リザーブ?66:リザーブ?76:リザーブ?
      37:テンキーの*47:テンキーの757:F1167:リザーブ?77:リザーブ?
      38:左Alt48:テンキーの858:F1268:リザーブ?78:リザーブ?
      39:スペース49:テンキーの959:リザーブ?69:リザーブ?79:変換
      3A:CapsLock4A:テンキーの-5A:リザーブ?6A:リザーブ?7A:リザーブ?
      3B:F14B:テンキーの45B:リザーブ?6B:リザーブ?7B:無変換
      3C:F24C:テンキーの55C:リザーブ?6C:リザーブ?7C:リザーブ?
      3D:F34D:テンキーの65D: リザーブ?6D:リザーブ?7D:\
      3E:F44E:テンキーの+5E:リザーブ?6E:リザーブ?7E:リザーブ?
      3F:F54F:テンキーの15F:リザーブ?6F:リザーブ?7F:リザーブ?
      • 註:
      • 00はキーボードエラーを意味する。
  • E0拡張キーコード
    • これは E0 1C などの形式で送られてくる。メイクは E0 1C で、ブレイクは E0 9C というふうになる。ここに書かれていないものはリザーブ。
      E0 1C:テンキーのEnterE0 49:PageUpE0 5B:左Windows
      E0 1D:右CtrlE0 4B:←E0 5C:右Windows
      E0 35:テンキーの/E0 4D:→E0 5D:メニュー?キー
      E0 37:PrintScreenE0 4F:End
      E0 38:右AltE0 50:↓
      E0 46:BreakE0 51:PageDown
      E0 47:HomeE0 52:Insert
      E0 48:↑E0 53:Delete
  • 以下のキーコードは、実際のキー入力と関わりなく送られてくるので、読み捨てるのが良いとKは考えている。
    E0 2A:無視E0 AA:無視
    E0 36:無視E0 B6:無視
  • E1拡張キーコード
    • これは2種類しかない
      E1 1D 45:PauseのメイクE1 9D C5:Pauseのブレイク
  • キーのリピート
    • リピートは、ブレイクすることなくメイクが送られてくることで表現される
    • BreakとPauseはリピートが発生しない
  • LEDの制御など
    • NumLockやCapsLockなどのLEDの制御には、次の方法でキーボードにコマンドやデータを送る。
      • 1.ステータスレジスタを読んで、bit1が0になるのを待つ。
      • 2.データ出力(0060のこと)に、送りたい1バイトを書く。
      • 3.キーボードから1バイト通知が来るのを待つ。これはキー入力を待つのと同じ方法になる(IRQで待ってもいいし、ステータスレジスタのbit0が1になるのをループで見張ってもいい)。
      • 4.その通知が0xfaであれば、その1バイトは正しくキーボードに送られたことを意味する。0xfeであれば送信ミスなので、1.に戻ってもう一回送る。
    • LED制御の場合は、上記の手法を2回やって、 ED xx というデータを送ればよい。ここで、xxのbit0がScrollLock、bit1がNumLock、bit2がCapsLockになる(それぞれ0で消灯、1で点灯)。bit3-7はリザーブで常に0。
    • その他のコマンドとして以下のものがある。
      • EE:このコマンドはキーボードが正常に動作しているかどうかのチェックのためのもので、うまくいっているときは、キーボードから0xeeという1バイトが送られてくる。この1バイトは、4.での0xfaの代わりに送られてくるので注意。
      • F0 xx:このコマンドはキーボードのスキャンコード(キーコード)のフォーマットを設定するためのもので、xx=01に設定するのが一般的である。xx=02やxx=03にもできるが、この場合このページでの説明通りにはならなくなる。なお、xx=00にすると現在設定されているモードを通知してくる。04以上はリザーブ。キーボードをリセットするとデフォルトでは F0 02 になっていると説明している資料もあるけど、Kが試した範囲ではみんな F0 01 になっているようであった。
      • F2:このコマンドを送ると、2バイトのキーボードIDが通知されてくる。これは通常、0x83abである。これで英語キーボードか日本語キーボードかを見分けられるということはないと思うが、実験したことはないのでKには確信はない。英語キーボードで0x83abが送られてくるのはまず間違いない。
      • F3 xx:このコマンドはキーリピート間隔を設定する。xxのbit0-4の5ビットで、リピート間隔を設定でき、数字が小さいほどリピート間隔が小さくなる(=リピートが速くなる)。bit5-6の2ビットでリピート開始までの時間を制御できて、0:250ms、1:500ms、2:750ms、3:1000msから選べる。bit7はリザーブで常に0にすること。キーボードがリセットされたときは、 F3 2B の状態になっている。
      • F4:キーボード入力を可能にする(キーボードイネーブル)。電源投入時はイネーブルになっている。
      • F5:キーボード初期化&キーボードディゼーブル。設定を電源時状態に戻して、しかもキーボード入力を受け付けない状態にする(これはいろいろ設定をやり直すときに、設定中にキーデータが混ざるとややこしくなるので、それを避けるためのコマンド)。
      • F6:キーボード初期化(ディゼーブルなし)。基本的にF5と同じだけど、キーボードはイネーブルになっている。
      • F7:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • F8:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • F9:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • FA:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • FB:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • FC:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • FD:スキャンコード(コマンドF0参照)が3の場合しか関係ないので、説明省略。
      • FE:キーボードに対して、「直前の1バイトをうまく受け取れなかったから再度送ってくれ」と通知するためのコマンド。キーコード受信時などでパリティエラーがあったりしたときに、利用するといいかもしれない。
      • FF:キーボードリセット。これはF6とは異なり、単に初期化するだけではなく、電源投入時に行う自己診断も再度やる。自己診断に成功すると、キーボードは0xaaというデータを勝手に送ってくる。自己診断に失敗すると、0xfcというデータを送ってくる。PC動作中にキーボードを接続した場合も(こういうことをやっていいのかどうかは分からないけど)、0xaaか0xfcが最初にやってくる。
  • ほかにキーボードインターフェースを使ってできること
    • キーボードインタフェースは、なぜかキーボード以外のデバイスも管轄していて、いろいろなことができます。
    • 以下のコマンドや後続データを書く場合は、かならずステータスレジスタを読んで、「キーボードコントローラに送信データを送ってよい」になっているかどうか確認してくださいね。
    • 8042モードレジスタ直接書き込み:
      • KBC制御コマンド出力(0064)に、60を書き込む。
      • その後、KBCデータ出力(0060)にモードレジスタに書き込みたいデータを書く。
      • モードレジスタのビット構成は以下のとおり。
      • bit0:これを1にすると、キーボードからデータが来たときにIRQ-1を発生させるようになる。
      • bit1:これを1にすると、マウスからデータが来たときにIRQ-12を発生させるようになる。
      • bit2:システムフラグ。用途はよく分からない。とりあえず1にしとけばいいらしい(パワーオンリセットによってここは0クリアされるらしい)。
      • bit3:これを1にするとキーボードロックができなくなるらしい。
      • bit4:これを1にするとキーボードインタフェースが使えなくなる。
      • bit5:これを1にするとマウスインタフェースが使えなくなる。
      • bit6:スキャンコード01を使うときはこれを1にする。他のスキャンコードを使うときはこのビットを0にするらしいが実は良く分からない。
      • bit7:このピットはリザーブなので常に0を設定する。
    • 8042モードレジスタ直接読み込み:
      • KBC制御コマンド出力(0064)に、20を書き込む。
      • するとKBCデータポートに8042モードレジスタの内容が送られてくるので、これを受け取る。
    • キーボードインタフェース無効化コマンド:
      • KBC制御コマンド出力(0064)に、ADを書き込む。
      • このコマンドによって8042モードレジスタのbit4が1になる。
    • キーボードインタフェース有効化コマンド:
      • KBC制御コマンド出力(0064)に、AEを書き込む。
      • このコマンドによって8042モードレジスタのbit4が0になる。
    • マウスインタフェース無効化コマンド:
      • KBC制御コマンド出力(0064)に、A7を書き込む。
      • このコマンドによって8042モードレジスタのbit5が1になる。
    • マウスインタフェース有効化コマンド:
      • KBC制御コマンド出力(0064)に、A8を書き込む。
      • このコマンドによって8042モードレジスタのbit5が0になる。
  • (まだ未完成)

リンク

こめんと欄

  • マウスはどのように制御するのですか? -- 名無しさん 2005-03-08 (火) 19:42:26
  • ご質問ありがとうございます。マウス関係はそのうちページを作りたいと思います。 -- K 2005-03-10 (木) 13:15:21
  • レスありがとうございます。マウスページ期待しております。 -- 名無しさん 2005-03-10 (木) 23:45:05
  • CapsLockが知らないうちについているってことはあるのでしょうか? -- kyon? 2007-06-19 (火) 15:19:35
  • 参考になりました。 -- 名無しさん2 2009-07-12 (日) 18:43:04
  • 参考になりました。 -- 名無しさん2 2009-07-13 (月) 20:37:48
  • 8042モードレジスタのbit6は、scan code set 1に変換するかどうかを選択するビットらしいです。1にセットすると、スキャンコードがscan code set 1に変換された後、インプットバッファに送られ、0にクリアすると、スキャンコードが無変換でバッファに送られます。(参考:http://www.computer-engineering.org/ps2keyboard/) -- uchan 2009-08-30 (日) 17:48:12
  • なぜ98のキーボードの説明がないのか。疑問を持っている -- 2010-04-07 (水) 15:22:47
  • Why isn't the page English-commented? -- RS 2010-06-07 (月) 21:24:16
  • 初めまして。ちょっと質問があります。5Bはwindowsキー,5Dはアプリケーションキーではないでしょうか。 -- MNAS? 2014-03-16 (日) 07:01:26
  • 確認ができたので、編集しました。 -- MNAS? 2014-03-25 (火) 18:56:12
  • すみません。拡張キーコードの時もありました. -- MNAS? 2014-03-31 (月) 11:14:29

コメントお名前NameLink

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2014-09-05 (金) 11:41:37 (2526d)