vga.c revision 1.115 1 1.115 mlelstv /* $NetBSD: vga.c,v 1.115 2015/03/01 07:05:59 mlelstv 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.115 mlelstv __KERNEL_RCSID(0, "$NetBSD: vga.c,v 1.115 2015/03/01 07:05:59 mlelstv 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.37 drochner f = malloc(sizeof(struct egavga_font), M_DEVBUF, M_NOWAIT);
364 1.37 drochner if (!f) {
365 1.37 drochner wsfont_unlock(cookie);
366 1.37 drochner return (0);
367 1.37 drochner }
368 1.37 drochner f->wsfont = wf;
369 1.37 drochner f->cookie = cookie;
370 1.37 drochner f->slot = -1; /* not yet loaded */
371 1.37 drochner f->usecount = 0; /* incremented below */
372 1.37 drochner TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
373 1.37 drochner
374 1.37 drochner found:
375 1.37 drochner f->usecount++;
376 1.37 drochner #ifdef VGAFONTDEBUG
377 1.37 drochner if (scr != &vga_console_screen || vga_console_attached)
378 1.37 drochner printf("vga_getfont: usecount=%d\n", f->usecount);
379 1.37 drochner #endif
380 1.37 drochner return (f);
381 1.37 drochner }
382 1.37 drochner
383 1.110 mlelstv static void
384 1.45 junyoung egavga_unreffont(struct vga_config *vc, struct egavga_font *f)
385 1.37 drochner {
386 1.37 drochner
387 1.37 drochner f->usecount--;
388 1.37 drochner #ifdef VGAFONTDEBUG
389 1.37 drochner printf("vga_unreffont: usecount=%d\n", f->usecount);
390 1.37 drochner #endif
391 1.58 drochner if (f->usecount == 0 && f->cookie != -1) {
392 1.37 drochner TAILQ_REMOVE(&vc->vc_fontlist, f, next);
393 1.41 drochner if (f->slot != -1) {
394 1.41 drochner KASSERT(vc->vc_fonts[f->slot] == f);
395 1.41 drochner vc->vc_fonts[f->slot] = 0;
396 1.41 drochner }
397 1.37 drochner wsfont_unlock(f->cookie);
398 1.38 drochner #ifdef VGA_CONSOLE_SCREENTYPE
399 1.38 drochner if (f != &vga_consolefont)
400 1.38 drochner #endif
401 1.37 drochner free(f, M_DEVBUF);
402 1.37 drochner }
403 1.37 drochner }
404 1.12 drochner
405 1.110 mlelstv static int
406 1.69 jdolecek vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1,
407 1.69 jdolecek const char *name2)
408 1.12 drochner {
409 1.12 drochner const struct wsscreen_descr *type = scr->pcs.type;
410 1.37 drochner struct egavga_font *f1, *f2;
411 1.12 drochner
412 1.37 drochner f1 = egavga_getfont(vc, scr, name1, 1);
413 1.37 drochner if (!f1)
414 1.37 drochner return (ENXIO);
415 1.12 drochner
416 1.37 drochner if (VGA_SCREEN_CANTWOFONTS(type) && name2) {
417 1.37 drochner f2 = egavga_getfont(vc, scr, name2, 0);
418 1.37 drochner if (!f2) {
419 1.37 drochner egavga_unreffont(vc, f1);
420 1.37 drochner return (ENXIO);
421 1.12 drochner }
422 1.37 drochner } else
423 1.37 drochner f2 = 0;
424 1.12 drochner
425 1.12 drochner #ifdef VGAFONTDEBUG
426 1.37 drochner if (scr != &vga_console_screen || vga_console_attached) {
427 1.37 drochner printf("vga (%s): font1=%s (slot %d)", type->name,
428 1.66 tsutsui f1->wsfont->name, f1->slot);
429 1.37 drochner if (f2)
430 1.37 drochner printf(", font2=%s (slot %d)",
431 1.66 tsutsui f2->wsfont->name, f2->slot);
432 1.37 drochner printf("\n");
433 1.37 drochner }
434 1.12 drochner #endif
435 1.37 drochner if (scr->fontset1)
436 1.37 drochner egavga_unreffont(vc, scr->fontset1);
437 1.37 drochner scr->fontset1 = f1;
438 1.37 drochner if (scr->fontset2)
439 1.37 drochner egavga_unreffont(vc, scr->fontset2);
440 1.37 drochner scr->fontset2 = f2;
441 1.37 drochner return (0);
442 1.12 drochner }
443 1.12 drochner
444 1.110 mlelstv static void
445 1.45 junyoung vga_init_screen(struct vga_config *vc, struct vgascreen *scr,
446 1.45 junyoung const struct wsscreen_descr *type, int existing, long *attrp)
447 1.1 drochner {
448 1.8 drochner int cpos;
449 1.111 christos int res __diagused;
450 1.1 drochner
451 1.4 drochner scr->cfg = vc;
452 1.4 drochner scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl;
453 1.4 drochner scr->pcs.type = type;
454 1.39 drochner scr->pcs.active = existing;
455 1.8 drochner scr->mindispoffset = 0;
456 1.63 drochner if (vc->vc_quirks & VGA_QUIRK_NOFASTSCROLL)
457 1.63 drochner scr->maxdispoffset = 0;
458 1.63 drochner else
459 1.63 drochner scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2;
460 1.1 drochner
461 1.1 drochner if (existing) {
462 1.39 drochner vc->active = scr;
463 1.39 drochner
464 1.1 drochner cpos = vga_6845_read(&vc->hdl, cursorh) << 8;
465 1.1 drochner cpos |= vga_6845_read(&vc->hdl, cursorl);
466 1.1 drochner
467 1.1 drochner /* make sure we have a valid cursor position */
468 1.1 drochner if (cpos < 0 || cpos >= type->nrows * type->ncols)
469 1.1 drochner cpos = 0;
470 1.8 drochner
471 1.8 drochner scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh) << 9;
472 1.8 drochner scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl) << 1;
473 1.8 drochner
474 1.8 drochner /* make sure we have a valid memory offset */
475 1.8 drochner if (scr->pcs.dispoffset < scr->mindispoffset ||
476 1.8 drochner scr->pcs.dispoffset > scr->maxdispoffset)
477 1.8 drochner scr->pcs.dispoffset = scr->mindispoffset;
478 1.40 drochner
479 1.40 drochner if (type != vc->currenttype) {
480 1.40 drochner vga_setscreentype(&vc->hdl, type);
481 1.40 drochner vc->currenttype = type;
482 1.40 drochner }
483 1.8 drochner } else {
484 1.8 drochner cpos = 0;
485 1.8 drochner scr->pcs.dispoffset = scr->mindispoffset;
486 1.1 drochner }
487 1.1 drochner
488 1.72 christos scr->pcs.visibleoffset = scr->pcs.dispoffset;
489 1.72 christos scr->vga_rollover = 0;
490 1.72 christos
491 1.60 junyoung scr->pcs.cursorrow = cpos / type->ncols;
492 1.60 junyoung scr->pcs.cursorcol = cpos % type->ncols;
493 1.25 ad pcdisplay_cursor_init(&scr->pcs, existing);
494 1.1 drochner
495 1.1 drochner #ifdef __alpha__
496 1.4 drochner if (!vc->hdl.vh_mono)
497 1.3 drochner /*
498 1.3 drochner * DEC firmware uses a blue background.
499 1.75 jmmv * XXX These should be specified as kernel options for
500 1.75 jmmv * XXX alpha only, not hardcoded here (which is wrong
501 1.75 jmmv * XXX anyway because the emulation layer will assume
502 1.75 jmmv * XXX the default attribute is white on black).
503 1.3 drochner */
504 1.59 junyoung res = vga_allocattr(scr, WSCOL_WHITE, WSCOL_BLUE,
505 1.66 tsutsui WSATTR_WSCOLORS, attrp);
506 1.3 drochner else
507 1.3 drochner #endif
508 1.59 junyoung res = vga_allocattr(scr, 0, 0, 0, attrp);
509 1.3 drochner #ifdef DIAGNOSTIC
510 1.3 drochner if (res)
511 1.3 drochner panic("vga_init_screen: attribute botch");
512 1.1 drochner #endif
513 1.1 drochner
514 1.4 drochner scr->pcs.mem = NULL;
515 1.15 drochner
516 1.15 drochner scr->fontset1 = scr->fontset2 = 0;
517 1.12 drochner if (vga_selectfont(vc, scr, 0, 0)) {
518 1.12 drochner if (scr == &vga_console_screen)
519 1.12 drochner panic("vga_init_screen: no font");
520 1.12 drochner else
521 1.12 drochner printf("vga_init_screen: no font\n");
522 1.12 drochner }
523 1.40 drochner if (existing)
524 1.40 drochner vga_setfont(vc, scr);
525 1.15 drochner
526 1.1 drochner vc->nscreens++;
527 1.1 drochner LIST_INSERT_HEAD(&vc->screens, scr, next);
528 1.1 drochner }
529 1.1 drochner
530 1.110 mlelstv static void
531 1.45 junyoung vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt)
532 1.1 drochner {
533 1.1 drochner struct vga_handle *vh = &vc->hdl;
534 1.106 christos uint8_t mor;
535 1.12 drochner int i;
536 1.1 drochner
537 1.66 tsutsui vh->vh_iot = iot;
538 1.66 tsutsui vh->vh_memt = memt;
539 1.1 drochner
540 1.66 tsutsui if (bus_space_map(vh->vh_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga))
541 1.66 tsutsui panic("vga_init: couldn't map vga io");
542 1.1 drochner
543 1.1 drochner /* read "misc output register" */
544 1.106 christos mor = vga_raw_read(vh, VGA_MISC_DATAR);
545 1.4 drochner vh->vh_mono = !(mor & 1);
546 1.1 drochner
547 1.4 drochner if (bus_space_map(vh->vh_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0,
548 1.66 tsutsui &vh->vh_ioh_6845))
549 1.66 tsutsui panic("vga_init: couldn't map 6845 io");
550 1.1 drochner
551 1.66 tsutsui if (bus_space_map(vh->vh_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh))
552 1.66 tsutsui panic("vga_init: couldn't map memory");
553 1.1 drochner
554 1.66 tsutsui if (bus_space_subregion(vh->vh_memt, vh->vh_allmemh,
555 1.66 tsutsui (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, &vh->vh_memh))
556 1.66 tsutsui panic("vga_init: mem subrange failed");
557 1.5 drochner
558 1.1 drochner vc->nscreens = 0;
559 1.1 drochner LIST_INIT(&vc->screens);
560 1.1 drochner vc->active = NULL;
561 1.34 drochner vc->currenttype = vh->vh_mono ? &vga_25lscreen_mono : &vga_25lscreen;
562 1.93 ad callout_init(&vc->vc_switch_callout, 0);
563 1.12 drochner
564 1.68 tsutsui wsfont_init();
565 1.68 tsutsui if (vga_no_builtinfont) {
566 1.68 tsutsui struct wsdisplay_font *wf;
567 1.68 tsutsui int cookie;
568 1.68 tsutsui
569 1.68 tsutsui cookie = wsfont_find(NULL, 8, 16, 0,
570 1.108 macallan WSDISPLAY_FONTORDER_L2R, 0, WSFONT_FIND_BITMAP);
571 1.68 tsutsui if (cookie == -1 || wsfont_lock(cookie, &wf))
572 1.68 tsutsui panic("vga_init: can't load console font");
573 1.68 tsutsui vga_loadchars(&vc->hdl, 0, wf->firstchar, wf->numchars,
574 1.68 tsutsui wf->fontheight, wf->data);
575 1.68 tsutsui vga_builtinfont.wsfont = wf;
576 1.68 tsutsui vga_builtinfont.cookie = cookie;
577 1.68 tsutsui vga_builtinfont.slot = 0;
578 1.68 tsutsui }
579 1.12 drochner vc->vc_fonts[0] = &vga_builtinfont;
580 1.23 drochner for (i = 1; i < 8; i++)
581 1.12 drochner vc->vc_fonts[i] = 0;
582 1.37 drochner TAILQ_INIT(&vc->vc_fontlist);
583 1.37 drochner TAILQ_INSERT_HEAD(&vc->vc_fontlist, &vga_builtinfont, next);
584 1.12 drochner
585 1.12 drochner vc->currentfontset1 = vc->currentfontset2 = 0;
586 1.76 jmmv
587 1.78 jmmv if (!vh->vh_mono && (u_int)WSDISPLAY_BORDER_COLOR < sizeof(fgansitopc))
588 1.78 jmmv _vga_attr_write(vh, VGA_ATC_OVERSCAN,
589 1.78 jmmv fgansitopc[WSDISPLAY_BORDER_COLOR]);
590 1.106 christos vga_save_palette(vc);
591 1.1 drochner }
592 1.1 drochner
593 1.1 drochner void
594 1.45 junyoung vga_common_attach(struct vga_softc *sc, bus_space_tag_t iot,
595 1.56 drochner bus_space_tag_t memt, int type, int quirks,
596 1.56 drochner const struct vga_funcs *vf)
597 1.28 soda {
598 1.1 drochner int console;
599 1.1 drochner struct vga_config *vc;
600 1.1 drochner struct wsemuldisplaydev_attach_args aa;
601 1.1 drochner
602 1.1 drochner console = vga_is_console(iot, type);
603 1.1 drochner
604 1.1 drochner if (console) {
605 1.1 drochner vc = &vga_console_vc;
606 1.1 drochner vga_console_attached = 1;
607 1.1 drochner } else {
608 1.1 drochner vc = malloc(sizeof(struct vga_config), M_DEVBUF, M_WAITOK);
609 1.1 drochner vga_init(vc, iot, memt);
610 1.1 drochner }
611 1.1 drochner
612 1.58 drochner if (quirks & VGA_QUIRK_ONEFONT) {
613 1.58 drochner vc->vc_nfontslots = 1;
614 1.58 drochner #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
615 1.58 drochner /*
616 1.58 drochner * XXX maybe invalidate font in slot > 0, but this can
617 1.58 drochner * only be happen with VGA_CONSOLE_SCREENTYPE, and then
618 1.58 drochner * we require VGA_CONSOLE_ATI_BROKEN_FONTSEL anyway.
619 1.58 drochner */
620 1.58 drochner #endif
621 1.58 drochner } else {
622 1.58 drochner vc->vc_nfontslots = 8;
623 1.58 drochner #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
624 1.58 drochner /*
625 1.58 drochner * XXX maybe validate builtin font shifted to slot 1 if
626 1.58 drochner * slot 0 got overwritten because of VGA_CONSOLE_SCREENTYPE,
627 1.58 drochner * but it will be reloaded anyway if needed.
628 1.58 drochner */
629 1.58 drochner #endif
630 1.58 drochner }
631 1.58 drochner
632 1.58 drochner /*
633 1.58 drochner * Save the builtin font to memory. In case it got overwritten
634 1.58 drochner * in console initialization, use the copy in slot 1.
635 1.58 drochner */
636 1.58 drochner #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
637 1.58 drochner #define BUILTINFONTLOC (vga_builtinfont.slot == -1 ? 1 : 0)
638 1.58 drochner #else
639 1.58 drochner KASSERT(vga_builtinfont.slot == 0);
640 1.58 drochner #define BUILTINFONTLOC (0)
641 1.58 drochner #endif
642 1.68 tsutsui if (!vga_no_builtinfont) {
643 1.69 jdolecek char *data =
644 1.68 tsutsui malloc(256 * vga_builtinfont.wsfont->fontheight,
645 1.68 tsutsui M_DEVBUF, M_WAITOK);
646 1.68 tsutsui vga_readoutchars(&vc->hdl, BUILTINFONTLOC, 0, 256,
647 1.69 jdolecek vga_builtinfont.wsfont->fontheight, data);
648 1.69 jdolecek vga_builtinfont.wsfont->data = data;
649 1.68 tsutsui }
650 1.56 drochner
651 1.42 thorpej vc->vc_type = type;
652 1.42 thorpej vc->vc_funcs = vf;
653 1.63 drochner vc->vc_quirks = quirks;
654 1.42 thorpej
655 1.42 thorpej sc->sc_vc = vc;
656 1.42 thorpej vc->softc = sc;
657 1.28 soda
658 1.1 drochner aa.console = console;
659 1.4 drochner aa.scrdata = (vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist);
660 1.1 drochner aa.accessops = &vga_accessops;
661 1.1 drochner aa.accesscookie = vc;
662 1.1 drochner
663 1.98 cube config_found_ia(sc->sc_dev, "wsemuldisplaydev", &aa, wsemuldisplaydevprint);
664 1.1 drochner }
665 1.1 drochner
666 1.1 drochner int
667 1.45 junyoung vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check)
668 1.1 drochner {
669 1.3 drochner long defattr;
670 1.3 drochner const struct wsscreen_descr *scr;
671 1.3 drochner
672 1.1 drochner if (check && !vga_common_probe(iot, memt))
673 1.1 drochner return (ENXIO);
674 1.1 drochner
675 1.1 drochner /* set up bus-independent VGA configuration */
676 1.1 drochner vga_init(&vga_console_vc, iot, memt);
677 1.34 drochner #ifdef VGA_CONSOLE_SCREENTYPE
678 1.34 drochner scr = wsdisplay_screentype_pick(vga_console_vc.hdl.vh_mono ?
679 1.66 tsutsui &vga_screenlist_mono : &vga_screenlist, VGA_CONSOLE_SCREENTYPE);
680 1.34 drochner if (!scr)
681 1.34 drochner panic("vga_cnattach: invalid screen type");
682 1.34 drochner #else
683 1.11 drochner scr = vga_console_vc.currenttype;
684 1.34 drochner #endif
685 1.56 drochner #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
686 1.56 drochner /*
687 1.56 drochner * On some (most/all?) ATI cards, only font slot 0 is usable.
688 1.56 drochner * vga_init_screen() might need font slot 0 for a non-default
689 1.58 drochner * console font, so save the builtin VGA font to another font slot.
690 1.58 drochner * The attach() code will take care later.
691 1.56 drochner */
692 1.63 drochner vga_console_vc.vc_quirks |= VGA_QUIRK_ONEFONT; /* redundant */
693 1.56 drochner vga_copyfont01(&vga_console_vc.hdl);
694 1.56 drochner vga_console_vc.vc_nfontslots = 1;
695 1.56 drochner #else
696 1.56 drochner vga_console_vc.vc_nfontslots = 8;
697 1.56 drochner #endif
698 1.79 christos #ifdef notdef
699 1.63 drochner /* until we know better, assume "fast scrolling" does not work */
700 1.63 drochner vga_console_vc.vc_quirks |= VGA_QUIRK_NOFASTSCROLL;
701 1.79 christos #endif
702 1.63 drochner
703 1.4 drochner vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr);
704 1.1 drochner
705 1.3 drochner wsdisplay_cnattach(scr, &vga_console_screen,
706 1.66 tsutsui vga_console_screen.pcs.cursorcol,
707 1.66 tsutsui vga_console_screen.pcs.cursorrow, defattr);
708 1.1 drochner
709 1.1 drochner vgaconsole = 1;
710 1.1 drochner vga_console_type = type;
711 1.1 drochner return (0);
712 1.1 drochner }
713 1.1 drochner
714 1.1 drochner int
715 1.88 jmcneill vga_cndetach(void)
716 1.88 jmcneill {
717 1.88 jmcneill struct vga_config *vc;
718 1.88 jmcneill struct vga_handle *vh;
719 1.88 jmcneill
720 1.88 jmcneill vc = &vga_console_vc;
721 1.88 jmcneill vh = &vc->hdl;
722 1.88 jmcneill
723 1.88 jmcneill if (vgaconsole) {
724 1.112 mlelstv wsdisplay_cndetach();
725 1.112 mlelstv
726 1.88 jmcneill bus_space_unmap(vh->vh_iot, vh->vh_ioh_vga, 0x10);
727 1.88 jmcneill bus_space_unmap(vh->vh_iot, vh->vh_ioh_6845, 0x10);
728 1.115 mlelstv bus_space_unmap(vh->vh_memt, vh->vh_allmemh, 0x20000);
729 1.88 jmcneill
730 1.112 mlelstv vga_console_attached = 0;
731 1.112 mlelstv vgaconsole = 0;
732 1.112 mlelstv
733 1.88 jmcneill return 1;
734 1.88 jmcneill }
735 1.88 jmcneill
736 1.88 jmcneill return 0;
737 1.88 jmcneill }
738 1.88 jmcneill
739 1.88 jmcneill int
740 1.45 junyoung vga_is_console(bus_space_tag_t iot, int type)
741 1.1 drochner {
742 1.1 drochner if (vgaconsole &&
743 1.1 drochner !vga_console_attached &&
744 1.104 dyoung bus_space_is_equal(iot, vga_console_vc.hdl.vh_iot) &&
745 1.1 drochner (vga_console_type == -1 || (type == vga_console_type)))
746 1.1 drochner return (1);
747 1.1 drochner return (0);
748 1.1 drochner }
749 1.1 drochner
750 1.46 lukem static int
751 1.46 lukem vga_get_video(struct vga_config *vc)
752 1.46 lukem {
753 1.67 tsutsui
754 1.67 tsutsui return (vga_ts_read(&vc->hdl, mode) & VGA_TS_MODE_BLANK) == 0;
755 1.46 lukem }
756 1.46 lukem
757 1.46 lukem static void
758 1.46 lukem vga_set_video(struct vga_config *vc, int state)
759 1.46 lukem {
760 1.46 lukem int val;
761 1.46 lukem
762 1.46 lukem vga_ts_write(&vc->hdl, syncreset, 0x01);
763 1.46 lukem if (state) { /* unblank screen */
764 1.46 lukem val = vga_ts_read(&vc->hdl, mode);
765 1.67 tsutsui vga_ts_write(&vc->hdl, mode, val & ~VGA_TS_MODE_BLANK);
766 1.46 lukem #ifndef VGA_NO_VBLANK
767 1.46 lukem val = vga_6845_read(&vc->hdl, mode);
768 1.46 lukem vga_6845_write(&vc->hdl, mode, val | 0x80);
769 1.46 lukem #endif
770 1.46 lukem } else { /* blank screen */
771 1.46 lukem val = vga_ts_read(&vc->hdl, mode);
772 1.67 tsutsui vga_ts_write(&vc->hdl, mode, val | VGA_TS_MODE_BLANK);
773 1.46 lukem #ifndef VGA_NO_VBLANK
774 1.46 lukem val = vga_6845_read(&vc->hdl, mode);
775 1.46 lukem vga_6845_write(&vc->hdl, mode, val & ~0x80);
776 1.46 lukem #endif
777 1.46 lukem }
778 1.46 lukem vga_ts_write(&vc->hdl, syncreset, 0x03);
779 1.46 lukem }
780 1.46 lukem
781 1.110 mlelstv static int
782 1.92 christos vga_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
783 1.1 drochner {
784 1.1 drochner struct vga_config *vc = v;
785 1.87 jmmv struct vgascreen *scr = vs;
786 1.42 thorpej const struct vga_funcs *vf = vc->vc_funcs;
787 1.1 drochner
788 1.1 drochner switch (cmd) {
789 1.106 christos case WSDISPLAYIO_SMODE:
790 1.106 christos if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL)
791 1.106 christos vga_restore_palette(vc);
792 1.106 christos return 0;
793 1.106 christos
794 1.1 drochner case WSDISPLAYIO_GTYPE:
795 1.1 drochner *(int *)data = vc->vc_type;
796 1.10 augustss return 0;
797 1.12 drochner
798 1.1 drochner case WSDISPLAYIO_GINFO:
799 1.42 thorpej /* XXX should get detailed hardware information here */
800 1.49 atatat return EPASSTHROUGH;
801 1.42 thorpej
802 1.46 lukem case WSDISPLAYIO_GVIDEO:
803 1.66 tsutsui *(int *)data = (vga_get_video(vc) ?
804 1.66 tsutsui WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF);
805 1.46 lukem return 0;
806 1.46 lukem
807 1.46 lukem case WSDISPLAYIO_SVIDEO:
808 1.46 lukem vga_set_video(vc, *(int *)data == WSDISPLAYIO_VIDEO_ON);
809 1.46 lukem return 0;
810 1.46 lukem
811 1.87 jmmv case WSDISPLAYIO_GETWSCHAR:
812 1.87 jmmv KASSERT(scr != NULL);
813 1.87 jmmv return pcdisplay_getwschar(&scr->pcs,
814 1.87 jmmv (struct wsdisplay_char *)data);
815 1.87 jmmv
816 1.87 jmmv case WSDISPLAYIO_PUTWSCHAR:
817 1.87 jmmv KASSERT(scr != NULL);
818 1.87 jmmv return pcdisplay_putwschar(&scr->pcs,
819 1.87 jmmv (struct wsdisplay_char *)data);
820 1.87 jmmv
821 1.85 drochner #ifdef WSDISPLAY_CUSTOM_BORDER
822 1.85 drochner case WSDISPLAYIO_GBORDER:
823 1.85 drochner return (vga_getborder(vc, (u_int *)data));
824 1.85 drochner
825 1.85 drochner case WSDISPLAYIO_SBORDER:
826 1.85 drochner return (vga_setborder(vc, *(u_int *)data));
827 1.85 drochner #endif
828 1.85 drochner
829 1.1 drochner case WSDISPLAYIO_GETCMAP:
830 1.1 drochner case WSDISPLAYIO_PUTCMAP:
831 1.1 drochner case WSDISPLAYIO_GCURPOS:
832 1.1 drochner case WSDISPLAYIO_SCURPOS:
833 1.1 drochner case WSDISPLAYIO_GCURMAX:
834 1.1 drochner case WSDISPLAYIO_GCURSOR:
835 1.1 drochner case WSDISPLAYIO_SCURSOR:
836 1.1 drochner /* NONE of these operations are by the generic VGA driver. */
837 1.49 atatat return EPASSTHROUGH;
838 1.1 drochner }
839 1.12 drochner
840 1.42 thorpej if (vc->vc_funcs == NULL)
841 1.49 atatat return (EPASSTHROUGH);
842 1.42 thorpej
843 1.42 thorpej if (vf->vf_ioctl == NULL)
844 1.49 atatat return (EPASSTHROUGH);
845 1.42 thorpej
846 1.83 christos return ((*vf->vf_ioctl)(v, cmd, data, flag, l));
847 1.1 drochner }
848 1.1 drochner
849 1.29 simonb static paddr_t
850 1.91 christos vga_mmap(void *v, void *vs, off_t offset, int prot)
851 1.1 drochner {
852 1.42 thorpej struct vga_config *vc = v;
853 1.42 thorpej const struct vga_funcs *vf = vc->vc_funcs;
854 1.1 drochner
855 1.42 thorpej if (vc->vc_funcs == NULL)
856 1.42 thorpej return (-1);
857 1.28 soda
858 1.42 thorpej if (vf->vf_mmap == NULL)
859 1.42 thorpej return (-1);
860 1.32 thorpej
861 1.42 thorpej return ((*vf->vf_mmap)(v, offset, prot));
862 1.1 drochner }
863 1.1 drochner
864 1.110 mlelstv static int
865 1.45 junyoung vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
866 1.45 junyoung int *curxp, int *curyp, long *defattrp)
867 1.1 drochner {
868 1.1 drochner struct vga_config *vc = v;
869 1.1 drochner struct vgascreen *scr;
870 1.1 drochner
871 1.1 drochner if (vc->nscreens == 1) {
872 1.38 drochner struct vgascreen *scr1 = vc->screens.lh_first;
873 1.1 drochner /*
874 1.1 drochner * When allocating the second screen, get backing store
875 1.1 drochner * for the first one too.
876 1.1 drochner * XXX We could be more clever and use video RAM.
877 1.1 drochner */
878 1.38 drochner scr1->pcs.mem =
879 1.66 tsutsui malloc(scr1->pcs.type->ncols * scr1->pcs.type->nrows * 2,
880 1.66 tsutsui M_DEVBUF, M_WAITOK);
881 1.1 drochner }
882 1.1 drochner
883 1.1 drochner scr = malloc(sizeof(struct vgascreen), M_DEVBUF, M_WAITOK);
884 1.4 drochner vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp);
885 1.1 drochner
886 1.39 drochner if (vc->nscreens > 1) {
887 1.4 drochner scr->pcs.mem = malloc(type->ncols * type->nrows * 2,
888 1.66 tsutsui M_DEVBUF, M_WAITOK);
889 1.4 drochner pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp);
890 1.1 drochner }
891 1.1 drochner
892 1.1 drochner *cookiep = scr;
893 1.60 junyoung *curxp = scr->pcs.cursorcol;
894 1.60 junyoung *curyp = scr->pcs.cursorrow;
895 1.1 drochner
896 1.1 drochner return (0);
897 1.1 drochner }
898 1.1 drochner
899 1.110 mlelstv static void
900 1.91 christos vga_free_screen(void *v, void *cookie)
901 1.1 drochner {
902 1.1 drochner struct vgascreen *vs = cookie;
903 1.11 drochner struct vga_config *vc = vs->cfg;
904 1.1 drochner
905 1.1 drochner LIST_REMOVE(vs, next);
906 1.82 dbj vc->nscreens--;
907 1.38 drochner if (vs->fontset1)
908 1.38 drochner egavga_unreffont(vc, vs->fontset1);
909 1.38 drochner if (vs->fontset2)
910 1.38 drochner egavga_unreffont(vc, vs->fontset2);
911 1.38 drochner
912 1.1 drochner if (vs != &vga_console_screen)
913 1.1 drochner free(vs, M_DEVBUF);
914 1.1 drochner else
915 1.1 drochner panic("vga_free_screen: console");
916 1.11 drochner
917 1.11 drochner if (vc->active == vs)
918 1.11 drochner vc->active = 0;
919 1.1 drochner }
920 1.1 drochner
921 1.40 drochner static void vga_usefont(struct vga_config *, struct egavga_font *);
922 1.37 drochner
923 1.40 drochner static void
924 1.45 junyoung vga_usefont(struct vga_config *vc, struct egavga_font *f)
925 1.37 drochner {
926 1.37 drochner int slot;
927 1.37 drochner struct egavga_font *of;
928 1.37 drochner
929 1.37 drochner if (f->slot != -1)
930 1.37 drochner goto toend;
931 1.37 drochner
932 1.51 drochner for (slot = 0; slot < vc->vc_nfontslots; slot++) {
933 1.37 drochner if (!vc->vc_fonts[slot])
934 1.37 drochner goto loadit;
935 1.37 drochner }
936 1.37 drochner
937 1.37 drochner /* have to kick out another one */
938 1.37 drochner TAILQ_FOREACH(of, &vc->vc_fontlist, next) {
939 1.37 drochner if (of->slot != -1) {
940 1.37 drochner KASSERT(vc->vc_fonts[of->slot] == of);
941 1.37 drochner slot = of->slot;
942 1.37 drochner of->slot = -1;
943 1.37 drochner goto loadit;
944 1.37 drochner }
945 1.37 drochner }
946 1.54 junyoung panic("vga_usefont");
947 1.37 drochner
948 1.37 drochner loadit:
949 1.52 drochner vga_loadchars(&vc->hdl, slot, f->wsfont->firstchar,
950 1.66 tsutsui f->wsfont->numchars, f->wsfont->fontheight, f->wsfont->data);
951 1.37 drochner f->slot = slot;
952 1.37 drochner vc->vc_fonts[slot] = f;
953 1.37 drochner
954 1.37 drochner toend:
955 1.37 drochner TAILQ_REMOVE(&vc->vc_fontlist, f, next);
956 1.37 drochner TAILQ_INSERT_TAIL(&vc->vc_fontlist, f, next);
957 1.37 drochner }
958 1.37 drochner
959 1.12 drochner static void
960 1.45 junyoung vga_setfont(struct vga_config *vc, struct vgascreen *scr)
961 1.12 drochner {
962 1.12 drochner int fontslot1, fontslot2;
963 1.12 drochner
964 1.37 drochner if (scr->fontset1)
965 1.37 drochner vga_usefont(vc, scr->fontset1);
966 1.37 drochner if (scr->fontset2)
967 1.37 drochner vga_usefont(vc, scr->fontset2);
968 1.37 drochner
969 1.12 drochner fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0);
970 1.12 drochner fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1);
971 1.12 drochner if (vc->currentfontset1 != fontslot1 ||
972 1.12 drochner vc->currentfontset2 != fontslot2) {
973 1.12 drochner vga_setfontset(&vc->hdl, fontslot1, fontslot2);
974 1.12 drochner vc->currentfontset1 = fontslot1;
975 1.12 drochner vc->currentfontset2 = fontslot2;
976 1.12 drochner }
977 1.12 drochner }
978 1.12 drochner
979 1.110 mlelstv static int
980 1.91 christos vga_show_screen(void *v, void *cookie, int waitok,
981 1.45 junyoung void (*cb)(void *, int, int), void *cbarg)
982 1.1 drochner {
983 1.4 drochner struct vgascreen *scr = cookie, *oldscr;
984 1.1 drochner struct vga_config *vc = scr->cfg;
985 1.22 drochner
986 1.22 drochner oldscr = vc->active; /* can be NULL! */
987 1.22 drochner if (scr == oldscr) {
988 1.22 drochner return (0);
989 1.22 drochner }
990 1.22 drochner
991 1.22 drochner vc->wantedscreen = cookie;
992 1.22 drochner vc->switchcb = cb;
993 1.22 drochner vc->switchcbarg = cbarg;
994 1.22 drochner if (cb) {
995 1.26 thorpej callout_reset(&vc->vc_switch_callout, 0,
996 1.26 thorpej (void(*)(void *))vga_doswitch, vc);
997 1.22 drochner return (EAGAIN);
998 1.22 drochner }
999 1.22 drochner
1000 1.22 drochner vga_doswitch(vc);
1001 1.22 drochner return (0);
1002 1.22 drochner }
1003 1.22 drochner
1004 1.110 mlelstv static void
1005 1.45 junyoung vga_doswitch(struct vga_config *vc)
1006 1.22 drochner {
1007 1.22 drochner struct vgascreen *scr, *oldscr;
1008 1.1 drochner struct vga_handle *vh = &vc->hdl;
1009 1.22 drochner const struct wsscreen_descr *type;
1010 1.1 drochner
1011 1.22 drochner scr = vc->wantedscreen;
1012 1.22 drochner if (!scr) {
1013 1.22 drochner printf("vga_doswitch: disappeared\n");
1014 1.22 drochner (*vc->switchcb)(vc->switchcbarg, EIO, 0);
1015 1.22 drochner return;
1016 1.22 drochner }
1017 1.22 drochner type = scr->pcs.type;
1018 1.11 drochner oldscr = vc->active; /* can be NULL! */
1019 1.4 drochner #ifdef DIAGNOSTIC
1020 1.11 drochner if (oldscr) {
1021 1.11 drochner if (!oldscr->pcs.active)
1022 1.11 drochner panic("vga_show_screen: not active");
1023 1.11 drochner if (oldscr->pcs.type != vc->currenttype)
1024 1.11 drochner panic("vga_show_screen: bad type");
1025 1.11 drochner }
1026 1.4 drochner #endif
1027 1.4 drochner if (scr == oldscr) {
1028 1.1 drochner return;
1029 1.4 drochner }
1030 1.4 drochner #ifdef DIAGNOSTIC
1031 1.4 drochner if (scr->pcs.active)
1032 1.4 drochner panic("vga_show_screen: active");
1033 1.4 drochner #endif
1034 1.4 drochner
1035 1.11 drochner if (oldscr) {
1036 1.11 drochner const struct wsscreen_descr *oldtype = oldscr->pcs.type;
1037 1.1 drochner
1038 1.11 drochner oldscr->pcs.active = 0;
1039 1.11 drochner bus_space_read_region_2(vh->vh_memt, vh->vh_memh,
1040 1.66 tsutsui oldscr->pcs.dispoffset, oldscr->pcs.mem,
1041 1.66 tsutsui oldtype->ncols * oldtype->nrows);
1042 1.11 drochner }
1043 1.1 drochner
1044 1.11 drochner if (vc->currenttype != type) {
1045 1.4 drochner vga_setscreentype(vh, type);
1046 1.11 drochner vc->currenttype = type;
1047 1.11 drochner }
1048 1.12 drochner
1049 1.12 drochner vga_setfont(vc, scr);
1050 1.106 christos vga_restore_palette(vc);
1051 1.1 drochner
1052 1.80 mycroft scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset;
1053 1.11 drochner if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) {
1054 1.8 drochner vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9);
1055 1.8 drochner vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1);
1056 1.8 drochner }
1057 1.8 drochner
1058 1.11 drochner bus_space_write_region_2(vh->vh_memt, vh->vh_memh,
1059 1.66 tsutsui scr->pcs.dispoffset, scr->pcs.mem, type->ncols * type->nrows);
1060 1.11 drochner scr->pcs.active = 1;
1061 1.1 drochner
1062 1.4 drochner vc->active = scr;
1063 1.1 drochner
1064 1.4 drochner pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron,
1065 1.66 tsutsui scr->pcs.cursorrow, scr->pcs.cursorcol);
1066 1.22 drochner
1067 1.22 drochner vc->wantedscreen = 0;
1068 1.22 drochner if (vc->switchcb)
1069 1.22 drochner (*vc->switchcb)(vc->switchcbarg, 0, 0);
1070 1.1 drochner }
1071 1.1 drochner
1072 1.1 drochner static int
1073 1.45 junyoung vga_load_font(void *v, void *cookie, struct wsdisplay_font *data)
1074 1.1 drochner {
1075 1.12 drochner struct vga_config *vc = v;
1076 1.1 drochner struct vgascreen *scr = cookie;
1077 1.12 drochner char *name2;
1078 1.37 drochner int res;
1079 1.12 drochner
1080 1.12 drochner if (scr) {
1081 1.50 hannken name2 = NULL;
1082 1.50 hannken if (data->name) {
1083 1.50 hannken name2 = strchr(data->name, ',');
1084 1.50 hannken if (name2)
1085 1.50 hannken *name2++ = '\0';
1086 1.50 hannken }
1087 1.12 drochner res = vga_selectfont(vc, scr, data->name, name2);
1088 1.52 drochner if (!res && scr->pcs.active)
1089 1.12 drochner vga_setfont(vc, scr);
1090 1.12 drochner return (res);
1091 1.12 drochner }
1092 1.1 drochner
1093 1.1 drochner return (0);
1094 1.1 drochner }
1095 1.1 drochner
1096 1.3 drochner static int
1097 1.59 junyoung vga_allocattr(void *id, int fg, int bg, int flags, long *attrp)
1098 1.3 drochner {
1099 1.3 drochner struct vgascreen *scr = id;
1100 1.3 drochner struct vga_config *vc = scr->cfg;
1101 1.3 drochner
1102 1.95 mjf if (__predict_false((unsigned int)fg >= sizeof(fgansitopc) ||
1103 1.95 mjf (unsigned int)bg >= sizeof(bgansitopc)))
1104 1.95 mjf return (EINVAL);
1105 1.95 mjf
1106 1.4 drochner if (vc->hdl.vh_mono) {
1107 1.3 drochner if (flags & WSATTR_WSCOLORS)
1108 1.3 drochner return (EINVAL);
1109 1.3 drochner if (flags & WSATTR_REVERSE)
1110 1.3 drochner *attrp = 0x70;
1111 1.3 drochner else
1112 1.3 drochner *attrp = 0x07;
1113 1.3 drochner if (flags & WSATTR_UNDERLINE)
1114 1.3 drochner *attrp |= FG_UNDERLINE;
1115 1.3 drochner if (flags & WSATTR_HILIT)
1116 1.3 drochner *attrp |= FG_INTENSE;
1117 1.3 drochner } else {
1118 1.3 drochner if (flags & (WSATTR_UNDERLINE | WSATTR_REVERSE))
1119 1.3 drochner return (EINVAL);
1120 1.3 drochner if (flags & WSATTR_WSCOLORS)
1121 1.3 drochner *attrp = fgansitopc[fg] | bgansitopc[bg];
1122 1.3 drochner else
1123 1.3 drochner *attrp = 7;
1124 1.3 drochner if (flags & WSATTR_HILIT)
1125 1.3 drochner *attrp += 8;
1126 1.3 drochner }
1127 1.3 drochner if (flags & WSATTR_BLINK)
1128 1.3 drochner *attrp |= FG_BLINK;
1129 1.3 drochner return (0);
1130 1.8 drochner }
1131 1.8 drochner
1132 1.45 junyoung static void
1133 1.45 junyoung vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
1134 1.8 drochner {
1135 1.8 drochner struct vgascreen *scr = id;
1136 1.8 drochner bus_space_tag_t memt = scr->pcs.hdl->ph_memt;
1137 1.8 drochner bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
1138 1.8 drochner int ncols = scr->pcs.type->ncols;
1139 1.8 drochner bus_size_t srcoff, dstoff;
1140 1.8 drochner
1141 1.8 drochner srcoff = srcrow * ncols + 0;
1142 1.8 drochner dstoff = dstrow * ncols + 0;
1143 1.8 drochner
1144 1.8 drochner if (scr->pcs.active) {
1145 1.8 drochner if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
1146 1.18 ad #ifdef PCDISPLAY_SOFTCURSOR
1147 1.20 ad int cursoron = scr->pcs.cursoron;
1148 1.20 ad
1149 1.21 mycroft if (cursoron)
1150 1.21 mycroft pcdisplay_cursor(&scr->pcs, 0,
1151 1.60 junyoung scr->pcs.cursorrow, scr->pcs.cursorcol);
1152 1.18 ad #endif
1153 1.8 drochner /* scroll up whole screen */
1154 1.8 drochner if ((scr->pcs.dispoffset + srcrow * ncols * 2)
1155 1.8 drochner <= scr->maxdispoffset) {
1156 1.8 drochner scr->pcs.dispoffset += srcrow * ncols * 2;
1157 1.8 drochner } else {
1158 1.8 drochner bus_space_copy_region_2(memt, memh,
1159 1.66 tsutsui scr->pcs.dispoffset + srcoff * 2,
1160 1.66 tsutsui memh, scr->mindispoffset, nrows * ncols);
1161 1.8 drochner scr->pcs.dispoffset = scr->mindispoffset;
1162 1.8 drochner }
1163 1.8 drochner vga_6845_write(&scr->cfg->hdl, startadrh,
1164 1.66 tsutsui scr->pcs.dispoffset >> 9);
1165 1.8 drochner vga_6845_write(&scr->cfg->hdl, startadrl,
1166 1.66 tsutsui scr->pcs.dispoffset >> 1);
1167 1.18 ad #ifdef PCDISPLAY_SOFTCURSOR
1168 1.21 mycroft if (cursoron)
1169 1.21 mycroft pcdisplay_cursor(&scr->pcs, 1,
1170 1.60 junyoung scr->pcs.cursorrow, scr->pcs.cursorcol);
1171 1.18 ad #endif
1172 1.8 drochner } else {
1173 1.8 drochner bus_space_copy_region_2(memt, memh,
1174 1.66 tsutsui scr->pcs.dispoffset + srcoff * 2,
1175 1.66 tsutsui memh, scr->pcs.dispoffset + dstoff * 2,
1176 1.66 tsutsui nrows * ncols);
1177 1.8 drochner }
1178 1.8 drochner } else
1179 1.36 thorpej memcpy(&scr->pcs.mem[dstoff], &scr->pcs.mem[srcoff],
1180 1.66 tsutsui nrows * ncols * 2);
1181 1.12 drochner }
1182 1.12 drochner
1183 1.12 drochner #ifdef WSCONS_SUPPORT_PCVTFONTS
1184 1.12 drochner
1185 1.12 drochner #define NOTYET 0xffff
1186 1.106 christos static const uint16_t pcvt_unichars[0xa0] = {
1187 1.44 bjh21 /* 0 */ _e006U, /* N/L control */
1188 1.14 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1189 1.12 drochner NOTYET,
1190 1.12 drochner 0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */
1191 1.12 drochner 0x240a, /* SYMBOL FOR LINE FEED */
1192 1.12 drochner 0x240b, /* SYMBOL FOR VERTICAL TABULATION */
1193 1.12 drochner 0x240c, /* SYMBOL FOR FORM FEED */
1194 1.12 drochner 0x240d, /* SYMBOL FOR CARRIAGE RETURN */
1195 1.12 drochner NOTYET, NOTYET,
1196 1.14 drochner /* 1 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1197 1.12 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1198 1.12 drochner /* 2 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1199 1.12 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1200 1.14 drochner /* 3 */ NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1201 1.12 drochner NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET, NOTYET,
1202 1.12 drochner /* 4 */ 0x03c1, /* GREEK SMALL LETTER RHO */
1203 1.12 drochner 0x03c8, /* GREEK SMALL LETTER PSI */
1204 1.12 drochner 0x2202, /* PARTIAL DIFFERENTIAL */
1205 1.12 drochner 0x03bb, /* GREEK SMALL LETTER LAMDA */
1206 1.12 drochner 0x03b9, /* GREEK SMALL LETTER IOTA */
1207 1.12 drochner 0x03b7, /* GREEK SMALL LETTER ETA */
1208 1.12 drochner 0x03b5, /* GREEK SMALL LETTER EPSILON */
1209 1.12 drochner 0x03c7, /* GREEK SMALL LETTER CHI */
1210 1.12 drochner 0x2228, /* LOGICAL OR */
1211 1.12 drochner 0x2227, /* LOGICAL AND */
1212 1.12 drochner 0x222a, /* UNION */
1213 1.12 drochner 0x2283, /* SUPERSET OF */
1214 1.12 drochner 0x2282, /* SUBSET OF */
1215 1.12 drochner 0x03a5, /* GREEK CAPITAL LETTER UPSILON */
1216 1.12 drochner 0x039e, /* GREEK CAPITAL LETTER XI */
1217 1.12 drochner 0x03a8, /* GREEK CAPITAL LETTER PSI */
1218 1.14 drochner /* 5 */ 0x03a0, /* GREEK CAPITAL LETTER PI */
1219 1.12 drochner 0x21d2, /* RIGHTWARDS DOUBLE ARROW */
1220 1.12 drochner 0x21d4, /* LEFT RIGHT DOUBLE ARROW */
1221 1.12 drochner 0x039b, /* GREEK CAPITAL LETTER LAMDA */
1222 1.12 drochner 0x0398, /* GREEK CAPITAL LETTER THETA */
1223 1.12 drochner 0x2243, /* ASYMPTOTICALLY EQUAL TO */
1224 1.12 drochner 0x2207, /* NABLA */
1225 1.12 drochner 0x2206, /* INCREMENT */
1226 1.12 drochner 0x221d, /* PROPORTIONAL TO */
1227 1.12 drochner 0x2234, /* THEREFORE */
1228 1.12 drochner 0x222b, /* INTEGRAL */
1229 1.12 drochner 0x2215, /* DIVISION SLASH */
1230 1.12 drochner 0x2216, /* SET MINUS */
1231 1.44 bjh21 _e00eU, /* angle? */
1232 1.44 bjh21 _e00dU, /* inverted angle? */
1233 1.44 bjh21 _e00bU, /* braceleftmid */
1234 1.44 bjh21 /* 6 */ _e00cU, /* bracerightmid */
1235 1.44 bjh21 _e007U, /* bracelefttp */
1236 1.44 bjh21 _e008U, /* braceleftbt */
1237 1.44 bjh21 _e009U, /* bracerighttp */
1238 1.44 bjh21 _e00aU, /* bracerightbt */
1239 1.12 drochner 0x221a, /* SQUARE ROOT */
1240 1.12 drochner 0x03c9, /* GREEK SMALL LETTER OMEGA */
1241 1.12 drochner 0x00a5, /* YEN SIGN */
1242 1.12 drochner 0x03be, /* GREEK SMALL LETTER XI */
1243 1.12 drochner 0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */
1244 1.12 drochner 0x00fe, /* LATIN SMALL LETTER THORN */
1245 1.12 drochner 0x00f0, /* LATIN SMALL LETTER ETH */
1246 1.12 drochner 0x00de, /* LATIN CAPITAL LETTER THORN */
1247 1.12 drochner 0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */
1248 1.12 drochner 0x00d7, /* MULTIPLICATION SIGN */
1249 1.12 drochner 0x00d0, /* LATIN CAPITAL LETTER ETH */
1250 1.14 drochner /* 7 */ 0x00be, /* VULGAR FRACTION THREE QUARTERS */
1251 1.12 drochner 0x00b8, /* CEDILLA */
1252 1.12 drochner 0x00b4, /* ACUTE ACCENT */
1253 1.12 drochner 0x00af, /* MACRON */
1254 1.12 drochner 0x00ae, /* REGISTERED SIGN */
1255 1.12 drochner 0x00ad, /* SOFT HYPHEN */
1256 1.12 drochner 0x00ac, /* NOT SIGN */
1257 1.12 drochner 0x00a8, /* DIAERESIS */
1258 1.12 drochner 0x2260, /* NOT EQUAL TO */
1259 1.102 drochner 0x23bd, /* scan 9 */
1260 1.102 drochner 0x23bc, /* scan 7 */
1261 1.102 drochner 0x2500, /* scan 5 */
1262 1.102 drochner 0x23bb, /* scan 3 */
1263 1.102 drochner 0x23ba, /* scan 1 */
1264 1.12 drochner 0x03c5, /* GREEK SMALL LETTER UPSILON */
1265 1.12 drochner 0x00f8, /* LATIN SMALL LETTER O WITH STROKE */
1266 1.12 drochner /* 8 */ 0x0153, /* LATIN SMALL LIGATURE OE */
1267 1.12 drochner 0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */
1268 1.12 drochner 0x00e3, /* LATIN SMALL LETTER A WITH TILDE */
1269 1.12 drochner 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1270 1.12 drochner 0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1271 1.12 drochner 0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */
1272 1.12 drochner 0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */
1273 1.12 drochner 0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */
1274 1.12 drochner 0x0152, /* LATIN CAPITAL LIGATURE OE */
1275 1.12 drochner 0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */
1276 1.12 drochner 0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1277 1.12 drochner 0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */
1278 1.12 drochner 0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */
1279 1.12 drochner 0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1280 1.12 drochner 0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1281 1.12 drochner 0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */
1282 1.14 drochner /* 9 */ 0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */
1283 1.12 drochner 0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1284 1.12 drochner 0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1285 1.12 drochner 0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */
1286 1.12 drochner 0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */
1287 1.12 drochner 0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1288 1.12 drochner 0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */
1289 1.12 drochner 0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */
1290 1.12 drochner 0x00b9, /* SUPERSCRIPT ONE */
1291 1.12 drochner 0x00b7, /* MIDDLE DOT */
1292 1.12 drochner 0x03b6, /* GREEK SMALL LETTER ZETA */
1293 1.12 drochner 0x00b3, /* SUPERSCRIPT THREE */
1294 1.12 drochner 0x00a9, /* COPYRIGHT SIGN */
1295 1.12 drochner 0x00a4, /* CURRENCY SIGN */
1296 1.12 drochner 0x03ba, /* GREEK SMALL LETTER KAPPA */
1297 1.44 bjh21 _e000U /* mirrored question mark? */
1298 1.12 drochner };
1299 1.12 drochner
1300 1.45 junyoung static int vga_pcvt_mapchar(int, u_int *);
1301 1.12 drochner
1302 1.12 drochner static int
1303 1.45 junyoung vga_pcvt_mapchar(int uni, u_int *index)
1304 1.12 drochner {
1305 1.12 drochner int i;
1306 1.12 drochner
1307 1.12 drochner for (i = 0; i < 0xa0; i++) /* 0xa0..0xff are reserved */
1308 1.13 drochner if (uni == pcvt_unichars[i]) {
1309 1.13 drochner *index = i;
1310 1.13 drochner return (5);
1311 1.13 drochner }
1312 1.13 drochner *index = 0x99; /* middle dot */
1313 1.13 drochner return (0);
1314 1.12 drochner }
1315 1.12 drochner
1316 1.12 drochner #endif /* WSCONS_SUPPORT_PCVTFONTS */
1317 1.12 drochner
1318 1.34 drochner #ifdef WSCONS_SUPPORT_ISO7FONTS
1319 1.34 drochner
1320 1.34 drochner static int
1321 1.45 junyoung vga_iso7_mapchar(int uni, u_int *index)
1322 1.34 drochner {
1323 1.34 drochner
1324 1.34 drochner /*
1325 1.34 drochner * U+0384 (GREEK TONOS) to
1326 1.34 drochner * U+03ce (GREEK SMALL LETTER OMEGA WITH TONOS)
1327 1.34 drochner * map directly to the iso-9 font
1328 1.34 drochner */
1329 1.34 drochner if (uni >= 0x0384 && uni <= 0x03ce) {
1330 1.34 drochner /* U+0384 is at offset 0xb4 in the font */
1331 1.34 drochner *index = uni - 0x0384 + 0xb4;
1332 1.34 drochner return (5);
1333 1.34 drochner }
1334 1.34 drochner
1335 1.34 drochner /* XXX more chars in the iso-9 font */
1336 1.34 drochner
1337 1.34 drochner *index = 0xa4; /* shaded rectangle */
1338 1.34 drochner return (0);
1339 1.34 drochner }
1340 1.34 drochner
1341 1.34 drochner #endif /* WSCONS_SUPPORT_ISO7FONTS */
1342 1.34 drochner
1343 1.107 drochner static const uint16_t iso2_unichars[0x60] = {
1344 1.107 drochner 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7,
1345 1.107 drochner 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B,
1346 1.107 drochner 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7,
1347 1.107 drochner 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C,
1348 1.107 drochner 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7,
1349 1.107 drochner 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E,
1350 1.107 drochner 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7,
1351 1.107 drochner 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF,
1352 1.107 drochner 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7,
1353 1.107 drochner 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F,
1354 1.107 drochner 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7,
1355 1.107 drochner 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9
1356 1.107 drochner };
1357 1.107 drochner
1358 1.107 drochner static const uint16_t koi8_unichars[0x40] = {
1359 1.107 drochner 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
1360 1.107 drochner 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E,
1361 1.107 drochner 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
1362 1.107 drochner 0x044C, 0x044B, 0x0437, 0x0448, 0x044D, 0x0449, 0x0447, 0x044A,
1363 1.107 drochner 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
1364 1.107 drochner 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E,
1365 1.107 drochner 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
1366 1.107 drochner 0x042C, 0x042B, 0x0417, 0x0428, 0x042D, 0x0429, 0x0427, 0x042A
1367 1.107 drochner };
1368 1.107 drochner
1369 1.45 junyoung static int _vga_mapchar(void *, const struct egavga_font *, int, u_int *);
1370 1.12 drochner
1371 1.12 drochner static int
1372 1.45 junyoung _vga_mapchar(void *id, const struct egavga_font *font, int uni, u_int *index)
1373 1.12 drochner {
1374 1.12 drochner
1375 1.37 drochner switch (font->wsfont->encoding) {
1376 1.12 drochner case WSDISPLAY_FONTENC_ISO:
1377 1.13 drochner if (uni < 256) {
1378 1.13 drochner *index = uni;
1379 1.13 drochner return (5);
1380 1.13 drochner } else {
1381 1.13 drochner *index = ' ';
1382 1.13 drochner return (0);
1383 1.13 drochner }
1384 1.107 drochner case WSDISPLAY_FONTENC_ISO2:
1385 1.107 drochner if (uni < 0xa0) {
1386 1.107 drochner *index = uni;
1387 1.107 drochner return (5);
1388 1.107 drochner } else {
1389 1.107 drochner int i;
1390 1.107 drochner for (i = 0; i < 0x60; i++) {
1391 1.107 drochner if (uni == iso2_unichars[i]) {
1392 1.107 drochner *index = i + 0xa0;
1393 1.107 drochner return (5);
1394 1.107 drochner }
1395 1.107 drochner }
1396 1.107 drochner *index = 0xa4; /* currency sign */
1397 1.107 drochner return (0);
1398 1.107 drochner }
1399 1.107 drochner case WSDISPLAY_FONTENC_KOI8_R:
1400 1.107 drochner if (uni < 0x80) {
1401 1.107 drochner *index = uni;
1402 1.107 drochner return (5);
1403 1.107 drochner } else {
1404 1.107 drochner int i;
1405 1.107 drochner for (i = 0; i < 0x40; i++) {
1406 1.107 drochner if (uni == koi8_unichars[i]) {
1407 1.107 drochner *index = i + 0xc0;
1408 1.107 drochner return (5);
1409 1.107 drochner }
1410 1.107 drochner }
1411 1.107 drochner *index = 0x94; /* box */
1412 1.107 drochner return (0);
1413 1.107 drochner }
1414 1.12 drochner case WSDISPLAY_FONTENC_IBM:
1415 1.13 drochner return (pcdisplay_mapchar(id, uni, index));
1416 1.12 drochner #ifdef WSCONS_SUPPORT_PCVTFONTS
1417 1.12 drochner case WSDISPLAY_FONTENC_PCVT:
1418 1.13 drochner return (vga_pcvt_mapchar(uni, index));
1419 1.34 drochner #endif
1420 1.34 drochner #ifdef WSCONS_SUPPORT_ISO7FONTS
1421 1.34 drochner case WSDISPLAY_FONTENC_ISO7:
1422 1.34 drochner return (vga_iso7_mapchar(uni, index));
1423 1.12 drochner #endif
1424 1.13 drochner default:
1425 1.16 drochner #ifdef VGAFONTDEBUG
1426 1.37 drochner printf("_vga_mapchar: encoding=%d\n", font->wsfont->encoding);
1427 1.16 drochner #endif
1428 1.13 drochner *index = ' ';
1429 1.13 drochner return (0);
1430 1.12 drochner }
1431 1.12 drochner }
1432 1.12 drochner
1433 1.13 drochner static int
1434 1.45 junyoung vga_mapchar(void *id, int uni, u_int *index)
1435 1.12 drochner {
1436 1.12 drochner struct vgascreen *scr = id;
1437 1.45 junyoung u_int idx1, idx2;
1438 1.13 drochner int res1, res2;
1439 1.12 drochner
1440 1.13 drochner res1 = 0;
1441 1.13 drochner idx1 = ' '; /* space */
1442 1.13 drochner if (scr->fontset1)
1443 1.13 drochner res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1);
1444 1.13 drochner res2 = -1;
1445 1.12 drochner if (scr->fontset2) {
1446 1.12 drochner KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type));
1447 1.13 drochner res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2);
1448 1.12 drochner }
1449 1.13 drochner if (res2 > res1) {
1450 1.14 drochner *index = idx2 | 0x0800; /* attribute bit 3 */
1451 1.14 drochner return (res2);
1452 1.13 drochner }
1453 1.13 drochner *index = idx1;
1454 1.13 drochner return (res1);
1455 1.53 christos }
1456 1.53 christos
1457 1.72 christos #ifdef WSDISPLAY_SCROLLSUPPORT
1458 1.110 mlelstv static void
1459 1.72 christos vga_scroll(void *v, void *cookie, int lines)
1460 1.72 christos {
1461 1.72 christos struct vga_config *vc = v;
1462 1.72 christos struct vgascreen *scr = cookie;
1463 1.72 christos struct vga_handle *vh = &vc->hdl;
1464 1.72 christos
1465 1.72 christos if (lines == 0) {
1466 1.72 christos if (scr->pcs.visibleoffset == scr->pcs.dispoffset)
1467 1.72 christos return;
1468 1.72 christos
1469 1.72 christos scr->pcs.visibleoffset = scr->pcs.dispoffset;
1470 1.72 christos }
1471 1.72 christos else {
1472 1.72 christos int vga_scr_end;
1473 1.72 christos int margin = scr->pcs.type->ncols * 2;
1474 1.72 christos int ul, we, p, st;
1475 1.72 christos
1476 1.72 christos vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols *
1477 1.72 christos scr->pcs.type->nrows * 2);
1478 1.72 christos if (scr->vga_rollover > vga_scr_end + margin) {
1479 1.72 christos ul = vga_scr_end;
1480 1.72 christos we = scr->vga_rollover + scr->pcs.type->ncols * 2;
1481 1.72 christos } else {
1482 1.72 christos ul = 0;
1483 1.72 christos we = 0x8000;
1484 1.72 christos }
1485 1.72 christos p = (scr->pcs.visibleoffset - ul + we) % we + lines *
1486 1.72 christos (scr->pcs.type->ncols * 2);
1487 1.72 christos st = (scr->pcs.dispoffset - ul + we) % we;
1488 1.72 christos if (p < margin)
1489 1.72 christos p = 0;
1490 1.72 christos if (p > st - margin)
1491 1.72 christos p = st;
1492 1.72 christos scr->pcs.visibleoffset = (p + ul) % we;
1493 1.72 christos }
1494 1.81 perry
1495 1.72 christos vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9);
1496 1.72 christos vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1);
1497 1.72 christos }
1498 1.72 christos #endif
1499 1.72 christos
1500 1.110 mlelstv static void
1501 1.72 christos vga_putchar(void *c, int row, int col, u_int uc, long attr)
1502 1.72 christos {
1503 1.72 christos
1504 1.72 christos pcdisplay_putchar(c, row, col, uc, attr);
1505 1.72 christos }
1506 1.72 christos
1507 1.76 jmmv #ifdef WSDISPLAY_CUSTOM_BORDER
1508 1.85 drochner static int
1509 1.85 drochner vga_getborder(struct vga_config *vc, u_int *valuep)
1510 1.76 jmmv {
1511 1.85 drochner struct vga_handle *vh = &vc->hdl;
1512 1.76 jmmv u_int idx;
1513 1.106 christos uint8_t value;
1514 1.76 jmmv
1515 1.85 drochner if (vh->vh_mono)
1516 1.85 drochner return ENODEV;
1517 1.76 jmmv
1518 1.76 jmmv value = _vga_attr_read(vh, VGA_ATC_OVERSCAN);
1519 1.85 drochner for (idx = 0; idx < sizeof(fgansitopc); idx++) {
1520 1.85 drochner if (fgansitopc[idx] == value) {
1521 1.85 drochner *valuep = idx;
1522 1.85 drochner return (0);
1523 1.85 drochner }
1524 1.85 drochner }
1525 1.85 drochner return (EIO);
1526 1.76 jmmv }
1527 1.76 jmmv
1528 1.76 jmmv static int
1529 1.85 drochner vga_setborder(struct vga_config *vc, u_int value)
1530 1.76 jmmv {
1531 1.85 drochner struct vga_handle *vh = &vc->hdl;
1532 1.76 jmmv
1533 1.85 drochner if (vh->vh_mono)
1534 1.85 drochner return ENODEV;
1535 1.85 drochner if (value >= sizeof(fgansitopc))
1536 1.85 drochner return EINVAL;
1537 1.76 jmmv
1538 1.76 jmmv _vga_attr_write(vh, VGA_ATC_OVERSCAN, fgansitopc[value]);
1539 1.76 jmmv return (0);
1540 1.76 jmmv }
1541 1.76 jmmv #endif /* WSDISPLAY_CUSTOM_BORDER */
1542 1.97 jmcneill
1543 1.97 jmcneill void
1544 1.97 jmcneill vga_resume(struct vga_softc *sc)
1545 1.97 jmcneill {
1546 1.97 jmcneill #ifdef VGA_RESET_ON_RESUME
1547 1.97 jmcneill vga_initregs(&sc->sc_vc->hdl);
1548 1.97 jmcneill #endif
1549 1.105 jmcneill #ifdef PCDISPLAY_SOFTCURSOR
1550 1.105 jmcneill /* Disable the hardware cursor */
1551 1.105 jmcneill vga_6845_write(&sc->sc_vc->hdl, curstart, 0x20);
1552 1.105 jmcneill vga_6845_write(&sc->sc_vc->hdl, curend, 0x00);
1553 1.105 jmcneill #endif
1554 1.97 jmcneill }
1555 1.106 christos
1556 1.110 mlelstv static void
1557 1.106 christos vga_save_palette(struct vga_config *vc)
1558 1.106 christos {
1559 1.106 christos struct vga_handle *vh = &vc->hdl;
1560 1.106 christos size_t i;
1561 1.106 christos uint8_t *palette = vc->palette;
1562 1.106 christos
1563 1.106 christos if (vh->vh_mono)
1564 1.106 christos return;
1565 1.106 christos
1566 1.106 christos vga_raw_write(vh, VGA_DAC_PELMASK, 0xff);
1567 1.106 christos vga_raw_write(vh, VGA_DAC_ADDRR, 0x00);
1568 1.106 christos for (i = 0; i < sizeof(vc->palette); i++)
1569 1.106 christos *palette++ = vga_raw_read(vh, VGA_DAC_PALETTE);
1570 1.106 christos
1571 1.109 uwe vga_reset_state(vh); /* reset flip/flop */
1572 1.106 christos }
1573 1.106 christos
1574 1.110 mlelstv static void
1575 1.106 christos vga_restore_palette(struct vga_config *vc)
1576 1.106 christos {
1577 1.106 christos struct vga_handle *vh = &vc->hdl;
1578 1.106 christos size_t i;
1579 1.106 christos uint8_t *palette = vc->palette;
1580 1.106 christos
1581 1.106 christos if (vh->vh_mono)
1582 1.106 christos return;
1583 1.106 christos
1584 1.106 christos vga_raw_write(vh, VGA_DAC_PELMASK, 0xff);
1585 1.106 christos vga_raw_write(vh, VGA_DAC_ADDRW, 0x00);
1586 1.106 christos for (i = 0; i < sizeof(vc->palette); i++)
1587 1.106 christos vga_raw_write(vh, VGA_DAC_PALETTE, *palette++);
1588 1.106 christos
1589 1.109 uwe vga_reset_state(vh); /* reset flip/flop */
1590 1.106 christos vga_enable(vh);
1591 1.106 christos }
1592