1/*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer as
10 *    the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD$");
30
31#include "opt_syscons.h"
32
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/fbio.h>
37#include <sys/consio.h>
38
39#include <machine/md_var.h>
40#include <machine/bus.h>
41
42#include <dev/fb/fbreg.h>
43#include <dev/syscons/syscons.h>
44
45#define vtb_wrap(vtb, at, offset)				\
46    (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size)
47
48void
49sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait)
50{
51	vtb->vtb_flags = 0;
52	vtb->vtb_type = type;
53	vtb->vtb_cols = cols;
54	vtb->vtb_rows = rows;
55	vtb->vtb_size = cols*rows;
56	vtb->vtb_buffer = 0;
57	vtb->vtb_tail = 0;
58
59	switch (type) {
60	case VTB_MEMORY:
61	case VTB_RINGBUFFER:
62		if ((buf == NULL) && (cols*rows != 0)) {
63			vtb->vtb_buffer =
64				(vm_offset_t)malloc(cols*rows*sizeof(u_int16_t),
65						    M_DEVBUF,
66						    (wait) ? M_WAITOK : M_NOWAIT);
67			if (vtb->vtb_buffer != 0) {
68				bzero((void *)sc_vtb_pointer(vtb, 0),
69				      cols*rows*sizeof(u_int16_t));
70				vtb->vtb_flags |= VTB_ALLOCED;
71			}
72		} else {
73			vtb->vtb_buffer = (vm_offset_t)buf;
74		}
75		vtb->vtb_flags |= VTB_VALID;
76		break;
77#ifndef __sparc64__
78	case VTB_FRAMEBUFFER:
79		vtb->vtb_buffer = (vm_offset_t)buf;
80		vtb->vtb_flags |= VTB_VALID;
81		break;
82#endif
83	default:
84		break;
85	}
86}
87
88void
89sc_vtb_destroy(sc_vtb_t *vtb)
90{
91	vm_offset_t p;
92
93	vtb->vtb_cols = 0;
94	vtb->vtb_rows = 0;
95	vtb->vtb_size = 0;
96	vtb->vtb_tail = 0;
97
98	p = vtb->vtb_buffer;
99	vtb->vtb_buffer = 0;
100	switch (vtb->vtb_type) {
101	case VTB_MEMORY:
102	case VTB_RINGBUFFER:
103		if ((vtb->vtb_flags & VTB_ALLOCED) && (p != 0))
104			free((void *)p, M_DEVBUF);
105		break;
106	default:
107		break;
108	}
109	vtb->vtb_flags = 0;
110	vtb->vtb_type = VTB_INVALID;
111}
112
113size_t
114sc_vtb_size(int cols, int rows)
115{
116	return (size_t)(cols*rows*sizeof(u_int16_t));
117}
118
119int
120sc_vtb_getc(sc_vtb_t *vtb, int at)
121{
122#ifndef __sparc64__
123	if (vtb->vtb_type == VTB_FRAMEBUFFER)
124		return (readw(sc_vtb_pointer(vtb, at)) & 0x00ff);
125	else
126#endif
127		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0x00ff);
128}
129
130int
131sc_vtb_geta(sc_vtb_t *vtb, int at)
132{
133#ifndef __sparc64__
134	if (vtb->vtb_type == VTB_FRAMEBUFFER)
135		return (readw(sc_vtb_pointer(vtb, at)) & 0xff00);
136	else
137#endif
138		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0xff00);
139}
140
141void
142sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
143{
144#ifndef __sparc64__
145	if (vtb->vtb_type == VTB_FRAMEBUFFER)
146		writew(sc_vtb_pointer(vtb, at), a | c);
147	else
148#endif
149		*(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c;
150}
151
152vm_offset_t
153sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
154{
155#ifndef __sparc64__
156	if (vtb->vtb_type == VTB_FRAMEBUFFER)
157		writew(p, a | c);
158	else
159#endif
160		*(u_int16_t *)p = a | c;
161	return (p + sizeof(u_int16_t));
162}
163
164vm_offset_t
165sc_vtb_pointer(sc_vtb_t *vtb, int at)
166{
167	return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
168}
169
170int
171sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset)
172{
173	return ((pos + offset + vtb->vtb_size)%vtb->vtb_size);
174}
175
176void
177sc_vtb_clear(sc_vtb_t *vtb, int c, int attr)
178{
179#ifndef __sparc64__
180	if (vtb->vtb_type == VTB_FRAMEBUFFER)
181		fillw_io(attr | c, sc_vtb_pointer(vtb, 0), vtb->vtb_size);
182	else
183#endif
184		fillw(attr | c, (void *)sc_vtb_pointer(vtb, 0), vtb->vtb_size);
185}
186
187void
188sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count)
189{
190#ifndef __sparc64__
191	/* XXX if both are VTB_VRAMEBUFFER... */
192	if (vtb2->vtb_type == VTB_FRAMEBUFFER)
193		bcopy_toio(sc_vtb_pointer(vtb1, from),
194			   sc_vtb_pointer(vtb2, to),
195			   count*sizeof(u_int16_t));
196	else if (vtb1->vtb_type == VTB_FRAMEBUFFER)
197		bcopy_fromio(sc_vtb_pointer(vtb1, from),
198			     sc_vtb_pointer(vtb2, to),
199			     count*sizeof(u_int16_t));
200	else
201#endif
202		bcopy((void *)sc_vtb_pointer(vtb1, from),
203		      (void *)sc_vtb_pointer(vtb2, to),
204		      count*sizeof(u_int16_t));
205}
206
207void
208sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count)
209{
210	int len;
211
212	if (vtb2->vtb_type != VTB_RINGBUFFER)
213		return;
214
215	while (count > 0) {
216		len = imin(count, vtb2->vtb_size - vtb2->vtb_tail);
217#ifndef __sparc64__
218		if (vtb1->vtb_type == VTB_FRAMEBUFFER)
219			bcopy_fromio(sc_vtb_pointer(vtb1, from),
220				     sc_vtb_pointer(vtb2, vtb2->vtb_tail),
221				     len*sizeof(u_int16_t));
222		else
223#endif
224			bcopy((void *)sc_vtb_pointer(vtb1, from),
225			      (void *)sc_vtb_pointer(vtb2, vtb2->vtb_tail),
226			      len*sizeof(u_int16_t));
227		from += len;
228		count -= len;
229		vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len);
230	}
231}
232
233void
234sc_vtb_seek(sc_vtb_t *vtb, int pos)
235{
236	vtb->vtb_tail = pos%vtb->vtb_size;
237}
238
239void
240sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr)
241{
242	if (at + count > vtb->vtb_size)
243		count = vtb->vtb_size - at;
244#ifndef __sparc64__
245	if (vtb->vtb_type == VTB_FRAMEBUFFER)
246		fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
247	else
248#endif
249		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
250}
251
252void
253sc_vtb_move(sc_vtb_t *vtb, int from, int to, int count)
254{
255	if (from + count > vtb->vtb_size)
256		count = vtb->vtb_size - from;
257	if (to + count > vtb->vtb_size)
258		count = vtb->vtb_size - to;
259	if (count <= 0)
260		return;
261#ifndef __sparc64__
262	if (vtb->vtb_type == VTB_FRAMEBUFFER)
263		bcopy_io(sc_vtb_pointer(vtb, from),
264			 sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
265	else
266#endif
267		bcopy((void *)sc_vtb_pointer(vtb, from),
268		      (void *)sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
269}
270
271void
272sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr)
273{
274	int len;
275
276	if (at + count > vtb->vtb_size)
277		count = vtb->vtb_size - at;
278	len = vtb->vtb_size - at - count;
279	if (len > 0) {
280#ifndef __sparc64__
281		if (vtb->vtb_type == VTB_FRAMEBUFFER)
282			bcopy_io(sc_vtb_pointer(vtb, at + count),
283				 sc_vtb_pointer(vtb, at),
284				 len*sizeof(u_int16_t));
285		else
286#endif
287			bcopy((void *)sc_vtb_pointer(vtb, at + count),
288			      (void *)sc_vtb_pointer(vtb, at),
289			      len*sizeof(u_int16_t));
290	}
291#ifndef __sparc64__
292	if (vtb->vtb_type == VTB_FRAMEBUFFER)
293		fillw_io(attr | c, sc_vtb_pointer(vtb, at + len),
294			 vtb->vtb_size - at - len);
295	else
296#endif
297		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at + len),
298		      vtb->vtb_size - at - len);
299}
300
301void
302sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr)
303{
304	if (at + count > vtb->vtb_size)
305		count = vtb->vtb_size - at;
306	else {
307#ifndef __sparc64__
308		if (vtb->vtb_type == VTB_FRAMEBUFFER)
309			bcopy_io(sc_vtb_pointer(vtb, at),
310				 sc_vtb_pointer(vtb, at + count),
311				 (vtb->vtb_size - at - count)*sizeof(u_int16_t));
312		else
313#endif
314			bcopy((void *)sc_vtb_pointer(vtb, at),
315			      (void *)sc_vtb_pointer(vtb, at + count),
316			      (vtb->vtb_size - at - count)*sizeof(u_int16_t));
317	}
318#ifndef __sparc64__
319	if (vtb->vtb_type == VTB_FRAMEBUFFER)
320		fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
321	else
322#endif
323		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
324}
325