2 * Copyright (c) 1998 Kazutaka YOKOTA and Michael Smith
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/sys/i386/isa/vesa.c,v 1.32.2.1 2002/08/13 02:42:33 rwatson Exp $
27 * $DragonFly: src/sys/dev/video/i386/vesa/vesa.c,v 1.25 2008/04/30 04:05:21 dillon Exp $
33 #ifndef VGA_NO_MODE_CHANGE
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
41 #include <sys/thread2.h>
44 #include <vm/vm_extern.h>
45 #include <vm/vm_kern.h>
48 #include <machine/md_var.h>
49 #include <machine/vm86.h>
50 #include <machine/pc/bios.h>
51 #include <machine/pc/vesa.h>
53 #include <dev/video/fb/fbreg.h>
54 #include <dev/video/fb/vgareg.h>
57 #include <bus/isa/isareg.h>
59 #include <bus/isa/i386/isa.h>
62 #define VESA_VIA_CLE266 "VIA CLE266\r\n"
68 /* VESA video adapter state buffer stub */
71 #define V_STATE_SIG 0x61736576
74 typedef struct adp_state adp_state_t
;
76 /* VESA video adapter */
77 static video_adapter_t
*vesa_adp
= NULL
;
78 static int vesa_state_buf_size
= 0;
79 #define VESA_VM86_BUFSIZE (3 * PAGE_SIZE)
80 static void *vesa_vm86_buf
;
84 static int vesa_nop(void);
86 static int vesa_error(void);
87 static vi_probe_t vesa_probe
;
88 static vi_init_t vesa_init
;
89 static vi_get_info_t vesa_get_info
;
90 static vi_query_mode_t vesa_query_mode
;
91 static vi_set_mode_t vesa_set_mode
;
92 static vi_save_font_t vesa_save_font
;
93 static vi_load_font_t vesa_load_font
;
94 static vi_show_font_t vesa_show_font
;
95 static vi_save_palette_t vesa_save_palette
;
96 static vi_load_palette_t vesa_load_palette
;
97 static vi_set_border_t vesa_set_border
;
98 static vi_save_state_t vesa_save_state
;
99 static vi_load_state_t vesa_load_state
;
100 static vi_set_win_org_t vesa_set_origin
;
101 static vi_read_hw_cursor_t vesa_read_hw_cursor
;
102 static vi_set_hw_cursor_t vesa_set_hw_cursor
;
103 static vi_set_hw_cursor_shape_t vesa_set_hw_cursor_shape
;
104 static vi_blank_display_t vesa_blank_display
;
105 static vi_mmap_t vesa_mmap
;
106 static vi_ioctl_t vesa_ioctl
;
107 static vi_clear_t vesa_clear
;
108 static vi_fill_rect_t vesa_fill_rect
;
109 static vi_bitblt_t vesa_bitblt
;
110 static vi_diag_t vesa_diag
;
111 static int vesa_bios_info(int level
);
112 static struct vm86context vesa_vmcontext
;
114 static video_switch_t vesavidsw
= {
131 vesa_set_hw_cursor_shape
,
143 static video_switch_t
*prevvidsw
;
145 /* VESA BIOS video modes */
149 #define MODE_TABLE_DELTA 8
151 static int vesa_vmode_max
= 0;
152 static video_info_t vesa_vmode_empty
= { EOT
};
153 static video_info_t
*vesa_vmode
= &vesa_vmode_empty
;
155 static int vesa_init_done
= FALSE
;
156 static int has_vesa_bios
= FALSE
;
157 static int dpms_states
;
158 static struct vesa_info
*vesa_adp_info
= NULL
;
159 static uint16_t *vesa_vmodetab
= NULL
;
160 static char *vesa_oemstr
= NULL
;
161 static char *vesa_vendorstr
= NULL
;
162 static char *vesa_prodstr
= NULL
;
163 static char *vesa_revstr
= NULL
;
165 /* local macros and functions */
166 #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
168 static int int10_set_mode(int mode
);
169 static int vesa_bios_get_mode(int mode
, struct vesa_mode
*vmode
);
170 static int vesa_bios_set_mode(int mode
);
171 static int vesa_bios_get_dac(void);
172 static int vesa_bios_set_dac(int bits
);
173 static int vesa_bios_save_palette(int start
, int colors
, u_char
*palette
,
175 static int vesa_bios_save_palette2(int start
, int colors
, u_char
*r
, u_char
*g
,
176 u_char
*b
, int bits
);
177 static int vesa_bios_load_palette(int start
, int colors
, const u_char
*palette
,
180 static int vesa_bios_load_palette2(int start
, int colors
, u_char
*r
, u_char
*g
,
181 u_char
*b
, int bits
);
186 #define STATE_HW (1<<0)
187 #define STATE_DATA (1<<1)
188 #define STATE_DAC (1<<2)
189 #define STATE_REG (1<<3)
190 #define STATE_MOST (STATE_HW | STATE_DATA | STATE_REG)
191 #define STATE_ALL (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
192 static int vesa_bios_state_buf_size(void);
193 static int vesa_bios_save_restore(int code
, void *p
, size_t size
);
194 static int vesa_bios_get_line_length(void);
195 static int vesa_bios_set_line_length(int pixel
, int *bytes
, int *lines
);
197 static int vesa_bios_get_start(int *x
, int *y
);
199 static int vesa_bios_set_start(int x
, int y
);
200 static int vesa_translate_flags(uint16_t vflags
);
201 static int vesa_translate_mmodel(uint8_t vmodel
);
202 static void *vesa_fix_ptr(uint32_t p
, uint16_t seg
, uint16_t off
,
204 static int vesa_bios_init(void);
205 static vm_offset_t
vesa_map_buffer(u_int paddr
, size_t size
);
206 static void vesa_unmap_buffer(vm_offset_t vaddr
, size_t size
);
207 static int vesa_probe_dpms(void);
210 static int vesa_get_origin(video_adapter_t
*adp
, off_t
*offset
);
214 dump_buffer(u_char
*buf
, size_t len
)
218 for (i
= 0; i
< len
;) {
219 kprintf("%02x ", buf
[i
]);
225 /* INT 10 BIOS calls */
227 int10_set_mode(int mode
)
229 struct vm86frame vmf
;
231 bzero(&vmf
, sizeof(vmf
));
232 vmf
.vmf_eax
= 0x0000 | mode
;
233 vm86_intcall(0x10, &vmf
);
237 /* VESA BIOS calls */
239 vesa_bios_get_mode(int mode
, struct vesa_mode
*vmode
)
241 struct vm86frame vmf
;
245 bzero(&vmf
, sizeof(vmf
));
246 vmf
.vmf_eax
= 0x4f01;
249 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)buf
, &vmf
.vmf_es
, &vmf
.vmf_di
);
251 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
252 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
254 bcopy(buf
, vmode
, sizeof(*vmode
));
259 vesa_bios_set_mode(int mode
)
261 struct vm86frame vmf
;
264 bzero(&vmf
, sizeof(vmf
));
265 vmf
.vmf_eax
= 0x4f02;
267 err
= vm86_intcall(0x10, &vmf
);
268 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
272 vesa_bios_get_dac(void)
274 struct vm86frame vmf
;
277 bzero(&vmf
, sizeof(vmf
));
278 vmf
.vmf_eax
= 0x4f08;
279 vmf
.vmf_ebx
= 1; /* get DAC width */
280 err
= vm86_intcall(0x10, &vmf
);
281 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
283 return ((vmf
.vmf_ebx
>> 8) & 0x00ff);
287 vesa_bios_set_dac(int bits
)
289 struct vm86frame vmf
;
292 bzero(&vmf
, sizeof(vmf
));
293 vmf
.vmf_eax
= 0x4f08;
294 vmf
.vmf_ebx
= (bits
<< 8);
295 err
= vm86_intcall(0x10, &vmf
);
296 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
298 return ((vmf
.vmf_ebx
>> 8) & 0x00ff);
302 vesa_bios_save_palette(int start
, int colors
, u_char
*palette
, int bits
)
304 struct vm86frame vmf
;
309 bzero(&vmf
, sizeof(vmf
));
310 vmf
.vmf_eax
= 0x4f09;
311 vmf
.vmf_ebx
= 1; /* get primary palette data */
312 vmf
.vmf_ecx
= colors
;
315 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)p
, &vmf
.vmf_es
, &vmf
.vmf_di
);
317 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
318 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
322 for (i
= 0; i
< colors
; ++i
) {
323 palette
[i
*3] = p
[i
*4 + 2] << bits
;
324 palette
[i
*3 + 1] = p
[i
*4 + 1] << bits
;
325 palette
[i
*3 + 2] = p
[i
*4] << bits
;
331 vesa_bios_save_palette2(int start
, int colors
, u_char
*r
, u_char
*g
, u_char
*b
,
334 struct vm86frame vmf
;
339 bzero(&vmf
, sizeof(vmf
));
340 vmf
.vmf_eax
= 0x4f09;
341 vmf
.vmf_ebx
= 1; /* get primary palette data */
342 vmf
.vmf_ecx
= colors
;
345 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)p
, &vmf
.vmf_es
, &vmf
.vmf_di
);
347 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
348 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
352 for (i
= 0; i
< colors
; ++i
) {
353 r
[i
] = p
[i
*4 + 2] << bits
;
354 g
[i
] = p
[i
*4 + 1] << bits
;
355 b
[i
] = p
[i
*4] << bits
;
361 vesa_bios_load_palette(int start
, int colors
, const u_char
*palette
, int bits
)
363 struct vm86frame vmf
;
370 for (i
= 0; i
< colors
; ++i
) {
371 p
[i
*4] = palette
[i
*3 + 2] >> bits
;
372 p
[i
*4 + 1] = palette
[i
*3 + 1] >> bits
;
373 p
[i
*4 + 2] = palette
[i
*3] >> bits
;
377 bzero(&vmf
, sizeof(vmf
));
378 vmf
.vmf_eax
= 0x4f09;
379 vmf
.vmf_ebx
= 0; /* set primary palette data */
380 vmf
.vmf_ecx
= colors
;
382 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)p
, &vmf
.vmf_es
, &vmf
.vmf_di
);
384 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
385 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
390 vesa_bios_load_palette2(int start
, int colors
, u_char
*r
, u_char
*g
, u_char
*b
,
393 struct vm86frame vmf
;
400 for (i
= 0; i
< colors
; ++i
) {
401 p
[i
*4] = b
[i
] >> bits
;
402 p
[i
*4 + 1] = g
[i
] >> bits
;
403 p
[i
*4 + 2] = r
[i
] >> bits
;
407 bzero(&vmf
, sizeof(vmf
));
408 vmf
.vmf_eax
= 0x4f09;
409 vmf
.vmf_ebx
= 0; /* set primary palette data */
410 vmf
.vmf_ecx
= colors
;
412 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)p
, &vmf
.vmf_es
, &vmf
.vmf_di
);
414 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
415 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
420 vesa_bios_state_buf_size(void)
422 struct vm86frame vmf
;
425 bzero(&vmf
, sizeof(vmf
));
426 vmf
.vmf_eax
= 0x4f04;
427 vmf
.vmf_ecx
= STATE_ALL
;
428 vmf
.vmf_edx
= STATE_SIZE
;
429 err
= vm86_intcall(0x10, &vmf
);
430 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
432 return vmf
.vmf_bx
*64;
436 vesa_bios_save_restore(int code
, void *p
, size_t size
)
438 struct vm86frame vmf
;
442 if (size
> VESA_VM86_BUFSIZE
)
445 bzero(&vmf
, sizeof(vmf
));
446 vmf
.vmf_eax
= 0x4f04;
447 vmf
.vmf_ecx
= STATE_ALL
;
448 vmf
.vmf_edx
= code
; /* STATE_SAVE/STATE_LOAD */
450 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)buf
, &vmf
.vmf_es
, &vmf
.vmf_bx
);
453 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
455 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
459 vesa_bios_get_line_length(void)
461 struct vm86frame vmf
;
464 bzero(&vmf
, sizeof(vmf
));
465 vmf
.vmf_eax
= 0x4f06;
466 vmf
.vmf_ebx
= 1; /* get scan line length */
467 err
= vm86_intcall(0x10, &vmf
);
468 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
470 return vmf
.vmf_bx
; /* line length in bytes */
474 vesa_bios_set_line_length(int pixel
, int *bytes
, int *lines
)
476 struct vm86frame vmf
;
479 bzero(&vmf
, sizeof(vmf
));
480 vmf
.vmf_eax
= 0x4f06;
481 vmf
.vmf_ebx
= 0; /* set scan line length in pixel */
483 err
= vm86_intcall(0x10, &vmf
);
485 kprintf("bx:%d, cx:%d, dx:%d\n", vmf
.vmf_bx
, vmf
.vmf_cx
, vmf
.vmf_dx
);
487 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
498 vesa_bios_get_start(int *x
, int *y
)
500 struct vm86frame vmf
;
503 bzero(&vmf
, sizeof(vmf
));
504 vmf
.vmf_eax
= 0x4f07;
505 vmf
.vmf_ebx
= 1; /* get display start */
506 err
= vm86_intcall(0x10, &vmf
);
507 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
516 vesa_bios_set_start(int x
, int y
)
518 struct vm86frame vmf
;
521 bzero(&vmf
, sizeof(vmf
));
522 vmf
.vmf_eax
= 0x4f07;
523 vmf
.vmf_ebx
= 0x80; /* set display start */
526 err
= vm86_intcall(0x10, &vmf
);
527 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
531 vesa_translate_flags(uint16_t vflags
)
538 { V_MODECOLOR
, V_INFO_COLOR
, 0 },
539 { V_MODEGRAPHICS
, V_INFO_GRAPHICS
, 0 },
540 { V_MODELFB
, V_INFO_LINEAR
, 0 },
545 for (flags
= 0, i
= 0; i
< sizeof(ftable
)/sizeof(ftable
[0]); ++i
) {
546 flags
|= (vflags
& ftable
[i
].mask
) ?
547 ftable
[i
].set
: ftable
[i
].reset
;
553 vesa_translate_mmodel(uint8_t vmodel
)
559 { V_MMTEXT
, V_INFO_MM_TEXT
},
560 { V_MMCGA
, V_INFO_MM_CGA
},
561 { V_MMHGC
, V_INFO_MM_HGC
},
562 { V_MMEGA
, V_INFO_MM_PLANAR
},
563 { V_MMPACKED
, V_INFO_MM_PACKED
},
564 { V_MMDIRCOLOR
, V_INFO_MM_DIRECT
},
568 for (i
= 0; mtable
[i
].mmodel
>= 0; ++i
) {
569 if (mtable
[i
].vmodel
== vmodel
)
570 return mtable
[i
].mmodel
;
572 return V_INFO_MM_OTHER
;
576 vesa_fix_ptr(uint32_t p
, uint16_t seg
, uint16_t off
, u_char
*buf
)
580 if (((p
>> 16) == seg
) && ((p
& 0xffff) >= off
))
581 return (void *)(buf
+ ((p
& 0xffff) - off
));
583 p
= BIOS_SADDRTOLADDR(p
);
584 return (void *)BIOS_PADDRTOVADDR(p
);
591 static u_char buf
[512];
592 struct vm86frame vmf
;
593 struct vesa_mode vmode
;
604 has_vesa_bios
= FALSE
;
605 vesa_adp_info
= NULL
;
607 vesa_vmode
[0].vi_mode
= EOT
;
609 /* Allocate a buffer and add each page to the vm86 context. */
610 vesa_vm86_buf
= kmalloc(VESA_VM86_BUFSIZE
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
611 KASSERT(((vm_offset_t
)vesa_vm86_buf
& PAGE_MASK
) == 0,
612 ("bad vesa_vm86_buf alignment"));
613 for (i
= 0; i
< howmany(VESA_VM86_BUFSIZE
, PAGE_SIZE
); i
++)
614 vm86_addpage(&vesa_vmcontext
, i
+ 1,
615 (vm_offset_t
)vesa_vm86_buf
+ PAGE_SIZE
* i
);
617 vmbuf
= vesa_vm86_buf
;
618 bzero(&vmf
, sizeof(vmf
)); /* paranoia */
619 bcopy("VBE2", vmbuf
, 4); /* try for VBE2 data */
620 vmf
.vmf_eax
= 0x4f00;
621 vm86_getptr(&vesa_vmcontext
, (vm_offset_t
)vmbuf
, &vmf
.vmf_es
, &vmf
.vmf_di
);
623 err
= vm86_datacall(0x10, &vmf
, &vesa_vmcontext
);
624 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f) || bcmp("VESA", vmbuf
, 4))
626 bcopy(vmbuf
, buf
, sizeof(buf
));
627 vesa_adp_info
= (struct vesa_info
*)buf
;
629 kprintf("VESA: information block\n");
630 dump_buffer(buf
, 64);
632 if (vesa_adp_info
->v_version
< 0x0102) {
633 kprintf("VESA: VBE version %d.%d is not supported; "
634 "version 1.2 or later is required.\n",
635 bcd2bin((vesa_adp_info
->v_version
& 0xff00) >> 8),
636 bcd2bin(vesa_adp_info
->v_version
& 0x00ff));
640 /* fix string ptrs */
641 vesa_oemstr
= (char *)vesa_fix_ptr(vesa_adp_info
->v_oemstr
,
642 vmf
.vmf_es
, vmf
.vmf_di
, buf
);
643 is_via_cle266
= strcmp(vesa_oemstr
, VESA_VIA_CLE266
) == 0;
645 if (vesa_adp_info
->v_version
>= 0x0200) {
647 (char *)vesa_fix_ptr(vesa_adp_info
->v_vendorstr
,
648 vmf
.vmf_es
, vmf
.vmf_di
, buf
);
650 (char *)vesa_fix_ptr(vesa_adp_info
->v_prodstr
,
651 vmf
.vmf_es
, vmf
.vmf_di
, buf
);
653 (char *)vesa_fix_ptr(vesa_adp_info
->v_revstr
,
654 vmf
.vmf_es
, vmf
.vmf_di
, buf
);
657 /* obtain video mode information */
658 vesa_vmodetab
= (uint16_t *)vesa_fix_ptr(vesa_adp_info
->v_modetable
,
659 vmf
.vmf_es
, vmf
.vmf_di
, buf
);
660 if (vesa_vmodetab
== NULL
)
662 for (i
= 0, modes
= 0;
663 (i
< (M_VESA_MODE_MAX
- M_VESA_BASE
+ 1))
664 && (vesa_vmodetab
[i
] != 0xffff); ++i
) {
665 if (vesa_bios_get_mode(vesa_vmodetab
[i
], &vmode
))
668 /* reject unsupported modes */
669 if ((vmode
.v_modeattr
& (V_MODESUPP
| V_MODEOPTINFO
)) !=
670 (V_MODESUPP
| V_MODEOPTINFO
)) {
672 kprintf("Rejecting VESA %s mode: %d x %d x %d bpp attr = %x\n",
673 vmode
.v_modeattr
& V_MODEGRAPHICS
? "graphics" : "text",
674 vmode
.v_width
, vmode
.v_height
, vmode
.v_bpp
,
680 /* expand the array if necessary */
681 if (modes
>= vesa_vmode_max
) {
682 vesa_vmode_max
+= MODE_TABLE_DELTA
;
683 p
= kmalloc(sizeof(*vesa_vmode
)*(vesa_vmode_max
+ 1),
686 kprintf("vesa_bios_init(): modes:%d, vesa_mode_max:%d\n",
687 modes
, vesa_vmode_max
);
690 bcopy(vesa_vmode
, p
, sizeof(*vesa_vmode
)*modes
);
691 kfree(vesa_vmode
, M_DEVBUF
);
697 kprintf("Found VESA %s mode: %d x %d x %d bpp\n",
698 vmode
.v_modeattr
& V_MODEGRAPHICS
? "graphics" : "text",
699 vmode
.v_width
, vmode
.v_height
, vmode
.v_bpp
);
702 if ((vmode
.v_width
& 0xff00) >> 8 == vmode
.v_height
- 1) {
703 vmode
.v_width
&= 0xff;
704 vmode
.v_waseg
= 0xb8000 >> 4;
708 /* copy some fields */
709 bzero(&vesa_vmode
[modes
], sizeof(vesa_vmode
[modes
]));
710 vesa_vmode
[modes
].vi_mode
= vesa_vmodetab
[i
];
711 vesa_vmode
[modes
].vi_width
= vmode
.v_width
;
712 vesa_vmode
[modes
].vi_height
= vmode
.v_height
;
713 vesa_vmode
[modes
].vi_depth
= vmode
.v_bpp
;
714 vesa_vmode
[modes
].vi_planes
= vmode
.v_planes
;
715 vesa_vmode
[modes
].vi_cwidth
= vmode
.v_cwidth
;
716 vesa_vmode
[modes
].vi_cheight
= vmode
.v_cheight
;
717 vesa_vmode
[modes
].vi_window
= (u_int
)vmode
.v_waseg
<< 4;
719 vesa_vmode
[modes
].vi_window_size
= vmode
.v_wsize
*1024;
720 vesa_vmode
[modes
].vi_window_gran
= vmode
.v_wgran
*1024;
721 if (vmode
.v_modeattr
& V_MODELFB
)
722 vesa_vmode
[modes
].vi_buffer
= vmode
.v_lfb
;
724 vesa_vmode
[modes
].vi_buffer
= 0;
726 vesa_vmode
[modes
].vi_buffer_size
727 = vesa_adp_info
->v_memsize
*64*1024;
729 if (vmode
.v_offscreen
> vmode
.v_lfb
)
730 vesa_vmode
[modes
].vi_buffer_size
731 = vmode
.v_offscreen
+ vmode
.v_offscreensize
*1024
734 vesa_vmode
[modes
].vi_buffer_size
735 = vmode
.v_offscreen
+ vmode
.v_offscreensize
*1024
737 vesa_vmode
[modes
].vi_mem_model
738 = vesa_translate_mmodel(vmode
.v_memmodel
);
739 vesa_vmode
[modes
].vi_pixel_fields
[0] = 0;
740 vesa_vmode
[modes
].vi_pixel_fields
[1] = 0;
741 vesa_vmode
[modes
].vi_pixel_fields
[2] = 0;
742 vesa_vmode
[modes
].vi_pixel_fields
[3] = 0;
743 vesa_vmode
[modes
].vi_pixel_fsizes
[0] = 0;
744 vesa_vmode
[modes
].vi_pixel_fsizes
[1] = 0;
745 vesa_vmode
[modes
].vi_pixel_fsizes
[2] = 0;
746 vesa_vmode
[modes
].vi_pixel_fsizes
[3] = 0;
747 if (vesa_vmode
[modes
].vi_mem_model
== V_INFO_MM_PACKED
) {
748 vesa_vmode
[modes
].vi_pixel_size
= (vmode
.v_bpp
+ 7)/8;
749 } else if (vesa_vmode
[modes
].vi_mem_model
== V_INFO_MM_DIRECT
) {
750 vesa_vmode
[modes
].vi_pixel_size
= (vmode
.v_bpp
+ 7)/8;
751 vesa_vmode
[modes
].vi_pixel_fields
[0]
752 = vmode
.v_redfieldpos
;
753 vesa_vmode
[modes
].vi_pixel_fields
[1]
754 = vmode
.v_greenfieldpos
;
755 vesa_vmode
[modes
].vi_pixel_fields
[2]
756 = vmode
.v_bluefieldpos
;
757 vesa_vmode
[modes
].vi_pixel_fields
[3]
758 = vmode
.v_resfieldpos
;
759 vesa_vmode
[modes
].vi_pixel_fsizes
[0]
760 = vmode
.v_redmasksize
;
761 vesa_vmode
[modes
].vi_pixel_fsizes
[1]
762 = vmode
.v_greenmasksize
;
763 vesa_vmode
[modes
].vi_pixel_fsizes
[2]
764 = vmode
.v_bluemasksize
;
765 vesa_vmode
[modes
].vi_pixel_fsizes
[3]
766 = vmode
.v_resmasksize
;
768 vesa_vmode
[modes
].vi_pixel_size
= 0;
771 vesa_vmode
[modes
].vi_flags
772 = vesa_translate_flags(vmode
.v_modeattr
) | V_INFO_VESA
;
775 vesa_vmode
[modes
].vi_mode
= EOT
;
777 kprintf("VESA: %d mode(s) found\n", modes
);
779 has_vesa_bios
= (modes
> 0);
783 dpms_states
= vesa_probe_dpms();
784 if (dpms_states
!= 0 && bootverbose
)
785 kprintf("VESA: DPMS support (states:0x%x)\n", dpms_states
);
791 vesa_map_buffer(u_int paddr
, size_t size
)
796 off
= paddr
- trunc_page(paddr
);
797 vaddr
= (vm_offset_t
)pmap_mapdev(paddr
- off
, size
+ off
);
799 kprintf("vesa_map_buffer: paddr:%x vaddr:%x size:%x off:%x\n",
800 paddr
, vaddr
, size
, off
);
802 return (vaddr
+ off
);
806 vesa_unmap_buffer(vm_offset_t vaddr
, size_t size
)
809 kprintf("vesa_unmap_buffer: vaddr:%x size:%x\n", vaddr
, size
);
811 pmap_unmapdev(vaddr
, size
);
817 * Probe DPMS support and return the supported states.
821 vesa_probe_dpms(void)
823 struct vm86frame vmf
;
826 bzero(&vmf
, sizeof(vmf
));
827 vmf
.vmf_eax
= 0x4f10;
829 err
= vm86_intcall(0x10, &vmf
);
830 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
831 return -1; /* no support */
833 return (vmf
.vmf_ebx
>> 8);
839 vesa_configure(int flags
)
841 video_adapter_t
*adp
;
847 if (flags
& VIO_PROBE_ONLY
)
851 * If the VESA module has already been loaded, abort loading
852 * the module this time.
854 for (i
= 0; (adp
= vid_get_adapter(i
)) != NULL
; ++i
) {
855 if (adp
->va_flags
& V_ADP_VESA
)
857 if (adp
->va_type
== KD_VGA
)
861 * The VGA adapter is not found. This is because either
862 * 1) the VGA driver has not been initialized, or 2) the VGA card
863 * is not present. If 1) is the case, we shall defer
864 * initialization for now and try again later.
867 vga_sub_configure
= vesa_configure
;
871 /* count number of registered adapters */
872 for (++i
; vid_get_adapter(i
) != NULL
; ++i
)
878 if (vesa_bios_init()) {
882 vesa_adp
->va_flags
|= V_ADP_VESA
| V_ADP_COLOR
;
884 prevvidsw
= vidsw
[vesa_adp
->va_index
];
885 vidsw
[vesa_adp
->va_index
] = &vesavidsw
;
886 vesa_init_done
= TRUE
;
905 vesa_probe(int unit
, video_adapter_t
**adpp
, void *arg
, int flags
)
907 return (*prevvidsw
->probe
)(unit
, adpp
, arg
, flags
);
911 vesa_init(int unit
, video_adapter_t
*adp
, int flags
)
913 return (*prevvidsw
->init
)(unit
, adp
, flags
);
917 vesa_get_info(video_adapter_t
*adp
, int mode
, video_info_t
*info
)
921 if ((*prevvidsw
->get_info
)(adp
, mode
, info
) == 0)
927 for (i
= 0; vesa_vmode
[i
].vi_mode
!= EOT
; ++i
) {
928 if (vesa_vmode
[i
].vi_mode
== NA
)
930 if (vesa_vmode
[i
].vi_mode
== mode
) {
931 *info
= vesa_vmode
[i
];
939 vesa_query_mode(video_adapter_t
*adp
, video_info_t
*info
)
943 if ((*prevvidsw
->query_mode
)(adp
, info
) == 0)
948 for (i
= 0; vesa_vmode
[i
].vi_mode
!= EOT
; ++i
) {
949 if ((info
->vi_width
!= 0)
950 && (info
->vi_width
!= vesa_vmode
[i
].vi_width
))
952 if ((info
->vi_height
!= 0)
953 && (info
->vi_height
!= vesa_vmode
[i
].vi_height
))
955 if ((info
->vi_cwidth
!= 0)
956 && (info
->vi_cwidth
!= vesa_vmode
[i
].vi_cwidth
))
958 if ((info
->vi_cheight
!= 0)
959 && (info
->vi_cheight
!= vesa_vmode
[i
].vi_cheight
))
961 if ((info
->vi_depth
!= 0)
962 && (info
->vi_depth
!= vesa_vmode
[i
].vi_depth
))
964 if ((info
->vi_planes
!= 0)
965 && (info
->vi_planes
!= vesa_vmode
[i
].vi_planes
))
967 /* pixel format, memory model */
968 if ((info
->vi_flags
!= 0)
969 && (info
->vi_flags
!= vesa_vmode
[i
].vi_flags
))
971 *info
= vesa_vmode
[i
];
978 vesa_set_mode(video_adapter_t
*adp
, int mode
)
984 return (*prevvidsw
->set_mode
)(adp
, mode
);
987 kprintf("VESA: set_mode(): %d(%x) -> %d(%x)\n",
988 adp
->va_mode
, adp
->va_mode
, mode
, mode
);
991 * If the current mode is a VESA mode and the new mode is not,
992 * restore the state of the adapter first by setting one of the
993 * standard VGA mode, so that non-standard, extended SVGA registers
994 * are set to the state compatible with the standard VGA modes.
995 * Otherwise (*prevvidsw->set_mode)() may not be able to set up
996 * the new mode correctly.
998 if (VESA_MODE(adp
->va_mode
)) {
999 if ((*prevvidsw
->get_info
)(adp
, mode
, &info
) == 0) {
1000 int10_set_mode(adp
->va_initial_bios_mode
);
1001 if (adp
->va_info
.vi_flags
& V_INFO_LINEAR
)
1002 vesa_unmap_buffer(adp
->va_buffer
,
1003 vesa_adp_info
->v_memsize
*64*1024);
1005 * Once (*prevvidsw->get_info)() succeeded,
1006 * (*prevvidsw->set_mode)() below won't fail...
1011 /* we may not need to handle this mode after all... */
1012 if ((*prevvidsw
->set_mode
)(adp
, mode
) == 0)
1015 /* is the new mode supported? */
1016 if (vesa_get_info(adp
, mode
, &info
))
1018 /* assert(VESA_MODE(mode)); */
1021 kprintf("VESA: about to set a VESA mode...\n");
1023 /* don't use the linear frame buffer for text modes. XXX */
1024 if (!(info
.vi_flags
& V_INFO_GRAPHICS
))
1025 info
.vi_flags
&= ~V_INFO_LINEAR
;
1027 if (vesa_bios_set_mode(mode
| ((info
.vi_flags
& V_INFO_LINEAR
) ? 0x4000 : 0)))
1030 if (adp
->va_info
.vi_flags
& V_INFO_LINEAR
)
1031 vesa_unmap_buffer(adp
->va_buffer
,
1032 vesa_adp_info
->v_memsize
*64*1024);
1035 kprintf("VESA: mode set!\n");
1037 vesa_adp
->va_mode
= mode
;
1038 if (info
.vi_flags
& V_INFO_LINEAR
) {
1040 kprintf("VESA: setting up LFB\n");
1042 vesa_adp
->va_buffer
=
1043 vesa_map_buffer(info
.vi_buffer
,
1044 vesa_adp_info
->v_memsize
*64*1024);
1045 vesa_adp
->va_buffer_size
= info
.vi_buffer_size
;
1046 vesa_adp
->va_window
= vesa_adp
->va_buffer
;
1047 vesa_adp
->va_window_size
= info
.vi_buffer_size
/info
.vi_planes
;
1048 vesa_adp
->va_window_gran
= info
.vi_buffer_size
/info
.vi_planes
;
1050 vesa_adp
->va_buffer
= 0;
1051 vesa_adp
->va_buffer_size
= info
.vi_buffer_size
;
1052 vesa_adp
->va_window
= BIOS_PADDRTOVADDR(info
.vi_window
);
1053 vesa_adp
->va_window_size
= info
.vi_window_size
;
1054 vesa_adp
->va_window_gran
= info
.vi_window_gran
;
1056 vesa_adp
->va_window_orig
= 0;
1057 len
= vesa_bios_get_line_length();
1059 vesa_adp
->va_line_width
= len
;
1060 } else if (info
.vi_flags
& V_INFO_GRAPHICS
) {
1061 switch (info
.vi_depth
/info
.vi_planes
) {
1063 vesa_adp
->va_line_width
= info
.vi_width
/8;
1066 vesa_adp
->va_line_width
= info
.vi_width
/4;
1069 vesa_adp
->va_line_width
= info
.vi_width
/2;
1072 default: /* shouldn't happen */
1073 vesa_adp
->va_line_width
= info
.vi_width
;
1077 vesa_adp
->va_line_width
= info
.vi_width
;
1079 vesa_adp
->va_disp_start
.x
= 0;
1080 vesa_adp
->va_disp_start
.y
= 0;
1082 kprintf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n",
1083 info
.vi_width
, len
, vesa_adp
->va_line_width
);
1085 bcopy(&info
, &vesa_adp
->va_info
, sizeof(vesa_adp
->va_info
));
1087 /* move hardware cursor out of the way */
1088 (*vidsw
[vesa_adp
->va_index
]->set_hw_cursor
)(vesa_adp
, -1, -1);
1094 vesa_save_font(video_adapter_t
*adp
, int page
, int fontsize
, u_char
*data
,
1097 return (*prevvidsw
->save_font
)(adp
, page
, fontsize
, data
, ch
, count
);
1101 vesa_load_font(video_adapter_t
*adp
, int page
, int fontsize
, u_char
*data
,
1104 return (*prevvidsw
->load_font
)(adp
, page
, fontsize
, data
, ch
, count
);
1108 vesa_show_font(video_adapter_t
*adp
, int page
)
1110 return (*prevvidsw
->show_font
)(adp
, page
);
1114 vesa_save_palette(video_adapter_t
*adp
, u_char
*palette
)
1119 if ((adp
== vesa_adp
) && (vesa_adp_info
->v_flags
& V_DAC8
)
1120 && VESA_MODE(adp
->va_mode
)) {
1121 bits
= vesa_bios_get_dac();
1122 error
= vesa_bios_save_palette(0, 256, palette
, bits
);
1129 return (*prevvidsw
->save_palette
)(adp
, palette
);
1133 vesa_load_palette(video_adapter_t
*adp
, const u_char
*palette
)
1139 if ((adp
== vesa_adp
) && (vesa_adp_info
->v_flags
& V_DAC8
)
1140 && VESA_MODE(adp
->va_mode
) && ((bits
= vesa_bios_set_dac(8)) > 6)) {
1141 error
= vesa_bios_load_palette(0, 256, palette
, bits
);
1144 if (vesa_bios_set_dac(6) != 6)
1149 return (*prevvidsw
->load_palette
)(adp
, palette
);
1153 vesa_set_border(video_adapter_t
*adp
, int color
)
1155 return (*prevvidsw
->set_border
)(adp
, color
);
1159 vesa_save_state(video_adapter_t
*adp
, void *p
, size_t size
)
1161 if (adp
!= vesa_adp
)
1162 return (*prevvidsw
->save_state
)(adp
, p
, size
);
1164 if (vesa_state_buf_size
== 0)
1165 vesa_state_buf_size
= vesa_bios_state_buf_size();
1167 return (sizeof(int) + vesa_state_buf_size
);
1168 else if (size
< (sizeof(int) + vesa_state_buf_size
))
1171 ((adp_state_t
*)p
)->sig
= V_STATE_SIG
;
1172 bzero(((adp_state_t
*)p
)->regs
, vesa_state_buf_size
);
1173 return vesa_bios_save_restore(STATE_SAVE
, ((adp_state_t
*)p
)->regs
,
1174 vesa_state_buf_size
);
1178 vesa_load_state(video_adapter_t
*adp
, void *p
)
1180 if ((adp
!= vesa_adp
) || (((adp_state_t
*)p
)->sig
!= V_STATE_SIG
))
1181 return (*prevvidsw
->load_state
)(adp
, p
);
1183 return vesa_bios_save_restore(STATE_LOAD
, ((adp_state_t
*)p
)->regs
,
1184 vesa_state_buf_size
);
1189 vesa_get_origin(video_adapter_t
*adp
, off_t
*offset
)
1191 struct vm86frame vmf
;
1194 bzero(&vmf
, sizeof(vmf
));
1195 vmf
.vmf_eax
= 0x4f05;
1196 vmf
.vmf_ebx
= 0x10; /* WINDOW_A, XXX */
1197 err
= vm86_intcall(0x10, &vmf
);
1198 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
1200 *offset
= vmf
.vmf_dx
*adp
->va_window_gran
;
1206 vesa_set_origin(video_adapter_t
*adp
, off_t offset
)
1208 struct vm86frame vmf
;
1212 * This function should return as quickly as possible to
1213 * maintain good performance of the system. For this reason,
1214 * error checking is kept minimal and let the VESA BIOS to
1217 if (adp
!= vesa_adp
)
1218 return (*prevvidsw
->set_win_org
)(adp
, offset
);
1220 /* if this is a linear frame buffer, do nothing */
1221 if (adp
->va_info
.vi_flags
& V_INFO_LINEAR
)
1224 if (adp
->va_window_gran
== 0)
1227 bzero(&vmf
, sizeof(vmf
));
1228 vmf
.vmf_eax
= 0x4f05;
1229 vmf
.vmf_ebx
= 0; /* WINDOW_A, XXX */
1230 vmf
.vmf_edx
= offset
/adp
->va_window_gran
;
1231 err
= vm86_intcall(0x10, &vmf
);
1232 if ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f))
1234 bzero(&vmf
, sizeof(vmf
));
1235 vmf
.vmf_eax
= 0x4f05;
1236 vmf
.vmf_ebx
= 1; /* WINDOW_B, XXX */
1237 vmf
.vmf_edx
= offset
/adp
->va_window_gran
;
1238 err
= vm86_intcall(0x10, &vmf
);
1239 adp
->va_window_orig
= (offset
/adp
->va_window_gran
)*adp
->va_window_gran
;
1244 vesa_read_hw_cursor(video_adapter_t
*adp
, int *col
, int *row
)
1246 return (*prevvidsw
->read_hw_cursor
)(adp
, col
, row
);
1250 vesa_set_hw_cursor(video_adapter_t
*adp
, int col
, int row
)
1252 return (*prevvidsw
->set_hw_cursor
)(adp
, col
, row
);
1256 vesa_set_hw_cursor_shape(video_adapter_t
*adp
, int base
, int height
,
1257 int celsize
, int blink
)
1259 return (*prevvidsw
->set_hw_cursor_shape
)(adp
, base
, height
, celsize
,
1264 * vesa_blank_display
1266 * Use DPMS if it is supported by the adapter and supports the requested
1267 * state, else use the traditional VGA method. When unblanking, use both
1268 * methods because either might have put us into the blanked state previously.
1272 vesa_blank_display(video_adapter_t
*adp
, int mode
)
1274 struct vm86frame vmf
;
1277 if (mode
== V_DISPLAY_ON
) {
1278 err
= (*prevvidsw
->blank_display
)(adp
, V_DISPLAY_ON
);
1279 if (dpms_states
== 0) {
1282 bzero(&vmf
, sizeof(vmf
));
1283 vmf
.vmf_eax
= 0x4f10;
1285 err
= vm86_intcall(0x10, &vmf
);
1286 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
1288 } else if (dpms_states
& mode
) {
1289 bzero(&vmf
, sizeof(vmf
));
1290 vmf
.vmf_eax
= 0x4f10;
1291 vmf
.vmf_ebx
= (mode
<< 8) | 1;
1292 err
= vm86_intcall(0x10, &vmf
);
1293 return ((err
!= 0) || (vmf
.vmf_ax
!= 0x4f));
1296 return (*prevvidsw
->blank_display
)(adp
, mode
);
1300 vesa_mmap(video_adapter_t
*adp
, vm_offset_t offset
, int prot
)
1303 kprintf("vesa_mmap(): window:0x%x, buffer:0x%x, offset:0x%x\n",
1304 adp
->va_info
.vi_window
, adp
->va_info
.vi_buffer
, offset
);
1307 if ((adp
== vesa_adp
) && (adp
->va_info
.vi_flags
& V_INFO_LINEAR
)) {
1308 /* va_window_size == va_buffer_size/vi_planes */
1309 /* XXX: is this correct? */
1310 if (offset
> adp
->va_window_size
- PAGE_SIZE
)
1313 return i386_btop(adp
->va_info
.vi_buffer
+ offset
);
1316 return (*prevvidsw
->mmap
)(adp
, offset
, prot
);
1321 vesa_clear(video_adapter_t
*adp
)
1323 return (*prevvidsw
->clear
)(adp
);
1327 vesa_fill_rect(video_adapter_t
*adp
, int val
, int x
, int y
, int cx
, int cy
)
1329 return (*prevvidsw
->fill_rect
)(adp
, val
, x
, y
, cx
, cy
);
1333 vesa_bitblt(video_adapter_t
*adp
,...)
1340 get_palette(video_adapter_t
*adp
, int base
, int count
,
1341 u_char
*red
, u_char
*green
, u_char
*blue
, u_char
*trans
)
1349 if ((base
< 0) || (base
>= 256) || (count
< 0) || (count
> 256))
1351 if ((base
+ count
) > 256)
1353 if (!(vesa_adp_info
->v_flags
& V_DAC8
) || !VESA_MODE(adp
->va_mode
))
1356 bits
= vesa_bios_get_dac();
1360 r
= kmalloc(count
*3, M_DEVBUF
, M_WAITOK
);
1363 error
= vesa_bios_save_palette2(base
, count
, r
, g
, b
, bits
);
1365 copyout(r
, red
, count
);
1366 copyout(g
, green
, count
);
1367 copyout(b
, blue
, count
);
1368 if (trans
!= NULL
) {
1370 copyout(r
, trans
, count
);
1375 /* if error && bits != 6 at this point, we are in in trouble... XXX */
1380 set_palette(video_adapter_t
*adp
, int base
, int count
,
1381 u_char
*red
, u_char
*green
, u_char
*blue
, u_char
*trans
)
1391 if ((base
< 0) || (base
>= 256) || (base
+ count
> 256))
1393 if (!(vesa_adp_info
->v_flags
& V_DAC8
) || !VESA_MODE(adp
->va_mode
)
1394 || ((bits
= vesa_bios_set_dac(8)) <= 6))
1397 r
= kmalloc(count
*3, M_DEVBUF
, M_WAITOK
);
1400 copyin(red
, r
, count
);
1401 copyin(green
, g
, count
);
1402 copyin(blue
, b
, count
);
1404 error
= vesa_bios_load_palette2(base
, count
, r
, g
, b
, bits
);
1409 /* if the following call fails, we are in trouble... XXX */
1410 vesa_bios_set_dac(6);
1416 vesa_ioctl(video_adapter_t
*adp
, u_long cmd
, caddr_t arg
)
1420 if (adp
!= vesa_adp
)
1421 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1424 case FBIO_SETWINORG
: /* set frame buffer window origin */
1425 if (!VESA_MODE(adp
->va_mode
))
1426 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1427 return (vesa_set_origin(adp
, *(off_t
*)arg
) ? ENODEV
: 0);
1429 case FBIO_SETDISPSTART
: /* set display start address */
1430 if (!VESA_MODE(adp
->va_mode
))
1431 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1432 if (vesa_bios_set_start(((video_display_start_t
*)arg
)->x
,
1433 ((video_display_start_t
*)arg
)->y
))
1435 adp
->va_disp_start
.x
= ((video_display_start_t
*)arg
)->x
;
1436 adp
->va_disp_start
.y
= ((video_display_start_t
*)arg
)->y
;
1439 case FBIO_SETLINEWIDTH
: /* set line length in pixel */
1440 if (!VESA_MODE(adp
->va_mode
))
1441 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1442 if (vesa_bios_set_line_length(*(u_int
*)arg
, &bytes
, NULL
))
1444 adp
->va_line_width
= bytes
;
1446 kprintf("new line width:%d\n", adp
->va_line_width
);
1450 case FBIO_GETPALETTE
: /* get color palette */
1451 if (get_palette(adp
, ((video_color_palette_t
*)arg
)->index
,
1452 ((video_color_palette_t
*)arg
)->count
,
1453 ((video_color_palette_t
*)arg
)->red
,
1454 ((video_color_palette_t
*)arg
)->green
,
1455 ((video_color_palette_t
*)arg
)->blue
,
1456 ((video_color_palette_t
*)arg
)->transparent
))
1457 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1461 case FBIO_SETPALETTE
: /* set color palette */
1462 if (set_palette(adp
, ((video_color_palette_t
*)arg
)->index
,
1463 ((video_color_palette_t
*)arg
)->count
,
1464 ((video_color_palette_t
*)arg
)->red
,
1465 ((video_color_palette_t
*)arg
)->green
,
1466 ((video_color_palette_t
*)arg
)->blue
,
1467 ((video_color_palette_t
*)arg
)->transparent
))
1468 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1471 case FBIOGETCMAP
: /* get color palette */
1472 if (get_palette(adp
, ((struct fbcmap
*)arg
)->index
,
1473 ((struct fbcmap
*)arg
)->count
,
1474 ((struct fbcmap
*)arg
)->red
,
1475 ((struct fbcmap
*)arg
)->green
,
1476 ((struct fbcmap
*)arg
)->blue
, NULL
))
1477 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1480 case FBIOPUTCMAP
: /* set color palette */
1481 if (set_palette(adp
, ((struct fbcmap
*)arg
)->index
,
1482 ((struct fbcmap
*)arg
)->count
,
1483 ((struct fbcmap
*)arg
)->red
,
1484 ((struct fbcmap
*)arg
)->green
,
1485 ((struct fbcmap
*)arg
)->blue
, NULL
))
1486 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1490 return (*prevvidsw
->ioctl
)(adp
, cmd
, arg
);
1495 vesa_diag(video_adapter_t
*adp
, int level
)
1499 /* call the previous handler first */
1500 error
= (*prevvidsw
->diag
)(adp
, level
);
1504 if (adp
!= vesa_adp
)
1514 vesa_bios_info(int level
)
1517 struct vesa_mode vmode
;
1522 /* general adapter information */
1523 kprintf("VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n",
1524 bcd2bin((vesa_adp_info
->v_version
& 0xff00) >> 8),
1525 bcd2bin(vesa_adp_info
->v_version
& 0x00ff),
1526 vesa_adp_info
->v_memsize
* 64, vesa_adp_info
->v_flags
,
1527 vesa_vmodetab
, vesa_adp_info
->v_modetable
);
1530 if (vesa_oemstr
!= NULL
)
1531 kprintf("VESA: %s\n", vesa_oemstr
);
1537 if (vesa_adp_info
->v_version
>= 0x0200 && bootverbose
) {
1538 /* vendor name, product name, product revision */
1539 kprintf("VESA: %s %s %s\n",
1540 (vesa_vendorstr
!= NULL
) ? vesa_vendorstr
: "unknown",
1541 (vesa_prodstr
!= NULL
) ? vesa_prodstr
: "unknown",
1542 (vesa_revstr
!= NULL
) ? vesa_revstr
: "?");
1546 /* mode information */
1548 (i
< (M_VESA_MODE_MAX
- M_VESA_BASE
+ 1))
1549 && (vesa_vmodetab
[i
] != 0xffff); ++i
) {
1550 if (vesa_bios_get_mode(vesa_vmodetab
[i
], &vmode
))
1553 /* print something for diagnostic purpose */
1554 kprintf("VESA: mode:0x%03x, flags:0x%04x",
1555 vesa_vmodetab
[i
], vmode
.v_modeattr
);
1556 if (vmode
.v_modeattr
& V_MODEOPTINFO
) {
1557 if (vmode
.v_modeattr
& V_MODEGRAPHICS
) {
1558 kprintf(", G %dx%dx%d %d, ",
1559 vmode
.v_width
, vmode
.v_height
,
1560 vmode
.v_bpp
, vmode
.v_planes
);
1562 kprintf(", T %dx%d, ",
1563 vmode
.v_width
, vmode
.v_height
);
1565 kprintf("font:%dx%d, ",
1566 vmode
.v_cwidth
, vmode
.v_cheight
);
1567 kprintf("pages:%d, mem:%d",
1568 vmode
.v_ipages
+ 1, vmode
.v_memmodel
);
1570 if (vmode
.v_modeattr
& V_MODELFB
) {
1571 kprintf("\nVESA: LFB:0x%x, off:0x%x, off_size:0x%x",
1572 vmode
.v_lfb
, vmode
.v_offscreen
,
1573 vmode
.v_offscreensize
*1024);
1576 kprintf("VESA: window A:0x%x (%x), window B:0x%x (%x), ",
1577 vmode
.v_waseg
, vmode
.v_waattr
,
1578 vmode
.v_wbseg
, vmode
.v_wbattr
);
1579 kprintf("size:%dk, gran:%dk\n",
1580 vmode
.v_wsize
, vmode
.v_wgran
);
1582 #endif /* VESA_DEBUG > 1 */
1587 /* module loading */
1597 /* locate a VGA adapter */
1600 error
= vesa_configure(0);
1604 vesa_bios_info(bootverbose
);
1612 u_char palette
[256*3];
1615 /* if the adapter is currently in a VESA mode, don't unload */
1616 if ((vesa_adp
!= NULL
) && VESA_MODE(vesa_adp
->va_mode
))
1619 * FIXME: if there is at least one vty which is in a VESA mode,
1620 * we shouldn't be unloading! XXX
1624 if (vesa_adp
!= NULL
) {
1625 if (vesa_adp_info
->v_flags
& V_DAC8
) {
1626 bits
= vesa_bios_get_dac();
1628 vesa_bios_save_palette(0, 256, palette
, bits
);
1629 vesa_bios_set_dac(6);
1630 vesa_bios_load_palette(0, 256, palette
, 6);
1633 vesa_adp
->va_flags
&= ~V_ADP_VESA
;
1634 vidsw
[vesa_adp
->va_index
] = prevvidsw
;
1638 if (vesa_vm86_buf
!= NULL
)
1639 kfree(vesa_vm86_buf
, M_DEVBUF
);
1645 vesa_mod_event(module_t mod
, int type
, void *data
)
1651 return vesa_unload();
1658 static moduledata_t vesa_mod
= {
1664 DECLARE_MODULE(vesa
, vesa_mod
, SI_SUB_DRIVERS
, SI_ORDER_MIDDLE
);
1666 #endif /* VGA_NO_MODE_CHANGE */