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