| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2422 人关注过本帖
标题:一步步写操作系统之第四步:创建键盘中断处理模块和初步搭建程序执行系统
只看楼主 加入收藏
miaowangjian
Rank: 2
等 级:论坛游民
帖 子:34
专家分:30
注 册:2010-1-29
结帖率:100%
收藏
 问题点数:0 回复次数:7 
一步步写操作系统之第四步:创建键盘中断处理模块和初步搭建程序执行系统
键盘中断处理模块:
    在前一步,已经可以对键盘中断有反应了,但是按下一次键盘按钮后,就不再反应了。这是因为,必须要向键盘数据端口取出从键盘传来的扫描码后,才会继续等待与保存下一个键盘中断产生的扫描码。
  t_8 scan_code = in_byte(KB_DATA); //获取扫描码,KB_DATA为键盘数据端口: 0x60

    键盘每个按钮按下时和持续按下不松开会产生键盘中断,以及对应按键的扫描码(scan_code),松开时,也会产生键盘中断,此时对应键盘提供的叫做中断码(Break Code),详情见“keyboard.h”的宏定义。
对于同一个键盘按钮,扫描码和中断码有如下关系:
扫描码(scan_code)+ 0x80 = 中断码(Break Code)

    此外,一些特殊的键盘按钮,会有E0或E1前缀。
    总之,扫描码(中断码)与对应的ASCII码和功能键的映射有自己的一套规则。在编写键盘驱动时,为了简便,都是建立一个数组,通过使用扫描码或是换算成扫描码的中断码作为下标,查找到对应的按键ASCII码或功能键。具体见 “keyboard.h”里的keymap[]数组。对于一些组合键,再进行特殊处理。

    关于键盘中断处理,就解释到这,很多的,可以看看下面“keyboard.h”和“keyboard.c”等具体的代码。
程序执行系统:
    程序执行系统,或者说“域结构”是我的操作系统特有的一个执行机制,用于代替普通的操作系统里的进程调度机制。简单的说,“域结构”就是一个双向链表,每个节点都包含一个无参无fanh值的函数(执行函数)。通过不断循环调用每个节点的执行函数以及动态的添加或删除执行函数节点形成的一个程序执行系统。
    与普通的操作系统里的进程调度机制相比,“域结构”机制是以函数为单位依次轮换执行,而进程调度是以进程(某个独立的程序)为单位根据调度算法轮换执行。
    相对来说,“域结构”机制有诸多缺点,最大的一个问题是可靠性与安全性。但是出于个人原因,我还是选择了使用这种调用机制。

    键盘中断处理模块,虽然是通过“域结构”调用的,但是基本的流程还是和常用的键盘驱动程序一样。但这只是暂时测试用的,使用“域结构”编写的“域程序”需要遵循特定的规则,在接下来的几步里,会逐步改进“域结构”并修改这个键盘处理模块。

下面是此次修改了的文件和新添加的文件:
code:i8259.c(改)
因为修改不大,仅是修改了一个函数,所以不全部贴出来了。
将:
程序代码:
#pragma align(16)
asm void hwint01()  //Interrupt routine for irq 1 (keyboard)
{
  hwint_master(1)
}
改为:(就是将原来的宏hwint_master(1),展开为具体代码,并将调用中断处理函数表的函数改为调用OnKeyEvent()函数)
程序代码:
#pragma align(16)
asm void hwint01()  //Interrupt routine for irq 1 (keyboard)
{
  pushad     // ┓
  push    ds // ┃
  push    es // ┣ 保存原寄存器值
  push    fs // ┃
  push    gs // ┛

  in      al, INT_M_CTLMASK       // ┓
  or      al, (1 << 1)            // ┣ 屏蔽当前中断
  out     INT_M_CTLMASK, al       // ┛
  mov     al, EOI                 // ┓置EOI位,其后8259A才能相应新的中断
  out     INT_M_CTL, al           // ┛
  sti     //允许响应新的中断
  call    OnKeyEvent              // 调用键盘中断处理程序
  cli
  in      al, INT_M_CTLMASK       // ┓
  and     al, ~(1 << 1)           // ┣ 恢复接受当前中断
  out     INT_M_CTLMASK, al       // ┛

  pop     gs // ┓
  pop     fs // ┃
  pop     es // ┣ 还原寄存器值
  pop     ds // ┃
  popad      // ┛
  iretd
}

