xref: /csrg-svn/sys/pmax/dev/cfb.c (revision 52959)
152891Sbostic /*-
252891Sbostic  * Copyright (c) 1992 The Regents of the University of California.
352891Sbostic  * All rights reserved.
452891Sbostic  *
552891Sbostic  * This code is derived from software contributed to Berkeley by
652891Sbostic  * Ralph Campbell.
752891Sbostic  *
852891Sbostic  * %sccs.include.redist.c%
952891Sbostic  *
10*52959Sralph  *	@(#)cfb.c	7.2 (Berkeley) 03/15/92
1152891Sbostic  */
1252891Sbostic 
1352891Sbostic /*
1452891Sbostic  *  devGraphics.c --
1552891Sbostic  *
1652891Sbostic  *     	This file contains machine-dependent routines for the graphics device.
1752891Sbostic  *
1852891Sbostic  *	Copyright (C) 1989 Digital Equipment Corporation.
1952891Sbostic  *	Permission to use, copy, modify, and distribute this software and
2052891Sbostic  *	its documentation for any purpose and without fee is hereby granted,
2152891Sbostic  *	provided that the above copyright notice appears in all copies.
2252891Sbostic  *	Digital Equipment Corporation makes no representations about the
2352891Sbostic  *	suitability of this software for any purpose.  It is provided "as is"
2452891Sbostic  *	without express or implied warranty.
2552891Sbostic  *
2652891Sbostic  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
2752891Sbostic  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
2852891Sbostic  */
2952891Sbostic /*
3052891Sbostic  * Mach Operating System
3152891Sbostic  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
3252891Sbostic  * All Rights Reserved.
3352891Sbostic  *
3452891Sbostic  * Permission to use, copy, modify and distribute this software and its
3552891Sbostic  * documentation is hereby granted, provided that both the copyright
3652891Sbostic  * notice and this permission notice appear in all copies of the
3752891Sbostic  * software, derivative works or modified versions, and any portions
3852891Sbostic  * thereof, and that both notices appear in supporting documentation.
3952891Sbostic  *
4052891Sbostic  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
4152891Sbostic  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
4252891Sbostic  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
4352891Sbostic  *
4452891Sbostic  * Carnegie Mellon requests users of this software to return to
4552891Sbostic  *
4652891Sbostic  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
4752891Sbostic  *  School of Computer Science
4852891Sbostic  *  Carnegie Mellon University
4952891Sbostic  *  Pittsburgh PA 15213-3890
5052891Sbostic  *
5152891Sbostic  * any improvements or extensions that they make and grant Carnegie the
5252891Sbostic  * rights to redistribute these changes.
5352891Sbostic  */
5452891Sbostic 
5552891Sbostic #include "cfb.h"
5652891Sbostic #if NCFB > 0
5752891Sbostic 
5852891Sbostic /*
5952891Sbostic  * This is a device driver for the PMAG-BA color frame buffer
6052891Sbostic  * on the TURBOchannel.
6152891Sbostic  * XXX This is just to get a console working;
6252891Sbostic  *	it will need changes to work with X11R5.
6352891Sbostic  */
6452891Sbostic 
6552891Sbostic #include "param.h"
6652891Sbostic #include "time.h"
6752891Sbostic #include "kernel.h"
6852891Sbostic #include "ioctl.h"
6952891Sbostic #include "file.h"
7052891Sbostic #include "errno.h"
7152891Sbostic #include "proc.h"
7252891Sbostic #include "mman.h"
7352891Sbostic #include "vm/vm.h"
7452891Sbostic 
7552891Sbostic #include "machine/machConst.h"
7652891Sbostic #include "machine/machMon.h"
7752891Sbostic #include "machine/dc7085cons.h"
7852891Sbostic #include "machine/pmioctl.h"
7952891Sbostic 
8052891Sbostic #include "device.h"
8152891Sbostic #include "cfbreg.h"
8252891Sbostic #include "font.c"
8352891Sbostic 
8452891Sbostic #define MAX_ROW	56
8552891Sbostic #define MAX_COL	80
8652891Sbostic 
8752891Sbostic /*
8852891Sbostic  * Macro to translate from a time struct to milliseconds.
8952891Sbostic  */
9052891Sbostic #define TO_MS(tv) ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))
9152891Sbostic 
9252891Sbostic static int	isMono;		/* true if B&W frame buffer */
9352891Sbostic static int	initialized;	/* true if 'probe' was successful */
9452891Sbostic static int	GraphicsOpen;	/* true if the graphics device is open */
9552891Sbostic static int	row, col;	/* row and col for console cursor */
9652891Sbostic static struct	selinfo cfb_selp;	/* process waiting for select */
9752891Sbostic static unsigned	fb_addr;	/* frame buffer kernel virtual address */
9852891Sbostic static unsigned	planemask_addr;	/* plane mask kernel virtual address */
9952891Sbostic 
10052891Sbostic /*
10152891Sbostic  * These need to be mapped into user space.
10252891Sbostic  */
10352891Sbostic static struct pmuaccess {
10452891Sbostic 	PM_Info		scrInfo;
10552891Sbostic 	pmEvent		events[PM_MAXEVQ];
10652891Sbostic 	pmTimeCoord	tcs[MOTION_BUFFER_SIZE];
10752891Sbostic } pmu;
10852891Sbostic 
10952891Sbostic /*
11052891Sbostic  * Font mask bits used by Blitc().
11152891Sbostic  */
11252891Sbostic static unsigned int fontmaskBits[16] = {
11352891Sbostic 	0x00000000,
11452891Sbostic 	0x00000001,
11552891Sbostic 	0x00000100,
11652891Sbostic 	0x00000101,
11752891Sbostic 	0x00010000,
11852891Sbostic 	0x00010001,
11952891Sbostic 	0x00010100,
12052891Sbostic 	0x00010101,
12152891Sbostic 	0x01000000,
12252891Sbostic 	0x01000001,
12352891Sbostic 	0x01000100,
12452891Sbostic 	0x01000101,
12552891Sbostic 	0x01010000,
12652891Sbostic 	0x01010001,
12752891Sbostic 	0x01010100,
12852891Sbostic 	0x01010101
12952891Sbostic };
13052891Sbostic 
13152891Sbostic /*
13252891Sbostic  * Forward references.
13352891Sbostic  */
13452891Sbostic static void Scroll();
13552891Sbostic static void Blitc();
13652891Sbostic 
13752891Sbostic static void ScreenInit();
13852891Sbostic static void LoadCursor();
13952891Sbostic static void RestoreCursorColor();
14052891Sbostic static void CursorColor();
14152891Sbostic static void PosCursor();
14252891Sbostic static void InitColorMap();
14352891Sbostic static void LoadColorMap();
14452891Sbostic static void EnableVideo();
14552891Sbostic static void DisableVideo();
14652891Sbostic 
14752891Sbostic extern void dcKBDPutc();
14852891Sbostic extern void (*dcDivertXInput)();
14952891Sbostic extern void (*dcMouseEvent)();
15052891Sbostic extern void (*dcMouseButtons)();
15152891Sbostic 
15252891Sbostic int	cfbprobe();
15352891Sbostic struct	driver cfbdriver = {
15452891Sbostic 	"cfb", cfbprobe, 0, 0,
15552891Sbostic };
15652891Sbostic 
15752891Sbostic /*
15852891Sbostic  * Test to see if device is present.
15952891Sbostic  * Return true if found and initialized ok.
16052891Sbostic  */
16152891Sbostic cfbprobe(cp)
16252891Sbostic 	register struct pmax_ctlr *cp;
16352891Sbostic {
16452891Sbostic 
16552891Sbostic 	if (!initialized) {
16652891Sbostic 		if (!cfb_init(cp))
16752891Sbostic 			return (0);
16852891Sbostic 	}
16952891Sbostic 	printf("cfb%d at nexus0 csr 0x%x priority %d\n",
17052891Sbostic 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
17152891Sbostic 	return (1);
17252891Sbostic }
17352891Sbostic 
17452891Sbostic /*
17552891Sbostic  *----------------------------------------------------------------------
17652891Sbostic  *
17752891Sbostic  * cfbKbdEvent --
17852891Sbostic  *
17952891Sbostic  *	Process a received character.
18052891Sbostic  *
18152891Sbostic  * Results:
18252891Sbostic  *	None.
18352891Sbostic  *
18452891Sbostic  * Side effects:
18552891Sbostic  *	Events added to the queue.
18652891Sbostic  *
18752891Sbostic  *----------------------------------------------------------------------
18852891Sbostic  */
18952891Sbostic void
19052891Sbostic cfbKbdEvent(ch)
19152891Sbostic 	int ch;
19252891Sbostic {
19352891Sbostic 	register pmEvent *eventPtr;
19452891Sbostic 	int i;
19552891Sbostic 
19652891Sbostic 	if (!GraphicsOpen)
19752891Sbostic 		return;
19852891Sbostic 
19952891Sbostic 	/*
20052891Sbostic 	 * See if there is room in the queue.
20152891Sbostic 	 */
20252891Sbostic 	i = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
20352891Sbostic 	if (i == pmu.scrInfo.qe.eHead)
20452891Sbostic 		return;
20552891Sbostic 
20652891Sbostic 	/*
20752891Sbostic 	 * Add the event to the queue.
20852891Sbostic 	 */
20952891Sbostic 	eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
21052891Sbostic 	eventPtr->type = BUTTON_RAW_TYPE;
21152891Sbostic 	eventPtr->device = KEYBOARD_DEVICE;
21252891Sbostic 	eventPtr->x = pmu.scrInfo.mouse.x;
21352891Sbostic 	eventPtr->y = pmu.scrInfo.mouse.y;
21452891Sbostic 	eventPtr->time = TO_MS(time);
21552891Sbostic 	eventPtr->key = ch;
21652891Sbostic 	pmu.scrInfo.qe.eTail = i;
21752891Sbostic 	selwakeup(&cfb_selp);
21852891Sbostic }
21952891Sbostic 
22052891Sbostic /*
22152891Sbostic  *----------------------------------------------------------------------
22252891Sbostic  *
22352891Sbostic  * cfbMouseEvent --
22452891Sbostic  *
22552891Sbostic  *	Process a mouse event.
22652891Sbostic  *
22752891Sbostic  * Results:
22852891Sbostic  *	None.
22952891Sbostic  *
23052891Sbostic  * Side effects:
23152891Sbostic  *	An event is added to the event queue.
23252891Sbostic  *
23352891Sbostic  *----------------------------------------------------------------------
23452891Sbostic  */
23552891Sbostic void
23652891Sbostic cfbMouseEvent(newRepPtr)
23752891Sbostic 	register MouseReport *newRepPtr;
23852891Sbostic {
23952891Sbostic 	unsigned milliSec;
24052891Sbostic 	int i;
24152891Sbostic 	pmEvent *eventPtr;
24252891Sbostic 
24352891Sbostic 	if (!GraphicsOpen)
24452891Sbostic 		return;
24552891Sbostic 
24652891Sbostic 	milliSec = TO_MS(time);
24752891Sbostic 
24852891Sbostic 	/*
24952891Sbostic 	 * Check to see if we have to accelerate the mouse
25052891Sbostic 	 */
25152891Sbostic 	if (pmu.scrInfo.mscale >= 0) {
25252891Sbostic 		if (newRepPtr->dx >= pmu.scrInfo.mthreshold) {
25352891Sbostic 			newRepPtr->dx +=
25452891Sbostic 				(newRepPtr->dx - pmu.scrInfo.mthreshold) *
25552891Sbostic 				pmu.scrInfo.mscale;
25652891Sbostic 		}
25752891Sbostic 		if (newRepPtr->dy >= pmu.scrInfo.mthreshold) {
25852891Sbostic 			newRepPtr->dy +=
25952891Sbostic 				(newRepPtr->dy - pmu.scrInfo.mthreshold) *
26052891Sbostic 				pmu.scrInfo.mscale;
26152891Sbostic 		}
26252891Sbostic 	}
26352891Sbostic 
26452891Sbostic 	/*
26552891Sbostic 	 * Update mouse position
26652891Sbostic 	 */
26752891Sbostic 	if (newRepPtr->state & MOUSE_X_SIGN) {
26852891Sbostic 		pmu.scrInfo.mouse.x += newRepPtr->dx;
26952891Sbostic 		if (pmu.scrInfo.mouse.x > pmu.scrInfo.max_cur_x)
27052891Sbostic 			pmu.scrInfo.mouse.x = pmu.scrInfo.max_cur_x;
27152891Sbostic 	} else {
27252891Sbostic 		pmu.scrInfo.mouse.x -= newRepPtr->dx;
27352891Sbostic 		if (pmu.scrInfo.mouse.x < pmu.scrInfo.min_cur_x)
27452891Sbostic 			pmu.scrInfo.mouse.x = pmu.scrInfo.min_cur_x;
27552891Sbostic 	}
27652891Sbostic 	if (newRepPtr->state & MOUSE_Y_SIGN) {
27752891Sbostic 		pmu.scrInfo.mouse.y -= newRepPtr->dy;
27852891Sbostic 		if (pmu.scrInfo.mouse.y < pmu.scrInfo.min_cur_y)
27952891Sbostic 			pmu.scrInfo.mouse.y = pmu.scrInfo.min_cur_y;
28052891Sbostic 	} else {
28152891Sbostic 		pmu.scrInfo.mouse.y += newRepPtr->dy;
28252891Sbostic 		if (pmu.scrInfo.mouse.y > pmu.scrInfo.max_cur_y)
28352891Sbostic 			pmu.scrInfo.mouse.y = pmu.scrInfo.max_cur_y;
28452891Sbostic 	}
28552891Sbostic 
28652891Sbostic 	/*
28752891Sbostic 	 * Move the hardware cursor.
28852891Sbostic 	 */
28952891Sbostic 	PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
29052891Sbostic 
29152891Sbostic 	/*
29252891Sbostic 	 * Store the motion event in the motion buffer.
29352891Sbostic 	 */
29452891Sbostic 	pmu.tcs[pmu.scrInfo.qe.tcNext].time = milliSec;
29552891Sbostic 	pmu.tcs[pmu.scrInfo.qe.tcNext].x = pmu.scrInfo.mouse.x;
29652891Sbostic 	pmu.tcs[pmu.scrInfo.qe.tcNext].y = pmu.scrInfo.mouse.y;
29752891Sbostic 	if (++pmu.scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE)
29852891Sbostic 		pmu.scrInfo.qe.tcNext = 0;
29952891Sbostic 	if (pmu.scrInfo.mouse.y < pmu.scrInfo.mbox.bottom &&
30052891Sbostic 	    pmu.scrInfo.mouse.y >=  pmu.scrInfo.mbox.top &&
30152891Sbostic 	    pmu.scrInfo.mouse.x < pmu.scrInfo.mbox.right &&
30252891Sbostic 	    pmu.scrInfo.mouse.x >=  pmu.scrInfo.mbox.left)
30352891Sbostic 		return;
30452891Sbostic 
30552891Sbostic 	pmu.scrInfo.mbox.bottom = 0;
30652891Sbostic 	if (PM_EVROUND(pmu.scrInfo.qe.eTail + 1) == pmu.scrInfo.qe.eHead)
30752891Sbostic 		return;
30852891Sbostic 
30952891Sbostic 	i = PM_EVROUND(pmu.scrInfo.qe.eTail - 1);
31052891Sbostic 	if ((pmu.scrInfo.qe.eTail != pmu.scrInfo.qe.eHead) &&
31152891Sbostic 	    (i != pmu.scrInfo.qe.eHead)) {
31252891Sbostic 		pmEvent *eventPtr;
31352891Sbostic 
31452891Sbostic 		eventPtr = &pmu.events[i];
31552891Sbostic 		if (eventPtr->type == MOTION_TYPE) {
31652891Sbostic 			eventPtr->x = pmu.scrInfo.mouse.x;
31752891Sbostic 			eventPtr->y = pmu.scrInfo.mouse.y;
31852891Sbostic 			eventPtr->time = milliSec;
31952891Sbostic 			eventPtr->device = MOUSE_DEVICE;
32052891Sbostic 			return;
32152891Sbostic 		}
32252891Sbostic 	}
32352891Sbostic 	/*
32452891Sbostic 	 * Put event into queue and wakeup any waiters.
32552891Sbostic 	 */
32652891Sbostic 	eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
32752891Sbostic 	eventPtr->type = MOTION_TYPE;
32852891Sbostic 	eventPtr->time = milliSec;
32952891Sbostic 	eventPtr->x = pmu.scrInfo.mouse.x;
33052891Sbostic 	eventPtr->y = pmu.scrInfo.mouse.y;
33152891Sbostic 	eventPtr->device = MOUSE_DEVICE;
33252891Sbostic 	pmu.scrInfo.qe.eTail = PM_EVROUND(pmu.scrInfo.qe.eTail + 1);
33352891Sbostic 	selwakeup(&cfb_selp);
33452891Sbostic }
33552891Sbostic 
33652891Sbostic /*
33752891Sbostic  *----------------------------------------------------------------------
33852891Sbostic  *
33952891Sbostic  * cfbMouseButtons --
34052891Sbostic  *
34152891Sbostic  *	Process mouse buttons.
34252891Sbostic  *
34352891Sbostic  * Results:
34452891Sbostic  *	None.
34552891Sbostic  *
34652891Sbostic  * Side effects:
34752891Sbostic  *	None.
34852891Sbostic  *
34952891Sbostic  *----------------------------------------------------------------------
35052891Sbostic  */
35152891Sbostic void
35252891Sbostic cfbMouseButtons(newRepPtr)
35352891Sbostic 	MouseReport *newRepPtr;
35452891Sbostic {
35552891Sbostic 	static char temp, oldSwitch, newSwitch;
35652891Sbostic 	int i, j;
35752891Sbostic 	pmEvent *eventPtr;
35852891Sbostic 	static MouseReport lastRep;
35952891Sbostic 
36052891Sbostic 	if (!GraphicsOpen)
36152891Sbostic 		return;
36252891Sbostic 
36352891Sbostic 	newSwitch = newRepPtr->state & 0x07;
36452891Sbostic 	oldSwitch = lastRep.state & 0x07;
36552891Sbostic 
36652891Sbostic 	temp = oldSwitch ^ newSwitch;
36752891Sbostic 	if (temp == 0)
36852891Sbostic 		return;
36952891Sbostic 	for (j = 1; j < 8; j <<= 1) {
37052891Sbostic 		if ((j & temp) == 0)
37152891Sbostic 			continue;
37252891Sbostic 
37352891Sbostic 		/*
37452891Sbostic 		 * Check for room in the queue
37552891Sbostic 		 */
37652891Sbostic 		i = PM_EVROUND(pmu.scrInfo.qe.eTail+1);
37752891Sbostic 		if (i == pmu.scrInfo.qe.eHead)
37852891Sbostic 			return;
37952891Sbostic 
38052891Sbostic 		/*
38152891Sbostic 		 * Put event into queue.
38252891Sbostic 		 */
38352891Sbostic 		eventPtr = &pmu.events[pmu.scrInfo.qe.eTail];
38452891Sbostic 
38552891Sbostic 		switch (j) {
38652891Sbostic 		case RIGHT_BUTTON:
38752891Sbostic 			eventPtr->key = EVENT_RIGHT_BUTTON;
38852891Sbostic 			break;
38952891Sbostic 
39052891Sbostic 		case MIDDLE_BUTTON:
39152891Sbostic 			eventPtr->key = EVENT_MIDDLE_BUTTON;
39252891Sbostic 			break;
39352891Sbostic 
39452891Sbostic 		case LEFT_BUTTON:
39552891Sbostic 			eventPtr->key = EVENT_LEFT_BUTTON;
39652891Sbostic 		}
39752891Sbostic 		if (newSwitch & j)
39852891Sbostic 			eventPtr->type = BUTTON_DOWN_TYPE;
39952891Sbostic 		else
40052891Sbostic 			eventPtr->type = BUTTON_UP_TYPE;
40152891Sbostic 		eventPtr->device = MOUSE_DEVICE;
40252891Sbostic 
40352891Sbostic 		eventPtr->time = TO_MS(time);
40452891Sbostic 		eventPtr->x = pmu.scrInfo.mouse.x;
40552891Sbostic 		eventPtr->y = pmu.scrInfo.mouse.y;
40652891Sbostic 	}
40752891Sbostic 	pmu.scrInfo.qe.eTail = i;
40852891Sbostic 	selwakeup(&cfb_selp);
40952891Sbostic 
41052891Sbostic 	lastRep = *newRepPtr;
41152891Sbostic 	pmu.scrInfo.mswitches = newSwitch;
41252891Sbostic }
41352891Sbostic 
41452891Sbostic /*
41552891Sbostic  *----------------------------------------------------------------------
41652891Sbostic  *
41752891Sbostic  * Scroll --
41852891Sbostic  *
41952891Sbostic  *	Scroll the screen.
42052891Sbostic  *
42152891Sbostic  * Results:
42252891Sbostic  *	None.
42352891Sbostic  *
42452891Sbostic  * Side effects:
42552891Sbostic  *	None.
42652891Sbostic  *
42752891Sbostic  *----------------------------------------------------------------------
42852891Sbostic  */
42952891Sbostic static void
43052891Sbostic Scroll()
43152891Sbostic {
43252891Sbostic 	register int *dest, *src;
43352891Sbostic 	register int *end;
43452891Sbostic 	register int temp0, temp1, temp2, temp3;
43552891Sbostic 	register int i, scanInc, lineCount;
43652891Sbostic 	int line;
43752891Sbostic 
43852891Sbostic 	/*
43952891Sbostic 	 * If the mouse is on we don't scroll so that the bit map remains sane.
44052891Sbostic 	 */
44152891Sbostic 	if (GraphicsOpen) {
44252891Sbostic 		row = 0;
44352891Sbostic 		return;
44452891Sbostic 	}
44552891Sbostic 
44652891Sbostic 	/*
44752891Sbostic 	 *  The following is an optimization to cause the scrolling
44852891Sbostic 	 *  of text to be memory limited.  Basically the writebuffer is
44952891Sbostic 	 *  4 words (32 bits ea.) long so to achieve maximum speed we
45052891Sbostic 	 *  read and write in multiples of 4 words. We also limit the
45152891Sbostic 	 *  size to be MAX_COL characters for more speed.
45252891Sbostic 	 */
45352891Sbostic 	if (isMono) {
45452891Sbostic 		lineCount = 5;
45552891Sbostic 		line = 1920 * 2;
45652891Sbostic 		scanInc = 44;
45752891Sbostic 	} else {
45852891Sbostic 		lineCount = 40;
45952891Sbostic 		scanInc = 96;
46052891Sbostic 		line = 1920 * 8;
46152891Sbostic 	}
46252891Sbostic 	src = (int *)(fb_addr + line);
46352891Sbostic 	dest = (int *)(fb_addr);
46452891Sbostic 	end = (int *)(fb_addr + (60 * line) - line);
46552891Sbostic 	do {
46652891Sbostic 		i = 0;
46752891Sbostic 		do {
46852891Sbostic 			temp0 = src[0];
46952891Sbostic 			temp1 = src[1];
47052891Sbostic 			temp2 = src[2];
47152891Sbostic 			temp3 = src[3];
47252891Sbostic 			dest[0] = temp0;
47352891Sbostic 			dest[1] = temp1;
47452891Sbostic 			dest[2] = temp2;
47552891Sbostic 			dest[3] = temp3;
47652891Sbostic 			dest += 4;
47752891Sbostic 			src += 4;
47852891Sbostic 			i++;
47952891Sbostic 		} while (i < lineCount);
48052891Sbostic 		src += scanInc;
48152891Sbostic 		dest += scanInc;
48252891Sbostic 	} while (src < end);
48352891Sbostic 
48452891Sbostic 	/*
48552891Sbostic 	 * Now zero out the last two lines
48652891Sbostic 	 */
48752891Sbostic 	bzero(fb_addr + (row * line), 3 * line);
48852891Sbostic }
48952891Sbostic 
49052891Sbostic /*
49152891Sbostic  *----------------------------------------------------------------------
49252891Sbostic  *
49352891Sbostic  * cfbPutc --
49452891Sbostic  *
49552891Sbostic  *	Write a character to the console.
49652891Sbostic  *
49752891Sbostic  * Results:
49852891Sbostic  *	None.
49952891Sbostic  *
50052891Sbostic  * Side effects:
50152891Sbostic  *	None.
50252891Sbostic  *
50352891Sbostic  *----------------------------------------------------------------------
50452891Sbostic  */
50552891Sbostic cfbPutc(c)
50652891Sbostic 	register int c;
50752891Sbostic {
50852891Sbostic 	int s;
50952891Sbostic 
51052891Sbostic 	s = splhigh();	/* in case we do any printf's at interrupt time */
51152891Sbostic 	if (initialized) {
51252891Sbostic #ifdef DEBUG
51352891Sbostic 		/*
51452891Sbostic 		 * If the HELP key is pressed, wait for another
51552891Sbostic 		 * HELP key press to start/stop output.
51652891Sbostic 		 */
51752891Sbostic 		if (dcDebugGetc() == LK_HELP) {
51852891Sbostic 			while (dcDebugGetc() != LK_HELP)
51952891Sbostic 				;
52052891Sbostic 		}
52152891Sbostic #endif
52252891Sbostic 		Blitc(c);
52352891Sbostic 	} else {
52452891Sbostic 		void (*f)() = (void (*)())MACH_MON_PUTCHAR;
52552891Sbostic 
52652891Sbostic 		(*f)(c);
52752891Sbostic 	}
52852891Sbostic 	splx(s);
52952891Sbostic }
53052891Sbostic 
53152891Sbostic /*
53252891Sbostic  *----------------------------------------------------------------------
53352891Sbostic  *
53452891Sbostic  * Blitc --
53552891Sbostic  *
53652891Sbostic  *	Write a character to the screen.
53752891Sbostic  *
53852891Sbostic  * Results:
53952891Sbostic  *	None.
54052891Sbostic  *
54152891Sbostic  * Side effects:
54252891Sbostic  *	None.
54352891Sbostic  *
54452891Sbostic  *----------------------------------------------------------------------
54552891Sbostic  */
54652891Sbostic static void
54752891Sbostic Blitc(c)
54852891Sbostic 	register int c;
54952891Sbostic {
55052891Sbostic 	register char *bRow, *fRow;
55152891Sbostic 	register int i;
55252891Sbostic 	register int ote = isMono ? 256 : 1024; /* offset to table entry */
55352891Sbostic 	int colMult = isMono ? 1 : 8;
55452891Sbostic 
55552891Sbostic 	c &= 0xff;
55652891Sbostic 
55752891Sbostic 	switch (c) {
55852891Sbostic 	case '\t':
55952891Sbostic 		for (i = 8 - (col & 0x7); i > 0; i--)
56052891Sbostic 			Blitc(' ');
56152891Sbostic 		break;
56252891Sbostic 
56352891Sbostic 	case '\r':
56452891Sbostic 		col = 0;
56552891Sbostic 		break;
56652891Sbostic 
56752891Sbostic 	case '\b':
56852891Sbostic 		col--;
56952891Sbostic 		if (col < 0)
57052891Sbostic 			col = 0;
57152891Sbostic 		break;
57252891Sbostic 
57352891Sbostic 	case '\n':
57452891Sbostic 		if (row + 1 >= MAX_ROW)
57552891Sbostic 			Scroll();
57652891Sbostic 		else
57752891Sbostic 			row++;
57852891Sbostic 		col = 0;
57952891Sbostic 		break;
58052891Sbostic 
58152891Sbostic 	case '\007':
58252891Sbostic 		dcKBDPutc(LK_RING_BELL);
58352891Sbostic 		break;
58452891Sbostic 
58552891Sbostic 	default:
58652891Sbostic 		/*
58752891Sbostic 		 * 0xA1 to 0xFD are the printable characters added with 8-bit
58852891Sbostic 		 * support.
58952891Sbostic 		 */
59052891Sbostic 		if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD)
59152891Sbostic 			break;
59252891Sbostic 		/*
59352891Sbostic 		 * If the next character will wrap around then
59452891Sbostic 		 * increment row counter or scroll screen.
59552891Sbostic 		 */
59652891Sbostic 		if (col >= MAX_COL) {
59752891Sbostic 			col = 0;
59852891Sbostic 			if (row + 1 >= MAX_ROW)
59952891Sbostic 				Scroll();
60052891Sbostic 			else
60152891Sbostic 				row++;
60252891Sbostic 		}
60352891Sbostic 		bRow = (char *)(fb_addr +
60452891Sbostic 			(row * 15 & 0x3ff) * ote + col * colMult);
60552891Sbostic 		i = c - ' ';
60652891Sbostic 		/*
60752891Sbostic 		 * This is to skip the (32) 8-bit
60852891Sbostic 		 * control chars, as well as DEL
60952891Sbostic 		 * and 0xA0 which aren't printable
61052891Sbostic 		 */
61152891Sbostic 		if (c > '~')
61252891Sbostic 			i -= 34;
61352891Sbostic 		i *= 15;
61452891Sbostic 		fRow = (char *)((int)pmFont + i);
61552891Sbostic 
61652891Sbostic 		/* inline expansion for speed */
61752891Sbostic 		if (isMono) {
61852891Sbostic 			*bRow = *fRow++; bRow += ote;
61952891Sbostic 			*bRow = *fRow++; bRow += ote;
62052891Sbostic 			*bRow = *fRow++; bRow += ote;
62152891Sbostic 			*bRow = *fRow++; bRow += ote;
62252891Sbostic 			*bRow = *fRow++; bRow += ote;
62352891Sbostic 			*bRow = *fRow++; bRow += ote;
62452891Sbostic 			*bRow = *fRow++; bRow += ote;
62552891Sbostic 			*bRow = *fRow++; bRow += ote;
62652891Sbostic 			*bRow = *fRow++; bRow += ote;
62752891Sbostic 			*bRow = *fRow++; bRow += ote;
62852891Sbostic 			*bRow = *fRow++; bRow += ote;
62952891Sbostic 			*bRow = *fRow++; bRow += ote;
63052891Sbostic 			*bRow = *fRow++; bRow += ote;
63152891Sbostic 			*bRow = *fRow++; bRow += ote;
63252891Sbostic 			*bRow = *fRow++; bRow += ote;
63352891Sbostic 		} else {
63452891Sbostic 			register int j;
63552891Sbostic 			register unsigned int *pInt;
63652891Sbostic 
63752891Sbostic 			pInt = (unsigned int *)bRow;
63852891Sbostic 			for (j = 0; j < 15; j++) {
63952891Sbostic 				/*
64052891Sbostic 				 * fontmaskBits converts a nibble
64152891Sbostic 				 * (4 bytes) to a long word
64252891Sbostic 				 * containing 4 pixels corresponding
64352891Sbostic 				 * to each bit in the nibble.  Thus
64452891Sbostic 				 * we write two longwords for each
64552891Sbostic 				 * byte in font.
64652891Sbostic 				 *
64752891Sbostic 				 * Remember the font is 8 bits wide
64852891Sbostic 				 * and 15 bits high.
64952891Sbostic 				 *
65052891Sbostic 				 * We add 256 to the pointer to
65152891Sbostic 				 * point to the pixel on the
65252891Sbostic 				 * next scan line
65352891Sbostic 				 * directly below the current
65452891Sbostic 				 * pixel.
65552891Sbostic 				 */
65652891Sbostic 				pInt[0] = fontmaskBits[(*fRow) & 0xf];
65752891Sbostic 				pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf];
65852891Sbostic 				fRow++;
65952891Sbostic 				pInt += 256;
66052891Sbostic 			}
66152891Sbostic 		}
66252891Sbostic 		col++; /* increment column counter */
66352891Sbostic 	}
66452891Sbostic 	if (!GraphicsOpen)
66552891Sbostic 		PosCursor(col * 8, row * 15);
66652891Sbostic }
66752891Sbostic 
66852891Sbostic /*ARGSUSED*/
66952891Sbostic cfbopen(dev, flag)
67052891Sbostic 	dev_t dev;
67152891Sbostic 	int flag;
67252891Sbostic {
67352891Sbostic 
67452891Sbostic 	if (!initialized)
67552891Sbostic 		return (ENXIO);
67652891Sbostic 	if (GraphicsOpen)
67752891Sbostic 		return (EBUSY);
67852891Sbostic 
67952891Sbostic 	GraphicsOpen = 1;
68052891Sbostic 	if (!isMono)
68152891Sbostic 		InitColorMap();
68252891Sbostic 	/*
68352891Sbostic 	 * Set up event queue for later
68452891Sbostic 	 */
68552891Sbostic 	pmu.scrInfo.qe.eSize = PM_MAXEVQ;
68652891Sbostic 	pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
68752891Sbostic 	pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
68852891Sbostic 	pmu.scrInfo.qe.tcNext = 0;
68952891Sbostic 	pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
69052891Sbostic 	return (0);
69152891Sbostic }
69252891Sbostic 
69352891Sbostic /*ARGSUSED*/
69452891Sbostic cfbclose(dev, flag)
69552891Sbostic 	dev_t dev;
69652891Sbostic 	int flag;
69752891Sbostic {
698*52959Sralph 	int s;
69952891Sbostic 
70052891Sbostic 	if (!GraphicsOpen)
70152891Sbostic 		return (EBADF);
70252891Sbostic 
70352891Sbostic 	GraphicsOpen = 0;
70452891Sbostic 	if (!isMono)
70552891Sbostic 		InitColorMap();
706*52959Sralph 	s = spltty();
707*52959Sralph 	dcDivertXInput = (void (*)())0;
708*52959Sralph 	dcMouseEvent = (void (*)())0;
709*52959Sralph 	dcMouseButtons = (void (*)())0;
710*52959Sralph 	splx(s);
71152891Sbostic 	ScreenInit();
71252891Sbostic 	vmUserUnmap();
71352891Sbostic 	bzero(fb_addr, (isMono ? 1024 / 8 : 1024) * 864);
71452891Sbostic 	PosCursor(col * 8, row * 15);
71552891Sbostic 	return (0);
71652891Sbostic }
71752891Sbostic 
71852891Sbostic /*ARGSUSED*/
71952891Sbostic cfbioctl(dev, cmd, data, flag)
72052891Sbostic 	dev_t dev;
72152891Sbostic 	caddr_t data;
72252891Sbostic {
723*52959Sralph 	int s;
72452891Sbostic 
72552891Sbostic 	switch (cmd) {
72652891Sbostic 	case QIOCGINFO:
72752891Sbostic 	    {
72852891Sbostic 		caddr_t addr;
72952891Sbostic 		extern caddr_t vmUserMap();
73052891Sbostic 
73152891Sbostic 		/*
73252891Sbostic 		 * Map the all the data the user needs access to into
73352891Sbostic 		 * user space.
73452891Sbostic 		 */
73552891Sbostic 		addr = vmUserMap(sizeof(pmu), (unsigned)&pmu);
73652891Sbostic 		if (addr == (caddr_t)0)
73752891Sbostic 			goto mapError;
73852891Sbostic 		*(PM_Info **)data = &((struct pmuaccess *)addr)->scrInfo;
73952891Sbostic 		pmu.scrInfo.qe.events = ((struct pmuaccess *)addr)->events;
74052891Sbostic 		pmu.scrInfo.qe.tcs = ((struct pmuaccess *)addr)->tcs;
74152891Sbostic 		/*
74252891Sbostic 		 * Map the plane mask into the user's address space.
74352891Sbostic 		 */
74452891Sbostic 		addr = vmUserMap(4, planemask_addr);
74552891Sbostic 		if (addr == (caddr_t)0)
74652891Sbostic 			goto mapError;
74752891Sbostic 		pmu.scrInfo.planemask = (char *)addr;
74852891Sbostic 		/*
74952891Sbostic 		 * Map the frame buffer into the user's address space.
75052891Sbostic 		 */
75152891Sbostic 		addr = vmUserMap(isMono ? 256*1024 : 1024*1024, fb_addr);
75252891Sbostic 		if (addr == (caddr_t)0)
75352891Sbostic 			goto mapError;
75452891Sbostic 		pmu.scrInfo.bitmap = (char *)addr;
75552891Sbostic 		break;
75652891Sbostic 
75752891Sbostic 	mapError:
75852891Sbostic 		vmUserUnmap();
75952891Sbostic 		printf("Cannot map shared data structures\n");
76052891Sbostic 		return (EIO);
76152891Sbostic 	    }
76252891Sbostic 
76352891Sbostic 	case QIOCPMSTATE:
76452891Sbostic 		/*
76552891Sbostic 		 * Set mouse state.
76652891Sbostic 		 */
76752891Sbostic 		pmu.scrInfo.mouse = *(pmCursor *)data;
76852891Sbostic 		PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y);
76952891Sbostic 		break;
77052891Sbostic 
77152891Sbostic 	case QIOCINIT:
77252891Sbostic 		/*
77352891Sbostic 		 * Initialize the screen.
77452891Sbostic 		 */
77552891Sbostic 		ScreenInit();
77652891Sbostic 		break;
77752891Sbostic 
77852891Sbostic 	case QIOCKPCMD:
77952891Sbostic 	    {
78052891Sbostic 		pmKpCmd *kpCmdPtr;
78152891Sbostic 		unsigned char *cp;
78252891Sbostic 
78352891Sbostic 		kpCmdPtr = (pmKpCmd *)data;
78452891Sbostic 		if (kpCmdPtr->nbytes == 0)
78552891Sbostic 			kpCmdPtr->cmd |= 0x80;
78652891Sbostic 		if (!GraphicsOpen)
78752891Sbostic 			kpCmdPtr->cmd |= 1;
78852891Sbostic 		dcKBDPutc((int)kpCmdPtr->cmd);
78952891Sbostic 		cp = &kpCmdPtr->par[0];
79052891Sbostic 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
79152891Sbostic 			if (kpCmdPtr->nbytes == 1)
79252891Sbostic 				*cp |= 0x80;
79352891Sbostic 			dcKBDPutc((int)*cp);
79452891Sbostic 		}
79552891Sbostic 		break;
79652891Sbostic 	    }
79752891Sbostic 
79852891Sbostic 	case QIOCADDR:
79952891Sbostic 		*(PM_Info **)data = &pmu.scrInfo;
80052891Sbostic 		break;
80152891Sbostic 
80252891Sbostic 	case QIOWCURSOR:
80352891Sbostic 		LoadCursor((unsigned short *)data);
80452891Sbostic 		break;
80552891Sbostic 
80652891Sbostic 	case QIOWCURSORCOLOR:
80752891Sbostic 		CursorColor((unsigned int *)data);
80852891Sbostic 		break;
80952891Sbostic 
81052891Sbostic 	case QIOSETCMAP:
81152891Sbostic 		LoadColorMap((ColorMap *)data);
81252891Sbostic 		break;
81352891Sbostic 
81452891Sbostic 	case QIOKERNLOOP:
815*52959Sralph 		s = spltty();
81652891Sbostic 		dcDivertXInput = cfbKbdEvent;
81752891Sbostic 		dcMouseEvent = cfbMouseEvent;
81852891Sbostic 		dcMouseButtons = cfbMouseButtons;
819*52959Sralph 		splx(s);
82052891Sbostic 		break;
82152891Sbostic 
82252891Sbostic 	case QIOKERNUNLOOP:
823*52959Sralph 		s = spltty();
82452891Sbostic 		dcDivertXInput = (void (*)())0;
82552891Sbostic 		dcMouseEvent = (void (*)())0;
82652891Sbostic 		dcMouseButtons = (void (*)())0;
827*52959Sralph 		splx(s);
82852891Sbostic 		break;
82952891Sbostic 
83052891Sbostic 	case QIOVIDEOON:
83152891Sbostic 		EnableVideo();
83252891Sbostic 		break;
83352891Sbostic 
83452891Sbostic 	case QIOVIDEOOFF:
83552891Sbostic 		DisableVideo();
83652891Sbostic 		break;
83752891Sbostic 
83852891Sbostic 	default:
83952891Sbostic 		printf("cfb0: Unknown ioctl command %x\n", cmd);
84052891Sbostic 		return (EINVAL);
84152891Sbostic 	}
84252891Sbostic 	return (0);
84352891Sbostic }
84452891Sbostic 
84552891Sbostic cfbselect(dev, flag, p)
84652891Sbostic 	dev_t dev;
84752891Sbostic 	int flag;
84852891Sbostic 	struct proc *p;
84952891Sbostic {
85052891Sbostic 
85152891Sbostic 	switch (flag) {
85252891Sbostic 	case FREAD:
85352891Sbostic 		if (pmu.scrInfo.qe.eHead != pmu.scrInfo.qe.eTail)
85452891Sbostic 			return (1);
85552891Sbostic 		selrecord(p, &cfb_selp);
85652891Sbostic 		break;
85752891Sbostic 	}
85852891Sbostic 
85952891Sbostic 	return (0);
86052891Sbostic }
86152891Sbostic 
86252891Sbostic static u_char	cursor_RGB[6];	/* cursor color 2 & 3 */
86352891Sbostic 
86452891Sbostic /*
86552891Sbostic  * The default cursor.
86652891Sbostic  */
86752891Sbostic static unsigned short defCursor[1024] = {
86852891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
86952891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87052891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87152891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87252891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87352891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87452891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87552891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87652891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87752891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87852891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
87952891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88052891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88152891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88252891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88352891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88452891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88552891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88652891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88752891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88852891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
88952891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89052891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89152891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89252891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89352891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89452891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89552891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89652891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89752891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89852891Sbostic 	0x00FF, 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
89952891Sbostic 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
90052891Sbostic };
90152891Sbostic 
90252891Sbostic #define	CFB_OFFSET_VRAM		0x0		/* from module's base */
90352891Sbostic 						/* Replicated at x100000 */
90452891Sbostic #define CFB_OFFSET_BT459	0x200000	/* Bt459 registers */
90552891Sbostic #define CFB_OFFSET_IREQ		0x300000	/* Interrupt req. control */
90652891Sbostic #define CFB_OFFSET_ROM		0x380000	/* Diagnostic ROM */
90752891Sbostic #define CFB_OFFSET_RESET	0x3c0000	/* Bt459 resets on writes */
90852891Sbostic 
90952891Sbostic /*
91052891Sbostic  * Generic register access
91152891Sbostic  */
91252891Sbostic void
91352891Sbostic bt459_select_reg(regs, regno)
91452891Sbostic 	bt459_regmap_t *regs;
91552891Sbostic {
91652891Sbostic 	regs->addr_lo = regno;
91752891Sbostic 	regs->addr_hi = regno >> 8;
91852891Sbostic 	MachEmptyWriteBuffer();
91952891Sbostic }
92052891Sbostic 
92152891Sbostic void
92252891Sbostic bt459_write_reg(regs, regno, val)
92352891Sbostic 	bt459_regmap_t *regs;
92452891Sbostic {
92552891Sbostic 	regs->addr_lo = regno;
92652891Sbostic 	regs->addr_hi = regno >> 8;
92752891Sbostic 	MachEmptyWriteBuffer();
92852891Sbostic 	regs->addr_reg = val;
92952891Sbostic 	MachEmptyWriteBuffer();
93052891Sbostic }
93152891Sbostic 
93252891Sbostic unsigned char
93352891Sbostic bt459_read_reg(regs, regno)
93452891Sbostic 	bt459_regmap_t *regs;
93552891Sbostic {
93652891Sbostic 	regs->addr_lo = regno;
93752891Sbostic 	regs->addr_hi = regno >> 8;
93852891Sbostic 	MachEmptyWriteBuffer();
93952891Sbostic 	return regs->addr_reg;
94052891Sbostic }
94152891Sbostic 
94252891Sbostic #ifdef DEBUG
94352891Sbostic bt459_print_colormap(regs)
94452891Sbostic 	bt459_regmap_t *regs;
94552891Sbostic {
94652891Sbostic 	register int i;
94752891Sbostic 
94852891Sbostic 	bt459_select_reg(regs, 0);
94952891Sbostic 	for (i = 0; i < 256; i++) {
95052891Sbostic 		register unsigned red, green, blue;
95152891Sbostic 
95252891Sbostic 		red = regs->addr_cmap;
95352891Sbostic 		green = regs->addr_cmap;
95452891Sbostic 		blue = regs->addr_cmap;
95552891Sbostic 		printf("%x->[x%x x%x x%x]\n", i, red, green, blue);
95652891Sbostic 	}
95752891Sbostic }
95852891Sbostic #endif
95952891Sbostic 
96052891Sbostic /*
96152891Sbostic  * Test to see if device is present.
96252891Sbostic  * Return true if found and initialized ok.
96352891Sbostic  */
96452891Sbostic cfb_init(cp)
96552891Sbostic 	register struct pmax_ctlr *cp;
96652891Sbostic {
96752891Sbostic 	bt459_regmap_t *regs;
96852891Sbostic 
96952891Sbostic 	/* check for no frame buffer */
97052891Sbostic 	if (badaddr(cp->pmax_addr, 4))
97152891Sbostic 		return (0);
97252891Sbostic 
97352891Sbostic 	fb_addr = (unsigned)cp->pmax_addr + CFB_OFFSET_VRAM;
97452891Sbostic 	planemask_addr = 0; /* XXX */
97552891Sbostic 	regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
97652891Sbostic 
97752891Sbostic 	if (bt459_read_reg(regs, BT459_REG_ID) != 0x4a)
97852891Sbostic 		return (0);
97952891Sbostic 
98052891Sbostic 	*(int *)(fb_addr + CFB_OFFSET_RESET) = 0;	/* force chip reset */
98152891Sbostic 	DELAY(2000);	/* ???? check right time on specs! ???? */
98252891Sbostic 
98352891Sbostic 	/* use 4:1 input mux */
98452891Sbostic 	bt459_write_reg(regs, BT459_REG_CMD0, 0x40);
98552891Sbostic 
98652891Sbostic 	/* no zooming, no panning */
98752891Sbostic 	bt459_write_reg(regs, BT459_REG_CMD1, 0x00);
98852891Sbostic 
98952891Sbostic 	/*
99052891Sbostic 	 * signature test, X-windows cursor, no overlays, SYNC* PLL,
99152891Sbostic 	 * normal RAM select, 7.5 IRE pedestal, do sync
99252891Sbostic 	 */
99352891Sbostic 	bt459_write_reg(regs, BT459_REG_CMD2, 0xc2);
99452891Sbostic 
99552891Sbostic 	/* get all pixel bits */
99652891Sbostic 	bt459_write_reg(regs, BT459_REG_PRM, 0xff);
99752891Sbostic 
99852891Sbostic 	/* no blinking */
99952891Sbostic 	bt459_write_reg(regs, BT459_REG_PBM, 0x00);
100052891Sbostic 
100152891Sbostic 	/* no overlay */
100252891Sbostic 	bt459_write_reg(regs, BT459_REG_ORM, 0x00);
100352891Sbostic 
100452891Sbostic 	/* no overlay blink */
100552891Sbostic 	bt459_write_reg(regs, BT459_REG_OBM, 0x00);
100652891Sbostic 
100752891Sbostic 	/* no interleave, no underlay */
100852891Sbostic 	bt459_write_reg(regs, BT459_REG_ILV, 0x00);
100952891Sbostic 
101052891Sbostic 	/* normal operation, no signature analysis */
101152891Sbostic 	bt459_write_reg(regs, BT459_REG_TEST, 0x00);
101252891Sbostic 
101352891Sbostic 	/*
101452891Sbostic 	 * no blinking, 1bit cross hair, XOR reg&crosshair,
101552891Sbostic 	 * no crosshair on either plane 0 or 1,
101652891Sbostic 	 * regular cursor on both planes.
101752891Sbostic 	 */
101852891Sbostic 	bt459_write_reg(regs, BT459_REG_CCR, 0xc0);
101952891Sbostic 
102052891Sbostic 	/* home cursor */
102152891Sbostic 	bt459_write_reg(regs, BT459_REG_CXLO, 0x00);
102252891Sbostic 	bt459_write_reg(regs, BT459_REG_CXHI, 0x00);
102352891Sbostic 	bt459_write_reg(regs, BT459_REG_CYLO, 0x00);
102452891Sbostic 	bt459_write_reg(regs, BT459_REG_CYHI, 0x00);
102552891Sbostic 
102652891Sbostic 	/* no crosshair window */
102752891Sbostic 	bt459_write_reg(regs, BT459_REG_WXLO, 0x00);
102852891Sbostic 	bt459_write_reg(regs, BT459_REG_WXHI, 0x00);
102952891Sbostic 	bt459_write_reg(regs, BT459_REG_WYLO, 0x00);
103052891Sbostic 	bt459_write_reg(regs, BT459_REG_WYHI, 0x00);
103152891Sbostic 	bt459_write_reg(regs, BT459_REG_WWLO, 0x00);
103252891Sbostic 	bt459_write_reg(regs, BT459_REG_WWHI, 0x00);
103352891Sbostic 	bt459_write_reg(regs, BT459_REG_WHLO, 0x00);
103452891Sbostic 	bt459_write_reg(regs, BT459_REG_WHHI, 0x00);
103552891Sbostic 
103652891Sbostic 	/*
103752891Sbostic 	 * Initialize screen info.
103852891Sbostic 	 */
103952891Sbostic 	pmu.scrInfo.max_row = MAX_ROW;
104052891Sbostic 	pmu.scrInfo.max_col = MAX_COL;
104152891Sbostic 	pmu.scrInfo.max_x = 1024;
104252891Sbostic 	pmu.scrInfo.max_y = 864;
104352891Sbostic 	pmu.scrInfo.max_cur_x = 1023;
104452891Sbostic 	pmu.scrInfo.max_cur_y = 863;
104552891Sbostic 	pmu.scrInfo.version = 11;
104652891Sbostic 	pmu.scrInfo.mthreshold = 4;
104752891Sbostic 	pmu.scrInfo.mscale = 2;
104852891Sbostic 	pmu.scrInfo.min_cur_x = 0;
104952891Sbostic 	pmu.scrInfo.min_cur_y = 0;
105052891Sbostic 	pmu.scrInfo.qe.timestamp_ms = TO_MS(time);
105152891Sbostic 	pmu.scrInfo.qe.eSize = PM_MAXEVQ;
105252891Sbostic 	pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0;
105352891Sbostic 	pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
105452891Sbostic 	pmu.scrInfo.qe.tcNext = 0;
105552891Sbostic 
105652891Sbostic 	/*
105752891Sbostic 	 * Initialize the color map, the screen, and the mouse.
105852891Sbostic 	 */
105952891Sbostic 	InitColorMap();
106052891Sbostic 	ScreenInit();
106152891Sbostic 	Scroll();
106252891Sbostic 
106352891Sbostic 	initialized = 1;
106452891Sbostic 	return (1);
106552891Sbostic }
106652891Sbostic 
106752891Sbostic /*
106852891Sbostic  * ----------------------------------------------------------------------------
106952891Sbostic  *
107052891Sbostic  * ScreenInit --
107152891Sbostic  *
107252891Sbostic  *	Initialize the screen.
107352891Sbostic  *
107452891Sbostic  * Results:
107552891Sbostic  *	None.
107652891Sbostic  *
107752891Sbostic  * Side effects:
107852891Sbostic  *	The screen is initialized.
107952891Sbostic  *
108052891Sbostic  * ----------------------------------------------------------------------------
108152891Sbostic  */
108252891Sbostic static void
108352891Sbostic ScreenInit()
108452891Sbostic {
108552891Sbostic 
108652891Sbostic 	/*
108752891Sbostic 	 * Home the cursor.
108852891Sbostic 	 * We want an LSI terminal emulation. We want the graphics
108952891Sbostic 	 * terminal to scroll from the bottom. So start at the bottom.
109052891Sbostic 	 */
109152891Sbostic 	row = 55;
109252891Sbostic 	col = 0;
109352891Sbostic 
109452891Sbostic 	/*
109552891Sbostic 	 * Load the cursor with the default values
109652891Sbostic 	 *
109752891Sbostic 	 */
109852891Sbostic 	LoadCursor(defCursor);
109952891Sbostic }
110052891Sbostic 
110152891Sbostic /*
110252891Sbostic  * ----------------------------------------------------------------------------
110352891Sbostic  *
110452891Sbostic  * LoadCursor --
110552891Sbostic  *
110652891Sbostic  *	Routine to load the cursor Sprite pattern.
110752891Sbostic  *
110852891Sbostic  * Results:
110952891Sbostic  *	None.
111052891Sbostic  *
111152891Sbostic  * Side effects:
111252891Sbostic  *	The cursor is loaded into the hardware cursor.
111352891Sbostic  *
111452891Sbostic  * ----------------------------------------------------------------------------
111552891Sbostic  */
111652891Sbostic static void
111752891Sbostic LoadCursor(cur)
111852891Sbostic 	unsigned short *cur;
111952891Sbostic {
112052891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
112152891Sbostic 	register int i, j;
112252891Sbostic 
112352891Sbostic 	/*
112452891Sbostic 	 * As per specs, must run a check to see if we
112552891Sbostic 	 * had contention. If so, re-write the cursor.
112652891Sbostic 	 */
112752891Sbostic 	for (j = 0; j < 2; j++) {
112852891Sbostic 		/* loop once to write */
112952891Sbostic 		bt459_select_reg(regs, BT459_REG_CRAM_BASE);
113052891Sbostic 		for (i = 0; i < 1024; i++) {
113152891Sbostic 			regs->addr_reg = cur[i];
113252891Sbostic 			MachEmptyWriteBuffer();
113352891Sbostic 		}
113452891Sbostic 
113552891Sbostic 		/* loop to check, if fail write again */
113652891Sbostic 		bt459_select_reg(regs, BT459_REG_CRAM_BASE);
113752891Sbostic 		for (i = 0; i < 1024; i++)
113852891Sbostic 			if (regs->addr_reg != cur[i])
113952891Sbostic 				break;
114052891Sbostic 		if (i == 1024)
114152891Sbostic 			break;	/* all went well first shot */
114252891Sbostic 	}
114352891Sbostic }
114452891Sbostic 
114552891Sbostic /*
114652891Sbostic  * ----------------------------------------------------------------------------
114752891Sbostic  *
114852891Sbostic  * RestoreCursorColor --
114952891Sbostic  *
115052891Sbostic  *	Routine to restore the color of the cursor.
115152891Sbostic  *
115252891Sbostic  * Results:
115352891Sbostic  *	None.
115452891Sbostic  *
115552891Sbostic  * Side effects:
115652891Sbostic  *	None.
115752891Sbostic  *
115852891Sbostic  * ----------------------------------------------------------------------------
115952891Sbostic  */
116052891Sbostic static void
116152891Sbostic RestoreCursorColor()
116252891Sbostic {
116352891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
116452891Sbostic 	register int i;
116552891Sbostic 
116652891Sbostic 	bt459_select_reg(regs, BT459_REG_CCOLOR_2);
116752891Sbostic 	for (i = 0; i < 6; i++) {
116852891Sbostic 		regs->addr_reg = cursor_RGB[i];
116952891Sbostic 		MachEmptyWriteBuffer();
117052891Sbostic 	}
117152891Sbostic }
117252891Sbostic 
117352891Sbostic /*
117452891Sbostic  * ----------------------------------------------------------------------------
117552891Sbostic  *
117652891Sbostic  * CursorColor --
117752891Sbostic  *
117852891Sbostic  *	Set the color of the cursor.
117952891Sbostic  *
118052891Sbostic  * Results:
118152891Sbostic  *	None.
118252891Sbostic  *
118352891Sbostic  * Side effects:
118452891Sbostic  *	None.
118552891Sbostic  *
118652891Sbostic  * ----------------------------------------------------------------------------
118752891Sbostic  */
118852891Sbostic static void
118952891Sbostic CursorColor(color)
119052891Sbostic 	unsigned int color[];
119152891Sbostic {
119252891Sbostic 	register int i, j;
119352891Sbostic 
119452891Sbostic 	for (i = 0; i < 6; i++)
119552891Sbostic 		cursor_RGB[i] = (u_char)(color[i] >> 8);
119652891Sbostic 
119752891Sbostic 	RestoreCursorColor();
119852891Sbostic }
119952891Sbostic 
120052891Sbostic /*
120152891Sbostic  *----------------------------------------------------------------------
120252891Sbostic  *
120352891Sbostic  * PosCursor --
120452891Sbostic  *
120552891Sbostic  *	Postion the cursor.
120652891Sbostic  *
120752891Sbostic  * Results:
120852891Sbostic  *	None.
120952891Sbostic  *
121052891Sbostic  * Side effects:
121152891Sbostic  *	None.
121252891Sbostic  *
121352891Sbostic  *----------------------------------------------------------------------
121452891Sbostic  */
121552891Sbostic static void
121652891Sbostic PosCursor(x, y)
121752891Sbostic 	register int x, y;
121852891Sbostic {
121952891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
122052891Sbostic 
122152891Sbostic 	if (y < pmu.scrInfo.min_cur_y || y > pmu.scrInfo.max_cur_y)
122252891Sbostic 		y = pmu.scrInfo.max_cur_y;
122352891Sbostic 	if (x < pmu.scrInfo.min_cur_x || x > pmu.scrInfo.max_cur_x)
122452891Sbostic 		x = pmu.scrInfo.max_cur_x;
122552891Sbostic 	pmu.scrInfo.cursor.x = x;		/* keep track of real cursor */
122652891Sbostic 	pmu.scrInfo.cursor.y = y;		/* position, indep. of mouse */
122752891Sbostic 
122852891Sbostic 	x += 219;
122952891Sbostic 	y += 34;
123052891Sbostic 
123152891Sbostic 	bt459_select_reg(regs, BT459_REG_CXLO);
123252891Sbostic 	regs->addr_reg = x;
123352891Sbostic 	MachEmptyWriteBuffer();
123452891Sbostic 	regs->addr_reg = x >> 8;
123552891Sbostic 	MachEmptyWriteBuffer();
123652891Sbostic 	regs->addr_reg = y;
123752891Sbostic 	MachEmptyWriteBuffer();
123852891Sbostic 	regs->addr_reg = y >> 8;
123952891Sbostic 	MachEmptyWriteBuffer();
124052891Sbostic }
124152891Sbostic 
124252891Sbostic /*
124352891Sbostic  * ----------------------------------------------------------------------------
124452891Sbostic  *
124552891Sbostic  * InitColorMap --
124652891Sbostic  *
124752891Sbostic  *	Initialize the color map.
124852891Sbostic  *
124952891Sbostic  * Results:
125052891Sbostic  *	None.
125152891Sbostic  *
125252891Sbostic  * Side effects:
125352891Sbostic  *	The colormap is initialized appropriately.
125452891Sbostic  *
125552891Sbostic  * ----------------------------------------------------------------------------
125652891Sbostic  */
125752891Sbostic static void
125852891Sbostic InitColorMap()
125952891Sbostic {
126052891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
126152891Sbostic 	register int i;
126252891Sbostic 
126352891Sbostic 	bt459_select_reg(regs, 0);
126452891Sbostic 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
126552891Sbostic 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
126652891Sbostic 	regs->addr_cmap = 0; MachEmptyWriteBuffer();
126752891Sbostic 
126852891Sbostic 	for (i = 1; i < 256; i++) {
126952891Sbostic 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
127052891Sbostic 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
127152891Sbostic 		regs->addr_cmap = 0xff; MachEmptyWriteBuffer();
127252891Sbostic 	}
127352891Sbostic 
127452891Sbostic 	for (i = 0; i < 3; i++) {
127552891Sbostic 		cursor_RGB[i] = 0x00;
127652891Sbostic 		cursor_RGB[i + 3] = 0xff;
127752891Sbostic 	}
127852891Sbostic 	RestoreCursorColor();
127952891Sbostic }
128052891Sbostic 
128152891Sbostic /*
128252891Sbostic  * ----------------------------------------------------------------------------
128352891Sbostic  *
128452891Sbostic  * LoadColorMap --
128552891Sbostic  *
128652891Sbostic  *	Load the color map.
128752891Sbostic  *
128852891Sbostic  * Results:
128952891Sbostic  *	None.
129052891Sbostic  *
129152891Sbostic  * Side effects:
129252891Sbostic  *	The color map is loaded.
129352891Sbostic  *
129452891Sbostic  * ----------------------------------------------------------------------------
129552891Sbostic  */
129652891Sbostic static void
129752891Sbostic LoadColorMap(ptr)
129852891Sbostic 	ColorMap *ptr;
129952891Sbostic {
130052891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
130152891Sbostic 
130252891Sbostic 	if (ptr->index > 256)
130352891Sbostic 		return;
130452891Sbostic 
130552891Sbostic 	bt459_select_reg(regs, ptr->index);
130652891Sbostic 
130752891Sbostic 	regs->addr_cmap = ptr->Entry.red; MachEmptyWriteBuffer();
130852891Sbostic 	regs->addr_cmap = ptr->Entry.green; MachEmptyWriteBuffer();
130952891Sbostic 	regs->addr_cmap = ptr->Entry.blue; MachEmptyWriteBuffer();
131052891Sbostic }
131152891Sbostic 
131252891Sbostic /*
131352891Sbostic  * Video on/off state.
131452891Sbostic  */
131552891Sbostic struct vstate {
131652891Sbostic 	u_char	color0[3];	/* saved color map entry zero */
131752891Sbostic 	u_char	off;		/* TRUE if display is off */
131852891Sbostic } vstate;
131952891Sbostic 
132052891Sbostic /*
132152891Sbostic  * ----------------------------------------------------------------------------
132252891Sbostic  *
132352891Sbostic  * EnableVideo --
132452891Sbostic  *
132552891Sbostic  *	Enable the video display.
132652891Sbostic  *
132752891Sbostic  * Results:
132852891Sbostic  *	None.
132952891Sbostic  *
133052891Sbostic  * Side effects:
133152891Sbostic  *	The display is enabled.
133252891Sbostic  *
133352891Sbostic  * ----------------------------------------------------------------------------
133452891Sbostic  */
133552891Sbostic static void
133652891Sbostic EnableVideo()
133752891Sbostic {
133852891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
133952891Sbostic 
134052891Sbostic 	if (!vstate.off)
134152891Sbostic 		return;
134252891Sbostic 
134352891Sbostic 	/* restore old color map entry zero */
134452891Sbostic 	bt459_select_reg(regs, 0);
134552891Sbostic 	regs->addr_cmap = vstate.color0[0];
134652891Sbostic 	MachEmptyWriteBuffer();
134752891Sbostic 	regs->addr_cmap = vstate.color0[1];
134852891Sbostic 	MachEmptyWriteBuffer();
134952891Sbostic 	regs->addr_cmap = vstate.color0[2];
135052891Sbostic 	MachEmptyWriteBuffer();
135152891Sbostic 
135252891Sbostic 	/* enable normal display */
135352891Sbostic 	bt459_write_reg(regs, BT459_REG_PRM, 0xff);
135452891Sbostic 	bt459_write_reg(regs, BT459_REG_CCR, 0xc0);
135552891Sbostic 
135652891Sbostic 	vstate.off = 0;
135752891Sbostic }
135852891Sbostic 
135952891Sbostic /*
136052891Sbostic  * ----------------------------------------------------------------------------
136152891Sbostic  *
136252891Sbostic  * DisableVideo --
136352891Sbostic  *
136452891Sbostic  *	Disable the video display.
136552891Sbostic  *
136652891Sbostic  * Results:
136752891Sbostic  *	None.
136852891Sbostic  *
136952891Sbostic  * Side effects:
137052891Sbostic  *	The display is disabled.
137152891Sbostic  *
137252891Sbostic  * ----------------------------------------------------------------------------
137352891Sbostic  */
137452891Sbostic static void
137552891Sbostic DisableVideo()
137652891Sbostic {
137752891Sbostic 	bt459_regmap_t *regs = (bt459_regmap_t *)(fb_addr + CFB_OFFSET_BT459);
137852891Sbostic 
137952891Sbostic 	if (vstate.off)
138052891Sbostic 		return;
138152891Sbostic 
138252891Sbostic 	/* save old color map entry zero */
138352891Sbostic 	bt459_select_reg(regs, 0);
138452891Sbostic 	vstate.color0[0] = regs->addr_cmap;
138552891Sbostic 	vstate.color0[1] = regs->addr_cmap;
138652891Sbostic 	vstate.color0[2] = regs->addr_cmap;
138752891Sbostic 
138852891Sbostic 	/* set color map entry zero to zero */
138952891Sbostic 	bt459_select_reg(regs, 0);
139052891Sbostic 	regs->addr_cmap = 0;
139152891Sbostic 	MachEmptyWriteBuffer();
139252891Sbostic 	regs->addr_cmap = 0;
139352891Sbostic 	MachEmptyWriteBuffer();
139452891Sbostic 	regs->addr_cmap = 0;
139552891Sbostic 	MachEmptyWriteBuffer();
139652891Sbostic 
139752891Sbostic 	/* disable display */
139852891Sbostic 	bt459_write_reg(regs, BT459_REG_PRM, 0);
139952891Sbostic 	bt459_write_reg(regs, BT459_REG_CCR, 0);
140052891Sbostic 
140152891Sbostic 	vstate.off = 1;
140252891Sbostic }
140352891Sbostic #endif
1404