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