code:kernel.c(改)
程序代码:
//文件:kernel.c
//功能:内核程序,目前功能为测试print.c里的几个输出函数
//运行:run.exe自动会编译boot.c与生成img并调用Bochs运行此程序。
//作者:miao
//时间:2010-5-24

#define YCBIT 32  //告诉编译器,以32位格式编译程序
#define YCORG 0x0 //此值会对在编译时对变量函数等产生地址基址偏移量,简单起便,设置为0
#include "global.h"
#include "kernel.h"
#include "print.h"
#include "klib.h"
#include "i8259.h"
#include "yu.h"
#include "keyboard.h"

void init();

//内核入口点
asm void main()
{
  lgdt  cs:GdtPtr           //加载新的GDTR

  mov   eax, SelectorVideo
  mov   gs, ax              //视频段选择子(目的)
  mov   eax, SelectorData32 //令32位代码段的变量(printPlace)可以读写
  mov   ds, ax

  call  init        //初始化函数

  sti    //开中断
  jmp  kernel_main
}

void init()
{
  disp_str("================ init start =================\n");

  disp_str(" init idt -------------------------------- ");
  init_prot(); //初始化IDT
  disp_str("ok\n");

  disp_str(" init keyboard --------------------------- ");
  init_keyboard();//初始化键盘
  disp_str("ok\n");

  disp_str(" init yu ---------------------------------\n");
  life = 100;//初始化根域生命值
  AddAction(nullAction);

  disp_str("      load keyboard action --------------- ");

  AddAction(keyBoard);//加载键盘服务域

  disp_str("ok\n");

  disp_str("================ init end ===================\n");
}

int kernel_main()
{
  disp_str("================ yu start ===================\n");
  while(life)
  {
    Run();
  }
  disp_str("================ yu end =====================\n");
  disp_str("died");
  while(1);
  return 0;
}

#include "print.c"
#include "klib.c"
#include "i8259.c"
#include "yu.c"
#include "keyboard.c"

code:yu.h(新)
程序代码:
//文件:yu.h
//功能:yu头文件,域结构需要用到的公共函数的声明等
//作者:miao
//时间:2010-5-24

#define NULL 0

typedef void (*action_fun)();

//动作结构
struct action_s
{
  char *name;             //动作名称
  action_fun run;         //动作调用的函数
  struct action_s *last;  //上一动作
  struct action_s *next;  //下一动作
};

//动作链表
struct actionList_s
{
  unsigned int count;    //动作计数器
  struct action_s *seek;  //当前动作
}actionList = {0,NULL};

//根域生命值(为零,退出域动作链表循环)
int life = 0;

//添加一个动作到动作链表表里
void AddAction(struct action_s *newAction);
//从动作链表里删除一个动作
void DelAction(struct action_s *delAction);
void Run(); //执行当前动作
void NullActionFun();//空动作,限制链表执行速度或将来用于管理动作链表
struct action_s nullAction = {"NullFun",&NullActionFun,NULL,NULL};

code:yu.c(新)
程序代码:
//文件:yu.c
//功能:域结构,管理一个动作双向链表,循环执行链表上的动作函数
//作者:miao
//时间:2010-5-24

//添加一个动作到动作链表里
void AddAction(struct action_s *newAction)
{
  if((*newAction).next != NULL)
  {
    return;
  }

  if(actionList.count == 0)//若链表里没有元素
  {
    actionList.seek = newAction;
    (*newAction).next = newAction;
    (*newAction).last = newAction;
  }
  else//向动链表表添加一个动作到seek动作指针前
  {
    (*newAction).last = (*actionList.seek).last;
    (*newAction).next = actionList.seek;

    (*(*actionList.seek).last).next = newAction;
    (*actionList.seek).last = newAction;
  }
  actionList.count++;
}
//从动作链表里删除一个动作
void DelAction(struct action_s *delAction)
{
  if((*delAction).next == NULL)
  {
    return;
  }

  if(actionList.count == 0) return;//若链表里没有元素

  if(actionList.count == 1)
    actionList.seek = NULL;
  else  //将此动作从链表里移除
  {
    (*(*delAction).last).next =(*delAction).next;
    (*(*delAction).next).last =(*delAction).last;

    actionList.seek = (*delAction).last;
  }

  (*delAction).next = NULL;
  (*delAction).last = NULL;
  actionList.count--;
}

void Run()
{
  //执行当前动作
  if(actionList.seek != NULL)
  {
    (*actionList.seek).run();
  }
  //OnRun();//执行on事件

  //指向下一个动作
  if(actionList.seek != NULL)
    actionList.seek = (*actionList.seek).next;
}

