xref: /original-bsd/sys/pmax/dev/fb.c (revision 3b43aa51)
1 /*-
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell and Rick Macklem.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)fb.c	7.2 (Berkeley) 12/20/92
11  */
12 
13 /*
14  *  devGraphics.c --
15  *
16  *     	This file contains machine-dependent routines for the graphics device.
17  *
18  *	Copyright (C) 1989 Digital Equipment Corporation.
19  *	Permission to use, copy, modify, and distribute this software and
20  *	its documentation for any purpose and without fee is hereby granted,
21  *	provided that the above copyright notice appears in all copies.
22  *	Digital Equipment Corporation makes no representations about the
23  *	suitability of this software for any purpose.  It is provided "as is"
24  *	without express or implied warranty.
25  *
26  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
27  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
28  */
29 
30 /*
31  * This file has all the routines common to the various frame buffer drivers
32  * including a generic ioctl routine. The pmax_fb structure is passed into the
33  * routines and has device specifics stored in it.
34  * The LK201 keycode mapping routine is also here along with initialization
35  * functions for the keyboard and mouse.
36  */
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/ioctl.h>
41 #include <sys/tty.h>
42 #include <sys/time.h>
43 #include <sys/kernel.h>
44 #include <sys/ioctl.h>
45 #include <sys/file.h>
46 #include <sys/errno.h>
47 #include <sys/proc.h>
48 #include <sys/mman.h>
49 #include <sys/syslog.h>
50 
51 #include <vm/vm.h>
52 
53 #include <machine/machConst.h>
54 #include <machine/pmioctl.h>
55 
56 #include <pmax/dev/device.h>
57 #include <pmax/dev/font.c>
58 #include <pmax/dev/fbreg.h>
59 
60 #include <pmax/stand/dec_prom.h>
61 
62 #include <pmax/pmax/cons.h>
63 #include <pmax/pmax/pmaxtype.h>
64 
65 #include <dc.h>
66 #include <scc.h>
67 #include <dtop.h>
68 
69 void fbKbdEvent(), fbMouseEvent(), fbMouseButtons(), fbScroll();
70 void fbBlitc(), fbPutc();
71 extern int pmax_boardtype;
72 extern struct consdev cn_tab;
73 #if NDC > 0
74 #include <machine/dc7085cons.h>
75 extern int dcGetc(), dcparam();
76 extern void dcPutc();
77 #endif
78 #if NDTOP > 0
79 #include <pmax/dev/dtopreg.h>
80 extern void dtopKBDPutc();
81 #endif
82 #if NSCC > 0
83 #include <pmax/dev/sccreg.h>
84 extern int sccGetc(), sccparam();
85 extern void sccPutc();
86 #endif
87 
88 /*
89  * The default cursor.
90  */
91 u_short defCursor[32] = {
92 /* plane A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
93 	      0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
94 /* plane B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
95               0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
96 
97 };
98 
99 /*
100  * Font mask bits used by fbBlitc().
101  */
102 static unsigned int fontmaskBits[16] = {
103 	0x00000000,
104 	0x00000001,
105 	0x00000100,
106 	0x00000101,
107 	0x00010000,
108 	0x00010001,
109 	0x00010100,
110 	0x00010101,
111 	0x01000000,
112 	0x01000001,
113 	0x01000100,
114 	0x01000101,
115 	0x01010000,
116 	0x01010001,
117 	0x01010100,
118 	0x01010101
119 };
120 
121 /*
122  * Ascii values of command keys.
123  */
124 #define KBD_TAB		'\t'
125 #define KBD_DEL		127
126 #define KBD_RET		'\r'
127 
128 /*
129  *  Define "hardware-independent" codes for the control, shift, meta and
130  *  function keys.  Codes start after the last 7-bit ASCII code (127)
131  *  and are assigned in an arbitrary order.
132  */
133 #define KBD_NOKEY	128
134 
135 #define KBD_F1		201
136 #define KBD_F2		202
137 #define KBD_F3		203
138 #define KBD_F4		204
139 #define KBD_F5		205
140 #define KBD_F6		206
141 #define KBD_F7		207
142 #define KBD_F8		208
143 #define KBD_F9		209
144 #define KBD_F10		210
145 #define KBD_F11		211
146 #define KBD_F12		212
147 #define KBD_F13		213
148 #define KBD_F14		214
149 #define KBD_HELP	215
150 #define KBD_DO		216
151 #define KBD_F17		217
152 #define KBD_F18		218
153 #define KBD_F19		219
154 #define KBD_F20		220
155 
156 #define KBD_FIND	221
157 #define KBD_INSERT	222
158 #define KBD_REMOVE	223
159 #define KBD_SELECT	224
160 #define KBD_PREVIOUS	225
161 #define KBD_NEXT	226
162 
163 #define KBD_KP_ENTER	227
164 #define KBD_KP_F1	228
165 #define KBD_KP_F2	229
166 #define KBD_KP_F3	230
167 #define KBD_KP_F4	231
168 #define KBD_LEFT	232
169 #define KBD_RIGHT	233
170 #define KBD_DOWN	234
171 #define KBD_UP		235
172 
173 #define KBD_CONTROL	236
174 #define KBD_SHIFT	237
175 #define KBD_CAPSLOCK	238
176 #define KBD_ALTERNATE	239
177 
178 /*
179  * Keyboard to Ascii, unshifted.
180  */
181 static unsigned char unshiftedAscii[] = {
182 /*  0 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
183 /*  4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
184 /*  8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
185 /*  c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
186 /* 10 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
187 /* 14 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
188 /* 18 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
189 /* 1c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
190 /* 20 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
191 /* 24 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
192 /* 28 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
193 /* 2c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
194 /* 30 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
195 /* 34 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
196 /* 38 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
197 /* 3c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
198 /* 40 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
199 /* 44 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
200 /* 48 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
201 /* 4c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
202 /* 50 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
203 /* 54 */ KBD_NOKEY,	KBD_NOKEY,	KBD_F1,		KBD_F2,
204 /* 58 */ KBD_F3,	KBD_F4,		KBD_F5,		KBD_NOKEY,
205 /* 5c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
206 /* 60 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
207 /* 64 */ KBD_F6,	KBD_F7,		KBD_F8,		KBD_F9,
208 /* 68 */ KBD_F10,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
209 /* 6c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
210 /* 70 */ KBD_NOKEY,	'\033',		KBD_F12,	KBD_F13,
211 /* 74 */ KBD_F14,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
212 /* 78 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
213 /* 7c */ KBD_HELP,	KBD_DO,		KBD_NOKEY,	KBD_NOKEY,
214 /* 80 */ KBD_F17,	KBD_F18,	KBD_F19,	KBD_F20,
215 /* 84 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
216 /* 88 */ KBD_NOKEY,	KBD_NOKEY,	KBD_FIND,	KBD_INSERT,
217 /* 8c */ KBD_REMOVE,	KBD_SELECT,	KBD_PREVIOUS,	KBD_NEXT,
218 /* 90 */ KBD_NOKEY,	KBD_NOKEY,	'0',		KBD_NOKEY,
219 /* 94 */ '.',		KBD_KP_ENTER,	'1',		'2',
220 /* 98 */ '3',		'4',		'5',		'6',
221 /* 9c */ ',',		'7',		'8',		'9',
222 /* a0 */ '-',		KBD_KP_F1,	KBD_KP_F2,	KBD_KP_F3,
223 /* a4 */ KBD_KP_F4,	KBD_NOKEY,	KBD_NOKEY,	KBD_LEFT,
224 /* a8 */ KBD_RIGHT,	KBD_DOWN, 	KBD_UP,		KBD_NOKEY,
225 /* ac */ KBD_NOKEY,	KBD_NOKEY,	KBD_SHIFT,	KBD_CONTROL,
226 /* b0 */ KBD_CAPSLOCK,	KBD_ALTERNATE,	KBD_NOKEY,	KBD_NOKEY,
227 /* b4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
228 /* b8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
229 /* bc */ KBD_DEL,	KBD_RET,	KBD_TAB,	'`',
230 /* c0 */ '1',		'q',		'a',		'z',
231 /* c4 */ KBD_NOKEY,	'2',		'w',		's',
232 /* c8 */ 'x',		'<',		KBD_NOKEY,	'3',
233 /* cc */ 'e',		'd',		'c',		KBD_NOKEY,
234 /* d0 */ '4',		'r',		'f',		'v',
235 /* d4 */ ' ',		KBD_NOKEY,	'5',		't',
236 /* d8 */ 'g',		'b',		KBD_NOKEY,	'6',
237 /* dc */ 'y',		'h',		'n',		KBD_NOKEY,
238 /* e0 */ '7',		'u',		'j',		'm',
239 /* e4 */ KBD_NOKEY,	'8',		'i',		'k',
240 /* e8 */ ',',		KBD_NOKEY,	'9',		'o',
241 /* ec */ 'l',		'.',		KBD_NOKEY,	'0',
242 /* f0 */ 'p',		KBD_NOKEY,	';',		'/',
243 /* f4 */ KBD_NOKEY,	'=',		']',		'\\',
244 /* f8 */ KBD_NOKEY,	'-',		'[',		'\'',
245 /* fc */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
246 };
247 
248 /*
249  * Keyboard to Ascii, shifted.
250  */
251 static unsigned char shiftedAscii[] = {
252 /*  0 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
253 /*  4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
254 /*  8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
255 /*  c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
256 /* 10 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
257 /* 14 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
258 /* 18 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
259 /* 1c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
260 /* 20 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
261 /* 24 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
262 /* 28 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
263 /* 2c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
264 /* 30 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
265 /* 34 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
266 /* 38 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
267 /* 3c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
268 /* 40 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
269 /* 44 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
270 /* 48 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
271 /* 4c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
272 /* 50 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
273 /* 54 */ KBD_NOKEY,	KBD_NOKEY,	KBD_F1,		KBD_F2,
274 /* 58 */ KBD_F3,	KBD_F4,		KBD_F5,		KBD_NOKEY,
275 /* 5c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
276 /* 60 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
277 /* 64 */ KBD_F6,	KBD_F7,		KBD_F8,		KBD_F9,
278 /* 68 */ KBD_F10,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
279 /* 6c */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
280 /* 70 */ KBD_NOKEY,	KBD_F11,	KBD_F12,	KBD_F13,
281 /* 74 */ KBD_F14,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
282 /* 78 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
283 /* 7c */ KBD_HELP,	KBD_DO,		KBD_NOKEY,	KBD_NOKEY,
284 /* 80 */ KBD_F17,	KBD_F18,	KBD_F19,	KBD_F20,
285 /* 84 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
286 /* 88 */ KBD_NOKEY,	KBD_NOKEY,	KBD_FIND,	KBD_INSERT,
287 /* 8c */ KBD_REMOVE,	KBD_SELECT,	KBD_PREVIOUS,	KBD_NEXT,
288 /* 90 */ KBD_NOKEY,	KBD_NOKEY,	'0',		KBD_NOKEY,
289 /* 94 */ '.',		KBD_KP_ENTER,	'1',		'2',
290 /* 98 */ '3',		'4',		'5',		'6',
291 /* 9c */ ',',		'7',		'8',		'9',
292 /* a0 */ '-',		KBD_KP_F1,	KBD_KP_F2,	KBD_KP_F3,
293 /* a4 */ KBD_KP_F4,	KBD_NOKEY,	KBD_NOKEY,	KBD_LEFT,
294 /* a8 */ KBD_RIGHT,	KBD_DOWN, 	KBD_UP,		KBD_NOKEY,
295 /* ac */ KBD_NOKEY,	KBD_NOKEY,	KBD_SHIFT,	KBD_CONTROL,
296 /* b0 */ KBD_CAPSLOCK,	KBD_ALTERNATE,	KBD_NOKEY,	KBD_NOKEY,
297 /* b4 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
298 /* b8 */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
299 /* bc */ KBD_DEL,	KBD_RET,	KBD_TAB,	'~',
300 /* c0 */ '!',		'q',		'a',		'z',
301 /* c4 */ KBD_NOKEY,	'@',		'w',		's',
302 /* c8 */ 'x',		'>',		KBD_NOKEY,	'#',
303 /* cc */ 'e',		'd',		'c',		KBD_NOKEY,
304 /* d0 */ '$',		'r',		'f',		'v',
305 /* d4 */ ' ',		KBD_NOKEY,	'%',		't',
306 /* d8 */ 'g',		'b',		KBD_NOKEY,	'^',
307 /* dc */ 'y',		'h',		'n',		KBD_NOKEY,
308 /* e0 */ '&',		'u',		'j',		'm',
309 /* e4 */ KBD_NOKEY,	'*',		'i',		'k',
310 /* e8 */ '<',		KBD_NOKEY,	'(',		'o',
311 /* ec */ 'l',		'>',		KBD_NOKEY,	')',
312 /* f0 */ 'p',		KBD_NOKEY,	':',		'?',
313 /* f4 */ KBD_NOKEY,	'+',		'}',		'|',
314 /* f8 */ KBD_NOKEY,	'_',		'{',		'"',
315 /* fc */ KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,	KBD_NOKEY,
316 };
317 
318 /*
319  * Keyboard initialization string.
320  */
321 static u_char kbdInitString[] = {
322 	LK_LED_ENABLE, LED_ALL,		/* show we are resetting keyboard */
323 	LK_DEFAULTS,
324 	LK_CMD_MODE(LK_AUTODOWN, 1),
325 	LK_CMD_MODE(LK_AUTODOWN, 2),
326 	LK_CMD_MODE(LK_AUTODOWN, 3),
327 	LK_CMD_MODE(LK_DOWN, 4),	/* could also be LK_AUTODOWN */
328 	LK_CMD_MODE(LK_UPDOWN, 5),
329 	LK_CMD_MODE(LK_UPDOWN, 6),
330 	LK_CMD_MODE(LK_AUTODOWN, 7),
331 	LK_CMD_MODE(LK_AUTODOWN, 8),
332 	LK_CMD_MODE(LK_AUTODOWN, 9),
333 	LK_CMD_MODE(LK_AUTODOWN, 10),
334 	LK_CMD_MODE(LK_AUTODOWN, 11),
335 	LK_CMD_MODE(LK_AUTODOWN, 12),
336 	LK_CMD_MODE(LK_DOWN, 13),
337 	LK_CMD_MODE(LK_AUTODOWN, 14),
338 	LK_AR_ENABLE,			/* we want autorepeat by default */
339 	LK_CL_ENABLE, 0x83,		/* keyclick, volume */
340 	LK_KBD_ENABLE,			/* the keyboard itself */
341 	LK_BELL_ENABLE, 0x83,		/* keyboard bell, volume */
342 	LK_LED_DISABLE, LED_ALL,	/* clear keyboard leds */
343 };
344 
345 /*
346  *----------------------------------------------------------------------
347  *
348  * fbKbdEvent --
349  *
350  *	Process a received character.
351  *
352  * Results:
353  *	None.
354  *
355  * Side effects:
356  *	Events added to the queue.
357  *
358  *----------------------------------------------------------------------
359  */
360 void
361 fbKbdEvent(ch, fp)
362 	int ch;
363 	register struct pmax_fb *fp;
364 {
365 	register pmEvent *eventPtr;
366 	int i;
367 
368 	if (!fp->GraphicsOpen)
369 		return;
370 
371 	/*
372 	 * See if there is room in the queue.
373 	 */
374 	i = PM_EVROUND(fp->fbu->scrInfo.qe.eTail + 1);
375 	if (i == fp->fbu->scrInfo.qe.eHead)
376 		return;
377 
378 	/*
379 	 * Add the event to the queue.
380 	 */
381 	eventPtr = &fp->fbu->events[fp->fbu->scrInfo.qe.eTail];
382 	eventPtr->type = BUTTON_RAW_TYPE;
383 	eventPtr->device = KEYBOARD_DEVICE;
384 	eventPtr->x = fp->fbu->scrInfo.mouse.x;
385 	eventPtr->y = fp->fbu->scrInfo.mouse.y;
386 	eventPtr->time = TO_MS(time);
387 	eventPtr->key = ch;
388 	fp->fbu->scrInfo.qe.eTail = i;
389 	selwakeup(&fp->selp);
390 }
391 
392 /*
393  *----------------------------------------------------------------------
394  *
395  * fbMouseEvent --
396  *
397  *	Process a mouse event.
398  *
399  * Results:
400  *	None.
401  *
402  * Side effects:
403  *	An event is added to the event queue.
404  *
405  *----------------------------------------------------------------------
406  */
407 void
408 fbMouseEvent(newRepPtr, fp)
409 	register MouseReport *newRepPtr;
410 	register struct pmax_fb *fp;
411 {
412 	unsigned milliSec;
413 	int i;
414 	pmEvent *eventPtr;
415 
416 	if (!fp->GraphicsOpen)
417 		return;
418 
419 	milliSec = TO_MS(time);
420 
421 	/*
422 	 * Check to see if we have to accelerate the mouse
423 	 */
424 	if (fp->fbu->scrInfo.mscale >= 0) {
425 		if (newRepPtr->dx >= fp->fbu->scrInfo.mthreshold) {
426 			newRepPtr->dx +=
427 				(newRepPtr->dx - fp->fbu->scrInfo.mthreshold) *
428 				fp->fbu->scrInfo.mscale;
429 		}
430 		if (newRepPtr->dy >= fp->fbu->scrInfo.mthreshold) {
431 			newRepPtr->dy +=
432 				(newRepPtr->dy - fp->fbu->scrInfo.mthreshold) *
433 				fp->fbu->scrInfo.mscale;
434 		}
435 	}
436 
437 	/*
438 	 * Update mouse position
439 	 */
440 	if (newRepPtr->state & MOUSE_X_SIGN) {
441 		fp->fbu->scrInfo.mouse.x += newRepPtr->dx;
442 		if (fp->fbu->scrInfo.mouse.x > fp->fbu->scrInfo.max_cur_x)
443 			fp->fbu->scrInfo.mouse.x = fp->fbu->scrInfo.max_cur_x;
444 	} else {
445 		fp->fbu->scrInfo.mouse.x -= newRepPtr->dx;
446 		if (fp->fbu->scrInfo.mouse.x < fp->fbu->scrInfo.min_cur_x)
447 			fp->fbu->scrInfo.mouse.x = fp->fbu->scrInfo.min_cur_x;
448 	}
449 	if (newRepPtr->state & MOUSE_Y_SIGN) {
450 		fp->fbu->scrInfo.mouse.y -= newRepPtr->dy;
451 		if (fp->fbu->scrInfo.mouse.y < fp->fbu->scrInfo.min_cur_y)
452 			fp->fbu->scrInfo.mouse.y = fp->fbu->scrInfo.min_cur_y;
453 	} else {
454 		fp->fbu->scrInfo.mouse.y += newRepPtr->dy;
455 		if (fp->fbu->scrInfo.mouse.y > fp->fbu->scrInfo.max_cur_y)
456 			fp->fbu->scrInfo.mouse.y = fp->fbu->scrInfo.max_cur_y;
457 	}
458 
459 	/*
460 	 * Move the hardware cursor.
461 	 */
462 	(*fp->posCursor)(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
463 
464 	/*
465 	 * Store the motion event in the motion buffer.
466 	 */
467 	fp->fbu->tcs[fp->fbu->scrInfo.qe.tcNext].time = milliSec;
468 	fp->fbu->tcs[fp->fbu->scrInfo.qe.tcNext].x = fp->fbu->scrInfo.mouse.x;
469 	fp->fbu->tcs[fp->fbu->scrInfo.qe.tcNext].y = fp->fbu->scrInfo.mouse.y;
470 	if (++fp->fbu->scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE)
471 		fp->fbu->scrInfo.qe.tcNext = 0;
472 	if (fp->fbu->scrInfo.mouse.y < fp->fbu->scrInfo.mbox.bottom &&
473 	    fp->fbu->scrInfo.mouse.y >=  fp->fbu->scrInfo.mbox.top &&
474 	    fp->fbu->scrInfo.mouse.x < fp->fbu->scrInfo.mbox.right &&
475 	    fp->fbu->scrInfo.mouse.x >=  fp->fbu->scrInfo.mbox.left)
476 		return;
477 
478 	fp->fbu->scrInfo.mbox.bottom = 0;
479 	if (PM_EVROUND(fp->fbu->scrInfo.qe.eTail + 1) == fp->fbu->scrInfo.qe.eHead)
480 		return;
481 
482 	i = PM_EVROUND(fp->fbu->scrInfo.qe.eTail - 1);
483 	if ((fp->fbu->scrInfo.qe.eTail != fp->fbu->scrInfo.qe.eHead) &&
484 	    (i != fp->fbu->scrInfo.qe.eHead)) {
485 		pmEvent *eventPtr;
486 
487 		eventPtr = &fp->fbu->events[i];
488 		if (eventPtr->type == MOTION_TYPE) {
489 			eventPtr->x = fp->fbu->scrInfo.mouse.x;
490 			eventPtr->y = fp->fbu->scrInfo.mouse.y;
491 			eventPtr->time = milliSec;
492 			eventPtr->device = MOUSE_DEVICE;
493 			return;
494 		}
495 	}
496 	/*
497 	 * Put event into queue and wakeup any waiters.
498 	 */
499 	eventPtr = &fp->fbu->events[fp->fbu->scrInfo.qe.eTail];
500 	eventPtr->type = MOTION_TYPE;
501 	eventPtr->time = milliSec;
502 	eventPtr->x = fp->fbu->scrInfo.mouse.x;
503 	eventPtr->y = fp->fbu->scrInfo.mouse.y;
504 	eventPtr->device = MOUSE_DEVICE;
505 	fp->fbu->scrInfo.qe.eTail = PM_EVROUND(fp->fbu->scrInfo.qe.eTail + 1);
506 	selwakeup(&fp->selp);
507 }
508 
509 /*
510  *----------------------------------------------------------------------
511  *
512  * fbMouseButtons --
513  *
514  *	Process mouse buttons.
515  *
516  * Results:
517  *	None.
518  *
519  * Side effects:
520  *	None.
521  *
522  *----------------------------------------------------------------------
523  */
524 void
525 fbMouseButtons(newRepPtr, fp)
526 	MouseReport *newRepPtr;
527 	register struct pmax_fb *fp;
528 {
529 	static char temp, oldSwitch, newSwitch;
530 	int i, j;
531 	pmEvent *eventPtr;
532 	static MouseReport lastRep;
533 
534 	if (!fp->GraphicsOpen)
535 		return;
536 
537 	newSwitch = newRepPtr->state & 0x07;
538 	oldSwitch = lastRep.state & 0x07;
539 
540 	temp = oldSwitch ^ newSwitch;
541 	if (temp == 0)
542 		return;
543 	for (j = 1; j < 8; j <<= 1) {
544 		if ((j & temp) == 0)
545 			continue;
546 
547 		/*
548 		 * Check for room in the queue
549 		 */
550 		i = PM_EVROUND(fp->fbu->scrInfo.qe.eTail+1);
551 		if (i == fp->fbu->scrInfo.qe.eHead)
552 			return;
553 
554 		/*
555 		 * Put event into queue.
556 		 */
557 		eventPtr = &fp->fbu->events[fp->fbu->scrInfo.qe.eTail];
558 
559 		switch (j) {
560 		case RIGHT_BUTTON:
561 			eventPtr->key = EVENT_RIGHT_BUTTON;
562 			break;
563 
564 		case MIDDLE_BUTTON:
565 			eventPtr->key = EVENT_MIDDLE_BUTTON;
566 			break;
567 
568 		case LEFT_BUTTON:
569 			eventPtr->key = EVENT_LEFT_BUTTON;
570 		}
571 		if (newSwitch & j)
572 			eventPtr->type = BUTTON_DOWN_TYPE;
573 		else
574 			eventPtr->type = BUTTON_UP_TYPE;
575 		eventPtr->device = MOUSE_DEVICE;
576 
577 		eventPtr->time = TO_MS(time);
578 		eventPtr->x = fp->fbu->scrInfo.mouse.x;
579 		eventPtr->y = fp->fbu->scrInfo.mouse.y;
580 		fp->fbu->scrInfo.qe.eTail = i;
581 	}
582 	selwakeup(&fp->selp);
583 
584 	lastRep = *newRepPtr;
585 	fp->fbu->scrInfo.mswitches = newSwitch;
586 }
587 
588 /*
589  *----------------------------------------------------------------------
590  *
591  * fbScroll --
592  *
593  *	Scroll the screen.
594  *
595  * Results:
596  *	None.
597  *
598  * Side effects:
599  *	None.
600  *
601  *----------------------------------------------------------------------
602  */
603 void
604 fbScroll(fp)
605 	register struct pmax_fb *fp;
606 {
607 	register int *dest, *src;
608 	register int *end;
609 	register int temp0, temp1, temp2, temp3;
610 	register int i, scanInc, lineCount;
611 	int line;
612 
613 	/*
614 	 * If the mouse is on we don't scroll so that the bit map remains sane.
615 	 */
616 	if (fp->GraphicsOpen) {
617 		fp->row = 0;
618 		return;
619 	}
620 
621 	/*
622 	 *  The following is an optimization to cause the scrolling
623 	 *  of text to be memory limited.  Basically the writebuffer is
624 	 *  4 words (32 bits ea.) long so to achieve maximum speed we
625 	 *  read and write in multiples of 4 words. We also limit the
626 	 *  size to be fp->fbu->scrInfo.max_col characters for more speed.
627 	 */
628 	if (fp->isMono) {
629 		lineCount = 5;
630 		line = 1920 * 2;
631 		scanInc = 44;
632 	} else {
633 		lineCount = 40;
634 		scanInc = 96;
635 		line = 1920 * 8;
636 	}
637 	src = (int *)(fp->fr_addr + line);
638 	dest = (int *)(fp->fr_addr);
639 	end = (int *)(fp->fr_addr + (60 * line) - line);
640 	do {
641 		i = 0;
642 		do {
643 			temp0 = src[0];
644 			temp1 = src[1];
645 			temp2 = src[2];
646 			temp3 = src[3];
647 			dest[0] = temp0;
648 			dest[1] = temp1;
649 			dest[2] = temp2;
650 			dest[3] = temp3;
651 			dest += 4;
652 			src += 4;
653 			i++;
654 		} while (i < lineCount);
655 		src += scanInc;
656 		dest += scanInc;
657 	} while (src < end);
658 
659 	/*
660 	 * Now zero out the last two lines
661 	 */
662 	bzero(fp->fr_addr + (fp->row * line), 3 * line);
663 }
664 
665 /*
666  *----------------------------------------------------------------------
667  *
668  * fbPutc --
669  *
670  *	Write a character to the console.
671  *
672  * Results:
673  *	None.
674  *
675  * Side effects:
676  *	None.
677  *
678  *----------------------------------------------------------------------
679  */
680 void
681 fbPutc(dev, c)
682 	dev_t dev;
683 	register int c;
684 {
685 	int s;
686 
687 	if (cn_tab.cn_fb) {
688 		static int recurse;
689 
690 		/*
691 		 * We need to prevent recursion in case a printf to the
692 		 * console happens at interrupt time but using splhigh()
693 		 * all the time locks out interrupts too much. We simply
694 		 * discard the character in this case and rely on the
695 		 * console log buffer to save the message.
696 		 */
697 		if (recurse)
698 			return;
699 		recurse = 1;
700 		fbBlitc(c, cn_tab.cn_fb);
701 		recurse = 0;
702 	} else {
703 		s = splhigh();
704 		(*callv->printf)("%c", c);
705 		splx(s);
706 	}
707 }
708 
709 /*
710  *----------------------------------------------------------------------
711  *
712  * fbBlitc --
713  *
714  *	Write a character to the screen.
715  *
716  * Results:
717  *	None.
718  *
719  * Side effects:
720  *	None.
721  *
722  *----------------------------------------------------------------------
723  */
724 void
725 fbBlitc(c, fp)
726 	register int c;
727 	register struct pmax_fb *fp;
728 {
729 	register char *bRow, *fRow;
730 	register int i;
731 	register int ote = fp->isMono ? 256 : 1024; /* offset to table entry */
732 	int colMult = fp->isMono ? 1 : 8;
733 
734 	c &= 0xff;
735 
736 	switch (c) {
737 	case '\t':
738 		for (i = 8 - (fp->col & 0x7); i > 0; i--)
739 			fbBlitc(' ', fp);
740 		break;
741 
742 	case '\r':
743 		fp->col = 0;
744 		break;
745 
746 	case '\b':
747 		fp->col--;
748 		if (fp->col < 0)
749 			fp->col = 0;
750 		break;
751 
752 	case '\n':
753 		if (fp->row + 1 >= fp->fbu->scrInfo.max_row)
754 			fbScroll(fp);
755 		else
756 			fp->row++;
757 		fp->col = 0;
758 		break;
759 
760 	case '\007':
761 		(*fp->KBDPutc)(fp->kbddev, LK_RING_BELL);
762 		break;
763 
764 	default:
765 		/*
766 		 * 0xA1 to 0xFD are the printable characters added with 8-bit
767 		 * support.
768 		 */
769 		if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD)
770 			break;
771 		/*
772 		 * If the next character will wrap around then
773 		 * increment fp->row counter or scroll screen.
774 		 */
775 		if (fp->col >= fp->fbu->scrInfo.max_col) {
776 			fp->col = 0;
777 			if (fp->row + 1 >= fp->fbu->scrInfo.max_row)
778 				fbScroll(fp);
779 			else
780 				fp->row++;
781 		}
782 		bRow = (char *)(fp->fr_addr +
783 			(fp->row * 15 & 0x3ff) * ote + fp->col * colMult);
784 		i = c - ' ';
785 		/*
786 		 * This is to skip the (32) 8-bit
787 		 * control chars, as well as DEL
788 		 * and 0xA0 which aren't printable
789 		 */
790 		if (c > '~')
791 			i -= 34;
792 		i *= 15;
793 		fRow = (char *)((int)pmFont + i);
794 
795 		/* inline expansion for speed */
796 		if (fp->isMono) {
797 			*bRow = *fRow++; bRow += ote;
798 			*bRow = *fRow++; bRow += ote;
799 			*bRow = *fRow++; bRow += ote;
800 			*bRow = *fRow++; bRow += ote;
801 			*bRow = *fRow++; bRow += ote;
802 			*bRow = *fRow++; bRow += ote;
803 			*bRow = *fRow++; bRow += ote;
804 			*bRow = *fRow++; bRow += ote;
805 			*bRow = *fRow++; bRow += ote;
806 			*bRow = *fRow++; bRow += ote;
807 			*bRow = *fRow++; bRow += ote;
808 			*bRow = *fRow++; bRow += ote;
809 			*bRow = *fRow++; bRow += ote;
810 			*bRow = *fRow++; bRow += ote;
811 			*bRow = *fRow++; bRow += ote;
812 		} else {
813 			register int j;
814 			register unsigned int *pInt;
815 
816 			pInt = (unsigned int *)bRow;
817 			for (j = 0; j < 15; j++) {
818 				/*
819 				 * fontmaskBits converts a nibble
820 				 * (4 bytes) to a long word
821 				 * containing 4 pixels corresponding
822 				 * to each bit in the nibble.  Thus
823 				 * we write two longwords for each
824 				 * byte in font.
825 				 *
826 				 * Remember the font is 8 bits wide
827 				 * and 15 bits high.
828 				 *
829 				 * We add 256 to the pointer to
830 				 * point to the pixel on the
831 				 * next scan line
832 				 * directly below the current
833 				 * pixel.
834 				 */
835 				pInt[0] = fontmaskBits[(*fRow) & 0xf];
836 				pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf];
837 				fRow++;
838 				pInt += 256;
839 			}
840 		}
841 		fp->col++; /* increment column counter */
842 	}
843 	if (!fp->GraphicsOpen)
844 		(*fp->posCursor)(fp->col * 8, fp->row * 15);
845 }
846 
847 /*
848  * ----------------------------------------------------------------------------
849  *
850  * kbdMapChar --
851  *
852  *	Map characters from the keyboard to ASCII. Return -1 if there is
853  *	no valid mapping.
854  *
855  * Results:
856  *	None.
857  *
858  * Side effects:
859  *	Remember state of shift and control keys.
860  *
861  * ----------------------------------------------------------------------------
862  */
863 kbdMapChar(cc)
864 	int cc;
865 {
866 	static u_char shiftDown;
867 	static u_char ctrlDown;
868 	static u_char lastChar;
869 
870 	switch (cc) {
871 	case KEY_REPEAT:
872 		cc = lastChar;
873 		goto done;
874 
875 	case KEY_UP:
876 		shiftDown = 0;
877 		ctrlDown = 0;
878 		return (-1);
879 
880 	case KEY_SHIFT:
881 	case KEY_R_SHIFT:
882 		if (ctrlDown || shiftDown)
883 			shiftDown = 0;
884 		else
885 			shiftDown = 1;
886 		return (-1);
887 
888 	case KEY_CONTROL:
889 		if (shiftDown || ctrlDown)
890 			ctrlDown = 0;
891 		else
892 			ctrlDown = 1;
893 		return (-1);
894 
895 	case LK_POWER_ERROR:
896 	case LK_KDOWN_ERROR:
897 	case LK_INPUT_ERROR:
898 	case LK_OUTPUT_ERROR:
899 		log(LOG_WARNING,
900 			"lk201: keyboard error, code=%x\n", cc);
901 		return (-1);
902 	}
903 	if (shiftDown)
904 		cc = shiftedAscii[cc];
905 	else
906 		cc = unshiftedAscii[cc];
907 	if (cc >= KBD_NOKEY) {
908 		/*
909 		 * A function key was typed - ignore it.
910 		 */
911 		return (-1);
912 	}
913 	if (cc >= 'a' && cc <= 'z') {
914 		if (ctrlDown)
915 			cc = cc - 'a' + '\1'; /* ^A */
916 		else if (shiftDown)
917 			cc = cc - 'a' + 'A';
918 	} else if (ctrlDown) {
919 		if (cc >= '[' && cc <= '_')
920 			cc = cc - '@';
921 		else if (cc == ' ' || cc == '@')
922 			cc = '\0';
923 	}
924 	lastChar = cc;
925 done:
926 	return (cc);
927 }
928 
929 /*
930  * Initialize the Keyboard.
931  */
932 void
933 KBDReset(kbddev, putc)
934 	dev_t kbddev;
935 	void (*putc)();
936 {
937 	register int i;
938 	static int inKBDReset;
939 
940 	if (inKBDReset)
941 		return;
942 	inKBDReset = 1;
943 	for (i = 0; i < sizeof(kbdInitString); i++)
944 		(*putc)(kbddev, (int)kbdInitString[i]);
945 	inKBDReset = 0;
946 }
947 
948 /*
949  * Initialize the mouse.
950  */
951 void
952 MouseInit(mdev, putc, getc)
953 	dev_t mdev;
954 	void (*putc)();
955 	int (*getc)();
956 {
957 	int id_byte1, id_byte2, id_byte3, id_byte4;
958 
959 	/*
960 	 * Initialize the mouse.
961 	 */
962 	(*putc)(mdev, MOUSE_SELF_TEST);
963 	id_byte1 = (*getc)(mdev);
964 	if (id_byte1 < 0) {
965 		printf("MouseInit: Timeout on 1st byte of self-test report\n");
966 		return;
967 	}
968 	id_byte2 = (*getc)(mdev);
969 	if (id_byte2 < 0) {
970 		printf("MouseInit: Timeout on 2nd byte of self-test report\n");
971 		return;
972 	}
973 	id_byte3 = (*getc)(mdev);
974 	if (id_byte3 < 0) {
975 		printf("MouseInit: Timeout on 3rd byte of self-test report\n");
976 		return;
977 	}
978 	id_byte4 = (*getc)(mdev);
979 	if (id_byte4 < 0) {
980 		printf("MouseInit: Timeout on 4th byte of self-test report\n");
981 		return;
982 	}
983 	if ((id_byte2 & 0x0f) != 0x2)
984 		printf("MouseInit: We don't have a mouse!!!\n");
985 	/*
986 	 * For some reason, the mouse doesn't see this command if it comes
987 	 * too soon after a self test.
988 	 */
989 	DELAY(100);
990 	(*putc)(mdev, MOUSE_INCREMENTAL);
991 }
992 
993 /*
994  * Get a character off of the keyboard.
995  */
996 int
997 KBDGetc()
998 {
999 	register int c;
1000 
1001 	for (;;) {
1002 		c = (*cn_tab.cn_kbdgetc)(cn_tab.cn_dev);
1003 		if (c == 0)
1004 			return (-1);
1005 		if ((c = kbdMapChar(c & 0xff)) >= 0)
1006 			break;
1007 	}
1008 	return (c);
1009 }
1010 
1011 /*
1012  * Configure the keyboard/mouse based on machine type for turbochannel
1013  * display boards.
1014  */
1015 tb_kbdmouseconfig(fp)
1016 	struct pmax_fb *fp;
1017 {
1018 
1019 	switch (pmax_boardtype) {
1020 #if NDC > 0
1021 	case DS_3MAX:
1022 		fp->KBDPutc = dcPutc;
1023 		fp->kbddev = makedev(DCDEV, DCKBD_PORT);
1024 		break;
1025 #endif
1026 #if NSCC > 0
1027 	case DS_3MIN:
1028 	case DS_3MAXPLUS:
1029 		fp->KBDPutc = sccPutc;
1030 		fp->kbddev = makedev(SCCDEV, SCCKBD_PORT);
1031 		break;
1032 #endif
1033 #if NDTOP > 0
1034 	case DS_MAXINE:
1035 		fp->KBDPutc = dtopKBDPutc;
1036 		fp->kbddev = makedev(DTOPDEV, DTOPKBD_PORT);
1037 		break;
1038 #endif
1039 	default:
1040 		printf("Can't configure keyboard/mouse\n");
1041 		return (1);
1042 	};
1043 	return (0);
1044 }
1045