xref: /netbsd-src/sys/arch/sgimips/gio/grtwo.c (revision c29d51755812ace2e87aeefdb06cb2b4dac7087a)
1 /* $NetBSD: grtwo.c,v 1.13 2012/10/27 17:18:09 chs 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.13 2012/10/27 17:18:09 chs 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 <machine/sysconf.h>
46 
47 #include <dev/wscons/wsconsio.h>
48 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/wsfont/wsfont.h>
50 
51 #include <sgimips/gio/giovar.h>
52 #include <sgimips/gio/grtwovar.h>
53 #include <sgimips/gio/grtworeg.h>
54 
55 #include <sgimips/dev/int2var.h>
56 
57 struct grtwo_softc {
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(device_t, cfdata_t, void *);
86 static void     grtwo_attach(device_t, device_t, void *);
87 
88 CFATTACH_DECL_NEW(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 *, void *, u_long, void *, int, struct lwp *);
103 static paddr_t  grtwo_mmap(void *, 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 int	grtwo_intr0(void *);
112 static int	grtwo_intr6(void *);
113 
114 static const struct wsdisplay_emulops grtwo_textops = {
115 	.cursor = grtwo_cursor,
116 	.mapchar = grtwo_mapchar,
117 	.putchar = grtwo_putchar,
118 	.copycols = grtwo_copycols,
119 	.erasecols = grtwo_erasecols,
120 	.copyrows = grtwo_copyrows,
121 	.eraserows = grtwo_eraserows,
122 	.allocattr = grtwo_allocattr
123 };
124 
125 static const struct wsdisplay_accessops grtwo_accessops = {
126 	.ioctl = grtwo_ioctl,
127 	.mmap = grtwo_mmap,
128 	.alloc_screen = grtwo_alloc_screen,
129 	.free_screen = grtwo_free_screen,
130 	.show_screen = grtwo_show_screen,
131 };
132 
133 static const struct wsscreen_descr grtwo_screen = {
134 	.name = "1280x1024",
135 	.ncols = 160,
136 	.nrows = 64, /* 40 */
137 	.textops = &grtwo_textops,
138 	.fontwidth = 8,
139 	.fontheight = 16,
140 	.capabilities = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
141 };
142 
143 static const struct wsscreen_descr *_grtwo_screenlist[] = {
144 	&grtwo_screen
145 };
146 
147 static const struct wsscreen_list grtwo_screenlist = {
148 	sizeof(_grtwo_screenlist) / sizeof(struct wsscreen_descr *),
149 	_grtwo_screenlist
150 };
151 
152 static struct grtwo_devconfig grtwo_console_dc;
153 static int      grtwo_is_console = 0;
154 
155 #define GR2_ATTR_ENCODE(fg,bg)	(((fg) << 8) | (bg))
156 #define GR2_ATTR_BG(a)		((a) & 0xff)
157 #define GR2_ATTR_FG(a)		(((a) >> 8) & 0xff)
158 
159 static const u_int16_t grtwo_cursor_data[128] = {
160 	/* Bit 0 */
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 	0xff00, 0x0000,
175 	0xff00, 0x0000,
176 	0xff00, 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 	0x0000, 0x0000,
191 	0x0000, 0x0000,
192 	0x0000, 0x0000,
193 
194 	/* Bit 1 */
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 	0x0000, 0x0000,
225 	0x0000, 0x0000,
226 	0x0000, 0x0000,
227 };
228 
229 static const u_int8_t grtwo_defcmap[8 * 3] = {
230 	/* Normal colors */
231 	0x00, 0x00, 0x00,	/* black */
232 	0x7f, 0x00, 0x00,	/* red */
233 	0x00, 0x7f, 0x00,	/* green */
234 	0x7f, 0x7f, 0x00,	/* brown */
235 	0x00, 0x00, 0x7f,	/* blue */
236 	0x7f, 0x00, 0x7f,	/* magenta */
237 	0x00, 0x7f, 0x7f,	/* cyan */
238 	0xc7, 0xc7, 0xc7,	/* white - XXX too dim? */
239 };
240 
241 static void
242 grtwo_wait_gfifo(struct grtwo_devconfig * dc)
243 {
244 	int2_wait_fifo(1);
245 }
246 
247 static inline void
248 grtwo_set_color(bus_space_tag_t iot, bus_space_handle_t ioh, int color)
249 {
250 	bus_space_write_4(iot, ioh, GR2_FIFO_COLOR, color);
251 }
252 
253 /* Helper functions */
254 static void
255 grtwo_fill_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
256 		     int y2, u_int8_t color)
257 {
258 	int remaining;
259 	int from_y;
260 	int to_y;
261 
262 	/* gr2 sees coordinate 0,0 as the lower left corner, and 1279,1023
263 	   as the upper right.  To keep things consistent, we shall flip the
264 	   y axis. */
265 
266 	/* There appears to be a limit to the number of vertical lines that we
267 	   can run through the graphics engine at one go.  This probably has
268 	   something to do with vertical refresh.  Single-row fills are okay,
269 	   multiple-row screw up the board in exciting ways.  The copy_rectangle
270 	   workaround doesn't work for fills. */
271 
272 	/* Coordinates, not length.  Remember that! */
273 
274 	to_y = min(dc->yres - 1 - y1, dc->yres - 1 - y2);
275 	from_y = max(dc->yres - 1 - y1, dc->yres - 1 - y2);
276 
277 	remaining = to_y - from_y;
278 
279 	grtwo_wait_gfifo(dc);
280 	grtwo_set_color(dc->iot, dc->ioh, color);
281 
282 	while (remaining) {
283 		if (remaining <= 32)
284 		{
285 			delay(10000);
286 			grtwo_wait_gfifo(dc);
287 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1);
288 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
289 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
290 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y + remaining);
291 			break;
292 		} else {
293 			delay(100000);
294 			grtwo_wait_gfifo(dc);
295 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTI2D, x1);
296 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
297 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
298 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y + remaining);
299 			from_y += 32;
300 			remaining -=32;
301 		}
302 	}
303 }
304 
305 static void
306 grtwo_copy_rectangle(struct grtwo_devconfig * dc, int x1, int y1, int x2,
307 		     int y2, int width, int height)
308 {
309 	int             length = (width + 3) >> 2;
310 	int             lines = 4864 / length;
311 	int             from_y;
312 	int             to_y;
313 	int		temp_height;
314 
315 	if ((y2 <= y1) || (height < lines)) {
316 		grtwo_wait_gfifo(dc);
317 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
318 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
319 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
320 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y1);
321 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, width);
322 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, height);
323 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
324 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y2);
325 	} else {
326 		from_y = y1 + height - lines;
327 		to_y = y2 + height - lines;
328 		temp_height = MIN(height, lines);
329 
330 		while (temp_height) {
331 			grtwo_wait_gfifo(dc);
332 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_RECTCOPY, length);
333 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, lines);
334 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x1);
335 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, from_y);
336 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, width);
337 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, temp_height);
338 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, x2);
339 			bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, to_y);
340 			height -= temp_height;
341 			height = MIN(height, lines);
342 			from_y -= temp_height;
343 			to_y -= temp_height;
344 		}
345 	}
346 }
347 
348 static void
349 grtwo_cmap_setrgb(struct grtwo_devconfig * dc, int index, u_int8_t r, u_int8_t g, u_int8_t b)
350 {
351 	grtwo_wait_gfifo(dc);
352 	bus_space_write_1(dc->iot, dc->ioh, XMAPALL_ADDRHI,
353 			  ((index & 0x1f00) >> 8) );
354 	bus_space_write_1(dc->iot, dc->ioh, XMAPALL_ADDRLO,
355 			  (index & 0xff));
356 	bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, r);
357 	bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, g);
358 	bus_space_write_1(dc->iot, dc->ioh, XMAPALL_CLUT, b);
359 }
360 
361 static void
362 grtwo_setup_hw(struct grtwo_devconfig * dc)
363 {
364 	int             i = 0;
365 
366 	/* Get various revisions */
367 	dc->boardrev = (~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0))) & GR2_REVISION_RD0_VERSION_MASK;
368 
369 	/*
370 	 * boards prior to rev 4 have a pretty whacky config scheme.
371          * what is doubly weird is that i have a rev 2 board, but the rev 4
372 	 * probe routines work just fine.
373 	 * we'll trust SGI, though, and separate things a bit.  it's only
374 	 * critical for the display depth calculation.
375 	 */
376 
377 	if (dc->boardrev < 4) {
378 		dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & GR2_REVISION_RD2_BACKEND_REV) >> 2;
379 		if (dc->backendrev == 0)
380 			return;
381 		dc->zbuffer = !(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION_RD1_ZBUFFER);
382 		if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMA) != 3)
383 		  i++;
384 		if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMB) != 0x0c)
385 		  i++;
386 		if ( (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD3) & GR2_REVISION_RD3_VMC) != 0x30)
387 		  i++;
388 		dc->depth = 8 * i;
389 		dc->monitor =
390 			((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD2) & 0x03) << 1) |
391 			(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & 0x01);
392 	} else {
393 		dc->backendrev = ~(bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1)) & 0x03;
394 		if (dc->backendrev == 0)
395 			return;
396 		dc->zbuffer = bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_ZBUFFER;
397 		dc->depth = ((bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD1) & GR2_REVISION4_RD1_24BPP) >> 4) ? 24 : 8;
398 		dc->monitor = (bus_space_read_4(dc->iot, dc->ioh, GR2_REVISION_RD0) & GR2_REVISION4_RD0_MONITOR_MASK) >> 4;
399 	}
400 
401 	dc->hq2rev = (bus_space_read_4(dc->iot, dc->ioh, HQ2_VERSION) & HQ2_VERSION_MASK) >> HQ2_VERSION_SHIFT;
402 	dc->ge7rev = (bus_space_read_4(dc->iot, dc->ioh, GE7_REVISION) & GE7_REVISION_MASK) >> 5;
403 	/* dc->vc1rev = vc1_read_ireg(dc, 5) & 0x07; */
404 
405 	/* gr2 supports 1280x1024 only */
406 	dc->xres = 1280;
407 	dc->yres = 1024;
408 
409 #if 0
410 	/* Setup cursor glyph */
411 
412 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
413 		(VC1_SRAM_CURSOR0_BASE >> 8) & 0xff);
414 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
415 		VC1_SRAM_CURSOR0_BASE & 0xff);
416 	for (i = 0; i < 128; i++)
417 		bus_space_write_4(dc->iot, dc->ioh, VC1_SRAM, grtwo_cursor_data[i]);
418 
419 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI,
420 		(VC1_CURSOR_EP >> 8) & 0xff);
421 	bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO,
422 		VC1_CURSOR_EP & 0xff);
423 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, VC1_SRAM_CURSOR0_BASE);
424 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
425 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
426 	bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND, 0);
427 
428 	/* Turn on cursor function, display, DID */
429 	bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
430 		VC1_SYSCTL_VC1 | VC1_SYSCTL_DID |
431 		VC1_SYSCTL_CURSOR | VC1_SYSCTL_CURSOR_DISPLAY);
432 #endif
433 
434 	/* Setup CMAP */
435 	for (i = 0; i < 8; i++)
436 		grtwo_cmap_setrgb(dc, i, grtwo_defcmap[i * 3],
437 			grtwo_defcmap[i * 3 + 1], grtwo_defcmap[i * 3 + 2]);
438 }
439 
440 /* Attach routines */
441 static int
442 grtwo_match(device_t parent, cfdata_t cf, void *aux)
443 {
444 	struct gio_attach_args *ga = aux;
445 
446 	if (ga->ga_addr != 0x1f000000 && ga->ga_addr != 0x1f400000 &&
447 	    ga->ga_addr != 0x1f600000)
448 		return (0);
449 
450 	/*
451 	 * grtwo doesn't have anything that even vaguely resembles a product
452 	 * ID.  Instead, we determine presence by looking at the HQ2 "mystery"
453 	 * register, which contains a magic number.
454 	 */
455 	if ( platform.badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY),
456 	    sizeof(u_int32_t)) )
457 		return 0;
458 
459 	if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef)
460 		return 0;
461 
462 	return 1;
463 }
464 
465 static void
466 grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga)
467 {
468 	dc->dc_addr = ga->ga_addr;
469 
470 	dc->iot = ga->ga_iot;
471 	dc->ioh = ga->ga_ioh;
472 	int i = 0;
473 
474 	wsfont_init();
475 
476 	dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
477 				  WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
478 
479 	if (dc->dc_font < 0)
480 		panic("grtwo_attach_common: no suitable fonts");
481 
482 	if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
483 		panic("grtwo_attach_common: unable to lock font data");
484 
485 	grtwo_setup_hw(dc);
486 
487 	/* Large fills are broken.  For now, clear the screen line-by-line. */
488 	for (i = 0; i < 64; i++)
489 		grtwo_eraserows(dc, i, 1, 0);
490 
491 	/* If large fills worked, we'd do this instead:
492 	grtwo_fill_rectangle(dc, 0, 0, dc->xres - 1, dc->yres - 1, 0);
493 	*/
494 }
495 
496 static void
497 grtwo_attach(device_t parent, device_t self, void *aux)
498 {
499 	struct gio_attach_args *ga = aux;
500 	struct grtwo_softc *sc = device_private(self);
501 	struct wsemuldisplaydev_attach_args wa;
502 
503 	if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) {
504 		wa.console = 1;
505 		sc->sc_dc = &grtwo_console_dc;
506 	} else {
507 		wa.console = 0;
508 		sc->sc_dc = malloc(sizeof(struct grtwo_devconfig),
509 				   M_DEVBUF, M_WAITOK | M_ZERO);
510 		if (sc->sc_dc == NULL)
511 			panic("grtwo_attach: out of memory");
512 
513 		grtwo_attach_common(sc->sc_dc, ga);
514 	}
515 
516 	aprint_naive(": Display adapter\n");
517 
518 	aprint_normal(": GR2 (board rev %x, monitor %d, depth %d)\n",
519 	      sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth);
520 
521 	wa.scrdata = &grtwo_screenlist;
522 	wa.accessops = &grtwo_accessops;
523 	wa.accesscookie = sc->sc_dc;
524 
525         if ((cpu_intr_establish(0, IPL_TTY, grtwo_intr0, sc)) == NULL)
526                 printf(": unable to establish interrupt!\n");
527 
528         if ((cpu_intr_establish(6, IPL_TTY, grtwo_intr6, sc)) == NULL)
529                 printf(": unable to establish interrupt!\n");
530 
531 	config_found(self, &wa, wsemuldisplaydevprint);
532 }
533 
534 int
535 grtwo_cnattach(struct gio_attach_args * ga)
536 {
537 	long            defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
538 
539 	if (!grtwo_match(NULL, NULL, ga)) {
540 		return ENXIO;
541 	}
542 
543 	grtwo_attach_common(&grtwo_console_dc, ga);
544 	wsdisplay_cnattach(&grtwo_screen, &grtwo_console_dc, 0, 0, defattr);
545 
546 	grtwo_is_console = 1;
547 
548 	return 0;
549 }
550 
551 /* wsdisplay textops */
552 static void
553 grtwo_cursor(void *c, int on, int row, int col)
554 {
555 	struct grtwo_devconfig *dc = (void *) c;
556 	u_int32_t control;
557 	control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL);
558 
559 	if (!on) {
560 		bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
561 			control & ~VC1_SYSCTL_CURSOR_DISPLAY);
562 	} else {
563 		bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8
564 			);
565 		bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff);
566 		bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
567 				  col * dc->dc_fontdata->fontwidth);
568 		bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
569 				  row * dc->dc_fontdata->fontheight);
570 		bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
571 			control | VC1_SYSCTL_CURSOR_DISPLAY);
572 	}
573 }
574 
575 static int
576 grtwo_mapchar(void *c, int ch, unsigned int *cp)
577 {
578 	struct grtwo_devconfig *dc = (void *) c;
579 
580 	if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
581 		ch = wsfont_map_unichar(dc->dc_fontdata, ch);
582 
583 		if (ch < 0)
584 			goto fail;
585 	}
586 	if (ch < dc->dc_fontdata->firstchar ||
587 	    ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
588 		goto fail;
589 
590 	*cp = ch;
591 	return 5;
592 
593 fail:
594 	*cp = ' ';
595 	return 0;
596 }
597 
598 static void
599 grtwo_putchar(void *c, int row, int col, u_int ch, long attr)
600 {
601 	struct grtwo_devconfig *dc = (void *) c;
602 	struct wsdisplay_font *font = dc->dc_fontdata;
603 	u_int8_t        *bitmap = (u_int8_t *) font->data + (ch - font->firstchar + 1) * font->fontheight * font->stride;
604 	u_int32_t        pattern;
605 	int             i;
606 	int             x = col * font->fontwidth;
607 	int             y = dc->yres - ( (row + 1) * font->fontheight);
608 
609 	/* Set the drawing color */
610 	grtwo_wait_gfifo(dc);
611 	grtwo_set_color(dc->iot, dc->ioh, (((attr) >> 8) & 0xff));
612 	grtwo_wait_gfifo(dc);
613 
614 	/* Set drawing coordinates */
615 	grtwo_wait_gfifo(dc);
616 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x);
617 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y);
618 
619 	/* This works for font sizes < 18 */
620 	grtwo_wait_gfifo(dc);
621 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth);
622 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight);
623 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 2);
624 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */
625 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */
626 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
627 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
628 
629 	for (i = 0; i < font->fontheight; i++) {
630 		/* It appears that writes have to be 16 bits.  An "I tell you
631 		   two times" sort of thing?  Thanks, SGI */
632 		pattern = *bitmap | (*bitmap << 8);
633 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern);
634 		bitmap -= font->stride;
635 	}
636 
637 	/* pad up to 18 */
638 	for (i = font->fontheight; i < 18; i++)
639 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000);
640 }
641 
642 static void
643 grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols)
644 {
645 #if 1
646 	printf("grtwo_copycols: %i %i %i %i\n", row, srccol, dstcol, ncols);
647 #else
648 	struct grtwo_devconfig *dc = (void *) c;
649 	struct wsdisplay_font *font = dc->dc_fontdata;
650 	grtwo_copy_rectangle(dc,
651 			     srccol * font->fontwidth,	/* x1 */
652 			     0,	/* y1 */
653 			     dstcol * font->fontwidth,	/* x2 */
654 			     0,	/* y2 */
655 			     ncols * font->fontwidth,	/* dx */
656 			     dc->yres );	/* dy */
657 #endif
658 }
659 
660 static void
661 grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr)
662 {
663 	struct grtwo_devconfig *dc = (void *) c;
664 	struct wsdisplay_font *font = dc->dc_fontdata;
665 
666 	grtwo_fill_rectangle(dc,
667 			     startcol * font->fontwidth,	/* x1 */
668 			     0,	/* y1 */
669 			     (startcol * font->fontwidth) + ncols * font->fontwidth,	/* x2 */
670 			     dc->yres,	/* y2 */
671 			     GR2_ATTR_BG(attr));
672 }
673 
674 static void
675 grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows)
676 {
677 	struct grtwo_devconfig *dc = (void *) c;
678 	struct wsdisplay_font *font = dc->dc_fontdata;
679 
680 	grtwo_copy_rectangle(dc,
681 			     0,	/* x1 */
682 			     srcrow * font->fontheight,	/* y1 */
683 			     0, /* x2 */
684 			     dstrow * font->fontheight,	/* y2 */
685 			     dc->xres,	/* dx */
686 			     nrows * font->fontheight);
687 }
688 
689 static void
690 grtwo_eraserows(void *c, int startrow, int nrows, long attr)
691 {
692 	struct grtwo_devconfig *dc = (void *) c;
693 	struct wsdisplay_font *font = dc->dc_fontdata;
694 	grtwo_fill_rectangle(dc,
695 			     0,	/* x1 */
696 			     startrow * font->fontheight,	/* y1 */
697 			     dc->xres,	/* x2 */
698 			     (startrow * font->fontheight) + nrows * font->fontheight,	/* y2 */
699 			     GR2_ATTR_BG(attr));
700 }
701 
702 static int
703 grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr)
704 {
705 	if (flags & WSATTR_BLINK)
706 		return EINVAL;
707 
708 	if ((flags & WSATTR_WSCOLORS) == 0) {
709 		fg = WSCOL_WHITE;
710 		bg = WSCOL_BLACK;
711 	}
712 	if (flags & WSATTR_HILIT)
713 		fg += 8;
714 
715 	if (flags & WSATTR_REVERSE) {
716 		int             tmp = fg;
717 		fg = bg;
718 		bg = tmp;
719 	}
720 	*attr = GR2_ATTR_ENCODE(fg, bg);
721 
722 	return 0;
723 }
724 
725 /* wsdisplay accessops */
726 
727 static int
728 grtwo_ioctl(void *c, void *vs, u_long cmd, void *data, int flag,
729 	struct lwp *l)
730 {
731 	struct grtwo_softc *sc = c;
732 
733 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
734 
735 	switch (cmd) {
736 	case WSDISPLAYIO_GINFO:
737 		FBINFO.width = sc->sc_dc->xres;
738 		FBINFO.height = sc->sc_dc->yres;
739 		FBINFO.depth = sc->sc_dc->depth;
740 		FBINFO.cmsize = 1 << FBINFO.depth;
741 		return 0;
742 	case WSDISPLAYIO_GTYPE:
743 		*(u_int *) data = WSDISPLAY_TYPE_GR2;
744 		return 0;
745 	}
746 	return EPASSTHROUGH;
747 }
748 
749 static          paddr_t
750 grtwo_mmap(void *c, void *vs, off_t offset, int prot)
751 {
752 	struct grtwo_devconfig *dc = c;
753 
754 	if (offset >= 0xfffff)
755 		return -1;
756 
757 	return mips_btop(dc->dc_addr + offset);
758 }
759 
760 static int
761 grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep,
762 		   int *cursxp, int *cursyp, long *attrp)
763 {
764 	/*
765 	 * This won't get called for console screen and we don't support
766 	 * virtual screens
767 	 */
768 
769 	return ENOMEM;
770 }
771 
772 static void
773 grtwo_free_screen(void *c, void *cookie)
774 {
775 	panic("grtwo_free_screen");
776 }
777 static int
778 grtwo_show_screen(void *c, void *cookie, int waitok,
779 		  void (*cb) (void *, int, int), void *cbarg)
780 {
781 	return 0;
782 }
783 
784 static int
785 grtwo_intr0(void *arg)
786 {
787 	/* struct grtwo_devconfig *dc = arg; */
788 	return 1;
789 }
790 
791 
792 static int
793 grtwo_intr6(void *arg)
794 {
795 	/* struct grtwo_devconfig *dc = arg; */
796 	return 1;
797 }
798 
799