//空动作,限制链表执行速度或将来用于管理动作链表
void NullActionFun()
{
  for(int i=0;i<100;i++)
  for(int j=0;j<1999;j++);
  asm
  {
    inc  word gs:[((80 * 0+ 0) * 0)]
  }
}

code:keyboard.h(新)
程序代码:
//文件:keyboard.h
//功能:keyboard头文件,内核需要用到的公共函数的声明等
//作者:miao
//时间:2010-5-24
//AT(大口)键盘 8042端口

//键盘数据端口 读:读取输出缓冲器 写:写入输入缓冲器(8042 Data&8048 Command)
#define  KB_DATA   0x60
//键盘命令端口 读:读取状态寄存器 写:写入输入缓冲器(8042 Command)
#define  KB_CMD    0x64

#define  LED_CODE  0xED
#define  KB_ACK    0xFA

#define FLAG_BREAK     0x0080    //通过scan_code & FLAG_BREAK 来判断是否是Break Code
#define FLAG_EXT       0x0100    //标准功能键
#define FLAG_SHIFT_L   0x0200    //Shift左键
#define FLAG_SHIFT_R   0x0400    //Shift右键
#define FLAG_CTRL_L    0x0800    //Control左键
#define FLAG_CTRL_R    0x1000    //Control右键
#define FLAG_ALT_L     0x2000    //Alternate左键
#define FLAG_ALT_R     0x4000    //Alternate右键
#define FLAG_PAD       0x8000    //数字区的键

//键扫描码:具体的值请参考keymap最右边的列或者下表
#define MASK_RAW       0x01FF
//特殊功能键
#define ESC            (0x01 + FLAG_EXT)  // Esc
#define TAB            (0x02 + FLAG_EXT)  // Tab
#define ENTER          (0x03 + FLAG_EXT)  // Enter
#define BACKSPACE      (0x04 + FLAG_EXT)  // BackSpace

#define GUI_L          (0x05 + FLAG_EXT)  // L GUI
#define GUI_R          (0x06 + FLAG_EXT)  // R GUI
#define APPS           (0x07 + FLAG_EXT)  // APPS

//Shift, Ctrl, Alt
#define SHIFT_L        (0x08 + FLAG_EXT)  // L Shift
#define SHIFT_R        (0x09 + FLAG_EXT)  // R Shift
#define CTRL_L         (0x0A + FLAG_EXT)  // L Ctrl
#define CTRL_R         (0x0B + FLAG_EXT)  // R Ctrl
#define ALT_L          (0x0C + FLAG_EXT)  // L Alt
#define ALT_R          (0x0D + FLAG_EXT)  // R Alt 

//锁定键
#define CAPS_LOCK      (0x0E + FLAG_EXT)  // 大写锁定键
#define NUM_LOCK       (0x0F + FLAG_EXT)  // 数字锁定键
#define SCROLL_LOCK    (0x10 + FLAG_EXT)  // 屏幕滚动锁定键 

//功能键
#define F1    (0x11 + FLAG_EXT)  // F1
#define F2    (0x12 + FLAG_EXT)  // F2
#define F3    (0x13 + FLAG_EXT)  // F3
#define F4    (0x14 + FLAG_EXT)  // F4
#define F5    (0x15 + FLAG_EXT)  // F5
#define F6    (0x16 + FLAG_EXT)  // F6
#define F7    (0x17 + FLAG_EXT)  // F7
#define F8    (0x18 + FLAG_EXT)  // F8
#define F9    (0x19 + FLAG_EXT)  // F9
#define F10   (0x1A + FLAG_EXT)  // F10
#define F11   (0x1B + FLAG_EXT)  // F11
#define F12   (0x1C + FLAG_EXT)  // F12

//控制区
#define PRINTSCREEN  (0x1D + FLAG_EXT)  // Print Screen
#define PAUSEBREAK   (0x1E + FLAG_EXT)  // Pause/Break
#define INSERT       (0x1F + FLAG_EXT)  // Insert
#define DELETE       (0x20 + FLAG_EXT)  // Delete
#define HOME         (0x21 + FLAG_EXT)  // Home
#define END          (0x22 + FLAG_EXT)  // End
#define PAGEUP       (0x23 + FLAG_EXT)  // Page Up
#define PAGEDOWN     (0x24 + FLAG_EXT)  // Page Down
#define UP           (0x25 + FLAG_EXT)  // Up
#define DOWN         (0x26 + FLAG_EXT)  // Down
#define LEFT         (0x27 + FLAG_EXT)  // Left
#define RIGHT        (0x28 + FLAG_EXT)  // Right

