xref: /csrg-svn/sys/pmax/dev/fb.c (revision 58793)
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.3 (Berkeley) 03/23/93
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 		if (fp->fbu->scrInfo.max_x > 1024) {
635 			scanInc = 352;
636 			line = 1920 * 16;
637 		} else {
638 			scanInc = 96;
639 			line = 1920 * 8;
640 		}
641 	}
642 	src = (int *)(fp->fr_addr + line);
643 	dest = (int *)(fp->fr_addr);
644 	end = (int *)(fp->fr_addr + (68 * line) - line);
645 	do {
646 		i = 0;
647 		do {
648 			temp0 = src[0];
649 			temp1 = src[1];
650 			temp2 = src[2];
651 			temp3 = src[3];
652 			dest[0] = temp0;
653 			dest[1] = temp1;
654 			dest[2] = temp2;
655 			dest[3] = temp3;
656 			dest += 4;
657 			src += 4;
658 			i++;
659 		} while (i < lineCount);
660 		src += scanInc;
661 		dest += scanInc;
662 	} while (src < end);
663 
664 	/*
665 	 * Now zero out the last two lines
666 	 */
667 	bzero(fp->fr_addr + (fp->row * line), 3 * line);
668 }
669 
670 /*
671  *----------------------------------------------------------------------
672  *
673  * fbPutc --
674  *
675  *	Write a character to the console.
676  *
677  * Results:
678  *	None.
679  *
680  * Side effects:
681  *	None.
682  *
683  *----------------------------------------------------------------------
684  */
685 void
686 fbPutc(dev, c)
687 	dev_t dev;
688 	register int c;
689 {
690 	int s;
691 
692 	if (cn_tab.cn_fb) {
693 		static int recurse;
694 
695 		/*
696 		 * We need to prevent recursion in case a printf to the
697 		 * console happens at interrupt time but using splhigh()
698 		 * all the time locks out interrupts too much. We simply
699 		 * discard the character in this case and rely on the
700 		 * console log buffer to save the message.
701 		 */
702 		if (recurse)
703 			return;
704 		recurse = 1;
705 		fbBlitc(c, cn_tab.cn_fb);
706 		recurse = 0;
707 	} else {
708 		s = splhigh();
709 		(*callv->printf)("%c", c);
710 		splx(s);
711 	}
712 }
713 
714 /*
715  *----------------------------------------------------------------------
716  *
717  * fbBlitc --
718  *
719  *	Write a character to the screen.
720  *
721  * Results:
722  *	None.
723  *
724  * Side effects:
725  *	None.
726  *
727  *----------------------------------------------------------------------
728  */
729 void
730 fbBlitc(c, fp)
731 	register int c;
732 	register struct pmax_fb *fp;
733 {
734 	register char *bRow, *fRow;
735 	register int i;
736 	register int ote;
737 	int colMult = fp->isMono ? 1 : 8;
738 
739 	if (fp->isMono)
740 		ote = 256;
741 	else
742 		ote = ((fp->fbu->scrInfo.max_x + 1023) / 1024) * 1024;
743 	c &= 0xff;
744 
745 	switch (c) {
746 	case '\t':
747 		for (i = 8 - (fp->col & 0x7); i > 0; i--)
748 			fbBlitc(' ', fp);
749 		break;
750 
751 	case '\r':
752 		fp->col = 0;
753 		break;
754 
755 	case '\b':
756 		fp->col--;
757 		if (fp->col < 0)
758 			fp->col = 0;
759 		break;
760 
761 	case '\n':
762 		if (fp->row + 1 >= fp->fbu->scrInfo.max_row)
763 			fbScroll(fp);
764 		else
765 			fp->row++;
766 		fp->col = 0;
767 		break;
768 
769 	case '\007':
770 		(*fp->KBDPutc)(fp->kbddev, LK_RING_BELL);
771 		break;
772 
773 	default:
774 		/*
775 		 * 0xA1 to 0xFD are the printable characters added with 8-bit
776 		 * support.
777 		 */
778 		if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD)
779 			break;
780 		/*
781 		 * If the next character will wrap around then
782 		 * increment fp->row counter or scroll screen.
783 		 */
784 		if (fp->col >= fp->fbu->scrInfo.max_col) {
785 			fp->col = 0;
786 			if (fp->row + 1 >= fp->fbu->scrInfo.max_row)
787 				fbScroll(fp);
788 			else
789 				fp->row++;
790 		}
791 		bRow = (char *)(fp->fr_addr +
792 			(fp->row * 15 & 0x3ff) * ote + fp->col * colMult);
793 		i = c - ' ';
794 		/*
795 		 * This is to skip the (32) 8-bit
796 		 * control chars, as well as DEL
797 		 * and 0xA0 which aren't printable
798 		 */
799 		if (c > '~')
800 			i -= 34;
801 		i *= 15;
802 		fRow = (char *)((int)pmFont + i);
803 
804 		/* inline expansion for speed */
805 		if (fp->isMono) {
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 			*bRow = *fRow++; bRow += ote;
813 			*bRow = *fRow++; bRow += ote;
814 			*bRow = *fRow++; bRow += ote;
815 			*bRow = *fRow++; bRow += ote;
816 			*bRow = *fRow++; bRow += ote;
817 			*bRow = *fRow++; bRow += ote;
818 			*bRow = *fRow++; bRow += ote;
819 			*bRow = *fRow++; bRow += ote;
820 			*bRow = *fRow++; bRow += ote;
821 		} else {
822 			register int j;
823 			register unsigned int *pInt;
824 
825 			pInt = (unsigned int *)bRow;
826 			for (j = 0; j < 15; j++) {
827 				/*
828 				 * fontmaskBits converts a nibble
829 				 * (4 bytes) to a long word
830 				 * containing 4 pixels corresponding
831 				 * to each bit in the nibble.  Thus
832 				 * we write two longwords for each
833 				 * byte in font.
834 				 *
835 				 * Remember the font is 8 bits wide
836 				 * and 15 bits high.
837 				 *
838 				 * We add 256/512 to the pointer to
839 				 * point to the pixel on the
840 				 * next scan line
841 				 * directly below the current
842 				 * pixel.
843 				 */
844 				pInt[0] = fontmaskBits[(*fRow) & 0xf];
845 				pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf];
846 				fRow++;
847 				if (fp->fbu->scrInfo.max_x > 1024)
848 					pInt += 512;
849 				else
850 					pInt += 256;
851 			}
852 		}
853 		fp->col++; /* increment column counter */
854 	}
855 	if (!fp->GraphicsOpen)
856 		(*fp->posCursor)(fp->col * 8, fp->row * 15);
857 }
858 
859 /*
860  * ----------------------------------------------------------------------------
861  *
862  * kbdMapChar --
863  *
864  *	Map characters from the keyboard to ASCII. Return -1 if there is
865  *	no valid mapping.
866  *
867  * Results:
868  *	None.
869  *
870  * Side effects:
871  *	Remember state of shift and control keys.
872  *
873  * ----------------------------------------------------------------------------
874  */
875 kbdMapChar(cc)
876 	int cc;
877 {
878 	static u_char shiftDown;
879 	static u_char ctrlDown;
880 	static u_char lastChar;
881 
882 	switch (cc) {
883 	case KEY_REPEAT:
884 		cc = lastChar;
885 		goto done;
886 
887 	case KEY_UP:
888 		shiftDown = 0;
889 		ctrlDown = 0;
890 		return (-1);
891 
892 	case KEY_SHIFT:
893 	case KEY_R_SHIFT:
894 		if (ctrlDown || shiftDown)
895 			shiftDown = 0;
896 		else
897 			shiftDown = 1;
898 		return (-1);
899 
900 	case KEY_CONTROL:
901 		if (shiftDown || ctrlDown)
902 			ctrlDown = 0;
903 		else
904 			ctrlDown = 1;
905 		return (-1);
906 
907 	case LK_POWER_ERROR:
908 	case LK_KDOWN_ERROR:
909 	case LK_INPUT_ERROR:
910 	case LK_OUTPUT_ERROR:
911 		log(LOG_WARNING,
912 			"lk201: keyboard error, code=%x\n", cc);
913 		return (-1);
914 	}
915 	if (shiftDown)
916 		cc = shiftedAscii[cc];
917 	else
918 		cc = unshiftedAscii[cc];
919 	if (cc >= KBD_NOKEY) {
920 		/*
921 		 * A function key was typed - ignore it.
922 		 */
923 		return (-1);
924 	}
925 	if (cc >= 'a' && cc <= 'z') {
926 		if (ctrlDown)
927 			cc = cc - 'a' + '\1'; /* ^A */
928 		else if (shiftDown)
929 			cc = cc - 'a' + 'A';
930 	} else if (ctrlDown) {
931 		if (cc >= '[' && cc <= '_')
932 			cc = cc - '@';
933 		else if (cc == ' ' || cc == '@')
934 			cc = '\0';
935 	}
936 	lastChar = cc;
937 done:
938 	return (cc);
939 }
940 
941 /*
942  * Initialize the Keyboard.
943  */
944 void
945 KBDReset(kbddev, putc)
946 	dev_t kbddev;
947 	void (*putc)();
948 {
949 	register int i;
950 	static int inKBDReset;
951 
952 	if (inKBDReset)
953 		return;
954 	inKBDReset = 1;
955 	for (i = 0; i < sizeof(kbdInitString); i++)
956 		(*putc)(kbddev, (int)kbdInitString[i]);
957 	inKBDReset = 0;
958 }
959 
960 /*
961  * Initialize the mouse.
962  */
963 void
964 MouseInit(mdev, putc, getc)
965 	dev_t mdev;
966 	void (*putc)();
967 	int (*getc)();
968 {
969 	int id_byte1, id_byte2, id_byte3, id_byte4;
970 
971 	/*
972 	 * Initialize the mouse.
973 	 */
974 	(*putc)(mdev, MOUSE_SELF_TEST);
975 	id_byte1 = (*getc)(mdev);
976 	if (id_byte1 < 0) {
977 		printf("MouseInit: Timeout on 1st byte of self-test report\n");
978 		return;
979 	}
980 	id_byte2 = (*getc)(mdev);
981 	if (id_byte2 < 0) {
982 		printf("MouseInit: Timeout on 2nd byte of self-test report\n");
983 		return;
984 	}
985 	id_byte3 = (*getc)(mdev);
986 	if (id_byte3 < 0) {
987 		printf("MouseInit: Timeout on 3rd byte of self-test report\n");
988 		return;
989 	}
990 	id_byte4 = (*getc)(mdev);
991 	if (id_byte4 < 0) {
992 		printf("MouseInit: Timeout on 4th byte of self-test report\n");
993 		return;
994 	}
995 	if ((id_byte2 & 0x0f) != 0x2)
996 		printf("MouseInit: We don't have a mouse!!!\n");
997 	/*
998 	 * For some reason, the mouse doesn't see this command if it comes
999 	 * too soon after a self test.
1000 	 */
1001 	DELAY(100);
1002 	(*putc)(mdev, MOUSE_INCREMENTAL);
1003 }
1004 
1005 /*
1006  * Get a character off of the keyboard.
1007  */
1008 int
1009 KBDGetc()
1010 {
1011 	register int c;
1012 
1013 	for (;;) {
1014 		c = (*cn_tab.cn_kbdgetc)(cn_tab.cn_dev);
1015 		if (c == 0)
1016 			return (-1);
1017 		if ((c = kbdMapChar(c & 0xff)) >= 0)
1018 			break;
1019 	}
1020 	return (c);
1021 }
1022 
1023 /*
1024  * Configure the keyboard/mouse based on machine type for turbochannel
1025  * display boards.
1026  */
1027 tb_kbdmouseconfig(fp)
1028 	struct pmax_fb *fp;
1029 {
1030 
1031 	switch (pmax_boardtype) {
1032 #if NDC > 0
1033 	case DS_3MAX:
1034 		fp->KBDPutc = dcPutc;
1035 		fp->kbddev = makedev(DCDEV, DCKBD_PORT);
1036 		break;
1037 #endif
1038 #if NSCC > 0
1039 	case DS_3MIN:
1040 	case DS_3MAXPLUS:
1041 		fp->KBDPutc = sccPutc;
1042 		fp->kbddev = makedev(SCCDEV, SCCKBD_PORT);
1043 		break;
1044 #endif
1045 #if NDTOP > 0
1046 	case DS_MAXINE:
1047 		fp->KBDPutc = dtopKBDPutc;
1048 		fp->kbddev = makedev(DTOPDEV, DTOPKBD_PORT);
1049 		break;
1050 #endif
1051 	default:
1052 		printf("Can't configure keyboard/mouse\n");
1053 		return (1);
1054 	};
1055 	return (0);
1056 }
1057