何らかのブログ

日記とか備忘録

OS上でキーボードを動かすまでの話

CPU実験も無事終わり、余興の余興をやりたいと思い、かねてからの目標であったキーボードドライバを作ろうと思った。

twoproc

VHDL書けないのでtwoprocについて周りの優秀な人たちが教えてくれた資料やアドバイスをまとめる。

 優秀な人に言われた通りの手順で頑張ってく。
  1. 参考資料を読む
  2. twoprocで書かれたコードを読む

 

参考資料

http://t.co/jtCVasfO8y

 

twoprocで書かれたコード

github.com

 

キーボードコントローラ

とりあえず何となく分かったので、次に普及品であるintel 8042キーボードコントローラについて調べた。

 

ここのサイトが詳しい。

KBC/Intel 8042 - OS Project Wiki

キーボード コントローラ(KBC)

こんな感じになるのかな

gist.github.com

 

PS/2プロトコル

ここのサイトにPS/2の仕様が記載されているので、まとめる。

Computer-Engineering.org

PS/2は6-pin Mini-DINという規格で、Data,Clockの2本のシリアルバスで双方向通信を行う。

キーボード→コントローラの通信

DataとClockはどちらもHighの状態から始まる。デバイスが情報を送ろうとするとき最初にClockがHighであるかチェックし、もしLowなら中断する。すなわちKBCは送信したい命令がなければClock <= 'H'を送り続けていればよい。

通信は0xxxxxxxxp1の11bitであり、もしKBCが中断させたい場合はstop bitが送られるまでに100マイクロ秒以上Clock <= '0'を送ればよい。

Clockの立ち上がりでDataは次のbitへ5マイクロ秒以内に切り替える。Dataの切り替えからClockの下がりまで5~25マイクロ秒以内でなければならない。つまりfalling_edgeかClock = '0'でDataを読み込めば良い訳だけど、立ち上がるまでの時間すなわち周波数が10~16.7kHzを幅があるので、falling_edgeの方がいいっぽい。

中断されたとき用にキーボードは16byteの出力バッファを持っているらしい。

コントローラ→キーボードの通信

最初にPS/2デバイスは常にClock信号を生成している。もしKBCがデータを送りたいとき、以下の手順に従う。

  1. 100マイクロ秒以上Clock <= '0'を送る。
  2. Data <= '0'を送る。
  3. Clock <= 'H'を送り、「Request-to-send」状態にする。(start bitの送信)
  4. デバイスがClockを'0'にするのを待つ。
  5. 送りたいデータのbitにDataを設定する。
  6. デバイスがClockを'1'にするのを待つ。
  7. デバイスがClockを'0'にするのを待つ。
  8. 5-7を残りの7ビットとパリティビットに関して繰り返す。
  9. Data <= 'H'を送る。(STOP)
  10. デバイスがData<='0'にするのを待つ。
  11. デバイスがClock<='0'にするのを待つ。
  12. デバイスがData<='H'、Clock<='H'にするのを待つ。(ACK)

ClockがLowの時にKBCはデータを変更し、ClockがHighの時にデバイスがDataを受信する。最初のKBCによるClock<='0'からデバイスによるClock<='0'までの間隔は15ミリ秒未満である必要があり、パケットの送信は2ミリ秒以内になされる必要がある。これを超過した場合、または応答を必要とするコマンドをKBCが送って20ミリ秒以上経っても応答がない場合KBCはTimeoutフラグを立てる必要がある。ACKをKBCが受け取ってからデータを処理するまではClock <= '0'にしておいた方がよい。中断するにはACK来るまで(11ビット目まで)にClock<='0'を100マイクロ秒以上送りつづける。


と、ここまで書いたが授業が始まったので続きはまたこんどで

 

VMware Playerでファイル共有ができなくなった話

以下のようなエラーメッセージが出てファイル共有だけが有効にならなかった。

