xref: /freebsd/sys/dev/syscons/scvtb.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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  * $FreeBSD$
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 vtb_wrap(vtb, at, offset)				\
42     (((at) + (offset) + (vtb)->vtb_size)%(vtb)->vtb_size)
43 
44 void
45 sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, void *buf, int wait)
46 {
47 	vtb->vtb_flags = 0;
48 	vtb->vtb_type = type;
49 	vtb->vtb_cols = cols;
50 	vtb->vtb_rows = rows;
51 	vtb->vtb_size = cols*rows;
52 	vtb->vtb_buffer = NULL;
53 	vtb->vtb_tail = 0;
54 
55 	switch (type) {
56 	case VTB_MEMORY:
57 	case VTB_RINGBUFFER:
58 		if ((buf == NULL) && (cols*rows != 0)) {
59 			vtb->vtb_buffer =
60 				(vm_offset_t)malloc(cols*rows*sizeof(u_int16_t),
61 						    M_DEVBUF,
62 						    (wait) ? M_WAITOK : M_NOWAIT);
63 			if (vtb->vtb_buffer != NULL)
64 				bzero((void *)sc_vtb_pointer(vtb, 0),
65 				      cols*rows*sizeof(u_int16_t));
66 		} else {
67 			vtb->vtb_buffer = (vm_offset_t)buf;
68 		}
69 		vtb->vtb_flags |= VTB_VALID;
70 		break;
71 	case VTB_FRAMEBUFFER:
72 		vtb->vtb_buffer = (vm_offset_t)buf;
73 		vtb->vtb_flags |= VTB_VALID;
74 		break;
75 	default:
76 		break;
77 	}
78 }
79 
80 void
81 sc_vtb_destroy(sc_vtb_t *vtb)
82 {
83 	vm_offset_t p;
84 
85 	vtb->vtb_flags = 0;
86 	vtb->vtb_cols = 0;
87 	vtb->vtb_rows = 0;
88 	vtb->vtb_size = 0;
89 	vtb->vtb_tail = 0;
90 
91 	p = vtb->vtb_buffer;
92 	vtb->vtb_buffer = NULL;
93 	switch (vtb->vtb_type) {
94 	case VTB_MEMORY:
95 	case VTB_RINGBUFFER:
96 		if (p != NULL)
97 			free((void *)p, M_DEVBUF);
98 		break;
99 	default:
100 		break;
101 	}
102 	vtb->vtb_type = VTB_INVALID;
103 }
104 
105 size_t
106 sc_vtb_size(int cols, int rows)
107 {
108 	return (size_t)(cols*rows*sizeof(u_int16_t));
109 }
110 
111 int
112 sc_vtb_getc(sc_vtb_t *vtb, int at)
113 {
114 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
115 		return (readw(sc_vtb_pointer(vtb, at)) & 0x00ff);
116 	else
117 		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0x00ff);
118 }
119 
120 int
121 sc_vtb_geta(sc_vtb_t *vtb, int at)
122 {
123 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
124 		return (readw(sc_vtb_pointer(vtb, at)) & 0xff00);
125 	else
126 		return (*(u_int16_t *)sc_vtb_pointer(vtb, at) & 0xff00);
127 }
128 
129 void
130 sc_vtb_putc(sc_vtb_t *vtb, int at, int c, int a)
131 {
132 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
133 		writew(sc_vtb_pointer(vtb, at), a | c);
134 	else
135 		*(u_int16_t *)sc_vtb_pointer(vtb, at) = a | c;
136 }
137 
138 vm_offset_t
139 sc_vtb_putchar(sc_vtb_t *vtb, vm_offset_t p, int c, int a)
140 {
141 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
142 		writew(p, a | c);
143 	else
144 		*(u_int16_t *)p = a | c;
145 	return (p + sizeof(u_int16_t));
146 }
147 
148 vm_offset_t
149 sc_vtb_pointer(sc_vtb_t *vtb, int at)
150 {
151 	return (vtb->vtb_buffer + sizeof(u_int16_t)*(at));
152 }
153 
154 int
155 sc_vtb_pos(sc_vtb_t *vtb, int pos, int offset)
156 {
157 	return ((pos + offset + vtb->vtb_size)%vtb->vtb_size);
158 }
159 
160 void
161 sc_vtb_clear(sc_vtb_t *vtb, int c, int attr)
162 {
163 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
164 		fillw_io(attr | c, sc_vtb_pointer(vtb, 0), vtb->vtb_size);
165 	else
166 		fillw(attr | c, (void *)sc_vtb_pointer(vtb, 0), vtb->vtb_size);
167 }
168 
169 void
170 sc_vtb_copy(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int to, int count)
171 {
172 	/* XXX if both are VTB_VRAMEBUFFER... */
173 	if (vtb2->vtb_type == VTB_FRAMEBUFFER) {
174 		bcopy_toio(sc_vtb_pointer(vtb1, from),
175 			   sc_vtb_pointer(vtb2, to),
176 			   count*sizeof(u_int16_t));
177 	} else if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
178 		bcopy_fromio(sc_vtb_pointer(vtb1, from),
179 			     sc_vtb_pointer(vtb2, to),
180 			     count*sizeof(u_int16_t));
181 	} else {
182 		bcopy((void *)sc_vtb_pointer(vtb1, from),
183 		      (void *)sc_vtb_pointer(vtb2, to),
184 		      count*sizeof(u_int16_t));
185 	}
186 }
187 
188 void
189 sc_vtb_append(sc_vtb_t *vtb1, int from, sc_vtb_t *vtb2, int count)
190 {
191 	int len;
192 
193 	if (vtb2->vtb_type != VTB_RINGBUFFER)
194 		return;
195 
196 	while (count > 0) {
197 		len = imin(count, vtb2->vtb_size - vtb2->vtb_tail);
198 		if (vtb1->vtb_type == VTB_FRAMEBUFFER) {
199 			bcopy_fromio(sc_vtb_pointer(vtb1, from),
200 				     sc_vtb_pointer(vtb2, vtb2->vtb_tail),
201 				     len*sizeof(u_int16_t));
202 		} else {
203 			bcopy((void *)sc_vtb_pointer(vtb1, from),
204 			      (void *)sc_vtb_pointer(vtb2, vtb2->vtb_tail),
205 			      len*sizeof(u_int16_t));
206 		}
207 		from += len;
208 		count -= len;
209 		vtb2->vtb_tail = vtb_wrap(vtb2, vtb2->vtb_tail, len);
210 	}
211 }
212 
213 void
214 sc_vtb_seek(sc_vtb_t *vtb, int pos)
215 {
216 	vtb->vtb_tail = pos%vtb->vtb_size;
217 }
218 
219 void
220 sc_vtb_erase(sc_vtb_t *vtb, int at, int count, int c, int attr)
221 {
222 	if (at + count > vtb->vtb_size)
223 		count = vtb->vtb_size - at;
224 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
225 		fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
226 	else
227 		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
228 }
229 
230 void
231 sc_vtb_move(sc_vtb_t *vtb, int from, int to, int count)
232 {
233 	if (from + count > vtb->vtb_size)
234 		count = vtb->vtb_size - from;
235 	if (to + count > vtb->vtb_size)
236 		count = vtb->vtb_size - to;
237 	if (count <= 0)
238 		return;
239 	if (vtb->vtb_type == VTB_FRAMEBUFFER) {
240 		bcopy_io(sc_vtb_pointer(vtb, from),
241 			 sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
242 	} else {
243 		bcopy((void *)sc_vtb_pointer(vtb, from),
244 		      (void *)sc_vtb_pointer(vtb, to), count*sizeof(u_int16_t));
245 	}
246 }
247 
248 void
249 sc_vtb_delete(sc_vtb_t *vtb, int at, int count, int c, int attr)
250 {
251 	int len;
252 
253 	if (at + count > vtb->vtb_size)
254 		count = vtb->vtb_size - at;
255 	len = vtb->vtb_size - at - count;
256 	if (len > 0) {
257 		if (vtb->vtb_type == VTB_FRAMEBUFFER) {
258 			bcopy_io(sc_vtb_pointer(vtb, at + count),
259 				 sc_vtb_pointer(vtb, at),
260 				 len*sizeof(u_int16_t));
261 		} else {
262 			bcopy((void *)sc_vtb_pointer(vtb, at + count),
263 			      (void *)sc_vtb_pointer(vtb, at),
264 			      len*sizeof(u_int16_t));
265 		}
266 	}
267 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
268 		fillw_io(attr | c, sc_vtb_pointer(vtb, at + len),
269 			 vtb->vtb_size - at - len);
270 	else
271 		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at + len),
272 		      vtb->vtb_size - at - len);
273 }
274 
275 void
276 sc_vtb_ins(sc_vtb_t *vtb, int at, int count, int c, int attr)
277 {
278 	if (at + count > vtb->vtb_size) {
279 		count = vtb->vtb_size - at;
280 	} else {
281 		if (vtb->vtb_type == VTB_FRAMEBUFFER) {
282 			bcopy_io(sc_vtb_pointer(vtb, at),
283 				 sc_vtb_pointer(vtb, at + count),
284 				 (vtb->vtb_size - at - count)*sizeof(u_int16_t));
285 		} else {
286 			bcopy((void *)sc_vtb_pointer(vtb, at),
287 			      (void *)sc_vtb_pointer(vtb, at + count),
288 			      (vtb->vtb_size - at - count)*sizeof(u_int16_t));
289 		}
290 	}
291 	if (vtb->vtb_type == VTB_FRAMEBUFFER)
292 		fillw_io(attr | c, sc_vtb_pointer(vtb, at), count);
293 	else
294 		fillw(attr | c, (void *)sc_vtb_pointer(vtb, at), count);
295 }
296