148104Syokota/*-
248104Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
348104Syokota * All rights reserved.
448104Syokota *
548104Syokota * Redistribution and use in source and binary forms, with or without
648104Syokota * modification, are permitted provided that the following conditions
748104Syokota * are met:
848104Syokota * 1. Redistributions of source code must retain the above copyright
948104Syokota *    notice, this list of conditions and the following disclaimer as
1048104Syokota *    the first lines of this file unmodified.
1148104Syokota * 2. Redistributions in binary form must reproduce the above copyright
1248104Syokota *    notice, this list of conditions and the following disclaimer in the
1348104Syokota *    documentation and/or other materials provided with the distribution.
1448104Syokota *
1548104Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1648104Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1748104Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1848104Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1948104Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2048104Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2148104Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2248104Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2348104Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2448104Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2548104Syokota *
2685810Sobrien * Copyright (c) 2000 Andrew Miklic
2748104Syokota */
2848104Syokota
2985810Sobrien#include <sys/cdefs.h>
3085810Sobrien__FBSDID("$FreeBSD$");
3185810Sobrien
3248104Syokota#include "opt_syscons.h"
3385810Sobrien#include "opt_gfb.h"
34124770Sgrehan#ifdef __powerpc__
35124770Sgrehan#include "opt_ofwfb.h"
36124770Sgrehan#endif
3748104Syokota
3848104Syokota#include <sys/param.h>
3948104Syokota#include <sys/systm.h>
4048104Syokota#include <sys/kernel.h>
4166834Sphk#include <sys/fbio.h>
4266834Sphk#include <sys/consio.h>
4348104Syokota
4465176Sdfr#include <machine/bus.h>
4548104Syokota
4648104Syokota#include <dev/fb/fbreg.h>
4748104Syokota#include <dev/syscons/syscons.h>
4848104Syokota
4948104Syokota#ifndef SC_RENDER_DEBUG
5048104Syokota#define SC_RENDER_DEBUG		0
5148104Syokota#endif
5248104Syokota
5385810Sobrienstatic vr_clear_t		gfb_clear;
5485810Sobrienstatic vr_draw_border_t		gfb_border;
5585810Sobrienstatic vr_draw_t		gfb_draw;
5685810Sobrienstatic vr_set_cursor_t		gfb_cursor_shape;
5785810Sobrienstatic vr_draw_cursor_t		gfb_cursor;
5885810Sobrienstatic vr_blink_cursor_t	gfb_blink;
5948104Syokota#ifndef SC_NO_CUTPASTE
6085810Sobrienstatic vr_draw_mouse_t		gfb_mouse;
6148104Syokota#else
6285810Sobrien#define gfb_mouse		(vr_draw_mouse_t *)gfb_nop
6348104Syokota#endif
6448104Syokota
65147358Speterstatic void			gfb_nop(scr_stat *scp);
6648104Syokota
6785810Sobriensc_rndr_sw_t txtrndrsw = {
68146746Smarius	(vr_init_t *)gfb_nop,
6985810Sobrien	gfb_clear,
7085810Sobrien	gfb_border,
7185810Sobrien	gfb_draw,
7285810Sobrien	gfb_cursor_shape,
7385810Sobrien	gfb_cursor,
7485810Sobrien	gfb_blink,
7585810Sobrien	(vr_set_mouse_t *)gfb_nop,
7685810Sobrien	gfb_mouse,
7748104Syokota};
7848104Syokota
7948104Syokota#ifdef SC_PIXEL_MODE
8085810Sobriensc_rndr_sw_t gfbrndrsw = {
81146746Smarius	(vr_init_t *)gfb_nop,
8285810Sobrien	gfb_clear,
8385810Sobrien	gfb_border,
8485810Sobrien	gfb_draw,
8585810Sobrien	gfb_cursor_shape,
8685810Sobrien	gfb_cursor,
8785810Sobrien	gfb_blink,
8885810Sobrien	(vr_set_mouse_t *)gfb_nop,
8985810Sobrien	gfb_mouse,
9048104Syokota};
9148104Syokota#endif /* SC_PIXEL_MODE */
9248104Syokota
9348104Syokota#ifndef SC_NO_MODE_CHANGE
9485810Sobriensc_rndr_sw_t grrndrsw = {
95146746Smarius	(vr_init_t *)gfb_nop,
9685810Sobrien	(vr_clear_t *)gfb_nop,
9785810Sobrien	gfb_border,
9885810Sobrien	(vr_draw_t *)gfb_nop,
9985810Sobrien	(vr_set_cursor_t *)gfb_nop,
10085810Sobrien	(vr_draw_cursor_t *)gfb_nop,
10185810Sobrien	(vr_blink_cursor_t *)gfb_nop,
10285810Sobrien	(vr_set_mouse_t *)gfb_nop,
10385810Sobrien	(vr_draw_mouse_t *)gfb_nop,
10448104Syokota};
10548104Syokota#endif /* SC_NO_MODE_CHANGE */
10648104Syokota
10785810Sobrien#ifndef SC_NO_CUTPASTE
108170932Smarius#ifdef __sparc64__
109170932Smariusstatic u_char mouse_pointer[22 * 2] = {
110170932Smarius	0x00, 0x00,	/* ............ */
111170932Smarius	0x80, 0x00,	/* *........... */
112170932Smarius	0xc0, 0x00,	/* **.......... */
113170932Smarius	0xe0, 0x00,	/* ***......... */
114170932Smarius	0xf0, 0x00,	/* ****........ */
115170932Smarius	0xf8, 0x00,	/* *****....... */
116170932Smarius	0xfc, 0x00,	/* ******...... */
117170932Smarius	0xfe, 0x00,	/* *******..... */
118170932Smarius	0xff, 0x00,	/* ********.... */
119170932Smarius	0xff, 0x80,	/* *********... */
120170932Smarius	0xfc, 0xc0,	/* ******..**.. */
121170932Smarius	0xdc, 0x00,	/* **.***...... */
122170932Smarius	0x8e, 0x00,	/* *...***..... */
123170932Smarius	0x0e, 0x00,	/* ....***..... */
124170932Smarius	0x07, 0x00,	/* .....***.... */
125170932Smarius	0x04, 0x00,	/* .....*...... */
126170932Smarius	0x00, 0x00,	/* ............ */
127170932Smarius	0x00, 0x00,	/* ............ */
128170932Smarius	0x00, 0x00,	/* ............ */
129170932Smarius	0x00, 0x00,	/* ............ */
130170932Smarius	0x00, 0x00,	/* ............ */
131170932Smarius	0x00, 0x00	/* ............ */
132170932Smarius};
133170932Smarius#else
13485810Sobrienstatic u_char mouse_pointer[16] = {
13585810Sobrien	0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
13685810Sobrien	0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
13748104Syokota};
13848104Syokota#endif
139170932Smarius#endif
14048104Syokota
14148104Syokotastatic void
142147358Spetergfb_nop(scr_stat *scp)
14348104Syokota{
14448104Syokota}
14548104Syokota
14648104Syokota/* text mode renderer */
14748104Syokota
14848104Syokotastatic void
14985810Sobriengfb_clear(scr_stat *scp, int c, int attr)
15048104Syokota{
151174985Swkoszek	vidd_clear(scp->sc->adp);
15248104Syokota}
15348104Syokota
15448104Syokotastatic void
15585810Sobriengfb_border(scr_stat *scp, int color)
15648104Syokota{
157174985Swkoszek	vidd_set_border(scp->sc->adp, color);
15848104Syokota}
15948104Syokota
16048104Syokotastatic void
16185810Sobriengfb_draw(scr_stat *scp, int from, int count, int flip)
16248104Syokota{
163119383Sjake	int c;
164119383Sjake	int a;
16585810Sobrien	int i, n;
16685810Sobrien	video_adapter_t *adp;
16748104Syokota
16885810Sobrien	adp = scp->sc->adp;
16948104Syokota
17085810Sobrien	/*
17185810Sobrien	   Determine if we need to scroll based on the offset
17285810Sobrien	   and the number of characters to be displayed...
17385810Sobrien	 */
17485810Sobrien	if (from + count > scp->xsize*scp->ysize) {
17585810Sobrien
17685810Sobrien		/*
17785810Sobrien		   Calculate the number of characters past the end of the
17885810Sobrien		   visible screen...
17985810Sobrien		*/
18085810Sobrien		count = (from + count) -
18185810Sobrien		    (adp->va_info.vi_width * adp->va_info.vi_height);
18285810Sobrien
18385810Sobrien		/*
18485810Sobrien		   Calculate the number of rows past the end of the visible
18585810Sobrien		   screen...
18685810Sobrien		*/
18785810Sobrien		n = (count / adp->va_info.vi_width) + 1;
18885810Sobrien
18985810Sobrien		/* Scroll to make room for new text rows... */
190174985Swkoszek		vidd_copy(adp, n, 0, n);
19190664Sgallatin#if 0
192174985Swkoszek		vidd_clear(adp, n);
19385810Sobrien#endif
19485810Sobrien
19585810Sobrien		/* Display new text rows... */
196174985Swkoszek		vidd_puts(adp, from,
19785810Sobrien		    (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
19885810Sobrien	}
19985810Sobrien
20085810Sobrien	/*
20185810Sobrien	   We don't need to scroll, so we can just put the characters
20285810Sobrien	   all-at-once...
20385810Sobrien	*/
20485810Sobrien	else {
20585810Sobrien
20685810Sobrien		/*
20785810Sobrien		   Determine the method by which we are to display characters
20885810Sobrien		   (are we going to print forwards or backwards?
20985810Sobrien		   do we need to do a character-by-character copy, then?)...
21085810Sobrien		*/
21185810Sobrien		if (flip)
21285810Sobrien			for (i = count; i-- > 0; ++from) {
21385810Sobrien				c = sc_vtb_getc(&scp->vtb, from);
21485810Sobrien				a = sc_vtb_geta(&scp->vtb, from) >> 8;
215174985Swkoszek				vidd_putc(adp, from, c,
216119383Sjake				    (a >> 4) | ((a & 0xf) << 4));
21785810Sobrien			}
21885810Sobrien		else {
219174985Swkoszek			vidd_puts(adp, from,
22085810Sobrien			    (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
22185810Sobrien			    count);
22248104Syokota		}
22348104Syokota	}
22448104Syokota}
22548104Syokota
22648104Syokotastatic void
22785810Sobriengfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
22848104Syokota{
22948104Syokota	if (base < 0 || base >= scp->font_size)
23048104Syokota		return;
23148104Syokota	/* the caller may set height <= 0 in order to disable the cursor */
23248104Syokota#if 0
23385810Sobrien	scp->cursor_base = base;
23485810Sobrien	scp->cursor_height = height;
23548104Syokota#endif
236174985Swkoszek	vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
237174985Swkoszek	    blink);
23848104Syokota}
23948104Syokota
24085810Sobrienstatic int pxlblinkrate = 0;
24158872Syokota
242146472Smarius#if defined(__sparc64__) || defined(SC_OFWFB)
24358872Syokotastatic void
24485810Sobriengfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
24548104Syokota{
24648104Syokota	video_adapter_t *adp;
247119383Sjake	int a, c;
24848104Syokota
249119383Sjake	if (scp->curs_attr.height <= 0)	/* the text cursor is disabled */
25048104Syokota		return;
25148104Syokota
25248104Syokota	adp = scp->sc->adp;
25385810Sobrien	if(blink) {
25448104Syokota		scp->status |= VR_CURSOR_BLINK;
25548104Syokota		if (on) {
25648104Syokota			scp->status |= VR_CURSOR_ON;
257174985Swkoszek			vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
25848104Syokota		} else {
25948104Syokota			if (scp->status & VR_CURSOR_ON)
260174985Swkoszek				vidd_set_hw_cursor(adp, -1, -1);
26148104Syokota			scp->status &= ~VR_CURSOR_ON;
26248104Syokota		}
26348104Syokota	} else {
26448104Syokota		scp->status &= ~VR_CURSOR_BLINK;
26585810Sobrien		if(on) {
26648104Syokota			scp->status |= VR_CURSOR_ON;
267174985Swkoszek			vidd_putc(scp->sc->adp, scp->cursor_oldpos,
268119383Sjake			    sc_vtb_getc(&scp->vtb, scp->cursor_oldpos),
269119383Sjake			    sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8);
270119383Sjake			a = sc_vtb_geta(&scp->vtb, at) >> 8;
271119383Sjake			c = sc_vtb_getc(&scp->vtb, at);
272174985Swkoszek			vidd_putc(scp->sc->adp, at, c,
273174985Swkoszek			    (a >> 4) | ((a & 0xf) << 4));
274119383Sjake			scp->cursor_saveunder_attr = a;
275119383Sjake			scp->cursor_saveunder_char = c;
27648104Syokota		} else {
27748104Syokota			if (scp->status & VR_CURSOR_ON)
278174985Swkoszek				vidd_putc(scp->sc->adp, at,
279174985Swkoszek				    scp->cursor_saveunder_char,
28085810Sobrien				    scp->cursor_saveunder_attr);
28148104Syokota			scp->status &= ~VR_CURSOR_ON;
28248104Syokota		}
28348104Syokota	}
28448104Syokota}
285119383Sjake#else
28648104Syokotastatic void
28785810Sobriengfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
28848104Syokota{
28985810Sobrien	video_adapter_t *adp;
29048104Syokota
29185810Sobrien	adp = scp->sc->adp;
29294617Sobrien	if (scp->curs_attr.height <= 0)
29394617Sobrien		/* the text cursor is disabled */
29448104Syokota		return;
29548104Syokota
29648104Syokota	if (on) {
29758232Syokota		if (!blink) {
29858232Syokota			scp->status |= VR_CURSOR_ON;
299174985Swkoszek			vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
30058232Syokota		} else if (++pxlblinkrate & 4) {
30158232Syokota			pxlblinkrate = 0;
30258232Syokota			scp->status ^= VR_CURSOR_ON;
30385810Sobrien			if(scp->status & VR_CURSOR_ON)
304174985Swkoszek				vidd_set_hw_cursor(adp, at%scp->xsize,
305174985Swkoszek				    at/scp->xsize);
30685810Sobrien			else
307174985Swkoszek				vidd_set_hw_cursor(adp, -1, -1);
30858232Syokota		}
30948104Syokota	} else {
31048104Syokota		if (scp->status & VR_CURSOR_ON)
311174985Swkoszek			vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
31248104Syokota		scp->status &= ~VR_CURSOR_ON;
31348104Syokota	}
31448104Syokota	if (blink)
31548104Syokota		scp->status |= VR_CURSOR_BLINK;
31648104Syokota	else
31748104Syokota		scp->status &= ~VR_CURSOR_BLINK;
31848104Syokota}
319119383Sjake#endif
32048104Syokota
32148104Syokotastatic void
32285810Sobriengfb_blink(scr_stat *scp, int at, int flip)
32348104Syokota{
32448104Syokota	if (!(scp->status & VR_CURSOR_BLINK))
32548104Syokota		return;
32658232Syokota	if (!(++pxlblinkrate & 4))
32748104Syokota		return;
32858232Syokota	pxlblinkrate = 0;
32948104Syokota	scp->status ^= VR_CURSOR_ON;
33085810Sobrien	gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
33185810Sobrien	    scp->status & VR_CURSOR_ON, flip);
33248104Syokota}
33348104Syokota
33448104Syokota#ifndef SC_NO_CUTPASTE
33548104Syokota
33685810Sobrienstatic void
33785810Sobriengfb_mouse(scr_stat *scp, int x, int y, int on)
33848104Syokota{
339170932Smarius#ifdef __sparc64__
340174985Swkoszek		vidd_putm(scp->sc->adp, x, y, mouse_pointer,
341174985Swkoszek		    on ? 0xffffffff : 0x0, 22, 12);
342170932Smarius#else
34385810Sobrien	int i, pos;
34448104Syokota
34585810Sobrien	if (on) {
34648104Syokota
34785810Sobrien		/* Display the mouse pointer image... */
348174985Swkoszek		vidd_putm(scp->sc->adp, x, y, mouse_pointer,
349174985Swkoszek		    0xffffffff, 16, 8);
35048104Syokota	} else {
35148104Syokota
35285810Sobrien		/*
35385810Sobrien		   Erase the mouse cursor image by redrawing the text
35485810Sobrien		   underneath it...
35585810Sobrien		*/
35685810Sobrien		return;
35785810Sobrien		pos = x*scp->xsize + y;
35885810Sobrien		i = (y < scp->xsize - 1) ? 2 : 1;
35985810Sobrien		(*scp->rndr->draw)(scp, pos, i, FALSE);
36085810Sobrien		if (x < scp->ysize - 1)
36185810Sobrien			(*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
36248104Syokota	}
363170932Smarius#endif
36448104Syokota}
36548104Syokota
36648104Syokota#endif /* SC_NO_CUTPASTE */
367