remove debug stuff
[unix-history] / usr / src / sys / pmax / dev / pm.c
CommitLineData
12d43ee5
KM
1/*
2 * Copyright (c) 1992 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.
7 *
8 * %sccs.include.redist.c%
9 *
46a3a9ac 10 * @(#)pm.c 7.4 (Berkeley) %G%
12d43ee5
KM
11 *
12 * devGraphics.c --
13 *
14 * This file contains machine-dependent routines for the graphics device.
15 *
16 * Copyright (C) 1989 Digital Equipment Corporation.
17 * Permission to use, copy, modify, and distribute this software and
18 * its documentation for any purpose and without fee is hereby granted,
19 * provided that the above copyright notice appears in all copies.
20 * Digital Equipment Corporation makes no representations about the
21 * suitability of this software for any purpose. It is provided "as is"
22 * without express or implied warranty.
23 *
24 * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
25 * v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
26 */
27
28#include "pm.h"
29#if NPM > 0
30
31#include "param.h"
32#include "time.h"
33#include "kernel.h"
34#include "ioctl.h"
35#include "file.h"
36#include "errno.h"
37#include "proc.h"
38#include "mman.h"
39#include "vm/vm.h"
40
41#include "machine/machConst.h"
42#include "machine/machMon.h"
43#include "machine/dc7085cons.h"
44#include "machine/pmioctl.h"
12d43ee5
KM
45
46#include "device.h"
bd53ca78 47#include "pmreg.h"
12d43ee5
KM
48#include "font.c"
49
bd53ca78
RC
50#define MAX_ROW 56
51#define MAX_COL 80
52
12d43ee5
KM
53/*
54 * Macro to translate from a time struct to milliseconds.
55 */
56#define TO_MS(tv) ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))
57
58static u_short curReg; /* copy of PCCRegs.cmdr since it's read only */
59static int isMono; /* true if B&W frame buffer */
60static int initialized; /* true if 'probe' was successful */
61static int GraphicsOpen; /* true if the graphics device is open */
bd53ca78 62static int row, col; /* row and col for console cursor */
86e31fc2 63static struct selinfo pm_selp;/* process waiting for select */
12d43ee5
KM
64
65/*
66 * These need to be mapped into user space.
67 */
68static struct pmuaccess {
69 PM_Info scrInfo;
70 pmEvent events[PM_MAXEVQ];
71 pmTimeCoord tcs[MOTION_BUFFER_SIZE];
72} pmu;
73
12d43ee5
KM
74/*
75 * Font mask bits used by Blitc().
76 */
77static unsigned int fontmaskBits[16] = {
78 0x00000000,
79 0x00000001,
80 0x00000100,
81 0x00000101,
82 0x00010000,
83 0x00010001,
84 0x00010100,
85 0x00010101,
86 0x01000000,
87 0x01000001,
88 0x01000100,
89 0x01000101,
90 0x01010000,
91 0x01010001,
92 0x01010100,
93 0x01010101
94};
95
96/*
97 * Forward references.
98 */
bd53ca78
RC
99static void Scroll();
100static void Blitc();
101
12d43ee5
KM
102static void ScreenInit();
103static void LoadCursor();
104static void RestoreCursorColor();
105static void CursorColor();
bd53ca78 106static void PosCursor();
12d43ee5
KM
107static void InitColorMap();
108static void VDACInit();
109static void LoadColorMap();
bd53ca78
RC
110static void EnableVideo();
111static void DisableVideo();
12d43ee5
KM
112
113extern void dcKBDPutc();
bd53ca78
RC
114extern void (*dcDivertXInput)();
115extern void (*dcMouseEvent)();
116extern void (*dcMouseButtons)();
12d43ee5
KM
117
118int pmprobe();
119struct driver pmdriver = {
120 "pm", pmprobe, 0, 0,
121};
122
123/*
124 * Test to see if device is present.
125 * Return true if found and initialized ok.
126 */
127/*ARGSUSED*/
128pmprobe(cp)
129 register struct pmax_ctlr *cp;
130{
131
132 if (!initialized && !pminit())
133 return (0);
134 if (isMono)
135 printf("pm0 (monochrome display)\n");
136 else
137 printf("pm0 (color display)\n");
138 return (1);
139}
140
141/*
bd53ca78 142 *----------------------------------------------------------------------
12d43ee5 143 *
bd53ca78 144 * pmKbdEvent --
12d43ee5 145 *
bd53ca78 146 * Process a received character.
12d43ee5
KM
147 *
148 * Results:
149 * None.
150 *
151 * Side effects:
bd53ca78 152 * Events added to the queue.
12d43ee5 153 *
bd53ca78 154 *----------------------------------------------------------------------
12d43ee5 155 */
bd53ca78
RC
156void
157pmKbdEvent(ch)
158 int ch;
12d43ee5 159{
bd53ca78
RC
160 register pmEvent *eventPtr;
161 int i;
162
163 if (!GraphicsOpen)
164 return;
12d43ee5
KM
165
166 /*
bd53ca78 167 * See if there is room in the queue.
12d43ee5 168 */
bd53ca78
RC
169 i = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
170 if (i == pmu.scrInfo.qe.eHead)
171 return;
12d43ee5
KM
172
173 /*
bd53ca78 174 * Add the event to the queue.
12d43ee5 175 */
bd53ca78
RC
176 eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
177 eventPtr->type = BUTTON_RAW_TYPE;
178 eventPtr->device = KEYBOARD_DEVICE;
179 eventPtr->x = pmu.scrInfo.mouse.x;
180 eventPtr->y = pmu.scrInfo.mouse.y;
181 eventPtr->time = TO_MS(time);
182 eventPtr->key = ch;
183 pmu.scrInfo.qe.eTail = i;
184 selwakeup(&pm_selp);
12d43ee5
KM
185}
186
187/*
bd53ca78 188 *----------------------------------------------------------------------
12d43ee5 189 *
bd53ca78 190 * pmMouseEvent --
12d43ee5 191 *
bd53ca78 192 * Process a mouse event.
12d43ee5
KM
193 *
194 * Results:
195 * None.
196 *
197 * Side effects:
bd53ca78 198 * An event is added to the event queue.
12d43ee5 199 *
bd53ca78 200 *----------------------------------------------------------------------
12d43ee5 201 */
bd53ca78
RC
202void
203pmMouseEvent(newRepPtr)
204 register MouseReport *newRepPtr;
12d43ee5 205{
bd53ca78
RC
206 unsigned milliSec;
207 int i;
208 pmEvent *eventPtr;
12d43ee5 209
bd53ca78
RC
210 if (!GraphicsOpen)
211 return;
212
213 milliSec = TO_MS(time);
214
215 /*
216 * Check to see if we have to accelerate the mouse
217 */
218 if (pmu.scrInfo.mscale >= 0) {
219 if (newRepPtr->dx >= pmu.scrInfo.mthreshold) {
220 newRepPtr->dx +=
221 (newRepPtr->dx - pmu.scrInfo.mthreshold) *
222 pmu.scrInfo.mscale;
223 }
224 if (newRepPtr->dy >= pmu.scrInfo.mthreshold) {
225 newRepPtr->dy +=
226 (newRepPtr->dy - pmu.scrInfo.mthreshold) *
227 pmu.scrInfo.mscale;
228 }
12d43ee5 229 }
bd53ca78
RC
230
231 /*
232 * Update mouse position
233 */
234 if (newRepPtr->state & MOUSE_X_SIGN) {
235 pmu.scrInfo.mouse.x += newRepPtr->dx;
236 if (pmu.scrInfo.mouse.x > pmu.scrInfo.max_cur_x)
237 pmu.scrInfo.mouse.x = pmu.scrInfo.max_cur_x;
238 } else {
239 pmu.scrInfo.mouse.x -= newRepPtr->dx;
240 if (pmu.scrInfo.mouse.x < pmu.scrInfo.min_cur_x)
241 pmu.scrInfo.mouse.x = pmu.scrInfo.min_cur_x;
242 }
243 if (newRepPtr->state & MOUSE_Y_SIGN) {
244 pmu.scrInfo.mouse.y -= newRepPtr->dy;
245 if (pmu.scrInfo.mouse.y < pmu.scrInfo.min_cur_y)
246 pmu.scrInfo.mouse.y = pmu.scrInfo.min_cur_y;
247 } else {
248 pmu.scrInfo.mouse.y += newRepPtr->dy;
249 if (pmu.scrInfo.mouse.y > pmu.scrInfo.max_cur_y)
250 pmu.scrInfo.mouse.y = pmu.scrInfo.max_cur_y;
251 }
252
253 /*
254 * Move the hardware cursor.
255 */
256 PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
257
258 /*
259 * Store the motion event in the motion buffer.
260 */
261 pmu.tcs[pmu.scrInfo.qe.tcNext].time = milliSec;
262 pmu.tcs[pmu.scrInfo.qe.tcNext].x = pmu.scrInfo.mouse.x;
263 pmu.tcs[pmu.scrInfo.qe.tcNext].y = pmu.scrInfo.mouse.y;
264 if (++pmu.scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE)
265 pmu.scrInfo.qe.tcNext = 0;
266 if (pmu.scrInfo.mouse.y < pmu.scrInfo.mbox.bottom &&
267 pmu.scrInfo.mouse.y >= pmu.scrInfo.mbox.top &&
268 pmu.scrInfo.mouse.x < pmu.scrInfo.mbox.right &&
269 pmu.scrInfo.mouse.x >= pmu.scrInfo.mbox.left)
270 return;
271
272 pmu.scrInfo.mbox.bottom = 0;
273 if (PM_EVROUND(pmu.scrInfo.qe.eTail + 1) == pmu.scrInfo.qe.eHead)
274 return;
275
276 i = PM_EVROUND(pmu.scrInfo.qe.eTail - 1);
277 if ((pmu.scrInfo.qe.eTail != pmu.scrInfo.qe.eHead) &&
278 (i != pmu.scrInfo.qe.eHead)) {
279 pmEvent *eventPtr;
280
281 eventPtr = &pmu.events[i];
282 if (eventPtr->type == MOTION_TYPE) {
283 eventPtr->x = pmu.scrInfo.mouse.x;
284 eventPtr->y = pmu.scrInfo.mouse.y;
285 eventPtr->time = milliSec;
286 eventPtr->device = MOUSE_DEVICE;
287 return;
288 }
289 }
290 /*
291 * Put event into queue and wakeup any waiters.
292 */
293 eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
294 eventPtr->type = MOTION_TYPE;
295 eventPtr->time = milliSec;
296 eventPtr->x = pmu.scrInfo.mouse.x;
297 eventPtr->y = pmu.scrInfo.mouse.y;
298 eventPtr->device = MOUSE_DEVICE;
299 pmu.scrInfo.qe.eTail = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
300 selwakeup(&pm_selp);
12d43ee5
KM
301}
302
303/*
bd53ca78 304 *----------------------------------------------------------------------
12d43ee5 305 *
bd53ca78 306 * pmMouseButtons --
12d43ee5 307 *
bd53ca78 308 * Process mouse buttons.
12d43ee5
KM
309 *
310 * Results:
311 * None.
312 *
313 * Side effects:
314 * None.
315 *
bd53ca78 316 *----------------------------------------------------------------------
12d43ee5 317 */
bd53ca78
RC
318void
319pmMouseButtons(newRepPtr)
320 MouseReport *newRepPtr;
12d43ee5 321{
bd53ca78
RC
322 static char temp, oldSwitch, newSwitch;
323 int i, j;
324 pmEvent *eventPtr;
325 static MouseReport lastRep;
12d43ee5 326
bd53ca78
RC
327 if (!GraphicsOpen)
328 return;
12d43ee5 329
bd53ca78
RC
330 newSwitch = newRepPtr->state & 0x07;
331 oldSwitch = lastRep.state & 0x07;
12d43ee5 332
bd53ca78
RC
333 temp = oldSwitch ^ newSwitch;
334 if (temp == 0)
335 return;
336 for (j = 1; j < 8; j <<= 1) {
337 if ((j & temp) == 0)
338 continue;
339
340 /*
341 * Check for room in the queue
342 */
343 i = PM_EVROUND(pmu.scrInfo.qe.eTail+1);
344 if (i == pmu.scrInfo.qe.eHead)
345 return;
346
347 /*
348 * Put event into queue.
349 */
350 eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
351
352 switch (j) {
353 case RIGHT_BUTTON:
354 eventPtr->key = EVENT_RIGHT_BUTTON;
355 break;
356
357 case MIDDLE_BUTTON:
358 eventPtr->key = EVENT_MIDDLE_BUTTON;
359 break;
360
361 case LEFT_BUTTON:
362 eventPtr->key = EVENT_LEFT_BUTTON;
363 }
364 if (newSwitch & j)
365 eventPtr->type = BUTTON_DOWN_TYPE;
366 else
367 eventPtr->type = BUTTON_UP_TYPE;
368 eventPtr->device = MOUSE_DEVICE;
369
370 eventPtr->time = TO_MS(time);
371 eventPtr->x = pmu.scrInfo.mouse.x;
372 eventPtr->y = pmu.scrInfo.mouse.y;
12d43ee5 373 }
bd53ca78
RC
374 pmu.scrInfo.qe.eTail = i;
375 selwakeup(&pm_selp);
376
377 lastRep = *newRepPtr;
378 pmu.scrInfo.mswitches = newSwitch;
12d43ee5
KM
379}
380
381/*
bd53ca78 382 *----------------------------------------------------------------------
12d43ee5 383 *
bd53ca78 384 * Scroll --
12d43ee5 385 *
bd53ca78 386 * Scroll the screen.
12d43ee5
KM
387 *
388 * Results:
389 * None.
390 *
391 * Side effects:
392 * None.
393 *
bd53ca78 394 *----------------------------------------------------------------------
12d43ee5
KM
395 */
396static void
bd53ca78 397Scroll()
12d43ee5 398{
bd53ca78
RC
399 register int *dest, *src;
400 register int *end;
401 register int temp0, temp1, temp2, temp3;
402 register int i, scanInc, lineCount;
403 int line;
12d43ee5 404
bd53ca78
RC
405 /*
406 * If the mouse is on we don't scroll so that the bit map remains sane.
407 */
408 if (GraphicsOpen) {
409 row = 0;
410 return;
411 }
12d43ee5 412
bd53ca78
RC
413 /*
414 * The following is an optimization to cause the scrolling
415 * of text to be memory limited. Basically the writebuffer is
416 * 4 words (32 bits ea.) long so to achieve maximum speed we
417 * read and write in multiples of 4 words. We also limit the
418 * size to be MAX_COL characters for more speed.
419 */
420 if (isMono) {
421 lineCount = 5;
422 line = 1920 * 2;
423 scanInc = 44;
424 } else {
425 lineCount = 40;
426 scanInc = 96;
427 line = 1920 * 8;
428 }
429 src = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + line);
430 dest = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR);
431 end = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + (60 * line) - line);
432 do {
433 i = 0;
434 do {
435 temp0 = src[0];
436 temp1 = src[1];
437 temp2 = src[2];
438 temp3 = src[3];
439 dest[0] = temp0;
440 dest[1] = temp1;
441 dest[2] = temp2;
442 dest[3] = temp3;
443 dest += 4;
444 src += 4;
445 i++;
446 } while (i < lineCount);
447 src += scanInc;
448 dest += scanInc;
449 } while (src < end);
12d43ee5 450
bd53ca78
RC
451 /*
452 * Now zero out the last two lines
453 */
454 bzero(MACH_UNCACHED_FRAME_BUFFER_ADDR + (row * line), 3 * line);
12d43ee5
KM
455}
456
457/*
bd53ca78 458 *----------------------------------------------------------------------
12d43ee5 459 *
bd53ca78 460 * pmPutc --
12d43ee5 461 *
bd53ca78 462 * Write a character to the console.
12d43ee5
KM
463 *
464 * Results:
465 * None.
466 *
467 * Side effects:
bd53ca78 468 * None.
12d43ee5 469 *
bd53ca78 470 *----------------------------------------------------------------------
12d43ee5 471 */
bd53ca78
RC
472pmPutc(c)
473 register int c;
12d43ee5 474{
bd53ca78 475 int s;
12d43ee5 476
bd53ca78
RC
477 s = splhigh(); /* in case we do any printf's at interrupt time */
478 if (initialized) {
479#ifdef DEBUG
480 /*
481 * If the HELP key is pressed, wait for another
482 * HELP key press to start/stop output.
483 */
484 if (dcDebugGetc() == LK_HELP) {
485 while (dcDebugGetc() != LK_HELP)
486 ;
12d43ee5 487 }
bd53ca78
RC
488#endif
489 Blitc(c);
12d43ee5 490 } else {
bd53ca78 491 void (*f)() = (void (*)())MACH_MON_PUTCHAR;
12d43ee5 492
bd53ca78 493 (*f)(c);
12d43ee5 494 }
bd53ca78 495 splx(s);
12d43ee5
KM
496}
497
498/*
bd53ca78 499 *----------------------------------------------------------------------
12d43ee5 500 *
bd53ca78 501 * Blitc --
12d43ee5 502 *
bd53ca78 503 * Write a character to the screen.
12d43ee5
KM
504 *
505 * Results:
506 * None.
507 *
508 * Side effects:
509 * None.
510 *
bd53ca78 511 *----------------------------------------------------------------------
12d43ee5
KM
512 */
513static void
bd53ca78
RC
514Blitc(c)
515 register int c;
12d43ee5 516{
bd53ca78
RC
517 register char *bRow, *fRow;
518 register int i;
519 register int ote = isMono ? 256 : 1024; /* offset to table entry */
520 int colMult = isMono ? 1 : 8;
12d43ee5 521
bd53ca78 522 c &= 0xff;
12d43ee5 523
bd53ca78
RC
524 switch (c) {
525 case '\t':
526 for (i = 8 - (col & 0x7); i > 0; i--)
527 Blitc(' ');
528 break;
12d43ee5 529
bd53ca78
RC
530 case '\r':
531 col = 0;
532 break;
12d43ee5 533
bd53ca78
RC
534 case '\b':
535 col--;
536 if (col < 0)
537 col = 0;
538 break;
12d43ee5 539
bd53ca78
RC
540 case '\n':
541 if (row + 1 >= MAX_ROW)
542 Scroll();
543 else
544 row++;
545 col = 0;
546 break;
547
548 case '\007':
549 dcKBDPutc(LK_RING_BELL);
550 break;
551
552 default:
553 /*
554 * 0xA1 to 0xFD are the printable characters added with 8-bit
555 * support.
556 */
557 if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD)
558 break;
559 /*
560 * If the next character will wrap around then
561 * increment row counter or scroll screen.
562 */
563 if (col >= MAX_COL) {
564 col = 0;
565 if (row + 1 >= MAX_ROW)
566 Scroll();
567 else
568 row++;
569 }
570 bRow = (char *)(MACH_UNCACHED_FRAME_BUFFER_ADDR +
571 (row * 15 & 0x3ff) * ote + col * colMult);
572 i = c - ' ';
573 /*
574 * This is to skip the (32) 8-bit
575 * control chars, as well as DEL
576 * and 0xA0 which aren't printable
577 */
578 if (c > '~')
579 i -= 34;
580 i *= 15;
581 fRow = (char *)((int)pmFont + i);
12d43ee5 582
bd53ca78
RC
583 /* inline expansion for speed */
584 if (isMono) {
585 *bRow = *fRow++; bRow += ote;
586 *bRow = *fRow++; bRow += ote;
587 *bRow = *fRow++; bRow += ote;
588 *bRow = *fRow++; bRow += ote;
589 *bRow = *fRow++; bRow += ote;
590 *bRow = *fRow++; bRow += ote;
591 *bRow = *fRow++; bRow += ote;
592 *bRow = *fRow++; bRow += ote;
593 *bRow = *fRow++; bRow += ote;
594 *bRow = *fRow++; bRow += ote;
595 *bRow = *fRow++; bRow += ote;
596 *bRow = *fRow++; bRow += ote;
597 *bRow = *fRow++; bRow += ote;
598 *bRow = *fRow++; bRow += ote;
599 *bRow = *fRow++; bRow += ote;
600 } else {
601 register int j;
602 register unsigned int *pInt;
603
604 pInt = (unsigned int *)bRow;
605 for (j = 0; j < 15; j++) {
606 /*
607 * fontmaskBits converts a nibble
608 * (4 bytes) to a long word
609 * containing 4 pixels corresponding
610 * to each bit in the nibble. Thus
611 * we write two longwords for each
612 * byte in font.
613 *
614 * Remember the font is 8 bits wide
615 * and 15 bits high.
616 *
617 * We add 256 to the pointer to
618 * point to the pixel on the
619 * next scan line
620 * directly below the current
621 * pixel.
622 */
623 pInt[0] = fontmaskBits[(*fRow) & 0xf];
624 pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf];
625 fRow++;
626 pInt += 256;
627 }
628 }
629 col++; /* increment column counter */
630 }
12d43ee5 631 if (!GraphicsOpen)
bd53ca78
RC
632 PosCursor(col * 8, row * 15);
633}
12d43ee5 634
bd53ca78
RC
635/*ARGSUSED*/
636pmopen(dev, flag)
637 dev_t dev;
638 int flag;
639{
640
641 if (!initialized)
642 return (ENXIO);
643 if (GraphicsOpen)
644 return (EBUSY);
12d43ee5 645
bd53ca78
RC
646 GraphicsOpen = 1;
647 if (!isMono)
648 InitColorMap();
12d43ee5 649 /*
bd53ca78 650 * Set up event queue for later
12d43ee5 651 */
bd53ca78
RC
652 pmu.scrInfo.qe.eSize = PM_MAXEVQ;
653 pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
654 pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
655 pmu.scrInfo.qe.tcNext = 0;
656 pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
657 return (0);
12d43ee5
KM
658}
659
bd53ca78
RC
660/*ARGSUSED*/
661pmclose(dev, flag)
662 dev_t dev;
663 int flag;
12d43ee5 664{
46a3a9ac 665 int s;
12d43ee5
KM
666
667 if (!GraphicsOpen)
bd53ca78 668 return (EBADF);
12d43ee5 669
bd53ca78
RC
670 GraphicsOpen = 0;
671 if (!isMono)
672 InitColorMap();
46a3a9ac
RC
673 s = spltty();
674 dcDivertXInput = (void (*)())0;
675 dcMouseEvent = (void (*)())0;
676 dcMouseButtons = (void (*)())0;
677 splx(s);
bd53ca78
RC
678 ScreenInit();
679 vmUserUnmap();
680 bzero((caddr_t)MACH_UNCACHED_FRAME_BUFFER_ADDR,
681 (isMono ? 1024 / 8 : 1024) * 864);
682 PosCursor(col * 8, row * 15);
683 return (0);
684}
12d43ee5 685
bd53ca78
RC
686/*ARGSUSED*/
687pmioctl(dev, cmd, data, flag)
688 dev_t dev;
689 caddr_t data;
690{
691 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
46a3a9ac 692 int s;
12d43ee5 693
bd53ca78
RC
694 switch (cmd) {
695 case QIOCGINFO:
696 {
697 caddr_t addr;
698 extern caddr_t vmUserMap();
12d43ee5 699
bd53ca78
RC
700 /*
701 * Map the all the data the user needs access to into
702 * user space.
703 */
704 addr = vmUserMap(sizeof(pmu), (unsigned)&pmu);
705 if (addr == (caddr_t)0)
706 goto mapError;
707 *(PM_Info **)data = &((struct pmuaccess *)addr)->scrInfo;
708 pmu.scrInfo.qe.events = ((struct pmuaccess *)addr)->events;
709 pmu.scrInfo.qe.tcs = ((struct pmuaccess *)addr)->tcs;
710 /*
711 * Map the plane mask into the user's address space.
712 */
713 addr = vmUserMap(4, (unsigned)MACH_PLANE_MASK_ADDR);
714 if (addr == (caddr_t)0)
715 goto mapError;
716 pmu.scrInfo.planemask = (char *)addr;
717 /*
718 * Map the frame buffer into the user's address space.
719 */
720 addr = vmUserMap(isMono ? 256*1024 : 1024*1024,
721 (unsigned)MACH_UNCACHED_FRAME_BUFFER_ADDR);
722 if (addr == (caddr_t)0)
723 goto mapError;
724 pmu.scrInfo.bitmap = (char *)addr;
725 break;
12d43ee5 726
bd53ca78
RC
727 mapError:
728 vmUserUnmap();
729 printf("Cannot map shared data structures\n");
730 return (EIO);
731 }
12d43ee5 732
bd53ca78
RC
733 case QIOCPMSTATE:
734 /*
735 * Set mouse state.
736 */
737 pmu.scrInfo.mouse = *(pmCursor *)data;
738 PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
739 break;
12d43ee5 740
bd53ca78
RC
741 case QIOCINIT:
742 /*
743 * Initialize the screen.
744 */
745 ScreenInit();
746 break;
12d43ee5 747
bd53ca78
RC
748 case QIOCKPCMD:
749 {
750 pmKpCmd *kpCmdPtr;
751 unsigned char *cp;
12d43ee5 752
bd53ca78
RC
753 kpCmdPtr = (pmKpCmd *)data;
754 if (kpCmdPtr->nbytes == 0)
755 kpCmdPtr->cmd |= 0x80;
756 if (!GraphicsOpen)
757 kpCmdPtr->cmd |= 1;
758 dcKBDPutc((int)kpCmdPtr->cmd);
759 cp = &kpCmdPtr->par[0];
760 for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
761 if (kpCmdPtr->nbytes == 1)
762 *cp |= 0x80;
763 dcKBDPutc((int)*cp);
764 }
765 break;
766 }
12d43ee5 767
bd53ca78
RC
768 case QIOCADDR:
769 *(PM_Info **)data = &pmu.scrInfo;
770 break;
12d43ee5 771
bd53ca78
RC
772 case QIOWCURSOR:
773 LoadCursor((unsigned short *)data);
774 break;
12d43ee5 775
bd53ca78
RC
776 case QIOWCURSORCOLOR:
777 CursorColor((unsigned int *)data);
778 break;
12d43ee5 779
bd53ca78
RC
780 case QIOSETCMAP:
781 LoadColorMap((ColorMap *)data);
782 break;
12d43ee5 783
bd53ca78 784 case QIOKERNLOOP:
46a3a9ac 785 s = spltty();
bd53ca78
RC
786 dcDivertXInput = pmKbdEvent;
787 dcMouseEvent = pmMouseEvent;
788 dcMouseButtons = pmMouseButtons;
46a3a9ac 789 splx(s);
bd53ca78 790 break;
12d43ee5 791
bd53ca78 792 case QIOKERNUNLOOP:
46a3a9ac 793 s = spltty();
bd53ca78
RC
794 dcDivertXInput = (void (*)())0;
795 dcMouseEvent = (void (*)())0;
796 dcMouseButtons = (void (*)())0;
46a3a9ac 797 splx(s);
bd53ca78 798 break;
12d43ee5 799
bd53ca78
RC
800 case QIOVIDEOON:
801 if (!isMono)
802 RestoreCursorColor();
803 curReg |= PCC_ENPA;
804 curReg &= ~PCC_FOPB;
805 pcc->cmdr = curReg;
806 break;
12d43ee5 807
bd53ca78
RC
808 case QIOVIDEOOFF:
809 if (!isMono)
810 VDACInit();
811 curReg |= PCC_FOPB;
812 curReg &= ~PCC_ENPA;
813 pcc->cmdr = curReg;
814 break;
815
816 default:
817 printf("pm0: Unknown ioctl command %x\n", cmd);
818 return (EINVAL);
12d43ee5 819 }
bd53ca78
RC
820 return (0);
821}
12d43ee5 822
bd53ca78
RC
823pmselect(dev, flag, p)
824 dev_t dev;
825 int flag;
826 struct proc *p;
827{
828
829 switch (flag) {
830 case FREAD:
831 if (pmu.scrInfo.qe.eHead != pmu.scrInfo.qe.eTail)
832 return (1);
833 selrecord(p, &pm_selp);
834 break;
835 }
836
837 return (0);
12d43ee5
KM
838}
839
bd53ca78
RC
840static u_char bg_RGB[3]; /* background color for the cursor */
841static u_char fg_RGB[3]; /* foreground color for the cursor */
842
12d43ee5 843/*
bd53ca78 844 * The default cursor.
12d43ee5 845 */
bd53ca78
RC
846unsigned short defCursor[32] = {
847/* plane A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
848 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
849/* plane B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
850 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
851
852};
853
854/*
855 * Test to see if device is present.
856 * Return true if found and initialized ok.
857 */
858pminit()
12d43ee5
KM
859{
860 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
861
bd53ca78
RC
862 isMono = *(u_short *)MACH_SYS_CSR_ADDR & MACH_CSR_MONO;
863 if (isMono) {
864 /* check for no frame buffer */
865 if (badaddr((char *)MACH_UNCACHED_FRAME_BUFFER_ADDR, 4))
866 return (0);
867 }
868
869 /*
870 * Initialize the screen.
871 */
872 pcc->cmdr = PCC_FOPB | PCC_VBHI;
873
874 /*
875 * Initialize the cursor register.
876 */
877 pcc->cmdr = curReg = PCC_ENPA | PCC_ENPB;
878
879 /*
880 * Initialize screen info.
881 */
882 pmu.scrInfo.max_row = 56;
883 pmu.scrInfo.max_col = 80;
884 pmu.scrInfo.max_x = 1024;
885 pmu.scrInfo.max_y = 864;
886 pmu.scrInfo.max_cur_x = 1023;
887 pmu.scrInfo.max_cur_y = 863;
888 pmu.scrInfo.version = 11;
889 pmu.scrInfo.mthreshold = 4;
890 pmu.scrInfo.mscale = 2;
891 pmu.scrInfo.min_cur_x = -15;
892 pmu.scrInfo.min_cur_y = -15;
893 pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
894 pmu.scrInfo.qe.eSize = PM_MAXEVQ;
895 pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
896 pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
897 pmu.scrInfo.qe.tcNext = 0;
898
899 /*
900 * Initialize the color map, the screen, and the mouse.
901 */
902 InitColorMap();
903 ScreenInit();
904 Scroll();
905
906 initialized = 1;
907 return (1);
908}
12d43ee5
KM
909
910/*
bd53ca78 911 * ----------------------------------------------------------------------------
12d43ee5 912 *
bd53ca78 913 * ScreenInit --
12d43ee5 914 *
bd53ca78 915 * Initialize the screen.
12d43ee5
KM
916 *
917 * Results:
918 * None.
919 *
920 * Side effects:
bd53ca78 921 * The screen is initialized.
12d43ee5 922 *
bd53ca78 923 * ----------------------------------------------------------------------------
12d43ee5
KM
924 */
925static void
bd53ca78 926ScreenInit()
12d43ee5 927{
12d43ee5 928
bd53ca78
RC
929 /*
930 * Home the cursor.
931 * We want an LSI terminal emulation. We want the graphics
932 * terminal to scroll from the bottom. So start at the bottom.
933 */
934 row = 55;
935 col = 0;
12d43ee5 936
bd53ca78
RC
937 /*
938 * Load the cursor with the default values
939 *
12d43ee5 940 */
bd53ca78 941 LoadCursor(defCursor);
12d43ee5
KM
942}
943
944/*
bd53ca78 945 * ----------------------------------------------------------------------------
12d43ee5 946 *
bd53ca78 947 * LoadCursor --
12d43ee5 948 *
bd53ca78 949 * Routine to load the cursor Sprite pattern.
12d43ee5
KM
950 *
951 * Results:
952 * None.
953 *
954 * Side effects:
bd53ca78 955 * The cursor is loaded into the hardware cursor.
12d43ee5 956 *
bd53ca78 957 * ----------------------------------------------------------------------------
12d43ee5 958 */
bd53ca78
RC
959static void
960LoadCursor(cur)
961 unsigned short *cur;
12d43ee5 962{
bd53ca78
RC
963 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
964 register int i;
12d43ee5 965
bd53ca78
RC
966 curReg |= PCC_LODSA;
967 pcc->cmdr = curReg;
968 for (i = 0; i < 32; i++) {
969 pcc->memory = cur[i];
970 MachEmptyWriteBuffer();
12d43ee5 971 }
bd53ca78
RC
972 curReg &= ~PCC_LODSA;
973 pcc->cmdr = curReg;
12d43ee5
KM
974}
975
976/*
bd53ca78 977 * ----------------------------------------------------------------------------
12d43ee5 978 *
bd53ca78 979 * RestoreCursorColor --
12d43ee5 980 *
bd53ca78 981 * Routine to restore the color of the cursor.
12d43ee5
KM
982 *
983 * Results:
984 * None.
985 *
986 * Side effects:
987 * None.
988 *
bd53ca78 989 * ----------------------------------------------------------------------------
12d43ee5
KM
990 */
991static void
bd53ca78 992RestoreCursorColor()
12d43ee5 993{
bd53ca78 994 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
12d43ee5 995 register int i;
12d43ee5 996
bd53ca78
RC
997 vdac->overWA = 0x04;
998 MachEmptyWriteBuffer();
999 for (i = 0; i < 3; i++) {
1000 vdac->over = bg_RGB[i];
1001 MachEmptyWriteBuffer();
12d43ee5 1002 }
12d43ee5 1003
bd53ca78
RC
1004 vdac->overWA = 0x08;
1005 MachEmptyWriteBuffer();
1006 vdac->over = 0x00;
1007 MachEmptyWriteBuffer();
1008 vdac->over = 0x00;
1009 MachEmptyWriteBuffer();
1010 vdac->over = 0x7f;
1011 MachEmptyWriteBuffer();
12d43ee5 1012
bd53ca78
RC
1013 vdac->overWA = 0x0c;
1014 MachEmptyWriteBuffer();
1015 for (i = 0; i < 3; i++) {
1016 vdac->over = fg_RGB[i];
1017 MachEmptyWriteBuffer();
1018 }
1019}
12d43ee5 1020
bd53ca78
RC
1021/*
1022 * ----------------------------------------------------------------------------
1023 *
1024 * CursorColor --
1025 *
1026 * Set the color of the cursor.
1027 *
1028 * Results:
1029 * None.
1030 *
1031 * Side effects:
1032 * None.
1033 *
1034 * ----------------------------------------------------------------------------
1035 */
1036static void
1037CursorColor(color)
1038 unsigned int color[];
1039{
1040 register int i, j;
12d43ee5 1041
bd53ca78
RC
1042 for (i = 0; i < 3; i++)
1043 bg_RGB[i] = (u_char)(color[i] >> 8);
12d43ee5 1044
bd53ca78
RC
1045 for (i = 3, j = 0; i < 6; i++, j++)
1046 fg_RGB[j] = (u_char)(color[i] >> 8);
12d43ee5 1047
bd53ca78
RC
1048 RestoreCursorColor();
1049}
12d43ee5 1050
bd53ca78
RC
1051/*
1052 * ----------------------------------------------------------------------------
1053 *
1054 * InitColorMap --
1055 *
1056 * Initialize the color map.
1057 *
1058 * Results:
1059 * None.
1060 *
1061 * Side effects:
1062 * The colormap is initialized appropriately whether it is color or
1063 * monochrome.
1064 *
1065 * ----------------------------------------------------------------------------
1066 */
1067static void
1068InitColorMap()
1069{
1070 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
1071 register int i;
12d43ee5 1072
bd53ca78
RC
1073 *(char *)MACH_PLANE_MASK_ADDR = 0xff;
1074 MachEmptyWriteBuffer();
12d43ee5 1075
bd53ca78
RC
1076 if (isMono) {
1077 vdac->mapWA = 0; MachEmptyWriteBuffer();
1078 for (i = 0; i < 256; i++) {
1079 vdac->map = (i < 128) ? 0x00 : 0xff;
1080 MachEmptyWriteBuffer();
1081 vdac->map = (i < 128) ? 0x00 : 0xff;
1082 MachEmptyWriteBuffer();
1083 vdac->map = (i < 128) ? 0x00 : 0xff;
1084 MachEmptyWriteBuffer();
1085 }
1086 } else {
1087 vdac->mapWA = 0; MachEmptyWriteBuffer();
1088 vdac->map = 0; MachEmptyWriteBuffer();
1089 vdac->map = 0; MachEmptyWriteBuffer();
1090 vdac->map = 0; MachEmptyWriteBuffer();
12d43ee5 1091
bd53ca78
RC
1092 for (i = 1; i < 256; i++) {
1093 vdac->map = 0xff; MachEmptyWriteBuffer();
1094 vdac->map = 0xff; MachEmptyWriteBuffer();
1095 vdac->map = 0xff; MachEmptyWriteBuffer();
1096 }
1097 }
12d43ee5 1098
bd53ca78
RC
1099 for (i = 0; i < 3; i++) {
1100 bg_RGB[i] = 0x00;
1101 fg_RGB[i] = 0xff;
1102 }
1103 RestoreCursorColor();
1104}
12d43ee5 1105
bd53ca78
RC
1106/*
1107 * ----------------------------------------------------------------------------
1108 *
1109 * VDACInit --
1110 *
1111 * Initialize the VDAC.
1112 *
1113 * Results:
1114 * None.
1115 *
1116 * Side effects:
1117 * None.
1118 *
1119 * ----------------------------------------------------------------------------
1120 */
1121static void
1122VDACInit()
1123{
1124 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
12d43ee5 1125
bd53ca78
RC
1126 /*
1127 *
1128 * Initialize the VDAC
1129 */
1130 vdac->overWA = 0x04; MachEmptyWriteBuffer();
1131 vdac->over = 0x00; MachEmptyWriteBuffer();
1132 vdac->over = 0x00; MachEmptyWriteBuffer();
1133 vdac->over = 0x00; MachEmptyWriteBuffer();
1134 vdac->overWA = 0x08; MachEmptyWriteBuffer();
1135 vdac->over = 0x00; MachEmptyWriteBuffer();
1136 vdac->over = 0x00; MachEmptyWriteBuffer();
1137 vdac->over = 0x7f; MachEmptyWriteBuffer();
1138 vdac->overWA = 0x0c; MachEmptyWriteBuffer();
1139 vdac->over = 0xff; MachEmptyWriteBuffer();
1140 vdac->over = 0xff; MachEmptyWriteBuffer();
1141 vdac->over = 0xff; MachEmptyWriteBuffer();
1142}
12d43ee5 1143
bd53ca78
RC
1144/*
1145 * ----------------------------------------------------------------------------
1146 *
1147 * LoadColorMap --
1148 *
1149 * Load the color map.
1150 *
1151 * Results:
1152 * None.
1153 *
1154 * Side effects:
1155 * The color map is loaded.
1156 *
1157 * ----------------------------------------------------------------------------
1158 */
1159static void
1160LoadColorMap(ptr)
1161 ColorMap *ptr;
1162{
1163 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR;
12d43ee5 1164
bd53ca78
RC
1165 if (ptr->index > 256)
1166 return;
1167
1168 vdac->mapWA = ptr->index; MachEmptyWriteBuffer();
1169 vdac->map = ptr->Entry.red; MachEmptyWriteBuffer();
1170 vdac->map = ptr->Entry.green; MachEmptyWriteBuffer();
1171 vdac->map = ptr->Entry.blue; MachEmptyWriteBuffer();
12d43ee5
KM
1172}
1173
bd53ca78
RC
1174/*
1175 *----------------------------------------------------------------------
1176 *
1177 * PosCursor --
1178 *
1179 * Postion the cursor.
1180 *
1181 * Results:
1182 * None.
1183 *
1184 * Side effects:
1185 * None.
1186 *
1187 *----------------------------------------------------------------------
1188 */
1189static void
1190PosCursor(x, y)
1191 register int x, y;
12d43ee5 1192{
bd53ca78 1193 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR;
12d43ee5 1194
bd53ca78
RC
1195 if (y < pmu.scrInfo.min_cur_y || y > pmu.scrInfo.max_cur_y)
1196 y = pmu.scrInfo.max_cur_y;
1197 if (x < pmu.scrInfo.min_cur_x || x > pmu.scrInfo.max_cur_x)
1198 x = pmu.scrInfo.max_cur_x;
1199 pmu.scrInfo.cursor.x = x; /* keep track of real cursor */
1200 pmu.scrInfo.cursor.y = y; /* position, indep. of mouse */
1201 pcc->xpos = PCC_X_OFFSET + x;
1202 pcc->ypos = PCC_Y_OFFSET + y;
12d43ee5 1203}
12d43ee5 1204#endif