xref: /csrg-svn/sys/pmax/dev/cfb.c (revision 52891)
1*52891Sbostic /*-
2*52891Sbostic  * Copyright (c) 1992 The Regents of the University of California.
3*52891Sbostic  * All rights reserved.
4*52891Sbostic  *
5*52891Sbostic  * This code is derived from software contributed to Berkeley by
6*52891Sbostic  * Ralph Campbell.
7*52891Sbostic  *
8*52891Sbostic  * %sccs.include.redist.c%
9*52891Sbostic  *
10*52891Sbostic  *	@(#)cfb.c	7.1 (Berkeley) 03/09/92
11*52891Sbostic  */
12*52891Sbostic 
13*52891Sbostic /*
14*52891Sbostic  *  devGraphics.c --
15*52891Sbostic  *
16*52891Sbostic  *     	This file contains machine-dependent routines for the graphics device.
17*52891Sbostic  *
18*52891Sbostic  *	Copyright (C) 1989 Digital Equipment Corporation.
19*52891Sbostic  *	Permission to use, copy, modify, and distribute this software and
20*52891Sbostic  *	its documentation for any purpose and without fee is hereby granted,
21*52891Sbostic  *	provided that the above copyright notice appears in all copies.
22*52891Sbostic  *	Digital Equipment Corporation makes no representations about the
23*52891Sbostic  *	suitability of this software for any purpose.  It is provided "as is"
24*52891Sbostic  *	without express or implied warranty.
25*52891Sbostic  *
26*52891Sbostic  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
27*52891Sbostic  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
28*52891Sbostic  */
29*52891Sbostic /*
30*52891Sbostic  * Mach Operating System
31*52891Sbostic  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
32*52891Sbostic  * All Rights Reserved.
33*52891Sbostic  *
34*52891Sbostic  * Permission to use, copy, modify and distribute this software and its
35*52891Sbostic  * documentation is hereby granted, provided that both the copyright
36*52891Sbostic  * notice and this permission notice appear in all copies of the
37*52891Sbostic  * software, derivative works or modified versions, and any portions
38*52891Sbostic  * thereof, and that both notices appear in supporting documentation.
39*52891Sbostic  *
40*52891Sbostic  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
41*52891Sbostic  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
42*52891Sbostic  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43*52891Sbostic  *
44*52891Sbostic  * Carnegie Mellon requests users of this software to return to
45*52891Sbostic  *
46*52891Sbostic  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
47*52891Sbostic  *  School of Computer Science
48*52891Sbostic  *  Carnegie Mellon University
49*52891Sbostic  *  Pittsburgh PA 15213-3890
50*52891Sbostic  *
51*52891Sbostic  * any improvements or extensions that they make and grant Carnegie the
52*52891Sbostic  * rights to redistribute these changes.
53*52891Sbostic  */
54*52891Sbostic 
55*52891Sbostic #include "cfb.h"
56*52891Sbostic #if NCFB > 0
57*52891Sbostic 
58*52891Sbostic /*
59*52891Sbostic  * This is a device driver for the PMAG-BA color frame buffer
60*52891Sbostic  * on the TURBOchannel.
61*52891Sbostic  * XXX This is just to get a console working;
62*52891Sbostic  *	it will need changes to work with X11R5.
63*52891Sbostic  */
64*52891Sbostic 
65*52891Sbostic #include "param.h"
66*52891Sbostic #include "time.h"
67*52891Sbostic #include "kernel.h"
68*52891Sbostic #include "ioctl.h"
69*52891Sbostic #include "file.h"
70*52891Sbostic #include "errno.h"
71*52891Sbostic #include "proc.h"
72*52891Sbostic #include "mman.h"
73*52891Sbostic #include "vm/vm.h"
74*52891Sbostic 
75*52891Sbostic #include "machine/machConst.h"
76*52891Sbostic #include "machine/machMon.h"
77*52891Sbostic #include "machine/dc7085cons.h"
78*52891Sbostic #include "machine/pmioctl.h"
79*52891Sbostic 
80*52891Sbostic #include "device.h"
81*52891Sbostic #include "cfbreg.h"
82*52891Sbostic #include "font.c"
83*52891Sbostic 
84*52891Sbostic #define MAX_ROW	56
85*52891Sbostic #define MAX_COL	80
86*52891Sbostic 
87*52891Sbostic /*
88*52891Sbostic  * Macro to translate from a time struct to milliseconds.
89*52891Sbostic  */
90*52891Sbostic #define TO_MS(tv) ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))
91*52891Sbostic 
92*52891Sbostic static int	isMono;		/* true if B&W frame buffer */
93*52891Sbostic static int	initialized;	/* true if 'probe' was successful */
94*52891Sbostic static int	GraphicsOpen;	/* true if the graphics device is open */
95*52891Sbostic static int	row, col;	/* row and col for console cursor */
96*52891Sbostic static struct	selinfo cfb_selp;	/* process waiting for select */
97*52891Sbostic static unsigned	fb_addr;	/* frame buffer kernel virtual address */
98*52891Sbostic static unsigned	planemask_addr;	/* plane mask kernel virtual address */
99*52891Sbostic 
100*52891Sbostic /*
101*52891Sbostic  * These need to be mapped into user space.
102*52891Sbostic  */
103*52891Sbostic static struct pmuaccess {
104*52891Sbostic 	PM_Info		scrInfo;
105*52891Sbostic 	pmEvent		events[PM_MAXEVQ];
106*52891Sbostic 	pmTimeCoord	tcs[MOTION_BUFFER_SIZE];
107*52891Sbostic } pmu;
108*52891Sbostic 
109*52891Sbostic /*
110*52891Sbostic  * Font mask bits used by Blitc().
111*52891Sbostic  */
112*52891Sbostic static unsigned int fontmaskBits[16] = {
113*52891Sbostic 	0x00000000,
114*52891Sbostic 	0x00000001,
115*52891Sbostic 	0x00000100,
116*52891Sbostic 	0x00000101,
117*52891Sbostic 	0x00010000,
118*52891Sbostic 	0x00010001,
119*52891Sbostic 	0x00010100,
120*52891Sbostic 	0x00010101,
121*52891Sbostic 	0x01000000,
122*52891Sbostic 	0x01000001,
123*52891Sbostic 	0x01000100,
124*52891Sbostic 	0x01000101,
125*52891Sbostic 	0x01010000,
126*52891Sbostic 	0x01010001,
127*52891Sbostic 	0x01010100,
128*52891Sbostic 	0x01010101
129*52891Sbostic };
130*52891Sbostic 
131*52891Sbostic /*
132*52891Sbostic  * Forward references.
133*52891Sbostic  */
134*52891Sbostic static void Scroll();
135*52891Sbostic static void Blitc();
136*52891Sbostic 
137*52891Sbostic static void ScreenInit();
138*52891Sbostic static void LoadCursor();
139*52891Sbostic static void RestoreCursorColor();
140*52891Sbostic static void CursorColor();
141*52891Sbostic static void PosCursor();
142*52891Sbostic static void InitColorMap();
143*52891Sbostic static void LoadColorMap();
144*52891Sbostic static void EnableVideo();
145*52891Sbostic static void DisableVideo();
146*52891Sbostic 
147*52891Sbostic extern void dcKBDPutc();
148*52891Sbostic extern void (*dcDivertXInput)();
149*52891Sbostic extern void (*dcMouseEvent)();
150*52891Sbostic extern void (*dcMouseButtons)();
151*52891Sbostic 
152*52891Sbostic int	cfbprobe();
153*52891Sbostic struct	driver cfbdriver = {
154*52891Sbostic 	"cfb", cfbprobe, 0, 0,
155*52891Sbostic };
156*52891Sbostic 
157*52891Sbostic /*
158*52891Sbostic  * Test to see if device is present.
159*52891Sbostic  * Return true if found and initialized ok.
160*52891Sbostic  */
161*52891Sbostic cfbprobe(cp)
162*52891Sbostic 	register struct pmax_ctlr *cp;
163*52891Sbostic {
164*52891Sbostic 
165*52891Sbostic 	if (!initialized) {
166*52891Sbostic 		if (!cfb_init(cp))
167*52891Sbostic 			return (0);
168*52891Sbostic 	}
169*52891Sbostic 	printf("cfb%d at nexus0 csr 0x%x priority %d\n",
170*52891Sbostic 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
171*52891Sbostic 	return (1);
172*52891Sbostic }
173*52891Sbostic 
174*52891Sbostic /*
175*52891Sbostic  *----------------------------------------------------------------------
176*52891Sbostic  *
177*52891Sbostic  * cfbKbdEvent --
178*52891Sbostic  *
179*52891Sbostic  *	Process a received character.
180*52891Sbostic  *
181*52891Sbostic  * Results:
182*52891Sbostic  *	None.
183*52891Sbostic  *
184*52891Sbostic  * Side effects:
185*52891Sbostic  *	Events added to the queue.
186*52891Sbostic  *
187*52891Sbostic  *----------------------------------------------------------------------
188*52891Sbostic  */
189*52891Sbostic void
190*52891Sbostic cfbKbdEvent(ch)
191*52891Sbostic 	int ch;
192*52891Sbostic {
193*52891Sbostic 	register pmEvent *eventPtr;
194*52891Sbostic 	int i;
195*52891Sbostic 
196*52891Sbostic 	if (!GraphicsOpen)
197*52891Sbostic 		return;
198*52891Sbostic 
199*52891Sbostic 	/*
200*52891Sbostic 	 * See if there is room in the queue.
201*52891Sbostic 	 */
202*52891Sbostic 	i = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
203*52891Sbostic 	if (i == pmu.scrInfo.qe.eHead)
204*52891Sbostic 		return;
205*52891Sbostic 
206*52891Sbostic 	/*
207*52891Sbostic 	 * Add the event to the queue.
208*52891Sbostic 	 */
209*52891Sbostic 	eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
210*52891Sbostic 	eventPtr->type = BUTTON_RAW_TYPE;
211*52891Sbostic 	eventPtr->device = KEYBOARD_DEVICE;
212*52891Sbostic 	eventPtr->x = pmu.scrInfo.mouse.x;
213*52891Sbostic 	eventPtr->y = pmu.scrInfo.mouse.y;
214*52891Sbostic 	eventPtr->time = TO_MS(time);
215*52891Sbostic 	eventPtr->key = ch;
216*52891Sbostic 	pmu.scrInfo.qe.eTail = i;
217*52891Sbostic 	selwakeup(&cfb_selp);
218*52891Sbostic }
219*52891Sbostic 
220*52891Sbostic /*
221*52891Sbostic  *----------------------------------------------------------------------
222*52891Sbostic  *
223*52891Sbostic  * cfbMouseEvent --
224*52891Sbostic  *
225*52891Sbostic  *	Process a mouse event.
226*52891Sbostic  *
227*52891Sbostic  * Results:
228*52891Sbostic  *	None.
229*52891Sbostic  *
230*52891Sbostic  * Side effects:
231*52891Sbostic  *	An event is added to the event queue.
232*52891Sbostic  *
233*52891Sbostic  *----------------------------------------------------------------------
234*52891Sbostic  */
235*52891Sbostic void
236*52891Sbostic cfbMouseEvent(newRepPtr)
237*52891Sbostic 	register MouseReport *newRepPtr;
238*52891Sbostic {
239*52891Sbostic 	unsigned milliSec;
240*52891Sbostic 	int i;
241*52891Sbostic 	pmEvent *eventPtr;
242*52891Sbostic 
243*52891Sbostic 	if (!GraphicsOpen)
244*52891Sbostic 		return;
245*52891Sbostic 
246*52891Sbostic 	milliSec = TO_MS(time);
247*52891Sbostic 
248*52891Sbostic 	/*
249*52891Sbostic 	 * Check to see if we have to accelerate the mouse
250*52891Sbostic 	 */
251*52891Sbostic 	if (pmu.scrInfo.mscale >= 0) {
252*52891Sbostic 		if (newRepPtr->dx >= pmu.scrInfo.mthreshold) {
253*52891Sbostic 			newRepPtr->dx +=
254*52891Sbostic 				(newRepPtr->dx - pmu.scrInfo.mthreshold) *
255*52891Sbostic 				pmu.scrInfo.mscale;
256*52891Sbostic 		}
257*52891Sbostic 		if (newRepPtr->dy >= pmu.scrInfo.mthreshold) {
258*52891Sbostic 			newRepPtr->dy +=
259*52891Sbostic 				(newRepPtr->dy - pmu.scrInfo.mthreshold) *
260*52891Sbostic 				pmu.scrInfo.mscale;
261*52891Sbostic 		}
262*52891Sbostic 	}
263*52891Sbostic 
264*52891Sbostic 	/*
265*52891Sbostic 	 * Update mouse position
266*52891Sbostic 	 */
267*52891Sbostic 	if (newRepPtr->state & MOUSE_X_SIGN) {
268*52891Sbostic 		pmu.scrInfo.mouse.x += newRepPtr->dx;
269*52891Sbostic 		if (pmu.scrInfo.mouse.x > pmu.scrInfo.max_cur_x)
270*52891Sbostic 			pmu.scrInfo.mouse.x = pmu.scrInfo.max_cur_x;
271*52891Sbostic 	} else {
272*52891Sbostic 		pmu.scrInfo.mouse.x -= newRepPtr->dx;
273*52891Sbostic 		if (pmu.scrInfo.mouse.x < pmu.scrInfo.min_cur_x)
274*52891Sbostic 			pmu.scrInfo.mouse.x = pmu.scrInfo.min_cur_x;
275*52891Sbostic 	}
276*52891Sbostic 	if (newRepPtr->state & MOUSE_Y_SIGN) {
277*52891Sbostic 		pmu.scrInfo.mouse.y -= newRepPtr->dy;
278*52891Sbostic 		if (pmu.scrInfo.mouse.y < pmu.scrInfo.min_cur_y)
279*52891Sbostic 			pmu.scrInfo.mouse.y = pmu.scrInfo.min_cur_y;
280*52891Sbostic 	} else {
281*52891Sbostic 		pmu.scrInfo.mouse.y += newRepPtr->dy;
282*52891Sbostic 		if (pmu.scrInfo.mouse.y > pmu.scrInfo.max_cur_y)
283*52891Sbostic 			pmu.scrInfo.mouse.y = pmu.scrInfo.max_cur_y;
284*52891Sbostic 	}
285*52891Sbostic 
286*52891Sbostic 	/*
287*52891Sbostic 	 * Move the hardware cursor.
288*52891Sbostic 	 */
289*52891Sbostic 	PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
290*52891Sbostic 
291*52891Sbostic 	/*
292*52891Sbostic 	 * Store the motion event in the motion buffer.
293*52891Sbostic 	 */
294*52891Sbostic 	pmu.tcs[pmu.scrInfo.qe.tcNext].time = milliSec;
295*52891Sbostic 	pmu.tcs[pmu.scrInfo.qe.tcNext].x = pmu.scrInfo.mouse.x;
296*52891Sbostic 	pmu.tcs[pmu.scrInfo.qe.tcNext].y = pmu.scrInfo.mouse.y;
297*52891Sbostic 	if (++pmu.scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE)
298*52891Sbostic 		pmu.scrInfo.qe.tcNext = 0;
299*52891Sbostic 	if (pmu.scrInfo.mouse.y < pmu.scrInfo.mbox.bottom &&
300*52891Sbostic 	    pmu.scrInfo.mouse.y >=  pmu.scrInfo.mbox.top &&
301*52891Sbostic 	    pmu.scrInfo.mouse.x < pmu.scrInfo.mbox.right &&
302*52891Sbostic 	    pmu.scrInfo.mouse.x >=  pmu.scrInfo.mbox.left)
303*52891Sbostic 		return;
304*52891Sbostic 
305*52891Sbostic 	pmu.scrInfo.mbox.bottom = 0;
306*52891Sbostic 	if (PM_EVROUND(pmu.scrInfo.qe.eTail + 1) == pmu.scrInfo.qe.eHead)
307*52891Sbostic 		return;
308*52891Sbostic 
309*52891Sbostic 	i = PM_EVROUND(pmu.scrInfo.qe.eTail - 1);
310*52891Sbostic 	if ((pmu.scrInfo.qe.eTail != pmu.scrInfo.qe.eHead) &&
311*52891Sbostic 	    (i != pmu.scrInfo.qe.eHead)) {
312*52891Sbostic 		pmEvent *eventPtr;
313*52891Sbostic 
314*52891Sbostic 		eventPtr = &pmu.events[i];
315*52891Sbostic 		if (eventPtr->type == MOTION_TYPE) {
316*52891Sbostic 			eventPtr->x = pmu.scrInfo.mouse.x;
317*52891Sbostic 			eventPtr->y = pmu.scrInfo.mouse.y;
318*52891Sbostic 			eventPtr->time = milliSec;
319*52891Sbostic 			eventPtr->device = MOUSE_DEVICE;
320*52891Sbostic 			return;
321*52891Sbostic 		}
322*52891Sbostic 	}
323*52891Sbostic 	/*
324*52891Sbostic 	 * Put event into queue and wakeup any waiters.
325*52891Sbostic 	 */
326*52891Sbostic 	eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
327*52891Sbostic 	eventPtr->type = MOTION_TYPE;
328*52891Sbostic 	eventPtr->time = milliSec;
329*52891Sbostic 	eventPtr->x = pmu.scrInfo.mouse.x;
330*52891Sbostic 	eventPtr->y = pmu.scrInfo.mouse.y;
331*52891Sbostic 	eventPtr->device = MOUSE_DEVICE;
332*52891Sbostic 	pmu.scrInfo.qe.eTail = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
333*52891Sbostic 	selwakeup(&cfb_selp);
334*52891Sbostic }
335*52891Sbostic 
336*52891Sbostic /*
337*52891Sbostic  *----------------------------------------------------------------------
338*52891Sbostic  *
339*52891Sbostic  * cfbMouseButtons --
340*52891Sbostic  *
341*52891Sbostic  *	Process mouse buttons.
342*52891Sbostic  *
343*52891Sbostic  * Results:
344*52891Sbostic  *	None.
345*52891Sbostic  *
346*52891Sbostic  * Side effects:
347*52891Sbostic  *	None.
348*52891Sbostic  *
349*52891Sbostic  *----------------------------------------------------------------------
350*52891Sbostic  */
351*52891Sbostic void
352*52891Sbostic cfbMouseButtons(newRepPtr)
353*52891Sbostic 	MouseReport *newRepPtr;
354*52891Sbostic {
355*52891Sbostic 	static char temp, oldSwitch, newSwitch;
356*52891Sbostic 	int i, j;
357*52891Sbostic 	pmEvent *eventPtr;
358*52891Sbostic 	static MouseReport lastRep;
359*52891Sbostic 
360*52891Sbostic 	if (!GraphicsOpen)
361*52891Sbostic 		return;
362*52891Sbostic 
363*52891Sbostic 	newSwitch = newRepPtr->state & 0x07;
364*52891Sbostic 	oldSwitch = lastRep.state & 0x07;
365*52891Sbostic 
366*52891Sbostic 	temp = oldSwitch ^ newSwitch;
367*52891Sbostic 	if (temp == 0)
368*52891Sbostic 		return;
369*52891Sbostic 	for (j = 1; j < 8; j <<= 1) {
370*52891Sbostic 		if ((j & temp) == 0)
371*52891Sbostic 			continue;
372*52891Sbostic 
373*52891Sbostic 		/*
374*52891Sbostic 		 * Check for room in the queue
375*52891Sbostic 		 */
376*52891Sbostic 		i = PM_EVROUND(pmu.scrInfo.qe.eTail+1);
377*52891Sbostic 		if (i == pmu.scrInfo.qe.eHead)
378*52891Sbostic 			return;
379*52891Sbostic 
380*52891Sbostic 		/*
381*52891Sbostic 		 * Put event into queue.
382*52891Sbostic 		 */
383*52891Sbostic 		eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
384*52891Sbostic 
385*52891Sbostic 		switch (j) {
386*52891Sbostic 		case RIGHT_BUTTON:
387*52891Sbostic 			eventPtr->key = EVENT_RIGHT_BUTTON;
388*52891Sbostic 			break;
389*52891Sbostic 
390*52891Sbostic 		case MIDDLE_BUTTON:
391*52891Sbostic 			eventPtr->key = EVENT_MIDDLE_BUTTON;
392*52891Sbostic 			break;
393*52891Sbostic 
394*52891Sbostic 		case LEFT_BUTTON:
395*52891Sbostic 			eventPtr->key = EVENT_LEFT_BUTTON;
396*52891Sbostic 		}
397*52891Sbostic 		if (newSwitch & j)
398*52891Sbostic 			eventPtr->type = BUTTON_DOWN_TYPE;
399*52891Sbostic 		else
400*52891Sbostic 			eventPtr->type = BUTTON_UP_TYPE;
401*52891Sbostic 		eventPtr->device = MOUSE_DEVICE;
402*52891Sbostic 
403*52891Sbostic 		eventPtr->time = TO_MS(time);
404*52891Sbostic 		eventPtr->x = pmu.scrInfo.mouse.x;
405*52891Sbostic 		eventPtr->y = pmu.scrInfo.mouse.y;
406*52891Sbostic 	}
407*52891Sbostic 	pmu.scrInfo.qe.eTail = i;
408*52891Sbostic 	selwakeup(&cfb_selp);
409*52891Sbostic 
410*52891Sbostic 	lastRep = *newRepPtr;
411*52891Sbostic 	pmu.scrInfo.mswitches = newSwitch;
412*52891Sbostic }
413*52891Sbostic 
414*52891Sbostic /*
415*52891Sbostic  *----------------------------------------------------------------------
416*52891Sbostic  *
417*52891Sbostic  * Scroll --
418*52891Sbostic  *
419*52891Sbostic  *	Scroll the screen.
420*52891Sbostic  *
421*52891Sbostic  * Results:
422*52891Sbostic  *	None.
423*52891Sbostic  *
424*52891Sbostic  * Side effects:
425*52891Sbostic  *	None.
426*52891Sbostic  *
427*52891Sbostic  *----------------------------------------------------------------------
428*52891Sbostic  */
429*52891Sbostic static void
430*52891Sbostic Scroll()
431*52891Sbostic {
432*52891Sbostic 	register int *dest, *src;
433*52891Sbostic 	register int *end;
434*52891Sbostic 	register int temp0, temp1, temp2, temp3;
435*52891Sbostic 	register int i, scanInc, lineCount;
436*52891Sbostic 	int line;
437*52891Sbostic 
438*52891Sbostic 	/*
439*52891Sbostic 	 * If the mouse is on we don't scroll so that the bit map remains sane.
440*52891Sbostic 	 */
441*52891Sbostic 	if (GraphicsOpen) {
442*52891Sbostic 		row = 0;
443*52891Sbostic 		return;
444*52891Sbostic 	}
445*52891Sbostic 
446*52891Sbostic 	/*
447*52891Sbostic 	 *  The following is an optimization to cause the scrolling
448*52891Sbostic 	 *  of text to be memory limited.  Basically the writebuffer is
449*52891Sbostic 	 *  4 words (32 bits ea.) long so to achieve maximum speed we
450*52891Sbostic 	 *  read and write in multiples of 4 words. We also limit the
451*52891Sbostic 	 *  size to be MAX_COL characters for more speed.
452*52891Sbostic 	 */
453*52891Sbostic 	if (isMono) {
454*52891Sbostic 		lineCount = 5;
455*52891Sbostic 		line = 1920 * 2;
456*52891Sbostic 		scanInc = 44;
457*52891Sbostic 	} else {
458*52891Sbostic 		lineCount = 40;
459*52891Sbostic 		scanInc = 96;
460*52891Sbostic 		line = 1920 * 8;
461*52891Sbostic 	}
462*52891Sbostic 	src = (int *)(fb_addr + line);
463*52891Sbostic 	dest = (int *)(fb_addr);
464*52891Sbostic 	end = (int *)(fb_addr + (60 * line) - line);
465*52891Sbostic 	do {
466*52891Sbostic 		i = 0;
467*52891Sbostic 		do {
468*52891Sbostic 			temp0 = src[0];
469*52891Sbostic 			temp1 = src[1];
470*52891Sbostic 			temp2 = src[2];
471*52891Sbostic 			temp3 = src[3];
472*52891Sbostic 			dest[0] = temp0;
473*52891Sbostic 			dest[1] = temp1;
474*52891Sbostic 			dest[2] = temp2;
475*52891Sbostic 			dest[3] = temp3;
476*52891Sbostic 			dest += 4;
477*52891Sbostic 			src += 4;
478*52891Sbostic 			i++;
479*52891Sbostic 		} while (i < lineCount);
480*52891Sbostic 		src += scanInc;
481*52891Sbostic 		dest += scanInc;
482*52891Sbostic 	} while (src < end);
483*52891Sbostic 
484*52891Sbostic 	/*
485*52891Sbostic 	 * Now zero out the last two lines
486*52891Sbostic 	 */
487*52891Sbostic 	bzero(fb_addr + (row * line), 3 * line);
488*52891Sbostic }
489*52891Sbostic 
490*52891Sbostic /*
491*52891Sbostic  *----------------------------------------------------------------------
492*52891Sbostic  *
493*52891Sbostic  * cfbPutc --
494*52891Sbostic  *
495*52891Sbostic  *	Write a character to the console.
496*52891Sbostic  *
497*52891Sbostic  * Results:
498*52891Sbostic  *	None.
499*52891Sbostic  *
500*52891Sbostic  * Side effects:
501*52891Sbostic  *	None.
502*52891Sbostic  *
503*52891Sbostic  *----------------------------------------------------------------------
504*52891Sbostic  */
505*52891Sbostic cfbPutc(c)
506*52891Sbostic 	register int c;
507*52891Sbostic {
508*52891Sbostic 	int s;
509*52891Sbostic 
510*52891Sbostic 	s = splhigh();	/* in case we do any printf's at interrupt time */
511*52891Sbostic 	if (initialized) {
512*52891Sbostic #ifdef DEBUG
513*52891Sbostic 		/*
514*52891Sbostic 		 * If the HELP key is pressed, wait for another
515*52891Sbostic 		 * HELP key press to start/stop output.
516*52891Sbostic 		 */
517*52891Sbostic 		if (dcDebugGetc() == LK_HELP) {
518*52891Sbostic 			while (dcDebugGetc() != LK_HELP)
519*52891Sbostic 				;
520*52891Sbostic 		}
521*52891Sbostic #endif
522*52891Sbostic 		Blitc(c);
523*52891Sbostic 	} else {
524*52891Sbostic 		void (*f)() = (void (*)())MACH_MON_PUTCHAR;
525*52891Sbostic 
526*52891Sbostic 		(*f)(c);
527*52891Sbostic 	}
528*52891Sbostic 	splx(s);
529*52891Sbostic }
530*52891Sbostic 
531*52891Sbostic /*
532*52891Sbostic  *----------------------------------------------------------------------
533*52891Sbostic  *
534*52891Sbostic  * Blitc --
535*52891Sbostic  *
536*52891Sbostic  *	Write a character to the screen.
537*52891Sbostic  *
538*52891Sbostic  * Results:
539*52891Sbostic  *	None.
540*52891Sbostic  *
541*52891Sbostic  * Side effects:
542*52891Sbostic  *	None.
543*52891Sbostic  *
544*52891Sbostic  *----------------------------------------------------------------------
545*52891Sbostic  */
546*52891Sbostic static void
547*52891Sbostic Blitc(c)
548*52891Sbostic 	register int c;
549*52891Sbostic {
550*52891Sbostic 	register char *bRow, *fRow;
551*52891Sbostic 	register int i;
552*52891Sbostic 	register int ote = isMono ? 256 : 1024; /* offset to table entry */
553*52891Sbostic 	int colMult = isMono ? 1 : 8;
554*52891Sbostic 
555*52891Sbostic 	c &= 0xff;
556*52891Sbostic 
557*52891Sbostic 	switch (c) {
558*52891Sbostic 	case '\t':
559*52891Sbostic 		for (i = 8 - (col & 0x7); i > 0; i--)
560*52891Sbostic 			Blitc(' ');
561*52891Sbostic 		break;
562*52891Sbostic 
563*52891Sbostic 	case '\r':
564*52891Sbostic 		col = 0;
565*52891Sbostic 		break;
566*52891Sbostic 
567*52891Sbostic 	case '\b':
568*52891Sbostic 		col--;
569*52891Sbostic 		if (col < 0)
570*52891Sbostic 			col = 0;
571*52891Sbostic 		break;
572*52891Sbostic 
573*52891Sbostic 	case '\n':
574*52891Sbostic 		if (row + 1 >= MAX_ROW)
575*52891Sbostic 			Scroll();
576*52891Sbostic 		else
577*52891Sbostic 			row++;
578*52891Sbostic 		col = 0;
579*52891Sbostic 		break;
580*52891Sbostic 
581*52891Sbostic 	case '\007':
582*52891Sbostic 		dcKBDPutc(LK_RING_BELL);
583*52891Sbostic 		break;
584*52891Sbostic 
585*52891Sbostic 	default:
586*52891Sbostic 		/*
587*52891Sbostic 		 * 0xA1 to 0xFD are the printable characters added with 8-bit
588*52891Sbostic 		 * support.
589*52891Sbostic 		 */
590*52891Sbostic 		if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD)
591*52891Sbostic 			break;
592*52891Sbostic 		/*
593*52891Sbostic 		 * If the next character will wrap around then
594*52891Sbostic 		 * increment row counter or scroll screen.
595*52891Sbostic 		 */
596*52891Sbostic 		if (col >= MAX_COL) {
597*52891Sbostic 			col = 0;
598*52891Sbostic 			if (row + 1 >= MAX_ROW)
599*52891Sbostic 				Scroll();
600*52891Sbostic 			else
601*52891Sbostic 				row++;
602*52891Sbostic 		}
603*52891Sbostic 		bRow = (char *)(fb_addr +
604*52891Sbostic 			(row * 15 & 0x3ff) * ote + col * colMult);
605*52891Sbostic 		i = c - ' ';
606*52891Sbostic 		/*
607*52891Sbostic 		 * This is to skip the (32) 8-bit
608*52891Sbostic 		 * control chars, as well as DEL
609*52891Sbostic 		 * and 0xA0 which aren't printable
610*52891Sbostic 		 */
611*52891Sbostic 		if (c > '~')
612*52891Sbostic 			i -= 34;
613*52891Sbostic 		i *= 15;
614*52891Sbostic 		fRow = (char *)((int)pmFont + i);
615*52891Sbostic 
616*52891Sbostic 		/* inline expansion for speed */
617*52891Sbostic 		if (isMono) {
618*52891Sbostic 			*bRow = *fRow++; bRow += ote;
619*52891Sbostic 			*bRow = *fRow++; bRow += ote;
620*52891Sbostic 			*bRow = *fRow++; bRow += ote;
621*52891Sbostic 			*bRow = *fRow++; bRow += ote;
622*52891Sbostic 			*bRow = *fRow++; bRow += ote;
623*52891Sbostic 			*bRow = *fRow++; bRow += ote;
624*52891Sbostic 			*bRow = *fRow++; bRow += ote;
625*52891Sbostic 			*bRow = *fRow++; bRow += ote;
626*52891Sbostic 			*bRow = *fRow++; bRow += ote;
627*52891Sbostic 			*bRow = *fRow++; bRow += ote;
628*52891Sbostic 			*bRow = *fRow++; bRow += ote;
629*52891Sbostic 			*bRow = *fRow++; bRow += ote;
630*52891Sbostic 			*bRow = *fRow++; bRow += ote;
631*52891Sbostic 			*bRow = *fRow++; bRow += ote;
632*52891Sbostic 			*bRow = *fRow++; bRow += ote;
633*52891Sbostic 		} else {
634*52891Sbostic 			register int j;
635*52891Sbostic 			register unsigned int *pInt;
636*52891Sbostic 
637*52891Sbostic 			pInt = (unsigned int *)bRow;
638*52891Sbostic 			for (j = 0; j < 15; j++) {
639*52891Sbostic 				/*
640*52891Sbostic 				 * fontmaskBits converts a nibble
641*52891Sbostic 				 * (4 bytes) to a long word
642*52891Sbostic 				 * containing 4 pixels corresponding
643*52891Sbostic 				 * to each bit in the nibble.  Thus
644*52891Sbostic 				 * we write two longwords for each
645*52891Sbostic 				 * byte in font.
646*52891Sbostic 				 *
647*52891Sbostic 				 * Remember the font is 8 bits wide
648*52891Sbostic 				 * and 15 bits high.
649*52891Sbostic 				 *
650*52891Sbostic 				 * We add 256 to the pointer to
651*52891Sbostic 				 * point to the pixel on the
652*52891Sbostic 				 * next scan line
653*52891Sbostic 				 * directly below the current
654*52891Sbostic 				 * pixel.
655*52891Sbostic 				 */
656*52891Sbostic 				pInt[0] = fontmaskBits[(*fRow) & 0xf];
657*52891Sbostic 				pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf];
658*52891Sbostic 				fRow++;
659*52891Sbostic 				pInt += 256;
660*52891Sbostic 			}
661*52891Sbostic 		}
662*52891Sbostic 		col++; /* increment column counter */
663*52891Sbostic 	}
664*52891Sbostic 	if (!GraphicsOpen)
665*52891Sbostic 		PosCursor(col * 8, row * 15);
666*52891Sbostic }
667*52891Sbostic 
668*52891Sbostic /*ARGSUSED*/
669*52891Sbostic cfbopen(dev, flag)
670*52891Sbostic 	dev_t dev;
671*52891Sbostic 	int flag;
672*52891Sbostic {
673*52891Sbostic 
674*52891Sbostic 	if (!initialized)
675*52891Sbostic 		return (ENXIO);
676*52891Sbostic 	if (GraphicsOpen)
677*52891Sbostic 		return (EBUSY);
678*52891Sbostic 
679*52891Sbostic 	GraphicsOpen = 1;
680*52891Sbostic 	if (!isMono)
681*52891Sbostic 		InitColorMap();
682*52891Sbostic 	/*
683*52891Sbostic 	 * Set up event queue for later
684*52891Sbostic 	 */
685*52891Sbostic 	pmu.scrInfo.qe.eSize = PM_MAXEVQ;
686*52891Sbostic 	pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
687*52891Sbostic 	pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
688*52891Sbostic 	pmu.scrInfo.qe.tcNext = 0;
689*52891Sbostic 	pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
690*52891Sbostic 	return (0);
691*52891Sbostic }
692*52891Sbostic 
693*52891Sbostic /*ARGSUSED*/
694*52891Sbostic cfbclose(dev, flag)
695*52891Sbostic 	dev_t dev;
696*52891Sbostic 	int flag;
697*52891Sbostic {
698*52891Sbostic 
699*52891Sbostic 	if (!GraphicsOpen)
700*52891Sbostic 		return (EBADF);
701*52891Sbostic 
702*52891Sbostic 	GraphicsOpen = 0;
703*52891Sbostic 	if (!isMono)
704*52891Sbostic 		InitColorMap();
705*52891Sbostic 	ScreenInit();
706*52891Sbostic 	vmUserUnmap();
707*52891Sbostic 	bzero(fb_addr, (isMono ? 1024 / 8 : 1024) * 864);
708*52891Sbostic 	PosCursor(col * 8, row * 15);
709*52891Sbostic 	return (0);
710*52891Sbostic }
711*52891Sbostic 
712*52891Sbostic /*ARGSUSED*/
713*52891Sbostic cfbioctl(dev, cmd, data, flag)
714*52891Sbostic 	dev_t dev;
715*52891Sbostic 	caddr_t data;
716*52891Sbostic {
717*52891Sbostic 
718*52891Sbostic 	switch (cmd) {
719*52891Sbostic 	case QIOCGINFO:
720*52891Sbostic 	    {
721*52891Sbostic 		caddr_t addr;
722*52891Sbostic 		extern caddr_t vmUserMap();
723*52891Sbostic 
724*52891Sbostic 		/*
725*52891Sbostic 		 * Map the all the data the user needs access to into
726*52891Sbostic 		 * user space.
727*52891Sbostic 		 */
728*52891Sbostic 		addr = vmUserMap(sizeof(pmu), (unsigned)&pmu);
729*52891Sbostic 		if (addr == (caddr_t)0)
730*52891Sbostic 			goto mapError;
731*52891Sbostic 		*(PM_Info **)data = &((struct pmuaccess *)addr)->scrInfo;
732*52891Sbostic 		pmu.scrInfo.qe.events = ((struct pmuaccess *)addr)->events;
733*52891Sbostic 		pmu.scrInfo.qe.tcs = ((struct pmuaccess *)addr)->tcs;
734*52891Sbostic 		/*
735*52891Sbostic 		 * Map the plane mask into the user's address space.
736*52891Sbostic 		 */
737*52891Sbostic 		addr = vmUserMap(4, planemask_addr);
738*52891Sbostic 		if (addr == (caddr_t)0)
739*52891Sbostic 			goto mapError;
740*52891Sbostic 		pmu.scrInfo.planemask = (char *)addr;
741*52891Sbostic 		/*
742*52891Sbostic 		 * Map the frame buffer into the user's address space.
743*52891Sbostic 		 */
744*52891Sbostic 		addr = vmUserMap(isMono ? 256*1024 : 1024*1024, fb_addr);
745*52891Sbostic 		if (addr == (caddr_t)0)
746*52891Sbostic 			goto mapError;
747*52891Sbostic 		pmu.scrInfo.bitmap = (char *)addr;
748*52891Sbostic 		break;
749*52891Sbostic 
750*52891Sbostic 	mapError:
751*52891Sbostic 		vmUserUnmap();
752*52891Sbostic 		printf("Cannot map shared data structures\n");
753*52891Sbostic 		return (EIO);
754*52891Sbostic 	    }
755*52891Sbostic 
756*52891Sbostic 	case QIOCPMSTATE:
757*52891Sbostic 		/*
758*52891Sbostic 		 * Set mouse state.
759*52891Sbostic 		 */
760*52891Sbostic 		pmu.scrInfo.mouse = *(pmCursor *)data;
761*52891Sbostic 		PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
762*52891Sbostic 		break;
763*52891Sbostic 
764*52891Sbostic 	case QIOCINIT:
765*52891Sbostic 		/*
766*52891Sbostic 		 * Initialize the screen.
767*52891Sbostic 		 */
768*52891Sbostic 		ScreenInit();
769*52891Sbostic 		break;
770*52891Sbostic 
771*52891Sbostic 	case QIOCKPCMD:
772*52891Sbostic 	    {
773*52891Sbostic 		pmKpCmd *kpCmdPtr;
774*52891Sbostic 		unsigned char *cp;
775*52891Sbostic 
776*52891Sbostic 		kpCmdPtr = (pmKpCmd *)data;
777*52891Sbostic 		if (kpCmdPtr->nbytes == 0)
778*52891Sbostic 			kpCmdPtr->cmd |= 0x80;
779*52891Sbostic 		if (!GraphicsOpen)
780*52891Sbostic 			kpCmdPtr->cmd |= 1;
781*52891Sbostic 		dcKBDPutc((int)kpCmdPtr->cmd);
782*52891Sbostic 		cp = &kpCmdPtr->par[0];
783*52891Sbostic 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
784*52891Sbostic 			if (kpCmdPtr->nbytes == 1)
785*52891Sbostic 				*cp |= 0x80;
786*52891Sbostic 			dcKBDPutc((int)*cp);
787*52891Sbostic 		}
788*52891Sbostic 		break;
789*52891Sbostic 	    }
790*52891Sbostic 
791*52891Sbostic 	case QIOCADDR:
792*52891Sbostic 		*(PM_Info **)data = &pmu.scrInfo;
793*52891Sbostic 		break;
794*52891Sbostic 
795*52891Sbostic 	case QIOWCURSOR:
796*52891Sbostic 		LoadCursor((unsigned short *)data);
797*52891Sbostic 		break;
798*52891Sbostic 
799*52891Sbostic 	case QIOWCURSORCOLOR:
800*52891Sbostic 		CursorColor((unsigned int *)data);
801*52891Sbostic 		break;
802*52891Sbostic 
803*52891Sbostic 	case QIOSETCMAP:
804*52891Sbostic 		LoadColorMap((ColorMap *)data);
805*52891Sbostic 		break;
806*52891Sbostic 
807*52891Sbostic 	case QIOKERNLOOP:
808*52891Sbostic 		dcDivertXInput = cfbKbdEvent;
809*52891Sbostic 		dcMouseEvent = cfbMouseEvent;
810*52891Sbostic 		dcMouseButtons = cfbMouseButtons;
811*52891Sbostic 		break;
812*52891Sbostic 
813*52891Sbostic 	case QIOKERNUNLOOP:
814*52891Sbostic 		dcDivertXInput = (void (*)())0;
815*52891Sbostic 		dcMouseEvent = (void (*)())0;
816*52891Sbostic 		dcMouseButtons = (void (*)())0;
817*52891Sbostic 		break;
818*52891Sbostic 
819*52891Sbostic 	case QIOVIDEOON:
820*52891Sbostic 		EnableVideo();
821*52891Sbostic 		break;
822*52891Sbostic 
823*52891Sbostic 	case QIOVIDEOOFF:
824*52891Sbostic 		DisableVideo();
825*52891Sbostic 		break;
826*52891Sbostic 
827*52891Sbostic 	default:
828*52891Sbostic 		printf("cfb0: Unknown ioctl command %x\n", cmd);
829*52891Sbostic 		return (EINVAL);
830*52891Sbostic 	}
831*52891Sbostic 	return (0);
832*52891Sbostic }
833*52891Sbostic 
834*52891Sbostic cfbselect(dev, flag, p)
835*52891Sbostic 	dev_t dev;
836*52891Sbostic 	int flag;
837*52891Sbostic 	struct proc *p;
838*52891Sbostic {
839*52891Sbostic 
840*52891Sbostic 	switch (flag) {
841*52891Sbostic 	case FREAD:
842*52891Sbostic 		if (pmu.scrInfo.qe.eHead != pmu.scrInfo.qe.eTail)
843*52891Sbostic 			return (1);
844*52891Sbostic 		selrecord(p, &cfb_selp);
845*52891Sbostic 		break;
846*52891Sbostic 	}
847*52891Sbostic 
848*52891Sbostic 	return (0);
849*52891Sbostic }
850*52891Sbostic 
851*52891Sbostic static u_char	cursor_RGB[6];	/* cursor color 2 & 3 */
852*52891Sbostic 
853*52891Sbostic /*
854*52891Sbostic  * The default cursor.
855*52891Sbostic  */
856*52891Sbostic static unsigned short defCursor[1024] = {
857*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
858*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
859*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
860*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
861*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
862*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
863*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
864*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
865*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
866*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
867*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
868*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
869*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
870*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
871*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
872*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
873*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
874*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
875*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
876*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
877*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
878*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
879*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
880*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
881*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
882*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
883*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
884*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
885*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
886*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
887*52891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
888*52891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
889*52891Sbostic };
890*52891Sbostic 
891*52891Sbostic #define	CFB_OFFSET_VRAM		0x0		/* from module's base */
892*52891Sbostic 						/* Replicated at x100000 */
893*52891Sbostic #define CFB_OFFSET_BT459	0x200000	/* Bt459 registers */
894*52891Sbostic #define CFB_OFFSET_IREQ		0x300000	/* Interrupt req. control */
895*52891Sbostic #define CFB_OFFSET_ROM		0x380000	/* Diagnostic ROM */
896*52891Sbostic #define CFB_OFFSET_RESET	0x3c0000	/* Bt459 resets on writes */
897*52891Sbostic 
898*52891Sbostic /*
899*52891Sbostic  * Generic register access
900*52891Sbostic  */
901*52891Sbostic void
902*52891Sbostic bt459_select_reg(regs, regno)
903*52891Sbostic 	bt459_regmap_t *regs;
904*52891Sbostic {
905*52891Sbostic 	regs->addr_lo = regno;
906*52891Sbostic 	regs->addr_hi = regno >> 8;
907*52891Sbostic 	MachEmptyWriteBuffer();
908*52891Sbostic }
909*52891Sbostic 
910*52891Sbostic void
911*52891Sbostic bt459_write_reg(regs, regno, val)
912*52891Sbostic 	bt459_regmap_t *regs;
913*52891Sbostic {
914*52891Sbostic 	regs->addr_lo = regno;
915*52891Sbostic 	regs->addr_hi = regno >> 8;
916*52891Sbostic 	MachEmptyWriteBuffer();
917*52891Sbostic 	regs->addr_reg = val;
918*52891Sbostic 	MachEmptyWriteBuffer();
919*52891Sbostic }
920*52891Sbostic 
921*52891Sbostic unsigned char
922*52891Sbostic bt459_read_reg(regs, regno)
923*52891Sbostic 	bt459_regmap_t *regs;
924*52891Sbostic {
925*52891Sbostic 	regs->addr_lo = regno;
926*52891Sbostic 	regs->addr_hi = regno >> 8;
927*52891Sbostic 	MachEmptyWriteBuffer();
928*52891Sbostic 	return regs->addr_reg;
929*52891Sbostic }
930*52891Sbostic 
931*52891Sbostic #ifdef DEBUG
932*52891Sbostic bt459_print_colormap(regs)
933*52891Sbostic 	bt459_regmap_t *regs;
934*52891Sbostic {
935*52891Sbostic 	register int i;
936*52891Sbostic 
937*52891Sbostic 	bt459_select_reg(regs, 0);
938*52891Sbostic 	for (i = 0; i < 256; i++) {
939*52891Sbostic 		register unsigned red, green, blue;
940*52891Sbostic 
941*52891Sbostic 		red = regs->addr_cmap;
942*52891Sbostic 		green = regs->addr_cmap;
943*52891Sbostic 		blue = regs->addr_cmap;
944*52891Sbostic 		printf("%x->[x%x x%x x%x]\n", i, red, green, blue);
945*52891Sbostic 	}
946*52891Sbostic }
947*52891Sbostic #endif
948*52891Sbostic 
949*52891Sbostic /*
950*52891Sbostic  * Test to see if device is present.
951*52891Sbostic  * Return true if found and initialized ok.
952*52891Sbostic  */
953*52891Sbostic cfb_init(cp)
954*52891Sbostic 	register struct pmax_ctlr *cp;
955*52891Sbostic {
956*52891Sbostic 	bt459_regmap_t *regs;
957*52891Sbostic 
958*52891Sbostic 	/* check for no frame buffer */
959*52891Sbostic 	if (badaddr(cp->pmax_addr, 4))
960*52891Sbostic 		return (0);
961*52891Sbostic 
962*52891Sbostic 	fb_addr = (unsigned)cp->pmax_addr + CFB_OFFSET_VRAM;
963*52891Sbostic 	planemask_addr = 0; /* XXX */
964*52891Sbostic 	regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
965*52891Sbostic 
966*52891Sbostic 	if (bt459_read_reg(regs, BT459_REG_ID) != 0x4a)
967*52891Sbostic 		return (0);
968*52891Sbostic 
969*52891Sbostic 	*(int *)(fb_addr + CFB_OFFSET_RESET) = 0;	/* force chip reset */
970*52891Sbostic 	DELAY(2000);	/* ???? check right time on specs! ???? */
971*52891Sbostic 
972*52891Sbostic 	/* use 4:1 input mux */
973*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CMD0, 0x40);
974*52891Sbostic 
975*52891Sbostic 	/* no zooming, no panning */
976*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CMD1, 0x00);
977*52891Sbostic 
978*52891Sbostic 	/*
979*52891Sbostic 	 * signature test, X-windows cursor, no overlays, SYNC* PLL,
980*52891Sbostic 	 * normal RAM select, 7.5 IRE pedestal, do sync
981*52891Sbostic 	 */
982*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CMD2, 0xc2);
983*52891Sbostic 
984*52891Sbostic 	/* get all pixel bits */
985*52891Sbostic 	bt459_write_reg(regs, BT459_REG_PRM, 0xff);
986*52891Sbostic 
987*52891Sbostic 	/* no blinking */
988*52891Sbostic 	bt459_write_reg(regs, BT459_REG_PBM, 0x00);
989*52891Sbostic 
990*52891Sbostic 	/* no overlay */
991*52891Sbostic 	bt459_write_reg(regs, BT459_REG_ORM, 0x00);
992*52891Sbostic 
993*52891Sbostic 	/* no overlay blink */
994*52891Sbostic 	bt459_write_reg(regs, BT459_REG_OBM, 0x00);
995*52891Sbostic 
996*52891Sbostic 	/* no interleave, no underlay */
997*52891Sbostic 	bt459_write_reg(regs, BT459_REG_ILV, 0x00);
998*52891Sbostic 
999*52891Sbostic 	/* normal operation, no signature analysis */
1000*52891Sbostic 	bt459_write_reg(regs, BT459_REG_TEST, 0x00);
1001*52891Sbostic 
1002*52891Sbostic 	/*
1003*52891Sbostic 	 * no blinking, 1bit cross hair, XOR reg&crosshair,
1004*52891Sbostic 	 * no crosshair on either plane 0 or 1,
1005*52891Sbostic 	 * regular cursor on both planes.
1006*52891Sbostic 	 */
1007*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CCR, 0xc0);
1008*52891Sbostic 
1009*52891Sbostic 	/* home cursor */
1010*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CXLO, 0x00);
1011*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CXHI, 0x00);
1012*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CYLO, 0x00);
1013*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CYHI, 0x00);
1014*52891Sbostic 
1015*52891Sbostic 	/* no crosshair window */
1016*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WXLO, 0x00);
1017*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WXHI, 0x00);
1018*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WYLO, 0x00);
1019*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WYHI, 0x00);
1020*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WWLO, 0x00);
1021*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WWHI, 0x00);
1022*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WHLO, 0x00);
1023*52891Sbostic 	bt459_write_reg(regs, BT459_REG_WHHI, 0x00);
1024*52891Sbostic 
1025*52891Sbostic 	/*
1026*52891Sbostic 	 * Initialize screen info.
1027*52891Sbostic 	 */
1028*52891Sbostic 	pmu.scrInfo.max_row = MAX_ROW;
1029*52891Sbostic 	pmu.scrInfo.max_col = MAX_COL;
1030*52891Sbostic 	pmu.scrInfo.max_x = 1024;
1031*52891Sbostic 	pmu.scrInfo.max_y = 864;
1032*52891Sbostic 	pmu.scrInfo.max_cur_x = 1023;
1033*52891Sbostic 	pmu.scrInfo.max_cur_y = 863;
1034*52891Sbostic 	pmu.scrInfo.version = 11;
1035*52891Sbostic 	pmu.scrInfo.mthreshold = 4;
1036*52891Sbostic 	pmu.scrInfo.mscale = 2;
1037*52891Sbostic 	pmu.scrInfo.min_cur_x = 0;
1038*52891Sbostic 	pmu.scrInfo.min_cur_y = 0;
1039*52891Sbostic 	pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
1040*52891Sbostic 	pmu.scrInfo.qe.eSize = PM_MAXEVQ;
1041*52891Sbostic 	pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
1042*52891Sbostic 	pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
1043*52891Sbostic 	pmu.scrInfo.qe.tcNext = 0;
1044*52891Sbostic 
1045*52891Sbostic 	/*
1046*52891Sbostic 	 * Initialize the color map, the screen, and the mouse.
1047*52891Sbostic 	 */
1048*52891Sbostic 	InitColorMap();
1049*52891Sbostic 	ScreenInit();
1050*52891Sbostic 	Scroll();
1051*52891Sbostic 
1052*52891Sbostic 	initialized = 1;
1053*52891Sbostic 	return (1);
1054*52891Sbostic }
1055*52891Sbostic 
1056*52891Sbostic /*
1057*52891Sbostic  * ----------------------------------------------------------------------------
1058*52891Sbostic  *
1059*52891Sbostic  * ScreenInit --
1060*52891Sbostic  *
1061*52891Sbostic  *	Initialize the screen.
1062*52891Sbostic  *
1063*52891Sbostic  * Results:
1064*52891Sbostic  *	None.
1065*52891Sbostic  *
1066*52891Sbostic  * Side effects:
1067*52891Sbostic  *	The screen is initialized.
1068*52891Sbostic  *
1069*52891Sbostic  * ----------------------------------------------------------------------------
1070*52891Sbostic  */
1071*52891Sbostic static void
1072*52891Sbostic ScreenInit()
1073*52891Sbostic {
1074*52891Sbostic 
1075*52891Sbostic 	/*
1076*52891Sbostic 	 * Home the cursor.
1077*52891Sbostic 	 * We want an LSI terminal emulation. We want the graphics
1078*52891Sbostic 	 * terminal to scroll from the bottom. So start at the bottom.
1079*52891Sbostic 	 */
1080*52891Sbostic 	row = 55;
1081*52891Sbostic 	col = 0;
1082*52891Sbostic 
1083*52891Sbostic 	/*
1084*52891Sbostic 	 * Load the cursor with the default values
1085*52891Sbostic 	 *
1086*52891Sbostic 	 */
1087*52891Sbostic 	LoadCursor(defCursor);
1088*52891Sbostic }
1089*52891Sbostic 
1090*52891Sbostic /*
1091*52891Sbostic  * ----------------------------------------------------------------------------
1092*52891Sbostic  *
1093*52891Sbostic  * LoadCursor --
1094*52891Sbostic  *
1095*52891Sbostic  *	Routine to load the cursor Sprite pattern.
1096*52891Sbostic  *
1097*52891Sbostic  * Results:
1098*52891Sbostic  *	None.
1099*52891Sbostic  *
1100*52891Sbostic  * Side effects:
1101*52891Sbostic  *	The cursor is loaded into the hardware cursor.
1102*52891Sbostic  *
1103*52891Sbostic  * ----------------------------------------------------------------------------
1104*52891Sbostic  */
1105*52891Sbostic static void
1106*52891Sbostic LoadCursor(cur)
1107*52891Sbostic 	unsigned short *cur;
1108*52891Sbostic {
1109*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1110*52891Sbostic 	register int i, j;
1111*52891Sbostic 
1112*52891Sbostic 	/*
1113*52891Sbostic 	 * As per specs, must run a check to see if we
1114*52891Sbostic 	 * had contention. If so, re-write the cursor.
1115*52891Sbostic 	 */
1116*52891Sbostic 	for (j = 0; j < 2; j++) {
1117*52891Sbostic 		/* loop once to write */
1118*52891Sbostic 		bt459_select_reg(regs, BT459_REG_CRAM_BASE);
1119*52891Sbostic 		for (i = 0; i < 1024; i++) {
1120*52891Sbostic 			regs->addr_reg = cur[i];
1121*52891Sbostic 			MachEmptyWriteBuffer();
1122*52891Sbostic 		}
1123*52891Sbostic 
1124*52891Sbostic 		/* loop to check, if fail write again */
1125*52891Sbostic 		bt459_select_reg(regs, BT459_REG_CRAM_BASE);
1126*52891Sbostic 		for (i = 0; i < 1024; i++)
1127*52891Sbostic 			if (regs->addr_reg != cur[i])
1128*52891Sbostic 				break;
1129*52891Sbostic 		if (i == 1024)
1130*52891Sbostic 			break;	/* all went well first shot */
1131*52891Sbostic 	}
1132*52891Sbostic }
1133*52891Sbostic 
1134*52891Sbostic /*
1135*52891Sbostic  * ----------------------------------------------------------------------------
1136*52891Sbostic  *
1137*52891Sbostic  * RestoreCursorColor --
1138*52891Sbostic  *
1139*52891Sbostic  *	Routine to restore the color of the cursor.
1140*52891Sbostic  *
1141*52891Sbostic  * Results:
1142*52891Sbostic  *	None.
1143*52891Sbostic  *
1144*52891Sbostic  * Side effects:
1145*52891Sbostic  *	None.
1146*52891Sbostic  *
1147*52891Sbostic  * ----------------------------------------------------------------------------
1148*52891Sbostic  */
1149*52891Sbostic static void
1150*52891Sbostic RestoreCursorColor()
1151*52891Sbostic {
1152*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1153*52891Sbostic 	register int i;
1154*52891Sbostic 
1155*52891Sbostic 	bt459_select_reg(regs, BT459_REG_CCOLOR_2);
1156*52891Sbostic 	for (i = 0; i < 6; i++) {
1157*52891Sbostic 		regs->addr_reg = cursor_RGB[i];
1158*52891Sbostic 		MachEmptyWriteBuffer();
1159*52891Sbostic 	}
1160*52891Sbostic }
1161*52891Sbostic 
1162*52891Sbostic /*
1163*52891Sbostic  * ----------------------------------------------------------------------------
1164*52891Sbostic  *
1165*52891Sbostic  * CursorColor --
1166*52891Sbostic  *
1167*52891Sbostic  *	Set the color of the cursor.
1168*52891Sbostic  *
1169*52891Sbostic  * Results:
1170*52891Sbostic  *	None.
1171*52891Sbostic  *
1172*52891Sbostic  * Side effects:
1173*52891Sbostic  *	None.
1174*52891Sbostic  *
1175*52891Sbostic  * ----------------------------------------------------------------------------
1176*52891Sbostic  */
1177*52891Sbostic static void
1178*52891Sbostic CursorColor(color)
1179*52891Sbostic 	unsigned int color[];
1180*52891Sbostic {
1181*52891Sbostic 	register int i, j;
1182*52891Sbostic 
1183*52891Sbostic 	for (i = 0; i < 6; i++)
1184*52891Sbostic 		cursor_RGB[i] = (u_char)(color[i] >> 8);
1185*52891Sbostic 
1186*52891Sbostic 	RestoreCursorColor();
1187*52891Sbostic }
1188*52891Sbostic 
1189*52891Sbostic /*
1190*52891Sbostic  *----------------------------------------------------------------------
1191*52891Sbostic  *
1192*52891Sbostic  * PosCursor --
1193*52891Sbostic  *
1194*52891Sbostic  *	Postion the cursor.
1195*52891Sbostic  *
1196*52891Sbostic  * Results:
1197*52891Sbostic  *	None.
1198*52891Sbostic  *
1199*52891Sbostic  * Side effects:
1200*52891Sbostic  *	None.
1201*52891Sbostic  *
1202*52891Sbostic  *----------------------------------------------------------------------
1203*52891Sbostic  */
1204*52891Sbostic static void
1205*52891Sbostic PosCursor(x, y)
1206*52891Sbostic 	register int x, y;
1207*52891Sbostic {
1208*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1209*52891Sbostic 
1210*52891Sbostic 	if (y < pmu.scrInfo.min_cur_y || y > pmu.scrInfo.max_cur_y)
1211*52891Sbostic 		y = pmu.scrInfo.max_cur_y;
1212*52891Sbostic 	if (x < pmu.scrInfo.min_cur_x || x > pmu.scrInfo.max_cur_x)
1213*52891Sbostic 		x = pmu.scrInfo.max_cur_x;
1214*52891Sbostic 	pmu.scrInfo.cursor.x = x;		/* keep track of real cursor */
1215*52891Sbostic 	pmu.scrInfo.cursor.y = y;		/* position, indep. of mouse */
1216*52891Sbostic 
1217*52891Sbostic 	x += 219;
1218*52891Sbostic 	y += 34;
1219*52891Sbostic 
1220*52891Sbostic 	bt459_select_reg(regs, BT459_REG_CXLO);
1221*52891Sbostic 	regs->addr_reg = x;
1222*52891Sbostic 	MachEmptyWriteBuffer();
1223*52891Sbostic 	regs->addr_reg = x >> 8;
1224*52891Sbostic 	MachEmptyWriteBuffer();
1225*52891Sbostic 	regs->addr_reg = y;
1226*52891Sbostic 	MachEmptyWriteBuffer();
1227*52891Sbostic 	regs->addr_reg = y >> 8;
1228*52891Sbostic 	MachEmptyWriteBuffer();
1229*52891Sbostic }
1230*52891Sbostic 
1231*52891Sbostic /*
1232*52891Sbostic  * ----------------------------------------------------------------------------
1233*52891Sbostic  *
1234*52891Sbostic  * InitColorMap --
1235*52891Sbostic  *
1236*52891Sbostic  *	Initialize the color map.
1237*52891Sbostic  *
1238*52891Sbostic  * Results:
1239*52891Sbostic  *	None.
1240*52891Sbostic  *
1241*52891Sbostic  * Side effects:
1242*52891Sbostic  *	The colormap is initialized appropriately.
1243*52891Sbostic  *
1244*52891Sbostic  * ----------------------------------------------------------------------------
1245*52891Sbostic  */
1246*52891Sbostic static void
1247*52891Sbostic InitColorMap()
1248*52891Sbostic {
1249*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1250*52891Sbostic 	register int i;
1251*52891Sbostic 
1252*52891Sbostic 	bt459_select_reg(regs, 0);
1253*52891Sbostic 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
1254*52891Sbostic 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
1255*52891Sbostic 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
1256*52891Sbostic 
1257*52891Sbostic 	for (i = 1; i < 256; i++) {
1258*52891Sbostic 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
1259*52891Sbostic 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
1260*52891Sbostic 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
1261*52891Sbostic 	}
1262*52891Sbostic 
1263*52891Sbostic 	for (i = 0; i < 3; i++) {
1264*52891Sbostic 		cursor_RGB[i] = 0x00;
1265*52891Sbostic 		cursor_RGB[i + 3] = 0xff;
1266*52891Sbostic 	}
1267*52891Sbostic 	RestoreCursorColor();
1268*52891Sbostic }
1269*52891Sbostic 
1270*52891Sbostic /*
1271*52891Sbostic  * ----------------------------------------------------------------------------
1272*52891Sbostic  *
1273*52891Sbostic  * LoadColorMap --
1274*52891Sbostic  *
1275*52891Sbostic  *	Load the color map.
1276*52891Sbostic  *
1277*52891Sbostic  * Results:
1278*52891Sbostic  *	None.
1279*52891Sbostic  *
1280*52891Sbostic  * Side effects:
1281*52891Sbostic  *	The color map is loaded.
1282*52891Sbostic  *
1283*52891Sbostic  * ----------------------------------------------------------------------------
1284*52891Sbostic  */
1285*52891Sbostic static void
1286*52891Sbostic LoadColorMap(ptr)
1287*52891Sbostic 	ColorMap *ptr;
1288*52891Sbostic {
1289*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1290*52891Sbostic 
1291*52891Sbostic 	if (ptr->index > 256)
1292*52891Sbostic 		return;
1293*52891Sbostic 
1294*52891Sbostic 	bt459_select_reg(regs, ptr->index);
1295*52891Sbostic 
1296*52891Sbostic 	regs->addr_cmap = ptr->Entry.red; MachEmptyWriteBuffer();
1297*52891Sbostic 	regs->addr_cmap = ptr->Entry.green; MachEmptyWriteBuffer();
1298*52891Sbostic 	regs->addr_cmap = ptr->Entry.blue; MachEmptyWriteBuffer();
1299*52891Sbostic }
1300*52891Sbostic 
1301*52891Sbostic /*
1302*52891Sbostic  * Video on/off state.
1303*52891Sbostic  */
1304*52891Sbostic struct vstate {
1305*52891Sbostic 	u_char	color0[3];	/* saved color map entry zero */
1306*52891Sbostic 	u_char	off;		/* TRUE if display is off */
1307*52891Sbostic } vstate;
1308*52891Sbostic 
1309*52891Sbostic /*
1310*52891Sbostic  * ----------------------------------------------------------------------------
1311*52891Sbostic  *
1312*52891Sbostic  * EnableVideo --
1313*52891Sbostic  *
1314*52891Sbostic  *	Enable the video display.
1315*52891Sbostic  *
1316*52891Sbostic  * Results:
1317*52891Sbostic  *	None.
1318*52891Sbostic  *
1319*52891Sbostic  * Side effects:
1320*52891Sbostic  *	The display is enabled.
1321*52891Sbostic  *
1322*52891Sbostic  * ----------------------------------------------------------------------------
1323*52891Sbostic  */
1324*52891Sbostic static void
1325*52891Sbostic EnableVideo()
1326*52891Sbostic {
1327*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1328*52891Sbostic 
1329*52891Sbostic 	if (!vstate.off)
1330*52891Sbostic 		return;
1331*52891Sbostic 
1332*52891Sbostic 	/* restore old color map entry zero */
1333*52891Sbostic 	bt459_select_reg(regs, 0);
1334*52891Sbostic 	regs->addr_cmap = vstate.color0[0];
1335*52891Sbostic 	MachEmptyWriteBuffer();
1336*52891Sbostic 	regs->addr_cmap = vstate.color0[1];
1337*52891Sbostic 	MachEmptyWriteBuffer();
1338*52891Sbostic 	regs->addr_cmap = vstate.color0[2];
1339*52891Sbostic 	MachEmptyWriteBuffer();
1340*52891Sbostic 
1341*52891Sbostic 	/* enable normal display */
1342*52891Sbostic 	bt459_write_reg(regs, BT459_REG_PRM, 0xff);
1343*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CCR, 0xc0);
1344*52891Sbostic 
1345*52891Sbostic 	vstate.off = 0;
1346*52891Sbostic }
1347*52891Sbostic 
1348*52891Sbostic /*
1349*52891Sbostic  * ----------------------------------------------------------------------------
1350*52891Sbostic  *
1351*52891Sbostic  * DisableVideo --
1352*52891Sbostic  *
1353*52891Sbostic  *	Disable the video display.
1354*52891Sbostic  *
1355*52891Sbostic  * Results:
1356*52891Sbostic  *	None.
1357*52891Sbostic  *
1358*52891Sbostic  * Side effects:
1359*52891Sbostic  *	The display is disabled.
1360*52891Sbostic  *
1361*52891Sbostic  * ----------------------------------------------------------------------------
1362*52891Sbostic  */
1363*52891Sbostic static void
1364*52891Sbostic DisableVideo()
1365*52891Sbostic {
1366*52891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
1367*52891Sbostic 
1368*52891Sbostic 	if (vstate.off)
1369*52891Sbostic 		return;
1370*52891Sbostic 
1371*52891Sbostic 	/* save old color map entry zero */
1372*52891Sbostic 	bt459_select_reg(regs, 0);
1373*52891Sbostic 	vstate.color0[0] = regs->addr_cmap;
1374*52891Sbostic 	vstate.color0[1] = regs->addr_cmap;
1375*52891Sbostic 	vstate.color0[2] = regs->addr_cmap;
1376*52891Sbostic 
1377*52891Sbostic 	/* set color map entry zero to zero */
1378*52891Sbostic 	bt459_select_reg(regs, 0);
1379*52891Sbostic 	regs->addr_cmap = 0;
1380*52891Sbostic 	MachEmptyWriteBuffer();
1381*52891Sbostic 	regs->addr_cmap = 0;
1382*52891Sbostic 	MachEmptyWriteBuffer();
1383*52891Sbostic 	regs->addr_cmap = 0;
1384*52891Sbostic 	MachEmptyWriteBuffer();
1385*52891Sbostic 
1386*52891Sbostic 	/* disable display */
1387*52891Sbostic 	bt459_write_reg(regs, BT459_REG_PRM, 0);
1388*52891Sbostic 	bt459_write_reg(regs, BT459_REG_CCR, 0);
1389*52891Sbostic 
1390*52891Sbostic 	vstate.off = 1;
1391*52891Sbostic }
1392*52891Sbostic #endif
1393