00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "../drivers.h"
00010 #include <sys/ioctl.h>
00011 #include <sys/kbdio.h>
00012 #include <sys/time.h>
00013 #include <sys/select.h>
00014 #include <termios.h>
00015 #include <signal.h>
00016 #include <unistd.h>
00017 #include <minix/callnr.h>
00018 #include <minix/com.h>
00019 #include <minix/keymap.h>
00020 #include "tty.h"
00021 #include "keymaps/us-std.src"
00022 #include "../../kernel/const.h"
00023 #include "../../kernel/config.h"
00024 #include "../../kernel/type.h"
00025 #include "../../kernel/proc.h"
00026
00027 int irq_hook_id = -1;
00028 int aux_irq_hook_id = -1;
00029
00030
00031 #define KEYBD 0x60
00032
00033
00034 #define KB_COMMAND 0x64
00035 #define KB_STATUS 0x64
00036 #define KB_ACK 0xFA
00037 #define KB_AUX_BYTE 0x20
00038 #define KB_OUT_FULL 0x01
00039 #define KB_IN_FULL 0x02
00040 #define KBC_RD_RAM_CCB 0x20
00041 #define KBC_WR_RAM_CCB 0x60
00042 #define KBC_DI_AUX 0xA7
00043 #define KBC_EN_AUX 0xA8
00044 #define KBC_DI_KBD 0xAD
00045 #define KBC_EN_KBD 0xAE
00046 #define KBC_WRITE_AUX 0xD4
00047 #define LED_CODE 0xED
00048 #define MAX_KB_ACK_RETRIES 0x1000
00049 #define MAX_KB_BUSY_RETRIES 0x1000
00050 #define KBIT 0x80
00051
00052 #define KBC_IN_DELAY 7
00053
00054
00055 #define ESC_SCAN 0x01
00056 #define SLASH_SCAN 0x35
00057 #define RSHIFT_SCAN 0x36
00058 #define HOME_SCAN 0x47
00059 #define INS_SCAN 0x52
00060 #define DEL_SCAN 0x53
00061
00062 #define KBD_BUFSZ 1024
00063 #define KBD_OUT_BUFSZ 16
00064
00065
00066
00067 #define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
00068
00069 #define CONSOLE 0
00070 #define KB_IN_BYTES 32
00071 PRIVATE char ibuf[KB_IN_BYTES];
00072 PRIVATE char *ihead = ibuf;
00073 PRIVATE char *itail = ibuf;
00074 PRIVATE int icount;
00075
00076 PRIVATE int esc;
00077 PRIVATE int alt_l;
00078 PRIVATE int alt_r;
00079 PRIVATE int alt;
00080 PRIVATE int ctrl_l;
00081 PRIVATE int ctrl_r;
00082 PRIVATE int ctrl;
00083 PRIVATE int shift_l;
00084 PRIVATE int shift_r;
00085 PRIVATE int shift;
00086 PRIVATE int num_down;
00087 PRIVATE int caps_down;
00088 PRIVATE int scroll_down;
00089 PRIVATE int locks[NR_CONS];
00090
00091
00092 #define SCROLL_LOCK 0x01
00093 #define NUM_LOCK 0x02
00094 #define CAPS_LOCK 0x04
00095
00096 PRIVATE char numpad_map[] =
00097 {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
00098
00099
00100 typedef struct observer { int proc_nr; int events; } obs_t;
00101 PRIVATE obs_t fkey_obs[12];
00102 PRIVATE obs_t sfkey_obs[12];
00103
00104 PRIVATE struct kbd
00105 {
00106 int minor;
00107 int nr_open;
00108 char buf[KBD_BUFSZ];
00109 int offset;
00110 int avail;
00111 int req_size;
00112 int req_proc;
00113 vir_bytes req_addr;
00114 int incaller;
00115 int select_ops;
00116 int select_proc;
00117 } kbd, kbdaux;
00118
00119
00120
00121
00122 PRIVATE struct kbd_outack
00123 {
00124 unsigned char buf[KBD_OUT_BUFSZ];
00125 int offset;
00126 int avail;
00127 int expect_ack;
00128 } kbdout;
00129
00130 PRIVATE int kbd_watchdog_set= 0;
00131 PRIVATE int kbd_alive= 1;
00132 PRIVATE timer_t tmr_kbd_wd;
00133
00134 FORWARD _PROTOTYPE( void handle_req, (struct kbd *kbdp, message *m) );
00135 FORWARD _PROTOTYPE( int handle_status, (struct kbd *kbdp, message *m) );
00136 FORWARD _PROTOTYPE( void kbc_cmd0, (int cmd) );
00137 FORWARD _PROTOTYPE( void kbc_cmd1, (int cmd, int data) );
00138 FORWARD _PROTOTYPE( int kbc_read, (void) );
00139 FORWARD _PROTOTYPE( void kbd_send, (void) );
00140 FORWARD _PROTOTYPE( int kb_ack, (void) );
00141 FORWARD _PROTOTYPE( int kb_wait, (void) );
00142 FORWARD _PROTOTYPE( int func_key, (int scode) );
00143 FORWARD _PROTOTYPE( int scan_keyboard, (unsigned char *bp, int *isauxp) );
00144 FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
00145 FORWARD _PROTOTYPE( void set_leds, (void) );
00146 FORWARD _PROTOTYPE( void show_key_mappings, (void) );
00147 FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try) );
00148 FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
00149 FORWARD _PROTOTYPE( void micro_delay, (unsigned long usecs) );
00150 FORWARD _PROTOTYPE( void kbd_watchdog, (timer_t *tmrp) );
00151
00152
00153
00154
00155 PUBLIC void do_kbd(message *m)
00156 {
00157 handle_req(&kbd, m);
00158 }
00159
00160
00161
00162
00163
00164 PUBLIC int kbd_status(message *m)
00165 {
00166 int r;
00167
00168 r= handle_status(&kbd, m);
00169 if (r)
00170 return r;
00171 return handle_status(&kbdaux, m);
00172 }
00173
00174
00175
00176
00177
00178 PUBLIC void do_kbdaux(message *m)
00179 {
00180 handle_req(&kbdaux, m);
00181 }
00182
00183
00184
00185
00186
00187 PRIVATE void handle_req(kbdp, m)
00188 struct kbd *kbdp;
00189 message *m;
00190 {
00191 int i, n, r, ops, watch;
00192 unsigned char c;
00193
00194
00195 r= EINVAL;
00196 switch (m->m_type) {
00197 case DEV_OPEN:
00198 kbdp->nr_open++;
00199 r= OK;
00200 break;
00201 case DEV_CLOSE:
00202 kbdp->nr_open--;
00203 if (kbdp->nr_open < 0)
00204 {
00205 printf("TTY(kbd): open count is negative\n");
00206 kbdp->nr_open= 0;
00207 }
00208 if (kbdp->nr_open == 0)
00209 kbdp->avail= 0;
00210 r= OK;
00211 break;
00212 case DEV_READ:
00213 if (kbdp->req_size)
00214 {
00215
00216 r= EIO;
00217 break;
00218 }
00219 if (kbdp->avail == 0)
00220 {
00221
00222 kbdp->req_size= m->COUNT;
00223 kbdp->req_proc= m->IO_ENDPT;
00224 kbdp->req_addr= (vir_bytes)m->ADDRESS;
00225 kbdp->incaller= m->m_source;
00226 r= SUSPEND;
00227 break;
00228 }
00229
00230
00231 n= kbdp->avail;
00232 if (n > m->COUNT)
00233 n= m->COUNT;
00234 if (kbdp->offset + n > KBD_BUFSZ)
00235 n= KBD_BUFSZ-kbdp->offset;
00236 if (n <= 0)
00237 panic("TTY", "do_kbd(READ): bad n", n);
00238 r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset],
00239 m->IO_ENDPT, D, (vir_bytes) m->ADDRESS, n);
00240 if (r == OK)
00241 {
00242 kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
00243 kbdp->avail -= n;
00244 r= n;
00245 }
00246
00247 break;
00248
00249 case DEV_WRITE:
00250 if (kbdp != &kbdaux)
00251 {
00252 printf("write to keyboard not implemented\n");
00253 r= EINVAL;
00254 break;
00255 }
00256
00257
00258
00259
00260
00261 for (i= 0; i<m->COUNT; i++)
00262 {
00263 r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS+i,
00264 SELF, D, (vir_bytes)&c, 1);
00265 if (r != OK)
00266 break;
00267 kbc_cmd1(KBC_WRITE_AUX, c);
00268 }
00269 r= i;
00270 break;
00271
00272 case CANCEL:
00273 kbdp->req_size= 0;
00274 r= OK;
00275 break;
00276 case DEV_SELECT:
00277 ops = m->IO_ENDPT & (SEL_RD|SEL_WR|SEL_ERR);
00278 watch = (m->IO_ENDPT & SEL_NOTIFY) ? 1 : 0;
00279
00280 r= 0;
00281 if (kbdp->avail && (ops & SEL_RD))
00282 {
00283 r |= SEL_RD;
00284 break;
00285 }
00286
00287 if (ops && watch)
00288 {
00289 kbdp->select_ops |= ops;
00290 kbdp->select_proc= m->m_source;
00291 }
00292 break;
00293 case DEV_IOCTL:
00294 if (kbdp == &kbd && m->TTY_REQUEST == KIOCSLEDS)
00295 {
00296 kio_leds_t leds;
00297 unsigned char b;
00298
00299 r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
00300 SELF, D, (vir_bytes)&leds, sizeof(leds));
00301 if (r != OK)
00302 break;
00303 b= 0;
00304 if (leds.kl_bits & KBD_LEDS_NUM) b |= NUM_LOCK;
00305 if (leds.kl_bits & KBD_LEDS_CAPS) b |= CAPS_LOCK;
00306 if (leds.kl_bits & KBD_LEDS_SCROLL) b |= SCROLL_LOCK;
00307 if (kbdout.avail == 0)
00308 kbdout.offset= 0;
00309 if (kbdout.offset + kbdout.avail + 2 > KBD_OUT_BUFSZ)
00310 {
00311
00312
00313
00314 kbdout.expect_ack= 0;
00315 }
00316 else
00317 {
00318 kbdout.buf[kbdout.offset+kbdout.avail]=
00319 LED_CODE;
00320 kbdout.buf[kbdout.offset+kbdout.avail+1]= b;
00321 kbdout.avail += 2;
00322 }
00323 if (!kbdout.expect_ack)
00324 kbd_send();
00325 r= OK;
00326 break;
00327 }
00328 if (kbdp == &kbd && m->TTY_REQUEST == KIOCBELL)
00329 {
00330 kio_bell_t bell;
00331 clock_t ticks;
00332
00333 r= sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
00334 SELF, D, (vir_bytes)&bell, sizeof(bell));
00335 if (r != OK)
00336 break;
00337
00338 ticks= bell.kb_duration.tv_usec * HZ / 1000000;
00339 ticks += bell.kb_duration.tv_sec * HZ;
00340 if (!ticks)
00341 ticks++;
00342 beep_x(bell.kb_pitch, ticks);
00343
00344 r= OK;
00345 break;
00346 }
00347 r= ENOTTY;
00348 break;
00349
00350 default:
00351 printf("Warning, TTY(kbd) got unexpected request %d from %d\n",
00352 m->m_type, m->m_source);
00353 r= EINVAL;
00354 }
00355 tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
00356 }
00357
00358
00359
00360
00361
00362 PRIVATE int handle_status(kbdp, m)
00363 struct kbd *kbdp;
00364 message *m;
00365 {
00366 int n, r;
00367
00368 if (kbdp->avail && kbdp->req_size && m->m_source == kbdp->incaller)
00369 {
00370
00371 n= kbdp->avail;
00372 if (n > kbdp->req_size)
00373 n= kbdp->req_size;
00374 if (kbdp->offset + n > KBD_BUFSZ)
00375 n= KBD_BUFSZ-kbdp->offset;
00376 if (n <= 0)
00377 panic("TTY", "kbd_status: bad n", n);
00378 kbdp->req_size= 0;
00379 r= sys_vircopy(SELF, D, (vir_bytes)&kbdp->buf[kbdp->offset],
00380 kbdp->req_proc, D, kbdp->req_addr, n);
00381 if (r == OK)
00382 {
00383 kbdp->offset= (kbdp->offset+n) % KBD_BUFSZ;
00384 kbdp->avail -= n;
00385 r= n;
00386 }
00387
00388 m->m_type = DEV_REVIVE;
00389 m->REP_ENDPT= kbdp->req_proc;
00390 m->REP_STATUS= r;
00391 return 1;
00392 }
00393 if (kbdp->avail && (kbdp->select_ops & SEL_RD) &&
00394 m->m_source == kbdp->select_proc)
00395 {
00396 m->m_type = DEV_IO_READY;
00397 m->DEV_MINOR = kbdp->minor;
00398 m->DEV_SEL_OPS = SEL_RD;
00399
00400 kbdp->select_ops &= ~SEL_RD;
00401 return 1;
00402 }
00403
00404 return 0;
00405 }
00406
00407
00408
00409
00410
00411
00412 #define map_key0(scode) \
00413 ((unsigned) keymap[(scode) * MAP_COLS])
00414
00415
00416
00417
00418 PRIVATE unsigned map_key(scode)
00419 int scode;
00420 {
00421
00422
00423 int caps, column, lk;
00424 u16_t *keyrow;
00425
00426 if (scode == SLASH_SCAN && esc) return '/';
00427
00428 keyrow = &keymap[scode * MAP_COLS];
00429
00430 caps = shift;
00431 lk = locks[ccurrent];
00432 if ((lk & NUM_LOCK) && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
00433 if ((lk & CAPS_LOCK) && (keyrow[0] & HASCAPS)) caps = !caps;
00434
00435 if (alt) {
00436 column = 2;
00437 if (ctrl || alt_r) column = 3;
00438 if (caps) column = 4;
00439 } else {
00440 column = 0;
00441 if (caps) column = 1;
00442 if (ctrl) column = 5;
00443 }
00444 return keyrow[column] & ~HASCAPS;
00445 }
00446
00447
00448
00449
00450 PUBLIC void kbd_interrupt(m_ptr)
00451 message *m_ptr;
00452 {
00453
00454 int o, isaux;
00455 unsigned char scode;
00456 struct kbd *kbdp;
00457 static timer_t timer;
00458
00459
00460 if (!scan_keyboard(&scode, &isaux))
00461 return;
00462
00463 if (isaux)
00464 kbdp= &kbdaux;
00465 else if (kbd.nr_open && !panicing)
00466 kbdp= &kbd;
00467 else
00468 kbdp= NULL;
00469
00470 if (kbdp)
00471 {
00472
00473 if (kbdp->avail >= KBD_BUFSZ)
00474 {
00475 printf("kbd_interrupt: %s buffer is full\n",
00476 isaux ? "kbdaux" : "keyboard");
00477 return;
00478 }
00479 o= (kbdp->offset + kbdp->avail) % KBD_BUFSZ;
00480 kbdp->buf[o]= scode;
00481 kbdp->avail++;
00482 if (kbdp->req_size)
00483 notify(kbdp->incaller);
00484 if (kbdp->select_ops & SEL_RD)
00485 notify(kbdp->select_proc);
00486 return;
00487 }
00488
00489
00490 if (icount < KB_IN_BYTES) {
00491 *ihead++ = scode;
00492 if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
00493 icount++;
00494 tty_table[ccurrent].tty_events = 1;
00495 if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
00496 select_retry(&tty_table[ccurrent]);
00497 }
00498 }
00499 }
00500
00501
00502
00503
00504 PRIVATE int kb_read(tp, try)
00505 tty_t *tp;
00506 int try;
00507 {
00508
00509 char buf[3];
00510 int scode;
00511 unsigned ch;
00512
00513 tp = &tty_table[ccurrent];
00514
00515 if (try) {
00516 if (icount > 0) return 1;
00517 return 0;
00518 }
00519
00520 while (icount > 0) {
00521 scode = *itail++;
00522 if (itail == ibuf + KB_IN_BYTES) itail = ibuf;
00523 icount--;
00524
00525
00526 if (func_key(scode)) continue;
00527
00528
00529 ch = make_break(scode);
00530
00531 if (ch <= 0xFF) {
00532
00533 buf[0] = ch;
00534 (void) in_process(tp, buf, 1);
00535 } else
00536 if (HOME <= ch && ch <= INSRT) {
00537
00538 buf[0] = ESC;
00539 buf[1] = '[';
00540 buf[2] = numpad_map[ch - HOME];
00541 (void) in_process(tp, buf, 3);
00542 } else
00543 if (ch == ALEFT) {
00544
00545 select_console(ccurrent - 1);
00546 set_leds();
00547 } else
00548 if (ch == ARIGHT) {
00549
00550 select_console(ccurrent + 1);
00551 set_leds();
00552 } else
00553 if (AF1 <= ch && ch <= AF12) {
00554
00555 select_console(ch - AF1);
00556 set_leds();
00557 } else
00558 if (CF1 <= ch && ch <= CF12) {
00559 switch(ch) {
00560 case CF1: show_key_mappings(); break;
00561 case CF3: toggle_scroll(); break;
00562 case CF7: sigchar(&tty_table[CONSOLE], SIGQUIT); break;
00563 case CF8: sigchar(&tty_table[CONSOLE], SIGINT); break;
00564 case CF9: sigchar(&tty_table[CONSOLE], SIGKILL); break;
00565 }
00566 }
00567 }
00568
00569 return 1;
00570 }
00571
00572
00573
00574
00575 PRIVATE void kbd_send()
00576 {
00577 unsigned long sb;
00578 int r;
00579 clock_t now;
00580
00581 if (!kbdout.avail)
00582 return;
00583 if (kbdout.expect_ack)
00584 return;
00585
00586 sys_inb(KB_STATUS, &sb);
00587 if (sb & (KB_OUT_FULL|KB_IN_FULL))
00588 {
00589 printf("not sending 1: sb = 0x%x\n", sb);
00590 return;
00591 }
00592 micro_delay(KBC_IN_DELAY);
00593 sys_inb(KB_STATUS, &sb);
00594 if (sb & (KB_OUT_FULL|KB_IN_FULL))
00595 {
00596 printf("not sending 2: sb = 0x%x\n", sb);
00597 return;
00598 }
00599
00600
00601 #if 0
00602 printf("sending byte 0x%x to keyboard\n", kbdout.buf[kbdout.offset]);
00603 #endif
00604 sys_outb(KEYBD, kbdout.buf[kbdout.offset]);
00605 kbdout.offset++;
00606 kbdout.avail--;
00607 kbdout.expect_ack= 1;
00608
00609 kbd_alive= 1;
00610 if (kbd_watchdog_set)
00611 {
00612
00613
00614
00615 if ((r= getuptime(&now)) != OK)
00616 panic("TTY","Keyboard couldn't get clock's uptime.", r);
00617 tmrs_settimer(&tty_timers, &tmr_kbd_wd, now+HZ, kbd_watchdog,
00618 NULL);
00619 if (tty_timers->tmr_exp_time != tty_next_timeout) {
00620 tty_next_timeout = tty_timers->tmr_exp_time;
00621 if ((r= sys_setalarm(tty_next_timeout, 1)) != OK)
00622 panic("TTY","Keyboard couldn't set alarm.", r);
00623 }
00624 kbd_watchdog_set= 1;
00625 }
00626 }
00627
00628
00629
00630
00631 PRIVATE unsigned make_break(scode)
00632 int scode;
00633 {
00634
00635
00636
00637
00638 int ch, make, escape;
00639 static int CAD_count = 0;
00640
00641
00642
00643
00644
00645 if (ctrl && alt && (scode == DEL_SCAN || scode == INS_SCAN))
00646 {
00647 if (++CAD_count == 3) sys_abort(RBT_HALT);
00648 sys_kill(INIT_PROC_NR, SIGABRT);
00649 return -1;
00650 }
00651
00652
00653 make = (scode & KEY_RELEASE) == 0;
00654
00655 ch = map_key(scode &= ASCII_MASK);
00656
00657 escape = esc;
00658 esc = 0;
00659
00660 switch (ch) {
00661 case CTRL:
00662 *(escape ? &ctrl_r : &ctrl_l) = make;
00663 ctrl = ctrl_l | ctrl_r;
00664 break;
00665 case SHIFT:
00666 *(scode == RSHIFT_SCAN ? &shift_r : &shift_l) = make;
00667 shift = shift_l | shift_r;
00668 break;
00669 case ALT:
00670 *(escape ? &alt_r : &alt_l) = make;
00671 alt = alt_l | alt_r;
00672 break;
00673 case CALOCK:
00674 if (caps_down < make) {
00675 locks[ccurrent] ^= CAPS_LOCK;
00676 set_leds();
00677 }
00678 caps_down = make;
00679 break;
00680 case NLOCK:
00681 if (num_down < make) {
00682 locks[ccurrent] ^= NUM_LOCK;
00683 set_leds();
00684 }
00685 num_down = make;
00686 break;
00687 case SLOCK:
00688 if (scroll_down < make) {
00689 locks[ccurrent] ^= SCROLL_LOCK;
00690 set_leds();
00691 }
00692 scroll_down = make;
00693 break;
00694 case EXTKEY:
00695 esc = 1;
00696 return(-1);
00697 default:
00698 if (make) return(ch);
00699 }
00700
00701
00702 return(-1);
00703 }
00704
00705
00706
00707
00708 PRIVATE void set_leds()
00709 {
00710
00711 int s;
00712 if (! machine.pc_at) return;
00713
00714 kb_wait();
00715 if ((s=sys_outb(KEYBD, LED_CODE)) != OK)
00716 printf("Warning, sys_outb couldn't prepare for LED values: %d\n", s);
00717
00718 kb_ack();
00719
00720 kb_wait();
00721 if ((s=sys_outb(KEYBD, locks[ccurrent])) != OK)
00722 printf("Warning, sys_outb couldn't give LED values: %d\n", s);
00723
00724 kb_ack();
00725 }
00726
00727
00728
00729
00730 PRIVATE void kbc_cmd0(cmd)
00731 int cmd;
00732 {
00733 kb_wait();
00734 sys_outb(KB_COMMAND, cmd);
00735 }
00736
00737
00738
00739
00740 PRIVATE void kbc_cmd1(cmd, data)
00741 int cmd;
00742 int data;
00743 {
00744 kb_wait();
00745 sys_outb(KB_COMMAND, cmd);
00746 kb_wait();
00747 sys_outb(KEYBD, data);
00748 }
00749
00750
00751
00752
00753
00754 PRIVATE int kbc_read()
00755 {
00756 int i;
00757 unsigned long byte, st;
00758 #if 0
00759 struct micro_state ms;
00760 #endif
00761
00762 #if DEBUG
00763 printf("in kbc_read\n");
00764 #endif
00765
00766
00767
00768
00769 for (i= 0; i<1000; i++)
00770 #if 0
00771 micro_start(&ms);
00772 do
00773 #endif
00774 {
00775 sys_inb(KB_STATUS, &st);
00776 if (st & KB_OUT_FULL)
00777 {
00778 micro_delay(KBC_IN_DELAY);
00779 sys_inb(KEYBD, &byte);
00780 if (st & KB_AUX_BYTE)
00781 {
00782 #if DEBUG
00783 printf(
00784 "keyboard`kbc_read: ignoring byte (0x%x) from aux device.\n",
00785 byte);
00786 #endif
00787 continue;
00788 }
00789 #if DEBUG
00790 printf("keyboard`kbc_read: returning byte 0x%x\n",
00791 byte);
00792 #endif
00793 return byte;
00794 }
00795 }
00796 #if 0
00797 while (micro_elapsed(&ms) < 1000000);
00798 #endif
00799 panic("TTY", "kbc_read failed to complete", NO_NUM);
00800 }
00801
00802
00803
00804
00805
00806
00807 PRIVATE int kb_wait()
00808 {
00809
00810
00811 int retries;
00812 unsigned long status, temp;
00813 int s, isaux;
00814 unsigned char byte;
00815
00816 retries = MAX_KB_BUSY_RETRIES + 1;
00817 do {
00818 s = sys_inb(KB_STATUS, &status);
00819 if (status & KB_OUT_FULL) {
00820 if (scan_keyboard(&byte, &isaux))
00821 {
00822 #if 0
00823 printf("ignoring %sbyte in kb_wait\n", isaux ? "AUX " : "");
00824 #endif
00825 }
00826 }
00827 if (! (status & (KB_IN_FULL|KB_OUT_FULL)) )
00828 break;
00829 } while (--retries != 0);
00830 return(retries);
00831 }
00832
00833
00834
00835
00836 PRIVATE int kb_ack()
00837 {
00838
00839
00840 int retries, s;
00841 unsigned long u8val;
00842
00843
00844 retries = MAX_KB_ACK_RETRIES + 1;
00845 do {
00846 s = sys_inb(KEYBD, &u8val);
00847 if (u8val == KB_ACK)
00848 break;
00849 } while(--retries != 0);
00850
00851 return(retries);
00852 }
00853
00854
00855
00856
00857 PUBLIC void kb_init(tp)
00858 tty_t *tp;
00859 {
00860
00861
00862 tp->tty_devread = kb_read;
00863 }
00864
00865
00866
00867
00868 PUBLIC void kb_init_once(void)
00869 {
00870 int i;
00871 u8_t ccb;
00872
00873 set_leds();
00874 scan_keyboard(NULL, NULL);
00875
00876
00877 for (i=0; i<12; i++) {
00878 fkey_obs[i].proc_nr = NONE;
00879 fkey_obs[i].events = 0;
00880 sfkey_obs[i].proc_nr = NONE;
00881 sfkey_obs[i].events = 0;
00882 }
00883
00884 kbd.minor= KBD_MINOR;
00885 kbdaux.minor= KBDAUX_MINOR;
00886
00887
00888 irq_hook_id = KEYBOARD_IRQ;
00889 if ((i=sys_irqsetpolicy(KEYBOARD_IRQ, IRQ_REENABLE, &irq_hook_id)) != OK)
00890 panic("TTY", "Couldn't set keyboard IRQ policy", i);
00891 if ((i=sys_irqenable(&irq_hook_id)) != OK)
00892 panic("TTY", "Couldn't enable keyboard IRQs", i);
00893 kbd_irq_set |= (1 << KEYBOARD_IRQ);
00894
00895
00896 aux_irq_hook_id = KBD_AUX_IRQ;
00897 if ((i=sys_irqsetpolicy(KBD_AUX_IRQ, IRQ_REENABLE,
00898 &aux_irq_hook_id)) != OK)
00899 panic("TTY", "Couldn't set AUX IRQ policy", i);
00900 if ((i=sys_irqenable(&aux_irq_hook_id)) != OK)
00901 panic("TTY", "Couldn't enable AUX IRQs", i);
00902 kbd_irq_set |= (1 << KBD_AUX_IRQ);
00903
00904
00905 kbc_cmd0(KBC_DI_KBD);
00906 kbc_cmd0(KBC_DI_AUX);
00907
00908
00909 kbc_cmd0(KBC_RD_RAM_CCB);
00910 ccb= kbc_read();
00911
00912
00913 kbc_cmd1(KBC_WR_RAM_CCB, ccb | 3);
00914
00915
00916 kbc_cmd0(KBC_EN_KBD);
00917
00918
00919 kbc_cmd0(KBC_EN_AUX);
00920 }
00921
00922
00923
00924
00925 PUBLIC int kbd_loadmap(m)
00926 message *m;
00927 {
00928
00929 int result;
00930 result = sys_vircopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
00931 SELF, D, (vir_bytes) keymap,
00932 (vir_bytes) sizeof(keymap));
00933 return(result);
00934 }
00935
00936
00937
00938
00939 PUBLIC void do_fkey_ctl(m_ptr)
00940 message *m_ptr;
00941 {
00942
00943
00944
00945 int i;
00946 int result;
00947
00948 switch (m_ptr->FKEY_REQUEST) {
00949 case FKEY_MAP:
00950 result = OK;
00951 for (i=0; i < 12; i++) {
00952 if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
00953 #if DEAD_CODE
00954
00955
00956
00957
00958 if (fkey_obs[i].proc_nr == NONE) {
00959 #endif
00960 fkey_obs[i].proc_nr = m_ptr->m_source;
00961 fkey_obs[i].events = 0;
00962 bit_unset(m_ptr->FKEY_FKEYS, i+1);
00963 #if DEAD_CODE
00964 } else {
00965 printf("WARNING, fkey_map failed F%d\n", i+1);
00966 result = EBUSY;
00967 }
00968 #endif
00969 }
00970 }
00971 for (i=0; i < 12; i++) {
00972 if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
00973 #if DEAD_CODE
00974 if (sfkey_obs[i].proc_nr == NONE) {
00975 #endif
00976 sfkey_obs[i].proc_nr = m_ptr->m_source;
00977 sfkey_obs[i].events = 0;
00978 bit_unset(m_ptr->FKEY_SFKEYS, i+1);
00979 #if DEAD_CODE
00980 } else {
00981 printf("WARNING, fkey_map failed Shift F%d\n", i+1);
00982 result = EBUSY;
00983 }
00984 #endif
00985 }
00986 }
00987 break;
00988 case FKEY_UNMAP:
00989 result = OK;
00990 for (i=0; i < 12; i++) {
00991 if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
00992 if (fkey_obs[i].proc_nr == m_ptr->m_source) {
00993 fkey_obs[i].proc_nr = NONE;
00994 fkey_obs[i].events = 0;
00995 bit_unset(m_ptr->FKEY_FKEYS, i+1);
00996 } else {
00997 result = EPERM;
00998 }
00999 }
01000 }
01001 for (i=0; i < 12; i++) {
01002 if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
01003 if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
01004 sfkey_obs[i].proc_nr = NONE;
01005 sfkey_obs[i].events = 0;
01006 bit_unset(m_ptr->FKEY_SFKEYS, i+1);
01007 } else {
01008 result = EPERM;
01009 }
01010 }
01011 }
01012 break;
01013 case FKEY_EVENTS:
01014 m_ptr->FKEY_FKEYS = m_ptr->FKEY_SFKEYS = 0;
01015 for (i=0; i < 12; i++) {
01016 if (fkey_obs[i].proc_nr == m_ptr->m_source) {
01017 if (fkey_obs[i].events) {
01018 bit_set(m_ptr->FKEY_FKEYS, i+1);
01019 fkey_obs[i].events = 0;
01020 }
01021 }
01022 if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
01023 if (sfkey_obs[i].events) {
01024 bit_set(m_ptr->FKEY_SFKEYS, i+1);
01025 sfkey_obs[i].events = 0;
01026 }
01027 }
01028 }
01029 break;
01030 default:
01031 result = EINVAL;
01032 }
01033
01034
01035 m_ptr->m_type = result;
01036 send(m_ptr->m_source, m_ptr);
01037 }
01038
01039
01040
01041
01042 PRIVATE int func_key(scode)
01043 int scode;
01044 {
01045
01046
01047
01048
01049
01050
01051 message m;
01052 int key;
01053 int proc_nr;
01054 int i,s;
01055
01056
01057 if (scode & KEY_RELEASE) return(FALSE);
01058 key = map_key(scode);
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 if (F1 <= key && key <= F12) {
01069 proc_nr = fkey_obs[key - F1].proc_nr;
01070 fkey_obs[key - F1].events ++ ;
01071 } else if (SF1 <= key && key <= SF12) {
01072 proc_nr = sfkey_obs[key - SF1].proc_nr;
01073 sfkey_obs[key - SF1].events ++;
01074 }
01075 else {
01076 return(FALSE);
01077 }
01078
01079
01080 if (proc_nr != NONE) {
01081 m.NOTIFY_TYPE = FKEY_PRESSED;
01082 notify(proc_nr);
01083 }
01084 return(TRUE);
01085 }
01086
01087
01088
01089
01090 PRIVATE void show_key_mappings()
01091 {
01092 int i,s;
01093 struct proc proc;
01094
01095 printf("\n");
01096 printf("System information. Known function key mappings to request debug dumps:\n");
01097 printf("-------------------------------------------------------------------------\n");
01098 for (i=0; i<12; i++) {
01099
01100 printf(" %sF%d: ", i+1<10? " ":"", i+1);
01101 if (fkey_obs[i].proc_nr != NONE) {
01102 if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK)
01103 printf("sys_getproc: %d\n", s);
01104 printf("%-14.14s", proc.p_name);
01105 } else {
01106 printf("%-14.14s", "<none>");
01107 }
01108
01109 printf(" %sShift-F%d: ", i+1<10? " ":"", i+1);
01110 if (sfkey_obs[i].proc_nr != NONE) {
01111 if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK)
01112 printf("sys_getproc: %d\n", s);
01113 printf("%-14.14s", proc.p_name);
01114 } else {
01115 printf("%-14.14s", "<none>");
01116 }
01117 printf("\n");
01118 }
01119 printf("\n");
01120 printf("Press one of the registered function keys to trigger a debug dump.\n");
01121 printf("\n");
01122 }
01123
01124
01125
01126
01127 PRIVATE int scan_keyboard(bp, isauxp)
01128 unsigned char *bp;
01129 int *isauxp;
01130 {
01131 #if 0
01132
01133 pvb_pair_t byte_in[2], byte_out[2];
01134
01135 byte_in[0].port = KEYBD;
01136 byte_in[1].port = PORT_B;
01137 sys_vinb(byte_in, 2);
01138
01139 pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT);
01140 pv_set(byte_out[1], PORT_B, byte_in[1].value);
01141 sys_voutb(byte_out, 2);
01142
01143 return(byte_in[0].value);
01144 #else
01145 unsigned long b, sb;
01146
01147 sys_inb(KB_STATUS, &sb);
01148 if (!(sb & KB_OUT_FULL))
01149 {
01150 if (kbdout.avail && !kbdout.expect_ack)
01151 kbd_send();
01152 return 0;
01153 }
01154 sys_inb(KEYBD, &b);
01155 #if 0
01156 printf("got byte 0x%x from %s\n", b, (sb & KB_AUX_BYTE) ? "AUX" : "keyboard");
01157 #endif
01158 if (!(sb & KB_AUX_BYTE) && b == KB_ACK && kbdout.expect_ack)
01159 {
01160 #if 1
01161 printf("got ACK from keyboard\n");
01162 #endif
01163 kbdout.expect_ack= 0;
01164 micro_delay(KBC_IN_DELAY);
01165 kbd_send();
01166 return 0;
01167 }
01168 if (bp)
01169 *bp= b;
01170 if (isauxp)
01171 *isauxp= !!(sb & KB_AUX_BYTE);
01172 if (kbdout.avail && !kbdout.expect_ack)
01173 {
01174 micro_delay(KBC_IN_DELAY);
01175 kbd_send();
01176 }
01177 return 1;
01178 #endif
01179 }
01180
01181 static void micro_delay(unsigned long usecs)
01182 {
01183 tickdelay(MICROS_TO_TICKS(usecs));
01184 }
01185
01186
01187
01188
01189 PRIVATE void kbd_watchdog(tmrp)
01190 timer_t *tmrp;
01191 {
01192 int r;
01193 clock_t now;
01194
01195 kbd_watchdog_set= 0;
01196 if (!kbdout.avail)
01197 return;
01198 if (!kbd_alive)
01199 {
01200 printf("kbd_watchdog: should reset keyboard\n");
01201 }
01202 kbd_alive= 0;
01203
01204 if ((r= getuptime(&now)) != OK)
01205 panic("TTY","Keyboard couldn't get clock's uptime.", r);
01206 tmrs_settimer(&tty_timers, &tmr_kbd_wd, now+HZ, kbd_watchdog,
01207 NULL);
01208 if (tty_timers->tmr_exp_time != tty_next_timeout) {
01209 tty_next_timeout = tty_timers->tmr_exp_time;
01210 if ((r= sys_setalarm(tty_next_timeout, 1)) != OK)
01211 panic("TTY","Keyboard couldn't set alarm.", r);
01212 }
01213 kbd_watchdog_set= 1;
01214 }