00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/init.h>
00016 #include <agnix/ioport.h>
00017 #include <agnix/console.h>
00018 #include <agnix/terminal.h>
00019 #include <agnix/memory.h>
00020 #include <agnix/irq.h>
00021 #include <agnix/machine.h>
00022
00023 #define MOD_NAME "CHAR_KBD: \t"
00024
00025 #define KBD_DTA_PORT 0x60
00026 #define KBD_CMD_PORT 0x64
00027 #define KBD_STS_PORT 0x64
00028
00029 #define KBD_DCMD_READID 0xF2
00030 #define KBD_DCMD_SETDELAY 0xF3
00031 #define KBD_DCMD_ENABLE 0xF4
00032 #define KBD_DCMD_DISABLE 0xF5
00033 #define KBD_DCMD_RESET 0xFF
00034
00035 #define KBD_CCMD_WRITEMODE 0x60
00036 #define KBD_CCMD_SELFTEST 0xAA
00037 #define KBD_CCMD_IFACETEST 0xAB
00038 #define KBD_CCMD_SETLEDS 0xED
00039
00040 #define KBD_WAIT_LOOPS 10000000
00041 #define KBD_STS_OBF 0x01
00042 #define KBD_STS_IBF 0x02
00043 #define KBD_STS_PERR 0x80
00044 #define KBD_STS_GTMO 0x40
00045
00046 #define KBD_IRQ 1
00047
00048 #define SPECIAL 0
00049 #define KBD_CODE_ESC 0x01
00050 #define KBD_CODE_BACKSPACE 0x0E
00051 #define KBD_CODE_TAB 0x0F
00052 #define KBD_CODE_CTRL 0x1D
00053 #define KBD_CODE_SHIFTL 0x2A
00054 #define KBD_CODE_SHIFTR 0x36
00055 #define KBD_CODE_PRINT 0x37
00056 #define KBD_CODE_ALT 0x38
00057 #define KBD_CODE_CAPS 0x3A
00058 #define KBD_CODE_SCROLL 0x45
00059 #define KBD_CODE_NUM 0x46
00060
00061 #define KBD_CODE_F1 0x3B
00062 #define KBD_CODE_F2 0x3C
00063 #define KBD_CODE_F3 0x3D
00064 #define KBD_CODE_F4 0x3E
00065 #define KBD_CODE_F5 0x3F
00066 #define KBD_CODE_F6 0x40
00067 #define KBD_CODE_F7 0x41
00068 #define KBD_CODE_F8 0x42
00069 #define KBD_CODE_F9 0x43
00070 #define KBD_CODE_F10 0x44
00071
00072
00073
00074 #define ENTER 10
00075 #define F1 'A'
00076 #define F2 'B'
00077 #define F3 'C'
00078 #define F4 'D'
00079 #define F5 'E'
00080 #define F6 'F'
00081 #define F7 'G'
00082 #define F8 'H'
00083 #define F9 'I'
00084 #define F10 'J'
00085 #define F11 'K'
00086 #define F12 'L'
00087 #define PAUSE 'P'
00088
00089 #define KBD_LED_SCROLL 0x01
00090 #define KBD_LED_NUM 0x02
00091 #define KBD_LED_CAPS 0x04
00092
00093 #define KBD_FLG_SCROLL KBD_LED_SCROLL
00094 #define KBD_FLG_NUM KBD_LED_NUM
00095 #define KBD_FLG_CAPS KBD_LED_CAPS
00096 #define KBD_FLG_SHIFT 0x08
00097 #define KBD_FLG_CNTRL 0x10
00098 #define KBD_FLG_ALT 0x20
00099
00100 #define MAX_KBD_ACTIONS 16
00101
00102 extern int term_cur;
00103 extern struct terminal_s term_sys[MAX_TERMINALS];
00104
00105 u8 kbd_flags = 0;
00106
00107 int kbd_action_count = 0;
00108
00109 struct kbd_action_s {
00110 u8 active_flags;
00111 u8 passive_flags;
00112 u8 scancode;
00113 int (*kbd_action_routine)(int scancode);
00114 };
00115
00116 struct kbd_action_s kbd_action[MAX_KBD_ACTIONS];
00117
00118 char scancode_to_ascii[0x100] = {
00119 SPECIAL, SPECIAL,
00120 '1','2','3','4','5','6','7','8','9','0','-','=',
00121 SPECIAL, SPECIAL,
00122 'q','w','e','r','t','y','u','i','o','p','[',']',ENTER,SPECIAL,
00123 'a','s','d','f','g','h','j','k','l',';','\'',SPECIAL,'\\',
00124 '<','z','x','c','v','b','n','m',',','.','/',SPECIAL,SPECIAL,SPECIAL,
00125 ' ',SPECIAL,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,PAUSE,SPECIAL,SPECIAL,
00126 };
00127
00128 char scancode_to_ascii_shift[0x100] = {
00129 SPECIAL, SPECIAL,
00130 '!','@','#','$','%','^','&','*','(',')','_','+',
00131 SPECIAL, SPECIAL,
00132 'Q','W','E','R','T','Y','U','I','O','P','{','}',ENTER,SPECIAL,
00133 'A','S','D','F','G','H','J','K','L',':','"',SPECIAL,'|',
00134 '>','Z','X','C','V','B','N','M','<','>','?',SPECIAL,SPECIAL,SPECIAL,
00135 ' ',SPECIAL,'~','~','~','~','~','~','~','~','~','~','~','~',PAUSE,SPECIAL,SPECIAL,
00136 };
00137
00138
00139
00140 u8 kbd_status_read(void)
00141 {
00142 u8 status;
00143
00144 status = inb(KBD_STS_PORT);
00145
00146 return status;
00147 }
00148
00149 int kbd_wait_for_bf(u8 which_bf, int neg)
00150 {
00151 u8 status;
00152 int wait_loops = KBD_WAIT_LOOPS;
00153
00154 for (; wait_loops >= 0; wait_loops--) {
00155 status = kbd_status_read();
00156
00157 if (neg) {
00158 if (!(status & which_bf))
00159 return 1;
00160 }
00161 else {
00162 if (status & which_bf)
00163 return 1;
00164 }
00165 }
00166
00167 return 0;
00168 }
00169
00170 int kbd_wait_for_notibf(void)
00171 {
00172 return kbd_wait_for_bf(KBD_STS_IBF, 1);
00173 }
00174
00175 int kbd_wait_for_obf(void)
00176 {
00177 return kbd_wait_for_bf(KBD_STS_OBF, 0);
00178 }
00179
00180 void kbd_data_write(u8 cmd)
00181 {
00182 kbd_wait_for_notibf();
00183 outb(cmd, KBD_DTA_PORT);
00184 }
00185
00186 char kbd_data_read(void)
00187 {
00188 u8 status;
00189 char data = -1;
00190
00191 status = kbd_status_read();
00192
00193 if ((status & KBD_STS_OBF) && !(status & (KBD_STS_PERR | KBD_STS_GTMO))) {
00194
00195 data = inb(KBD_DTA_PORT);
00196 }
00197
00198 return data;
00199 }
00200
00201 char kbd_data_read_wait(void)
00202 {
00203 char data = -1;
00204
00205 if (kbd_wait_for_obf())
00206 data = kbd_data_read();
00207
00208 return data;
00209 }
00210
00211 void kbd_cmd_write(u8 cmd)
00212 {
00213 kbd_wait_for_notibf();
00214 outb(cmd, KBD_CMD_PORT);
00215 }
00216
00217 void kbd_set_leds(u8 leds_mask)
00218 {
00219 kbd_data_write(KBD_CCMD_SETLEDS);
00220 kbd_data_write(leds_mask);
00221 }
00222
00223 int kbd_change_led_flag(u8 led_flag)
00224 {
00225 if (kbd_flags & led_flag)
00226 kbd_flags &= ~led_flag;
00227 else
00228 kbd_flags |= led_flag;
00229
00230 return 1;
00231 }
00232
00233 void kbd_irq_handler(u32 data)
00234 {
00235 u8 status;
00236 u8 scancode;
00237 char asciicode;
00238 int leds_changed = 0;
00239 int i, k;
00240
00241 for (k = 0; k < 20000; k++) {
00242
00243 status = kbd_status_read();
00244 if ((status & KBD_STS_OBF) && !(status & (KBD_STS_PERR | KBD_STS_GTMO))) {
00245
00246 scancode = inb(KBD_DTA_PORT);
00247
00248 switch(scancode) {
00249 case KBD_CODE_CTRL:
00250 kbd_flags |= KBD_FLG_CNTRL;
00251 break;
00252 case KBD_CODE_CTRL+128:
00253 kbd_flags &= ~KBD_FLG_CNTRL;
00254 break;
00255 case KBD_CODE_ALT:
00256 kbd_flags |= KBD_FLG_ALT;
00257 break;
00258 case KBD_CODE_ALT+128:
00259 kbd_flags &= ~KBD_FLG_ALT;
00260 break;
00261 case KBD_CODE_CAPS:
00262 leds_changed = kbd_change_led_flag(KBD_FLG_CAPS);
00263 break;
00264 case KBD_CODE_SCROLL:
00265 leds_changed = kbd_change_led_flag(KBD_FLG_SCROLL);
00266 break;
00267 case KBD_CODE_NUM:
00268 leds_changed = kbd_change_led_flag(KBD_FLG_NUM);
00269 break;
00270 case KBD_CODE_SHIFTR:
00271 case KBD_CODE_SHIFTL:
00272 kbd_flags |= KBD_FLG_SHIFT;
00273 break;
00274 case KBD_CODE_SHIFTR+128:
00275 case KBD_CODE_SHIFTL+128:
00276 kbd_flags &= ~KBD_FLG_SHIFT;
00277 break;
00278 default:
00279
00280 if ((scancode >= KBD_CODE_F1) && (scancode <= KBD_CODE_F10) &&
00281 (kbd_flags & KBD_FLG_ALT)) {
00282 terminal_switch(scancode - KBD_CODE_F1);
00283 break;
00284 }
00285
00286 if (scancode < 128) {
00287
00288 if ((kbd_flags & KBD_FLG_SHIFT) || (kbd_flags & KBD_FLG_CAPS))
00289 asciicode = scancode_to_ascii_shift[scancode];
00290 else
00291 asciicode = scancode_to_ascii[scancode];
00292
00293 if (asciicode != 0) {
00294 if (term_sys[term_cur].ops && term_sys[term_cur].ops->write_char)
00295 term_sys[term_cur].ops->write_char(&term_sys[term_cur], asciicode);
00296
00297 }
00298 }
00299 }
00300
00301 for (i = 0; i < kbd_action_count; i++) {
00302 if (((!kbd_action[i].scancode) || (kbd_action[i].scancode == scancode)) &&
00303 ((kbd_action[i].active_flags & kbd_flags) == kbd_action[i].active_flags)) {
00304 kbd_action[i].kbd_action_routine(scancode);
00305 }
00306 }
00307
00308 if (leds_changed)
00309 kbd_set_leds(kbd_flags & 0x07);
00310
00311 break;
00312 }
00313 }
00314
00315 if (k == 20000)
00316 printk("Keyboard interrupt error!\n");
00317 }
00318
00319 int kbd_screen_scroll = 0;
00320
00321 int kbd_screen_up(int scancode)
00322 {
00323 kbd_screen_scroll++;
00324
00325 term_sys[term_cur].term_driver->ops->refresh(&term_sys[term_cur], kbd_screen_scroll);
00326
00327 return 0;
00328 }
00329
00330 int kbd_screen_down(int scancode)
00331 {
00332 if (kbd_screen_scroll > 0) {
00333 kbd_screen_scroll--;
00334 term_sys[term_cur].term_driver->ops->refresh(&term_sys[term_cur], kbd_screen_scroll);
00335 }
00336
00337 return 0;
00338 }
00339
00340 int cad_power_down(int scancode)
00341 {
00342 do_machine_reboot();
00343
00344
00345 return 0;
00346 }
00347
00348 int kbd_set_actions(void)
00349 {
00350 memset(kbd_action, 0, sizeof(struct kbd_action_s) * MAX_KBD_ACTIONS);
00351
00352 kbd_action[0].active_flags = 0;
00353 kbd_action[0].passive_flags = 0;
00354 kbd_action[0].scancode = 73;
00355 kbd_action[0].kbd_action_routine = kbd_screen_up;
00356
00357 kbd_action[1].active_flags = 0;
00358 kbd_action[1].passive_flags = 0;
00359 kbd_action[1].scancode = 81;
00360 kbd_action[1].kbd_action_routine = kbd_screen_down;
00361
00362 kbd_action[2].active_flags = KBD_FLG_ALT | KBD_FLG_CNTRL;
00363 kbd_action[2].passive_flags = 0;
00364 kbd_action[2].scancode = 0x53;
00365 kbd_action[2].kbd_action_routine = cad_power_down;
00366
00367 kbd_action_count = 3;
00368
00369 return 0;
00370 }
00371
00372 struct irq_routine_s kbd_irq_routine = {
00373 kbd_irq_handler, 0, IRQ_FLAG_RANDOM,
00374 };
00375
00376 int adi_chrdrv_kbd_init(void)
00377 {
00378 char data;
00379
00380 printk(MOD_NAME "PC keyboard ... ");
00381
00382 kbd_cmd_write(KBD_CCMD_SELFTEST);
00383 if ((data=kbd_data_read_wait()) != 0x55) {
00384 printk("Your keyboard is failed!\n");
00385 return -1;
00386 }
00387
00388 kbd_cmd_write(KBD_CCMD_IFACETEST);
00389 if (kbd_data_read_wait() != 0x00) {
00390 printk("Your keyboard is failed!\n");
00391 return -1;
00392 }
00393
00394 printk("ok\n");
00395
00396 kbd_cmd_write(KBD_CCMD_WRITEMODE);
00397 kbd_data_write(0x40 | 0x20 | 0x04 | 0x01);
00398
00399
00400 kbd_data_write(KBD_DCMD_ENABLE);
00401
00402 kbd_set_leds(0x00);
00403
00404 kbd_set_actions();
00405
00406 install_irq(KBD_IRQ, &kbd_irq_routine);
00407
00408 return 0;
00409 }