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