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