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