In file included from ./arch/x86/include/asm/percpu.h:44:0,
                 from ./arch/x86/include/asm/preempt.h:5,
                 from include/linux/preempt.h:18,
                 from include/linux/spinlock.h:50,
                 from include/linux/mmzone.h:7,
                 from include/linux/gfp.h:5,
                 from include/linux/mm.h:9,
                 from include/linux/pagemap.h:7,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:29:
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c: In function ‘HgfsPermission’:
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1928:31: error: ‘union <anonymous>’ has no member named ‘d_alias’
                            d_u.d_alias) {
                               ^
include/linux/kernel.h:834:29: note: in definition of macro ‘container_of’
  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                             ^
include/linux/list.h:698:15: note: in expansion of macro ‘hlist_entry’
     ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
               ^
include/linux/list.h:708:13: note: in expansion of macro ‘hlist_entry_safe’
  for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
             ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
include/linux/kernel.h:834:48: warning: initialization from incompatible pointer type
  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                ^
include/linux/list.h:687:40: note: in expansion of macro ‘container_of’
 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
                                        ^
include/linux/list.h:698:15: note: in expansion of macro ‘hlist_entry’
     ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
               ^
include/linux/list.h:708:13: note: in expansion of macro ‘hlist_entry_safe’
  for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
             ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
In file included from include/linux/compiler-gcc.h:106:0,
                 from include/linux/compiler.h:54,
                 from include/uapi/linux/stddef.h:1,
                 from include/linux/stddef.h:4,
                 from ./include/uapi/linux/posix_types.h:4,
                 from include/uapi/linux/types.h:13,
                 from include/linux/types.h:5,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/./shared/driver-config.h:71,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:26:
include/linux/compiler-gcc4.h:14:34: error: ‘union <anonymous>’ has no member named ‘d_alias’
 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
                                  ^
include/linux/stddef.h:17:31: note: in expansion of macro ‘__compiler_offsetof’
 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
                               ^
include/linux/kernel.h:835:29: note: in expansion of macro ‘offsetof’
  (type *)( (char *)__mptr - offsetof(type,member) );})
                             ^
include/linux/list.h:687:40: note: in expansion of macro ‘container_of’
 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
                                        ^
include/linux/list.h:698:15: note: in expansion of macro ‘hlist_entry’
     ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
               ^
include/linux/list.h:708:13: note: in expansion of macro ‘hlist_entry_safe’
  for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
             ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
