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