Home | History | Annotate | Line # | Download | only in gio
light.c revision 1.7
      1  1.7       chs /*	$Id: light.c,v 1.7 2012/10/27 17:18:09 chs Exp $	*/
      2  1.1    rumble 
      3  1.1    rumble /*
      4  1.1    rumble  * Copyright (c) 2006 Stephen M. Rumble
      5  1.1    rumble  * Copyright (c) 2003 Ilpo Ruotsalainen
      6  1.1    rumble  * All rights reserved.
      7  1.1    rumble  *
      8  1.1    rumble  * Redistribution and use in source and binary forms, with or without
      9  1.1    rumble  * modification, are permitted provided that the following conditions
     10  1.1    rumble  * are met:
     11  1.1    rumble  * 1. Redistributions of source code must retain the above copyright
     12  1.1    rumble  *    notice, this list of conditions and the following disclaimer.
     13  1.1    rumble  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1    rumble  *    notice, this list of conditions and the following disclaimer in the
     15  1.1    rumble  *    documentation and/or other materials provided with the distribution.
     16  1.1    rumble  * 3. The name of the author may not be used to endorse or promote products
     17  1.1    rumble  *    derived from this software without specific prior written permission.
     18  1.1    rumble  *
     19  1.1    rumble  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  1.1    rumble  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  1.1    rumble  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  1.1    rumble  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  1.1    rumble  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  1.1    rumble  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  1.1    rumble  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  1.1    rumble  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  1.1    rumble  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  1.1    rumble  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  1.1    rumble  *
     30  1.1    rumble  * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>>
     31  1.1    rumble  */
     32  1.1    rumble 
     33  1.1    rumble /*
     34  1.1    rumble  * SGI "Light" graphics, a.k.a. "Entry", "Starter", "LG1", and "LG2".
     35  1.1    rumble  *
     36  1.1    rumble  * 1024x768 8bpp at 60Hz.
     37  1.1    rumble  *
     38  1.1    rumble  * This driver supports the boards found in Indigo R3k and R4k machines.
     39  1.1    rumble  * There is a Crimson variant, but the register offsets differ significantly.
     40  1.1    rumble  *
     41  1.2    rumble  * Light's REX chip is the precursor of the REX3 found in "newport", hence
     42  1.2    rumble  * much similarity exists.
     43  1.1    rumble  */
     44  1.1    rumble 
     45  1.1    rumble #include <sys/cdefs.h>
     46  1.7       chs __KERNEL_RCSID(0, "$NetBSD: light.c,v 1.7 2012/10/27 17:18:09 chs Exp $");
     47  1.1    rumble 
     48  1.1    rumble #include <sys/param.h>
     49  1.1    rumble #include <sys/systm.h>
     50  1.1    rumble #include <sys/device.h>
     51  1.1    rumble #include <sys/malloc.h>
     52  1.1    rumble 
     53  1.4    rumble #include <machine/sysconf.h>
     54  1.4    rumble 
     55  1.1    rumble #include <dev/wscons/wsconsio.h>
     56  1.1    rumble #include <dev/wscons/wsdisplayvar.h>
     57  1.1    rumble #include <dev/wsfont/wsfont.h>
     58  1.1    rumble 
     59  1.1    rumble #include <sgimips/gio/giovar.h>
     60  1.1    rumble #include <sgimips/gio/lightvar.h>
     61  1.1    rumble #include <sgimips/gio/lightreg.h>
     62  1.1    rumble 
     63  1.1    rumble struct light_softc {
     64  1.1    rumble 	struct light_devconfig *sc_dc;
     65  1.1    rumble };
     66  1.1    rumble 
     67  1.1    rumble struct light_devconfig {
     68  1.1    rumble 	uint32_t		dc_addr;
     69  1.1    rumble 
     70  1.1    rumble 	bus_space_tag_t		dc_st;
     71  1.1    rumble 	bus_space_handle_t	dc_sh;
     72  1.1    rumble 
     73  1.1    rumble 	int			dc_boardrev;
     74  1.1    rumble 	int                     dc_font;
     75  1.1    rumble 	struct wsdisplay_font  *dc_fontdata;
     76  1.1    rumble };
     77  1.1    rumble 
     78  1.1    rumble /* always 1024x768x8 */
     79  1.1    rumble #define LIGHT_XRES	1024
     80  1.1    rumble #define LIGHT_YRES	768
     81  1.1    rumble #define LIGHT_DEPTH	8
     82  1.1    rumble 
     83  1.7       chs static int	light_match(device_t, cfdata_t, void *);
     84  1.7       chs static void	light_attach(device_t, device_t, void *);
     85  1.1    rumble 
     86  1.7       chs CFATTACH_DECL_NEW(light, sizeof(struct light_softc), light_match, light_attach,
     87  1.1    rumble     NULL, NULL);
     88  1.1    rumble 
     89  1.1    rumble /* wsdisplay_emulops */
     90  1.1    rumble static void	light_cursor(void *, int, int, int);
     91  1.1    rumble static int	light_mapchar(void *, int, unsigned int *);
     92  1.1    rumble static void	light_putchar(void *, int, int, u_int, long);
     93  1.1    rumble static void	light_copycols(void *, int, int, int, int);
     94  1.1    rumble static void	light_erasecols(void *, int, int, int, long);
     95  1.1    rumble static void	light_copyrows(void *, int, int, int);
     96  1.1    rumble static void	light_eraserows(void *, int, int, long);
     97  1.1    rumble static int	light_allocattr(void *, int, int, int, long *);
     98  1.1    rumble 
     99  1.1    rumble /* wsdisplay_accessops */
    100  1.5  christos static int	light_ioctl(void *, void *, u_long, void *, int, struct lwp *);
    101  1.1    rumble static paddr_t	light_mmap(void *, void *, off_t, int);
    102  1.1    rumble static int	light_alloc_screen(void *, const struct wsscreen_descr *,
    103  1.1    rumble     void **, int *, int *, long *);
    104  1.1    rumble static void	light_free_screen(void *, void *);
    105  1.1    rumble static int	light_show_screen(void *, void *, int,
    106  1.1    rumble     void (*)(void *, int, int), void *);
    107  1.1    rumble 
    108  1.1    rumble static const struct wsdisplay_accessops light_accessops = {
    109  1.1    rumble 	.ioctl		= light_ioctl,
    110  1.1    rumble 	.mmap		= light_mmap,
    111  1.1    rumble 	.alloc_screen	= light_alloc_screen,
    112  1.1    rumble 	.free_screen	= light_free_screen,
    113  1.1    rumble 	.show_screen	= light_show_screen,
    114  1.1    rumble 	.load_font	= NULL,
    115  1.1    rumble 	.pollc		= NULL,
    116  1.1    rumble 	.scroll		= NULL
    117  1.1    rumble };
    118  1.1    rumble 
    119  1.1    rumble static const struct wsdisplay_emulops light_emulops = {
    120  1.1    rumble 	.cursor		= light_cursor,
    121  1.1    rumble 	.mapchar	= light_mapchar,
    122  1.1    rumble 	.putchar	= light_putchar,
    123  1.1    rumble 	.copycols	= light_copycols,
    124  1.1    rumble 	.erasecols	= light_erasecols,
    125  1.1    rumble 	.copyrows	= light_copyrows,
    126  1.1    rumble 	.eraserows	= light_eraserows,
    127  1.1    rumble 	.allocattr	= light_allocattr,
    128  1.1    rumble 	.replaceattr	= NULL
    129  1.1    rumble };
    130  1.1    rumble 
    131  1.1    rumble static const struct wsscreen_descr light_screen = {
    132  1.1    rumble 	.name           = "1024x768",
    133  1.1    rumble 	.ncols          = 128,
    134  1.1    rumble 	.nrows          = 48,
    135  1.1    rumble 	.textops        = &light_emulops,
    136  1.1    rumble 	.fontwidth      = 8,
    137  1.1    rumble 	.fontheight     = 16,
    138  1.1    rumble 	.capabilities   = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_REVERSE
    139  1.1    rumble };
    140  1.1    rumble 
    141  1.1    rumble const struct wsscreen_descr *_light_screenlist[] = {
    142  1.1    rumble 	&light_screen
    143  1.1    rumble };
    144  1.1    rumble 
    145  1.1    rumble static const struct wsscreen_list light_screenlist = {
    146  1.1    rumble 	sizeof(_light_screenlist) / sizeof(_light_screenlist[0]),
    147  1.1    rumble 	_light_screenlist
    148  1.1    rumble };
    149  1.1    rumble 
    150  1.1    rumble static struct light_devconfig	light_console_dc;
    151  1.1    rumble static int			light_is_console = 0;
    152  1.1    rumble 
    153  1.1    rumble #define LIGHT_ATTR_ENCODE(fg, bg)	(((fg << 8) & 0xff00) | (bg * 0x00ff))
    154  1.1    rumble #define LIGHT_ATTR_FG(attr)		((attr >> 8) & 0x00ff)
    155  1.1    rumble #define LIGHT_ATTR_BG(attr)		(attr & 0x00ff)
    156  1.1    rumble 
    157  1.1    rumble #define LIGHT_IS_LG1(_rev)		((_rev) < 2)	/* else LG2 */
    158  1.1    rumble 
    159  1.1    rumble /*******************************************************************************
    160  1.1    rumble  * REX routines and helper functions
    161  1.1    rumble  ******************************************************************************/
    162  1.1    rumble 
    163  1.1    rumble static uint32_t
    164  1.1    rumble rex_read(struct light_devconfig *dc, uint32_t rset, uint32_t r)
    165  1.1    rumble {
    166  1.1    rumble 
    167  1.1    rumble 	return (bus_space_read_4(dc->dc_st, dc->dc_sh, rset + r));
    168  1.1    rumble }
    169  1.1    rumble 
    170  1.1    rumble static void
    171  1.1    rumble rex_write(struct light_devconfig *dc, uint32_t rset, uint32_t r, uint32_t v)
    172  1.1    rumble {
    173  1.1    rumble 
    174  1.1    rumble 	bus_space_write_4(dc->dc_st, dc->dc_sh, rset + r, v);
    175  1.1    rumble }
    176  1.1    rumble 
    177  1.2    rumble static uint8_t
    178  1.2    rumble rex_vc1_read(struct light_devconfig *dc)
    179  1.2    rumble {
    180  1.2    rumble 
    181  1.2    rumble 	rex_write(dc, REX_PAGE1_GO, REX_P1REG_CFGSEL, REX_CFGSEL_VC1_SYSCTL);
    182  1.2    rumble 	rex_read(dc, REX_PAGE1_GO, REX_P1REG_VC1_ADDRDATA);
    183  1.2    rumble 	return (rex_read(dc, REX_PAGE1_SET, REX_P1REG_VC1_ADDRDATA));
    184  1.2    rumble }
    185  1.2    rumble 
    186  1.2    rumble static void
    187  1.2    rumble rex_vc1_write(struct light_devconfig *dc, uint8_t val)
    188  1.2    rumble {
    189  1.2    rumble 
    190  1.2    rumble 	rex_write(dc, REX_PAGE1_GO, REX_P1REG_CFGSEL, REX_CFGSEL_VC1_SYSCTL);
    191  1.2    rumble 	rex_write(dc, REX_PAGE1_SET, REX_P1REG_VC1_ADDRDATA, val);
    192  1.2    rumble 	rex_write(dc, REX_PAGE1_GO, REX_P1REG_VC1_ADDRDATA, val);
    193  1.2    rumble }
    194  1.2    rumble 
    195  1.1    rumble static void
    196  1.1    rumble rex_wait(struct light_devconfig *dc)
    197  1.1    rumble {
    198  1.1    rumble 
    199  1.2    rumble 	while (rex_read(dc, REX_PAGE1_SET,REX_P1REG_CFGMODE) & REX_CFGMODE_BUSY)
    200  1.1    rumble 		;
    201  1.1    rumble }
    202  1.1    rumble 
    203  1.1    rumble static int
    204  1.1    rumble rex_revision(struct light_devconfig *dc)
    205  1.1    rumble {
    206  1.1    rumble 
    207  1.2    rumble 	rex_write(dc, REX_PAGE1_SET, REX_P1REG_CFGSEL, REX_CFGSEL_VC1_LADDR);
    208  1.2    rumble 	rex_read(dc, REX_PAGE1_GO, REX_P1REG_WCLOCKREV);
    209  1.2    rumble 	return (rex_read(dc, REX_PAGE1_SET, REX_P1REG_WCLOCKREV) & 0x7);
    210  1.1    rumble }
    211  1.1    rumble 
    212  1.1    rumble static void
    213  1.1    rumble rex_copy_rect(struct light_devconfig *dc, int from_x, int from_y, int to_x,
    214  1.1    rumble     int to_y, int width, int height)
    215  1.1    rumble {
    216  1.1    rumble 	int dx, dy, ystarti, yendi;
    217  1.1    rumble 
    218  1.1    rumble 	dx = from_x - to_x;
    219  1.1    rumble 	dy = from_y - to_y;
    220  1.1    rumble 
    221  1.1    rumble 	/* adjust for y. NB: STOPONX, STOPONY are inclusive */
    222  1.1    rumble 	if (to_y > from_y) {
    223  1.1    rumble 		ystarti = to_y + height - 1;
    224  1.1    rumble 		yendi = to_y;
    225  1.1    rumble 	} else {
    226  1.1    rumble 		ystarti = to_y;
    227  1.1    rumble 		yendi = to_y + height - 1;
    228  1.1    rumble 	}
    229  1.1    rumble 
    230  1.1    rumble 	rex_wait(dc);
    231  1.1    rumble 
    232  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_XSTARTI, to_x);
    233  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_XENDI, to_x + width);
    234  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_YSTARTI, ystarti);
    235  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_YENDI, yendi);
    236  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_COMMAND, REX_OP_DRAW |
    237  1.2    rumble 	    REX_LOGICOP_SRC | REX_OP_FLG_LOGICSRC | REX_OP_FLG_QUADMODE |
    238  1.2    rumble 	    REX_OP_FLG_BLOCK | REX_OP_FLG_STOPONX | REX_OP_FLG_STOPONY);
    239  1.2    rumble 	rex_write(dc, REX_PAGE0_GO, REX_P0REG_XYMOVE,
    240  1.1    rumble 	    ((dx << 16) & 0xffff0000) | (dy & 0x0000ffff));
    241  1.1    rumble }
    242  1.1    rumble 
    243  1.1    rumble static void
    244  1.1    rumble rex_fill_rect(struct light_devconfig *dc, int from_x, int from_y, int to_x,
    245  1.1    rumble     int to_y, long attr)
    246  1.1    rumble {
    247  1.1    rumble 
    248  1.1    rumble 	rex_wait(dc);
    249  1.1    rumble 
    250  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_YSTARTI, from_y);
    251  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_YENDI, to_y);
    252  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_XSTARTI, from_x);
    253  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_XENDI, to_x);
    254  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_COLORREDI, LIGHT_ATTR_BG(attr));
    255  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_COMMAND, REX_OP_DRAW |
    256  1.2    rumble 	    REX_LOGICOP_SRC | REX_OP_FLG_QUADMODE | REX_OP_FLG_BLOCK |
    257  1.2    rumble 	    REX_OP_FLG_STOPONX | REX_OP_FLG_STOPONY);
    258  1.2    rumble 	rex_read(dc, REX_PAGE0_GO, REX_P0REG_COMMAND);
    259  1.1    rumble }
    260  1.1    rumble 
    261  1.1    rumble /*******************************************************************************
    262  1.1    rumble  * match/attach functions
    263  1.1    rumble  ******************************************************************************/
    264  1.1    rumble 
    265  1.1    rumble static int
    266  1.7       chs light_match(device_t parent, cfdata_t cf, void *aux)
    267  1.1    rumble {
    268  1.1    rumble 	struct gio_attach_args *ga = aux;
    269  1.1    rumble 
    270  1.1    rumble 	if (ga->ga_addr != LIGHT_ADDR_0 && ga->ga_addr != LIGHT_ADDR_1)
    271  1.1    rumble 		return (0);
    272  1.1    rumble 
    273  1.4    rumble 	if (platform.badaddr(
    274  1.4    rumble 	    (void *)(ga->ga_ioh + REX_PAGE1_SET + REX_P1REG_XYOFFSET),
    275  1.3    rumble 	    sizeof(uint32_t)))
    276  1.3    rumble 		return (0);
    277  1.3    rumble 
    278  1.3    rumble 	if (bus_space_read_4(ga->ga_iot, ga->ga_ioh,
    279  1.3    rumble 	    REX_PAGE1_SET + REX_P1REG_XYOFFSET) != 0x08000800)
    280  1.3    rumble 		return (0);
    281  1.3    rumble 
    282  1.1    rumble 	return (1);
    283  1.1    rumble }
    284  1.1    rumble 
    285  1.1    rumble static void
    286  1.1    rumble light_attach_common(struct light_devconfig *dc, struct gio_attach_args *ga)
    287  1.1    rumble {
    288  1.1    rumble 
    289  1.1    rumble 	dc->dc_addr = ga->ga_addr;
    290  1.1    rumble 	dc->dc_st = ga->ga_iot;
    291  1.1    rumble 	dc->dc_sh = ga->ga_ioh;
    292  1.1    rumble 
    293  1.1    rumble 	dc->dc_boardrev = rex_revision(dc);
    294  1.1    rumble 
    295  1.1    rumble 	wsfont_init();
    296  1.1    rumble 
    297  1.1    rumble 	dc->dc_font = wsfont_find(NULL, 8, 16, 0, WSDISPLAY_FONTORDER_L2R,
    298  1.6  macallan 	    WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
    299  1.1    rumble 
    300  1.1    rumble 	if (dc->dc_font < 0)
    301  1.1    rumble 		panic("light_attach_common: no suitable fonts");
    302  1.1    rumble 
    303  1.1    rumble 	if (wsfont_lock(dc->dc_font, &dc->dc_fontdata))
    304  1.1    rumble 		panic("light_attach_common: unable to lock font data");
    305  1.1    rumble 
    306  1.2    rumble 	rex_vc1_write(dc, rex_vc1_read(dc) & ~(VC1_SYSCTL_CURSOR |
    307  1.2    rumble 	    VC1_SYSCTL_CURSOR_ON));
    308  1.1    rumble 	rex_fill_rect(dc, 0, 0, LIGHT_XRES - 1, LIGHT_YRES - 1, 0);
    309  1.1    rumble }
    310  1.1    rumble 
    311  1.1    rumble static void
    312  1.7       chs light_attach(device_t parent, device_t self, void *aux)
    313  1.1    rumble {
    314  1.1    rumble 	struct gio_attach_args *ga = aux;
    315  1.7       chs 	struct light_softc *sc = device_private(self);
    316  1.1    rumble 	struct wsemuldisplaydev_attach_args wa;
    317  1.1    rumble 
    318  1.1    rumble 	if (light_is_console && ga->ga_addr == light_console_dc.dc_addr) {
    319  1.1    rumble 		wa.console = 1;
    320  1.1    rumble 		sc->sc_dc = &light_console_dc;
    321  1.1    rumble 	} else {
    322  1.1    rumble 		wa.console = 0;
    323  1.1    rumble 		sc->sc_dc = malloc(sizeof(struct light_devconfig), M_DEVBUF,
    324  1.1    rumble 		    M_WAITOK | M_ZERO);
    325  1.1    rumble 		if (sc->sc_dc == NULL)
    326  1.1    rumble 			panic("light_attach: out of memory");
    327  1.1    rumble 
    328  1.1    rumble 		light_attach_common(sc->sc_dc, ga);
    329  1.1    rumble 	}
    330  1.1    rumble 
    331  1.1    rumble 	aprint_naive(": Display adapter\n");
    332  1.1    rumble 
    333  1.2    rumble 	aprint_normal(": SGI LG%d (board revision %d)\n",
    334  1.1    rumble 	    LIGHT_IS_LG1(sc->sc_dc->dc_boardrev) ? 1 : 2,
    335  1.1    rumble 	    sc->sc_dc->dc_boardrev);
    336  1.1    rumble 
    337  1.1    rumble 	wa.scrdata = &light_screenlist;
    338  1.1    rumble 	wa.accessops = &light_accessops;
    339  1.1    rumble 	wa.accesscookie = sc->sc_dc;
    340  1.1    rumble 
    341  1.7       chs 	config_found(self, &wa, wsemuldisplaydevprint);
    342  1.1    rumble }
    343  1.1    rumble 
    344  1.1    rumble int
    345  1.1    rumble light_cnattach(struct gio_attach_args *ga)
    346  1.1    rumble {
    347  1.1    rumble 
    348  1.1    rumble 	if (!light_match(NULL, NULL, ga))
    349  1.1    rumble 		return (ENXIO);
    350  1.1    rumble 
    351  1.1    rumble 	light_attach_common(&light_console_dc, ga);
    352  1.1    rumble 
    353  1.1    rumble 	wsdisplay_cnattach(&light_screen, &light_console_dc, 0, 0,
    354  1.1    rumble 	    LIGHT_ATTR_ENCODE(WSCOL_WHITE, WSCOL_BLACK));
    355  1.1    rumble 
    356  1.1    rumble 	light_is_console = 1;
    357  1.1    rumble 
    358  1.1    rumble 	return (0);
    359  1.1    rumble }
    360  1.1    rumble 
    361  1.1    rumble /*******************************************************************************
    362  1.1    rumble  * wsdisplay_emulops
    363  1.1    rumble  ******************************************************************************/
    364  1.1    rumble 
    365  1.1    rumble static void
    366  1.1    rumble light_cursor(void *c, int on, int row, int col)
    367  1.1    rumble {
    368  1.1    rumble 	/* XXX */
    369  1.1    rumble }
    370  1.1    rumble 
    371  1.1    rumble static int
    372  1.1    rumble light_mapchar(void *c, int ch, unsigned int *cp)
    373  1.1    rumble {
    374  1.1    rumble 	struct light_devconfig *dc = (void *)c;
    375  1.1    rumble 
    376  1.1    rumble 	if (dc->dc_fontdata->encoding != WSDISPLAY_FONTENC_ISO) {
    377  1.1    rumble 		ch = wsfont_map_unichar(dc->dc_fontdata, ch);
    378  1.1    rumble 
    379  1.1    rumble 		if (ch < 0)
    380  1.1    rumble 			goto fail;
    381  1.1    rumble 	}
    382  1.1    rumble 
    383  1.1    rumble 	if (ch < dc->dc_fontdata->firstchar ||
    384  1.1    rumble 	    ch >= dc->dc_fontdata->firstchar + dc->dc_fontdata->numchars)
    385  1.1    rumble 		goto fail;
    386  1.1    rumble 
    387  1.1    rumble 	*cp = ch;
    388  1.1    rumble 	return 5;
    389  1.1    rumble 
    390  1.1    rumble fail:
    391  1.1    rumble 	*cp = ' ';
    392  1.1    rumble 	return 0;
    393  1.1    rumble }
    394  1.1    rumble 
    395  1.1    rumble static void
    396  1.1    rumble light_putchar(void *c, int row, int col, u_int ch, long attr)
    397  1.1    rumble {
    398  1.1    rumble         struct light_devconfig *dc = c;
    399  1.1    rumble 	struct wsdisplay_font *font = dc->dc_fontdata;
    400  1.1    rumble 	uint8_t *bitmap;
    401  1.1    rumble 	uint32_t pattern;
    402  1.1    rumble 	int i, x, y;
    403  1.1    rumble 
    404  1.1    rumble 	bitmap = (u_int8_t *)font->data +
    405  1.1    rumble 	    ((ch - font->firstchar) * font->fontheight * font->stride);
    406  1.1    rumble 	x = col * font->fontwidth;
    407  1.1    rumble 	y = row * font->fontheight;
    408  1.1    rumble 
    409  1.1    rumble 	rex_wait(dc);
    410  1.1    rumble 
    411  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_YSTARTI, y);
    412  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_YENDI, y + font->fontheight - 1);
    413  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_XSTARTI, x);
    414  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_XENDI, x + font->fontwidth - 1);
    415  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_COLORREDI, LIGHT_ATTR_FG(attr));
    416  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_COLORBACK, LIGHT_ATTR_BG(attr));
    417  1.2    rumble 	rex_write(dc, REX_PAGE0_GO,  REX_P0REG_COMMAND, REX_OP_NOP);
    418  1.1    rumble 
    419  1.1    rumble 	rex_wait(dc);
    420  1.1    rumble 
    421  1.2    rumble 	rex_write(dc, REX_PAGE0_SET, REX_P0REG_COMMAND, REX_OP_DRAW |
    422  1.2    rumble 	    REX_LOGICOP_SRC | REX_OP_FLG_ENZPATTERN | REX_OP_FLG_QUADMODE |
    423  1.2    rumble 	    REX_OP_FLG_XYCONTINUE | REX_OP_FLG_STOPONX | REX_OP_FLG_BLOCK |
    424  1.2    rumble 	    REX_OP_FLG_LENGTH32 | REX_OP_FLG_ZOPAQUE);
    425  1.1    rumble 
    426  1.1    rumble 	for (i = 0; i < font->fontheight; i++) {
    427  1.1    rumble 		/* XXX assumes font->fontwidth == 8 */
    428  1.1    rumble 		pattern = *bitmap << 24;
    429  1.2    rumble 		rex_write(dc, REX_PAGE0_GO, REX_P0REG_ZPATTERN, pattern);
    430  1.1    rumble 		bitmap += font->stride;
    431  1.1    rumble 	}
    432  1.1    rumble }
    433  1.1    rumble 
    434  1.1    rumble /* copy set of columns within the same line */
    435  1.1    rumble static void
    436  1.1    rumble light_copycols(void *c, int row, int srccol, int dstcol, int ncols)
    437  1.1    rumble {
    438  1.1    rumble 	struct light_devconfig *dc = c;
    439  1.1    rumble 	struct wsdisplay_font *font = dc->dc_fontdata;
    440  1.1    rumble 	int from_x, from_y, to_x, to_y, width, height;
    441  1.1    rumble 
    442  1.1    rumble 	from_x	= srccol * font->fontwidth;
    443  1.1    rumble 	from_y	= row * font->fontheight;
    444  1.1    rumble 	to_x	= dstcol * font->fontwidth;
    445  1.1    rumble 	to_y	= from_y;
    446  1.1    rumble 	width	= ncols * font->fontwidth;
    447  1.1    rumble 	height	= font->fontheight;
    448  1.1    rumble 
    449  1.1    rumble 	rex_copy_rect(c, from_x, from_y, to_x, to_y, width, height);
    450  1.1    rumble }
    451  1.1    rumble 
    452  1.1    rumble /* erase a set of columns in the same line */
    453  1.1    rumble static void
    454  1.1    rumble light_erasecols(void *c, int row, int startcol, int ncols, long attr)
    455  1.1    rumble {
    456  1.1    rumble 	struct light_devconfig *dc = c;
    457  1.1    rumble 	struct wsdisplay_font *font = dc->dc_fontdata;
    458  1.1    rumble 	int from_x, from_y, to_x, to_y;
    459  1.1    rumble 
    460  1.1    rumble 	from_x	= startcol * font->fontwidth;
    461  1.1    rumble 	from_y	= row * font->fontheight;
    462  1.1    rumble 	to_x	= from_x + (ncols * font->fontwidth) - 1;
    463  1.1    rumble 	to_y	= from_y + font->fontheight - 1;
    464  1.1    rumble 
    465  1.1    rumble 	rex_fill_rect(c, from_x, from_y, to_x, to_y, attr);
    466  1.1    rumble }
    467  1.1    rumble 
    468  1.1    rumble /* copy a set of complete rows */
    469  1.1    rumble static void
    470  1.1    rumble light_copyrows(void *c, int srcrow, int dstrow, int nrows)
    471  1.1    rumble {
    472  1.1    rumble 	struct light_devconfig *dc = c;
    473  1.1    rumble 	struct wsdisplay_font *font = dc->dc_fontdata;
    474  1.1    rumble 	int from_x, from_y, to_x, to_y, width, height;
    475  1.1    rumble 
    476  1.1    rumble 	from_x	= 0;
    477  1.1    rumble 	from_y	= srcrow * font->fontheight;
    478  1.1    rumble 	to_x	= 0;
    479  1.1    rumble 	to_y	= dstrow * font->fontheight;
    480  1.1    rumble 	width	= LIGHT_XRES;
    481  1.1    rumble 	height	= nrows * font->fontheight;
    482  1.1    rumble 
    483  1.1    rumble 	rex_copy_rect(c, from_x, from_y, to_x, to_y, width, height);
    484  1.1    rumble }
    485  1.1    rumble 
    486  1.1    rumble /* erase a set of complete rows */
    487  1.1    rumble static void
    488  1.1    rumble light_eraserows(void *c, int row, int nrows, long attr)
    489  1.1    rumble {
    490  1.1    rumble 	struct light_devconfig *dc = c;
    491  1.1    rumble 	struct wsdisplay_font *font = dc->dc_fontdata;
    492  1.1    rumble 	int from_x, from_y, to_x, to_y;
    493  1.1    rumble 
    494  1.1    rumble 	from_x	= 0;
    495  1.1    rumble 	from_y	= row * font->fontheight;
    496  1.1    rumble 	to_x	= LIGHT_XRES - 1;
    497  1.1    rumble 	to_y	= from_y + (nrows * font->fontheight) - 1;
    498  1.1    rumble 
    499  1.1    rumble 	rex_fill_rect(c, from_x, from_y, to_x, to_y, attr);
    500  1.1    rumble }
    501  1.1    rumble 
    502  1.1    rumble static int
    503  1.1    rumble light_allocattr(void *c, int fg, int bg, int flags, long *attr)
    504  1.1    rumble {
    505  1.1    rumble 
    506  1.2    rumble 	if (flags & ~(WSATTR_WSCOLORS | WSATTR_HILIT | WSATTR_REVERSE))
    507  1.1    rumble 		return (EINVAL);
    508  1.1    rumble 
    509  1.1    rumble 	if ((flags & WSATTR_WSCOLORS) == 0) {
    510  1.1    rumble 		fg = WSCOL_WHITE;
    511  1.1    rumble 		bg = WSCOL_BLACK;
    512  1.1    rumble 	}
    513  1.1    rumble 
    514  1.1    rumble 	if (flags & WSATTR_HILIT)
    515  1.1    rumble 		fg += 8;
    516  1.1    rumble 
    517  1.1    rumble 	if (flags & WSATTR_REVERSE) {
    518  1.1    rumble 		int tmp = fg;
    519  1.1    rumble 		fg = bg;
    520  1.1    rumble 		bg = tmp;
    521  1.1    rumble 	}
    522  1.1    rumble 
    523  1.1    rumble 	*attr = LIGHT_ATTR_ENCODE(fg, bg);
    524  1.1    rumble 	return (0);
    525  1.1    rumble }
    526  1.1    rumble 
    527  1.1    rumble /*******************************************************************************
    528  1.1    rumble  * wsdisplay_accessops
    529  1.1    rumble  ******************************************************************************/
    530  1.1    rumble 
    531  1.1    rumble static int
    532  1.5  christos light_ioctl(void *c, void *vs, u_long cmd, void *data, int flag,
    533  1.1    rumble     struct lwp *l)
    534  1.1    rumble {
    535  1.1    rumble 	struct wsdisplay_fbinfo *fbinfo = (struct wsdisplay_fbinfo *)data;
    536  1.1    rumble 
    537  1.1    rumble 	switch (cmd) {
    538  1.1    rumble 	case WSDISPLAYIO_GINFO:
    539  1.1    rumble 		fbinfo->width	= LIGHT_XRES;
    540  1.1    rumble 		fbinfo->height	= LIGHT_YRES;
    541  1.1    rumble 		fbinfo->depth	= LIGHT_DEPTH;
    542  1.1    rumble 		fbinfo->cmsize	= 1 << LIGHT_DEPTH;
    543  1.1    rumble 		return (0);
    544  1.1    rumble 
    545  1.2    rumble 	case WSDISPLAYIO_GMODE:
    546  1.2    rumble 		*(u_int *)data = WSDISPLAYIO_MODE_EMUL;
    547  1.2    rumble 		break;
    548  1.2    rumble 
    549  1.1    rumble 	case WSDISPLAYIO_GTYPE:
    550  1.1    rumble 		*(u_int *)data = WSDISPLAY_TYPE_LIGHT;
    551  1.1    rumble 		return (0);
    552  1.2    rumble 
    553  1.2    rumble 	case WSDISPLAYIO_SVIDEO:
    554  1.2    rumble 		/*
    555  1.2    rumble 		 * Turning off VC1 will stop refreshing the video ram (or so I
    556  1.2    rumble 		 * suspect). We'll blank the screen after bringing it back up,
    557  1.2    rumble 		 * since that's nicer than displaying garbage.
    558  1.2    rumble 		 */
    559  1.2    rumble 		if (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF)
    560  1.2    rumble 			rex_vc1_write(c,rex_vc1_read(c) & ~VC1_SYSCTL_VIDEO_ON);
    561  1.2    rumble 		else {
    562  1.2    rumble 			rex_vc1_write(c, rex_vc1_read(c) | VC1_SYSCTL_VIDEO_ON);
    563  1.2    rumble 			rex_fill_rect(c, 0, 0, LIGHT_XRES-1, LIGHT_YRES-1, 0);
    564  1.2    rumble 		}
    565  1.2    rumble 		return (0);
    566  1.1    rumble 	}
    567  1.1    rumble 
    568  1.1    rumble 	return (EPASSTHROUGH);
    569  1.1    rumble }
    570  1.1    rumble 
    571  1.1    rumble static paddr_t
    572  1.1    rumble light_mmap(void *c, void *vs, off_t off, int prot)
    573  1.1    rumble {
    574  1.2    rumble         struct light_devconfig *dc = c;
    575  1.2    rumble 
    576  1.2    rumble 	if (off >= 0x7fff)
    577  1.2    rumble 		return (-1);
    578  1.2    rumble 
    579  1.2    rumble 	return (mips_btop(dc->dc_addr + off));
    580  1.1    rumble }
    581  1.1    rumble 
    582  1.1    rumble static int
    583  1.1    rumble light_alloc_screen(void *c, const struct wsscreen_descr *type, void **cookiep,
    584  1.1    rumble     int *curxp, int *curyp, long *attr)
    585  1.1    rumble {
    586  1.1    rumble 
    587  1.1    rumble 	return (ENOMEM);
    588  1.1    rumble }
    589  1.1    rumble 
    590  1.1    rumble static void
    591  1.1    rumble light_free_screen(void *c, void *cookie)
    592  1.1    rumble {
    593  1.1    rumble 
    594  1.1    rumble 	panic("light_free_screen");
    595  1.1    rumble }
    596  1.1    rumble 
    597  1.1    rumble static int
    598  1.1    rumble light_show_screen(void *c, void *cookie, int waitok,
    599  1.1    rumble     void (*cb)(void *, int, int), void *cbarg)
    600  1.1    rumble {
    601  1.1    rumble 
    602  1.1    rumble 	return (0);
    603  1.1    rumble }
    604