In file included from include/linux/preempt.h:10:0,
                 from include/linux/spinlock.h:50,
                 from include/linux/mmzone.h:7,
                 from include/linux/gfp.h:5,
                 from include/linux/mm.h:9,
                 from include/linux/pagemap.h:7,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:29:
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1928:31: error: ‘union <anonymous>’ has no member named ‘d_alias’
                            d_u.d_alias) {
                               ^
include/linux/list.h:697:12: note: in definition of macro ‘hlist_entry_safe’
  ({ typeof(ptr) ____ptr = (ptr); \
            ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1928:31: error: ‘union <anonymous>’ has no member named ‘d_alias’
                            d_u.d_alias) {
                               ^
include/linux/list.h:697:28: note: in definition of macro ‘hlist_entry_safe’
  ({ typeof(ptr) ____ptr = (ptr); \
                            ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
In file included from ./arch/x86/include/asm/percpu.h:44:0,
                 from ./arch/x86/include/asm/preempt.h:5,
                 from include/linux/preempt.h:18,
                 from include/linux/spinlock.h:50,
                 from include/linux/mmzone.h:7,
                 from include/linux/gfp.h:5,
                 from include/linux/mm.h:9,
                 from include/linux/pagemap.h:7,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:29:
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1928:31: error: ‘union <anonymous>’ has no member named ‘d_alias’
                            d_u.d_alias) {
                               ^
include/linux/kernel.h:834:29: note: in definition of macro ‘container_of’
  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                             ^
include/linux/list.h:698:15: note: in expansion of macro ‘hlist_entry’
     ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
               ^
include/linux/list.h:710:13: note: in expansion of macro ‘hlist_entry_safe’
       pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
             ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
include/linux/kernel.h:834:48: warning: initialization makes pointer from integer without a cast
  const typeof( ((type *)0)->member ) *__mptr = (ptr); \
                                                ^
include/linux/list.h:687:40: note: in expansion of macro ‘container_of’
 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
                                        ^
include/linux/list.h:698:15: note: in expansion of macro ‘hlist_entry’
     ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
               ^
include/linux/list.h:710:13: note: in expansion of macro ‘hlist_entry_safe’
       pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
             ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
In file included from include/linux/compiler-gcc.h:106:0,
                 from include/linux/compiler.h:54,
                 from include/uapi/linux/stddef.h:1,
                 from include/linux/stddef.h:4,
                 from ./include/uapi/linux/posix_types.h:4,
                 from include/uapi/linux/types.h:13,
                 from include/linux/types.h:5,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/./shared/driver-config.h:71,
                 from /tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:26:
include/linux/compiler-gcc4.h:14:34: error: ‘union <anonymous>’ has no member named ‘d_alias’
 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
                                  ^
include/linux/stddef.h:17:31: note: in expansion of macro ‘__compiler_offsetof’
 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
                               ^
include/linux/kernel.h:835:29: note: in expansion of macro ‘offsetof’
  (type *)( (char *)__mptr - offsetof(type,member) );})
                             ^
include/linux/list.h:687:40: note: in expansion of macro ‘container_of’
 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
                                        ^
include/linux/list.h:698:15: note: in expansion of macro ‘hlist_entry’
     ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
               ^
include/linux/list.h:710:13: note: in expansion of macro ‘hlist_entry_safe’
       pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
             ^
/tmp/modconfig-Etbo2b/vmhgfs-only/inode.c:1920:7: note: in expansion of macro ‘hlist_for_each_entry’
       hlist_for_each_entry(dentry,
       ^
scripts/Makefile.build:257: recipe for target '/tmp/modconfig-Etbo2b/vmhgfs-only/inode.o' failed
make[2]: *** [/tmp/modconfig-Etbo2b/vmhgfs-only/inode.o] Error 1
make[2]: *** 未完了のジョブを待っています....
Makefile:1333: recipe for target '_module_/tmp/modconfig-Etbo2b/vmhgfs-only' failed
make[1]: *** [_module_/tmp/modconfig-Etbo2b/vmhgfs-only] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-3.16.0-031600-generic'
Makefile:120: recipe for target 'vmhgfs.ko' failed
make: *** [vmhgfs.ko] Error 2
make: Leaving directory '/tmp/modconfig-Etbo2b/vmhgfs-only'

The filesystem driver (vmhgfs module) is used only for the shared folder 
feature. The rest of the software provided by VMware Tools is designed to work 
independently of this feature.

どうやらこういうことらしい。

http://qiita.com/maccotsan/items/fafdc01deac71c20bd60

qnighy氏によればそのままでは上手く動かなかったらしいので、その辺も含めて調べてみる


一応成功したので記載しておく

実行環境

ホスト:Windows 8.1
ゲスト:Xubuntu 14.10-2
カーネルバージョン:3.16.0-031600-generic
VMware Player 7.1
VMwareTools9.9.2-2496486

方法

vmware-tools-patches/patches/vmhgfs at 19d5e2f68db4cdc835747102102d8661f8c670a9 · rasa/vmware-tools-patches · GitHubをダウンロードする。

  1. vmware-tools-patches-masterを展開し、VMwareTools...tar.gzをフォルダ内に移動する。
  2. untar-all-and-patch.shを実行。
  3. patch適用済のVMwareTools...tar.gzを展開し、sudo ./vmware-install.plを実行。

カーネルを改造したりしてなければ3.14以上では大体のバージョンに対応してるらしい。
他のサイトで見かけたようなuntar-and-patch-and-compile.shの実行では解決しなかった場合は上記を行うとよいと思う。