scvtb.c revision 55391
1/*-
2 * Copyright (c) 1999 FreeBSD(98) Porting Team.
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 * $FreeBSD: head/sys/pc98/cbus/scvtb.c 55391 2000-01-04 04:46:50Z nyan $
27 */
28
29#include "sc.h"
30#include "opt_syscons.h"
31
32#if NSC > 0
33
34#include <sys/param.h>
35#include <sys/systm.h>
36#include <sys/malloc.h>
37
38#include <machine/console.h>
39#include <machine/md_var.h>
40
41#include <dev/fb/fbreg.h>
42#include <dev/syscons/syscons.h>
43
44#define ATTR_OFFSET	0x2000
45
46#define vtb_wrap(vtb, at, offset)				\
47    (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size)
48
49static u_int16_t	at2pc98(u_int16_t attr);
50static vm_offset_t	sc_vtb_attr_pointer(sc_vtb_t *vtb, int at);
51
52static u_int16_t
53at2pc98(u_int16_t attr)
54{
55	static u_char ibmpc_to_pc98[16] = {
56		0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1,
57		0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9
58	};
59	static u_char ibmpc_to_pc98rev[16] = {
60		0x05, 0x25, 0x85, 0xa5, 0x45, 0x65, 0xc5, 0xe5,
61		0x0d, 0x2d, 0x8d, 0xad, 0x4d, 0x6d, 0xcd, 0xed
62	};
63	u_char fg_at, bg_at;
64	u_int16_t at;
65
66	if (attr & 0x00FF)
67		return (attr);
68
69	fg_at = ((attr >> 8) & 0x0F);
70	bg_at = ((attr >> 12) & 0x0F);
71
72	if (bg_at) {
73		if (bg_at & 0x08) {
74			if (bg_at & 0x07) {
75				/* reverse & blink */
76				at = ibmpc_to_pc98rev[bg_at] | 0x02;
77			} else {
78				/* normal & blink */
79				at = ibmpc_to_pc98[fg_at] | 0x02;
80			}
81		} else {
82			/* reverse */
83			at = ibmpc_to_pc98rev[bg_at];
84		}
85	} else {
86		/* normal */
87		at = ibmpc_to_pc98[fg_at];
88	}
89	at |= attr;
90	return (at);
91}
92
93void
94sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait)
95{
96	vtb->vtb_flags = 0;
97	vtb->vtb_type = type;
98	vtb->vtb_cols = cols;
99	vtb->vtb_rows = rows;
100	vtb->vtb_size = cols*rows;
101	vtb->vtb_buffer = NULL;
102	vtb->vtb_tail = 0;
103
104	switch (type) {
105	case VTB_MEMORY:
106	case VTB_RINGBUFFER:
107		if ((buf == NULL) && (cols*rows != 0)) {
108			vtb->vtb_buffer =
109				(vm_offset_t)malloc(cols*rows*sizeof(u_int16_t)*2,
110						    M_DEVBUF,
111						    (wait) ? M_WAITOK : M_NOWAIT);
112			if (vtb->vtb_buffer != NULL) {
113				bzero((void *)sc_vtb_pointer(vtb, 0),
114				      cols*rows*sizeof(u_int16_t)*2);
115			}
116		} else {
117			vtb->vtb_buffer = (vm_offset_t)buf;
118		}
119		vtb->vtb_flags |= VTB_VALID;
120		break;
121	case VTB_FRAMEBUFFER:
122		vtb->vtb_buffer = (vm_offset_t)buf;
123		vtb->vtb_flags |= VTB_VALID;
124		break;
125	default:
126		break;
127	}
128}
129
130void
131sc_vtb_destroy(sc_vtb_t *vtb)
132{
133	vm_offset_t p;
134
135	vtb->vtb_flags = 0;
136	vtb->vtb_cols = 0;
137	vtb->vtb_rows = 0;
138	vtb->vtb_size = 0;
139	vtb->vtb_tail = 0;
140
141	p = vtb->vtb_buffer;
142	vtb->vtb_buffer = NULL;
143	switch (vtb->vtb_type) {
144	case VTB_MEMORY:
145	case VTB_RINGBUFFER:
146		if (p != NULL)
147			free((void *)p, M_DEVBUF);
148		break;
149	default:
150		break;
151	}
152	vtb->vtb_type = VTB_INVALID;
153}
154
155size_t
156sc_vtb_size(int cols, int rows)
157{
158	return (size_t)(cols*rows*sizeof(u_int16_t)*2);
159}
160
161int
162sc_vtb_getc(sc_vtb_t *vtb, int at)
163{
164	if (vtb->vtb_type == VTB_FRAMEBUFFER)
165		return (readw(sc_vtb_pointer(vtb, at)) & 0x00ff);
166	else
167		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0x00ff);
168}
169
170int
171sc_vtb_geta(sc_vtb_t *vtb, int at)
172{
173	if (vtb->vtb_type == VTB_FRAMEBUFFER)
174		return (readw(sc_vtb_attr_pointer(vtb, at)) & 0x00ff);
175	else
176		return (*(u_int16_t *)sc_vtb_attr_pointer(vtb, at) & 0x00ff);
177}
178
179void
180sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
181{
182	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
183		writew(sc_vtb_pointer(vtb, at), c);
184		writew(sc_vtb_attr_pointer(vtb, at), at2pc98(a));
185	} else {
186		*(u_int16_t *)sc_vtb_pointer(vtb, at) = c;
187		*(u_int16_t *)sc_vtb_attr_pointer(vtb, at) = at2pc98(a);
188	}
189}
190
191vm_offset_t
192sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
193{
194	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
195		writew(p, c);
196		writew(p + ATTR_OFFSET, at2pc98(a));
197	} else {
198		*(u_int16_t *)p = c;
199		*(u_int16_t *)(p + vtb->vtb_size*sizeof(u_int16_t)) = at2pc98(a);
200	}
201	return (p + sizeof(u_int16_t));
202}
203
204vm_offset_t
205sc_vtb_pointer(sc_vtb_t *vtb, int at)
206{
207	return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
208}
209
210static vm_offset_t
211sc_vtb_attr_pointer(sc_vtb_t *vtb, int at)
212{
213	return (vtb->vtb_buffer + sizeof(u_int16_t)*(at)
214		+ ((vtb->vtb_type == VTB_FRAMEBUFFER) ?
215			ATTR_OFFSET : vtb->vtb_size*sizeof(u_int16_t)));
216}
217
218int
219sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset)
220{
221	return ((pos + offset + vtb->vtb_size)%vtb->vtb_size);
222}
223
224void
225sc_vtb_clear(sc_vtb_t *vtb, int c, int attr)
226{
227	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
228		fillw_io(c, sc_vtb_pointer(vtb, 0), vtb->vtb_size);
229		fillw_io(at2pc98(attr), sc_vtb_attr_pointer(vtb, 0), vtb->vtb_size);
230	} else {
231		fillw(c, (void *)sc_vtb_pointer(vtb, 0), vtb->vtb_size);
232		fillw(at2pc98(attr), (void *)sc_vtb_attr_pointer(vtb, 0), vtb->vtb_size);
233	}
234}
235
236void
237sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count)
238{
239	if (vtb2->vtb_type == VTB_FRAMEBUFFER) {
240		bcopy_toio(sc_vtb_pointer(vtb1, from),
241			   sc_vtb_pointer(vtb2, to),
242			   count*sizeof(u_int16_t));
243		bcopy_toio(sc_vtb_attr_pointer(vtb1, from),
244			   sc_vtb_attr_pointer(vtb2, to),
245			   count*sizeof(u_int16_t));
246	} else if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
247		bcopy_fromio(sc_vtb_pointer(vtb1, from),
248			     sc_vtb_pointer(vtb2, to),
249			     count*sizeof(u_int16_t));
250		bcopy_fromio(sc_vtb_attr_pointer(vtb1, from),
251			     sc_vtb_attr_pointer(vtb2, to),
252			     count*sizeof(u_int16_t));
253	} else {
254		bcopy((void *)sc_vtb_pointer(vtb1, from),
255		      (void *)sc_vtb_pointer(vtb2, to),
256		      count*sizeof(u_int16_t));
257		bcopy((void *)sc_vtb_attr_pointer(vtb1, from),
258		      (void *)sc_vtb_attr_pointer(vtb2, to),
259		      count*sizeof(u_int16_t));
260	}
261}
262
263void
264sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count)
265{
266	int len;
267
268	if (vtb2->vtb_type != VTB_RINGBUFFER)
269		return;
270
271	while (count > 0) {
272		len = imin(count, vtb2->vtb_size - vtb2->vtb_tail);
273		if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
274			bcopy_fromio(sc_vtb_pointer(vtb1, from),
275				     sc_vtb_pointer(vtb2, vtb2->vtb_tail),
276				     len*sizeof(u_int16_t));
277			bcopy_fromio(sc_vtb_attr_pointer(vtb1, from),
278				     sc_vtb_attr_pointer(vtb2, vtb2->vtb_tail),
279				     len*sizeof(u_int16_t));
280		} else {
281			bcopy((void *)sc_vtb_pointer(vtb1, from),
282			      (void *)sc_vtb_pointer(vtb2, vtb2->vtb_tail),
283			      len*sizeof(u_int16_t));
284			bcopy((void *)sc_vtb_attr_pointer(vtb1, from),
285			      (void *)sc_vtb_attr_pointer(vtb2, vtb2->vtb_tail),
286			      len*sizeof(u_int16_t));
287		}
288		from += len;
289		count -= len;
290		vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len);
291	}
292}
293
294void
295sc_vtb_seek(sc_vtb_t *vtb, int pos)
296{
297	vtb->vtb_tail = pos%vtb->vtb_size;
298}
299
300void
301sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr)
302{
303	if (at + count > vtb->vtb_size)
304		count = vtb->vtb_size - at;
305	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
306		fillw_io(c, sc_vtb_pointer(vtb, at), count);
307		fillw_io(at2pc98(attr), sc_vtb_attr_pointer(vtb, at), count);
308	} else {
309		fillw(c, (void *)sc_vtb_pointer(vtb, at), count);
310		fillw(at2pc98(attr), (void *)sc_vtb_attr_pointer(vtb, at), count);
311	}
312}
313
314void
315sc_vtb_move(sc_vtb_t *vtb, int from, int to, int count)
316{
317	if (from + count > vtb->vtb_size)
318		count = vtb->vtb_size - from;
319	if (to + count > vtb->vtb_size)
320		count = vtb->vtb_size - to;
321	if (count <= 0)
322		return;
323	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
324		bcopy_io(sc_vtb_pointer(vtb, from),
325			 sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
326		bcopy_io(sc_vtb_attr_pointer(vtb, from),
327			 sc_vtb_attr_pointer(vtb, to), count*sizeof(u_int16_t));
328	} else {
329		bcopy((void *)sc_vtb_pointer(vtb, from),
330		      (void *)sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
331		bcopy((void *)sc_vtb_attr_pointer(vtb, from),
332		      (void *)sc_vtb_attr_pointer(vtb, to), count*sizeof(u_int16_t));
333	}
334}
335
336void
337sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr)
338{
339	int len;
340
341	if (at + count > vtb->vtb_size)
342		count = vtb->vtb_size - at;
343	len = vtb->vtb_size - at - count;
344	if (len > 0) {
345		if (vtb->vtb_type == VTB_FRAMEBUFFER) {
346			bcopy_io(sc_vtb_pointer(vtb, at + count),
347				 sc_vtb_pointer(vtb, at),
348				 len*sizeof(u_int16_t));
349			bcopy_io(sc_vtb_attr_pointer(vtb, at + count),
350				 sc_vtb_attr_pointer(vtb, at),
351				 len*sizeof(u_int16_t));
352		} else {
353			bcopy((void *)sc_vtb_pointer(vtb, at + count),
354			      (void *)sc_vtb_pointer(vtb, at),
355			      len*sizeof(u_int16_t));
356			bcopy((void *)sc_vtb_attr_pointer(vtb, at + count),
357			      (void *)sc_vtb_attr_pointer(vtb, at),
358			      len*sizeof(u_int16_t));
359		}
360	}
361	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
362		fillw_io(c, sc_vtb_pointer(vtb, at + len),
363			 vtb->vtb_size - at - len);
364		fillw_io(at2pc98(attr),
365			 sc_vtb_attr_pointer(vtb, at + len),
366			 vtb->vtb_size - at - len);
367	} else {
368		fillw(c, (void *)sc_vtb_pointer(vtb, at + len),
369		      vtb->vtb_size - at - len);
370		fillw(at2pc98(attr),
371		      (void *)sc_vtb_attr_pointer(vtb, at + len),
372		      vtb->vtb_size - at - len);
373	}
374}
375
376void
377sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr)
378{
379	if (at + count > vtb->vtb_size) {
380		count = vtb->vtb_size - at;
381	} else {
382		if (vtb->vtb_type == VTB_FRAMEBUFFER) {
383			bcopy_io(sc_vtb_pointer(vtb, at),
384				 sc_vtb_pointer(vtb, at + count),
385				 (vtb->vtb_size - at - count)*sizeof(u_int16_t));
386			bcopy_io(sc_vtb_attr_pointer(vtb, at),
387				 sc_vtb_attr_pointer(vtb, at + count),
388				 (vtb->vtb_size - at - count)*sizeof(u_int16_t));
389		} else {
390			bcopy((void *)sc_vtb_pointer(vtb, at),
391			      (void *)sc_vtb_pointer(vtb, at + count),
392			      (vtb->vtb_size - at - count)*sizeof(u_int16_t));
393			bcopy((void *)sc_vtb_attr_pointer(vtb, at),
394			      (void *)sc_vtb_attr_pointer(vtb, at + count),
395			      (vtb->vtb_size - at - count)*sizeof(u_int16_t));
396		}
397	}
398	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
399		fillw_io(c, sc_vtb_pointer(vtb, at), count);
400		fillw_io(at2pc98(attr),
401			 sc_vtb_attr_pointer(vtb, at), count);
402	} else {
403		fillw(c, (void *)sc_vtb_pointer(vtb, at), count);
404		fillw(at2pc98(attr),
405		      (void *)sc_vtb_attr_pointer(vtb, at), count);
406	}
407}
408
409#endif /* NSC */
410