pccons.c revision 1.36 1 1.36 lukem /* $NetBSD: pccons.c,v 1.36 2003/07/15 00:04:45 lukem Exp $ */
2 1.14 soda /* $OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $ */
3 1.13 soda /* NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp */
4 1.1 jonathan
5 1.1 jonathan /*-
6 1.11 mycroft * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
7 1.1 jonathan * Copyright (c) 1990 The Regents of the University of California.
8 1.1 jonathan * All rights reserved.
9 1.1 jonathan *
10 1.1 jonathan * This code is derived from software contributed to Berkeley by
11 1.1 jonathan * William Jolitz and Don Ahn.
12 1.1 jonathan *
13 1.11 mycroft * Copyright (c) 1994 Charles M. Hannum.
14 1.1 jonathan * Copyright (c) 1992, 1993 Erik Forsberg.
15 1.1 jonathan *
16 1.1 jonathan * Redistribution and use in source and binary forms, with or without
17 1.1 jonathan * modification, are permitted provided that the following conditions
18 1.1 jonathan * are met:
19 1.1 jonathan * 1. Redistributions of source code must retain the above copyright
20 1.1 jonathan * notice, this list of conditions and the following disclaimer.
21 1.1 jonathan * 2. Redistributions in binary form must reproduce the above copyright
22 1.1 jonathan * notice, this list of conditions and the following disclaimer in the
23 1.1 jonathan * documentation and/or other materials provided with the distribution.
24 1.1 jonathan * 3. All advertising materials mentioning features or use of this software
25 1.1 jonathan * must display the following acknowledgement:
26 1.1 jonathan * This product includes software developed by the University of
27 1.1 jonathan * California, Berkeley and its contributors.
28 1.1 jonathan * 4. Neither the name of the University nor the names of its contributors
29 1.1 jonathan * may be used to endorse or promote products derived from this software
30 1.1 jonathan * without specific prior written permission.
31 1.1 jonathan *
32 1.1 jonathan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 1.1 jonathan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 1.1 jonathan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 1.1 jonathan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 1.1 jonathan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 1.1 jonathan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 1.1 jonathan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 1.1 jonathan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 1.1 jonathan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 1.1 jonathan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 1.1 jonathan * SUCH DAMAGE.
43 1.1 jonathan *
44 1.1 jonathan * @(#)pccons.c 5.11 (Berkeley) 5/21/91
45 1.1 jonathan */
46 1.1 jonathan
47 1.1 jonathan /*
48 1.1 jonathan * code to work keyboard & display for PC-style console
49 1.1 jonathan */
50 1.36 lukem
51 1.36 lukem #include <sys/cdefs.h>
52 1.36 lukem __KERNEL_RCSID(0, "$NetBSD: pccons.c,v 1.36 2003/07/15 00:04:45 lukem Exp $");
53 1.1 jonathan
54 1.14 soda #include "opt_ddb.h"
55 1.14 soda
56 1.1 jonathan #include <sys/param.h>
57 1.1 jonathan #include <sys/systm.h>
58 1.1 jonathan #include <sys/tty.h>
59 1.1 jonathan #include <sys/callout.h>
60 1.8 jonathan #include <sys/poll.h>
61 1.13 soda #include <sys/conf.h>
62 1.13 soda #include <sys/vnode.h>
63 1.13 soda #include <sys/kernel.h>
64 1.13 soda #include <sys/kcore.h>
65 1.27 soda #include <sys/device.h>
66 1.28 chs #include <sys/proc.h>
67 1.1 jonathan
68 1.27 soda #include <machine/bus.h>
69 1.1 jonathan
70 1.1 jonathan #include <machine/display.h>
71 1.1 jonathan #include <machine/pccons.h>
72 1.1 jonathan #include <machine/kbdreg.h>
73 1.1 jonathan
74 1.13 soda #include <dev/cons.h>
75 1.27 soda #include <dev/isa/isavar.h>
76 1.13 soda
77 1.27 soda #include <arc/arc/arcbios.h>
78 1.27 soda #include <arc/dev/pcconsvar.h>
79 1.20 soda
80 1.1 jonathan #define XFREE86_BUG_COMPAT
81 1.1 jonathan
82 1.1 jonathan #ifndef BEEP_FREQ
83 1.1 jonathan #define BEEP_FREQ 1600
84 1.1 jonathan #endif
85 1.1 jonathan #ifndef BEEP_TIME
86 1.1 jonathan #define BEEP_TIME (hz/5)
87 1.1 jonathan #endif
88 1.1 jonathan
89 1.1 jonathan #define PCBURST 128
90 1.1 jonathan
91 1.1 jonathan static u_short *Crtat; /* pointer to backing store */
92 1.1 jonathan static u_short *crtat; /* pointer to current char */
93 1.1 jonathan static u_char async, kernel, polling; /* Really, you don't want to know. */
94 1.1 jonathan static u_char lock_state = 0x00, /* all off */
95 1.1 jonathan old_lock_state = 0xff,
96 1.1 jonathan typematic_rate = 0xff, /* don't update until set by user */
97 1.1 jonathan old_typematic_rate = 0xff;
98 1.1 jonathan static u_short cursor_shape = 0xffff, /* don't update until set by user */
99 1.1 jonathan old_cursor_shape = 0xffff;
100 1.13 soda static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
101 1.1 jonathan int pc_xmode = 0;
102 1.1 jonathan
103 1.1 jonathan /*
104 1.1 jonathan * Keyboard output queue.
105 1.1 jonathan */
106 1.1 jonathan int kb_oq_put = 0;
107 1.1 jonathan int kb_oq_get = 0;
108 1.1 jonathan u_char kb_oq[8];
109 1.1 jonathan
110 1.1 jonathan #define PCUNIT(x) (minor(x))
111 1.1 jonathan
112 1.1 jonathan static struct video_state {
113 1.1 jonathan int cx, cy; /* escape parameters */
114 1.1 jonathan int row, col; /* current cursor position */
115 1.1 jonathan int nrow, ncol, nchr; /* current screen geometry */
116 1.13 soda int offset; /* Saved cursor pos */
117 1.1 jonathan u_char state; /* parser state */
118 1.1 jonathan #define VSS_ESCAPE 1
119 1.1 jonathan #define VSS_EBRACE 2
120 1.1 jonathan #define VSS_EPARAM 3
121 1.1 jonathan char so; /* in standout mode? */
122 1.1 jonathan char color; /* color or mono display */
123 1.1 jonathan char at; /* normal attributes */
124 1.1 jonathan char so_at; /* standout attributes */
125 1.1 jonathan } vs;
126 1.1 jonathan
127 1.17 thorpej static struct callout async_update_ch = CALLOUT_INITIALIZER;
128 1.17 thorpej
129 1.13 soda void pc_xmode_on __P((void));
130 1.13 soda void pc_xmode_off __P((void));
131 1.13 soda static u_char kbc_get8042cmd __P((void));
132 1.13 soda int kbd_cmd __P((u_char, u_char));
133 1.13 soda static __inline int kbd_wait_output __P((void));
134 1.13 soda static __inline int kbd_wait_input __P((void));
135 1.27 soda void kbd_flush_input __P((void));
136 1.13 soda void set_cursor_shape __P((void));
137 1.13 soda void get_cursor_shape __P((void));
138 1.13 soda void async_update __P((void));
139 1.33 simonb void do_async_update __P((u_char));
140 1.13 soda
141 1.13 soda void pccnputc __P((dev_t, int c));
142 1.13 soda int pccngetc __P((dev_t));
143 1.13 soda void pccnpollc __P((dev_t, int));
144 1.1 jonathan
145 1.13 soda extern struct cfdriver pc_cd;
146 1.13 soda
147 1.30 gehenna dev_type_open(pcopen);
148 1.30 gehenna dev_type_close(pcclose);
149 1.30 gehenna dev_type_read(pcread);
150 1.30 gehenna dev_type_write(pcwrite);
151 1.30 gehenna dev_type_ioctl(pcioctl);
152 1.30 gehenna dev_type_tty(pctty);
153 1.30 gehenna dev_type_poll(pcpoll);
154 1.30 gehenna dev_type_mmap(pcmmap);
155 1.30 gehenna
156 1.30 gehenna const struct cdevsw pc_cdevsw = {
157 1.30 gehenna pcopen, pcclose, pcread, pcwrite, pcioctl,
158 1.31 jdolecek nostop, pctty, pcpoll, pcmmap, ttykqfilter, D_TTY
159 1.30 gehenna };
160 1.30 gehenna
161 1.1 jonathan #define CHR 2
162 1.1 jonathan
163 1.1 jonathan char *sget __P((void));
164 1.1 jonathan void sput __P((u_char *, int));
165 1.1 jonathan
166 1.13 soda void pcstart __P((struct tty *));
167 1.13 soda int pcparam __P((struct tty *, struct termios *));
168 1.13 soda static __inline void wcopy __P((void *, void *, u_int));
169 1.27 soda void pc_context_init __P((bus_space_tag_t, bus_space_tag_t, bus_space_tag_t,
170 1.27 soda struct pccons_config *));
171 1.13 soda
172 1.13 soda extern void fillw __P((int, u_int16_t *, int));
173 1.1 jonathan
174 1.1 jonathan #define KBD_DELAY \
175 1.1 jonathan DELAY(10);
176 1.1 jonathan
177 1.27 soda #define crtc_read_1(reg) \
178 1.27 soda bus_space_read_1(pccons_console_context.pc_crt_iot, \
179 1.27 soda pccons_console_context.pc_6845_ioh, reg)
180 1.27 soda #define crtc_write_1(reg, data) \
181 1.27 soda bus_space_write_1(pccons_console_context.pc_crt_iot, \
182 1.27 soda pccons_console_context.pc_6845_ioh, reg, data)
183 1.27 soda
184 1.27 soda struct pccons_context pccons_console_context;
185 1.27 soda
186 1.27 soda void
187 1.27 soda kbd_context_init(kbd_iot, config)
188 1.27 soda bus_space_tag_t kbd_iot;
189 1.27 soda struct pccons_config *config;
190 1.27 soda {
191 1.27 soda struct pccons_kbd_context *pkc = &pccons_console_context.pc_pkc;
192 1.27 soda
193 1.27 soda if (pkc->pkc_initialized)
194 1.27 soda return;
195 1.27 soda pkc->pkc_initialized = 1;
196 1.27 soda
197 1.27 soda pkc->pkc_iot = kbd_iot;
198 1.27 soda
199 1.27 soda bus_space_map(kbd_iot, config->pc_kbd_cmdp, 1, 0,
200 1.27 soda &pkc->pkc_cmd_ioh);
201 1.27 soda bus_space_map(kbd_iot, config->pc_kbd_datap, 1, 0,
202 1.27 soda &pkc->pkc_data_ioh);
203 1.27 soda }
204 1.27 soda
205 1.20 soda void
206 1.27 soda pc_context_init(crt_iot, crt_memt, kbd_iot, config)
207 1.27 soda bus_space_tag_t crt_iot, crt_memt, kbd_iot;
208 1.27 soda struct pccons_config *config;
209 1.20 soda {
210 1.27 soda struct pccons_context *pc = &pccons_console_context;
211 1.20 soda
212 1.27 soda if (pc->pc_initialized)
213 1.20 soda return;
214 1.27 soda pc->pc_initialized = 1;
215 1.27 soda
216 1.27 soda kbd_context_init(kbd_iot, config);
217 1.27 soda
218 1.27 soda pc->pc_crt_iot = crt_iot;
219 1.27 soda pc->pc_crt_memt = crt_memt;
220 1.20 soda
221 1.27 soda bus_space_map(crt_iot, config->pc_mono_iobase, 2, 0,
222 1.27 soda &pc->pc_mono_ioh);
223 1.27 soda bus_space_map(crt_memt, config->pc_mono_memaddr, 0x20000, 0,
224 1.27 soda &pc->pc_mono_memh);
225 1.27 soda bus_space_map(crt_iot, config->pc_cga_iobase, 2, 0,
226 1.27 soda &pc->pc_cga_ioh);
227 1.27 soda bus_space_map(crt_memt, config->pc_cga_memaddr, 0x20000, 0,
228 1.27 soda &pc->pc_cga_memh);
229 1.20 soda
230 1.27 soda /*
231 1.27 soda * pc->pc_6845_ioh and pc->pc_crt_memh will be initialized later,
232 1.27 soda * when `Crtat' is initialized.
233 1.27 soda */
234 1.27 soda
235 1.27 soda pc->pc_config = config;
236 1.27 soda
237 1.27 soda (*config->pc_init)();
238 1.20 soda }
239 1.20 soda
240 1.13 soda /*
241 1.13 soda * bcopy variant that only moves word-aligned 16-bit entities,
242 1.13 soda * for stupid VGA cards. cnt is required to be an even vale.
243 1.13 soda */
244 1.13 soda static __inline void
245 1.13 soda wcopy(src, tgt, cnt)
246 1.13 soda void *src, *tgt;
247 1.13 soda u_int cnt;
248 1.13 soda {
249 1.13 soda u_int16_t *from = src;
250 1.13 soda u_int16_t *to = tgt;
251 1.13 soda
252 1.13 soda cnt >>= 1;
253 1.13 soda if (to < from || to >= from + cnt)
254 1.13 soda while(cnt--)
255 1.13 soda *to++ = *from++;
256 1.13 soda else {
257 1.13 soda to += cnt;
258 1.13 soda from += cnt;
259 1.13 soda while(cnt--)
260 1.13 soda *--to = *--from;
261 1.13 soda }
262 1.13 soda }
263 1.13 soda
264 1.13 soda static __inline int
265 1.1 jonathan kbd_wait_output()
266 1.1 jonathan {
267 1.1 jonathan u_int i;
268 1.1 jonathan
269 1.1 jonathan for (i = 100000; i; i--)
270 1.27 soda if ((kbd_cmd_read_1() & KBS_IBF) == 0) {
271 1.1 jonathan KBD_DELAY;
272 1.1 jonathan return 1;
273 1.1 jonathan }
274 1.1 jonathan return 0;
275 1.1 jonathan }
276 1.1 jonathan
277 1.13 soda static __inline int
278 1.1 jonathan kbd_wait_input()
279 1.1 jonathan {
280 1.1 jonathan u_int i;
281 1.1 jonathan
282 1.1 jonathan for (i = 100000; i; i--)
283 1.27 soda if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
284 1.1 jonathan KBD_DELAY;
285 1.1 jonathan return 1;
286 1.1 jonathan }
287 1.1 jonathan return 0;
288 1.1 jonathan }
289 1.1 jonathan
290 1.27 soda void
291 1.1 jonathan kbd_flush_input()
292 1.1 jonathan {
293 1.1 jonathan u_char c;
294 1.1 jonathan
295 1.27 soda while ((c = kbd_cmd_read_1()) & 0x03)
296 1.1 jonathan if ((c & KBS_DIB) == KBS_DIB) {
297 1.1 jonathan /* XXX - delay is needed to prevent some keyboards from
298 1.1 jonathan wedging when the system boots */
299 1.1 jonathan delay(6);
300 1.27 soda (void) kbd_data_read_1();
301 1.1 jonathan }
302 1.13 soda }
303 1.13 soda
304 1.1 jonathan #if 1
305 1.1 jonathan /*
306 1.1 jonathan * Get the current command byte.
307 1.1 jonathan */
308 1.1 jonathan static u_char
309 1.1 jonathan kbc_get8042cmd()
310 1.1 jonathan {
311 1.1 jonathan
312 1.1 jonathan if (!kbd_wait_output())
313 1.1 jonathan return -1;
314 1.27 soda kbd_cmd_write_1(K_RDCMDBYTE);
315 1.1 jonathan if (!kbd_wait_input())
316 1.1 jonathan return -1;
317 1.27 soda return kbd_data_read_1();
318 1.1 jonathan }
319 1.1 jonathan #endif
320 1.1 jonathan
321 1.1 jonathan /*
322 1.1 jonathan * Pass command byte to keyboard controller (8042).
323 1.1 jonathan */
324 1.27 soda int
325 1.1 jonathan kbc_put8042cmd(val)
326 1.1 jonathan u_char val;
327 1.1 jonathan {
328 1.1 jonathan
329 1.1 jonathan if (!kbd_wait_output())
330 1.1 jonathan return 0;
331 1.27 soda kbd_cmd_write_1(K_LDCMDBYTE);
332 1.1 jonathan if (!kbd_wait_output())
333 1.1 jonathan return 0;
334 1.27 soda kbd_data_write_1(val);
335 1.1 jonathan return 1;
336 1.1 jonathan }
337 1.1 jonathan
338 1.1 jonathan /*
339 1.1 jonathan * Pass command to keyboard itself
340 1.1 jonathan */
341 1.1 jonathan int
342 1.1 jonathan kbd_cmd(val, polling)
343 1.1 jonathan u_char val;
344 1.1 jonathan u_char polling;
345 1.1 jonathan {
346 1.1 jonathan u_int retries = 3;
347 1.35 tsutsui u_int i;
348 1.1 jonathan
349 1.1 jonathan if(!polling) {
350 1.1 jonathan i = spltty();
351 1.1 jonathan if(kb_oq_get == kb_oq_put) {
352 1.27 soda kbd_data_write_1(val);
353 1.1 jonathan }
354 1.1 jonathan kb_oq[kb_oq_put] = val;
355 1.1 jonathan kb_oq_put = (kb_oq_put + 1) & 7;
356 1.1 jonathan splx(i);
357 1.1 jonathan return(1);
358 1.1 jonathan }
359 1.1 jonathan else do {
360 1.1 jonathan if (!kbd_wait_output())
361 1.1 jonathan return 0;
362 1.27 soda kbd_data_write_1(val);
363 1.1 jonathan for (i = 100000; i; i--) {
364 1.27 soda if (kbd_cmd_read_1() & KBS_DIB) {
365 1.35 tsutsui u_char c;
366 1.1 jonathan
367 1.1 jonathan KBD_DELAY;
368 1.27 soda c = kbd_data_read_1();
369 1.1 jonathan if (c == KBR_ACK || c == KBR_ECHO) {
370 1.1 jonathan return 1;
371 1.1 jonathan }
372 1.1 jonathan if (c == KBR_RESEND) {
373 1.1 jonathan break;
374 1.1 jonathan }
375 1.1 jonathan #ifdef DIAGNOSTIC
376 1.6 christos printf("kbd_cmd: input char %x lost\n", c);
377 1.1 jonathan #endif
378 1.1 jonathan }
379 1.1 jonathan }
380 1.1 jonathan } while (--retries);
381 1.1 jonathan return 0;
382 1.1 jonathan }
383 1.1 jonathan
384 1.1 jonathan void
385 1.1 jonathan set_cursor_shape()
386 1.1 jonathan {
387 1.27 soda crtc_write_1(0, 10);
388 1.27 soda crtc_write_1(1, cursor_shape >> 8);
389 1.27 soda crtc_write_1(0, 11);
390 1.27 soda crtc_write_1(1, cursor_shape);
391 1.1 jonathan old_cursor_shape = cursor_shape;
392 1.1 jonathan }
393 1.1 jonathan
394 1.1 jonathan void
395 1.1 jonathan get_cursor_shape()
396 1.1 jonathan {
397 1.27 soda crtc_write_1(0, 10);
398 1.27 soda cursor_shape = crtc_read_1(1) << 8;
399 1.27 soda crtc_write_1(0, 11);
400 1.27 soda cursor_shape |= crtc_read_1(1);
401 1.1 jonathan
402 1.1 jonathan /*
403 1.1 jonathan * real 6845's, as found on, MDA, Hercules or CGA cards, do
404 1.1 jonathan * not support reading the cursor shape registers. the 6845
405 1.1 jonathan * tri-states it's data bus. This is _normally_ read by the
406 1.1 jonathan * cpu as either 0x00 or 0xff.. in which case we just use
407 1.1 jonathan * a line cursor.
408 1.1 jonathan */
409 1.1 jonathan if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
410 1.1 jonathan cursor_shape = 0x0b10;
411 1.1 jonathan else
412 1.1 jonathan cursor_shape &= 0x1f1f;
413 1.1 jonathan }
414 1.1 jonathan
415 1.1 jonathan void
416 1.1 jonathan do_async_update(poll)
417 1.1 jonathan u_char poll;
418 1.1 jonathan {
419 1.1 jonathan int pos;
420 1.1 jonathan static int old_pos = -1;
421 1.1 jonathan
422 1.1 jonathan async = 0;
423 1.1 jonathan
424 1.1 jonathan if (lock_state != old_lock_state) {
425 1.1 jonathan old_lock_state = lock_state;
426 1.1 jonathan if (!kbd_cmd(KBC_MODEIND, poll) ||
427 1.1 jonathan !kbd_cmd(lock_state, poll)) {
428 1.6 christos printf("pc: timeout updating leds\n");
429 1.1 jonathan (void) kbd_cmd(KBC_ENABLE, poll);
430 1.1 jonathan }
431 1.1 jonathan }
432 1.1 jonathan if (typematic_rate != old_typematic_rate) {
433 1.1 jonathan old_typematic_rate = typematic_rate;
434 1.1 jonathan if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
435 1.1 jonathan !kbd_cmd(typematic_rate, poll)) {
436 1.6 christos printf("pc: timeout updating typematic rate\n");
437 1.1 jonathan (void) kbd_cmd(KBC_ENABLE, poll);
438 1.1 jonathan }
439 1.1 jonathan }
440 1.1 jonathan
441 1.1 jonathan if (pc_xmode > 0)
442 1.1 jonathan return;
443 1.1 jonathan
444 1.1 jonathan pos = crtat - Crtat;
445 1.1 jonathan if (pos != old_pos) {
446 1.27 soda crtc_write_1(0, 14);
447 1.27 soda crtc_write_1(1, pos >> 8);
448 1.27 soda crtc_write_1(0, 15);
449 1.27 soda crtc_write_1(1, pos);
450 1.1 jonathan old_pos = pos;
451 1.1 jonathan }
452 1.1 jonathan if (cursor_shape != old_cursor_shape)
453 1.1 jonathan set_cursor_shape();
454 1.1 jonathan }
455 1.1 jonathan
456 1.1 jonathan void
457 1.1 jonathan async_update()
458 1.1 jonathan {
459 1.1 jonathan
460 1.1 jonathan if (kernel || polling) {
461 1.1 jonathan if (async)
462 1.17 thorpej callout_stop(&async_update_ch);
463 1.1 jonathan do_async_update(1);
464 1.1 jonathan } else {
465 1.1 jonathan if (async)
466 1.1 jonathan return;
467 1.1 jonathan async = 1;
468 1.17 thorpej callout_reset(&async_update_ch, 1,
469 1.17 thorpej (void(*)(void *))do_async_update, NULL);
470 1.1 jonathan }
471 1.1 jonathan }
472 1.1 jonathan
473 1.1 jonathan /*
474 1.1 jonathan * these are both bad jokes
475 1.1 jonathan */
476 1.1 jonathan int
477 1.27 soda pccons_common_match(crt_iot, crt_memt, kbd_iot, config)
478 1.27 soda bus_space_tag_t crt_iot, crt_memt, kbd_iot;
479 1.27 soda struct pccons_config *config;
480 1.1 jonathan {
481 1.27 soda int i;
482 1.1 jonathan
483 1.27 soda pc_context_init(crt_iot, crt_memt, kbd_iot, config);
484 1.20 soda
485 1.1 jonathan /* Enable interrupts and keyboard, etc. */
486 1.1 jonathan if (!kbc_put8042cmd(CMDBYTE)) {
487 1.13 soda printf("pcprobe: command error\n");
488 1.1 jonathan return 0;
489 1.1 jonathan }
490 1.1 jonathan
491 1.1 jonathan #if 1
492 1.1 jonathan /* Flush any garbage. */
493 1.1 jonathan kbd_flush_input();
494 1.1 jonathan /* Reset the keyboard. */
495 1.1 jonathan if (!kbd_cmd(KBC_RESET, 1)) {
496 1.13 soda printf("pcprobe: reset error %d\n", 1);
497 1.1 jonathan goto lose;
498 1.1 jonathan }
499 1.1 jonathan for (i = 600000; i; i--)
500 1.27 soda if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
501 1.1 jonathan KBD_DELAY;
502 1.1 jonathan break;
503 1.1 jonathan }
504 1.27 soda if (i == 0 || kbd_data_read_1() != KBR_RSTDONE) {
505 1.13 soda printf("pcprobe: reset error %d\n", 2);
506 1.1 jonathan goto lose;
507 1.1 jonathan }
508 1.1 jonathan /*
509 1.1 jonathan * Some keyboards seem to leave a second ack byte after the reset.
510 1.1 jonathan * This is kind of stupid, but we account for them anyway by just
511 1.1 jonathan * flushing the buffer.
512 1.1 jonathan */
513 1.1 jonathan kbd_flush_input();
514 1.1 jonathan /* Just to be sure. */
515 1.1 jonathan if (!kbd_cmd(KBC_ENABLE, 1)) {
516 1.13 soda printf("pcprobe: reset error %d\n", 3);
517 1.1 jonathan goto lose;
518 1.1 jonathan }
519 1.1 jonathan
520 1.1 jonathan /*
521 1.1 jonathan * Some keyboard/8042 combinations do not seem to work if the keyboard
522 1.1 jonathan * is set to table 1; in fact, it would appear that some keyboards just
523 1.1 jonathan * ignore the command altogether. So by default, we use the AT scan
524 1.1 jonathan * codes and have the 8042 translate them. Unfortunately, this is
525 1.1 jonathan * known to not work on some PS/2 machines. We try desparately to deal
526 1.1 jonathan * with this by checking the (lack of a) translate bit in the 8042 and
527 1.1 jonathan * attempting to set the keyboard to XT mode. If this all fails, well,
528 1.1 jonathan * tough luck.
529 1.1 jonathan *
530 1.1 jonathan * XXX It would perhaps be a better choice to just use AT scan codes
531 1.1 jonathan * and not bother with this.
532 1.1 jonathan */
533 1.1 jonathan if (kbc_get8042cmd() & KC8_TRANS) {
534 1.1 jonathan /* The 8042 is translating for us; use AT codes. */
535 1.1 jonathan if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
536 1.13 soda printf("pcprobe: reset error %d\n", 4);
537 1.1 jonathan goto lose;
538 1.1 jonathan }
539 1.1 jonathan } else {
540 1.1 jonathan /* Stupid 8042; set keyboard to XT codes. */
541 1.1 jonathan if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
542 1.13 soda printf("pcprobe: reset error %d\n", 5);
543 1.1 jonathan goto lose;
544 1.1 jonathan }
545 1.1 jonathan }
546 1.1 jonathan
547 1.1 jonathan lose:
548 1.1 jonathan /*
549 1.13 soda * Technically, we should probably fail the probe. But we'll be nice
550 1.1 jonathan * and allow keyboard-less machines to boot with the console.
551 1.1 jonathan */
552 1.1 jonathan #endif
553 1.1 jonathan
554 1.1 jonathan return 1;
555 1.1 jonathan }
556 1.1 jonathan
557 1.27 soda void pccons_common_attach(sc, crt_iot, crt_memt, kbd_iot, config)
558 1.27 soda struct pc_softc *sc;
559 1.27 soda bus_space_tag_t crt_iot, crt_memt, kbd_iot;
560 1.27 soda struct pccons_config *config;
561 1.27 soda {
562 1.6 christos printf(": %s\n", vs.color ? "color" : "mono");
563 1.1 jonathan do_async_update(1);
564 1.1 jonathan }
565 1.1 jonathan
566 1.1 jonathan int
567 1.1 jonathan pcopen(dev, flag, mode, p)
568 1.1 jonathan dev_t dev;
569 1.1 jonathan int flag, mode;
570 1.1 jonathan struct proc *p;
571 1.1 jonathan {
572 1.1 jonathan struct pc_softc *sc;
573 1.1 jonathan int unit = PCUNIT(dev);
574 1.1 jonathan struct tty *tp;
575 1.1 jonathan
576 1.2 thorpej if (unit >= pc_cd.cd_ndevs)
577 1.1 jonathan return ENXIO;
578 1.2 thorpej sc = pc_cd.cd_devs[unit];
579 1.1 jonathan if (sc == 0)
580 1.1 jonathan return ENXIO;
581 1.1 jonathan
582 1.1 jonathan if (!sc->sc_tty) {
583 1.1 jonathan tp = sc->sc_tty = ttymalloc();
584 1.1 jonathan }
585 1.1 jonathan else {
586 1.1 jonathan tp = sc->sc_tty;
587 1.1 jonathan }
588 1.1 jonathan
589 1.1 jonathan tp->t_oproc = pcstart;
590 1.1 jonathan tp->t_param = pcparam;
591 1.1 jonathan tp->t_dev = dev;
592 1.1 jonathan if ((tp->t_state & TS_ISOPEN) == 0) {
593 1.1 jonathan ttychars(tp);
594 1.1 jonathan tp->t_iflag = TTYDEF_IFLAG;
595 1.1 jonathan tp->t_oflag = TTYDEF_OFLAG;
596 1.1 jonathan tp->t_cflag = TTYDEF_CFLAG;
597 1.1 jonathan tp->t_lflag = TTYDEF_LFLAG;
598 1.1 jonathan tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
599 1.1 jonathan pcparam(tp, &tp->t_termios);
600 1.1 jonathan ttsetwater(tp);
601 1.1 jonathan } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
602 1.1 jonathan return EBUSY;
603 1.1 jonathan tp->t_state |= TS_CARR_ON;
604 1.1 jonathan
605 1.22 eeh return ((*tp->t_linesw->l_open)(dev, tp));
606 1.1 jonathan }
607 1.1 jonathan
608 1.1 jonathan int
609 1.1 jonathan pcclose(dev, flag, mode, p)
610 1.1 jonathan dev_t dev;
611 1.1 jonathan int flag, mode;
612 1.1 jonathan struct proc *p;
613 1.1 jonathan {
614 1.2 thorpej struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
615 1.1 jonathan struct tty *tp = sc->sc_tty;
616 1.1 jonathan
617 1.22 eeh (*tp->t_linesw->l_close)(tp, flag);
618 1.1 jonathan ttyclose(tp);
619 1.1 jonathan #ifdef notyet /* XXX */
620 1.1 jonathan ttyfree(tp);
621 1.1 jonathan #endif
622 1.1 jonathan return(0);
623 1.1 jonathan }
624 1.1 jonathan
625 1.1 jonathan int
626 1.1 jonathan pcread(dev, uio, flag)
627 1.1 jonathan dev_t dev;
628 1.1 jonathan struct uio *uio;
629 1.1 jonathan int flag;
630 1.1 jonathan {
631 1.2 thorpej struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
632 1.1 jonathan struct tty *tp = sc->sc_tty;
633 1.1 jonathan
634 1.22 eeh return ((*tp->t_linesw->l_read)(tp, uio, flag));
635 1.1 jonathan }
636 1.1 jonathan
637 1.1 jonathan int
638 1.1 jonathan pcwrite(dev, uio, flag)
639 1.1 jonathan dev_t dev;
640 1.1 jonathan struct uio *uio;
641 1.1 jonathan int flag;
642 1.1 jonathan {
643 1.2 thorpej struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
644 1.1 jonathan struct tty *tp = sc->sc_tty;
645 1.1 jonathan
646 1.22 eeh return ((*tp->t_linesw->l_write)(tp, uio, flag));
647 1.25 scw }
648 1.25 scw
649 1.25 scw int
650 1.25 scw pcpoll(dev, events, p)
651 1.25 scw dev_t dev;
652 1.25 scw int events;
653 1.25 scw struct proc *p;
654 1.25 scw {
655 1.25 scw struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
656 1.25 scw struct tty *tp = sc->sc_tty;
657 1.32 tsutsui
658 1.25 scw return ((*tp->t_linesw->l_poll)(tp, events, p));
659 1.1 jonathan }
660 1.1 jonathan
661 1.1 jonathan struct tty *
662 1.1 jonathan pctty(dev)
663 1.1 jonathan dev_t dev;
664 1.1 jonathan {
665 1.2 thorpej struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
666 1.1 jonathan struct tty *tp = sc->sc_tty;
667 1.1 jonathan
668 1.1 jonathan return (tp);
669 1.1 jonathan }
670 1.1 jonathan
671 1.1 jonathan /*
672 1.1 jonathan * Got a console receive interrupt -
673 1.1 jonathan * the console processor wants to give us a character.
674 1.1 jonathan * Catch the character, and see who it goes to.
675 1.1 jonathan */
676 1.1 jonathan int
677 1.1 jonathan pcintr(arg)
678 1.1 jonathan void *arg;
679 1.1 jonathan {
680 1.1 jonathan struct pc_softc *sc = arg;
681 1.35 tsutsui struct tty *tp = sc->sc_tty;
682 1.1 jonathan u_char *cp;
683 1.1 jonathan
684 1.27 soda if ((kbd_cmd_read_1() & KBS_DIB) == 0)
685 1.1 jonathan return 0;
686 1.1 jonathan if (polling)
687 1.1 jonathan return 1;
688 1.1 jonathan do {
689 1.1 jonathan cp = sget();
690 1.1 jonathan if (!tp || (tp->t_state & TS_ISOPEN) == 0)
691 1.1 jonathan return 1;
692 1.1 jonathan if (cp)
693 1.1 jonathan do
694 1.22 eeh (*tp->t_linesw->l_rint)(*cp++, tp);
695 1.1 jonathan while (*cp);
696 1.27 soda } while (kbd_cmd_read_1() & KBS_DIB);
697 1.1 jonathan return 1;
698 1.1 jonathan }
699 1.1 jonathan
700 1.1 jonathan int
701 1.1 jonathan pcioctl(dev, cmd, data, flag, p)
702 1.1 jonathan dev_t dev;
703 1.1 jonathan u_long cmd;
704 1.1 jonathan caddr_t data;
705 1.1 jonathan int flag;
706 1.1 jonathan struct proc *p;
707 1.1 jonathan {
708 1.2 thorpej struct pc_softc *sc = pc_cd.cd_devs[PCUNIT(dev)];
709 1.1 jonathan struct tty *tp = sc->sc_tty;
710 1.1 jonathan int error;
711 1.1 jonathan
712 1.22 eeh error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
713 1.29 atatat if (error != EPASSTHROUGH)
714 1.1 jonathan return error;
715 1.1 jonathan error = ttioctl(tp, cmd, data, flag, p);
716 1.29 atatat if (error != EPASSTHROUGH)
717 1.1 jonathan return error;
718 1.1 jonathan
719 1.1 jonathan switch (cmd) {
720 1.1 jonathan case CONSOLE_X_MODE_ON:
721 1.1 jonathan pc_xmode_on();
722 1.1 jonathan return 0;
723 1.1 jonathan case CONSOLE_X_MODE_OFF:
724 1.1 jonathan pc_xmode_off();
725 1.1 jonathan return 0;
726 1.1 jonathan case CONSOLE_X_BELL:
727 1.1 jonathan /*
728 1.1 jonathan * If set, data is a pointer to a length 2 array of
729 1.1 jonathan * integers. data[0] is the pitch in Hz and data[1]
730 1.1 jonathan * is the duration in msec.
731 1.1 jonathan */
732 1.1 jonathan if (data)
733 1.1 jonathan sysbeep(((int*)data)[0],
734 1.1 jonathan (((int*)data)[1] * hz) / 1000);
735 1.1 jonathan else
736 1.1 jonathan sysbeep(BEEP_FREQ, BEEP_TIME);
737 1.1 jonathan return 0;
738 1.1 jonathan case CONSOLE_SET_TYPEMATIC_RATE: {
739 1.1 jonathan u_char rate;
740 1.1 jonathan
741 1.1 jonathan if (!data)
742 1.1 jonathan return EINVAL;
743 1.1 jonathan rate = *((u_char *)data);
744 1.1 jonathan /*
745 1.1 jonathan * Check that it isn't too big (which would cause it to be
746 1.1 jonathan * confused with a command).
747 1.1 jonathan */
748 1.1 jonathan if (rate & 0x80)
749 1.1 jonathan return EINVAL;
750 1.1 jonathan typematic_rate = rate;
751 1.1 jonathan async_update();
752 1.1 jonathan return 0;
753 1.1 jonathan }
754 1.13 soda case CONSOLE_SET_KEYMAP: {
755 1.13 soda pccons_keymap_t *map = (pccons_keymap_t *) data;
756 1.13 soda int i;
757 1.13 soda
758 1.13 soda if (!data)
759 1.13 soda return EINVAL;
760 1.13 soda for (i = 0; i < KB_NUM_KEYS; i++)
761 1.13 soda if (map[i].unshift[KB_CODE_SIZE-1] ||
762 1.13 soda map[i].shift[KB_CODE_SIZE-1] ||
763 1.13 soda map[i].ctl[KB_CODE_SIZE-1] ||
764 1.13 soda map[i].altgr[KB_CODE_SIZE-1] ||
765 1.13 soda map[i].shift_altgr[KB_CODE_SIZE-1])
766 1.13 soda return EINVAL;
767 1.13 soda
768 1.13 soda bcopy(data, scan_codes, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
769 1.13 soda return 0;
770 1.13 soda }
771 1.13 soda case CONSOLE_GET_KEYMAP:
772 1.13 soda if (!data)
773 1.13 soda return EINVAL;
774 1.13 soda bcopy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
775 1.13 soda return 0;
776 1.13 soda
777 1.1 jonathan default:
778 1.29 atatat return EPASSTHROUGH;
779 1.1 jonathan }
780 1.1 jonathan
781 1.1 jonathan #ifdef DIAGNOSTIC
782 1.1 jonathan panic("pcioctl: impossible");
783 1.1 jonathan #endif
784 1.1 jonathan }
785 1.1 jonathan
786 1.1 jonathan void
787 1.1 jonathan pcstart(tp)
788 1.1 jonathan struct tty *tp;
789 1.1 jonathan {
790 1.1 jonathan struct clist *cl;
791 1.13 soda int s, len;
792 1.1 jonathan u_char buf[PCBURST];
793 1.1 jonathan
794 1.1 jonathan s = spltty();
795 1.1 jonathan if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
796 1.1 jonathan goto out;
797 1.1 jonathan tp->t_state |= TS_BUSY;
798 1.1 jonathan splx(s);
799 1.1 jonathan /*
800 1.1 jonathan * We need to do this outside spl since it could be fairly
801 1.1 jonathan * expensive and we don't want our serial ports to overflow.
802 1.1 jonathan */
803 1.1 jonathan cl = &tp->t_outq;
804 1.1 jonathan len = q_to_b(cl, buf, PCBURST);
805 1.1 jonathan sput(buf, len);
806 1.1 jonathan s = spltty();
807 1.1 jonathan tp->t_state &= ~TS_BUSY;
808 1.1 jonathan if (cl->c_cc) {
809 1.1 jonathan tp->t_state |= TS_TIMEOUT;
810 1.17 thorpej callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
811 1.1 jonathan }
812 1.1 jonathan if (cl->c_cc <= tp->t_lowat) {
813 1.1 jonathan if (tp->t_state & TS_ASLEEP) {
814 1.1 jonathan tp->t_state &= ~TS_ASLEEP;
815 1.1 jonathan wakeup(cl);
816 1.1 jonathan }
817 1.1 jonathan selwakeup(&tp->t_wsel);
818 1.1 jonathan }
819 1.1 jonathan out:
820 1.1 jonathan splx(s);
821 1.1 jonathan }
822 1.1 jonathan
823 1.13 soda /* ARGSUSED */
824 1.27 soda void pccons_common_cnattach(crt_iot, crt_memt, kbd_iot, config)
825 1.27 soda bus_space_tag_t crt_iot, crt_memt, kbd_iot;
826 1.27 soda struct pccons_config *config;
827 1.1 jonathan {
828 1.1 jonathan int maj;
829 1.13 soda static struct consdev pccons = {
830 1.34 tsutsui NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, NULL,
831 1.34 tsutsui NULL, NODEV, CN_NORMAL
832 1.13 soda };
833 1.13 soda
834 1.13 soda /*
835 1.13 soda * For now, don't screw with it.
836 1.13 soda */
837 1.13 soda /* crtat = 0; */
838 1.14 soda
839 1.27 soda pc_context_init(crt_iot, crt_memt, kbd_iot, config);
840 1.1 jonathan
841 1.1 jonathan /* locate the major number */
842 1.30 gehenna maj = cdevsw_lookup_major(&pc_cdevsw);
843 1.13 soda pccons.cn_dev = makedev(maj, 0);
844 1.1 jonathan
845 1.13 soda cn_tab = &pccons;
846 1.1 jonathan }
847 1.1 jonathan
848 1.1 jonathan /* ARGSUSED */
849 1.1 jonathan void
850 1.1 jonathan pccnputc(dev, c)
851 1.1 jonathan dev_t dev;
852 1.13 soda int c;
853 1.1 jonathan {
854 1.15 soda u_char cc, oldkernel = kernel;
855 1.1 jonathan
856 1.1 jonathan kernel = 1;
857 1.15 soda if (c == '\n') {
858 1.1 jonathan sput("\r\n", 2);
859 1.15 soda } else {
860 1.15 soda cc = c;
861 1.15 soda sput(&cc, 1);
862 1.15 soda }
863 1.1 jonathan kernel = oldkernel;
864 1.1 jonathan }
865 1.1 jonathan
866 1.1 jonathan /* ARGSUSED */
867 1.13 soda int
868 1.1 jonathan pccngetc(dev)
869 1.1 jonathan dev_t dev;
870 1.1 jonathan {
871 1.35 tsutsui char *cp;
872 1.1 jonathan
873 1.1 jonathan if (pc_xmode > 0)
874 1.1 jonathan return 0;
875 1.1 jonathan
876 1.1 jonathan do {
877 1.1 jonathan /* wait for byte */
878 1.27 soda while ((kbd_cmd_read_1() & KBS_DIB) == 0);
879 1.1 jonathan /* see if it's worthwhile */
880 1.1 jonathan cp = sget();
881 1.1 jonathan } while (!cp);
882 1.1 jonathan if (*cp == '\r')
883 1.1 jonathan return '\n';
884 1.1 jonathan return *cp;
885 1.1 jonathan }
886 1.1 jonathan
887 1.1 jonathan void
888 1.1 jonathan pccnpollc(dev, on)
889 1.1 jonathan dev_t dev;
890 1.1 jonathan int on;
891 1.1 jonathan {
892 1.1 jonathan
893 1.1 jonathan polling = on;
894 1.1 jonathan if (!on) {
895 1.1 jonathan int unit;
896 1.1 jonathan struct pc_softc *sc;
897 1.1 jonathan int s;
898 1.1 jonathan
899 1.1 jonathan /*
900 1.1 jonathan * If disabling polling on a device that's been configured,
901 1.1 jonathan * make sure there are no bytes left in the FIFO, holding up
902 1.1 jonathan * the interrupt line. Otherwise we won't get any further
903 1.1 jonathan * interrupts.
904 1.1 jonathan */
905 1.1 jonathan unit = PCUNIT(dev);
906 1.2 thorpej if (pc_cd.cd_ndevs > unit) {
907 1.2 thorpej sc = pc_cd.cd_devs[unit];
908 1.1 jonathan if (sc != 0) {
909 1.1 jonathan s = spltty();
910 1.1 jonathan pcintr(sc);
911 1.1 jonathan splx(s);
912 1.1 jonathan }
913 1.1 jonathan }
914 1.1 jonathan }
915 1.32 tsutsui }
916 1.1 jonathan
917 1.1 jonathan /*
918 1.1 jonathan * Set line parameters.
919 1.1 jonathan */
920 1.1 jonathan int
921 1.1 jonathan pcparam(tp, t)
922 1.1 jonathan struct tty *tp;
923 1.1 jonathan struct termios *t;
924 1.1 jonathan {
925 1.1 jonathan
926 1.1 jonathan tp->t_ispeed = t->c_ispeed;
927 1.1 jonathan tp->t_ospeed = t->c_ospeed;
928 1.1 jonathan tp->t_cflag = t->c_cflag;
929 1.1 jonathan return 0;
930 1.1 jonathan }
931 1.1 jonathan
932 1.1 jonathan #define wrtchar(c, at) do {\
933 1.1 jonathan char *cp = (char *)crtat; *cp++ = (c); *cp = (at); crtat++; vs.col++; \
934 1.1 jonathan } while (0)
935 1.1 jonathan
936 1.1 jonathan /* translate ANSI color codes to standard pc ones */
937 1.1 jonathan static char fgansitopc[] = {
938 1.1 jonathan FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
939 1.1 jonathan FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
940 1.1 jonathan };
941 1.1 jonathan
942 1.1 jonathan static char bgansitopc[] = {
943 1.1 jonathan BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
944 1.1 jonathan BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
945 1.1 jonathan };
946 1.1 jonathan
947 1.1 jonathan static u_char iso2ibm437[] =
948 1.32 tsutsui {
949 1.1 jonathan 0, 0, 0, 0, 0, 0, 0, 0,
950 1.1 jonathan 0, 0, 0, 0, 0, 0, 0, 0,
951 1.1 jonathan 0, 0, 0, 0, 0, 0, 0, 0,
952 1.1 jonathan 0, 0, 0, 0, 0, 0, 0, 0,
953 1.1 jonathan 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40,
954 1.1 jonathan 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0,
955 1.1 jonathan 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa,
956 1.1 jonathan 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8,
957 1.1 jonathan 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80,
958 1.1 jonathan 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
959 1.1 jonathan 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f,
960 1.1 jonathan 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1,
961 1.1 jonathan 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87,
962 1.1 jonathan 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
963 1.1 jonathan 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f,
964 1.1 jonathan 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0
965 1.1 jonathan };
966 1.1 jonathan
967 1.1 jonathan /*
968 1.1 jonathan * `pc3' termcap emulation.
969 1.1 jonathan */
970 1.1 jonathan void
971 1.1 jonathan sput(cp, n)
972 1.1 jonathan u_char *cp;
973 1.1 jonathan int n;
974 1.1 jonathan {
975 1.27 soda struct pccons_context *pc = &pccons_console_context;
976 1.1 jonathan u_char c, scroll = 0;
977 1.1 jonathan
978 1.1 jonathan if (pc_xmode > 0)
979 1.1 jonathan return;
980 1.1 jonathan
981 1.1 jonathan if (crtat == 0) {
982 1.13 soda volatile u_short *cp;
983 1.1 jonathan u_short was;
984 1.1 jonathan unsigned cursorat;
985 1.1 jonathan
986 1.27 soda cp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh);
987 1.1 jonathan was = *cp;
988 1.27 soda *cp = 0xA55A;
989 1.1 jonathan if (*cp != 0xA55A) {
990 1.27 soda cp = bus_space_vaddr(pc->pc_crt_memt,
991 1.27 soda pc->pc_mono_memh);
992 1.27 soda pc->pc_6845_ioh = pc->pc_mono_ioh;
993 1.27 soda pc->pc_crt_memh = pc->pc_mono_memh;
994 1.1 jonathan vs.color = 0;
995 1.1 jonathan } else {
996 1.1 jonathan *cp = was;
997 1.27 soda pc->pc_6845_ioh = pc->pc_cga_ioh;
998 1.27 soda pc->pc_crt_memh = pc->pc_cga_memh;
999 1.1 jonathan vs.color = 1;
1000 1.1 jonathan }
1001 1.1 jonathan
1002 1.1 jonathan #ifdef FAT_CURSOR
1003 1.1 jonathan cursor_shape = 0x0012;
1004 1.1 jonathan #else
1005 1.1 jonathan get_cursor_shape();
1006 1.1 jonathan #endif
1007 1.1 jonathan
1008 1.13 soda bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
1009 1.13 soda vs.nchr = vs.ncol * vs.nrow;
1010 1.13 soda vs.col--;
1011 1.13 soda vs.row--;
1012 1.13 soda cursorat = vs.ncol * vs.row + vs.col;
1013 1.13 soda vs.at = FG_LIGHTGREY | BG_BLACK;
1014 1.13 soda
1015 1.1 jonathan Crtat = (u_short *)cp;
1016 1.13 soda crtat = Crtat + cursorat;
1017 1.1 jonathan
1018 1.1 jonathan if (vs.color == 0)
1019 1.1 jonathan vs.so_at = FG_BLACK | BG_LIGHTGREY;
1020 1.1 jonathan else
1021 1.1 jonathan vs.so_at = FG_YELLOW | BG_BLACK;
1022 1.1 jonathan
1023 1.1 jonathan fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
1024 1.1 jonathan }
1025 1.1 jonathan
1026 1.1 jonathan while (n--) {
1027 1.1 jonathan if (!(c = *cp++))
1028 1.1 jonathan continue;
1029 1.1 jonathan
1030 1.1 jonathan switch (c) {
1031 1.1 jonathan case 0x1B:
1032 1.1 jonathan if (vs.state >= VSS_ESCAPE) {
1033 1.32 tsutsui wrtchar(c, vs.so_at);
1034 1.1 jonathan vs.state = 0;
1035 1.1 jonathan goto maybe_scroll;
1036 1.1 jonathan } else
1037 1.1 jonathan vs.state = VSS_ESCAPE;
1038 1.1 jonathan break;
1039 1.1 jonathan
1040 1.13 soda case 0x9B: /* CSI */
1041 1.13 soda vs.cx = vs.cy = 0;
1042 1.13 soda vs.state = VSS_EBRACE;
1043 1.13 soda break;
1044 1.13 soda
1045 1.1 jonathan case '\t': {
1046 1.1 jonathan int inccol = 8 - (vs.col & 7);
1047 1.1 jonathan crtat += inccol;
1048 1.1 jonathan vs.col += inccol;
1049 1.1 jonathan }
1050 1.1 jonathan maybe_scroll:
1051 1.13 soda if (vs.col >= vs.ncol) {
1052 1.13 soda vs.col -= vs.ncol;
1053 1.1 jonathan scroll = 1;
1054 1.1 jonathan }
1055 1.1 jonathan break;
1056 1.1 jonathan
1057 1.13 soda case '\b':
1058 1.1 jonathan if (crtat <= Crtat)
1059 1.1 jonathan break;
1060 1.1 jonathan --crtat;
1061 1.1 jonathan if (--vs.col < 0)
1062 1.13 soda vs.col += vs.ncol; /* non-destructive backspace */
1063 1.1 jonathan break;
1064 1.1 jonathan
1065 1.1 jonathan case '\r':
1066 1.1 jonathan crtat -= vs.col;
1067 1.1 jonathan vs.col = 0;
1068 1.1 jonathan break;
1069 1.1 jonathan
1070 1.1 jonathan case '\n':
1071 1.1 jonathan crtat += vs.ncol;
1072 1.1 jonathan scroll = 1;
1073 1.1 jonathan break;
1074 1.1 jonathan
1075 1.1 jonathan default:
1076 1.1 jonathan switch (vs.state) {
1077 1.1 jonathan case 0:
1078 1.1 jonathan if (c == '\a')
1079 1.1 jonathan sysbeep(BEEP_FREQ, BEEP_TIME);
1080 1.1 jonathan else {
1081 1.1 jonathan /*
1082 1.1 jonathan * If we're outputting multiple printed
1083 1.1 jonathan * characters, just blast them to the
1084 1.1 jonathan * screen until we reach the end of the
1085 1.1 jonathan * buffer or a control character. This
1086 1.1 jonathan * saves time by short-circuiting the
1087 1.1 jonathan * switch.
1088 1.1 jonathan * If we reach the end of the line, we
1089 1.1 jonathan * break to do a scroll check.
1090 1.1 jonathan */
1091 1.1 jonathan for (;;) {
1092 1.1 jonathan if (c & 0x80)
1093 1.1 jonathan c = iso2ibm437[c&0x7f];
1094 1.1 jonathan
1095 1.1 jonathan if (vs.so)
1096 1.1 jonathan wrtchar(c, vs.so_at);
1097 1.1 jonathan else
1098 1.1 jonathan wrtchar(c, vs.at);
1099 1.1 jonathan if (vs.col >= vs.ncol) {
1100 1.1 jonathan vs.col = 0;
1101 1.1 jonathan scroll = 1;
1102 1.1 jonathan break;
1103 1.1 jonathan }
1104 1.1 jonathan if (!n || (c = *cp) < ' ')
1105 1.1 jonathan break;
1106 1.1 jonathan n--, cp++;
1107 1.1 jonathan }
1108 1.1 jonathan }
1109 1.1 jonathan break;
1110 1.1 jonathan case VSS_ESCAPE:
1111 1.13 soda switch (c) {
1112 1.13 soda case '[': /* Start ESC [ sequence */
1113 1.13 soda vs.cx = vs.cy = 0;
1114 1.13 soda vs.state = VSS_EBRACE;
1115 1.13 soda break;
1116 1.13 soda case 'c': /* Create screen & home */
1117 1.13 soda fillw((vs.at << 8) | ' ',
1118 1.13 soda Crtat, vs.nchr);
1119 1.13 soda crtat = Crtat;
1120 1.13 soda vs.col = 0;
1121 1.13 soda vs.state = 0;
1122 1.13 soda break;
1123 1.13 soda case '7': /* save cursor pos */
1124 1.13 soda vs.offset = crtat - Crtat;
1125 1.13 soda vs.state = 0;
1126 1.13 soda break;
1127 1.13 soda case '8': /* restore cursor pos */
1128 1.13 soda crtat = Crtat + vs.offset;
1129 1.13 soda vs.row = vs.offset / vs.ncol;
1130 1.13 soda vs.col = vs.offset % vs.ncol;
1131 1.13 soda vs.state = 0;
1132 1.13 soda break;
1133 1.13 soda default: /* Invalid, clear state */
1134 1.32 tsutsui wrtchar(c, vs.so_at);
1135 1.13 soda vs.state = 0;
1136 1.13 soda goto maybe_scroll;
1137 1.1 jonathan }
1138 1.1 jonathan break;
1139 1.13 soda
1140 1.1 jonathan default: /* VSS_EBRACE or VSS_EPARAM */
1141 1.1 jonathan switch (c) {
1142 1.1 jonathan int pos;
1143 1.1 jonathan case 'm':
1144 1.1 jonathan if (!vs.cx)
1145 1.1 jonathan vs.so = 0;
1146 1.1 jonathan else
1147 1.1 jonathan vs.so = 1;
1148 1.1 jonathan vs.state = 0;
1149 1.1 jonathan break;
1150 1.1 jonathan case 'A': { /* back cx rows */
1151 1.1 jonathan int cx = vs.cx;
1152 1.1 jonathan if (cx <= 0)
1153 1.1 jonathan cx = 1;
1154 1.1 jonathan else
1155 1.1 jonathan cx %= vs.nrow;
1156 1.1 jonathan pos = crtat - Crtat;
1157 1.1 jonathan pos -= vs.ncol * cx;
1158 1.1 jonathan if (pos < 0)
1159 1.1 jonathan pos += vs.nchr;
1160 1.1 jonathan crtat = Crtat + pos;
1161 1.1 jonathan vs.state = 0;
1162 1.1 jonathan break;
1163 1.1 jonathan }
1164 1.1 jonathan case 'B': { /* down cx rows */
1165 1.1 jonathan int cx = vs.cx;
1166 1.1 jonathan if (cx <= 0)
1167 1.1 jonathan cx = 1;
1168 1.1 jonathan else
1169 1.1 jonathan cx %= vs.nrow;
1170 1.1 jonathan pos = crtat - Crtat;
1171 1.1 jonathan pos += vs.ncol * cx;
1172 1.32 tsutsui if (pos >= vs.nchr)
1173 1.1 jonathan pos -= vs.nchr;
1174 1.1 jonathan crtat = Crtat + pos;
1175 1.1 jonathan vs.state = 0;
1176 1.1 jonathan break;
1177 1.1 jonathan }
1178 1.1 jonathan case 'C': { /* right cursor */
1179 1.1 jonathan int cx = vs.cx,
1180 1.1 jonathan col = vs.col;
1181 1.1 jonathan if (cx <= 0)
1182 1.1 jonathan cx = 1;
1183 1.1 jonathan else
1184 1.1 jonathan cx %= vs.ncol;
1185 1.1 jonathan pos = crtat - Crtat;
1186 1.1 jonathan pos += cx;
1187 1.1 jonathan col += cx;
1188 1.1 jonathan if (col >= vs.ncol) {
1189 1.1 jonathan pos -= vs.ncol;
1190 1.1 jonathan col -= vs.ncol;
1191 1.1 jonathan }
1192 1.1 jonathan vs.col = col;
1193 1.1 jonathan crtat = Crtat + pos;
1194 1.1 jonathan vs.state = 0;
1195 1.1 jonathan break;
1196 1.1 jonathan }
1197 1.1 jonathan case 'D': { /* left cursor */
1198 1.1 jonathan int cx = vs.cx,
1199 1.1 jonathan col = vs.col;
1200 1.1 jonathan if (cx <= 0)
1201 1.1 jonathan cx = 1;
1202 1.1 jonathan else
1203 1.1 jonathan cx %= vs.ncol;
1204 1.1 jonathan pos = crtat - Crtat;
1205 1.1 jonathan pos -= cx;
1206 1.1 jonathan col -= cx;
1207 1.1 jonathan if (col < 0) {
1208 1.1 jonathan pos += vs.ncol;
1209 1.1 jonathan col += vs.ncol;
1210 1.1 jonathan }
1211 1.1 jonathan vs.col = col;
1212 1.1 jonathan crtat = Crtat + pos;
1213 1.1 jonathan vs.state = 0;
1214 1.1 jonathan break;
1215 1.1 jonathan }
1216 1.1 jonathan case 'J': /* Clear ... */
1217 1.1 jonathan switch (vs.cx) {
1218 1.1 jonathan case 0:
1219 1.1 jonathan /* ... to end of display */
1220 1.13 soda fillw((vs.at << 8) | ' ',
1221 1.13 soda crtat,
1222 1.1 jonathan Crtat + vs.nchr - crtat);
1223 1.1 jonathan break;
1224 1.1 jonathan case 1:
1225 1.1 jonathan /* ... to next location */
1226 1.13 soda fillw((vs.at << 8) | ' ',
1227 1.13 soda Crtat,
1228 1.1 jonathan crtat - Crtat + 1);
1229 1.1 jonathan break;
1230 1.1 jonathan case 2:
1231 1.1 jonathan /* ... whole display */
1232 1.13 soda fillw((vs.at << 8) | ' ',
1233 1.13 soda Crtat,
1234 1.1 jonathan vs.nchr);
1235 1.1 jonathan break;
1236 1.1 jonathan }
1237 1.1 jonathan vs.state = 0;
1238 1.1 jonathan break;
1239 1.1 jonathan case 'K': /* Clear line ... */
1240 1.1 jonathan switch (vs.cx) {
1241 1.1 jonathan case 0:
1242 1.1 jonathan /* ... current to EOL */
1243 1.13 soda fillw((vs.at << 8) | ' ',
1244 1.13 soda crtat,
1245 1.1 jonathan vs.ncol - vs.col);
1246 1.1 jonathan break;
1247 1.1 jonathan case 1:
1248 1.1 jonathan /* ... beginning to next */
1249 1.1 jonathan fillw((vs.at << 8) | ' ',
1250 1.1 jonathan crtat - vs.col,
1251 1.1 jonathan vs.col + 1);
1252 1.1 jonathan break;
1253 1.1 jonathan case 2:
1254 1.1 jonathan /* ... entire line */
1255 1.1 jonathan fillw((vs.at << 8) | ' ',
1256 1.1 jonathan crtat - vs.col, vs.ncol);
1257 1.1 jonathan break;
1258 1.1 jonathan }
1259 1.1 jonathan vs.state = 0;
1260 1.1 jonathan break;
1261 1.1 jonathan case 'f': /* in system V consoles */
1262 1.1 jonathan case 'H': { /* Cursor move */
1263 1.1 jonathan int cx = vs.cx,
1264 1.1 jonathan cy = vs.cy;
1265 1.1 jonathan if (!cx || !cy) {
1266 1.1 jonathan crtat = Crtat;
1267 1.1 jonathan vs.col = 0;
1268 1.1 jonathan } else {
1269 1.1 jonathan if (cx > vs.nrow)
1270 1.1 jonathan cx = vs.nrow;
1271 1.1 jonathan if (cy > vs.ncol)
1272 1.1 jonathan cy = vs.ncol;
1273 1.1 jonathan crtat = Crtat +
1274 1.1 jonathan (cx - 1) * vs.ncol + cy - 1;
1275 1.1 jonathan vs.col = cy - 1;
1276 1.1 jonathan }
1277 1.1 jonathan vs.state = 0;
1278 1.1 jonathan break;
1279 1.1 jonathan }
1280 1.1 jonathan case 'M': { /* delete cx rows */
1281 1.1 jonathan u_short *crtAt = crtat - vs.col;
1282 1.1 jonathan int cx = vs.cx,
1283 1.1 jonathan row = (crtAt - Crtat) / vs.ncol,
1284 1.1 jonathan nrow = vs.nrow - row;
1285 1.1 jonathan if (cx <= 0)
1286 1.1 jonathan cx = 1;
1287 1.1 jonathan else if (cx > nrow)
1288 1.1 jonathan cx = nrow;
1289 1.1 jonathan if (cx < nrow)
1290 1.13 soda #ifdef PCCONS_FORCE_WORD
1291 1.13 soda wcopy(crtAt + vs.ncol * cx,
1292 1.13 soda crtAt, vs.ncol * (nrow -
1293 1.13 soda cx) * CHR);
1294 1.13 soda #else
1295 1.1 jonathan bcopy(crtAt + vs.ncol * cx,
1296 1.1 jonathan crtAt, vs.ncol * (nrow -
1297 1.1 jonathan cx) * CHR);
1298 1.13 soda #endif
1299 1.1 jonathan fillw((vs.at << 8) | ' ',
1300 1.1 jonathan crtAt + vs.ncol * (nrow - cx),
1301 1.1 jonathan vs.ncol * cx);
1302 1.1 jonathan vs.state = 0;
1303 1.1 jonathan break;
1304 1.1 jonathan }
1305 1.1 jonathan case 'S': { /* scroll up cx lines */
1306 1.1 jonathan int cx = vs.cx;
1307 1.1 jonathan if (cx <= 0)
1308 1.1 jonathan cx = 1;
1309 1.1 jonathan else if (cx > vs.nrow)
1310 1.1 jonathan cx = vs.nrow;
1311 1.1 jonathan if (cx < vs.nrow)
1312 1.13 soda #ifdef PCCONS_FORCE_WORD
1313 1.13 soda wcopy(Crtat + vs.ncol * cx,
1314 1.13 soda Crtat, vs.ncol * (vs.nrow -
1315 1.13 soda cx) * CHR);
1316 1.13 soda #else
1317 1.1 jonathan bcopy(Crtat + vs.ncol * cx,
1318 1.1 jonathan Crtat, vs.ncol * (vs.nrow -
1319 1.1 jonathan cx) * CHR);
1320 1.13 soda #endif
1321 1.1 jonathan fillw((vs.at << 8) | ' ',
1322 1.1 jonathan Crtat + vs.ncol * (vs.nrow - cx),
1323 1.1 jonathan vs.ncol * cx);
1324 1.13 soda /* crtat -= vs.ncol * cx; XXX */
1325 1.1 jonathan vs.state = 0;
1326 1.1 jonathan break;
1327 1.1 jonathan }
1328 1.1 jonathan case 'L': { /* insert cx rows */
1329 1.1 jonathan u_short *crtAt = crtat - vs.col;
1330 1.1 jonathan int cx = vs.cx,
1331 1.1 jonathan row = (crtAt - Crtat) / vs.ncol,
1332 1.1 jonathan nrow = vs.nrow - row;
1333 1.1 jonathan if (cx <= 0)
1334 1.1 jonathan cx = 1;
1335 1.1 jonathan else if (cx > nrow)
1336 1.1 jonathan cx = nrow;
1337 1.1 jonathan if (cx < nrow)
1338 1.13 soda #ifdef PCCONS_FORCE_WORD
1339 1.13 soda wcopy(crtAt,
1340 1.13 soda crtAt + vs.ncol * cx,
1341 1.13 soda vs.ncol * (nrow - cx) *
1342 1.13 soda CHR);
1343 1.13 soda #else
1344 1.1 jonathan bcopy(crtAt,
1345 1.1 jonathan crtAt + vs.ncol * cx,
1346 1.1 jonathan vs.ncol * (nrow - cx) *
1347 1.1 jonathan CHR);
1348 1.13 soda #endif
1349 1.1 jonathan fillw((vs.at << 8) | ' ', crtAt,
1350 1.1 jonathan vs.ncol * cx);
1351 1.1 jonathan vs.state = 0;
1352 1.1 jonathan break;
1353 1.1 jonathan }
1354 1.1 jonathan case 'T': { /* scroll down cx lines */
1355 1.1 jonathan int cx = vs.cx;
1356 1.1 jonathan if (cx <= 0)
1357 1.1 jonathan cx = 1;
1358 1.1 jonathan else if (cx > vs.nrow)
1359 1.1 jonathan cx = vs.nrow;
1360 1.1 jonathan if (cx < vs.nrow)
1361 1.13 soda #ifdef PCCONS_FORCE_WORD
1362 1.13 soda wcopy(Crtat,
1363 1.13 soda Crtat + vs.ncol * cx,
1364 1.13 soda vs.ncol * (vs.nrow - cx) *
1365 1.13 soda CHR);
1366 1.13 soda #else
1367 1.1 jonathan bcopy(Crtat,
1368 1.1 jonathan Crtat + vs.ncol * cx,
1369 1.1 jonathan vs.ncol * (vs.nrow - cx) *
1370 1.1 jonathan CHR);
1371 1.13 soda #endif
1372 1.1 jonathan fillw((vs.at << 8) | ' ', Crtat,
1373 1.1 jonathan vs.ncol * cx);
1374 1.13 soda /* crtat += vs.ncol * cx; XXX */
1375 1.1 jonathan vs.state = 0;
1376 1.1 jonathan break;
1377 1.1 jonathan }
1378 1.1 jonathan case ';': /* Switch params in cursor def */
1379 1.1 jonathan vs.state = VSS_EPARAM;
1380 1.1 jonathan break;
1381 1.1 jonathan case 'r':
1382 1.1 jonathan vs.so_at = (vs.cx & FG_MASK) |
1383 1.1 jonathan ((vs.cy << 4) & BG_MASK);
1384 1.1 jonathan vs.state = 0;
1385 1.1 jonathan break;
1386 1.13 soda case 's': /* save cursor pos */
1387 1.13 soda vs.offset = crtat - Crtat;
1388 1.13 soda vs.state = 0;
1389 1.13 soda break;
1390 1.13 soda case 'u': /* restore cursor pos */
1391 1.13 soda crtat = Crtat + vs.offset;
1392 1.13 soda vs.row = vs.offset / vs.ncol;
1393 1.13 soda vs.col = vs.offset % vs.ncol;
1394 1.13 soda vs.state = 0;
1395 1.13 soda break;
1396 1.1 jonathan case 'x': /* set attributes */
1397 1.1 jonathan switch (vs.cx) {
1398 1.1 jonathan case 0:
1399 1.1 jonathan vs.at = FG_LIGHTGREY | BG_BLACK;
1400 1.1 jonathan break;
1401 1.1 jonathan case 1:
1402 1.1 jonathan /* ansi background */
1403 1.1 jonathan if (!vs.color)
1404 1.1 jonathan break;
1405 1.1 jonathan vs.at &= FG_MASK;
1406 1.1 jonathan vs.at |= bgansitopc[vs.cy & 7];
1407 1.1 jonathan break;
1408 1.1 jonathan case 2:
1409 1.1 jonathan /* ansi foreground */
1410 1.1 jonathan if (!vs.color)
1411 1.1 jonathan break;
1412 1.1 jonathan vs.at &= BG_MASK;
1413 1.1 jonathan vs.at |= fgansitopc[vs.cy & 7];
1414 1.1 jonathan break;
1415 1.1 jonathan case 3:
1416 1.1 jonathan /* pc text attribute */
1417 1.1 jonathan if (vs.state >= VSS_EPARAM)
1418 1.1 jonathan vs.at = vs.cy;
1419 1.1 jonathan break;
1420 1.1 jonathan }
1421 1.1 jonathan vs.state = 0;
1422 1.1 jonathan break;
1423 1.32 tsutsui
1424 1.1 jonathan default: /* Only numbers valid here */
1425 1.1 jonathan if ((c >= '0') && (c <= '9')) {
1426 1.1 jonathan if (vs.state >= VSS_EPARAM) {
1427 1.1 jonathan vs.cy *= 10;
1428 1.1 jonathan vs.cy += c - '0';
1429 1.1 jonathan } else {
1430 1.1 jonathan vs.cx *= 10;
1431 1.1 jonathan vs.cx += c - '0';
1432 1.1 jonathan }
1433 1.1 jonathan } else
1434 1.1 jonathan vs.state = 0;
1435 1.1 jonathan break;
1436 1.1 jonathan }
1437 1.1 jonathan break;
1438 1.1 jonathan }
1439 1.1 jonathan }
1440 1.1 jonathan if (scroll) {
1441 1.1 jonathan scroll = 0;
1442 1.1 jonathan /* scroll check */
1443 1.1 jonathan if (crtat >= Crtat + vs.nchr) {
1444 1.1 jonathan if (!kernel) {
1445 1.1 jonathan int s = spltty();
1446 1.13 soda if (lock_state & KB_SCROLL)
1447 1.13 soda tsleep(&lock_state,
1448 1.1 jonathan PUSER, "pcputc", 0);
1449 1.1 jonathan splx(s);
1450 1.1 jonathan }
1451 1.13 soda #if PCCONS_FORCE_WORD
1452 1.13 soda wcopy(Crtat + vs.ncol, Crtat,
1453 1.13 soda (vs.nchr - vs.ncol) * CHR);
1454 1.13 soda #else
1455 1.1 jonathan bcopy(Crtat + vs.ncol, Crtat,
1456 1.1 jonathan (vs.nchr - vs.ncol) * CHR);
1457 1.13 soda #endif
1458 1.1 jonathan fillw((vs.at << 8) | ' ',
1459 1.13 soda Crtat + vs.nchr - vs.ncol,
1460 1.13 soda vs.ncol);
1461 1.1 jonathan crtat -= vs.ncol;
1462 1.1 jonathan }
1463 1.1 jonathan }
1464 1.1 jonathan }
1465 1.1 jonathan async_update();
1466 1.1 jonathan }
1467 1.1 jonathan
1468 1.13 soda /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
1469 1.13 soda left and right shift when reading the keyboard map */
1470 1.13 soda static pccons_keymap_t scan_codes[KB_NUM_KEYS] = {
1471 1.13 soda /* type unshift shift control altgr shift_altgr scancode */
1472 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 0 unused */
1473 1.13 soda { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */
1474 1.13 soda { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */
1475 1.13 soda { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */
1476 1.13 soda { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */
1477 1.13 soda { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */
1478 1.13 soda { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */
1479 1.13 soda { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */
1480 1.13 soda { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */
1481 1.13 soda { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */
1482 1.13 soda { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */
1483 1.13 soda { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */
1484 1.13 soda { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */
1485 1.13 soda { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */
1486 1.13 soda { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */
1487 1.13 soda { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */
1488 1.13 soda { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */
1489 1.13 soda { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */
1490 1.13 soda { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */
1491 1.13 soda { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */
1492 1.13 soda { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */
1493 1.13 soda { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */
1494 1.13 soda { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */
1495 1.13 soda { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */
1496 1.13 soda { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */
1497 1.13 soda { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */
1498 1.13 soda { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */
1499 1.13 soda { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */
1500 1.13 soda { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */
1501 1.13 soda { KB_CTL, "", "", "", "", ""}, /* 29 control */
1502 1.13 soda { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */
1503 1.13 soda { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */
1504 1.13 soda { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */
1505 1.13 soda { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */
1506 1.13 soda { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */
1507 1.13 soda { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */
1508 1.13 soda { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */
1509 1.13 soda { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */
1510 1.13 soda { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */
1511 1.13 soda { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */
1512 1.13 soda { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */
1513 1.13 soda { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */
1514 1.13 soda { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */
1515 1.13 soda { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */
1516 1.13 soda { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */
1517 1.13 soda { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */
1518 1.13 soda { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */
1519 1.13 soda { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */
1520 1.13 soda { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */
1521 1.13 soda { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */
1522 1.13 soda { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */
1523 1.13 soda { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */
1524 1.13 soda { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */
1525 1.13 soda { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */
1526 1.13 soda { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */
1527 1.13 soda { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */
1528 1.13 soda { KB_ALT, "", "", "", "", ""}, /* 56 alt */
1529 1.13 soda { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */
1530 1.13 soda { KB_CAPS, "", "", "", "", ""}, /* 58 caps */
1531 1.13 soda { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */
1532 1.13 soda { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */
1533 1.13 soda { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */
1534 1.13 soda { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */
1535 1.13 soda { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */
1536 1.13 soda { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */
1537 1.13 soda { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */
1538 1.13 soda { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */
1539 1.13 soda { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */
1540 1.13 soda { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */
1541 1.13 soda { KB_NUM, "", "", "", "", ""}, /* 69 num lock */
1542 1.13 soda { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */
1543 1.13 soda { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */
1544 1.13 soda { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */
1545 1.13 soda { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */
1546 1.13 soda { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */
1547 1.13 soda { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */
1548 1.13 soda { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */
1549 1.13 soda { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */
1550 1.13 soda { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */
1551 1.13 soda { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */
1552 1.13 soda { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */
1553 1.13 soda { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */
1554 1.13 soda { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */
1555 1.13 soda { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */
1556 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 84 0 */
1557 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 85 0 */
1558 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 86 0 */
1559 1.13 soda { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */
1560 1.13 soda { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */
1561 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 89 0 */
1562 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 90 0 */
1563 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 91 0 */
1564 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 92 0 */
1565 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 93 0 */
1566 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 94 0 */
1567 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 95 0 */
1568 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 96 0 */
1569 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 97 0 */
1570 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 98 0 */
1571 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 99 0 */
1572 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 100 */
1573 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 101 */
1574 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 102 */
1575 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 103 */
1576 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 104 */
1577 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 105 */
1578 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 106 */
1579 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 107 */
1580 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 108 */
1581 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 109 */
1582 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 110 */
1583 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 111 */
1584 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 112 */
1585 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 113 */
1586 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 114 */
1587 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 115 */
1588 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 116 */
1589 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 117 */
1590 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 118 */
1591 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 119 */
1592 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 120 */
1593 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 121 */
1594 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 122 */
1595 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 123 */
1596 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 124 */
1597 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 125 */
1598 1.13 soda { KB_NONE, "", "", "", "", ""}, /* 126 */
1599 1.13 soda { KB_NONE, "", "", "", "", ""} /* 127 */
1600 1.1 jonathan };
1601 1.1 jonathan
1602 1.1 jonathan /*
1603 1.1 jonathan * Get characters from the keyboard. If none are present, return NULL.
1604 1.1 jonathan */
1605 1.1 jonathan char *
1606 1.1 jonathan sget()
1607 1.1 jonathan {
1608 1.1 jonathan u_char dt;
1609 1.1 jonathan static u_char extended = 0, shift_state = 0;
1610 1.1 jonathan static u_char capchar[2];
1611 1.1 jonathan
1612 1.1 jonathan top:
1613 1.1 jonathan KBD_DELAY;
1614 1.27 soda dt = kbd_data_read_1();
1615 1.1 jonathan
1616 1.1 jonathan switch (dt) {
1617 1.1 jonathan case KBR_ACK: case KBR_ECHO:
1618 1.1 jonathan kb_oq_get = (kb_oq_get + 1) & 7;
1619 1.1 jonathan if(kb_oq_get != kb_oq_put) {
1620 1.27 soda kbd_data_write_1(kb_oq[kb_oq_get]);
1621 1.1 jonathan }
1622 1.1 jonathan goto loop;
1623 1.1 jonathan case KBR_RESEND:
1624 1.27 soda kbd_data_write_1(kb_oq[kb_oq_get]);
1625 1.1 jonathan goto loop;
1626 1.1 jonathan }
1627 1.1 jonathan
1628 1.1 jonathan if (pc_xmode > 0) {
1629 1.1 jonathan #if defined(DDB) && defined(XSERVER_DDB)
1630 1.1 jonathan /* F12 enters the debugger while in X mode */
1631 1.1 jonathan if (dt == 88)
1632 1.1 jonathan Debugger();
1633 1.1 jonathan #endif
1634 1.1 jonathan capchar[0] = dt;
1635 1.1 jonathan capchar[1] = 0;
1636 1.1 jonathan /*
1637 1.1 jonathan * Check for locking keys.
1638 1.1 jonathan *
1639 1.1 jonathan * XXX Setting the LEDs this way is a bit bogus. What if the
1640 1.1 jonathan * keyboard has been remapped in X?
1641 1.1 jonathan */
1642 1.13 soda switch (scan_codes[dt & 0x7f].type) {
1643 1.13 soda case KB_NUM:
1644 1.1 jonathan if (dt & 0x80) {
1645 1.13 soda shift_state &= ~KB_NUM;
1646 1.1 jonathan break;
1647 1.1 jonathan }
1648 1.13 soda if (shift_state & KB_NUM)
1649 1.1 jonathan break;
1650 1.13 soda shift_state |= KB_NUM;
1651 1.13 soda lock_state ^= KB_NUM;
1652 1.1 jonathan async_update();
1653 1.1 jonathan break;
1654 1.13 soda case KB_CAPS:
1655 1.1 jonathan if (dt & 0x80) {
1656 1.13 soda shift_state &= ~KB_CAPS;
1657 1.1 jonathan break;
1658 1.1 jonathan }
1659 1.13 soda if (shift_state & KB_CAPS)
1660 1.1 jonathan break;
1661 1.13 soda shift_state |= KB_CAPS;
1662 1.13 soda lock_state ^= KB_CAPS;
1663 1.1 jonathan async_update();
1664 1.1 jonathan break;
1665 1.13 soda case KB_SCROLL:
1666 1.1 jonathan if (dt & 0x80) {
1667 1.13 soda shift_state &= ~KB_SCROLL;
1668 1.1 jonathan break;
1669 1.1 jonathan }
1670 1.13 soda if (shift_state & KB_SCROLL)
1671 1.1 jonathan break;
1672 1.13 soda shift_state |= KB_SCROLL;
1673 1.13 soda lock_state ^= KB_SCROLL;
1674 1.13 soda if ((lock_state & KB_SCROLL) == 0)
1675 1.1 jonathan wakeup((caddr_t)&lock_state);
1676 1.1 jonathan async_update();
1677 1.1 jonathan break;
1678 1.1 jonathan }
1679 1.1 jonathan return capchar;
1680 1.1 jonathan }
1681 1.1 jonathan
1682 1.1 jonathan switch (dt) {
1683 1.1 jonathan case KBR_EXTENDED:
1684 1.1 jonathan extended = 1;
1685 1.1 jonathan goto loop;
1686 1.1 jonathan }
1687 1.1 jonathan
1688 1.13 soda #ifdef DDB
1689 1.1 jonathan /*
1690 1.1 jonathan * Check for cntl-alt-esc.
1691 1.1 jonathan */
1692 1.13 soda if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
1693 1.13 soda /* XXX - check pccons_is_console */
1694 1.13 soda Debugger();
1695 1.1 jonathan dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */
1696 1.1 jonathan }
1697 1.1 jonathan #endif
1698 1.1 jonathan
1699 1.1 jonathan /*
1700 1.1 jonathan * Check for make/break.
1701 1.1 jonathan */
1702 1.1 jonathan if (dt & 0x80) {
1703 1.1 jonathan /*
1704 1.1 jonathan * break
1705 1.1 jonathan */
1706 1.1 jonathan dt &= 0x7f;
1707 1.13 soda switch (scan_codes[dt].type) {
1708 1.13 soda case KB_NUM:
1709 1.13 soda shift_state &= ~KB_NUM;
1710 1.1 jonathan break;
1711 1.13 soda case KB_CAPS:
1712 1.13 soda shift_state &= ~KB_CAPS;
1713 1.1 jonathan break;
1714 1.13 soda case KB_SCROLL:
1715 1.13 soda shift_state &= ~KB_SCROLL;
1716 1.1 jonathan break;
1717 1.13 soda case KB_SHIFT:
1718 1.13 soda shift_state &= ~KB_SHIFT;
1719 1.1 jonathan break;
1720 1.13 soda case KB_ALT:
1721 1.1 jonathan if (extended)
1722 1.13 soda shift_state &= ~KB_ALTGR;
1723 1.1 jonathan else
1724 1.13 soda shift_state &= ~KB_ALT;
1725 1.1 jonathan break;
1726 1.13 soda case KB_CTL:
1727 1.13 soda shift_state &= ~KB_CTL;
1728 1.1 jonathan break;
1729 1.1 jonathan }
1730 1.1 jonathan } else {
1731 1.1 jonathan /*
1732 1.1 jonathan * make
1733 1.1 jonathan */
1734 1.13 soda switch (scan_codes[dt].type) {
1735 1.1 jonathan /*
1736 1.1 jonathan * locking keys
1737 1.1 jonathan */
1738 1.13 soda case KB_NUM:
1739 1.13 soda if (shift_state & KB_NUM)
1740 1.1 jonathan break;
1741 1.13 soda shift_state |= KB_NUM;
1742 1.13 soda lock_state ^= KB_NUM;
1743 1.1 jonathan async_update();
1744 1.1 jonathan break;
1745 1.13 soda case KB_CAPS:
1746 1.13 soda if (shift_state & KB_CAPS)
1747 1.1 jonathan break;
1748 1.13 soda shift_state |= KB_CAPS;
1749 1.13 soda lock_state ^= KB_CAPS;
1750 1.1 jonathan async_update();
1751 1.1 jonathan break;
1752 1.13 soda case KB_SCROLL:
1753 1.13 soda if (shift_state & KB_SCROLL)
1754 1.1 jonathan break;
1755 1.13 soda shift_state |= KB_SCROLL;
1756 1.13 soda lock_state ^= KB_SCROLL;
1757 1.13 soda if ((lock_state & KB_SCROLL) == 0)
1758 1.1 jonathan wakeup((caddr_t)&lock_state);
1759 1.1 jonathan async_update();
1760 1.1 jonathan break;
1761 1.1 jonathan /*
1762 1.1 jonathan * non-locking keys
1763 1.1 jonathan */
1764 1.13 soda case KB_SHIFT:
1765 1.13 soda shift_state |= KB_SHIFT;
1766 1.1 jonathan break;
1767 1.13 soda case KB_ALT:
1768 1.1 jonathan if (extended)
1769 1.13 soda shift_state |= KB_ALTGR;
1770 1.1 jonathan else
1771 1.13 soda shift_state |= KB_ALT;
1772 1.1 jonathan break;
1773 1.13 soda case KB_CTL:
1774 1.13 soda shift_state |= KB_CTL;
1775 1.1 jonathan break;
1776 1.13 soda case KB_ASCII:
1777 1.13 soda /* control has highest priority */
1778 1.13 soda if (shift_state & KB_CTL)
1779 1.13 soda capchar[0] = scan_codes[dt].ctl[0];
1780 1.13 soda else if (shift_state & KB_ALTGR) {
1781 1.13 soda if (shift_state & KB_SHIFT)
1782 1.13 soda capchar[0] = scan_codes[dt].shift_altgr[0];
1783 1.13 soda else
1784 1.13 soda capchar[0] = scan_codes[dt].altgr[0];
1785 1.1 jonathan }
1786 1.13 soda else {
1787 1.13 soda if (shift_state & KB_SHIFT)
1788 1.13 soda capchar[0] = scan_codes[dt].shift[0];
1789 1.13 soda else
1790 1.13 soda capchar[0] = scan_codes[dt].unshift[0];
1791 1.13 soda }
1792 1.13 soda if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
1793 1.1 jonathan capchar[0] <= 'z') {
1794 1.1 jonathan capchar[0] -= ('a' - 'A');
1795 1.1 jonathan }
1796 1.13 soda capchar[0] |= (shift_state & KB_ALT);
1797 1.1 jonathan extended = 0;
1798 1.1 jonathan return capchar;
1799 1.13 soda case KB_NONE:
1800 1.6 christos printf("keycode %d\n",dt);
1801 1.1 jonathan break;
1802 1.13 soda case KB_FUNC: {
1803 1.1 jonathan char *more_chars;
1804 1.13 soda if (shift_state & KB_SHIFT)
1805 1.13 soda more_chars = scan_codes[dt].shift;
1806 1.13 soda else if (shift_state & KB_CTL)
1807 1.13 soda more_chars = scan_codes[dt].ctl;
1808 1.1 jonathan else
1809 1.13 soda more_chars = scan_codes[dt].unshift;
1810 1.1 jonathan extended = 0;
1811 1.1 jonathan return more_chars;
1812 1.1 jonathan }
1813 1.13 soda case KB_KP: {
1814 1.1 jonathan char *more_chars;
1815 1.13 soda if (shift_state & (KB_SHIFT | KB_CTL) ||
1816 1.13 soda (lock_state & KB_NUM) == 0 || extended)
1817 1.13 soda more_chars = scan_codes[dt].shift;
1818 1.1 jonathan else
1819 1.13 soda more_chars = scan_codes[dt].unshift;
1820 1.1 jonathan extended = 0;
1821 1.1 jonathan return more_chars;
1822 1.1 jonathan }
1823 1.1 jonathan }
1824 1.1 jonathan }
1825 1.1 jonathan
1826 1.1 jonathan extended = 0;
1827 1.1 jonathan loop:
1828 1.27 soda if ((kbd_cmd_read_1() & KBS_DIB) == 0)
1829 1.1 jonathan return 0;
1830 1.1 jonathan goto top;
1831 1.1 jonathan }
1832 1.1 jonathan
1833 1.21 simonb paddr_t
1834 1.1 jonathan pcmmap(dev, offset, nprot)
1835 1.1 jonathan dev_t dev;
1836 1.21 simonb off_t offset;
1837 1.1 jonathan int nprot;
1838 1.1 jonathan {
1839 1.27 soda struct pccons_context *pc = &pccons_console_context;
1840 1.27 soda paddr_t pa;
1841 1.1 jonathan
1842 1.27 soda if (offset >= 0xa0000 && offset < 0xc0000) {
1843 1.27 soda if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1844 1.27 soda return (-1);
1845 1.27 soda pa += offset - pc->pc_config->pc_mono_memaddr;
1846 1.27 soda return (mips_btop(pa));
1847 1.27 soda }
1848 1.27 soda if (offset >= 0x0000 && offset < 0x10000) {
1849 1.27 soda if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa))
1850 1.27 soda return (-1);
1851 1.27 soda pa += offset - pc->pc_config->pc_mono_iobase;
1852 1.27 soda return (mips_btop(pa));
1853 1.27 soda }
1854 1.27 soda if (offset >= 0x40000000 && offset < 0x40800000) {
1855 1.27 soda if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1856 1.27 soda return (-1);
1857 1.27 soda pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr;
1858 1.27 soda return (mips_btop(pa));
1859 1.13 soda }
1860 1.27 soda return (-1);
1861 1.1 jonathan }
1862 1.1 jonathan
1863 1.13 soda void
1864 1.1 jonathan pc_xmode_on()
1865 1.1 jonathan {
1866 1.1 jonathan if (pc_xmode)
1867 1.1 jonathan return;
1868 1.1 jonathan pc_xmode = 1;
1869 1.1 jonathan
1870 1.1 jonathan #ifdef XFREE86_BUG_COMPAT
1871 1.1 jonathan /* If still unchanged, get current shape. */
1872 1.1 jonathan if (cursor_shape == 0xffff)
1873 1.1 jonathan get_cursor_shape();
1874 1.1 jonathan #endif
1875 1.1 jonathan }
1876 1.1 jonathan
1877 1.13 soda void
1878 1.1 jonathan pc_xmode_off()
1879 1.1 jonathan {
1880 1.1 jonathan if (pc_xmode == 0)
1881 1.1 jonathan return;
1882 1.1 jonathan pc_xmode = 0;
1883 1.1 jonathan
1884 1.1 jonathan #ifdef XFREE86_BUG_COMPAT
1885 1.1 jonathan /* XXX It would be hard to justify why the X server doesn't do this. */
1886 1.1 jonathan set_cursor_shape();
1887 1.1 jonathan #endif
1888 1.1 jonathan async_update();
1889 1.1 jonathan }
1890