//电源管理键
#define POWER  (0x29 + FLAG_EXT)  // Power
#define SLEEP  (0x2A + FLAG_EXT)  // Sleep
#define WAKE   (0x2B + FLAG_EXT)  // Wake Up

//数字区
#define PAD_SLASH  (0x2C + FLAG_EXT)  // /
#define PAD_STAR   (0x2D + FLAG_EXT)  // *
#define PAD_MINUS  (0x2E + FLAG_EXT)  // -
#define PAD_PLUS   (0x2F + FLAG_EXT)  // +
#define PAD_ENTER  (0x30 + FLAG_EXT)  // Enter
#define PAD_DOT    (0x31 + FLAG_EXT)  // .
#define PAD_0      (0x32 + FLAG_EXT)  // 0
#define PAD_1      (0x33 + FLAG_EXT)  // 1
#define PAD_2      (0x34 + FLAG_EXT)  // 2
#define PAD_3      (0x35 + FLAG_EXT)  // 3
#define PAD_4      (0x36 + FLAG_EXT)  // 4
#define PAD_5      (0x37 + FLAG_EXT)  // 5
#define PAD_6      (0x38 + FLAG_EXT)  // 6
#define PAD_7      (0x39 + FLAG_EXT)  // 7
#define PAD_8      (0x3A + FLAG_EXT)  // 8
#define PAD_9      (0x3B + FLAG_EXT)  // 9
#define PAD_UP        PAD_8      // Up
#define PAD_DOWN      PAD_2      // Down
#define PAD_LEFT      PAD_4      // Left
#define PAD_RIGHT     PAD_6      // Right
#define PAD_HOME      PAD_7      // Home
#define PAD_END       PAD_1      // End
#define PAD_PAGEUP    PAD_9      // Page Up
#define PAD_PAGEDOWN  PAD_3      // Page Down
#define PAD_INS       PAD_0      // Ins
#define PAD_MID       PAD_5      // Middle key
#define PAD_DEL       PAD_DOT    // Del

#define MAP_COLS       3     //keymap 的列数
#define NR_SCAN_CODES  0x80  //扫描码的数目(keymap的行数)

