xref: /netbsd-src/sys/arch/sparc/dev/cgfourteen.c (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
1 /*	$NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp $ */
2 
3 /*
4  * Copyright (c) 1996
5  *	The President and Fellows of Harvard College. All rights reserved.
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This software was developed by the Computer Systems Engineering group
10  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11  * contributed to Berkeley.
12  *
13  * All advertising materials mentioning features or use of this software
14  * must display the following acknowledgement:
15  *	This product includes software developed by Harvard University.
16  *	This product includes software developed by the University of
17  *	California, Lawrence Berkeley Laboratory.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in the
26  *    documentation and/or other materials provided with the distribution.
27  * 3. All advertising materials mentioning features or use of this software
28  *    must display the following acknowledgement:
29  *	This product includes software developed by the University of
30  *	California, Berkeley and its contributors.
31  *	This product includes software developed by Harvard University and
32  *	its contributors.
33  * 4. Neither the name of the University nor the names of its contributors
34  *    may be used to endorse or promote products derived from this software
35  *    without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  *
49  *   Based on:
50  *	NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp
51  *	NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp
52  */
53 
54 /*
55  * Driver for Campus-II on-board mbus-based video (cgfourteen).
56  * Provides minimum emulation of a Sun cgthree 8-bit framebuffer to
57  * allow X to run.
58  *
59  * Does not handle interrupts, even though they can occur.
60  *
61  * XXX should defer colormap updates to vertical retrace interrupts
62  */
63 
64 /*
65  * The following is for debugging only; it opens up a security hole
66  * enabled by allowing any user to map the control registers for the
67  * cg14 into their space.
68  */
69 #undef CG14_MAP_REGS
70 
71 /*
72  * The following enables 24-bit operation: when opened, the framebuffer
73  * will switch to 24-bit mode (actually 32-bit mode), and provide a
74  * simple cg8 emulation.
75  *
76  * XXX Note that the code enabled by this define is currently untested/broken.
77  */
78 #undef CG14_CG8
79 
80 #include <sys/cdefs.h>
81 __KERNEL_RCSID(0, "$NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp $");
82 
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/buf.h>
86 #include <sys/device.h>
87 #include <sys/ioctl.h>
88 #include <sys/malloc.h>
89 #include <sys/mman.h>
90 #include <sys/tty.h>
91 #include <sys/conf.h>
92 
93 #include <uvm/uvm_extern.h>
94 
95 #include <machine/bus.h>
96 #include <machine/autoconf.h>
97 
98 #include <dev/sbus/sbusvar.h>
99 
100 #include <dev/sun/fbio.h>
101 #include <dev/sun/fbvar.h>
102 
103 #include <sparc/dev/cgfourteenreg.h>
104 #include <sparc/dev/cgfourteenvar.h>
105 
106 /* autoconfiguration driver */
107 static int	cgfourteenmatch(struct device *, struct cfdata *, void *);
108 static void	cgfourteenattach(struct device *, struct device *, void *);
109 static void	cgfourteenunblank(struct device *);
110 
111 CFATTACH_DECL(cgfourteen, sizeof(struct cgfourteen_softc),
112     cgfourteenmatch, cgfourteenattach, NULL, NULL);
113 
114 extern struct cfdriver cgfourteen_cd;
115 
116 dev_type_open(cgfourteenopen);
117 dev_type_close(cgfourteenclose);
118 dev_type_ioctl(cgfourteenioctl);
119 dev_type_mmap(cgfourteenmmap);
120 
121 const struct cdevsw cgfourteen_cdevsw = {
122 	cgfourteenopen, cgfourteenclose, noread, nowrite, cgfourteenioctl,
123 	nostop, notty, nopoll, cgfourteenmmap, nokqfilter,
124 };
125 
126 /* frame buffer generic driver */
127 static struct fbdriver cgfourteenfbdriver = {
128 	cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl,
129 	nopoll, cgfourteenmmap, nokqfilter
130 };
131 
132 static void cg14_set_video(struct cgfourteen_softc *, int);
133 static int  cg14_get_video(struct cgfourteen_softc *);
134 static int  cg14_get_cmap(struct fbcmap *, union cg14cmap *, int);
135 static int  cg14_put_cmap(struct fbcmap *, union cg14cmap *, int);
136 static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int);
137 static void cg14_init(struct cgfourteen_softc *);
138 static void cg14_reset(struct cgfourteen_softc *);
139 static void cg14_loadomap(struct cgfourteen_softc *);	/* cursor overlay */
140 static void cg14_setcursor(struct cgfourteen_softc *);	/* set position */
141 static void cg14_loadcursor(struct cgfourteen_softc *);	/* set shape */
142 
143 /*
144  * We map the display memory with an offset of 256K when emulating the cg3 or
145  * cg8; the cg3 uses this offset for compatibility with the cg4, and both the
146  * cg4 and cg8 have a mono overlay plane and an overlay enable plane in the
147  * first 256K.  Mapping at an offset of 0x04000000 causes only the color
148  * frame buffer to be mapped, without the overlay planes.
149  */
150 #define START		(128*1024 + 128*1024)
151 #define NOOVERLAY	(0x04000000)
152 
153 /*
154  * Match a cgfourteen.
155  */
156 static int
157 cgfourteenmatch(struct device *parent, struct cfdata *cf, void *aux)
158 {
159 	union obio_attach_args *uoba = aux;
160 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
161 
162 	/*
163 	 * The cgfourteen is a local-bus video adaptor, accessed directly
164 	 * via the processor, and not through device space or an external
165 	 * bus. Thus we look _only_ at the obio bus.
166 	 * Additionally, these things exist only on the Sun4m.
167 	 */
168 
169 	if (uoba->uoba_isobio4 != 0 || !CPU_ISSUN4M)
170 		return (0);
171 
172 	/* Check driver name */
173 	return (strcmp(cf->cf_name, sa->sa_name) == 0);
174 }
175 
176 /*
177  * Attach a display.  We need to notice if it is the console, too.
178  */
179 static void
180 cgfourteenattach(struct device *parent, struct device *self, void *aux)
181 {
182 	union obio_attach_args *uoba = aux;
183 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
184 	struct cgfourteen_softc *sc = (struct cgfourteen_softc *)self;
185 	struct fbdevice *fb = &sc->sc_fb;
186 	bus_space_handle_t bh;
187 	int node, ramsize;
188 	volatile uint32_t *lut;
189 	int i, isconsole;
190 
191 	node = sa->sa_node;
192 
193 	/* Remember cookies for cgfourteenmmap() */
194 	sc->sc_bustag = sa->sa_bustag;
195 
196 	fb->fb_driver = &cgfourteenfbdriver;
197 	fb->fb_device = &sc->sc_dev;
198 	/* Mask out invalid flags from the user. */
199 	fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags & FB_USERMASK;
200 
201 	/*
202 	 * We're emulating a cg3/8, so represent ourselves as one
203 	 */
204 #ifdef CG14_CG8
205 	fb->fb_type.fb_type = FBTYPE_MEMCOLOR;
206 	fb->fb_type.fb_depth = 32;
207 #else
208 	fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
209 	fb->fb_type.fb_depth = 8;
210 #endif
211 	fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node);
212 #ifdef CG14_CG8
213 	/*
214 	 * fb_setsize_obp set fb->fb_linebytes based on the current
215 	 * depth reported by obp, but that defaults to 8 bits (as
216 	 * reported by getpropint().  Update the value to reflect
217 	 * the depth that will be used after open.
218 	 * The display memory size returned by the cg8 driver includes
219 	 * the space used by the overlay planes, but the size returned
220 	 * by the cg3 driver does not; emulate the other drivers.
221 	 */
222 	fb->fb_linebytes = (fb->fb_type.fb_width * fb->fb_type.fb_depth) / 8;
223 	ramsize = roundup(START + (fb->fb_type.fb_height * fb->fb_linebytes),
224 			PAGE_SIZE);
225 #else
226 	ramsize = roundup(fb->fb_type.fb_height * fb->fb_linebytes, PAGE_SIZE);
227 #endif
228 	fb->fb_type.fb_cmsize = CG14_CLUT_SIZE;
229 	fb->fb_type.fb_size = ramsize;
230 
231 	if (sa->sa_nreg < 2) {
232 		printf("%s: only %d register sets\n",
233 			self->dv_xname, sa->sa_nreg);
234 		return;
235 	}
236 	bcopy(sa->sa_reg, sc->sc_physadr,
237 	      sa->sa_nreg * sizeof(struct openprom_addr));
238 
239 	/*
240 	 * Now map in the 8 useful pages of registers
241 	 */
242 	if (sa->sa_size < 0x10000) {
243 #ifdef DIAGNOSTIC
244 		printf("warning: can't find all cgfourteen registers...\n");
245 #endif
246 		sa->sa_size = 0x10000;
247 	}
248 	if (sbus_bus_map(sa->sa_bustag,
249 			 sa->sa_slot, sa->sa_offset, sa->sa_size,
250 			 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
251 		printf("%s: cannot map control registers\n", self->dv_xname);
252 		return;
253 	}
254 
255 	sc->sc_ctl   = (struct cg14ctl  *) (bh);
256 	sc->sc_hwc   = (struct cg14curs *) (bh + CG14_OFFSET_CURS);
257 	sc->sc_dac   = (struct cg14dac  *) (bh + CG14_OFFSET_DAC);
258 	sc->sc_xlut  = (struct cg14xlut *) (bh + CG14_OFFSET_XLUT);
259 	sc->sc_clut1 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT1);
260 	sc->sc_clut2 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT2);
261 	sc->sc_clut3 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT3);
262 	sc->sc_clutincr =        (u_int *) (bh + CG14_OFFSET_CLUTINCR);
263 
264 	/*
265 	 * Let the user know that we're here
266 	 */
267 #ifdef CG14_CG8
268 	printf(": cgeight emulated at %dx%dx24bpp",
269 		fb->fb_type.fb_width, fb->fb_type.fb_height);
270 #else
271 	printf(": cgthree emulated at %dx%dx8bpp",
272 		fb->fb_type.fb_width, fb->fb_type.fb_height);
273 #endif
274 	/*
275 	 * Enable the video, but don't change the pixel depth.
276 	 */
277 	cg14_set_video(sc, 1);
278 
279 	/*
280 	 * Grab the initial colormap
281 	 */
282 	lut = sc->sc_clut1->clut_lut;
283 	for (i = 0; i < CG14_CLUT_SIZE; i++)
284 		sc->sc_cmap.cm_chip[i] = lut[i];
285 
286 	/* See if we're the console */
287 	isconsole = fb_is_console(node);
288 
289 	if (isconsole) {
290 		printf(" (console)\n");
291 #ifdef notdef
292 		/*
293 		 * We don't use the raster console since the cg14 is
294 		 * fast enough already.
295 		 */
296 #ifdef RASTERCONSOLE
297 		fbrcons_init(fb);
298 #endif
299 #endif /* notdef */
300 	} else
301 		printf("\n");
302 
303 	/* Attach to /dev/fb */
304 	fb_attach(&sc->sc_fb, isconsole);
305 }
306 
307 /*
308  * Keep track of the number of opens made. In the 24-bit driver, we need to
309  * switch to 24-bit mode on the first open, and switch back to 8-bit on
310  * the last close. This kind of nonsense is needed to give screenblank
311  * a fighting chance of working.
312  */
313 static int cg14_opens = 0;
314 
315 int
316 cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l)
317 {
318 	struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)];
319 	int unit = minor(dev);
320 	int s, oldopens;
321 
322 	if (unit >= cgfourteen_cd.cd_ndevs ||
323 	    cgfourteen_cd.cd_devs[unit] == NULL)
324 		return (ENXIO);
325 
326 	s = splhigh();
327 	oldopens = cg14_opens++;
328 	splx(s);
329 
330 	/* Setup the cg14 as we want it, and save the original PROM state */
331 	if (oldopens == 0)	/* first open only, to make screenblank work */
332 		cg14_init(sc);
333 
334 	return (0);
335 }
336 
337 int
338 cgfourteenclose(dev_t dev, int flags, int mode, struct lwp *l)
339 {
340 	struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)];
341 	int s, opens;
342 
343 	s = splhigh();
344 	opens = --cg14_opens;
345 	if (cg14_opens < 0)
346 		opens = cg14_opens = 0;
347 	splx(s);
348 
349 	/*
350 	 * Restore video state to make the PROM happy, on last close.
351 	 */
352 	if (opens == 0)
353 		cg14_reset(sc);
354 
355 	return (0);
356 }
357 
358 int
359 cgfourteenioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l)
360 {
361 	struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)];
362 	struct fbgattr *fba;
363 	union cg14cursor_cmap tcm;
364 	int v, error;
365 	u_int count;
366 	u_int eplane[32], cplane[32];
367 
368 	switch (cmd) {
369 
370 	case FBIOGTYPE:
371 		*(struct fbtype *)data = sc->sc_fb.fb_type;
372 		break;
373 
374 	case FBIOGATTR:
375 		fba = (struct fbgattr *)data;
376 		fba->real_type = FBTYPE_MDICOLOR;
377 		fba->owner = 0;		/* XXX ??? */
378 		fba->fbtype = sc->sc_fb.fb_type;
379 		fba->sattr.flags = 0;
380 		fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
381 		fba->sattr.dev_specific[0] = -1;
382 		fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
383 		fba->emu_types[1] = -1;
384 		break;
385 
386 	case FBIOGETCMAP:
387 		return (cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap,
388 				     CG14_CLUT_SIZE));
389 
390 	case FBIOPUTCMAP:
391 		/* copy to software map */
392 #define p ((struct fbcmap *)data)
393 #ifdef CG14_CG8
394 		p->index &= 0xffffff;
395 #endif
396 		error = cg14_put_cmap(p, &sc->sc_cmap, CG14_CLUT_SIZE);
397 		if (error)
398 			return (error);
399 		/* now blast them into the chip */
400 		/* XXX should use retrace interrupt */
401 		cg14_load_hwcmap(sc, p->index, p->count);
402 #undef p
403 		break;
404 
405 	case FBIOGVIDEO:
406 		*(int *)data = cg14_get_video(sc);
407 		break;
408 
409 	case FBIOSVIDEO:
410 		cg14_set_video(sc, *(int *)data);
411 		break;
412 
413 /* these are for both FBIOSCURSOR and FBIOGCURSOR */
414 #define p ((struct fbcursor *)data)
415 #define cc (&sc->sc_cursor)
416 	case FBIOGCURSOR:
417 		/* do not quite want everything here... */
418 		p->set = FB_CUR_SETALL;	/* close enough, anyway */
419 		p->enable = cc->cc_enable;
420 		p->pos = cc->cc_pos;
421 		p->hot = cc->cc_hot;
422 		p->size = cc->cc_size;
423 
424 		/* begin ugh ... can we lose some of this crap?? */
425 		if (p->image != NULL) {
426 			count = cc->cc_size.y * 32 / NBBY;
427 			error = copyout(cc->cc_cplane, p->image, count);
428 			if (error)
429 				return (error);
430 			error = copyout(cc->cc_eplane, p->mask, count);
431 			if (error)
432 				return (error);
433 		}
434 		if (p->cmap.red != NULL) {
435 			error = cg14_get_cmap(&p->cmap,
436 			    (union cg14cmap *)&cc->cc_color, 2);
437 			if (error)
438 				return (error);
439 		} else {
440 			p->cmap.index = 0;
441 			p->cmap.count = 2;
442 		}
443 		/* end ugh */
444 		break;
445 
446 	case FBIOSCURSOR:
447 		/*
448 		 * For setcmap and setshape, verify parameters, so that
449 		 * we do not get halfway through an update and then crap
450 		 * out with the software state screwed up.
451 		 */
452 		v = p->set;
453 		if (v & FB_CUR_SETCMAP) {
454 			/*
455 			 * This use of a temporary copy of the cursor
456 			 * colormap is not terribly efficient, but these
457 			 * copies are small (8 bytes)...
458 			 */
459 			tcm = cc->cc_color;
460 			error = cg14_put_cmap(&p->cmap, (union cg14cmap *)&tcm,
461 					      2);
462 			if (error)
463 				return (error);
464 		}
465 		if (v & FB_CUR_SETSHAPE) {
466 			if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32)
467 				return (EINVAL);
468 			count = p->size.y * 32 / NBBY;
469 			error = copyin(p->mask, eplane, count);
470 			if (error)
471 				return error;
472 			error = copyin(p->image, cplane, count);
473 			if (error)
474 				return error;
475 		}
476 
477 		/* parameters are OK; do it */
478 		if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) {
479 			if (v & FB_CUR_SETCUR)
480 				cc->cc_enable = p->enable;
481 			if (v & FB_CUR_SETPOS)
482 				cc->cc_pos = p->pos;
483 			if (v & FB_CUR_SETHOT)
484 				cc->cc_hot = p->hot;
485 			cg14_setcursor(sc);
486 		}
487 		if (v & FB_CUR_SETCMAP) {
488 			cc->cc_color = tcm;
489 			cg14_loadomap(sc); /* XXX defer to vertical retrace */
490 		}
491 		if (v & FB_CUR_SETSHAPE) {
492 			cc->cc_size = p->size;
493 			count = p->size.y * 32 / NBBY;
494 			memset(cc->cc_eplane, 0, sizeof cc->cc_eplane);
495 			memcpy(cc->cc_eplane, eplane, count);
496 			memset(cc->cc_cplane, 0, sizeof cc->cc_cplane);
497 			memcpy(cc->cc_cplane, cplane, count);
498 			cg14_loadcursor(sc);
499 		}
500 		break;
501 
502 #undef cc
503 #undef p
504 	case FBIOGCURPOS:
505 		*(struct fbcurpos *)data = sc->sc_cursor.cc_pos;
506 		break;
507 
508 	case FBIOSCURPOS:
509 		sc->sc_cursor.cc_pos = *(struct fbcurpos *)data;
510 		cg14_setcursor(sc);
511 		break;
512 
513 	case FBIOGCURMAX:
514 		/* max cursor size is 32x32 */
515 		((struct fbcurpos *)data)->x = 32;
516 		((struct fbcurpos *)data)->y = 32;
517 		break;
518 
519 	default:
520 		return (ENOTTY);
521 	}
522 	return (0);
523 }
524 
525 /*
526  * Undo the effect of an FBIOSVIDEO that turns the video off.
527  */
528 static void
529 cgfourteenunblank(struct device *dev)
530 {
531 
532 	cg14_set_video((struct cgfourteen_softc *)dev, 1);
533 }
534 
535 /*
536  * Return the address that would map the given device at the given
537  * offset, allowing for the given protection, or return -1 for error.
538  *
539  * The cg14 frame buffer can be mapped in either 8-bit or 32-bit mode
540  * starting at the address stored in the PROM. In 8-bit mode, the X
541  * channel is not present, and can be ignored. In 32-bit mode, mapping
542  * at 0K delivers a 32-bpp buffer where the upper 8 bits select the X
543  * channel information. We hardwire the Xlut to all zeroes to insure
544  * that, regardless of this value, direct 24-bit color access will be
545  * used.
546  *
547  * Alternatively, mapping the frame buffer at an offset of 16M seems to
548  * tell the chip to ignore the X channel. XXX where does it get the X value
549  * to use?
550  */
551 paddr_t
552 cgfourteenmmap(dev_t dev, off_t off, int prot)
553 {
554 	struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)];
555 
556 	if (off & PGOFSET)
557 		panic("cgfourteenmmap");
558 
559 	if (off < 0)
560 		return (-1);
561 
562 #if defined(DEBUG) && defined(CG14_MAP_REGS) /* XXX: security hole */
563 	/*
564 	 * Map the control registers into user space. Should only be
565 	 * used for debugging!
566 	 */
567 	if ((u_int)off >= 0x10000000 && (u_int)off < 0x10000000 + 16*4096) {
568 		off -= 0x10000000;
569 		if (bus_space_mmap(sc->sc_bustag,
570 			BUS_ADDR(sc->sc_physadr[CG14_CTL_IDX].sbr_slot,
571 				sc->sc_physadr[CG14_CTL_IDX].sbr_offset),
572 			off, prot, BUS_SPACE_MAP_LINEAR));
573 	}
574 #endif
575 
576 	if ((u_int)off >= NOOVERLAY)
577 		off -= NOOVERLAY;
578 	else if ((u_int)off >= START)
579 		off -= START;
580 	else
581 		off = 0;
582 
583 	/*
584 	 * fb_size includes the overlay space only for the CG8.
585 	 */
586 #ifdef CG14_CG8
587 	if (off >= sc->sc_fb.fb_type.fb_size - START)
588 #else
589 	if (off >= sc->sc_fb.fb_type.fb_size)
590 #endif
591 	{
592 #ifdef DEBUG
593 		printf("\nmmap request out of bounds: request 0x%x, "
594 		    "bound 0x%x\n", (unsigned) off,
595 		    (unsigned)sc->sc_fb.fb_type.fb_size);
596 #endif
597 		return (-1);
598 	}
599 
600 	return (bus_space_mmap(sc->sc_bustag,
601 		BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].oa_space,
602 			sc->sc_physadr[CG14_PXL_IDX].oa_base),
603 		off, prot, BUS_SPACE_MAP_LINEAR));
604 }
605 
606 /*
607  * Miscellaneous helper functions
608  */
609 
610 /* Initialize the framebuffer, storing away useful state for later reset */
611 static void
612 cg14_init(struct cgfourteen_softc *sc)
613 {
614 	volatile uint32_t *clut;
615 	volatile uint8_t  *xlut;
616 	int i;
617 
618 	/*
619 	 * We stash away the following to restore on close:
620 	 *
621 	 * 	color look-up table 1 	(sc->sc_saveclut)
622 	 *	x look-up table		(sc->sc_savexlut)
623 	 *	control register	(sc->sc_savectl)
624 	 *	cursor control register (sc->sc_savehwc)
625 	 */
626 	sc->sc_savectl = sc->sc_ctl->ctl_mctl;
627 	sc->sc_savehwc = sc->sc_hwc->curs_ctl;
628 
629 	clut = sc->sc_clut1->clut_lut;
630 	xlut = sc->sc_xlut->xlut_lut;
631 	for (i = 0; i < CG14_CLUT_SIZE; i++) {
632 		sc->sc_saveclut.cm_chip[i] = clut[i];
633 		sc->sc_savexlut[i] = xlut[i];
634 	}
635 
636 #ifdef CG14_CG8
637 	/*
638 	 * Enable the video, and put in 24 bit mode.
639 	 */
640 	sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_32 |
641 		CG14_MCTL_POWERCTL;
642 
643 	/*
644 	 * Zero the xlut to enable direct-color mode
645 	 */
646 	memset(sc->sc_xlut, 0, CG14_CLUT_SIZE);
647 #else
648 	/*
649 	 * Enable the video and put it in 8 bit mode
650 	 */
651 	sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_8 |
652 		CG14_MCTL_POWERCTL;
653 #endif
654 }
655 
656 /* Restore the state saved on cg14_init */
657 static void
658 cg14_reset(struct cgfourteen_softc *sc)
659 {
660 	volatile uint32_t *clut;
661 	volatile uint8_t  *xlut;
662 	int i;
663 
664 	/*
665 	 * We restore the following, saved in cg14_init:
666 	 *
667 	 * 	color look-up table 1 	(sc->sc_saveclut)
668 	 *	x look-up table		(sc->sc_savexlut)
669 	 *	control register	(sc->sc_savectl)
670 	 *	cursor control register (sc->sc_savehwc)
671 	 *
672 	 * Note that we don't touch the video enable bits in the
673 	 * control register; otherwise, screenblank wouldn't work.
674 	 */
675 	sc->sc_ctl->ctl_mctl = (sc->sc_ctl->ctl_mctl & (CG14_MCTL_ENABLEVID |
676 							CG14_MCTL_POWERCTL)) |
677 				(sc->sc_savectl & ~(CG14_MCTL_ENABLEVID |
678 						    CG14_MCTL_POWERCTL));
679 	sc->sc_hwc->curs_ctl = sc->sc_savehwc;
680 
681 	clut = sc->sc_clut1->clut_lut;
682 	xlut = sc->sc_xlut->xlut_lut;
683 	for (i = 0; i < CG14_CLUT_SIZE; i++) {
684 		clut[i] = sc->sc_saveclut.cm_chip[i];
685 		xlut[i] = sc->sc_savexlut[i];
686 	}
687 }
688 
689 /* Enable/disable video display; power down monitor if DPMS-capable */
690 static void
691 cg14_set_video(struct cgfourteen_softc *sc, int enable)
692 {
693 
694 	/*
695 	 * We can only use DPMS to power down the display if the chip revision
696 	 * is greater than 0.
697 	 */
698 	if (enable) {
699 		if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0)
700 			sc->sc_ctl->ctl_mctl |= (CG14_MCTL_ENABLEVID |
701 						 CG14_MCTL_POWERCTL);
702 		else
703 			sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEVID;
704 	} else {
705 		if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0)
706 			sc->sc_ctl->ctl_mctl &= ~(CG14_MCTL_ENABLEVID |
707 						  CG14_MCTL_POWERCTL);
708 		else
709 			sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEVID;
710 	}
711 }
712 
713 /* Get status of video display */
714 static int
715 cg14_get_video(struct cgfourteen_softc *sc)
716 {
717 
718 	return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0);
719 }
720 
721 /* Read the software shadow colormap */
722 static int
723 cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize)
724 {
725 	u_int i, start, count;
726 	u_char *cp;
727 	int error;
728 
729 	start = p->index;
730 	count = p->count;
731 	if (start >= cmsize || count > cmsize - start)
732 		return (EINVAL);
733 
734 	for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) {
735 		error = copyout(&cp[3], &p->red[i], 1);
736 		if (error)
737 			return error;
738 		error = copyout(&cp[2], &p->green[i], 1);
739 		if (error)
740 			return error;
741 		error = copyout(&cp[1], &p->blue[i], 1);
742 		if (error)
743 			return error;
744 	}
745 	return (0);
746 }
747 
748 /* Write the software shadow colormap */
749 static int
750 cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize)
751 {
752 	u_int i, start, count;
753 	u_char *cp;
754 	u_char cmap[256][4];
755 	int error;
756 
757 	start = p->index;
758 	count = p->count;
759 	if (start >= cmsize || count > cmsize - start)
760 		return (EINVAL);
761 
762 	memcpy(&cmap, &cm->cm_map, sizeof cmap);
763 	for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) {
764 		error = copyin(&p->red[i], &cp[3], 1);
765 		if (error)
766 			return error;
767 		error = copyin(&p->green[i], &cp[2], 1);
768 		if (error)
769 			return error;
770 		error = copyin(&p->blue[i], &cp[1], 1);
771 		if (error)
772 			return error;
773 		cp[0] = 0;	/* no alpha channel */
774 	}
775 	memcpy(&cm->cm_map, &cmap, sizeof cmap);
776 	return (0);
777 }
778 
779 static void
780 cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors)
781 {
782 
783 	/* XXX switch to auto-increment, and on retrace intr */
784 
785 	/* Setup pointers to source and dest */
786 	uint32_t *colp = &sc->sc_cmap.cm_chip[start];
787 	volatile uint32_t *lutp = &sc->sc_clut1->clut_lut[start];
788 
789 	/* Copy by words */
790 	while (--ncolors >= 0)
791 		*lutp++ = *colp++;
792 }
793 
794 /*
795  * Load the cursor (overlay `foreground' and `background') colors.
796  */
797 static void
798 cg14_setcursor(struct cgfourteen_softc *sc)
799 {
800 
801 	/* we need to subtract the hot-spot value here */
802 #define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f)
803 
804 	sc->sc_hwc->curs_ctl = (sc->sc_cursor.cc_enable ? CG14_CURS_ENABLE : 0);
805 	sc->sc_hwc->curs_x = COORD(x);
806 	sc->sc_hwc->curs_y = COORD(y);
807 
808 #undef COORD
809 }
810 
811 static void
812 cg14_loadcursor(struct cgfourteen_softc *sc)
813 {
814 	volatile struct cg14curs *hwc;
815 	u_int edgemask, m;
816 	int i;
817 
818 	/*
819 	 * Keep the top size.x bits.  Here we *throw out* the top
820 	 * size.x bits from an all-one-bits word, introducing zeros in
821 	 * the top size.x bits, then invert all the bits to get what
822 	 * we really wanted as our mask.  But this fails if size.x is
823 	 * 32---a sparc uses only the low 5 bits of the shift count---
824 	 * so we have to special case that.
825 	 */
826 	edgemask = ~0;
827 	if (sc->sc_cursor.cc_size.x < 32)
828 		edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x);
829 	hwc = sc->sc_hwc;
830 	for (i = 0; i < 32; i++) {
831 		m = sc->sc_cursor.cc_eplane[i] & edgemask;
832 		hwc->curs_plane0[i] = m;
833 		hwc->curs_plane1[i] = m & sc->sc_cursor.cc_cplane[i];
834 	}
835 }
836 
837 static void
838 cg14_loadomap(struct cgfourteen_softc *sc)
839 {
840 
841 	/* set background color */
842 	sc->sc_hwc->curs_color1 = sc->sc_cursor.cc_color.cm_chip[0];
843 	/* set foreground color */
844 	sc->sc_hwc->curs_color2 = sc->sc_cursor.cc_color.cm_chip[1];
845 }
846