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