1 /* $NetBSD: vga.c,v 1.100 2008/03/16 19:57:39 dyoung Exp $ */
4 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
7 * Author: Chris G. Demetriou
9 * Permission to use, copy, modify and distribute this software and
10 * its documentation is hereby granted, provided that both the copyright
11 * notice and this permission notice appear in all copies of the
12 * software, derivative works or modified versions, and any portions
13 * thereof, and that both notices appear in supporting documentation.
15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 * Carnegie Mellon requests users of this software to return to
21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22 * School of Computer Science
23 * Carnegie Mellon University
24 * Pittsburgh PA 15213-3890
26 * any improvements or extensions that they make and grant Carnegie the
27 * rights to redistribute these changes.
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: vga.c,v 1.100 2008/03/16 19:57:39 dyoung Exp $");
33 /* for WSCONS_SUPPORT_PCVTFONTS */
34 #include "opt_wsdisplay_compat.h"
35 /* for WSDISPLAY_CUSTOM_BORDER */
36 #include "opt_wsdisplay_border.h"
37 /* for WSDISPLAY_CUSTOM_OUTPUT */
38 #include "opt_wsmsgattrs.h"
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/callout.h>
43 #include <sys/kernel.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46 #include <sys/queue.h>
49 #include <dev/ic/mc6845reg.h>
50 #include <dev/ic/pcdisplayvar.h>
51 #include <dev/ic/vgareg.h>
52 #include <dev/ic/vgavar.h>
54 #include <dev/wscons/wsdisplayvar.h>
55 #include <dev/wscons/wsconsio.h>
56 #include <dev/wscons/unicode.h>
57 #include <dev/wsfont/wsfont.h>
59 #include <dev/ic/pcdisplay.h>
61 int vga_no_builtinfont
= 0;
63 static struct wsdisplay_font _vga_builtinfont
= {
64 "builtin", /* typeface name */
67 WSDISPLAY_FONTENC_IBM
, /* encoding */
71 WSDISPLAY_FONTORDER_L2R
, /* bit order */
77 struct wsdisplay_font
*wsfont
;
78 int cookie
; /* wsfont handle, -1 invalid */
79 int slot
; /* in adapter RAM */
81 TAILQ_ENTRY(egavga_font
) next
; /* LRU queue */
84 static struct egavga_font vga_builtinfont
= {
85 .wsfont
= &_vga_builtinfont
,
90 #ifdef VGA_CONSOLE_SCREENTYPE
91 static struct egavga_font vga_consolefont
;
95 struct pcdisplayscreen pcs
;
97 LIST_ENTRY(vgascreen
) next
;
99 struct vga_config
*cfg
;
102 struct egavga_font
*fontset1
, *fontset2
;
106 int mindispoffset
, maxdispoffset
;
111 static int vgaconsole
, vga_console_type
, vga_console_attached
;
112 static struct vgascreen vga_console_screen
;
113 static struct vga_config vga_console_vc
;
115 struct egavga_font
*egavga_getfont(struct vga_config
*, struct vgascreen
*,
117 void egavga_unreffont(struct vga_config
*, struct egavga_font
*);
119 int vga_selectfont(struct vga_config
*, struct vgascreen
*, const char *,
121 void vga_init_screen(struct vga_config
*, struct vgascreen
*,
122 const struct wsscreen_descr
*, int, long *);
123 void vga_init(struct vga_config
*, bus_space_tag_t
, bus_space_tag_t
);
124 static void vga_setfont(struct vga_config
*, struct vgascreen
*);
126 static int vga_mapchar(void *, int, unsigned int *);
127 void vga_putchar(void *, int, int, u_int
, long);
128 static int vga_allocattr(void *, int, int, int, long *);
129 static void vga_copyrows(void *, int, int, int);
130 #ifdef WSDISPLAY_SCROLLSUPPORT
131 void vga_scroll (void *, void *, int);
134 const struct wsdisplay_emulops vga_emulops
= {
143 #ifdef WSDISPLAY_CUSTOM_OUTPUT
144 pcdisplay_replaceattr
,
151 * translate WS(=ANSI) color codes to standard pc ones
153 static const unsigned char fgansitopc
[] = {
156 * XXX DEC HAS SWITCHED THE CODES FOR BLUE AND RED!!!
157 * XXX We should probably not bother with this
158 * XXX (reinitialize the palette registers).
160 FG_BLACK
, FG_BLUE
, FG_GREEN
, FG_CYAN
, FG_RED
,
161 FG_MAGENTA
, FG_BROWN
, FG_LIGHTGREY
163 FG_BLACK
, FG_RED
, FG_GREEN
, FG_BROWN
, FG_BLUE
,
164 FG_MAGENTA
, FG_CYAN
, FG_LIGHTGREY
168 BG_BLACK
, BG_BLUE
, BG_GREEN
, BG_CYAN
, BG_RED
,
169 BG_MAGENTA
, BG_BROWN
, BG_LIGHTGREY
171 BG_BLACK
, BG_RED
, BG_GREEN
, BG_BROWN
, BG_BLUE
,
172 BG_MAGENTA
, BG_CYAN
, BG_LIGHTGREY
176 const struct wsscreen_descr vga_25lscreen
= {
180 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
| WSSCREEN_BLINK
,
182 }, vga_25lscreen_mono
= {
186 WSSCREEN_HILIT
| WSSCREEN_UNDERLINE
| WSSCREEN_BLINK
| WSSCREEN_REVERSE
,
188 }, vga_25lscreen_bf
= {
192 WSSCREEN_WSCOLORS
| WSSCREEN_BLINK
,
198 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
| WSSCREEN_BLINK
,
200 }, vga_40lscreen_mono
= {
204 WSSCREEN_HILIT
| WSSCREEN_UNDERLINE
| WSSCREEN_BLINK
| WSSCREEN_REVERSE
,
206 }, vga_40lscreen_bf
= {
210 WSSCREEN_WSCOLORS
| WSSCREEN_BLINK
,
216 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
| WSSCREEN_BLINK
,
218 }, vga_50lscreen_mono
= {
222 WSSCREEN_HILIT
| WSSCREEN_UNDERLINE
| WSSCREEN_BLINK
| WSSCREEN_REVERSE
,
224 }, vga_50lscreen_bf
= {
228 WSSCREEN_WSCOLORS
| WSSCREEN_BLINK
,
234 WSSCREEN_WSCOLORS
| WSSCREEN_HILIT
| WSSCREEN_BLINK
,
236 }, vga_24lscreen_mono
= {
240 WSSCREEN_HILIT
| WSSCREEN_UNDERLINE
| WSSCREEN_BLINK
| WSSCREEN_REVERSE
,
242 }, vga_24lscreen_bf
= {
246 WSSCREEN_WSCOLORS
| WSSCREEN_BLINK
,
250 #define VGA_SCREEN_CANTWOFONTS(type) (!((type)->capabilities & WSSCREEN_HILIT))
252 const struct wsscreen_descr
*_vga_scrlist
[] = {
261 /* XXX other formats, graphics screen? */
262 }, *_vga_scrlist_mono
[] = {
267 /* XXX other formats, graphics screen? */
270 const struct wsscreen_list vga_screenlist
= {
271 sizeof(_vga_scrlist
) / sizeof(struct wsscreen_descr
*),
273 }, vga_screenlist_mono
= {
274 sizeof(_vga_scrlist_mono
) / sizeof(struct wsscreen_descr
*),
278 static int vga_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
279 static paddr_t
vga_mmap(void *, void *, off_t
, int);
280 static int vga_alloc_screen(void *, const struct wsscreen_descr
*,
281 void **, int *, int *, long *);
282 static void vga_free_screen(void *, void *);
283 static int vga_show_screen(void *, void *, int,
284 void (*)(void *, int, int), void *);
285 static int vga_load_font(void *, void *, struct wsdisplay_font
*);
286 #ifdef WSDISPLAY_CUSTOM_BORDER
287 static int vga_getborder(struct vga_config
*, u_int
*);
288 static int vga_setborder(struct vga_config
*, u_int
);
289 #endif /* WSDISPLAY_CUSTOM_BORDER */
291 void vga_doswitch(struct vga_config
*);
293 const struct wsdisplay_accessops vga_accessops
= {
301 #ifdef WSDISPLAY_SCROLLSUPPORT
309 * We want at least ASCII 32..127 be present in the
312 #define vga_valid_primary_font(f) \
313 (f->wsfont->encoding == WSDISPLAY_FONTENC_IBM || \
314 f->wsfont->encoding == WSDISPLAY_FONTENC_ISO || \
315 f->wsfont->encoding == WSDISPLAY_FONTENC_ISO7)
318 egavga_getfont(struct vga_config
*vc
, struct vgascreen
*scr
, const char *name
,
321 struct egavga_font
*f
;
323 struct wsdisplay_font
*wf
;
325 TAILQ_FOREACH(f
, &vc
->vc_fontlist
, next
) {
326 if (wsfont_matches(f
->wsfont
, name
,
327 8, scr
->pcs
.type
->fontheight
, 0) &&
328 (!primary
|| vga_valid_primary_font(f
))) {
330 if (scr
!= &vga_console_screen
|| vga_console_attached
)
331 printf("vga_getfont: %s already present\n",
332 name
? name
: "<default>");
338 cookie
= wsfont_find(name
, 8, scr
->pcs
.type
->fontheight
, 0,
339 WSDISPLAY_FONTORDER_L2R
, 0);
340 /* XXX obey "primary" */
343 if (scr
!= &vga_console_screen
|| vga_console_attached
)
344 printf("vga_getfont: %s not found\n",
345 name
? name
: "<default>");
350 if (wsfont_lock(cookie
, &wf
))
353 #ifdef VGA_CONSOLE_SCREENTYPE
354 if (scr
== &vga_console_screen
)
355 f
= &vga_consolefont
;
358 f
= malloc(sizeof(struct egavga_font
), M_DEVBUF
, M_NOWAIT
);
360 wsfont_unlock(cookie
);
365 f
->slot
= -1; /* not yet loaded */
366 f
->usecount
= 0; /* incremented below */
367 TAILQ_INSERT_TAIL(&vc
->vc_fontlist
, f
, next
);
372 if (scr
!= &vga_console_screen
|| vga_console_attached
)
373 printf("vga_getfont: usecount=%d\n", f
->usecount
);
379 egavga_unreffont(struct vga_config
*vc
, struct egavga_font
*f
)
384 printf("vga_unreffont: usecount=%d\n", f
->usecount
);
386 if (f
->usecount
== 0 && f
->cookie
!= -1) {
387 TAILQ_REMOVE(&vc
->vc_fontlist
, f
, next
);
389 KASSERT(vc
->vc_fonts
[f
->slot
] == f
);
390 vc
->vc_fonts
[f
->slot
] = 0;
392 wsfont_unlock(f
->cookie
);
393 #ifdef VGA_CONSOLE_SCREENTYPE
394 if (f
!= &vga_consolefont
)
401 vga_selectfont(struct vga_config
*vc
, struct vgascreen
*scr
, const char *name1
,
404 const struct wsscreen_descr
*type
= scr
->pcs
.type
;
405 struct egavga_font
*f1
, *f2
;
407 f1
= egavga_getfont(vc
, scr
, name1
, 1);
411 if (VGA_SCREEN_CANTWOFONTS(type
) && name2
) {
412 f2
= egavga_getfont(vc
, scr
, name2
, 0);
414 egavga_unreffont(vc
, f1
);
421 if (scr
!= &vga_console_screen
|| vga_console_attached
) {
422 printf("vga (%s): font1=%s (slot %d)", type
->name
,
423 f1
->wsfont
->name
, f1
->slot
);
425 printf(", font2=%s (slot %d)",
426 f2
->wsfont
->name
, f2
->slot
);
431 egavga_unreffont(vc
, scr
->fontset1
);
434 egavga_unreffont(vc
, scr
->fontset2
);
440 vga_init_screen(struct vga_config
*vc
, struct vgascreen
*scr
,
441 const struct wsscreen_descr
*type
, int existing
, long *attrp
)
447 scr
->pcs
.hdl
= (struct pcdisplay_handle
*)&vc
->hdl
;
448 scr
->pcs
.type
= type
;
449 scr
->pcs
.active
= existing
;
450 scr
->mindispoffset
= 0;
451 if (vc
->vc_quirks
& VGA_QUIRK_NOFASTSCROLL
)
452 scr
->maxdispoffset
= 0;
454 scr
->maxdispoffset
= 0x8000 - type
->nrows
* type
->ncols
* 2;
459 cpos
= vga_6845_read(&vc
->hdl
, cursorh
) << 8;
460 cpos
|= vga_6845_read(&vc
->hdl
, cursorl
);
462 /* make sure we have a valid cursor position */
463 if (cpos
< 0 || cpos
>= type
->nrows
* type
->ncols
)
466 scr
->pcs
.dispoffset
= vga_6845_read(&vc
->hdl
, startadrh
) << 9;
467 scr
->pcs
.dispoffset
|= vga_6845_read(&vc
->hdl
, startadrl
) << 1;
469 /* make sure we have a valid memory offset */
470 if (scr
->pcs
.dispoffset
< scr
->mindispoffset
||
471 scr
->pcs
.dispoffset
> scr
->maxdispoffset
)
472 scr
->pcs
.dispoffset
= scr
->mindispoffset
;
474 if (type
!= vc
->currenttype
) {
475 vga_setscreentype(&vc
->hdl
, type
);
476 vc
->currenttype
= type
;
480 scr
->pcs
.dispoffset
= scr
->mindispoffset
;
483 scr
->pcs
.visibleoffset
= scr
->pcs
.dispoffset
;
484 scr
->vga_rollover
= 0;
486 scr
->pcs
.cursorrow
= cpos
/ type
->ncols
;
487 scr
->pcs
.cursorcol
= cpos
% type
->ncols
;
488 pcdisplay_cursor_init(&scr
->pcs
, existing
);
491 if (!vc
->hdl
.vh_mono
)
493 * DEC firmware uses a blue background.
494 * XXX These should be specified as kernel options for
495 * XXX alpha only, not hardcoded here (which is wrong
496 * XXX anyway because the emulation layer will assume
497 * XXX the default attribute is white on black).
499 res
= vga_allocattr(scr
, WSCOL_WHITE
, WSCOL_BLUE
,
500 WSATTR_WSCOLORS
, attrp
);
503 res
= vga_allocattr(scr
, 0, 0, 0, attrp
);
506 panic("vga_init_screen: attribute botch");
511 scr
->fontset1
= scr
->fontset2
= 0;
512 if (vga_selectfont(vc
, scr
, 0, 0)) {
513 if (scr
== &vga_console_screen
)
514 panic("vga_init_screen: no font");
516 printf("vga_init_screen: no font\n");
519 vga_setfont(vc
, scr
);
522 LIST_INSERT_HEAD(&vc
->screens
, scr
, next
);
526 vga_init(struct vga_config
*vc
, bus_space_tag_t iot
, bus_space_tag_t memt
)
528 struct vga_handle
*vh
= &vc
->hdl
;
535 if (bus_space_map(vh
->vh_iot
, 0x3c0, 0x10, 0, &vh
->vh_ioh_vga
))
536 panic("vga_init: couldn't map vga io");
538 /* read "misc output register" */
539 mor
= bus_space_read_1(vh
->vh_iot
, vh
->vh_ioh_vga
, VGA_MISC_DATAR
);
540 vh
->vh_mono
= !(mor
& 1);
542 if (bus_space_map(vh
->vh_iot
, (vh
->vh_mono
? 0x3b0 : 0x3d0), 0x10, 0,
544 panic("vga_init: couldn't map 6845 io");
546 if (bus_space_map(vh
->vh_memt
, 0xa0000, 0x20000, 0, &vh
->vh_allmemh
))
547 panic("vga_init: couldn't map memory");
549 if (bus_space_subregion(vh
->vh_memt
, vh
->vh_allmemh
,
550 (vh
->vh_mono
? 0x10000 : 0x18000), 0x8000, &vh
->vh_memh
))
551 panic("vga_init: mem subrange failed");
553 /* should only reserve the space (no need to map - save KVM) */
554 vc
->vc_biostag
= memt
;
555 if (bus_space_map(vc
->vc_biostag
, 0xc0000, 0x8000, 0, &vc
->vc_bioshdl
))
556 vc
->vc_biosmapped
= 0;
558 vc
->vc_biosmapped
= 1;
561 LIST_INIT(&vc
->screens
);
563 vc
->currenttype
= vh
->vh_mono
? &vga_25lscreen_mono
: &vga_25lscreen
;
564 callout_init(&vc
->vc_switch_callout
, 0);
567 if (vga_no_builtinfont
) {
568 struct wsdisplay_font
*wf
;
571 cookie
= wsfont_find(NULL
, 8, 16, 0,
572 WSDISPLAY_FONTORDER_L2R
, 0);
573 if (cookie
== -1 || wsfont_lock(cookie
, &wf
))
574 panic("vga_init: can't load console font");
575 vga_loadchars(&vc
->hdl
, 0, wf
->firstchar
, wf
->numchars
,
576 wf
->fontheight
, wf
->data
);
577 vga_builtinfont
.wsfont
= wf
;
578 vga_builtinfont
.cookie
= cookie
;
579 vga_builtinfont
.slot
= 0;
581 vc
->vc_fonts
[0] = &vga_builtinfont
;
582 for (i
= 1; i
< 8; i
++)
584 TAILQ_INIT(&vc
->vc_fontlist
);
585 TAILQ_INSERT_HEAD(&vc
->vc_fontlist
, &vga_builtinfont
, next
);
587 vc
->currentfontset1
= vc
->currentfontset2
= 0;
589 if (!vh
->vh_mono
&& (u_int
)WSDISPLAY_BORDER_COLOR
< sizeof(fgansitopc
))
590 _vga_attr_write(vh
, VGA_ATC_OVERSCAN
,
591 fgansitopc
[WSDISPLAY_BORDER_COLOR
]);
595 vga_common_attach(struct vga_softc
*sc
, bus_space_tag_t iot
,
596 bus_space_tag_t memt
, int type
, int quirks
,
597 const struct vga_funcs
*vf
)
600 struct vga_config
*vc
;
601 struct wsemuldisplaydev_attach_args aa
;
603 console
= vga_is_console(iot
, type
);
606 vc
= &vga_console_vc
;
607 vga_console_attached
= 1;
609 vc
= malloc(sizeof(struct vga_config
), M_DEVBUF
, M_WAITOK
);
610 vga_init(vc
, iot
, memt
);
613 if (quirks
& VGA_QUIRK_ONEFONT
) {
614 vc
->vc_nfontslots
= 1;
615 #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
617 * XXX maybe invalidate font in slot > 0, but this can
618 * only be happen with VGA_CONSOLE_SCREENTYPE, and then
619 * we require VGA_CONSOLE_ATI_BROKEN_FONTSEL anyway.
623 vc
->vc_nfontslots
= 8;
624 #ifndef VGA_CONSOLE_ATI_BROKEN_FONTSEL
626 * XXX maybe validate builtin font shifted to slot 1 if
627 * slot 0 got overwritten because of VGA_CONSOLE_SCREENTYPE,
628 * but it will be reloaded anyway if needed.
634 * Save the builtin font to memory. In case it got overwritten
635 * in console initialization, use the copy in slot 1.
637 #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
638 #define BUILTINFONTLOC (vga_builtinfont.slot == -1 ? 1 : 0)
640 KASSERT(vga_builtinfont
.slot
== 0);
641 #define BUILTINFONTLOC (0)
643 if (!vga_no_builtinfont
) {
645 malloc(256 * vga_builtinfont
.wsfont
->fontheight
,
647 vga_readoutchars(&vc
->hdl
, BUILTINFONTLOC
, 0, 256,
648 vga_builtinfont
.wsfont
->fontheight
, data
);
649 vga_builtinfont
.wsfont
->data
= data
;
654 vc
->vc_quirks
= quirks
;
659 aa
.console
= console
;
660 aa
.scrdata
= (vc
->hdl
.vh_mono
? &vga_screenlist_mono
: &vga_screenlist
);
661 aa
.accessops
= &vga_accessops
;
662 aa
.accesscookie
= vc
;
664 config_found_ia(sc
->sc_dev
, "wsemuldisplaydev", &aa
, wsemuldisplaydevprint
);
668 vga_cnattach(bus_space_tag_t iot
, bus_space_tag_t memt
, int type
, int check
)
671 const struct wsscreen_descr
*scr
;
673 if (check
&& !vga_common_probe(iot
, memt
))
676 /* set up bus-independent VGA configuration */
677 vga_init(&vga_console_vc
, iot
, memt
);
678 #ifdef VGA_CONSOLE_SCREENTYPE
679 scr
= wsdisplay_screentype_pick(vga_console_vc
.hdl
.vh_mono
?
680 &vga_screenlist_mono
: &vga_screenlist
, VGA_CONSOLE_SCREENTYPE
);
682 panic("vga_cnattach: invalid screen type");
684 scr
= vga_console_vc
.currenttype
;
686 #ifdef VGA_CONSOLE_ATI_BROKEN_FONTSEL
688 * On some (most/all?) ATI cards, only font slot 0 is usable.
689 * vga_init_screen() might need font slot 0 for a non-default
690 * console font, so save the builtin VGA font to another font slot.
691 * The attach() code will take care later.
693 vga_console_vc
.vc_quirks
|= VGA_QUIRK_ONEFONT
; /* redundant */
694 vga_copyfont01(&vga_console_vc
.hdl
);
695 vga_console_vc
.vc_nfontslots
= 1;
697 vga_console_vc
.vc_nfontslots
= 8;
700 /* until we know better, assume "fast scrolling" does not work */
701 vga_console_vc
.vc_quirks
|= VGA_QUIRK_NOFASTSCROLL
;
704 vga_init_screen(&vga_console_vc
, &vga_console_screen
, scr
, 1, &defattr
);
706 wsdisplay_cnattach(scr
, &vga_console_screen
,
707 vga_console_screen
.pcs
.cursorcol
,
708 vga_console_screen
.pcs
.cursorrow
, defattr
);
711 vga_console_type
= type
;
718 struct vga_config
*vc
;
719 struct vga_handle
*vh
;
721 vc
= &vga_console_vc
;
725 bus_space_unmap(vh
->vh_iot
, vh
->vh_ioh_vga
, 0x10);
726 bus_space_unmap(vh
->vh_iot
, vh
->vh_ioh_6845
, 0x10);
735 vga_is_console(bus_space_tag_t iot
, int type
)
738 !vga_console_attached
&&
739 iot
== vga_console_vc
.hdl
.vh_iot
&&
740 (vga_console_type
== -1 || (type
== vga_console_type
)))
746 vga_get_video(struct vga_config
*vc
)
749 return (vga_ts_read(&vc
->hdl
, mode
) & VGA_TS_MODE_BLANK
) == 0;
753 vga_set_video(struct vga_config
*vc
, int state
)
757 vga_ts_write(&vc
->hdl
, syncreset
, 0x01);
758 if (state
) { /* unblank screen */
759 val
= vga_ts_read(&vc
->hdl
, mode
);
760 vga_ts_write(&vc
->hdl
, mode
, val
& ~VGA_TS_MODE_BLANK
);
761 #ifndef VGA_NO_VBLANK
762 val
= vga_6845_read(&vc
->hdl
, mode
);
763 vga_6845_write(&vc
->hdl
, mode
, val
| 0x80);
765 } else { /* blank screen */
766 val
= vga_ts_read(&vc
->hdl
, mode
);
767 vga_ts_write(&vc
->hdl
, mode
, val
| VGA_TS_MODE_BLANK
);
768 #ifndef VGA_NO_VBLANK
769 val
= vga_6845_read(&vc
->hdl
, mode
);
770 vga_6845_write(&vc
->hdl
, mode
, val
& ~0x80);
773 vga_ts_write(&vc
->hdl
, syncreset
, 0x03);
777 vga_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
779 struct vga_config
*vc
= v
;
780 struct vgascreen
*scr
= vs
;
781 const struct vga_funcs
*vf
= vc
->vc_funcs
;
784 case WSDISPLAYIO_GTYPE
:
785 *(int *)data
= vc
->vc_type
;
788 case WSDISPLAYIO_GINFO
:
789 /* XXX should get detailed hardware information here */
792 case WSDISPLAYIO_GVIDEO
:
793 *(int *)data
= (vga_get_video(vc
) ?
794 WSDISPLAYIO_VIDEO_ON
: WSDISPLAYIO_VIDEO_OFF
);
797 case WSDISPLAYIO_SVIDEO
:
798 vga_set_video(vc
, *(int *)data
== WSDISPLAYIO_VIDEO_ON
);
801 case WSDISPLAYIO_GETWSCHAR
:
802 KASSERT(scr
!= NULL
);
803 return pcdisplay_getwschar(&scr
->pcs
,
804 (struct wsdisplay_char
*)data
);
806 case WSDISPLAYIO_PUTWSCHAR
:
807 KASSERT(scr
!= NULL
);
808 return pcdisplay_putwschar(&scr
->pcs
,
809 (struct wsdisplay_char
*)data
);
811 #ifdef WSDISPLAY_CUSTOM_BORDER
812 case WSDISPLAYIO_GBORDER
:
813 return (vga_getborder(vc
, (u_int
*)data
));
815 case WSDISPLAYIO_SBORDER
:
816 return (vga_setborder(vc
, *(u_int
*)data
));
819 case WSDISPLAYIO_GETCMAP
:
820 case WSDISPLAYIO_PUTCMAP
:
821 case WSDISPLAYIO_GCURPOS
:
822 case WSDISPLAYIO_SCURPOS
:
823 case WSDISPLAYIO_GCURMAX
:
824 case WSDISPLAYIO_GCURSOR
:
825 case WSDISPLAYIO_SCURSOR
:
826 /* NONE of these operations are by the generic VGA driver. */
830 if (vc
->vc_funcs
== NULL
)
831 return (EPASSTHROUGH
);
833 if (vf
->vf_ioctl
== NULL
)
834 return (EPASSTHROUGH
);
836 return ((*vf
->vf_ioctl
)(v
, cmd
, data
, flag
, l
));
840 vga_mmap(void *v
, void *vs
, off_t offset
, int prot
)
842 struct vga_config
*vc
= v
;
843 const struct vga_funcs
*vf
= vc
->vc_funcs
;
845 if (vc
->vc_funcs
== NULL
)
848 if (vf
->vf_mmap
== NULL
)
851 return ((*vf
->vf_mmap
)(v
, offset
, prot
));
855 vga_alloc_screen(void *v
, const struct wsscreen_descr
*type
, void **cookiep
,
856 int *curxp
, int *curyp
, long *defattrp
)
858 struct vga_config
*vc
= v
;
859 struct vgascreen
*scr
;
861 if (vc
->nscreens
== 1) {
862 struct vgascreen
*scr1
= vc
->screens
.lh_first
;
864 * When allocating the second screen, get backing store
865 * for the first one too.
866 * XXX We could be more clever and use video RAM.
869 malloc(scr1
->pcs
.type
->ncols
* scr1
->pcs
.type
->nrows
* 2,
873 scr
= malloc(sizeof(struct vgascreen
), M_DEVBUF
, M_WAITOK
);
874 vga_init_screen(vc
, scr
, type
, vc
->nscreens
== 0, defattrp
);
876 if (vc
->nscreens
> 1) {
877 scr
->pcs
.mem
= malloc(type
->ncols
* type
->nrows
* 2,
879 pcdisplay_eraserows(&scr
->pcs
, 0, type
->nrows
, *defattrp
);
883 *curxp
= scr
->pcs
.cursorcol
;
884 *curyp
= scr
->pcs
.cursorrow
;
890 vga_free_screen(void *v
, void *cookie
)
892 struct vgascreen
*vs
= cookie
;
893 struct vga_config
*vc
= vs
->cfg
;
895 LIST_REMOVE(vs
, next
);
898 egavga_unreffont(vc
, vs
->fontset1
);
900 egavga_unreffont(vc
, vs
->fontset2
);
902 if (vs
!= &vga_console_screen
)
905 panic("vga_free_screen: console");
907 if (vc
->active
== vs
)
911 static void vga_usefont(struct vga_config
*, struct egavga_font
*);
914 vga_usefont(struct vga_config
*vc
, struct egavga_font
*f
)
917 struct egavga_font
*of
;
922 for (slot
= 0; slot
< vc
->vc_nfontslots
; slot
++) {
923 if (!vc
->vc_fonts
[slot
])
927 /* have to kick out another one */
928 TAILQ_FOREACH(of
, &vc
->vc_fontlist
, next
) {
929 if (of
->slot
!= -1) {
930 KASSERT(vc
->vc_fonts
[of
->slot
] == of
);
936 panic("vga_usefont");
939 vga_loadchars(&vc
->hdl
, slot
, f
->wsfont
->firstchar
,
940 f
->wsfont
->numchars
, f
->wsfont
->fontheight
, f
->wsfont
->data
);
942 vc
->vc_fonts
[slot
] = f
;
945 TAILQ_REMOVE(&vc
->vc_fontlist
, f
, next
);
946 TAILQ_INSERT_TAIL(&vc
->vc_fontlist
, f
, next
);
950 vga_setfont(struct vga_config
*vc
, struct vgascreen
*scr
)
952 int fontslot1
, fontslot2
;
955 vga_usefont(vc
, scr
->fontset1
);
957 vga_usefont(vc
, scr
->fontset2
);
959 fontslot1
= (scr
->fontset1
? scr
->fontset1
->slot
: 0);
960 fontslot2
= (scr
->fontset2
? scr
->fontset2
->slot
: fontslot1
);
961 if (vc
->currentfontset1
!= fontslot1
||
962 vc
->currentfontset2
!= fontslot2
) {
963 vga_setfontset(&vc
->hdl
, fontslot1
, fontslot2
);
964 vc
->currentfontset1
= fontslot1
;
965 vc
->currentfontset2
= fontslot2
;
970 vga_show_screen(void *v
, void *cookie
, int waitok
,
971 void (*cb
)(void *, int, int), void *cbarg
)
973 struct vgascreen
*scr
= cookie
, *oldscr
;
974 struct vga_config
*vc
= scr
->cfg
;
976 oldscr
= vc
->active
; /* can be NULL! */
981 vc
->wantedscreen
= cookie
;
983 vc
->switchcbarg
= cbarg
;
985 callout_reset(&vc
->vc_switch_callout
, 0,
986 (void(*)(void *))vga_doswitch
, vc
);
995 vga_doswitch(struct vga_config
*vc
)
997 struct vgascreen
*scr
, *oldscr
;
998 struct vga_handle
*vh
= &vc
->hdl
;
999 const struct wsscreen_descr
*type
;
1001 scr
= vc
->wantedscreen
;
1003 printf("vga_doswitch: disappeared\n");
1004 (*vc
->switchcb
)(vc
->switchcbarg
, EIO
, 0);
1007 type
= scr
->pcs
.type
;
1008 oldscr
= vc
->active
; /* can be NULL! */
1011 if (!oldscr
->pcs
.active
)
1012 panic("vga_show_screen: not active");
1013 if (oldscr
->pcs
.type
!= vc
->currenttype
)
1014 panic("vga_show_screen: bad type");
1017 if (scr
== oldscr
) {
1021 if (scr
->pcs
.active
)
1022 panic("vga_show_screen: active");
1026 const struct wsscreen_descr
*oldtype
= oldscr
->pcs
.type
;
1028 oldscr
->pcs
.active
= 0;
1029 bus_space_read_region_2(vh
->vh_memt
, vh
->vh_memh
,
1030 oldscr
->pcs
.dispoffset
, oldscr
->pcs
.mem
,
1031 oldtype
->ncols
* oldtype
->nrows
);
1034 if (vc
->currenttype
!= type
) {
1035 vga_setscreentype(vh
, type
);
1036 vc
->currenttype
= type
;
1039 vga_setfont(vc
, scr
);
1040 /* XXX swich colours! */
1042 scr
->pcs
.visibleoffset
= scr
->pcs
.dispoffset
= scr
->mindispoffset
;
1043 if (!oldscr
|| (scr
->pcs
.dispoffset
!= oldscr
->pcs
.dispoffset
)) {
1044 vga_6845_write(vh
, startadrh
, scr
->pcs
.dispoffset
>> 9);
1045 vga_6845_write(vh
, startadrl
, scr
->pcs
.dispoffset
>> 1);
1048 bus_space_write_region_2(vh
->vh_memt
, vh
->vh_memh
,
1049 scr
->pcs
.dispoffset
, scr
->pcs
.mem
, type
->ncols
* type
->nrows
);
1050 scr
->pcs
.active
= 1;
1054 pcdisplay_cursor(&scr
->pcs
, scr
->pcs
.cursoron
,
1055 scr
->pcs
.cursorrow
, scr
->pcs
.cursorcol
);
1057 vc
->wantedscreen
= 0;
1059 (*vc
->switchcb
)(vc
->switchcbarg
, 0, 0);
1063 vga_load_font(void *v
, void *cookie
, struct wsdisplay_font
*data
)
1065 struct vga_config
*vc
= v
;
1066 struct vgascreen
*scr
= cookie
;
1073 name2
= strchr(data
->name
, ',');
1077 res
= vga_selectfont(vc
, scr
, data
->name
, name2
);
1078 if (!res
&& scr
->pcs
.active
)
1079 vga_setfont(vc
, scr
);
1087 vga_allocattr(void *id
, int fg
, int bg
, int flags
, long *attrp
)
1089 struct vgascreen
*scr
= id
;
1090 struct vga_config
*vc
= scr
->cfg
;
1092 if (__predict_false((unsigned int)fg
>= sizeof(fgansitopc
) ||
1093 (unsigned int)bg
>= sizeof(bgansitopc
)))
1096 if (vc
->hdl
.vh_mono
) {
1097 if (flags
& WSATTR_WSCOLORS
)
1099 if (flags
& WSATTR_REVERSE
)
1103 if (flags
& WSATTR_UNDERLINE
)
1104 *attrp
|= FG_UNDERLINE
;
1105 if (flags
& WSATTR_HILIT
)
1106 *attrp
|= FG_INTENSE
;
1108 if (flags
& (WSATTR_UNDERLINE
| WSATTR_REVERSE
))
1110 if (flags
& WSATTR_WSCOLORS
)
1111 *attrp
= fgansitopc
[fg
] | bgansitopc
[bg
];
1114 if (flags
& WSATTR_HILIT
)
1117 if (flags
& WSATTR_BLINK
)
1123 vga_copyrows(void *id
, int srcrow
, int dstrow
, int nrows
)
1125 struct vgascreen
*scr
= id
;
1126 bus_space_tag_t memt
= scr
->pcs
.hdl
->ph_memt
;
1127 bus_space_handle_t memh
= scr
->pcs
.hdl
->ph_memh
;
1128 int ncols
= scr
->pcs
.type
->ncols
;
1129 bus_size_t srcoff
, dstoff
;
1131 srcoff
= srcrow
* ncols
+ 0;
1132 dstoff
= dstrow
* ncols
+ 0;
1134 if (scr
->pcs
.active
) {
1135 if (dstrow
== 0 && (srcrow
+ nrows
== scr
->pcs
.type
->nrows
)) {
1136 #ifdef PCDISPLAY_SOFTCURSOR
1137 int cursoron
= scr
->pcs
.cursoron
;
1140 pcdisplay_cursor(&scr
->pcs
, 0,
1141 scr
->pcs
.cursorrow
, scr
->pcs
.cursorcol
);
1143 /* scroll up whole screen */
1144 if ((scr
->pcs
.dispoffset
+ srcrow
* ncols
* 2)
1145 <= scr
->maxdispoffset
) {
1146 scr
->pcs
.dispoffset
+= srcrow
* ncols
* 2;
1148 bus_space_copy_region_2(memt
, memh
,
1149 scr
->pcs
.dispoffset
+ srcoff
* 2,
1150 memh
, scr
->mindispoffset
, nrows
* ncols
);
1151 scr
->pcs
.dispoffset
= scr
->mindispoffset
;
1153 vga_6845_write(&scr
->cfg
->hdl
, startadrh
,
1154 scr
->pcs
.dispoffset
>> 9);
1155 vga_6845_write(&scr
->cfg
->hdl
, startadrl
,
1156 scr
->pcs
.dispoffset
>> 1);
1157 #ifdef PCDISPLAY_SOFTCURSOR
1159 pcdisplay_cursor(&scr
->pcs
, 1,
1160 scr
->pcs
.cursorrow
, scr
->pcs
.cursorcol
);
1163 bus_space_copy_region_2(memt
, memh
,
1164 scr
->pcs
.dispoffset
+ srcoff
* 2,
1165 memh
, scr
->pcs
.dispoffset
+ dstoff
* 2,
1169 memcpy(&scr
->pcs
.mem
[dstoff
], &scr
->pcs
.mem
[srcoff
],
1173 #ifdef WSCONS_SUPPORT_PCVTFONTS
1175 #define NOTYET 0xffff
1176 static const u_int16_t pcvt_unichars
[0xa0] = {
1177 /* 0 */ _e006U
, /* N/L control */
1178 NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1180 0x2409, /* SYMBOL FOR HORIZONTAL TABULATION */
1181 0x240a, /* SYMBOL FOR LINE FEED */
1182 0x240b, /* SYMBOL FOR VERTICAL TABULATION */
1183 0x240c, /* SYMBOL FOR FORM FEED */
1184 0x240d, /* SYMBOL FOR CARRIAGE RETURN */
1186 /* 1 */ NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1187 NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1188 /* 2 */ NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1189 NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1190 /* 3 */ NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1191 NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
, NOTYET
,
1192 /* 4 */ 0x03c1, /* GREEK SMALL LETTER RHO */
1193 0x03c8, /* GREEK SMALL LETTER PSI */
1194 0x2202, /* PARTIAL DIFFERENTIAL */
1195 0x03bb, /* GREEK SMALL LETTER LAMDA */
1196 0x03b9, /* GREEK SMALL LETTER IOTA */
1197 0x03b7, /* GREEK SMALL LETTER ETA */
1198 0x03b5, /* GREEK SMALL LETTER EPSILON */
1199 0x03c7, /* GREEK SMALL LETTER CHI */
1200 0x2228, /* LOGICAL OR */
1201 0x2227, /* LOGICAL AND */
1203 0x2283, /* SUPERSET OF */
1204 0x2282, /* SUBSET OF */
1205 0x03a5, /* GREEK CAPITAL LETTER UPSILON */
1206 0x039e, /* GREEK CAPITAL LETTER XI */
1207 0x03a8, /* GREEK CAPITAL LETTER PSI */
1208 /* 5 */ 0x03a0, /* GREEK CAPITAL LETTER PI */
1209 0x21d2, /* RIGHTWARDS DOUBLE ARROW */
1210 0x21d4, /* LEFT RIGHT DOUBLE ARROW */
1211 0x039b, /* GREEK CAPITAL LETTER LAMDA */
1212 0x0398, /* GREEK CAPITAL LETTER THETA */
1213 0x2243, /* ASYMPTOTICALLY EQUAL TO */
1215 0x2206, /* INCREMENT */
1216 0x221d, /* PROPORTIONAL TO */
1217 0x2234, /* THEREFORE */
1218 0x222b, /* INTEGRAL */
1219 0x2215, /* DIVISION SLASH */
1220 0x2216, /* SET MINUS */
1221 _e00eU
, /* angle? */
1222 _e00dU
, /* inverted angle? */
1223 _e00bU
, /* braceleftmid */
1224 /* 6 */ _e00cU
, /* bracerightmid */
1225 _e007U
, /* bracelefttp */
1226 _e008U
, /* braceleftbt */
1227 _e009U
, /* bracerighttp */
1228 _e00aU
, /* bracerightbt */
1229 0x221a, /* SQUARE ROOT */
1230 0x03c9, /* GREEK SMALL LETTER OMEGA */
1231 0x00a5, /* YEN SIGN */
1232 0x03be, /* GREEK SMALL LETTER XI */
1233 0x00fd, /* LATIN SMALL LETTER Y WITH ACUTE */
1234 0x00fe, /* LATIN SMALL LETTER THORN */
1235 0x00f0, /* LATIN SMALL LETTER ETH */
1236 0x00de, /* LATIN CAPITAL LETTER THORN */
1237 0x00dd, /* LATIN CAPITAL LETTER Y WITH ACUTE */
1238 0x00d7, /* MULTIPLICATION SIGN */
1239 0x00d0, /* LATIN CAPITAL LETTER ETH */
1240 /* 7 */ 0x00be, /* VULGAR FRACTION THREE QUARTERS */
1241 0x00b8, /* CEDILLA */
1242 0x00b4, /* ACUTE ACCENT */
1243 0x00af, /* MACRON */
1244 0x00ae, /* REGISTERED SIGN */
1245 0x00ad, /* SOFT HYPHEN */
1246 0x00ac, /* NOT SIGN */
1247 0x00a8, /* DIAERESIS */
1248 0x2260, /* NOT EQUAL TO */
1249 _e005U
, /* scan 9 */
1250 _e004U
, /* scan 7 */
1251 _e003U
, /* scan 5 */
1252 _e002U
, /* scan 3 */
1253 _e001U
, /* scan 1 */
1254 0x03c5, /* GREEK SMALL LETTER UPSILON */
1255 0x00f8, /* LATIN SMALL LETTER O WITH STROKE */
1256 /* 8 */ 0x0153, /* LATIN SMALL LIGATURE OE */
1257 0x00f5, /* LATIN SMALL LETTER O WITH TILDE !!!doc bug */
1258 0x00e3, /* LATIN SMALL LETTER A WITH TILDE */
1259 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1260 0x00db, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1261 0x00da, /* LATIN CAPITAL LETTER U WITH ACUTE */
1262 0x00d9, /* LATIN CAPITAL LETTER U WITH GRAVE */
1263 0x00d8, /* LATIN CAPITAL LETTER O WITH STROKE */
1264 0x0152, /* LATIN CAPITAL LIGATURE OE */
1265 0x00d5, /* LATIN CAPITAL LETTER O WITH TILDE */
1266 0x00d4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1267 0x00d3, /* LATIN CAPITAL LETTER O WITH ACUTE */
1268 0x00d2, /* LATIN CAPITAL LETTER O WITH GRAVE */
1269 0x00cf, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1270 0x00ce, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1271 0x00cd, /* LATIN CAPITAL LETTER I WITH ACUTE */
1272 /* 9 */ 0x00cc, /* LATIN CAPITAL LETTER I WITH GRAVE */
1273 0x00cb, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1274 0x00ca, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1275 0x00c8, /* LATIN CAPITAL LETTER E WITH GRAVE */
1276 0x00c3, /* LATIN CAPITAL LETTER A WITH TILDE */
1277 0x00c2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1278 0x00c1, /* LATIN CAPITAL LETTER A WITH ACUTE */
1279 0x00c0, /* LATIN CAPITAL LETTER A WITH GRAVE */
1280 0x00b9, /* SUPERSCRIPT ONE */
1281 0x00b7, /* MIDDLE DOT */
1282 0x03b6, /* GREEK SMALL LETTER ZETA */
1283 0x00b3, /* SUPERSCRIPT THREE */
1284 0x00a9, /* COPYRIGHT SIGN */
1285 0x00a4, /* CURRENCY SIGN */
1286 0x03ba, /* GREEK SMALL LETTER KAPPA */
1287 _e000U
/* mirrored question mark? */
1290 static int vga_pcvt_mapchar(int, u_int
*);
1293 vga_pcvt_mapchar(int uni
, u_int
*index
)
1297 for (i
= 0; i
< 0xa0; i
++) /* 0xa0..0xff are reserved */
1298 if (uni
== pcvt_unichars
[i
]) {
1302 *index
= 0x99; /* middle dot */
1306 #endif /* WSCONS_SUPPORT_PCVTFONTS */
1308 #ifdef WSCONS_SUPPORT_ISO7FONTS
1311 vga_iso7_mapchar(int uni
, u_int
*index
)
1315 * U+0384 (GREEK TONOS) to
1316 * U+03ce (GREEK SMALL LETTER OMEGA WITH TONOS)
1317 * map directly to the iso-9 font
1319 if (uni
>= 0x0384 && uni
<= 0x03ce) {
1320 /* U+0384 is at offset 0xb4 in the font */
1321 *index
= uni
- 0x0384 + 0xb4;
1325 /* XXX more chars in the iso-9 font */
1327 *index
= 0xa4; /* shaded rectangle */
1331 #endif /* WSCONS_SUPPORT_ISO7FONTS */
1333 static int _vga_mapchar(void *, const struct egavga_font
*, int, u_int
*);
1336 _vga_mapchar(void *id
, const struct egavga_font
*font
, int uni
, u_int
*index
)
1339 switch (font
->wsfont
->encoding
) {
1340 case WSDISPLAY_FONTENC_ISO
:
1348 case WSDISPLAY_FONTENC_IBM
:
1349 return (pcdisplay_mapchar(id
, uni
, index
));
1350 #ifdef WSCONS_SUPPORT_PCVTFONTS
1351 case WSDISPLAY_FONTENC_PCVT
:
1352 return (vga_pcvt_mapchar(uni
, index
));
1354 #ifdef WSCONS_SUPPORT_ISO7FONTS
1355 case WSDISPLAY_FONTENC_ISO7
:
1356 return (vga_iso7_mapchar(uni
, index
));
1360 printf("_vga_mapchar: encoding=%d\n", font
->wsfont
->encoding
);
1368 vga_mapchar(void *id
, int uni
, u_int
*index
)
1370 struct vgascreen
*scr
= id
;
1375 idx1
= ' '; /* space */
1377 res1
= _vga_mapchar(id
, scr
->fontset1
, uni
, &idx1
);
1379 if (scr
->fontset2
) {
1380 KASSERT(VGA_SCREEN_CANTWOFONTS(scr
->pcs
.type
));
1381 res2
= _vga_mapchar(id
, scr
->fontset2
, uni
, &idx2
);
1384 *index
= idx2
| 0x0800; /* attribute bit 3 */
1391 #ifdef WSDISPLAY_SCROLLSUPPORT
1393 vga_scroll(void *v
, void *cookie
, int lines
)
1395 struct vga_config
*vc
= v
;
1396 struct vgascreen
*scr
= cookie
;
1397 struct vga_handle
*vh
= &vc
->hdl
;
1400 if (scr
->pcs
.visibleoffset
== scr
->pcs
.dispoffset
)
1403 scr
->pcs
.visibleoffset
= scr
->pcs
.dispoffset
;
1407 int margin
= scr
->pcs
.type
->ncols
* 2;
1410 vga_scr_end
= (scr
->pcs
.dispoffset
+ scr
->pcs
.type
->ncols
*
1411 scr
->pcs
.type
->nrows
* 2);
1412 if (scr
->vga_rollover
> vga_scr_end
+ margin
) {
1414 we
= scr
->vga_rollover
+ scr
->pcs
.type
->ncols
* 2;
1419 p
= (scr
->pcs
.visibleoffset
- ul
+ we
) % we
+ lines
*
1420 (scr
->pcs
.type
->ncols
* 2);
1421 st
= (scr
->pcs
.dispoffset
- ul
+ we
) % we
;
1424 if (p
> st
- margin
)
1426 scr
->pcs
.visibleoffset
= (p
+ ul
) % we
;
1429 vga_6845_write(vh
, startadrh
, scr
->pcs
.visibleoffset
>> 9);
1430 vga_6845_write(vh
, startadrl
, scr
->pcs
.visibleoffset
>> 1);
1435 vga_putchar(void *c
, int row
, int col
, u_int uc
, long attr
)
1438 pcdisplay_putchar(c
, row
, col
, uc
, attr
);
1441 #ifdef WSDISPLAY_CUSTOM_BORDER
1443 vga_getborder(struct vga_config
*vc
, u_int
*valuep
)
1445 struct vga_handle
*vh
= &vc
->hdl
;
1452 value
= _vga_attr_read(vh
, VGA_ATC_OVERSCAN
);
1453 for (idx
= 0; idx
< sizeof(fgansitopc
); idx
++) {
1454 if (fgansitopc
[idx
] == value
) {
1463 vga_setborder(struct vga_config
*vc
, u_int value
)
1465 struct vga_handle
*vh
= &vc
->hdl
;
1469 if (value
>= sizeof(fgansitopc
))
1472 _vga_attr_write(vh
, VGA_ATC_OVERSCAN
, fgansitopc
[value
]);
1475 #endif /* WSDISPLAY_CUSTOM_BORDER */
1478 vga_resume(struct vga_softc
*sc
)
1480 #ifdef VGA_RESET_ON_RESUME
1481 vga_initregs(&sc
->sc_vc
->hdl
);