vga.c revision 1.120 1 1.120 thorpej /* $NetBSD: vga.c,v 1.120 2021/08/07 16:19:12 thorpej Exp $ */
2 1.1 drochner
3 1.1 drochner /*
4 1.1 drochner * Copyright (c) 1995, 1996 Carnegie-Mellon University.
5 1.1 drochner * All rights reserved.
6 1.1 drochner *
7 1.1 drochner * Author: Chris G. Demetriou
8 1.81 perry *
9 1.1 drochner * Permission to use, copy, modify and distribute this software and
10 1.1 drochner * its documentation is hereby granted, provided that both the copyright
11 1.1 drochner * notice and this permission notice appear in all copies of the
12 1.1 drochner * software, derivative works or modified versions, and any portions
13 1.1 drochner * thereof, and that both notices appear in supporting documentation.
14 1.81 perry *
15 1.81 perry * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 1.81 perry * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 1.1 drochner * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18 1.81 perry *
19 1.1 drochner * Carnegie Mellon requests users of this software to return to
20 1.1 drochner *
21 1.1 drochner * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
22 1.1 drochner * School of Computer Science
23 1.1 drochner * Carnegie Mellon University
24 1.1 drochner * Pittsburgh PA 15213-3890
25 1.1 drochner *
26 1.1 drochner * any improvements or extensions that they make and grant Carnegie the
27 1.1 drochner * rights to redistribute these changes.
28 1.1 drochner */
29 1.43 lukem
30 1.94 dsl #include <sys/cdefs.h>
31 1.120 thorpej __KERNEL_RCSID(0, "$NetBSD: vga.c,v 1.120 2021/08/07 16:19:12 thorpej Exp $");
32 1.94 dsl
33 1.112 mlelstv #include "opt_vga.h"
34 1.87 jmmv /* for WSCONS_SUPPORT_PCVTFONTS */
35 1.75 jmmv #include "opt_wsdisplay_compat.h"
36 1.76 jmmv /* for WSDISPLAY_CUSTOM_BORDER */
37 1.76 jmmv #include "opt_wsdisplay_border.h"
38 1.75 jmmv /* for WSDISPLAY_CUSTOM_OUTPUT */
39 1.75 jmmv #include "opt_wsmsgattrs.h"
40 1.75 jmmv
41 1.1 drochner #include <sys/param.h>
42 1.1 drochner #include <sys/systm.h>
43 1.26 thorpej #include <sys/callout.h>
44 1.1 drochner #include <sys/kernel.h>
45 1.1 drochner #include <sys/device.h>
46 1.1 drochner #include <sys/malloc.h>
47 1.1 drochner #include <sys/queue.h>
48 1.96 ad #include <sys/bus.h>
49 1.1 drochner
50 1.4 drochner #include <dev/ic/mc6845reg.h>
51 1.4 drochner #include <dev/ic/pcdisplayvar.h>
52 1.4 drochner #include <dev/ic/vgareg.h>
53 1.4 drochner #include <dev/ic/vgavar.h>
54 1.4 drochner
55 1.1 drochner #include <dev/wscons/wsdisplayvar.h>
56 1.1 drochner #include <dev/wscons/wsconsio.h>
57 1.14 drochner #include <dev/wscons/unicode.h>
58 1.37 drochner #include <dev/wsfont/wsfont.h>
59 1.1 drochner
60 1.3 drochner #include <dev/ic/pcdisplay.h>
61 1.1 drochner
62 1.68 tsutsui int vga_no_builtinfont = 0;
63 1.68 tsutsui
64 1.37 drochner static struct wsdisplay_font _vga_builtinfont = {
65 1.66 tsutsui "builtin", /* typeface name */
66 1.66 tsutsui 0, /* firstchar */
67 1.66 tsutsui 256, /* numbers */
68 1.66 tsutsui WSDISPLAY_FONTENC_IBM, /* encoding */
69 1.66 tsutsui 8, /* width */
70 1.66 tsutsui 16, /* height */
71 1.66 tsutsui 1, /* stride */
72 1.66 tsutsui WSDISPLAY_FONTORDER_L2R, /* bit order */
73 1.66 tsutsui 0, /* byte order */
74 1.66 tsutsui NULL /* data */
75 1.12 drochner };
76 1.12 drochner
77 1.37 drochner struct egavga_font {
78 1.37 drochner struct wsdisplay_font *wsfont;
79 1.58 drochner int cookie; /* wsfont handle, -1 invalid */
80 1.37 drochner int slot; /* in adapter RAM */
81 1.37 drochner int usecount;
82 1.37 drochner TAILQ_ENTRY(egavga_font) next; /* LRU queue */
83 1.37 drochner };
84 1.37 drochner
85 1.37 drochner static struct egavga_font vga_builtinfont = {
86 1.89 christos .wsfont = &_vga_builtinfont,
87 1.89 christos .cookie = -1,
88 1.89 christos .slot = 0,
89 1.37 drochner };
90 1.37 drochner
91 1.38 drochner #ifdef VGA_CONSOLE_SCREENTYPE
92 1.38 drochner static struct egavga_font vga_consolefont;
93 1.38 drochner #endif
94 1.38 drochner
95 1.1 drochner struct vgascreen {
96 1.4 drochner struct pcdisplayscreen pcs;
97 1.4 drochner
98 1.1 drochner LIST_ENTRY(vgascreen) next;
99 1.1 drochner
100 1.1 drochner struct vga_config *cfg;
101 1.1 drochner
102 1.1 drochner /* videostate */
103 1.37 drochner struct egavga_font *fontset1, *fontset2;
104 1.1 drochner /* font data */
105 1.8 drochner
106 1.8 drochner int mindispoffset, maxdispoffset;
107 1.72 christos int vga_rollover;
108 1.72 christos int visibleoffset;
109 1.1 drochner };
110 1.1 drochner
111 1.1 drochner static int vgaconsole, vga_console_type, vga_console_attached;
112 1.1 drochner static struct vgascreen vga_console_screen;
113 1.1 drochner static struct vga_config vga_console_vc;
114 1.1 drochner
115 1.110 mlelstv static struct egavga_font *egavga_getfont(struct vga_config *, struct vgascreen *,
116 1.69 jdolecek const char *, int);
117 1.110 mlelstv static void egavga_unreffont(struct vga_config *, struct egavga_font *);
118 1.37 drochner
119 1.110 mlelstv static int vga_selectfont(struct vga_config *, struct vgascreen *, const char *,
120 1.69 jdolecek const char *);
121 1.110 mlelstv static void vga_init_screen(struct vga_config *, struct vgascreen *,
122 1.45 junyoung const struct wsscreen_descr *, int, long *);
123 1.110 mlelstv static void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t);
124 1.45 junyoung static void vga_setfont(struct vga_config *, struct vgascreen *);
125 1.45 junyoung
126 1.45 junyoung static int vga_mapchar(void *, int, unsigned int *);
127 1.110 mlelstv static void vga_putchar(void *, int, int, u_int, long);
128 1.59 junyoung static int vga_allocattr(void *, int, int, int, long *);
129 1.45 junyoung static void vga_copyrows(void *, int, int, int);
130 1.74 christos #ifdef WSDISPLAY_SCROLLSUPPORT
131 1.110 mlelstv static void vga_scroll (void *, void *, int);
132 1.74 christos #endif
133 1.1 drochner
134 1.1 drochner const struct wsdisplay_emulops vga_emulops = {
135 1.4 drochner pcdisplay_cursor,
136 1.12 drochner vga_mapchar,
137 1.72 christos vga_putchar,
138 1.4 drochner pcdisplay_copycols,
139 1.4 drochner pcdisplay_erasecols,
140 1.8 drochner vga_copyrows,
141 1.4 drochner pcdisplay_eraserows,
142 1.75 jmmv vga_allocattr,
143 1.75 jmmv #ifdef WSDISPLAY_CUSTOM_OUTPUT
144 1.75 jmmv pcdisplay_replaceattr,
145 1.75 jmmv #else
146 1.75 jmmv NULL,
147 1.75 jmmv #endif
148 1.3 drochner };
149 1.3 drochner
150 1.3 drochner /*
151 1.3 drochner * translate WS(=ANSI) color codes to standard pc ones
152 1.3 drochner */
153 1.35 jdolecek static const unsigned char fgansitopc[] = {
154 1.3 drochner #ifdef __alpha__
155 1.3 drochner /*
156 1.3 drochner * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
157 1.3 drochner * XXX We should probably not bother with this
158 1.3 drochner * XXX (reinitialize the palette registers).
159 1.3 drochner */
160 1.3 drochner FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, FG_RED,
161 1.3 drochner FG_MAGENTA, FG_BROWN, FG_LIGHTGREY
162 1.3 drochner #else
163 1.3 drochner FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
164 1.3 drochner FG_MAGENTA, FG_CYAN, FG_LIGHTGREY
165 1.3 drochner #endif
166 1.3 drochner }, bgansitopc[] = {
167 1.3 drochner #ifdef __alpha__
168 1.3 drochner BG_BLACK, BG_BLUE, BG_GREEN, BG_CYAN, BG_RED,
169 1.3 drochner BG_MAGENTA, BG_BROWN, BG_LIGHTGREY
170 1.3 drochner #else
171 1.3 drochner BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
172 1.3 drochner BG_MAGENTA, BG_CYAN, BG_LIGHTGREY
173 1.3 drochner #endif
174 1.1 drochner };
175 1.1 drochner
176 1.33 lukem const struct wsscreen_descr vga_25lscreen = {
177 1.1 drochner "80x25", 80, 25,
178 1.1 drochner &vga_emulops,
179 1.3 drochner 8, 16,
180 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
181 1.89 christos NULL,
182 1.33 lukem }, vga_25lscreen_mono = {
183 1.3 drochner "80x25", 80, 25,
184 1.3 drochner &vga_emulops,
185 1.3 drochner 8, 16,
186 1.89 christos WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
187 1.89 christos NULL,
188 1.33 lukem }, vga_25lscreen_bf = {
189 1.12 drochner "80x25bf", 80, 25,
190 1.12 drochner &vga_emulops,
191 1.12 drochner 8, 16,
192 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
193 1.89 christos NULL,
194 1.17 drochner }, vga_40lscreen = {
195 1.17 drochner "80x40", 80, 40,
196 1.17 drochner &vga_emulops,
197 1.17 drochner 8, 10,
198 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
199 1.89 christos NULL,
200 1.17 drochner }, vga_40lscreen_mono = {
201 1.17 drochner "80x40", 80, 40,
202 1.17 drochner &vga_emulops,
203 1.17 drochner 8, 10,
204 1.89 christos WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
205 1.89 christos NULL,
206 1.17 drochner }, vga_40lscreen_bf = {
207 1.17 drochner "80x40bf", 80, 40,
208 1.17 drochner &vga_emulops,
209 1.17 drochner 8, 10,
210 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
211 1.89 christos NULL,
212 1.12 drochner }, vga_50lscreen = {
213 1.1 drochner "80x50", 80, 50,
214 1.1 drochner &vga_emulops,
215 1.3 drochner 8, 8,
216 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
217 1.89 christos NULL,
218 1.3 drochner }, vga_50lscreen_mono = {
219 1.3 drochner "80x50", 80, 50,
220 1.3 drochner &vga_emulops,
221 1.3 drochner 8, 8,
222 1.89 christos WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
223 1.89 christos NULL,
224 1.12 drochner }, vga_50lscreen_bf = {
225 1.12 drochner "80x50bf", 80, 50,
226 1.12 drochner &vga_emulops,
227 1.12 drochner 8, 8,
228 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
229 1.89 christos NULL,
230 1.30 drochner }, vga_24lscreen = {
231 1.30 drochner "80x24", 80, 24,
232 1.30 drochner &vga_emulops,
233 1.30 drochner 8, 16,
234 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_BLINK,
235 1.89 christos NULL,
236 1.30 drochner }, vga_24lscreen_mono = {
237 1.30 drochner "80x24", 80, 24,
238 1.30 drochner &vga_emulops,
239 1.30 drochner 8, 16,
240 1.89 christos WSSCREEN_HILIT | WSSCREEN_UNDERLINE | WSSCREEN_BLINK | WSSCREEN_REVERSE,
241 1.89 christos NULL,
242 1.30 drochner }, vga_24lscreen_bf = {
243 1.30 drochner "80x24bf", 80, 24,
244 1.30 drochner &vga_emulops,
245 1.30 drochner 8, 16,
246 1.89 christos WSSCREEN_WSCOLORS | WSSCREEN_BLINK,
247 1.89 christos NULL,
248 1.1 drochner };
249 1.1 drochner
250 1.12 drochner #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
251 1.12 drochner
252 1.2 drochner const struct wsscreen_descr *_vga_scrlist[] = {
253 1.33 lukem &vga_25lscreen,
254 1.33 lukem &vga_25lscreen_bf,
255 1.17 drochner &vga_40lscreen,
256 1.17 drochner &vga_40lscreen_bf,
257 1.1 drochner &vga_50lscreen,
258 1.12 drochner &vga_50lscreen_bf,
259 1.30 drochner &vga_24lscreen,
260 1.30 drochner &vga_24lscreen_bf,
261 1.1 drochner /* XXX other formats, graphics screen? */
262 1.3 drochner }, *_vga_scrlist_mono[] = {
263 1.33 lukem &vga_25lscreen_mono,
264 1.17 drochner &vga_40lscreen_mono,
265 1.3 drochner &vga_50lscreen_mono,
266 1.30 drochner &vga_24lscreen_mono,
267 1.3 drochner /* XXX other formats, graphics screen? */
268 1.1 drochner };
269 1.1 drochner
270 1.3 drochner const struct wsscreen_list vga_screenlist = {
271 1.3 drochner sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *),
272 1.3 drochner _vga_scrlist
273 1.3 drochner }, vga_screenlist_mono = {
274 1.3 drochner sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *),
275 1.3 drochner _vga_scrlist_mono
276 1.1 drochner };
277 1.1 drochner
278 1.92 christos static int vga_ioctl(void *, void *, u_long, void *, int, struct lwp *);
279 1.86 jmmv static paddr_t vga_mmap(void *, void *, off_t, int);
280 1.45 junyoung static int vga_alloc_screen(void *, const struct wsscreen_descr *,
281 1.45 junyoung void **, int *, int *, long *);
282 1.45 junyoung static void vga_free_screen(void *, void *);
283 1.45 junyoung static int vga_show_screen(void *, void *, int,
284 1.45 junyoung void (*)(void *, int, int), void *);
285 1.45 junyoung static int vga_load_font(void *, void *, struct wsdisplay_font *);
286 1.76 jmmv #ifdef WSDISPLAY_CUSTOM_BORDER
287 1.85 drochner static int vga_getborder(struct vga_config *, u_int *);
288 1.85 drochner static int vga_setborder(struct vga_config *, u_int);
289 1.76 jmmv #endif /* WSDISPLAY_CUSTOM_BORDER */
290 1.1 drochner
291 1.110 mlelstv static void vga_doswitch(struct vga_config *);
292 1.110 mlelstv static void vga_save_palette(struct vga_config *);
293 1.110 mlelstv static void vga_restore_palette(struct vga_config *);
294 1.110 mlelstv
295 1.22 drochner
296 1.1 drochner const struct wsdisplay_accessops vga_accessops = {
297 1.1 drochner vga_ioctl,
298 1.1 drochner vga_mmap,
299 1.1 drochner vga_alloc_screen,
300 1.1 drochner vga_free_screen,
301 1.1 drochner vga_show_screen,
302 1.53 christos vga_load_font,
303 1.53 christos NULL,
304 1.73 christos #ifdef WSDISPLAY_SCROLLSUPPORT
305 1.73 christos vga_scroll,
306 1.73 christos #else
307 1.73 christos NULL,
308 1.73 christos #endif
309 1.1 drochner };
310 1.1 drochner
311 1.12 drochner /*
312 1.15 drochner * We want at least ASCII 32..127 be present in the
313 1.15 drochner * first font slot.
314 1.12 drochner */
315 1.12 drochner #define vga_valid_primary_font(f) \
316 1.37 drochner (f->wsfont->encoding == WSDISPLAY_FONTENC_IBM || \
317 1.37 drochner f->wsfont->encoding == WSDISPLAY_FONTENC_ISO || \
318 1.107 drochner f->wsfont->encoding == WSDISPLAY_FONTENC_ISO2 || \
319 1.107 drochner f->wsfont->encoding == WSDISPLAY_FONTENC_ISO7 || \
320 1.107 drochner f->wsfont->encoding == WSDISPLAY_FONTENC_KOI8_R)
321 1.37 drochner
322 1.110 mlelstv static struct egavga_font *
323 1.69 jdolecek egavga_getfont(struct vga_config *vc, struct vgascreen *scr, const char *name,
324 1.45 junyoung int primary)
325 1.37 drochner {
326 1.37 drochner struct egavga_font *f;
327 1.37 drochner int cookie;
328 1.37 drochner struct wsdisplay_font *wf;
329 1.37 drochner
330 1.37 drochner TAILQ_FOREACH(f, &vc->vc_fontlist, next) {
331 1.37 drochner if (wsfont_matches(f->wsfont, name,
332 1.108 macallan 8, scr->pcs.type->fontheight, 0, WSFONT_FIND_BITMAP) &&
333 1.37 drochner (!primary || vga_valid_primary_font(f))) {
334 1.37 drochner #ifdef VGAFONTDEBUG
335 1.37 drochner if (scr != &vga_console_screen || vga_console_attached)
336 1.37 drochner printf("vga_getfont: %s already present\n",
337 1.66 tsutsui name ? name : "<default>");
338 1.37 drochner #endif
339 1.37 drochner goto found;
340 1.37 drochner }
341 1.37 drochner }
342 1.37 drochner
343 1.48 ad cookie = wsfont_find(name, 8, scr->pcs.type->fontheight, 0,
344 1.108 macallan WSDISPLAY_FONTORDER_L2R, 0, WSFONT_FIND_BITMAP);
345 1.37 drochner /* XXX obey "primary" */
346 1.37 drochner if (cookie == -1) {
347 1.37 drochner #ifdef VGAFONTDEBUG
348 1.37 drochner if (scr != &vga_console_screen || vga_console_attached)
349 1.51 drochner printf("vga_getfont: %s not found\n",
350 1.66 tsutsui name ? name : "<default>");
351 1.37 drochner #endif
352 1.37 drochner return (0);
353 1.37 drochner }
354 1.37 drochner
355 1.47 ad if (wsfont_lock(cookie, &wf))
356 1.37 drochner return (0);
357 1.37 drochner
358 1.38 drochner #ifdef VGA_CONSOLE_SCREENTYPE
359 1.38 drochner if (scr == &vga_console_screen)
360 1.38 drochner f = &vga_consolefont;
361 1.38 drochner else
362 1.38 drochner #endif
363 1.116 chs f = malloc(sizeof(struct egavga_font), M_DEVBUF, M_WAITOK);
364 1.37 drochner f->wsfont = wf;
365 1.37 drochner f->cookie = cookie;
366 1.37 drochner f->slot = -1; /* not yet loaded */
367 1.37 drochner f->usecount = 0; /* incremented below */
368 1.37 drochner TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
369 1.37 drochner
370 1.37 drochner found:
371 1.37 drochner f->usecount++;
372 1.37 drochner #ifdef VGAFONTDEBUG
373 1.37 drochner if (scr != &vga_console_screen || vga_console_attached)
374 1.37 drochner printf("vga_getfont: usecount=%d\n", f->usecount);
375 1.37 drochner #endif
376 1.37 drochner return (f);
377 1.37 drochner }
378 1.37 drochner
379 1.110 mlelstv static void
380 1.45 junyoung egavga_unreffont(struct vga_config *vc, struct egavga_font *f)
381 1.37 drochner {
382 1.37 drochner
383 1.37 drochner f->usecount--;
384 1.37 drochner #ifdef VGAFONTDEBUG
385 1.37 drochner printf("vga_unreffont: usecount=%d\n", f->usecount);
386 1.37 drochner #endif
387 1.58 drochner if (f->usecount == 0 && f->cookie != -1) {
388 1.37 drochner TAILQ_REMOVE(&vc->vc_fontlist, f, next);
389 1.41 drochner if (f->slot != -1) {
390 1.41 drochner KASSERT(vc->vc_fonts[f->slot] == f);
391 1.41 drochner vc->vc_fonts[f->slot] = 0;
392 1.41 drochner }
393 1.37 drochner wsfont_unlock(f->cookie);
394 1.38 drochner #ifdef VGA_CONSOLE_SCREENTYPE
395 1.38 drochner if (f != &vga_consolefont)
396 1.38 drochner #endif
397 1.37 drochner free(f, M_DEVBUF);
398 1.37 drochner }
399 1.37 drochner }
400 1.12 drochner
401 1.110 mlelstv static int
402 1.69 jdolecek vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1,
403 1.69 jdolecek const char *name2)
404 1.12 drochner {
405 1.12 drochner const struct wsscreen_descr *type = scr->pcs.type;
406 1.37 drochner struct egavga_font *f1, *f2;
407 1.12 drochner
408 1.37 drochner f1 = egavga_getfont(vc, scr, name1, 1);
409 1.37 drochner if (!f1)
410 1.37 drochner return (ENXIO);
411 1.12 drochner
412 1.37 drochner if (VGA_SCREEN_CANTWOFONTS(type) && name2) {
413 1.37 drochner f2 = egavga_getfont(vc, scr, name2, 0);
414 1.37 drochner if (!f2) {
415 1.37 drochner egavga_unreffont(vc, f1);
416 1.37 drochner return (ENXIO);
417 1.12 drochner }
418 1.37 drochner } else
419 1.37 drochner f2 = 0;
420 1.12 drochner
421 1.12 drochner #ifdef VGAFONTDEBUG
422 1.37 drochner if (scr != &vga_console_screen || vga_console_attached) {
423 1.37 drochner printf("vga (%s): font1=%s (slot %d)", type->name,
424 1.66 tsutsui f1->wsfont->name, f1->slot);
425 1.37 drochner if (f2)
426 1.37 drochner printf(", font2=%s (slot %d)",
427 1.66 tsutsui f2->wsfont->name, f2->slot);
428 1.37 drochner printf("\n");
429 1.37 drochner }
430 1.12 drochner #endif
431 1.37 drochner if (scr->fontset1)
432 1.37 drochner egavga_unreffont(vc, scr->fontset1);
433 1.37 drochner scr->fontset1 = f1;
434 1.37 drochner if (scr->fontset2)
435 1.37 drochner egavga_unreffont(vc, scr->fontset2);
436 1.37 drochner scr->fontset2 = f2;
437 1.37 drochner return (0);
438 1.12 drochner }
439 1.12 drochner
440 1.110 mlelstv static void
441 1.45 junyoung vga_init_screen(struct vga_config *vc, struct vgascreen *scr,
442 1.45 junyoung const struct wsscreen_descr *type, int existing, long *attrp)
443 1.1 drochner {
444 1.8 drochner int cpos;
445 1.111 christos int res __diagused;
446 1.1 drochner
447 1.4 drochner scr->cfg = vc;
448 1.4 drochner scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
449 1.4 drochner scr->pcs.type = type;
450 1.39 drochner scr->pcs.active = existing;
451 1.8 drochner scr->mindispoffset = 0;
452 1.63 drochner if (vc->vc_quirks & VGA_QUIRK_NOFASTSCROLL)
453 1.63 drochner scr->maxdispoffset = 0;
454 1.63 drochner else
455 1.63 drochner scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
456 1.1 drochner
457 1.1 drochner if (existing) {
458 1.39 drochner vc->active = scr;
459 1.39 drochner
460 1.1 drochner cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
461 1.1 drochner cpos |= vga_6845_read(&vc->hdl, cursorl);
462 1.1 drochner
463 1.1 drochner /* make sure we have a valid cursor position */
464 1.1 drochner if (cpos < 0 || cpos >= type->nrows * type->ncols)
465 1.1 drochner cpos = 0;
466 1.8 drochner
467 1.8 drochner scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
468 1.8 drochner scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
469 1.8 drochner
470 1.8 drochner /* make sure we have a valid memory offset */
471 1.8 drochner if (scr->pcs.dispoffset < scr->mindispoffset ||
472 1.8 drochner scr->pcs.dispoffset > scr->maxdispoffset)
473 1.8 drochner scr->pcs.dispoffset = scr->mindispoffset;
474 1.40 drochner
475 1.40 drochner if (type != vc->currenttype) {
476 1.40 drochner vga_setscreentype(&vc->hdl, type);
477 1.40 drochner vc->currenttype = type;
478 1.40 drochner }
479 1.8 drochner } else {
480 1.8 drochner cpos = 0;
481 1.8 drochner scr->pcs.dispoffset = scr->mindispoffset;
482 1.1 drochner }
483 1.1 drochner
484 1.72 christos scr->pcs.visibleoffset = scr->pcs.dispoffset;
485 1.72 christos scr->vga_rollover = 0;
486 1.72 christos
487 1.60 junyoung scr->pcs.cursorrow = cpos / type->ncols;
488 1.60 junyoung scr->pcs.cursorcol = cpos % type->ncols;
489 1.25 ad pcdisplay_cursor_init(&scr->pcs, existing);
490 1.1 drochner
491 1.1 drochner #ifdef __alpha__
492 1.4 drochner if (!vc->hdl.vh_mono)
493 1.3 drochner /*
494 1.3 drochner * DEC firmware uses a blue background.
495 1.75 jmmv * XXX These should be specified as kernel options for
496 1.75 jmmv * XXX alpha only, not hardcoded here (which is wrong
497 1.75 jmmv * XXX anyway because the emulation layer will assume
498 1.75 jmmv * XXX the default attribute is white on black).
499 1.3 drochner */
500 1.59 junyoung res = vga_allocattr(scr, WSCOL_WHITE, WSCOL_BLUE,
501 1.66 tsutsui WSATTR_WSCOLORS, attrp);
502 1.3 drochner else
503 1.3 drochner #endif
504 1.59 junyoung res = vga_allocattr(scr, 0, 0, 0, attrp);
505 1.3 drochner #ifdef DIAGNOSTIC
506 1.3 drochner if (res)
507 1.3 drochner panic("vga_init_screen: attribute botch");
508 1.1 drochner #endif
509 1.1 drochner
510 1.4 drochner scr->pcs.mem = NULL;
511 1.15 drochner
512 1.15 drochner scr->fontset1 = scr->fontset2 = 0;
513 1.12 drochner if (vga_selectfont(vc, scr, 0, 0)) {
514 1.12 drochner if (scr == &vga_console_screen)
515 1.12 drochner panic("vga_init_screen: no font");
516 1.12 drochner else
517 1.12 drochner printf("vga_init_screen: no font\n");
518 1.12 drochner }
519 1.40 drochner if (existing)
520 1.40 drochner vga_setfont(vc, scr);
521 1.15 drochner
522 1.1 drochner vc->nscreens++;
523 1.1 drochner LIST_INSERT_HEAD(&vc->screens, scr, next);
524 1.1 drochner }
525 1.1 drochner
526 1.110 mlelstv static void
527 1.45 junyoung vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt)
528 1.1 drochner {
529 1.1 drochner struct vga_handle *vh = &vc->hdl;
530 1.106 christos uint8_t mor;
531 1.12 drochner int i;
532 1.1 drochner
533 1.66 tsutsui vh->vh_iot = iot;
534 1.66 tsutsui vh->vh_memt = memt;
535 1.1 drochner
536 1.66 tsutsui if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
537 1.66 tsutsui panic("vga_init: couldn't map vga io");
538 1.1 drochner
539 1.1 drochner /* read "misc output register" */
540 1.106 christos mor = vga_raw_read(vh, VGA_MISC_DATAR);
541 1.4 drochner vh->vh_mono = !(mor & 1);
542 1.1 drochner
543 1.4 drochner if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
544 1.66 tsutsui &vh->vh_ioh_6845))
545 1.66 tsutsui panic("vga_init: couldn't map 6845 io");
546 1.1 drochner
547 1.117 ad if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000,
548 1.118 ad BUS_SPACE_MAP_CACHEABLE, &vh->vh_allmemh))
549 1.66 tsutsui panic("vga_init: couldn't map memory");
550 1.1 drochner
551 1.66 tsutsui if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
552 1.66 tsutsui (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, &vh->vh_memh))
553 1.66 tsutsui panic("vga_init: mem subrange failed");
554 1.5 drochner
555 1.1 drochner vc->nscreens = 0;
556 1.1 drochner LIST_INIT(&vc->screens);
557 1.1 drochner vc->active = NULL;
558 1.34 drochner vc->currenttype = vh->vh_mono ? &vga_25lscreen_mono : &vga_25lscreen;
559 1.93 ad callout_init(&vc->vc_switch_callout, 0);
560 1.12 drochner
561 1.68 tsutsui wsfont_init();
562 1.68 tsutsui if (vga_no_builtinfont) {
563 1.68 tsutsui struct wsdisplay_font *wf;
564 1.68 tsutsui int cookie;
565 1.68 tsutsui
566 1.68 tsutsui cookie = wsfont_find(NULL, 8, 16, 0,
567 1.108 macallan WSDISPLAY_FONTORDER_L2R, 0, WSFONT_FIND_BITMAP);
568 1.68 tsutsui if (cookie == -1 || wsfont_lock(cookie, &wf))
569 1.68 tsutsui panic("vga_init: can't load console font");
570 1.68 tsutsui vga_loadchars(&vc->hdl, 0, wf->firstchar, wf->numchars,
571 1.68 tsutsui wf->fontheight, wf->data);
572 1.68 tsutsui vga_builtinfont.wsfont = wf;
573 1.68 tsutsui vga_builtinfont.cookie = cookie;
574 1.68 tsutsui vga_builtinfont.slot = 0;
575 1.68 tsutsui }
576 1.12 drochner vc->vc_fonts[0] = &vga_builtinfont;
577 1.23 drochner for (i = 1; i < 8; i++)
578 1.12 drochner vc->vc_fonts[i] = 0;
579 1.37 drochner TAILQ_INIT(&vc->vc_fontlist);
580 1.37 drochner TAILQ_INSERT_HEAD(&vc->vc_fontlist, &vga_builtinfont, next);
581 1.12 drochner
582 1.12 drochner vc->currentfontset1 = vc->currentfontset2 = 0;
583 1.76 jmmv
584 1.78 jmmv if (!vh->vh_mono && (u_int)WSDISPLAY_BORDER_COLOR < sizeof(fgansitopc))
585 1.78 jmmv _vga_attr_write(vh, VGA_ATC_OVERSCAN,
586 1.78 jmmv fgansitopc[WSDISPLAY_BORDER_COLOR]);
587 1.106 christos vga_save_palette(vc);
588 1.1 drochner }
589 1.1 drochner
590 1.1 drochner void
591 1.45 junyoung vga_common_attach(struct vga_softc *sc, bus_space_tag_t iot,
592 1.56 drochner bus_space_tag_t memt, int type, int quirks,
593 1.56 drochner const struct vga_funcs *vf)
594 1.28 soda {
595 1.1 drochner int console;
596 1.1 drochner struct vga_config *vc;
597 1.1 drochner struct wsemuldisplaydev_attach_args aa;
598 1.1 drochner
599 1.1 drochner console = vga_is_console(iot, type);
600 1.1 drochner
601 1.1 drochner if (console) {
602 1.1 drochner vc = &vga_console_vc;
603 1.1 drochner vga_console_attached = 1;
604 1.1 drochner } else {
605 1.1 drochner vc = malloc(sizeof(struct vga_config), M_DEVBUF, M_WAITOK);
606 1.1 drochner vga_init(vc, iot, memt);
607 1.1 drochner }
608 1.1 drochner
609 1.58 drochner if (quirks & VGA_QUIRK_ONEFONT) {
610 1.58 drochner vc->vc_nfontslots = 1;
611 1.58 drochner #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
612 1.58 drochner /*
613 1.58 drochner * XXX maybe invalidate font in slot > 0, but this can
614 1.58 drochner * only be happen with VGA_CONSOLE_SCREENTYPE, and then
615 1.58 drochner * we require VGA_CONSOLE_ATI_BROKEN_FONTSEL anyway.
616 1.58 drochner */
617 1.58 drochner #endif
618 1.58 drochner } else {
619 1.58 drochner vc->vc_nfontslots = 8;
620 1.58 drochner #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
621 1.58 drochner /*
622 1.58 drochner * XXX maybe validate builtin font shifted to slot 1 if
623 1.58 drochner * slot 0 got overwritten because of VGA_CONSOLE_SCREENTYPE,
624 1.58 drochner * but it will be reloaded anyway if needed.
625 1.58 drochner */
626 1.58 drochner #endif
627 1.58 drochner }
628 1.58 drochner
629 1.58 drochner /*
630 1.58 drochner * Save the builtin font to memory. In case it got overwritten
631 1.58 drochner * in console initialization, use the copy in slot 1.
632 1.58 drochner */
633 1.58 drochner #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
634 1.58 drochner #define BUILTINFONTLOC (vga_builtinfont.slot == -1 ? 1 : 0)
635 1.58 drochner #else
636 1.58 drochner KASSERT(vga_builtinfont.slot == 0);
637 1.58 drochner #define BUILTINFONTLOC (0)
638 1.58 drochner #endif
639 1.68 tsutsui if (!vga_no_builtinfont) {
640 1.69 jdolecek char *data =
641 1.68 tsutsui malloc(256 * vga_builtinfont.wsfont->fontheight,
642 1.68 tsutsui M_DEVBUF, M_WAITOK);
643 1.68 tsutsui vga_readoutchars(&vc->hdl, BUILTINFONTLOC, 0, 256,
644 1.69 jdolecek vga_builtinfont.wsfont->fontheight, data);
645 1.69 jdolecek vga_builtinfont.wsfont->data = data;
646 1.68 tsutsui }
647 1.56 drochner
648 1.42 thorpej vc->vc_type = type;
649 1.42 thorpej vc->vc_funcs = vf;
650 1.63 drochner vc->vc_quirks = quirks;
651 1.42 thorpej
652 1.42 thorpej sc->sc_vc = vc;
653 1.42 thorpej vc->softc = sc;
654 1.28 soda
655 1.1 drochner aa.console = console;
656 1.4 drochner aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
657 1.1 drochner aa.accessops = &vga_accessops;
658 1.1 drochner aa.accesscookie = vc;
659 1.1 drochner
660 1.119 thorpej config_found(sc->sc_dev, &aa, wsemuldisplaydevprint,
661 1.120 thorpej CFARGS(.iattr = "wsemuldisplaydev"));
662 1.1 drochner }
663 1.1 drochner
664 1.1 drochner int
665 1.45 junyoung vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
666 1.1 drochner {
667 1.3 drochner long defattr;
668 1.3 drochner const struct wsscreen_descr *scr;
669 1.3 drochner
670 1.1 drochner if (check && !vga_common_probe(iot, memt))
671 1.1 drochner return (ENXIO);
672 1.1 drochner
673 1.1 drochner /* set up bus-independent VGA configuration */
674 1.1 drochner vga_init(&vga_console_vc, iot, memt);
675 1.34 drochner #ifdef VGA_CONSOLE_SCREENTYPE
676 1.34 drochner scr = wsdisplay_screentype_pick(vga_console_vc.hdl.vh_mono ?
677 1.66 tsutsui &vga_screenlist_mono : &vga_screenlist, VGA_CONSOLE_SCREENTYPE);
678 1.34 drochner if (!scr)
679 1.34 drochner panic("vga_cnattach: invalid screen type");
680 1.34 drochner #else
681 1.11 drochner scr = vga_console_vc.currenttype;
682 1.34 drochner #endif
683 1.56 drochner #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
684 1.56 drochner /*
685 1.56 drochner * On some (most/all?) ATI cards, only font slot 0 is usable.
686 1.56 drochner * vga_init_screen() might need font slot 0 for a non-default
687 1.58 drochner * console font, so save the builtin VGA font to another font slot.
688 1.58 drochner * The attach() code will take care later.
689 1.56 drochner */
690 1.63 drochner vga_console_vc.vc_quirks |= VGA_QUIRK_ONEFONT; /* redundant */
691 1.56 drochner vga_copyfont01(&vga_console_vc.hdl);
692 1.56 drochner vga_console_vc.vc_nfontslots = 1;
693 1.56 drochner #else
694 1.56 drochner vga_console_vc.vc_nfontslots = 8;
695 1.56 drochner #endif
696 1.79 christos #ifdef notdef
697 1.63 drochner /* until we know better, assume "fast scrolling" does not work */
698 1.63 drochner vga_console_vc.vc_quirks |= VGA_QUIRK_NOFASTSCROLL;
699 1.79 christos #endif
700 1.63 drochner
701 1.4 drochner vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
702 1.1 drochner
703 1.3 drochner wsdisplay_cnattach(scr, &vga_console_screen,
704 1.66 tsutsui vga_console_screen.pcs.cursorcol,
705 1.66 tsutsui vga_console_screen.pcs.cursorrow, defattr);
706 1.1 drochner
707 1.1 drochner vgaconsole = 1;
708 1.1 drochner vga_console_type = type;
709 1.1 drochner return (0);
710 1.1 drochner }
711 1.1 drochner
712 1.1 drochner int
713 1.88 jmcneill vga_cndetach(void)
714 1.88 jmcneill {
715 1.88 jmcneill struct vga_config *vc;
716 1.88 jmcneill struct vga_handle *vh;
717 1.88 jmcneill
718 1.88 jmcneill vc = &vga_console_vc;
719 1.88 jmcneill vh = &vc->hdl;
720 1.88 jmcneill
721 1.88 jmcneill if (vgaconsole) {
722 1.112 mlelstv wsdisplay_cndetach();
723 1.112 mlelstv
724 1.88 jmcneill bus_space_unmap(vh->vh_iot, vh->vh_ioh_vga, 0x10);
725 1.88 jmcneill bus_space_unmap(vh->vh_iot, vh->vh_ioh_6845, 0x10);
726 1.115 mlelstv bus_space_unmap(vh->vh_memt, vh->vh_allmemh, 0x20000);
727 1.88 jmcneill
728 1.112 mlelstv vga_console_attached = 0;
729 1.112 mlelstv vgaconsole = 0;
730 1.112 mlelstv
731 1.88 jmcneill return 1;
732 1.88 jmcneill }
733 1.88 jmcneill
734 1.88 jmcneill return 0;
735 1.88 jmcneill }
736 1.88 jmcneill
737 1.88 jmcneill int
738 1.45 junyoung vga_is_console(bus_space_tag_t iot, int type)
739 1.1 drochner {
740 1.1 drochner if (vgaconsole &&
741 1.1 drochner !vga_console_attached &&
742 1.104 dyoung bus_space_is_equal(iot, vga_console_vc.hdl.vh_iot) &&
743 1.1 drochner (vga_console_type == -1 || (type == vga_console_type)))
744 1.1 drochner return (1);
745 1.1 drochner return (0);
746 1.1 drochner }
747 1.1 drochner
748 1.46 lukem static int
749 1.46 lukem vga_get_video(struct vga_config *vc)
750 1.46 lukem {
751 1.67 tsutsui
752 1.67 tsutsui return (vga_ts_read(&vc->hdl, mode) & VGA_TS_MODE_BLANK) == 0;
753 1.46 lukem }
754 1.46 lukem
755 1.46 lukem static void
756 1.46 lukem vga_set_video(struct vga_config *vc, int state)
757 1.46 lukem {
758 1.46 lukem int val;
759 1.46 lukem
760 1.46 lukem vga_ts_write(&vc->hdl, syncreset, 0x01);
761 1.46 lukem if (state) { /* unblank screen */
762 1.46 lukem val = vga_ts_read(&vc->hdl, mode);
763 1.67 tsutsui vga_ts_write(&vc->hdl, mode, val & ~VGA_TS_MODE_BLANK);
764 1.46 lukem #ifndef VGA_NO_VBLANK
765 1.46 lukem val = vga_6845_read(&vc->hdl, mode);
766 1.46 lukem vga_6845_write(&vc->hdl, mode, val | 0x80);
767 1.46 lukem #endif
768 1.46 lukem } else { /* blank screen */
769 1.46 lukem val = vga_ts_read(&vc->hdl, mode);
770 1.67 tsutsui vga_ts_write(&vc->hdl, mode, val | VGA_TS_MODE_BLANK);
771 1.46 lukem #ifndef VGA_NO_VBLANK
772 1.46 lukem val = vga_6845_read(&vc->hdl, mode);
773 1.46 lukem vga_6845_write(&vc->hdl, mode, val & ~0x80);
774 1.46 lukem #endif
775 1.46 lukem }
776 1.46 lukem vga_ts_write(&vc->hdl, syncreset, 0x03);
777 1.46 lukem }
778 1.46 lukem
779 1.110 mlelstv static int
780 1.92 christos vga_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
781 1.1 drochner {
782 1.1 drochner struct vga_config *vc = v;
783 1.87 jmmv struct vgascreen *scr = vs;
784 1.42 thorpej const struct vga_funcs *vf = vc->vc_funcs;
785 1.1 drochner
786 1.1 drochner switch (cmd) {
787 1.106 christos case WSDISPLAYIO_SMODE:
788 1.106 christos if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL)
789 1.106 christos vga_restore_palette(vc);
790 1.106 christos return 0;
791 1.106 christos
792 1.1 drochner case WSDISPLAYIO_GTYPE:
793 1.1 drochner *(int *)data = vc->vc_type;
794 1.10 augustss return 0;
795 1.12 drochner
796 1.1 drochner case WSDISPLAYIO_GINFO:
797 1.42 thorpej /* XXX should get detailed hardware information here */
798 1.49 atatat return EPASSTHROUGH;
799 1.42 thorpej
800 1.46 lukem case WSDISPLAYIO_GVIDEO:
801 1.66 tsutsui *(int *)data = (vga_get_video(vc) ?
802 1.66 tsutsui WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF);
803 1.46 lukem return 0;
804 1.46 lukem
805 1.46 lukem case WSDISPLAYIO_SVIDEO:
806 1.46 lukem vga_set_video(vc, *(int *)data == WSDISPLAYIO_VIDEO_ON);
807 1.46 lukem return 0;
808 1.46 lukem
809 1.87 jmmv case WSDISPLAYIO_GETWSCHAR:
810 1.87 jmmv KASSERT(scr != NULL);
811 1.87 jmmv return pcdisplay_getwschar(&scr->pcs,
812 1.87 jmmv (struct wsdisplay_char *)data);
813 1.87 jmmv
814 1.87 jmmv case WSDISPLAYIO_PUTWSCHAR:
815 1.87 jmmv KASSERT(scr != NULL);
816 1.87 jmmv return pcdisplay_putwschar(&scr->pcs,
817 1.87 jmmv (struct wsdisplay_char *)data);
818 1.87 jmmv
819 1.85 drochner #ifdef WSDISPLAY_CUSTOM_BORDER
820 1.85 drochner case WSDISPLAYIO_GBORDER:
821 1.85 drochner return (vga_getborder(vc, (u_int *)data));
822 1.85 drochner
823 1.85 drochner case WSDISPLAYIO_SBORDER:
824 1.85 drochner return (vga_setborder(vc, *(u_int *)data));
825 1.85 drochner #endif
826 1.85 drochner
827 1.1 drochner case WSDISPLAYIO_GETCMAP:
828 1.1 drochner case WSDISPLAYIO_PUTCMAP:
829 1.1 drochner case WSDISPLAYIO_GCURPOS:
830 1.1 drochner case WSDISPLAYIO_SCURPOS:
831 1.1 drochner case WSDISPLAYIO_GCURMAX:
832 1.1 drochner case WSDISPLAYIO_GCURSOR:
833 1.1 drochner case WSDISPLAYIO_SCURSOR:
834 1.1 drochner /* NONE of these operations are by the generic VGA driver. */
835 1.49 atatat return EPASSTHROUGH;
836 1.1 drochner }
837 1.12 drochner
838 1.42 thorpej if (vc->vc_funcs == NULL)
839 1.49 atatat return (EPASSTHROUGH);
840 1.42 thorpej
841 1.42 thorpej if (vf->vf_ioctl == NULL)
842 1.49 atatat return (EPASSTHROUGH);
843 1.42 thorpej
844 1.83 christos return ((*vf->vf_ioctl)(v, cmd, data, flag, l));
845 1.1 drochner }
846 1.1 drochner
847 1.29 simonb static paddr_t
848 1.91 christos vga_mmap(void *v, void *vs, off_t offset, int prot)
849 1.1 drochner {
850 1.42 thorpej struct vga_config *vc = v;
851 1.42 thorpej const struct vga_funcs *vf = vc->vc_funcs;
852 1.1 drochner
853 1.42 thorpej if (vc->vc_funcs == NULL)
854 1.42 thorpej return (-1);
855 1.28 soda
856 1.42 thorpej if (vf->vf_mmap == NULL)
857 1.42 thorpej return (-1);
858 1.32 thorpej
859 1.42 thorpej return ((*vf->vf_mmap)(v, offset, prot));
860 1.1 drochner }
861 1.1 drochner
862 1.110 mlelstv static int
863 1.45 junyoung vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
864 1.45 junyoung int *curxp, int *curyp, long *defattrp)
865 1.1 drochner {
866 1.1 drochner struct vga_config *vc = v;
867 1.1 drochner struct vgascreen *scr;
868 1.1 drochner
869 1.1 drochner if (vc->nscreens == 1) {
870 1.38 drochner struct vgascreen *scr1 = vc->screens.lh_first;
871 1.1 drochner /*
872 1.1 drochner * When allocating the second screen, get backing store
873 1.1 drochner * for the first one too.
874 1.1 drochner * XXX We could be more clever and use video RAM.
875 1.1 drochner */
876 1.38 drochner scr1->pcs.mem =
877 1.66 tsutsui malloc(scr1->pcs.type->ncols * scr1->pcs.type->nrows * 2,
878 1.66 tsutsui M_DEVBUF, M_WAITOK);
879 1.1 drochner }
880 1.1 drochner
881 1.1 drochner scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
882 1.4 drochner vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
883 1.1 drochner
884 1.39 drochner if (vc->nscreens > 1) {
885 1.4 drochner scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
886 1.66 tsutsui M_DEVBUF, M_WAITOK);
887 1.4 drochner pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
888 1.1 drochner }
889 1.1 drochner
890 1.1 drochner *cookiep = scr;
891 1.60 junyoung *curxp = scr->pcs.cursorcol;
892 1.60 junyoung *curyp = scr->pcs.cursorrow;
893 1.1 drochner
894 1.1 drochner return (0);
895 1.1 drochner }
896 1.1 drochner
897 1.110 mlelstv static void
898 1.91 christos vga_free_screen(void *v, void *cookie)
899 1.1 drochner {
900 1.1 drochner struct vgascreen *vs = cookie;
901 1.11 drochner struct vga_config *vc = vs->cfg;
902 1.1 drochner
903 1.1 drochner LIST_REMOVE(vs, next);
904 1.82 dbj vc->nscreens--;
905 1.38 drochner if (vs->fontset1)
906 1.38 drochner egavga_unreffont(vc, vs->fontset1);
907 1.38 drochner if (vs->fontset2)
908 1.38 drochner egavga_unreffont(vc, vs->fontset2);
909 1.38 drochner
910 1.1 drochner if (vs != &vga_console_screen)
911 1.1 drochner free(vs, M_DEVBUF);
912 1.1 drochner else
913 1.1 drochner panic("vga_free_screen: console");
914 1.11 drochner
915 1.11 drochner if (vc->active == vs)
916 1.11 drochner vc->active = 0;
917 1.1 drochner }
918 1.1 drochner
919 1.40 drochner static void vga_usefont(struct vga_config *, struct egavga_font *);
920 1.37 drochner
921 1.40 drochner static void
922 1.45 junyoung vga_usefont(struct vga_config *vc, struct egavga_font *f)
923 1.37 drochner {
924 1.37 drochner int slot;
925 1.37 drochner struct egavga_font *of;
926 1.37 drochner
927 1.37 drochner if (f->slot != -1)
928 1.37 drochner goto toend;
929 1.37 drochner
930 1.51 drochner for (slot = 0; slot < vc->vc_nfontslots; slot++) {
931 1.37 drochner if (!vc->vc_fonts[slot])
932 1.37 drochner goto loadit;
933 1.37 drochner }
934 1.37 drochner
935 1.37 drochner /* have to kick out another one */
936 1.37 drochner TAILQ_FOREACH(of, &vc->vc_fontlist, next) {
937 1.37 drochner if (of->slot != -1) {
938 1.37 drochner KASSERT(vc->vc_fonts[of->slot] == of);
939 1.37 drochner slot = of->slot;
940 1.37 drochner of->slot = -1;
941 1.37 drochner goto loadit;
942 1.37 drochner }
943 1.37 drochner }
944 1.54 junyoung panic("vga_usefont");
945 1.37 drochner
946 1.37 drochner loadit:
947 1.52 drochner vga_loadchars(&vc->hdl, slot, f->wsfont->firstchar,
948 1.66 tsutsui f->wsfont->numchars, f->wsfont->fontheight, f->wsfont->data);
949 1.37 drochner f->slot = slot;
950 1.37 drochner vc->vc_fonts[slot] = f;
951 1.37 drochner
952 1.37 drochner toend:
953 1.37 drochner TAILQ_REMOVE(&vc->vc_fontlist, f, next);
954 1.37 drochner TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
955 1.37 drochner }
956 1.37 drochner
957 1.12 drochner static void
958 1.45 junyoung vga_setfont(struct vga_config *vc, struct vgascreen *scr)
959 1.12 drochner {
960 1.12 drochner int fontslot1, fontslot2;
961 1.12 drochner
962 1.37 drochner if (scr->fontset1)
963 1.37 drochner vga_usefont(vc, scr->fontset1);
964 1.37 drochner if (scr->fontset2)
965 1.37 drochner vga_usefont(vc, scr->fontset2);
966 1.37 drochner
967 1.12 drochner fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
968 1.12 drochner fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
969 1.12 drochner if (vc->currentfontset1 != fontslot1 ||
970 1.12 drochner vc->currentfontset2 != fontslot2) {
971 1.12 drochner vga_setfontset(&vc->hdl, fontslot1, fontslot2);
972 1.12 drochner vc->currentfontset1 = fontslot1;
973 1.12 drochner vc->currentfontset2 = fontslot2;
974 1.12 drochner }
975 1.12 drochner }
976 1.12 drochner
977 1.110 mlelstv static int
978 1.91 christos vga_show_screen(void *v, void *cookie, int waitok,
979 1.45 junyoung void (*cb)(void *, int, int), void *cbarg)
980 1.1 drochner {
981 1.4 drochner struct vgascreen *scr = cookie, *oldscr;
982 1.1 drochner struct vga_config *vc = scr->cfg;
983 1.22 drochner
984 1.22 drochner oldscr = vc->active; /* can be NULL! */
985 1.22 drochner if (scr == oldscr) {
986 1.22 drochner return (0);
987 1.22 drochner }
988 1.22 drochner
989 1.22 drochner vc->wantedscreen = cookie;
990 1.22 drochner vc->switchcb = cb;
991 1.22 drochner vc->switchcbarg = cbarg;
992 1.22 drochner if (cb) {
993 1.26 thorpej callout_reset(&vc->vc_switch_callout, 0,
994 1.26 thorpej (void(*)(void *))vga_doswitch, vc);
995 1.22 drochner return (EAGAIN);
996 1.22 drochner }
997 1.22 drochner
998 1.22 drochner vga_doswitch(vc);
999 1.22 drochner return (0);
1000 1.22 drochner }
1001 1.22 drochner
1002 1.110 mlelstv static void
1003 1.45 junyoung vga_doswitch(struct vga_config *vc)
1004 1.22 drochner {
1005 1.22 drochner struct vgascreen *scr, *oldscr;
1006 1.1 drochner struct vga_handle *vh = &vc->hdl;
1007 1.22 drochner const struct wsscreen_descr *type;
1008 1.1 drochner
1009 1.22 drochner scr = vc->wantedscreen;
1010 1.22 drochner if (!scr) {
1011 1.22 drochner printf("vga_doswitch: disappeared\n");
1012 1.22 drochner (*vc->switchcb)(vc->switchcbarg, EIO, 0);
1013 1.22 drochner return;
1014 1.22 drochner }
1015 1.22 drochner type = scr->pcs.type;
1016 1.11 drochner oldscr = vc->active; /* can be NULL! */
1017 1.4 drochner #ifdef DIAGNOSTIC
1018 1.11 drochner if (oldscr) {
1019 1.11 drochner if (!oldscr->pcs.active)
1020 1.11 drochner panic("vga_show_screen: not active");
1021 1.11 drochner if (oldscr->pcs.type != vc->currenttype)
1022 1.11 drochner panic("vga_show_screen: bad type");
1023 1.11 drochner }
1024 1.4 drochner #endif
1025 1.4 drochner if (scr == oldscr) {
1026 1.1 drochner return;
1027 1.4 drochner }
1028 1.4 drochner #ifdef DIAGNOSTIC
1029 1.4 drochner if (scr->pcs.active)
1030 1.4 drochner panic("vga_show_screen: active");
1031 1.4 drochner #endif
1032 1.4 drochner
1033 1.11 drochner if (oldscr) {
1034 1.11 drochner const struct wsscreen_descr *oldtype = oldscr->pcs.type;
1035 1.1 drochner
1036 1.11 drochner oldscr->pcs.active = 0;
1037 1.11 drochner bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
1038 1.66 tsutsui oldscr->pcs.dispoffset, oldscr->pcs.mem,
1039 1.66 tsutsui oldtype->ncols * oldtype->nrows);
1040 1.11 drochner }
1041 1.1 drochner
1042 1.11 drochner if (vc->currenttype != type) {
1043 1.4 drochner vga_setscreentype(vh, type);
1044 1.11 drochner vc->currenttype = type;
1045 1.11 drochner }
1046 1.12 drochner
1047 1.12 drochner vga_setfont(vc, scr);
1048 1.106 christos vga_restore_palette(vc);
1049 1.1 drochner
1050 1.80 mycroft scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
1051 1.11 drochner if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
1052 1.8 drochner vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
1053 1.8 drochner vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
1054 1.8 drochner }
1055 1.8 drochner
1056 1.11 drochner bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
1057 1.66 tsutsui scr->pcs.dispoffset, scr->pcs.mem, type->ncols * type->nrows);
1058 1.11 drochner scr->pcs.active = 1;
1059 1.1 drochner
1060 1.4 drochner vc->active = scr;
1061 1.1 drochner
1062 1.4 drochner pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
1063 1.66 tsutsui scr->pcs.cursorrow, scr->pcs.cursorcol);
1064 1.22 drochner
1065 1.22 drochner vc->wantedscreen = 0;
1066 1.22 drochner if (vc->switchcb)
1067 1.22 drochner (*vc->switchcb)(vc->switchcbarg, 0, 0);
1068 1.1 drochner }
1069 1.1 drochner
1070 1.1 drochner static int
1071 1.45 junyoung vga_load_font(void *v, void *cookie, struct wsdisplay_font *data)
1072 1.1 drochner {
1073 1.12 drochner struct vga_config *vc = v;
1074 1.1 drochner struct vgascreen *scr = cookie;
1075 1.12 drochner char *name2;
1076 1.37 drochner int res;
1077 1.12 drochner
1078 1.12 drochner if (scr) {
1079 1.50 hannken name2 = NULL;
1080 1.50 hannken if (data->name) {
1081 1.50 hannken name2 = strchr(data->name, ',');
1082 1.50 hannken if (name2)
1083 1.50 hannken *name2++ = '\0';
1084 1.50 hannken }
1085 1.12 drochner res = vga_selectfont(vc, scr, data->name, name2);
1086 1.52 drochner if (!res && scr->pcs.active)
1087 1.12 drochner vga_setfont(vc, scr);
1088 1.12 drochner return (res);
1089 1.12 drochner }
1090 1.1 drochner
1091 1.1 drochner return (0);
1092 1.1 drochner }
1093 1.1 drochner
1094 1.3 drochner static int
1095 1.59 junyoung vga_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1096 1.3 drochner {
1097 1.3 drochner struct vgascreen *scr = id;
1098 1.3 drochner struct vga_config *vc = scr->cfg;
1099 1.3 drochner
1100 1.95 mjf if (__predict_false((unsigned int)fg >= sizeof(fgansitopc) ||
1101 1.95 mjf (unsigned int)bg >= sizeof(bgansitopc)))
1102 1.95 mjf return (EINVAL);
1103 1.95 mjf
1104 1.4 drochner if (vc->hdl.vh_mono) {
1105 1.3 drochner if (flags & WSATTR_WSCOLORS)
1106 1.3 drochner return (EINVAL);
1107 1.3 drochner if (flags & WSATTR_REVERSE)
1108 1.3 drochner *attrp = 0x70;
1109 1.3 drochner else
1110 1.3 drochner *attrp = 0x07;
1111 1.3 drochner if (flags & WSATTR_UNDERLINE)
1112 1.3 drochner *attrp |= FG_UNDERLINE;
1113 1.3 drochner if (flags & WSATTR_HILIT)
1114 1.3 drochner *attrp |= FG_INTENSE;
1115 1.3 drochner } else {
1116 1.3 drochner if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
1117 1.3 drochner return (EINVAL);
1118 1.3 drochner if (flags & WSATTR_WSCOLORS)
1119 1.3 drochner *attrp = fgansitopc[fg] | bgansitopc[bg];
1120 1.3 drochner else
1121 1.3 drochner *attrp = 7;
1122 1.3 drochner if (flags & WSATTR_HILIT)
1123 1.3 drochner *attrp += 8;
1124 1.3 drochner }
1125 1.3 drochner if (flags & WSATTR_BLINK)
1126 1.3 drochner *attrp |= FG_BLINK;
1127 1.3 drochner return (0);
1128 1.8 drochner }
1129 1.8 drochner
1130 1.45 junyoung static void
1131 1.45 junyoung vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
1132 1.8 drochner {
1133 1.8 drochner struct vgascreen *scr = id;
1134 1.8 drochner bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
1135 1.8 drochner bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
1136 1.8 drochner int ncols = scr->pcs.type->ncols;
1137 1.8 drochner bus_size_t srcoff, dstoff;
1138 1.8 drochner
1139 1.8 drochner srcoff = srcrow * ncols + 0;
1140 1.8 drochner dstoff = dstrow * ncols + 0;
1141 1.8 drochner
1142 1.8 drochner if (scr->pcs.active) {
1143 1.8 drochner if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
1144 1.18 ad #ifdef PCDISPLAY_SOFTCURSOR
1145 1.20 ad int cursoron = scr->pcs.cursoron;
1146 1.20 ad
1147 1.21 mycroft if (cursoron)
1148 1.21 mycroft pcdisplay_cursor(&scr->pcs, 0,
1149 1.60 junyoung scr->pcs.cursorrow, scr->pcs.cursorcol);
1150 1.18 ad #endif
1151 1.8 drochner /* scroll up whole screen */
1152 1.8 drochner if ((scr->pcs.dispoffset + srcrow * ncols * 2)
1153 1.8 drochner <= scr->maxdispoffset) {
1154 1.8 drochner scr->pcs.dispoffset += srcrow * ncols * 2;
1155 1.8 drochner } else {
1156 1.8 drochner bus_space_copy_region_2(memt, memh,
1157 1.66 tsutsui scr->pcs.dispoffset + srcoff * 2,
1158 1.66 tsutsui memh, scr->mindispoffset, nrows * ncols);
1159 1.8 drochner scr->pcs.dispoffset = scr->mindispoffset;
1160 1.8 drochner }
1161 1.8 drochner vga_6845_write(&scr->cfg->hdl, startadrh,
1162 1.66 tsutsui scr->pcs.dispoffset >> 9);
1163 1.8 drochner vga_6845_write(&scr->cfg->hdl, startadrl,
1164 1.66 tsutsui scr->pcs.dispoffset >> 1);
1165 1.18 ad #ifdef PCDISPLAY_SOFTCURSOR
1166 1.21 mycroft if (cursoron)
1167 1.21 mycroft pcdisplay_cursor(&scr->pcs, 1,
1168 1.60 junyoung scr->pcs.cursorrow, scr->pcs.cursorcol);
1169 1.18 ad #endif
1170 1.8 drochner } else {
1171 1.8 drochner bus_space_copy_region_2(memt, memh,
1172 1.66 tsutsui scr->pcs.dispoffset + srcoff * 2,
1173 1.66 tsutsui memh, scr->pcs.dispoffset + dstoff * 2,
1174 1.66 tsutsui nrows * ncols);
1175 1.8 drochner }
1176 1.8 drochner } else
1177 1.36 thorpej memcpy(&scr->pcs.mem[dstoff], &scr->pcs.mem[srcoff],
1178 1.66 tsutsui nrows * ncols * 2);
1179 1.12 drochner }
1180 1.12 drochner
1181 1.12 drochner #ifdef WSCONS_SUPPORT_PCVTFONTS
1182 1.12 drochner
1183 1.12 drochner #define NOTYET 0xffff
1184 1.106 christos static const uint16_t pcvt_unichars[0xa0] = {
1185 1.44 bjh21 /* 0 */ _e006U, /* N/L control */
1186 1.14 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1187 1.12 drochner NOTYET,
1188 1.12 drochner 0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */
1189 1.12 drochner 0x240a, /* SYMBOL FOR LINE FEED */
1190 1.12 drochner 0x240b, /* SYMBOL FOR VERTICAL TABULATION */
1191 1.12 drochner 0x240c, /* SYMBOL FOR FORM FEED */
1192 1.12 drochner 0x240d, /* SYMBOL FOR CARRIAGE RETURN */
1193 1.12 drochner NOTYET, NOTYET,
1194 1.14 drochner /* 1 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1195 1.12 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1196 1.12 drochner /* 2 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1197 1.12 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1198 1.14 drochner /* 3 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1199 1.12 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1200 1.12 drochner /* 4 */ 0x03c1, /* GREEK SMALL LETTER RHO */
1201 1.12 drochner 0x03c8, /* GREEK SMALL LETTER PSI */
1202 1.12 drochner 0x2202, /* PARTIAL DIFFERENTIAL */
1203 1.12 drochner 0x03bb, /* GREEK SMALL LETTER LAMDA */
1204 1.12 drochner 0x03b9, /* GREEK SMALL LETTER IOTA */
1205 1.12 drochner 0x03b7, /* GREEK SMALL LETTER ETA */
1206 1.12 drochner 0x03b5, /* GREEK SMALL LETTER EPSILON */
1207 1.12 drochner 0x03c7, /* GREEK SMALL LETTER CHI */
1208 1.12 drochner 0x2228, /* LOGICAL OR */
1209 1.12 drochner 0x2227, /* LOGICAL AND */
1210 1.12 drochner 0x222a, /* UNION */
1211 1.12 drochner 0x2283, /* SUPERSET OF */
1212 1.12 drochner 0x2282, /* SUBSET OF */
1213 1.12 drochner 0x03a5, /* GREEK CAPITAL LETTER UPSILON */
1214 1.12 drochner 0x039e, /* GREEK CAPITAL LETTER XI */
1215 1.12 drochner 0x03a8, /* GREEK CAPITAL LETTER PSI */
1216 1.14 drochner /* 5 */ 0x03a0, /* GREEK CAPITAL LETTER PI */
1217 1.12 drochner 0x21d2, /* RIGHTWARDS DOUBLE ARROW */
1218 1.12 drochner 0x21d4, /* LEFT RIGHT DOUBLE ARROW */
1219 1.12 drochner 0x039b, /* GREEK CAPITAL LETTER LAMDA */
1220 1.12 drochner 0x0398, /* GREEK CAPITAL LETTER THETA */
1221 1.12 drochner 0x2243, /* ASYMPTOTICALLY EQUAL TO */
1222 1.12 drochner 0x2207, /* NABLA */
1223 1.12 drochner 0x2206, /* INCREMENT */
1224 1.12 drochner 0x221d, /* PROPORTIONAL TO */
1225 1.12 drochner 0x2234, /* THEREFORE */
1226 1.12 drochner 0x222b, /* INTEGRAL */
1227 1.12 drochner 0x2215, /* DIVISION SLASH */
1228 1.12 drochner 0x2216, /* SET MINUS */
1229 1.44 bjh21 _e00eU, /* angle? */
1230 1.44 bjh21 _e00dU, /* inverted angle? */
1231 1.44 bjh21 _e00bU, /* braceleftmid */
1232 1.44 bjh21 /* 6 */ _e00cU, /* bracerightmid */
1233 1.44 bjh21 _e007U, /* bracelefttp */
1234 1.44 bjh21 _e008U, /* braceleftbt */
1235 1.44 bjh21 _e009U, /* bracerighttp */
1236 1.44 bjh21 _e00aU, /* bracerightbt */
1237 1.12 drochner 0x221a, /* SQUARE ROOT */
1238 1.12 drochner 0x03c9, /* GREEK SMALL LETTER OMEGA */
1239 1.12 drochner 0x00a5, /* YEN SIGN */
1240 1.12 drochner 0x03be, /* GREEK SMALL LETTER XI */
1241 1.12 drochner 0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */
1242 1.12 drochner 0x00fe, /* LATIN SMALL LETTER THORN */
1243 1.12 drochner 0x00f0, /* LATIN SMALL LETTER ETH */
1244 1.12 drochner 0x00de, /* LATIN CAPITAL LETTER THORN */
1245 1.12 drochner 0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */
1246 1.12 drochner 0x00d7, /* MULTIPLICATION SIGN */
1247 1.12 drochner 0x00d0, /* LATIN CAPITAL LETTER ETH */
1248 1.14 drochner /* 7 */ 0x00be, /* VULGAR FRACTION THREE QUARTERS */
1249 1.12 drochner 0x00b8, /* CEDILLA */
1250 1.12 drochner 0x00b4, /* ACUTE ACCENT */
1251 1.12 drochner 0x00af, /* MACRON */
1252 1.12 drochner 0x00ae, /* REGISTERED SIGN */
1253 1.12 drochner 0x00ad, /* SOFT HYPHEN */
1254 1.12 drochner 0x00ac, /* NOT SIGN */
1255 1.12 drochner 0x00a8, /* DIAERESIS */
1256 1.12 drochner 0x2260, /* NOT EQUAL TO */
1257 1.102 drochner 0x23bd, /* scan 9 */
1258 1.102 drochner 0x23bc, /* scan 7 */
1259 1.102 drochner 0x2500, /* scan 5 */
1260 1.102 drochner 0x23bb, /* scan 3 */
1261 1.102 drochner 0x23ba, /* scan 1 */
1262 1.12 drochner 0x03c5, /* GREEK SMALL LETTER UPSILON */
1263 1.12 drochner 0x00f8, /* LATIN SMALL LETTER O WITH STROKE */
1264 1.12 drochner /* 8 */ 0x0153, /* LATIN SMALL LIGATURE OE */
1265 1.12 drochner 0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */
1266 1.12 drochner 0x00e3, /* LATIN SMALL LETTER A WITH TILDE */
1267 1.12 drochner 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1268 1.12 drochner 0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1269 1.12 drochner 0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */
1270 1.12 drochner 0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */
1271 1.12 drochner 0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */
1272 1.12 drochner 0x0152, /* LATIN CAPITAL LIGATURE OE */
1273 1.12 drochner 0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */
1274 1.12 drochner 0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1275 1.12 drochner 0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */
1276 1.12 drochner 0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */
1277 1.12 drochner 0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1278 1.12 drochner 0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1279 1.12 drochner 0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */
1280 1.14 drochner /* 9 */ 0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */
1281 1.12 drochner 0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1282 1.12 drochner 0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1283 1.12 drochner 0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */
1284 1.12 drochner 0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */
1285 1.12 drochner 0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1286 1.12 drochner 0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */
1287 1.12 drochner 0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */
1288 1.12 drochner 0x00b9, /* SUPERSCRIPT ONE */
1289 1.12 drochner 0x00b7, /* MIDDLE DOT */
1290 1.12 drochner 0x03b6, /* GREEK SMALL LETTER ZETA */
1291 1.12 drochner 0x00b3, /* SUPERSCRIPT THREE */
1292 1.12 drochner 0x00a9, /* COPYRIGHT SIGN */
1293 1.12 drochner 0x00a4, /* CURRENCY SIGN */
1294 1.12 drochner 0x03ba, /* GREEK SMALL LETTER KAPPA */
1295 1.44 bjh21 _e000U /* mirrored question mark? */
1296 1.12 drochner };
1297 1.12 drochner
1298 1.45 junyoung static int vga_pcvt_mapchar(int, u_int *);
1299 1.12 drochner
1300 1.12 drochner static int
1301 1.45 junyoung vga_pcvt_mapchar(int uni, u_int *index)
1302 1.12 drochner {
1303 1.12 drochner int i;
1304 1.12 drochner
1305 1.12 drochner for (i = 0; i < 0xa0; i++) /* 0xa0..0xff are reserved */
1306 1.13 drochner if (uni == pcvt_unichars[i]) {
1307 1.13 drochner *index = i;
1308 1.13 drochner return (5);
1309 1.13 drochner }
1310 1.13 drochner *index = 0x99; /* middle dot */
1311 1.13 drochner return (0);
1312 1.12 drochner }
1313 1.12 drochner
1314 1.12 drochner #endif /* WSCONS_SUPPORT_PCVTFONTS */
1315 1.12 drochner
1316 1.34 drochner #ifdef WSCONS_SUPPORT_ISO7FONTS
1317 1.34 drochner
1318 1.34 drochner static int
1319 1.45 junyoung vga_iso7_mapchar(int uni, u_int *index)
1320 1.34 drochner {
1321 1.34 drochner
1322 1.34 drochner /*
1323 1.34 drochner * U+0384 (GREEK TONOS) to
1324 1.34 drochner * U+03ce (GREEK SMALL LETTER OMEGA WITH TONOS)
1325 1.34 drochner * map directly to the iso-9 font
1326 1.34 drochner */
1327 1.34 drochner if (uni >= 0x0384 && uni <= 0x03ce) {
1328 1.34 drochner /* U+0384 is at offset 0xb4 in the font */
1329 1.34 drochner *index = uni - 0x0384 + 0xb4;
1330 1.34 drochner return (5);
1331 1.34 drochner }
1332 1.34 drochner
1333 1.34 drochner /* XXX more chars in the iso-9 font */
1334 1.34 drochner
1335 1.34 drochner *index = 0xa4; /* shaded rectangle */
1336 1.34 drochner return (0);
1337 1.34 drochner }
1338 1.34 drochner
1339 1.34 drochner #endif /* WSCONS_SUPPORT_ISO7FONTS */
1340 1.34 drochner
1341 1.107 drochner static const uint16_t iso2_unichars[0x60] = {
1342 1.107 drochner 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
1343 1.107 drochner 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
1344 1.107 drochner 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
1345 1.107 drochner 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
1346 1.107 drochner 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
1347 1.107 drochner 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
1348 1.107 drochner 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
1349 1.107 drochner 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
1350 1.107 drochner 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
1351 1.107 drochner 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
1352 1.107 drochner 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
1353 1.107 drochner 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
1354 1.107 drochner };
1355 1.107 drochner
1356 1.107 drochner static const uint16_t koi8_unichars[0x40] = {
1357 1.107 drochner 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
1358 1.107 drochner 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
1359 1.107 drochner 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
1360 1.107 drochner 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
1361 1.107 drochner 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
1362 1.107 drochner 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
1363 1.107 drochner 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
1364 1.107 drochner 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
1365 1.107 drochner };
1366 1.107 drochner
1367 1.45 junyoung static int _vga_mapchar(void *, const struct egavga_font *, int, u_int *);
1368 1.12 drochner
1369 1.12 drochner static int
1370 1.45 junyoung _vga_mapchar(void *id, const struct egavga_font *font, int uni, u_int *index)
1371 1.12 drochner {
1372 1.12 drochner
1373 1.37 drochner switch (font->wsfont->encoding) {
1374 1.12 drochner case WSDISPLAY_FONTENC_ISO:
1375 1.13 drochner if (uni < 256) {
1376 1.13 drochner *index = uni;
1377 1.13 drochner return (5);
1378 1.13 drochner } else {
1379 1.13 drochner *index = ' ';
1380 1.13 drochner return (0);
1381 1.13 drochner }
1382 1.107 drochner case WSDISPLAY_FONTENC_ISO2:
1383 1.107 drochner if (uni < 0xa0) {
1384 1.107 drochner *index = uni;
1385 1.107 drochner return (5);
1386 1.107 drochner } else {
1387 1.107 drochner int i;
1388 1.107 drochner for (i = 0; i < 0x60; i++) {
1389 1.107 drochner if (uni == iso2_unichars[i]) {
1390 1.107 drochner *index = i + 0xa0;
1391 1.107 drochner return (5);
1392 1.107 drochner }
1393 1.107 drochner }
1394 1.107 drochner *index = 0xa4; /* currency sign */
1395 1.107 drochner return (0);
1396 1.107 drochner }
1397 1.107 drochner case WSDISPLAY_FONTENC_KOI8_R:
1398 1.107 drochner if (uni < 0x80) {
1399 1.107 drochner *index = uni;
1400 1.107 drochner return (5);
1401 1.107 drochner } else {
1402 1.107 drochner int i;
1403 1.107 drochner for (i = 0; i < 0x40; i++) {
1404 1.107 drochner if (uni == koi8_unichars[i]) {
1405 1.107 drochner *index = i + 0xc0;
1406 1.107 drochner return (5);
1407 1.107 drochner }
1408 1.107 drochner }
1409 1.107 drochner *index = 0x94; /* box */
1410 1.107 drochner return (0);
1411 1.107 drochner }
1412 1.12 drochner case WSDISPLAY_FONTENC_IBM:
1413 1.13 drochner return (pcdisplay_mapchar(id, uni, index));
1414 1.12 drochner #ifdef WSCONS_SUPPORT_PCVTFONTS
1415 1.12 drochner case WSDISPLAY_FONTENC_PCVT:
1416 1.13 drochner return (vga_pcvt_mapchar(uni, index));
1417 1.34 drochner #endif
1418 1.34 drochner #ifdef WSCONS_SUPPORT_ISO7FONTS
1419 1.34 drochner case WSDISPLAY_FONTENC_ISO7:
1420 1.34 drochner return (vga_iso7_mapchar(uni, index));
1421 1.12 drochner #endif
1422 1.13 drochner default:
1423 1.16 drochner #ifdef VGAFONTDEBUG
1424 1.37 drochner printf("_vga_mapchar: encoding=%d\n", font->wsfont->encoding);
1425 1.16 drochner #endif
1426 1.13 drochner *index = ' ';
1427 1.13 drochner return (0);
1428 1.12 drochner }
1429 1.12 drochner }
1430 1.12 drochner
1431 1.13 drochner static int
1432 1.45 junyoung vga_mapchar(void *id, int uni, u_int *index)
1433 1.12 drochner {
1434 1.12 drochner struct vgascreen *scr = id;
1435 1.45 junyoung u_int idx1, idx2;
1436 1.13 drochner int res1, res2;
1437 1.12 drochner
1438 1.13 drochner res1 = 0;
1439 1.13 drochner idx1 = ' '; /* space */
1440 1.13 drochner if (scr->fontset1)
1441 1.13 drochner res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
1442 1.13 drochner res2 = -1;
1443 1.12 drochner if (scr->fontset2) {
1444 1.12 drochner KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
1445 1.13 drochner res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
1446 1.12 drochner }
1447 1.13 drochner if (res2 > res1) {
1448 1.14 drochner *index = idx2 | 0x0800; /* attribute bit 3 */
1449 1.14 drochner return (res2);
1450 1.13 drochner }
1451 1.13 drochner *index = idx1;
1452 1.13 drochner return (res1);
1453 1.53 christos }
1454 1.53 christos
1455 1.72 christos #ifdef WSDISPLAY_SCROLLSUPPORT
1456 1.110 mlelstv static void
1457 1.72 christos vga_scroll(void *v, void *cookie, int lines)
1458 1.72 christos {
1459 1.72 christos struct vga_config *vc = v;
1460 1.72 christos struct vgascreen *scr = cookie;
1461 1.72 christos struct vga_handle *vh = &vc->hdl;
1462 1.72 christos
1463 1.72 christos if (lines == 0) {
1464 1.72 christos if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
1465 1.72 christos return;
1466 1.72 christos
1467 1.72 christos scr->pcs.visibleoffset = scr->pcs.dispoffset;
1468 1.72 christos }
1469 1.72 christos else {
1470 1.72 christos int vga_scr_end;
1471 1.72 christos int margin = scr->pcs.type->ncols * 2;
1472 1.72 christos int ul, we, p, st;
1473 1.72 christos
1474 1.72 christos vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
1475 1.72 christos scr->pcs.type->nrows * 2);
1476 1.72 christos if (scr->vga_rollover > vga_scr_end + margin) {
1477 1.72 christos ul = vga_scr_end;
1478 1.72 christos we = scr->vga_rollover + scr->pcs.type->ncols * 2;
1479 1.72 christos } else {
1480 1.72 christos ul = 0;
1481 1.72 christos we = 0x8000;
1482 1.72 christos }
1483 1.72 christos p = (scr->pcs.visibleoffset - ul + we) % we + lines *
1484 1.72 christos (scr->pcs.type->ncols * 2);
1485 1.72 christos st = (scr->pcs.dispoffset - ul + we) % we;
1486 1.72 christos if (p < margin)
1487 1.72 christos p = 0;
1488 1.72 christos if (p > st - margin)
1489 1.72 christos p = st;
1490 1.72 christos scr->pcs.visibleoffset = (p + ul) % we;
1491 1.72 christos }
1492 1.81 perry
1493 1.72 christos vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
1494 1.72 christos vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
1495 1.72 christos }
1496 1.72 christos #endif
1497 1.72 christos
1498 1.110 mlelstv static void
1499 1.72 christos vga_putchar(void *c, int row, int col, u_int uc, long attr)
1500 1.72 christos {
1501 1.72 christos
1502 1.72 christos pcdisplay_putchar(c, row, col, uc, attr);
1503 1.72 christos }
1504 1.72 christos
1505 1.76 jmmv #ifdef WSDISPLAY_CUSTOM_BORDER
1506 1.85 drochner static int
1507 1.85 drochner vga_getborder(struct vga_config *vc, u_int *valuep)
1508 1.76 jmmv {
1509 1.85 drochner struct vga_handle *vh = &vc->hdl;
1510 1.76 jmmv u_int idx;
1511 1.106 christos uint8_t value;
1512 1.76 jmmv
1513 1.85 drochner if (vh->vh_mono)
1514 1.85 drochner return ENODEV;
1515 1.76 jmmv
1516 1.76 jmmv value = _vga_attr_read(vh, VGA_ATC_OVERSCAN);
1517 1.85 drochner for (idx = 0; idx < sizeof(fgansitopc); idx++) {
1518 1.85 drochner if (fgansitopc[idx] == value) {
1519 1.85 drochner *valuep = idx;
1520 1.85 drochner return (0);
1521 1.85 drochner }
1522 1.85 drochner }
1523 1.85 drochner return (EIO);
1524 1.76 jmmv }
1525 1.76 jmmv
1526 1.76 jmmv static int
1527 1.85 drochner vga_setborder(struct vga_config *vc, u_int value)
1528 1.76 jmmv {
1529 1.85 drochner struct vga_handle *vh = &vc->hdl;
1530 1.76 jmmv
1531 1.85 drochner if (vh->vh_mono)
1532 1.85 drochner return ENODEV;
1533 1.85 drochner if (value >= sizeof(fgansitopc))
1534 1.85 drochner return EINVAL;
1535 1.76 jmmv
1536 1.76 jmmv _vga_attr_write(vh, VGA_ATC_OVERSCAN, fgansitopc[value]);
1537 1.76 jmmv return (0);
1538 1.76 jmmv }
1539 1.76 jmmv #endif /* WSDISPLAY_CUSTOM_BORDER */
1540 1.97 jmcneill
1541 1.97 jmcneill void
1542 1.97 jmcneill vga_resume(struct vga_softc *sc)
1543 1.97 jmcneill {
1544 1.97 jmcneill #ifdef VGA_RESET_ON_RESUME
1545 1.97 jmcneill vga_initregs(&sc->sc_vc->hdl);
1546 1.97 jmcneill #endif
1547 1.105 jmcneill #ifdef PCDISPLAY_SOFTCURSOR
1548 1.105 jmcneill /* Disable the hardware cursor */
1549 1.105 jmcneill vga_6845_write(&sc->sc_vc->hdl, curstart, 0x20);
1550 1.105 jmcneill vga_6845_write(&sc->sc_vc->hdl, curend, 0x00);
1551 1.105 jmcneill #endif
1552 1.97 jmcneill }
1553 1.106 christos
1554 1.110 mlelstv static void
1555 1.106 christos vga_save_palette(struct vga_config *vc)
1556 1.106 christos {
1557 1.106 christos struct vga_handle *vh = &vc->hdl;
1558 1.106 christos size_t i;
1559 1.106 christos uint8_t *palette = vc->palette;
1560 1.106 christos
1561 1.106 christos if (vh->vh_mono)
1562 1.106 christos return;
1563 1.106 christos
1564 1.106 christos vga_raw_write(vh, VGA_DAC_PELMASK, 0xff);
1565 1.106 christos vga_raw_write(vh, VGA_DAC_ADDRR, 0x00);
1566 1.106 christos for (i = 0; i < sizeof(vc->palette); i++)
1567 1.106 christos *palette++ = vga_raw_read(vh, VGA_DAC_PALETTE);
1568 1.106 christos
1569 1.109 uwe vga_reset_state(vh); /* reset flip/flop */
1570 1.106 christos }
1571 1.106 christos
1572 1.110 mlelstv static void
1573 1.106 christos vga_restore_palette(struct vga_config *vc)
1574 1.106 christos {
1575 1.106 christos struct vga_handle *vh = &vc->hdl;
1576 1.106 christos size_t i;
1577 1.106 christos uint8_t *palette = vc->palette;
1578 1.106 christos
1579 1.106 christos if (vh->vh_mono)
1580 1.106 christos return;
1581 1.106 christos
1582 1.106 christos vga_raw_write(vh, VGA_DAC_PELMASK, 0xff);
1583 1.106 christos vga_raw_write(vh, VGA_DAC_ADDRW, 0x00);
1584 1.106 christos for (i = 0; i < sizeof(vc->palette); i++)
1585 1.106 christos vga_raw_write(vh, VGA_DAC_PALETTE, *palette++);
1586 1.106 christos
1587 1.109 uwe vga_reset_state(vh); /* reset flip/flop */
1588 1.106 christos vga_enable(vh);
1589 1.106 christos }
1590