FreeBSD/Linux Kernel Cross Reference
sys/i386ps2/kd.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989 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.c,v $
34 * Revision 2.2 93/02/04 08:00:40 danner
35 * Integrate PS2 code from IBM.
36 * [93/01/18 prithvi]
37 *
38 * Revision 2.16 92/01/03 20:11:31 dbg
39 * Fix io_port mapping setup.
40 * [91/12/18 dbg]
41 *
42 * Revision 2.15 91/11/12 11:10:01 rvb
43 * Get kd_kbd_magic from 2.5 version.
44 * [91/10/17 23:08:19 rvb]
45 *
46 * Use scroll lock vs insert to turn on "keyboard" mouse.
47 * To make DOS happy.
48 * [91/10/17 rvb]
49 *
50 * Revision 2.14 91/10/07 17:25:53 af
51 * Add support for ibm ps2 "keyboard" mouse. Try to be general
52 * about it to support other "keyboard mice", but we don't have
53 * any.
54 * [91/09/25 rvb]
55 * Changes by mg32 from Mach2.5:
56 * Neet bug. Setting LED's yields TWO ack's. And since we
57 * only read one this screwed us up.
58 * Bound's check the esc string
59 * [91/09/04 rvb]
60 *
61 * Revision 2.13 91/06/25 10:27:15 rpd
62 * Fixed kdopen to call kd_io_map_open with the tty unlocked.
63 * [91/05/21 rpd]
64 *
65 * Revision 2.12 91/05/18 14:30:22 rpd
66 * Fixed kdopen to call ttychars with the tty unlocked.
67 * [91/03/31 rpd]
68 *
69 * Revision 2.11 91/05/14 16:26:36 mrt
70 * Correcting copyright
71 *
72 * Revision 2.10 91/05/08 12:44:09 dbg
73 * Create and destroy io_port sets to map IO ports into user
74 * threads.
75 * [91/04/26 14:40:17 dbg]
76 *
77 * Revision 2.9 91/02/14 14:43:18 mrt
78 * Merge cleanup.
79 * [91/01/28 17:14:11 rvb]
80 *
81 * Drop priority around display routines in kdstart, so that
82 * scrolling or clearing the screen doesn't block other interrupts
83 * (e.g. com driver).
84 * [91/01/28 15:29:45 rvb]
85 *
86 *
87 * Revision 2.8 91/02/05 17:18:52 mrt
88 * Changed to new Mach copyright
89 * [91/02/01 17:45:11 mrt]
90 *
91 * Revision 2.7 90/12/04 14:46:47 jsb
92 * Changes for merged intel/pmap.{c,h}.
93 * [90/12/04 11:22:02 jsb]
94 *
95 * Revision 2.6 90/11/26 14:50:18 rvb
96 * jsb bet me to XMK34, sigh ...
97 * [90/11/26 rvb]
98 *
99 * Synched 2.5 & 3.0 at I386q (r1.9.1.12) & XMK35 (r2.6)
100 * [90/11/15 rvb]
101 *
102 * Revision 1.9.1.11 90/09/18 08:39:24 rvb
103 * Bug in kdstart could break w/o resetting spl. [osf]
104 *
105 * Revision 2.5 90/08/27 22:00:44 dbg
106 * Make cnpollc switch into and out of graphics mode ('X' support).
107 * [90/08/22 dbg]
108 *
109 * Add XTABS to console flags - kd_putc does not understand tab
110 * characters.
111 * [90/08/17 dbg]
112 *
113 * Change cngetc to not echo.
114 * [90/07/20 dbg]
115 *
116 * Revision 1.9.1.10 90/07/27 11:26:27 rvb
117 * Fix Intel Copyright as per B. Davies authorization.
118 * [90/07/27 rvb]
119 *
120 * Revision 1.9.1.9 90/06/07 08:05:34 rvb
121 * Add some more comments about device-specific layer. [kupfer]
122 *
123 * Revision 2.4 90/06/02 14:49:26 rpd
124 * Converted to new IPC.
125 * [90/06/01 rpd]
126 *
127 * Revision 1.9.1.8 90/05/15 11:15:43 rvb
128 * Bug fixes, for tab and sit_for(0). From dbg.
129 *
130 * Revision 2.3 90/05/21 13:27:11 dbg
131 * Correct check for extend/resend/ack in cndogetc.
132 * [90/05/15 dbg]
133 *
134 * Revision 1.9.1.7 90/05/14 13:21:11 rvb
135 * Check for an Olivetti EVC1 video adapter. [lance]
136 *
137 * Revision 2.2 90/05/03 15:44:27 dbg
138 * Converted for pure kernel.
139 * [90/04/23 dbg]
140 *
141 * Revision 1.9.1.6 90/03/07 13:28:35 rvb
142 * I386e- merge:
143 * flush map_ega_vga & ifdef ORC caps lock hack [kupfer]
144 *
145 * Revision 1.9.1.5 90/02/28 15:50:02 rvb
146 * Fix numerous typo's in Olivetti disclaimer.
147 * Integrate in Olivetti Changes ... largely comments
148 * [90/02/28 rvb]
149 *
150 * Revision 1.9.1.4 90/02/01 13:37:02 rvb
151 * Temporary vga implementation
152 * [90/01/31 rvb]
153 *
154 * Revision 1.9.1.3 90/01/08 13:31:06 rvb
155 * Add Intel copyright.
156 * Add Olivetti copyright.
157 * [90/01/08 rvb]
158 *
159 * Revision 1.9.1.2 90/01/02 13:52:24 rvb
160 * 1. For now, make caps lock key == ctrl key.
161 * 2. Remove splhi from around cngetc. Why should we need it?
162 * And it causes us to lose time.
163 *
164 * Revision 1.9.1.1 89/10/22 11:34:16 rvb
165 * Revision 1.13 89/09/27 16:02:42 kupfer
166 * Add support for resetting display before reboot.
167 *
168 * Revision 1.9 89/09/20 17:28:43 rvb
169 * 89/09/13 Added kd_debug_put [kupfer]
170 *
171 * Revision 1.8 89/09/09 15:22:24 rvb
172 * Remove a few spl's that shouldn't be here.
173 * Make mach_kdb depend on header file.
174 * kd.h -> kdreg.h
175 * [89/09/07 rvb]
176 *
177 * Revision 1.7 89/07/17 10:40:55 rvb
178 * Olivetti Changes to X79 upto 5/9/89:
179 * [89/07/11 rvb]
180 *
181 * Revision 1.7 89/07/07 16:24:07 kupfer
182 * X79 merge, 2nd attempt
183 *
184 * Revision 1.5.1.1 89/04/27 11:46:22 kupfer
185 * Merge of X79 with our latest & greatest.
186 *
187 * Revision 1.1.1.1 89/04/27 11:27:06 kupfer
188 * X79 from CMU.
189 *
190 * Revision 1.6 89/04/05 13:01:54 rvb
191 * Put kdasm into its own separate file. Fix kdcheckmagic()
192 * forward defintion and define rebootflag as extern. All for
193 * gcc.
194 * [89/03/04 rvb]
195 *
196 * Revision 1.5 89/03/09 20:06:22 rpd
197 * More cleanup.
198 *
199 * Revision 1.4 89/02/26 12:37:02 gm0w
200 * Changes for cleanup.
201 *
202 */
203
204 /*
205 * Olivetti Mach Console driver v0.0
206 * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
207 * All rights reserved.
208 *
209 */
210 /*
211 Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
212 Cupertino, California.
213
214 All Rights Reserved
215
216 Permission to use, copy, modify, and distribute this software and
217 its documentation for any purpose and without fee is hereby
218 granted, provided that the above copyright notice appears in all
219 copies and that both the copyright notice and this permission notice
220 appear in supporting documentation, and that the name of Olivetti
221 not be used in advertising or publicity pertaining to distribution
222 of the software without specific, written prior permission.
223
224 OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
225 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
226 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
227 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
228 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
229 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
230 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
231 */
232
233 /*
234 Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
235
236 All Rights Reserved
237
238 Permission to use, copy, modify, and distribute this software and
239 its documentation for any purpose and without fee is hereby
240 granted, provided that the above copyright notice appears in all
241 copies and that both the copyright notice and this permission notice
242 appear in supporting documentation, and that the name of Intel
243 not be used in advertising or publicity pertaining to distribution
244 of the software without specific, written prior permission.
245
246 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
247 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
248 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
249 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
250 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
251 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
252 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
253 */
254
255 /* $ Header: $ */
256
257 #include <platforms.h>
258 #include <mach_kdb.h>
259
260 #ifdef MACH_KERNEL
261 #include <sys/types.h>
262 #include <kern/time_out.h>
263 #include <device/conf.h>
264 #include <device/tty.h>
265 #include <device/io_req.h>
266 #include <device/buf.h> /* for struct uio (!) */
267 #include <i386/io_port.h>
268 #else MACH_KERNEL
269 #include <sys/types.h>
270 #include <sys/param.h>
271 #include <sys/conf.h>
272 #include <sys/dir.h>
273 #include <sys/user.h>
274 #include <sys/proc.h>
275 #include <sys/ioctl.h>
276 #include <sys/tty.h>
277 #include <sys/systm.h>
278 #include <sys/uio.h>
279 #include <sys/file.h>
280 #include <sys/kernel.h>
281 #endif MACH_KERNEL
282 #include <vm/vm_kern.h>
283 #include <mach/vm_param.h>
284 #include <i386at/cram.h>
285 #include <i386at/kd.h>
286 #include <i386at/kdsoft.h>
287
288 #ifdef PS2
289 #include <i386ps2/kd_var.h>
290 #endif PS2
291
292 #include <blit.h>
293 #if NBLIT > 0
294 #define BIT_BLIT 1 /* use bit blit code */
295 #include <i386at/blitvar.h>
296 #else
297 #define blit_present() FALSE
298 #define blit_init() /* nothing */
299 #endif
300
301 #include <evc.h>
302 #if NEVC > 0
303 int evc1init();
304 #else
305 #define evc1init() FALSE
306 #endif
307
308 #define DEBUG 1 /* export feep() */
309
310 /*
311 * If KD_NEEDS_VM is turned on, then cnputc will drop characters on the
312 * floor until the virtual memory code is initialized.
313 * This is needed to access some graphics cards which live at high
314 * addresses.
315 */
316
317 #if NBLIT > 0
318 #define KD_NEEDS_VM 1 /* "Mars Needs Women" */
319 #else
320 #define KD_NEEDS_VM 0
321 #endif
322
323 #define DEFAULT -1 /* see kd_atoi */
324
325 void kd_enqsc(); /* enqueues a scancode */
326
327 void timeout();
328 #ifdef MACH_KERNEL
329 #else MACH_KERNEL
330 void ttinit();
331 void ttiocom();
332 void ttrstrt();
333 void ttywait();
334 void wakeup();
335 #endif MACH_KERNEL
336
337
338 struct tty kd_tty;
339 extern int rebootflag;
340
341
342 static void charput(), charmvup(), charmvdown(), charclear(), charsetcursor();
343 static void kd_noopreset();
344 boolean_t kdcheckmagic();
345
346 /*
347 * These routines define the interface to the device-specific layer.
348 * See kdsoft.h for a more complete description of what each routine does.
349 */
350 void (*kd_dput)() = charput; /* put attributed char */
351 void (*kd_dmvup)() = charmvup; /* block move up */
352 void (*kd_dmvdown)() = charmvdown; /* block move down */
353 void (*kd_dclear)() = charclear; /* block clear */
354 void (*kd_dsetcursor)() = charsetcursor;
355 /* set cursor position on displayed page */
356 void (*kd_dreset)() = kd_noopreset; /* prepare for reboot */
357
358 /* forward declarations */
359 unsigned char kd_getdata(), state2leds();
360
361
362 /*
363 * Globals used for both character-based controllers and bitmap-based
364 * controllers. Default is EGA.
365 */
366
367 vm_offset_t kd_bitmap_start = (vm_offset_t)0xa0000; /* XXX - put in kd.h */
368 u_char *vid_start = (u_char *)EGA_START;
369 /* VM start of video RAM or frame buffer */
370 csrpos_t kd_curpos = 0; /* set indirectly by kd_setpos--see kdsoft.h */
371 short kd_lines = 25;
372 short kd_cols = 80;
373 char kd_attr = KA_NORMAL; /* current attribute */
374
375 /*
376 * kd_state shows the state of the modifier keys (ctrl, caps lock,
377 * etc.) It should normally be changed by calling set_kd_state(), so
378 * that the keyboard status LEDs are updated correctly.
379 */
380 int kd_state = KS_NORMAL;
381 int kb_mode = KB_ASCII; /* event/ascii */
382
383 #ifdef RVB_KBD_MOUSE
384 int kd_kbd_mouse = 0;
385 int kd_kbd_magic_scale = 6;
386 int kd_kbd_magic_buttons = 0;
387 #endif /* RVB_KBD_MOUSE */
388
389 /*
390 * Some keyboard commands work by sending a command, waiting for an
391 * ack (handled by kdintr), then sending data, which generates a
392 * second ack. If we are in the middle of such a sequence, kd_ack
393 * shows what the ack is for.
394 *
395 * When a byte is sent to the keyboard, it is kept around in last_sent
396 * in case it needs to be resent.
397 *
398 * The rest of the variables here hold the data required to complete
399 * the sequence.
400 *
401 * XXX - the System V driver keeps a command queue, I guess in case we
402 * want to start a command while another is in progress. Is this
403 * something we should worry about?
404 */
405 enum why_ack {NOT_WAITING, SET_LEDS, DATA_ACK};
406 enum why_ack kd_ack = NOT_WAITING;
407
408 u_char last_sent = 0;
409
410 u_char kd_nextled = 0;
411
412 /*
413 * We don't provide any mutex protection for this flag because we know
414 * that this module will have been initialized by the time multiple
415 * threads are running.
416 */
417 boolean_t kd_initialized = FALSE; /* driver initialized? */
418 boolean_t kd_extended = FALSE;
419
420 /* Array for processing escape sequences. */
421 #define K_MAXESC 16
422 u_char esc_seq[K_MAXESC];
423 u_char *esc_spt = (u_char *)0;
424
425 /*
426 * This array maps scancodes to Ascii characters (or character
427 * sequences).
428 * Each row corresponds to one key. There are NUMOUTPUT bytes per key
429 * state. The states are ordered: Normal, SHIFT, CTRL, ALT,
430 * SHIFT/ALT.
431 */
432 unsigned char key_map[NUMKEYS][WIDTH_KMAP] = {
433 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
434 {K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC},
435 {K_ONE,NC,NC, K_BANG,NC,NC, K_ONE,NC,NC, 0x1b,0x4e,0x31, 0x1b,0x4e,0x21},
436 {K_TWO,NC,NC, K_ATSN,NC,NC, K_NUL,NC,NC, 0x1b,0x4e,0x32, 0x1b,0x4e,0x40},
437 {K_THREE,NC,NC, K_POUND,NC,NC, K_THREE,NC,NC, 0x1b,0x4e,0x33, 0x1b,0x4e,0x23},
438 {K_FOUR,NC,NC, K_DOLLAR,NC,NC, K_FOUR,NC,NC, 0x1b,0x4e,0x34, 0x1b,0x4e,0x24},
439 {K_FIVE,NC,NC, K_PERC,NC,NC, K_FIVE,NC,NC, 0x1b,0x4e,0x35, 0x1b,0x4e,0x25},
440 {K_SIX,NC,NC, K_CARET,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x36, 0x1b,0x4e,0x5e},
441 {K_SEVEN,NC,NC, K_AMPER,NC,NC, K_SEVEN,NC,NC, 0x1b,0x4e,0x37, 0x1b,0x4e,0x26},
442 {K_EIGHT,NC,NC, K_ASTER,NC,NC, K_EIGHT,NC,NC, 0x1b,0x4e,0x38, 0x1b,0x4e,0x2a},
443 {K_NINE,NC,NC, K_LPAREN,NC,NC, K_NINE,NC,NC, 0x1b,0x4e,0x39,0x1b,0x4e,0x28},
444 {K_ZERO,NC,NC, K_RPAREN,NC,NC, K_ZERO,NC,NC, 0x1b,0x4e,0x30,0x1b,0x4e,0x29},
445 {K_MINUS,NC,NC, K_UNDSC,NC,NC, K_US,NC,NC, 0x1b,0x4e,0x2d, 0x1b,0x4e,0x5f},
446 {K_EQL,NC,NC, K_PLUS,NC,NC, K_EQL,NC,NC, 0x1b,0x4e,0x3d, 0x1b,0x4e,0x2b},
447 {K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC},
448 {K_HT,NC,NC, K_GS,NC,NC, K_HT,NC,NC, K_HT,NC,NC, K_GS,NC,NC},
449 {K_q,NC,NC, K_Q,NC,NC, K_DC1,NC,NC, 0x1b,0x4e,0x71, 0x1b,0x4e,0x51},
450 {K_w,NC,NC, K_W,NC,NC, K_ETB,NC,NC, 0x1b,0x4e,0x77, 0x1b,0x4e,0x57},
451 {K_e,NC,NC, K_E,NC,NC, K_ENQ,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45},
452 {K_r,NC,NC, K_R,NC,NC, K_DC2,NC,NC, 0x1b,0x4e,0x72, 0x1b,0x4e,0x52},
453 {K_t,NC,NC, K_T,NC,NC, K_DC4,NC,NC, 0x1b,0x4e,0x74, 0x1b,0x4e,0x54},
454 {K_y,NC,NC, K_Y,NC,NC, K_EM,NC,NC, 0x1b,0x4e,0x79, 0x1b,0x4e,0x59},
455 {K_u,NC,NC, K_U,NC,NC, K_NAK,NC,NC, 0x1b,0x4e,0x75, 0x1b,0x4e,0x55},
456 {K_i,NC,NC, K_I,NC,NC, K_HT,NC,NC, 0x1b,0x4e,0x69, 0x1b,0x4e,0x49},
457 {K_o,NC,NC, K_O,NC,NC, K_SI,NC,NC, 0x1b,0x4e,0x6f, 0x1b,0x4e,0x4f},
458 {K_p,NC,NC, K_P,NC,NC, K_DLE,NC,NC, 0x1b,0x4e,0x70, 0x1b,0x4e,0x50},
459 {K_LBRKT,NC,NC, K_LBRACE,NC,NC, K_ESC,NC,NC, 0x1b,0x4e,0x5b, 0x1b,0x4e,0x7b},
460 {K_RBRKT,NC,NC, K_RBRACE,NC,NC, K_GS,NC,NC, 0x1b,0x4e,0x5d, 0x1b,0x4e,0x7d},
461 {K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC},
462 {K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC,
463 K_SCAN,K_CTLSC,NC},
464 {K_a,NC,NC, K_A,NC,NC, K_SOH,NC,NC, 0x1b,0x4e,0x61, 0x1b,0x4e,0x41},
465 {K_s,NC,NC, K_S,NC,NC, K_DC3,NC,NC, 0x1b,0x4e,0x73, 0x1b,0x4e,0x53},
466 {K_d,NC,NC, K_D,NC,NC, K_EOT,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45},
467 {K_f,NC,NC, K_F,NC,NC, K_ACK,NC,NC, 0x1b,0x4e,0x66, 0x1b,0x4e,0x46},
468 {K_g,NC,NC, K_G,NC,NC, K_BEL,NC,NC, 0x1b,0x4e,0x67, 0x1b,0x4e,0x47},
469 {K_h,NC,NC, K_H,NC,NC, K_BS,NC,NC, 0x1b,0x4e,0x68, 0x1b,0x4e,0x48},
470 {K_j,NC,NC, K_J,NC,NC, K_LF,NC,NC, 0x1b,0x4e,0x6a, 0x1b,0x4e,0x4a},
471 {K_k,NC,NC, K_K,NC,NC, K_VT,NC,NC, 0x1b,0x4e,0x6b, 0x1b,0x4e,0x4b},
472 {K_l,NC,NC, K_L,NC,NC, K_FF,NC,NC, 0x1b,0x4e,0x6c, 0x1b,0x4e,0x4c},
473 {K_SEMI,NC,NC, K_COLON,NC,NC, K_SEMI,NC,NC, 0x1b,0x4e,0x3b, 0x1b,0x4e,0x3a},
474 {K_SQUOTE,NC,NC,K_DQUOTE,NC,NC,K_SQUOTE,NC,NC,0x1b,0x4e,0x27,0x1b,0x4e,0x22},
475 {K_GRAV,NC,NC, K_TILDE,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x60, 0x1b,0x4e,0x7e},
476 {K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC,
477 K_SCAN,K_LSHSC,NC},
478 {K_BSLSH,NC,NC, K_PIPE,NC,NC, K_FS,NC,NC, 0x1b,0x4e,0x5c, 0x1b,0x4e,0x7c},
479 {K_z,NC,NC, K_Z,NC,NC, K_SUB,NC,NC, 0x1b,0x4e,0x7a, 0x1b,0x4e,0x5a},
480 {K_x,NC,NC, K_X,NC,NC, K_CAN,NC,NC, 0x1b,0x4e,0x78, 0x1b,0x4e,0x58},
481 {K_c,NC,NC, K_C,NC,NC, K_ETX,NC,NC, 0x1b,0x4e,0x63, 0x1b,0x4e,0x43},
482 {K_v,NC,NC, K_V,NC,NC, K_SYN,NC,NC, 0x1b,0x4e,0x76, 0x1b,0x4e,0x56},
483 {K_b,NC,NC, K_B,NC,NC, K_STX,NC,NC, 0x1b,0x4e,0x62, 0x1b,0x4e,0x42},
484 {K_n,NC,NC, K_N,NC,NC, K_SO,NC,NC, 0x1b,0x4e,0x6e, 0x1b,0x4e,0x4e},
485 {K_m,NC,NC, K_M,NC,NC, K_CR,NC,NC, 0x1b,0x4e,0x6d, 0x1b,0x4e,0x4d},
486 {K_COMMA,NC,NC, K_LTHN,NC,NC, K_COMMA,NC,NC, 0x1b,0x4e,0x2c, 0x1b,0x4e,0x3c},
487 {K_PERIOD,NC,NC, K_GTHN,NC,NC, K_PERIOD,NC,NC,0x1b,0x4e,0x2e,0x1b,0x4e,0x3e},
488 {K_SLASH,NC,NC, K_QUES,NC,NC, K_SLASH,NC,NC, 0x1b,0x4e,0x2f, 0x1b,0x4e,0x3f},
489 {K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC,
490 K_SCAN,K_RSHSC,NC},
491 {K_ASTER,NC,NC, K_ASTER,NC,NC, K_ASTER,NC,NC, 0x1b,0x4e,0x2a,0x1b,0x4e,0x2a},
492 {K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC,
493 K_SCAN,K_ALTSC,NC},
494 {K_SPACE,NC,NC, K_SPACE,NC,NC, K_NUL,NC,NC, K_SPACE,NC,NC, K_SPACE,NC,NC},
495 {K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC,
496 K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC},
497 {K_F1, K_F1S, K_F1, K_F1, K_F1S},
498 {K_F2, K_F2S, K_F2, K_F2, K_F2S},
499 {K_F3, K_F3S, K_F3, K_F3, K_F3S},
500 {K_F4, K_F4S, K_F4, K_F4, K_F4S},
501 {K_F5, K_F5S, K_F5, K_F5, K_F5S},
502 {K_F6, K_F6S, K_F6, K_F6, K_F6S},
503 {K_F7, K_F7S, K_F7, K_F7, K_F7S},
504 {K_F8, K_F8S, K_F8, K_F8, K_F8S},
505 {K_F9, K_F9S, K_F9, K_F9, K_F9S},
506 {K_F10, K_F10S, K_F10, K_F10, K_F10S},
507 {K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC,
508 K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC},
509 {K_SCRL, K_NUL,NC,NC, K_SCRL, K_SCRL, K_NUL,NC,NC},
510 {K_HOME, K_SEVEN,NC,NC, K_HOME, K_HOME, 0x1b,0x4e,0x37},
511 {K_UA, K_EIGHT,NC,NC, K_UA, K_UA, 0x1b,0x4e,0x38},
512 {K_PUP, K_NINE,NC,NC, K_PUP, K_PUP, 0x1b,0x4e,0x39},
513 {0x1b,0x5b,0x53, K_MINUS,NC,NC, 0x1b,0x5b,0x53,0x1b,0x5b,0x53,0x1b,0x4e,0x2d},
514 {K_LA, K_FOUR,NC,NC, K_LA, K_LA, 0x1b,0x4e,0x34},
515 {0x1b,0x5b,0x47,K_FIVE,NC,NC,0x1b,0x5b,0x47, 0x1b,0x5b,0x47, 0x1b,0x4e,0x35},
516 {K_RA, K_SIX,NC,NC, K_RA, K_RA, 0x1b,0x4e,0x36},
517 {0x1b,0x5b,0x54,K_PLUS,NC,NC, 0x1b,0x5b,0x54, 0x1b,0x5b,0x54, 0x1b,0x4e,0x2b},
518 {K_END, K_ONE,NC,NC, K_END, K_END, 0x1b,0x4e,0x31},
519 {K_DA, K_TWO,NC,NC, K_DA, K_DA, 0x1b,0x4e,0x32},
520 {K_PDN, K_THREE,NC,NC, K_PDN, K_PDN, 0x1b,0x4e,0x33},
521 {K_INS, K_ZERO,NC,NC, K_INS, K_INS, 0x1b,0x4e,0x30},
522 {K_DEL,NC,NC, K_PERIOD,NC,NC, K_DEL,NC,NC, K_DEL,NC,NC, 0x1b,0x4e,0x2e},
523 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
524 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
525 {NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC},
526 {K_F11, K_F11S, K_F11, K_F11, K_F11S},
527 {K_F12, K_F12S, K_F12, K_F12, K_F12S}
528 };
529
530
531 /*
532 * Globals used only for character-based controllers.
533 */
534
535 short kd_index_reg = EGA_IDX_REG;
536 short kd_io_reg = EGA_IO_REG;
537
538 /*
539 * IO port sets for different controllers.
540 */
541 io_reg_t vga_port_list[] = {
542 0x3b4, 0x3b5, 0x3b8, 0x3b9, 0x3ba, /* MDA/EGA */
543 0x3d4, 0x3d5, 0x3d8, 0x3d9, 0x3da, /* CGA/EGA */
544 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4, 0x3c5, 0x3c6, 0x3c7,
545 0x3c8, 0x3c9, 0x3ca, 0x3cb, 0x3cc, 0x3cd, 0x3ce, 0x3cf,
546 IO_REG_NULL
547 };
548
549 device_t kd_io_device = 0;
550
551 kd_io_map_open(device)
552 device_t device;
553 {
554 kd_io_device = device;
555 io_port_create(device, vga_port_list);
556 }
557
558 kd_io_map_close()
559 {
560 io_port_destroy(kd_io_device);
561 kd_io_device = 0;
562 }
563
564 /*
565 * Globals used only for bitmap-based controllers. See kdsoft.h for
566 * an explanation of what some of these variables are used for.
567 */
568
569 u_char *font_start = 0; /* starting addr of font */
570
571 short fb_width = 0; /* bits in frame buffer scan line */
572 short fb_height = 0; /* scan lines in frame buffer*/
573 short char_width = 0; /* bit width of 1 char */
574 short char_height = 0; /* bit height of 1 char */
575 short chars_in_font = 0;
576 short cursor_height = 0; /* bit height of cursor */
577
578 /* These initial values are simply guesses. */
579 u_char char_black = 0;
580 u_char char_white = 0xff;
581
582 short xstart = 0;
583 short ystart = 0;
584
585 short char_byte_width = 0; /* char_width/NBBY */
586 short fb_byte_width = 0; /* fb_width/NBBY */
587 short font_byte_width = 0; /* num bytes in 1 scan line of font */
588
589 #ifdef MACH_KERNEL
590 /*
591 * Switch for poll vs. interrupt.
592 */
593 int kd_pollc = 0;
594
595 /*
596 * cninit:
597 *
598 * Initialize the console.
599 */
600 cninit()
601 {
602 kdinit();
603 }
604 #endif MACH_KERNEL
605
606 /*
607 * cnputc:
608 *
609 * This function is used to put characters out to the console,
610 * one at a time, for things like printf(). It does CR/NL
611 * mapping.
612 *
613 * input : character 'c' to be put on the screen.
614 *
615 * output : character from input is put on the screen.
616 *
617 */
618 cnputc(c)
619 u_char c;
620 {
621 int i;
622
623 #if KD_NEEDS_VM
624 #ifdef MACH_KERNEL
625 if (kernel_pmap == 0 || kernel_pmap->dirbase == 0)
626 #else MACH_KERNEL
627 if (kernel_map == 0 || kernel_pmap == 0 || kernel_pmap->cr3 == 0)
628 #endif MACH_KERNEL
629 return;
630 #endif
631 kdinit();
632 switch(c) {
633 case K_LF:
634 kd_putc(K_CR);
635 kd_putc(K_LF);
636 break;
637 case K_HT:
638 for (i = 8 - (CURRENT_COLUMN(kd_curpos) % 8); i > 0; i--)
639 kd_putc(' ');
640 break;
641 default:
642 #if MACH_RDB /* we need escape sequences processed for RDB */
643 if (c == (K_ESC)) {
644 if (esc_spt == esc_seq) {
645 *(esc_spt++)=(K_ESC);
646 *(esc_spt) = '\0';
647 }
648 else {
649 kd_putc((K_ESC));
650 esc_spt = esc_seq;
651 }
652 }
653 else {
654 if (esc_spt - esc_seq) {
655 *(esc_spt++) = c;
656 *(esc_spt) = '\0';
657 kd_parseesc();
658 }
659 else {
660 kd_putc(c&0x7f);
661 }
662 }
663 #else
664 kd_putc(c);
665 #endif
666 break;
667 }
668
669 #if 0
670 {
671 volatile int cnt;
672 for (cnt=0; cnt<10000; cnt++)
673 ; /* allow output delays for debugging */
674 }
675 #endif
676
677 return;
678 }
679
680
681 /*
682 * cngetc:
683 *
684 * Get one character using polling, rather than interrupts. Used
685 * by the kernel debugger. Note that Caps Lock is ignored.
686 * Normally this routine is called with interrupts already
687 * disabled, but there is code in place so that it will be more
688 * likely to work even if interrupts are turned on.
689 */
690 #ifdef MACH_KERNEL
691 cngetc()
692 {
693 return (cndogetc(TRUE));
694 }
695
696 cnmaygetc()
697 {
698 return (cndogetc(FALSE));
699 }
700
701 cndogetc(wait)
702 boolean_t wait;
703 #else MACH_KERNEL
704 cngetc()
705 #endif MACH_KERNEL
706 {
707 unsigned char c;
708 unsigned char scancode;
709 unsigned int char_idx;
710 extern int kd_mouse;
711 #ifdef notdef
712 int o_pri;
713 #endif
714 boolean_t up;
715
716 kdinit();
717 kd_extended = FALSE;
718 #ifdef notdef
719 o_pri = splhi();
720 #endif
721 for ( ; ; ) {
722 while (!(inb(K_STATUS) & K_OBUF_FUL))
723 #ifdef MACH_KERNEL
724 if (!wait)
725 return (-1);
726 #else MACH_KERNEL
727 continue;
728 #endif MACH_KERNEL
729 up = FALSE;
730
731 /*
732 * We'd come here for mouse events in debugger, if
733 * the mouse were on.
734 */
735 if (kd_mouse && ((inb(K_STATUS) & 0x20) == 0x20)) {
736 printf("M%xP", inb(K_RDWR));
737 continue;
738 }
739
740 scancode = inb(K_RDWR);
741 #ifdef MACH_KERNEL
742 /*
743 * Handle extend modifier and
744 * ack/resend, otherwise we may never receive
745 * a key.
746 */
747 if (scancode == K_EXTEND) {
748 kd_extended = TRUE;
749 continue;
750 } else if (scancode == K_RESEND) {
751 printf("cngetc: resend");
752 kd_resend();
753 continue;
754 } else if (scancode == K_ACKSC) {
755 printf("cngetc: handle_ack");
756 kd_handle_ack();
757 continue;
758 }
759 #endif MACH_KERNEL
760 if (scancode & K_UP) {
761 up = TRUE;
762 scancode &= ~K_UP;
763 }
764 #ifdef RVB_KBD_MOUSE
765 if (kd_kbd_mouse)
766 kd_kbd_magic(scancode);
767 #endif /* RVB_KBD_MOUSE */
768 if (scancode < NUMKEYS) {
769 /* Lookup in map, then process. */
770 char_idx = kdstate2idx(kd_state, kd_extended);
771 c = key_map[scancode][char_idx];
772 if (c == K_SCAN) {
773 c = key_map[scancode][++char_idx];
774 kd_state = do_modifier(kd_state, c, up);
775 #ifdef notdef
776 cnsetleds(state2leds(kd_state));
777 #endif
778 } else if (!up) {
779 /* regular key-down */
780 if (c == K_CR)
781 c = K_LF;
782 #ifndef PS2
783 #ifdef MACH_KERNEL
784 #else MACH_KERNEL
785 cnputc(c);
786 #endif MACH_KERNEL
787 #endif PS2
788 #ifdef notdef
789 splx(o_pri);
790 #endif
791 return(c & 0177);
792 }
793 }
794 }
795 }
796
797
798 #ifdef DEBUG
799 /*
800 * feep:
801 *
802 * Ring the bell for a short time.
803 * Warning: uses outb(). You may prefer to use kd_debug_put.
804 */
805 feep()
806 {
807 int i;
808
809 kd_bellon();
810 for (i = 0; i < 50000; ++i)
811 ;
812 kd_belloff();
813 }
814
815 pause()
816 {
817 int i;
818
819 for (i = 0; i < 50000; ++i)
820 ;
821 }
822
823 /*
824 * Put a debugging character on the screen.
825 * LOC=0 means put it in the bottom right corner, LOC=1 means put it
826 * one column to the left, etc.
827 */
828 kd_debug_put(loc, c)
829 int loc;
830 char c;
831 {
832 csrpos_t pos = ONE_PAGE - (loc+1) * ONE_SPACE;
833
834 (*kd_dput)(pos, c, KA_NORMAL);
835 }
836 #endif /* DEBUG */
837
838
839 #if MACH_KERNEL
840 extern int mouse_in_use;
841 int old_mouse_in_use;
842 int old_kb_mode;
843
844 cnpollc(on)
845 boolean_t on;
846 {
847 if (on) {
848 /* switch into X */
849 old_mouse_in_use = mouse_in_use;
850 old_kb_mode = kb_mode;
851 mouse_in_use = 0;
852 kb_mode = KB_ASCII;
853 X_kdb_enter();
854
855 kd_pollc++;
856 }
857 else {
858 --kd_pollc;
859
860 /* switch out of X */
861 X_kdb_exit();
862 mouse_in_use = old_mouse_in_use;
863 kb_mode = old_kb_mode;
864 }
865 }
866 #else MACH_KERNEL
867 /*
868 * cnpollc:
869 *
870 * I think this routine is supposed to switch the keyboard
871 * between polled mode and interrupt-driven mode. I don't know
872 * if that's important for the AT keyboard.
873 */
874
875 cnpollc(on)
876 boolean_t on;
877 {
878 }
879 #endif MACH_KERNEL
880
881
882
883 /*
884 * kdopen:
885 *
886 * This opens the console driver and sets up the tty and other
887 * rudimentary stuff including calling the line discipline for
888 * setting up the device independent stuff for a tty driver.
889 *
890 * input: device number 'dev', and flag
891 *
892 * output: device is opened and setup
893 *
894 */
895 #ifdef MACH_KERNEL
896 kdopen(dev, flag, ior)
897 dev_t dev;
898 int flag;
899 io_req_t ior;
900 #else MACH_KERNEL
901 /*ARGSUSED*/
902 kdopen(dev, flag)
903 int dev;
904 int flag;
905 #endif MACH_KERNEL
906 {
907 struct tty *tp;
908 int kdstart();
909 int o_pri;
910 #ifdef MACH_KERNEL
911 int kdstop();
912 #endif MACH_KERNEL
913
914 tp = &kd_tty;
915 #ifdef MACH_KERNEL
916 o_pri = spltty();
917 simple_lock(&tp->t_lock);
918 #endif MACH_KERNEL
919 if (!(tp->t_state & (TS_ISOPEN|TS_WOPEN))) {
920 #ifdef MACH_KERNEL
921 /* XXX ttychars allocates memory */
922 simple_unlock(&tp->t_lock);
923 #endif MACH_KERNEL
924 ttychars(tp);
925 #ifdef MACH_KERNEL
926 simple_lock(&tp->t_lock);
927 #endif MACH_KERNEL
928 /*
929 * Special support for boot-time rc scripts, which don't
930 * stty the console.
931 */
932 tp->t_oproc = kdstart;
933 #ifdef MACH_KERNEL
934 tp->t_stop = kdstop;
935 #endif MACH_KERNEL
936 tp->t_ospeed = tp->t_ispeed = B9600;
937 tp->t_flags = ODDP|EVENP|ECHO|CRMOD|XTABS;
938 kdinit();
939 #ifdef PS2
940 kdabios_init();
941 #endif PS2
942
943 #ifdef MACH_KERNEL
944 /* XXX kd_io_map_open allocates memory */
945 simple_unlock(&tp->t_lock);
946 #endif MACH_KERNEL
947 kd_io_map_open(ior->io_device);
948 #ifdef MACH_KERNEL
949 simple_lock(&tp->t_lock);
950 #endif MACH_KERNEL
951 }
952 #ifdef MACH_KERNEL
953 tp->t_state |= TS_CARR_ON;
954 simple_unlock(&tp->t_lock);
955 splx(o_pri);
956 return (char_open(dev, tp, flag, ior));
957 #else MACH_KERNEL
958 o_pri = SPLKD();
959 tp->t_state |= TS_CARR_ON;
960 (*linesw[tp->t_line].l_open)(dev, tp);
961 splx(o_pri);
962 return(0);
963 #endif MACH_KERNEL
964 }
965
966
967 /*
968 * kdclose:
969 *
970 * This function merely executes the device independent code for
971 * closing the line discipline.
972 *
973 * input: device number 'dev', and flag
974 *
975 * output: device is closed
976 *
977 */
978 /*ARGSUSED*/
979 kdclose(dev, flag)
980 int dev;
981 int flag;
982 {
983 struct tty *tp;
984
985 tp = &kd_tty;
986 #ifdef MACH_KERNEL
987 {
988 int s = spltty();
989 simple_lock(&tp->t_lock);
990 ttyclose(tp);
991 simple_unlock(&tp->t_lock);
992 splx(s);
993 }
994 #else MACH_KERNEL
995 (*linesw[tp->t_line].l_close)(tp);
996 ttyclose(tp);
997 #endif MACH_KERNEL
998
999 kd_io_map_close();
1000
1001 return;
1002
1003 }
1004
1005
1006 /*
1007 * kdread:
1008 *
1009 * This function executes the device independent code to read from
1010 * the tty.
1011 *
1012 * input: device number 'dev'
1013 *
1014 * output: characters are read from tty clists
1015 *
1016 */
1017 /*ARGSUSED*/
1018 kdread(dev, uio)
1019 int dev;
1020 struct uio *uio;
1021 {
1022 struct tty *tp;
1023
1024 tp = &kd_tty;
1025 tp->t_state |= TS_CARR_ON;
1026 return((*linesw[kd_tty.t_line].l_read)(tp, uio));
1027 }
1028
1029
1030 /*
1031 * kdwrite:
1032 *
1033 * This function does the device independent write action for this
1034 * console (tty) driver.
1035 *
1036 * input: device number 'dev'
1037 *
1038 * output: characters are written to tty clists
1039 *
1040 */
1041 /*ARGSUSED*/
1042 kdwrite(dev, uio)
1043 int dev;
1044 struct uio *uio;
1045 {
1046 return((*linesw[kd_tty.t_line].l_write)(&kd_tty, uio));
1047 }
1048
1049 /*
1050 * Mmap.
1051 */
1052
1053 /*ARGSUSED*/
1054 int
1055 kdmmap(dev, off, prot)
1056 dev_t dev;
1057 off_t off;
1058 int prot;
1059 {
1060 if ((u_int) off >= (128*1024))
1061 return(-1);
1062
1063 /* Get page frame number for the page to be mapped. */
1064 return(i386_btop(kd_bitmap_start+off));
1065 }
1066
1067 #ifdef MACH_KERNEL
1068 kdportdeath(dev, port)
1069 dev_t dev;
1070 mach_port_t port;
1071 {
1072 return (tty_portdeath(&kd_tty, port));
1073 }
1074
1075 /*ARGSUSED*/
1076 io_return_t kdgetstat(dev, flavor, data, count)
1077 dev_t dev;
1078 int flavor;
1079 int * data; /* pointer to OUT array */
1080 unsigned int *count; /* OUT */
1081 {
1082 io_return_t result;
1083
1084 switch (flavor) {
1085 case KDGSTATE:
1086 if (*count < 1)
1087 return (D_INVALID_OPERATION);
1088 *data = kd_state;
1089 *count = 1;
1090 result = D_SUCCESS;
1091 break;
1092
1093 case KDGKBENT:
1094 result = kdgetkbent((struct kbentry *)data);
1095 *count = sizeof(struct kbentry)/sizeof(int);
1096 break;
1097
1098 default:
1099 result = tty_get_status(&kd_tty, flavor, data, count);
1100 break;
1101 }
1102 return (result);
1103 }
1104
1105 /*ARGSUSED*/
1106 io_return_t kdsetstat(dev, flavor, data, count)
1107 dev_t dev;
1108 int flavor;
1109 int * data;
1110 unsigned int count;
1111 {
1112 io_return_t result;
1113
1114 switch (flavor) {
1115 case KDSKBENT:
1116 if (count < sizeof(struct kbentry)/sizeof(int)) {
1117 return (D_INVALID_OPERATION);
1118 }
1119 result = kdsetkbent((struct kbentry *)data, 0);
1120 break;
1121
1122 case KDSETBELL:
1123 if (count < 1)
1124 return (D_INVALID_OPERATION);
1125 result = kdsetbell(*data, 0);
1126 break;
1127
1128 default:
1129 result = tty_set_status(&kd_tty, flavor, data, count);
1130 }
1131 return (result);
1132 }
1133
1134 #else MACH_KERNEL
1135 /*
1136 * kdioctl:
1137 *
1138 * This function executes the device independent code to manipulate
1139 * the tty, plus it provides ioctl's that are specific to the
1140 * console.
1141 *
1142 * input: device number 'dev', command 'cmd', pointer to arguments
1143 * 'addr', mode
1144 *
1145 * output: dependent and independent tty manipulation
1146 *
1147 */
1148 /*ARGSUSED*/
1149 int
1150 kdioctl(dev, cmd, addr, mode)
1151 int dev;
1152 int cmd;
1153 caddr_t addr;
1154 int mode;
1155 {
1156 register int err = -1;
1157 struct tty *tp = &kd_tty;
1158
1159 /*
1160 * First look for an ioctl that is specific to the kd driver.
1161 * If we don't find one (err == -1), try the line discipline
1162 * ioctl's and then the generic tty ioctl's.
1163 */
1164
1165 switch(cmd) {
1166
1167 case TIOCSBRK:
1168 case TIOCCBRK:
1169 case TIOCSDTR:
1170 case TIOCCDTR:
1171 err = 0;
1172 break;
1173
1174 case KDGSTATE:
1175 *addr = kd_state;
1176 err = 0;
1177 break;
1178
1179 case KDGKBENT: /* get entry from key_map */
1180 err = kdgetkbent((struct kbentry *)addr);
1181 break;
1182
1183 case KDSKBENT: /* set entry in key_map */
1184 err = kdsetkbent((struct kbentry *)addr, mode);
1185 break;
1186
1187 case KDSETBELL:
1188 err = kdsetbell(*addr, mode);
1189 break;
1190 }
1191 if (err >= 0)
1192 return(err);
1193
1194 if ((err = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr, mode)) >= 0)
1195 return(err);
1196
1197 if ((err = ttioctl(tp, cmd, addr, mode)) >= 0)
1198 return(err);
1199
1200 return(ENOTTY);
1201 }
1202 #endif MACH_KERNEL
1203
1204
1205 /*
1206 * kdsetbell:
1207 *
1208 * Turn the bell on or off. Returns error code, if given bogus
1209 * on/off value.
1210 */
1211 int
1212 kdsetbell(val, flags)
1213 int val; /* on or off */
1214 int flags; /* flags set for console */
1215 {
1216 int err = 0;
1217
1218 #ifdef MACH_KERNEL
1219 #else MACH_KERNEL
1220 if ((flags & (FWRITE | FREAD)) != (FWRITE | FREAD))
1221 return(EACCES);
1222 #endif MACH_KERNEL
1223
1224 if (val == KD_BELLON)
1225 kd_bellon();
1226 else if (val == KD_BELLOFF)
1227 kd_belloff();
1228 else
1229 #ifdef MACH_KERNEL
1230 err = D_INVALID_OPERATION;
1231 #else MACH_KERNEL
1232 err = EINVAL;
1233 #endif MACH_KERNEL
1234
1235 return(err);
1236 }
1237
1238
1239 /*
1240 * kdgetkbent:
1241 *
1242 * Get entry from key mapping table. Returns error code, if any.
1243 */
1244 int
1245 kdgetkbent(kbent)
1246 struct kbentry * kbent;
1247 {
1248 u_char *cp;
1249 int o_pri = SPLKD(); /* probably superfluous */
1250
1251 cp = &key_map[kbent->kb_index][CHARIDX(kbent->kb_state)];
1252 kbent->kb_value[0] = *cp++;
1253 kbent->kb_value[1] = *cp++;
1254 kbent->kb_value[2] = *cp;
1255 (void)splx(o_pri);
1256 return(0);
1257 }
1258
1259
1260 /*
1261 * kdsetkbent:
1262 *
1263 * Set entry in key mapping table. Return error code, if any.
1264 */
1265 int
1266 kdsetkbent(kbent, flags)
1267 struct kbentry * kbent;
1268 int flags; /* flags set for console */
1269 {
1270 u_char *cp;
1271 int o_pri;
1272
1273 #ifdef MACH_KERNEL
1274 #else MACH_KERNEL
1275 if ((flags & (FWRITE | FREAD)) != (FWRITE | FREAD))
1276 return(EACCES);
1277 #endif MACH_KERNEL
1278
1279 o_pri = SPLKD();
1280 cp = &key_map[kbent->kb_index][CHARIDX(kbent->kb_state)];
1281 *cp++ = kbent->kb_value[0];
1282 *cp++ = kbent->kb_value[1];
1283 *cp = kbent->kb_value[2];
1284 (void)splx(o_pri);
1285 return(0);
1286 }
1287
1288 /*
1289 * kdintr:
1290 *
1291 * This function is the interrupt code for the driver. Since this is
1292 * a special tty (console), interrupts are only for input, so we read in
1293 * the character. If in ascii mode, we then do the mapping translation
1294 * from the keyboard switch table and place the characters on the tty's
1295 * input switch table. If in event mode, we create and queue a kd_event.
1296 *
1297 * input: interrupt vector 'vec'
1298 *
1299 * output: character or sequence is placed on appropriate queue
1300 *
1301 */
1302 /*ARGSUSED*/
1303 #ifdef MACH_KERNEL
1304 kdintr(unit, spl, regs) /* XXX not right for PS2!! */
1305 int unit, spl, regs;
1306 #else MACH_KERNEL
1307 kdintr(vec, regs)
1308 int vec;
1309 int regs;
1310 #endif MACH_KERNEL
1311 {
1312 struct tty *tp;
1313 unsigned char c;
1314 unsigned char scancode;
1315 int o_pri;
1316 int char_idx;
1317 boolean_t up = FALSE; /* key-up event */
1318 extern int mouse_in_use;
1319 extern int kd_mouse;
1320 #ifdef MACH_KERNEL
1321 if (kd_pollc)
1322 return; /* kdb polling kbd */
1323 #endif MACH_KERNEL
1324
1325 tp = &kd_tty;
1326 #ifndef PS2
1327 while ((inb(K_STATUS) & K_OBUF_FUL) == 0); /* this should never loop */
1328 /*
1329 * We may have seen a mouse event.
1330 */
1331 if (kd_mouse && ((inb(K_STATUS) & 0x20) == 0x20)) {
1332 if (mouse_in_use) {
1333 mouse_handle_byte((u_char)inb(K_RDWR));
1334 return;
1335 } else {
1336 printf("M%xI", inb(K_RDWR));
1337 return;
1338 }
1339 }
1340
1341 scancode = inb(K_RDWR);
1342
1343 #else /* PS2 */
1344
1345 o_pri = SPLKD();
1346 if (kdabios_intr() == INTR_FAIL)
1347 goto done;
1348 if ((scancode = kbd_abios_data.sc) == 0)
1349 goto done;
1350 #endif PS2
1351
1352 if (scancode == K_EXTEND) {
1353 if (kb_mode != KB_EVENT)
1354 kd_extended = TRUE;
1355 goto done;
1356 } else if (scancode == K_RESEND) {
1357 kd_resend();
1358 goto done;
1359 } else if (scancode == K_ACKSC) {
1360 kd_handle_ack();
1361 goto done;
1362 #ifdef RVB_KBD_MOUSE
1363 } else if (kd_kbd_mouse && kd_kbd_magic(scancode)) {
1364 goto done;
1365 #endif /* RVB_KBD_MOUSE */
1366 #ifdef PS2
1367 } else if (kdcheckmagic(scancode, regs)) {
1368 #else
1369 } else if (kdcheckmagic(scancode, ®s)) {
1370 #endif PS2
1371 goto done;
1372 } else if (kb_mode == KB_EVENT) {
1373 kd_enqsc(scancode);
1374 goto done;
1375 } /* else... */
1376
1377 if (scancode & K_UP) {
1378 up = TRUE;
1379 scancode &= ~K_UP;
1380 }
1381 if (scancode < NUMKEYS) {
1382 /* Lookup in map, then process. */
1383 char_idx = kdstate2idx(kd_state, kd_extended);
1384 c = key_map[scancode][char_idx];
1385 if (c == K_SCAN) {
1386 c = key_map[scancode][++char_idx];
1387 set_kd_state(do_modifier(kd_state, c, up));
1388 } else if (!up) {
1389 /* regular key-down */
1390 int max; /* max index for char sequence */
1391
1392 max = char_idx + NUMOUTPUT;
1393 char_idx++;
1394 if (!kd_extended) {
1395 if (kd_state&KS_CLKED) {
1396 if (kd_isupper(c)) {
1397 c += ('a' - 'A');
1398 max = char_idx;
1399 }
1400 else if (kd_islower(c)) {
1401 c -= ('a' - 'A');
1402 max = char_idx;
1403 }
1404 }
1405 /*
1406 * Notice that even if the keypad is remapped,
1407 * NumLock only effects the keys that are
1408 * physically part of the keypad. Is this
1409 * The Right Thing?
1410 */
1411 if ((kd_state&KS_NLKED) &&
1412 (((K_HOMESC) <= scancode) &&
1413 (scancode <= (K_DELSC)))) {
1414 char_idx = CHARIDX(SHIFT_STATE);
1415 c = key_map[scancode][char_idx];
1416 max = char_idx + NUMOUTPUT;
1417 char_idx++;
1418 }
1419 }
1420
1421 /*
1422 * here's where we actually put the char (or
1423 * char sequence, for function keys) onto the
1424 * input queue.
1425 */
1426 for ( ; (c != K_DONE) && (char_idx <= max);
1427 c = key_map[scancode][char_idx++]) {
1428 (*linesw[tp->t_line].l_rint)(c, tp);
1429 }
1430 kd_extended = FALSE;
1431 }
1432 }
1433
1434 done:
1435 #ifdef PS2
1436 splx(o_pri);
1437 #endif /* PS2 */
1438 }
1439
1440 /*
1441 * kd_handle_ack:
1442 *
1443 * For pending commands, complete the command. For data bytes,
1444 * drop the ack on the floor.
1445 */
1446 kd_handle_ack()
1447 {
1448 switch (kd_ack) {
1449 case SET_LEDS:
1450 kd_setleds2();
1451 kd_ack = DATA_ACK;
1452 break;
1453 case DATA_ACK:
1454 kd_ack = NOT_WAITING;
1455 break;
1456 case NOT_WAITING:
1457 printf("unexpected ACK from keyboard\n");
1458 break;
1459 default:
1460 panic("bogus kd_ack\n");
1461 break;
1462 }
1463 }
1464
1465 /*
1466 * kd_resend:
1467 *
1468 * Resend a missed keyboard command or data byte.
1469 */
1470 kd_resend()
1471 {
1472 if (kd_ack == NOT_WAITING)
1473 printf("unexpected RESEND from keyboard\n");
1474 else
1475 kd_senddata(last_sent);
1476 }
1477
1478
1479 /*
1480 * do_modifier:
1481 *
1482 * Change keyboard state according to which modifier key and
1483 * whether it went down or up.
1484 *
1485 * input: the current state, the key, and the key's direction.
1486 * The key can be any key, not just a modifier key.
1487 *
1488 * output: the new state
1489 */
1490 int
1491 do_modifier(state, c, up)
1492 int state;
1493 Scancode c;
1494 boolean_t up;
1495 {
1496 switch (c) {
1497 case (K_ALTSC):
1498 if (up)
1499 state &= ~KS_ALTED;
1500 else
1501 state |= KS_ALTED;
1502 kd_extended = FALSE;
1503 break;
1504 #ifndef ORC
1505 case (K_CLCKSC):
1506 #endif ORC
1507 case (K_CTLSC):
1508 if (up)
1509 state &= ~KS_CTLED;
1510 else
1511 state |= KS_CTLED;
1512 kd_extended = FALSE;
1513 break;
1514 #ifdef ORC
1515 case (K_CLCKSC):
1516 if (!up)
1517 state ^= KS_CLKED;
1518 break;
1519 #endif ORC
1520 case (K_NLCKSC):
1521 if (!up)
1522 state ^= KS_NLKED;
1523 break;
1524 case (K_LSHSC):
1525 case (K_RSHSC):
1526 if (up)
1527 state &= ~KS_SHIFTED;
1528 else
1529 state |= KS_SHIFTED;
1530 kd_extended = FALSE;
1531 break;
1532 }
1533
1534 return(state);
1535 }
1536
1537
1538 /*
1539 * kdcheckmagic:
1540 *
1541 * Check for magic keystrokes for invoking the debugger or
1542 * rebooting or ...
1543 *
1544 * input: an unprocessed scancode
1545 *
1546 * output: TRUE if a magic key combination was recognized and
1547 * processed. FALSE otherwise.
1548 *
1549 * side effects:
1550 * various actions possible, depending on which keys are
1551 * pressed. If the debugger is called, steps are taken
1552 * to ensure that the system doesn't think the magic keys
1553 * are still held down.
1554 */
1555 boolean_t
1556 kdcheckmagic(scancode, regs)
1557 Scancode scancode;
1558 int *regs;
1559 {
1560 static int magic_state = KS_NORMAL; /* like kd_state */
1561 boolean_t up = FALSE;
1562 extern int rebootflag;
1563
1564 #ifdef RVB_KBD_MOUSE
1565 if (scancode == 0x46) /* scroll lock */
1566 /* if (scancode == 0x52) /* insert key */
1567 {
1568 kd_kbd_mouse = !kd_kbd_mouse;
1569 kd_kbd_magic_buttons = 0;
1570 return(TRUE);
1571 }
1572 #endif /* RVB_KBD_MOUSE */
1573
1574 if (scancode & K_UP) {
1575 up = TRUE;
1576 scancode &= ~K_UP;
1577 }
1578 magic_state = do_modifier(magic_state, scancode, up);
1579
1580 if ((magic_state&(KS_CTLED|KS_ALTED)) == (KS_CTLED|KS_ALTED)) {
1581 switch (scancode) {
1582 #if MACH_KDB
1583 case K_dSC: /* ctl-alt-d */
1584 #ifdef MACH_KERNEL
1585 kdb_kintr(); /* invoke debugger */
1586 #else MACH_KERNEL
1587 kdb((int)0, regs);
1588 /* invoke debugger */
1589 #endif MACH_KERNEL
1590 /* Returned from debugger, so reset kbd state. */
1591 (void)SPLKD();
1592 magic_state = KS_NORMAL;
1593 if (kb_mode == KB_ASCII)
1594 #ifdef MACH_KERNEL
1595 kd_state = KS_NORMAL;
1596 /* setting leds kills kbd */
1597 #else MACH_KERNEL
1598 set_kd_state(KS_NORMAL);
1599 #endif MACH_KERNEL
1600 else {
1601 kd_enqsc(K_ALTSC | K_UP);
1602 kd_enqsc(K_CTLSC | K_UP);
1603 kd_enqsc(K_dSC | K_UP);
1604 }
1605 return(TRUE);
1606 break;
1607 #endif MACH_KDB
1608
1609 #if MACH_RDB
1610 #define K_pad4SC 0x4b
1611 case K_pad4SC: /* ctl-alt-pad4 */
1612 DEBUGF(kddebug & KTSDEBUG_INFO,
1613 printf("Ctrl-Alt-pad4 detected, calling kernel debugger...\n"));
1614 /*
1615 * cleaning up the 'up' scancodes of ctrl, alt and
1616 * pad4. Also reset the state variables properly
1617 * before calling the kernel debugger.
1618 */
1619 kbd_clr_ctrl_alt_pad4(); /* eat 'up' scancodes */
1620 magic_state = KS_NORMAL;
1621 if (kb_mode == KB_ASCII) {
1622 kd_state &= ~(KS_ALTED | KS_CTLED);
1623 kd_extended = FALSE;
1624 } else {
1625 kd_enqsc(K_ALTSC | K_UP);
1626 kd_enqsc(K_CTLSC | K_UP);
1627 kd_enqsc(K_pad4SC | K_UP);
1628 }
1629 if (regs)
1630 kdb_set_tf(regs); /* request single step interrupt */
1631 else
1632 break; /* ignore if in debugger already */
1633 return(TRUE);
1634 #endif MACH_RDB
1635
1636 case K_DELSC: /* ctl-alt-del */
1637 /* if rebootflag is on, reboot the system */
1638 if (rebootflag)
1639 kdreboot();
1640 break;
1641 }
1642 }
1643 return(FALSE);
1644 }
1645
1646
1647 /*
1648 * kdstate2idx:
1649 *
1650 * Return the value for the 2nd index into key_map that
1651 * corresponds to the given state.
1652 */
1653 int
1654 kdstate2idx(state, extended)
1655 int state; /* bit vector, not a state index */
1656 boolean_t extended;
1657 {
1658 int state_idx = NORM_STATE;
1659
1660 if ((!extended) && state != KS_NORMAL) {
1661 if ((state&(KS_SHIFTED|KS_ALTED)) == (KS_SHIFTED|KS_ALTED))
1662 state_idx = SHIFT_ALT;
1663 else if (state&KS_SHIFTED)
1664 state_idx = SHIFT_STATE;
1665 else if (state&KS_ALTED)
1666 state_idx = ALT_STATE;
1667 else if (state&KS_CTLED)
1668 state_idx = CTRL_STATE;
1669 }
1670
1671 return (CHARIDX(state_idx));
1672 }
1673
1674 /*
1675 * kdstart:
1676 *
1677 * This function does the general processing of characters and other
1678 * operations for the device driver. The device independent portion of
1679 * the tty driver calls this routine (it's setup in kdinit) with a
1680 * given command. That command is then processed, and control is passed
1681 * back to the kernel.
1682 *
1683 * input: tty pointer 'tp', and command to execute 'cmd'
1684 *
1685 * output: command is executed
1686 *
1687 * Entered and left at spltty. Drops priority to spl0 to display character.
1688 * ASSUMES that it is never called from interrupt-driven code.
1689 */
1690 kdstart(tp)
1691 struct tty *tp;
1692 {
1693 int o_pri;
1694 int ch;
1695 unsigned char c;
1696
1697 if (tp->t_state & TS_TTSTOP)
1698 return;
1699 for ( ; ; ) {
1700 tp->t_state &= ~TS_BUSY;
1701 if (tp->t_state & TS_TTSTOP)
1702 break;
1703 if ((tp->t_outq.c_cc <= 0) || (ch = getc(&tp->t_outq)) == -1)
1704 break;
1705 c = ch;
1706
1707 /*
1708 * Drop priority for long screen updates. ttstart() calls us at
1709 * spltty.
1710 */
1711 o_pri = splsoftclock(); /* block timeout */
1712
1713 if (c == (K_ESC)) {
1714 if (esc_spt == esc_seq) {
1715 *(esc_spt++)=(K_ESC);
1716 *(esc_spt) = '\0';
1717 } else {
1718 kd_putc((K_ESC));
1719 esc_spt = esc_seq;
1720 }
1721 } else {
1722 if (esc_spt - esc_seq) {
1723 if (esc_spt - esc_seq > K_MAXESC - 1)
1724 esc_spt = esc_seq;
1725 else {
1726 *(esc_spt++) = c;
1727 *(esc_spt) = '\0';
1728 kd_parseesc();
1729 }
1730 } else {
1731 kd_putc(c);
1732 }
1733 }
1734 splx(o_pri);
1735 }
1736 if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
1737 #ifdef MACH_KERNEL
1738 tt_write_wakeup(tp);
1739 #else MACH_KERNEL
1740 if (tp->t_state & TS_ASLEEP) {
1741 tp->t_state &= ~TS_ASLEEP;
1742 wakeup((caddr_t)&tp->t_outq);
1743 }
1744 if (tp->t_wsel) {
1745 selwakeup(tp->t_wsel, tp->t_state&TS_WCOLL);
1746 tp->t_wsel = 0;
1747 tp->t_state &= ~TS_WCOLL;
1748 }
1749 #endif MACH_KERNEL
1750 }
1751 }
1752
1753 #ifdef MACH_KERNEL
1754 /*ARGSUSED*/
1755 kdstop(tp, flags)
1756 register struct tty *tp;
1757 int flags;
1758 {
1759 /*
1760 * do nothing - all characters are output by one call to
1761 * kdstart.
1762 */
1763 }
1764 #endif MACH_KERNEL
1765
1766 /*
1767 * kdinit:
1768 *
1769 * This code initializes the structures and sets up the port registers
1770 * for the console driver.
1771 *
1772 * Each bitmap-based graphics card is likely to require a unique
1773 * way to determine the card's presence. The driver runs through
1774 * each "special" card that it knows about and uses the first one
1775 * that it finds. If it doesn't find any, it assumes that an
1776 * EGA-like card is installed.
1777 *
1778 * input : None. Interrupts are assumed to be disabled
1779 * output : Driver is initialized
1780 *
1781 */
1782 kdinit()
1783 {
1784 void kd_xga_init();
1785 unsigned char k_comm; /* keyboard command byte */
1786
1787 if (kd_initialized)
1788 return;
1789
1790 esc_spt = esc_seq;
1791 kd_attr = KA_NORMAL;
1792
1793 /*
1794 * board specific initialization: set up globals and kd_dxxx
1795 * pointers, and synch displayed cursor with logical cursor.
1796 */
1797 if (!evc1init())
1798 if (blit_present())
1799 blit_init();
1800 else
1801 kd_xga_init();
1802
1803 /* get rid of any garbage in output buffer */
1804 if (inb(K_STATUS) & K_OBUF_FUL)
1805 (void)inb(K_RDWR);
1806
1807 cnsetleds(kd_state = KS_NORMAL);
1808
1809 kd_sendcmd(KC_CMD_READ); /* ask for the ctlr command byte */
1810 k_comm = kd_getdata();
1811 k_comm &= ~K_CB_DISBLE; /* clear keyboard disable bit */
1812 k_comm |= K_CB_ENBLIRQ; /* enable interrupt */
1813 kd_sendcmd(KC_CMD_WRITE); /* write new ctlr command byte */
1814 kd_senddata(k_comm);
1815 kd_initialized = TRUE;
1816
1817 return;
1818 }
1819
1820 /*
1821 * kd_belloff:
1822 *
1823 * This routine shuts the bell off, by sending the appropriate code
1824 * to the speaker port.
1825 *
1826 * input : None
1827 * output : bell is turned off
1828 *
1829 */
1830 kd_belloff()
1831 {
1832 unsigned char status;
1833
1834 status = (inb(K_PORTB) & ~(K_SPKRDATA | K_ENABLETMR2));
1835 outb(K_PORTB, status);
1836 return;
1837 }
1838
1839
1840 /*
1841 * kd_bellon:
1842 *
1843 * This routine turns the bell on.
1844 *
1845 * input : None
1846 * output : bell is turned on
1847 *
1848 */
1849 kd_bellon()
1850 {
1851 unsigned char status;
1852
1853 /* program timer 2 */
1854 outb(K_TMRCTL, K_SELTMR2 | K_RDLDTWORD | K_TSQRWAVE | K_TBINARY);
1855 outb(K_TMR2, 1500 & 0xff); /* LSB */
1856 outb(K_TMR2, (int)1500 >> 8); /* MSB */
1857
1858 /* start speaker - why must we turn on K_SPKRDATA? */
1859 status = (inb(K_PORTB)| K_ENABLETMR2 | K_SPKRDATA);
1860 outb(K_PORTB, status);
1861 return;
1862 }
1863
1864 /*
1865 *
1866 * Function kd_putc():
1867 *
1868 * This function simply puts a character on the screen. It does some
1869 * special processing for linefeed, carriage return, backspace and
1870 * the bell.
1871 *
1872 * input : character to be displayed
1873 * output : character is displayed, or some action is taken
1874 *
1875 */
1876 int sit_for_0 = 1;
1877
1878 kd_putc(ch)
1879 u_char ch;
1880 {
1881 if ((!ch) && sit_for_0)
1882 return;
1883
1884 switch (ch) {
1885 case ((K_LF)):
1886 kd_down();
1887 break;
1888 case ((K_CR)):
1889 kd_cr();
1890 break;
1891 case ((K_BS)):
1892 kd_left();
1893 break;
1894 case ((K_BEL)):
1895 /*
1896 * Similar problem to K_BS here (behavior might depend
1897 * on tty setting). Also check LF and CR.
1898 */
1899 kd_bellon();
1900 timeout(kd_belloff, 0, hz/8 );
1901 break;
1902 default:
1903 (*kd_dput)(kd_curpos, ch, kd_attr);
1904 kd_right();
1905 break;
1906 }
1907 return;
1908 }
1909
1910
1911 /*
1912 * kd_setpos:
1913 *
1914 * This function sets the software and hardware cursor position
1915 * on the screen, using device-specific code to actually move and
1916 * display the cursor.
1917 *
1918 * input : position on (or off) screen to move the cursor to
1919 * output : cursor position is updated, screen has been scrolled
1920 * if necessary to bring cursor position back onto
1921 * screen.
1922 *
1923 */
1924 kd_setpos(newpos)
1925 csrpos_t newpos;
1926 {
1927 if (newpos > ONE_PAGE) {
1928 kd_scrollup();
1929 newpos = BOTTOM_LINE;
1930 }
1931 if (newpos < 0) {
1932 kd_scrolldn();
1933 newpos = 0;
1934 }
1935
1936 (*kd_dsetcursor)(newpos);
1937 }
1938
1939
1940 /*
1941 * kd_scrollup:
1942 *
1943 * This function scrolls the screen up one line using a DMA memory
1944 * copy.
1945 *
1946 * input : None
1947 * output : lines on screen appear to be shifted up one line
1948 *
1949 */
1950 kd_scrollup()
1951 {
1952 csrpos_t to;
1953 csrpos_t from;
1954 int count;
1955
1956 /* scroll up */
1957 to = 0;
1958 from = ONE_LINE;
1959 count = (ONE_PAGE - ONE_LINE)/ONE_SPACE;
1960 (*kd_dmvup)(from, to, count);
1961
1962 /* clear bottom line */
1963 to = BOTTOM_LINE;
1964 count = ONE_LINE/ONE_SPACE;
1965 (*kd_dclear)(to, count, kd_attr);
1966 return;
1967 }
1968
1969
1970 /*
1971 * kd_scrolldn:
1972 *
1973 * Scrolls the characters on the screen down one line.
1974 *
1975 * input : None
1976 * output : Lines on screen appear to be moved down one line
1977 *
1978 */
1979 kd_scrolldn()
1980 {
1981 csrpos_t to;
1982 csrpos_t from;
1983 int count;
1984
1985 /* move down */
1986 to = ONE_PAGE - ONE_SPACE;
1987 from = ONE_PAGE - ONE_LINE - ONE_SPACE;
1988 count = (ONE_PAGE - ONE_LINE) / ONE_SPACE;
1989 (*kd_dmvdown)(from, to, count);
1990
1991 /* clear top line */
1992 to = 0;
1993 count = ONE_LINE/ONE_SPACE;
1994 (*kd_dclear)(to, count, kd_attr);
1995 return;
1996
1997 }
1998
1999
2000 /*
2001 * kd_parseesc:
2002 *
2003 * This routine begins the parsing of an escape sequence. It uses the
2004 * escape sequence array and the escape spot pointer to handle
2005 * asynchronous parsing of escape sequences.
2006 *
2007 * input : String of characters prepended by an escape
2008 * output : Appropriate actions are taken depending on the string as
2009 * defined by the ansi terminal specification
2010 *
2011 */
2012 kd_parseesc()
2013 {
2014 u_char *escp;
2015
2016 escp = esc_seq + 1; /* point to char following ESC */
2017 switch(*(escp)) {
2018 case 'c':
2019 kd_cls();
2020 kd_home();
2021 esc_spt = esc_seq; /* reset spot in ESC sequence */
2022 break;
2023 case '[':
2024 escp++;
2025 kd_parserest(escp);
2026 break;
2027 case '\0':
2028 break; /* not enough info yet */
2029 default:
2030 kd_putc(*escp);
2031 esc_spt = esc_seq; /* inv sequence char, reset */
2032 break;
2033 }
2034 return;
2035
2036 }
2037
2038
2039 /*
2040 * kd_parserest:
2041 *
2042 * This function will complete the parsing of an escape sequence and
2043 * call the appropriate support routine if it matches a character. This
2044 * function could be greatly improved by using a function jump table, and
2045 * removing this bulky switch statement.
2046 *
2047 * input : An string
2048 * output : Appropriate action based on whether the string matches a
2049 * sequence acceptable to the ansi terminal specification
2050 *
2051 */
2052 kd_parserest(cp)
2053 u_char *cp;
2054 {
2055 int number;
2056 csrpos_t newpos;
2057
2058 cp += kd_atoi(cp, &number);
2059 switch(*cp) {
2060 case 'm':
2061 switch(number) {
2062 case DEFAULT:
2063 case 0:
2064 kd_attr = KA_NORMAL;
2065 break;
2066 case 7:
2067 kd_attr = KA_REVERSE;
2068 break;
2069 default:
2070 kd_attr = KA_NORMAL;
2071 break;
2072 }
2073 esc_spt = esc_seq;
2074 break;
2075 case '@':
2076 if (number == DEFAULT)
2077 kd_insch(1);
2078 else
2079 kd_insch(number);
2080 esc_spt = esc_seq;
2081 break;
2082 case 'H':
2083 kd_home();
2084 esc_spt = esc_seq;
2085 break;
2086 case 'A':
2087 if (number == DEFAULT)
2088 kd_up();
2089 else
2090 while (number--)
2091 kd_up();
2092 esc_spt = esc_seq;
2093 break;
2094 case 'B':
2095 if (number == DEFAULT)
2096 kd_down();
2097 else
2098 while (number--)
2099 kd_down();
2100 esc_spt = esc_seq;
2101 break;
2102 case 'C':
2103 if (number == DEFAULT)
2104 kd_right();
2105 else
2106 while (number--)
2107 kd_right();
2108 esc_spt = esc_seq;
2109 break;
2110 case 'D':
2111 if (number == DEFAULT)
2112 kd_left();
2113 else
2114 while (number--)
2115 kd_left();
2116 esc_spt = esc_seq;
2117 break;
2118 case 'E':
2119 kd_cr();
2120 if (number == DEFAULT)
2121 kd_down();
2122 else
2123 while (number--)
2124 kd_down();
2125 esc_spt = esc_seq;
2126 break;
2127 case 'F':
2128 kd_cr();
2129 if (number == DEFAULT)
2130 kd_up();
2131 else
2132 while (number--)
2133 kd_up();
2134 esc_spt = esc_seq;
2135 break;
2136 case 'G':
2137 if (number == DEFAULT)
2138 number = 0;
2139 else
2140 if (number > 0)
2141 --number; /* because number is from 1 */
2142 kd_setpos(BEG_OF_LINE(kd_curpos) + number * ONE_SPACE);
2143 esc_spt = esc_seq;
2144 break;
2145 case ';':
2146 ++cp;
2147 if (*cp == '\0')
2148 break; /* not ready yet */
2149 if (number == DEFAULT)
2150 number = 0;
2151 else
2152 if (number > 0)
2153 --number; /* numbered from 1 */
2154 newpos = (number * ONE_LINE); /* setup row */
2155 cp += kd_atoi(cp, &number);
2156 if (*cp == '\0')
2157 break; /* not ready yet */
2158 if (number == DEFAULT)
2159 number = 0;
2160 else if (number > 0)
2161 number--;
2162 newpos += (number * ONE_SPACE); /* setup column */
2163 if (newpos < 0)
2164 newpos = 0; /* upper left */
2165 if (newpos > ONE_PAGE)
2166 newpos = (ONE_PAGE - ONE_SPACE);
2167 /* lower right */
2168 if (*cp == '\0')
2169 break; /* not ready yet */
2170 if (*cp == 'H') {
2171 kd_setpos(newpos);
2172 esc_spt = esc_seq; /* done, reset */
2173 }
2174 else
2175 esc_spt = esc_seq;
2176 break; /* done or not ready */
2177 case 'J':
2178 switch(number) {
2179 case DEFAULT:
2180 case 0:
2181 kd_cltobcur(); /* clears from current
2182 pos to bottom.
2183 */
2184 break;
2185 case 1:
2186 kd_cltopcur(); /* clears from top to
2187 current pos.
2188 */
2189 break;
2190 case 2:
2191 kd_cls();
2192 break;
2193 default:
2194 break;
2195 }
2196 esc_spt = esc_seq; /* reset it */
2197 break;
2198 case 'K':
2199 switch(number) {
2200 case DEFAULT:
2201 case 0:
2202 kd_cltoecur(); /* clears from current
2203 pos to eoln.
2204 */
2205 break;
2206 case 1:
2207 kd_clfrbcur(); /* clears from begin
2208 of line to current
2209 pos.
2210 */
2211 break;
2212 case 2:
2213 kd_eraseln(); /* clear entire line */
2214 break;
2215 default:
2216 break;
2217 }
2218 esc_spt = esc_seq;
2219 break;
2220 case 'L':
2221 if (number == DEFAULT)
2222 kd_insln(1);
2223 else
2224 kd_insln(number);
2225 esc_spt = esc_seq;
2226 break;
2227 case 'M':
2228 if (number == DEFAULT)
2229 kd_delln(1);
2230 else
2231 kd_delln(number);
2232 esc_spt = esc_seq;
2233 break;
2234 case 'P':
2235 if (number == DEFAULT)
2236 kd_delch(1);
2237 else
2238 kd_delch(number);
2239 esc_spt = esc_seq;
2240 break;
2241 case 'S':
2242 if (number == DEFAULT)
2243 kd_scrollup();
2244 else
2245 while (number--)
2246 kd_scrollup();
2247 esc_spt = esc_seq;
2248 break;
2249 case 'T':
2250 if (number == DEFAULT)
2251 kd_scrolldn();
2252 else
2253 while (number--)
2254 kd_scrolldn();
2255 esc_spt = esc_seq;
2256 break;
2257 case 'X':
2258 if (number == DEFAULT)
2259 kd_erase(1);
2260 else
2261 kd_erase(number);
2262 esc_spt = esc_seq;
2263 break;
2264 case '\0':
2265 break; /* not enough yet */
2266 default:
2267 kd_putc(*cp); /* show inv character */
2268 esc_spt = esc_seq; /* inv entry, reset */
2269 break;
2270 }
2271 return;
2272 }
2273
2274 /*
2275 * kd_atoi:
2276 *
2277 * This function converts an ascii string into an integer, and
2278 * returns DEFAULT if no integer was found. Note that this is why
2279 * we don't use the regular atio(), because ZERO is ZERO and not
2280 * the DEFAULT in all cases.
2281 *
2282 * input : string
2283 * output : a number or possibly DEFAULT, and the count of characters
2284 * consumed by the conversion
2285 *
2286 */
2287 int
2288 kd_atoi(cp, nump)
2289 u_char *cp;
2290 int *nump;
2291 {
2292 int number;
2293 u_char *original;
2294
2295 original = cp;
2296 for (number = 0; ('' <= *cp) && (*cp <= '9'); cp++)
2297 number = (number * 10) + (*cp - '');
2298 if (original == cp)
2299 *nump = DEFAULT;
2300 else
2301 *nump = number;
2302 return(cp - original);
2303 }
2304
2305
2306 /*
2307 * kd_cls:
2308 *
2309 * This function clears the screen with spaces and the current attribute.
2310 *
2311 * input : None
2312 * output : Screen is cleared
2313 *
2314 */
2315 kd_cls()
2316 {
2317 (*kd_dclear)(0, ONE_PAGE/ONE_SPACE, kd_attr);
2318 return;
2319 }
2320
2321
2322 /*
2323 * kd_home:
2324 *
2325 * This function will move the cursor to the home position on the screen,
2326 * as well as set the internal cursor position (kd_curpos) to home.
2327 *
2328 * input : None
2329 * output : Cursor position is moved
2330 *
2331 */
2332 kd_home()
2333 {
2334 kd_setpos(0);
2335 return;
2336 }
2337
2338
2339 /*
2340 * kd_up:
2341 *
2342 * This function moves the cursor up one line position.
2343 *
2344 * input : None
2345 * output : Cursor moves up one line, or screen is scrolled
2346 *
2347 */
2348 kd_up()
2349 {
2350 if (kd_curpos < ONE_LINE)
2351 kd_scrolldn();
2352 else
2353 kd_setpos(kd_curpos - ONE_LINE);
2354 return;
2355 }
2356
2357
2358 /*
2359 * kd_down:
2360 *
2361 * This function moves the cursor down one line position.
2362 *
2363 * input : None
2364 * output : Cursor moves down one line or the screen is scrolled
2365 *
2366 */
2367 kd_down()
2368 {
2369 if (kd_curpos >= (ONE_PAGE - ONE_LINE))
2370 kd_scrollup();
2371 else
2372 kd_setpos(kd_curpos + ONE_LINE);
2373 return;
2374 }
2375
2376
2377 /*
2378 * kd_right:
2379 *
2380 * This function moves the cursor one position to the right.
2381 *
2382 * input : None
2383 * output : Cursor moves one position to the right
2384 *
2385 */
2386 kd_right()
2387 {
2388 if (kd_curpos < (ONE_PAGE - ONE_SPACE))
2389 kd_setpos(kd_curpos + ONE_SPACE);
2390 else {
2391 kd_scrollup();
2392 kd_setpos(BEG_OF_LINE(kd_curpos));
2393 }
2394 return;
2395 }
2396
2397
2398 /*
2399 * kd_left:
2400 *
2401 * This function moves the cursor one position to the left.
2402 *
2403 * input : None
2404 * output : Cursor moves one position to the left
2405 *
2406 */
2407 kd_left()
2408 {
2409 if (0 < kd_curpos)
2410 kd_setpos(kd_curpos - ONE_SPACE);
2411 return;
2412 }
2413
2414
2415 /*
2416 * kd_cr:
2417 *
2418 * This function moves the cursor to the beginning of the current
2419 * line.
2420 *
2421 * input : None
2422 * output : Cursor moves to the beginning of the current line
2423 *
2424 */
2425 kd_cr()
2426 {
2427 kd_setpos(BEG_OF_LINE(kd_curpos));
2428 return;
2429 }
2430
2431
2432 /*
2433 * kd_cltobcur:
2434 *
2435 * This function clears from the current cursor position to the bottom
2436 * of the screen.
2437 *
2438 * input : None
2439 * output : Screen is cleared from current cursor postion to bottom
2440 *
2441 */
2442 kd_cltobcur()
2443 {
2444 csrpos_t start;
2445 int count;
2446
2447 start = kd_curpos;
2448 count = (ONE_PAGE - kd_curpos)/ONE_SPACE;
2449 (*kd_dclear)(start, count, kd_attr);
2450 return;
2451 }
2452
2453
2454 /*
2455 * kd_cltopcur:
2456 *
2457 * This function clears from the current cursor position to the top
2458 * of the screen.
2459 *
2460 * input : None
2461 * output : Screen is cleared from current cursor postion to top
2462 *
2463 */
2464 kd_cltopcur()
2465 {
2466 int count;
2467
2468 count = (kd_curpos + ONE_SPACE) / ONE_SPACE;
2469 (*kd_dclear)(0, count, kd_attr);
2470 return;
2471 }
2472
2473
2474 /*
2475 * kd_cltoecur:
2476 *
2477 * This function clears from the current cursor position to eoln.
2478 *
2479 * input : None
2480 * output : Line is cleared from current cursor position to eoln
2481 *
2482 */
2483 kd_cltoecur()
2484 {
2485 csrpos_t i;
2486 csrpos_t hold;
2487
2488 hold = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2489 for (i = kd_curpos; i < hold; i += ONE_SPACE) {
2490 (*kd_dput)(i, K_SPACE, kd_attr);
2491 }
2492 }
2493
2494
2495 /*
2496 * kd_clfrbcur:
2497 *
2498 * This function clears from the beginning of the line to the current
2499 * cursor position.
2500 *
2501 * input : None
2502 * output : Line is cleared from beginning to current position
2503 *
2504 */
2505 kd_clfrbcur()
2506 {
2507 csrpos_t i;
2508
2509 for (i = BEG_OF_LINE(kd_curpos); i <= kd_curpos; i += ONE_SPACE) {
2510 (*kd_dput)(i, K_SPACE, kd_attr);
2511 }
2512 }
2513
2514
2515 /*
2516 * kd_delln:
2517 *
2518 * This function deletes 'number' lines on the screen by effectively
2519 * scrolling the lines up and replacing the old lines with spaces.
2520 *
2521 * input : number of lines to delete
2522 * output : lines appear to be deleted
2523 *
2524 */
2525 kd_delln(number)
2526 int number;
2527 {
2528 csrpos_t to;
2529 csrpos_t from;
2530 int delbytes; /* num of bytes to delete */
2531 int count; /* num of words to move or fill */
2532
2533 if (number <= 0)
2534 return;
2535
2536 delbytes = number * ONE_LINE;
2537 to = BEG_OF_LINE(kd_curpos);
2538 if (to + delbytes >= ONE_PAGE)
2539 delbytes = ONE_PAGE - to;
2540 if (to + delbytes < ONE_PAGE) {
2541 from = to + delbytes;
2542 count = (ONE_PAGE - from) / ONE_SPACE;
2543 (*kd_dmvup)(from, to, count);
2544 }
2545
2546 to = ONE_PAGE - delbytes;
2547 count = delbytes / ONE_SPACE;
2548 (*kd_dclear)(to, count, kd_attr);
2549 return;
2550 }
2551
2552
2553 /*
2554 * kd_insln:
2555 *
2556 * This function inserts a line above the current one by
2557 * scrolling the current line and all the lines below it down.
2558 *
2559 * input : number of lines to insert
2560 * output : New lines appear to be inserted
2561 *
2562 */
2563 kd_insln(number)
2564 int number;
2565 {
2566 csrpos_t to;
2567 csrpos_t from;
2568 int count;
2569 csrpos_t top; /* top of block to be moved */
2570 int insbytes; /* num of bytes inserted */
2571
2572 if (number <= 0)
2573 return;
2574
2575 top = BEG_OF_LINE(kd_curpos);
2576 insbytes = number * ONE_LINE;
2577 if (top + insbytes > ONE_PAGE)
2578 insbytes = ONE_PAGE - top;
2579 to = ONE_PAGE - ONE_SPACE;
2580 from = to - insbytes;
2581 if (from > top) {
2582 count = (from - top + ONE_SPACE) / ONE_SPACE;
2583 (*kd_dmvdown)(from, to, count);
2584 }
2585
2586 count = insbytes / ONE_SPACE;
2587 (*kd_dclear)(top, count, kd_attr);
2588 return;
2589 }
2590
2591
2592 /*
2593 * kd_delch:
2594 *
2595 * This function deletes a number of characters from the current
2596 * position in the line.
2597 *
2598 * input : number of characters to delete
2599 * output : characters appear to be deleted
2600 *
2601 */
2602 kd_delch(number)
2603 int number;
2604 {
2605 int count; /* num words moved/filled */
2606 int delbytes; /* bytes to delete */
2607 register csrpos_t to;
2608 csrpos_t from;
2609 csrpos_t nextline; /* start of next line */
2610
2611 if (number <= 0)
2612 return;
2613
2614 nextline = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2615 delbytes = number * ONE_SPACE;
2616 if (kd_curpos + delbytes > nextline)
2617 delbytes = nextline - kd_curpos;
2618 if (kd_curpos + delbytes < nextline) {
2619 from = kd_curpos + delbytes;
2620 to = kd_curpos;
2621 count = (nextline - from) / ONE_SPACE;
2622 (*kd_dmvup)(from, to, count);
2623 }
2624
2625 to = nextline - delbytes;
2626 count = delbytes / ONE_SPACE;
2627 (*kd_dclear)(to, count, kd_attr);
2628 return;
2629
2630 }
2631
2632
2633 /*
2634 * kd_erase:
2635 *
2636 * This function overwrites characters with a space starting with the
2637 * current cursor position and ending in number spaces away.
2638 *
2639 * input : number of characters to erase
2640 * output : characters appear to be blanked or erased
2641 *
2642 */
2643 kd_erase(number)
2644 int number;
2645 {
2646 csrpos_t i;
2647 csrpos_t stop;
2648
2649 stop = kd_curpos + (ONE_SPACE * number);
2650 if (stop > BEG_OF_LINE(kd_curpos) + ONE_LINE)
2651 stop = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2652 for (i = kd_curpos; i < stop; i += ONE_SPACE) {
2653 (*kd_dput)(i, K_SPACE, kd_attr);
2654 }
2655 return;
2656 }
2657
2658
2659 /*
2660 * kd_eraseln:
2661 *
2662 * This function erases the current line with spaces.
2663 *
2664 * input : None
2665 * output : Current line is erased
2666 *
2667 */
2668 kd_eraseln()
2669 {
2670 csrpos_t i;
2671 csrpos_t stop;
2672
2673 stop = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2674 for (i = BEG_OF_LINE(kd_curpos); i < stop; i += ONE_SPACE) {
2675 (*kd_dput)(i, K_SPACE, kd_attr);
2676 }
2677 return;
2678 }
2679
2680
2681 /*
2682 * kd_insch:
2683 *
2684 * This function inserts a blank at the current cursor position
2685 * and moves all other characters on the line over.
2686 *
2687 * input : number of blanks to insert
2688 * output : Blanks are inserted at cursor position
2689 *
2690 */
2691 kd_insch(number)
2692 int number;
2693 {
2694 csrpos_t to;
2695 csrpos_t from;
2696 int count;
2697 csrpos_t nextline; /* start of next line */
2698 int insbytes; /* num of bytes inserted */
2699
2700 if (number <= 0)
2701 return;
2702
2703 nextline = BEG_OF_LINE(kd_curpos) + ONE_LINE;
2704 insbytes = number * ONE_SPACE;
2705 if (kd_curpos + insbytes > nextline)
2706 insbytes = nextline - kd_curpos;
2707
2708 to = nextline - ONE_SPACE;
2709 from = to - insbytes;
2710 if (from >= kd_curpos) {
2711 count = (from - kd_curpos + ONE_SPACE) / ONE_SPACE;
2712 (*kd_dmvdown)(from, to, count);
2713 }
2714
2715 count = insbytes / ONE_SPACE;
2716 (*kd_dclear)(kd_curpos, count, kd_attr);
2717 return;
2718 }
2719
2720
2721 /*
2722 * kd_isupper, kd_islower:
2723 *
2724 * Didn't want to include ctype.h because it brings in stdio.h, and
2725 * only want to see if the darn character is uppercase or lowercase.
2726 *
2727 * input : Character 'c'
2728 * output : isuuper gives TRUE if character is uppercase, islower
2729 * returns TRUE if character is lowercase
2730 *
2731 */
2732 kd_isupper(c)
2733 u_char c;
2734 {
2735 if (('A' <= c) && (c <= 'Z'))
2736 return(TRUE);
2737 return(FALSE);
2738 }
2739
2740 kd_islower(c)
2741 u_char c;
2742 {
2743 if (('a' <= c) && (c <= 'z'))
2744 return(TRUE);
2745 return(FALSE);
2746 }
2747
2748 /*
2749 * kd_senddata:
2750 *
2751 * This function sends a byte to the keyboard RDWR port, but
2752 * first waits until the input/output data buffer is clear before
2753 * sending the data. Note that this byte can be either data or a
2754 * keyboard command.
2755 *
2756 */
2757 kd_senddata(ch)
2758 unsigned char ch;
2759 {
2760 while (inb(K_STATUS) & K_IBUF_FUL)
2761 continue;
2762 outb(K_RDWR, ch);
2763 last_sent = ch;
2764 return;
2765 }
2766
2767 /*
2768 * kd_sendcmd:
2769 *
2770 * This function sends a command byte to the keyboard command
2771 * port, but first waits until the input/output data buffer is
2772 * clear before sending the data.
2773 *
2774 */
2775 kd_sendcmd(ch)
2776 unsigned char ch;
2777 {
2778 while (inb(K_STATUS) & K_IBUF_FUL)
2779 continue;
2780 outb(K_CMD, ch);
2781 return;
2782 }
2783
2784
2785 /*
2786 * kd_getdata:
2787 *
2788 * This function returns a data byte from the keyboard RDWR port,
2789 * after waiting until the port is flagged as having something to
2790 * read.
2791 */
2792 unsigned char
2793 kd_getdata()
2794 {
2795 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
2796 return(inb(K_RDWR));
2797 }
2798
2799 kd_cmdreg_read()
2800 {
2801 int ch = KC_CMD_READ;
2802
2803 while (inb(K_STATUS) & K_IBUF_FUL);
2804 outb(K_CMD, ch);
2805
2806 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
2807 return(inb(K_RDWR));
2808 }
2809
2810 kd_cmdreg_write(val)
2811 {
2812 int ch = KC_CMD_WRITE;
2813
2814 while (inb(K_STATUS) & K_IBUF_FUL);
2815 outb(K_CMD, ch);
2816
2817 while (inb(K_STATUS) & K_IBUF_FUL);
2818 outb(K_RDWR, val);
2819 }
2820
2821 int kd_mouse_write_no_ack = 0;
2822 kd_mouse_write(val)
2823 {
2824 int ch=0xd4; /* magic */
2825 int s = spltty();
2826 int ret = 0;
2827
2828 while (inb(K_STATUS) & K_IBUF_FUL);
2829 outb(K_CMD, ch);
2830
2831 while (inb(K_STATUS) & K_IBUF_FUL);
2832 outb(K_RDWR, val);
2833
2834 if (kd_mouse_write_no_ack) goto done;
2835
2836 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
2837 if ((inb(K_STATUS) & 0x20) == 0x20) {
2838 switch (ret = inb(K_RDWR)) {
2839 case 0xfa:
2840 break;
2841 case 0xfe:
2842 case 0xfc:
2843 default:
2844 printf("kd_mouse_write: saw %x for %x\n",
2845 ret, val);
2846 }
2847 } else { /* abort */
2848 printf("kd_mouse_write: sync error ??? on %x\n", val);
2849 }
2850
2851 done: splx(s);
2852 return ret;
2853 }
2854
2855 kd_mouse_read(no, buf)
2856 char *buf;
2857 {
2858 int s = spltty();
2859
2860 while (no-- > 0) {
2861 while ((inb(K_STATUS) & K_OBUF_FUL) == 0);
2862 /*
2863 * We may have seen a mouse event.
2864 */
2865 if ((inb(K_STATUS) & 0x20) == 0x20) {
2866 *buf++ = (u_char)inb(K_RDWR);
2867 } else /* abort */
2868 printf("kd_mouse_read: sync error\n");
2869 break;
2870 }
2871 splx(s);
2872 }
2873
2874 /*
2875 * set_kd_state:
2876 *
2877 * Set kd_state and update the keyboard status LEDs.
2878 */
2879
2880 set_kd_state(newstate)
2881 int newstate;
2882 {
2883 kd_state = newstate;
2884 kd_setleds1(state2leds(newstate));
2885 }
2886
2887 /*
2888 * state2leds:
2889 *
2890 * Return a byte containing LED settings for the keyboard, given
2891 * a state vector.
2892 */
2893 u_char
2894 state2leds(state)
2895 int state;
2896 {
2897 u_char result = 0;
2898
2899 if (state & KS_NLKED)
2900 result |= K_LED_NUMLK;
2901 if (state & KS_CLKED)
2902 result |= K_LED_CAPSLK;
2903 return(result);
2904 }
2905
2906 /*
2907 * kd_setleds[12]:
2908 *
2909 * Set the keyboard LEDs according to the given byte.
2910 */
2911 kd_setleds1(val)
2912 u_char val;
2913 {
2914 #ifndef PS2
2915 if (kd_ack != NOT_WAITING) {
2916 printf("kd_setleds1: unexpected state (%d)\n", kd_ack);
2917 return;
2918 }
2919
2920 kd_ack = SET_LEDS;
2921 kd_nextled = val;
2922 kd_senddata(K_CMD_LEDS);
2923 #endif PS2
2924 }
2925
2926 kd_setleds2()
2927 {
2928 #ifndef PS2
2929 kd_senddata(kd_nextled);
2930 #endif PS2
2931 }
2932
2933
2934 /*
2935 * cnsetleds:
2936 *
2937 * like kd_setleds[12], but not interrupt-based.
2938 * Currently disabled because cngetc ignores caps lock and num
2939 * lock anyway.
2940 */
2941 cnsetleds(val)
2942 u_char val;
2943 {
2944 kd_senddata(K_CMD_LEDS);
2945 (void)kd_getdata(); /* XXX - assume is ACK */
2946 kd_senddata(val);
2947 (void)kd_getdata(); /* XXX - assume is ACK */
2948 }
2949
2950 kdreboot()
2951 {
2952 #if 1
2953 (*kd_dreset)();
2954 kd_sendcmd(0xFE); /* XXX - magic # */
2955 #else
2956 #ifdef PS2
2957 /*
2958 * Tell the BIOS not to clear and test memory.
2959 */
2960 *(unsigned short *)phystokv(0x472) = 0x1234;
2961
2962 #if MACH_RDB
2963 db_reboot();
2964 #endif MACH_RDB
2965 #else
2966 (*kd_dreset)();
2967 kd_sendcmd(0xFE); /* XXX - magic # */
2968 #endif PS2
2969 #endif
2970 }
2971
2972 #ifdef RVB_KBD_MOUSE
2973 kd_kbd_magic(scancode)
2974 {
2975 struct mouse_motion moved = {0, 0};
2976
2977 if (kd_kbd_mouse == 2)
2978 printf("sc = %x\n", scancode);
2979
2980 switch (scancode) {
2981 /* f1 f2 f3 */
2982 case 0x3b:
2983 mouse_button(MOUSE_LEFT, (kd_kbd_magic_buttons & 1));
2984 kd_kbd_magic_buttons ^= 1;
2985 break;
2986 case 0x3c:
2987 mouse_button(MOUSE_MIDDLE, (kd_kbd_magic_buttons & 2)>>1);
2988 kd_kbd_magic_buttons ^= 2;
2989 break;
2990 case 0x3d:
2991 mouse_button(MOUSE_RIGHT, (kd_kbd_magic_buttons & 4)>>2);
2992 kd_kbd_magic_buttons ^= 4;
2993 break;
2994
2995 /* right left up down */
2996 case 0x4d:
2997 moved.mm_deltaX = kd_kbd_magic_scale;
2998 mouse_moved(moved);
2999 break;
3000 case 0x4b:
3001 moved.mm_deltaX = -kd_kbd_magic_scale;
3002 mouse_moved(moved);
3003 break;
3004 case 0x48:
3005 moved.mm_deltaY = kd_kbd_magic_scale;
3006 mouse_moved(moved);
3007 break;
3008 case 0x50:
3009 moved.mm_deltaY = -kd_kbd_magic_scale;
3010 mouse_moved(moved);
3011 break;
3012 #ifdef notyet
3013 /* f5 f6 f7 f8 */
3014 case 0x3f:
3015 moved.mm_deltaX = kd_kbd_magic_scale;
3016 mouse_moved(moved);
3017 break;
3018 case 0x40:
3019 moved.mm_deltaX = -kd_kbd_magic_scale;
3020 mouse_moved(moved);
3021 break;
3022 case 0x41:
3023 moved.mm_deltaY = kd_kbd_magic_scale;
3024 mouse_moved(moved);
3025 break;
3026 case 0x42:
3027 moved.mm_deltaY = -kd_kbd_magic_scale;
3028 mouse_moved(moved);
3029 break;
3030
3031 /* f9 f10 f11 f12 */
3032 case 0x43:
3033 moved.mm_deltaX = kd_kbd_magic_scale;
3034 moved.mm_deltaY = kd_kbd_magic_scale;
3035 mouse_moved(moved);
3036 break;
3037 case 0x44:
3038 moved.mm_deltaX = -kd_kbd_magic_scale;
3039 moved.mm_deltaY = kd_kbd_magic_scale;
3040 mouse_moved(moved);
3041 break;
3042 case 0x57:
3043 moved.mm_deltaX = kd_kbd_magic_scale;
3044 moved.mm_deltaY = -kd_kbd_magic_scale;
3045 mouse_moved(moved);
3046 break;
3047 case 0x58:
3048 moved.mm_deltaX = -kd_kbd_magic_scale;
3049 moved.mm_deltaY = -kd_kbd_magic_scale;
3050 mouse_moved(moved);
3051 break;
3052 #endif notyet
3053 /* home pageup end pagedown */
3054 case 0x47:
3055 moved.mm_deltaX = -kd_kbd_magic_scale;
3056 moved.mm_deltaY = kd_kbd_magic_scale;
3057 mouse_moved(moved);
3058 break;
3059 case 0x49:
3060 moved.mm_deltaX = kd_kbd_magic_scale;
3061 moved.mm_deltaY = kd_kbd_magic_scale;
3062 mouse_moved(moved);
3063 break;
3064 case 0x4f:
3065 moved.mm_deltaX = -kd_kbd_magic_scale;
3066 moved.mm_deltaY = -kd_kbd_magic_scale;
3067 mouse_moved(moved);
3068 break;
3069 case 0x51:
3070 moved.mm_deltaX = kd_kbd_magic_scale;
3071 moved.mm_deltaY = -kd_kbd_magic_scale;
3072 mouse_moved(moved);
3073 break;
3074
3075 default:
3076 return 0;
3077 }
3078 return 1;
3079 }
3080 #endif /* RVB_KBD_MOUSE */
3081
3082
3083
3084 /*
3085 * Code specific to EGA/CGA/VGA boards. This code relies on the fact
3086 * that the "slam" functions take a word count and ONE_SPACE takes up
3087 * 1 word.
3088 */
3089 #define SLAMBPW 2 /* bytes per word for "slam" fcns */
3090
3091
3092 /*
3093 * kd_xga_init:
3094 *
3095 * Initialization specific to character-based graphics adapters.
3096 */
3097 void
3098 kd_xga_init()
3099 {
3100 csrpos_t xga_getpos();
3101 unsigned char screen;
3102
3103 #ifdef PS2
3104 vid_start = (u_char *)phystokv(EGA_START);
3105 screen = ((*vid_start == 0xff) ? CM_MONO_80 : CM_EGA_VGA);
3106 #else
3107 outb(CMOS_ADDR, CMOS_EB);
3108 screen = inb(CMOS_DATA) & CM_SCRMSK;
3109 #endif PS2
3110 switch(screen) {
3111 case CM_EGA_VGA:
3112 /*
3113 * Here we'll want to query to bios on the card
3114 * itself, because then we can figure out what
3115 * type we have exactly. At this point we only
3116 * know that the card is NOT CGA or MONO. For
3117 * now, however, we assume backwards compatability
3118 * with 0xb8000 as the starting screen offset
3119 * memory location for these cards.
3120 *
3121 */
3122
3123 vid_start = (u_char *)phystokv(EGA_START);
3124 kd_index_reg = EGA_IDX_REG;
3125 kd_io_reg = EGA_IO_REG;
3126 kd_lines = 25;
3127 kd_cols = 80;
3128 kd_bitmap_start = 0xa0000; /* XXX - magic numbers */
3129 { /* XXX - is there a cleaner way to do this? */
3130 char *addr = (char *)phystokv(kd_bitmap_start);
3131 int i;
3132 for (i = 0; i < 200; i++)
3133 addr[i] = 0x00;
3134 }
3135 break;
3136 case CM_CGA_40:
3137 vid_start = (u_char *)phystokv(CGA_START);
3138 kd_index_reg = CGA_IDX_REG;
3139 kd_io_reg = CGA_IO_REG;
3140 kd_lines = 25;
3141 kd_cols = 40;
3142 break;
3143 case CM_CGA_80:
3144 vid_start = (u_char *)phystokv(CGA_START);
3145 kd_index_reg = CGA_IDX_REG;
3146 kd_io_reg = CGA_IO_REG;
3147 kd_lines = 25;
3148 kd_cols = 80;
3149 break;
3150 case CM_MONO_80:
3151 vid_start = (u_char *)phystokv(MONO_START);
3152 kd_index_reg = MONO_IDX_REG;
3153 kd_io_reg = MONO_IO_REG;
3154 kd_lines = 25;
3155 kd_cols = 80;
3156 break;
3157 default:
3158 printf("kd: unknown screen type, defaulting to EGA\n");
3159 }
3160
3161 kd_setpos(xga_getpos());
3162 }
3163
3164
3165 /*
3166 * xga_getpos:
3167 *
3168 * This function returns the current hardware cursor position on the
3169 * screen, scaled for compatibility with kd_curpos.
3170 *
3171 * input : None
3172 * output : returns the value of cursor position on screen
3173 *
3174 */
3175 csrpos_t
3176 xga_getpos()
3177
3178 {
3179 unsigned char low;
3180 unsigned char high;
3181 short pos;
3182
3183 outb(kd_index_reg, C_HIGH);
3184 high = inb(kd_io_reg);
3185 outb(kd_index_reg, C_LOW);
3186 low = inb(kd_io_reg);
3187 pos = (0xff&low) + ((unsigned short)high<<8);
3188
3189 return(ONE_SPACE * (csrpos_t)pos);
3190 }
3191
3192
3193 /*
3194 * charput:
3195 *
3196 * Put attributed character for EGA/CGA/etc.
3197 */
3198 static void
3199 charput(pos, ch, chattr)
3200 csrpos_t pos; /* where to put it */
3201 char ch; /* the character */
3202 char chattr; /* its attribute */
3203 {
3204 *(vid_start + pos) = ch;
3205 *(vid_start + pos + 1) = chattr;
3206 }
3207
3208
3209 /*
3210 * charsetcursor:
3211 *
3212 * Set hardware cursor position for EGA/CGA/etc.
3213 */
3214 static void
3215 charsetcursor(newpos)
3216 csrpos_t newpos;
3217 {
3218 short curpos; /* position, not scaled for attribute byte */
3219
3220 curpos = newpos / ONE_SPACE;
3221 outb(kd_index_reg, C_HIGH);
3222 outb(kd_io_reg, (u_char)(curpos>>8));
3223 outb(kd_index_reg, C_LOW);
3224 outb(kd_io_reg, (u_char)(curpos&0xff));
3225
3226 kd_curpos = newpos;
3227 }
3228
3229
3230 /*
3231 * charmvup:
3232 *
3233 * Block move up for EGA/CGA/etc.
3234 */
3235 static void
3236 charmvup(from, to, count)
3237 csrpos_t from, to;
3238 int count;
3239 {
3240 kd_slmscu(vid_start+from, vid_start+to, count);
3241 }
3242
3243
3244 /*
3245 * charmvdown:
3246 *
3247 * Block move down for EGA/CGA/etc.
3248 */
3249 static void
3250 charmvdown(from, to, count)
3251 csrpos_t from, to;
3252 int count;
3253 {
3254 kd_slmscd(vid_start+from, vid_start+to, count);
3255 }
3256
3257
3258 /*
3259 * charclear:
3260 *
3261 * Fast clear for CGA/EGA/etc.
3262 */
3263 static void
3264 charclear(to, count, chattr)
3265 csrpos_t to;
3266 int count;
3267 char chattr;
3268 {
3269 kd_slmwd(vid_start+to, count, ((unsigned short)chattr<<8)+K_SPACE);
3270 }
3271
3272
3273 /*
3274 * kd_noopreset:
3275 *
3276 * No-op reset routine for kd_dreset.
3277 */
3278 static void
3279 kd_noopreset()
3280 {
3281 }
3282
3283
3284
3285 #ifdef BIT_BLIT
3286 /*
3287 * Generic routines for bitmap devices (i.e., assume no hardware
3288 * assist). Assumes a simple byte ordering (i.e., a byte at a lower
3289 * address is to the left of the byte at the next higher address).
3290 * For the 82786, this works anyway if the characters are 2 bytes
3291 * wide. (more bubble gum and paper clips.)
3292 *
3293 * See the comments above about SLAMBPW.
3294 */
3295
3296 void bmpch2bit(), bmppaintcsr();
3297 u_char *bit2fbptr();
3298
3299
3300 /*
3301 * bmpput: Copy a character from the font to the frame buffer.
3302 */
3303
3304 void
3305 bmpput(pos, ch, chattr)
3306 csrpos_t pos;
3307 char ch, chattr;
3308 {
3309 short xbit, ybit; /* u/l corner of char pos */
3310 register u_char *to, *from;
3311 register short i, j;
3312 u_char mask = (chattr == KA_REVERSE ? 0xff : 0);
3313
3314 if ((u_char)ch >= chars_in_font)
3315 ch = K_QUES;
3316
3317 bmpch2bit(pos, &xbit, &ybit);
3318 to = bit2fbptr(xbit, ybit);
3319 from = font_start + ch * char_byte_width;
3320 for (i = 0; i < char_height; ++i) {
3321 for (j = 0; j < char_byte_width; ++j)
3322 *(to+j) = *(from+j) ^ mask;
3323 to += fb_byte_width;
3324 from += font_byte_width;
3325 }
3326 }
3327
3328 /*
3329 * bmpcp1char: copy 1 char from one place in the frame buffer to
3330 * another.
3331 */
3332 void
3333 bmpcp1char(from, to)
3334 csrpos_t from, to;
3335 {
3336 short from_xbit, from_ybit;
3337 short to_xbit, to_ybit;
3338 register u_char *tp, *fp;
3339 register short i, j;
3340
3341 bmpch2bit(from, &from_xbit, &from_ybit);
3342 bmpch2bit(to, &to_xbit, &to_ybit);
3343
3344 tp = bit2fbptr(to_xbit, to_ybit);
3345 fp = bit2fbptr(from_xbit, from_ybit);
3346
3347 for (i = 0; i < char_height; ++i) {
3348 for (j = 0; j < char_byte_width; ++j)
3349 *(tp+j) = *(fp+j);
3350 tp += fb_byte_width;
3351 fp += fb_byte_width;
3352 }
3353 }
3354
3355 /*
3356 * bmpvmup: Copy a block of character positions upwards.
3357 */
3358 void
3359 bmpmvup(from, to, count)
3360 csrpos_t from, to;
3361 int count;
3362 {
3363 short from_xbit, from_ybit;
3364 short to_xbit, to_ybit;
3365 short i;
3366
3367 bmpch2bit(from, &from_xbit, &from_ybit);
3368 bmpch2bit(to, &to_xbit, &to_ybit);
3369
3370 if (from_xbit == xstart && to_xbit == xstart && count%kd_cols == 0) {
3371 /* fast case - entire lines */
3372 from_xbit = to_xbit = 0;
3373 bmppaintcsr(kd_curpos, char_black); /* don't copy cursor */
3374 count /= kd_cols; /* num lines */
3375 count *= fb_byte_width * (char_height+cursor_height);
3376 kd_slmscu(bit2fbptr(from_xbit, from_ybit),
3377 bit2fbptr(to_xbit, to_ybit),
3378 count/SLAMBPW);
3379 bmppaintcsr(kd_curpos, char_white);
3380 } else {
3381 /* slow case - everything else */
3382 for (i=0; i < count; ++i) {
3383 bmpcp1char(from, to);
3384 from += ONE_SPACE;
3385 to += ONE_SPACE;
3386 }
3387 }
3388 }
3389
3390 /*
3391 * bmpmvdown: copy a block of characters down.
3392 */
3393 void
3394 bmpmvdown(from, to, count)
3395 csrpos_t from, to;
3396 int count;
3397 {
3398 short from_xbit, from_ybit;
3399 short to_xbit, to_ybit;
3400 short i;
3401
3402 bmpch2bit(from, &from_xbit, &from_ybit);
3403 bmpch2bit(to, &to_xbit, &to_ybit);
3404
3405 if (from_xbit == xstart + (kd_cols - 1) * char_width
3406 && to_xbit == xstart + (kd_cols - 1) * char_width
3407 && count%kd_cols == 0) {
3408 /* fast case - entire lines*/
3409 from_xbit = to_xbit = 8 * (fb_byte_width - 1);
3410 /* last byte on line */
3411 bmppaintcsr(kd_curpos, char_black); /* don't copy cursor */
3412 count /= kd_cols; /* num lines */
3413 count *= fb_byte_width * (char_height+cursor_height);
3414 kd_slmscd(bit2fbptr(from_xbit, from_ybit),
3415 bit2fbptr(to_xbit, to_ybit),
3416 count/SLAMBPW);
3417 bmppaintcsr(kd_curpos, char_white);
3418 } else {
3419 /* slow case - everything else */
3420 for (i=0; i < count; ++i) {
3421 bmpcp1char(from, to);
3422 from -= ONE_SPACE;
3423 to -= ONE_SPACE;
3424 }
3425 }
3426 }
3427
3428 /*
3429 * bmpclear: clear one or more character positions.
3430 */
3431 void
3432 bmpclear(to, count, chattr)
3433 csrpos_t to; /* 1st char */
3434 int count; /* num chars */
3435 char chattr; /* reverse or normal */
3436 {
3437 register short i;
3438 u_short clearval;
3439 u_short clearbyte = (chattr == KA_REVERSE ? char_white : char_black);
3440
3441 clearval = (u_short)clearbyte<<8 + clearbyte;
3442 if (to == 0 && count >= kd_lines * kd_cols) {
3443 /* fast case - entire page */
3444 kd_slmwd(vid_start, (fb_byte_width * fb_height)/SLAMBPW,
3445 clearval);
3446 } else
3447 /* slow case */
3448 for (i = 0; i < count; ++i) {
3449 bmpput(to, K_SPACE, chattr);
3450 to += ONE_SPACE;
3451 }
3452 }
3453
3454 /*
3455 * bmpsetcursor: update the display and set the logical cursor.
3456 */
3457 void
3458 bmpsetcursor(pos)
3459 csrpos_t pos;
3460 {
3461 /* erase old cursor & paint new one */
3462 bmppaintcsr(kd_curpos, char_black);
3463 bmppaintcsr(pos, char_white);
3464 kd_curpos = pos;
3465 }
3466
3467 /*
3468 * bmppaintcsr: paint cursor bits.
3469 */
3470 void
3471 bmppaintcsr(pos, val)
3472 csrpos_t pos;
3473 u_char val;
3474 {
3475 short xbit, ybit;
3476 register u_char *cp;
3477 register short line, byte;
3478
3479 bmpch2bit(pos, &xbit, &ybit);
3480 ybit += char_height; /* position at bottom of line */
3481 cp = bit2fbptr(xbit, ybit);
3482 for (line = 0; line < cursor_height; ++line) {
3483 for (byte = 0; byte < char_byte_width; ++byte)
3484 *(cp+byte) = val;
3485 cp += fb_byte_width;
3486 }
3487 }
3488
3489 /*
3490 * bmpch2bit: convert character position to x and y bit addresses.
3491 * (0, 0) is the upper left corner.
3492 */
3493 void
3494 bmpch2bit(pos, xb, yb)
3495 csrpos_t pos;
3496 short *xb, *yb; /* x, y bit positions, u/l corner */
3497 {
3498 register short xch, ych;
3499
3500 xch = (pos / ONE_SPACE) % kd_cols;
3501 ych = pos / (ONE_SPACE * kd_cols);
3502 *xb = xstart + xch * char_width;
3503 *yb = ystart + ych * (char_height + cursor_height);
3504 }
3505
3506 /*
3507 * bit2fbptr: return a pointer into the frame buffer corresponding to
3508 * the bit address (x, y).
3509 * Assumes that xb and yb don't point to the middle of a
3510 * byte.
3511 */
3512 u_char *
3513 bit2fbptr(xb, yb)
3514 short xb, yb;
3515 {
3516 return(vid_start + yb * fb_byte_width + xb/8);
3517 }
3518
3519 #endif BIT_BLIT
3520
3521 #ifdef PS2
3522 #include <i386ps2/kd_abios.c>
3523 #endif PS2
Cache object: 5ab73b6fb7db47d279e453f1a2030972
|