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 *
2648104Syokota */
2748104Syokota
28119420Sobrien#include <sys/cdefs.h>
29119420Sobrien__FBSDID("$FreeBSD$");
30119420Sobrien
3148104Syokota#include "opt_syscons.h"
3248104Syokota
3348104Syokota#include <sys/param.h>
3448104Syokota#include <sys/systm.h>
3548104Syokota#include <sys/malloc.h>
3666834Sphk#include <sys/fbio.h>
3766834Sphk#include <sys/consio.h>
3848104Syokota
3948104Syokota#include <machine/md_var.h>
4065176Sdfr#include <machine/bus.h>
4148104Syokota
4248104Syokota#include <dev/fb/fbreg.h>
4348104Syokota#include <dev/syscons/syscons.h>
4448104Syokota
4548104Syokota#define vtb_wrap(vtb, at, offset)				\
4648104Syokota    (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size)
4748104Syokota
4848104Syokotavoid
4948104Syokotasc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait)
5048104Syokota{
5148104Syokota	vtb->vtb_flags = 0;
5248104Syokota	vtb->vtb_type = type;
5348104Syokota	vtb->vtb_cols = cols;
5448104Syokota	vtb->vtb_rows = rows;
5548104Syokota	vtb->vtb_size = cols*rows;
56102241Sarchie	vtb->vtb_buffer = 0;
5748104Syokota	vtb->vtb_tail = 0;
5848104Syokota
5948104Syokota	switch (type) {
6048104Syokota	case VTB_MEMORY:
6148104Syokota	case VTB_RINGBUFFER:
6248104Syokota		if ((buf == NULL) && (cols*rows != 0)) {
6348104Syokota			vtb->vtb_buffer =
6448104Syokota				(vm_offset_t)malloc(cols*rows*sizeof(u_int16_t),
6548104Syokota						    M_DEVBUF,
66111119Simp						    (wait) ? M_WAITOK : M_NOWAIT);
67102241Sarchie			if (vtb->vtb_buffer != 0) {
6848104Syokota				bzero((void *)sc_vtb_pointer(vtb, 0),
6948104Syokota				      cols*rows*sizeof(u_int16_t));
7078956Syokota				vtb->vtb_flags |= VTB_ALLOCED;
7178956Syokota			}
7248104Syokota		} else {
7348104Syokota			vtb->vtb_buffer = (vm_offset_t)buf;
7448104Syokota		}
7548104Syokota		vtb->vtb_flags |= VTB_VALID;
7648104Syokota		break;
77146476Smarius#ifndef __sparc64__
7848104Syokota	case VTB_FRAMEBUFFER:
7948104Syokota		vtb->vtb_buffer = (vm_offset_t)buf;
8048104Syokota		vtb->vtb_flags |= VTB_VALID;
8148104Syokota		break;
82146476Smarius#endif
8348104Syokota	default:
8448104Syokota		break;
8548104Syokota	}
8648104Syokota}
8748104Syokota
8848104Syokotavoid
8948104Syokotasc_vtb_destroy(sc_vtb_t *vtb)
9048104Syokota{
9148104Syokota	vm_offset_t p;
9248104Syokota
9348104Syokota	vtb->vtb_cols = 0;
9448104Syokota	vtb->vtb_rows = 0;
9548104Syokota	vtb->vtb_size = 0;
9648104Syokota	vtb->vtb_tail = 0;
9748104Syokota
9848104Syokota	p = vtb->vtb_buffer;
99102241Sarchie	vtb->vtb_buffer = 0;
10048104Syokota	switch (vtb->vtb_type) {
10148104Syokota	case VTB_MEMORY:
10248104Syokota	case VTB_RINGBUFFER:
103102241Sarchie		if ((vtb->vtb_flags & VTB_ALLOCED) && (p != 0))
10448104Syokota			free((void *)p, M_DEVBUF);
10548104Syokota		break;
10648104Syokota	default:
10748104Syokota		break;
10848104Syokota	}
10978956Syokota	vtb->vtb_flags = 0;
11048104Syokota	vtb->vtb_type = VTB_INVALID;
11148104Syokota}
11248104Syokota
11348104Syokotasize_t
11448104Syokotasc_vtb_size(int cols, int rows)
11548104Syokota{
11648104Syokota	return (size_t)(cols*rows*sizeof(u_int16_t));
11748104Syokota}
11848104Syokota
11948104Syokotaint
12048104Syokotasc_vtb_getc(sc_vtb_t *vtb, int at)
12148104Syokota{
122146476Smarius#ifndef __sparc64__
12348104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
12448104Syokota		return (readw(sc_vtb_pointer(vtb, at)) & 0x00ff);
12548104Syokota	else
126146476Smarius#endif
12748104Syokota		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0x00ff);
12848104Syokota}
12948104Syokota
13048104Syokotaint
13148104Syokotasc_vtb_geta(sc_vtb_t *vtb, int at)
13248104Syokota{
133146476Smarius#ifndef __sparc64__
13448104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
13548104Syokota		return (readw(sc_vtb_pointer(vtb, at)) & 0xff00);
13648104Syokota	else
137146476Smarius#endif
13848104Syokota		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0xff00);
13948104Syokota}
14048104Syokota
14148104Syokotavoid
14248104Syokotasc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
14348104Syokota{
144146476Smarius#ifndef __sparc64__
14548104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
14648104Syokota		writew(sc_vtb_pointer(vtb, at), a | c);
14748104Syokota	else
148146476Smarius#endif
14948104Syokota		*(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c;
15048104Syokota}
15148104Syokota
15248104Syokotavm_offset_t
15348104Syokotasc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
15448104Syokota{
155146476Smarius#ifndef __sparc64__
15648104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
15748104Syokota		writew(p, a | c);
15848104Syokota	else
159146476Smarius#endif
16048104Syokota		*(u_int16_t *)p = a | c;
16148104Syokota	return (p + sizeof(u_int16_t));
16248104Syokota}
16348104Syokota
16448104Syokotavm_offset_t
16548104Syokotasc_vtb_pointer(sc_vtb_t *vtb, int at)
16648104Syokota{
16748104Syokota	return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
16848104Syokota}
16948104Syokota
17048104Syokotaint
17148104Syokotasc_vtb_pos(sc_vtb_t *vtb, int pos, int offset)
17248104Syokota{
17348104Syokota	return ((pos + offset + vtb->vtb_size)%vtb->vtb_size);
17448104Syokota}
17548104Syokota
17648104Syokotavoid
17748104Syokotasc_vtb_clear(sc_vtb_t *vtb, int c, int attr)
17848104Syokota{
179146476Smarius#ifndef __sparc64__
18048104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
18148104Syokota		fillw_io(attr | c, sc_vtb_pointer(vtb, 0), vtb->vtb_size);
18248104Syokota	else
183146476Smarius#endif
18448104Syokota		fillw(attr | c, (void *)sc_vtb_pointer(vtb, 0), vtb->vtb_size);
18548104Syokota}
18648104Syokota
18748104Syokotavoid
18848104Syokotasc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count)
18948104Syokota{
190146476Smarius#ifndef __sparc64__
19148104Syokota	/* XXX if both are VTB_VRAMEBUFFER... */
192146476Smarius	if (vtb2->vtb_type == VTB_FRAMEBUFFER)
19348104Syokota		bcopy_toio(sc_vtb_pointer(vtb1, from),
19448104Syokota			   sc_vtb_pointer(vtb2, to),
19548104Syokota			   count*sizeof(u_int16_t));
196146476Smarius	else if (vtb1->vtb_type == VTB_FRAMEBUFFER)
19748104Syokota		bcopy_fromio(sc_vtb_pointer(vtb1, from),
19848104Syokota			     sc_vtb_pointer(vtb2, to),
19948104Syokota			     count*sizeof(u_int16_t));
200146476Smarius	else
201146476Smarius#endif
20248104Syokota		bcopy((void *)sc_vtb_pointer(vtb1, from),
20348104Syokota		      (void *)sc_vtb_pointer(vtb2, to),
20448104Syokota		      count*sizeof(u_int16_t));
20548104Syokota}
20648104Syokota
20748104Syokotavoid
20848104Syokotasc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count)
20948104Syokota{
21048104Syokota	int len;
21148104Syokota
21248104Syokota	if (vtb2->vtb_type != VTB_RINGBUFFER)
21348104Syokota		return;
21448104Syokota
21548104Syokota	while (count > 0) {
21648104Syokota		len = imin(count, vtb2->vtb_size - vtb2->vtb_tail);
217146476Smarius#ifndef __sparc64__
218146476Smarius		if (vtb1->vtb_type == VTB_FRAMEBUFFER)
21948104Syokota			bcopy_fromio(sc_vtb_pointer(vtb1, from),
22048104Syokota				     sc_vtb_pointer(vtb2, vtb2->vtb_tail),
22148104Syokota				     len*sizeof(u_int16_t));
222146476Smarius		else
223146476Smarius#endif
22448104Syokota			bcopy((void *)sc_vtb_pointer(vtb1, from),
22548104Syokota			      (void *)sc_vtb_pointer(vtb2, vtb2->vtb_tail),
22648104Syokota			      len*sizeof(u_int16_t));
22748104Syokota		from += len;
22848104Syokota		count -= len;
22948104Syokota		vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len);
23048104Syokota	}
23148104Syokota}
23248104Syokota
23348104Syokotavoid
23448104Syokotasc_vtb_seek(sc_vtb_t *vtb, int pos)
23548104Syokota{
23648104Syokota	vtb->vtb_tail = pos%vtb->vtb_size;
23748104Syokota}
23848104Syokota
23948104Syokotavoid
24048104Syokotasc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr)
24148104Syokota{
24248104Syokota	if (at + count > vtb->vtb_size)
24348104Syokota		count = vtb->vtb_size - at;
244146476Smarius#ifndef __sparc64__
24548104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
24648104Syokota		fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
24748104Syokota	else
248146476Smarius#endif
24948104Syokota		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
25048104Syokota}
25148104Syokota
25248104Syokotavoid
25348189Syokotasc_vtb_move(sc_vtb_t *vtb, int from, int to, int count)
25448189Syokota{
25548189Syokota	if (from + count > vtb->vtb_size)
25648189Syokota		count = vtb->vtb_size - from;
25748189Syokota	if (to + count > vtb->vtb_size)
25848189Syokota		count = vtb->vtb_size - to;
25948189Syokota	if (count <= 0)
26048189Syokota		return;
261146476Smarius#ifndef __sparc64__
262146476Smarius	if (vtb->vtb_type == VTB_FRAMEBUFFER)
26348189Syokota		bcopy_io(sc_vtb_pointer(vtb, from),
26448189Syokota			 sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
265146476Smarius	else
266146476Smarius#endif
26748189Syokota		bcopy((void *)sc_vtb_pointer(vtb, from),
26848189Syokota		      (void *)sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
26948189Syokota}
27048189Syokota
27148189Syokotavoid
27248104Syokotasc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr)
27348104Syokota{
27448104Syokota	int len;
27548104Syokota
27648104Syokota	if (at + count > vtb->vtb_size)
27748104Syokota		count = vtb->vtb_size - at;
27848104Syokota	len = vtb->vtb_size - at - count;
27948104Syokota	if (len > 0) {
280146476Smarius#ifndef __sparc64__
281146476Smarius		if (vtb->vtb_type == VTB_FRAMEBUFFER)
28248104Syokota			bcopy_io(sc_vtb_pointer(vtb, at + count),
28348104Syokota				 sc_vtb_pointer(vtb, at),
28448104Syokota				 len*sizeof(u_int16_t));
285146476Smarius		else
286146476Smarius#endif
28748104Syokota			bcopy((void *)sc_vtb_pointer(vtb, at + count),
28848104Syokota			      (void *)sc_vtb_pointer(vtb, at),
28948104Syokota			      len*sizeof(u_int16_t));
29048104Syokota	}
291146476Smarius#ifndef __sparc64__
29248104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
29348104Syokota		fillw_io(attr | c, sc_vtb_pointer(vtb, at + len),
29448104Syokota			 vtb->vtb_size - at - len);
29548104Syokota	else
296146476Smarius#endif
29748104Syokota		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at + len),
29848104Syokota		      vtb->vtb_size - at - len);
29948104Syokota}
30048104Syokota
30148104Syokotavoid
30248104Syokotasc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr)
30348104Syokota{
304146476Smarius	if (at + count > vtb->vtb_size)
30548104Syokota		count = vtb->vtb_size - at;
306146476Smarius	else {
307146476Smarius#ifndef __sparc64__
308146476Smarius		if (vtb->vtb_type == VTB_FRAMEBUFFER)
30948104Syokota			bcopy_io(sc_vtb_pointer(vtb, at),
31048104Syokota				 sc_vtb_pointer(vtb, at + count),
31148104Syokota				 (vtb->vtb_size - at - count)*sizeof(u_int16_t));
312146476Smarius		else
313146476Smarius#endif
31448104Syokota			bcopy((void *)sc_vtb_pointer(vtb, at),
31548104Syokota			      (void *)sc_vtb_pointer(vtb, at + count),
31648104Syokota			      (vtb->vtb_size - at - count)*sizeof(u_int16_t));
31748104Syokota	}
318146476Smarius#ifndef __sparc64__
31948104Syokota	if (vtb->vtb_type == VTB_FRAMEBUFFER)
32048104Syokota		fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
32148104Syokota	else
322146476Smarius#endif
32348104Syokota		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
32448104Syokota}
325