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