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