xref: /netbsd-src/sys/arch/sgimips/gio/grtwo.c (revision 4b896b232495b7a9b8b94a1cf1e21873296d53b8)
1 /* $NetBSD: grtwo.c,v 1.1 2004/03/18 08:52:04 sekiya Exp $	 */
2 
3 /*
4  * Copyright (c) 2004 Christopher SEKIYA
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>>
30  */
31 
32 /* wscons driver for SGI GR2 family of framebuffers
33  *
34  * Heavily based on the newport wscons driver.
35  */
36 
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: grtwo.c,v 1.1 2004/03/18 08:52:04 sekiya Exp $");
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/malloc.h>
44 
45 #include <dev/wscons/wsconsio.h>
46 #include <dev/wscons/wsdisplayvar.h>
47 #include <dev/wsfont/wsfont.h>
48 
49 #include <sgimips/gio/giovar.h>
50 #include <sgimips/gio/grtwovar.h>
51 #include <sgimips/gio/grtworeg.h>
52 
53 #include <sgimips/dev/int2var.h>
54 
55 struct grtwo_softc {
56 	struct device   sc_dev;
57 
58 	struct grtwo_devconfig *sc_dc;
59 };
60 
61 struct grtwo_devconfig {
62 	u_int32_t        dc_addr;
63 
64 	bus_space_tag_t iot;
65 	bus_space_handle_t ioh;
66 
67 	u_int8_t	boardrev;
68 	u_int8_t	backendrev;
69 	int             hq2rev;
70 	int             ge7rev;
71 	int             vc1rev;
72 	int             zbuffer;
73 	int             cmaprev;
74 	int             xmaprev;
75 	int             rexrev;
76 	int             xres;
77 	int             yres;
78 	int             depth;
79 	int             monitor;
80 
81 	int             dc_font;
82 	struct wsdisplay_font *dc_fontdata;
83 };
84 
85 static int      grtwo_match(struct device *, struct cfdata *, void *);
86 static void     grtwo_attach(struct device *, struct device *, void *);
87 
88 CFATTACH_DECL(grtwo, sizeof(struct grtwo_softc),
89 	      grtwo_match, grtwo_attach, NULL, NULL);
90 
91 /* textops */
92 static void     grtwo_cursor(void *, int, int, int);
93 static int      grtwo_mapchar(void *, int, unsigned int *);
94 static void     grtwo_putchar(void *, int, int, u_int, long);
95 static void     grtwo_copycols(void *, int, int, int, int);
96 static void     grtwo_erasecols(void *, int, int, int, long);
97 static void     grtwo_copyrows(void *, int, int, int);
98 static void     grtwo_eraserows(void *, int, int, long);
99 static int      grtwo_allocattr(void *, int, int, int, long *);
100 
101 /* accessops */
102 static int      grtwo_ioctl(void *, u_long, caddr_t, int, struct proc *);
103 static paddr_t  grtwo_mmap(void *, off_t, int);
104 static int
105 grtwo_alloc_screen(void *, const struct wsscreen_descr *,
106 		   void **, int *, int *, long *);
107 static void     grtwo_free_screen(void *, void *);
108 static int
109                 grtwo_show_screen(void *, void *, int, void (*) (void *, int, int), void *);
110 
111 static const struct wsdisplay_emulops grtwo_textops = {
112 	.cursor = grtwo_cursor,
113 	.mapchar = grtwo_mapchar,
114 	.putchar = grtwo_putchar,
115 	.copycols = grtwo_copycols,
116 	.erasecols = grtwo_erasecols,
117 	.copyrows = grtwo_copyrows,
118 	.eraserows = grtwo_eraserows,
119 	.allocattr = grtwo_allocattr
120 };
121 
122 static const struct wsdisplay_accessops grtwo_accessops = {
123 	.ioctl = grtwo_ioctl,
124 	.mmap = grtwo_mmap,
125 	.alloc_screen = grtwo_alloc_screen,
126 	.free_screen = grtwo_free_screen,
127 	.show_screen = grtwo_show_screen,
128 };
129 
130 static const struct wsscreen_descr grtwo_screen = {
131 	.name = "1280x1024",
132 	.ncols = 160,
133 	.nrows = 64,
134 	.textops = &grtwo_textops,
135 	.fontwidth = 8,
136 	.fontheight = 16,
137 	.capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
138 };
139 
140 static const struct wsscreen_descr *_grtwo_screenlist[] = {
141 	&grtwo_screen
142 };
143 
144 static const struct wsscreen_list grtwo_screenlist = {
145 	sizeof(_grtwo_screenlist) / sizeof(struct wsscreen_descr *),
146 	_grtwo_screenlist
147 };
148 
149 static struct grtwo_devconfig grtwo_console_dc;
150 static int      grtwo_is_console = 0;
151 
152 #define GR2_ATTR_ENCODE(fg,bg)	(((fg) << 8) | (bg))
153 #define GR2_ATTR_BG(a)		((a) & 0xff)
154 #define GR2_ATTR_FG(a)		(((a) >> 8) & 0xff)
155 
156 static const u_int16_t grtwo_cursor_data[128] = {
157 	/* Bit 0 */
158 	0xff00, 0x0000,
159 	0xff00, 0x0000,
160 	0xff00, 0x0000,
161 	0xff00, 0x0000,
162 	0xff00, 0x0000,
163 	0xff00, 0x0000,
164 	0xff00, 0x0000,
165 	0xff00, 0x0000,
166 	0xff00, 0x0000,
167 	0xff00, 0x0000,
168 	0xff00, 0x0000,
169 	0xff00, 0x0000,
170 	0xff00, 0x0000,
171 	0xff00, 0x0000,
172 	0xff00, 0x0000,
173 	0xff00, 0x0000,
174 	0x0000, 0x0000,
175 	0x0000, 0x0000,
176 	0x0000, 0x0000,
177 	0x0000, 0x0000,
178 	0x0000, 0x0000,
179 	0x0000, 0x0000,
180 	0x0000, 0x0000,
181 	0x0000, 0x0000,
182 	0x0000, 0x0000,
183 	0x0000, 0x0000,
184 	0x0000, 0x0000,
185 	0x0000, 0x0000,
186 	0x0000, 0x0000,
187 	0x0000, 0x0000,
188 	0x0000, 0x0000,
189 	0x0000, 0x0000,
190 
191 	/* Bit 1 */
192 	0x0000, 0x0000,
193 	0x0000, 0x0000,
194 	0x0000, 0x0000,
195 	0x0000, 0x0000,
196 	0x0000, 0x0000,
197 	0x0000, 0x0000,
198 	0x0000, 0x0000,
199 	0x0000, 0x0000,
200 	0x0000, 0x0000,
201 	0x0000, 0x0000,
202 	0x0000, 0x0000,
203 	0x0000, 0x0000,
204 	0x0000, 0x0000,
205 	0x0000, 0x0000,
206 	0x0000, 0x0000,
207 	0x0000, 0x0000,
208 	0x0000, 0x0000,
209 	0x0000, 0x0000,
210 	0x0000, 0x0000,
211 	0x0000, 0x0000,
212 	0x0000, 0x0000,
213 	0x0000, 0x0000,
214 	0x0000, 0x0000,
215 	0x0000, 0x0000,
216 	0x0000, 0x0000,
217 	0x0000, 0x0000,
218 	0x0000, 0x0000,
219 	0x0000, 0x0000,
220 	0x0000, 0x0000,
221 	0x0000, 0x0000,
222 	0x0000, 0x0000,
223 	0x0000, 0x0000,
224 };
225 
226 static const u_int8_t grtwo_defcmap[8 * 3] = {
227 	/* Normal colors */
228 	0x00, 0x00, 0x00,	/* black */
229 	0x7f, 0x00, 0x00,	/* red */
230 	0x00, 0x7f, 0x00,	/* green */
231 	0x7f, 0x7f, 0x00,	/* brown */
232 	0x00, 0x00, 0x7f,	/* blue */
233 	0x7f, 0x00, 0x7f,	/* magenta */
234 	0x00, 0x7f, 0x7f,	/* cyan */
235 	0xc7, 0xc7, 0xc7,	/* white - XXX too dim? */
236 };
237 
238 static void
239 grtwo_wait_gfifo(struct grtwo_devconfig * dc)
240 {
241 	int2_wait_fifo(1);
242 }
243 
244 /* Helper functions */
245 static void
246 grtwo_fill_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
247 		     int y2, u_int8_t color)
248 {
249 	/* gr2 sees coordinate 0,0 as the lower left corner of the screen */
250 	y1 = dc->yres - y1;
251 	y2 = dc->yres - y2;
252 
253 	grtwo_wait_gfifo(dc);
254 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_COLOR, color);
255 	grtwo_wait_gfifo(dc);
256 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1);
257 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1);
258 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
259 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2);
260 }
261 
262 static void
263 grtwo_copy_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
264 		     int y2, int dx, int dy)
265 {
266 	int             length = (dx + 3) >> 2;
267 	int             lines = 4864 / length;
268 	int             from_y;
269 	int             to_y;
270 	int             height;
271 
272 	y1 = dc->yres - y1 - dy;
273 	y2 = dc->yres - y2 - dy;
274 
275 	if ((y2 <= y1) || (dy < lines)) {
276 		grtwo_wait_gfifo(dc);
277 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
278 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
279 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
280 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1);
281 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dx);
282 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dy);
283 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
284 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2);
285 	} else {
286 		from_y = y1 + dy - lines;
287 		to_y = y2 + dy - lines;
288 		height = MIN(dy, lines);
289 
290 		while (height) {
291 			grtwo_wait_gfifo(dc);
292 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
293 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
294 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
295 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
296 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, dx);
297 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, height);
298 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
299 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, to_y);
300 			dy -= height;
301 			height = MIN(dy, lines);
302 			from_y -= height;
303 			to_y -= height;
304 		}
305 	}
306 }
307 
308 static void
309 grtwo_cmap_setrgb(struct grtwo_devconfig * dc, int index, u_int8_t r, u_int8_t g, u_int8_t b)
310 {
311 	/* index += 0x1000; */
312 
313 	grtwo_wait_gfifo(dc);
314 	bus_space_write_4(dc->iot, dc->ioh, XMAPALL_ADDRHI,
315 			  (index & 0x1f00) >> 8);
316 	bus_space_write_4(dc->iot, dc->ioh, XMAPALL_ADDRLO,
317 			  (index & 0xff));
318 	bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, r);
319 	bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, g);
320 	bus_space_write_4(dc->iot, dc->ioh, XMAPALL_CLUT, b);
321 }
322 
323 static void
324 grtwo_setup_hw(struct grtwo_devconfig * dc)
325 {
326 	int             i = 0;
327 
328 	/* Get various revisions */
329 	dc->boardrev = (~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0))) & GR2_REVISION_RD0_VERSION_MASK;
330 
331 	/*
332 	 * boards prior to rev 4 have a pretty whacky config scheme.
333          * what is doubly weird is that i have a rev 2 board, but the rev 4
334 	 * probe routines work just fine.
335 	 * we'll trust SGI, though, and separate things a bit.  it's only
336 	 * critical for the display depth calculation.
337 	 */
338 
339 	if (dc->boardrev < 4) {
340 		dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & GR2_REVISION_RD2_BACKEND_REV) >> 2;
341 		if (dc->backendrev == 0)
342 			return;
343 		dc->zbuffer = !(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION_RD1_ZBUFFER);
344 		if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMA) != 3)
345 		  i++;
346 		if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMB) != 0x0c)
347 		  i++;
348 		if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMC) != 0x30)
349 		  i++;
350 		dc->depth = 8 * i;
351 		dc->monitor =
352 			((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & 0x03) << 1) |
353 			(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & 0x01);
354 	} else {
355 		dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1)) & 0x03;
356 		if (dc->backendrev == 0)
357 			return;
358 		dc->zbuffer = bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_ZBUFFER;
359 		dc->depth = ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_24BPP) >> 4) ? 24 : 8;
360 		dc->monitor = (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0) & GR2_REVISION4_RD0_MONITOR_MASK) >> 4;
361 	}
362 
363 	dc->hq2rev = (bus_space_read_4(dc->iot, dc->ioh, HQ2_VERSION) & HQ2_VERSION_MASK) >> HQ2_VERSION_SHIFT;
364 	dc->ge7rev = (bus_space_read_4(dc->iot, dc->ioh, GE7_REVISION) & GE7_REVISION_MASK) >> 5;
365 	/* dc->vc1rev = vc1_read_ireg(dc, 5) & 0x07; */
366 
367 	/* gr2 supports 1280x1024 only */
368 	dc->xres = 1280;
369 	dc->yres = 1024;
370 
371 #if 0
372 	/* Setup cursor glyph */
373 
374 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
375 		(VC1_SRAM_CURSOR0_BASE >> 8) & 0xff);
376 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
377 		VC1_SRAM_CURSOR0_BASE & 0xff);
378 	for (i = 0; i < 128; i++)
379 		bus_space_write_4(dc->iot, dc->ioh, VC1_SRAM, grtwo_cursor_data[i]);
380 
381 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
382 		(VC1_CURSOR_EP >> 8) & 0xff);
383 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
384 		VC1_CURSOR_EP & 0xff);
385 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, VC1_SRAM_CURSOR0_BASE);
386 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
387 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
388 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
389 
390 	/* Turn on cursor function, display, DID */
391 	bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
392 		VC1_SYSCTL_VC1 | VC1_SYSCTL_DID |
393 		VC1_SYSCTL_CURSOR | VC1_SYSCTL_CURSOR_DISPLAY);
394 #endif
395 
396 	/* Setup CMAP */
397 	for (i = 0; i < 8; i++)
398 		grtwo_cmap_setrgb(dc, i, grtwo_defcmap[i * 3],
399 			grtwo_defcmap[i * 3 + 1], grtwo_defcmap[i * 3 + 2]);
400 }
401 
402 /* Attach routines */
403 static int
404 grtwo_match(struct device * parent, struct cfdata * self, void *aux)
405 {
406 	struct gio_attach_args *ga = aux;
407 
408 	/*
409 	 * grtwo doesn't have anything that even vaguely resembles a product
410 	 * ID.  Instead, we determine presence by looking at the HQ2 "mystery"
411 	 * register, which contains a magic number.
412 	 */
413 	if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) )
414 		return 0;
415 
416 	if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef)
417 		return 0;
418 
419 	return 1;
420 }
421 
422 static void
423 grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga)
424 {
425 	dc->dc_addr = ga->ga_addr;
426 
427 	dc->iot = ga->ga_iot;
428 	dc->ioh = ga->ga_ioh;
429 
430 	wsfont_init();
431 
432 	dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
433 				  WSDISPLAY_FONTORDER_L2R);
434 
435 	if (dc->dc_font < 0)
436 		panic("grtwo_attach_common: no suitable fonts");
437 
438 	if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
439 		panic("grtwo_attach_common: unable to lock font data");
440 
441 	grtwo_setup_hw(dc);
442 
443 	grtwo_fill_rectangle(dc, 0, 0, dc->xres, dc->yres, 0);
444 }
445 
446 static void
447 grtwo_attach(struct device * parent, struct device * self, void *aux)
448 {
449 	struct gio_attach_args *ga = aux;
450 	struct grtwo_softc *sc = (void *) self;
451 	struct wsemuldisplaydev_attach_args wa;
452 
453 	if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) {
454 		wa.console = 1;
455 		sc->sc_dc = &grtwo_console_dc;
456 	} else {
457 		wa.console = 0;
458 		sc->sc_dc = malloc(sizeof(struct grtwo_devconfig),
459 				   M_DEVBUF, M_WAITOK | M_ZERO);
460 		if (sc->sc_dc == NULL)
461 			panic("grtwo_attach: out of memory");
462 
463 		grtwo_attach_common(sc->sc_dc, ga);
464 	}
465 
466 	aprint_naive(": Display adapter\n");
467 
468 	aprint_normal(": SGI GR2 (board rev %x, monitor %d, depth %d)\n",
469 	      sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth);
470 
471 	wa.scrdata = &grtwo_screenlist;
472 	wa.accessops = &grtwo_accessops;
473 	wa.accesscookie = sc->sc_dc;
474 
475 	config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint);
476 }
477 
478 int
479 grtwo_cnattach(struct gio_attach_args * ga)
480 {
481 	long            defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
482 	const struct wsscreen_descr *screen;
483 
484 	if (!grtwo_match(NULL, NULL, ga)) {
485 		return ENXIO;
486 	}
487 
488 	grtwo_attach_common(&grtwo_console_dc, ga);
489 
490 	screen = &grtwo_screen;
491 
492 	wsdisplay_cnattach(screen, &grtwo_console_dc, 0, 0, defattr);
493 
494 	grtwo_is_console = 1;
495 
496 	return 0;
497 }
498 
499 /* wsdisplay textops */
500 static void
501 grtwo_cursor(void *c, int on, int row, int col)
502 {
503 	struct grtwo_devconfig *dc = (void *) c;
504 	u_int32_t control;
505 	control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL);
506 
507 	if (!on) {
508 		bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
509 			control & ~VC1_SYSCTL_CURSOR_DISPLAY);
510 	} else {
511 		bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8
512 			);
513 		bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff);
514 		bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
515 				  col * dc->dc_fontdata->fontwidth);
516 		bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
517 				  row * dc->dc_fontdata->fontheight);
518 		bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
519 			control | VC1_SYSCTL_CURSOR_DISPLAY);
520 	}
521 }
522 
523 static int
524 grtwo_mapchar(void *c, int ch, unsigned int *cp)
525 {
526 	struct grtwo_devconfig *dc = (void *) c;
527 
528 	if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
529 		ch = wsfont_map_unichar(dc->dc_fontdata, ch);
530 
531 		if (ch < 0)
532 			goto fail;
533 	}
534 	if (ch < dc->dc_fontdata->firstchar ||
535 	    ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
536 		goto fail;
537 
538 	*cp = ch;
539 	return 5;
540 
541 fail:
542 	*cp = ' ';
543 	return 0;
544 }
545 
546 static void
547 grtwo_putchar(void *c, int row, int col, u_int ch, long attr)
548 {
549 	struct grtwo_devconfig *dc = (void *) c;
550 	struct wsdisplay_font *font = dc->dc_fontdata;
551 	u_int8_t        *bitmap = (u_int8_t *) font->data + (ch - font->firstchar) * font->fontheight * font->stride;
552 	u_int32_t        pattern;
553 	int             i;
554 	int             x = col * font->fontwidth;
555 	int             y = dc->yres - ( (row + 1) * font->fontheight);
556 
557 	/* Set the drawing color */
558 	grtwo_wait_gfifo(dc);
559 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_COLOR, attr);
560 
561 	/* Set drawing coordinates */
562 	grtwo_wait_gfifo(dc);
563 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x);
564 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y);
565 
566 	grtwo_wait_gfifo(dc);
567 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth);
568 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight);
569 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 1);
570 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */
571 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */
572 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
573 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
574 
575 	for (i = 0; i < font->fontheight; i++) {
576 		/* It appears that writes have to be 16 bits.  An "I tell you
577 		   two times" sort of thing?  Thanks, SGI */
578 		pattern = *bitmap | (*bitmap << 8);
579 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern);
580 		bitmap += font->stride;
581 	}
582 
583 	/* pad up to 18 */
584 	for (i = font->fontheight; i < 18; i++)
585 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000);
586 }
587 
588 static void
589 grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols)
590 {
591 	struct grtwo_devconfig *dc = (void *) c;
592 	struct wsdisplay_font *font = dc->dc_fontdata;
593 
594 	grtwo_copy_rectangle(dc,
595 			     srccol * font->fontwidth,	/* x1 */
596 			     row * font->fontheight,	/* y1 */
597 			     (srccol + ncols + 1) * font->fontwidth - 1,	/* x2 */
598 			     (row + 1) * font->fontheight - 1,	/* y2 */
599 			     dstcol * font->fontheight,	/* dx */
600 			     row * font->fontheight);	/* dy */
601 }
602 
603 static void
604 grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr)
605 {
606 	struct grtwo_devconfig *dc = (void *) c;
607 	struct wsdisplay_font *font = dc->dc_fontdata;
608 
609 	grtwo_fill_rectangle(dc,
610 			     startcol * font->fontwidth,	/* x1 */
611 			     row * font->fontheight,	/* y1 */
612 			     (startcol + ncols + 1) * font->fontwidth - 1,	/* x2 */
613 			     (row + 1) * font->fontheight - 1,	/* y2 */
614 			     GR2_ATTR_BG(attr));
615 }
616 
617 static void
618 grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows)
619 {
620 	struct grtwo_devconfig *dc = (void *) c;
621 	struct wsdisplay_font *font = dc->dc_fontdata;
622 
623 	grtwo_copy_rectangle(dc,
624 			     0,	/* x1 */
625 			     srcrow * font->fontheight,	/* y1 */
626 			     dc->xres,	/* x2 */
627 			     (srcrow + nrows + 1) * font->fontheight - 1,	/* y2 */
628 			     0,	/* dx */
629 			     dstrow * font->fontheight);	/* dy */
630 }
631 
632 static void
633 grtwo_eraserows(void *c, int startrow, int nrows, long attr)
634 {
635 	struct grtwo_devconfig *dc = (void *) c;
636 	struct wsdisplay_font *font = dc->dc_fontdata;
637 
638 	grtwo_fill_rectangle(dc,
639 			     0,	/* x1 */
640 			     startrow * font->fontheight,	/* y1 */
641 			     dc->xres,	/* x2 */
642 			     (startrow + nrows + 1) * font->fontheight - 1,	/* y2 */
643 			     GR2_ATTR_BG(attr));
644 }
645 
646 static int
647 grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr)
648 {
649 	if (flags & WSATTR_BLINK)
650 		return EINVAL;
651 
652 	if ((flags & WSATTR_WSCOLORS) == 0) {
653 		fg = WSCOL_WHITE;
654 		bg = WSCOL_BLACK;
655 	}
656 	if (flags & WSATTR_HILIT)
657 		fg += 8;
658 
659 	if (flags & WSATTR_REVERSE) {
660 		int             tmp = fg;
661 		fg = bg;
662 		bg = tmp;
663 	}
664 	*attr = GR2_ATTR_ENCODE(fg, bg);
665 
666 	return 0;
667 }
668 
669 /* wsdisplay accessops */
670 
671 static int
672 grtwo_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc * p)
673 {
674 	struct grtwo_softc *sc = c;
675 
676 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
677 
678 	switch (cmd) {
679 	case WSDISPLAYIO_GINFO:
680 		FBINFO.width = sc->sc_dc->xres;
681 		FBINFO.height = sc->sc_dc->yres;
682 		FBINFO.depth = sc->sc_dc->depth;
683 		FBINFO.cmsize = 1 << FBINFO.depth;
684 		return 0;
685 	case WSDISPLAYIO_GTYPE:
686 		*(u_int *) data = WSDISPLAY_TYPE_GR2;
687 		return 0;
688 	}
689 	return EPASSTHROUGH;
690 }
691 
692 static          paddr_t
693 grtwo_mmap(void *c, off_t offset, int prot)
694 {
695 	struct grtwo_devconfig *dc = c;
696 
697 	if (offset >= 0xfffff)
698 		return -1;
699 
700 	return mips_btop(dc->dc_addr + offset);
701 }
702 
703 static int
704 grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep,
705 		   int *cursxp, int *cursyp, long *attrp)
706 {
707 	/*
708 	 * This won't get called for console screen and we don't support
709 	 * virtual screens
710 	 */
711 
712 	return ENOMEM;
713 }
714 
715 static void
716 grtwo_free_screen(void *c, void *cookie)
717 {
718 	panic("grtwo_free_screen");
719 }
720 static int
721 grtwo_show_screen(void *c, void *cookie, int waitok,
722 		  void (*cb) (void *, int, int), void *cbarg)
723 {
724 	return 0;
725 }
726