xref: /csrg-svn/sys/pmax/dev/dc.c (revision 52674)
152130Smckusick /*
252130Smckusick  * Copyright (c) 1992 Regents of the University of California.
352130Smckusick  * All rights reserved.
452130Smckusick  *
552130Smckusick  * This code is derived from software contributed to Berkeley by
652130Smckusick  * Ralph Campbell.
752130Smckusick  *
852130Smckusick  * %sccs.include.redist.c%
952130Smckusick  *
10*52674Smckusick  *	@(#)dc.c	7.2 (Berkeley) 02/26/92
1152130Smckusick  *
1252130Smckusick  * devDC7085.c --
1352130Smckusick  *
1452130Smckusick  *     	This file contains machine-dependent routines that handle the
1552130Smckusick  *	output queue for the serial lines.
1652130Smckusick  *
1752130Smckusick  *	Copyright (C) 1989 Digital Equipment Corporation.
1852130Smckusick  *	Permission to use, copy, modify, and distribute this software and
1952130Smckusick  *	its documentation for any purpose and without fee is hereby granted,
2052130Smckusick  *	provided that the above copyright notice appears in all copies.
2152130Smckusick  *	Digital Equipment Corporation makes no representations about the
2252130Smckusick  *	suitability of this software for any purpose.  It is provided "as is"
2352130Smckusick  *	without express or implied warranty.
2452130Smckusick  *
2552130Smckusick  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c,
2652130Smckusick  *	v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)";
2752130Smckusick  */
2852130Smckusick 
2952130Smckusick #include "dc.h"
3052130Smckusick #if NDC > 0
3152130Smckusick /*
3252130Smckusick  * DC7085 (DZ-11 look alike) Driver
3352130Smckusick  */
3452130Smckusick #include "param.h"
3552130Smckusick #include "systm.h"
3652130Smckusick #include "ioctl.h"
3752130Smckusick #include "tty.h"
3852130Smckusick #include "proc.h"
3952130Smckusick #include "map.h"
4052130Smckusick #include "buf.h"
4152130Smckusick #include "conf.h"
4252130Smckusick #include "file.h"
4352130Smckusick #include "uio.h"
4452130Smckusick #include "kernel.h"
4552130Smckusick #include "syslog.h"
4652130Smckusick 
4752130Smckusick #include "machine/dc7085cons.h"
4852130Smckusick 
4952130Smckusick #include "device.h"
5052130Smckusick #include "pdma.h"
5152130Smckusick 
5252130Smckusick /*
5352130Smckusick  * Driver information for auto-configuration stuff.
5452130Smckusick  */
5552130Smckusick int	dcprobe();
5652130Smckusick struct	driver dcdriver = {
5752130Smckusick 	"dc", dcprobe, 0, 0,
5852130Smckusick };
5952130Smckusick 
6052130Smckusick #define	NDCLINE 	(NDC*4)
6152130Smckusick 
6252130Smckusick extern int dcstart(), dcxint();
6352130Smckusick extern int ttrstrt();
6452130Smckusick 
6552130Smckusick struct	tty dc_tty[NDCLINE];
6652130Smckusick int	dc_cnt = NDCLINE;
6752130Smckusick int	dcDivertXInput;		/* true if diverting KBD input to X */
6852130Smckusick #ifdef DEBUG
6952130Smckusick int	debugChar;
7052130Smckusick #endif
7152130Smckusick 
7252130Smckusick /*
7352130Smckusick  * Software copy of brk register since it isn't readable
7452130Smckusick  */
7552130Smckusick int	dc_brk[NDC];
7652130Smckusick char	dcsoftCAR[NDC];		/* mask of dc's with carrier on (DSR) */
7752130Smckusick 
7852130Smckusick /*
7952130Smckusick  * The DC7085 doesn't interrupt on carrier transitions, so
8052130Smckusick  * we have to use a timer to watch it.
8152130Smckusick  */
8252130Smckusick int	dc_timer;		/* true if timer started */
8352130Smckusick 
8452130Smckusick /*
8552130Smckusick  * Pdma structures for fast output code
8652130Smckusick  */
8752130Smckusick struct	pdma dcpdma[NDCLINE];
8852130Smckusick 
8952130Smckusick struct speedtab dcspeedtab[] = {
9052130Smckusick 	0,	0,
9152130Smckusick 	50,	LPR_B50,
9252130Smckusick 	75,	LPR_B75,
9352130Smckusick 	110,	LPR_B110,
9452130Smckusick 	134,	LPR_B134,
9552130Smckusick 	150,	LPR_B150,
9652130Smckusick 	300,	LPR_B300,
9752130Smckusick 	600,	LPR_B600,
9852130Smckusick 	1200,	LPR_B1200,
9952130Smckusick 	1800,	LPR_B1800,
10052130Smckusick 	2400,	LPR_B2400,
10152130Smckusick 	4800,	LPR_B4800,
10252130Smckusick 	9600,	LPR_B9600,
10352130Smckusick 	-1,	-1
10452130Smckusick };
10552130Smckusick 
10652130Smckusick #ifndef	PORTSELECTOR
10752130Smckusick #define	ISPEED	TTYDEF_SPEED
10852130Smckusick #define	LFLAG	TTYDEF_LFLAG
10952130Smckusick #else
11052130Smckusick #define	ISPEED	B4800
11152130Smckusick #define	LFLAG	(TTYDEF_LFLAG & ~ECHO)
11252130Smckusick #endif
11352130Smckusick 
11452130Smckusick /*
11552130Smckusick  * Ascii values of command keys.
11652130Smckusick  */
11752130Smckusick #define KBD_TAB		'\t'
11852130Smckusick #define KBD_DEL		127
11952130Smckusick #define KBD_RET		'\r'
12052130Smckusick 
12152130Smckusick /*
12252130Smckusick  *  Define "hardware-independent" codes for the control, shift, meta and
12352130Smckusick  *  function keys.  Codes start after the last 7-bit ASCII code (127)
12452130Smckusick  *  and are assigned in an arbitrary order.
12552130Smckusick  */
12652130Smckusick #define KBD_NOKEY	128
12752130Smckusick 
12852130Smckusick #define KBD_F1		201
12952130Smckusick #define KBD_F2		202
13052130Smckusick #define KBD_F3		203
13152130Smckusick #define KBD_F4		204
13252130Smckusick #define KBD_F5		205
13352130Smckusick #define KBD_F6		206
13452130Smckusick #define KBD_F7		207
13552130Smckusick #define KBD_F8		208
13652130Smckusick #define KBD_F9		209
13752130Smckusick #define KBD_F10		210
13852130Smckusick #define KBD_F11		211
13952130Smckusick #define KBD_F12		212
14052130Smckusick #define KBD_F13		213
14152130Smckusick #define KBD_F14		214
14252130Smckusick #define KBD_HELP	215
14352130Smckusick #define KBD_DO		216
14452130Smckusick #define KBD_F17		217
14552130Smckusick #define KBD_F18		218
14652130Smckusick #define KBD_F19		219
14752130Smckusick #define KBD_F20		220
14852130Smckusick 
14952130Smckusick #define KBD_FIND	221
15052130Smckusick #define KBD_INSERT	222
15152130Smckusick #define KBD_REMOVE	223
15252130Smckusick #define KBD_SELECT	224
15352130Smckusick #define KBD_PREVIOUS	225
15452130Smckusick #define KBD_NEXT	226
15552130Smckusick 
15652130Smckusick #define KBD_KP_ENTER	227
15752130Smckusick #define KBD_KP_F1	228
15852130Smckusick #define KBD_KP_F2	229
15952130Smckusick #define KBD_KP_F3	230
16052130Smckusick #define KBD_KP_F4	231
16152130Smckusick #define KBD_LEFT	232
16252130Smckusick #define KBD_RIGHT	233
16352130Smckusick #define KBD_DOWN	234
16452130Smckusick #define KBD_UP		235
16552130Smckusick 
16652130Smckusick #define KBD_CONTROL	236
16752130Smckusick #define KBD_SHIFT	237
16852130Smckusick #define KBD_CAPSLOCK	238
16952130Smckusick #define KBD_ALTERNATE	239
17052130Smckusick 
17152130Smckusick /*
17252130Smckusick  * Keyboard to Ascii, unshifted.
17352130Smckusick  */
17452130Smckusick static unsigned char unshiftedAscii[] = {
17552130Smckusick /*  0 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
17652130Smckusick /*  4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
17752130Smckusick /*  8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
17852130Smckusick /*  c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
17952130Smckusick /* 10 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18052130Smckusick /* 14 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18152130Smckusick /* 18 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18252130Smckusick /* 1c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18352130Smckusick /* 20 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18452130Smckusick /* 24 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18552130Smckusick /* 28 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18652130Smckusick /* 2c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18752130Smckusick /* 30 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18852130Smckusick /* 34 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
18952130Smckusick /* 38 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19052130Smckusick /* 3c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19152130Smckusick /* 40 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19252130Smckusick /* 44 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19352130Smckusick /* 48 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19452130Smckusick /* 4c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19552130Smckusick /* 50 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19652130Smckusick /* 54 */ KBD_NOKEY,	KBD_NOKEY,	KBD_F1,		KBD_F2,
19752130Smckusick /* 58 */ KBD_F3,	KBD_F4,		KBD_F5,		KBD_NOKEY,
19852130Smckusick /* 5c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19952130Smckusick /* 60 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20052130Smckusick /* 64 */ KBD_F6,	KBD_F7,		KBD_F8,		KBD_F9,
20152130Smckusick /* 68 */ KBD_F10,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20252130Smckusick /* 6c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20352130Smckusick /* 70 */ KBD_NOKEY,	'\033',		KBD_F12,	KBD_F13,
20452130Smckusick /* 74 */ KBD_F14,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20552130Smckusick /* 78 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20652130Smckusick /* 7c */ KBD_HELP,	KBD_DO,		KBD_NOKEY,	KBD_NOKEY,
20752130Smckusick /* 80 */ KBD_F17,	KBD_F18,	KBD_F19,	KBD_F20,
20852130Smckusick /* 84 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20952130Smckusick /* 88 */ KBD_NOKEY,	KBD_NOKEY,	KBD_FIND,	KBD_INSERT,
21052130Smckusick /* 8c */ KBD_REMOVE,	KBD_SELECT,	KBD_PREVIOUS,	KBD_NEXT,
21152130Smckusick /* 90 */ KBD_NOKEY,	KBD_NOKEY,	'0',		KBD_NOKEY,
21252130Smckusick /* 94 */ '.',		KBD_KP_ENTER,	'1',		'2',
21352130Smckusick /* 98 */ '3',		'4',		'5',		'6',
21452130Smckusick /* 9c */ ',',		'7',		'8',		'9',
21552130Smckusick /* a0 */ '-',		KBD_KP_F1,	KBD_KP_F2,	KBD_KP_F3,
21652130Smckusick /* a4 */ KBD_KP_F4,	KBD_NOKEY,	KBD_NOKEY,	KBD_LEFT,
21752130Smckusick /* a8 */ KBD_RIGHT,	KBD_DOWN, 	KBD_UP,		KBD_NOKEY,
21852130Smckusick /* ac */ KBD_NOKEY,	KBD_NOKEY,	KBD_SHIFT,	KBD_CONTROL,
21952130Smckusick /* b0 */ KBD_CAPSLOCK,	KBD_ALTERNATE,	KBD_NOKEY,	KBD_NOKEY,
22052130Smckusick /* b4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
22152130Smckusick /* b8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
22252130Smckusick /* bc */ KBD_DEL,	KBD_RET,	KBD_TAB,	'`',
22352130Smckusick /* c0 */ '1',		'q',		'a',		'z',
22452130Smckusick /* c4 */ KBD_NOKEY,	'2',		'w',		's',
22552130Smckusick /* c8 */ 'x',		'<',		KBD_NOKEY,	'3',
22652130Smckusick /* cc */ 'e',		'd',		'c',		KBD_NOKEY,
22752130Smckusick /* d0 */ '4',		'r',		'f',		'v',
22852130Smckusick /* d4 */ ' ',		KBD_NOKEY,	'5',		't',
22952130Smckusick /* d8 */ 'g',		'b',		KBD_NOKEY,	'6',
23052130Smckusick /* dc */ 'y',		'h',		'n',		KBD_NOKEY,
23152130Smckusick /* e0 */ '7',		'u',		'j',		'm',
23252130Smckusick /* e4 */ KBD_NOKEY,	'8',		'i',		'k',
23352130Smckusick /* e8 */ ',',		KBD_NOKEY,	'9',		'o',
23452130Smckusick /* ec */ 'l',		'.',		KBD_NOKEY,	'0',
23552130Smckusick /* f0 */ 'p',		KBD_NOKEY,	';',		'/',
23652130Smckusick /* f4 */ KBD_NOKEY,	'=',		']',		'\\',
23752130Smckusick /* f8 */ KBD_NOKEY,	'-',		'[',		'\'',
23852130Smckusick /* fc */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
23952130Smckusick };
24052130Smckusick 
24152130Smckusick /*
24252130Smckusick  * Keyboard to Ascii, shifted.
24352130Smckusick  */
24452130Smckusick static unsigned char shiftedAscii[] = {
24552130Smckusick /*  0 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
24652130Smckusick /*  4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
24752130Smckusick /*  8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
24852130Smckusick /*  c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
24952130Smckusick /* 10 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25052130Smckusick /* 14 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25152130Smckusick /* 18 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25252130Smckusick /* 1c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25352130Smckusick /* 20 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25452130Smckusick /* 24 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25552130Smckusick /* 28 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25652130Smckusick /* 2c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25752130Smckusick /* 30 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25852130Smckusick /* 34 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25952130Smckusick /* 38 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26052130Smckusick /* 3c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26152130Smckusick /* 40 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26252130Smckusick /* 44 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26352130Smckusick /* 48 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26452130Smckusick /* 4c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26552130Smckusick /* 50 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26652130Smckusick /* 54 */ KBD_NOKEY,	KBD_NOKEY,	KBD_F1,		KBD_F2,
26752130Smckusick /* 58 */ KBD_F3,	KBD_F4,		KBD_F5,		KBD_NOKEY,
26852130Smckusick /* 5c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26952130Smckusick /* 60 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27052130Smckusick /* 64 */ KBD_F6,	KBD_F7,		KBD_F8,		KBD_F9,
27152130Smckusick /* 68 */ KBD_F10,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27252130Smckusick /* 6c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27352130Smckusick /* 70 */ KBD_NOKEY,	KBD_F11,	KBD_F12,	KBD_F13,
27452130Smckusick /* 74 */ KBD_F14,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27552130Smckusick /* 78 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27652130Smckusick /* 7c */ KBD_HELP,	KBD_DO,		KBD_NOKEY,	KBD_NOKEY,
27752130Smckusick /* 80 */ KBD_F17,	KBD_F18,	KBD_F19,	KBD_F20,
27852130Smckusick /* 84 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27952130Smckusick /* 88 */ KBD_NOKEY,	KBD_NOKEY,	KBD_FIND,	KBD_INSERT,
28052130Smckusick /* 8c */ KBD_REMOVE,	KBD_SELECT,	KBD_PREVIOUS,	KBD_NEXT,
28152130Smckusick /* 90 */ KBD_NOKEY,	KBD_NOKEY,	'0',		KBD_NOKEY,
28252130Smckusick /* 94 */ '.',		KBD_KP_ENTER,	'1',		'2',
28352130Smckusick /* 98 */ '3',		'4',		'5',		'6',
28452130Smckusick /* 9c */ ',',		'7',		'8',		'9',
28552130Smckusick /* a0 */ '-',		KBD_KP_F1,	KBD_KP_F2,	KBD_KP_F3,
28652130Smckusick /* a4 */ KBD_KP_F4,	KBD_NOKEY,	KBD_NOKEY,	KBD_LEFT,
28752130Smckusick /* a8 */ KBD_RIGHT,	KBD_DOWN, 	KBD_UP,		KBD_NOKEY,
28852130Smckusick /* ac */ KBD_NOKEY,	KBD_NOKEY,	KBD_SHIFT,	KBD_CONTROL,
28952130Smckusick /* b0 */ KBD_CAPSLOCK,	KBD_ALTERNATE,	KBD_NOKEY,	KBD_NOKEY,
29052130Smckusick /* b4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
29152130Smckusick /* b8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
29252130Smckusick /* bc */ KBD_DEL,	KBD_RET,	KBD_TAB,	'~',
29352130Smckusick /* c0 */ '!',		'q',		'a',		'z',
29452130Smckusick /* c4 */ KBD_NOKEY,	'@',		'w',		's',
29552130Smckusick /* c8 */ 'x',		'>',		KBD_NOKEY,	'#',
29652130Smckusick /* cc */ 'e',		'd',		'c',		KBD_NOKEY,
29752130Smckusick /* d0 */ '$',		'r',		'f',		'v',
29852130Smckusick /* d4 */ ' ',		KBD_NOKEY,	'%',		't',
29952130Smckusick /* d8 */ 'g',		'b',		KBD_NOKEY,	'^',
30052130Smckusick /* dc */ 'y',		'h',		'n',		KBD_NOKEY,
30152130Smckusick /* e0 */ '&',		'u',		'j',		'm',
30252130Smckusick /* e4 */ KBD_NOKEY,	'*',		'i',		'k',
30352130Smckusick /* e8 */ '<',		KBD_NOKEY,	'(',		'o',
30452130Smckusick /* ec */ 'l',		'>',		KBD_NOKEY,	')',
30552130Smckusick /* f0 */ 'p',		KBD_NOKEY,	':',		'?',
30652130Smckusick /* f4 */ KBD_NOKEY,	'+',		'}',		'|',
30752130Smckusick /* f8 */ KBD_NOKEY,	'_',		'{',		'"',
30852130Smckusick /* fc */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
30952130Smckusick };
31052130Smckusick 
31152130Smckusick /*
31252130Smckusick  * Keyboard initialization string.
31352130Smckusick  */
31452130Smckusick static u_char kbdInitString[] = {
31552130Smckusick 	LK_LED_ENABLE, LED_ALL,		/* show we are resetting keyboard */
31652130Smckusick 	LK_DEFAULTS,
31752130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 1),
31852130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 2),
31952130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 3),
32052130Smckusick 	LK_CMD_MODE(LK_DOWN, 4),	/* could also be LK_AUTODOWN */
32152130Smckusick 	LK_CMD_MODE(LK_UPDOWN, 5),
32252130Smckusick 	LK_CMD_MODE(LK_UPDOWN, 6),
32352130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 7),
32452130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 8),
32552130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 9),
32652130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 10),
32752130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 11),
32852130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 12),
32952130Smckusick 	LK_CMD_MODE(LK_DOWN, 13),
33052130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 14),
33152130Smckusick 	LK_AR_ENABLE,			/* we want autorepeat by default */
33252130Smckusick 	LK_CL_ENABLE, 0x83,		/* keyclick, volume */
33352130Smckusick 	LK_KBD_ENABLE,			/* the keyboard itself */
33452130Smckusick 	LK_BELL_ENABLE, 0x83,		/* keyboard bell, volume */
33552130Smckusick 	LK_LED_DISABLE, LED_ALL,	/* clear keyboard leds */
33652130Smckusick };
33752130Smckusick 
33852130Smckusick /*
33952130Smckusick  * Test to see if device is present.
34052130Smckusick  * Return true if found and initialized ok.
34152130Smckusick  */
34252130Smckusick dcprobe(cp)
34352130Smckusick 	register struct pmax_ctlr *cp;
34452130Smckusick {
34552130Smckusick 	register dcregs *dcaddr;
34652130Smckusick 	register struct pdma *pdp;
34752130Smckusick 	register struct tty *tp;
34852130Smckusick 	register int cntr;
34952130Smckusick 	extern dcscan();
35052130Smckusick 	extern void dcKBDReset();
35152130Smckusick 	extern void MouseInit();
35252130Smckusick 
35352130Smckusick 	if (cp->pmax_unit >= NDC)
35452130Smckusick 		return (0);
35552130Smckusick 	if (badaddr(cp->pmax_addr, 2))
35652130Smckusick 		return (0);
35752130Smckusick 
35852130Smckusick 	/* reset chip */
35952130Smckusick 	dcaddr = (dcregs *)cp->pmax_addr;
36052130Smckusick 	dcaddr->dc_csr = CSR_CLR;
36152130Smckusick 	MachEmptyWriteBuffer();
36252130Smckusick 	while (dcaddr->dc_csr & CSR_CLR)
36352130Smckusick 		;
36452130Smckusick 	dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE;
36552130Smckusick 
36652130Smckusick 	/* init pseudo DMA structures */
36752130Smckusick 	pdp = &dcpdma[cp->pmax_unit * 4];
36852130Smckusick 	tp = &dc_tty[cp->pmax_unit * 4];
36952130Smckusick 	for (cntr = 0; cntr < 4; cntr++) {
37052130Smckusick 		pdp->p_addr = dcaddr;
37152130Smckusick 		pdp->p_arg = (int)tp;
37252130Smckusick 		pdp->p_fcn = dcxint;
37352130Smckusick 		tp->t_addr = (caddr_t)pdp;
37452130Smckusick 		pdp++, tp++;
37552130Smckusick 	}
37652130Smckusick 	dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB;
37752130Smckusick 
37852130Smckusick 	if (dc_timer == 0) {
37952130Smckusick 		dc_timer = 1;
38052130Smckusick 		timeout(dcscan, (caddr_t)0, hz);
38152130Smckusick 	}
38252130Smckusick 	printf("dc%d at nexus0 csr 0x%x\n", cp->pmax_unit, cp->pmax_addr);
38352130Smckusick 	if (cp->pmax_unit == 0) {
38452130Smckusick 		int s;
38552130Smckusick 
38652130Smckusick 		s = spltty();
38752130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR |
38852130Smckusick 			KBD_PORT;
38952130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
39052130Smckusick 			LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT;
39152130Smckusick 		MachEmptyWriteBuffer();
39252130Smckusick 		dcKBDReset();
39352130Smckusick 		MouseInit();
39452130Smckusick 		splx(s);
39552130Smckusick 	}
39652130Smckusick 	return (1);
39752130Smckusick }
39852130Smckusick 
39952130Smckusick dcopen(dev, flag)
40052130Smckusick 	dev_t dev;
40152130Smckusick {
40252130Smckusick 	register struct tty *tp;
40352130Smckusick 	register int unit;
40452130Smckusick 	int s, error = 0;
40552130Smckusick 	extern int dcparam();
40652130Smckusick 
40752130Smckusick 	unit = minor(dev);
40852130Smckusick 	if (unit >= dc_cnt || dcpdma[unit].p_addr == 0)
40952130Smckusick 		return (ENXIO);
41052130Smckusick 	tp = &dc_tty[unit];
41152130Smckusick 	tp->t_addr = (caddr_t)&dcpdma[unit];
41252130Smckusick 	tp->t_oproc = dcstart;
41352130Smckusick 	tp->t_param = dcparam;
41452130Smckusick 	tp->t_dev = dev;
41552130Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
41652130Smckusick 		tp->t_state |= TS_WOPEN;
41752130Smckusick 		ttychars(tp);
41852130Smckusick #ifndef PORTSELECTOR
41952130Smckusick 		if (tp->t_ispeed == 0) {
42052130Smckusick #endif
42152130Smckusick 			tp->t_iflag = TTYDEF_IFLAG;
42252130Smckusick 			tp->t_oflag = TTYDEF_OFLAG;
42352130Smckusick 			tp->t_cflag = TTYDEF_CFLAG;
42452130Smckusick 			tp->t_lflag = LFLAG;
42552130Smckusick 			tp->t_ispeed = tp->t_ospeed = ISPEED;
42652130Smckusick #ifdef PORTSELECTOR
42752130Smckusick 			tp->t_cflag |= HUPCL;
42852130Smckusick #else
42952130Smckusick 		}
43052130Smckusick #endif
43152130Smckusick 		(void) dcparam(tp, &tp->t_termios);
43252130Smckusick 		ttsetwater(tp);
43352130Smckusick 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
43452130Smckusick 		return (EBUSY);
43552130Smckusick 	(void) dcmctl(dev, DML_DTR, DMSET);
43652130Smckusick 	s = spltty();
43752130Smckusick 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
43852130Smckusick 	       !(tp->t_state & TS_CARR_ON)) {
43952130Smckusick 		tp->t_state |= TS_WOPEN;
44052130Smckusick 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
44152130Smckusick 		    ttopen, 0))
44252130Smckusick 			break;
44352130Smckusick 	}
44452130Smckusick 	splx(s);
44552130Smckusick 	if (error)
44652130Smckusick 		return (error);
44752130Smckusick 	return ((*linesw[tp->t_line].l_open)(dev, tp));
44852130Smckusick }
44952130Smckusick 
45052130Smckusick /*ARGSUSED*/
45152130Smckusick dcclose(dev, flag)
45252130Smckusick 	dev_t dev;
45352130Smckusick {
45452130Smckusick 	register struct tty *tp;
45552130Smckusick 	register int unit, bit;
45652130Smckusick 
45752130Smckusick 	unit = minor(dev);
45852130Smckusick 	tp = &dc_tty[unit];
45952130Smckusick 	bit = 1 << ((unit & 03) + 8);
46052130Smckusick 	if (dc_brk[unit >> 2] & bit) {
46152130Smckusick 		dc_brk[unit >> 2] &= ~bit;
46252130Smckusick 		ttyoutput(0, tp);
46352130Smckusick 	}
46452130Smckusick 	(*linesw[tp->t_line].l_close)(tp);
46552130Smckusick 	if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
46652130Smckusick 	    !(tp->t_state & TS_ISOPEN))
46752130Smckusick 		(void) dcmctl(dev, 0, DMSET);
46852130Smckusick 	return (ttyclose(tp));
46952130Smckusick }
47052130Smckusick 
47152130Smckusick dcread(dev, uio, flag)
47252130Smckusick 	dev_t dev;
47352130Smckusick 	struct uio *uio;
47452130Smckusick {
47552130Smckusick 	register struct tty *tp;
47652130Smckusick 
47752130Smckusick 	tp = &dc_tty[minor(dev)];
47852130Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
47952130Smckusick }
48052130Smckusick 
48152130Smckusick dcwrite(dev, uio, flag)
48252130Smckusick 	dev_t dev;
48352130Smckusick 	struct uio *uio;
48452130Smckusick {
48552130Smckusick 	register struct tty *tp;
48652130Smckusick 
48752130Smckusick 	tp = &dc_tty[minor(dev)];
48852130Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
48952130Smckusick }
49052130Smckusick 
49152130Smckusick /*
49252130Smckusick  * Check for interrupts from all devices.
49352130Smckusick  */
49452130Smckusick dcintr()
49552130Smckusick {
49652130Smckusick 	register struct pdma *p;
49752130Smckusick 	register unsigned csr;
49852130Smckusick 	register int unit;
49952130Smckusick 
50052130Smckusick 	for (unit = 0, p = dcpdma; p < &dcpdma[NDCLINE]; unit += 4, p += 4) {
50152130Smckusick 		while ((csr = p->p_addr->dc_csr) & (CSR_RDONE | CSR_TRDY)) {
50252130Smckusick 			if (csr & CSR_RDONE)
50352130Smckusick 				dcrint(unit);
50452130Smckusick 			if (csr & CSR_TRDY)
50552130Smckusick 				dcxint(&dc_tty[unit + ((csr >> 8) & 03)]);
50652130Smckusick 		}
50752130Smckusick 	}
50852130Smckusick }
50952130Smckusick 
51052130Smckusick dcrint(unit)
51152130Smckusick 	register int unit;
51252130Smckusick {
51352130Smckusick 	register dcregs *dcaddr;
51452130Smckusick 	register struct tty *tp;
51552130Smckusick 	register int c, cc;
51652130Smckusick 	register struct tty *tp0;
51752130Smckusick 	int overrun = 0;
51852130Smckusick 
51952130Smckusick 	dcaddr = dcpdma[unit].p_addr;
52052130Smckusick 	tp0 = &dc_tty[unit];
52152130Smckusick 	while ((c = dcaddr->dc_rbuf) < 0) {	/* char present */
52252130Smckusick 		cc = c & 0xff;
52352130Smckusick 		tp = tp0 + ((c >> 8) & 03);
52452130Smckusick 		if ((c & RBUF_OERR) && overrun == 0) {
52552130Smckusick 			log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2,
52652130Smckusick 				(c >> 8) & 03);
52752130Smckusick 			overrun = 1;
52852130Smckusick 		}
52952130Smckusick 		/* the keyboard requires special translation */
53052130Smckusick 		if (tp == &dc_tty[KBD_PORT]) {
53152130Smckusick 			static u_char shiftDown;
53252130Smckusick 			static u_char ctrlDown;
53352130Smckusick 			static u_char lastChar;
53452130Smckusick 
53552130Smckusick #ifdef DEBUG
53652130Smckusick 			if (cc == LK_DO)
53752130Smckusick 				panic("dcrint");
53852130Smckusick 			debugChar = cc;
53952130Smckusick 
54052130Smckusick #endif
54152130Smckusick 			if (dcDivertXInput) {
54252130Smckusick #ifdef DEBUG
54352130Smckusick 				if (cc == KEY_F1) {
54452130Smckusick 					dcDivertXInput = 0;
54552130Smckusick 					continue;
54652130Smckusick 				}
54752130Smckusick #endif
54852130Smckusick 				pmKbdEvent(cc);
54952130Smckusick 				continue;
55052130Smckusick 			}
55152130Smckusick 
55252130Smckusick 			switch (cc) {
55352130Smckusick 			case KEY_REPEAT:
55452130Smckusick 				cc = lastChar;
55552130Smckusick 				goto done;
55652130Smckusick 
55752130Smckusick 			case KEY_UP:
55852130Smckusick 				shiftDown = 0;
55952130Smckusick 				ctrlDown = 0;
56052130Smckusick 				continue;
56152130Smckusick 
56252130Smckusick 			case KEY_SHIFT:
56352130Smckusick 				if (ctrlDown)
56452130Smckusick 					shiftDown = 0;
56552130Smckusick 				else
56652130Smckusick 					shiftDown = 1;
56752130Smckusick 				continue;
56852130Smckusick 
56952130Smckusick 			case KEY_CONTROL:
57052130Smckusick 				if (shiftDown)
57152130Smckusick 					ctrlDown = 0;
57252130Smckusick 				else
57352130Smckusick 					ctrlDown = 1;
57452130Smckusick 				continue;
57552130Smckusick 
57652130Smckusick 			case LK_POWER_ERROR:
57752130Smckusick 			case LK_KDOWN_ERROR:
57852130Smckusick 			case LK_INPUT_ERROR:
57952130Smckusick 			case LK_OUTPUT_ERROR:
58052130Smckusick 				log(LOG_WARNING,
58152130Smckusick 					"dc0,0: keyboard error, code=%x\n", cc);
58252130Smckusick 				continue;
58352130Smckusick 			}
58452130Smckusick 			if (shiftDown)
58552130Smckusick 				cc = shiftedAscii[cc];
58652130Smckusick 			else
58752130Smckusick 				cc = unshiftedAscii[cc];
58852130Smckusick 			if (cc >= KBD_NOKEY) {
58952130Smckusick 				/*
59052130Smckusick 				 * A function key was typed - ignore it.
59152130Smckusick 				 */
59252130Smckusick 				continue;
59352130Smckusick 			}
59452130Smckusick 			if (cc >= 'a' && cc <= 'z') {
59552130Smckusick 				if (ctrlDown)
59652130Smckusick 					cc = cc - 'a' + '\1'; /* ^A */
59752130Smckusick 				else if (shiftDown)
59852130Smckusick 					cc = cc - 'a' + 'A';
59952130Smckusick 			} else if (ctrlDown) {
60052130Smckusick 				if (cc >= '[' && cc <= '_')
60152130Smckusick 					cc = cc - '@';
60252130Smckusick 				else if (cc == ' ' || cc == '@')
60352130Smckusick 					cc = '\0';
60452130Smckusick 			}
60552130Smckusick 			lastChar = cc;
60652130Smckusick 		done:
60752130Smckusick 			;
60852130Smckusick 		} else if (tp == &dc_tty[MOUSE_PORT]) {
60952130Smckusick 			register MouseReport *newRepPtr;
61052130Smckusick 			static MouseReport currentRep;
61152130Smckusick 
61252130Smckusick 			newRepPtr = &currentRep;
61352130Smckusick 			newRepPtr->byteCount++;
61452130Smckusick 			if (cc & MOUSE_START_FRAME) {
61552130Smckusick 				/*
61652130Smckusick 				 * The first mouse report byte (button state).
61752130Smckusick 				 */
61852130Smckusick 				newRepPtr->state = cc;
61952130Smckusick 				if (newRepPtr->byteCount > 1)
62052130Smckusick 					newRepPtr->byteCount = 1;
62152130Smckusick 			} else if (newRepPtr->byteCount == 2) {
62252130Smckusick 				/*
62352130Smckusick 				 * The second mouse report byte (delta x).
62452130Smckusick 				 */
62552130Smckusick 				newRepPtr->dx = cc;
62652130Smckusick 			} else if (newRepPtr->byteCount == 3) {
62752130Smckusick 				/*
62852130Smckusick 				 * The final mouse report byte (delta y).
62952130Smckusick 				 */
63052130Smckusick 				newRepPtr->dy = cc;
63152130Smckusick 				newRepPtr->byteCount = 0;
63252130Smckusick 				if (newRepPtr->dx != 0 || newRepPtr->dy != 0) {
63352130Smckusick 					/*
63452130Smckusick 					 * If the mouse moved,
63552130Smckusick 					 * post a motion event.
63652130Smckusick 					 */
63752130Smckusick 					pmMouseEvent(newRepPtr);
63852130Smckusick 				}
63952130Smckusick 				pmMouseButtons(newRepPtr);
64052130Smckusick 			}
64152130Smckusick 			continue;
64252130Smckusick 		}
64352130Smckusick 		if (!(tp->t_state & TS_ISOPEN)) {
64452130Smckusick 			wakeup((caddr_t)&tp->t_rawq);
64552130Smckusick #ifdef PORTSELECTOR
64652130Smckusick 			if (!(tp->t_state & TS_WOPEN))
64752130Smckusick #endif
64852130Smckusick 				continue;
64952130Smckusick 		}
65052130Smckusick 		if (c & RBUF_FERR)
65152130Smckusick 			cc |= TTY_FE;
65252130Smckusick 		if (c & RBUF_PERR)
65352130Smckusick 			cc |= TTY_PE;
65452130Smckusick 		(*linesw[tp->t_line].l_rint)(cc, tp);
65552130Smckusick 	}
65652130Smckusick 	DELAY(10);
65752130Smckusick }
65852130Smckusick 
65952130Smckusick /*ARGSUSED*/
66052130Smckusick dcioctl(dev, cmd, data, flag)
66152130Smckusick 	dev_t dev;
66252130Smckusick 	caddr_t data;
66352130Smckusick {
66452130Smckusick 	register struct tty *tp;
66552130Smckusick 	register int unit = minor(dev);
66652130Smckusick 	register int dc = unit >> 2;
66752130Smckusick 	int error;
66852130Smckusick 
66952130Smckusick 	tp = &dc_tty[unit];
67052130Smckusick 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
67152130Smckusick 	if (error >= 0)
67252130Smckusick 		return (error);
67352130Smckusick 	error = ttioctl(tp, cmd, data, flag);
67452130Smckusick 	if (error >= 0)
67552130Smckusick 		return (error);
67652130Smckusick 
67752130Smckusick 	switch (cmd) {
67852130Smckusick 
67952130Smckusick 	case TIOCSBRK:
68052130Smckusick 		dc_brk[dc] |= 1 << ((unit & 03) + 8);
68152130Smckusick 		ttyoutput(0, tp);
68252130Smckusick 		break;
68352130Smckusick 
68452130Smckusick 	case TIOCCBRK:
68552130Smckusick 		dc_brk[dc] &= ~(1 << ((unit & 03) + 8));
68652130Smckusick 		ttyoutput(0, tp);
68752130Smckusick 		break;
68852130Smckusick 
68952130Smckusick 	case TIOCSDTR:
69052130Smckusick 		(void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS);
69152130Smckusick 		break;
69252130Smckusick 
69352130Smckusick 	case TIOCCDTR:
69452130Smckusick 		(void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC);
69552130Smckusick 		break;
69652130Smckusick 
69752130Smckusick 	case TIOCMSET:
69852130Smckusick 		(void) dcmctl(dev, *(int *)data, DMSET);
69952130Smckusick 		break;
70052130Smckusick 
70152130Smckusick 	case TIOCMBIS:
70252130Smckusick 		(void) dcmctl(dev, *(int *)data, DMBIS);
70352130Smckusick 		break;
70452130Smckusick 
70552130Smckusick 	case TIOCMBIC:
70652130Smckusick 		(void) dcmctl(dev, *(int *)data, DMBIC);
70752130Smckusick 		break;
70852130Smckusick 
70952130Smckusick 	case TIOCMGET:
71052130Smckusick 		*(int *)data = dcmctl(dev, 0, DMGET);
71152130Smckusick 		break;
71252130Smckusick 
71352130Smckusick 	default:
71452130Smckusick 		return (ENOTTY);
71552130Smckusick 	}
71652130Smckusick 	return (0);
71752130Smckusick }
71852130Smckusick 
71952130Smckusick dcparam(tp, t)
72052130Smckusick 	register struct tty *tp;
72152130Smckusick 	register struct termios *t;
72252130Smckusick {
72352130Smckusick 	register dcregs *dcaddr;
72452130Smckusick 	register int lpr;
72552130Smckusick 	register int cflag = t->c_cflag;
72652130Smckusick 	int unit = minor(tp->t_dev);
72752130Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab);
72852130Smckusick 
72952130Smckusick 	/* check requested parameters */
73052130Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
73152130Smckusick             (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6)
73252130Smckusick                 return (EINVAL);
73352130Smckusick         /* and copy to tty */
73452130Smckusick         tp->t_ispeed = t->c_ispeed;
73552130Smckusick         tp->t_ospeed = t->c_ospeed;
73652130Smckusick         tp->t_cflag = cflag;
73752130Smckusick 
73852130Smckusick 	dcaddr = dcpdma[unit].p_addr;
73952130Smckusick 	if (tp == dc_tty + KBD_PORT) {
74052130Smckusick 		/* handle the keyboard specially */
74152130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR |
74252130Smckusick 			KBD_PORT;
74352130Smckusick 		MachEmptyWriteBuffer();
74452130Smckusick 		return (0);
74552130Smckusick 	}
74652130Smckusick 	if (tp == dc_tty + MOUSE_PORT) {
74752130Smckusick 		/* handle the mouse specially */
74852130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
74952130Smckusick 			LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT;
75052130Smckusick 		MachEmptyWriteBuffer();
75152130Smckusick 		return (0);
75252130Smckusick 	}
75352130Smckusick 	if (ospeed == 0) {
75452130Smckusick 		(void) dcmctl(unit, 0, DMSET);	/* hang up line */
75552130Smckusick 		return (0);
75652130Smckusick 	}
75752130Smckusick 	lpr = LPR_RXENAB | ospeed | (unit & 03);
75852130Smckusick 	if ((cflag & CSIZE) == CS7)
75952130Smckusick 		lpr |= LPR_7_BIT_CHAR;
76052130Smckusick 	else
76152130Smckusick 		lpr |= LPR_8_BIT_CHAR;
76252130Smckusick 	if (cflag & PARENB)
76352130Smckusick 		lpr |= LPR_PARENB;
76452130Smckusick 	if (cflag & PARODD)
76552130Smckusick 		lpr |= LPR_OPAR;
76652130Smckusick 	if (cflag & CSTOPB)
76752130Smckusick 		lpr |= LPR_2_STOP;
76852130Smckusick 	dcaddr->dc_lpr = lpr;
76952130Smckusick 	MachEmptyWriteBuffer();
77052130Smckusick 	return (0);
77152130Smckusick }
77252130Smckusick 
77352130Smckusick dcxint(tp)
77452130Smckusick 	register struct tty *tp;
77552130Smckusick {
77652130Smckusick 	register struct pdma *dp;
77752130Smckusick 	register dcregs *dcaddr;
77852130Smckusick 
77952130Smckusick 	dp = (struct pdma *)tp->t_addr;
78052130Smckusick 	if (dp->p_mem < dp->p_end) {
78152130Smckusick 		dcaddr = dp->p_addr;
78252130Smckusick 		dcaddr->dc_tdr = dc_brk[(tp - dc_tty) >> 2] | *dp->p_mem++;
78352130Smckusick 		MachEmptyWriteBuffer();
78452130Smckusick 		DELAY(10);
78552130Smckusick 		return;
78652130Smckusick 	}
78752130Smckusick 	tp->t_state &= ~TS_BUSY;
78852130Smckusick 	if (tp->t_state & TS_FLUSH)
78952130Smckusick 		tp->t_state &= ~TS_FLUSH;
79052130Smckusick 	else {
79152130Smckusick 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
79252130Smckusick 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
79352130Smckusick 	}
79452130Smckusick 	if (tp->t_line)
79552130Smckusick 		(*linesw[tp->t_line].l_start)(tp);
79652130Smckusick 	else
79752130Smckusick 		dcstart(tp);
79852130Smckusick 	if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
79952130Smckusick 		dp->p_addr->dc_tcr &= ~(1 << (minor(tp->t_dev) & 03));
80052130Smckusick 		MachEmptyWriteBuffer();
80152130Smckusick 		DELAY(10);
80252130Smckusick 	}
80352130Smckusick }
80452130Smckusick 
80552130Smckusick dcstart(tp)
80652130Smckusick 	register struct tty *tp;
80752130Smckusick {
80852130Smckusick 	register struct pdma *dp;
80952130Smckusick 	register dcregs *dcaddr;
81052130Smckusick 	register int cc;
81152130Smckusick 	int s;
81252130Smckusick 
81352130Smckusick 	dp = (struct pdma *)tp->t_addr;
81452130Smckusick 	dcaddr = dp->p_addr;
81552130Smckusick 	s = spltty();
81652130Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
81752130Smckusick 		goto out;
81852130Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
81952130Smckusick 		if (tp->t_state & TS_ASLEEP) {
82052130Smckusick 			tp->t_state &= ~TS_ASLEEP;
82152130Smckusick 			wakeup((caddr_t)&tp->t_outq);
82252130Smckusick 		}
823*52674Smckusick 		selwakeup(&tp->t_wsel);
82452130Smckusick 	}
82552130Smckusick 	if (tp->t_outq.c_cc == 0)
82652130Smckusick 		goto out;
82752130Smckusick 	/* handle console specially */
82852130Smckusick 	if (tp == dc_tty) {
82952130Smckusick 		while (tp->t_outq.c_cc > 0) {
83052130Smckusick 			cc = getc(&tp->t_outq) & 0x7f;
83152130Smckusick 			pmPutc(cc);
83252130Smckusick 		}
83352130Smckusick 		/*
83452130Smckusick 		 * After we flush the output queue we may need to wake
83552130Smckusick 		 * up the process that made the output.
83652130Smckusick 		 */
83752130Smckusick 		if (tp->t_outq.c_cc <= tp->t_lowat) {
83852130Smckusick 			if (tp->t_state & TS_ASLEEP) {
83952130Smckusick 				tp->t_state &= ~TS_ASLEEP;
84052130Smckusick 				wakeup((caddr_t)&tp->t_outq);
84152130Smckusick 			}
842*52674Smckusick 			selwakeup(&tp->t_wsel);
84352130Smckusick 		}
84452130Smckusick 		goto out;
84552130Smckusick 	}
84652130Smckusick 	if (tp->t_flags & (RAW|LITOUT))
84752130Smckusick 		cc = ndqb(&tp->t_outq, 0);
84852130Smckusick 	else {
84952130Smckusick 		cc = ndqb(&tp->t_outq, 0200);
85052130Smckusick 		if (cc == 0) {
85152130Smckusick 			cc = getc(&tp->t_outq);
85252130Smckusick 			timeout(ttrstrt, (caddr_t)tp, (cc & 0x7f) + 6);
85352130Smckusick 			tp->t_state |= TS_TIMEOUT;
85452130Smckusick 			goto out;
85552130Smckusick 		}
85652130Smckusick 	}
85752130Smckusick 	tp->t_state |= TS_BUSY;
85852130Smckusick 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
85952130Smckusick 	dp->p_end += cc;
86052130Smckusick 	dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03);
86152130Smckusick 	MachEmptyWriteBuffer();
86252130Smckusick out:
86352130Smckusick 	splx(s);
86452130Smckusick }
86552130Smckusick 
86652130Smckusick /*
86752130Smckusick  * Stop output on a line.
86852130Smckusick  */
86952130Smckusick /*ARGSUSED*/
87052130Smckusick dcstop(tp, flag)
87152130Smckusick 	register struct tty *tp;
87252130Smckusick {
87352130Smckusick 	register struct pdma *dp;
87452130Smckusick 	register int s;
87552130Smckusick 
87652130Smckusick 	dp = (struct pdma *)tp->t_addr;
87752130Smckusick 	s = spltty();
87852130Smckusick 	if (tp->t_state & TS_BUSY) {
87952130Smckusick 		dp->p_end = dp->p_mem;
88052130Smckusick 		if (!(tp->t_state & TS_TTSTOP))
88152130Smckusick 			tp->t_state |= TS_FLUSH;
88252130Smckusick 	}
88352130Smckusick 	splx(s);
88452130Smckusick }
88552130Smckusick 
88652130Smckusick dcmctl(dev, bits, how)
88752130Smckusick 	dev_t dev;
88852130Smckusick 	int bits, how;
88952130Smckusick {
89052130Smckusick 	register dcregs *dcaddr;
89152130Smckusick 	register int unit, mbits;
89252130Smckusick 	int b, s;
89352130Smckusick 
89452130Smckusick 	unit = minor(dev);
89552130Smckusick 	b = 1 << (unit & 03);
89652130Smckusick 	dcaddr = dcpdma[unit].p_addr;
89752130Smckusick 	s = spltty();
89852130Smckusick 	/* only channel 2 has modem control (what about line 3?) */
89952130Smckusick 	if ((unit & 03) == 2) {
90052130Smckusick 		mbits = 0;
90152130Smckusick 		if (dcaddr->dc_tcr & TCR_DTR2)
90252130Smckusick 			mbits |= DML_DTR;
90352130Smckusick 		if (dcaddr->dc_msr & MSR_DSR2)
90452130Smckusick 			mbits |= DML_DSR | DML_CAR;
90552130Smckusick 	} else
90652130Smckusick 		mbits = DML_DTR | DML_DSR | DML_CAR;
90752130Smckusick 	switch (how) {
90852130Smckusick 	case DMSET:
90952130Smckusick 		mbits = bits;
91052130Smckusick 		break;
91152130Smckusick 
91252130Smckusick 	case DMBIS:
91352130Smckusick 		mbits |= bits;
91452130Smckusick 		break;
91552130Smckusick 
91652130Smckusick 	case DMBIC:
91752130Smckusick 		mbits &= ~bits;
91852130Smckusick 		break;
91952130Smckusick 
92052130Smckusick 	case DMGET:
92152130Smckusick 		(void) splx(s);
92252130Smckusick 		return (mbits);
92352130Smckusick 	}
92452130Smckusick 	if ((unit & 03) == 2) {
92552130Smckusick 		if (mbits & DML_DTR)
92652130Smckusick 			dcaddr->dc_tcr |= TCR_DTR2;
92752130Smckusick 		else
92852130Smckusick 			dcaddr->dc_tcr &= ~TCR_DTR2;
92952130Smckusick 	}
93052130Smckusick 	if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b))
93152130Smckusick 		dc_tty[unit].t_state |= TS_CARR_ON;
93252130Smckusick 	(void) splx(s);
93352130Smckusick 	return (mbits);
93452130Smckusick }
93552130Smckusick 
93652130Smckusick /*
93752130Smckusick  * This is called by timeout() periodically.
93852130Smckusick  * Check to see if modem status bits have changed.
93952130Smckusick  */
94052130Smckusick dcscan()
94152130Smckusick {
94252130Smckusick 	register dcregs *dcaddr;
94352130Smckusick 	register struct tty *tp;
94452130Smckusick 	register int i, bit, car;
94552130Smckusick 	int s;
94652130Smckusick 
94752130Smckusick 	s = spltty();
94852130Smckusick 	/* only channel 2 has modem control (what about line 3?) */
94952130Smckusick 	dcaddr = dcpdma[i = 2].p_addr;
95052130Smckusick 	tp = &dc_tty[i];
95152130Smckusick 	bit = TCR_DTR2;
95252130Smckusick 	if (dcsoftCAR[i >> 2] & bit)
95352130Smckusick 		car = 1;
95452130Smckusick 	else
95552130Smckusick 		car = dcaddr->dc_msr & MSR_DSR2;
95652130Smckusick 	if (car) {
95752130Smckusick 		/* carrier present */
95852130Smckusick 		if (!(tp->t_state & TS_CARR_ON))
95952130Smckusick 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
96052130Smckusick 	} else if ((tp->t_state & TS_CARR_ON) &&
96152130Smckusick 	    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
96252130Smckusick 		dcaddr->dc_tcr &= ~bit;
96352130Smckusick 	splx(s);
96452130Smckusick 	timeout(dcscan, (caddr_t)0, hz);
96552130Smckusick }
96652130Smckusick 
96752130Smckusick /*
96852130Smckusick  * ----------------------------------------------------------------------------
96952130Smckusick  *
97052130Smckusick  * dcKBDPutc --
97152130Smckusick  *
97252130Smckusick  *	Put a character out to the keyboard.
97352130Smckusick  *
97452130Smckusick  * Results:
97552130Smckusick  *	None.
97652130Smckusick  *
97752130Smckusick  * Side effects:
97852130Smckusick  *	A character is written to the keyboard.
97952130Smckusick  *
98052130Smckusick  * ----------------------------------------------------------------------------
98152130Smckusick  */
98252130Smckusick void
98352130Smckusick dcKBDPutc(c)
98452130Smckusick 	register int c;
98552130Smckusick {
98652130Smckusick 	register dcregs *dcaddr;
98752130Smckusick 	register u_short tcr;
98852130Smckusick 	register int timeout;
98952130Smckusick 	int s, line;
99052130Smckusick 
99152130Smckusick 	s = spltty();
99252130Smckusick 
99352130Smckusick 	dcaddr = dcpdma[KBD_PORT].p_addr;
99452130Smckusick 	tcr = dcaddr->dc_tcr;
99552130Smckusick 	dcaddr->dc_tcr = tcr | (1 << KBD_PORT);
99652130Smckusick 	MachEmptyWriteBuffer();
99752130Smckusick 	DELAY(10);
99852130Smckusick 	while (1) {
99952130Smckusick 		/*
100052130Smckusick 		 * Wait for transmitter to be not busy.
100152130Smckusick 		 */
100252130Smckusick 		timeout = 1000000;
100352130Smckusick 		while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
100452130Smckusick 			timeout--;
100552130Smckusick 		if (timeout == 0) {
100652130Smckusick 			printf("dcKBDPutc: timeout waiting for CSR_TRDY\n");
100752130Smckusick 			break;
100852130Smckusick 		}
100952130Smckusick 		line = (dcaddr->dc_csr >> 8) & 3;
101052130Smckusick 		/*
101152130Smckusick 		 * Check to be sure its the right port.
101252130Smckusick 		 */
101352130Smckusick 		if (line != KBD_PORT) {
101452130Smckusick 			tcr |= 1 << line;
101552130Smckusick 			dcaddr->dc_tcr &= ~(1 << line);
101652130Smckusick 			MachEmptyWriteBuffer();
101752130Smckusick 			DELAY(10);
101852130Smckusick 			continue;
101952130Smckusick 		}
102052130Smckusick 		/*
102152130Smckusick 		 * Start sending the character.
102252130Smckusick 		 */
102352130Smckusick 		dcaddr->dc_tdr = dc_brk[0] | (c & 0xff);
102452130Smckusick 		MachEmptyWriteBuffer();
102552130Smckusick 		DELAY(10);
102652130Smckusick 		/*
102752130Smckusick 		 * Wait for character to be sent.
102852130Smckusick 		 */
102952130Smckusick 		while (1) {
103052130Smckusick 			/*
103152130Smckusick 			 * cc -O bug: this code produces and infinite loop!
103252130Smckusick 			 * while (!(dcaddr->dc_csr & CSR_TRDY))
103352130Smckusick 			 *	;
103452130Smckusick 			 */
103552130Smckusick 			timeout = 1000000;
103652130Smckusick 			while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
103752130Smckusick 				timeout--;
103852130Smckusick 			line = (dcaddr->dc_csr >> 8) & 3;
103952130Smckusick 			if (line != KBD_PORT) {
104052130Smckusick 				tcr |= 1 << line;
104152130Smckusick 				dcaddr->dc_tcr &= ~(1 << line);
104252130Smckusick 				MachEmptyWriteBuffer();
104352130Smckusick 				DELAY(10);
104452130Smckusick 				continue;
104552130Smckusick 			}
104652130Smckusick 			dcaddr->dc_tcr &= ~(1 << KBD_PORT);
104752130Smckusick 			MachEmptyWriteBuffer();
104852130Smckusick 			DELAY(10);
104952130Smckusick 			break;
105052130Smckusick 		}
105152130Smckusick 		break;
105252130Smckusick 	}
105352130Smckusick 	/*
105452130Smckusick 	 * Enable interrupts for other lines which became ready.
105552130Smckusick 	 */
105652130Smckusick 	if (tcr & 0xF) {
105752130Smckusick 		dcaddr->dc_tcr = tcr;
105852130Smckusick 		MachEmptyWriteBuffer();
105952130Smckusick 		DELAY(10);
106052130Smckusick 	}
106152130Smckusick 
106252130Smckusick 	splx(s);
106352130Smckusick }
106452130Smckusick 
106552130Smckusick #ifdef DEBUG
106652130Smckusick /*
106752130Smckusick  * ----------------------------------------------------------------------------
106852130Smckusick  *
106952130Smckusick  * dcKBDGetc --
107052130Smckusick  *
107152130Smckusick  *	Read a character from the keyboard.
107252130Smckusick  *
107352130Smckusick  * Results:
107452130Smckusick  *	A character read from the mouse, -1 if none were ready.
107552130Smckusick  *
107652130Smckusick  * Side effects:
107752130Smckusick  *	None.
107852130Smckusick  *
107952130Smckusick  * ----------------------------------------------------------------------------
108052130Smckusick  */
108152130Smckusick int
108252130Smckusick dcKBDGetc()
108352130Smckusick {
108452130Smckusick 	register dcregs *dcaddr;
108552130Smckusick 	register int c;
108652130Smckusick 
108752130Smckusick 	dcaddr = dcpdma[KBD_PORT].p_addr;
108852130Smckusick 	if (!dcaddr)
108952130Smckusick 		return (0);
109052130Smckusick 	if (c = debugChar)
109152130Smckusick 		debugChar = 0;
109252130Smckusick 	else {
109352130Smckusick 		while (dcaddr->dc_csr & CSR_RDONE) {
109452130Smckusick 			c = dcaddr->dc_rbuf;
109552130Smckusick 			DELAY(10);
109652130Smckusick 			if (((c >> 8) & 03) == KBD_PORT)
109752130Smckusick 				break;
109852130Smckusick 			c = 0;
109952130Smckusick 		}
110052130Smckusick 	}
110152130Smckusick 	return (c & 0xff);
110252130Smckusick }
110352130Smckusick #endif
110452130Smckusick 
110552130Smckusick /*
110652130Smckusick  * ----------------------------------------------------------------------------
110752130Smckusick  *
110852130Smckusick  * dcKBDReset --
110952130Smckusick  *
111052130Smckusick  *	Reset the keyboard to default characteristics.
111152130Smckusick  *
111252130Smckusick  * Results:
111352130Smckusick  *	None.
111452130Smckusick  *
111552130Smckusick  * Side effects:
111652130Smckusick  *	None.
111752130Smckusick  *
111852130Smckusick  * ----------------------------------------------------------------------------
111952130Smckusick  */
112052130Smckusick void
112152130Smckusick dcKBDReset()
112252130Smckusick {
112352130Smckusick 	register int i;
112452130Smckusick 	static int inKBDReset;
112552130Smckusick 
112652130Smckusick 	if (inKBDReset)
112752130Smckusick 		return;
112852130Smckusick 	inKBDReset = 1;
112952130Smckusick 	for (i = 0; i < sizeof(kbdInitString); i++)
113052130Smckusick 		dcKBDPutc((int)kbdInitString[i]);
113152130Smckusick 	inKBDReset = 0;
113252130Smckusick }
113352130Smckusick 
113452130Smckusick /*
113552130Smckusick  * ----------------------------------------------------------------------------
113652130Smckusick  *
113752130Smckusick  * MousePutc --
113852130Smckusick  *
113952130Smckusick  *	Write a character to the mouse.
114052130Smckusick  *	This is only called at initialization time.
114152130Smckusick  *
114252130Smckusick  * Results:
114352130Smckusick  *	None.
114452130Smckusick  *
114552130Smckusick  * Side effects:
114652130Smckusick  *	A character is written to the mouse.
114752130Smckusick  *
114852130Smckusick  * ----------------------------------------------------------------------------
114952130Smckusick  */
115052130Smckusick static void
115152130Smckusick MousePutc(c)
115252130Smckusick 	int c;
115352130Smckusick {
115452130Smckusick 	register dcregs *dcaddr;
115552130Smckusick 	register u_short tcr;
115652130Smckusick 	register int timeout;
115752130Smckusick 	int line;
115852130Smckusick 
115952130Smckusick 	dcaddr = dcpdma[MOUSE_PORT].p_addr;
116052130Smckusick 	tcr = dcaddr->dc_tcr;
116152130Smckusick 	dcaddr->dc_tcr = tcr | (1 << MOUSE_PORT);
116252130Smckusick 	MachEmptyWriteBuffer();
116352130Smckusick 	DELAY(10);
116452130Smckusick 	while (1) {
116552130Smckusick 		/*
116652130Smckusick 		 * Wait for transmitter to be not busy.
116752130Smckusick 		 */
116852130Smckusick 		timeout = 1000000;
116952130Smckusick 		while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
117052130Smckusick 			timeout--;
117152130Smckusick 		if (timeout == 0) {
117252130Smckusick 			printf("MousePutc: timeout waiting for CSR_TRDY\n");
117352130Smckusick 			break;
117452130Smckusick 		}
117552130Smckusick 		line = (dcaddr->dc_csr >> 8) & 3;
117652130Smckusick 		/*
117752130Smckusick 		 * Check to be sure its the right port.
117852130Smckusick 		 */
117952130Smckusick 		if (line != MOUSE_PORT) {
118052130Smckusick 			tcr |= 1 << line;
118152130Smckusick 			dcaddr->dc_tcr &= ~(1 << line);
118252130Smckusick 			MachEmptyWriteBuffer();
118352130Smckusick 			DELAY(10);
118452130Smckusick 			continue;
118552130Smckusick 		}
118652130Smckusick 		/*
118752130Smckusick 		 * Start sending the character.
118852130Smckusick 		 */
118952130Smckusick 		dcaddr->dc_tdr = dc_brk[0] | (c & 0xff);
119052130Smckusick 		MachEmptyWriteBuffer();
119152130Smckusick 		DELAY(10);
119252130Smckusick 		/*
119352130Smckusick 		 * Wait for character to be sent.
119452130Smckusick 		 */
119552130Smckusick 		while (1) {
119652130Smckusick 			/*
119752130Smckusick 			 * cc -O bug: this code produces and infinite loop!
119852130Smckusick 			 * while (!(dcaddr->dc_csr & CSR_TRDY))
119952130Smckusick 			 *	;
120052130Smckusick 			 */
120152130Smckusick 			timeout = 1000000;
120252130Smckusick 			while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
120352130Smckusick 				timeout--;
120452130Smckusick 			line = (dcaddr->dc_csr >> 8) & 3;
120552130Smckusick 			if (line != MOUSE_PORT) {
120652130Smckusick 				tcr |= 1 << line;
120752130Smckusick 				dcaddr->dc_tcr &= ~(1 << line);
120852130Smckusick 				MachEmptyWriteBuffer();
120952130Smckusick 				DELAY(10);
121052130Smckusick 				continue;
121152130Smckusick 			}
121252130Smckusick 			dcaddr->dc_tcr &= ~(1 << MOUSE_PORT);
121352130Smckusick 			MachEmptyWriteBuffer();
121452130Smckusick 			DELAY(10);
121552130Smckusick 			break;
121652130Smckusick 		}
121752130Smckusick 		break;
121852130Smckusick 	}
121952130Smckusick 	/*
122052130Smckusick 	 * Enable interrupts for other lines which became ready.
122152130Smckusick 	 */
122252130Smckusick 	if (tcr & 0xF) {
122352130Smckusick 		dcaddr->dc_tcr = tcr;
122452130Smckusick 		MachEmptyWriteBuffer();
122552130Smckusick 		DELAY(10);
122652130Smckusick 	}
122752130Smckusick }
122852130Smckusick 
122952130Smckusick /*
123052130Smckusick  * ----------------------------------------------------------------------------
123152130Smckusick  *
123252130Smckusick  * MouseGetc --
123352130Smckusick  *
123452130Smckusick  *	Read a character from the mouse.
123552130Smckusick  *	This is only called at initialization time.
123652130Smckusick  *
123752130Smckusick  * Results:
123852130Smckusick  *	A character read from the mouse, -1 if we timed out waiting.
123952130Smckusick  *
124052130Smckusick  * Side effects:
124152130Smckusick  *	None.
124252130Smckusick  *
124352130Smckusick  * ----------------------------------------------------------------------------
124452130Smckusick  */
124552130Smckusick static int
124652130Smckusick MouseGetc()
124752130Smckusick {
124852130Smckusick 	register dcregs *dcaddr;
124952130Smckusick 	register int timeout;
125052130Smckusick 	register int c;
125152130Smckusick 
125252130Smckusick 	dcaddr = dcpdma[MOUSE_PORT].p_addr;
125352130Smckusick 	for (timeout = 1000000; timeout > 0; timeout--) {
125452130Smckusick 		if (!(dcaddr->dc_csr & CSR_RDONE))
125552130Smckusick 			continue;
125652130Smckusick 		c = dcaddr->dc_rbuf;
125752130Smckusick 		DELAY(10);
125852130Smckusick 		if (((c >> 8) & 03) != MOUSE_PORT)
125952130Smckusick 			continue;
126052130Smckusick 		return (c & 0xff);
126152130Smckusick 	}
126252130Smckusick 
126352130Smckusick 	return (-1);
126452130Smckusick }
126552130Smckusick 
126652130Smckusick /*
126752130Smckusick  * ----------------------------------------------------------------------------
126852130Smckusick  *
126952130Smckusick  * MouseInit --
127052130Smckusick  *
127152130Smckusick  *	Initialize the mouse.
127252130Smckusick  *
127352130Smckusick  * Results:
127452130Smckusick  *	None.
127552130Smckusick  *
127652130Smckusick  * Side effects:
127752130Smckusick  *	None.
127852130Smckusick  *
127952130Smckusick  * ----------------------------------------------------------------------------
128052130Smckusick  */
128152130Smckusick static void
128252130Smckusick MouseInit()
128352130Smckusick {
128452130Smckusick 	int id_byte1, id_byte2, id_byte3, id_byte4;
128552130Smckusick 
128652130Smckusick 	/*
128752130Smckusick 	 * Initialize the mouse.
128852130Smckusick 	 */
128952130Smckusick 	MousePutc(MOUSE_SELF_TEST);
129052130Smckusick 	id_byte1 = MouseGetc();
129152130Smckusick 	if (id_byte1 < 0) {
129252130Smckusick 		printf("MouseInit: Timeout on 1st byte of self-test report\n");
129352130Smckusick 		return;
129452130Smckusick 	}
129552130Smckusick 	id_byte2 = MouseGetc();
129652130Smckusick 	if (id_byte2 < 0) {
129752130Smckusick 		printf("MouseInit: Timeout on 2nd byte of self-test report\n");
129852130Smckusick 		return;
129952130Smckusick 	}
130052130Smckusick 	id_byte3 = MouseGetc();
130152130Smckusick 	if (id_byte3 < 0) {
130252130Smckusick 		printf("MouseInit: Timeout on 3rd byte of self-test report\n");
130352130Smckusick 		return;
130452130Smckusick 	}
130552130Smckusick 	id_byte4 = MouseGetc();
130652130Smckusick 	if (id_byte4 < 0) {
130752130Smckusick 		printf("MouseInit: Timeout on 4th byte of self-test report\n");
130852130Smckusick 		return;
130952130Smckusick 	}
131052130Smckusick 	if ((id_byte2 & 0x0f) != 0x2)
131152130Smckusick 		printf("MouseInit: We don't have a mouse!!!\n");
131252130Smckusick 	/*
131352130Smckusick 	 * For some reason, the mouse doesn't see this command if it comes
131452130Smckusick 	 * too soon after a self test.
131552130Smckusick 	 */
131652130Smckusick 	DELAY(100);
131752130Smckusick 	MousePutc(MOUSE_INCREMENTAL);
131852130Smckusick }
131952130Smckusick #endif /* NDC */
1320