-
Notifications
You must be signed in to change notification settings - Fork 2
/
PS2Keyboard.c
163 lines (127 loc) · 2.77 KB
/
PS2Keyboard.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <Driver/IO/PortIO.h>
// PS2 Out Port의 Buffer가 차있는지
BOOL PS2CheckOutputBufferNotEmpty()
{
if(PortIO_InByte(0x64) & 0x01)
return TRUE;
return FALSE;
}
// PS2 In Port의 Buffer가 차있는지
BOOL PS2CheckInputBufferNotEmpty()
{
if(PortIO_InByte(0x64) & 0x02)
return TRUE;
return FALSE;
}
// PS2 Port의 응답을 확인 & 키 코드를 푸시
BOOL WaitACKWithScanCodePushQueue()
{
BOOL result = FALSE;
for(int i = 0; i< 100; i++)
{
//0xFFFF 만큼 반복할 시간안에 응답이 충분히 옴
for(int j = 0 ; j < 0xFFFF; j++)
{
if(PS2CheckOutputBufferNotEmpty())
break;
}
//데이터가 ACK이면, 이전 요청에 대한 응답
BYTE data = PortIO_InByte(0x60);
if(data == 0xFA)
{
result = TRUE;
break;
}
else
{
ConvertScanCodeWithPushKeyQueue(data);
}
}
return result;
}
BOOL PS2ActivationKeyboard()
{
//키보드 활성화 PORT IO 기능 사용
BOOL interrupt_status = SetInterruptFlag(FALSE);
PortIO_OutByte( 0x64, 0xAE );
for(int i=0; i< 0xFFFF; i++)
{
if(PS2CheckInputBufferNotEmpty() == FALSE)
{
break;
}
}
PortIO_OutByte(0x60, 0xF4);
BOOL result = WaitACKWithScanCodePushQueue();
SetInterruptFlag(interrupt_status);
return result;
}
//PortIO를 통한 A20게이트 활성화
void PS2EnableA20Gate()
{
PortIO_OutByte(0x64, 0xD0);
for(int i = 0; i < 0xFFFF; i++)
{
if(PS2CheckOutputBufferNotEmpty() == TRUE)
break;
}
BYTE OutPutData = PortIO_InByte(0x60);
OutPutData |= 0x01;
for(int i=0; i < 0xFFFF; i++)
{
if(PS2CheckInputBufferNotEmpty() == FALSE)
break;
}
PortIO_OutByte(0x64, 0xD1);
PortIO_OutByte(0x60, OutPutData);
}
//Keyboard의 LED를 On Off
BOOL PS2SetKeyboardLED(BOOL _CapsLockOn, BOOL _NumLockOn, BOOL _ScrollLockOn)
{
BOOL intrrupt_status = SetInterruptFlag(FALSE);
//Busy Waiting 0xFFFF Iteration.
for(int i = 0; i< 0xFFFF; i++)
{
if(PS2CheckInputBufferNotEmpty() == FALSE)
break;
}
//LED 상태 변경 커멘드 전송
PortIO_OutByte(0x60, 0xED);
for(int i = 0; i < 0xFFFF; i++)
{
if(PS2CheckInputBufferNotEmpty() == FALSE)
break;
}
BOOL result = WaitACKWithScanCodePushQueue();
if(result == FALSE)
return FALSE;
// LED 변경 값 전송 후 대기
PortIO_OutByte( 0x60, (_CapsLockOn << 2)|(_NumLockOn << 1)|(_ScrollLockOn));
for(int i = 0; i< 0xFFFF; i++)
{
if(PS2CheckInputBufferNotEmpty() == FALSE)
break;
}
result = WaitACKWithScanCodePushQueue();
if(result == FALSE)
return FALSE;
return TRUE;
}
void PS2Reboot()
{
for(int i = 0; i < 0xFFFF; i++)
{
if(PS2CheckInputBufferNotEmpty() == FALSE)
break;
}
PortIO_OutByte(0x64, 0xD1);
PortIO_OutByte(0x60, 0x00);
while(1)
{
}
}
BYTE PS2GetKeyboardScanCode()
{
while(PS2CheckOutputBufferNotEmpty() == FALSE);
return PortIO_InByte(0x60);
}