pcdisplay_subr.c revision 1.33.12.2 1 1.33.12.2 mjf /* $NetBSD: pcdisplay_subr.c,v 1.33.12.2 2007/07/28 20:28:57 mjf Exp $ */
2 1.33.12.2 mjf
3 1.33.12.2 mjf /*
4 1.33.12.2 mjf * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5 1.33.12.2 mjf * All rights reserved.
6 1.33.12.2 mjf *
7 1.33.12.2 mjf * Author: Chris G. Demetriou
8 1.33.12.2 mjf *
9 1.33.12.2 mjf * Permission to use, copy, modify and distribute this software and
10 1.33.12.2 mjf * its documentation is hereby granted, provided that both the copyright
11 1.33.12.2 mjf * notice and this permission notice appear in all copies of the
12 1.33.12.2 mjf * software, derivative works or modified versions, and any portions
13 1.33.12.2 mjf * thereof, and that both notices appear in supporting documentation.
14 1.33.12.2 mjf *
15 1.33.12.2 mjf * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 1.33.12.2 mjf * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 1.33.12.2 mjf * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 1.33.12.2 mjf *
19 1.33.12.2 mjf * Carnegie Mellon requests users of this software to return to
20 1.33.12.2 mjf *
21 1.33.12.2 mjf * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
22 1.33.12.2 mjf * School of Computer Science
23 1.33.12.2 mjf * Carnegie Mellon University
24 1.33.12.2 mjf * Pittsburgh PA 15213-3890
25 1.33.12.2 mjf *
26 1.33.12.2 mjf * any improvements or extensions that they make and grant Carnegie the
27 1.33.12.2 mjf * rights to redistribute these changes.
28 1.33.12.2 mjf */
29 1.33.12.2 mjf
30 1.33.12.2 mjf #include <sys/cdefs.h>
31 1.33.12.2 mjf __KERNEL_RCSID(0, "$NetBSD: pcdisplay_subr.c,v 1.33.12.2 2007/07/28 20:28:57 mjf Exp $");
32 1.33.12.2 mjf
33 1.33.12.2 mjf #include "opt_wsmsgattrs.h" /* for WSDISPLAY_CUSTOM_OUTPUT */
34 1.33.12.2 mjf
35 1.33.12.2 mjf #include <sys/param.h>
36 1.33.12.2 mjf #include <sys/systm.h>
37 1.33.12.2 mjf #include <sys/device.h>
38 1.33.12.2 mjf #include <machine/bus.h>
39 1.33.12.2 mjf
40 1.33.12.2 mjf #include <dev/ic/mc6845reg.h>
41 1.33.12.2 mjf #include <dev/ic/pcdisplayvar.h>
42 1.33.12.2 mjf #include <dev/wscons/wsconsio.h>
43 1.33.12.2 mjf
44 1.33.12.2 mjf #include <dev/wscons/wsdisplayvar.h>
45 1.33.12.2 mjf
46 1.33.12.2 mjf void
47 1.33.12.2 mjf pcdisplay_cursor_init(struct pcdisplayscreen *scr, int existing)
48 1.33.12.2 mjf {
49 1.33.12.2 mjf #ifdef PCDISPLAY_SOFTCURSOR
50 1.33.12.2 mjf bus_space_tag_t memt;
51 1.33.12.2 mjf bus_space_handle_t memh;
52 1.33.12.2 mjf int off;
53 1.33.12.2 mjf
54 1.33.12.2 mjf pcdisplay_6845_write(scr->hdl, curstart, 0x10);
55 1.33.12.2 mjf pcdisplay_6845_write(scr->hdl, curend, 0x10);
56 1.33.12.2 mjf
57 1.33.12.2 mjf if (existing) {
58 1.33.12.2 mjf /*
59 1.33.12.2 mjf * This is the first screen. At this point, scr->mem is NULL
60 1.33.12.2 mjf * (no backing store), so we can't use pcdisplay_cursor() to
61 1.33.12.2 mjf * do this.
62 1.33.12.2 mjf */
63 1.33.12.2 mjf memt = scr->hdl->ph_memt;
64 1.33.12.2 mjf memh = scr->hdl->ph_memh;
65 1.33.12.2 mjf off = (scr->cursorrow * scr->type->ncols + scr->cursorcol) * 2
66 1.33.12.2 mjf + scr->dispoffset;
67 1.33.12.2 mjf
68 1.33.12.2 mjf scr->cursortmp = bus_space_read_2(memt, memh, off);
69 1.33.12.2 mjf bus_space_write_2(memt, memh, off, scr->cursortmp ^ 0x7700);
70 1.33.12.2 mjf } else
71 1.33.12.2 mjf scr->cursortmp = 0;
72 1.33.12.2 mjf #else
73 1.33.12.2 mjf /*
74 1.33.12.2 mjf * Firmware might not have initialized the cursor shape. Make
75 1.33.12.2 mjf * sure there's something we can see.
76 1.33.12.2 mjf * Don't touch the hardware if this is not the first screen.
77 1.33.12.2 mjf */
78 1.33.12.2 mjf if (existing) {
79 1.33.12.2 mjf pcdisplay_6845_write(scr->hdl, curstart,
80 1.33.12.2 mjf scr->type->fontheight - 2);
81 1.33.12.2 mjf pcdisplay_6845_write(scr->hdl, curend,
82 1.33.12.2 mjf scr->type->fontheight - 1);
83 1.33.12.2 mjf }
84 1.33.12.2 mjf #endif
85 1.33.12.2 mjf scr->cursoron = 1;
86 1.33.12.2 mjf }
87 1.33.12.2 mjf
88 1.33.12.2 mjf void
89 1.33.12.2 mjf pcdisplay_cursor(void *id, int on, int row, int col)
90 1.33.12.2 mjf {
91 1.33.12.2 mjf #ifdef PCDISPLAY_SOFTCURSOR
92 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
93 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
94 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
95 1.33.12.2 mjf int off;
96 1.33.12.2 mjf
97 1.33.12.2 mjf /* Remove old cursor image */
98 1.33.12.2 mjf if (scr->cursoron) {
99 1.33.12.2 mjf off = scr->cursorrow * scr->type->ncols + scr->cursorcol;
100 1.33.12.2 mjf if (scr->active)
101 1.33.12.2 mjf bus_space_write_2(memt, memh, scr->dispoffset + off * 2,
102 1.33.12.2 mjf scr->cursortmp);
103 1.33.12.2 mjf else
104 1.33.12.2 mjf scr->mem[off] = scr->cursortmp;
105 1.33.12.2 mjf }
106 1.33.12.2 mjf
107 1.33.12.2 mjf scr->cursorrow = row;
108 1.33.12.2 mjf scr->cursorcol = col;
109 1.33.12.2 mjf
110 1.33.12.2 mjf if ((scr->cursoron = on) == 0)
111 1.33.12.2 mjf return;
112 1.33.12.2 mjf
113 1.33.12.2 mjf off = (scr->cursorrow * scr->type->ncols + scr->cursorcol);
114 1.33.12.2 mjf if (scr->active) {
115 1.33.12.2 mjf off = off * 2 + scr->dispoffset;
116 1.33.12.2 mjf scr->cursortmp = bus_space_read_2(memt, memh, off);
117 1.33.12.2 mjf bus_space_write_2(memt, memh, off, scr->cursortmp ^ 0x7700);
118 1.33.12.2 mjf } else {
119 1.33.12.2 mjf scr->cursortmp = scr->mem[off];
120 1.33.12.2 mjf scr->mem[off] = scr->cursortmp ^ 0x7700;
121 1.33.12.2 mjf }
122 1.33.12.2 mjf #else /* PCDISPLAY_SOFTCURSOR */
123 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
124 1.33.12.2 mjf int pos;
125 1.33.12.2 mjf
126 1.33.12.2 mjf scr->cursorrow = row;
127 1.33.12.2 mjf scr->cursorcol = col;
128 1.33.12.2 mjf scr->cursoron = on;
129 1.33.12.2 mjf
130 1.33.12.2 mjf if (scr->active) {
131 1.33.12.2 mjf if (!on)
132 1.33.12.2 mjf pos = 0x3fff;
133 1.33.12.2 mjf else
134 1.33.12.2 mjf pos = scr->dispoffset / 2
135 1.33.12.2 mjf + row * scr->type->ncols + col;
136 1.33.12.2 mjf
137 1.33.12.2 mjf pcdisplay_6845_write(scr->hdl, cursorh, pos >> 8);
138 1.33.12.2 mjf pcdisplay_6845_write(scr->hdl, cursorl, pos);
139 1.33.12.2 mjf }
140 1.33.12.2 mjf #endif /* PCDISPLAY_SOFTCURSOR */
141 1.33.12.2 mjf }
142 1.33.12.2 mjf
143 1.33.12.2 mjf #if 0
144 1.33.12.2 mjf unsigned int
145 1.33.12.2 mjf pcdisplay_mapchar_simple(void *id, int uni)
146 1.33.12.2 mjf {
147 1.33.12.2 mjf if (uni < 128)
148 1.33.12.2 mjf return (uni);
149 1.33.12.2 mjf
150 1.33.12.2 mjf return (1); /* XXX ??? smiley */
151 1.33.12.2 mjf }
152 1.33.12.2 mjf #endif
153 1.33.12.2 mjf
154 1.33.12.2 mjf void
155 1.33.12.2 mjf pcdisplay_putchar(void *id, int row, int col, unsigned int c, long attr)
156 1.33.12.2 mjf {
157 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
158 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
159 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
160 1.33.12.2 mjf size_t off;
161 1.33.12.2 mjf
162 1.33.12.2 mjf off = row * scr->type->ncols + col;
163 1.33.12.2 mjf
164 1.33.12.2 mjf /* check for bogus row and column sizes */
165 1.33.12.2 mjf if (__predict_false(off >= (scr->type->ncols * scr->type->nrows)))
166 1.33.12.2 mjf return;
167 1.33.12.2 mjf
168 1.33.12.2 mjf if (scr->active)
169 1.33.12.2 mjf bus_space_write_2(memt, memh, scr->dispoffset + off * 2,
170 1.33.12.2 mjf c | (attr << 8));
171 1.33.12.2 mjf else
172 1.33.12.2 mjf scr->mem[off] = c | (attr << 8);
173 1.33.12.2 mjf
174 1.33.12.2 mjf scr->visibleoffset = scr->dispoffset;
175 1.33.12.2 mjf }
176 1.33.12.2 mjf
177 1.33.12.2 mjf void
178 1.33.12.2 mjf pcdisplay_copycols(void *id, int row, int srccol, int dstcol, int ncols)
179 1.33.12.2 mjf {
180 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
181 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
182 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
183 1.33.12.2 mjf bus_size_t srcoff, dstoff;
184 1.33.12.2 mjf
185 1.33.12.2 mjf srcoff = dstoff = row * scr->type->ncols;
186 1.33.12.2 mjf srcoff += srccol;
187 1.33.12.2 mjf dstoff += dstcol;
188 1.33.12.2 mjf
189 1.33.12.2 mjf if (scr->active)
190 1.33.12.2 mjf bus_space_copy_region_2(memt, memh,
191 1.33.12.2 mjf scr->dispoffset + srcoff * 2,
192 1.33.12.2 mjf memh, scr->dispoffset + dstoff * 2,
193 1.33.12.2 mjf ncols);
194 1.33.12.2 mjf else
195 1.33.12.2 mjf memcpy(&scr->mem[dstoff], &scr->mem[srcoff], ncols * 2);
196 1.33.12.2 mjf }
197 1.33.12.2 mjf
198 1.33.12.2 mjf void
199 1.33.12.2 mjf pcdisplay_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
200 1.33.12.2 mjf {
201 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
202 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
203 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
204 1.33.12.2 mjf bus_size_t off;
205 1.33.12.2 mjf u_int16_t val;
206 1.33.12.2 mjf int i;
207 1.33.12.2 mjf
208 1.33.12.2 mjf off = row * scr->type->ncols + startcol;
209 1.33.12.2 mjf
210 1.33.12.2 mjf val = (fillattr << 8) | ' ';
211 1.33.12.2 mjf
212 1.33.12.2 mjf if (scr->active)
213 1.33.12.2 mjf bus_space_set_region_2(memt, memh, scr->dispoffset + off * 2,
214 1.33.12.2 mjf val, ncols);
215 1.33.12.2 mjf else
216 1.33.12.2 mjf for (i = 0; i < ncols; i++)
217 1.33.12.2 mjf scr->mem[off + i] = val;
218 1.33.12.2 mjf }
219 1.33.12.2 mjf
220 1.33.12.2 mjf void
221 1.33.12.2 mjf pcdisplay_copyrows(void *id, int srcrow, int dstrow, int nrows)
222 1.33.12.2 mjf {
223 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
224 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
225 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
226 1.33.12.2 mjf int ncols = scr->type->ncols;
227 1.33.12.2 mjf bus_size_t srcoff, dstoff;
228 1.33.12.2 mjf
229 1.33.12.2 mjf srcoff = srcrow * ncols + 0;
230 1.33.12.2 mjf dstoff = dstrow * ncols + 0;
231 1.33.12.2 mjf
232 1.33.12.2 mjf if (scr->active)
233 1.33.12.2 mjf bus_space_copy_region_2(memt, memh,
234 1.33.12.2 mjf scr->dispoffset + srcoff * 2,
235 1.33.12.2 mjf memh, scr->dispoffset + dstoff * 2,
236 1.33.12.2 mjf nrows * ncols);
237 1.33.12.2 mjf else
238 1.33.12.2 mjf memcpy(&scr->mem[dstoff], &scr->mem[srcoff],
239 1.33.12.2 mjf nrows * ncols * 2);
240 1.33.12.2 mjf }
241 1.33.12.2 mjf
242 1.33.12.2 mjf void
243 1.33.12.2 mjf pcdisplay_eraserows(void *id, int startrow, int nrows, long fillattr)
244 1.33.12.2 mjf {
245 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
246 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
247 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
248 1.33.12.2 mjf bus_size_t off, count;
249 1.33.12.2 mjf u_int16_t val;
250 1.33.12.2 mjf u_int i;
251 1.33.12.2 mjf
252 1.33.12.2 mjf off = startrow * scr->type->ncols;
253 1.33.12.2 mjf count = nrows * scr->type->ncols;
254 1.33.12.2 mjf
255 1.33.12.2 mjf val = (fillattr << 8) | ' ';
256 1.33.12.2 mjf
257 1.33.12.2 mjf if (scr->active)
258 1.33.12.2 mjf bus_space_set_region_2(memt, memh, scr->dispoffset + off * 2,
259 1.33.12.2 mjf val, count);
260 1.33.12.2 mjf else
261 1.33.12.2 mjf for (i = 0; i < count; i++)
262 1.33.12.2 mjf scr->mem[off + i] = val;
263 1.33.12.2 mjf }
264 1.33.12.2 mjf
265 1.33.12.2 mjf #ifdef WSDISPLAY_CUSTOM_OUTPUT
266 1.33.12.2 mjf void
267 1.33.12.2 mjf pcdisplay_replaceattr(void *id, long oldattr, long newattr)
268 1.33.12.2 mjf {
269 1.33.12.2 mjf struct pcdisplayscreen *scr = id;
270 1.33.12.2 mjf bus_space_tag_t memt = scr->hdl->ph_memt;
271 1.33.12.2 mjf bus_space_handle_t memh = scr->hdl->ph_memh;
272 1.33.12.2 mjf int off;
273 1.33.12.2 mjf uint16_t chardata;
274 1.33.12.2 mjf
275 1.33.12.2 mjf if (scr->active)
276 1.33.12.2 mjf for (off = 0; off < scr->type->nrows * scr->type->ncols;
277 1.33.12.2 mjf off++) {
278 1.33.12.2 mjf chardata = bus_space_read_2(memt, memh,
279 1.33.12.2 mjf scr->dispoffset + off * 2);
280 1.33.12.2 mjf if ((long)(chardata >> 8) == oldattr)
281 1.33.12.2 mjf bus_space_write_2(memt, memh,
282 1.33.12.2 mjf scr->dispoffset + off * 2,
283 1.33.12.2 mjf ((u_int16_t)(newattr << 8)) |
284 1.33.12.2 mjf (chardata & 0x00FF));
285 1.33.12.2 mjf }
286 1.33.12.2 mjf else
287 1.33.12.2 mjf for (off = 0; off < scr->type->nrows * scr->type->ncols;
288 1.33.12.2 mjf off++) {
289 1.33.12.2 mjf chardata = scr->mem[off];
290 1.33.12.2 mjf if ((long)(chardata >> 8) == oldattr)
291 1.33.12.2 mjf scr->mem[off] = ((u_int16_t)(newattr << 8)) |
292 1.33.12.2 mjf (chardata & 0x00FF);
293 1.33.12.2 mjf }
294 1.33.12.2 mjf }
295 1.33.12.2 mjf #endif /* WSDISPLAY_CUSTOM_OUTPUT */
296 1.33.12.2 mjf
297 1.33.12.2 mjf int
298 1.33.12.2 mjf pcdisplay_getwschar(struct pcdisplayscreen *scr, struct wsdisplay_char *wschar)
299 1.33.12.2 mjf {
300 1.33.12.2 mjf size_t off;
301 1.33.12.2 mjf uint16_t chardata;
302 1.33.12.2 mjf uint8_t attrbyte;
303 1.33.12.2 mjf
304 1.33.12.2 mjf KASSERT(scr != NULL && wschar != NULL);
305 1.33.12.2 mjf
306 1.33.12.2 mjf off = wschar->row * scr->type->ncols + wschar->col;
307 1.33.12.2 mjf if (off >= scr->type->ncols * scr->type->nrows)
308 1.33.12.2 mjf return -1;
309 1.33.12.2 mjf
310 1.33.12.2 mjf if (scr->active)
311 1.33.12.2 mjf chardata = bus_space_read_2(scr->hdl->ph_memt,
312 1.33.12.2 mjf scr->hdl->ph_memh, scr->dispoffset + off * 2);
313 1.33.12.2 mjf else
314 1.33.12.2 mjf chardata = scr->mem[off];
315 1.33.12.2 mjf
316 1.33.12.2 mjf wschar->letter = (chardata & 0x00FF);
317 1.33.12.2 mjf wschar->flags = 0;
318 1.33.12.2 mjf attrbyte = (chardata & 0xFF00) >> 8;
319 1.33.12.2 mjf if ((attrbyte & 0x08)) wschar->flags |= WSDISPLAY_CHAR_BRIGHT;
320 1.33.12.2 mjf if ((attrbyte & 0x80)) wschar->flags |= WSDISPLAY_CHAR_BLINK;
321 1.33.12.2 mjf wschar->foreground = attrbyte & 0x07;
322 1.33.12.2 mjf wschar->background = (attrbyte >> 4) & 0x07;
323 1.33.12.2 mjf
324 1.33.12.2 mjf return 0;
325 1.33.12.2 mjf }
326 1.33.12.2 mjf
327 1.33.12.2 mjf int
328 1.33.12.2 mjf pcdisplay_putwschar(struct pcdisplayscreen *scr, struct wsdisplay_char *wschar)
329 1.33.12.2 mjf {
330 1.33.12.2 mjf size_t off;
331 1.33.12.2 mjf uint16_t chardata;
332 1.33.12.2 mjf uint8_t attrbyte;
333 1.33.12.2 mjf
334 1.33.12.2 mjf KASSERT(scr != NULL && wschar != NULL);
335 1.33.12.2 mjf
336 1.33.12.2 mjf off = wschar->row * scr->type->ncols + wschar->col;
337 1.33.12.2 mjf if (off >= (scr->type->ncols * scr->type->nrows))
338 1.33.12.2 mjf return -1;
339 1.33.12.2 mjf
340 1.33.12.2 mjf attrbyte = wschar->background & 0x07;
341 1.33.12.2 mjf if (wschar->flags & WSDISPLAY_CHAR_BLINK) attrbyte |= 0x08;
342 1.33.12.2 mjf attrbyte <<= 4;
343 1.33.12.2 mjf attrbyte |= wschar->foreground & 0x07;
344 1.33.12.2 mjf if (wschar->flags & WSDISPLAY_CHAR_BRIGHT) attrbyte |= 0x08;
345 1.33.12.2 mjf chardata = (attrbyte << 8) | wschar->letter;
346 1.33.12.2 mjf
347 1.33.12.2 mjf if (scr->active)
348 1.33.12.2 mjf bus_space_write_2(scr->hdl->ph_memt, scr->hdl->ph_memh,
349 1.33.12.2 mjf scr->dispoffset + off * 2, chardata);
350 1.33.12.2 mjf else
351 1.33.12.2 mjf scr->mem[off] = chardata;
352 1.33.12.2 mjf
353 1.33.12.2 mjf return 0;
354 1.33.12.2 mjf }
355