1*cdc507f0Sandvar /* $NetBSD: pccons.c,v 1.63 2022/05/24 20:50:18 andvar Exp $ */
271f6ef9eSsoda /* $OpenBSD: pccons.c,v 1.22 1999/01/30 22:39:37 imp Exp $ */
3564df9b6Ssoda /* NetBSD: pccons.c,v 1.89 1995/05/04 19:35:20 cgd Exp */
48519eaf8Ssoda
58519eaf8Ssoda /*-
68519eaf8Ssoda * Copyright (c) 1990 The Regents of the University of California.
78519eaf8Ssoda * All rights reserved.
88519eaf8Ssoda *
98519eaf8Ssoda * This code is derived from software contributed to Berkeley by
108519eaf8Ssoda * William Jolitz and Don Ahn.
118519eaf8Ssoda *
12aad01611Sagc * modification, are permitted provided that the following conditions
13aad01611Sagc * are met:
14aad01611Sagc * 1. Redistributions of source code must retain the above copyright
15aad01611Sagc * notice, this list of conditions and the following disclaimer.
16aad01611Sagc * 2. Redistributions in binary form must reproduce the above copyright
17aad01611Sagc * notice, this list of conditions and the following disclaimer in the
18aad01611Sagc * documentation and/or other materials provided with the distribution.
19aad01611Sagc * 3. Neither the name of the University nor the names of its contributors
20aad01611Sagc * may be used to endorse or promote products derived from this software
21aad01611Sagc * without specific prior written permission.
22aad01611Sagc *
23aad01611Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24aad01611Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25aad01611Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26aad01611Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27aad01611Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28aad01611Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29aad01611Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30aad01611Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31aad01611Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32aad01611Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33aad01611Sagc * SUCH DAMAGE.
34aad01611Sagc *
35aad01611Sagc * @(#)pccons.c 5.11 (Berkeley) 5/21/91
36aad01611Sagc */
37aad01611Sagc
38aad01611Sagc /*-
39aad01611Sagc * Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
40aad01611Sagc *
41aad01611Sagc * This code is derived from software contributed to Berkeley by
42aad01611Sagc * William Jolitz and Don Ahn.
43aad01611Sagc *
448519eaf8Ssoda * Copyright (c) 1994 Charles M. Hannum.
458519eaf8Ssoda * Copyright (c) 1992, 1993 Erik Forsberg.
468519eaf8Ssoda *
478519eaf8Ssoda * Redistribution and use in source and binary forms, with or without
488519eaf8Ssoda * modification, are permitted provided that the following conditions
498519eaf8Ssoda * are met:
508519eaf8Ssoda * 1. Redistributions of source code must retain the above copyright
518519eaf8Ssoda * notice, this list of conditions and the following disclaimer.
528519eaf8Ssoda * 2. Redistributions in binary form must reproduce the above copyright
538519eaf8Ssoda * notice, this list of conditions and the following disclaimer in the
548519eaf8Ssoda * documentation and/or other materials provided with the distribution.
558519eaf8Ssoda * 3. All advertising materials mentioning features or use of this software
568519eaf8Ssoda * must display the following acknowledgement:
578519eaf8Ssoda * This product includes software developed by the University of
588519eaf8Ssoda * California, Berkeley and its contributors.
598519eaf8Ssoda * 4. Neither the name of the University nor the names of its contributors
608519eaf8Ssoda * may be used to endorse or promote products derived from this software
618519eaf8Ssoda * without specific prior written permission.
628519eaf8Ssoda *
638519eaf8Ssoda * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
648519eaf8Ssoda * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
658519eaf8Ssoda * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
668519eaf8Ssoda * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
678519eaf8Ssoda * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
688519eaf8Ssoda * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
698519eaf8Ssoda * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
708519eaf8Ssoda * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
718519eaf8Ssoda * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
728519eaf8Ssoda * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
738519eaf8Ssoda * SUCH DAMAGE.
748519eaf8Ssoda *
758519eaf8Ssoda * @(#)pccons.c 5.11 (Berkeley) 5/21/91
768519eaf8Ssoda */
778519eaf8Ssoda
788519eaf8Ssoda /*
798519eaf8Ssoda * code to work keyboard & display for PC-style console
808519eaf8Ssoda */
818519eaf8Ssoda
82a4183603Slukem #include <sys/cdefs.h>
83*cdc507f0Sandvar __KERNEL_RCSID(0, "$NetBSD: pccons.c,v 1.63 2022/05/24 20:50:18 andvar Exp $");
84a4183603Slukem
8571f6ef9eSsoda #include "opt_ddb.h"
8671f6ef9eSsoda
878519eaf8Ssoda #include <sys/param.h>
888519eaf8Ssoda #include <sys/systm.h>
898519eaf8Ssoda #include <sys/tty.h>
908519eaf8Ssoda #include <sys/callout.h>
918519eaf8Ssoda #include <sys/poll.h>
92564df9b6Ssoda #include <sys/conf.h>
93564df9b6Ssoda #include <sys/vnode.h>
94564df9b6Ssoda #include <sys/kernel.h>
95564df9b6Ssoda #include <sys/kcore.h>
96b7abba77Ssoda #include <sys/device.h>
9780373b7eSchs #include <sys/proc.h>
988ccb6c93Selad #include <sys/kauth.h>
998519eaf8Ssoda
100cf10107dSdyoung #include <sys/bus.h>
101b7abba77Ssoda
1020b60e690Stsutsui #include <dev/ic/pcdisplay.h>
1038519eaf8Ssoda #include <machine/pccons.h>
1048519eaf8Ssoda #include <machine/kbdreg.h>
1058519eaf8Ssoda
106564df9b6Ssoda #include <dev/cons.h>
107b7abba77Ssoda #include <dev/isa/isavar.h>
108564df9b6Ssoda
109b7abba77Ssoda #include <arc/arc/arcbios.h>
110b7abba77Ssoda #include <arc/dev/pcconsvar.h>
1115175a612Ssoda
112c234c43aStsutsui #include "ioconf.h"
113c234c43aStsutsui
1148519eaf8Ssoda #define XFREE86_BUG_COMPAT
1158519eaf8Ssoda
1168519eaf8Ssoda #ifndef BEEP_FREQ
1178519eaf8Ssoda #define BEEP_FREQ 1600
1188519eaf8Ssoda #endif
1198519eaf8Ssoda #ifndef BEEP_TIME
1208519eaf8Ssoda #define BEEP_TIME (hz/5)
1218519eaf8Ssoda #endif
1228519eaf8Ssoda
1238519eaf8Ssoda #define PCBURST 128
1248519eaf8Ssoda
1258519eaf8Ssoda static u_short *Crtat; /* pointer to backing store */
1268519eaf8Ssoda static u_short *crtat; /* pointer to current char */
1278519eaf8Ssoda static u_char async, kernel, polling; /* Really, you don't want to know. */
1288519eaf8Ssoda static u_char lock_state = 0x00, /* all off */
1298519eaf8Ssoda old_lock_state = 0xff,
1308519eaf8Ssoda typematic_rate = 0xff, /* don't update until set by user */
1318519eaf8Ssoda old_typematic_rate = 0xff;
1328519eaf8Ssoda static u_short cursor_shape = 0xffff, /* don't update until set by user */
1338519eaf8Ssoda old_cursor_shape = 0xffff;
134564df9b6Ssoda static pccons_keymap_t scan_codes[KB_NUM_KEYS];/* keyboard translation table */
1358519eaf8Ssoda int pc_xmode = 0;
1368519eaf8Ssoda
1378519eaf8Ssoda /*
1388519eaf8Ssoda * Keyboard output queue.
1398519eaf8Ssoda */
1408519eaf8Ssoda int kb_oq_put = 0;
1418519eaf8Ssoda int kb_oq_get = 0;
1428519eaf8Ssoda u_char kb_oq[8];
1438519eaf8Ssoda
1448519eaf8Ssoda #define PCUNIT(x) (minor(x))
1458519eaf8Ssoda
1468519eaf8Ssoda static struct video_state {
1478519eaf8Ssoda int cx, cy; /* escape parameters */
1488519eaf8Ssoda int row, col; /* current cursor position */
1498519eaf8Ssoda int nrow, ncol, nchr; /* current screen geometry */
150564df9b6Ssoda int offset; /* Saved cursor pos */
1518519eaf8Ssoda u_char state; /* parser state */
1528519eaf8Ssoda #define VSS_ESCAPE 1
1538519eaf8Ssoda #define VSS_EBRACE 2
1548519eaf8Ssoda #define VSS_EPARAM 3
1558519eaf8Ssoda char so; /* in standout mode? */
1568519eaf8Ssoda char color; /* color or mono display */
1578519eaf8Ssoda char at; /* normal attributes */
1588519eaf8Ssoda char so_at; /* standout attributes */
1598519eaf8Ssoda } vs;
1608519eaf8Ssoda
16188ab7da9Sad static callout_t async_update_ch;
162b667a5a3Sthorpej
1637fe2a5a0Stsutsui void pc_xmode_on(void);
1647fe2a5a0Stsutsui void pc_xmode_off(void);
1657fe2a5a0Stsutsui static u_char kbc_get8042cmd(void);
1667fe2a5a0Stsutsui int kbd_cmd(u_char, u_char);
1675f1c88d7Sperry static inline int kbd_wait_output(void);
1685f1c88d7Sperry static inline int kbd_wait_input(void);
1697fe2a5a0Stsutsui void kbd_flush_input(void);
1707fe2a5a0Stsutsui void set_cursor_shape(void);
1717fe2a5a0Stsutsui void get_cursor_shape(void);
1727fe2a5a0Stsutsui void async_update(void);
1737fe2a5a0Stsutsui void do_async_update(u_char);
1748519eaf8Ssoda
1757fe2a5a0Stsutsui void pccnputc(dev_t, int c);
1767fe2a5a0Stsutsui int pccngetc(dev_t);
1777fe2a5a0Stsutsui void pccnpollc(dev_t, int);
1788519eaf8Ssoda
17977a6b82bSgehenna dev_type_open(pcopen);
18077a6b82bSgehenna dev_type_close(pcclose);
18177a6b82bSgehenna dev_type_read(pcread);
18277a6b82bSgehenna dev_type_write(pcwrite);
18377a6b82bSgehenna dev_type_ioctl(pcioctl);
18477a6b82bSgehenna dev_type_tty(pctty);
18577a6b82bSgehenna dev_type_poll(pcpoll);
18677a6b82bSgehenna dev_type_mmap(pcmmap);
18777a6b82bSgehenna
18877a6b82bSgehenna const struct cdevsw pc_cdevsw = {
189a68f9396Sdholland .d_open = pcopen,
190a68f9396Sdholland .d_close = pcclose,
191a68f9396Sdholland .d_read = pcread,
192a68f9396Sdholland .d_write = pcwrite,
193a68f9396Sdholland .d_ioctl = pcioctl,
194a68f9396Sdholland .d_stop = nostop,
195a68f9396Sdholland .d_tty = pctty,
196a68f9396Sdholland .d_poll = pcpoll,
197a68f9396Sdholland .d_mmap = pcmmap,
198a68f9396Sdholland .d_kqfilter = ttykqfilter,
199f9228f42Sdholland .d_discard = nodiscard,
200a68f9396Sdholland .d_flag = D_TTY
20177a6b82bSgehenna };
20277a6b82bSgehenna
2038519eaf8Ssoda #define CHR 2
2048519eaf8Ssoda
2057fe2a5a0Stsutsui char *sget(void);
20620751a78Smatt void sput(const u_char *, int);
2078519eaf8Ssoda
2087fe2a5a0Stsutsui void pcstart(struct tty *);
2097fe2a5a0Stsutsui int pcparam(struct tty *, struct termios *);
2105f1c88d7Sperry static inline void wcopy(void *, void *, u_int);
2117fe2a5a0Stsutsui void pc_context_init(bus_space_tag_t, bus_space_tag_t, bus_space_tag_t,
2127fe2a5a0Stsutsui struct pccons_config *);
213564df9b6Ssoda
2147fe2a5a0Stsutsui extern void fillw(int, uint16_t *, int);
2158519eaf8Ssoda
2168519eaf8Ssoda #define KBD_DELAY \
2178519eaf8Ssoda DELAY(10);
2188519eaf8Ssoda
219b7abba77Ssoda #define crtc_read_1(reg) \
220b7abba77Ssoda bus_space_read_1(pccons_console_context.pc_crt_iot, \
221b7abba77Ssoda pccons_console_context.pc_6845_ioh, reg)
222b7abba77Ssoda #define crtc_write_1(reg, data) \
223b7abba77Ssoda bus_space_write_1(pccons_console_context.pc_crt_iot, \
224b7abba77Ssoda pccons_console_context.pc_6845_ioh, reg, data)
225b7abba77Ssoda
226b7abba77Ssoda struct pccons_context pccons_console_context;
227b7abba77Ssoda
2285175a612Ssoda void
kbd_context_init(bus_space_tag_t kbd_iot,struct pccons_config * config)2297fe2a5a0Stsutsui kbd_context_init(bus_space_tag_t kbd_iot, struct pccons_config *config)
2305175a612Ssoda {
231b7abba77Ssoda struct pccons_kbd_context *pkc = &pccons_console_context.pc_pkc;
2325175a612Ssoda
233b7abba77Ssoda if (pkc->pkc_initialized)
2345175a612Ssoda return;
235b7abba77Ssoda pkc->pkc_initialized = 1;
2365175a612Ssoda
237b7abba77Ssoda pkc->pkc_iot = kbd_iot;
2385175a612Ssoda
239b7abba77Ssoda bus_space_map(kbd_iot, config->pc_kbd_cmdp, 1, 0,
240b7abba77Ssoda &pkc->pkc_cmd_ioh);
241b7abba77Ssoda bus_space_map(kbd_iot, config->pc_kbd_datap, 1, 0,
242b7abba77Ssoda &pkc->pkc_data_ioh);
2435175a612Ssoda }
244b7abba77Ssoda
245b7abba77Ssoda void
pc_context_init(bus_space_tag_t crt_iot,bus_space_tag_t crt_memt,bus_space_tag_t kbd_iot,struct pccons_config * config)2467fe2a5a0Stsutsui pc_context_init(bus_space_tag_t crt_iot, bus_space_tag_t crt_memt,
2477fe2a5a0Stsutsui bus_space_tag_t kbd_iot, struct pccons_config *config)
248b7abba77Ssoda {
249b7abba77Ssoda struct pccons_context *pc = &pccons_console_context;
250b7abba77Ssoda
251b7abba77Ssoda if (pc->pc_initialized)
252b7abba77Ssoda return;
253b7abba77Ssoda pc->pc_initialized = 1;
254b7abba77Ssoda
255b7abba77Ssoda kbd_context_init(kbd_iot, config);
256b7abba77Ssoda
257b7abba77Ssoda pc->pc_crt_iot = crt_iot;
258b7abba77Ssoda pc->pc_crt_memt = crt_memt;
259b7abba77Ssoda
260b7abba77Ssoda bus_space_map(crt_iot, config->pc_mono_iobase, 2, 0,
261b7abba77Ssoda &pc->pc_mono_ioh);
262b7abba77Ssoda bus_space_map(crt_memt, config->pc_mono_memaddr, 0x20000, 0,
263b7abba77Ssoda &pc->pc_mono_memh);
264b7abba77Ssoda bus_space_map(crt_iot, config->pc_cga_iobase, 2, 0,
265b7abba77Ssoda &pc->pc_cga_ioh);
266b7abba77Ssoda bus_space_map(crt_memt, config->pc_cga_memaddr, 0x20000, 0,
267b7abba77Ssoda &pc->pc_cga_memh);
268b7abba77Ssoda
269b7abba77Ssoda /*
270b7abba77Ssoda * pc->pc_6845_ioh and pc->pc_crt_memh will be initialized later,
271b7abba77Ssoda * when `Crtat' is initialized.
272b7abba77Ssoda */
273b7abba77Ssoda
274b7abba77Ssoda pc->pc_config = config;
275b7abba77Ssoda
276b7abba77Ssoda (*config->pc_init)();
2775175a612Ssoda }
2785175a612Ssoda
279564df9b6Ssoda /*
280564df9b6Ssoda * bcopy variant that only moves word-aligned 16-bit entities,
281e9281952Stsutsui * for stupid VGA cards. cnt is required to be an even value.
282564df9b6Ssoda */
2835f1c88d7Sperry static inline void
wcopy(void * src,void * tgt,u_int cnt)2847fe2a5a0Stsutsui wcopy(void *src, void *tgt, u_int cnt)
285564df9b6Ssoda {
2867fe2a5a0Stsutsui uint16_t *from = src;
2877fe2a5a0Stsutsui uint16_t *to = tgt;
288564df9b6Ssoda
289564df9b6Ssoda cnt >>= 1;
290564df9b6Ssoda if (to < from || to >= from + cnt)
291564df9b6Ssoda while (cnt--)
292564df9b6Ssoda *to++ = *from++;
293564df9b6Ssoda else {
294564df9b6Ssoda to += cnt;
295564df9b6Ssoda from += cnt;
296564df9b6Ssoda while (cnt--)
297564df9b6Ssoda *--to = *--from;
298564df9b6Ssoda }
299564df9b6Ssoda }
300564df9b6Ssoda
3015f1c88d7Sperry static inline int
kbd_wait_output(void)3027fe2a5a0Stsutsui kbd_wait_output(void)
3038519eaf8Ssoda {
3048519eaf8Ssoda u_int i;
3058519eaf8Ssoda
3068519eaf8Ssoda for (i = 100000; i; i--)
307b7abba77Ssoda if ((kbd_cmd_read_1() & KBS_IBF) == 0) {
3088519eaf8Ssoda KBD_DELAY;
3098519eaf8Ssoda return 1;
3108519eaf8Ssoda }
3118519eaf8Ssoda return 0;
3128519eaf8Ssoda }
3138519eaf8Ssoda
3145f1c88d7Sperry static inline int
kbd_wait_input(void)3157fe2a5a0Stsutsui kbd_wait_input(void)
3168519eaf8Ssoda {
3178519eaf8Ssoda u_int i;
3188519eaf8Ssoda
3198519eaf8Ssoda for (i = 100000; i; i--)
320b7abba77Ssoda if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
3218519eaf8Ssoda KBD_DELAY;
3228519eaf8Ssoda return 1;
3238519eaf8Ssoda }
3248519eaf8Ssoda return 0;
3258519eaf8Ssoda }
3268519eaf8Ssoda
327b7abba77Ssoda void
kbd_flush_input(void)3287fe2a5a0Stsutsui kbd_flush_input(void)
3298519eaf8Ssoda {
3307fe2a5a0Stsutsui uint8_t c;
3318519eaf8Ssoda
332b7abba77Ssoda while ((c = kbd_cmd_read_1()) & 0x03)
3338519eaf8Ssoda if ((c & KBS_DIB) == KBS_DIB) {
3348519eaf8Ssoda /* XXX - delay is needed to prevent some keyboards from
3358519eaf8Ssoda wedging when the system boots */
3368519eaf8Ssoda delay(6);
337b7abba77Ssoda (void)kbd_data_read_1();
3388519eaf8Ssoda }
3398519eaf8Ssoda }
3408519eaf8Ssoda
3418519eaf8Ssoda #if 1
3428519eaf8Ssoda /*
3438519eaf8Ssoda * Get the current command byte.
3448519eaf8Ssoda */
3458519eaf8Ssoda static u_char
kbc_get8042cmd(void)3467fe2a5a0Stsutsui kbc_get8042cmd(void)
3478519eaf8Ssoda {
3488519eaf8Ssoda
3498519eaf8Ssoda if (!kbd_wait_output())
3508519eaf8Ssoda return -1;
351b7abba77Ssoda kbd_cmd_write_1(K_RDCMDBYTE);
3528519eaf8Ssoda if (!kbd_wait_input())
3538519eaf8Ssoda return -1;
354b7abba77Ssoda return kbd_data_read_1();
3558519eaf8Ssoda }
3568519eaf8Ssoda #endif
3578519eaf8Ssoda
3588519eaf8Ssoda /*
3598519eaf8Ssoda * Pass command byte to keyboard controller (8042).
3608519eaf8Ssoda */
361b7abba77Ssoda int
kbc_put8042cmd(uint8_t val)36282357f6dSdsl kbc_put8042cmd(uint8_t val)
3638519eaf8Ssoda {
3648519eaf8Ssoda
3658519eaf8Ssoda if (!kbd_wait_output())
3668519eaf8Ssoda return 0;
367b7abba77Ssoda kbd_cmd_write_1(K_LDCMDBYTE);
3688519eaf8Ssoda if (!kbd_wait_output())
3698519eaf8Ssoda return 0;
370b7abba77Ssoda kbd_data_write_1(val);
3718519eaf8Ssoda return 1;
3728519eaf8Ssoda }
3738519eaf8Ssoda
3748519eaf8Ssoda /*
3758519eaf8Ssoda * Pass command to keyboard itself
3768519eaf8Ssoda */
3778519eaf8Ssoda int
kbd_cmd(uint8_t val,uint8_t polled)37820751a78Smatt kbd_cmd(uint8_t val, uint8_t polled)
3798519eaf8Ssoda {
3808519eaf8Ssoda u_int retries = 3;
3818e19dfb2Stsutsui u_int i;
3828519eaf8Ssoda
38320751a78Smatt if (!polled) {
3848519eaf8Ssoda i = spltty();
3858519eaf8Ssoda if (kb_oq_get == kb_oq_put) {
386b7abba77Ssoda kbd_data_write_1(val);
3878519eaf8Ssoda }
3888519eaf8Ssoda kb_oq[kb_oq_put] = val;
3898519eaf8Ssoda kb_oq_put = (kb_oq_put + 1) & 7;
3908519eaf8Ssoda splx(i);
3917fe2a5a0Stsutsui return 1;
3928519eaf8Ssoda }
39320751a78Smatt
39420751a78Smatt do {
3958519eaf8Ssoda if (!kbd_wait_output())
3968519eaf8Ssoda return 0;
397b7abba77Ssoda kbd_data_write_1(val);
3988519eaf8Ssoda for (i = 100000; i; i--) {
399b7abba77Ssoda if (kbd_cmd_read_1() & KBS_DIB) {
4007fe2a5a0Stsutsui uint8_t c;
4018519eaf8Ssoda
4028519eaf8Ssoda KBD_DELAY;
403b7abba77Ssoda c = kbd_data_read_1();
4048519eaf8Ssoda if (c == KBR_ACK || c == KBR_ECHO) {
4058519eaf8Ssoda return 1;
4068519eaf8Ssoda }
4078519eaf8Ssoda if (c == KBR_RESEND) {
4088519eaf8Ssoda break;
4098519eaf8Ssoda }
4108519eaf8Ssoda #ifdef DIAGNOSTIC
4118519eaf8Ssoda printf("kbd_cmd: input char %x lost\n", c);
4128519eaf8Ssoda #endif
4138519eaf8Ssoda }
4148519eaf8Ssoda }
4158519eaf8Ssoda } while (--retries);
4168519eaf8Ssoda return 0;
4178519eaf8Ssoda }
4188519eaf8Ssoda
4198519eaf8Ssoda void
set_cursor_shape(void)4207fe2a5a0Stsutsui set_cursor_shape(void)
4218519eaf8Ssoda {
4227fe2a5a0Stsutsui
423b7abba77Ssoda crtc_write_1(0, 10);
424b7abba77Ssoda crtc_write_1(1, cursor_shape >> 8);
425b7abba77Ssoda crtc_write_1(0, 11);
426b7abba77Ssoda crtc_write_1(1, cursor_shape);
4278519eaf8Ssoda old_cursor_shape = cursor_shape;
4288519eaf8Ssoda }
4298519eaf8Ssoda
4308519eaf8Ssoda void
get_cursor_shape(void)4317fe2a5a0Stsutsui get_cursor_shape(void)
4328519eaf8Ssoda {
4337fe2a5a0Stsutsui
434b7abba77Ssoda crtc_write_1(0, 10);
435b7abba77Ssoda cursor_shape = crtc_read_1(1) << 8;
436b7abba77Ssoda crtc_write_1(0, 11);
437b7abba77Ssoda cursor_shape |= crtc_read_1(1);
4388519eaf8Ssoda
4398519eaf8Ssoda /*
4408519eaf8Ssoda * real 6845's, as found on, MDA, Hercules or CGA cards, do
4418519eaf8Ssoda * not support reading the cursor shape registers. the 6845
442f0a7346dSsnj * tri-states its data bus. This is _normally_ read by the
443d20841bbSwiz * CPU as either 0x00 or 0xff.. in which case we just use
4448519eaf8Ssoda * a line cursor.
4458519eaf8Ssoda */
4468519eaf8Ssoda if (cursor_shape == 0x0000 || cursor_shape == 0xffff)
4478519eaf8Ssoda cursor_shape = 0x0b10;
4488519eaf8Ssoda else
4498519eaf8Ssoda cursor_shape &= 0x1f1f;
4508519eaf8Ssoda }
4518519eaf8Ssoda
4528519eaf8Ssoda void
do_async_update(uint8_t poll)4537fe2a5a0Stsutsui do_async_update(uint8_t poll)
4548519eaf8Ssoda {
4558519eaf8Ssoda int pos;
4568519eaf8Ssoda static int old_pos = -1;
4578519eaf8Ssoda
4588519eaf8Ssoda async = 0;
4598519eaf8Ssoda
4608519eaf8Ssoda if (lock_state != old_lock_state) {
4618519eaf8Ssoda old_lock_state = lock_state;
4628519eaf8Ssoda if (!kbd_cmd(KBC_MODEIND, poll) ||
4638519eaf8Ssoda !kbd_cmd(lock_state, poll)) {
4648519eaf8Ssoda printf("pc: timeout updating leds\n");
4658519eaf8Ssoda (void) kbd_cmd(KBC_ENABLE, poll);
4668519eaf8Ssoda }
4678519eaf8Ssoda }
4688519eaf8Ssoda if (typematic_rate != old_typematic_rate) {
4698519eaf8Ssoda old_typematic_rate = typematic_rate;
4708519eaf8Ssoda if (!kbd_cmd(KBC_TYPEMATIC, poll) ||
4718519eaf8Ssoda !kbd_cmd(typematic_rate, poll)) {
4728519eaf8Ssoda printf("pc: timeout updating typematic rate\n");
4738519eaf8Ssoda (void) kbd_cmd(KBC_ENABLE, poll);
4748519eaf8Ssoda }
4758519eaf8Ssoda }
4768519eaf8Ssoda
4778519eaf8Ssoda if (pc_xmode > 0)
4788519eaf8Ssoda return;
4798519eaf8Ssoda
4808519eaf8Ssoda pos = crtat - Crtat;
4818519eaf8Ssoda if (pos != old_pos) {
482b7abba77Ssoda crtc_write_1(0, 14);
483b7abba77Ssoda crtc_write_1(1, pos >> 8);
484b7abba77Ssoda crtc_write_1(0, 15);
485b7abba77Ssoda crtc_write_1(1, pos);
4868519eaf8Ssoda old_pos = pos;
4878519eaf8Ssoda }
4888519eaf8Ssoda if (cursor_shape != old_cursor_shape)
4898519eaf8Ssoda set_cursor_shape();
4908519eaf8Ssoda }
4918519eaf8Ssoda
4928519eaf8Ssoda void
async_update(void)4937fe2a5a0Stsutsui async_update(void)
4948519eaf8Ssoda {
4958519eaf8Ssoda
4968519eaf8Ssoda if (kernel || polling) {
4978519eaf8Ssoda if (async)
498b667a5a3Sthorpej callout_stop(&async_update_ch);
4998519eaf8Ssoda do_async_update(1);
5008519eaf8Ssoda } else {
5018519eaf8Ssoda if (async)
5028519eaf8Ssoda return;
5038519eaf8Ssoda async = 1;
504b667a5a3Sthorpej callout_reset(&async_update_ch, 1,
505b667a5a3Sthorpej (void(*)(void *))do_async_update, NULL);
5068519eaf8Ssoda }
5078519eaf8Ssoda }
5088519eaf8Ssoda
5098519eaf8Ssoda /*
5108519eaf8Ssoda * these are both bad jokes
5118519eaf8Ssoda */
5128519eaf8Ssoda int
pccons_common_match(bus_space_tag_t crt_iot,bus_space_tag_t crt_memt,bus_space_tag_t kbd_iot,struct pccons_config * config)5137fe2a5a0Stsutsui pccons_common_match(bus_space_tag_t crt_iot, bus_space_tag_t crt_memt,
5147fe2a5a0Stsutsui bus_space_tag_t kbd_iot, struct pccons_config *config)
5158519eaf8Ssoda {
516b7abba77Ssoda int i;
5178519eaf8Ssoda
518b7abba77Ssoda pc_context_init(crt_iot, crt_memt, kbd_iot, config);
5198519eaf8Ssoda
5208519eaf8Ssoda /* Enable interrupts and keyboard, etc. */
5218519eaf8Ssoda if (!kbc_put8042cmd(CMDBYTE)) {
522564df9b6Ssoda printf("pcprobe: command error\n");
5238519eaf8Ssoda return 0;
5248519eaf8Ssoda }
5258519eaf8Ssoda
5268519eaf8Ssoda #if 1
5278519eaf8Ssoda /* Flush any garbage. */
5288519eaf8Ssoda kbd_flush_input();
5298519eaf8Ssoda /* Reset the keyboard. */
5308519eaf8Ssoda if (!kbd_cmd(KBC_RESET, 1)) {
531564df9b6Ssoda printf("pcprobe: reset error %d\n", 1);
5328519eaf8Ssoda goto lose;
5338519eaf8Ssoda }
5348519eaf8Ssoda for (i = 600000; i; i--)
535b7abba77Ssoda if ((kbd_cmd_read_1() & KBS_DIB) != 0) {
5368519eaf8Ssoda KBD_DELAY;
5378519eaf8Ssoda break;
5388519eaf8Ssoda }
539b7abba77Ssoda if (i == 0 || kbd_data_read_1() != KBR_RSTDONE) {
540564df9b6Ssoda printf("pcprobe: reset error %d\n", 2);
5418519eaf8Ssoda goto lose;
5428519eaf8Ssoda }
5438519eaf8Ssoda /*
5448519eaf8Ssoda * Some keyboards seem to leave a second ack byte after the reset.
5458519eaf8Ssoda * This is kind of stupid, but we account for them anyway by just
5468519eaf8Ssoda * flushing the buffer.
5478519eaf8Ssoda */
5488519eaf8Ssoda kbd_flush_input();
5498519eaf8Ssoda /* Just to be sure. */
5508519eaf8Ssoda if (!kbd_cmd(KBC_ENABLE, 1)) {
551564df9b6Ssoda printf("pcprobe: reset error %d\n", 3);
5528519eaf8Ssoda goto lose;
5538519eaf8Ssoda }
5548519eaf8Ssoda
5558519eaf8Ssoda /*
5568519eaf8Ssoda * Some keyboard/8042 combinations do not seem to work if the keyboard
5578519eaf8Ssoda * is set to table 1; in fact, it would appear that some keyboards just
5588519eaf8Ssoda * ignore the command altogether. So by default, we use the AT scan
5598519eaf8Ssoda * codes and have the 8042 translate them. Unfortunately, this is
560*cdc507f0Sandvar * known to not work on some PS/2 machines. We try desperately to deal
5618519eaf8Ssoda * with this by checking the (lack of a) translate bit in the 8042 and
5628519eaf8Ssoda * attempting to set the keyboard to XT mode. If this all fails, well,
5638519eaf8Ssoda * tough luck.
5648519eaf8Ssoda *
5658519eaf8Ssoda * XXX It would perhaps be a better choice to just use AT scan codes
5668519eaf8Ssoda * and not bother with this.
5678519eaf8Ssoda */
5688519eaf8Ssoda if (kbc_get8042cmd() & KC8_TRANS) {
5698519eaf8Ssoda /* The 8042 is translating for us; use AT codes. */
5708519eaf8Ssoda if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(2, 1)) {
571564df9b6Ssoda printf("pcprobe: reset error %d\n", 4);
5728519eaf8Ssoda goto lose;
5738519eaf8Ssoda }
5748519eaf8Ssoda } else {
5758519eaf8Ssoda /* Stupid 8042; set keyboard to XT codes. */
5768519eaf8Ssoda if (!kbd_cmd(KBC_SETTABLE, 1) || !kbd_cmd(1, 1)) {
577564df9b6Ssoda printf("pcprobe: reset error %d\n", 5);
5788519eaf8Ssoda goto lose;
5798519eaf8Ssoda }
5808519eaf8Ssoda }
5818519eaf8Ssoda
5828519eaf8Ssoda lose:
5838519eaf8Ssoda /*
584564df9b6Ssoda * Technically, we should probably fail the probe. But we'll be nice
5858519eaf8Ssoda * and allow keyboard-less machines to boot with the console.
5868519eaf8Ssoda */
5878519eaf8Ssoda #endif
5888519eaf8Ssoda
5898519eaf8Ssoda return 1;
5908519eaf8Ssoda }
5918519eaf8Ssoda
pccons_common_attach(struct pc_softc * sc,bus_space_tag_t crt_iot,bus_space_tag_t crt_memt,bus_space_tag_t kbd_iot,struct pccons_config * config)5927fe2a5a0Stsutsui void pccons_common_attach(struct pc_softc *sc, bus_space_tag_t crt_iot,
5937fe2a5a0Stsutsui bus_space_tag_t crt_memt, bus_space_tag_t kbd_iot,
5947fe2a5a0Stsutsui struct pccons_config *config)
5958519eaf8Ssoda {
5967fe2a5a0Stsutsui
5978519eaf8Ssoda printf(": %s\n", vs.color ? "color" : "mono");
59888ab7da9Sad callout_init(&async_update_ch, 0);
5998519eaf8Ssoda do_async_update(1);
6008519eaf8Ssoda }
6018519eaf8Ssoda
6028519eaf8Ssoda int
pcopen(dev_t dev,int flag,int mode,struct lwp * l)60395e1ffb1Schristos pcopen(dev_t dev, int flag, int mode, struct lwp *l)
6048519eaf8Ssoda {
6058519eaf8Ssoda struct pc_softc *sc;
6068519eaf8Ssoda struct tty *tp;
6078519eaf8Ssoda
608fa11f9bfScegger sc = device_lookup_private(&pc_cd, PCUNIT(dev));
609fa11f9bfScegger if (sc == NULL)
6108519eaf8Ssoda return ENXIO;
6118519eaf8Ssoda
6128519eaf8Ssoda if (!sc->sc_tty) {
6132626d576Srmind tp = sc->sc_tty = tty_alloc();
6148519eaf8Ssoda }
6158519eaf8Ssoda else {
6168519eaf8Ssoda tp = sc->sc_tty;
6178519eaf8Ssoda }
6188519eaf8Ssoda
6198519eaf8Ssoda tp->t_oproc = pcstart;
6208519eaf8Ssoda tp->t_param = pcparam;
6218519eaf8Ssoda tp->t_dev = dev;
622e8373398Selad
623e8373398Selad if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
624e8373398Selad return (EBUSY);
625e8373398Selad
6268519eaf8Ssoda if ((tp->t_state & TS_ISOPEN) == 0) {
6278519eaf8Ssoda ttychars(tp);
6288519eaf8Ssoda tp->t_iflag = TTYDEF_IFLAG;
6298519eaf8Ssoda tp->t_oflag = TTYDEF_OFLAG;
6308519eaf8Ssoda tp->t_cflag = TTYDEF_CFLAG;
6318519eaf8Ssoda tp->t_lflag = TTYDEF_LFLAG;
6328519eaf8Ssoda tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
6338519eaf8Ssoda pcparam(tp, &tp->t_termios);
6348519eaf8Ssoda ttsetwater(tp);
635e8373398Selad }
636e8373398Selad
6378519eaf8Ssoda tp->t_state |= TS_CARR_ON;
6388519eaf8Ssoda
6397fe2a5a0Stsutsui return (*tp->t_linesw->l_open)(dev, tp);
6408519eaf8Ssoda }
6418519eaf8Ssoda
6428519eaf8Ssoda int
pcclose(dev_t dev,int flag,int mode,struct lwp * l)64395e1ffb1Schristos pcclose(dev_t dev, int flag, int mode, struct lwp *l)
6448519eaf8Ssoda {
645fa11f9bfScegger struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
6468519eaf8Ssoda struct tty *tp = sc->sc_tty;
6478519eaf8Ssoda
648bc736332Seeh (*tp->t_linesw->l_close)(tp, flag);
6498519eaf8Ssoda ttyclose(tp);
6508519eaf8Ssoda #ifdef notyet /* XXX */
6512626d576Srmind tty_free(tp);
6528519eaf8Ssoda #endif
6537fe2a5a0Stsutsui return 0;
6548519eaf8Ssoda }
6558519eaf8Ssoda
6568519eaf8Ssoda int
pcread(dev_t dev,struct uio * uio,int flag)6577fe2a5a0Stsutsui pcread(dev_t dev, struct uio *uio, int flag)
6588519eaf8Ssoda {
659fa11f9bfScegger struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
6608519eaf8Ssoda struct tty *tp = sc->sc_tty;
6618519eaf8Ssoda
6627fe2a5a0Stsutsui return (*tp->t_linesw->l_read)(tp, uio, flag);
6638519eaf8Ssoda }
6648519eaf8Ssoda
6658519eaf8Ssoda int
pcwrite(dev_t dev,struct uio * uio,int flag)6667fe2a5a0Stsutsui pcwrite(dev_t dev, struct uio *uio, int flag)
6678519eaf8Ssoda {
668fa11f9bfScegger struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
6698519eaf8Ssoda struct tty *tp = sc->sc_tty;
6708519eaf8Ssoda
6717fe2a5a0Stsutsui return (*tp->t_linesw->l_write)(tp, uio, flag);
6728519eaf8Ssoda }
6738519eaf8Ssoda
6742963ff5cSscw int
pcpoll(dev_t dev,int events,struct lwp * l)67595e1ffb1Schristos pcpoll(dev_t dev, int events, struct lwp *l)
6762963ff5cSscw {
677fa11f9bfScegger struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
6782963ff5cSscw struct tty *tp = sc->sc_tty;
6792963ff5cSscw
68095e1ffb1Schristos return (*tp->t_linesw->l_poll)(tp, events, l);
6812963ff5cSscw }
6822963ff5cSscw
6838519eaf8Ssoda struct tty *
pctty(dev_t dev)6847fe2a5a0Stsutsui pctty(dev_t dev)
6858519eaf8Ssoda {
686fa11f9bfScegger struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
6878519eaf8Ssoda struct tty *tp = sc->sc_tty;
6888519eaf8Ssoda
6897fe2a5a0Stsutsui return tp;
6908519eaf8Ssoda }
6918519eaf8Ssoda
6928519eaf8Ssoda /*
6938519eaf8Ssoda * Got a console receive interrupt -
6948519eaf8Ssoda * the console processor wants to give us a character.
6958519eaf8Ssoda * Catch the character, and see who it goes to.
6968519eaf8Ssoda */
6978519eaf8Ssoda int
pcintr(void * arg)6987fe2a5a0Stsutsui pcintr(void *arg)
6998519eaf8Ssoda {
7008519eaf8Ssoda struct pc_softc *sc = arg;
7018e19dfb2Stsutsui struct tty *tp = sc->sc_tty;
7027fe2a5a0Stsutsui uint8_t *cp;
7038519eaf8Ssoda
704b7abba77Ssoda if ((kbd_cmd_read_1() & KBS_DIB) == 0)
7058519eaf8Ssoda return 0;
7068519eaf8Ssoda if (polling)
7078519eaf8Ssoda return 1;
7088519eaf8Ssoda do {
7098519eaf8Ssoda cp = sget();
7108519eaf8Ssoda if (!tp || (tp->t_state & TS_ISOPEN) == 0)
7118519eaf8Ssoda return 1;
7128519eaf8Ssoda if (cp)
7138519eaf8Ssoda do
714bc736332Seeh (*tp->t_linesw->l_rint)(*cp++, tp);
7158519eaf8Ssoda while (*cp);
716b7abba77Ssoda } while (kbd_cmd_read_1() & KBS_DIB);
7178519eaf8Ssoda return 1;
7188519eaf8Ssoda }
7198519eaf8Ssoda
7208519eaf8Ssoda int
pcioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)72153524e44Schristos pcioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
7228519eaf8Ssoda {
723fa11f9bfScegger struct pc_softc *sc = device_lookup_private(&pc_cd, PCUNIT(dev));
7248519eaf8Ssoda struct tty *tp = sc->sc_tty;
7258519eaf8Ssoda int error;
7268519eaf8Ssoda
72795e1ffb1Schristos error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
72831144d99Satatat if (error != EPASSTHROUGH)
7298519eaf8Ssoda return error;
73095e1ffb1Schristos error = ttioctl(tp, cmd, data, flag, l);
73131144d99Satatat if (error != EPASSTHROUGH)
7328519eaf8Ssoda return error;
7338519eaf8Ssoda
7348519eaf8Ssoda switch (cmd) {
7358519eaf8Ssoda case CONSOLE_X_MODE_ON:
7368519eaf8Ssoda pc_xmode_on();
7378519eaf8Ssoda return 0;
7388519eaf8Ssoda case CONSOLE_X_MODE_OFF:
7398519eaf8Ssoda pc_xmode_off();
7408519eaf8Ssoda return 0;
7418519eaf8Ssoda case CONSOLE_X_BELL:
7428519eaf8Ssoda /*
7438519eaf8Ssoda * If set, data is a pointer to a length 2 array of
7448519eaf8Ssoda * integers. data[0] is the pitch in Hz and data[1]
7458519eaf8Ssoda * is the duration in msec.
7468519eaf8Ssoda */
7478519eaf8Ssoda if (data)
7488519eaf8Ssoda sysbeep(((int*)data)[0],
7498519eaf8Ssoda (((int*)data)[1] * hz) / 1000);
7508519eaf8Ssoda else
7518519eaf8Ssoda sysbeep(BEEP_FREQ, BEEP_TIME);
7528519eaf8Ssoda return 0;
7538519eaf8Ssoda case CONSOLE_SET_TYPEMATIC_RATE: {
7548519eaf8Ssoda u_char rate;
7558519eaf8Ssoda
7568519eaf8Ssoda if (!data)
7578519eaf8Ssoda return EINVAL;
7588519eaf8Ssoda rate = *((u_char *)data);
7598519eaf8Ssoda /*
7608519eaf8Ssoda * Check that it isn't too big (which would cause it to be
7618519eaf8Ssoda * confused with a command).
7628519eaf8Ssoda */
7638519eaf8Ssoda if (rate & 0x80)
7648519eaf8Ssoda return EINVAL;
7658519eaf8Ssoda typematic_rate = rate;
7668519eaf8Ssoda async_update();
7678519eaf8Ssoda return 0;
7688519eaf8Ssoda }
769564df9b6Ssoda case CONSOLE_SET_KEYMAP: {
770564df9b6Ssoda pccons_keymap_t *map = (pccons_keymap_t *) data;
771564df9b6Ssoda int i;
772564df9b6Ssoda
773564df9b6Ssoda if (!data)
774564df9b6Ssoda return EINVAL;
775564df9b6Ssoda for (i = 0; i < KB_NUM_KEYS; i++)
776564df9b6Ssoda if (map[i].unshift[KB_CODE_SIZE-1] ||
777564df9b6Ssoda map[i].shift[KB_CODE_SIZE-1] ||
778564df9b6Ssoda map[i].ctl[KB_CODE_SIZE-1] ||
779564df9b6Ssoda map[i].altgr[KB_CODE_SIZE-1] ||
780564df9b6Ssoda map[i].shift_altgr[KB_CODE_SIZE-1])
781564df9b6Ssoda return EINVAL;
782564df9b6Ssoda
783e9281952Stsutsui memcpy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
784564df9b6Ssoda return 0;
785564df9b6Ssoda }
786564df9b6Ssoda case CONSOLE_GET_KEYMAP:
787564df9b6Ssoda if (!data)
788564df9b6Ssoda return EINVAL;
789e9281952Stsutsui memcpy(scan_codes, data, sizeof(pccons_keymap_t[KB_NUM_KEYS]));
790564df9b6Ssoda return 0;
791564df9b6Ssoda
7928519eaf8Ssoda default:
79331144d99Satatat return EPASSTHROUGH;
7948519eaf8Ssoda }
7958519eaf8Ssoda
7968519eaf8Ssoda #ifdef DIAGNOSTIC
7978519eaf8Ssoda panic("pcioctl: impossible");
7988519eaf8Ssoda #endif
7998519eaf8Ssoda }
8008519eaf8Ssoda
8018519eaf8Ssoda void
pcstart(struct tty * tp)8027fe2a5a0Stsutsui pcstart(struct tty *tp)
8038519eaf8Ssoda {
804b93d54e0Stsutsui struct clist *cl;
805564df9b6Ssoda int s, len;
8068519eaf8Ssoda u_char buf[PCBURST];
8078519eaf8Ssoda
8088519eaf8Ssoda s = spltty();
8098519eaf8Ssoda if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
8108519eaf8Ssoda goto out;
8118519eaf8Ssoda tp->t_state |= TS_BUSY;
8128519eaf8Ssoda splx(s);
8138519eaf8Ssoda /*
8148519eaf8Ssoda * We need to do this outside spl since it could be fairly
8158519eaf8Ssoda * expensive and we don't want our serial ports to overflow.
8168519eaf8Ssoda */
817b93d54e0Stsutsui cl = &tp->t_outq;
8188519eaf8Ssoda len = q_to_b(cl, buf, PCBURST);
8198519eaf8Ssoda sput(buf, len);
8208519eaf8Ssoda s = spltty();
8218519eaf8Ssoda tp->t_state &= ~TS_BUSY;
822dc26833bSad if (ttypull(tp)) {
8238519eaf8Ssoda tp->t_state |= TS_TIMEOUT;
824d238692cSjoerg callout_schedule(&tp->t_rstrt_ch, 1);
8258519eaf8Ssoda }
8268519eaf8Ssoda out:
8278519eaf8Ssoda splx(s);
8288519eaf8Ssoda }
8298519eaf8Ssoda
8308519eaf8Ssoda /* ARGSUSED */
pccons_common_cnattach(bus_space_tag_t crt_iot,bus_space_tag_t crt_memt,bus_space_tag_t kbd_iot,struct pccons_config * config)8317fe2a5a0Stsutsui void pccons_common_cnattach(bus_space_tag_t crt_iot, bus_space_tag_t crt_memt,
8327fe2a5a0Stsutsui bus_space_tag_t kbd_iot, struct pccons_config *config)
8338519eaf8Ssoda {
834564df9b6Ssoda int maj;
835564df9b6Ssoda static struct consdev pccons = {
8361654f7e0Stsutsui NULL, NULL, pccngetc, pccnputc, pccnpollc, NULL, NULL,
8371654f7e0Stsutsui NULL, NODEV, CN_NORMAL
838564df9b6Ssoda };
8398519eaf8Ssoda
8408519eaf8Ssoda /*
8418519eaf8Ssoda * For now, don't screw with it.
8428519eaf8Ssoda */
8438519eaf8Ssoda /* crtat = 0; */
8445175a612Ssoda
845b7abba77Ssoda pc_context_init(crt_iot, crt_memt, kbd_iot, config);
846564df9b6Ssoda
847564df9b6Ssoda /* locate the major number */
84877a6b82bSgehenna maj = cdevsw_lookup_major(&pc_cdevsw);
849564df9b6Ssoda pccons.cn_dev = makedev(maj, 0);
850564df9b6Ssoda
851564df9b6Ssoda cn_tab = &pccons;
8528519eaf8Ssoda }
8538519eaf8Ssoda
8548519eaf8Ssoda /* ARGSUSED */
8558519eaf8Ssoda void
pccnputc(dev_t dev,int c)8567fe2a5a0Stsutsui pccnputc(dev_t dev, int c)
8578519eaf8Ssoda {
85865102815Ssoda u_char cc, oldkernel = kernel;
8598519eaf8Ssoda
8608519eaf8Ssoda kernel = 1;
86165102815Ssoda if (c == '\n') {
8628519eaf8Ssoda sput("\r\n", 2);
86365102815Ssoda } else {
86465102815Ssoda cc = c;
86565102815Ssoda sput(&cc, 1);
86665102815Ssoda }
8678519eaf8Ssoda kernel = oldkernel;
8688519eaf8Ssoda }
8698519eaf8Ssoda
8708519eaf8Ssoda /* ARGSUSED */
871564df9b6Ssoda int
pccngetc(dev_t dev)8727fe2a5a0Stsutsui pccngetc(dev_t dev)
8738519eaf8Ssoda {
8748e19dfb2Stsutsui char *cp;
8758519eaf8Ssoda
8768519eaf8Ssoda if (pc_xmode > 0)
8778519eaf8Ssoda return 0;
8788519eaf8Ssoda
8798519eaf8Ssoda do {
8808519eaf8Ssoda /* wait for byte */
881b7abba77Ssoda while ((kbd_cmd_read_1() & KBS_DIB) == 0);
8828519eaf8Ssoda /* see if it's worthwhile */
8838519eaf8Ssoda cp = sget();
8848519eaf8Ssoda } while (!cp);
8858519eaf8Ssoda if (*cp == '\r')
8868519eaf8Ssoda return '\n';
8878519eaf8Ssoda return *cp;
8888519eaf8Ssoda }
8898519eaf8Ssoda
8908519eaf8Ssoda void
pccnpollc(dev_t dev,int on)8917fe2a5a0Stsutsui pccnpollc(dev_t dev, int on)
8928519eaf8Ssoda {
8938519eaf8Ssoda
8948519eaf8Ssoda polling = on;
8958519eaf8Ssoda if (!on) {
8968519eaf8Ssoda int unit;
8978519eaf8Ssoda struct pc_softc *sc;
8988519eaf8Ssoda int s;
8998519eaf8Ssoda
9008519eaf8Ssoda /*
9018519eaf8Ssoda * If disabling polling on a device that's been configured,
9028519eaf8Ssoda * make sure there are no bytes left in the FIFO, holding up
9038519eaf8Ssoda * the interrupt line. Otherwise we won't get any further
9048519eaf8Ssoda * interrupts.
9058519eaf8Ssoda */
9068519eaf8Ssoda unit = PCUNIT(dev);
9078519eaf8Ssoda if (pc_cd.cd_ndevs > unit) {
908fa11f9bfScegger sc = device_lookup_private(&pc_cd, unit);
909fa11f9bfScegger if (sc != NULL) {
9108519eaf8Ssoda s = spltty();
9118519eaf8Ssoda pcintr(sc);
9128519eaf8Ssoda splx(s);
9138519eaf8Ssoda }
9148519eaf8Ssoda }
9158519eaf8Ssoda }
9168519eaf8Ssoda }
9178519eaf8Ssoda
9188519eaf8Ssoda /*
9198519eaf8Ssoda * Set line parameters.
9208519eaf8Ssoda */
9218519eaf8Ssoda int
pcparam(struct tty * tp,struct termios * t)9227fe2a5a0Stsutsui pcparam(struct tty *tp, struct termios *t)
9238519eaf8Ssoda {
9248519eaf8Ssoda
9258519eaf8Ssoda tp->t_ispeed = t->c_ispeed;
9268519eaf8Ssoda tp->t_ospeed = t->c_ospeed;
9278519eaf8Ssoda tp->t_cflag = t->c_cflag;
9288519eaf8Ssoda return 0;
9298519eaf8Ssoda }
9308519eaf8Ssoda
9318519eaf8Ssoda #define wrtchar(c, at) do {\
93220751a78Smatt char *cp0 = (char *)crtat; *cp0++ = (c); *cp0 = (at); crtat++; vs.col++; \
9338519eaf8Ssoda } while (0)
9348519eaf8Ssoda
9358519eaf8Ssoda /* translate ANSI color codes to standard pc ones */
9368519eaf8Ssoda static char fgansitopc[] = {
9378519eaf8Ssoda FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
9388519eaf8Ssoda FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
9398519eaf8Ssoda };
9408519eaf8Ssoda
9418519eaf8Ssoda static char bgansitopc[] = {
9428519eaf8Ssoda BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
9438519eaf8Ssoda BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
9448519eaf8Ssoda };
9458519eaf8Ssoda
9468519eaf8Ssoda static u_char iso2ibm437[] =
9478519eaf8Ssoda {
9488519eaf8Ssoda 0, 0, 0, 0, 0, 0, 0, 0,
9498519eaf8Ssoda 0, 0, 0, 0, 0, 0, 0, 0,
9508519eaf8Ssoda 0, 0, 0, 0, 0, 0, 0, 0,
9518519eaf8Ssoda 0, 0, 0, 0, 0, 0, 0, 0,
9528519eaf8Ssoda 0xff, 0xad, 0x9b, 0x9c, 0, 0x9d, 0, 0x40,
9538519eaf8Ssoda 0x6f, 0x63, 0x61, 0xae, 0, 0, 0, 0,
9548519eaf8Ssoda 0xf8, 0xf1, 0xfd, 0x33, 0, 0xe6, 0, 0xfa,
9558519eaf8Ssoda 0, 0x31, 0x6f, 0xaf, 0xac, 0xab, 0, 0xa8,
9568519eaf8Ssoda 0x41, 0x41, 0x41, 0x41, 0x8e, 0x8f, 0x92, 0x80,
9578519eaf8Ssoda 0x45, 0x90, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
9588519eaf8Ssoda 0x81, 0xa5, 0x4f, 0x4f, 0x4f, 0x4f, 0x99, 0x4f,
9598519eaf8Ssoda 0x4f, 0x55, 0x55, 0x55, 0x9a, 0x59, 0, 0xe1,
9608519eaf8Ssoda 0x85, 0xa0, 0x83, 0x61, 0x84, 0x86, 0x91, 0x87,
9618519eaf8Ssoda 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
9628519eaf8Ssoda 0, 0xa4, 0x95, 0xa2, 0x93, 0x6f, 0x94, 0x6f,
9638519eaf8Ssoda 0x6f, 0x97, 0xa3, 0x96, 0x81, 0x98, 0, 0
9648519eaf8Ssoda };
9658519eaf8Ssoda
9668519eaf8Ssoda /*
9678519eaf8Ssoda * `pc3' termcap emulation.
9688519eaf8Ssoda */
9698519eaf8Ssoda void
sput(const u_char * cp,int n)97020751a78Smatt sput(const u_char *cp, int n)
9718519eaf8Ssoda {
972b7abba77Ssoda struct pccons_context *pc = &pccons_console_context;
9738519eaf8Ssoda u_char c, scroll = 0;
9748519eaf8Ssoda
9758519eaf8Ssoda if (pc_xmode > 0)
9768519eaf8Ssoda return;
9778519eaf8Ssoda
9788519eaf8Ssoda if (crtat == 0) {
97920751a78Smatt volatile u_short *dp;
9808519eaf8Ssoda u_short was;
9818519eaf8Ssoda unsigned cursorat;
9828519eaf8Ssoda
98320751a78Smatt dp = bus_space_vaddr(pc->pc_crt_memt, pc->pc_cga_memh);
98420751a78Smatt was = *dp;
98520751a78Smatt *dp = 0xA55A;
98620751a78Smatt if (*dp != 0xA55A) {
98720751a78Smatt dp = bus_space_vaddr(pc->pc_crt_memt,
988b7abba77Ssoda pc->pc_mono_memh);
989b7abba77Ssoda pc->pc_6845_ioh = pc->pc_mono_ioh;
990b7abba77Ssoda pc->pc_crt_memh = pc->pc_mono_memh;
9918519eaf8Ssoda vs.color = 0;
9928519eaf8Ssoda } else {
99320751a78Smatt *dp = was;
994b7abba77Ssoda pc->pc_6845_ioh = pc->pc_cga_ioh;
995b7abba77Ssoda pc->pc_crt_memh = pc->pc_cga_memh;
9968519eaf8Ssoda vs.color = 1;
9978519eaf8Ssoda }
9988519eaf8Ssoda
9998519eaf8Ssoda #ifdef FAT_CURSOR
10008519eaf8Ssoda cursor_shape = 0x0012;
10018519eaf8Ssoda #else
10028519eaf8Ssoda get_cursor_shape();
10038519eaf8Ssoda #endif
10048519eaf8Ssoda
1005564df9b6Ssoda bios_display_info(&vs.col, &vs.row, &vs.ncol, &vs.nrow);
1006564df9b6Ssoda vs.nchr = vs.ncol * vs.nrow;
1007564df9b6Ssoda vs.col--;
1008564df9b6Ssoda vs.row--;
1009564df9b6Ssoda cursorat = vs.ncol * vs.row + vs.col;
10108519eaf8Ssoda vs.at = FG_LIGHTGREY | BG_BLACK;
10118519eaf8Ssoda
101220751a78Smatt Crtat = (u_short *)__UNVOLATILE(dp);
1013564df9b6Ssoda crtat = Crtat + cursorat;
1014564df9b6Ssoda
10158519eaf8Ssoda if (vs.color == 0)
10168519eaf8Ssoda vs.so_at = FG_BLACK | BG_LIGHTGREY;
10178519eaf8Ssoda else
10188519eaf8Ssoda vs.so_at = FG_YELLOW | BG_BLACK;
10198519eaf8Ssoda
10208519eaf8Ssoda fillw((vs.at << 8) | ' ', crtat, vs.nchr - cursorat);
10218519eaf8Ssoda }
10228519eaf8Ssoda
10238519eaf8Ssoda while (n--) {
10248519eaf8Ssoda if (!(c = *cp++))
10258519eaf8Ssoda continue;
10268519eaf8Ssoda
10278519eaf8Ssoda switch (c) {
10288519eaf8Ssoda case 0x1B:
10298519eaf8Ssoda if (vs.state >= VSS_ESCAPE) {
10308519eaf8Ssoda wrtchar(c, vs.so_at);
10318519eaf8Ssoda vs.state = 0;
10328519eaf8Ssoda goto maybe_scroll;
10338519eaf8Ssoda } else
10348519eaf8Ssoda vs.state = VSS_ESCAPE;
10358519eaf8Ssoda break;
10368519eaf8Ssoda
1037564df9b6Ssoda case 0x9B: /* CSI */
1038564df9b6Ssoda vs.cx = vs.cy = 0;
1039564df9b6Ssoda vs.state = VSS_EBRACE;
1040564df9b6Ssoda break;
1041564df9b6Ssoda
10428519eaf8Ssoda case '\t': {
10438519eaf8Ssoda int inccol = 8 - (vs.col & 7);
10448519eaf8Ssoda crtat += inccol;
10458519eaf8Ssoda vs.col += inccol;
10468519eaf8Ssoda }
10478519eaf8Ssoda maybe_scroll:
1048564df9b6Ssoda if (vs.col >= vs.ncol) {
1049564df9b6Ssoda vs.col -= vs.ncol;
10508519eaf8Ssoda scroll = 1;
10518519eaf8Ssoda }
10528519eaf8Ssoda break;
10538519eaf8Ssoda
1054564df9b6Ssoda case '\b':
10558519eaf8Ssoda if (crtat <= Crtat)
10568519eaf8Ssoda break;
10578519eaf8Ssoda --crtat;
10588519eaf8Ssoda if (--vs.col < 0)
1059564df9b6Ssoda vs.col += vs.ncol; /* non-destructive backspace */
10608519eaf8Ssoda break;
10618519eaf8Ssoda
10628519eaf8Ssoda case '\r':
10638519eaf8Ssoda crtat -= vs.col;
10648519eaf8Ssoda vs.col = 0;
10658519eaf8Ssoda break;
10668519eaf8Ssoda
10678519eaf8Ssoda case '\n':
10688519eaf8Ssoda crtat += vs.ncol;
10698519eaf8Ssoda scroll = 1;
10708519eaf8Ssoda break;
10718519eaf8Ssoda
10728519eaf8Ssoda default:
10738519eaf8Ssoda switch (vs.state) {
10748519eaf8Ssoda case 0:
10758519eaf8Ssoda if (c == '\a')
10768519eaf8Ssoda sysbeep(BEEP_FREQ, BEEP_TIME);
10778519eaf8Ssoda else {
10788519eaf8Ssoda /*
10798519eaf8Ssoda * If we're outputting multiple printed
10808519eaf8Ssoda * characters, just blast them to the
10818519eaf8Ssoda * screen until we reach the end of the
10828519eaf8Ssoda * buffer or a control character. This
10838519eaf8Ssoda * saves time by short-circuiting the
10848519eaf8Ssoda * switch.
10858519eaf8Ssoda * If we reach the end of the line, we
10868519eaf8Ssoda * break to do a scroll check.
10878519eaf8Ssoda */
10888519eaf8Ssoda for (;;) {
10898519eaf8Ssoda if (c & 0x80)
10908519eaf8Ssoda c = iso2ibm437[c&0x7f];
10918519eaf8Ssoda
10928519eaf8Ssoda if (vs.so)
10938519eaf8Ssoda wrtchar(c, vs.so_at);
10948519eaf8Ssoda else
10958519eaf8Ssoda wrtchar(c, vs.at);
10968519eaf8Ssoda if (vs.col >= vs.ncol) {
10978519eaf8Ssoda vs.col = 0;
10988519eaf8Ssoda scroll = 1;
10998519eaf8Ssoda break;
11008519eaf8Ssoda }
11018519eaf8Ssoda if (!n || (c = *cp) < ' ')
11028519eaf8Ssoda break;
11038519eaf8Ssoda n--, cp++;
11048519eaf8Ssoda }
11058519eaf8Ssoda }
11068519eaf8Ssoda break;
11078519eaf8Ssoda case VSS_ESCAPE:
1108564df9b6Ssoda switch (c) {
1109564df9b6Ssoda case '[': /* Start ESC [ sequence */
11108519eaf8Ssoda vs.cx = vs.cy = 0;
11118519eaf8Ssoda vs.state = VSS_EBRACE;
1112564df9b6Ssoda break;
1113564df9b6Ssoda case 'c': /* Create screen & home */
1114564df9b6Ssoda fillw((vs.at << 8) | ' ',
1115564df9b6Ssoda Crtat, vs.nchr);
11168519eaf8Ssoda crtat = Crtat;
11178519eaf8Ssoda vs.col = 0;
11188519eaf8Ssoda vs.state = 0;
1119564df9b6Ssoda break;
1120564df9b6Ssoda case '7': /* save cursor pos */
1121564df9b6Ssoda vs.offset = crtat - Crtat;
1122564df9b6Ssoda vs.state = 0;
1123564df9b6Ssoda break;
1124564df9b6Ssoda case '8': /* restore cursor pos */
1125564df9b6Ssoda crtat = Crtat + vs.offset;
1126564df9b6Ssoda vs.row = vs.offset / vs.ncol;
1127564df9b6Ssoda vs.col = vs.offset % vs.ncol;
1128564df9b6Ssoda vs.state = 0;
1129564df9b6Ssoda break;
1130564df9b6Ssoda default: /* Invalid, clear state */
11318519eaf8Ssoda wrtchar(c, vs.so_at);
11328519eaf8Ssoda vs.state = 0;
11338519eaf8Ssoda goto maybe_scroll;
11348519eaf8Ssoda }
11358519eaf8Ssoda break;
1136564df9b6Ssoda
11378519eaf8Ssoda default: /* VSS_EBRACE or VSS_EPARAM */
11388519eaf8Ssoda switch (c) {
11398519eaf8Ssoda int pos;
11408519eaf8Ssoda case 'm':
11418519eaf8Ssoda if (!vs.cx)
11428519eaf8Ssoda vs.so = 0;
11438519eaf8Ssoda else
11448519eaf8Ssoda vs.so = 1;
11458519eaf8Ssoda vs.state = 0;
11468519eaf8Ssoda break;
11478519eaf8Ssoda case 'A': { /* back cx rows */
11488519eaf8Ssoda int cx = vs.cx;
11498519eaf8Ssoda if (cx <= 0)
11508519eaf8Ssoda cx = 1;
11518519eaf8Ssoda else
11528519eaf8Ssoda cx %= vs.nrow;
11538519eaf8Ssoda pos = crtat - Crtat;
11548519eaf8Ssoda pos -= vs.ncol * cx;
11558519eaf8Ssoda if (pos < 0)
11568519eaf8Ssoda pos += vs.nchr;
11578519eaf8Ssoda crtat = Crtat + pos;
11588519eaf8Ssoda vs.state = 0;
11598519eaf8Ssoda break;
11608519eaf8Ssoda }
11618519eaf8Ssoda case 'B': { /* down cx rows */
11628519eaf8Ssoda int cx = vs.cx;
11638519eaf8Ssoda if (cx <= 0)
11648519eaf8Ssoda cx = 1;
11658519eaf8Ssoda else
11668519eaf8Ssoda cx %= vs.nrow;
11678519eaf8Ssoda pos = crtat - Crtat;
11688519eaf8Ssoda pos += vs.ncol * cx;
11698519eaf8Ssoda if (pos >= vs.nchr)
11708519eaf8Ssoda pos -= vs.nchr;
11718519eaf8Ssoda crtat = Crtat + pos;
11728519eaf8Ssoda vs.state = 0;
11738519eaf8Ssoda break;
11748519eaf8Ssoda }
11758519eaf8Ssoda case 'C': { /* right cursor */
11768519eaf8Ssoda int cx = vs.cx,
11778519eaf8Ssoda col = vs.col;
11788519eaf8Ssoda if (cx <= 0)
11798519eaf8Ssoda cx = 1;
11808519eaf8Ssoda else
11818519eaf8Ssoda cx %= vs.ncol;
11828519eaf8Ssoda pos = crtat - Crtat;
11838519eaf8Ssoda pos += cx;
11848519eaf8Ssoda col += cx;
11858519eaf8Ssoda if (col >= vs.ncol) {
11868519eaf8Ssoda pos -= vs.ncol;
11878519eaf8Ssoda col -= vs.ncol;
11888519eaf8Ssoda }
11898519eaf8Ssoda vs.col = col;
11908519eaf8Ssoda crtat = Crtat + pos;
11918519eaf8Ssoda vs.state = 0;
11928519eaf8Ssoda break;
11938519eaf8Ssoda }
11948519eaf8Ssoda case 'D': { /* left cursor */
11958519eaf8Ssoda int cx = vs.cx,
11968519eaf8Ssoda col = vs.col;
11978519eaf8Ssoda if (cx <= 0)
11988519eaf8Ssoda cx = 1;
11998519eaf8Ssoda else
12008519eaf8Ssoda cx %= vs.ncol;
12018519eaf8Ssoda pos = crtat - Crtat;
12028519eaf8Ssoda pos -= cx;
12038519eaf8Ssoda col -= cx;
12048519eaf8Ssoda if (col < 0) {
12058519eaf8Ssoda pos += vs.ncol;
12068519eaf8Ssoda col += vs.ncol;
12078519eaf8Ssoda }
12088519eaf8Ssoda vs.col = col;
12098519eaf8Ssoda crtat = Crtat + pos;
12108519eaf8Ssoda vs.state = 0;
12118519eaf8Ssoda break;
12128519eaf8Ssoda }
12138519eaf8Ssoda case 'J': /* Clear ... */
12148519eaf8Ssoda switch (vs.cx) {
12158519eaf8Ssoda case 0:
12168519eaf8Ssoda /* ... to end of display */
1217564df9b6Ssoda fillw((vs.at << 8) | ' ',
1218564df9b6Ssoda crtat,
12198519eaf8Ssoda Crtat + vs.nchr - crtat);
12208519eaf8Ssoda break;
12218519eaf8Ssoda case 1:
12228519eaf8Ssoda /* ... to next location */
1223564df9b6Ssoda fillw((vs.at << 8) | ' ',
1224564df9b6Ssoda Crtat,
12258519eaf8Ssoda crtat - Crtat + 1);
12268519eaf8Ssoda break;
12278519eaf8Ssoda case 2:
12288519eaf8Ssoda /* ... whole display */
1229564df9b6Ssoda fillw((vs.at << 8) | ' ',
1230564df9b6Ssoda Crtat,
12318519eaf8Ssoda vs.nchr);
12328519eaf8Ssoda break;
12338519eaf8Ssoda }
12348519eaf8Ssoda vs.state = 0;
12358519eaf8Ssoda break;
12368519eaf8Ssoda case 'K': /* Clear line ... */
12378519eaf8Ssoda switch (vs.cx) {
12388519eaf8Ssoda case 0:
12398519eaf8Ssoda /* ... current to EOL */
1240564df9b6Ssoda fillw((vs.at << 8) | ' ',
1241564df9b6Ssoda crtat,
12428519eaf8Ssoda vs.ncol - vs.col);
12438519eaf8Ssoda break;
12448519eaf8Ssoda case 1:
12458519eaf8Ssoda /* ... beginning to next */
12468519eaf8Ssoda fillw((vs.at << 8) | ' ',
12478519eaf8Ssoda crtat - vs.col,
12488519eaf8Ssoda vs.col + 1);
12498519eaf8Ssoda break;
12508519eaf8Ssoda case 2:
12518519eaf8Ssoda /* ... entire line */
12528519eaf8Ssoda fillw((vs.at << 8) | ' ',
12538519eaf8Ssoda crtat - vs.col, vs.ncol);
12548519eaf8Ssoda break;
12558519eaf8Ssoda }
12568519eaf8Ssoda vs.state = 0;
12578519eaf8Ssoda break;
12588519eaf8Ssoda case 'f': /* in system V consoles */
12598519eaf8Ssoda case 'H': { /* Cursor move */
12608519eaf8Ssoda int cx = vs.cx,
12618519eaf8Ssoda cy = vs.cy;
12628519eaf8Ssoda if (!cx || !cy) {
12638519eaf8Ssoda crtat = Crtat;
12648519eaf8Ssoda vs.col = 0;
12658519eaf8Ssoda } else {
12668519eaf8Ssoda if (cx > vs.nrow)
12678519eaf8Ssoda cx = vs.nrow;
12688519eaf8Ssoda if (cy > vs.ncol)
12698519eaf8Ssoda cy = vs.ncol;
12708519eaf8Ssoda crtat = Crtat +
12718519eaf8Ssoda (cx - 1) * vs.ncol + cy - 1;
12728519eaf8Ssoda vs.col = cy - 1;
12738519eaf8Ssoda }
12748519eaf8Ssoda vs.state = 0;
12758519eaf8Ssoda break;
12768519eaf8Ssoda }
12778519eaf8Ssoda case 'M': { /* delete cx rows */
12788519eaf8Ssoda u_short *crtAt = crtat - vs.col;
12798519eaf8Ssoda int cx = vs.cx,
12808519eaf8Ssoda row = (crtAt - Crtat) / vs.ncol,
12818519eaf8Ssoda nrow = vs.nrow - row;
12828519eaf8Ssoda if (cx <= 0)
12838519eaf8Ssoda cx = 1;
12848519eaf8Ssoda else if (cx > nrow)
12858519eaf8Ssoda cx = nrow;
12868519eaf8Ssoda if (cx < nrow)
1287564df9b6Ssoda #ifdef PCCONS_FORCE_WORD
1288564df9b6Ssoda wcopy(crtAt + vs.ncol * cx,
1289564df9b6Ssoda crtAt, vs.ncol * (nrow -
1290564df9b6Ssoda cx) * CHR);
1291564df9b6Ssoda #else
1292e9281952Stsutsui memmove(crtAt,
1293e9281952Stsutsui crtAt + vs.ncol * cx,
1294e9281952Stsutsui vs.ncol * (nrow - cx) *
1295e9281952Stsutsui CHR);
1296564df9b6Ssoda #endif
12978519eaf8Ssoda fillw((vs.at << 8) | ' ',
12988519eaf8Ssoda crtAt + vs.ncol * (nrow - cx),
12998519eaf8Ssoda vs.ncol * cx);
13008519eaf8Ssoda vs.state = 0;
13018519eaf8Ssoda break;
13028519eaf8Ssoda }
13038519eaf8Ssoda case 'S': { /* scroll up cx lines */
13048519eaf8Ssoda int cx = vs.cx;
13058519eaf8Ssoda if (cx <= 0)
13068519eaf8Ssoda cx = 1;
13078519eaf8Ssoda else if (cx > vs.nrow)
13088519eaf8Ssoda cx = vs.nrow;
13098519eaf8Ssoda if (cx < vs.nrow)
1310564df9b6Ssoda #ifdef PCCONS_FORCE_WORD
1311564df9b6Ssoda wcopy(Crtat + vs.ncol * cx,
1312564df9b6Ssoda Crtat, vs.ncol * (vs.nrow -
1313564df9b6Ssoda cx) * CHR);
1314564df9b6Ssoda #else
1315e9281952Stsutsui memmove(Crtat,
1316e9281952Stsutsui Crtat + vs.ncol * cx,
1317e9281952Stsutsui vs.ncol * (vs.nrow - cx) *
1318e9281952Stsutsui CHR);
1319564df9b6Ssoda #endif
13208519eaf8Ssoda fillw((vs.at << 8) | ' ',
13218519eaf8Ssoda Crtat + vs.ncol * (vs.nrow - cx),
13228519eaf8Ssoda vs.ncol * cx);
1323564df9b6Ssoda /* crtat -= vs.ncol * cx; XXX */
13248519eaf8Ssoda vs.state = 0;
13258519eaf8Ssoda break;
13268519eaf8Ssoda }
13278519eaf8Ssoda case 'L': { /* insert cx rows */
13288519eaf8Ssoda u_short *crtAt = crtat - vs.col;
13298519eaf8Ssoda int cx = vs.cx,
13308519eaf8Ssoda row = (crtAt - Crtat) / vs.ncol,
13318519eaf8Ssoda nrow = vs.nrow - row;
13328519eaf8Ssoda if (cx <= 0)
13338519eaf8Ssoda cx = 1;
13348519eaf8Ssoda else if (cx > nrow)
13358519eaf8Ssoda cx = nrow;
13368519eaf8Ssoda if (cx < nrow)
1337564df9b6Ssoda #ifdef PCCONS_FORCE_WORD
1338564df9b6Ssoda wcopy(crtAt,
1339564df9b6Ssoda crtAt + vs.ncol * cx,
1340564df9b6Ssoda vs.ncol * (nrow - cx) *
1341564df9b6Ssoda CHR);
1342564df9b6Ssoda #else
1343e9281952Stsutsui memmove(crtAt + vs.ncol * cx,
1344e9281952Stsutsui crtAt,
13458519eaf8Ssoda vs.ncol * (nrow - cx) *
13468519eaf8Ssoda CHR);
1347564df9b6Ssoda #endif
13488519eaf8Ssoda fillw((vs.at << 8) | ' ', crtAt,
13498519eaf8Ssoda vs.ncol * cx);
13508519eaf8Ssoda vs.state = 0;
13518519eaf8Ssoda break;
13528519eaf8Ssoda }
13538519eaf8Ssoda case 'T': { /* scroll down cx lines */
13548519eaf8Ssoda int cx = vs.cx;
13558519eaf8Ssoda if (cx <= 0)
13568519eaf8Ssoda cx = 1;
13578519eaf8Ssoda else if (cx > vs.nrow)
13588519eaf8Ssoda cx = vs.nrow;
13598519eaf8Ssoda if (cx < vs.nrow)
1360564df9b6Ssoda #ifdef PCCONS_FORCE_WORD
1361564df9b6Ssoda wcopy(Crtat,
1362564df9b6Ssoda Crtat + vs.ncol * cx,
1363564df9b6Ssoda vs.ncol * (vs.nrow - cx) *
1364564df9b6Ssoda CHR);
1365564df9b6Ssoda #else
1366e9281952Stsutsui memmove(Crtat + vs.ncol * cx,
1367e9281952Stsutsui Crtat,
13688519eaf8Ssoda vs.ncol * (vs.nrow - cx) *
13698519eaf8Ssoda CHR);
1370564df9b6Ssoda #endif
13718519eaf8Ssoda fillw((vs.at << 8) | ' ', Crtat,
13728519eaf8Ssoda vs.ncol * cx);
1373564df9b6Ssoda /* crtat += vs.ncol * cx; XXX */
13748519eaf8Ssoda vs.state = 0;
13758519eaf8Ssoda break;
13768519eaf8Ssoda }
13778519eaf8Ssoda case ';': /* Switch params in cursor def */
13788519eaf8Ssoda vs.state = VSS_EPARAM;
13798519eaf8Ssoda break;
13808519eaf8Ssoda case 'r':
13818519eaf8Ssoda vs.so_at = (vs.cx & FG_MASK) |
13828519eaf8Ssoda ((vs.cy << 4) & BG_MASK);
13838519eaf8Ssoda vs.state = 0;
13848519eaf8Ssoda break;
1385564df9b6Ssoda case 's': /* save cursor pos */
1386564df9b6Ssoda vs.offset = crtat - Crtat;
1387564df9b6Ssoda vs.state = 0;
1388564df9b6Ssoda break;
1389564df9b6Ssoda case 'u': /* restore cursor pos */
1390564df9b6Ssoda crtat = Crtat + vs.offset;
1391564df9b6Ssoda vs.row = vs.offset / vs.ncol;
1392564df9b6Ssoda vs.col = vs.offset % vs.ncol;
1393564df9b6Ssoda vs.state = 0;
1394564df9b6Ssoda break;
13958519eaf8Ssoda case 'x': /* set attributes */
13968519eaf8Ssoda switch (vs.cx) {
13978519eaf8Ssoda case 0:
13988519eaf8Ssoda vs.at = FG_LIGHTGREY | BG_BLACK;
13998519eaf8Ssoda break;
14008519eaf8Ssoda case 1:
14018519eaf8Ssoda /* ansi background */
14028519eaf8Ssoda if (!vs.color)
14038519eaf8Ssoda break;
14048519eaf8Ssoda vs.at &= FG_MASK;
14058519eaf8Ssoda vs.at |= bgansitopc[vs.cy & 7];
14068519eaf8Ssoda break;
14078519eaf8Ssoda case 2:
14088519eaf8Ssoda /* ansi foreground */
14098519eaf8Ssoda if (!vs.color)
14108519eaf8Ssoda break;
14118519eaf8Ssoda vs.at &= BG_MASK;
14128519eaf8Ssoda vs.at |= fgansitopc[vs.cy & 7];
14138519eaf8Ssoda break;
14148519eaf8Ssoda case 3:
14158519eaf8Ssoda /* pc text attribute */
14168519eaf8Ssoda if (vs.state >= VSS_EPARAM)
14178519eaf8Ssoda vs.at = vs.cy;
14188519eaf8Ssoda break;
14198519eaf8Ssoda }
14208519eaf8Ssoda vs.state = 0;
14218519eaf8Ssoda break;
14228519eaf8Ssoda
14238519eaf8Ssoda default: /* Only numbers valid here */
14248519eaf8Ssoda if ((c >= '0') && (c <= '9')) {
14258519eaf8Ssoda if (vs.state >= VSS_EPARAM) {
14268519eaf8Ssoda vs.cy *= 10;
14278519eaf8Ssoda vs.cy += c - '0';
14288519eaf8Ssoda } else {
14298519eaf8Ssoda vs.cx *= 10;
14308519eaf8Ssoda vs.cx += c - '0';
14318519eaf8Ssoda }
14328519eaf8Ssoda } else
14338519eaf8Ssoda vs.state = 0;
14348519eaf8Ssoda break;
14358519eaf8Ssoda }
14368519eaf8Ssoda break;
14378519eaf8Ssoda }
14388519eaf8Ssoda }
14398519eaf8Ssoda if (scroll) {
14408519eaf8Ssoda scroll = 0;
14418519eaf8Ssoda /* scroll check */
14428519eaf8Ssoda if (crtat >= Crtat + vs.nchr) {
14438519eaf8Ssoda if (!kernel) {
14448519eaf8Ssoda int s = spltty();
1445564df9b6Ssoda if (lock_state & KB_SCROLL)
1446564df9b6Ssoda tsleep(&lock_state,
14478519eaf8Ssoda PUSER, "pcputc", 0);
14488519eaf8Ssoda splx(s);
14498519eaf8Ssoda }
1450564df9b6Ssoda #if PCCONS_FORCE_WORD
1451564df9b6Ssoda wcopy(Crtat + vs.ncol, Crtat,
1452564df9b6Ssoda (vs.nchr - vs.ncol) * CHR);
1453564df9b6Ssoda #else
1454e9281952Stsutsui memmove(Crtat, Crtat + vs.ncol,
14558519eaf8Ssoda (vs.nchr - vs.ncol) * CHR);
1456564df9b6Ssoda #endif
14578519eaf8Ssoda fillw((vs.at << 8) | ' ',
1458564df9b6Ssoda Crtat + vs.nchr - vs.ncol,
1459564df9b6Ssoda vs.ncol);
14608519eaf8Ssoda crtat -= vs.ncol;
14618519eaf8Ssoda }
14628519eaf8Ssoda }
14638519eaf8Ssoda }
14648519eaf8Ssoda async_update();
14658519eaf8Ssoda }
14668519eaf8Ssoda
1467564df9b6Ssoda /* the unshifted code for KB_SHIFT keys is used by X to distinguish between
1468564df9b6Ssoda left and right shift when reading the keyboard map */
1469564df9b6Ssoda static pccons_keymap_t scan_codes[KB_NUM_KEYS] = {
1470564df9b6Ssoda /* type unshift shift control altgr shift_altgr scancode */
1471564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 0 unused */
1472564df9b6Ssoda { KB_ASCII, "\033", "\033", "\033", "", ""}, /* 1 ESCape */
1473564df9b6Ssoda { KB_ASCII, "1", "!", "!", "", ""}, /* 2 1 */
1474564df9b6Ssoda { KB_ASCII, "2", "@", "\000", "", ""}, /* 3 2 */
1475564df9b6Ssoda { KB_ASCII, "3", "#", "#", "", ""}, /* 4 3 */
1476564df9b6Ssoda { KB_ASCII, "4", "$", "$", "", ""}, /* 5 4 */
1477564df9b6Ssoda { KB_ASCII, "5", "%", "%", "", ""}, /* 6 5 */
1478564df9b6Ssoda { KB_ASCII, "6", "^", "\036", "", ""}, /* 7 6 */
1479564df9b6Ssoda { KB_ASCII, "7", "&", "&", "", ""}, /* 8 7 */
1480564df9b6Ssoda { KB_ASCII, "8", "*", "\010", "", ""}, /* 9 8 */
1481564df9b6Ssoda { KB_ASCII, "9", "(", "(", "", ""}, /* 10 9 */
1482564df9b6Ssoda { KB_ASCII, "0", ")", ")", "", ""}, /* 11 0 */
1483564df9b6Ssoda { KB_ASCII, "-", "_", "\037", "", ""}, /* 12 - */
1484564df9b6Ssoda { KB_ASCII, "=", "+", "+", "", ""}, /* 13 = */
1485564df9b6Ssoda { KB_ASCII, "\177", "\177", "\010", "", ""}, /* 14 backspace */
1486564df9b6Ssoda { KB_ASCII, "\t", "\t", "\t", "", ""}, /* 15 tab */
1487564df9b6Ssoda { KB_ASCII, "q", "Q", "\021", "", ""}, /* 16 q */
1488564df9b6Ssoda { KB_ASCII, "w", "W", "\027", "", ""}, /* 17 w */
1489564df9b6Ssoda { KB_ASCII, "e", "E", "\005", "", ""}, /* 18 e */
1490564df9b6Ssoda { KB_ASCII, "r", "R", "\022", "", ""}, /* 19 r */
1491564df9b6Ssoda { KB_ASCII, "t", "T", "\024", "", ""}, /* 20 t */
1492564df9b6Ssoda { KB_ASCII, "y", "Y", "\031", "", ""}, /* 21 y */
1493564df9b6Ssoda { KB_ASCII, "u", "U", "\025", "", ""}, /* 22 u */
1494564df9b6Ssoda { KB_ASCII, "i", "I", "\011", "", ""}, /* 23 i */
1495564df9b6Ssoda { KB_ASCII, "o", "O", "\017", "", ""}, /* 24 o */
1496564df9b6Ssoda { KB_ASCII, "p", "P", "\020", "", ""}, /* 25 p */
1497564df9b6Ssoda { KB_ASCII, "[", "{", "\033", "", ""}, /* 26 [ */
1498564df9b6Ssoda { KB_ASCII, "]", "}", "\035", "", ""}, /* 27 ] */
1499564df9b6Ssoda { KB_ASCII, "\r", "\r", "\n", "", ""}, /* 28 return */
1500564df9b6Ssoda { KB_CTL, "", "", "", "", ""}, /* 29 control */
1501564df9b6Ssoda { KB_ASCII, "a", "A", "\001", "", ""}, /* 30 a */
1502564df9b6Ssoda { KB_ASCII, "s", "S", "\023", "", ""}, /* 31 s */
1503564df9b6Ssoda { KB_ASCII, "d", "D", "\004", "", ""}, /* 32 d */
1504564df9b6Ssoda { KB_ASCII, "f", "F", "\006", "", ""}, /* 33 f */
1505564df9b6Ssoda { KB_ASCII, "g", "G", "\007", "", ""}, /* 34 g */
1506564df9b6Ssoda { KB_ASCII, "h", "H", "\010", "", ""}, /* 35 h */
1507564df9b6Ssoda { KB_ASCII, "j", "J", "\n", "", ""}, /* 36 j */
1508564df9b6Ssoda { KB_ASCII, "k", "K", "\013", "", ""}, /* 37 k */
1509564df9b6Ssoda { KB_ASCII, "l", "L", "\014", "", ""}, /* 38 l */
1510564df9b6Ssoda { KB_ASCII, ";", ":", ";", "", ""}, /* 39 ; */
1511564df9b6Ssoda { KB_ASCII, "'", "\"", "'", "", ""}, /* 40 ' */
1512564df9b6Ssoda { KB_ASCII, "`", "~", "`", "", ""}, /* 41 ` */
1513564df9b6Ssoda { KB_SHIFT, "\001", "", "", "", ""}, /* 42 shift */
1514564df9b6Ssoda { KB_ASCII, "\\", "|", "\034", "", ""}, /* 43 \ */
1515564df9b6Ssoda { KB_ASCII, "z", "Z", "\032", "", ""}, /* 44 z */
1516564df9b6Ssoda { KB_ASCII, "x", "X", "\030", "", ""}, /* 45 x */
1517564df9b6Ssoda { KB_ASCII, "c", "C", "\003", "", ""}, /* 46 c */
1518564df9b6Ssoda { KB_ASCII, "v", "V", "\026", "", ""}, /* 47 v */
1519564df9b6Ssoda { KB_ASCII, "b", "B", "\002", "", ""}, /* 48 b */
1520564df9b6Ssoda { KB_ASCII, "n", "N", "\016", "", ""}, /* 49 n */
1521564df9b6Ssoda { KB_ASCII, "m", "M", "\r", "", ""}, /* 50 m */
1522564df9b6Ssoda { KB_ASCII, ",", "<", "<", "", ""}, /* 51 , */
1523564df9b6Ssoda { KB_ASCII, ".", ">", ">", "", ""}, /* 52 . */
1524564df9b6Ssoda { KB_ASCII, "/", "?", "\037", "", ""}, /* 53 / */
1525564df9b6Ssoda { KB_SHIFT, "\002", "", "", "", ""}, /* 54 shift */
1526564df9b6Ssoda { KB_KP, "*", "*", "*", "", ""}, /* 55 kp * */
1527564df9b6Ssoda { KB_ALT, "", "", "", "", ""}, /* 56 alt */
1528564df9b6Ssoda { KB_ASCII, " ", " ", "\000", "", ""}, /* 57 space */
1529564df9b6Ssoda { KB_CAPS, "", "", "", "", ""}, /* 58 caps */
1530564df9b6Ssoda { KB_FUNC, "\033[M", "\033[Y", "\033[k", "", ""}, /* 59 f1 */
1531564df9b6Ssoda { KB_FUNC, "\033[N", "\033[Z", "\033[l", "", ""}, /* 60 f2 */
1532564df9b6Ssoda { KB_FUNC, "\033[O", "\033[a", "\033[m", "", ""}, /* 61 f3 */
1533564df9b6Ssoda { KB_FUNC, "\033[P", "\033[b", "\033[n", "", ""}, /* 62 f4 */
1534564df9b6Ssoda { KB_FUNC, "\033[Q", "\033[c", "\033[o", "", ""}, /* 63 f5 */
1535564df9b6Ssoda { KB_FUNC, "\033[R", "\033[d", "\033[p", "", ""}, /* 64 f6 */
1536564df9b6Ssoda { KB_FUNC, "\033[S", "\033[e", "\033[q", "", ""}, /* 65 f7 */
1537564df9b6Ssoda { KB_FUNC, "\033[T", "\033[f", "\033[r", "", ""}, /* 66 f8 */
1538564df9b6Ssoda { KB_FUNC, "\033[U", "\033[g", "\033[s", "", ""}, /* 67 f9 */
1539564df9b6Ssoda { KB_FUNC, "\033[V", "\033[h", "\033[t", "", ""}, /* 68 f10 */
1540564df9b6Ssoda { KB_NUM, "", "", "", "", ""}, /* 69 num lock */
1541564df9b6Ssoda { KB_SCROLL, "", "", "", "", ""}, /* 70 scroll lock */
1542564df9b6Ssoda { KB_KP, "7", "\033[H", "7", "", ""}, /* 71 kp 7 */
1543564df9b6Ssoda { KB_KP, "8", "\033[A", "8", "", ""}, /* 72 kp 8 */
1544564df9b6Ssoda { KB_KP, "9", "\033[I", "9", "", ""}, /* 73 kp 9 */
1545564df9b6Ssoda { KB_KP, "-", "-", "-", "", ""}, /* 74 kp - */
1546564df9b6Ssoda { KB_KP, "4", "\033[D", "4", "", ""}, /* 75 kp 4 */
1547564df9b6Ssoda { KB_KP, "5", "\033[E", "5", "", ""}, /* 76 kp 5 */
1548564df9b6Ssoda { KB_KP, "6", "\033[C", "6", "", ""}, /* 77 kp 6 */
1549564df9b6Ssoda { KB_KP, "+", "+", "+", "", ""}, /* 78 kp + */
1550564df9b6Ssoda { KB_KP, "1", "\033[F", "1", "", ""}, /* 79 kp 1 */
1551564df9b6Ssoda { KB_KP, "2", "\033[B", "2", "", ""}, /* 80 kp 2 */
1552564df9b6Ssoda { KB_KP, "3", "\033[G", "3", "", ""}, /* 81 kp 3 */
1553564df9b6Ssoda { KB_KP, "0", "\033[L", "0", "", ""}, /* 82 kp 0 */
1554564df9b6Ssoda { KB_KP, ",", "\177", ",", "", ""}, /* 83 kp , */
1555564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 84 0 */
1556564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 85 0 */
1557564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 86 0 */
1558564df9b6Ssoda { KB_FUNC, "\033[W", "\033[i", "\033[u", "", ""}, /* 87 f11 */
1559564df9b6Ssoda { KB_FUNC, "\033[X", "\033[j", "\033[v", "", ""}, /* 88 f12 */
1560564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 89 0 */
1561564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 90 0 */
1562564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 91 0 */
1563564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 92 0 */
1564564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 93 0 */
1565564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 94 0 */
1566564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 95 0 */
1567564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 96 0 */
1568564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 97 0 */
1569564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 98 0 */
1570564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 99 0 */
1571564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 100 */
1572564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 101 */
1573564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 102 */
1574564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 103 */
1575564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 104 */
1576564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 105 */
1577564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 106 */
1578564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 107 */
1579564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 108 */
1580564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 109 */
1581564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 110 */
1582564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 111 */
1583564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 112 */
1584564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 113 */
1585564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 114 */
1586564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 115 */
1587564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 116 */
1588564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 117 */
1589564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 118 */
1590564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 119 */
1591564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 120 */
1592564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 121 */
1593564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 122 */
1594564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 123 */
1595564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 124 */
1596564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 125 */
1597564df9b6Ssoda { KB_NONE, "", "", "", "", ""}, /* 126 */
1598564df9b6Ssoda { KB_NONE, "", "", "", "", ""} /* 127 */
15998519eaf8Ssoda };
16008519eaf8Ssoda
16018519eaf8Ssoda /*
16028519eaf8Ssoda * Get characters from the keyboard. If none are present, return NULL.
16038519eaf8Ssoda */
16048519eaf8Ssoda char *
sget(void)16057fe2a5a0Stsutsui sget(void)
16068519eaf8Ssoda {
16078519eaf8Ssoda u_char dt;
16088519eaf8Ssoda static u_char extended = 0, shift_state = 0;
16098519eaf8Ssoda static u_char capchar[2];
16108519eaf8Ssoda
16118519eaf8Ssoda top:
16128519eaf8Ssoda KBD_DELAY;
1613b7abba77Ssoda dt = kbd_data_read_1();
16148519eaf8Ssoda
16158519eaf8Ssoda switch (dt) {
16168519eaf8Ssoda case KBR_ACK: case KBR_ECHO:
16178519eaf8Ssoda kb_oq_get = (kb_oq_get + 1) & 7;
16188519eaf8Ssoda if(kb_oq_get != kb_oq_put) {
1619b7abba77Ssoda kbd_data_write_1(kb_oq[kb_oq_get]);
16208519eaf8Ssoda }
16218519eaf8Ssoda goto loop;
16228519eaf8Ssoda case KBR_RESEND:
1623b7abba77Ssoda kbd_data_write_1(kb_oq[kb_oq_get]);
16248519eaf8Ssoda goto loop;
16258519eaf8Ssoda }
16268519eaf8Ssoda
16278519eaf8Ssoda if (pc_xmode > 0) {
16288519eaf8Ssoda #if defined(DDB) && defined(XSERVER_DDB)
16298519eaf8Ssoda /* F12 enters the debugger while in X mode */
16308519eaf8Ssoda if (dt == 88)
16318519eaf8Ssoda Debugger();
16328519eaf8Ssoda #endif
16338519eaf8Ssoda capchar[0] = dt;
16348519eaf8Ssoda capchar[1] = 0;
16358519eaf8Ssoda /*
16368519eaf8Ssoda * Check for locking keys.
16378519eaf8Ssoda *
16388519eaf8Ssoda * XXX Setting the LEDs this way is a bit bogus. What if the
16398519eaf8Ssoda * keyboard has been remapped in X?
16408519eaf8Ssoda */
1641564df9b6Ssoda switch (scan_codes[dt & 0x7f].type) {
1642564df9b6Ssoda case KB_NUM:
16438519eaf8Ssoda if (dt & 0x80) {
1644564df9b6Ssoda shift_state &= ~KB_NUM;
16458519eaf8Ssoda break;
16468519eaf8Ssoda }
1647564df9b6Ssoda if (shift_state & KB_NUM)
16488519eaf8Ssoda break;
1649564df9b6Ssoda shift_state |= KB_NUM;
1650564df9b6Ssoda lock_state ^= KB_NUM;
16518519eaf8Ssoda async_update();
16528519eaf8Ssoda break;
1653564df9b6Ssoda case KB_CAPS:
16548519eaf8Ssoda if (dt & 0x80) {
1655564df9b6Ssoda shift_state &= ~KB_CAPS;
16568519eaf8Ssoda break;
16578519eaf8Ssoda }
1658564df9b6Ssoda if (shift_state & KB_CAPS)
16598519eaf8Ssoda break;
1660564df9b6Ssoda shift_state |= KB_CAPS;
1661564df9b6Ssoda lock_state ^= KB_CAPS;
16628519eaf8Ssoda async_update();
16638519eaf8Ssoda break;
1664564df9b6Ssoda case KB_SCROLL:
16658519eaf8Ssoda if (dt & 0x80) {
1666564df9b6Ssoda shift_state &= ~KB_SCROLL;
16678519eaf8Ssoda break;
16688519eaf8Ssoda }
1669564df9b6Ssoda if (shift_state & KB_SCROLL)
16708519eaf8Ssoda break;
1671564df9b6Ssoda shift_state |= KB_SCROLL;
1672564df9b6Ssoda lock_state ^= KB_SCROLL;
1673564df9b6Ssoda if ((lock_state & KB_SCROLL) == 0)
167453524e44Schristos wakeup((void *)&lock_state);
16758519eaf8Ssoda async_update();
16768519eaf8Ssoda break;
16778519eaf8Ssoda }
16788519eaf8Ssoda return capchar;
16798519eaf8Ssoda }
16808519eaf8Ssoda
16818519eaf8Ssoda switch (dt) {
16828519eaf8Ssoda case KBR_EXTENDED:
16838519eaf8Ssoda extended = 1;
16848519eaf8Ssoda goto loop;
16858519eaf8Ssoda }
16868519eaf8Ssoda
1687564df9b6Ssoda #ifdef DDB
16888519eaf8Ssoda /*
16898519eaf8Ssoda * Check for cntl-alt-esc.
16908519eaf8Ssoda */
1691564df9b6Ssoda if ((dt == 1) && (shift_state & (KB_CTL | KB_ALT)) == (KB_CTL | KB_ALT)) {
1692564df9b6Ssoda /* XXX - check pccons_is_console */
1693564df9b6Ssoda Debugger();
16948519eaf8Ssoda dt |= 0x80; /* discard esc (ddb discarded ctl-alt) */
16958519eaf8Ssoda }
16968519eaf8Ssoda #endif
16978519eaf8Ssoda
16988519eaf8Ssoda /*
16998519eaf8Ssoda * Check for make/break.
17008519eaf8Ssoda */
17018519eaf8Ssoda if (dt & 0x80) {
17028519eaf8Ssoda /*
17038519eaf8Ssoda * break
17048519eaf8Ssoda */
17058519eaf8Ssoda dt &= 0x7f;
1706564df9b6Ssoda switch (scan_codes[dt].type) {
1707564df9b6Ssoda case KB_NUM:
1708564df9b6Ssoda shift_state &= ~KB_NUM;
17098519eaf8Ssoda break;
1710564df9b6Ssoda case KB_CAPS:
1711564df9b6Ssoda shift_state &= ~KB_CAPS;
17128519eaf8Ssoda break;
1713564df9b6Ssoda case KB_SCROLL:
1714564df9b6Ssoda shift_state &= ~KB_SCROLL;
17158519eaf8Ssoda break;
1716564df9b6Ssoda case KB_SHIFT:
1717564df9b6Ssoda shift_state &= ~KB_SHIFT;
17188519eaf8Ssoda break;
1719564df9b6Ssoda case KB_ALT:
17208519eaf8Ssoda if (extended)
1721564df9b6Ssoda shift_state &= ~KB_ALTGR;
17228519eaf8Ssoda else
1723564df9b6Ssoda shift_state &= ~KB_ALT;
17248519eaf8Ssoda break;
1725564df9b6Ssoda case KB_CTL:
1726564df9b6Ssoda shift_state &= ~KB_CTL;
17278519eaf8Ssoda break;
17288519eaf8Ssoda }
17298519eaf8Ssoda } else {
17308519eaf8Ssoda /*
17318519eaf8Ssoda * make
17328519eaf8Ssoda */
1733564df9b6Ssoda switch (scan_codes[dt].type) {
17348519eaf8Ssoda /*
17358519eaf8Ssoda * locking keys
17368519eaf8Ssoda */
1737564df9b6Ssoda case KB_NUM:
1738564df9b6Ssoda if (shift_state & KB_NUM)
17398519eaf8Ssoda break;
1740564df9b6Ssoda shift_state |= KB_NUM;
1741564df9b6Ssoda lock_state ^= KB_NUM;
17428519eaf8Ssoda async_update();
17438519eaf8Ssoda break;
1744564df9b6Ssoda case KB_CAPS:
1745564df9b6Ssoda if (shift_state & KB_CAPS)
17468519eaf8Ssoda break;
1747564df9b6Ssoda shift_state |= KB_CAPS;
1748564df9b6Ssoda lock_state ^= KB_CAPS;
17498519eaf8Ssoda async_update();
17508519eaf8Ssoda break;
1751564df9b6Ssoda case KB_SCROLL:
1752564df9b6Ssoda if (shift_state & KB_SCROLL)
17538519eaf8Ssoda break;
1754564df9b6Ssoda shift_state |= KB_SCROLL;
1755564df9b6Ssoda lock_state ^= KB_SCROLL;
1756564df9b6Ssoda if ((lock_state & KB_SCROLL) == 0)
175753524e44Schristos wakeup((void *)&lock_state);
17588519eaf8Ssoda async_update();
17598519eaf8Ssoda break;
17608519eaf8Ssoda /*
17618519eaf8Ssoda * non-locking keys
17628519eaf8Ssoda */
1763564df9b6Ssoda case KB_SHIFT:
1764564df9b6Ssoda shift_state |= KB_SHIFT;
17658519eaf8Ssoda break;
1766564df9b6Ssoda case KB_ALT:
17678519eaf8Ssoda if (extended)
1768564df9b6Ssoda shift_state |= KB_ALTGR;
17698519eaf8Ssoda else
1770564df9b6Ssoda shift_state |= KB_ALT;
17718519eaf8Ssoda break;
1772564df9b6Ssoda case KB_CTL:
1773564df9b6Ssoda shift_state |= KB_CTL;
17748519eaf8Ssoda break;
1775564df9b6Ssoda case KB_ASCII:
1776564df9b6Ssoda /* control has highest priority */
1777564df9b6Ssoda if (shift_state & KB_CTL)
1778564df9b6Ssoda capchar[0] = scan_codes[dt].ctl[0];
1779564df9b6Ssoda else if (shift_state & KB_ALTGR) {
1780564df9b6Ssoda if (shift_state & KB_SHIFT)
1781564df9b6Ssoda capchar[0] = scan_codes[dt].shift_altgr[0];
1782564df9b6Ssoda else
1783564df9b6Ssoda capchar[0] = scan_codes[dt].altgr[0];
17848519eaf8Ssoda }
1785564df9b6Ssoda else {
1786564df9b6Ssoda if (shift_state & KB_SHIFT)
1787564df9b6Ssoda capchar[0] = scan_codes[dt].shift[0];
17888519eaf8Ssoda else
1789564df9b6Ssoda capchar[0] = scan_codes[dt].unshift[0];
1790564df9b6Ssoda }
1791564df9b6Ssoda if ((lock_state & KB_CAPS) && capchar[0] >= 'a' &&
17928519eaf8Ssoda capchar[0] <= 'z') {
17938519eaf8Ssoda capchar[0] -= ('a' - 'A');
17948519eaf8Ssoda }
1795564df9b6Ssoda capchar[0] |= (shift_state & KB_ALT);
17968519eaf8Ssoda extended = 0;
17978519eaf8Ssoda return capchar;
1798564df9b6Ssoda case KB_NONE:
17998519eaf8Ssoda printf("keycode %d\n",dt);
18008519eaf8Ssoda break;
1801564df9b6Ssoda case KB_FUNC: {
18028519eaf8Ssoda char *more_chars;
1803564df9b6Ssoda if (shift_state & KB_SHIFT)
1804564df9b6Ssoda more_chars = scan_codes[dt].shift;
1805564df9b6Ssoda else if (shift_state & KB_CTL)
1806564df9b6Ssoda more_chars = scan_codes[dt].ctl;
18078519eaf8Ssoda else
1808564df9b6Ssoda more_chars = scan_codes[dt].unshift;
18098519eaf8Ssoda extended = 0;
18108519eaf8Ssoda return more_chars;
18118519eaf8Ssoda }
1812564df9b6Ssoda case KB_KP: {
18138519eaf8Ssoda char *more_chars;
1814564df9b6Ssoda if (shift_state & (KB_SHIFT | KB_CTL) ||
1815564df9b6Ssoda (lock_state & KB_NUM) == 0 || extended)
1816564df9b6Ssoda more_chars = scan_codes[dt].shift;
18178519eaf8Ssoda else
1818564df9b6Ssoda more_chars = scan_codes[dt].unshift;
18198519eaf8Ssoda extended = 0;
18208519eaf8Ssoda return more_chars;
18218519eaf8Ssoda }
18228519eaf8Ssoda }
18238519eaf8Ssoda }
18248519eaf8Ssoda
18258519eaf8Ssoda extended = 0;
18268519eaf8Ssoda loop:
1827b7abba77Ssoda if ((kbd_cmd_read_1() & KBS_DIB) == 0)
18288519eaf8Ssoda return 0;
18298519eaf8Ssoda goto top;
18308519eaf8Ssoda }
18318519eaf8Ssoda
1832889c658bSsimonb paddr_t
pcmmap(dev_t dev,off_t offset,int nprot)18337fe2a5a0Stsutsui pcmmap(dev_t dev, off_t offset, int nprot)
18348519eaf8Ssoda {
1835b7abba77Ssoda struct pccons_context *pc = &pccons_console_context;
1836b7abba77Ssoda paddr_t pa;
18378519eaf8Ssoda
1838b7abba77Ssoda if (offset >= 0xa0000 && offset < 0xc0000) {
1839b7abba77Ssoda if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
18407fe2a5a0Stsutsui return -1;
1841b7abba77Ssoda pa += offset - pc->pc_config->pc_mono_memaddr;
18427fe2a5a0Stsutsui return mips_btop(pa);
1843564df9b6Ssoda }
1844b7abba77Ssoda if (offset >= 0x0000 && offset < 0x10000) {
1845b7abba77Ssoda if (bus_space_paddr(pc->pc_crt_iot, pc->pc_mono_ioh, &pa))
18467fe2a5a0Stsutsui return -1;
1847b7abba77Ssoda pa += offset - pc->pc_config->pc_mono_iobase;
18487fe2a5a0Stsutsui return mips_btop(pa);
1849b7abba77Ssoda }
1850b7abba77Ssoda if (offset >= 0x40000000 && offset < 0x40800000) {
1851b7abba77Ssoda if (bus_space_paddr(pc->pc_crt_memt, pc->pc_mono_memh, &pa))
1852b7abba77Ssoda return (-1);
1853b7abba77Ssoda pa += offset - 0x40000000 - pc->pc_config->pc_mono_memaddr;
18547fe2a5a0Stsutsui return mips_btop(pa);
1855b7abba77Ssoda }
18567fe2a5a0Stsutsui return -1;
18578519eaf8Ssoda }
18588519eaf8Ssoda
1859564df9b6Ssoda void
pc_xmode_on(void)18607fe2a5a0Stsutsui pc_xmode_on(void)
18618519eaf8Ssoda {
18628519eaf8Ssoda if (pc_xmode)
18638519eaf8Ssoda return;
18648519eaf8Ssoda pc_xmode = 1;
18658519eaf8Ssoda
18668519eaf8Ssoda #ifdef XFREE86_BUG_COMPAT
18678519eaf8Ssoda /* If still unchanged, get current shape. */
18688519eaf8Ssoda if (cursor_shape == 0xffff)
18698519eaf8Ssoda get_cursor_shape();
18708519eaf8Ssoda #endif
18718519eaf8Ssoda }
18728519eaf8Ssoda
1873564df9b6Ssoda void
pc_xmode_off(void)18747fe2a5a0Stsutsui pc_xmode_off(void)
18758519eaf8Ssoda {
18768519eaf8Ssoda if (pc_xmode == 0)
18778519eaf8Ssoda return;
18788519eaf8Ssoda pc_xmode = 0;
18798519eaf8Ssoda
18808519eaf8Ssoda #ifdef XFREE86_BUG_COMPAT
18818519eaf8Ssoda /* XXX It would be hard to justify why the X server doesn't do this. */
18828519eaf8Ssoda set_cursor_shape();
18838519eaf8Ssoda #endif
18848519eaf8Ssoda async_update();
18858519eaf8Ssoda }
1886