1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * Copyright (c) 1991 IBM Corporation
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation,
12 * and that the name IBM not be used in advertising or publicity
13 * pertaining to distribution of the software without specific, written
14 * prior permission.
15 *
16 * CARNEGIE MELLON AND IBM ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON AND IBM DISCLAIM ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31 /*
32 * HISTORY
33 * $Log: kd_abios.c,v $
34 * Revision 2.2 93/02/04 08:00:50 danner
35 * Integrate PS2 code from IBM.
36 * [93/01/18 prithvi]
37 *
38 */
39
40 /* ported --------------------------------------------------------------*/
41
42 #define KBD_DATA_PORT 0x60
43 #define KBD_STATUS_PORT 0x64
44 #define OUTPUT_BUFFER_FULL BIT0
45 #define INPUT_BUFFER_FULL BIT1
46 #define KBD_TX BIT6
47 #define KBD_RESET_CMD 0xff
48 #define KBD_ACK 0xfa
49 #define KBD_BAT_RC 0xaa
50 #define CTLR_READ_CMD_BYTE 0x20
51 #define CTLR_WRITE_CMD_BYTE 0x60
52
53 #define K_pad4SC 0x4b
54
55 static void
56 kbd_wait( int i)
57 {
58 while (i) i--;
59 }
60
61 static u_char
62 kbd_read_data_port()
63 {
64 while ((inb(KBD_STATUS_PORT) & OUTPUT_BUFFER_FULL) == 0); /* wait */
65 /*
66 * Hardware ref manual says we need to wait 7 usec before the
67 * data byte would show up at KBD_DATA_PORT. Wait a little
68 * longer just to be sure.
69 */
70 kbd_wait(7+3);
71 return(inb(KBD_DATA_PORT));
72 }
73
74 static void
75 kbd_write_port(int port, u_char val)
76 {
77 while (inb(KBD_STATUS_PORT) & (INPUT_BUFFER_FULL | OUTPUT_BUFFER_FULL));
78 outb(port, val);
79 }
80
81 static void
82 kbd_clr_hw_buffer()
83 {
84 /*
85 * get rid of any characters may have left in the keyboard
86 * hardware buffer (just want to start out clean)
87 */
88 while (inb(KBD_STATUS_PORT) & OUTPUT_BUFFER_FULL)
89 kbd_read_data_port();
90 } /* kbd_clr_hw_buffer */
91
92 /*
93 * kbd_tx_off
94 *
95 * Turn off keyboard controler scan code translation. For PC compatability,
96 * type 1 kbd controler will do scan code translation, which means you can
97 * only use scan code set 1. To use scan code set 3, we need to turn the
98 * translation off.
99 *
100 * It goes like this:
101 * outb(0x64, 0x20) read controler command byte
102 * ch = inb(0x60) & ~BIT6 turn off kbd translate
103 * outb(0x64, 0x60) write controler command byte
104 * outb(0x60, ch)
105 *
106 * This routine is called very early in main(). After hardware init
107 * but before debugger init.
108 */
109 void
110 kbd_tx_off()
111 {
112 u_char ch;
113
114 kbd_clr_hw_buffer();
115 kbd_write_port(KBD_STATUS_PORT, CTLR_READ_CMD_BYTE);
116 ch = kbd_read_data_port() & (~KBD_TX); /* turn off kbd translate */
117 kbd_write_port(KBD_STATUS_PORT, CTLR_WRITE_CMD_BYTE);
118 kbd_write_port(KBD_DATA_PORT, ch); /* write it back */
119
120 } /* kbd_tx_off */
121
122 void
123 kbd_tx_on()
124 {
125 u_char ch;
126
127 kbd_clr_hw_buffer();
128 kbd_write_port(KBD_STATUS_PORT, CTLR_READ_CMD_BYTE);
129 ch = kbd_read_data_port() | KBD_TX; /* turn on kbd translate */
130 kbd_write_port(KBD_STATUS_PORT, CTLR_WRITE_CMD_BYTE);
131 kbd_write_port(KBD_DATA_PORT, ch); /* write it back */
132
133 } /* kbd_tx_on */
134
135 /*
136 * kbd_debugger_init
137 *
138 * Init the keyboard for the kernel debugger. At power on, kbd
139 * default to scan code set 2. We want to use scan code set 3.
140 * So some juggling is needed here. Can't use abios here since
141 * this is done very early in the boot process. In the normal
142 * boot (without debugger), this is done in ktsopen(). It goes
143 * something like this:
144 *
145 * cmds ack rc good/bad
146 * reset kbd 0xff 0xfa 0xaa/0xfc
147 * select scan code set 3 0xf0,0x03 0xfa,0xfa
148 * set all key t/m/b 0xfa 0xfa
149 * set individual key m/b 0xfc 0xfa
150 * sc3 for left-alt 0x19 0xfa
151 * sc3 for right-alt 0x39 0xfa
152 * sc3 for left-ctrl 0x11 0xfa
153 * sc3 for action (right-ctrl) 0x58 0xfa
154 * sc3 for left-shift 0x12 0xfa
155 * sc3 for right-shift 0x59 0xfa
156 * sc3 for capslock 0x14 0xfa
157 * sc3 for numlock 0x76 0xfa
158 * enable kbd 0xf4 0xfa
159 */
160 u_char debugger_kbdcmds[] = {
161 0xf0, /* select alternate scan code */
162 0x03, /* scan code set 3 */
163 0xfa, /* set all key t/m/b */
164 0xfc, /* set individual key m/b */
165 0x19, /* sc3 for left-alt */
166 0x39, /* sc3 for right-alt*/
167 0x11, /* sc3 for left-ctrl */
168 0x58, /* sc3 for action (right-ctrl) */
169 0x12, /* sc3 for left-shift */
170 0x59, /* sc3 for right-shift */
171 0x14, /* sc3 for capslock */
172 0x76, /* sc3 for numlock */
173 0xf4}; /* enable kbd */
174 /*
175 * kbd_debugger_init
176 *
177 * Init the keyboard for the kernel debugger. At power on, kbd
178 * default to scan code set 2. OSF want to use scan code set 1.
179 * So some juggling is needed here. Can't use abios here since
180 * this is done very early in the boot process. In the normal
181 * boot (without debugger), this is done in ktsopen(). It goes
182 * something like this:
183 *
184 * cmds ack rc good/bad
185 * reset kbd 0xff 0xfa 0xaa/0xfc
186 * select scan code set 1 0xf0,0x03 0xfa,0xfa
187 */
188 u_char osf_debugger_kbdcmds[] = {
189 0xf0, /* select alternate scan code */
190 0x01}; /* scan code set 1 */
191
192 static void
193 kbd_debugger_init()
194 {
195 u_char ch;
196 int i;
197
198 kbd_clr_hw_buffer();
199
200 /*
201 * reset the keyboard
202 */
203 kbd_write_port(KBD_DATA_PORT, KBD_RESET_CMD);
204 ch = kbd_read_data_port(); /* read ack to reset cmd */
205 if (ch != KBD_ACK) {
206 DEBUGF(kddebug & DEBUG_ERR_COND,
207 printf("kbd_debugger_init: ERROR, expect 0x%x got 0x%x\n",
208 KBD_ACK, ch));
209 }
210 kbd_wait(500000); /* reset needs 1/2 second to complete */
211 ch = kbd_read_data_port(); /* read BAT completion code */
212 if (ch != KBD_BAT_RC) {
213 DEBUGF(kddebug & DEBUG_ERR_COND,
214 printf("kbd_debugger_init: ERROR, expect 0x%x got 0x%x\n",
215 KBD_BAT_RC, ch));
216 }
217
218 kbd_tx_off(); /* turn off keyboard translation */
219
220 /*
221 * now send the cmds
222 */
223 for (i = 0; i < sizeof(osf_debugger_kbdcmds); i++) {
224 kbd_write_port(KBD_DATA_PORT, osf_debugger_kbdcmds[i]);
225 ch = kbd_read_data_port(); /* read ack to the cmd */
226 if (ch != KBD_ACK) {
227 DEBUGF(kddebug & DEBUG_ERR_COND,
228 printf("kbd_debugger_init: ERROR, cmd 0x%x got 0x%x\n",
229 osf_debugger_kbdcmds[i], ch));
230 }
231 }
232
233 } /* kbd_debugger_init */
234
235 void
236 kbd_init_keyboard()
237 {
238 if (kbd_debugger_inited)
239 return;
240 kbd_debugger_init();
241 kbd_debugger_inited = TRUE;
242 DEBUGF(kddebug & KTSDEBUG_INFO,
243 printf("kbd_init_keyboard: keyboard inited.\n"));
244 }
245
246 int
247 kbdcall_abios(int abios_function, register struct Kbd_request * rb)
248 {
249 int rc;
250
251 DEBUGF(kddebug & DEBUG_ABIOS,
252 printf("kbdcall_abios: entering...\n"));
253
254 rb->r_function = abios_function;
255 rb->r_return_code = ABIOS_UNDEFINED;
256 rb->state |= KBD_RB_STARTED;
257 abios_common_start(rb, kbd_abios_data.lid_flags);
258 rc = rb->r_return_code;
259 DEBUGF(kddebug & DEBUG_ABIOS,
260 printf("kbdcall_abios: abios_common_start(), rc=0x%x\n", rc));
261
262 #ifdef LATER
263 /* need to use timeout() instead of busy wait loop ... */
264 if (rb->r_return_code == ABIOS_STAGE_ON_TIME) {
265 kbd_wait(KBD_TIME_TO_WAIT(*rb)); /* in usec */
266 abios_common_interrupt(rb, kbd_abios_data.lid_flags);
267 rb->state = KBD_RB_IDLE;
268 }
269 /*
270 * work...
271 * start a watchdog timer, w_start(), here in case the interrupt
272 * didn't happen. (rb->r_time_out >> 3) is the number of seconds
273 * to wait. If it is zero, this operation didn't have a timeout.
274 *
275 * kbd_watchdog_handler() may need to see the stuffs between
276 * ifdef LATER.
277 */
278 while (rb->r_return_code == ABIOS_STAGE_ON_INT) {
279 int pri_level = i_disable(INTMAX);
280 rb->state |= KBD_RB_SLEEPING;
281 i_enable(pri_level);
282 ktsstub_e_sleep(&rb->sleep_on_intr, EVENT_SIGRET);
283 }
284 /*
285 * work... may need w_stop() here
286 * also, need to setup a watchdog timer handler somewhere in
287 * ktsopen(). When the timer pop, e.g: the expected intr didn't
288 * happen, the handler arranges to call abios_common_timeout().
289 */
290
291 DEBUGF(kddebug & DEBUG_ABIOS,
292 printf("kbdcall_abios: resolving final return code:\n"));
293 DEBUGF(kddebug & DEBUG_ABIOS,
294 dump_abios_rb((caddr_t) rb, DUMP_ENTIRE_BLOCK));
295 #endif /* LATER */
296
297 /* work... need to handle other returned codes here */
298 switch (rc) {
299 case ABIOS_DONE:
300 break;
301 default:
302 DEBUGF(kddebug & DEBUG_ERR_COND,
303 printf("kbdcall_abios: ERROR, unknown rc=0x%x\n", rc));
304 } /* switch */
305
306 DEBUGF(kddebug & DEBUG_ABIOS, printf("kbdcall_abios: leaving...\n"));
307 return (rc);
308 } /* kbdcall_abios*/
309
310 int kdintr();
311
312 kdabios_init()
313 {
314 int rc;
315 int i, s, rb_len, num_rb;
316
317 if (kdabios_initialized)
318 return;
319
320 DEBUGF(kddebug & DEBUG_ABIOS,
321 printf("kdabios_init: entering...\n"));
322
323
324 kbd_abios_data.lid = abios_next_LID(KBD_ID,2);
325 rb_len = sizeof(struct Kbd_request);
326 num_rb = sizeof(kreq) / rb_len;
327 kbd_abios_data.num_rb = num_rb;
328 DEBUGF(kddebug & DEBUG_ABIOS,
329 printf("kdabios_init: num_rb=%d rb_len=%d\n", num_rb, rb_len));
330
331 /*
332 * initialize kbd request blocks
333 *
334 * request block kreq[0] is for continuous read function (0x08),
335 * (e.g.: get the keystrokes)
336 *
337 * request block kreq[1] is for single stage or discrete multi
338 * stage functions, (e.g.: reset, read leds, set leds, ...)
339 */
340 for (i = 0; i < num_rb; i++) {
341 kreq[i].r_current_req_blck_len = rb_len;
342 kreq[i].r_logical_id = kbd_abios_data.lid;
343 kreq[i].r_unit = 0;
344 kreq[i].request_header.Request_Block_Flags = 0;
345 kreq[i].request_header.ELA_Offset = 0;
346 kreq[i].r_return_code = ABIOS_UNDEFINED;
347 kreq[i].state = KBD_RB_IDLE;
348 kreq[i].sleep_on_intr = FALSE;
349 }
350
351 /*
352 * read logical id parameters for keyboard
353 *
354 * work...
355 * If we ever decided that the config manager will do abios
356 * read logical paramater for all devices, then this is
357 * not needed.
358 */
359 DEBUGF(kddebug & DEBUG_ABIOS,
360 printf("kdabios_init: ABIOS_LOGICAL_PARAMETER\n"));
361 KBD_SET_RESERVED_ABIOS_LOGICAL_PARAMETER(kreq[1]);
362 kbd_abios_data.lid_flags = 0;
363 rc = kbdcall_abios(ABIOS_LOGICAL_PARAMETER, &kreq[1]);
364 if (rc) {
365 DEBUGF(kddebug & DEBUG_ERR_COND,
366 printf("kdabios_init: ERROR, rc=0x%x\n", rc));
367 return;
368 }
369
370 /*
371 * update certain fields based on what abios just told us
372 */
373 kbd_abios_data.installed = (kreq[1].r_number_units > 0);
374 if (kbd_abios_data.installed == FALSE) {
375 DEBUGF(kddebug & DEBUG_ERR_COND,
376 printf("kdabios_init: ERROR, no keyboard!\n"));
377 return;
378 }
379 kbd_abios_data.lid_flags = kreq[1].r_logical_id_flags;
380 rb_len = kreq[1].r_request_block_length;
381 for (i = 0; i < num_rb; i++) {
382 kreq[i].r_current_req_blck_len = rb_len;
383 }
384
385
386 /*
387 * start reading keystrokes
388 */
389 DEBUGF(kddebug & DEBUG_ABIOS,
390 printf("kdabios_init: ABIOS_READ\n"));
391 KBD_SET_RESERVED_ABIOS_READ(kreq[0]);
392 kreq[0].r_function = ABIOS_READ;
393 kreq[0].r_return_code = ABIOS_UNDEFINED;
394 kreq[0].state |= KBD_RB_STARTED;
395 s = SPLKD();
396 #ifdef OSF
397 kd_handler.ih_level = kreq[1].r_hardware_intr;
398 kd_handler.ih_handler = kdintr;
399 kd_handler.ih_resolver = (int (*)()) NULL;
400 kd_handler.ih_stats.intr_type = INTR_DEVICE;
401 kd_handler.ih_stats.intr_cnt = 0;
402 kd_handler.ih_priority = SPL6;
403 kd_handler.ih_flags = IH_FLAG_NOSHARE;
404 if ((kd_handler_id = handler_add( &kd_handler )) != NULL)
405 handler_enable( kd_handler_id );
406 else
407 return;
408 #else
409 take_irq(kreq[1].r_hardware_intr, 0, kdintr, SPL6, "kd");
410 #endif OSF
411 abios_common_start(&kreq[0], kbd_abios_data.lid_flags);
412 rc = kreq[0].r_return_code;
413 splx(s);
414 DEBUGF(kddebug & DEBUG_ABIOS,
415 printf("kdabios_init: abios_common_start(), rc=%x\n", rc));
416 if (rc != ABIOS_STAGE_ON_INT) { /* read key fail */
417 kreq[0].state = KBD_RB_IDLE;
418 DEBUGF(kddebug & DEBUG_ERR_COND,
419 printf("kdabios_init: ERROR, READ, rc=%x\n", rc));
420 return;
421 }
422
423 kdabios_initialized = TRUE;
424
425 DEBUGF(kddebug & KTSDEBUG_INFO,
426 printf("When in loop, Ctrl-Alt-pad4=debugger, Ctrl-Alt-Del=reboot.\n"));
427 DEBUGF(kddebug & DEBUG_ABIOS, printf("kdabios_init: leaving...\n"));
428 }
429
430 int
431 kdabios_intr()
432 {
433 struct Kbd_abios_data *kabios; /* ptr to kbd abios global data */
434 int rc, abios_rc;
435 int i;
436
437 DEBUGF(kddebug & DEBUG_INTR,
438 printf("\nkdabios_intr: ENTERING ...\n"));
439
440 kabios = &kbd_abios_data;
441 kabios->sc = 0;
442 rc = INTR_FAIL;
443
444 for (i = 0; i < kabios->num_rb; i++) {
445 abios_rc = kreq[i].r_return_code;
446 if ((kreq[i].state == KBD_RB_IDLE) ||
447 (abios_rc == ABIOS_UNDEFINED))
448 continue; /* not me! */
449
450 if ((abios_rc & ABIOS_STAGE_ON_INT) == 0)
451 continue; /* not me either! */
452
453 abios_common_interrupt(&kreq[i], kabios->lid_flags);
454 abios_rc = kreq[i].r_return_code;
455 DEBUGF(kddebug & DEBUG_INTR,
456 printf("kdabios_intr: kreq[%d], abios_common_interrupt(), rc=0x%x\n", i, abios_rc));
457
458 if (abios_rc & ABIOS_NOT_MY_INT)
459 continue; /* not me either! */
460
461 rc = INTR_SUCC;
462 switch (abios_rc) { /* it is me */
463 case ABIOS_STAGE_ON_INT:
464 /*
465 * discrete multi stages, just continue. Eventualy
466 * we will get a done or some sort of errors.
467 */
468 kreq[i].state |= KBD_RB_STAGING;
469 break;
470
471 case ABIOS_KBD_RC_KEY_AVAIL:
472 /*
473 * key stroke available, grasp it, process it
474 * and continue to wait for the next one
475 */
476 kreq[i].state |= KBD_RB_STAGING;
477 kabios->sc = KBD_SCAN_CODE(kreq[i]);
478 DEBUGF(kddebug & KTSDEBUG_TERSE,
479 printf("kdabios_intr: got a scancode, 0x%02x\n",
480 kabios->sc));
481 break;
482
483 default:
484 /*
485 * All other abios return codes, good or bad, will be
486 * handled by caller of abios. As far as interrupt
487 * is concerned, we just have a successful one.
488 */
489 kreq[i].state = KBD_RB_IDLE;
490 break;
491
492 } /* switch */
493 } /* for */
494
495 DEBUGF(kddebug & DEBUG_INTR,
496 printf("kdabios_intr: rc = 0x%x %d\n", rc, rc));
497 if (rc != INTR_SUCC) {
498 DEBUGF(kddebug & DEBUG_ERR_COND,
499 printf("kdabios_intr: spurious intr from kbd, count=%d\n",
500 ++kabios->bad_intr_count));
501 }
502
503 DEBUGF(kddebug & DEBUG_INTR, printf("kdabios_intr: LEAVING ...\n"));
504 return (rc);
505 } /* kdabios_intr */
506
507 int
508 kbd_clr_ctrl_alt_pad4()
509 {
510 int ctrl_up, alt_up, pad4_up;
511 u_char ch;
512
513 ctrl_up = alt_up = pad4_up = FALSE;
514 while ((ctrl_up==FALSE) || (alt_up==FALSE) || (pad4_up==FALSE)) {
515 ch = kbd_read_data_port();
516 if (ch == (K_CTLSC | K_UP))
517 ctrl_up = TRUE;
518 else if (ch == (K_ALTSC | K_UP))
519 alt_up = TRUE;
520 else if (ch == (K_pad4SC | K_UP))
521 pad4_up = TRUE;
522 }
523 } /* kbd_clr_ctrl_alt_pad4 */
524
525 /* un-ported -----------------------------------------------------------*/
Cache object: 40fce4b96b6da440cbac5c75ab1a7c69
|