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