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