xref: /csrg-svn/sys/pmax/dev/cfb.c (revision 58974)
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  *	@(#)cfb.c	7.7 (Berkeley) 04/05/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  * Mach Operating System
31  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
32  * All Rights Reserved.
33  *
34  * Permission to use, copy, modify and distribute this software and its
35  * documentation is hereby granted, provided that both the copyright
36  * notice and this permission notice appear in all copies of the
37  * software, derivative works or modified versions, and any portions
38  * thereof, and that both notices appear in supporting documentation.
39  *
40  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
41  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
42  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43  *
44  * Carnegie Mellon requests users of this software to return to
45  *
46  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
47  *  School of Computer Science
48  *  Carnegie Mellon University
49  *  Pittsburgh PA 15213-3890
50  *
51  * any improvements or extensions that they make and grant Carnegie the
52  * rights to redistribute these changes.
53  */
54 
55 #include <cfb.h>
56 #if NCFB > 0
57 #include <sys/param.h>
58 #include <sys/time.h>
59 #include <sys/kernel.h>
60 #include <sys/ioctl.h>
61 #include <sys/file.h>
62 #include <sys/errno.h>
63 #include <sys/proc.h>
64 #include <sys/mman.h>
65 
66 #include <vm/vm.h>
67 
68 #include <machine/machConst.h>
69 #include <machine/pmioctl.h>
70 
71 #include <pmax/pmax/maxine.h>
72 #include <pmax/pmax/cons.h>
73 #include <pmax/pmax/pmaxtype.h>
74 
75 #include <pmax/dev/device.h>
76 #include <pmax/dev/cfbreg.h>
77 #include <pmax/dev/fbreg.h>
78 
79 #include <dc.h>
80 #include <dtop.h>
81 #include <scc.h>
82 
83 /*
84  * These need to be mapped into user space.
85  */
86 struct fbuaccess cfbu;
87 struct pmax_fb cfbfb;
88 
89 /*
90  * Forward references.
91  */
92 static void cfbScreenInit();
93 static void cfbLoadCursor();
94 static void cfbRestoreCursorColor();
95 static void cfbCursorColor();
96 void cfbPosCursor();
97 static void cfbInitColorMap();
98 static void cfbLoadColorMap();
99 static void bt459_set_cursor_ram(), bt459_video_on(), bt459_video_off();
100 static void bt459_select_reg(), bt459_write_reg();
101 static u_char bt459_read_reg();
102 static void cfbConfigMouse(), cfbDeconfigMouse();
103 
104 void cfbKbdEvent(), cfbMouseEvent(), cfbMouseButtons();
105 #if NDC > 0
106 extern void (*dcDivertXInput)();
107 extern void (*dcMouseEvent)();
108 extern void (*dcMouseButtons)();
109 #endif
110 #if NSCC > 0
111 extern void (*sccDivertXInput)();
112 extern void (*sccMouseEvent)();
113 extern void (*sccMouseButtons)();
114 #endif
115 #if NDTOP > 0
116 extern void (*dtopDivertXInput)();
117 extern void (*dtopMouseEvent)();
118 extern void (*dtopMouseButtons)();
119 #endif
120 extern int pmax_boardtype;
121 extern u_short defCursor[32];
122 extern struct consdev cn_tab;
123 
124 int	cfbprobe();
125 struct	driver cfbdriver = {
126 	"cfb", cfbprobe, 0, 0,
127 };
128 
129 #define	CFB_OFFSET_VRAM		0x0		/* from module's base */
130 #define CFB_OFFSET_BT459	0x200000	/* Bt459 registers */
131 #define CFB_OFFSET_IREQ		0x300000	/* Interrupt req. control */
132 #define CFB_OFFSET_ROM		0x380000	/* Diagnostic ROM */
133 #define CFB_OFFSET_RESET	0x3c0000	/* Bt459 resets on writes */
134 #define CFB_FB_SIZE		0x100000	/* frame buffer size */
135 
136 /*
137  * Test to see if device is present.
138  * Return true if found and initialized ok.
139  */
140 /*ARGSUSED*/
141 cfbprobe(cp)
142 	register struct pmax_ctlr *cp;
143 {
144 	register struct pmax_fb *fp = &cfbfb;
145 
146 	if (!fp->initialized && !cfbinit(cp->pmax_addr))
147 		return (0);
148 	printf("cfb0 (color display)\n");
149 	return (1);
150 }
151 
152 /*ARGSUSED*/
153 cfbopen(dev, flag)
154 	dev_t dev;
155 	int flag;
156 {
157 	register struct pmax_fb *fp = &cfbfb;
158 	int s;
159 
160 	if (!fp->initialized)
161 		return (ENXIO);
162 	if (fp->GraphicsOpen)
163 		return (EBUSY);
164 
165 	fp->GraphicsOpen = 1;
166 	cfbInitColorMap();
167 	/*
168 	 * Set up event queue for later
169 	 */
170 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
171 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
172 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
173 	fp->fbu->scrInfo.qe.tcNext = 0;
174 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
175 	cfbConfigMouse();
176 	return (0);
177 }
178 
179 /*ARGSUSED*/
180 cfbclose(dev, flag)
181 	dev_t dev;
182 	int flag;
183 {
184 	register struct pmax_fb *fp = &cfbfb;
185 	int s;
186 
187 	if (!fp->GraphicsOpen)
188 		return (EBADF);
189 
190 	fp->GraphicsOpen = 0;
191 	cfbInitColorMap();
192 	cfbDeconfigMouse();
193 	cfbScreenInit();
194 	bzero((caddr_t)fp->fr_addr, 1024 * 864);
195 	cfbPosCursor(fp->col * 8, fp->row * 15);
196 	return (0);
197 }
198 
199 /*ARGSUSED*/
200 cfbioctl(dev, cmd, data, flag, p)
201 	dev_t dev;
202 	caddr_t data;
203 	struct proc *p;
204 {
205 	register struct pmax_fb *fp = &cfbfb;
206 	int s;
207 
208 	switch (cmd) {
209 	case QIOCGINFO:
210 		return (fbmmap(fp, dev, data, p));
211 
212 	case QIOCPMSTATE:
213 		/*
214 		 * Set mouse state.
215 		 */
216 		fp->fbu->scrInfo.mouse = *(pmCursor *)data;
217 		cfbPosCursor(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
218 		break;
219 
220 	case QIOCINIT:
221 		/*
222 		 * Initialize the screen.
223 		 */
224 		cfbScreenInit();
225 		break;
226 
227 	case QIOCKPCMD:
228 	    {
229 		pmKpCmd *kpCmdPtr;
230 		unsigned char *cp;
231 
232 		kpCmdPtr = (pmKpCmd *)data;
233 		if (kpCmdPtr->nbytes == 0)
234 			kpCmdPtr->cmd |= 0x80;
235 		if (!fp->GraphicsOpen)
236 			kpCmdPtr->cmd |= 1;
237 		(*fp->KBDPutc)(fp->kbddev, (int)kpCmdPtr->cmd);
238 		cp = &kpCmdPtr->par[0];
239 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
240 			if (kpCmdPtr->nbytes == 1)
241 				*cp |= 0x80;
242 			(*fp->KBDPutc)(fp->kbddev, (int)*cp);
243 		}
244 		break;
245 	    }
246 
247 	case QIOCADDR:
248 		*(PM_Info **)data = &fp->fbu->scrInfo;
249 		break;
250 
251 	case QIOWCURSOR:
252 		cfbLoadCursor((unsigned short *)data);
253 		break;
254 
255 	case QIOWCURSORCOLOR:
256 		cfbCursorColor((unsigned int *)data);
257 		break;
258 
259 	case QIOSETCMAP:
260 		cfbLoadColorMap((ColorMap *)data);
261 		break;
262 
263 	case QIOKERNLOOP:
264 		cfbConfigMouse();
265 		break;
266 
267 	case QIOKERNUNLOOP:
268 		cfbDeconfigMouse();
269 		break;
270 
271 	case QIOVIDEOON:
272 		cfbRestoreCursorColor();
273 		bt459_video_on();
274 		break;
275 
276 	case QIOVIDEOOFF:
277 		bt459_video_off();
278 		break;
279 
280 	default:
281 		printf("cfb0: Unknown ioctl command %x\n", cmd);
282 		return (EINVAL);
283 	}
284 	return (0);
285 }
286 
287 cfbselect(dev, flag, p)
288 	dev_t dev;
289 	int flag;
290 	struct proc *p;
291 {
292 	struct pmax_fb *fp = &cfbfb;
293 
294 	switch (flag) {
295 	case FREAD:
296 		if (fp->fbu->scrInfo.qe.eHead != fp->fbu->scrInfo.qe.eTail)
297 			return (1);
298 		selrecord(p, &fp->selp);
299 		break;
300 	}
301 
302 	return (0);
303 }
304 
305 /*
306  * Return the physical page number that corresponds to byte offset 'off'.
307  */
308 /*ARGSUSED*/
309 cfbmap(dev, off, prot)
310 	dev_t dev;
311 {
312 	int len;
313 
314 	len = pmax_round_page(((vm_offset_t)&cfbu & PGOFSET) + sizeof(cfbu));
315 	if (off < len)
316 		return pmax_btop(MACH_CACHED_TO_PHYS(&cfbu) + off);
317 	off -= len;
318 	if (off >= cfbfb.fr_size)
319 		return (-1);
320 	return pmax_btop(MACH_UNCACHED_TO_PHYS(cfbfb.fr_addr) + off);
321 }
322 
323 static u_char	cursor_RGB[6];	/* cursor color 2 & 3 */
324 
325 /*
326  * XXX This assumes 2bits/cursor pixel so that the 1Kbyte cursor RAM
327  * defines a 64x64 cursor. If the bt459 does not map the cursor RAM
328  * this way, this code is Screwed!
329  */
330 static void
331 cfbLoadCursor(cursor)
332 	u_short *cursor;
333 {
334 	register int i, j, k, pos;
335 	register u_short ap, bp, out;
336 
337 	/*
338 	 * Fill in the cursor sprite using the A and B planes, as provided
339 	 * for the pmax.
340 	 * XXX This will have to change when the X server knows that this
341 	 * is not a pmax display.
342 	 */
343 	pos = 0;
344 	for (k = 0; k < 16; k++) {
345 		ap = *cursor;
346 		bp = *(cursor + 16);
347 		j = 0;
348 		while (j < 4) {
349 			out = 0;
350 			for (i = 0; i < 4; i++) {
351 #ifdef CURSOR_EL
352 				out = (out << 2) | ((ap & 0x1) << 1) |
353 					(bp & 0x1);
354 #else
355 				out = ((out >> 2) & 0x3f) |
356 					((ap & 0x1) << 7) |
357 					((bp & 0x1) << 6);
358 #endif
359 				ap >>= 1;
360 				bp >>= 1;
361 			}
362 			bt459_set_cursor_ram(pos, out);
363 			pos++;
364 			j++;
365 		}
366 		while (j < 16) {
367 			bt459_set_cursor_ram(pos, 0);
368 			pos++;
369 			j++;
370 		}
371 		cursor++;
372 	}
373 	while (pos < 1024) {
374 		bt459_set_cursor_ram(pos, 0);
375 		pos++;
376 	}
377 }
378 
379 /*
380  * Set a cursor ram value.
381  */
382 static void
383 bt459_set_cursor_ram(pos, val)
384 	int pos;
385 	register u_char val;
386 {
387 	register bt459_regmap_t *regs = (bt459_regmap_t *)
388 		(cfbfb.fr_addr + CFB_OFFSET_BT459);
389 	register int cnt;
390 	u_char nval;
391 
392 	cnt = 0;
393 	do {
394 		bt459_write_reg(regs, BT459_REG_CRAM_BASE + pos, val);
395 		nval = bt459_read_reg(regs, BT459_REG_CRAM_BASE + pos);
396 	} while (val != nval && ++cnt < 10);
397 }
398 
399 /*
400  * Generic register access
401  */
402 static void
403 bt459_select_reg(regs, regno)
404 	bt459_regmap_t *regs;
405 {
406 	regs->addr_lo = regno;
407 	regs->addr_hi = regno >> 8;
408 	MachEmptyWriteBuffer();
409 }
410 
411 static void
412 bt459_write_reg(regs, regno, val)
413 	bt459_regmap_t *regs;
414 {
415 	regs->addr_lo = regno;
416 	regs->addr_hi = regno >> 8;
417 	MachEmptyWriteBuffer();
418 	regs->addr_reg = val;
419 	MachEmptyWriteBuffer();
420 }
421 
422 static u_char
423 bt459_read_reg(regs, regno)
424 	bt459_regmap_t *regs;
425 {
426 	regs->addr_lo = regno;
427 	regs->addr_hi = regno >> 8;
428 	MachEmptyWriteBuffer();
429 	return (regs->addr_reg);
430 }
431 
432 /*
433  * Initialization
434  */
435 int
436 cfbinit(cp)
437 	char *cp;
438 {
439 	register bt459_regmap_t *regs;
440 	register struct pmax_fb *fp = &cfbfb;
441 
442 	/* check for no frame buffer */
443 	if (badaddr(cp, 4))
444 		return (0);
445 
446 	fp->isMono = 0;
447 	fp->fr_addr = (char *)(cp + CFB_OFFSET_VRAM);
448 	fp->fr_size = CFB_FB_SIZE;
449 	/*
450 	 * Must be in Uncached space since the fbuaccess structure is
451 	 * mapped into the user's address space uncached.
452 	 */
453 	fp->fbu = (struct fbuaccess *)
454 		MACH_PHYS_TO_UNCACHED(MACH_CACHED_TO_PHYS(&cfbu));
455 	fp->posCursor = cfbPosCursor;
456 	if (tb_kbdmouseconfig(fp))
457 		return (0);
458 
459 	/*
460 	 * Initialize the screen.
461 	 */
462 	regs = (bt459_regmap_t *)(fp->fr_addr + CFB_OFFSET_BT459);
463 
464 	if (bt459_read_reg(regs, BT459_REG_ID) != 0x4a)
465 		return (0);
466 
467 	/* Reset the chip */
468 	*(volatile int *)(fp->fr_addr + CFB_OFFSET_RESET) = 0;
469 	DELAY(2000);	/* ???? check right time on specs! ???? */
470 
471 	/* use 4:1 input mux */
472 	bt459_write_reg(regs, BT459_REG_CMD0, 0x40);
473 
474 	/* no zooming, no panning */
475 	bt459_write_reg(regs, BT459_REG_CMD1, 0x00);
476 
477 	/*
478 	 * signature test, X-windows cursor, no overlays, SYNC* PLL,
479 	 * normal RAM select, 7.5 IRE pedestal, do sync
480 	 */
481 	bt459_write_reg(regs, BT459_REG_CMD2, 0xc2);
482 
483 	/* get all pixel bits */
484 	bt459_write_reg(regs, BT459_REG_PRM, 0xff);
485 
486 	/* no blinking */
487 	bt459_write_reg(regs, BT459_REG_PBM, 0x00);
488 
489 	/* no overlay */
490 	bt459_write_reg(regs, BT459_REG_ORM, 0x00);
491 
492 	/* no overlay blink */
493 	bt459_write_reg(regs, BT459_REG_OBM, 0x00);
494 
495 	/* no interleave, no underlay */
496 	bt459_write_reg(regs, BT459_REG_ILV, 0x00);
497 
498 	/* normal operation, no signature analysis */
499 	bt459_write_reg(regs, BT459_REG_TEST, 0x00);
500 
501 	/*
502 	 * no blinking, 1bit cross hair, XOR reg&crosshair,
503 	 * no crosshair on either plane 0 or 1,
504 	 * regular cursor on both planes.
505 	 */
506 	bt459_write_reg(regs, BT459_REG_CCR, 0xc0);
507 
508 	/* home cursor */
509 	bt459_write_reg(regs, BT459_REG_CXLO, 0x00);
510 	bt459_write_reg(regs, BT459_REG_CXHI, 0x00);
511 	bt459_write_reg(regs, BT459_REG_CYLO, 0x00);
512 	bt459_write_reg(regs, BT459_REG_CYHI, 0x00);
513 
514 	/* no crosshair window */
515 	bt459_write_reg(regs, BT459_REG_WXLO, 0x00);
516 	bt459_write_reg(regs, BT459_REG_WXHI, 0x00);
517 	bt459_write_reg(regs, BT459_REG_WYLO, 0x00);
518 	bt459_write_reg(regs, BT459_REG_WYHI, 0x00);
519 	bt459_write_reg(regs, BT459_REG_WWLO, 0x00);
520 	bt459_write_reg(regs, BT459_REG_WWHI, 0x00);
521 	bt459_write_reg(regs, BT459_REG_WHLO, 0x00);
522 	bt459_write_reg(regs, BT459_REG_WHHI, 0x00);
523 
524 	/*
525 	 * Initialize screen info.
526 	 */
527 	fp->fbu->scrInfo.max_row = 56;
528 	fp->fbu->scrInfo.max_col = 80;
529 	fp->fbu->scrInfo.max_x = 1024;
530 	fp->fbu->scrInfo.max_y = 864;
531 	fp->fbu->scrInfo.max_cur_x = 1023;
532 	fp->fbu->scrInfo.max_cur_y = 863;
533 	fp->fbu->scrInfo.version = 11;
534 	fp->fbu->scrInfo.mthreshold = 4;
535 	fp->fbu->scrInfo.mscale = 2;
536 	fp->fbu->scrInfo.min_cur_x = 0;
537 	fp->fbu->scrInfo.min_cur_y = 0;
538 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
539 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
540 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
541 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
542 	fp->fbu->scrInfo.qe.tcNext = 0;
543 
544 	/*
545 	 * Initialize the color map, the screen, and the mouse.
546 	 */
547 	cfbInitColorMap();
548 	cfbScreenInit();
549 	fbScroll(fp);
550 
551 	fp->initialized = 1;
552 	if (cn_tab.cn_fb == (struct pmax_fb *)0)
553 		cn_tab.cn_fb = fp;
554 	return (1);
555 }
556 
557 /*
558  * ----------------------------------------------------------------------------
559  *
560  * cfbScreenInit --
561  *
562  *	Initialize the screen.
563  *
564  * Results:
565  *	None.
566  *
567  * Side effects:
568  *	The screen is initialized.
569  *
570  * ----------------------------------------------------------------------------
571  */
572 static void
573 cfbScreenInit()
574 {
575 	register struct pmax_fb *fp = &cfbfb;
576 
577 	/*
578 	 * Home the cursor.
579 	 * We want an LSI terminal emulation.  We want the graphics
580 	 * terminal to scroll from the bottom. So start at the bottom.
581 	 */
582 	fp->row = 55;
583 	fp->col = 0;
584 
585 	/*
586 	 * Load the cursor with the default values
587 	 *
588 	 */
589 	cfbLoadCursor(defCursor);
590 }
591 
592 /*
593  * ----------------------------------------------------------------------------
594  *
595  * RestoreCursorColor --
596  *
597  *	Routine to restore the color of the cursor.
598  *
599  * Results:
600  *	None.
601  *
602  * Side effects:
603  *	None.
604  *
605  * ----------------------------------------------------------------------------
606  */
607 static void
608 cfbRestoreCursorColor()
609 {
610 	bt459_regmap_t *regs = (bt459_regmap_t *)(cfbfb.fr_addr + CFB_OFFSET_BT459);
611 	register int i;
612 
613 	bt459_select_reg(regs, BT459_REG_CCOLOR_2);
614 	for (i = 0; i < 6; i++) {
615 		regs->addr_reg = cursor_RGB[i];
616 		MachEmptyWriteBuffer();
617 	}
618 }
619 
620 /*
621  * ----------------------------------------------------------------------------
622  *
623  * CursorColor --
624  *
625  *	Set the color of the cursor.
626  *
627  * Results:
628  *	None.
629  *
630  * Side effects:
631  *	None.
632  *
633  * ----------------------------------------------------------------------------
634  */
635 static void
636 cfbCursorColor(color)
637 	unsigned int color[];
638 {
639 	register int i, j;
640 
641 	for (i = 0; i < 6; i++)
642 		cursor_RGB[i] = (u_char)(color[i] >> 8);
643 
644 	cfbRestoreCursorColor();
645 }
646 
647 /*
648  *----------------------------------------------------------------------
649  *
650  * PosCursor --
651  *
652  *	Postion the cursor.
653  *
654  * Results:
655  *	None.
656  *
657  * Side effects:
658  *	None.
659  *
660  *----------------------------------------------------------------------
661  */
662 void
663 cfbPosCursor(x, y)
664 	register int x, y;
665 {
666 	bt459_regmap_t *regs = (bt459_regmap_t *)(cfbfb.fr_addr + CFB_OFFSET_BT459);
667 	register struct pmax_fb *fp = &cfbfb;
668 
669 	if (y < fp->fbu->scrInfo.min_cur_y || y > fp->fbu->scrInfo.max_cur_y)
670 		y = fp->fbu->scrInfo.max_cur_y;
671 	if (x < fp->fbu->scrInfo.min_cur_x || x > fp->fbu->scrInfo.max_cur_x)
672 		x = fp->fbu->scrInfo.max_cur_x;
673 	fp->fbu->scrInfo.cursor.x = x;		/* keep track of real cursor */
674 	fp->fbu->scrInfo.cursor.y = y;		/* position, indep. of mouse */
675 
676 	x += 219;
677 	y += 34;
678 
679 	bt459_select_reg(regs, BT459_REG_CXLO);
680 	regs->addr_reg = x;
681 	MachEmptyWriteBuffer();
682 	regs->addr_reg = x >> 8;
683 	MachEmptyWriteBuffer();
684 	regs->addr_reg = y;
685 	MachEmptyWriteBuffer();
686 	regs->addr_reg = y >> 8;
687 	MachEmptyWriteBuffer();
688 }
689 
690 /*
691  * ----------------------------------------------------------------------------
692  *
693  * InitColorMap --
694  *
695  *	Initialize the color map.
696  *
697  * Results:
698  *	None.
699  *
700  * Side effects:
701  *	The colormap is initialized appropriately.
702  *
703  * ----------------------------------------------------------------------------
704  */
705 static void
706 cfbInitColorMap()
707 {
708 	bt459_regmap_t *regs = (bt459_regmap_t *)(cfbfb.fr_addr + CFB_OFFSET_BT459);
709 	register int i;
710 
711 	bt459_select_reg(regs, 0);
712 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
713 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
714 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
715 
716 	for (i = 1; i < 256; i++) {
717 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
718 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
719 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
720 	}
721 
722 	for (i = 0; i < 3; i++) {
723 		cursor_RGB[i] = 0x00;
724 		cursor_RGB[i + 3] = 0xff;
725 	}
726 	cfbRestoreCursorColor();
727 }
728 
729 /*
730  * ----------------------------------------------------------------------------
731  *
732  * LoadColorMap --
733  *
734  *	Load the color map.
735  *
736  * Results:
737  *	None.
738  *
739  * Side effects:
740  *	The color map is loaded.
741  *
742  * ----------------------------------------------------------------------------
743  */
744 static void
745 cfbLoadColorMap(ptr)
746 	ColorMap *ptr;
747 {
748 	bt459_regmap_t *regs = (bt459_regmap_t *)(cfbfb.fr_addr + CFB_OFFSET_BT459);
749 
750 	if (ptr->index > 256)
751 		return;
752 
753 	bt459_select_reg(regs, ptr->index);
754 
755 	regs->addr_cmap = ptr->Entry.red; MachEmptyWriteBuffer();
756 	regs->addr_cmap = ptr->Entry.green; MachEmptyWriteBuffer();
757 	regs->addr_cmap = ptr->Entry.blue; MachEmptyWriteBuffer();
758 }
759 
760 /*
761  * Video on/off state.
762  */
763 static struct vstate {
764 	u_char	color0[3];	/* saved color map entry zero */
765 	u_char	off;		/* TRUE if display is off */
766 } vstate;
767 
768 /*
769  * ----------------------------------------------------------------------------
770  *
771  * bt459_video_on
772  *
773  *	Enable the video display.
774  *
775  * Results:
776  *	None.
777  *
778  * Side effects:
779  *	The display is enabled.
780  *
781  * ----------------------------------------------------------------------------
782  */
783 static void
784 bt459_video_on()
785 {
786 	bt459_regmap_t *regs = (bt459_regmap_t *)(cfbfb.fr_addr + CFB_OFFSET_BT459);
787 
788 	if (!vstate.off)
789 		return;
790 
791 	/* restore old color map entry zero */
792 	bt459_select_reg(regs, 0);
793 	regs->addr_cmap = vstate.color0[0];
794 	MachEmptyWriteBuffer();
795 	regs->addr_cmap = vstate.color0[1];
796 	MachEmptyWriteBuffer();
797 	regs->addr_cmap = vstate.color0[2];
798 	MachEmptyWriteBuffer();
799 
800 	/* enable normal display */
801 	bt459_write_reg(regs, BT459_REG_PRM, 0xff);
802 	bt459_write_reg(regs, BT459_REG_CCR, 0xc0);
803 
804 	vstate.off = 0;
805 }
806 
807 /*
808  * ----------------------------------------------------------------------------
809  *
810  * bt459_video_off
811  *
812  *	Disable the video display.
813  *
814  * Results:
815  *	None.
816  *
817  * Side effects:
818  *	The display is disabled.
819  *
820  * ----------------------------------------------------------------------------
821  */
822 static void
823 bt459_video_off()
824 {
825 	bt459_regmap_t *regs = (bt459_regmap_t *)(cfbfb.fr_addr + CFB_OFFSET_BT459);
826 
827 	if (vstate.off)
828 		return;
829 
830 	/* save old color map entry zero */
831 	bt459_select_reg(regs, 0);
832 	vstate.color0[0] = regs->addr_cmap;
833 	vstate.color0[1] = regs->addr_cmap;
834 	vstate.color0[2] = regs->addr_cmap;
835 
836 	/* set color map entry zero to zero */
837 	bt459_select_reg(regs, 0);
838 	regs->addr_cmap = 0;
839 	MachEmptyWriteBuffer();
840 	regs->addr_cmap = 0;
841 	MachEmptyWriteBuffer();
842 	regs->addr_cmap = 0;
843 	MachEmptyWriteBuffer();
844 
845 	/* disable display */
846 	bt459_write_reg(regs, BT459_REG_PRM, 0);
847 	bt459_write_reg(regs, BT459_REG_CCR, 0);
848 
849 	vstate.off = 1;
850 }
851 
852 /*
853  * cfb keyboard and mouse input. Just punt to the generic ones in fb.c
854  */
855 void
856 cfbKbdEvent(ch)
857 	int ch;
858 {
859 	fbKbdEvent(ch, &cfbfb);
860 }
861 
862 void
863 cfbMouseEvent(newRepPtr)
864 	MouseReport *newRepPtr;
865 {
866 	fbMouseEvent(newRepPtr, &cfbfb);
867 }
868 
869 void
870 cfbMouseButtons(newRepPtr)
871 	MouseReport *newRepPtr;
872 {
873 	fbMouseButtons(newRepPtr, &cfbfb);
874 }
875 
876 /*
877  * Configure the mouse and keyboard based on machine type
878  */
879 static void
880 cfbConfigMouse()
881 {
882 	int s;
883 
884 	s = spltty();
885 	switch (pmax_boardtype) {
886 #if NDC > 0
887 	case DS_3MAX:
888 		dcDivertXInput = cfbKbdEvent;
889 		dcMouseEvent = cfbMouseEvent;
890 		dcMouseButtons = cfbMouseButtons;
891 		break;
892 #endif
893 #if NSCC > 1
894 	case DS_3MIN:
895 		sccDivertXInput = cfbKbdEvent;
896 		sccMouseEvent = cfbMouseEvent;
897 		sccMouseButtons = cfbMouseButtons;
898 		break;
899 #endif
900 #if NDTOP > 0
901 	case DS_MAXINE:
902 		dtopDivertXInput = cfbKbdEvent;
903 		dtopMouseEvent = cfbMouseEvent;
904 		dtopMouseButtons = cfbMouseButtons;
905 		break;
906 #endif
907 	default:
908 		printf("Can't configure mouse/keyboard\n");
909 	};
910 	splx(s);
911 }
912 
913 /*
914  * and deconfigure them
915  */
916 static void
917 cfbDeconfigMouse()
918 {
919 	int s;
920 
921 	s = spltty();
922 	switch (pmax_boardtype) {
923 #if NDC > 0
924 	case DS_3MAX:
925 		dcDivertXInput = (void (*)())0;
926 		dcMouseEvent = (void (*)())0;
927 		dcMouseButtons = (void (*)())0;
928 		break;
929 #endif
930 #if NSCC > 1
931 	case DS_3MIN:
932 		sccDivertXInput = (void (*)())0;
933 		sccMouseEvent = (void (*)())0;
934 		sccMouseButtons = (void (*)())0;
935 		break;
936 #endif
937 #if NDTOP > 0
938 	case DS_MAXINE:
939 		dtopDivertXInput = (void (*)())0;
940 		dtopMouseEvent = (void (*)())0;
941 		dtopMouseButtons = (void (*)())0;
942 		break;
943 #endif
944 	default:
945 		printf("Can't deconfigure mouse/keyboard\n");
946 	};
947 }
948 #endif /* NCFB */
949