Home | History | Annotate | Line # | Download | only in ee
gsfb.c revision 1.6
      1 /*	$NetBSD: gsfb.c,v 1.6 2002/10/02 04:17:22 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001 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 #include "debug_playstation2.h"
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 
     44 #include <machine/autoconf.h>
     45 
     46 #include <dev/cons.h>
     47 
     48 #include <dev/wscons/wsconsio.h>
     49 #include <dev/wscons/wsdisplayvar.h>
     50 #include <dev/wscons/wscons_callbacks.h>
     51 
     52 #include <dev/wsfont/wsfont.h>
     53 
     54 #include <playstation2/ee/eevar.h>
     55 #include <playstation2/ee/gsvar.h>
     56 #include <playstation2/ee/gsreg.h>
     57 #include <playstation2/ee/dmacvar.h>
     58 #include <playstation2/ee/dmacreg.h>
     59 
     60 #ifdef DEBUG
     61 #define STATIC
     62 #else
     63 #define STATIC	static
     64 #endif
     65 
     66 STATIC struct gsfb {
     67 	int initialized;
     68 	int attached;
     69 	int is_console;
     70 	const struct wsscreen_descr *screen;
     71 	struct wsdisplay_font *font;
     72 } gsfb;
     73 
     74 STATIC void gsfb_dma_kick(paddr_t, size_t);
     75 STATIC void gsfb_font_expand_psmct32(const struct wsdisplay_font *, u_int,
     76     long, u_int32_t *);
     77 STATIC __inline__ void gsfb_set_cursor_pos(u_int32_t *, int, int, int, int);
     78 
     79 #define ATTR_FG_GET(a)	(((a )>> 24) & 0xf)
     80 #define ATTR_BG_GET(a)	(((a )>> 16) & 0xf)
     81 #define ATTR_FG_SET(x)	(((x) << 24) & 0x0f000000)
     82 #define ATTR_BG_SET(x)	(((x) << 16) & 0x000f0000)
     83 
     84 STATIC const u_int32_t gsfb_ansi_psmct32[] = {
     85 	0x80000000, /* black */
     86 	0x800000aa, /* red */
     87 	0x8000aa00, /* green */
     88 	0x8000aaaa, /* brown */
     89 	0x80aa0000, /* blue */
     90 	0x80aa00aa, /* magenta */
     91 	0x80aaaa00, /* cyan */
     92 	0x80aaaaaa, /* white */
     93 	0x80000000, /* black */
     94 	0x800000ff, /* red */
     95 	0x8000ff00, /* green */
     96 	0x8000ffff, /* brown */
     97 	0x80ff0000, /* blue */
     98 	0x80ff00ff, /* magenta */
     99 	0x80ffff00, /* cyan */
    100 	0x80ffffff, /* black */
    101 };
    102 
    103 #define TRXPOS_DXY(f, x, y)						\
    104 ({									\
    105 	f[9] = ((x) & 0x000007ff) | (((y) << 16) & 0x07ff0000);		\
    106 })
    107 
    108 #define TRXPOS_SY_DY(f, sy, dy)						\
    109 ({									\
    110 	f[8] = (((sy) << 16) & 0x07ff0000);				\
    111 	f[9] = (((dy) << 16) & 0x07ff0000);				\
    112 })
    113 
    114 #define TRXPOS_DXY_SXY(f, dx, dy, sx, sy)				\
    115 ({									\
    116 	f[8] = ((((sy) << 16) & 0x07ff0000) | ((sx) & 0x000007ff));	\
    117 	f[9] = ((((dy) << 16) & 0x07ff0000) | ((dx) & 0x000007ff));	\
    118 })
    119 
    120 STATIC u_int32_t gsfb_scroll_cmd_640x16[] __attribute__((__aligned__(16))) = {
    121         0x00008004, 0x10000000, 0x0000000e, 0x00000000,
    122         0x000a0000, 0x000a0000, 0x00000050, 0x00000000,
    123         0x07ff0000, 0x07ff0000, 0x00000051, 0x00000000,
    124         0x00000280, 0x00000010, 0x00000052, 0x00000000,
    125         0x00000002, 0x00000000, 0x00000053, 0x00000000,
    126 };
    127 
    128 STATIC u_int32_t gsfb_cursor_cmd[] __attribute__((__aligned__(16))) = {
    129 	0x00008007, 0x10000000, 0x0000000e, 0x00000000,
    130 	0x00000001, 0x00000000, 0x0000001a, 0x00000000,
    131         0x000000a4, 0x00000080, 0x00000042, 0x00000000,
    132 	0x00000046, 0x00000000, 0x00000000, 0x00000000,
    133 	0x80ffffff, 0x00000000, 0x00000001, 0x00000000,
    134 	0x00000000, 0x00000000, 0x0000000d, 0x00000000,
    135 	0x80ffffff, 0x00000000, 0x00000001, 0x00000000,
    136 	0x00000000, 0x00000000, 0x00000005, 0x00000000,
    137 };
    138 
    139 STATIC u_int32_t gsfb_copy_cmd_8x16[] __attribute__((__aligned__(16))) = {
    140         0x00008004, 0x10000000, 0x0000000e, 0x00000000,
    141         0x000a0000, 0x000a0000, 0x00000050, 0x00000000,
    142         0x07ff07ff, 0x07ff07ff, 0x00000051, 0x00000000,
    143         0x00000008, 0x00000010, 0x00000052, 0x00000000,
    144         0x00000002, 0x00000000, 0x00000053, 0x00000000,
    145 };
    146 
    147 STATIC u_int32_t gsfb_init_cmd_640x480[] __attribute__((__aligned__(16))) = {
    148 	0x00008008, 0x10000000, 0x0000000e, 0x00000000,
    149 	0x000a0000, 0x00000000, 0x0000004c, 0x00000000,
    150 	0x00000096, 0x00000000, 0x0000004e, 0x00000000,
    151 	0x02800000, 0x01e00000, 0x00000040, 0x00000000,
    152 	0x00000006, 0x00000000, 0x00000000, 0x00000000,
    153 	0x80000000, 0x00000000, 0x00000001, 0x00000000,
    154 	0x00000000, 0x00000000, 0x0000000d, 0x00000000,
    155 	0x80000000, 0x00000000, 0x00000001, 0x00000000,
    156 	0x1e002800, 0x00000000, 0x00000005, 0x00000000,
    157 };
    158 
    159 STATIC u_int32_t gsfb_load_cmd_8x16_psmct32[(6 + 32) * 4]
    160 	__attribute__((__aligned__(16))) = {
    161 	/* GIF tag + GS command */
    162         0x00000004, 0x10000000, 0x0000000e, 0x00000000,
    163         0x00000000, 0x000a0000, 0x00000050, 0x00000000,
    164         0x00000000, 0x00000000, 0x00000051, 0x00000000,
    165         0x00000008, 0x00000016, 0x00000052, 0x00000000,
    166         0x00000000, 0x00000000, 0x00000053, 0x00000000,
    167         0x00008020, 0x08000000, 0x00000000, 0x00000000,
    168 	/* Load area */
    169 #define FONT_SCRATCH_BASE	(6 * 4)
    170 };
    171 
    172 #ifdef GSFB_DEBUG_MONITOR
    173 #include <machine/stdarg.h>
    174 STATIC const struct _gsfb_debug_window {
    175 	int start, nrow, attr;
    176 } _gsfb_debug_window[3] = {
    177 	{ 24, 2 , ATTR_BG_SET(WSCOL_BROWN) | ATTR_FG_SET(WSCOL_BLUE) },
    178 	{ 26, 2 , ATTR_BG_SET(WSCOL_CYAN) | ATTR_FG_SET(WSCOL_BLUE) },
    179 	{ 28, 2 , ATTR_BG_SET(WSCOL_WHITE) | ATTR_FG_SET(WSCOL_BLUE) },
    180 };
    181 STATIC char _gsfb_debug_buf[80 * 2];
    182 #endif /* GSFB_DEBUG_MONITOR */
    183 
    184 STATIC int gsfb_match(struct device *, struct cfdata *, void *);
    185 STATIC void gsfb_attach(struct device *, struct device *, void *);
    186 
    187 CFATTACH_DECL(gsfb, sizeof(struct device),
    188     gsfb_match, gsfb_attach, NULL, NULL);
    189 
    190 STATIC void gsfb_hwinit(void);
    191 STATIC int gsfb_swinit(void);
    192 
    193 /* console */
    194 void gsfbcnprobe(struct consdev *);
    195 void gsfbcninit(struct consdev *);
    196 
    197 /* emul ops */
    198 STATIC void _gsfb_cursor(void *, int, int, int);
    199 STATIC int _gsfb_mapchar(void *, int, unsigned int *);
    200 STATIC void _gsfb_putchar(void *, int, int, u_int, long);
    201 STATIC void _gsfb_copycols(void *, int, int, int, int);
    202 STATIC void _gsfb_erasecols(void *, int, int, int, long);
    203 STATIC void _gsfb_copyrows(void *, int, int, int);
    204 STATIC void _gsfb_eraserows(void *, int, int, long);
    205 STATIC int _gsfb_allocattr(void *, int, int, int, long *);
    206 
    207 /* access ops */
    208 STATIC int _gsfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
    209 STATIC paddr_t _gsfb_mmap(void *, off_t, int);
    210 STATIC int _gsfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
    211     int *, int *, long *);
    212 STATIC void _gsfb_free_screen(void *, void *);
    213 STATIC int _gsfb_show_screen(void *, void *, int, void (*)(void *, int, int),
    214     void *);
    215 STATIC void _gsfb_pollc(void *, int);
    216 
    217 /*
    218  * wsdisplay attach args
    219  *   std: screen size 640 x 480, font size 8 x 16
    220  */
    221 #define GSFB_STD_SCREEN_WIDTH		640
    222 #define GSFB_STD_SCREEN_HEIGHT		480
    223 #define GSFB_STD_FONT_WIDTH		8
    224 #define GSFB_STD_FONT_HEIGHT		16
    225 const struct wsdisplay_emulops _gsfb_emulops = {
    226 	.cursor		= _gsfb_cursor,
    227 	.mapchar	= _gsfb_mapchar,
    228 	.putchar	= _gsfb_putchar,
    229 	.copycols	= _gsfb_copycols,
    230 	.erasecols	= _gsfb_erasecols,
    231 	.copyrows	= _gsfb_copyrows,
    232 	.eraserows	= _gsfb_eraserows,
    233 	.allocattr	= _gsfb_allocattr
    234 };
    235 
    236 const struct wsscreen_descr _gsfb_std_screen = {
    237 	.name		= "std",
    238 	.ncols		= 80,
    239 #ifdef GSFB_DEBUG_MONITOR
    240 	.nrows		= 24,
    241 #else
    242 	.nrows		= 30,
    243 #endif
    244 	.textops	= &_gsfb_emulops,
    245 	.fontwidth	= 8,
    246 	.fontheight	= 16,
    247 	.capabilities	= WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
    248 	WSSCREEN_WSCOLORS
    249 };
    250 
    251 const struct wsscreen_descr *_gsfb_screen_table[] = {
    252 	&_gsfb_std_screen,
    253 };
    254 
    255 struct wsscreen_list _gsfb_screen_list = {
    256 	.nscreens	= sizeof(_gsfb_screen_table) /
    257 	sizeof(_gsfb_screen_table[0]),
    258 	.screens	= _gsfb_screen_table
    259 };
    260 
    261 struct wsdisplay_accessops _gsfb_accessops = {
    262 	.ioctl		= _gsfb_ioctl,
    263 	.mmap		= _gsfb_mmap,
    264 	.alloc_screen	= _gsfb_alloc_screen,
    265 	.free_screen	= _gsfb_free_screen,
    266 	.show_screen	= _gsfb_show_screen,
    267 	.load_font	= 0,
    268 	.pollc		= _gsfb_pollc
    269 };
    270 
    271 int
    272 gsfb_match(struct device *parent, struct cfdata *cf, void *aux)
    273 {
    274 	extern struct cfdriver gsfb_cd;
    275 	struct mainbus_attach_args *ma = aux;
    276 
    277 	if (strcmp(ma->ma_name, gsfb_cd.cd_name) != 0)
    278 		return (0);
    279 
    280 	return (!gsfb.attached);
    281 }
    282 
    283 void
    284 gsfb_attach(struct device *parent, struct device *self, void *aux)
    285 {
    286 	struct wsemuldisplaydev_attach_args wa;
    287 
    288 	gsfb.attached = 1;
    289 	if (!gsfb.is_console && gsfb_swinit() != 0)
    290 		return;
    291 
    292 	printf("\n");
    293 
    294 	wa.console	= gsfb.is_console;
    295 	wa.scrdata	= &_gsfb_screen_list;
    296 	wa.accessops	= &_gsfb_accessops;
    297 	wa.accesscookie	= &gsfb;
    298 
    299 	config_found(self, &wa, wsdisplaydevprint);
    300 }
    301 
    302 /*
    303  * console
    304  */
    305 void
    306 gsfbcnprobe(struct consdev *cndev)
    307 {
    308 
    309 	cndev->cn_pri = CN_INTERNAL;
    310 }
    311 
    312 void
    313 gsfbcninit(struct consdev *cndev)
    314 {
    315 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_init_cmd_640x480);
    316 	long defattr =  ATTR_BG_SET(WSCOL_BLACK) | ATTR_FG_SET(WSCOL_WHITE);
    317 
    318 	gsfb.is_console = 1;
    319 
    320 	gsfb_hwinit();
    321 	gsfb_swinit();
    322 
    323 	gsfb_dma_kick(paddr, sizeof gsfb_init_cmd_640x480);
    324 #ifdef GSFB_DEBUG_MONITOR
    325 	{
    326 		const struct _gsfb_debug_window *win;
    327 		int i;
    328 
    329 		for (i = 0; i < 3; i++) {
    330 			win = &_gsfb_debug_window[i];
    331 			_gsfb_eraserows(0, win->start, win->nrow, win->attr);
    332 		}
    333 	}
    334 #endif /* GSFB_DEBUG_MONITOR */
    335 
    336 	wsdisplay_cnattach(&_gsfb_std_screen, &gsfb, 0, 0, defattr);
    337 }
    338 
    339 void
    340 gsfb_hwinit()
    341 {
    342 	gs_init(VESA_1A);
    343 	dmac_init();
    344 
    345 	/* reset GIF channel DMA */
    346 	_reg_write_4(D2_QWC_REG, 0);
    347 	_reg_write_4(D2_MADR_REG, 0);
    348 	_reg_write_4(D2_TADR_REG, 0);
    349 	_reg_write_4(D2_CHCR_REG, 0);
    350 }
    351 
    352 int
    353 gsfb_swinit()
    354 {
    355 	int font;
    356 
    357 	wsfont_init();
    358 	font = wsfont_find(NULL, 8, 16, 0,  WSDISPLAY_FONTORDER_L2R,
    359 	    WSDISPLAY_FONTORDER_L2R);
    360 	if (font < 0)
    361 		return (1);
    362 
    363 	if (wsfont_lock(font, &gsfb.font))
    364 		return (1);
    365 
    366 	gsfb.screen = &_gsfb_std_screen;
    367 	gsfb.initialized = 1;
    368 
    369 	return (0);
    370 }
    371 
    372 /*
    373  * wsdisplay
    374  */
    375 void
    376 _gsfb_cursor(void *cookie, int on, int row, int col)
    377 {
    378 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_cursor_cmd);
    379 	u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
    380 	struct wsdisplay_font *font = gsfb.font;
    381 
    382 	gsfb_set_cursor_pos(buf, col, row, font->fontwidth, font->fontheight);
    383 
    384 	gsfb_dma_kick(paddr, sizeof gsfb_cursor_cmd);
    385 }
    386 
    387 __inline__ void
    388 gsfb_set_cursor_pos(u_int32_t *p, int x, int y, int w, int h)
    389 {
    390 
    391 	x *= w;
    392 	y *= h;
    393 	p[20] = ((x << 4) & 0xffff) | ((y << 20) & 0xffff0000);
    394 	p[28] = (((x + w - 1) << 4) & 0xffff) |
    395 	    (((y + h - 1) << 20) & 0xffff0000);
    396 }
    397 
    398 int
    399 _gsfb_mapchar(void *cookie, int c, unsigned int *cp)
    400 {
    401 	struct wsdisplay_font *font = gsfb.font;
    402 
    403 	if (font->encoding != WSDISPLAY_FONTENC_ISO)
    404 		if ((c = wsfont_map_unichar(font, c)) < 0)
    405 			goto nomap;
    406 
    407 	if (c < font->firstchar || c >= font->firstchar + font->numchars)
    408 			goto nomap;
    409 
    410 	*cp = c;
    411 	return (5);
    412 
    413  nomap:
    414 	*cp = ' ';
    415 	return (0);
    416 }
    417 
    418 void
    419 _gsfb_putchar(void *cookie, int row, int col, u_int uc, long attr)
    420 {
    421 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_load_cmd_8x16_psmct32);
    422 	u_int32_t *buf = (void *)MIPS_PHYS_TO_KSEG1(paddr);
    423 	struct wsdisplay_font *font = gsfb.font;
    424 
    425 	/* copy font data to DMA region */
    426 	gsfb_font_expand_psmct32(font, uc, attr, &buf[FONT_SCRATCH_BASE]);
    427 
    428 	/* set destination position */
    429 	TRXPOS_DXY(buf, col * font->fontwidth, row * font->fontheight);
    430 
    431 	/* kick to GIF */
    432 	gsfb_dma_kick(paddr, sizeof gsfb_load_cmd_8x16_psmct32);
    433 }
    434 
    435 void
    436 _gsfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
    437 {
    438 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_copy_cmd_8x16);
    439 	u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
    440 	int y = gsfb.font->fontheight * row;
    441 	int w = gsfb.font->fontwidth;
    442 	int i;
    443 
    444 	if (dstcol > srccol) {
    445 		for (i = ncols - 1; i >= 0; i--) {
    446 			TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
    447 			gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
    448 		}
    449 	} else {
    450 		for (i = 0; i < ncols; i++) {
    451 			TRXPOS_DXY_SXY(cmd, (dstcol + i) * w, y, (srccol + i) * w, y);
    452 			gsfb_dma_kick(paddr, sizeof gsfb_copy_cmd_8x16);
    453 		}
    454 	}
    455 }
    456 
    457 void
    458 _gsfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
    459 {
    460 	int i;
    461 
    462 	for (i = 0; i < ncols; i++)
    463 		_gsfb_putchar(cookie, row, startcol + i, ' ', attr);
    464 }
    465 
    466 void
    467 _gsfb_copyrows(void *cookie, int src, int dst, int num)
    468 {
    469 	paddr_t paddr = MIPS_KSEG0_TO_PHYS(gsfb_scroll_cmd_640x16);
    470 	u_int32_t *cmd = (void *)MIPS_PHYS_TO_KSEG1(paddr);
    471 	int i;
    472 	int h = gsfb.font->fontheight;
    473 
    474 	if (dst > src) {
    475 		for (i = num - 1; i >= 0; i--) {
    476 			TRXPOS_SY_DY(cmd, (src + i) * h, (dst  + i) * h);
    477 			gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
    478 		}
    479 	} else {
    480 		for (i = 0; i < num; i++) {
    481 			TRXPOS_SY_DY(cmd, (src + i) * h, (dst  + i) * h);
    482 			gsfb_dma_kick(paddr, sizeof gsfb_scroll_cmd_640x16);
    483 		}
    484 	}
    485 }
    486 
    487 void
    488 _gsfb_eraserows(void *cookie, int row, int nrow, long attr)
    489 {
    490 	int i, j;
    491 
    492 	for (j = 0; j < nrow; j++)
    493 		for (i = 0; i < gsfb.screen->ncols; i++)
    494 			_gsfb_putchar(cookie, row + j, i, ' ', attr);
    495 }
    496 
    497 int
    498 _gsfb_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
    499 {
    500 
    501 	if ((flags & WSATTR_BLINK) != 0)
    502 		return (EINVAL);
    503 
    504 	if ((flags & WSATTR_WSCOLORS) == 0) {
    505 		fg = WSCOL_WHITE;
    506 		bg = WSCOL_BLACK;
    507 	}
    508 
    509 	if ((flags & WSATTR_HILIT) != 0)
    510 		fg += 8;
    511 
    512 	flags = (flags & WSATTR_UNDERLINE) ? 1 : 0;
    513 
    514 
    515 	*attr = ATTR_BG_SET(bg) | ATTR_FG_SET(fg) | flags;
    516 
    517 	return (0);
    518 }
    519 
    520 int
    521 _gsfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    522 {
    523 
    524 	return (EPASSTHROUGH); /* Inappropriate ioctl for device */
    525 }
    526 
    527 paddr_t
    528 _gsfb_mmap(void *v, off_t offset, int prot)
    529 {
    530 
    531 	return (NULL); /* can't mmap */
    532 }
    533 
    534 int
    535 _gsfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
    536     int *curxp, int *curyp, long *attrp)
    537 {
    538 
    539 	*attrp = ATTR_BG_SET(WSCOL_BLACK) | ATTR_FG_SET(WSCOL_WHITE);
    540 
    541 	return (0);
    542 }
    543 
    544 void
    545 _gsfb_free_screen(void *v, void *cookie)
    546 {
    547 }
    548 
    549 int
    550 _gsfb_show_screen(void *v, void *cookie, int waitok,
    551     void (*cb)(void *, int, int), void *cbarg)
    552 {
    553 
    554 	return (0);
    555 }
    556 
    557 void
    558 _gsfb_pollc(void *v, int on)
    559 {
    560 
    561 }
    562 
    563 /*
    564  * font expansion
    565  *   PSMCT32 only
    566  */
    567 void
    568 gsfb_font_expand_psmct32(const struct wsdisplay_font *font, u_int c, long attr,
    569     u_int32_t *buf)
    570 {
    571 	u_int32_t fg, bg;
    572 	u_int8_t *bitmap;
    573 	int i, j;
    574 
    575 	KDASSERT(((u_int32_t)buf & 15) == 0);
    576 
    577 	fg = gsfb_ansi_psmct32[ATTR_FG_GET(attr)];
    578 	bg = gsfb_ansi_psmct32[ATTR_BG_GET(attr)];
    579 
    580 	bitmap = (u_int8_t *)font->data + (c - font->firstchar) *
    581 	    font->fontheight * font->stride;
    582 	for (i = 0; i < font->fontheight; i++, bitmap++) {
    583 		u_int32_t b = *bitmap;
    584 		for (j = 0; j < font->fontwidth; j++, b <<= 1)
    585 			*buf++ = (b & 0x80) ? fg : bg;
    586 	}
    587 }
    588 
    589 void
    590 gsfb_dma_kick(paddr_t addr, size_t size)
    591 {
    592 	/* Wait for previous DMA request complete */
    593 	while (_reg_read_4(D2_QWC_REG))
    594 		;
    595 
    596 	/* Wait until GS FIFO empty */
    597 	while ((_reg_read_8(GS_S_CSR_REG) & (3 << 14)) != (1 << 14))
    598 		;
    599 
    600 	/* wait for DMA complete */
    601 	dmac_bus_poll(D_CH2_GIF);
    602 
    603 	/* transfer addr */
    604 	_reg_write_4(D2_MADR_REG, addr);
    605 	/* transfer data size (unit qword) */
    606 	_reg_write_4(D2_QWC_REG, bytetoqwc(size));
    607 
    608 	/* kick DMA (normal-mode) */
    609 	dmac_chcr_write(D_CH2_GIF, D_CHCR_STR);
    610 }
    611 
    612 #ifdef GSFB_DEBUG_MONITOR
    613 void
    614 __gsfb_print(int window, const char *fmt, ...)
    615 {
    616 	const struct _gsfb_debug_window *win;
    617 	int i, s, x, y, n, a;
    618 	u_int c;
    619 	va_list ap;
    620 
    621 	if (!gsfb.initialized)
    622 		return;
    623 
    624 	s = _intr_suspend();
    625 	win = &_gsfb_debug_window[window];
    626 	x = 0;
    627 	y = win->start;
    628 	n = win->nrow * 80;
    629 	a = win->attr;
    630 
    631 	va_start(ap, fmt);
    632 	vsnprintf(_gsfb_debug_buf, n, fmt, ap);
    633 	va_end(ap);
    634 
    635 	_gsfb_eraserows(0, y, win->nrow, a);
    636 
    637 	for (i = 0; i < n &&
    638 	    (c = (u_int)_gsfb_debug_buf[i] & 0x7f) != 0; i++) {
    639 		if (c == '\n')
    640 			x = 0, y++;
    641 		else
    642 			_gsfb_putchar(0, y, x++, c, a);
    643 	}
    644 
    645 	_intr_resume(s);
    646 }
    647 
    648 void
    649 __gsfb_print_hex(int a0, int a1, int a2, int a3)
    650 {
    651 	__gsfb_print(2, "a0=%08x a1=%08x a2=%08x a3=%08x",
    652 	    a0, a1, a2, a3);
    653 }
    654 #endif /* GSFB_DEBUG_MONITOR */
    655