这周和@whr 一起实现了Kestrel kernel的键盘响应,摒弃了原先使用的grub代码。 今天来总结一下代实现的关键

我们的核心汇编代码, 我来简单解读下
ENTRY(int21_handler)
cli      /* 禁用中断 */
pushw %es
pushw %ds
pushl %eax
pushl %ecx
pushl %edx
pushl %ebx
pushl %esp
pushl %ebp
pushl %esi
pushl %edi     /* 入栈, 保存现场 */
movb $0x61, %al        
outb %al, $PIC0_OCW2        /* 使用0x61去复位键盘中断 */
xorl %eax, %eax        /* 对eax寄存器清零 */
movw $0x0060, %dx  /* Port 0x60 是对PS/2 进行 read/write 的 Data Port */
inb %dx, %al             /* 从Port 0x60取出keycode到ax */
pushl %eax              /* 保护keycode */
movw %ss, %ax
movw %ax, %ds
movw %ax, %es
call input_buffer_put
cli
popl %eax
popl %edi
popl %esi
popl %ebp
popl %esp
popl %ebx
popl %edx
popl %ecx
popl %eax
popw %ds
popw %es
sti      /* 开启cpu中断 */
iret</pre></p>

下面附上一些wiki.osdev.org的资料:</h3>
 </p>

PS/2 Controller IO Ports</span></p>

The PS/2 Controller itself uses 2 IO ports (IO ports 0x60 and 0x64). Like many IO ports, reads and writes may access completely different internal registers.

Historical note : The PC-XT PPI had used port 0x61 to reset the keyboard interrupt request signal (among other unrelated functions). Port 0x61 has no keyboard related functions on AT and PS/2 compatibles.

IO Port</th></p> Access Type</th></p> Purpose</th>
</tr></p>
0x60</td></p> Read/Write</td></p> Data Port</td>
</tr></p>
0x64</td></p> Read</td></p> Status Register</td>
</tr></p>
0x64</td></p> Write</td></p> Command Register</td>
</tr>
</tbody>
</table>
关于通过keycode获取按键:</p>

wiki里给出了us键盘的keycode对应的按键,传送门:http://wiki.osdev.org/PS2_Keyboard#Scan_Code_Set_1</a></p>

简单的实现方法</p>

/*
static char keymap[] = {
-1, 0x1b, '1', '2', '3', '4', '5', '6', '7'
}*/
/* static char en_keymap1[] = " qwertyuiop[]\r";
static char en_keymap2[] = "asdfghjkl;'";
static char en_keymap3[] = "\\zxcvbnm,./";
static char extra_number_keymap[] = "789-456+1230.";

static char en_shift_keymap1[] = " QWERTYUIOP{}\r";
static char en_shift_keymap2[] = "ASDFGHJKL:\"";
static char en_shift_keymap3[] = "|ZXCVBNM<>?";

enum {L_SHIFT_P=0x2a, R_SHIFT_P=0x36, L_SHIFT_R=0xAA, R_SHIFT_R=0xB6}; */

switch(code) {
case 0x1:
return 0x1b;
case 0x2 ... 0xa:
return code + 0x2f;
case 0xb:
return 0x30;
case 0xc:
if(!shift_pressed){
return '-';
}else{
return '_';
}
case 0xd:
if(!shift_pressed){
return '=';
}else{
return '+';
}
case 0xe:
return 8;
case 0xf ... 0x1c:
if(!shift_pressed){
return en_keymap1[code - 0xf];
}else{
return en_shift_keymap1[code - 0xf];
}
case 0x1d:
return 0x1;
case 0x1e ... 0x29:
if(!shift_pressed){
return en_keymap2[code - 0x1e];
}else{
return en_shift_keymap2[code - 0x1e];
}
case 0x2b ... 0x35:
if(!shift_pressed){
return en_keymap3[code - 0x2b];
}else{
return en_shift_keymap3[code - 0x2b];
}
case 0x37:
return '*'; // Extra
case 0x39:
return ' ';
case 0x47 ... 0x53:
return extra_number_keymap[code - 0x47];
case L_SHIFT_P:
case R_SHIFT_P:
shift_checked = 0;
shift_pressed = 1;
/* kernel_printf("shift pressed\n"); */
return;

/* release */
case L_SHIFT_R:
case R_SHIFT_R:
shift_checked = 0;
shift_pressed = 0;
/* kernel_printf("shift releaseed\n"); */
return;

}
return -2;
}</pre>