t_32 keymap[NR_SCAN_CODES * MAP_COLS] = {
//shift未按下   shift按下    有0xE0前缀的扫描码
//!Shift        Shift        E0 XX      扫描码
  0,            0,           0,         //0x00 - none
  ESC,          ESC,         0,         //0x01 - ESC
  '1',          '!',         0,         //0x02 - '1'
  '2',          '@',         0,         //0x03 - '2'
  '3',          '#',         0,         //0x04 - '3'
  '4',          '$',         0,         //0x05 - '4'
  '5',          '%',         0,         //0x06 - '5'
  '6',          '^',         0,         //0x07 - '6'
  '7',          '&',         0,         //0x08 - '7'
  '8',          '*',         0,         //0x09 - '8'
  '9',          '(',         0,         //0x0A - '9'
  '0',          ')',         0,         //0x0B - '0'
  '-',          '_',         0,         //0x0C - '-'
  '=',          '+',         0,         //0x0D - '='
  BACKSPACE,    BACKSPACE,   0,         //0x0E - BS
  TAB,          TAB,         0,         //0x0F - TAB
  'q',          'Q',         0,         //0x10 - 'q'
  'w',          'W',         0,         //0x11 - 'w'
  'e',          'E',         0,         //0x12 - 'e'
  'r',          'R',         0,         //0x13 - 'r'
  't',          'T',         0,         //0x14 - 't'
  'y',          'Y',         0,         //0x15 - 'y'
  'u',          'U',         0,         //0x16 - 'u'
  'i',          'I',         0,         //0x17 - 'i'
  'o',          'O',         0,         //0x18 - 'o'
  'p',          'P',         0,         //0x19 - 'p'
  '[',          '{',         0,         //0x1A - '['
  ']',          '}',         0,         //0x1B - ']'
  ENTER,        ENTER,       PAD_ENTER, //0x1C - CR/LF
  CTRL_L,       CTRL_L,      CTRL_R,    //0x1D - l. Ctrl
  'a',          'A',         0,         //0x1E - 'a'
  's',          'S',         0,         //0x1F - 's'
  'd',          'D',         0,         //0x20 - 'd'
  'f',          'F',         0,         //0x21 - 'f'
  'g',          'G',         0,         //0x22 - 'g'
  'h',          'H',         0,         //0x23 - 'h'
  'j',          'J',         0,         //0x24 - 'j'
  'k',          'K',         0,         //0x25 - 'k'
  'l',          'L',         0,         //0x26 - 'l'
  ';',          ':',         0,         //0x27 - ';'
  '\'',         '"',         0,         //0x28 - '\''
  '`',          '~',         0,         //0x29 - '`'
  SHIFT_L,      SHIFT_L,     0,         //0x2A - l. SHIFT
  '\\',         '|',         0,         //0x2B - '\'
  'z',          'Z',         0,         //0x2C - 'z'
  'x',          'X',         0,         //0x2D - 'x'
  'c',          'C',         0,         //0x2E - 'c'
  'v',          'V',         0,         //0x2F - 'v'
  'b',          'B',         0,         //0x30 - 'b'
  'n',          'N',         0,         //0x31 - 'n'
  'm',          'M',         0,         //0x32 - 'm'
  ',',          '<',         0,         //0x33 - ','
  '.',          '>',         0,         //0x34 - '.'
  '/',          '?',         PAD_SLASH, //0x35 - '/'
  SHIFT_R,      SHIFT_R,     0,         //0x36 - r. SHIFT
  '*',          '*',         0,         //0x37 - '*'
  ALT_L,        ALT_L,       ALT_R,     //0x38 - ALT
  ' ',          ' ',         0,         //0x39 - ' '
  CAPS_LOCK,    CAPS_LOCK,   0,         //0x3A - CapsLock
  F1,           F1,          0,         //0x3B - F1
  F2,           F2,          0,         //0x3C - F2
  F3,           F3,          0,         //0x3D - F3
  F4,           F4,          0,         //0x3E - F4
  F5,           F5,          0,         //0x3F - F5
  F6,           F6,          0,         //0x40 - F6
  F7,           F7,          0,         //0x41 - F7
  F8,           F8,          0,         //0x42 - F8
  F9,           F9,          0,         //0x43 - F9
  F10,          F10,         0,         //0x44 - F10
  NUM_LOCK,     NUM_LOCK,    0,         //0x45 - NumLock
  SCROLL_LOCK,  SCROLL_LOCK, 0,         //0x46 - ScrLock
  PAD_HOME,     '7',         HOME,      //0x47 - Home
  PAD_UP,       '8',         UP,        //0x48 - CurUp
  PAD_PAGEUP,   '9',         PAGEUP,    //0x49 - PgUp
  PAD_MINUS,    '-',         0,         //0x4A - '-'
  PAD_LEFT,     '4',         LEFT,      //0x4B - Left
  PAD_MID,      '5',         0,         //0x4C - MID
  PAD_RIGHT,    '6',         RIGHT,     //0x4D - Right
  PAD_PLUS,     '+',         0,         //0x4E - '+'
  PAD_END,      '1',         END,       //0x4F - End
  PAD_DOWN,     '2',         DOWN,      //0x50 - Down
  PAD_PAGEDOWN, '3',         PAGEDOWN,  //0x51 - PgDown
  PAD_INS,      '0',         INSERT,    //0x52 - Insert
  PAD_DOT,      '.',         DELETE,    //0x53 - Delete
  0,            0,           0,         //0x54 - Enter
  0,            0,           0,         //0x55 - ???
  0,            0,           0,         //0x56 - ???
  F11,          F11,         0,         //0x57 - F11
  F12,          F12,         0,         //0x58 - F12
  0,            0,           0,         //0x59 - ???
  0,            0,           0,         //0x5A - ???
  0,            0,           GUI_L,     //0x5B - ???
  0,            0,           GUI_R,     //0x5C - ???
  0,            0,           APPS,      //0x5D - ???
  0,            0,           0,         //0x5E - ???
  0,            0,           0,         //0x5F - ???
  0,            0,           0,         //0x60 - ???
  0,            0,           0,         //0x61 - ???
  0,            0,           0,         //0x62 - ???
  0,            0,           0,         //0x63 - ???
  0,            0,           0,         //0x64 - ???
  0,            0,           0,         //0x65 - ???
  0,            0,           0,         //0x66 - ???
  0,            0,           0,         //0x67 - ???
  0,            0,           0,         //0x68 - ???
  0,            0,           0,         //0x69 - ???
  0,            0,           0,         //0x6A - ???
  0,            0,           0,         //0x6B - ???
  0,            0,           0,         //0x6C - ???
  0,            0,           0,         //0x6D - ???
  0,            0,           0,         //0x6E - ???
  0,            0,           0,         //0x6F - ???
  0,            0,           0,         //0x70 - ???
  0,            0,           0,         //0x71 - ???
  0,            0,           0,         //0x72 - ???
  0,            0,           0,         //0x73 - ???
  0,            0,           0,         //0x74 - ???
  0,            0,           0,         //0x75 - ???
  0,            0,           0,         //0x76 - ???
  0,            0,           0,         //0x77 - ???
  0,            0,           0,         //0x78 - ???
  0,            0,           0,         //0x78 - ???
  0,            0,           0,         //0x7A - ???
  0,            0,           0,         //0x7B - ???
  0,            0,           0,         //0x7C - ???
  0,            0,           0,         //0x7D - ???
  0,            0,           0,         //0x7E - ???
  0,            0,           0          //0x7F - ???
};

