xref: /csrg-svn/sys/pmax/dev/dc.c (revision 56525)
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.
752693Sralph  *	@(#)dz.c	7.9 (Berkeley) 6/28/90
852693Sralph  */
952693Sralph 
1052693Sralph /*
1152693Sralph  *  devDC7085.c --
1252130Smckusick  *
1352130Smckusick  * %sccs.include.redist.c%
1452130Smckusick  *
15*56525Sbostic  *	@(#)dc.c	7.10 (Berkeley) 10/11/92
1652130Smckusick  *
1752130Smckusick  * devDC7085.c --
1852130Smckusick  *
1952130Smckusick  *     	This file contains machine-dependent routines that handle the
2052130Smckusick  *	output queue for the serial lines.
2152130Smckusick  *
2252130Smckusick  *	Copyright (C) 1989 Digital Equipment Corporation.
2352130Smckusick  *	Permission to use, copy, modify, and distribute this software and
2452130Smckusick  *	its documentation for any purpose and without fee is hereby granted,
2552130Smckusick  *	provided that the above copyright notice appears in all copies.
2652130Smckusick  *	Digital Equipment Corporation makes no representations about the
2752130Smckusick  *	suitability of this software for any purpose.  It is provided "as is"
2852130Smckusick  *	without express or implied warranty.
2952130Smckusick  *
3052130Smckusick  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c,
3152130Smckusick  *	v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)";
3252130Smckusick  */
3352130Smckusick 
3452130Smckusick #include "dc.h"
3552130Smckusick #if NDC > 0
3652130Smckusick /*
3752130Smckusick  * DC7085 (DZ-11 look alike) Driver
3852130Smckusick  */
3956522Sbostic #include <sys/param.h>
4056522Sbostic #include <sys/systm.h>
4156522Sbostic #include <sys/ioctl.h>
4256522Sbostic #include <sys/tty.h>
4356522Sbostic #include <sys/proc.h>
4456522Sbostic #include <sys/map.h>
4556522Sbostic #include <sys/buf.h>
4656522Sbostic #include <sys/conf.h>
4756522Sbostic #include <sys/file.h>
4856522Sbostic #include <sys/uio.h>
4956522Sbostic #include <sys/kernel.h>
5056522Sbostic #include <sys/syslog.h>
5152130Smckusick 
5256522Sbostic #include <machine/dc7085cons.h>
5352130Smckusick 
54*56525Sbostic #include <pmax/dev/device.h>
55*56525Sbostic #include <pmax/dev/pdma.h>
5652130Smckusick 
5752130Smckusick /*
5852130Smckusick  * Driver information for auto-configuration stuff.
5952130Smckusick  */
6052130Smckusick int	dcprobe();
6152693Sralph void	dcintr();
6252130Smckusick struct	driver dcdriver = {
6352693Sralph 	"dc", dcprobe, 0, 0, dcintr,
6452130Smckusick };
6552130Smckusick 
6652130Smckusick #define	NDCLINE 	(NDC*4)
6752130Smckusick 
6854146Sralph extern void dcstart __P((struct tty *));
6954146Sralph extern void dcxint __P((struct tty *));
7056226Sralph extern void ttrstrt __P((void *));
7152130Smckusick 
7252130Smckusick struct	tty dc_tty[NDCLINE];
7352130Smckusick int	dc_cnt = NDCLINE;
7452863Sralph void	(*dcDivertXInput)();	/* X windows keyboard input routine */
7552863Sralph void	(*dcMouseEvent)();	/* X windows mouse motion event routine */
7652863Sralph void	(*dcMouseButtons)();	/* X windows mouse buttons event routine */
7752130Smckusick #ifdef DEBUG
7852130Smckusick int	debugChar;
7952130Smckusick #endif
8052130Smckusick 
8155744Sralph static void dcscan __P((void *));
8254146Sralph static int dcMapChar __P((int));
8354146Sralph static void dcKBDReset __P((void));
8454146Sralph static void MouseInit __P((void));
8554146Sralph 
8652130Smckusick /*
8752130Smckusick  * Software copy of brk register since it isn't readable
8852130Smckusick  */
8952130Smckusick int	dc_brk[NDC];
9052130Smckusick char	dcsoftCAR[NDC];		/* mask of dc's with carrier on (DSR) */
9152130Smckusick 
9252130Smckusick /*
9352130Smckusick  * The DC7085 doesn't interrupt on carrier transitions, so
9452130Smckusick  * we have to use a timer to watch it.
9552130Smckusick  */
9652130Smckusick int	dc_timer;		/* true if timer started */
9752130Smckusick 
9852130Smckusick /*
9952130Smckusick  * Pdma structures for fast output code
10052130Smckusick  */
10152130Smckusick struct	pdma dcpdma[NDCLINE];
10252130Smckusick 
10352130Smckusick struct speedtab dcspeedtab[] = {
10452130Smckusick 	0,	0,
10552130Smckusick 	50,	LPR_B50,
10652130Smckusick 	75,	LPR_B75,
10752130Smckusick 	110,	LPR_B110,
10852130Smckusick 	134,	LPR_B134,
10952130Smckusick 	150,	LPR_B150,
11052130Smckusick 	300,	LPR_B300,
11152130Smckusick 	600,	LPR_B600,
11252130Smckusick 	1200,	LPR_B1200,
11352130Smckusick 	1800,	LPR_B1800,
11452130Smckusick 	2400,	LPR_B2400,
11552130Smckusick 	4800,	LPR_B4800,
11652130Smckusick 	9600,	LPR_B9600,
11752693Sralph #ifdef DS5000
11852693Sralph 	19200,	LPR_B19200,
11952693Sralph #endif
12052130Smckusick 	-1,	-1
12152130Smckusick };
12252130Smckusick 
12352130Smckusick #ifndef	PORTSELECTOR
12452130Smckusick #define	ISPEED	TTYDEF_SPEED
12552130Smckusick #define	LFLAG	TTYDEF_LFLAG
12652130Smckusick #else
12752130Smckusick #define	ISPEED	B4800
12852130Smckusick #define	LFLAG	(TTYDEF_LFLAG & ~ECHO)
12952130Smckusick #endif
13052130Smckusick 
13152130Smckusick /*
13252130Smckusick  * Ascii values of command keys.
13352130Smckusick  */
13452130Smckusick #define KBD_TAB		'\t'
13552130Smckusick #define KBD_DEL		127
13652130Smckusick #define KBD_RET		'\r'
13752130Smckusick 
13852130Smckusick /*
13952130Smckusick  *  Define "hardware-independent" codes for the control, shift, meta and
14052130Smckusick  *  function keys.  Codes start after the last 7-bit ASCII code (127)
14152130Smckusick  *  and are assigned in an arbitrary order.
14252130Smckusick  */
14352130Smckusick #define KBD_NOKEY	128
14452130Smckusick 
14552130Smckusick #define KBD_F1		201
14652130Smckusick #define KBD_F2		202
14752130Smckusick #define KBD_F3		203
14852130Smckusick #define KBD_F4		204
14952130Smckusick #define KBD_F5		205
15052130Smckusick #define KBD_F6		206
15152130Smckusick #define KBD_F7		207
15252130Smckusick #define KBD_F8		208
15352130Smckusick #define KBD_F9		209
15452130Smckusick #define KBD_F10		210
15552130Smckusick #define KBD_F11		211
15652130Smckusick #define KBD_F12		212
15752130Smckusick #define KBD_F13		213
15852130Smckusick #define KBD_F14		214
15952130Smckusick #define KBD_HELP	215
16052130Smckusick #define KBD_DO		216
16152130Smckusick #define KBD_F17		217
16252130Smckusick #define KBD_F18		218
16352130Smckusick #define KBD_F19		219
16452130Smckusick #define KBD_F20		220
16552130Smckusick 
16652130Smckusick #define KBD_FIND	221
16752130Smckusick #define KBD_INSERT	222
16852130Smckusick #define KBD_REMOVE	223
16952130Smckusick #define KBD_SELECT	224
17052130Smckusick #define KBD_PREVIOUS	225
17152130Smckusick #define KBD_NEXT	226
17252130Smckusick 
17352130Smckusick #define KBD_KP_ENTER	227
17452130Smckusick #define KBD_KP_F1	228
17552130Smckusick #define KBD_KP_F2	229
17652130Smckusick #define KBD_KP_F3	230
17752130Smckusick #define KBD_KP_F4	231
17852130Smckusick #define KBD_LEFT	232
17952130Smckusick #define KBD_RIGHT	233
18052130Smckusick #define KBD_DOWN	234
18152130Smckusick #define KBD_UP		235
18252130Smckusick 
18352130Smckusick #define KBD_CONTROL	236
18452130Smckusick #define KBD_SHIFT	237
18552130Smckusick #define KBD_CAPSLOCK	238
18652130Smckusick #define KBD_ALTERNATE	239
18752130Smckusick 
18852130Smckusick /*
18952130Smckusick  * Keyboard to Ascii, unshifted.
19052130Smckusick  */
19152130Smckusick static unsigned char unshiftedAscii[] = {
19252130Smckusick /*  0 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19352130Smckusick /*  4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19452130Smckusick /*  8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19552130Smckusick /*  c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19652130Smckusick /* 10 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19752130Smckusick /* 14 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19852130Smckusick /* 18 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
19952130Smckusick /* 1c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20052130Smckusick /* 20 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20152130Smckusick /* 24 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20252130Smckusick /* 28 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20352130Smckusick /* 2c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20452130Smckusick /* 30 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20552130Smckusick /* 34 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20652130Smckusick /* 38 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20752130Smckusick /* 3c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20852130Smckusick /* 40 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
20952130Smckusick /* 44 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21052130Smckusick /* 48 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21152130Smckusick /* 4c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21252130Smckusick /* 50 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21352130Smckusick /* 54 */ KBD_NOKEY,	KBD_NOKEY,	KBD_F1,		KBD_F2,
21452130Smckusick /* 58 */ KBD_F3,	KBD_F4,		KBD_F5,		KBD_NOKEY,
21552130Smckusick /* 5c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21652130Smckusick /* 60 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21752130Smckusick /* 64 */ KBD_F6,	KBD_F7,		KBD_F8,		KBD_F9,
21852130Smckusick /* 68 */ KBD_F10,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
21952130Smckusick /* 6c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
22052130Smckusick /* 70 */ KBD_NOKEY,	'\033',		KBD_F12,	KBD_F13,
22152130Smckusick /* 74 */ KBD_F14,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
22252130Smckusick /* 78 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
22352130Smckusick /* 7c */ KBD_HELP,	KBD_DO,		KBD_NOKEY,	KBD_NOKEY,
22452130Smckusick /* 80 */ KBD_F17,	KBD_F18,	KBD_F19,	KBD_F20,
22552130Smckusick /* 84 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
22652130Smckusick /* 88 */ KBD_NOKEY,	KBD_NOKEY,	KBD_FIND,	KBD_INSERT,
22752130Smckusick /* 8c */ KBD_REMOVE,	KBD_SELECT,	KBD_PREVIOUS,	KBD_NEXT,
22852130Smckusick /* 90 */ KBD_NOKEY,	KBD_NOKEY,	'0',		KBD_NOKEY,
22952130Smckusick /* 94 */ '.',		KBD_KP_ENTER,	'1',		'2',
23052130Smckusick /* 98 */ '3',		'4',		'5',		'6',
23152130Smckusick /* 9c */ ',',		'7',		'8',		'9',
23252130Smckusick /* a0 */ '-',		KBD_KP_F1,	KBD_KP_F2,	KBD_KP_F3,
23352130Smckusick /* a4 */ KBD_KP_F4,	KBD_NOKEY,	KBD_NOKEY,	KBD_LEFT,
23452130Smckusick /* a8 */ KBD_RIGHT,	KBD_DOWN, 	KBD_UP,		KBD_NOKEY,
23552130Smckusick /* ac */ KBD_NOKEY,	KBD_NOKEY,	KBD_SHIFT,	KBD_CONTROL,
23652130Smckusick /* b0 */ KBD_CAPSLOCK,	KBD_ALTERNATE,	KBD_NOKEY,	KBD_NOKEY,
23752130Smckusick /* b4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
23852130Smckusick /* b8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
23952130Smckusick /* bc */ KBD_DEL,	KBD_RET,	KBD_TAB,	'`',
24052130Smckusick /* c0 */ '1',		'q',		'a',		'z',
24152130Smckusick /* c4 */ KBD_NOKEY,	'2',		'w',		's',
24252130Smckusick /* c8 */ 'x',		'<',		KBD_NOKEY,	'3',
24352130Smckusick /* cc */ 'e',		'd',		'c',		KBD_NOKEY,
24452130Smckusick /* d0 */ '4',		'r',		'f',		'v',
24552130Smckusick /* d4 */ ' ',		KBD_NOKEY,	'5',		't',
24652130Smckusick /* d8 */ 'g',		'b',		KBD_NOKEY,	'6',
24752130Smckusick /* dc */ 'y',		'h',		'n',		KBD_NOKEY,
24852130Smckusick /* e0 */ '7',		'u',		'j',		'm',
24952130Smckusick /* e4 */ KBD_NOKEY,	'8',		'i',		'k',
25052130Smckusick /* e8 */ ',',		KBD_NOKEY,	'9',		'o',
25152130Smckusick /* ec */ 'l',		'.',		KBD_NOKEY,	'0',
25252130Smckusick /* f0 */ 'p',		KBD_NOKEY,	';',		'/',
25352130Smckusick /* f4 */ KBD_NOKEY,	'=',		']',		'\\',
25452130Smckusick /* f8 */ KBD_NOKEY,	'-',		'[',		'\'',
25552130Smckusick /* fc */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
25652130Smckusick };
25752130Smckusick 
25852130Smckusick /*
25952130Smckusick  * Keyboard to Ascii, shifted.
26052130Smckusick  */
26152130Smckusick static unsigned char shiftedAscii[] = {
26252130Smckusick /*  0 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26352130Smckusick /*  4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26452130Smckusick /*  8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26552130Smckusick /*  c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26652130Smckusick /* 10 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26752130Smckusick /* 14 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26852130Smckusick /* 18 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
26952130Smckusick /* 1c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27052130Smckusick /* 20 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27152130Smckusick /* 24 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27252130Smckusick /* 28 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27352130Smckusick /* 2c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27452130Smckusick /* 30 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27552130Smckusick /* 34 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27652130Smckusick /* 38 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27752130Smckusick /* 3c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27852130Smckusick /* 40 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
27952130Smckusick /* 44 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28052130Smckusick /* 48 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28152130Smckusick /* 4c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28252130Smckusick /* 50 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28352130Smckusick /* 54 */ KBD_NOKEY,	KBD_NOKEY,	KBD_F1,		KBD_F2,
28452130Smckusick /* 58 */ KBD_F3,	KBD_F4,		KBD_F5,		KBD_NOKEY,
28552130Smckusick /* 5c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28652130Smckusick /* 60 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28752130Smckusick /* 64 */ KBD_F6,	KBD_F7,		KBD_F8,		KBD_F9,
28852130Smckusick /* 68 */ KBD_F10,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
28952130Smckusick /* 6c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
29052130Smckusick /* 70 */ KBD_NOKEY,	KBD_F11,	KBD_F12,	KBD_F13,
29152130Smckusick /* 74 */ KBD_F14,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
29252130Smckusick /* 78 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
29352130Smckusick /* 7c */ KBD_HELP,	KBD_DO,		KBD_NOKEY,	KBD_NOKEY,
29452130Smckusick /* 80 */ KBD_F17,	KBD_F18,	KBD_F19,	KBD_F20,
29552130Smckusick /* 84 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
29652130Smckusick /* 88 */ KBD_NOKEY,	KBD_NOKEY,	KBD_FIND,	KBD_INSERT,
29752130Smckusick /* 8c */ KBD_REMOVE,	KBD_SELECT,	KBD_PREVIOUS,	KBD_NEXT,
29852130Smckusick /* 90 */ KBD_NOKEY,	KBD_NOKEY,	'0',		KBD_NOKEY,
29952130Smckusick /* 94 */ '.',		KBD_KP_ENTER,	'1',		'2',
30052130Smckusick /* 98 */ '3',		'4',		'5',		'6',
30152130Smckusick /* 9c */ ',',		'7',		'8',		'9',
30252130Smckusick /* a0 */ '-',		KBD_KP_F1,	KBD_KP_F2,	KBD_KP_F3,
30352130Smckusick /* a4 */ KBD_KP_F4,	KBD_NOKEY,	KBD_NOKEY,	KBD_LEFT,
30452130Smckusick /* a8 */ KBD_RIGHT,	KBD_DOWN, 	KBD_UP,		KBD_NOKEY,
30552130Smckusick /* ac */ KBD_NOKEY,	KBD_NOKEY,	KBD_SHIFT,	KBD_CONTROL,
30652130Smckusick /* b0 */ KBD_CAPSLOCK,	KBD_ALTERNATE,	KBD_NOKEY,	KBD_NOKEY,
30752130Smckusick /* b4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
30852130Smckusick /* b8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
30952130Smckusick /* bc */ KBD_DEL,	KBD_RET,	KBD_TAB,	'~',
31052130Smckusick /* c0 */ '!',		'q',		'a',		'z',
31152130Smckusick /* c4 */ KBD_NOKEY,	'@',		'w',		's',
31252130Smckusick /* c8 */ 'x',		'>',		KBD_NOKEY,	'#',
31352130Smckusick /* cc */ 'e',		'd',		'c',		KBD_NOKEY,
31452130Smckusick /* d0 */ '$',		'r',		'f',		'v',
31552130Smckusick /* d4 */ ' ',		KBD_NOKEY,	'%',		't',
31652130Smckusick /* d8 */ 'g',		'b',		KBD_NOKEY,	'^',
31752130Smckusick /* dc */ 'y',		'h',		'n',		KBD_NOKEY,
31852130Smckusick /* e0 */ '&',		'u',		'j',		'm',
31952130Smckusick /* e4 */ KBD_NOKEY,	'*',		'i',		'k',
32052130Smckusick /* e8 */ '<',		KBD_NOKEY,	'(',		'o',
32152130Smckusick /* ec */ 'l',		'>',		KBD_NOKEY,	')',
32252130Smckusick /* f0 */ 'p',		KBD_NOKEY,	':',		'?',
32352130Smckusick /* f4 */ KBD_NOKEY,	'+',		'}',		'|',
32452130Smckusick /* f8 */ KBD_NOKEY,	'_',		'{',		'"',
32552130Smckusick /* fc */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
32652130Smckusick };
32752130Smckusick 
32852130Smckusick /*
32952130Smckusick  * Keyboard initialization string.
33052130Smckusick  */
33152130Smckusick static u_char kbdInitString[] = {
33252130Smckusick 	LK_LED_ENABLE, LED_ALL,		/* show we are resetting keyboard */
33352130Smckusick 	LK_DEFAULTS,
33452130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 1),
33552130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 2),
33652130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 3),
33752130Smckusick 	LK_CMD_MODE(LK_DOWN, 4),	/* could also be LK_AUTODOWN */
33852130Smckusick 	LK_CMD_MODE(LK_UPDOWN, 5),
33952130Smckusick 	LK_CMD_MODE(LK_UPDOWN, 6),
34052130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 7),
34152130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 8),
34252130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 9),
34352130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 10),
34452130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 11),
34552130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 12),
34652130Smckusick 	LK_CMD_MODE(LK_DOWN, 13),
34752130Smckusick 	LK_CMD_MODE(LK_AUTODOWN, 14),
34852130Smckusick 	LK_AR_ENABLE,			/* we want autorepeat by default */
34952130Smckusick 	LK_CL_ENABLE, 0x83,		/* keyclick, volume */
35052130Smckusick 	LK_KBD_ENABLE,			/* the keyboard itself */
35152130Smckusick 	LK_BELL_ENABLE, 0x83,		/* keyboard bell, volume */
35252130Smckusick 	LK_LED_DISABLE, LED_ALL,	/* clear keyboard leds */
35352130Smckusick };
35452130Smckusick 
35552130Smckusick /*
35652130Smckusick  * Test to see if device is present.
35752130Smckusick  * Return true if found and initialized ok.
35852130Smckusick  */
35952130Smckusick dcprobe(cp)
36052130Smckusick 	register struct pmax_ctlr *cp;
36152130Smckusick {
36252130Smckusick 	register dcregs *dcaddr;
36352130Smckusick 	register struct pdma *pdp;
36452130Smckusick 	register struct tty *tp;
36552130Smckusick 	register int cntr;
36652130Smckusick 
36752130Smckusick 	if (cp->pmax_unit >= NDC)
36852130Smckusick 		return (0);
36952130Smckusick 	if (badaddr(cp->pmax_addr, 2))
37052130Smckusick 		return (0);
37152130Smckusick 
37252130Smckusick 	/* reset chip */
37352130Smckusick 	dcaddr = (dcregs *)cp->pmax_addr;
37452130Smckusick 	dcaddr->dc_csr = CSR_CLR;
37552130Smckusick 	MachEmptyWriteBuffer();
37652130Smckusick 	while (dcaddr->dc_csr & CSR_CLR)
37752130Smckusick 		;
37852130Smckusick 	dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE;
37952130Smckusick 
38052130Smckusick 	/* init pseudo DMA structures */
38152130Smckusick 	pdp = &dcpdma[cp->pmax_unit * 4];
38252130Smckusick 	tp = &dc_tty[cp->pmax_unit * 4];
38352130Smckusick 	for (cntr = 0; cntr < 4; cntr++) {
38452130Smckusick 		pdp->p_addr = dcaddr;
38552130Smckusick 		pdp->p_arg = (int)tp;
38652130Smckusick 		pdp->p_fcn = dcxint;
38752130Smckusick 		tp->t_addr = (caddr_t)pdp;
38852130Smckusick 		pdp++, tp++;
38952130Smckusick 	}
39052130Smckusick 	dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB;
39152130Smckusick 
39252130Smckusick 	if (dc_timer == 0) {
39352130Smckusick 		dc_timer = 1;
39455744Sralph 		timeout(dcscan, (void *)0, hz);
39552130Smckusick 	}
39652693Sralph 	printf("dc%d at nexus0 csr 0x%x priority %d\n",
39752693Sralph 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
39852130Smckusick 	if (cp->pmax_unit == 0) {
39952130Smckusick 		int s;
40052130Smckusick 
40152130Smckusick 		s = spltty();
40252130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR |
40352130Smckusick 			KBD_PORT;
40452130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
40552130Smckusick 			LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT;
40652130Smckusick 		MachEmptyWriteBuffer();
40752130Smckusick 		dcKBDReset();
40852130Smckusick 		MouseInit();
40952130Smckusick 		splx(s);
41052130Smckusick 	}
41152130Smckusick 	return (1);
41252130Smckusick }
41352130Smckusick 
41454146Sralph dcopen(dev, flag, mode, p)
41552130Smckusick 	dev_t dev;
41654146Sralph 	int flag, mode;
41754146Sralph 	struct proc *p;
41852130Smckusick {
41952130Smckusick 	register struct tty *tp;
42052130Smckusick 	register int unit;
42152130Smckusick 	int s, error = 0;
42252130Smckusick 	extern int dcparam();
42352130Smckusick 
42452130Smckusick 	unit = minor(dev);
42552130Smckusick 	if (unit >= dc_cnt || dcpdma[unit].p_addr == 0)
42652130Smckusick 		return (ENXIO);
42752130Smckusick 	tp = &dc_tty[unit];
42852130Smckusick 	tp->t_addr = (caddr_t)&dcpdma[unit];
42952130Smckusick 	tp->t_oproc = dcstart;
43052130Smckusick 	tp->t_param = dcparam;
43152130Smckusick 	tp->t_dev = dev;
43252130Smckusick 	if ((tp->t_state & TS_ISOPEN) == 0) {
43352130Smckusick 		tp->t_state |= TS_WOPEN;
43452130Smckusick 		ttychars(tp);
43552130Smckusick #ifndef PORTSELECTOR
43652130Smckusick 		if (tp->t_ispeed == 0) {
43752130Smckusick #endif
43852130Smckusick 			tp->t_iflag = TTYDEF_IFLAG;
43952130Smckusick 			tp->t_oflag = TTYDEF_OFLAG;
44052130Smckusick 			tp->t_cflag = TTYDEF_CFLAG;
44152130Smckusick 			tp->t_lflag = LFLAG;
44252130Smckusick 			tp->t_ispeed = tp->t_ospeed = ISPEED;
44352130Smckusick #ifdef PORTSELECTOR
44452130Smckusick 			tp->t_cflag |= HUPCL;
44552130Smckusick #else
44652130Smckusick 		}
44752130Smckusick #endif
44852130Smckusick 		(void) dcparam(tp, &tp->t_termios);
44952130Smckusick 		ttsetwater(tp);
45052130Smckusick 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
45152130Smckusick 		return (EBUSY);
45252130Smckusick 	(void) dcmctl(dev, DML_DTR, DMSET);
45352130Smckusick 	s = spltty();
45452130Smckusick 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
45552130Smckusick 	       !(tp->t_state & TS_CARR_ON)) {
45652130Smckusick 		tp->t_state |= TS_WOPEN;
45752130Smckusick 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
45852130Smckusick 		    ttopen, 0))
45952130Smckusick 			break;
46052130Smckusick 	}
46152130Smckusick 	splx(s);
46252130Smckusick 	if (error)
46352130Smckusick 		return (error);
46452130Smckusick 	return ((*linesw[tp->t_line].l_open)(dev, tp));
46552130Smckusick }
46652130Smckusick 
46752130Smckusick /*ARGSUSED*/
46854146Sralph dcclose(dev, flag, mode, p)
46952130Smckusick 	dev_t dev;
47054146Sralph 	int flag, mode;
47154146Sralph 	struct proc *p;
47252130Smckusick {
47352130Smckusick 	register struct tty *tp;
47452130Smckusick 	register int unit, bit;
47552130Smckusick 
47652130Smckusick 	unit = minor(dev);
47752130Smckusick 	tp = &dc_tty[unit];
47852130Smckusick 	bit = 1 << ((unit & 03) + 8);
47952130Smckusick 	if (dc_brk[unit >> 2] & bit) {
48052130Smckusick 		dc_brk[unit >> 2] &= ~bit;
48152130Smckusick 		ttyoutput(0, tp);
48252130Smckusick 	}
48354146Sralph 	(*linesw[tp->t_line].l_close)(tp, flag);
48452130Smckusick 	if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
48552130Smckusick 	    !(tp->t_state & TS_ISOPEN))
48652130Smckusick 		(void) dcmctl(dev, 0, DMSET);
48752130Smckusick 	return (ttyclose(tp));
48852130Smckusick }
48952130Smckusick 
49052130Smckusick dcread(dev, uio, flag)
49152130Smckusick 	dev_t dev;
49252130Smckusick 	struct uio *uio;
49352130Smckusick {
49452130Smckusick 	register struct tty *tp;
49552130Smckusick 
49652130Smckusick 	tp = &dc_tty[minor(dev)];
49752130Smckusick 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
49852130Smckusick }
49952130Smckusick 
50052130Smckusick dcwrite(dev, uio, flag)
50152130Smckusick 	dev_t dev;
50252130Smckusick 	struct uio *uio;
50352130Smckusick {
50452130Smckusick 	register struct tty *tp;
50552130Smckusick 
50652130Smckusick 	tp = &dc_tty[minor(dev)];
50752130Smckusick 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
50852130Smckusick }
50952130Smckusick 
51052130Smckusick /*ARGSUSED*/
51154146Sralph dcioctl(dev, cmd, data, flag, p)
51252130Smckusick 	dev_t dev;
51352130Smckusick 	caddr_t data;
51454146Sralph 	int flag;
51554146Sralph 	struct proc *p;
51652130Smckusick {
51752130Smckusick 	register struct tty *tp;
51852130Smckusick 	register int unit = minor(dev);
51952130Smckusick 	register int dc = unit >> 2;
52052130Smckusick 	int error;
52152130Smckusick 
52252130Smckusick 	tp = &dc_tty[unit];
52354146Sralph 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
52452130Smckusick 	if (error >= 0)
52552130Smckusick 		return (error);
52652130Smckusick 	error = ttioctl(tp, cmd, data, flag);
52752130Smckusick 	if (error >= 0)
52852130Smckusick 		return (error);
52952130Smckusick 
53052130Smckusick 	switch (cmd) {
53152130Smckusick 
53252130Smckusick 	case TIOCSBRK:
53352130Smckusick 		dc_brk[dc] |= 1 << ((unit & 03) + 8);
53452130Smckusick 		ttyoutput(0, tp);
53552130Smckusick 		break;
53652130Smckusick 
53752130Smckusick 	case TIOCCBRK:
53852130Smckusick 		dc_brk[dc] &= ~(1 << ((unit & 03) + 8));
53952130Smckusick 		ttyoutput(0, tp);
54052130Smckusick 		break;
54152130Smckusick 
54252130Smckusick 	case TIOCSDTR:
54352130Smckusick 		(void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS);
54452130Smckusick 		break;
54552130Smckusick 
54652130Smckusick 	case TIOCCDTR:
54752130Smckusick 		(void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC);
54852130Smckusick 		break;
54952130Smckusick 
55052130Smckusick 	case TIOCMSET:
55152130Smckusick 		(void) dcmctl(dev, *(int *)data, DMSET);
55252130Smckusick 		break;
55352130Smckusick 
55452130Smckusick 	case TIOCMBIS:
55552130Smckusick 		(void) dcmctl(dev, *(int *)data, DMBIS);
55652130Smckusick 		break;
55752130Smckusick 
55852130Smckusick 	case TIOCMBIC:
55952130Smckusick 		(void) dcmctl(dev, *(int *)data, DMBIC);
56052130Smckusick 		break;
56152130Smckusick 
56252130Smckusick 	case TIOCMGET:
56352130Smckusick 		*(int *)data = dcmctl(dev, 0, DMGET);
56452130Smckusick 		break;
56552130Smckusick 
56652130Smckusick 	default:
56752130Smckusick 		return (ENOTTY);
56852130Smckusick 	}
56952130Smckusick 	return (0);
57052130Smckusick }
57152130Smckusick 
57252130Smckusick dcparam(tp, t)
57352130Smckusick 	register struct tty *tp;
57452130Smckusick 	register struct termios *t;
57552130Smckusick {
57652130Smckusick 	register dcregs *dcaddr;
57752130Smckusick 	register int lpr;
57852130Smckusick 	register int cflag = t->c_cflag;
57952130Smckusick 	int unit = minor(tp->t_dev);
58052130Smckusick 	int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab);
58152130Smckusick 
58252130Smckusick 	/* check requested parameters */
58352130Smckusick         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
58452130Smckusick             (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6)
58552130Smckusick                 return (EINVAL);
58652130Smckusick         /* and copy to tty */
58752130Smckusick         tp->t_ispeed = t->c_ispeed;
58852130Smckusick         tp->t_ospeed = t->c_ospeed;
58952130Smckusick         tp->t_cflag = cflag;
59052130Smckusick 
59152130Smckusick 	dcaddr = dcpdma[unit].p_addr;
59252130Smckusick 	if (tp == dc_tty + KBD_PORT) {
59352130Smckusick 		/* handle the keyboard specially */
59452130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_8_BIT_CHAR |
59552130Smckusick 			KBD_PORT;
59652130Smckusick 		MachEmptyWriteBuffer();
59752130Smckusick 		return (0);
59852130Smckusick 	}
59952130Smckusick 	if (tp == dc_tty + MOUSE_PORT) {
60052130Smckusick 		/* handle the mouse specially */
60152130Smckusick 		dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR |
60252130Smckusick 			LPR_PARENB | LPR_8_BIT_CHAR | MOUSE_PORT;
60352130Smckusick 		MachEmptyWriteBuffer();
60452130Smckusick 		return (0);
60552130Smckusick 	}
60652130Smckusick 	if (ospeed == 0) {
60752130Smckusick 		(void) dcmctl(unit, 0, DMSET);	/* hang up line */
60852130Smckusick 		return (0);
60952130Smckusick 	}
61052130Smckusick 	lpr = LPR_RXENAB | ospeed | (unit & 03);
61152130Smckusick 	if ((cflag & CSIZE) == CS7)
61252130Smckusick 		lpr |= LPR_7_BIT_CHAR;
61352130Smckusick 	else
61452130Smckusick 		lpr |= LPR_8_BIT_CHAR;
61552130Smckusick 	if (cflag & PARENB)
61652130Smckusick 		lpr |= LPR_PARENB;
61752130Smckusick 	if (cflag & PARODD)
61852130Smckusick 		lpr |= LPR_OPAR;
61952130Smckusick 	if (cflag & CSTOPB)
62052130Smckusick 		lpr |= LPR_2_STOP;
62152130Smckusick 	dcaddr->dc_lpr = lpr;
62252130Smckusick 	MachEmptyWriteBuffer();
62352130Smckusick 	return (0);
62452130Smckusick }
62552130Smckusick 
62652693Sralph /*
62752693Sralph  * Check for interrupts from all devices.
62852693Sralph  */
62952693Sralph void
63052693Sralph dcintr(unit)
63152693Sralph 	register int unit;
63252693Sralph {
63352693Sralph 	register dcregs *dcaddr;
63452693Sralph 	register unsigned csr;
63552693Sralph 
63652693Sralph 	unit <<= 2;
63752693Sralph 	dcaddr = dcpdma[unit].p_addr;
63852693Sralph 	while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) {
63952693Sralph 		if (csr & CSR_RDONE)
64052693Sralph 			dcrint(unit);
64152693Sralph 		if (csr & CSR_TRDY)
64252693Sralph 			dcxint(&dc_tty[unit + ((csr >> 8) & 03)]);
64352693Sralph 	}
64452693Sralph }
64552693Sralph 
64652693Sralph dcrint(unit)
64752693Sralph 	register int unit;
64852693Sralph {
64952693Sralph 	register dcregs *dcaddr;
65052693Sralph 	register struct tty *tp;
65152693Sralph 	register int c, cc;
65252693Sralph 	register struct tty *tp0;
65352693Sralph 	int overrun = 0;
65452693Sralph 
65552693Sralph 	dcaddr = dcpdma[unit].p_addr;
65652693Sralph 	tp0 = &dc_tty[unit];
65752693Sralph 	while ((c = dcaddr->dc_rbuf) < 0) {	/* char present */
65852693Sralph 		cc = c & 0xff;
65952693Sralph 		tp = tp0 + ((c >> 8) & 03);
66052693Sralph 		if ((c & RBUF_OERR) && overrun == 0) {
66152693Sralph 			log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2,
66252693Sralph 				(c >> 8) & 03);
66352693Sralph 			overrun = 1;
66452693Sralph 		}
66552693Sralph 		/* the keyboard requires special translation */
66652693Sralph 		if (tp == &dc_tty[KBD_PORT]) {
66752693Sralph #ifdef KADB
66852693Sralph 			if (cc == LK_DO) {
66952693Sralph 				spl0();
67052693Sralph 				kdbpanic();
67152693Sralph 				return;
67252693Sralph 			}
67352693Sralph #endif
67452693Sralph #ifdef DEBUG
67552693Sralph 			debugChar = cc;
67652693Sralph #endif
67752693Sralph 			if (dcDivertXInput) {
67852863Sralph 				(*dcDivertXInput)(cc);
67952693Sralph 				return;
68052693Sralph 			}
68152693Sralph 			if ((cc = dcMapChar(cc)) < 0)
68252693Sralph 				return;
68352863Sralph 		} else if (tp == &dc_tty[MOUSE_PORT] && dcMouseButtons) {
68452863Sralph 			register MouseReport *mrp;
68552693Sralph 			static MouseReport currentRep;
68652693Sralph 
68752863Sralph 			mrp = &currentRep;
68852863Sralph 			mrp->byteCount++;
68952693Sralph 			if (cc & MOUSE_START_FRAME) {
69052693Sralph 				/*
69152693Sralph 				 * The first mouse report byte (button state).
69252693Sralph 				 */
69352863Sralph 				mrp->state = cc;
69452863Sralph 				if (mrp->byteCount > 1)
69552863Sralph 					mrp->byteCount = 1;
69652863Sralph 			} else if (mrp->byteCount == 2) {
69752693Sralph 				/*
69852693Sralph 				 * The second mouse report byte (delta x).
69952693Sralph 				 */
70052863Sralph 				mrp->dx = cc;
70152863Sralph 			} else if (mrp->byteCount == 3) {
70252693Sralph 				/*
70352693Sralph 				 * The final mouse report byte (delta y).
70452693Sralph 				 */
70552863Sralph 				mrp->dy = cc;
70652863Sralph 				mrp->byteCount = 0;
70752863Sralph 				if (mrp->dx != 0 || mrp->dy != 0) {
70852693Sralph 					/*
70952693Sralph 					 * If the mouse moved,
71052693Sralph 					 * post a motion event.
71152693Sralph 					 */
71252863Sralph 					(*dcMouseEvent)(mrp);
71352693Sralph 				}
71452863Sralph 				(*dcMouseButtons)(mrp);
71552693Sralph 			}
71652693Sralph 			return;
71752693Sralph 		}
71852693Sralph 		if (!(tp->t_state & TS_ISOPEN)) {
71952693Sralph 			wakeup((caddr_t)&tp->t_rawq);
72052693Sralph #ifdef PORTSELECTOR
72152693Sralph 			if (!(tp->t_state & TS_WOPEN))
72252693Sralph #endif
72352693Sralph 				return;
72452693Sralph 		}
72552693Sralph 		if (c & RBUF_FERR)
72652693Sralph 			cc |= TTY_FE;
72752693Sralph 		if (c & RBUF_PERR)
72852693Sralph 			cc |= TTY_PE;
72952693Sralph 		(*linesw[tp->t_line].l_rint)(cc, tp);
73052693Sralph 	}
73152693Sralph 	DELAY(10);
73252693Sralph }
73352693Sralph 
73452755Sralph void
73552130Smckusick dcxint(tp)
73652130Smckusick 	register struct tty *tp;
73752130Smckusick {
73852130Smckusick 	register struct pdma *dp;
73952130Smckusick 	register dcregs *dcaddr;
74052130Smckusick 
74152130Smckusick 	dp = (struct pdma *)tp->t_addr;
74252130Smckusick 	if (dp->p_mem < dp->p_end) {
74352130Smckusick 		dcaddr = dp->p_addr;
74452130Smckusick 		dcaddr->dc_tdr = dc_brk[(tp - dc_tty) >> 2] | *dp->p_mem++;
74552130Smckusick 		MachEmptyWriteBuffer();
74652130Smckusick 		DELAY(10);
74752130Smckusick 		return;
74852130Smckusick 	}
74952130Smckusick 	tp->t_state &= ~TS_BUSY;
75052130Smckusick 	if (tp->t_state & TS_FLUSH)
75152130Smckusick 		tp->t_state &= ~TS_FLUSH;
75252130Smckusick 	else {
75352130Smckusick 		ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
75452130Smckusick 		dp->p_end = dp->p_mem = tp->t_outq.c_cf;
75552130Smckusick 	}
75652130Smckusick 	if (tp->t_line)
75752130Smckusick 		(*linesw[tp->t_line].l_start)(tp);
75852130Smckusick 	else
75952130Smckusick 		dcstart(tp);
76052130Smckusick 	if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
76152130Smckusick 		dp->p_addr->dc_tcr &= ~(1 << (minor(tp->t_dev) & 03));
76252130Smckusick 		MachEmptyWriteBuffer();
76352130Smckusick 		DELAY(10);
76452130Smckusick 	}
76552130Smckusick }
76652130Smckusick 
76752755Sralph void
76852130Smckusick dcstart(tp)
76952130Smckusick 	register struct tty *tp;
77052130Smckusick {
77152130Smckusick 	register struct pdma *dp;
77252130Smckusick 	register dcregs *dcaddr;
77352130Smckusick 	register int cc;
77452130Smckusick 	int s;
77552130Smckusick 
77652130Smckusick 	dp = (struct pdma *)tp->t_addr;
77752130Smckusick 	dcaddr = dp->p_addr;
77852130Smckusick 	s = spltty();
77952130Smckusick 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
78052130Smckusick 		goto out;
78152130Smckusick 	if (tp->t_outq.c_cc <= tp->t_lowat) {
78252130Smckusick 		if (tp->t_state & TS_ASLEEP) {
78352130Smckusick 			tp->t_state &= ~TS_ASLEEP;
78452130Smckusick 			wakeup((caddr_t)&tp->t_outq);
78552130Smckusick 		}
78652674Smckusick 		selwakeup(&tp->t_wsel);
78752130Smckusick 	}
78852130Smckusick 	if (tp->t_outq.c_cc == 0)
78952130Smckusick 		goto out;
79052130Smckusick 	/* handle console specially */
79152130Smckusick 	if (tp == dc_tty) {
79252130Smckusick 		while (tp->t_outq.c_cc > 0) {
79352130Smckusick 			cc = getc(&tp->t_outq) & 0x7f;
79452863Sralph 			cnputc(cc);
79552130Smckusick 		}
79652130Smckusick 		/*
79752130Smckusick 		 * After we flush the output queue we may need to wake
79852130Smckusick 		 * up the process that made the output.
79952130Smckusick 		 */
80052130Smckusick 		if (tp->t_outq.c_cc <= tp->t_lowat) {
80152130Smckusick 			if (tp->t_state & TS_ASLEEP) {
80252130Smckusick 				tp->t_state &= ~TS_ASLEEP;
80352130Smckusick 				wakeup((caddr_t)&tp->t_outq);
80452130Smckusick 			}
80552674Smckusick 			selwakeup(&tp->t_wsel);
80652130Smckusick 		}
80752130Smckusick 		goto out;
80852130Smckusick 	}
80952130Smckusick 	if (tp->t_flags & (RAW|LITOUT))
81052130Smckusick 		cc = ndqb(&tp->t_outq, 0);
81152130Smckusick 	else {
81252130Smckusick 		cc = ndqb(&tp->t_outq, 0200);
81352130Smckusick 		if (cc == 0) {
81452130Smckusick 			cc = getc(&tp->t_outq);
81555744Sralph 			timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6);
81652130Smckusick 			tp->t_state |= TS_TIMEOUT;
81752130Smckusick 			goto out;
81852130Smckusick 		}
81952130Smckusick 	}
82052130Smckusick 	tp->t_state |= TS_BUSY;
82152130Smckusick 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
82252130Smckusick 	dp->p_end += cc;
82352130Smckusick 	dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03);
82452130Smckusick 	MachEmptyWriteBuffer();
82552130Smckusick out:
82652130Smckusick 	splx(s);
82752130Smckusick }
82852130Smckusick 
82952130Smckusick /*
83052130Smckusick  * Stop output on a line.
83152130Smckusick  */
83252130Smckusick /*ARGSUSED*/
83352130Smckusick dcstop(tp, flag)
83452130Smckusick 	register struct tty *tp;
83552130Smckusick {
83652130Smckusick 	register struct pdma *dp;
83752130Smckusick 	register int s;
83852130Smckusick 
83952130Smckusick 	dp = (struct pdma *)tp->t_addr;
84052130Smckusick 	s = spltty();
84152130Smckusick 	if (tp->t_state & TS_BUSY) {
84252130Smckusick 		dp->p_end = dp->p_mem;
84352130Smckusick 		if (!(tp->t_state & TS_TTSTOP))
84452130Smckusick 			tp->t_state |= TS_FLUSH;
84552130Smckusick 	}
84652130Smckusick 	splx(s);
84752130Smckusick }
84852130Smckusick 
84952130Smckusick dcmctl(dev, bits, how)
85052130Smckusick 	dev_t dev;
85152130Smckusick 	int bits, how;
85252130Smckusick {
85352130Smckusick 	register dcregs *dcaddr;
85452130Smckusick 	register int unit, mbits;
85552130Smckusick 	int b, s;
85652693Sralph #ifdef DS5000
85752693Sralph 	register int msr;
85852693Sralph #endif
85952130Smckusick 
86052130Smckusick 	unit = minor(dev);
86152130Smckusick 	b = 1 << (unit & 03);
86252130Smckusick 	dcaddr = dcpdma[unit].p_addr;
86352130Smckusick 	s = spltty();
86452130Smckusick 	/* only channel 2 has modem control (what about line 3?) */
86552693Sralph 	switch (unit & 03) {
86652693Sralph 	case 2:
86752130Smckusick 		mbits = 0;
86852130Smckusick 		if (dcaddr->dc_tcr & TCR_DTR2)
86952130Smckusick 			mbits |= DML_DTR;
87052693Sralph #ifdef DS3100
87152130Smckusick 		if (dcaddr->dc_msr & MSR_DSR2)
87252130Smckusick 			mbits |= DML_DSR | DML_CAR;
87352693Sralph #endif
87452693Sralph #ifdef DS5000
87552693Sralph 		msr = dcaddr->dc_msr;
87652693Sralph 		if (msr & MSR_CD2)
87752693Sralph 			mbits |= DML_CAR;
87852693Sralph 		if (msr & MSR_DSR2)
87952693Sralph 			mbits |= DML_DSR;
88052693Sralph #endif
88152693Sralph 		break;
88252693Sralph 
88352693Sralph #ifdef DS5000
88452693Sralph 	case 3:
88552693Sralph 		mbits = 0;
88652693Sralph 		if (dcaddr->dc_tcr & TCR_DTR3)
88752693Sralph 			mbits |= DML_DTR;
88852693Sralph 		msr = dcaddr->dc_msr;
88952693Sralph 		if (msr & MSR_CD3)
89052693Sralph 			mbits |= DML_CAR;
89152693Sralph 		if (msr & MSR_DSR3)
89252693Sralph 			mbits |= DML_DSR;
89352693Sralph 		break;
89452693Sralph #endif
89552693Sralph 
89652693Sralph 	default:
89752130Smckusick 		mbits = DML_DTR | DML_DSR | DML_CAR;
89852693Sralph 	}
89952130Smckusick 	switch (how) {
90052130Smckusick 	case DMSET:
90152130Smckusick 		mbits = bits;
90252130Smckusick 		break;
90352130Smckusick 
90452130Smckusick 	case DMBIS:
90552130Smckusick 		mbits |= bits;
90652130Smckusick 		break;
90752130Smckusick 
90852130Smckusick 	case DMBIC:
90952130Smckusick 		mbits &= ~bits;
91052130Smckusick 		break;
91152130Smckusick 
91252130Smckusick 	case DMGET:
91352130Smckusick 		(void) splx(s);
91452130Smckusick 		return (mbits);
91552130Smckusick 	}
91652693Sralph 	switch (unit & 03) {
91752693Sralph 	case 2:
91852130Smckusick 		if (mbits & DML_DTR)
91952130Smckusick 			dcaddr->dc_tcr |= TCR_DTR2;
92052130Smckusick 		else
92152130Smckusick 			dcaddr->dc_tcr &= ~TCR_DTR2;
92252693Sralph 		break;
92352693Sralph 
92452693Sralph #ifdef DS5000
92552693Sralph 	case 3:
92652693Sralph 		if (mbits & DML_DTR)
92752693Sralph 			dcaddr->dc_tcr |= TCR_DTR3;
92852693Sralph 		else
92952693Sralph 			dcaddr->dc_tcr &= ~TCR_DTR3;
93052693Sralph #endif
93152130Smckusick 	}
93252130Smckusick 	if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b))
93352130Smckusick 		dc_tty[unit].t_state |= TS_CARR_ON;
93452130Smckusick 	(void) splx(s);
93552130Smckusick 	return (mbits);
93652130Smckusick }
93752130Smckusick 
93852130Smckusick /*
93952130Smckusick  * This is called by timeout() periodically.
94052130Smckusick  * Check to see if modem status bits have changed.
94152130Smckusick  */
94255744Sralph /* ARGSUSED */
94354146Sralph static void
94455744Sralph dcscan(arg)
94555744Sralph 	void *arg;
94652130Smckusick {
94752130Smckusick 	register dcregs *dcaddr;
94852130Smckusick 	register struct tty *tp;
94952130Smckusick 	register int i, bit, car;
95052130Smckusick 	int s;
95152130Smckusick 
95252130Smckusick 	s = spltty();
95352130Smckusick 	/* only channel 2 has modem control (what about line 3?) */
95452130Smckusick 	dcaddr = dcpdma[i = 2].p_addr;
95552130Smckusick 	tp = &dc_tty[i];
95652130Smckusick 	bit = TCR_DTR2;
95752130Smckusick 	if (dcsoftCAR[i >> 2] & bit)
95852130Smckusick 		car = 1;
95952130Smckusick 	else
96052130Smckusick 		car = dcaddr->dc_msr & MSR_DSR2;
96152130Smckusick 	if (car) {
96252130Smckusick 		/* carrier present */
96352130Smckusick 		if (!(tp->t_state & TS_CARR_ON))
96452130Smckusick 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
96552130Smckusick 	} else if ((tp->t_state & TS_CARR_ON) &&
96652130Smckusick 	    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
96752130Smckusick 		dcaddr->dc_tcr &= ~bit;
96852130Smckusick 	splx(s);
96955744Sralph 	timeout(dcscan, (void *)0, hz);
97052130Smckusick }
97152130Smckusick 
97252130Smckusick /*
97352130Smckusick  * ----------------------------------------------------------------------------
97452130Smckusick  *
97552130Smckusick  * dcKBDPutc --
97652130Smckusick  *
97752130Smckusick  *	Put a character out to the keyboard.
97852130Smckusick  *
97952130Smckusick  * Results:
98052130Smckusick  *	None.
98152130Smckusick  *
98252130Smckusick  * Side effects:
98352130Smckusick  *	A character is written to the keyboard.
98452130Smckusick  *
98552130Smckusick  * ----------------------------------------------------------------------------
98652130Smckusick  */
98752130Smckusick void
98852130Smckusick dcKBDPutc(c)
98952130Smckusick 	register int c;
99052130Smckusick {
99152130Smckusick 	register dcregs *dcaddr;
99252130Smckusick 	register u_short tcr;
99352130Smckusick 	register int timeout;
99452130Smckusick 	int s, line;
99552130Smckusick 
99652130Smckusick 	s = spltty();
99752130Smckusick 
99852130Smckusick 	dcaddr = dcpdma[KBD_PORT].p_addr;
99952130Smckusick 	tcr = dcaddr->dc_tcr;
100052130Smckusick 	dcaddr->dc_tcr = tcr | (1 << KBD_PORT);
100152130Smckusick 	MachEmptyWriteBuffer();
100252130Smckusick 	DELAY(10);
100352130Smckusick 	while (1) {
100452130Smckusick 		/*
100552130Smckusick 		 * Wait for transmitter to be not busy.
100652130Smckusick 		 */
100752130Smckusick 		timeout = 1000000;
100852130Smckusick 		while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
100952130Smckusick 			timeout--;
101052130Smckusick 		if (timeout == 0) {
101152130Smckusick 			printf("dcKBDPutc: timeout waiting for CSR_TRDY\n");
101252130Smckusick 			break;
101352130Smckusick 		}
101452130Smckusick 		line = (dcaddr->dc_csr >> 8) & 3;
101552130Smckusick 		/*
101652130Smckusick 		 * Check to be sure its the right port.
101752130Smckusick 		 */
101852130Smckusick 		if (line != KBD_PORT) {
101952130Smckusick 			tcr |= 1 << line;
102052130Smckusick 			dcaddr->dc_tcr &= ~(1 << line);
102152130Smckusick 			MachEmptyWriteBuffer();
102252130Smckusick 			DELAY(10);
102352130Smckusick 			continue;
102452130Smckusick 		}
102552130Smckusick 		/*
102652130Smckusick 		 * Start sending the character.
102752130Smckusick 		 */
102852130Smckusick 		dcaddr->dc_tdr = dc_brk[0] | (c & 0xff);
102952130Smckusick 		MachEmptyWriteBuffer();
103052130Smckusick 		DELAY(10);
103152130Smckusick 		/*
103252130Smckusick 		 * Wait for character to be sent.
103352130Smckusick 		 */
103452130Smckusick 		while (1) {
103552130Smckusick 			/*
103652130Smckusick 			 * cc -O bug: this code produces and infinite loop!
103752130Smckusick 			 * while (!(dcaddr->dc_csr & CSR_TRDY))
103852130Smckusick 			 *	;
103952130Smckusick 			 */
104052130Smckusick 			timeout = 1000000;
104152130Smckusick 			while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
104252130Smckusick 				timeout--;
104352130Smckusick 			line = (dcaddr->dc_csr >> 8) & 3;
104452130Smckusick 			if (line != KBD_PORT) {
104552130Smckusick 				tcr |= 1 << line;
104652130Smckusick 				dcaddr->dc_tcr &= ~(1 << line);
104752130Smckusick 				MachEmptyWriteBuffer();
104852130Smckusick 				DELAY(10);
104952130Smckusick 				continue;
105052130Smckusick 			}
105152130Smckusick 			dcaddr->dc_tcr &= ~(1 << KBD_PORT);
105252130Smckusick 			MachEmptyWriteBuffer();
105352130Smckusick 			DELAY(10);
105452130Smckusick 			break;
105552130Smckusick 		}
105652130Smckusick 		break;
105752130Smckusick 	}
105852130Smckusick 	/*
105952130Smckusick 	 * Enable interrupts for other lines which became ready.
106052130Smckusick 	 */
106152130Smckusick 	if (tcr & 0xF) {
106252130Smckusick 		dcaddr->dc_tcr = tcr;
106352130Smckusick 		MachEmptyWriteBuffer();
106452130Smckusick 		DELAY(10);
106552130Smckusick 	}
106652130Smckusick 
106752130Smckusick 	splx(s);
106852130Smckusick }
106952130Smckusick 
107052130Smckusick #ifdef DEBUG
107152130Smckusick /*
107252130Smckusick  * ----------------------------------------------------------------------------
107352130Smckusick  *
107452693Sralph  * dcDebugGetc --
107552130Smckusick  *
107652693Sralph  *	Read a character from the keyboard if one is ready (i.e., don't wait).
107752130Smckusick  *
107852130Smckusick  * Results:
107952130Smckusick  *	A character read from the mouse, -1 if none were ready.
108052130Smckusick  *
108152130Smckusick  * Side effects:
108252130Smckusick  *	None.
108352130Smckusick  *
108452130Smckusick  * ----------------------------------------------------------------------------
108552130Smckusick  */
108652130Smckusick int
108752693Sralph dcDebugGetc()
108852130Smckusick {
108952130Smckusick 	register dcregs *dcaddr;
109052130Smckusick 	register int c;
109154146Sralph 	int s;
109252130Smckusick 
109352130Smckusick 	dcaddr = dcpdma[KBD_PORT].p_addr;
109452130Smckusick 	if (!dcaddr)
109552130Smckusick 		return (0);
109654146Sralph 
109754146Sralph 	s = spltty();
109852130Smckusick 	if (c = debugChar)
109952130Smckusick 		debugChar = 0;
110052130Smckusick 	else {
110152130Smckusick 		while (dcaddr->dc_csr & CSR_RDONE) {
110252130Smckusick 			c = dcaddr->dc_rbuf;
110352130Smckusick 			DELAY(10);
110452130Smckusick 			if (((c >> 8) & 03) == KBD_PORT)
110552130Smckusick 				break;
110652130Smckusick 			c = 0;
110752130Smckusick 		}
110852130Smckusick 	}
110954146Sralph 	splx(s);
111054146Sralph 
111152130Smckusick 	return (c & 0xff);
111252130Smckusick }
111352130Smckusick #endif
111452130Smckusick 
111552130Smckusick /*
111652130Smckusick  * ----------------------------------------------------------------------------
111752130Smckusick  *
111852693Sralph  * dcKBDGetc --
111952693Sralph  *
112052693Sralph  *	Read a character from the keyboard.
112152693Sralph  *
112252693Sralph  * Results:
112352693Sralph  *	A character read from the keyboard.
112452693Sralph  *
112552693Sralph  * Side effects:
112652693Sralph  *	None.
112752693Sralph  *
112852693Sralph  * ----------------------------------------------------------------------------
112952693Sralph  */
113052693Sralph int
113152693Sralph dcKBDGetc()
113252693Sralph {
113352693Sralph 	register dcregs *dcaddr;
113452693Sralph 	register int c;
113552693Sralph 	int s;
113652693Sralph 
113752693Sralph 	dcaddr = dcpdma[KBD_PORT].p_addr;
113852693Sralph 	if (!dcaddr)
113952693Sralph 		return (-1);
114052693Sralph 	s = spltty();
114152693Sralph 	for (;;) {
114252693Sralph 		if (!(dcaddr->dc_csr & CSR_RDONE))
114352693Sralph 			continue;
114452693Sralph 		c = dcaddr->dc_rbuf;
114552693Sralph 		DELAY(10);
114652693Sralph 		if (((c >> 8) & 03) != KBD_PORT)
114752693Sralph 			continue;
114852693Sralph 		if ((c = dcMapChar(c & 0xff)) >= 0)
114952693Sralph 			break;
115052693Sralph 	}
115152693Sralph 	splx(s);
115252693Sralph 	return (c);
115352693Sralph }
115452693Sralph 
115552693Sralph /*
115652693Sralph  * ----------------------------------------------------------------------------
115752693Sralph  *
115852693Sralph  * dcMapChar --
115952693Sralph  *
116052693Sralph  *	Map characters from the keyboard to ASCII. Return -1 if there is
116152693Sralph  *	no valid mapping.
116252693Sralph  *
116352693Sralph  * Results:
116452693Sralph  *	None.
116552693Sralph  *
116652693Sralph  * Side effects:
116752693Sralph  *	Remember state of shift and control keys.
116852693Sralph  *
116952693Sralph  * ----------------------------------------------------------------------------
117052693Sralph  */
117152693Sralph static int
117252693Sralph dcMapChar(cc)
117352693Sralph 	int cc;
117452693Sralph {
117552693Sralph 	static u_char shiftDown;
117652693Sralph 	static u_char ctrlDown;
117752693Sralph 	static u_char lastChar;
117852693Sralph 
117952693Sralph 	switch (cc) {
118052693Sralph 	case KEY_REPEAT:
118152693Sralph 		cc = lastChar;
118252693Sralph 		goto done;
118352693Sralph 
118452693Sralph 	case KEY_UP:
118552693Sralph 		shiftDown = 0;
118652693Sralph 		ctrlDown = 0;
118752693Sralph 		return (-1);
118852693Sralph 
118952693Sralph 	case KEY_SHIFT:
119052693Sralph 		if (ctrlDown)
119152693Sralph 			shiftDown = 0;
119252693Sralph 		else
119352693Sralph 			shiftDown = 1;
119452693Sralph 		return (-1);
119552693Sralph 
119652693Sralph 	case KEY_CONTROL:
119752693Sralph 		if (shiftDown)
119852693Sralph 			ctrlDown = 0;
119952693Sralph 		else
120052693Sralph 			ctrlDown = 1;
120152693Sralph 		return (-1);
120252693Sralph 
120352693Sralph 	case LK_POWER_ERROR:
120452693Sralph 	case LK_KDOWN_ERROR:
120552693Sralph 	case LK_INPUT_ERROR:
120652693Sralph 	case LK_OUTPUT_ERROR:
120752693Sralph 		log(LOG_WARNING,
120852693Sralph 			"dc0,0: keyboard error, code=%x\n", cc);
120952693Sralph 		return (-1);
121052693Sralph 	}
121152693Sralph 	if (shiftDown)
121252693Sralph 		cc = shiftedAscii[cc];
121352693Sralph 	else
121452693Sralph 		cc = unshiftedAscii[cc];
121552693Sralph 	if (cc >= KBD_NOKEY) {
121652693Sralph 		/*
121752693Sralph 		 * A function key was typed - ignore it.
121852693Sralph 		 */
121952693Sralph 		return (-1);
122052693Sralph 	}
122152693Sralph 	if (cc >= 'a' && cc <= 'z') {
122252693Sralph 		if (ctrlDown)
122352693Sralph 			cc = cc - 'a' + '\1'; /* ^A */
122452693Sralph 		else if (shiftDown)
122552693Sralph 			cc = cc - 'a' + 'A';
122652693Sralph 	} else if (ctrlDown) {
122752693Sralph 		if (cc >= '[' && cc <= '_')
122852693Sralph 			cc = cc - '@';
122952693Sralph 		else if (cc == ' ' || cc == '@')
123052693Sralph 			cc = '\0';
123152693Sralph 	}
123252693Sralph 	lastChar = cc;
123352693Sralph done:
123452693Sralph 	return (cc);
123552693Sralph }
123652693Sralph 
123752693Sralph /*
123852693Sralph  * ----------------------------------------------------------------------------
123952693Sralph  *
124052130Smckusick  * dcKBDReset --
124152130Smckusick  *
124252130Smckusick  *	Reset the keyboard to default characteristics.
124352130Smckusick  *
124452130Smckusick  * Results:
124552130Smckusick  *	None.
124652130Smckusick  *
124752130Smckusick  * Side effects:
124852130Smckusick  *	None.
124952130Smckusick  *
125052130Smckusick  * ----------------------------------------------------------------------------
125152130Smckusick  */
125252130Smckusick void
125352130Smckusick dcKBDReset()
125452130Smckusick {
125552130Smckusick 	register int i;
125652130Smckusick 	static int inKBDReset;
125752130Smckusick 
125852130Smckusick 	if (inKBDReset)
125952130Smckusick 		return;
126052130Smckusick 	inKBDReset = 1;
126152130Smckusick 	for (i = 0; i < sizeof(kbdInitString); i++)
126252130Smckusick 		dcKBDPutc((int)kbdInitString[i]);
126352130Smckusick 	inKBDReset = 0;
126452130Smckusick }
126552130Smckusick 
126652130Smckusick /*
126752130Smckusick  * ----------------------------------------------------------------------------
126852130Smckusick  *
126952130Smckusick  * MousePutc --
127052130Smckusick  *
127152130Smckusick  *	Write a character to the mouse.
127252130Smckusick  *	This is only called at initialization time.
127352130Smckusick  *
127452130Smckusick  * Results:
127552130Smckusick  *	None.
127652130Smckusick  *
127752130Smckusick  * Side effects:
127852130Smckusick  *	A character is written to the mouse.
127952130Smckusick  *
128052130Smckusick  * ----------------------------------------------------------------------------
128152130Smckusick  */
128252130Smckusick static void
128352130Smckusick MousePutc(c)
128452130Smckusick 	int c;
128552130Smckusick {
128652130Smckusick 	register dcregs *dcaddr;
128752130Smckusick 	register u_short tcr;
128852130Smckusick 	register int timeout;
128952130Smckusick 	int line;
129052130Smckusick 
129152130Smckusick 	dcaddr = dcpdma[MOUSE_PORT].p_addr;
129252130Smckusick 	tcr = dcaddr->dc_tcr;
129352130Smckusick 	dcaddr->dc_tcr = tcr | (1 << MOUSE_PORT);
129452130Smckusick 	MachEmptyWriteBuffer();
129552130Smckusick 	DELAY(10);
129652130Smckusick 	while (1) {
129752130Smckusick 		/*
129852130Smckusick 		 * Wait for transmitter to be not busy.
129952130Smckusick 		 */
130052130Smckusick 		timeout = 1000000;
130152130Smckusick 		while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
130252130Smckusick 			timeout--;
130352130Smckusick 		if (timeout == 0) {
130452130Smckusick 			printf("MousePutc: timeout waiting for CSR_TRDY\n");
130552130Smckusick 			break;
130652130Smckusick 		}
130752130Smckusick 		line = (dcaddr->dc_csr >> 8) & 3;
130852130Smckusick 		/*
130952130Smckusick 		 * Check to be sure its the right port.
131052130Smckusick 		 */
131152130Smckusick 		if (line != MOUSE_PORT) {
131252130Smckusick 			tcr |= 1 << line;
131352130Smckusick 			dcaddr->dc_tcr &= ~(1 << line);
131452130Smckusick 			MachEmptyWriteBuffer();
131552130Smckusick 			DELAY(10);
131652130Smckusick 			continue;
131752130Smckusick 		}
131852130Smckusick 		/*
131952130Smckusick 		 * Start sending the character.
132052130Smckusick 		 */
132152130Smckusick 		dcaddr->dc_tdr = dc_brk[0] | (c & 0xff);
132252130Smckusick 		MachEmptyWriteBuffer();
132352130Smckusick 		DELAY(10);
132452130Smckusick 		/*
132552130Smckusick 		 * Wait for character to be sent.
132652130Smckusick 		 */
132752130Smckusick 		while (1) {
132852130Smckusick 			/*
132952130Smckusick 			 * cc -O bug: this code produces and infinite loop!
133052130Smckusick 			 * while (!(dcaddr->dc_csr & CSR_TRDY))
133152130Smckusick 			 *	;
133252130Smckusick 			 */
133352130Smckusick 			timeout = 1000000;
133452130Smckusick 			while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0)
133552130Smckusick 				timeout--;
133652130Smckusick 			line = (dcaddr->dc_csr >> 8) & 3;
133752130Smckusick 			if (line != MOUSE_PORT) {
133852130Smckusick 				tcr |= 1 << line;
133952130Smckusick 				dcaddr->dc_tcr &= ~(1 << line);
134052130Smckusick 				MachEmptyWriteBuffer();
134152130Smckusick 				DELAY(10);
134252130Smckusick 				continue;
134352130Smckusick 			}
134452130Smckusick 			dcaddr->dc_tcr &= ~(1 << MOUSE_PORT);
134552130Smckusick 			MachEmptyWriteBuffer();
134652130Smckusick 			DELAY(10);
134752130Smckusick 			break;
134852130Smckusick 		}
134952130Smckusick 		break;
135052130Smckusick 	}
135152130Smckusick 	/*
135252130Smckusick 	 * Enable interrupts for other lines which became ready.
135352130Smckusick 	 */
135452130Smckusick 	if (tcr & 0xF) {
135552130Smckusick 		dcaddr->dc_tcr = tcr;
135652130Smckusick 		MachEmptyWriteBuffer();
135752130Smckusick 		DELAY(10);
135852130Smckusick 	}
135952130Smckusick }
136052130Smckusick 
136152130Smckusick /*
136252130Smckusick  * ----------------------------------------------------------------------------
136352130Smckusick  *
136452130Smckusick  * MouseGetc --
136552130Smckusick  *
136652130Smckusick  *	Read a character from the mouse.
136752130Smckusick  *	This is only called at initialization time.
136852130Smckusick  *
136952130Smckusick  * Results:
137052130Smckusick  *	A character read from the mouse, -1 if we timed out waiting.
137152130Smckusick  *
137252130Smckusick  * Side effects:
137352130Smckusick  *	None.
137452130Smckusick  *
137552130Smckusick  * ----------------------------------------------------------------------------
137652130Smckusick  */
137752130Smckusick static int
137852130Smckusick MouseGetc()
137952130Smckusick {
138052130Smckusick 	register dcregs *dcaddr;
138152130Smckusick 	register int timeout;
138252130Smckusick 	register int c;
138352130Smckusick 
138452130Smckusick 	dcaddr = dcpdma[MOUSE_PORT].p_addr;
138552130Smckusick 	for (timeout = 1000000; timeout > 0; timeout--) {
138652130Smckusick 		if (!(dcaddr->dc_csr & CSR_RDONE))
138752130Smckusick 			continue;
138852130Smckusick 		c = dcaddr->dc_rbuf;
138952130Smckusick 		DELAY(10);
139052130Smckusick 		if (((c >> 8) & 03) != MOUSE_PORT)
139152130Smckusick 			continue;
139252130Smckusick 		return (c & 0xff);
139352130Smckusick 	}
139452130Smckusick 
139552130Smckusick 	return (-1);
139652130Smckusick }
139752130Smckusick 
139852130Smckusick /*
139952130Smckusick  * ----------------------------------------------------------------------------
140052130Smckusick  *
140152130Smckusick  * MouseInit --
140252130Smckusick  *
140352130Smckusick  *	Initialize the mouse.
140452130Smckusick  *
140552130Smckusick  * Results:
140652130Smckusick  *	None.
140752130Smckusick  *
140852130Smckusick  * Side effects:
140952130Smckusick  *	None.
141052130Smckusick  *
141152130Smckusick  * ----------------------------------------------------------------------------
141252130Smckusick  */
141352130Smckusick static void
141452130Smckusick MouseInit()
141552130Smckusick {
141652130Smckusick 	int id_byte1, id_byte2, id_byte3, id_byte4;
141752130Smckusick 
141852130Smckusick 	/*
141952130Smckusick 	 * Initialize the mouse.
142052130Smckusick 	 */
142152130Smckusick 	MousePutc(MOUSE_SELF_TEST);
142252130Smckusick 	id_byte1 = MouseGetc();
142352130Smckusick 	if (id_byte1 < 0) {
142452130Smckusick 		printf("MouseInit: Timeout on 1st byte of self-test report\n");
142552130Smckusick 		return;
142652130Smckusick 	}
142752130Smckusick 	id_byte2 = MouseGetc();
142852130Smckusick 	if (id_byte2 < 0) {
142952130Smckusick 		printf("MouseInit: Timeout on 2nd byte of self-test report\n");
143052130Smckusick 		return;
143152130Smckusick 	}
143252130Smckusick 	id_byte3 = MouseGetc();
143352130Smckusick 	if (id_byte3 < 0) {
143452130Smckusick 		printf("MouseInit: Timeout on 3rd byte of self-test report\n");
143552130Smckusick 		return;
143652130Smckusick 	}
143752130Smckusick 	id_byte4 = MouseGetc();
143852130Smckusick 	if (id_byte4 < 0) {
143952130Smckusick 		printf("MouseInit: Timeout on 4th byte of self-test report\n");
144052130Smckusick 		return;
144152130Smckusick 	}
144252130Smckusick 	if ((id_byte2 & 0x0f) != 0x2)
144352130Smckusick 		printf("MouseInit: We don't have a mouse!!!\n");
144452130Smckusick 	/*
144552130Smckusick 	 * For some reason, the mouse doesn't see this command if it comes
144652130Smckusick 	 * too soon after a self test.
144752130Smckusick 	 */
144852130Smckusick 	DELAY(100);
144952130Smckusick 	MousePutc(MOUSE_INCREMENTAL);
145052130Smckusick }
145152130Smckusick #endif /* NDC */
1452