* デバイスドライバってどうやって作るの?
 -(by [[K]], 2008.03.21)
 -発展課題のページ(全部読む前にここを読むのは混乱するのでおすすめじゃないです)
 --このページは子ページです。親ページはこちら → [[advance/driver]]
 ----
 -このページではキーボードのデバイスドライバを作っています。
 *** keydrv.c
 -これがキーボードドライバのプログラムになります。アプリのようにOSとは別にmakeします。
  #include "apilib.h"
  #include "dpilib.h"
  
  #define PIC0_OCW2      0x00a0
  #define PORT_KEYDAT    0x0060
  
  void irq01_driver(void);
  
  static int my_fifo;
  
  void HariMain(void)
  {
      int stack_irq[16 * 1024 / 4]; /* とりあえず割り込み処理用のスタック 16KB */
      int keydata, keycode, key_shift = 0, key_leds;
      static char keytable0[0x80] = {
          0,   0,   '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '^', 0x08, 0,
          'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '@', '[', 0x0a, 0, 'A', 'S',
          'D', 'F', 'G', 'H', 'J', 'K', 'L', ';', ':', 0,   0,   ']', 'Z', 'X', 'C', 'V',
          'B', 'N', 'M', ',', '.', '/', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
          0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
          '2', '3', '0', '.', 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0,   0,   0x5c, 0,  0,   0,   0,   0,   0,   0,   0,   0,   0x5c, 0,  0
      };
      static char keytable1[0x80] = {
          0,   0,   '!', 0x22, '#', '$', '%', '&', 0x27, '(', ')', '~', '=', '~', 0x08, 0,
          'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '`', '{', 0x0a, 0, 'A', 'S',
          'D', 'F', 'G', 'H', 'J', 'K', 'L', '+', '*', 0,   0,   '}', 'Z', 'X', 'C', 'V',
          'B', 'N', 'M', '<', '>', '?', 0,   '*', 0,   ' ', 0,   0,   0,   0,   0,   0,
          0,   0,   0,   0,   0,   0,   0,   '7', '8', '9', '-', '4', '5', '6', '+', '1',
          '2', '3', '0', '.', 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
          0,   0,   0,   '_', 0,   0,   0,   0,   0,   0,   0,   0,   0,   '|', 0,   0
      };
      my_fifo = dpi_get_myfifo(); 
      dpi_setdriver(0x01, &irq01_driver, stack_irq);
      key_leds = 0; /* 本当はこれもDPIを作ってOSに初期値を教えてもらうほうがいい  現状は手抜き */
      dpi_sendkey(key_leds + 0xf0); /* 念のために Lock LED に反映させる */
  
      for (;;) {
          keydata = api_getkey(1); /* FIFOからデータが来るまで待つ */
          keycode = 0;
          if (keydata < 0x80) {
              if (key_shift == 0) {
                  keycode = keytable0[i];
              } else {
                  keycode = keytable1[i];
              }
          }
          if ('A' <= keycode && keycode <= 'Z') {   /* 入力文字がアルファベット */
              if (((key_leds & 4) == 0 && key_shift == 0) ||
                      ((key_leds & 4) != 0 && key_shift != 0)) {
                  keycode += 0x20;   /* 大文字を小文字に変換 */
              }
          }
          if (keycode != 0) {
              dpi_sendkey(keycode);
          }
          if (keydata == 0x0f) {   /* Tab */
              dpi_sendkey(0xf8);
          }
          if (keydata == 0x2a) {   /* 左シフト ON */
              key_shift |= 1;
          }
          if (keydata == 0x36) {   /* 右シフト ON */
              key_shift |= 2;
          }
          if (keydata == 0xaa) {   /* 左シフト OFF */
              key_shift &= ~1;
          }
          if (keydata == 0xb6) {   /* 右シフト OFF */
              key_shift &= ~2;
          }
          if (keydata == 0x3a) {   /* CapsLock */
              key_leds ^= 4;
              dpi_sendkey(key_leds + 0xf0);
          }
          if (keydata == 0x45) {   /* NumLock */
              key_leds ^= 2;
              dpi_sendkey(key_leds + 0xf0);
          }
          if (keydata == 0x46) {   /* ScrollLock */
              key_leds ^= 1;
              dpi_sendkey(key_leds + 0xf0);
          }
          ... まだ書き途中
          if (keydata == 0x3b && key_shift != 0) {   /* Shift+F1 */
              dpi_sendkey(0xf9);
          }
          if (keydata == 0x3c && key_shift != 0) {   /* Shift+F2 */
              dpi_sendkey(0xfa);
          }
          if (keydata == 0x57) {   /* F11 */
              dpi_sendkey(0xfb);
          }
          if (keydata == 0xfa) {   /* キーボードがデータを無事に受け取った */
              dpi_sendkey(0xfc);
          }
          if (keydata == 0xfe) {   /* キーボードがデータを無事に受け取れなかった */
              dpi_sendkey(0xfd);
          }
      }
  }
  
  void irq01_driver(void)
  {
      int keydata;
      io_out8(PIC0_OCW2, 0x61); /* IRQ-01受付完了をPICに通知 */
      keydata = io_in8(PORT_KEYDAT);
      dpi_fifoput(myfifo, keydata);
      api_end(); /* なんとこれで割り込み処理を終わる(start_appで起動しているせい) */
  }
 -dpi_で始まる関数はapi関数みたいな感じでアセンブラで作ってください。いちいち書かなくても分かるだろうと思うので省略します。
 -ドライバを作るときに気をつけること:
 --irq01_driver()は割り込みが起きたときのタスク上で実行されるので、task = task_now();の結果が自分自身ではない。だからtask->ds_baseやtask->consも他のタスクでの値になっている。だから使えないと思うべきだ。そういうわけでAPI/DPIがどれでも使えるというわけではない。結局I/O命令で必要なデータを取って、それをmyfifoに送るくらいしかできない。
 --HariMain()からならAPIも好きなだけ問題なく呼べる。
 //--task_now()を改造すればこの問題は解決できる。多分そういう例もそのうちadvanceでやると思う。
 * こめんと欄
 -コメントは親ページへ → [[advance/driver]]

リロード   新規 編集 差分 添付   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS