The Keyboard Controller Essential steps for implementing Keyboard Controller

advertisement
The Keyboard Controller
Essential steps for implementing
an interrupt service routine for the
Keyboard Controller
Our near-term goal
• To build a ‘mini’ x86 operating system
• It should be able run a Linux application
• It needs to support:
– basic console input/output (keyboard, screen)
– handling of device-interrupts (timer, keyboard)
– ‘exit’ gracefully when application is finished
– utilize x86 privilege restrictions and 32bit code
• Certain building-blocks are already done
Keyboard and its controller
PIC
IRQ2
CPU
PIC
IRQ0
RAM
IRQ1
0x64
0x64
0x60
0x60
bus
control reg
TIMER
status reg
input buffer
output buffer
Keyboard Controller
output port
input port
PS/2 MOUSE
KEYBOARD
KB Controller Status
7
6
5
4
3
2
1
0
PARE
TIM
AUXB
KEYL
C/D
SYSF
INPB
OUTB
LEGEND
OUTB: Output-Buffer Full (1=yes, 0=no)
INPB: Input-Buffer Full (1=yes, 0=no)
SYSF: System-Flag (1=self-test successful, 0=power-on reset)
C/D: Command/Data was written to (1=port 0x64, 0=port 0x60)
KEYL: Keyboard-Lock status (1=keyboard available, 0=locked)
AUXB: Output-Buffer’s data is (1=for mouse, 0=for keyboard)
TIM: General Timeout-Error has occurred (1=yes, 0=no)
PARE: Parity-Error on last byte from keyboard/mouse (1=yes, 0=no)
A few Controller Commands
•
•
•
•
•
•
0xAD: Disable Keyboard
0xAE: Enable Keyboard
0xA7: Disable PS/2 Mouse
0xA8: Enable PS/2 Mouse
0xC0: Read input-port (to output buffer)
0XD0: Read output-port (to output buffer)
Command to set LEDs
• 0xED: Turns on/off the keyboard’s LEDs
#
#
#
•
•
•
•
Algorithm to change the keyboard’s Light Emitting Diodes
Wait until keyboard controller’s output buffer is not full
Output command-byte 0xED to port 0x60
Wait until keyboard controller’s output buffer is not full
Output octal value 0..7 to port 0x60
2
Octal-value =
1
CAPS
LOCK
NUM
LOCK
1=on
0=off
1=on
0=off
0
SCROLL
LOCK
1=on
0=off
Interrupt-Handler actions
• When the keyboard-controller issues an
interrupt, these actions should be taken:
–
–
–
–
–
–
–
–
–
Save values in the working CPU registers
Read keyboard-controller’s status-register
If the output-buffer has new data, read it
If a “special” key (shift/toggle), adjust kb_flags
For a normal key, translate scancode to ascii
Insert the code-pair at tail-end of kb-queue
Send EOI-command to Interrupt Controller
Restore the saved values from CPU registers
Resume the interrupted procedure (with ‘iret’)
Keyboard ‘scancode’ format
7
6
5
4
3
2
1
0
BRK
Key identifier (bits 6..0)
BRK (bit 7)
1 = ’Break’ (the key was released)
0 = ‘Make’ (the key was pressed)
Keyboard Queue
KBHEAD
KBTAIL
BIOS DATA AREA
•
•
•
•
KBFLAGS is word at address 0x40:0x17
KBHEAD is word at address 0x40:0x1A
KBTAIL is word at address 0x40:0x1C
KBQUEUE is array of 16 words
array base-address at 0x40:0x1E
• KBBASE is word at 0x40:0x80
• KBEDGE is word at 0x40:0x82
Format of KBFLAGS LSB
7
6
5
4
3
2
1
0
Insert-mode is active (1=yes, 0=no)
Caps-Lock is active (1=yes, 0=no)
Num-Lock is active (1=yes, 0=no)
Scroll-Lock is active (1=yes, 0=no)
Alt-Key is pressed (1=yes, 0=no)
Ctrl-Key is pressed (1=yes, 0=no)
Right-Shift key is pressed (1=yes, 0=no)
Left-Shift key is pressed (1=yes, 0=no)
Demo ‘minikybd.s’
• It shows a minimal implementation for the
keyboard-controller’s interrupt-handler
• It runs in Real-Mode
• It ‘echos’ a user’s keystrokes
Download