| File: | dev/ic/vga.c |
| Warning: | line 1145, column 17 The left operand of '|' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: vga.c,v 1.74 2021/05/27 23:24:40 cheloha Exp $ */ | |||
| 2 | /* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */ | |||
| 3 | ||||
| 4 | /*- | |||
| 5 | * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> | |||
| 6 | * Copyright (c) 1992-1998 Søren Schmidt | |||
| 7 | * All rights reserved. | |||
| 8 | * | |||
| 9 | * Redistribution and use in source and binary forms, with or without | |||
| 10 | * modification, are permitted provided that the following conditions | |||
| 11 | * are met: | |||
| 12 | * 1. Redistributions of source code must retain the above copyright | |||
| 13 | * notice, this list of conditions and the following disclaimer as | |||
| 14 | * the first lines of this file unmodified. | |||
| 15 | * 2. Redistributions in binary form must reproduce the above copyright | |||
| 16 | * notice, this list of conditions and the following disclaimer in the | |||
| 17 | * documentation and/or other materials provided with the distribution. | |||
| 18 | * 3. The name of the author may not be used to endorse or promote products | |||
| 19 | * derived from this software without specific prior written permission. | |||
| 20 | * | |||
| 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR | |||
| 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| 23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
| 24 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
| 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
| 26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
| 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
| 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
| 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
| 30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| 31 | * | |||
| 32 | */ | |||
| 33 | /* | |||
| 34 | * Copyright (c) 1995, 1996 Carnegie-Mellon University. | |||
| 35 | * All rights reserved. | |||
| 36 | * | |||
| 37 | * Author: Chris G. Demetriou | |||
| 38 | * | |||
| 39 | * Permission to use, copy, modify and distribute this software and | |||
| 40 | * its documentation is hereby granted, provided that both the copyright | |||
| 41 | * notice and this permission notice appear in all copies of the | |||
| 42 | * software, derivative works or modified versions, and any portions | |||
| 43 | * thereof, and that both notices appear in supporting documentation. | |||
| 44 | * | |||
| 45 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |||
| 46 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND | |||
| 47 | * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |||
| 48 | * | |||
| 49 | * Carnegie Mellon requests users of this software to return to | |||
| 50 | * | |||
| 51 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |||
| 52 | * School of Computer Science | |||
| 53 | * Carnegie Mellon University | |||
| 54 | * Pittsburgh PA 15213-3890 | |||
| 55 | * | |||
| 56 | * any improvements or extensions that they make and grant Carnegie the | |||
| 57 | * rights to redistribute these changes. | |||
| 58 | */ | |||
| 59 | ||||
| 60 | #include "vga.h" | |||
| 61 | ||||
| 62 | #include <sys/param.h> | |||
| 63 | #include <sys/systm.h> | |||
| 64 | #include <sys/kernel.h> | |||
| 65 | #include <sys/device.h> | |||
| 66 | #include <sys/malloc.h> | |||
| 67 | #include <sys/queue.h> | |||
| 68 | #include <machine/bus.h> | |||
| 69 | ||||
| 70 | #include <dev/ic/mc6845reg.h> | |||
| 71 | #include <dev/ic/pcdisplayvar.h> | |||
| 72 | #include <dev/ic/vgareg.h> | |||
| 73 | ||||
| 74 | #include <dev/wscons/wsdisplayvar.h> | |||
| 75 | #include <dev/wscons/wsconsio.h> | |||
| 76 | #include <dev/wscons/unicode.h> | |||
| 77 | ||||
| 78 | #include <dev/ic/vgavar.h> | |||
| 79 | #include <dev/ic/pcdisplay.h> | |||
| 80 | ||||
| 81 | static struct vgafont { | |||
| 82 | char name[WSFONT_NAME_SIZE32]; | |||
| 83 | int height; | |||
| 84 | int encoding; | |||
| 85 | #ifdef notyet | |||
| 86 | int firstchar, numchars; | |||
| 87 | #endif | |||
| 88 | int slot; | |||
| 89 | void *fontdata; | |||
| 90 | } vga_builtinfont = { | |||
| 91 | .name = "builtin", | |||
| 92 | .height = 16, | |||
| 93 | .encoding = WSDISPLAY_FONTENC_IBM1, | |||
| 94 | #ifdef notyet | |||
| 95 | .firstchar = 0, | |||
| 96 | .numchars = 256, | |||
| 97 | #endif | |||
| 98 | .slot = 0, | |||
| 99 | .fontdata = NULL((void *)0) | |||
| 100 | }; | |||
| 101 | ||||
| 102 | int vgaconsole, vga_console_type, vga_console_attached; | |||
| 103 | struct vgascreen vga_console_screen; | |||
| 104 | struct vga_config vga_console_vc; | |||
| 105 | ||||
| 106 | int vga_selectfont(struct vga_config *, struct vgascreen *, | |||
| 107 | const char *, const char *); | |||
| 108 | void vga_init_screen(struct vga_config *, struct vgascreen *, | |||
| 109 | const struct wsscreen_descr *, int, uint32_t *); | |||
| 110 | void vga_init(struct vga_config *, bus_space_tag_t, bus_space_tag_t); | |||
| 111 | void vga_setfont(struct vga_config *, struct vgascreen *); | |||
| 112 | void vga_pick_monitor_type(struct vga_config *); | |||
| 113 | ||||
| 114 | int vga_mapchar(void *, int, unsigned int *); | |||
| 115 | int vga_putchar(void *, int, int, u_int, uint32_t); | |||
| 116 | int vga_pack_attr(void *, int, int, int, uint32_t *); | |||
| 117 | int vga_copyrows(void *, int, int, int); | |||
| 118 | void vga_unpack_attr(void *, uint32_t, int *, int *, int *); | |||
| 119 | ||||
| 120 | static const struct wsdisplay_emulops vga_emulops = { | |||
| 121 | pcdisplay_cursor, | |||
| 122 | vga_mapchar, | |||
| 123 | vga_putchar, | |||
| 124 | pcdisplay_copycols, | |||
| 125 | pcdisplay_erasecols, | |||
| 126 | vga_copyrows, | |||
| 127 | pcdisplay_eraserows, | |||
| 128 | vga_pack_attr, | |||
| 129 | vga_unpack_attr | |||
| 130 | }; | |||
| 131 | ||||
| 132 | /* | |||
| 133 | * translate WS(=ANSI) color codes to standard pc ones | |||
| 134 | */ | |||
| 135 | static const unsigned char fgansitopc[] = { | |||
| 136 | #ifdef __alpha__ | |||
| 137 | /* | |||
| 138 | * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!! | |||
| 139 | * XXX We should probably not bother with this | |||
| 140 | * XXX (reinitialize the palette registers). | |||
| 141 | */ | |||
| 142 | FG_BLACK0, FG_BLUE1, FG_GREEN2, FG_CYAN3, FG_RED4, | |||
| 143 | FG_MAGENTA5, FG_BROWN6, FG_LIGHTGREY7 | |||
| 144 | #else | |||
| 145 | FG_BLACK0, FG_RED4, FG_GREEN2, FG_BROWN6, FG_BLUE1, | |||
| 146 | FG_MAGENTA5, FG_CYAN3, FG_LIGHTGREY7 | |||
| 147 | #endif | |||
| 148 | }, bgansitopc[] = { | |||
| 149 | #ifdef __alpha__ | |||
| 150 | BG_BLACK0x00, BG_BLUE0x10, BG_GREEN0x20, BG_CYAN0x30, BG_RED0x40, | |||
| 151 | BG_MAGENTA0x50, BG_BROWN0x60, BG_LIGHTGREY0x70 | |||
| 152 | #else | |||
| 153 | BG_BLACK0x00, BG_RED0x40, BG_GREEN0x20, BG_BROWN0x60, BG_BLUE0x10, | |||
| 154 | BG_MAGENTA0x50, BG_CYAN0x30, BG_LIGHTGREY0x70 | |||
| 155 | #endif | |||
| 156 | }; | |||
| 157 | ||||
| 158 | /* | |||
| 159 | * translate standard pc color codes to WS(=ANSI) ones | |||
| 160 | */ | |||
| 161 | static const u_int8_t pctoansi[] = { | |||
| 162 | #ifdef __alpha__ | |||
| 163 | WSCOL_BLACK0, WSCOL_RED1, WSCOL_GREEN2, WSCOL_BROWN3, | |||
| 164 | WSCOL_BLUE4, WSCOL_MAGENTA5, WSCOL_CYAN6, WSCOL_WHITE7 | |||
| 165 | #else | |||
| 166 | WSCOL_BLACK0, WSCOL_BLUE4, WSCOL_GREEN2, WSCOL_CYAN6, | |||
| 167 | WSCOL_RED1, WSCOL_MAGENTA5, WSCOL_BROWN3, WSCOL_WHITE7 | |||
| 168 | #endif | |||
| 169 | }; | |||
| 170 | ||||
| 171 | ||||
| 172 | const struct wsscreen_descr vga_stdscreen = { | |||
| 173 | "80x25", 80, 25, | |||
| 174 | &vga_emulops, | |||
| 175 | 8, 16, | |||
| 176 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8 | |||
| 177 | }, vga_stdscreen_mono = { | |||
| 178 | "80x25", 80, 25, | |||
| 179 | &vga_emulops, | |||
| 180 | 8, 16, | |||
| 181 | WSSCREEN_HILIT4 | WSSCREEN_UNDERLINE16 | WSSCREEN_BLINK8 | WSSCREEN_REVERSE2 | |||
| 182 | }, vga_stdscreen_bf = { | |||
| 183 | "80x25bf", 80, 25, | |||
| 184 | &vga_emulops, | |||
| 185 | 8, 16, | |||
| 186 | WSSCREEN_WSCOLORS1 | WSSCREEN_BLINK8 | |||
| 187 | }, vga_40lscreen = { | |||
| 188 | "80x40", 80, 40, | |||
| 189 | &vga_emulops, | |||
| 190 | 8, 10, | |||
| 191 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8 | |||
| 192 | }, vga_40lscreen_mono = { | |||
| 193 | "80x40", 80, 40, | |||
| 194 | &vga_emulops, | |||
| 195 | 8, 10, | |||
| 196 | WSSCREEN_HILIT4 | WSSCREEN_UNDERLINE16 | WSSCREEN_BLINK8 | WSSCREEN_REVERSE2 | |||
| 197 | }, vga_40lscreen_bf = { | |||
| 198 | "80x40bf", 80, 40, | |||
| 199 | &vga_emulops, | |||
| 200 | 8, 10, | |||
| 201 | WSSCREEN_WSCOLORS1 | WSSCREEN_BLINK8 | |||
| 202 | }, vga_50lscreen = { | |||
| 203 | "80x50", 80, 50, | |||
| 204 | &vga_emulops, | |||
| 205 | 8, 8, | |||
| 206 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8 | |||
| 207 | }, vga_50lscreen_mono = { | |||
| 208 | "80x50", 80, 50, | |||
| 209 | &vga_emulops, | |||
| 210 | 8, 8, | |||
| 211 | WSSCREEN_HILIT4 | WSSCREEN_UNDERLINE16 | WSSCREEN_BLINK8 | WSSCREEN_REVERSE2 | |||
| 212 | }, vga_50lscreen_bf = { | |||
| 213 | "80x50bf", 80, 50, | |||
| 214 | &vga_emulops, | |||
| 215 | 8, 8, | |||
| 216 | WSSCREEN_WSCOLORS1 | WSSCREEN_BLINK8 | |||
| 217 | }; | |||
| 218 | ||||
| 219 | #define VGA_SCREEN_CANTWOFONTS(type)(!((type)->capabilities & 4)) (!((type)->capabilities & WSSCREEN_HILIT4)) | |||
| 220 | ||||
| 221 | const struct wsscreen_descr *_vga_scrlist[] = { | |||
| 222 | &vga_stdscreen, | |||
| 223 | &vga_stdscreen_bf, | |||
| 224 | &vga_40lscreen, | |||
| 225 | &vga_40lscreen_bf, | |||
| 226 | &vga_50lscreen, | |||
| 227 | &vga_50lscreen_bf, | |||
| 228 | /* XXX other formats, graphics screen? */ | |||
| 229 | }, *_vga_scrlist_mono[] = { | |||
| 230 | &vga_stdscreen_mono, | |||
| 231 | &vga_40lscreen_mono, | |||
| 232 | &vga_50lscreen_mono, | |||
| 233 | /* XXX other formats, graphics screen? */ | |||
| 234 | }; | |||
| 235 | ||||
| 236 | const struct wsscreen_list vga_screenlist = { | |||
| 237 | sizeof(_vga_scrlist) / sizeof(struct wsscreen_descr *), | |||
| 238 | _vga_scrlist | |||
| 239 | }, vga_screenlist_mono = { | |||
| 240 | sizeof(_vga_scrlist_mono) / sizeof(struct wsscreen_descr *), | |||
| 241 | _vga_scrlist_mono | |||
| 242 | }; | |||
| 243 | ||||
| 244 | int vga_ioctl(void *, u_long, caddr_t, int, struct proc *); | |||
| 245 | paddr_t vga_mmap(void *, off_t, int); | |||
| 246 | int vga_alloc_screen(void *, const struct wsscreen_descr *, | |||
| 247 | void **, int *, int *, uint32_t *); | |||
| 248 | void vga_free_screen(void *, void *); | |||
| 249 | int vga_show_screen(void *, void *, int, | |||
| 250 | void (*) (void *, int, int), void *); | |||
| 251 | int vga_load_font(void *, void *, struct wsdisplay_font *); | |||
| 252 | int vga_list_font(void *, struct wsdisplay_font *); | |||
| 253 | void vga_scrollback(void *, void *, int); | |||
| 254 | void vga_burner(void *v, u_int on, u_int flags); | |||
| 255 | int vga_getchar(void *, int, int, struct wsdisplay_charcell *); | |||
| 256 | ||||
| 257 | void vga_doswitch(void *); | |||
| 258 | ||||
| 259 | const struct wsdisplay_accessops vga_accessops = { | |||
| 260 | .ioctl = vga_ioctl, | |||
| 261 | .mmap = vga_mmap, | |||
| 262 | .alloc_screen = vga_alloc_screen, | |||
| 263 | .free_screen = vga_free_screen, | |||
| 264 | .show_screen = vga_show_screen, | |||
| 265 | .load_font = vga_load_font, | |||
| 266 | .list_font = vga_list_font, | |||
| 267 | .scrollback = vga_scrollback, | |||
| 268 | .getchar = vga_getchar, | |||
| 269 | .burn_screen = vga_burner | |||
| 270 | }; | |||
| 271 | ||||
| 272 | /* | |||
| 273 | * The following functions implement back-end configuration grabbing | |||
| 274 | * and attachment. | |||
| 275 | */ | |||
| 276 | int | |||
| 277 | vga_common_probe(bus_space_tag_t iot, bus_space_tag_t memt) | |||
| 278 | { | |||
| 279 | bus_space_handle_t ioh_vga, ioh_6845, memh; | |||
| 280 | u_int8_t regval; | |||
| 281 | u_int16_t vgadata; | |||
| 282 | int gotio_vga, gotio_6845, gotmem, mono, rv; | |||
| 283 | int dispoffset; | |||
| 284 | ||||
| 285 | gotio_vga = gotio_6845 = gotmem = rv = 0; | |||
| 286 | ||||
| 287 | if (bus_space_map(iot, 0x3c0, 0x10, 0, &ioh_vga)) | |||
| 288 | goto bad; | |||
| 289 | gotio_vga = 1; | |||
| 290 | ||||
| 291 | /* read "misc output register" */ | |||
| 292 | regval = bus_space_read_1(iot, ioh_vga, 0xc)((iot)->read_1((ioh_vga), (0xc))); | |||
| 293 | mono = !(regval & 1); | |||
| 294 | ||||
| 295 | if (bus_space_map(iot, (mono ? 0x3b0 : 0x3d0), 0x10, 0, &ioh_6845)) | |||
| 296 | goto bad; | |||
| 297 | gotio_6845 = 1; | |||
| 298 | ||||
| 299 | if (bus_space_map(memt, 0xa0000, 0x20000, 0, &memh)) | |||
| 300 | goto bad; | |||
| 301 | gotmem = 1; | |||
| 302 | ||||
| 303 | dispoffset = (mono ? 0x10000 : 0x18000); | |||
| 304 | ||||
| 305 | vgadata = bus_space_read_2(memt, memh, dispoffset)((memt)->read_2((memh), (dispoffset))); | |||
| 306 | bus_space_write_2(memt, memh, dispoffset, 0xa55a)((memt)->write_2((memh), (dispoffset), (0xa55a))); | |||
| 307 | if (bus_space_read_2(memt, memh, dispoffset)((memt)->read_2((memh), (dispoffset))) != 0xa55a) | |||
| 308 | goto bad; | |||
| 309 | bus_space_write_2(memt, memh, dispoffset, vgadata)((memt)->write_2((memh), (dispoffset), (vgadata))); | |||
| 310 | ||||
| 311 | /* | |||
| 312 | * check if this is really a VGA | |||
| 313 | * (try to write "Color Select" register as XFree86 does) | |||
| 314 | * XXX check before if at least EGA? | |||
| 315 | */ | |||
| 316 | /* reset state */ | |||
| 317 | (void) bus_space_read_1(iot, ioh_6845, 10)((iot)->read_1((ioh_6845), (10))); | |||
| 318 | bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,((iot)->write_1((ioh_vga), (0), (20 | 0x20))) | |||
| 319 | 20 | 0x20)((iot)->write_1((ioh_vga), (0), (20 | 0x20))); /* colselect | enable */ | |||
| 320 | regval = bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR)((iot)->read_1((ioh_vga), (1))); | |||
| 321 | /* toggle the implemented bits */ | |||
| 322 | bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval ^ 0x0f)((iot)->write_1((ioh_vga), (0), (regval ^ 0x0f))); | |||
| 323 | bus_space_write_1(iot, ioh_vga, VGA_ATC_INDEX,((iot)->write_1((ioh_vga), (0), (20 | 0x20))) | |||
| 324 | 20 | 0x20)((iot)->write_1((ioh_vga), (0), (20 | 0x20))); | |||
| 325 | /* read back */ | |||
| 326 | if (bus_space_read_1(iot, ioh_vga, VGA_ATC_DATAR)((iot)->read_1((ioh_vga), (1))) != (regval ^ 0x0f)) | |||
| 327 | goto bad; | |||
| 328 | /* restore contents */ | |||
| 329 | bus_space_write_1(iot, ioh_vga, VGA_ATC_DATAW, regval)((iot)->write_1((ioh_vga), (0), (regval))); | |||
| 330 | ||||
| 331 | rv = 1; | |||
| 332 | bad: | |||
| 333 | if (gotio_vga) | |||
| 334 | bus_space_unmap(iot, ioh_vga, 0x10); | |||
| 335 | if (gotio_6845) | |||
| 336 | bus_space_unmap(iot, ioh_6845, 0x10); | |||
| 337 | if (gotmem) | |||
| 338 | bus_space_unmap(memt, memh, 0x20000); | |||
| 339 | ||||
| 340 | return (rv); | |||
| 341 | } | |||
| 342 | ||||
| 343 | /* | |||
| 344 | * We want at least ASCII 32..127 be present in the | |||
| 345 | * first font slot. | |||
| 346 | */ | |||
| 347 | int | |||
| 348 | vga_selectfont(struct vga_config *vc, struct vgascreen *scr, const char *name1, | |||
| 349 | const char *name2) /* NULL: take first found */ | |||
| 350 | { | |||
| 351 | const struct wsscreen_descr *type = scr->pcs.type; | |||
| 352 | struct vgafont *f1, *f2; | |||
| 353 | int i; | |||
| 354 | ||||
| 355 | f1 = f2 = 0; | |||
| 356 | ||||
| 357 | for (i = 0; i < VGA_MAXFONT8; i++) { | |||
| 358 | struct vgafont *f = vc->vc_fonts[i]; | |||
| 359 | if (!f || f->height != type->fontheight) | |||
| 360 | continue; | |||
| 361 | if (!f1 && (!name1 || !*name1 || | |||
| 362 | !strncmp(name1, f->name, WSFONT_NAME_SIZE32))) { | |||
| 363 | f1 = f; | |||
| 364 | continue; | |||
| 365 | } | |||
| 366 | if (!f2 && | |||
| 367 | VGA_SCREEN_CANTWOFONTS(type)(!((type)->capabilities & 4)) && | |||
| 368 | (!name2 || !*name2 || | |||
| 369 | !strncmp(name2, f->name, WSFONT_NAME_SIZE32))) { | |||
| 370 | f2 = f; | |||
| 371 | continue; | |||
| 372 | } | |||
| 373 | } | |||
| 374 | ||||
| 375 | /* | |||
| 376 | * The request fails if no primary font was found, | |||
| 377 | * or if a second font was requested but not found. | |||
| 378 | */ | |||
| 379 | if (f1 && (!name2 || !*name2 || f2)) { | |||
| 380 | #ifdef VGAFONTDEBUG | |||
| 381 | if (scr != &vga_console_screen || vga_console_attached) { | |||
| 382 | printf("vga (%s): font1=%s (slot %d)", type->name, | |||
| 383 | f1->name, f1->slot); | |||
| 384 | if (f2) | |||
| 385 | printf(", font2=%s (slot %d)", | |||
| 386 | f2->name, f2->slot); | |||
| 387 | printf("\n"); | |||
| 388 | } | |||
| 389 | #endif | |||
| 390 | scr->fontset1 = f1; | |||
| 391 | scr->fontset2 = f2; | |||
| 392 | return (0); | |||
| 393 | } | |||
| 394 | return (ENXIO6); | |||
| 395 | } | |||
| 396 | ||||
| 397 | void | |||
| 398 | vga_init_screen(struct vga_config *vc, struct vgascreen *scr, | |||
| 399 | const struct wsscreen_descr *type, int existing, uint32_t *attrp) | |||
| 400 | { | |||
| 401 | int cpos; | |||
| 402 | int res; | |||
| 403 | ||||
| 404 | scr->cfg = vc; | |||
| 405 | scr->pcs.hdl = (struct pcdisplay_handle *)&vc->hdl; | |||
| 406 | scr->pcs.type = type; | |||
| 407 | scr->pcs.active = 0; | |||
| 408 | scr->mindispoffset = 0; | |||
| 409 | scr->maxdispoffset = 0x8000 - type->nrows * type->ncols * 2; | |||
| 410 | ||||
| 411 | if (existing) { | |||
| 412 | cpos = vga_6845_read(&vc->hdl, cursorh)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, cursorh)) << 8; | |||
| 413 | cpos |= vga_6845_read(&vc->hdl, cursorl)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, cursorl)); | |||
| 414 | ||||
| 415 | /* make sure we have a valid cursor position */ | |||
| 416 | if (cpos < 0 || cpos >= type->nrows * type->ncols) | |||
| 417 | cpos = 0; | |||
| 418 | ||||
| 419 | scr->pcs.dispoffset = vga_6845_read(&vc->hdl, startadrh)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrh)) << 9; | |||
| 420 | scr->pcs.dispoffset |= vga_6845_read(&vc->hdl, startadrl)_pcdisplay_6845_read(&(&vc->hdl)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrl)) << 1; | |||
| 421 | ||||
| 422 | /* make sure we have a valid memory offset */ | |||
| 423 | if (scr->pcs.dispoffset < scr->mindispoffset || | |||
| 424 | scr->pcs.dispoffset > scr->maxdispoffset) | |||
| 425 | scr->pcs.dispoffset = scr->mindispoffset; | |||
| 426 | } else { | |||
| 427 | cpos = 0; | |||
| 428 | scr->pcs.dispoffset = scr->mindispoffset; | |||
| 429 | } | |||
| 430 | scr->pcs.visibleoffset = scr->pcs.dispoffset; | |||
| 431 | scr->vga_rollover = 0; | |||
| 432 | ||||
| 433 | scr->pcs.vc_crow = cpos / type->ncols; | |||
| 434 | scr->pcs.vc_ccol = cpos % type->ncols; | |||
| 435 | pcdisplay_cursor_init(&scr->pcs, existing); | |||
| 436 | ||||
| 437 | #ifdef __alpha__ | |||
| 438 | if (!vc->hdl.vh_mono) | |||
| 439 | /* | |||
| 440 | * DEC firmware uses a blue background. | |||
| 441 | */ | |||
| 442 | res = vga_pack_attr(scr, WSCOL_WHITE7, WSCOL_BLUE4, | |||
| 443 | WSATTR_WSCOLORS16, attrp); | |||
| 444 | else | |||
| 445 | #endif | |||
| 446 | res = vga_pack_attr(scr, 0, 0, 0, attrp); | |||
| 447 | #ifdef DIAGNOSTIC1 | |||
| 448 | if (res) | |||
| 449 | panic("vga_init_screen: attribute botch"); | |||
| 450 | #endif | |||
| 451 | ||||
| 452 | scr->pcs.mem = NULL((void *)0); | |||
| 453 | ||||
| 454 | scr->fontset1 = scr->fontset2 = 0; | |||
| 455 | if (vga_selectfont(vc, scr, 0, 0)) { | |||
| 456 | if (scr == &vga_console_screen) | |||
| 457 | panic("vga_init_screen: no font"); | |||
| 458 | else | |||
| 459 | printf("vga_init_screen: no font\n"); | |||
| 460 | } | |||
| 461 | ||||
| 462 | vc->nscreens++; | |||
| 463 | LIST_INSERT_HEAD(&vc->screens, scr, next)do { if (((scr)->next.le_next = (&vc->screens)-> lh_first) != ((void *)0)) (&vc->screens)->lh_first-> next.le_prev = &(scr)->next.le_next; (&vc->screens )->lh_first = (scr); (scr)->next.le_prev = &(&vc ->screens)->lh_first; } while (0); | |||
| 464 | } | |||
| 465 | ||||
| 466 | void | |||
| 467 | vga_init(struct vga_config *vc, bus_space_tag_t iot, bus_space_tag_t memt) | |||
| 468 | { | |||
| 469 | struct vga_handle *vh = &vc->hdl; | |||
| 470 | u_int8_t mor; | |||
| 471 | int i; | |||
| 472 | ||||
| 473 | vh->vh_iotvh_ph.ph_iot = iot; | |||
| 474 | vh->vh_memtvh_ph.ph_memt = memt; | |||
| 475 | ||||
| 476 | if (bus_space_map(vh->vh_iotvh_ph.ph_iot, 0x3c0, 0x10, 0, &vh->vh_ioh_vga)) | |||
| 477 | panic("vga_common_setup: can't map vga i/o"); | |||
| 478 | ||||
| 479 | /* read "misc output register" */ | |||
| 480 | mor = bus_space_read_1(vh->vh_iot, vh->vh_ioh_vga, 0xc)((vh->vh_ph.ph_iot)->read_1((vh->vh_ioh_vga), (0xc)) ); | |||
| 481 | vh->vh_mono = !(mor & 1); | |||
| 482 | ||||
| 483 | if (bus_space_map(vh->vh_iotvh_ph.ph_iot, (vh->vh_mono ? 0x3b0 : 0x3d0), 0x10, 0, | |||
| 484 | &vh->vh_ioh_6845vh_ph.ph_ioh_6845)) | |||
| 485 | panic("vga_common_setup: can't map 6845 i/o"); | |||
| 486 | ||||
| 487 | if (bus_space_map(vh->vh_memtvh_ph.ph_memt, 0xa0000, 0x20000, 0, &vh->vh_allmemh)) | |||
| 488 | panic("vga_common_setup: can't map mem space"); | |||
| 489 | ||||
| 490 | if (bus_space_subregion(vh->vh_memtvh_ph.ph_memt, vh->vh_allmemh, | |||
| 491 | (vh->vh_mono ? 0x10000 : 0x18000), 0x8000, | |||
| 492 | &vh->vh_memhvh_ph.ph_memh)) | |||
| 493 | panic("vga_common_setup: mem subrange failed"); | |||
| 494 | ||||
| 495 | #ifdef __alpha__ | |||
| 496 | vga_pick_monitor_type(vc); | |||
| 497 | #endif | |||
| 498 | ||||
| 499 | vc->nscreens = 0; | |||
| 500 | LIST_INIT(&vc->screens)do { ((&vc->screens)->lh_first) = ((void *)0); } while (0); | |||
| 501 | vc->active = NULL((void *)0); | |||
| 502 | #ifdef __alpha__ | |||
| 503 | if (vc->custom_list.screens != NULL((void *)0)) | |||
| 504 | vc->currenttype = vc->custom_list.screens[0]; | |||
| 505 | else | |||
| 506 | #endif | |||
| 507 | vc->currenttype = | |||
| 508 | vh->vh_mono ? &vga_stdscreen_mono : &vga_stdscreen; | |||
| 509 | ||||
| 510 | vc->vc_fonts[0] = &vga_builtinfont; | |||
| 511 | for (i = 1; i < VGA_MAXFONT8; i++) | |||
| 512 | vc->vc_fonts[i] = NULL((void *)0); | |||
| 513 | ||||
| 514 | vc->currentfontset1 = vc->currentfontset2 = 0; | |||
| 515 | ||||
| 516 | vga_save_palette(vc); | |||
| 517 | } | |||
| 518 | ||||
| 519 | struct vga_config * | |||
| 520 | vga_common_attach(struct device *self, bus_space_tag_t iot, | |||
| 521 | bus_space_tag_t memt, int type) | |||
| 522 | { | |||
| 523 | return vga_extended_attach(self, iot, memt, type, NULL((void *)0)); | |||
| 524 | } | |||
| 525 | ||||
| 526 | struct vga_config * | |||
| 527 | vga_extended_attach(struct device *self, bus_space_tag_t iot, | |||
| 528 | bus_space_tag_t memt, int type, paddr_t (*map)(void *, off_t, int)) | |||
| 529 | { | |||
| 530 | int console; | |||
| 531 | struct vga_config *vc; | |||
| 532 | struct wsemuldisplaydev_attach_args aa; | |||
| 533 | ||||
| 534 | console = vga_is_console(iot, type); | |||
| 535 | if (console) | |||
| 536 | vga_console_attached = 1; | |||
| 537 | ||||
| 538 | if (type == -1) | |||
| 539 | return NULL((void *)0); | |||
| 540 | ||||
| 541 | if (console) { | |||
| 542 | vc = &vga_console_vc; | |||
| 543 | } else { | |||
| 544 | vc = malloc(sizeof(*vc), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
| 545 | if (vc == NULL((void *)0)) | |||
| 546 | return NULL((void *)0); | |||
| 547 | vga_init(vc, iot, memt); | |||
| 548 | } | |||
| 549 | ||||
| 550 | vc->vc_softc = self; | |||
| 551 | vc->vc_type = type; | |||
| 552 | vc->vc_mmap = map; | |||
| 553 | ||||
| 554 | aa.console = console; | |||
| 555 | #ifdef __alpha__ | |||
| 556 | if (vc->custom_list.screens != NULL((void *)0)) | |||
| 557 | aa.scrdata = &vc->custom_list; | |||
| 558 | else | |||
| 559 | #endif | |||
| 560 | aa.scrdata = | |||
| 561 | vc->hdl.vh_mono ? &vga_screenlist_mono : &vga_screenlist; | |||
| 562 | ||||
| 563 | aa.accessops = &vga_accessops; | |||
| 564 | aa.accesscookie = vc; | |||
| 565 | aa.defaultscreens = 0; | |||
| 566 | ||||
| 567 | config_found_sm(self, &aa, wsemuldisplaydevprint, | |||
| 568 | wsemuldisplaydevsubmatch); | |||
| 569 | ||||
| 570 | return vc; | |||
| 571 | } | |||
| 572 | ||||
| 573 | int | |||
| 574 | vga_cnattach(bus_space_tag_t iot, bus_space_tag_t memt, int type, int check) | |||
| 575 | { | |||
| 576 | uint32_t defattr; | |||
| 577 | const struct wsscreen_descr *scr; | |||
| 578 | ||||
| 579 | if (check && !vga_common_probe(iot, memt)) | |||
| 580 | return (ENXIO6); | |||
| 581 | ||||
| 582 | /* set up bus-independent VGA configuration */ | |||
| 583 | vga_init(&vga_console_vc, iot, memt); | |||
| 584 | scr = vga_console_vc.currenttype; | |||
| 585 | vga_init_screen(&vga_console_vc, &vga_console_screen, scr, 1, &defattr); | |||
| 586 | ||||
| 587 | vga_console_screen.pcs.active = 1; | |||
| 588 | vga_console_vc.active = &vga_console_screen; | |||
| 589 | ||||
| 590 | wsdisplay_cnattach(scr, &vga_console_screen, | |||
| 591 | vga_console_screen.pcs.vc_ccol, | |||
| 592 | vga_console_screen.pcs.vc_crow, | |||
| 593 | defattr); | |||
| 594 | ||||
| 595 | vgaconsole = 1; | |||
| 596 | vga_console_type = type; | |||
| 597 | return (0); | |||
| 598 | } | |||
| 599 | ||||
| 600 | int | |||
| 601 | vga_is_console(bus_space_tag_t iot, int type) | |||
| 602 | { | |||
| 603 | if (vgaconsole && | |||
| 604 | !vga_console_attached && | |||
| 605 | iot == vga_console_vc.hdl.vh_iotvh_ph.ph_iot && | |||
| 606 | (vga_console_type == -1 || (type == vga_console_type))) | |||
| 607 | return (1); | |||
| 608 | return (0); | |||
| 609 | } | |||
| 610 | ||||
| 611 | int | |||
| 612 | vga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) | |||
| 613 | { | |||
| 614 | struct vga_config *vc = v; | |||
| 615 | int mode; | |||
| 616 | #if NVGA_PCI1 > 0 | |||
| 617 | int error; | |||
| 618 | ||||
| 619 | if (vc->vc_type == WSDISPLAY_TYPE_PCIVGA8 && | |||
| 620 | (error = vga_pci_ioctl(v, cmd, data, flag, p)) != ENOTTY25) | |||
| 621 | return (error); | |||
| 622 | #endif | |||
| 623 | ||||
| 624 | switch (cmd) { | |||
| 625 | case WSDISPLAYIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((64))): | |||
| 626 | *(int *)data = vc->vc_type; | |||
| 627 | /* XXX should get detailed hardware information here */ | |||
| 628 | break; | |||
| 629 | ||||
| 630 | case WSDISPLAYIO_SMODE((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((76))): | |||
| 631 | mode = *(u_int *)data; | |||
| 632 | if (mode == WSDISPLAYIO_MODE_EMUL0) { | |||
| 633 | vga_restore_fonts(vc); | |||
| 634 | vga_restore_palette(vc); | |||
| 635 | } | |||
| 636 | break; | |||
| 637 | ||||
| 638 | case WSDISPLAYIO_GVIDEO((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((68))): | |||
| 639 | case WSDISPLAYIO_SVIDEO((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) << 16) | ((('W')) << 8) | ((69))): | |||
| 640 | break; | |||
| 641 | ||||
| 642 | case WSDISPLAYIO_GINFO((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_fbinfo ) & 0x1fff) << 16) | ((('W')) << 8) | ((65))): | |||
| 643 | case WSDISPLAYIO_GETCMAP((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_cmap) & 0x1fff) << 16) | ((('W')) << 8) | ((66))): | |||
| 644 | case WSDISPLAYIO_PUTCMAP((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_cmap) & 0x1fff) << 16) | ((('W')) << 8) | ((67))): | |||
| 645 | case WSDISPLAYIO_GCURPOS((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_curpos ) & 0x1fff) << 16) | ((('W')) << 8) | ((70))): | |||
| 646 | case WSDISPLAYIO_SCURPOS((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_curpos ) & 0x1fff) << 16) | ((('W')) << 8) | ((71))): | |||
| 647 | case WSDISPLAYIO_GCURMAX((unsigned long)0x40000000 | ((sizeof(struct wsdisplay_curpos ) & 0x1fff) << 16) | ((('W')) << 8) | ((72))): | |||
| 648 | case WSDISPLAYIO_GCURSOR(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct wsdisplay_cursor) & 0x1fff) << 16) | ((('W' )) << 8) | ((73))): | |||
| 649 | case WSDISPLAYIO_SCURSOR((unsigned long)0x80000000 | ((sizeof(struct wsdisplay_cursor ) & 0x1fff) << 16) | ((('W')) << 8) | ((74))): | |||
| 650 | default: | |||
| 651 | /* NONE of these operations are by the generic VGA driver. */ | |||
| 652 | return ENOTTY25; | |||
| 653 | } | |||
| 654 | ||||
| 655 | return (0); | |||
| 656 | } | |||
| 657 | ||||
| 658 | paddr_t | |||
| 659 | vga_mmap(void *v, off_t offset, int prot) | |||
| 660 | { | |||
| 661 | struct vga_config *vc = v; | |||
| 662 | ||||
| 663 | if (vc->vc_mmap != NULL((void *)0)) | |||
| 664 | return (*vc->vc_mmap)(v, offset, prot); | |||
| 665 | ||||
| 666 | return (paddr_t)-1; | |||
| 667 | } | |||
| 668 | ||||
| 669 | int | |||
| 670 | vga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, | |||
| 671 | int *curxp, int *curyp, uint32_t *defattrp) | |||
| 672 | { | |||
| 673 | struct vga_config *vc = v; | |||
| 674 | struct vgascreen *scr; | |||
| 675 | ||||
| 676 | if (vc->nscreens == 1) { | |||
| 677 | /* | |||
| 678 | * When allocating the second screen, get backing store | |||
| 679 | * for the first one too. | |||
| 680 | * XXX We could be more clever and use video RAM. | |||
| 681 | */ | |||
| 682 | scr = LIST_FIRST(&vc->screens)((&vc->screens)->lh_first); | |||
| 683 | scr->pcs.mem = mallocarray(scr->pcs.type->ncols, | |||
| 684 | scr->pcs.type->nrows * 2, M_DEVBUF2, M_WAITOK0x0001); | |||
| 685 | } | |||
| 686 | ||||
| 687 | scr = malloc(sizeof(struct vgascreen), M_DEVBUF2, M_WAITOK0x0001); | |||
| 688 | vga_init_screen(vc, scr, type, vc->nscreens == 0, defattrp); | |||
| 689 | ||||
| 690 | if (vc->nscreens == 1) { | |||
| 691 | scr->pcs.active = 1; | |||
| 692 | vc->active = scr; | |||
| 693 | vc->currenttype = type; | |||
| 694 | } else { | |||
| 695 | scr->pcs.mem = mallocarray(type->ncols, | |||
| 696 | type->nrows * 2, M_DEVBUF2, M_WAITOK0x0001); | |||
| 697 | pcdisplay_eraserows(&scr->pcs, 0, type->nrows, *defattrp); | |||
| 698 | } | |||
| 699 | ||||
| 700 | *cookiep = scr; | |||
| 701 | *curxp = scr->pcs.vc_ccol; | |||
| 702 | *curyp = scr->pcs.vc_crow; | |||
| 703 | ||||
| 704 | return (0); | |||
| 705 | } | |||
| 706 | ||||
| 707 | void | |||
| 708 | vga_free_screen(void *v, void *cookie) | |||
| 709 | { | |||
| 710 | struct vgascreen *vs = cookie; | |||
| 711 | struct vga_config *vc = vs->cfg; | |||
| 712 | ||||
| 713 | LIST_REMOVE(vs, next)do { if ((vs)->next.le_next != ((void *)0)) (vs)->next. le_next->next.le_prev = (vs)->next.le_prev; *(vs)->next .le_prev = (vs)->next.le_next; ((vs)->next.le_prev) = ( (void *)-1); ((vs)->next.le_next) = ((void *)-1); } while ( 0); | |||
| 714 | vc->nscreens--; | |||
| 715 | if (vs != &vga_console_screen) { | |||
| 716 | /* | |||
| 717 | * deallocating the one but last screen | |||
| 718 | * removes backing store for the last one | |||
| 719 | */ | |||
| 720 | if (vc->nscreens == 1) | |||
| 721 | free(LIST_FIRST(&vc->screens)((&vc->screens)->lh_first)->pcs.mem, M_DEVBUF2, 0); | |||
| 722 | ||||
| 723 | /* Last screen has no backing store */ | |||
| 724 | if (vc->nscreens != 0) | |||
| 725 | free(vs->pcs.mem, M_DEVBUF2, 0); | |||
| 726 | ||||
| 727 | free(vs, M_DEVBUF2, sizeof *vs); | |||
| 728 | } else | |||
| 729 | panic("vga_free_screen: console"); | |||
| 730 | ||||
| 731 | if (vc->active == vs) | |||
| 732 | vc->active = NULL((void *)0); | |||
| 733 | } | |||
| 734 | ||||
| 735 | void | |||
| 736 | vga_setfont(struct vga_config *vc, struct vgascreen *scr) | |||
| 737 | { | |||
| 738 | int fontslot1, fontslot2; | |||
| 739 | ||||
| 740 | fontslot1 = (scr->fontset1 ? scr->fontset1->slot : 0); | |||
| 741 | fontslot2 = (scr->fontset2 ? scr->fontset2->slot : fontslot1); | |||
| 742 | if (vc->currentfontset1 != fontslot1 || | |||
| 743 | vc->currentfontset2 != fontslot2) { | |||
| 744 | vga_setfontset(&vc->hdl, fontslot1, fontslot2); | |||
| 745 | vc->currentfontset1 = fontslot1; | |||
| 746 | vc->currentfontset2 = fontslot2; | |||
| 747 | } | |||
| 748 | } | |||
| 749 | ||||
| 750 | int | |||
| 751 | vga_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), | |||
| 752 | void *cbarg) | |||
| 753 | { | |||
| 754 | struct vgascreen *scr = cookie, *oldscr; | |||
| 755 | struct vga_config *vc = scr->cfg; | |||
| 756 | ||||
| 757 | oldscr = vc->active; /* can be NULL! */ | |||
| 758 | if (scr == oldscr) { | |||
| 759 | return (0); | |||
| 760 | } | |||
| 761 | ||||
| 762 | vc->wantedscreen = cookie; | |||
| 763 | vc->switchcb = cb; | |||
| 764 | vc->switchcbarg = cbarg; | |||
| 765 | if (cb) { | |||
| 766 | timeout_set(&vc->vc_switch_timeout, vga_doswitch, vc); | |||
| 767 | timeout_add(&vc->vc_switch_timeout, 0); | |||
| 768 | return (EAGAIN35); | |||
| 769 | } | |||
| 770 | ||||
| 771 | vga_doswitch(vc); | |||
| 772 | return (0); | |||
| 773 | } | |||
| 774 | ||||
| 775 | void | |||
| 776 | vga_doswitch(void *arg) | |||
| 777 | { | |||
| 778 | struct vga_config *vc = arg; | |||
| 779 | struct vgascreen *scr, *oldscr; | |||
| 780 | struct vga_handle *vh = &vc->hdl; | |||
| 781 | const struct wsscreen_descr *type; | |||
| 782 | int s; | |||
| 783 | ||||
| 784 | scr = vc->wantedscreen; | |||
| 785 | if (!scr) { | |||
| 786 | printf("vga_doswitch: disappeared\n"); | |||
| 787 | (*vc->switchcb)(vc->switchcbarg, EIO5, 0); | |||
| 788 | return; | |||
| 789 | } | |||
| 790 | ||||
| 791 | type = scr->pcs.type; | |||
| 792 | oldscr = vc->active; /* can be NULL! */ | |||
| 793 | if (scr == oldscr) | |||
| 794 | return; | |||
| 795 | s = spltty()splraise(0x9); | |||
| 796 | #ifdef DIAGNOSTIC1 | |||
| 797 | if (oldscr) { | |||
| 798 | if (!oldscr->pcs.active) | |||
| 799 | panic("vga_show_screen: not active"); | |||
| 800 | if (oldscr->pcs.type != vc->currenttype) | |||
| 801 | panic("vga_show_screen: bad type"); | |||
| 802 | } | |||
| 803 | if (scr->pcs.active) | |||
| 804 | panic("vga_show_screen: active"); | |||
| 805 | #endif | |||
| 806 | ||||
| 807 | scr->vga_rollover = 0; | |||
| 808 | ||||
| 809 | if (oldscr) { | |||
| 810 | const struct wsscreen_descr *oldtype = oldscr->pcs.type; | |||
| 811 | ||||
| 812 | oldscr->pcs.active = 0; | |||
| 813 | bus_space_read_region_2(vh->vh_memt, vh->vh_memh,((vh->vh_ph.ph_memt)->read_region_2((vh->vh_ph.ph_memh ), (oldscr->pcs.dispoffset), (oldscr->pcs.mem), (oldtype ->ncols * oldtype->nrows))) | |||
| 814 | oldscr->pcs.dispoffset, oldscr->pcs.mem,((vh->vh_ph.ph_memt)->read_region_2((vh->vh_ph.ph_memh ), (oldscr->pcs.dispoffset), (oldscr->pcs.mem), (oldtype ->ncols * oldtype->nrows))) | |||
| 815 | oldtype->ncols * oldtype->nrows)((vh->vh_ph.ph_memt)->read_region_2((vh->vh_ph.ph_memh ), (oldscr->pcs.dispoffset), (oldscr->pcs.mem), (oldtype ->ncols * oldtype->nrows))); | |||
| 816 | } | |||
| 817 | ||||
| 818 | if (vc->currenttype != type) { | |||
| 819 | vga_setscreentype(vh, type); | |||
| 820 | vc->currenttype = type; | |||
| 821 | } | |||
| 822 | ||||
| 823 | vga_restore_fonts(vc); | |||
| 824 | vga_setfont(vc, scr); | |||
| 825 | vga_restore_palette(vc); | |||
| 826 | ||||
| 827 | scr->pcs.visibleoffset = scr->pcs.dispoffset = scr->mindispoffset; | |||
| 828 | if (!oldscr || (scr->pcs.dispoffset != oldscr->pcs.dispoffset)) { | |||
| 829 | vga_6845_write(vh, startadrh, scr->pcs.dispoffset >> 9)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrh), scr->pcs.dispoffset >> 9); | |||
| 830 | vga_6845_write(vh, startadrl, scr->pcs.dispoffset >> 1)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrl), scr->pcs.dispoffset >> 1); | |||
| 831 | } | |||
| 832 | ||||
| 833 | bus_space_write_region_2(vh->vh_memt, vh->vh_memh,((vh->vh_ph.ph_memt)->write_region_2((vh->vh_ph.ph_memh ), (scr->pcs.dispoffset), (scr->pcs.mem), (type->ncols * type->nrows))) | |||
| 834 | scr->pcs.dispoffset, scr->pcs.mem,((vh->vh_ph.ph_memt)->write_region_2((vh->vh_ph.ph_memh ), (scr->pcs.dispoffset), (scr->pcs.mem), (type->ncols * type->nrows))) | |||
| 835 | type->ncols * type->nrows)((vh->vh_ph.ph_memt)->write_region_2((vh->vh_ph.ph_memh ), (scr->pcs.dispoffset), (scr->pcs.mem), (type->ncols * type->nrows))); | |||
| 836 | scr->pcs.active = 1; | |||
| 837 | splx(s)spllower(s); | |||
| 838 | ||||
| 839 | vc->active = scr; | |||
| 840 | ||||
| 841 | pcdisplay_cursor_reset(&scr->pcs); | |||
| 842 | pcdisplay_cursor(&scr->pcs, scr->pcs.cursoron, | |||
| 843 | scr->pcs.vc_crow, scr->pcs.vc_ccol); | |||
| 844 | ||||
| 845 | vc->wantedscreen = 0; | |||
| 846 | if (vc->switchcb) | |||
| 847 | (*vc->switchcb)(vc->switchcbarg, 0, 0); | |||
| 848 | } | |||
| 849 | ||||
| 850 | int | |||
| 851 | vga_load_font(void *v, void *cookie, struct wsdisplay_font *data) | |||
| 852 | { | |||
| 853 | struct vga_config *vc = v; | |||
| 854 | struct vgascreen *scr = cookie; | |||
| 855 | char *name2; | |||
| 856 | int res, slot; | |||
| 857 | struct vgafont *f; | |||
| 858 | ||||
| 859 | if (data->data == NULL((void *)0)) { | |||
| 860 | if (scr == NULL((void *)0)) | |||
| 861 | return EINVAL22; | |||
| 862 | ||||
| 863 | if ((name2 = data->name) != NULL((void *)0)) { | |||
| 864 | while (*name2 && *name2 != ',') | |||
| 865 | name2++; | |||
| 866 | if (*name2) | |||
| 867 | *name2++ = '\0'; | |||
| 868 | } | |||
| 869 | res = vga_selectfont(vc, scr, data->name, name2); | |||
| 870 | if (res == 0) | |||
| 871 | vga_setfont(vc, scr); | |||
| 872 | return (res); | |||
| 873 | } | |||
| 874 | ||||
| 875 | if (data->fontwidth != 8 || data->stride != 1) | |||
| 876 | return (EINVAL22); /* XXX 1 byte per line */ | |||
| 877 | if (data->firstchar != 0 || data->numchars != 256) | |||
| 878 | return (EINVAL22); | |||
| 879 | ||||
| 880 | if (data->index < 0) { | |||
| 881 | for (slot = 0; slot < VGA_MAXFONT8; slot++) | |||
| 882 | if (!vc->vc_fonts[slot]) | |||
| 883 | break; | |||
| 884 | } else | |||
| 885 | slot = data->index; | |||
| 886 | ||||
| 887 | if (slot >= VGA_MAXFONT8) | |||
| 888 | return (ENOSPC28); | |||
| 889 | ||||
| 890 | if (vc->vc_fonts[slot] != NULL((void *)0)) | |||
| 891 | return (EEXIST17); | |||
| 892 | f = malloc(sizeof(struct vgafont), M_DEVBUF2, M_WAITOK0x0001 | M_CANFAIL0x0004); | |||
| 893 | if (f == NULL((void *)0)) | |||
| 894 | return (ENOMEM12); | |||
| 895 | strlcpy(f->name, data->name, sizeof(f->name)); | |||
| 896 | f->height = data->fontheight; | |||
| 897 | f->encoding = data->encoding; | |||
| 898 | #ifdef notyet | |||
| 899 | f->firstchar = data->firstchar; | |||
| 900 | f->numchars = data->numchars; | |||
| 901 | #endif | |||
| 902 | #ifdef VGAFONTDEBUG | |||
| 903 | printf("vga: load %s (8x%d, enc %d) font to slot %d\n", f->name, | |||
| 904 | f->height, f->encoding, slot); | |||
| 905 | #endif | |||
| 906 | vga_loadchars(&vc->hdl, slot, 0, 256, f->height, data->data); | |||
| 907 | f->slot = slot; | |||
| 908 | f->fontdata = data->data; | |||
| 909 | vc->vc_fonts[slot] = f; | |||
| 910 | data->cookie = f; | |||
| 911 | data->index = slot; | |||
| 912 | ||||
| 913 | return (0); | |||
| 914 | } | |||
| 915 | ||||
| 916 | int | |||
| 917 | vga_list_font(void *v, struct wsdisplay_font *data) | |||
| 918 | { | |||
| 919 | struct vga_config *vc = v; | |||
| 920 | struct vgafont *f; | |||
| 921 | ||||
| 922 | if (data->index < 0 || data->index >= VGA_MAXFONT8) | |||
| 923 | return EINVAL22; | |||
| 924 | ||||
| 925 | if ((f = vc->vc_fonts[data->index]) == NULL((void *)0)) | |||
| 926 | return EINVAL22; | |||
| 927 | ||||
| 928 | strlcpy(data->name, f->name, sizeof data->name); | |||
| 929 | #ifdef notyet | |||
| 930 | data->firstchar = f->firstchar; | |||
| 931 | data->numchars = f->numchars; | |||
| 932 | #else | |||
| 933 | data->firstchar = 0; | |||
| 934 | data->numchars = 256; | |||
| 935 | #endif | |||
| 936 | data->encoding = f->encoding; | |||
| 937 | data->fontwidth = 8; | |||
| 938 | data->fontheight = f->height; | |||
| 939 | data->stride = 1; | |||
| 940 | data->bitorder = data->byteorder = WSDISPLAY_FONTORDER_L2R1; | |||
| 941 | ||||
| 942 | return (0); | |||
| 943 | } | |||
| 944 | ||||
| 945 | void | |||
| 946 | vga_scrollback(void *v, void *cookie, int lines) | |||
| 947 | { | |||
| 948 | struct vga_config *vc = v; | |||
| 949 | struct vgascreen *scr = cookie; | |||
| 950 | struct vga_handle *vh = &vc->hdl; | |||
| 951 | ||||
| 952 | if (lines == 0) { | |||
| 953 | if (scr->pcs.visibleoffset == scr->pcs.dispoffset) | |||
| 954 | return; | |||
| 955 | ||||
| 956 | scr->pcs.visibleoffset = scr->pcs.dispoffset; /* reset */ | |||
| 957 | } | |||
| 958 | else { | |||
| 959 | int vga_scr_end; | |||
| 960 | int margin = scr->pcs.type->ncols * 2; | |||
| 961 | int ul, we, p, st; | |||
| 962 | ||||
| 963 | vga_scr_end = (scr->pcs.dispoffset + scr->pcs.type->ncols * | |||
| 964 | scr->pcs.type->nrows * 2); | |||
| 965 | if (scr->vga_rollover > vga_scr_end + margin) { | |||
| 966 | ul = vga_scr_end; | |||
| 967 | we = scr->vga_rollover + scr->pcs.type->ncols * 2; | |||
| 968 | } else { | |||
| 969 | ul = 0; | |||
| 970 | we = 0x8000; | |||
| 971 | } | |||
| 972 | p = (scr->pcs.visibleoffset - ul + we) % we + lines * | |||
| 973 | (scr->pcs.type->ncols * 2); | |||
| 974 | st = (scr->pcs.dispoffset - ul + we) % we; | |||
| 975 | if (p < margin) | |||
| 976 | p = 0; | |||
| 977 | if (p > st - margin) | |||
| 978 | p = st; | |||
| 979 | scr->pcs.visibleoffset = (p + ul) % we; | |||
| 980 | } | |||
| 981 | ||||
| 982 | /* update visible position */ | |||
| 983 | vga_6845_write(vh, startadrh, scr->pcs.visibleoffset >> 9)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrh), scr->pcs.visibleoffset >> 9); | |||
| 984 | vga_6845_write(vh, startadrl, scr->pcs.visibleoffset >> 1)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, startadrl), scr->pcs.visibleoffset >> 1); | |||
| 985 | } | |||
| 986 | ||||
| 987 | int | |||
| 988 | vga_pack_attr(void *id, int fg, int bg, int flags, uint32_t *attrp) | |||
| 989 | { | |||
| 990 | struct vgascreen *scr = id; | |||
| 991 | struct vga_config *vc = scr->cfg; | |||
| 992 | ||||
| 993 | if (vc->hdl.vh_mono) { | |||
| 994 | if (flags & WSATTR_WSCOLORS16) | |||
| 995 | return (EINVAL22); | |||
| 996 | if (flags & WSATTR_REVERSE1) | |||
| 997 | *attrp = 0x70; | |||
| 998 | else | |||
| 999 | *attrp = 0x07; | |||
| 1000 | if (flags & WSATTR_UNDERLINE8) | |||
| 1001 | *attrp |= FG_UNDERLINE0x01; | |||
| 1002 | if (flags & WSATTR_HILIT2) | |||
| 1003 | *attrp |= FG_INTENSE0x08; | |||
| 1004 | } else { | |||
| 1005 | if (flags & (WSATTR_UNDERLINE8 | WSATTR_REVERSE1)) | |||
| 1006 | return (EINVAL22); | |||
| 1007 | if (flags & WSATTR_WSCOLORS16) | |||
| 1008 | *attrp = fgansitopc[fg & 7] | bgansitopc[bg & 7]; | |||
| 1009 | else | |||
| 1010 | *attrp = 7; | |||
| 1011 | if ((flags & WSATTR_HILIT2) || (fg & 8) || (bg & 8)) | |||
| 1012 | *attrp += 8; | |||
| 1013 | } | |||
| 1014 | if (flags & WSATTR_BLINK4) | |||
| 1015 | *attrp |= FG_BLINK0x80; | |||
| 1016 | return (0); | |||
| 1017 | } | |||
| 1018 | ||||
| 1019 | void | |||
| 1020 | vga_unpack_attr(void *id, uint32_t attr, int *fg, int *bg, int *ul) | |||
| 1021 | { | |||
| 1022 | struct vgascreen *scr = id; | |||
| 1023 | struct vga_config *vc = scr->cfg; | |||
| 1024 | ||||
| 1025 | if (vc->hdl.vh_mono) { | |||
| 1026 | *fg = (attr & 0x07) == 0x07 ? WSCOL_WHITE7 : WSCOL_BLACK0; | |||
| 1027 | *bg = attr & 0x70 ? WSCOL_WHITE7 : WSCOL_BLACK0; | |||
| 1028 | if (ul != NULL((void *)0)) | |||
| 1029 | *ul = *fg != WSCOL_WHITE7 && (attr & 0x01) ? 1 : 0; | |||
| 1030 | } else { | |||
| 1031 | *fg = pctoansi[attr & 0x07]; | |||
| 1032 | *bg = pctoansi[(attr & 0x70) >> 4]; | |||
| 1033 | if (ul != NULL((void *)0)) | |||
| 1034 | *ul = 0; | |||
| 1035 | } | |||
| 1036 | if (attr & FG_INTENSE0x08) | |||
| 1037 | *fg += 8; | |||
| 1038 | } | |||
| 1039 | ||||
| 1040 | int | |||
| 1041 | vga_copyrows(void *id, int srcrow, int dstrow, int nrows) | |||
| 1042 | { | |||
| 1043 | struct vgascreen *scr = id; | |||
| 1044 | bus_space_tag_t memt = scr->pcs.hdl->ph_memt; | |||
| 1045 | bus_space_handle_t memh = scr->pcs.hdl->ph_memh; | |||
| 1046 | int ncols = scr->pcs.type->ncols; | |||
| 1047 | bus_size_t srcoff, dstoff; | |||
| 1048 | int s; | |||
| 1049 | ||||
| 1050 | srcoff = srcrow * ncols + 0; | |||
| 1051 | dstoff = dstrow * ncols + 0; | |||
| 1052 | ||||
| 1053 | s = spltty()splraise(0x9); | |||
| 1054 | if (scr->pcs.active) { | |||
| 1055 | if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) { | |||
| 1056 | #ifdef PCDISPLAY_SOFTCURSOR | |||
| 1057 | int cursoron = scr->pcs.cursoron; | |||
| 1058 | ||||
| 1059 | /* NOTE this assumes pcdisplay_cursor() never fails */ | |||
| 1060 | if (cursoron) | |||
| 1061 | pcdisplay_cursor(&scr->pcs, 0, | |||
| 1062 | scr->pcs.vc_crow, scr->pcs.vc_ccol); | |||
| 1063 | #endif | |||
| 1064 | /* scroll up whole screen */ | |||
| 1065 | if ((scr->pcs.dispoffset + srcrow * ncols * 2) | |||
| 1066 | <= scr->maxdispoffset) { | |||
| 1067 | scr->pcs.dispoffset += srcrow * ncols * 2; | |||
| 1068 | } else { | |||
| 1069 | bus_space_copy_2(memt, memh,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))) | |||
| 1070 | scr->pcs.dispoffset + srcoff * 2,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))) | |||
| 1071 | memh, scr->mindispoffset,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))) | |||
| 1072 | nrows * ncols)((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->mindispoffset), (nrows * ncols))); | |||
| 1073 | scr->vga_rollover = scr->pcs.dispoffset; | |||
| 1074 | scr->pcs.dispoffset = scr->mindispoffset; | |||
| 1075 | } | |||
| 1076 | scr->pcs.visibleoffset = scr->pcs.dispoffset; | |||
| 1077 | vga_6845_write(&scr->cfg->hdl, startadrh,_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrh), scr->pcs .dispoffset >> 9) | |||
| 1078 | scr->pcs.dispoffset >> 9)_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrh), scr->pcs .dispoffset >> 9); | |||
| 1079 | vga_6845_write(&scr->cfg->hdl, startadrl,_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrl), scr->pcs .dispoffset >> 1) | |||
| 1080 | scr->pcs.dispoffset >> 1)_pcdisplay_6845_write(&(&scr->cfg->hdl)->vh_ph , __builtin_offsetof(struct reg_mc6845, startadrl), scr->pcs .dispoffset >> 1); | |||
| 1081 | #ifdef PCDISPLAY_SOFTCURSOR | |||
| 1082 | /* NOTE this assumes pcdisplay_cursor() never fails */ | |||
| 1083 | if (cursoron) | |||
| 1084 | pcdisplay_cursor(&scr->pcs, 1, | |||
| 1085 | scr->pcs.vc_crow, scr->pcs.vc_ccol); | |||
| 1086 | #endif | |||
| 1087 | } else { | |||
| 1088 | bus_space_copy_2(memt, memh,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))) | |||
| 1089 | scr->pcs.dispoffset + srcoff * 2,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))) | |||
| 1090 | memh, scr->pcs.dispoffset + dstoff * 2,((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))) | |||
| 1091 | nrows * ncols)((memt)->copy_2((memh), (scr->pcs.dispoffset + srcoff * 2), (memh), (scr->pcs.dispoffset + dstoff * 2), (nrows * ncols ))); | |||
| 1092 | } | |||
| 1093 | } else | |||
| 1094 | bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff], | |||
| 1095 | nrows * ncols * 2); | |||
| 1096 | splx(s)spllower(s); | |||
| 1097 | ||||
| 1098 | return 0; | |||
| 1099 | } | |||
| 1100 | ||||
| 1101 | int _vga_mapchar(void *, struct vgafont *, int, unsigned int *); | |||
| 1102 | ||||
| 1103 | int | |||
| 1104 | _vga_mapchar(void *id, struct vgafont *font, int uni, unsigned int *index) | |||
| 1105 | { | |||
| 1106 | ||||
| 1107 | switch (font->encoding) { | |||
| 1108 | case WSDISPLAY_FONTENC_ISO0: | |||
| 1109 | if (uni < 256) { | |||
| 1110 | *index = uni; | |||
| 1111 | return (5); | |||
| 1112 | } else { | |||
| 1113 | *index = '?'; | |||
| 1114 | return (0); | |||
| 1115 | } | |||
| 1116 | break; | |||
| 1117 | case WSDISPLAY_FONTENC_IBM1: | |||
| 1118 | return (pcdisplay_mapchar(id, uni, index)); | |||
| 1119 | default: | |||
| 1120 | #ifdef VGAFONTDEBUG | |||
| 1121 | printf("_vga_mapchar: encoding=%d\n", font->encoding); | |||
| 1122 | #endif | |||
| 1123 | *index = '?'; | |||
| 1124 | return (0); | |||
| 1125 | } | |||
| 1126 | } | |||
| 1127 | ||||
| 1128 | int | |||
| 1129 | vga_mapchar(void *id, int uni, unsigned int *index) | |||
| 1130 | { | |||
| 1131 | struct vgascreen *scr = id; | |||
| 1132 | unsigned int idx1, idx2; | |||
| ||||
| 1133 | int res1, res2; | |||
| 1134 | ||||
| 1135 | res1 = 0; | |||
| 1136 | idx1 = ' '; /* space */ | |||
| 1137 | if (scr->fontset1) | |||
| 1138 | res1 = _vga_mapchar(id, scr->fontset1, uni, &idx1); | |||
| 1139 | res2 = -1; | |||
| 1140 | if (scr->fontset2) { | |||
| 1141 | KASSERT(VGA_SCREEN_CANTWOFONTS(scr->pcs.type))(((!((scr->pcs.type)->capabilities & 4))) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/vga.c", 1141, "VGA_SCREEN_CANTWOFONTS(scr->pcs.type)")); | |||
| 1142 | res2 = _vga_mapchar(id, scr->fontset2, uni, &idx2); | |||
| 1143 | } | |||
| 1144 | if (res2 >= res1) { | |||
| 1145 | *index = idx2 | 0x0800; /* attribute bit 3 */ | |||
| ||||
| 1146 | return (res2); | |||
| 1147 | } | |||
| 1148 | *index = idx1; | |||
| 1149 | return (res1); | |||
| 1150 | } | |||
| 1151 | ||||
| 1152 | int | |||
| 1153 | vga_putchar(void *c, int row, int col, u_int uc, uint32_t attr) | |||
| 1154 | { | |||
| 1155 | struct vgascreen *scr = c; | |||
| 1156 | int rc; | |||
| 1157 | int s; | |||
| 1158 | ||||
| 1159 | s = spltty()splraise(0x9); | |||
| 1160 | if (scr->pcs.active && scr->pcs.visibleoffset != scr->pcs.dispoffset) | |||
| 1161 | vga_scrollback(scr->cfg, scr, 0); | |||
| 1162 | rc = pcdisplay_putchar(c, row, col, uc, attr); | |||
| 1163 | splx(s)spllower(s); | |||
| 1164 | ||||
| 1165 | return rc; | |||
| 1166 | } | |||
| 1167 | ||||
| 1168 | void | |||
| 1169 | vga_burner(void *v, u_int on, u_int flags) | |||
| 1170 | { | |||
| 1171 | struct vga_config *vc = v; | |||
| 1172 | struct vga_handle *vh = &vc->hdl; | |||
| 1173 | u_int8_t r; | |||
| 1174 | int s; | |||
| 1175 | ||||
| 1176 | s = splhigh()splraise(0xd); | |||
| 1177 | vga_ts_write(vh, syncreset, 0x01)_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, syncreset ), 0x01); | |||
| 1178 | if (on) { | |||
| 1179 | vga_ts_write(vh, mode, (vga_ts_read(vh, mode) & ~0x20))_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, mode), (_vga_ts_read(vh, __builtin_offsetof(struct reg_vgats, mode) ) & ~0x20)); | |||
| 1180 | r = vga_6845_read(vh, mode)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, mode)) | 0x80; | |||
| 1181 | DELAY(10000)(*delay_func)(10000); | |||
| 1182 | vga_6845_write(vh, mode, r)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, mode), r); | |||
| 1183 | } else { | |||
| 1184 | vga_ts_write(vh, mode, (vga_ts_read(vh, mode) | 0x20))_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, mode), (_vga_ts_read(vh, __builtin_offsetof(struct reg_vgats, mode) ) | 0x20)); | |||
| 1185 | if (flags & WSDISPLAY_BURN_VBLANK0x0001) { | |||
| 1186 | r = vga_6845_read(vh, mode)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, mode)) & ~0x80; | |||
| 1187 | DELAY(10000)(*delay_func)(10000); | |||
| 1188 | vga_6845_write(vh, mode, r)_pcdisplay_6845_write(&(vh)->vh_ph, __builtin_offsetof (struct reg_mc6845, mode), r); | |||
| 1189 | } | |||
| 1190 | } | |||
| 1191 | vga_ts_write(vh, syncreset, 0x03)_vga_ts_write(vh, __builtin_offsetof(struct reg_vgats, syncreset ), 0x03); | |||
| 1192 | splx(s)spllower(s); | |||
| 1193 | } | |||
| 1194 | ||||
| 1195 | int | |||
| 1196 | vga_getchar(void *c, int row, int col, struct wsdisplay_charcell *cell) | |||
| 1197 | { | |||
| 1198 | struct vga_config *vc = c; | |||
| 1199 | ||||
| 1200 | return (pcdisplay_getchar(vc->active, row, col, cell)); | |||
| 1201 | } | |||
| 1202 | ||||
| 1203 | void | |||
| 1204 | vga_save_palette(struct vga_config *vc) | |||
| 1205 | { | |||
| 1206 | struct vga_handle *vh = &vc->hdl; | |||
| 1207 | uint i; | |||
| 1208 | uint8_t *palette = vc->vc_palette; | |||
| 1209 | ||||
| 1210 | if (vh->vh_mono) | |||
| 1211 | return; | |||
| 1212 | ||||
| 1213 | vga_raw_write(vh, VGA_DAC_MASK, 0xff)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x06 ), (0xff))); | |||
| 1214 | vga_raw_write(vh, VGA_DAC_READ, 0x00)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x07 ), (0x00))); | |||
| 1215 | for (i = 0; i < 3 * 256; i++) | |||
| 1216 | *palette++ = vga_raw_read(vh, VGA_DAC_DATA)((vh->vh_ph.ph_iot)->read_1((vh->vh_ioh_vga), (0x09) )); | |||
| 1217 | } | |||
| 1218 | ||||
| 1219 | void | |||
| 1220 | vga_restore_palette(struct vga_config *vc) | |||
| 1221 | { | |||
| 1222 | struct vga_handle *vh = &vc->hdl; | |||
| 1223 | uint i; | |||
| 1224 | uint8_t *palette = vc->vc_palette; | |||
| 1225 | ||||
| 1226 | if (vh->vh_mono) | |||
| 1227 | return; | |||
| 1228 | ||||
| 1229 | vga_raw_write(vh, VGA_DAC_MASK, 0xff)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x06 ), (0xff))); | |||
| 1230 | vga_raw_write(vh, VGA_DAC_WRITE, 0x00)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x08 ), (0x00))); | |||
| 1231 | for (i = 0; i < 3 * 256; i++) | |||
| 1232 | vga_raw_write(vh, VGA_DAC_DATA, *palette++)((vh->vh_ph.ph_iot)->write_1((vh->vh_ioh_vga), (0x09 ), (*palette++))); | |||
| 1233 | } | |||
| 1234 | ||||
| 1235 | void | |||
| 1236 | vga_restore_fonts(struct vga_config *vc) | |||
| 1237 | { | |||
| 1238 | int slot; | |||
| 1239 | struct vgafont *f; | |||
| 1240 | ||||
| 1241 | for (slot = 0; slot < VGA_MAXFONT8; slot++) { | |||
| 1242 | f = vc->vc_fonts[slot]; | |||
| 1243 | if (f == NULL((void *)0) || f->fontdata == NULL((void *)0)) | |||
| 1244 | continue; | |||
| 1245 | ||||
| 1246 | vga_loadchars(&vc->hdl, slot, 0, 256, f->height, f->fontdata); | |||
| 1247 | } | |||
| 1248 | } | |||
| 1249 | ||||
| 1250 | #ifdef __alpha__ | |||
| 1251 | void | |||
| 1252 | vga_pick_monitor_type(struct vga_config *vc) | |||
| 1253 | { | |||
| 1254 | struct vga_handle *vh = &vc->hdl; | |||
| 1255 | ||||
| 1256 | /* | |||
| 1257 | * The Tadpole Alphabook1 uses a 800x600 flat panel in text mode, | |||
| 1258 | * causing the display console to really be 100x37 instead of the | |||
| 1259 | * usual 80x25. | |||
| 1260 | * We attempt to detect this here by checking the CRTC registers. | |||
| 1261 | */ | |||
| 1262 | unsigned int hend, oflow, vend; | |||
| 1263 | unsigned int width, height; | |||
| 1264 | ||||
| 1265 | hend = vga_6845_read(vh, hdisple)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, hdisple)); | |||
| 1266 | oflow = vga_6845_read(vh, overfll)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, overfll)); | |||
| 1267 | vend = vga_6845_read(vh, vde)_pcdisplay_6845_read(&(vh)->vh_ph, __builtin_offsetof( struct reg_mc6845, vde)); | |||
| 1268 | if (oflow & 0x02) | |||
| 1269 | vend |= 0x100; | |||
| 1270 | if (oflow & 0x40) | |||
| 1271 | vend |= 0x200; | |||
| 1272 | ||||
| 1273 | width = hend + 1; | |||
| 1274 | height = (vend + 1) / 16; | |||
| 1275 | ||||
| 1276 | /* check that the values sound plausible */ | |||
| 1277 | if ((width > 80 && width <= 128) && (height > 25 && height <= 50)) { | |||
| 1278 | snprintf(vc->custom_scr.name, sizeof(vc->custom_scr.name), | |||
| 1279 | "%ux%u", width, height); | |||
| 1280 | vc->custom_scr.ncols = width; | |||
| 1281 | vc->custom_scr.nrows = height; | |||
| 1282 | vc->custom_scr.textops = &vga_emulops; | |||
| 1283 | vc->custom_scr.fontwidth = 8; | |||
| 1284 | vc->custom_scr.fontheight = 16; | |||
| 1285 | vc->custom_scr.capabilities = | |||
| 1286 | WSSCREEN_WSCOLORS1 | WSSCREEN_HILIT4 | WSSCREEN_BLINK8; | |||
| 1287 | vc->custom_scrlist[0] = &vc->custom_scr; | |||
| 1288 | vc->custom_list.nscreens = 1; | |||
| 1289 | vc->custom_list.screens = | |||
| 1290 | (const struct wsscreen_descr **)vc->custom_scrlist; | |||
| 1291 | } | |||
| 1292 | } | |||
| 1293 | #endif | |||
| 1294 | ||||
| 1295 | struct cfdriver vga_cd = { | |||
| 1296 | NULL((void *)0), "vga", DV_DULL | |||
| 1297 | }; |