Home | History | Annotate | Line # | Download | only in dev
ga.c revision 1.3
      1 /*	$NetBSD: ga.c,v 1.3 2007/02/22 05:31:52 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2004, 2005 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by UCHIYAMA Yasushi.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /* Graphic Adaptor  (350, 360) */
     40 
     41 #include <sys/cdefs.h>
     42 __KERNEL_RCSID(0, "$NetBSD: ga.c,v 1.3 2007/02/22 05:31:52 thorpej Exp $");
     43 
     44 #include <sys/param.h>
     45 #include <sys/systm.h>
     46 
     47 #ifdef _STANDALONE
     48 #include <lib/libsa/stand.h>
     49 #include <lib/libkern/libkern.h>
     50 #include "local.h"
     51 #endif
     52 #ifdef _KERNEL
     53 #include <uvm/uvm_extern.h>
     54 #include <machine/vmparam.h>
     55 #endif
     56 #include <machine/gareg.h>
     57 #include <machine/gavar.h>
     58 
     59 bool ga_map(struct ga *);
     60 void ga_clut_init(struct ga *);
     61 void ga_vblank_start(const struct ga *);
     62 void ga_bt463_reg(const struct ga *, int);
     63 void ga_bt463_data(const struct ga *, int);
     64 void ga_bt463_reg_data(const struct ga *, int, int);
     65 #ifdef _STANDALONE
     66 void ga_dda_busy(const struct ga *);
     67 void ga_ovl_init(const struct ga *);
     68 void ga_id_init(const struct ga *);
     69 void ga_block_clear(const struct ga *);
     70 void ga_plane_mask_test(const struct ga *);
     71 #endif
     72 
     73 #define	ga_reg_write(ga, ofs, val)					\
     74 	(*(volatile uint32_t *)((ga)->reg_addr + (ofs)) = (val))
     75 #define	ga_reg_read(ga, ofs)						\
     76 	(*(volatile uint32_t *)((ga)->reg_addr + (ofs)))
     77 
     78 bool
     79 ga_init(struct ga *ga)
     80 {
     81 	int i;
     82 
     83 	/* Map GA register and buffers */
     84 	if (ga->reg_addr == 0 && ga_map(ga) != 0)
     85 		return false;
     86 
     87 	/* This is 350 GA-ROM initialization sequence. */
     88 	if (ga->flags == 0x0000) {
     89 		ga_bt463_reg_data(ga, 0x201, 0x40);
     90 		ga_bt463_reg_data(ga, 0x202, 0x40);
     91 		ga_bt463_reg_data(ga, 0x203,
     92 		    ((ga_reg_read(ga, 0xe00) & 2) << 6) | 0x40);
     93 	} else if (ga->flags == 0x0001) {
     94 		ga_bt463_reg_data(ga, 0x201, 0x40);
     95 		ga_bt463_reg_data(ga, 0x202, 0);
     96 		ga_bt463_reg_data(ga, 0x203,
     97 		    ((ga_reg_read(ga, 0xe00) & 2) << 6) | 0x40);
     98 		ga_bt463_reg_data(ga, 0x204, 0xff);	/* Display ON/OFF ? */
     99 		ga_bt463_reg_data(ga, 0x206, 0);
    100 		ga_bt463_reg_data(ga, 0x20a, 0);
    101 	}
    102 
    103 	/* Window type table */
    104 	ga_bt463_reg(ga, 0x300);
    105 	for (i = 0; i < 16; i++) {
    106 		ga_bt463_data(ga, 0x00);
    107 		ga_bt463_data(ga, 0xe1);
    108 		ga_bt463_data(ga, 0x01);
    109 	}
    110 
    111 	ga_vblank_start(ga);
    112 
    113 	/* ??? */
    114 	ga_bt463_reg(ga, 0x302);
    115 	for (i = 0; i < 2; i++) {
    116 		ga_bt463_data(ga, 0x00);
    117 		ga_bt463_data(ga, 0xe3);
    118 		ga_bt463_data(ga, 0x21);
    119 	}
    120 
    121 	/* Read mask P0-P7 */
    122 	if (ga->flags != 0x0001) {
    123 		/* TR2A display blinks if this was done.. */
    124 		ga_bt463_reg(ga, 0x205);
    125 		for (i = 0; i < 4; i++)
    126 			ga_bt463_data(ga, 0xff);
    127 	}
    128 
    129 	/* Blink mask P0-P7 */
    130 	ga_bt463_reg(ga, 0x209);
    131 	for (i = 0; i < 4; i++)
    132 		ga_bt463_data(ga, 0x00);
    133 
    134 	ga_clut_init(ga);
    135 
    136 	/* ??? */
    137 	ga_bt463_reg(ga, 0x200);
    138 	for (i = 0; i < 0xff; i++) {
    139 		ga_reg_write(ga, 0xc8c, 0);
    140 		ga_reg_write(ga, 0xc8c, 0);
    141 		ga_reg_write(ga, 0xc8c, 0);
    142 	}
    143 
    144 	if (ga_reg_read(ga, 0xe00) & 2)
    145 		ga_reg_write(ga, 0xe08, 0x790);	/* 71Hz */
    146 	else
    147 		ga_reg_write(ga, 0xe08, 0x670); /* 60Hz */
    148 #ifdef _STANDALONE
    149 	ga_block_clear(ga);
    150 	ga_ovl_init(ga);
    151 	ga_id_init(ga);
    152 #endif
    153 	/* Cursor RAM clear */
    154 	ga_reg_write(ga, 0xc90, 0);
    155 	ga_reg_write(ga, 0xc94, 0);
    156 	ga_reg_write(ga, 0xca0, 0);
    157 	ga_reg_write(ga, 0xca4, 0);
    158 	for (i = 0; i < 512; i++) {
    159 		ga_reg_write(ga, 0xc98, 0);
    160 		ga_reg_write(ga, 0xca8, 0);
    161 	}
    162 
    163 	return true;
    164 }
    165 
    166 bool
    167 ga_map(struct ga *ga)
    168 {
    169 #ifdef _STANDALONE
    170 	/* IPL maps register region using 16Mpage */
    171 	ga->reg_addr = GA_REG_ADDR;
    172 #endif
    173 #ifdef _KERNEL
    174 	paddr_t pa, epa;
    175 	vaddr_t va, tva;
    176 
    177 	pa = (paddr_t)GA_REG_ADDR;
    178 	epa = pa + GA_REG_SIZE;
    179 
    180 	if (!(va = uvm_km_alloc(kernel_map, epa - pa, 0, UVM_KMF_VAONLY))) {
    181 		printf("can't map GA register.\n");
    182 		return false;
    183 	}
    184 
    185 	for (tva = va; pa < epa; pa += PAGE_SIZE, tva += PAGE_SIZE)
    186 		pmap_kenter_pa(tva, pa, VM_PROT_READ | VM_PROT_WRITE);
    187 
    188 	pmap_update(pmap_kernel());
    189 
    190 	ga->reg_addr = (uint32_t)va;
    191 #endif
    192 
    193 	return true;
    194 }
    195 
    196 void
    197 ga_vblank_start(const struct ga *ga)
    198 {
    199 
    200 	while ((ga_reg_read(ga, 0xe00) & 0x1) == 0)	/* V-blank */
    201 		;
    202 	while ((ga_reg_read(ga, 0xe00) & 0x1) == 1)
    203 		;
    204 	/* V-blank start */
    205 }
    206 
    207 /* Bt463 utils */
    208 void
    209 ga_bt463_reg(const struct ga *ga, int r)
    210 {
    211 
    212 	ga_reg_write(ga, 0xc80, r & 0xff);
    213 	ga_reg_write(ga, 0xc84, (r >> 8) & 0xff);
    214 }
    215 
    216 void
    217 ga_bt463_data(const struct ga *ga, int v)
    218 {
    219 
    220 	ga_reg_write(ga, 0xc88, v & 0xff);
    221 }
    222 
    223 void
    224 ga_bt463_reg_data(const struct ga *ga, int r, int v)
    225 {
    226 
    227 	ga_bt463_reg(ga, r);
    228 	ga_bt463_data(ga, v);
    229 }
    230 
    231 /* CLUT */
    232 void
    233 ga_clut_init(struct ga *ga)
    234 {
    235 	const uint8_t compo6[6] = { 0, 51, 102, 153, 204, 255 };
    236 	const uint8_t ansi_color[16][3] = {
    237 		{ 0x00, 0x00, 0x00 },
    238 		{ 0xff, 0x00, 0x00 },
    239 		{ 0x00, 0xff, 0x00 },
    240 		{ 0xff, 0xff, 0x00 },
    241 		{ 0x00, 0x00, 0xff },
    242 		{ 0xff, 0x00, 0xff },
    243 		{ 0x00, 0xff, 0xff },
    244 		{ 0xff, 0xff, 0xff },
    245 		{ 0x00, 0x00, 0x00 },
    246 		{ 0x80, 0x00, 0x00 },
    247 		{ 0x00, 0x80, 0x00 },
    248 		{ 0x80, 0x80, 0x00 },
    249 		{ 0x00, 0x00, 0x80 },
    250 		{ 0x80, 0x00, 0x80 },
    251 		{ 0x00, 0x80, 0x80 },
    252 		{ 0x80, 0x80, 0x80 },
    253 	};
    254 	int i, j, r, g, b;
    255 
    256 	ga_bt463_reg(ga, 0);
    257 	/* ANSI escape sequence */
    258 	for (i = 0; i < 16; i++) {
    259 		ga_reg_write(ga, 0xc8c, ga->clut[i][0] = ansi_color[i][0]);
    260 		ga_reg_write(ga, 0xc8c, ga->clut[i][1] = ansi_color[i][1]);
    261 		ga_reg_write(ga, 0xc8c, ga->clut[i][2] = ansi_color[i][2]);
    262 	}
    263 
    264 	/* 16 - 31, gray scale */
    265 	for ( ; i < 32; i++) {
    266 		j = (i - 16) * 17;
    267 		ga_reg_write(ga, 0xc8c, ga->clut[i][0] = j);
    268 		ga_reg_write(ga, 0xc8c, ga->clut[i][1] = j);
    269 		ga_reg_write(ga, 0xc8c, ga->clut[i][2] = j);
    270 	}
    271 
    272 	/* 32 - 247, RGB color */
    273 	for (r = 0; r < 6; r++) {
    274 		for (g = 0; g < 6; g++) {
    275 			for (b = 0; b < 6; b++, i++) {
    276 				ga_reg_write(ga, 0xc8c,
    277 				    ga->clut[i][0] = compo6[r]);
    278 				ga_reg_write(ga, 0xc8c,
    279 				    ga->clut[i][1] = compo6[g]);
    280 				ga_reg_write(ga, 0xc8c,
    281 				    ga->clut[i][2] = compo6[b]);
    282 			}
    283 		}
    284 	}
    285 
    286 	/* 248 - 256, white */
    287 	for ( ; i < 256; i++) {
    288 		ga_reg_write(ga, 0xc8c, ga->clut[i][0] = 0xff);
    289 		ga_reg_write(ga, 0xc8c, ga->clut[i][1] = 0xff);
    290 		ga_reg_write(ga, 0xc8c, ga->clut[i][2] = 0xff);
    291 	}
    292 
    293 	/* 257 - 528, black */
    294 	for ( ; i < 528; i++) {
    295 		ga_reg_write(ga, 0xc8c, 0);
    296 		ga_reg_write(ga, 0xc8c, 0);
    297 		ga_reg_write(ga, 0xc8c, 0);
    298 	}
    299 }
    300 
    301 void
    302 ga_clut_get(struct ga *ga)
    303 {
    304 	int i;
    305 
    306 	ga_bt463_reg(ga, 0);
    307 	for (i = 0; i < 256; i++) {
    308 		ga->clut[i][0] = ga_reg_read(ga, 0xc8c);
    309 		ga->clut[i][1] = ga_reg_read(ga, 0xc8c);
    310 		ga->clut[i][2] = ga_reg_read(ga, 0xc8c);
    311 	}
    312 }
    313 
    314 void
    315 ga_clut_set(const struct ga *ga)
    316 {
    317 	int i;
    318 
    319 	ga_bt463_reg(ga, 0);
    320 	for (i = 0; i < 256; i++) {
    321 		ga_reg_write(ga, 0xc8c, ga->clut[i][0]);
    322 		ga_reg_write(ga, 0xc8c, ga->clut[i][1]);
    323 		ga_reg_write(ga, 0xc8c, ga->clut[i][2]);
    324 	}
    325 }
    326 
    327 /* Not yet analyzed. */
    328 #ifdef _STANDALONE
    329 void
    330 ga_dda_busy(const struct ga *ga)
    331 {
    332 
    333 	while ((ga_reg_read(ga, 0xf00) & 0x8000) == 0)
    334 		;
    335 }
    336 
    337 void
    338 ga_ovl_init(const struct ga *ga)
    339 {
    340 	uint32_t *p0, *p1;
    341 
    342 	ga_reg_write(ga, 0x400, 0xffffffff);
    343 	p0 = (uint32_t *)0xf2000000;
    344 	p1 = (uint32_t *)0xf2200000;
    345 	while (p0 < p1)
    346 		*p0++ = 0;
    347 }
    348 
    349 void
    350 ga_id_init(const struct ga *ga)
    351 {
    352 	uint32_t *p0, *p1;
    353 
    354 	p0 = (uint32_t *)0xf3000000;
    355 	p1 = (uint32_t *)0xf3040000;
    356 	while (p0 < p1)
    357 		*p0++ = 0;
    358 }
    359 
    360 void
    361 ga_block_clear(const struct ga *ga)
    362 {
    363 	uint32_t *p0, *p1;
    364 
    365 	ga_reg_write(ga, 0xe80, 0);
    366 	ga_reg_write(ga, 0x400, 0xffffff);
    367 
    368 	p0 = (uint32_t *)0xf0c00000;
    369 	p1 = (uint32_t *)0xf0c80000;
    370 	while (p0 < p1)
    371 		*p0++ = 0xffffffff;
    372 }
    373 
    374 void
    375 ga_plane_mask_test(const struct ga *ga)
    376 {
    377 	int i;
    378 
    379 	ga_reg_write(ga, 0x400, 0xffffff);
    380 	*(volatile uint32_t *)0xf1000000 = 0;
    381 
    382 	ga_reg_write(ga, 0x400, 0xaaaaaa);
    383 	*(volatile uint32_t *)0xf1000000 = 0xffffff;
    384 
    385 	if ((*(volatile uint32_t *)0xf1000000 & 0xffffff) != 0xaaaaaa)
    386 		goto err;
    387 	ga_reg_write(ga, 0x400, 0xffffff);
    388 	*(volatile uint32_t *)0xf1000000 = 0;
    389 
    390 
    391 	*(volatile uint32_t *)0xf1080008 = 0;
    392 	ga_reg_write(ga, 0x400, 0x555555);
    393 	*(volatile uint32_t *)0xf1080008 = 0xffffff;
    394 	if ((*(volatile uint32_t *)0xf1080008 & 0xffffff) != 0x555555)
    395 		goto err;
    396 	ga_reg_write(ga, 0x400, 0xffffff);
    397 	*(volatile uint32_t *)0xf1080008 = 0;
    398 
    399 	*(volatile uint32_t *)0xf1100000 = 0;
    400 	*(volatile uint32_t *)0xf1100000 = 0xffffff;
    401 	if ((*(volatile uint32_t *)0xf1100000 & 0xffffff) != 0xffffff)
    402 		goto err;
    403 
    404 	ga_reg_write(ga, 0x400, 0xaaaaaa);
    405 	*(volatile uint32_t *)0xf1100000 = 0;
    406 	if ((*(volatile uint32_t *)0xf1100000 & 0xffffff) != 0x555555)
    407 		goto err;
    408 
    409 	ga_reg_write(ga, 0x400, 0);
    410 	*(volatile uint32_t *)0xf1100000 = 0xffffff;
    411 	if ((*(volatile uint32_t *)0xf1100000 & 0xffffff) != 0x555555)
    412 		goto err;
    413 
    414 	ga_reg_write(ga, 0x400, 0xffffff);
    415 	*(volatile uint32_t *)0xf1100000 = 0;
    416 
    417 	ga_reg_write(ga, 0xe80, 0xffffff);
    418 	ga_reg_write(ga, 0x400, 0xffffff);
    419 	*(volatile uint32_t *)0xf0c00000 = 0xffffffff;
    420 	for (i = 0; i < 32; i++)
    421 		if ((*(volatile uint32_t *)(0xf1000000 + i * 4) & 0xffffff) !=
    422 		    0xffffff)
    423 			goto err;
    424 
    425 	ga_reg_write(ga, 0xe80, 0);
    426 	ga_reg_write(ga, 0x400, 0xaaaaaa);
    427 	*(volatile uint32_t *)0xf0c00000 = 0xffffffff;
    428 	for (i = 0; i < 32; i++)
    429 		if ((*(volatile uint32_t *)(0xf1000000 + i * 4) & 0xffffff) !=
    430 		    0x555555)
    431 			goto err;
    432 	ga_reg_write(ga, 0x400, 0x555555);
    433 	*(volatile uint32_t *)0xf0c00000 = 0xffffffff;
    434 	for (i = 0; i < 32; i++)
    435 		if ((*(volatile uint32_t *)(0xf1000000 + i * 4) & 0xffffff) !=
    436 		    0x0)
    437 			goto err;
    438 
    439 	printf("SUCCESS\n");
    440 	return;
    441  err:
    442 	printf("ERROR\n");
    443 }
    444 #endif /* _STANDALONE */
    445