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