xref: /csrg-svn/sys/pmax/dev/xcfb.c (revision 69799)
156818Sralph /*-
263208Sbostic  * Copyright (c) 1992, 1993
363208Sbostic  *	The Regents of the University of California.  All rights reserved.
456818Sralph  *
556818Sralph  * This code is derived from software contributed to Berkeley by
656818Sralph  * Ralph Campbell and Rick Macklem.
756818Sralph  *
856818Sralph  * %sccs.include.redist.c%
956818Sralph  *
10*69799Sralph  *	@(#)xcfb.c	8.2 (Berkeley) 06/02/95
1156818Sralph  */
1256818Sralph 
1356818Sralph /*
1456818Sralph  * Mach Operating System
1556818Sralph  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
1656818Sralph  * All Rights Reserved.
1756818Sralph  *
1856818Sralph  * Permission to use, copy, modify and distribute this software and its
1956818Sralph  * documentation is hereby granted, provided that both the copyright
2056818Sralph  * notice and this permission notice appear in all copies of the
2156818Sralph  * software, derivative works or modified versions, and any portions
2256818Sralph  * thereof, and that both notices appear in supporting documentation.
2356818Sralph  *
2456818Sralph  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
2556818Sralph  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
2656818Sralph  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
2756818Sralph  *
2856818Sralph  * Carnegie Mellon requests users of this software to return to
2956818Sralph  *
3056818Sralph  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
3156818Sralph  *  School of Computer Science
3256818Sralph  *  Carnegie Mellon University
3356818Sralph  *  Pittsburgh PA 15213-3890
3456818Sralph  *
3556818Sralph  * any improvements or extensions that they make and grant Carnegie the
3656818Sralph  * rights to redistribute these changes.
3756818Sralph  */
3856818Sralph /*
3956818Sralph  *  devGraphics.c --
4056818Sralph  *
4156818Sralph  *     	This file contains machine-dependent routines for the graphics device.
4256818Sralph  *
4356818Sralph  *	Copyright (C) 1989 Digital Equipment Corporation.
4456818Sralph  *	Permission to use, copy, modify, and distribute this software and
4556818Sralph  *	its documentation for any purpose and without fee is hereby granted,
4656818Sralph  *	provided that the above copyright notice appears in all copies.
4756818Sralph  *	Digital Equipment Corporation makes no representations about the
4856818Sralph  *	suitability of this software for any purpose.  It is provided "as is"
4956818Sralph  *	without express or implied warranty.
5056818Sralph  *
5156818Sralph  * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
5256818Sralph  *	v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)";
5356818Sralph  */
5456818Sralph 
5556818Sralph #include <xcfb.h>
5656818Sralph #include <dtop.h>
5756818Sralph #if NXCFB > 0
5856818Sralph #if NDTOP == 0
5956818Sralph xcfb needs dtop device
6056818Sralph #else
6156818Sralph 
6256818Sralph #include <sys/param.h>
6356818Sralph #include <sys/time.h>
6456818Sralph #include <sys/kernel.h>
6556818Sralph #include <sys/ioctl.h>
6656818Sralph #include <sys/file.h>
6756818Sralph #include <sys/errno.h>
6856818Sralph #include <sys/proc.h>
6956818Sralph #include <sys/mman.h>
7056818Sralph 
7156818Sralph #include <vm/vm.h>
7256818Sralph 
7356818Sralph #include <machine/machConst.h>
7456818Sralph #include <machine/pmioctl.h>
7556818Sralph 
7656818Sralph #include <pmax/pmax/maxine.h>
7756818Sralph #include <pmax/pmax/cons.h>
7856818Sralph #include <pmax/pmax/pmaxtype.h>
7956818Sralph 
8056818Sralph #include <pmax/dev/device.h>
8156818Sralph #include <pmax/dev/xcfbreg.h>
8256818Sralph #include <pmax/dev/dtopreg.h>
8356818Sralph #include <pmax/dev/fbreg.h>
8456818Sralph 
8556818Sralph /*
8656818Sralph  * These need to be mapped into user space.
8756818Sralph  */
8856818Sralph struct fbuaccess xcfbu;
8956818Sralph struct pmax_fb xcfbfb;
9056818Sralph 
9156818Sralph /*
9256818Sralph  * Forward references.
9356818Sralph  */
9456818Sralph static void xcfbScreenInit();
9556818Sralph static void xcfbLoadCursor();
9656818Sralph static void xcfbRestoreCursorColor();
9756818Sralph static void xcfbCursorColor();
9856818Sralph void xcfbPosCursor();
9956818Sralph static void xcfbInitColorMap();
10056818Sralph static void xcfbLoadColorMap();
10156818Sralph static u_int ims332_read_register();
10256818Sralph static void ims332_write_register();
10356818Sralph static void ims332_load_colormap_entry();
10456818Sralph static void ims332_video_off();
10556818Sralph static void ims332_video_on();
10656818Sralph 
10756818Sralph void xcfbKbdEvent(), xcfbMouseEvent(), xcfbMouseButtons();
10858974Sralph extern void dtopKBDPutc();
10956818Sralph extern void (*dtopDivertXInput)();
11056818Sralph extern void (*dtopMouseEvent)();
11156818Sralph extern void (*dtopMouseButtons)();
11256818Sralph extern int pmax_boardtype;
11356818Sralph extern u_short defCursor[32];
11456818Sralph extern struct consdev cn_tab;
11556818Sralph 
11656818Sralph int	xcfbprobe();
11756818Sralph struct	driver xcfbdriver = {
11856818Sralph 	"xcfb", xcfbprobe, 0, 0,
11956818Sralph };
12056818Sralph 
12156818Sralph /*
12256818Sralph  * Test to see if device is present.
12356818Sralph  * Return true if found and initialized ok.
12456818Sralph  */
12556818Sralph /*ARGSUSED*/
12656818Sralph xcfbprobe(cp)
12756818Sralph 	register struct pmax_ctlr *cp;
12856818Sralph {
12956818Sralph 	register struct pmax_fb *fp = &xcfbfb;
13056818Sralph 
13156818Sralph 	if (pmax_boardtype != DS_MAXINE)
13256818Sralph 		return (0);
13356818Sralph 	if (!fp->initialized && !xcfbinit())
13456818Sralph 		return (0);
13556818Sralph 	printf("xcfb0 (color display)\n");
13656818Sralph 	return (1);
13756818Sralph }
13856818Sralph 
13956818Sralph /*ARGSUSED*/
14056818Sralph xcfbopen(dev, flag)
14156818Sralph 	dev_t dev;
14256818Sralph 	int flag;
14356818Sralph {
14456818Sralph 	register struct pmax_fb *fp = &xcfbfb;
14556818Sralph 	int s;
14656818Sralph 
14756818Sralph 	if (!fp->initialized)
14856818Sralph 		return (ENXIO);
14956818Sralph 	if (fp->GraphicsOpen)
15056818Sralph 		return (EBUSY);
15156818Sralph 
15256818Sralph 	fp->GraphicsOpen = 1;
15356818Sralph 	xcfbInitColorMap();
15456818Sralph 	/*
15556818Sralph 	 * Set up event queue for later
15656818Sralph 	 */
15756818Sralph 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
15856818Sralph 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
15956818Sralph 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
16056818Sralph 	fp->fbu->scrInfo.qe.tcNext = 0;
16156818Sralph 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
16256818Sralph 	s = spltty();
16356818Sralph 	dtopDivertXInput = xcfbKbdEvent;
16456818Sralph 	dtopMouseEvent = xcfbMouseEvent;
16556818Sralph 	dtopMouseButtons = xcfbMouseButtons;
16656818Sralph 	splx(s);
16756818Sralph 	return (0);
16856818Sralph }
16956818Sralph 
17056818Sralph /*ARGSUSED*/
17156818Sralph xcfbclose(dev, flag)
17256818Sralph 	dev_t dev;
17356818Sralph 	int flag;
17456818Sralph {
17556818Sralph 	register struct pmax_fb *fp = &xcfbfb;
17656818Sralph 	int s;
17756818Sralph 
17856818Sralph 	if (!fp->GraphicsOpen)
17956818Sralph 		return (EBADF);
18056818Sralph 
18156818Sralph 	fp->GraphicsOpen = 0;
18256818Sralph 	xcfbInitColorMap();
18356818Sralph 	s = spltty();
18456818Sralph 	dtopDivertXInput = (void (*)())0;
18556818Sralph 	dtopMouseEvent = (void (*)())0;
18656818Sralph 	dtopMouseButtons = (void (*)())0;
18756818Sralph 	splx(s);
18856818Sralph 	xcfbScreenInit();
18956818Sralph 	bzero((caddr_t)fp->fr_addr, 1024 * 768);
19056818Sralph 	xcfbPosCursor(fp->col * 8, fp->row * 15);
19156818Sralph 	return (0);
19256818Sralph }
19356818Sralph 
19456818Sralph /*ARGSUSED*/
19558974Sralph xcfbioctl(dev, cmd, data, flag, p)
19656818Sralph 	dev_t dev;
197*69799Sralph 	u_long cmd;
19856818Sralph 	caddr_t data;
19958974Sralph 	struct proc *p;
20056818Sralph {
20156818Sralph 	register struct pmax_fb *fp = &xcfbfb;
20256818Sralph 	int s;
20356818Sralph 
20456818Sralph 	switch (cmd) {
20556818Sralph 	case QIOCGINFO:
20658974Sralph 		return (fbmmap(fp, dev, data, p));
20756818Sralph 
20856818Sralph 	case QIOCPMSTATE:
20956818Sralph 		/*
21056818Sralph 		 * Set mouse state.
21156818Sralph 		 */
21256818Sralph 		fp->fbu->scrInfo.mouse = *(pmCursor *)data;
21356818Sralph 		xcfbPosCursor(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
21456818Sralph 		break;
21556818Sralph 
21656818Sralph 	case QIOCINIT:
21756818Sralph 		/*
21856818Sralph 		 * Initialize the screen.
21956818Sralph 		 */
22056818Sralph 		xcfbScreenInit();
22156818Sralph 		break;
22256818Sralph 
22356818Sralph 	case QIOCKPCMD:
22456818Sralph 	    {
22556818Sralph 		pmKpCmd *kpCmdPtr;
22656818Sralph 		unsigned char *cp;
22756818Sralph 
22856818Sralph 		kpCmdPtr = (pmKpCmd *)data;
22956818Sralph 		if (kpCmdPtr->nbytes == 0)
23056818Sralph 			kpCmdPtr->cmd |= 0x80;
23156818Sralph 		if (!fp->GraphicsOpen)
23256818Sralph 			kpCmdPtr->cmd |= 1;
23356818Sralph 		(*fp->KBDPutc)(fp->kbddev, (int)kpCmdPtr->cmd);
23456818Sralph 		cp = &kpCmdPtr->par[0];
23556818Sralph 		for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
23656818Sralph 			if (kpCmdPtr->nbytes == 1)
23756818Sralph 				*cp |= 0x80;
23856818Sralph 			(*fp->KBDPutc)(fp->kbddev, (int)*cp);
23956818Sralph 		}
24058974Sralph 		break;
24156818Sralph 	    }
24256818Sralph 
24356818Sralph 	case QIOCADDR:
24456818Sralph 		*(PM_Info **)data = &fp->fbu->scrInfo;
24556818Sralph 		break;
24656818Sralph 
24756818Sralph 	case QIOWCURSOR:
24856818Sralph 		xcfbLoadCursor((unsigned short *)data);
24956818Sralph 		break;
25056818Sralph 
25156818Sralph 	case QIOWCURSORCOLOR:
25256818Sralph 		xcfbCursorColor((unsigned int *)data);
25356818Sralph 		break;
25456818Sralph 
25556818Sralph 	case QIOSETCMAP:
25656818Sralph 		xcfbLoadColorMap((ColorMap *)data);
25756818Sralph 		break;
25856818Sralph 
25956818Sralph 	case QIOKERNLOOP:
26056818Sralph 		s = spltty();
26156818Sralph 		dtopDivertXInput = xcfbKbdEvent;
26256818Sralph 		dtopMouseEvent = xcfbMouseEvent;
26356818Sralph 		dtopMouseButtons = xcfbMouseButtons;
26456818Sralph 		splx(s);
26556818Sralph 		break;
26656818Sralph 
26756818Sralph 	case QIOKERNUNLOOP:
26856818Sralph 		s = spltty();
26956818Sralph 		dtopDivertXInput = (void (*)())0;
27056818Sralph 		dtopMouseEvent = (void (*)())0;
27156818Sralph 		dtopMouseButtons = (void (*)())0;
27256818Sralph 		splx(s);
27356818Sralph 		break;
27456818Sralph 
27556818Sralph 	case QIOVIDEOON:
27656818Sralph 		xcfbRestoreCursorColor();
27756818Sralph 		ims332_video_on();
27856818Sralph 		break;
27956818Sralph 
28056818Sralph 	case QIOVIDEOOFF:
28156818Sralph 		ims332_video_off();
28256818Sralph 		break;
28356818Sralph 
28456818Sralph 	default:
28556818Sralph 		printf("xcfb0: Unknown ioctl command %x\n", cmd);
28656818Sralph 		return (EINVAL);
28756818Sralph 	}
28856818Sralph 	return (0);
28956818Sralph }
29056818Sralph 
29158974Sralph /*
29258974Sralph  * Return the physical page number that corresponds to byte offset 'off'.
29358974Sralph  */
29458974Sralph /*ARGSUSED*/
29558974Sralph xcfbmap(dev, off, prot)
29658974Sralph 	dev_t dev;
29758974Sralph {
29858974Sralph 	int len;
29958974Sralph 
30058974Sralph 	len = pmax_round_page(((vm_offset_t)&xcfbu & PGOFSET) + sizeof(xcfbu));
30158974Sralph 	if (off < len)
30258974Sralph 		return pmax_btop(MACH_CACHED_TO_PHYS(&xcfbu) + off);
30358974Sralph 	off -= len;
30458974Sralph 	if (off >= xcfbfb.fr_size)
30558974Sralph 		return (-1);
30658974Sralph 	return pmax_btop(MACH_UNCACHED_TO_PHYS(xcfbfb.fr_addr) + off);
30758974Sralph }
30858974Sralph 
30956818Sralph xcfbselect(dev, flag, p)
31056818Sralph 	dev_t dev;
31156818Sralph 	int flag;
31256818Sralph 	struct proc *p;
31356818Sralph {
31456818Sralph 	struct pmax_fb *fp = &xcfbfb;
31556818Sralph 
31656818Sralph 	switch (flag) {
31756818Sralph 	case FREAD:
31856818Sralph 		if (fp->fbu->scrInfo.qe.eHead != fp->fbu->scrInfo.qe.eTail)
31956818Sralph 			return (1);
32056818Sralph 		selrecord(p, &fp->selp);
32156818Sralph 		break;
32256818Sralph 	}
32356818Sralph 
32456818Sralph 	return (0);
32556818Sralph }
32656818Sralph 
32756818Sralph static u_char	cursor_RGB[6];	/* cursor color 2 & 3 */
32856818Sralph 
32956818Sralph /*
33056818Sralph  *	Routines for the Inmos IMS-G332 Colour video controller
33156818Sralph  * 	Author: Alessandro Forin, Carnegie Mellon University
33256818Sralph  */
33356818Sralph static u_int
33456818Sralph ims332_read_register(regno)
33556818Sralph {
33656818Sralph 	register u_char *regs = (u_char *)IMS332_ADDRESS;
33756818Sralph 	unsigned char *rptr;
33856818Sralph 	register u_int val, v1;
33956818Sralph 
34056818Sralph 	/* spec sez: */
34156818Sralph 	rptr = regs + 0x80000 + (regno << 4);
34256818Sralph 	val = *((volatile u_short *) rptr );
34356818Sralph 	v1  = *((volatile u_short *) regs );
34456818Sralph 
34556818Sralph 	return (val & 0xffff) | ((v1 & 0xff00) << 8);
34656818Sralph }
34756818Sralph 
34856818Sralph static void
34956818Sralph ims332_write_register(regno, val)
35056818Sralph 	register unsigned int val;
35156818Sralph {
35256818Sralph 	register u_char *regs = (u_char *)IMS332_ADDRESS;
35356818Sralph 	u_char *wptr;
35456818Sralph 
35556818Sralph 	/* spec sez: */
35656818Sralph 	wptr = regs + 0xa0000 + (regno << 4);
35756818Sralph 	*((volatile u_int *)(regs)) = (val >> 8) & 0xff00;
35856818Sralph 	*((volatile u_short *)(wptr)) = val;
35956818Sralph }
36056818Sralph 
36156818Sralph #define	assert_ims332_reset_bit(r)	*r &= ~0x40
36256818Sralph #define	deassert_ims332_reset_bit(r)	*r |=  0x40
36356818Sralph 
36456818Sralph /*
36556818Sralph  * Color map
36656818Sralph  */
36756818Sralph static void
36856818Sralph xcfbLoadColorMap(ptr)
36956818Sralph 	ColorMap *ptr;
37056818Sralph {
37156818Sralph 	register int i;
37256818Sralph 
37356818Sralph 	if (ptr->index > 256)
37456818Sralph 		return;
37556818Sralph 	ims332_load_colormap_entry(ptr->index, ptr);
37656818Sralph }
37756818Sralph 
37856818Sralph static void
37956818Sralph ims332_load_colormap_entry(entry, map)
38056818Sralph 	ColorMap *map;
38156818Sralph {
38256818Sralph 	/* ?? stop VTG */
38356818Sralph 	ims332_write_register(IMS332_REG_LUT_BASE + (entry & 0xff),
38456818Sralph 			      (map->Entry.blue << 16) |
38556818Sralph 			      (map->Entry.green << 8) |
38656818Sralph 			      (map->Entry.red));
38756818Sralph }
38856818Sralph 
38956818Sralph static void
39056818Sralph xcfbInitColorMap()
39156818Sralph {
39256818Sralph 	register int i;
39356818Sralph 	ColorMap m;
39456818Sralph 
39556818Sralph 	m.Entry.red = m.Entry.green = m.Entry.blue = 0;
39656818Sralph 	ims332_load_colormap_entry(0, &m);
39756818Sralph 
39856818Sralph 	m.Entry.red = m.Entry.green = m.Entry.blue = 0xff;
39956818Sralph 	for (i = 1; i < 256; i++)
40056818Sralph 		ims332_load_colormap_entry(i, &m);
40156818Sralph 
40256818Sralph 	for (i = 0; i < 3; i++) {
40356818Sralph 		cursor_RGB[i] = 0x00;
40456818Sralph 		cursor_RGB[i + 3] = 0xff;
40556818Sralph 	}
40656818Sralph 	xcfbRestoreCursorColor();
40756818Sralph }
40856818Sralph 
40956818Sralph /*
41056818Sralph  * Video on/off
41156818Sralph  *
41256818Sralph  * It is unfortunate that X11 goes backward with white@0
41356818Sralph  * and black@1.  So we must stash away the zero-th entry
41456818Sralph  * and fix it while screen is off.  Also must remember
41556818Sralph  * it, sigh.
41656818Sralph  */
41756818Sralph static struct {
41856818Sralph 	u_int	save;
41956818Sralph 	int	off;
42056818Sralph } xcfb_vstate;
42156818Sralph 
42256818Sralph static void
42356818Sralph ims332_video_off()
42456818Sralph {
42556818Sralph 	register u_int csr;
42656818Sralph 
42756818Sralph 	if (xcfb_vstate.off)
42856818Sralph 		return;
42956818Sralph 
43056818Sralph 	xcfb_vstate.save = ims332_read_register(IMS332_REG_LUT_BASE);
43156818Sralph 
43256818Sralph 	ims332_write_register(IMS332_REG_LUT_BASE, 0);
43356818Sralph 
43456818Sralph 	ims332_write_register(IMS332_REG_COLOR_MASK, 0);
43556818Sralph 
43656818Sralph 	/* cursor now */
43756818Sralph 	csr = ims332_read_register(IMS332_REG_CSR_A);
43856818Sralph 	csr |= IMS332_CSR_A_DISABLE_CURSOR;
43956818Sralph 	ims332_write_register(IMS332_REG_CSR_A, csr);
44056818Sralph 
44156818Sralph 	xcfb_vstate.off = 1;
44256818Sralph }
44356818Sralph 
44456818Sralph static void
44556818Sralph ims332_video_on()
44656818Sralph {
44756818Sralph 	register u_int csr;
44856818Sralph 
44956818Sralph 	if (!xcfb_vstate.off)
45056818Sralph 		return;
45156818Sralph 
45256818Sralph 	ims332_write_register(IMS332_REG_LUT_BASE, xcfb_vstate.save);
45356818Sralph 
45456818Sralph 	ims332_write_register(IMS332_REG_COLOR_MASK, 0xffffffff);
45556818Sralph 
45656818Sralph 	/* cursor now */
45756818Sralph 	csr = ims332_read_register(IMS332_REG_CSR_A);
45856818Sralph 	csr &= ~IMS332_CSR_A_DISABLE_CURSOR;
45956818Sralph 	ims332_write_register(IMS332_REG_CSR_A, csr);
46056818Sralph 
46156818Sralph 	xcfb_vstate.off = 0;
46256818Sralph }
46356818Sralph 
46456818Sralph /*
46556818Sralph  * Cursor
46656818Sralph  */
46756818Sralph void
46856818Sralph xcfbPosCursor(x, y)
46956818Sralph 	register int x, y;
47056818Sralph {
47157234Sralph 	register struct pmax_fb *fp = &xcfbfb;
47256818Sralph 
47357234Sralph 	if (y < fp->fbu->scrInfo.min_cur_y || y > fp->fbu->scrInfo.max_cur_y)
47457234Sralph 		y = fp->fbu->scrInfo.max_cur_y;
47557234Sralph 	if (x < fp->fbu->scrInfo.min_cur_x || x > fp->fbu->scrInfo.max_cur_x)
47657234Sralph 		x = fp->fbu->scrInfo.max_cur_x;
47757234Sralph 	fp->fbu->scrInfo.cursor.x = x;		/* keep track of real cursor */
47857234Sralph 	fp->fbu->scrInfo.cursor.y = y;		/* position, indep. of mouse */
47956818Sralph 	ims332_write_register(IMS332_REG_CURSOR_LOC,
48056818Sralph 		((x & 0xfff) << 12) | (y & 0xfff));
48156818Sralph }
48256818Sralph 
48356818Sralph /*
48456818Sralph  * xcfbRestoreCursorColor
48556818Sralph  */
48656818Sralph static void
48756818Sralph xcfbRestoreCursorColor()
48856818Sralph {
48956818Sralph 
49056818Sralph 	/* Bg is color[0], Fg is color[1] */
49156818Sralph 	ims332_write_register(IMS332_REG_CURSOR_LUT_0,
49256818Sralph 			      (cursor_RGB[2] << 16) |
49356818Sralph 			      (cursor_RGB[1] << 8) |
49456818Sralph 			      (cursor_RGB[0]));
49556818Sralph 	ims332_write_register(IMS332_REG_CURSOR_LUT_1, 0x7f0000);
49656818Sralph 	ims332_write_register(IMS332_REG_CURSOR_LUT_2,
49756818Sralph 			      (cursor_RGB[5] << 16) |
49856818Sralph 			      (cursor_RGB[4] << 8) |
49956818Sralph 			      (cursor_RGB[3]));
50056818Sralph }
50156818Sralph 
50256818Sralph /*
50356818Sralph  * ----------------------------------------------------------------------------
50456818Sralph  *
50556818Sralph  * xcfbCursorColor --
50656818Sralph  *
50756818Sralph  *	Set the color of the cursor.
50856818Sralph  *
50956818Sralph  * Results:
51056818Sralph  *	None.
51156818Sralph  *
51256818Sralph  * Side effects:
51356818Sralph  *	None.
51456818Sralph  *
51556818Sralph  * ----------------------------------------------------------------------------
51656818Sralph  */
51756818Sralph static void
51856818Sralph xcfbCursorColor(color)
51956818Sralph 	unsigned int color[];
52056818Sralph {
52156818Sralph 	register int i, j;
52256818Sralph 
52356818Sralph 	for (i = 0; i < 6; i++)
52456818Sralph 		cursor_RGB[i] = (u_char)(color[i] >> 8);
52556818Sralph 
52656818Sralph 	xcfbRestoreCursorColor();
52756818Sralph }
52856818Sralph 
52956818Sralph static void
53056818Sralph xcfbLoadCursor(cursor)
53156818Sralph 	u_short *cursor;
53256818Sralph {
53356818Sralph 	register int i, j, k, pos;
53456818Sralph 	register u_short ap, bp, out;
53556818Sralph 
53656818Sralph 	/*
53756818Sralph 	 * Fill in the cursor sprite using the A and B planes, as provided
53856818Sralph 	 * for the pmax.
53956818Sralph 	 * XXX This will have to change when the X server knows that this
54056818Sralph 	 * is not a pmax display.
54156818Sralph 	 */
54256818Sralph 	pos = 0;
54356818Sralph 	for (k = 0; k < 16; k++) {
54456818Sralph 		ap = *cursor;
54556818Sralph 		bp = *(cursor + 16);
54656818Sralph 		j = 0;
54756818Sralph 		while (j < 2) {
54856818Sralph 			out = 0;
54956818Sralph 			for (i = 0; i < 8; i++) {
55057234Sralph 				out = ((out >> 2) & 0x3fff) |
55157234Sralph 					((ap & 0x1) << 15) |
55257234Sralph 					((bp & 0x1) << 14);
55356818Sralph 				ap >>= 1;
55456818Sralph 				bp >>= 1;
55556818Sralph 			}
55656818Sralph 			ims332_write_register(IMS332_REG_CURSOR_RAM + pos, out);
55756818Sralph 			pos++;
55856818Sralph 			j++;
55956818Sralph 		}
56056818Sralph 		while (j < 8) {
56156818Sralph 			ims332_write_register(IMS332_REG_CURSOR_RAM + pos, 0);
56256818Sralph 			pos++;
56356818Sralph 			j++;
56456818Sralph 		}
56556818Sralph 		cursor++;
56656818Sralph 	}
56756818Sralph 	while (pos < 512) {
56856818Sralph 		ims332_write_register(IMS332_REG_CURSOR_RAM + pos, 0);
56956818Sralph 		pos++;
57056818Sralph 	}
57156818Sralph }
57256818Sralph 
57356818Sralph /*
57456818Sralph  * Initialization
57556818Sralph  */
57656818Sralph int
57756818Sralph xcfbinit()
57856818Sralph {
57956818Sralph 	register u_int *reset = (u_int *)IMS332_RESET_ADDRESS;
58056818Sralph 	register struct pmax_fb *fp = &xcfbfb;
58156818Sralph 
58256818Sralph 	fp->isMono = 0;
58357234Sralph 
58457234Sralph 	/*
58557234Sralph 	 * Or Cached? A comment in the Mach driver suggests that the X server
58657234Sralph 	 * runs faster in cached address space, but the X server is going
58757234Sralph 	 * to blow away the data cache whenever it updates the screen, so..
58857234Sralph 	 */
58956818Sralph 	fp->fr_addr = (char *)
59057234Sralph 		MACH_PHYS_TO_UNCACHED(XINE_PHYS_CFB_START + VRAM_OFFSET);
59158974Sralph 	fp->fr_size = 0x100000;
59257234Sralph 	/*
59358974Sralph 	 * Must be in Uncached space since the fbuaccess structure is
59458974Sralph 	 * mapped into the user's address space uncached.
59557234Sralph 	 */
59657234Sralph 	fp->fbu = (struct fbuaccess *)
59757234Sralph 		MACH_PHYS_TO_UNCACHED(MACH_CACHED_TO_PHYS(&xcfbu));
59856818Sralph 	fp->posCursor = xcfbPosCursor;
59956818Sralph 	fp->KBDPutc = dtopKBDPutc;
60056818Sralph 	fp->kbddev = makedev(DTOPDEV, DTOPKBD_PORT);
60156818Sralph 
60256818Sralph 	/*
60356818Sralph 	 * Initialize the screen.
60456818Sralph 	 */
60556818Sralph #ifdef notdef
60656818Sralph 	assert_ims332_reset_bit(reset);
60756818Sralph 	DELAY(1);	/* specs sez 50ns.. */
60856818Sralph 	deassert_ims332_reset_bit(reset);
60956818Sralph 
61056818Sralph 	/* CLOCKIN appears to receive a 6.25 Mhz clock --> PLL 12 for 75Mhz monitor */
61156818Sralph 	ims332_write_register(IMS332_REG_BOOT, 12 | IMS332_BOOT_CLOCK_PLL);
61256818Sralph 
61356818Sralph 	/* initialize VTG */
61456818Sralph 	ims332_write_register(IMS332_REG_CSR_A,
61556818Sralph 				IMS332_BPP_8 | IMS332_CSR_A_DISABLE_CURSOR);
61656818Sralph 	DELAY(50);	/* spec does not say */
61756818Sralph 
61856818Sralph 	/* datapath registers (values taken from prom's settings) */
61956818Sralph 
62056818Sralph 	ims332_write_register(IMS332_REG_HALF_SYNCH, 0x10);
62156818Sralph 	ims332_write_register(IMS332_REG_BACK_PORCH, 0x21);
62256818Sralph 	ims332_write_register(IMS332_REG_DISPLAY, 0x100);
62356818Sralph 	ims332_write_register(IMS332_REG_SHORT_DIS, 0x5d);
62456818Sralph 	ims332_write_register(IMS332_REG_BROAD_PULSE, 0x9f);
62556818Sralph 	ims332_write_register(IMS332_REG_V_SYNC, 0xc);
62656818Sralph 	ims332_write_register(IMS332_REG_V_PRE_EQUALIZE, 2);
62756818Sralph 	ims332_write_register(IMS332_REG_V_POST_EQUALIZE, 2);
62856818Sralph 	ims332_write_register(IMS332_REG_V_BLANK, 0x2a);
62956818Sralph 	ims332_write_register(IMS332_REG_V_DISPLAY, 0x600);
63056818Sralph 	ims332_write_register(IMS332_REG_LINE_TIME, 0x146);
63156818Sralph 	ims332_write_register(IMS332_REG_LINE_START, 0x10);
63256818Sralph 	ims332_write_register(IMS332_REG_MEM_INIT, 0xa);
63356818Sralph 	ims332_write_register(IMS332_REG_XFER_DELAY, 0xa);
63456818Sralph 
63556818Sralph 	ims332_write_register(IMS332_REG_COLOR_MASK, 0xffffff);
63656818Sralph #endif
63756818Sralph 
63856818Sralph 	/*
63956818Sralph 	 * Initialize screen info.
64056818Sralph 	 */
64156818Sralph 	fp->fbu->scrInfo.max_row = 50;
64256818Sralph 	fp->fbu->scrInfo.max_col = 80;
64356818Sralph 	fp->fbu->scrInfo.max_x = 1024;
64456818Sralph 	fp->fbu->scrInfo.max_y = 768;
64557234Sralph 	fp->fbu->scrInfo.max_cur_x = 1008;
64657234Sralph 	fp->fbu->scrInfo.max_cur_y = 752;
64756818Sralph 	fp->fbu->scrInfo.version = 11;
64856818Sralph 	fp->fbu->scrInfo.mthreshold = 4;
64956818Sralph 	fp->fbu->scrInfo.mscale = 2;
65056818Sralph 	fp->fbu->scrInfo.min_cur_x = -15;
65156818Sralph 	fp->fbu->scrInfo.min_cur_y = -15;
65256818Sralph 	fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
65356818Sralph 	fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
65456818Sralph 	fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
65556818Sralph 	fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
65656818Sralph 	fp->fbu->scrInfo.qe.tcNext = 0;
65756818Sralph 
65856818Sralph 	xcfbInitColorMap();
65956818Sralph 
66056818Sralph 	ims332_write_register(IMS332_REG_CSR_A,
66156818Sralph 		IMS332_BPP_8 | IMS332_CSR_A_DMA_DISABLE | IMS332_CSR_A_VTG_ENABLE);
66256818Sralph 
66356818Sralph 	xcfbScreenInit();
66456818Sralph 	fbScroll(fp);
66556818Sralph 
66656818Sralph 	fp->initialized = 1;
66756818Sralph 	if (cn_tab.cn_fb == (struct pmax_fb *)0)
66856818Sralph 		cn_tab.cn_fb = fp;
66956818Sralph 	return (1);
67056818Sralph }
67156818Sralph 
67256818Sralph /*
67356818Sralph  * ----------------------------------------------------------------------------
67456818Sralph  *
67556818Sralph  * xcfbScreenInit --
67656818Sralph  *
67756818Sralph  *	Initialize the screen.
67856818Sralph  *
67956818Sralph  * Results:
68056818Sralph  *	None.
68156818Sralph  *
68256818Sralph  * Side effects:
68356818Sralph  *	The screen is initialized.
68456818Sralph  *
68556818Sralph  * ----------------------------------------------------------------------------
68656818Sralph  */
68756818Sralph static void
68856818Sralph xcfbScreenInit()
68956818Sralph {
69056818Sralph 	register struct pmax_fb *fp = &xcfbfb;
69156818Sralph 
69256818Sralph 	/*
69356818Sralph 	 * Home the cursor.
69456818Sralph 	 * We want an LSI terminal emulation.  We want the graphics
69556818Sralph 	 * terminal to scroll from the bottom. So start at the bottom.
69656818Sralph 	 */
69756818Sralph 	fp->row = 49;
69856818Sralph 	fp->col = 0;
69956818Sralph 
70056818Sralph 	/*
70156818Sralph 	 * Load the cursor with the default values
70256818Sralph 	 *
70356818Sralph 	 */
70456818Sralph 	xcfbLoadCursor(defCursor);
70556818Sralph }
70656818Sralph 
70756818Sralph /*
70856818Sralph  * xcfb keyboard and mouse input. Just punt to the generic ones in fb.c
70956818Sralph  */
71056818Sralph void
71156818Sralph xcfbKbdEvent(ch)
71256818Sralph 	int ch;
71356818Sralph {
71456818Sralph 	fbKbdEvent(ch, &xcfbfb);
71556818Sralph }
71656818Sralph 
71756818Sralph void
71856818Sralph xcfbMouseEvent(newRepPtr)
71956818Sralph 	MouseReport *newRepPtr;
72056818Sralph {
72156818Sralph 	fbMouseEvent(newRepPtr, &xcfbfb);
72256818Sralph }
72356818Sralph 
72456818Sralph void
72556818Sralph xcfbMouseButtons(newRepPtr)
72656818Sralph 	MouseReport *newRepPtr;
72756818Sralph {
72856818Sralph 	fbMouseButtons(newRepPtr, &xcfbfb);
72956818Sralph }
73056818Sralph #endif /* NDTOP */
73156818Sralph #endif /* NXCFB */
732