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