#define KB_IN_BYTES    32  //键盘输入缓冲区大小

struct s_kb
{
  char *p_head;           //指向缓冲区中下一个空闲位置
  char *p_tail;           //指向键盘任务应处理的字节
  int  count;             //缓冲区中共有多少字节
  char buf[KB_IN_BYTES];  //缓冲区
};
struct s_kb *keyBufPoint;
int *keyBoardLifePOint;
void OnKeyEvent();  //键盘中断处理函数

//键盘服务系统相关
int      kb_life = 0;
struct   s_kb kb_in;

t_bool   code_with_E0 = FALSE;
t_bool   shift_l;                // l shift 状态
t_bool   shift_r;                // r shift 状态
t_bool   alt_l;                  // l alt 状态
t_bool   alt_r;                  // r left 状态
t_bool   ctrl_l;                 // l ctrl 状态
t_bool   ctrl_r;                 // l ctrl 状态
t_bool   caps_lock;              // Caps Lock
t_bool   num_lock;               // Num Lock
t_bool   scroll_lock;            // Scroll Lock
int      column = 0;             // keyrow[column] 将是 keymap 中某一个值

void init_keyboard();//初始化键盘

void KeyBoardFun();//键盘动作函数
struct action_s keyBoard = {"keyBoard",&KeyBoardFun,NULL,NULL};

code:keyboard.c(新)
程序代码:
//文件:keyboard.c
//功能:初始化键盘、以及设置中断相关的函数
//作者:miao
//时间:2010-5-24

//键盘中断处理函数
void OnKeyEvent()
{
  //disp_str(" OnKeyEvent ");
  t_8 scan_code = in_byte(KB_DATA); //获取扫描码
  //disp_int(scan_code);

  //将扫描法放入缓冲区
  if(keyBufPoint->count < KB_IN_BYTES)     //若缓冲区未满,将信息记录
  {
    *(keyBufPoint->p_head++) = scan_code;  //记录扫描码
    if(keyBufPoint->p_head == keyBufPoint->buf + KB_IN_BYTES)
      keyBufPoint->p_head = keyBufPoint->buf;
    keyBufPoint->count++;
  }

  //启动键盘域
  if(*keyBoardLifePOint >= 0)
    (*keyBoardLifePOint)++;
}

//键盘中断初始化函数
void init_keyboard()
{
  //注册键盘中断处理域:指定键盘域的life指针
  keyBoardLifePOint = &kb_life;
  kb_life = 0;//键盘域的生命值
  keyBufPoint = &kb_in;
  //初始化键盘缓冲区
  kb_in.count = 0;
  kb_in.p_head = kb_in.p_tail = kb_in.buf;

  //初始化键盘标记
  caps_lock  = 0;
  num_lock  = 1;
  scroll_lock  = 0;

  enable_irq(KEYBOARD_IRQ);  //开键盘中断
}

void keyboard_read();//测试函数,将扫描码中的可显示字符显示到屏幕上
void KeyBoardFun()
{
  if(kb_life > 0)
  {
    keyboard_read();//显示所按键
    kb_life--;
    //disp_int(kb_life);
  }
}

