Home | History | Annotate | Line # | Download | only in gio
grtwo.c revision 1.7
      1 /* $NetBSD: grtwo.c,v 1.7 2006/04/12 19:38:23 jmmv 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.7 2006/04/12 19:38:23 jmmv 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 *, void *, u_long, caddr_t, 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 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(struct device * parent, struct cfdata * self, void *aux)
    443 {
    444 	struct gio_attach_args *ga = aux;
    445 
    446 	/*
    447 	 * grtwo doesn't have anything that even vaguely resembles a product
    448 	 * ID.  Instead, we determine presence by looking at the HQ2 "mystery"
    449 	 * register, which contains a magic number.
    450 	 */
    451 	if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) )
    452 		return 0;
    453 
    454 	if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef)
    455 		return 0;
    456 
    457 	return 1;
    458 }
    459 
    460 static void
    461 grtwo_attach_common(struct grtwo_devconfig * dc, struct gio_attach_args * ga)
    462 {
    463 	dc->dc_addr = ga->ga_addr;
    464 
    465 	dc->iot = ga->ga_iot;
    466 	dc->ioh = ga->ga_ioh;
    467 	int i = 0;
    468 
    469 	wsfont_init();
    470 
    471 	dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
    472 				  WSDISPLAY_FONTORDER_L2R);
    473 
    474 	if (dc->dc_font < 0)
    475 		panic("grtwo_attach_common: no suitable fonts");
    476 
    477 	if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
    478 		panic("grtwo_attach_common: unable to lock font data");
    479 
    480 	grtwo_setup_hw(dc);
    481 
    482 	/* Large fills are broken.  For now, clear the screen line-by-line. */
    483 	for (i = 0; i < 64; i++)
    484 		grtwo_eraserows(dc, i, 1, 0);
    485 
    486 	/* If large fills worked, we'd do this instead:
    487 	grtwo_fill_rectangle(dc, 0, 0, dc->xres - 1, dc->yres - 1, 0);
    488 	*/
    489 }
    490 
    491 static void
    492 grtwo_attach(struct device * parent, struct device * self, void *aux)
    493 {
    494 	struct gio_attach_args *ga = aux;
    495 	struct grtwo_softc *sc = (void *) self;
    496 	struct wsemuldisplaydev_attach_args wa;
    497 
    498 	if (grtwo_is_console && ga->ga_addr == grtwo_console_dc.dc_addr) {
    499 		wa.console = 1;
    500 		sc->sc_dc = &grtwo_console_dc;
    501 	} else {
    502 		wa.console = 0;
    503 		sc->sc_dc = malloc(sizeof(struct grtwo_devconfig),
    504 				   M_DEVBUF, M_WAITOK | M_ZERO);
    505 		if (sc->sc_dc == NULL)
    506 			panic("grtwo_attach: out of memory");
    507 
    508 		grtwo_attach_common(sc->sc_dc, ga);
    509 	}
    510 
    511 	aprint_naive(": Display adapter\n");
    512 
    513 	aprint_normal(": GR2 (board rev %x, monitor %d, depth %d)\n",
    514 	      sc->sc_dc->boardrev, sc->sc_dc->monitor, sc->sc_dc->depth);
    515 
    516 	wa.scrdata = &grtwo_screenlist;
    517 	wa.accessops = &grtwo_accessops;
    518 	wa.accesscookie = sc->sc_dc;
    519 
    520         if ((cpu_intr_establish(0, IPL_TTY, grtwo_intr0, sc)) == NULL)
    521                 printf(": unable to establish interrupt!\n");
    522 
    523         if ((cpu_intr_establish(6, IPL_TTY, grtwo_intr6, sc)) == NULL)
    524                 printf(": unable to establish interrupt!\n");
    525 
    526 	config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint);
    527 }
    528 
    529 int
    530 grtwo_cnattach(struct gio_attach_args * ga)
    531 {
    532 	long            defattr = GR2_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
    533 
    534 	if (!grtwo_match(NULL, NULL, ga)) {
    535 		return ENXIO;
    536 	}
    537 
    538 	grtwo_attach_common(&grtwo_console_dc, ga);
    539 	wsdisplay_cnattach(&grtwo_screen, &grtwo_console_dc, 0, 0, defattr);
    540 
    541 	grtwo_is_console = 1;
    542 
    543 	return 0;
    544 }
    545 
    546 /* wsdisplay textops */
    547 static void
    548 grtwo_cursor(void *c, int on, int row, int col)
    549 {
    550 	struct grtwo_devconfig *dc = (void *) c;
    551 	u_int32_t control;
    552 	control = bus_space_read_4(dc->iot, dc->ioh, VC1_SYSCTL);
    553 
    554 	if (!on) {
    555 		bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
    556 			control & ~VC1_SYSCTL_CURSOR_DISPLAY);
    557 	} else {
    558 		bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRHI, (VC1_CURSOR_XL & 0xff00) >> 8
    559 			);
    560 		bus_space_write_4(dc->iot, dc->ioh, VC1_ADDRLO, VC1_CURSOR_XL & 0xff);
    561 		bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
    562 				  col * dc->dc_fontdata->fontwidth);
    563 		bus_space_write_4(dc->iot, dc->ioh, VC1_COMMAND,
    564 				  row * dc->dc_fontdata->fontheight);
    565 		bus_space_write_4(dc->iot, dc->ioh, VC1_SYSCTL,
    566 			control | VC1_SYSCTL_CURSOR_DISPLAY);
    567 	}
    568 }
    569 
    570 static int
    571 grtwo_mapchar(void *c, int ch, unsigned int *cp)
    572 {
    573 	struct grtwo_devconfig *dc = (void *) c;
    574 
    575 	if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
    576 		ch = wsfont_map_unichar(dc->dc_fontdata, ch);
    577 
    578 		if (ch < 0)
    579 			goto fail;
    580 	}
    581 	if (ch < dc->dc_fontdata->firstchar ||
    582 	    ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
    583 		goto fail;
    584 
    585 	*cp = ch;
    586 	return 5;
    587 
    588 fail:
    589 	*cp = ' ';
    590 	return 0;
    591 }
    592 
    593 static void
    594 grtwo_putchar(void *c, int row, int col, u_int ch, long attr)
    595 {
    596 	struct grtwo_devconfig *dc = (void *) c;
    597 	struct wsdisplay_font *font = dc->dc_fontdata;
    598 	u_int8_t        *bitmap = (u_int8_t *) font->data + (ch - font->firstchar + 1) * font->fontheight * font->stride;
    599 	u_int32_t        pattern;
    600 	int             i;
    601 	int             x = col * font->fontwidth;
    602 	int             y = dc->yres - ( (row + 1) * font->fontheight);
    603 
    604 	/* Set the drawing color */
    605 	grtwo_wait_gfifo(dc);
    606 	grtwo_set_color(dc->iot, dc->ioh, (((attr) >> 8) & 0xff));
    607 	grtwo_wait_gfifo(dc);
    608 
    609 	/* Set drawing coordinates */
    610 	grtwo_wait_gfifo(dc);
    611 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_CMOV2I, x);
    612 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, y);
    613 
    614 	/* This works for font sizes < 18 */
    615 	grtwo_wait_gfifo(dc);
    616 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DRAWCHAR, font->fontwidth);
    617 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, font->fontheight);
    618 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 2);
    619 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* x offset */
    620 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0); /* y offset */
    621 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
    622 	bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0);
    623 
    624 	for (i = 0; i < font->fontheight; i++) {
    625 		/* It appears that writes have to be 16 bits.  An "I tell you
    626 		   two times" sort of thing?  Thanks, SGI */
    627 		pattern = *bitmap | (*bitmap << 8);
    628 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, pattern);
    629 		bitmap -= font->stride;
    630 	}
    631 
    632 	/* pad up to 18 */
    633 	for (i = font->fontheight; i < 18; i++)
    634 		bus_space_write_4(dc->iot, dc->ioh, GR2_FIFO_DATA, 0x0000);
    635 }
    636 
    637 static void
    638 grtwo_copycols(void *c, int row, int srccol, int dstcol, int ncols)
    639 {
    640 #if 1
    641 	printf("grtwo_copycols: %i %i %i %i\n", row, srccol, dstcol, ncols);
    642 #else
    643 	struct grtwo_devconfig *dc = (void *) c;
    644 	struct wsdisplay_font *font = dc->dc_fontdata;
    645 	grtwo_copy_rectangle(dc,
    646 			     srccol * font->fontwidth,	/* x1 */
    647 			     0,	/* y1 */
    648 			     dstcol * font->fontwidth,	/* x2 */
    649 			     0,	/* y2 */
    650 			     ncols * font->fontwidth,	/* dx */
    651 			     dc->yres );	/* dy */
    652 #endif
    653 }
    654 
    655 static void
    656 grtwo_erasecols(void *c, int row, int startcol, int ncols, long attr)
    657 {
    658 	struct grtwo_devconfig *dc = (void *) c;
    659 	struct wsdisplay_font *font = dc->dc_fontdata;
    660 
    661 	grtwo_fill_rectangle(dc,
    662 			     startcol * font->fontwidth,	/* x1 */
    663 			     0,	/* y1 */
    664 			     (startcol * font->fontwidth) + ncols * font->fontwidth,	/* x2 */
    665 			     dc->yres,	/* y2 */
    666 			     GR2_ATTR_BG(attr));
    667 }
    668 
    669 static void
    670 grtwo_copyrows(void *c, int srcrow, int dstrow, int nrows)
    671 {
    672 	struct grtwo_devconfig *dc = (void *) c;
    673 	struct wsdisplay_font *font = dc->dc_fontdata;
    674 
    675 	grtwo_copy_rectangle(dc,
    676 			     0,	/* x1 */
    677 			     srcrow * font->fontheight,	/* y1 */
    678 			     0, /* x2 */
    679 			     dstrow * font->fontheight,	/* y2 */
    680 			     dc->xres,	/* dx */
    681 			     nrows * font->fontheight);
    682 }
    683 
    684 static void
    685 grtwo_eraserows(void *c, int startrow, int nrows, long attr)
    686 {
    687 	struct grtwo_devconfig *dc = (void *) c;
    688 	struct wsdisplay_font *font = dc->dc_fontdata;
    689 	grtwo_fill_rectangle(dc,
    690 			     0,	/* x1 */
    691 			     startrow * font->fontheight,	/* y1 */
    692 			     dc->xres,	/* x2 */
    693 			     (startrow * font->fontheight) + nrows * font->fontheight,	/* y2 */
    694 			     GR2_ATTR_BG(attr));
    695 }
    696 
    697 static int
    698 grtwo_allocattr(void *c, int fg, int bg, int flags, long *attr)
    699 {
    700 	if (flags & WSATTR_BLINK)
    701 		return EINVAL;
    702 
    703 	if ((flags & WSATTR_WSCOLORS) == 0) {
    704 		fg = WSCOL_WHITE;
    705 		bg = WSCOL_BLACK;
    706 	}
    707 	if (flags & WSATTR_HILIT)
    708 		fg += 8;
    709 
    710 	if (flags & WSATTR_REVERSE) {
    711 		int             tmp = fg;
    712 		fg = bg;
    713 		bg = tmp;
    714 	}
    715 	*attr = GR2_ATTR_ENCODE(fg, bg);
    716 
    717 	return 0;
    718 }
    719 
    720 /* wsdisplay accessops */
    721 
    722 static int
    723 grtwo_ioctl(void *c, void *vs, u_long cmd, caddr_t data, int flag,
    724 	struct lwp *l)
    725 {
    726 	struct grtwo_softc *sc = c;
    727 
    728 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
    729 
    730 	switch (cmd) {
    731 	case WSDISPLAYIO_GINFO:
    732 		FBINFO.width = sc->sc_dc->xres;
    733 		FBINFO.height = sc->sc_dc->yres;
    734 		FBINFO.depth = sc->sc_dc->depth;
    735 		FBINFO.cmsize = 1 << FBINFO.depth;
    736 		return 0;
    737 	case WSDISPLAYIO_GTYPE:
    738 		*(u_int *) data = WSDISPLAY_TYPE_GR2;
    739 		return 0;
    740 	}
    741 	return EPASSTHROUGH;
    742 }
    743 
    744 static          paddr_t
    745 grtwo_mmap(void *c, void *vs, off_t offset, int prot)
    746 {
    747 	struct grtwo_devconfig *dc = c;
    748 
    749 	if (offset >= 0xfffff)
    750 		return -1;
    751 
    752 	return mips_btop(dc->dc_addr + offset);
    753 }
    754 
    755 static int
    756 grtwo_alloc_screen(void *c, const struct wsscreen_descr * type, void **cookiep,
    757 		   int *cursxp, int *cursyp, long *attrp)
    758 {
    759 	/*
    760 	 * This won't get called for console screen and we don't support
    761 	 * virtual screens
    762 	 */
    763 
    764 	return ENOMEM;
    765 }
    766 
    767 static void
    768 grtwo_free_screen(void *c, void *cookie)
    769 {
    770 	panic("grtwo_free_screen");
    771 }
    772 static int
    773 grtwo_show_screen(void *c, void *cookie, int waitok,
    774 		  void (*cb) (void *, int, int), void *cbarg)
    775 {
    776 	return 0;
    777 }
    778 
    779 static int
    780 grtwo_intr0(void *arg)
    781 {
    782 	/* struct grtwo_devconfig *dc = arg; */
    783 	return 1;
    784 }
    785 
    786 
    787 static int
    788 grtwo_intr6(void *arg)
    789 {
    790 	/* struct grtwo_devconfig *dc = arg; */
    791 	return 1;
    792 }
    793 
    794