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 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 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 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 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 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 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 */ 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 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 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 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