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