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