Home | History | Annotate | Line # | Download | only in gio
newport.c revision 1.3
      1 /*	$NetBSD: newport.c,v 1.3 2004/01/26 07:12:33 sekiya Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2003 Ilpo Ruotsalainen
      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 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: newport.c,v 1.3 2004/01/26 07:12:33 sekiya Exp $");
     34 
     35 #include <sys/param.h>
     36 #include <sys/systm.h>
     37 #include <sys/device.h>
     38 #include <sys/malloc.h>
     39 
     40 #include <dev/wscons/wsconsio.h>
     41 #include <dev/wscons/wsdisplayvar.h>
     42 #include <dev/wsfont/wsfont.h>
     43 
     44 #include <sgimips/gio/giovar.h>
     45 #include <sgimips/gio/newportvar.h>
     46 #include <sgimips/gio/newportreg.h>
     47 
     48 struct newport_softc {
     49 	struct device sc_dev;
     50 
     51 	struct newport_devconfig *sc_dc;
     52 };
     53 
     54 struct newport_devconfig {
     55 	uint32_t		dc_addr;
     56 
     57 	bus_space_tag_t		dc_st;
     58 	bus_space_handle_t	dc_sh;
     59 
     60 	int			dc_boardrev;
     61 	int			dc_cmaprev;
     62 	int			dc_xmaprev;
     63 	int			dc_rexrev;
     64 	int			dc_xres;
     65 	int			dc_yres;
     66 	int			dc_depth;
     67 
     68 	int			dc_screens;
     69 
     70 	int			dc_font;
     71 	struct wsdisplay_font	*dc_fontdata;
     72 };
     73 
     74 static int  newport_match(struct device *, struct cfdata *, void *);
     75 static void newport_attach(struct device *, struct device *, void *);
     76 
     77 CFATTACH_DECL(newport, sizeof(struct newport_softc),
     78     newport_match, newport_attach, NULL, NULL);
     79 
     80 /* textops */
     81 static void newport_cursor(void *, int, int, int);
     82 static int  newport_mapchar(void *, int, unsigned int *);
     83 static void newport_putchar(void *, int, int, u_int, long);
     84 static void newport_copycols(void *, int, int, int, int);
     85 static void newport_erasecols(void *, int, int, int, long);
     86 static void newport_copyrows(void *, int, int, int);
     87 static void newport_eraserows(void *, int, int, long);
     88 static int  newport_allocattr(void *, int, int, int, long *);
     89 
     90 /* accessops */
     91 static int     newport_ioctl(void *, u_long, caddr_t, int, struct proc *);
     92 static paddr_t newport_mmap(void *, off_t, int);
     93 static int     newport_alloc_screen(void *, const struct wsscreen_descr *,
     94     void **, int *, int *, long *);
     95 static void    newport_free_screen(void *, void *);
     96 static int     newport_show_screen(void *, void *, int,
     97     void (*)(void *, int, int), void *);
     98 
     99 static const struct wsdisplay_emulops newport_textops = {
    100 	.cursor		= newport_cursor,
    101 	.mapchar	= newport_mapchar,
    102 	.putchar	= newport_putchar,
    103 	.copycols	= newport_copycols,
    104 	.erasecols	= newport_erasecols,
    105 	.copyrows	= newport_copyrows,
    106 	.eraserows	= newport_eraserows,
    107 	.allocattr	= newport_allocattr
    108 };
    109 
    110 static const struct wsdisplay_accessops newport_accessops = {
    111 	.ioctl		= newport_ioctl,
    112 	.mmap		= newport_mmap,
    113 	.alloc_screen	= newport_alloc_screen,
    114 	.free_screen	= newport_free_screen,
    115 	.show_screen	= newport_show_screen,
    116 };
    117 
    118 static const struct wsscreen_descr newport_screen_1024x768 = {
    119 	.name		= "1024x768",
    120 	.ncols		= 128,
    121 	.nrows		= 48,
    122 	.textops	= &newport_textops,
    123 	.fontwidth	= 8,
    124 	.fontheight	= 16,
    125 	.capabilities	= WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
    126 };
    127 
    128 static const struct wsscreen_descr newport_screen_1280x1024 = {
    129 	.name		= "1280x1024",
    130 	.ncols		= 160,
    131 	.nrows		= 64,
    132 	.textops	= &newport_textops,
    133 	.fontwidth	= 8,
    134 	.fontheight	= 16,
    135 	.capabilities	= WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
    136 };
    137 
    138 static const struct wsscreen_descr *_newport_screenlist[] = {
    139 	&newport_screen_1024x768,
    140 	&newport_screen_1280x1024
    141 };
    142 
    143 static const struct wsscreen_list newport_screenlist = {
    144 	sizeof(_newport_screenlist) / sizeof(struct wsscreen_descr *),
    145 	_newport_screenlist
    146 };
    147 
    148 static struct newport_devconfig newport_console_dc;
    149 static int newport_is_console = 0;
    150 
    151 #define NEWPORT_ATTR_ENCODE(fg,bg)	(((fg) << 8) | (bg))
    152 #define NEWPORT_ATTR_BG(a)		((a) & 0xff)
    153 #define NEWPORT_ATTR_FG(a)		(((a) >> 8) & 0xff)
    154 
    155 static const uint16_t newport_cursor_data[128] = {
    156 	/* Bit 0 */
    157 	0xff00, 0x0000,
    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 	0x0000, 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 
    190 	/* Bit 1 */
    191 	0x0000, 0x0000,
    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 };
    224 
    225 static const uint8_t newport_defcmap[16*3] = {
    226 	/* Normal colors */
    227 	0x00, 0x00, 0x00, /* black */
    228 	0x7f, 0x00, 0x00, /* red */
    229 	0x00, 0x7f, 0x00, /* green */
    230 	0x7f, 0x7f, 0x00, /* brown */
    231 	0x00, 0x00, 0x7f, /* blue */
    232 	0x7f, 0x00, 0x7f, /* magenta */
    233 	0x00, 0x7f, 0x7f, /* cyan */
    234 	0xc7, 0xc7, 0xc7, /* white - XXX too dim? */
    235 
    236 	/* Hilite colors */
    237 	0x7f, 0x7f, 0x7f, /* black */
    238 	0xff, 0x00, 0x00, /* red */
    239 	0x00, 0xff, 0x00, /* green */
    240 	0xff, 0xff, 0x00, /* brown */
    241 	0x00, 0x00, 0xff, /* blue */
    242 	0xff, 0x00, 0xff, /* magenta */
    243 	0x00, 0xff, 0xff, /* cyan */
    244 	0xff, 0xff, 0xff, /* white */
    245 };
    246 
    247 /**** Low-level hardware register groveling functions ****/
    248 static void
    249 rex3_write(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val)
    250 {
    251 	bus_space_write_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET + rexreg,
    252 	    val);
    253 }
    254 
    255 static void
    256 rex3_write_go(struct newport_devconfig *dc, bus_size_t rexreg, uint32_t val)
    257 {
    258 	rex3_write(dc, rexreg + REX3_REG_GO, val);
    259 }
    260 
    261 static uint32_t
    262 rex3_read(struct newport_devconfig *dc, bus_size_t rexreg)
    263 {
    264 	return bus_space_read_4(dc->dc_st, dc->dc_sh, NEWPORT_REX3_OFFSET +
    265 	    rexreg);
    266 }
    267 
    268 static void
    269 rex3_wait_gfifo(struct newport_devconfig *dc)
    270 {
    271 	while (rex3_read(dc, REX3_REG_STATUS) & REX3_STATUS_GFXBUSY)
    272 		;
    273 }
    274 
    275 static void
    276 vc2_write_ireg(struct newport_devconfig *dc, uint8_t ireg, uint16_t val)
    277 {
    278 	rex3_write(dc, REX3_REG_DCBMODE,
    279 	    REX3_DCBMODE_DW_3 |
    280 	    REX3_DCBMODE_ENCRSINC |
    281 	    (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
    282 	    (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) |
    283 	    REX3_DCBMODE_ENASYNCACK |
    284 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    285 
    286 	rex3_write(dc, REX3_REG_DCBDATA0, (ireg << 24) | (val << 8));
    287 }
    288 
    289 static uint16_t
    290 vc2_read_ireg(struct newport_devconfig *dc, uint8_t ireg)
    291 {
    292 	rex3_write(dc, REX3_REG_DCBMODE,
    293 	    REX3_DCBMODE_DW_1 |
    294 	    REX3_DCBMODE_ENCRSINC |
    295 	    (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
    296 	    (VC2_DCBCRS_INDEX << REX3_DCBMODE_DCBCRS_SHIFT) |
    297 	    REX3_DCBMODE_ENASYNCACK |
    298 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    299 
    300 	rex3_write(dc, REX3_REG_DCBDATA0, ireg << 24);
    301 
    302 	rex3_write(dc, REX3_REG_DCBMODE,
    303 	    REX3_DCBMODE_DW_2 |
    304 	    REX3_DCBMODE_ENCRSINC |
    305 	    (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
    306 	    (VC2_DCBCRS_IREG << REX3_DCBMODE_DCBCRS_SHIFT) |
    307 	    REX3_DCBMODE_ENASYNCACK |
    308 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    309 
    310 	return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16);
    311 }
    312 
    313 static uint16_t
    314 vc2_read_ram(struct newport_devconfig *dc, uint16_t addr)
    315 {
    316 	vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr);
    317 
    318 	rex3_write(dc, REX3_REG_DCBMODE,
    319 	    REX3_DCBMODE_DW_2 |
    320 	    (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
    321 	    (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) |
    322 	    REX3_DCBMODE_ENASYNCACK |
    323 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    324 
    325 	return (uint16_t)(rex3_read(dc, REX3_REG_DCBDATA0) >> 16);
    326 }
    327 
    328 static void
    329 vc2_write_ram(struct newport_devconfig *dc, uint16_t addr, uint16_t val)
    330 {
    331 	vc2_write_ireg(dc, VC2_IREG_RAM_ADDRESS, addr);
    332 
    333 	rex3_write(dc, REX3_REG_DCBMODE,
    334 	    REX3_DCBMODE_DW_2 |
    335 	    (NEWPORT_DCBADDR_VC2 << REX3_DCBMODE_DCBADDR_SHIFT) |
    336 	    (VC2_DCBCRS_RAM << REX3_DCBMODE_DCBCRS_SHIFT) |
    337 	    REX3_DCBMODE_ENASYNCACK |
    338 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    339 
    340 	rex3_write(dc, REX3_REG_DCBDATA0, val << 16);
    341 }
    342 
    343 static u_int32_t
    344 xmap9_read(struct newport_devconfig *dc, int crs)
    345 {
    346 	rex3_write(dc, REX3_REG_DCBMODE,
    347 		REX3_DCBMODE_DW_1 |
    348 		(NEWPORT_DCBADDR_XMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) |
    349 		(crs << REX3_DCBMODE_DCBCRS_SHIFT) |
    350 		(3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
    351 		(2 << REX3_DCBMODE_CSHOLD_SHIFT) |
    352 		(1 << REX3_DCBMODE_CSSETUP_SHIFT));
    353 	return rex3_read(dc, REX3_REG_DCBDATA0);
    354 }
    355 
    356 static void
    357 xmap9_write(struct newport_devconfig *dc, int crs, uint8_t val)
    358 {
    359 	rex3_write(dc, REX3_REG_DCBMODE,
    360 	    REX3_DCBMODE_DW_1 |
    361 	    (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
    362 	    (crs << REX3_DCBMODE_DCBCRS_SHIFT) |
    363 	    (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
    364 	    (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
    365 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    366 
    367 	rex3_write(dc, REX3_REG_DCBDATA0, val << 24);
    368 }
    369 
    370 static void
    371 xmap9_write_mode(struct newport_devconfig *dc, uint8_t index, uint32_t mode)
    372 {
    373 	rex3_write(dc, REX3_REG_DCBMODE,
    374 	    REX3_DCBMODE_DW_4 |
    375 	    (NEWPORT_DCBADDR_XMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
    376 	    (XMAP9_DCBCRS_MODE_SETUP << REX3_DCBMODE_DCBCRS_SHIFT) |
    377 	    (3 << REX3_DCBMODE_CSWIDTH_SHIFT) |
    378 	    (2 << REX3_DCBMODE_CSHOLD_SHIFT) |
    379 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    380 
    381 	rex3_write(dc, REX3_REG_DCBDATA0, (index << 24) | mode);
    382 }
    383 
    384 /**** Helper functions ****/
    385 static void
    386 newport_fill_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2,
    387     int y2, uint8_t color)
    388 {
    389 	rex3_wait_gfifo(dc);
    390 
    391 	rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW |
    392 	    REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP |
    393 	    REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY);
    394 	rex3_write(dc, REX3_REG_WRMASK, 0xffffffff);
    395 	rex3_write(dc, REX3_REG_COLORI, color);
    396 	rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1);
    397 
    398 	rex3_write_go(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2);
    399 }
    400 
    401 static void
    402 newport_copy_rectangle(struct newport_devconfig *dc, int x1, int y1, int x2,
    403     int y2, int dx, int dy)
    404 {
    405 	uint32_t tmp;
    406 
    407 	rex3_wait_gfifo(dc);
    408 
    409 	rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_SCR2SCR |
    410 	    REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_DOSETUP |
    411 	    REX3_DRAWMODE0_STOPONX | REX3_DRAWMODE0_STOPONY);
    412 	rex3_write(dc, REX3_REG_XYSTARTI, (x1 << REX3_XYSTARTI_XSHIFT) | y1);
    413 	rex3_write(dc, REX3_REG_XYENDI, (x2 << REX3_XYENDI_XSHIFT) | y2);
    414 
    415 	tmp = (dy - y1) & 0xffff;
    416 	tmp |= (dx - x1) << REX3_XYMOVE_XSHIFT;
    417 
    418 	rex3_write_go(dc, REX3_REG_XYMOVE, tmp);
    419 }
    420 
    421 static void
    422 newport_cmap_setrgb(struct newport_devconfig *dc, int index, uint8_t r,
    423     uint8_t g, uint8_t b)
    424 {
    425 	rex3_write(dc, REX3_REG_DCBMODE,
    426 	    REX3_DCBMODE_DW_2 |
    427 	    REX3_DCBMODE_ENCRSINC |
    428 	    (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
    429 	    (CMAP_DCBCRS_ADDRESS_LOW << REX3_DCBMODE_DCBCRS_SHIFT) |
    430 	    (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
    431 	    (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
    432 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT) |
    433 	    REX3_DCBMODE_SWAPENDIAN);
    434 
    435 	rex3_write(dc, REX3_REG_DCBDATA0, index << 16);
    436 
    437 	rex3_write(dc, REX3_REG_DCBMODE,
    438 	    REX3_DCBMODE_DW_3 |
    439 	    (NEWPORT_DCBADDR_CMAP_BOTH << REX3_DCBMODE_DCBADDR_SHIFT) |
    440 	    (CMAP_DCBCRS_PALETTE << REX3_DCBMODE_DCBCRS_SHIFT) |
    441 	    (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
    442 	    (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
    443 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    444 
    445 	rex3_write(dc, REX3_REG_DCBDATA0, (r << 24) + (g << 16) + (b << 8));
    446 }
    447 
    448 static void
    449 newport_get_resolution(struct newport_devconfig *dc)
    450 {
    451 	uint16_t vep,lines;
    452 	uint16_t linep,cols;
    453 	uint16_t data;
    454 
    455 	vep = vc2_read_ireg(dc, VC2_IREG_VIDEO_ENTRY);
    456 
    457 	dc->dc_xres = 0;
    458 	dc->dc_yres = 0;
    459 
    460 	for (;;) {
    461 		/* Iterate over runs in video timing table */
    462 
    463 		cols = 0;
    464 
    465 		linep = vc2_read_ram(dc, vep++);
    466 		lines = vc2_read_ram(dc, vep++);
    467 
    468 		if (lines == 0)
    469 			break;
    470 
    471 		do {
    472 			/* Iterate over state runs in line sequence table */
    473 
    474 			data = vc2_read_ram(dc, linep++);
    475 
    476 			if ((data & 0x0001) == 0)
    477 				cols += (data >> 7) & 0xfe;
    478 
    479 			if ((data & 0x0080) == 0)
    480 				data = vc2_read_ram(dc, linep++);
    481 		} while ((data & 0x8000) == 0);
    482 
    483 		if (cols != 0) {
    484 			if (cols > dc->dc_xres)
    485 				dc->dc_xres = cols;
    486 
    487 			dc->dc_yres += lines;
    488 		}
    489 	}
    490 }
    491 
    492 static void
    493 newport_setup_hw(struct newport_devconfig *dc)
    494 {
    495 	uint16_t curp,tmp;
    496 	int i;
    497 	uint32_t scratch;
    498 
    499 	/* Get various revisions */
    500 	rex3_write(dc, REX3_REG_DCBMODE,
    501 	    REX3_DCBMODE_DW_1 |
    502 	    (NEWPORT_DCBADDR_CMAP_0 << REX3_DCBMODE_DCBADDR_SHIFT) |
    503 	    (CMAP_DCBCRS_REVISION << REX3_DCBMODE_DCBCRS_SHIFT) |
    504 	    (1 << REX3_DCBMODE_CSWIDTH_SHIFT) |
    505 	    (1 << REX3_DCBMODE_CSHOLD_SHIFT) |
    506 	    (1 << REX3_DCBMODE_CSSETUP_SHIFT));
    507 
    508 	scratch = rex3_read(dc, REX3_REG_DCBDATA0);
    509 
    510 	dc->dc_boardrev = (scratch >> 28) & 0x07;
    511 	dc->dc_cmaprev = scratch & 0x07;
    512 	dc->dc_xmaprev = xmap9_read(dc, XMAP9_DCBCRS_REVISION) & 0x07;
    513 
    514 	/* Setup cursor glyph */
    515 	curp = vc2_read_ireg(dc, VC2_IREG_CURSOR_ENTRY);
    516 
    517 	for (i=0; i<128; i++)
    518 		vc2_write_ram(dc, curp + i, newport_cursor_data[i]);
    519 
    520 	/* Setup VC2 to a known state */
    521 	tmp = vc2_read_ireg(dc, VC2_IREG_CONTROL) & VC2_CONTROL_INTERLACE;
    522 	vc2_write_ireg(dc, VC2_IREG_CONTROL, tmp |
    523 	    VC2_CONTROL_DISPLAY_ENABLE |
    524 	    VC2_CONTROL_VTIMING_ENABLE |
    525 	    VC2_CONTROL_DID_ENABLE |
    526 	    VC2_CONTROL_CURSORFUNC_ENABLE |
    527 	    VC2_CONTROL_CURSOR_ENABLE);
    528 
    529 	/* Setup XMAP9s */
    530 	xmap9_write(dc, XMAP9_DCBCRS_CONFIG,
    531 	    XMAP9_CONFIG_8BIT_SYSTEM | XMAP9_CONFIG_RGBMAP_CI);
    532 
    533 	xmap9_write(dc, XMAP9_DCBCRS_CURSOR_CMAP, 0);
    534 
    535 	xmap9_write_mode(dc, 0,
    536 	    XMAP9_MODE_GAMMA_BYPASS |
    537 	    XMAP9_MODE_PIXSIZE_8BPP);
    538 	xmap9_write(dc, XMAP9_DCBCRS_MODE_SELECT, 0);
    539 
    540 	/* Setup REX3 */
    541 	rex3_write(dc, REX3_REG_DRAWMODE1,
    542 	    REX3_DRAWMODE1_PLANES_CI |
    543 	    REX3_DRAWMODE1_DD_DD8 |
    544 	    REX3_DRAWMODE1_RWPACKED |
    545 	    REX3_DRAWMODE1_HD_HD8 |
    546 	    REX3_DRAWMODE1_COMPARE_LT |
    547 	    REX3_DRAWMODE1_COMPARE_EQ |
    548 	    REX3_DRAWMODE1_COMPARE_GT |
    549 	    REX3_DRAWMODE1_LO_SRC);
    550 	rex3_write(dc, REX3_REG_XYWIN, (4096 << 16) | 4096);
    551 	rex3_write(dc, REX3_REG_TOPSCAN, 0x3ff); /* XXX Why? XXX */
    552 
    553 	/* Setup CMAP */
    554 	for (i=0; i<16; i++)
    555 		newport_cmap_setrgb(dc, i, newport_defcmap[i*3],
    556 		    newport_defcmap[i*3 + 1], newport_defcmap[i*3 + 2]);
    557 }
    558 
    559 /**** Attach routines ****/
    560 static int
    561 newport_match(struct device *parent, struct cfdata *self, void *aux)
    562 {
    563 	struct gio_attach_args *ga = aux;
    564 
    565 	/* newport doesn't decode all addresses */
    566 	if (ga->ga_addr != 0x1f000000 && ga->ga_addr != 0x1f400000 &&
    567 	    ga->ga_addr != 0x1f800000 && ga->ga_addr != 0x1fc00000)
    568 		return 0;
    569 
    570 	/* newport doesn't respond with correct product id, empirically
    571 	 * both empty slots and newports seem to yield this result */
    572 	if (ga->ga_product != 0x04)
    573 		return 0;
    574 
    575 	/* Don't do the destructive probe if we're already attached */
    576 	if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr)
    577 		return 1;
    578 
    579 	/* Ugly, this probe is destructive, blame SGI... */
    580 	/* XXX Should be bus_space_peek/bus_space_poke XXX */
    581 	bus_space_write_4(ga->ga_iot, ga->ga_ioh,
    582 	    NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI, 0x12345678);
    583 	if (bus_space_read_4(ga->ga_iot, ga->ga_ioh,
    584 	      NEWPORT_REX3_OFFSET + REX3_REG_XSTART)
    585 	    != ((0x12345678 & 0xffff) << 11))
    586 		return 0;
    587 
    588 	return 1;
    589 }
    590 
    591 static void
    592 newport_attach_common(struct newport_devconfig *dc, struct gio_attach_args *ga)
    593 {
    594 	dc->dc_addr = ga->ga_addr;
    595 
    596 	dc->dc_screens = 0;
    597 
    598 	dc->dc_st = ga->ga_iot;
    599 	dc->dc_sh = ga->ga_ioh;
    600 
    601 	wsfont_init();
    602 
    603 	dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
    604 	    WSDISPLAY_FONTORDER_L2R);
    605 	if (dc->dc_font < 0)
    606 		panic("newport_attach_common: no suitable fonts");
    607 
    608 	if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
    609 		panic("newport_attach_common: unable to lock font data");
    610 
    611 	newport_setup_hw(dc);
    612 
    613 	newport_get_resolution(dc);
    614 
    615 	newport_fill_rectangle(dc, 0, 0, dc->dc_xres, dc->dc_yres, 0);
    616 }
    617 
    618 static void
    619 newport_attach(struct device *parent, struct device *self, void *aux)
    620 {
    621 	struct gio_attach_args *ga = aux;
    622 	struct newport_softc *sc = (void *)self;
    623 	struct wsemuldisplaydev_attach_args wa;
    624 
    625 	if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr) {
    626 		wa.console = 1;
    627 		sc->sc_dc = &newport_console_dc;
    628 	} else {
    629 		wa.console = 0;
    630 		sc->sc_dc = malloc(sizeof(struct newport_devconfig),
    631 		    M_DEVBUF, M_WAITOK | M_ZERO);
    632 		if (sc->sc_dc == NULL)
    633 			panic("newport_attach: out of memory");
    634 
    635 		newport_attach_common(sc->sc_dc, ga);
    636 	}
    637 
    638 	aprint_naive(": Display adapter\n");
    639 
    640 	aprint_normal(": SGI NG1 (board revision %d, cmap revision %d, xmap revision %d), depth %d\n",
    641 	    sc->sc_dc->dc_boardrev, sc->sc_dc->dc_cmaprev,
    642 	    sc->sc_dc->dc_xmaprev, sc->sc_dc->dc_depth);
    643 
    644 	wa.scrdata = &newport_screenlist;
    645 	wa.accessops = &newport_accessops;
    646 	wa.accesscookie = sc->sc_dc;
    647 
    648 	config_found(&sc->sc_dev, &wa, wsemuldisplaydevprint);
    649 }
    650 
    651 int
    652 newport_cnattach(struct gio_attach_args *ga)
    653 {
    654 	long defattr = NEWPORT_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK);
    655 	const struct wsscreen_descr *screen;
    656 
    657 	if (!newport_match(NULL, NULL, ga)) {
    658 		return ENXIO;
    659 	}
    660 
    661 	newport_attach_common(&newport_console_dc, ga);
    662 
    663 	if (newport_console_dc.dc_xres >= 1280 &&
    664 	    newport_console_dc.dc_yres >= 1024)
    665 		screen = &newport_screen_1280x1024;
    666 	else
    667 		screen = &newport_screen_1024x768;
    668 
    669 	wsdisplay_cnattach(screen, &newport_console_dc, 0, 0, defattr);
    670 
    671 	newport_is_console = 1;
    672 
    673 	return 0;
    674 }
    675 
    676 /**** wsdisplay textops ****/
    677 static void
    678 newport_cursor(void *c, int on, int row, int col)
    679 {
    680 	struct newport_devconfig *dc = (void *)c;
    681 	uint16_t control;
    682 	int x_offset;
    683 
    684 	control = vc2_read_ireg(dc, VC2_IREG_CONTROL);
    685 
    686 	if (!on) {
    687 		vc2_write_ireg(dc, VC2_IREG_CONTROL,
    688 		    control & ~VC2_CONTROL_CURSOR_ENABLE);
    689 	} else {
    690 		/* Work around bug in some board revisions */
    691 		if (dc->dc_boardrev < 6)
    692 			x_offset = 21;
    693 		else
    694 			x_offset = 31;
    695 
    696 		vc2_write_ireg(dc, VC2_IREG_CURSOR_X,
    697 		    col * dc->dc_fontdata->fontwidth + x_offset);
    698 		vc2_write_ireg(dc, VC2_IREG_CURSOR_Y,
    699 		    row * dc->dc_fontdata->fontheight + 31);
    700 
    701 		vc2_write_ireg(dc, VC2_IREG_CONTROL,
    702 		    control | VC2_CONTROL_CURSOR_ENABLE);
    703 	}
    704 }
    705 
    706 static int
    707 newport_mapchar(void *c, int ch, unsigned int *cp)
    708 {
    709 	struct newport_devconfig *dc = (void *)c;
    710 
    711 	if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
    712 		ch = wsfont_map_unichar(dc->dc_fontdata, ch);
    713 
    714 		if (ch < 0)
    715 			goto fail;
    716 	}
    717 
    718 	if (ch < dc->dc_fontdata->firstchar ||
    719 	    ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
    720 		goto fail;
    721 
    722 	*cp = ch;
    723 	return 5;
    724 
    725 fail:
    726 	*cp = ' ';
    727 	return 0;
    728 }
    729 
    730 static void
    731 newport_putchar(void *c, int row, int col, u_int ch, long attr)
    732 {
    733 	struct newport_devconfig *dc = (void *)c;
    734 	struct wsdisplay_font *font = dc->dc_fontdata;
    735 	uint8_t *bitmap = (u_int8_t *)font->data + (ch - font->firstchar) *
    736 	    font->fontheight * font->stride;
    737 	uint32_t pattern;
    738 	int i;
    739 	int x = col * font->fontwidth;
    740 	int y = row * font->fontheight;
    741 
    742 	rex3_wait_gfifo(dc);
    743 
    744 	rex3_write(dc, REX3_REG_DRAWMODE0, REX3_DRAWMODE0_OPCODE_DRAW |
    745 	    REX3_DRAWMODE0_ADRMODE_BLOCK | REX3_DRAWMODE0_STOPONX |
    746 	    REX3_DRAWMODE0_ENZPATTERN | REX3_DRAWMODE0_ZPOPAQUE);
    747 
    748 	rex3_write(dc, REX3_REG_XYSTARTI, (x << REX3_XYSTARTI_XSHIFT) | y);
    749 	rex3_write(dc, REX3_REG_XYENDI,
    750 	    (x + font->fontwidth - 1) << REX3_XYENDI_XSHIFT);
    751 
    752 	rex3_write(dc, REX3_REG_COLORI, NEWPORT_ATTR_FG(attr));
    753 	rex3_write(dc, REX3_REG_COLORBACK, NEWPORT_ATTR_BG(attr));
    754 
    755 	rex3_write(dc, REX3_REG_WRMASK, 0xffffffff);
    756 
    757 	for (i=0; i<font->fontheight; i++) {
    758 		/* XXX Works only with font->fontwidth == 8 XXX */
    759 		pattern = *bitmap << 24;
    760 
    761 		rex3_write_go(dc, REX3_REG_ZPATTERN, pattern);
    762 
    763 		bitmap += font->stride;
    764 	}
    765 }
    766 
    767 static void
    768 newport_copycols(void *c, int row, int srccol, int dstcol, int ncols)
    769 {
    770 	struct newport_devconfig *dc = (void *)c;
    771 	struct wsdisplay_font *font = dc->dc_fontdata;
    772 
    773 	newport_copy_rectangle(dc,
    774 	    srccol * font->fontwidth,			/* x1 */
    775 	    row * font->fontheight,			/* y1 */
    776 	    (srccol + ncols + 1) * font->fontwidth - 1,	/* x2 */
    777 	    (row + 1) * font->fontheight - 1,		/* y2 */
    778 	    dstcol * font->fontheight,			/* dx */
    779 	    row * font->fontheight);			/* dy */
    780 }
    781 
    782 static void
    783 newport_erasecols(void *c, int row, int startcol, int ncols,
    784     long attr)
    785 {
    786 	struct newport_devconfig *dc = (void *)c;
    787 	struct wsdisplay_font *font = dc->dc_fontdata;
    788 
    789 	newport_fill_rectangle(dc,
    790 	    startcol * font->fontwidth,				/* x1 */
    791 	    row * font->fontheight,				/* y1 */
    792 	    (startcol + ncols + 1) * font->fontwidth - 1,	/* x2 */
    793 	    (row + 1) * font->fontheight - 1,			/* y2 */
    794 	    NEWPORT_ATTR_BG(attr));
    795 }
    796 
    797 static void
    798 newport_copyrows(void *c, int srcrow, int dstrow, int nrows)
    799 {
    800 	struct newport_devconfig *dc = (void *)c;
    801 	struct wsdisplay_font *font = dc->dc_fontdata;
    802 
    803 	newport_copy_rectangle(dc,
    804 	    0,							/* x1 */
    805 	    srcrow * font->fontheight,				/* y1 */
    806 	    dc->dc_xres,					/* x2 */
    807 	    (srcrow + nrows + 1) * font->fontheight - 1,	/* y2 */
    808 	    0,							/* dx */
    809 	    dstrow * font->fontheight);				/* dy */
    810 }
    811 
    812 static void
    813 newport_eraserows(void *c, int startrow, int nrows, long attr)
    814 {
    815 	struct newport_devconfig *dc = (void *)c;
    816 	struct wsdisplay_font *font = dc->dc_fontdata;
    817 
    818 	newport_fill_rectangle(dc,
    819 	    0,							/* x1 */
    820 	    startrow * font->fontheight,			/* y1 */
    821 	    dc->dc_xres,					/* x2 */
    822 	    (startrow + nrows + 1) * font->fontheight - 1,	/* y2 */
    823 	    NEWPORT_ATTR_BG(attr));
    824 }
    825 
    826 static int
    827 newport_allocattr(void *c, int fg, int bg, int flags, long *attr)
    828 {
    829 	if (flags & WSATTR_BLINK)
    830 		return EINVAL;
    831 
    832 	if ((flags & WSATTR_WSCOLORS) == 0) {
    833 		fg = WSCOL_WHITE;
    834 		bg = WSCOL_BLACK;
    835 	}
    836 
    837 	if (flags & WSATTR_HILIT)
    838 		fg += 8;
    839 
    840 	if (flags & WSATTR_REVERSE) {
    841 		int tmp = fg;
    842 		fg = bg;
    843 		bg = tmp;
    844 	}
    845 
    846 	*attr = NEWPORT_ATTR_ENCODE(fg, bg);
    847 
    848 	return 0;
    849 }
    850 
    851 /**** wsdisplay accessops ****/
    852 
    853 static int
    854 newport_ioctl(void *c, u_long cmd, caddr_t data, int flag, struct proc *p)
    855 {
    856 	struct newport_softc *sc = c;
    857 
    858 #define FBINFO (*(struct wsdisplay_fbinfo*)data)
    859 
    860 	switch (cmd) {
    861 	case WSDISPLAYIO_GINFO:
    862 		FBINFO.width  = sc->sc_dc->dc_xres;
    863 		FBINFO.height = sc->sc_dc->dc_yres;
    864 		FBINFO.depth  = sc->sc_dc->dc_depth;
    865 		FBINFO.cmsize = 1 << FBINFO.depth;
    866 		return 0;
    867 	case WSDISPLAYIO_GTYPE:
    868 		*(u_int *)data = WSDISPLAY_TYPE_NEWPORT;
    869 		return 0;
    870 	}
    871 	return EPASSTHROUGH;
    872 }
    873 
    874 static paddr_t
    875 newport_mmap(void *c, off_t offset, int prot)
    876 {
    877 	return -1;
    878 }
    879 
    880 static int
    881 newport_alloc_screen(void *c, const struct wsscreen_descr *type, void **cookiep,
    882     int *cursxp, int *cursyp, long *attrp)
    883 {
    884 	/* This won't get called for console screen and we don't support
    885 	 * virtual screens */
    886 
    887 	return ENOMEM;
    888 }
    889 
    890 static void
    891 newport_free_screen(void *c, void *cookie)
    892 {
    893 	panic("newport_free_screen");
    894 }
    895 static int
    896 newport_show_screen(void *c, void *cookie, int waitok,
    897     void (*cb)(void *, int, int), void *cbarg)
    898 {
    899 	return 0;
    900 }
    901