/////////////////////以下为测试用//////////////////////////////
char output[] = "&";
void in_process(t_32 key)
{
  if (!(key & FLAG_EXT))
  {
    output[0] = key & 0xFF;
    disp_str(output);
  }
}
//从键盘缓冲区中读取下一个字节
t_8 get_byte_from_kb_buf()
{
  t_8  scan_code;

  //若键盘缓冲区为空,等待
  while(kb_in.count <= 0)
    disp_str("*");

  asm{cli}
  scan_code = *(kb_in.p_tail++);
  if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES)
    kb_in.p_tail = kb_in.buf;
  kb_in.count--;
  asm{sti}

  return scan_code;
}
//从键盘数据缓冲区读取数据
void keyboard_read()
{
  t_8 scan_code;
  t_bool make;  //TRUE:make FALSE:break
  t_32 key = 0; //用一个整型来表示一个键。
                //比如,如果 Home 被按下,则 key 值将为定义在 keyboard.h 中的 'HOME'。
  t_32 *keyrow; //指向 keymap[] 的某一行

  if(kb_in.count <= 0)//若键盘缓冲区为空,不处理
  {
    disp_str("+");
    return;
  }
  code_with_E0 = FALSE;
  scan_code = get_byte_from_kb_buf();

  if(scan_code== -1)
    return;

  //下面开始解析扫描码
  if (scan_code == 0xE1)
  {
    int i;
    t_8 pausebreak_scan_code[] = {0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5};
    t_bool is_pausebreak = TRUE;
    for(i=1;i<6;i++)
    {
      if (get_byte_from_kb_buf() != pausebreak_scan_code[i])
      {
        is_pausebreak = FALSE;
        break;
      }
    }
    if (is_pausebreak)
      key = PAUSEBREAK;
  }
  else if (scan_code == 0xE0)
  {
    scan_code = get_byte_from_kb_buf();

    //PrintScreen 被按下
    if(scan_code == 0x2A &&
       get_byte_from_kb_buf() == 0xE0 &&
       get_byte_from_kb_buf() == 0x37
      )
    {
      key = PRINTSCREEN;
      make = TRUE;
    }
    //PrintScreen 被释放
    if(scan_code == 0xB7 &&
       get_byte_from_kb_buf() == 0xE0 &&
       get_byte_from_kb_buf() == 0xAA
      )
    {
      key = PRINTSCREEN;
      make = FALSE;
    }
    //不是 PrintScreen。此时 scan_code 为 0xE0 紧跟的那个值。
    if (key == 0)
      code_with_E0 = TRUE;
  }
  if ((key != PAUSEBREAK) && (key != PRINTSCREEN))
  {
    //首先判断Make Code 还是 Break Code
    make = (scan_code & FLAG_BREAK ? FALSE : TRUE);
    //先定位到 keymap 中的行
    keyrow = &keymap[(scan_code & 0x7F) * MAP_COLS];

    column = 0;
    if (shift_l || shift_r)
      column = 1;
    if (code_with_E0)
      column = 2;

    key = keyrow[column];

    switch(key)
    {
      case SHIFT_L: shift_l = make; break;
      case SHIFT_R: shift_r = make; break;
      case CTRL_L:  ctrl_l  = make; break;
      case CTRL_R:  ctrl_r  = make; break;
      case ALT_L:   alt_l   = make; break;
      case ALT_R:   alt_l   = make; break;
      default: break;
    }
  }
  //忽略 Break Code
  if(make)
  {
    key |= shift_l ? FLAG_SHIFT_L : 0;
    key |= shift_r ? FLAG_SHIFT_R : 0;
    key |= ctrl_l  ? FLAG_CTRL_L  : 0;
    key |= ctrl_r  ? FLAG_CTRL_R  : 0;
    key |= alt_l   ? FLAG_ALT_L   : 0;
    key |= alt_r   ? FLAG_ALT_R   : 0;
    in_process(key);
  }
}


[ 本帖最后由 miaowangjian 于 2010-5-31 16:14 编辑 ]
搜索更多相关主题的帖子: 操作系统 模块 键盘 
2010-05-25 01:07
chengstone
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
帖 子:562
专家分:226
注 册:2004-4-3
收藏
得分:0 
域结构不错哦  有点函数调度的意思  目前来说用起来还不错 我比较担心未来在内核当中使用的效率
另:init()  函数里面的AddAction(nullAction); 这句是不是应该改成AddAction(&nullAction);
因为有下面这两句的定义
struct action_s nullAction = {"NullFun",&NullActionFun,NULL,NULL};
void AddAction(struct action_s *newAction)

PS:你的编译器代码也可以贴到这个版里来的,毕竟也算是OS的一部分

qq:69558139
2010-05-25 09:50
miaowangjian
Rank: 2
等 级:论坛游民
帖 子:34
专家分:30
注 册:2010-1-29
收藏
得分:0 
    关于“域”,我是打算作为整个操作系统的运行机制来使用的。
“在内核当中使用的效率”,如果是指作为 “Level0特权级的内核” 与 “Level3特权级的用户态” 间的切换问题的话,这个暂时不用担心,因为我的整个操作系统计划都运行在 “Level0特权级”,也就是说:整个操作系统(含应用程序)就是内核
    这也是我一开始说:““域结构”机制有诸多缺点,最大的一个问题是可靠性与安全性。”的原因。
    当然,在基本完善整个操作系统后,在“内核”外添加一个运行在用户态的“低级域”作为普通应用也是很容易的,要考虑的主要问题是与内核的“高级域”的通信问题(类似普通系统的系统调用)。

    对于“域”的问题,现在也还没什么可讨论的,因为大部分都还没实现。。。。我会在后面随着操作系统的编写逐渐设计完善并解释的。

    AddAction(nullAction);(还有AddAction(keyBoard);),从c语言语法上来说,确实应该加上一个取址符号(&),我最近都在用AS3.0编程,使用类对象传来传去,都忘记c的问题了,加上编译器(yc09)没报错……
    我刚刚反汇编对比了一下加上取址符号(&)前后的情况,反编译出的汇编指令是一样的。看来yc09将所有的结构体类型变量的传递都自动改为址传递了(与C99标准不符)。。。
    其实yc09还有许多地方在语法上和内部机制上与c标准也是不符的。但我个人还是比较喜欢这种特性的(尽管会导致不兼容与移植问题)。

    关于编译器,或者说“域语言编译器”,我是打算用“域语言”来设计和实现的(至少是用c写符合“域语言”规则来写)。对于我的这个操作系统来说,域语言编译器是非常重要的一个组成部分,在我实现了一个简单的tty和编辑器后,马上就要将它提上日程了。
    若指的是我作为热身,使用AS3.0编写的“C解释器”,最简陋的原始版的代码(1千行左右)我可以这两天内贴上来,至于第二版,还在完善中(代码很多,又都是一个整体,不能像操作系统一样,一部分一部分贴出来),什么时候能贴出来请大家指导,就难说了。。。
2010-05-25 14:30
chengstone
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
帖 子:562
专家分:226
注 册:2004-4-3
收藏
得分:0 
哈哈哈 我已经爱上你的系统了  你加油干吧 我一直对你的域结构未来发挥的作用很感兴趣   对于域结构在进程之间切换时的调度需要你多加考虑 目前为止你的内核不存在进程的概念 不知道你是否会在你的内核里面以其他的方式来实现进程还是根本不会用进程的方式处理程序 对于这个我觉得还挺有悬念的

qq:69558139
2010-05-25 18:01
chengstone
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
帖 子:562
专家分:226
注 册:2004-4-3
收藏
得分:0 
至于编译器我指的是你内核的编译器 就是域语言编译器

qq:69558139
2010-05-25 18:02
miaowangjian
Rank: 2
等 级:论坛游民
帖 子:34
专家分:30
注 册:2010-1-29
收藏
得分:0 
    
    我的这个系统,进程的职能,完全由域语言+域编译器(可能应该属于是实时编译器)+域管理器代替,也就不需要进程调度什么的,只是简单的不断循环调用域动作链表里的动作函数(这样,功能上会有所不足,后面会提到解决方案)。
    将来,为了弥补 域结构 机制带来的不可靠性和安全性(如域动作链表执行时,某个函数进入死循环、出现异常错误,或是非法使用一些特权指令等),可能会实现整个操作系统仅有的两个进程,一个执行在内核态的 域结构 ,一个执行在 用户态的 域结构。因为只有两个进程,调度也就非常简单了。。。这些,还是非常遥远的事,近期来看,完全不用考虑“进程”的概念。
    具体的,等待后面的部分吧
2010-05-25 18:28
miaowangjian
Rank: 2
等 级:论坛游民
帖 子:34
专家分:30
注 册:2010-1-29
收藏
得分:0 
因为我的粗心,将帖子里的
下面是此次修改了的文件和新添加的文件:
code:i8259.c(改)
错写成了
下面是此次修改了的文件和新添加的文件:
code:klib.c(改)
十分抱歉

先已改正
    若大家发现其他错误,欢迎指正。

2010-05-31 17:26
编程小将
Rank: 1
来 自:萧县
等 级:新手上路
帖 子:14
专家分:0
注 册:2010-12-8
收藏
得分:0 
来看看

玩的不是很时尚,但你绝对跟不上!
2010-12-11 00:22
快速回复:一步步写操作系统之第四步:创建键盘中断处理模块和初步搭建程序执行系 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.042339 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved