2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * Copyright (c) 1992-1998 Søren Schmidt
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer as
11 * the first lines of this file unmodified.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * $FreeBSD: src/sys/dev/fb/vga.c,v 1.9.2.1 2001/08/11 02:58:44 yokota Exp $
30 * $DragonFly: src/sys/dev/video/fb/vga.c,v 1.25 2008/01/19 08:50:12 swildner Exp $
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
40 #include <sys/fcntl.h>
41 #include <sys/malloc.h>
43 #include <sys/thread2.h>
45 #include <bus/isa/isareg.h>
47 #include <machine/clock.h>
48 #include <machine/md_var.h>
49 #include <machine/pc/bios.h>
52 #include <vm/vm_param.h>
63 vga_probe_unit(int unit, video_adapter_t *buf, int flags)
69 sw = vid_get_switch(VGA_DRIVER_NAME);
72 error = (*sw->probe)(unit, &adp, NULL, flags);
75 bcopy(adp, buf, sizeof(*buf));
80 vga_attach_unit(int unit, vga_softc_t *sc, int flags)
85 sw = vid_get_switch(VGA_DRIVER_NAME);
89 error = (*sw->probe)(unit, &sc->adp, NULL, flags);
92 return (*sw->init)(unit, sc->adp, flags);
95 /* cdev driver functions */
97 #ifdef FB_INSTALL_CDEV
102 vga_open(cdev_t dev, vga_softc_t *sc, int flag, int mode, struct ucred *cred)
106 if (mode & (O_CREAT | O_APPEND | O_TRUNC))
109 return genfbopen(&sc->gensc, sc->adp, flag, mode, cred);
113 vga_close(cdev_t dev, vga_softc_t *sc, int flag, int mode)
115 return genfbclose(&sc->gensc, sc->adp, flag, mode);
119 vga_read(cdev_t dev, vga_softc_t *sc, struct uio *uio, int flag)
121 return genfbread(&sc->gensc, sc->adp, uio, flag);
125 vga_write(cdev_t dev, vga_softc_t *sc, struct uio *uio, int flag)
127 return genfbread(&sc->gensc, sc->adp, uio, flag);
131 vga_ioctl(cdev_t dev, vga_softc_t *sc, u_long cmd, caddr_t arg, int flag,
134 return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, cred);
138 vga_mmap(cdev_t dev, vga_softc_t *sc, vm_offset_t offset, int prot)
140 return genfbmmap(&sc->gensc, sc->adp, offset, prot);
143 #endif /* FB_INSTALL_CDEV */
147 #define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
148 #define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
149 #define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
152 #define V_MODE_MAP_SIZE (M_VGA_CG320 + 1)
153 #define V_MODE_PARAM_SIZE 64
155 /* video adapter state buffer */
158 #define V_STATE_SIG 0x736f6962
159 u_char regs[V_MODE_PARAM_SIZE];
161 typedef struct adp_state adp_state_t;
164 * NOTE: `va_window' should have a virtual address, but is initialized
165 * with a physical address in the following table, as verify_adapter()
166 * will perform address conversion at run-time.
168 static video_adapter_t biosadapter = {
169 0, KD_VGA, VGA_DRIVER_NAME, 0, 0, V_ADP_COLOR, IO_VGA, 32,
170 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
171 0, 0, 0, M_VGA_C80x25, M_C80x25, M_VGA_C80x25
174 /* video driver declarations */
175 static int vga_configure(int flags);
176 int (*vga_sub_configure)(int flags);
178 static int vga_nop(void);
180 static int vga_error(void);
181 static vi_probe_t vga_probe;
182 static vi_init_t vga_init;
183 static vi_get_info_t vga_get_info;
184 static vi_query_mode_t vga_query_mode;
185 static vi_set_mode_t vga_set_mode;
186 static vi_save_font_t vga_save_font;
187 static vi_load_font_t vga_load_font;
188 static vi_show_font_t vga_show_font;
189 static vi_save_palette_t vga_save_palette;
190 static vi_load_palette_t vga_load_palette;
191 static vi_set_border_t vga_set_border;
192 static vi_save_state_t vga_save_state;
193 static vi_load_state_t vga_load_state;
194 static vi_set_win_org_t vga_set_origin;
195 static vi_read_hw_cursor_t vga_read_hw_cursor;
196 static vi_set_hw_cursor_t vga_set_hw_cursor;
197 static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape;
198 static vi_blank_display_t vga_blank_display;
199 static vi_mmap_t vga_mmap_buf;
200 static vi_ioctl_t vga_dev_ioctl;
201 #ifndef VGA_NO_MODE_CHANGE
202 static vi_clear_t vga_clear;
203 static vi_fill_rect_t vga_fill_rect;
204 static vi_bitblt_t vga_bitblt;
205 #else /* VGA_NO_MODE_CHANGE */
206 #define vga_clear (vi_clear_t *)vga_error
207 #define vga_fill_rect (vi_fill_rect_t *)vga_error
208 #define vga_bitblt (vi_bitblt_t *)vga_error
210 static vi_diag_t vga_diag;
212 static video_switch_t vgavidsw = {
229 vga_set_hw_cursor_shape,
241 VIDEO_DRIVER(vga, vgavidsw, vga_configure);
243 /* VGA BIOS standard video modes */
247 static video_info_t bios_vmode[] = {
249 { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1,
250 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
251 { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1,
252 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
253 { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1,
254 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
255 { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1,
256 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
258 { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1,
259 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
260 { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1,
261 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
262 { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1,
263 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
264 { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1,
265 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
267 { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1,
268 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
269 { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1,
270 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
271 { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
272 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
274 { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1,
275 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
277 { M_ENH_B80x43, 0, 80, 43, 8, 8, 2, 1,
278 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
279 { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1,
280 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
282 { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1,
283 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
284 { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
285 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
286 { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1,
287 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
288 { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1,
289 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
290 { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1,
291 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
292 { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1,
293 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
295 #ifndef VGA_NO_MODE_CHANGE
298 { M_VGA_M90x25, 0, 90, 25, 8, 16, 2, 1,
299 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
300 { M_VGA_C90x25, V_INFO_COLOR, 90, 25, 8, 16, 4, 1,
301 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
302 { M_VGA_M90x30, 0, 90, 30, 8, 16, 2, 1,
303 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
304 { M_VGA_C90x30, V_INFO_COLOR, 90, 30, 8, 16, 4, 1,
305 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
306 { M_VGA_M90x43, 0, 90, 43, 8, 8, 2, 1,
307 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
308 { M_VGA_C90x43, V_INFO_COLOR, 90, 43, 8, 8, 4, 1,
309 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
310 { M_VGA_M90x50, 0, 90, 50, 8, 8, 2, 1,
311 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
312 { M_VGA_C90x50, V_INFO_COLOR, 90, 50, 8, 8, 4, 1,
313 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
314 { M_VGA_M90x60, 0, 90, 60, 8, 8, 2, 1,
315 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
316 { M_VGA_C90x60, V_INFO_COLOR, 90, 60, 8, 8, 4, 1,
317 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
318 #endif /* VGA_WIDTH90 */
321 { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
322 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
323 { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
324 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
325 { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1,
326 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
328 { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4,
329 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
331 { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4,
332 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
334 { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
335 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 ,
337 { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
338 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
340 { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2,
341 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
343 { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
344 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
347 { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
348 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
350 { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
351 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
353 { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1,
354 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
355 V_INFO_MM_PACKED, 1 },
356 { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 4,
357 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
359 #endif /* VGA_NO_MODE_CHANGE */
364 static int vga_init_done = FALSE;
365 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
366 static u_char *video_mode_ptr = NULL;
368 static u_char *mode_map[V_MODE_MAP_SIZE];
369 static adp_state_t adpstate;
370 static adp_state_t adpstate2;
371 static int rows_offset = 1;
373 /* local macros and functions */
374 #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
376 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
377 static void map_mode_table(u_char **, u_char *, int);
379 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
380 static int map_mode_num(int);
382 static int map_bios_mode_num(int);
383 static u_char *get_mode_param(int);
384 static int verify_adapter(video_adapter_t *);
385 static void update_adapter_info(video_adapter_t *, video_info_t *);
386 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
387 #define COMP_IDENTICAL 0
388 #define COMP_SIMILAR 1
389 #define COMP_DIFFERENT 2
390 static int comp_adpregs(u_char *, u_char *);
392 static int probe_adapters(void);
393 static int set_line_length(video_adapter_t *, int);
394 static int set_display_start(video_adapter_t *, int, int);
396 #ifndef VGA_NO_MODE_CHANGE
398 static void set_width90(adp_state_t *);
400 #endif /* !VGA_NO_MODE_CHANGE */
402 #ifndef VGA_NO_FONT_LOADING
403 #define PARAM_BUFSIZE 6
404 static void set_font_mode(video_adapter_t *, u_char *);
405 static void set_normal_mode(video_adapter_t *, u_char *);
408 #ifndef VGA_NO_MODE_CHANGE
409 static void filll_io(int, vm_offset_t, size_t);
410 static void planar_fill(video_adapter_t *, int);
411 static void packed_fill(video_adapter_t *, int);
412 static void direct_fill(video_adapter_t *, int);
414 static void planar_fill_rect(video_adapter_t *, int, int, int, int, int);
415 static void packed_fill_rect(video_adapter_t *, int, int, int, int, int);
416 static void direct_fill_rect16(video_adapter_t *, int, int, int, int, int);
417 static void direct_fill_rect24(video_adapter_t *, int, int, int, int, int);
418 static void direct_fill_rect32(video_adapter_t *, int, int, int, int, int);
420 #endif /* !VGA_NO_MODE_CHANGE */
422 static void dump_buffer(u_char *, size_t);
424 #define ISMAPPED(pa, width) \
425 (((pa) <= (u_long)0x1000 - (width)) \
426 || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width)))
428 #define prologue(adp, flag, err) \
429 if (!vga_init_done || !((adp)->va_flags & (flag))) \
432 /* a backdoor for the console driver */
434 vga_configure(int flags)
437 if (probe_done(&biosadapter)) {
438 biosadapter.va_flags |= V_ADP_INITIALIZED;
439 if (!config_done(&biosadapter) && !(vid_register(&biosadapter) < 0))
440 biosadapter.va_flags |= V_ADP_REGISTERED;
442 if (vga_sub_configure != NULL)
443 (*vga_sub_configure)(flags);
448 /* local subroutines */
450 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
451 /* construct the mode parameter map */
453 map_mode_table(u_char *map[], u_char *table, int max)
457 for(i = 0; i < max; ++i)
458 map[i] = table + i*V_MODE_PARAM_SIZE;
459 for(; i < V_MODE_MAP_SIZE; ++i)
462 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
464 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
465 /* map the non-standard video mode to a known mode number */
467 map_mode_num(int mode)
473 { M_ENH_B80x43, M_ENH_B80x25 },
474 { M_ENH_C80x43, M_ENH_C80x25 },
475 { M_VGA_M80x30, M_VGA_M80x25 },
476 { M_VGA_C80x30, M_VGA_C80x25 },
477 { M_VGA_M80x50, M_VGA_M80x25 },
478 { M_VGA_C80x50, M_VGA_C80x25 },
479 { M_VGA_M80x60, M_VGA_M80x25 },
480 { M_VGA_C80x60, M_VGA_C80x25 },
482 { M_VGA_M90x25, M_VGA_M80x25 },
483 { M_VGA_C90x25, M_VGA_C80x25 },
484 { M_VGA_M90x30, M_VGA_M80x25 },
485 { M_VGA_C90x30, M_VGA_C80x25 },
486 { M_VGA_M90x43, M_ENH_B80x25 },
487 { M_VGA_C90x43, M_ENH_C80x25 },
488 { M_VGA_M90x50, M_VGA_M80x25 },
489 { M_VGA_C90x50, M_VGA_C80x25 },
490 { M_VGA_M90x60, M_VGA_M80x25 },
491 { M_VGA_C90x60, M_VGA_C80x25 },
493 { M_VGA_MODEX, M_VGA_CG320 },
497 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
498 if (mode_map[i].from == mode)
499 return mode_map[i].to;
503 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
505 /* turn the BIOS video number into our video mode number */
507 map_bios_mode_num(int bios_mode)
509 static int vga_modes[20] = {
510 M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */
511 M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */
514 M_VGA_M80x25, /* 7 */
520 M_BG640x480, M_CG640x480,
524 if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
525 return vga_modes[bios_mode];
530 /* look up a parameter table entry */
532 get_mode_param(int mode)
534 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
535 if (mode >= V_MODE_MAP_SIZE)
536 mode = map_mode_num(mode);
538 if ((mode >= 0) && (mode < V_MODE_MAP_SIZE))
539 return mode_map[mode];
545 verify_adapter(video_adapter_t *adp)
549 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
553 buf = BIOS_PADDRTOVADDR(adp->va_window);
556 if (readw(buf) != 0xA55A)
564 adp->va_flags |= V_ADP_STATELOAD | V_ADP_STATESAVE | V_ADP_PALETTE |
567 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
568 /* get the BIOS video mode pointer */
569 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
570 p = BIOS_SADDRTOLADDR(p);
571 if (ISMAPPED(p, sizeof(u_int32_t))) {
572 p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
573 p = BIOS_SADDRTOLADDR(p);
574 if (ISMAPPED(p, V_MODE_PARAM_SIZE))
575 video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
583 update_adapter_info(video_adapter_t *adp, video_info_t *info)
585 adp->va_flags |= V_ADP_COLOR;
586 adp->va_window = BIOS_PADDRTOVADDR(info->vi_window);
587 adp->va_window_size = info->vi_window_size;
588 adp->va_window_gran = info->vi_window_gran;
589 adp->va_window_orig = 0;
591 adp->va_buffer = info->vi_buffer;
592 adp->va_buffer_size = info->vi_buffer_size;
593 if (info->vi_mem_model == V_INFO_MM_VGAX) {
594 adp->va_line_width = info->vi_width/2;
595 } else if (info->vi_flags & V_INFO_GRAPHICS) {
596 switch (info->vi_depth/info->vi_planes) {
598 adp->va_line_width = info->vi_width/8;
601 adp->va_line_width = info->vi_width/4;
604 adp->va_line_width = info->vi_width/2;
607 default: /* shouldn't happen */
608 adp->va_line_width = info->vi_width;
612 adp->va_line_width = info->vi_width;
614 adp->va_disp_start.x = 0;
615 adp->va_disp_start.y = 0;
616 bcopy(info, &adp->va_info, sizeof(adp->va_info));
619 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
620 /* compare two parameter table entries */
622 comp_adpregs(u_char *buf1, u_char *buf2)
626 } params[V_MODE_PARAM_SIZE] = {
627 {0xff}, {0x00}, {0xff}, /* COLS}, ROWS}, POINTS */
628 {0x00}, {0x00}, /* page length */
629 {0xfe}, {0xff}, {0xff}, {0xff}, /* sequencer registers */
630 {0xf3}, /* misc register */
631 {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, /* CRTC */
632 {0xff}, {0xff}, {0xff}, {0x7f}, {0xff},
633 {0x00}, {0x00}, {0x00}, {0x00}, {0x00},
634 {0x00}, {0xff}, {0x7f}, {0xff}, {0xff},
635 {0x7f}, {0xff}, {0xff}, {0xef}, {0xff},
636 {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* attribute controller regs */
637 {0xff}, {0xff}, {0xff}, {0xff}, {0xff},
638 {0xff}, {0xff}, {0xff}, {0xff}, {0xff},
639 {0xff}, {0xff}, {0xff}, {0xff}, {0xf0},
640 {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* GDC register */
641 {0xff}, {0xff}, {0xff}, {0xff},
643 int identical = TRUE;
646 if ((buf1 == NULL) || (buf2 == NULL))
647 return COMP_DIFFERENT;
649 for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
650 if (params[i].mask == 0) /* don't care */
652 if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
653 return COMP_DIFFERENT;
654 if (buf1[i] != buf2[i])
657 return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
659 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
661 /* probe video adapters and return the number of detected adapters */
665 video_adapter_t *adp;
667 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
672 /* do this test only once */
675 vga_init_done = TRUE;
678 * Check BIOS data area.
679 * The VGA BIOS has more sophisticated mechanism and has this
680 * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains
681 * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
685 * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead
686 * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are
687 * zeros for VGA. However, VGA BIOS sets these bits in
688 * BIOSDATA_EQUIPMENT according to the monitor type detected.
691 if ((readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f) != 0x09)
693 #endif /* VGA_NO_BIOS */
695 if (verify_adapter(&biosadapter) != 0)
698 biosadapter.va_flags |= V_ADP_PROBED;
700 biosadapter.va_initial_bios_mode = readb(BIOS_PADDRTOVADDR(0x449));
701 biosadapter.va_mode = biosadapter.va_initial_mode =
702 map_bios_mode_num(biosadapter.va_initial_bios_mode);
706 * Ensure a zero start address. This is mainly to recover after
707 * switching from pcvt using userconfig(). The registers are w/o
708 * for old hardware so it's too hard to relocate the active screen
710 * This must be done before vga_save_state() for VGA.
717 /* the video mode parameter table in VGA BIOS */
718 /* NOTE: there can be only one VGA recognized by the video BIOS.
721 bzero(mode_map, sizeof(mode_map));
722 vga_save_state(adp, &adpstate, sizeof(adpstate));
723 for(i = 0; i < 16; i++)
724 adp->va_palette_regs[i] = adpstate.regs[35 + i];
725 #if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
726 mode_map[adp->va_initial_mode] = adpstate.regs;
728 #else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
729 if (video_mode_ptr == NULL) {
730 mode_map[adp->va_initial_mode] = adpstate.regs;
733 /* discard the table if we are not familiar with it... */
734 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
735 mp = get_mode_param(adp->va_initial_mode);
737 bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
738 switch (comp_adpregs(adpstate.regs, mp)) {
741 * OK, this parameter table looks reasonably familiar
745 * This is a kludge for Toshiba DynaBook SS433
746 * whose BIOS video mode table entry has the actual #
747 * of rows at the offset 1; BIOSes from other
748 * manufacturers store the # of rows - 1 there. XXX
750 rows_offset = adpstate.regs[1] + 1 - mp[1];
755 * Not exactly the same, but similar enough to be
756 * trusted. However, use the saved register values
757 * for the initial mode and other modes which are
758 * based on the initial mode.
760 mode_map[adp->va_initial_mode] = adpstate.regs;
761 rows_offset = adpstate.regs[1] + 1 - mp[1];
762 adpstate.regs[1] -= rows_offset - 1;
768 * Don't use the paramter table in BIOS. It doesn't
769 * look familiar to us. Video mode switching is allowed
770 * only if the new mode is the same as or based on
773 video_mode_ptr = NULL;
774 bzero(mode_map, sizeof(mode_map));
775 mode_map[adp->va_initial_mode] = adpstate.regs;
780 #endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
782 #ifndef VGA_NO_MODE_CHANGE
783 adp->va_flags |= V_ADP_MODECHANGE;
785 #ifndef VGA_NO_FONT_LOADING
786 adp->va_flags |= V_ADP_FONT;
789 /* XXX remove conflicting modes */
790 for (i = 0; i < M_VGA_CG320; i++) {
791 if (vga_get_info(&biosadapter, i, &info))
793 if ((info.vi_flags & V_INFO_COLOR) != V_ADP_COLOR)
798 vga_get_info(&biosadapter, biosadapter.va_initial_mode, &info);
799 info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
800 update_adapter_info(&biosadapter, &info);
803 * XXX: we should verify the following values for the primary adapter...
804 * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
805 * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02)
807 * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
808 * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
809 * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
810 * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
816 /* set the scan line length in pixel */
818 set_line_length(video_adapter_t *adp, int pixel)
821 int ppw; /* pixels per word */
822 int bpl; /* bytes per line */
825 mp = get_mode_param(adp->va_mode);
829 switch (adp->va_info.vi_mem_model) {
830 case V_INFO_MM_PLANAR:
831 ppw = 16/(adp->va_info.vi_depth/adp->va_info.vi_planes);
832 count = (pixel + ppw - 1)/ppw/2;
833 bpl = ((pixel + ppw - 1)/ppw/2)*4;
835 case V_INFO_MM_PACKED:
836 count = (pixel + 7)/8;
837 bpl = ((pixel + 7)/8)*8;
840 count = (pixel + 7)/8; /* columns */
841 bpl = (pixel + 7)/8; /* columns */
847 if (mp[10 + 0x17] & 0x40) /* CRTC mode control reg */
848 count *= 2; /* byte mode */
851 adp->va_line_width = bpl;
857 set_display_start(video_adapter_t *adp, int x, int y)
859 int off; /* byte offset (graphics mode)/word offset (text mode) */
860 int poff; /* pixel offset */
861 int roff; /* row offset */
862 int ppb; /* pixels per byte */
864 if (adp->va_info.vi_flags & V_INFO_GRAPHICS) {
865 ppb = 8/(adp->va_info.vi_depth/adp->va_info.vi_planes);
866 off = y*adp->va_line_width + x/ppb;
875 off = y/adp->va_info.vi_cheight*adp->va_line_width + x/ppb;
876 roff = y%adp->va_info.vi_cheight;
877 /* FIXME: is this correct? XXX */
885 outb(CRTC, 0xc); /* high */
886 outb(CRTC + 1, off >> 8);
887 outb(CRTC, 0xd); /* low */
888 outb(CRTC + 1, off & 0xff);
890 /* horizontal pel pan */
892 outb(ATC, 0x13 | 0x20);
897 /* preset raw scan */
899 outb(CRTC + 1, roff);
901 adp->va_disp_start.x = x;
902 adp->va_disp_start.y = y;
906 #ifndef VGA_NO_MODE_CHANGE
907 #ifdef __i386__ /* XXX */
909 fill(int val, void *d, size_t size)
916 #endif /* __i386__ */
919 filll_io(int val, vm_offset_t d, size_t size)
923 d += sizeof(u_int32_t);
926 #endif /* !VGA_NO_MODE_CHANGE */
945 vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
951 *adpp = &biosadapter;
957 vga_init(int unit, video_adapter_t *adp, int flags)
959 if ((unit != 0) || (adp == NULL) || !probe_done(adp))
962 if (!init_done(adp)) {
963 /* nothing to do really... */
964 adp->va_flags |= V_ADP_INITIALIZED;
967 if (!config_done(adp)) {
968 if (vid_register(adp) < 0)
970 adp->va_flags |= V_ADP_REGISTERED;
972 if (vga_sub_configure != NULL)
973 (*vga_sub_configure)(0);
980 * Return the video_info structure of the requested video mode.
983 vga_get_info(video_adapter_t *adp, int mode, video_info_t *info)
990 #ifndef VGA_NO_MODE_CHANGE
991 if (adp->va_flags & V_ADP_MODECHANGE) {
993 * If the parameter table entry for this mode is not found,
994 * the mode is not supported...
996 if (get_mode_param(mode) == NULL)
999 #endif /* VGA_NO_MODE_CHANGE */
1002 * Even if we don't support video mode switching on this adapter,
1003 * the information on the initial (thus current) video mode
1004 * should be made available.
1006 if (mode != adp->va_initial_mode)
1010 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1011 if (bios_vmode[i].vi_mode == NA)
1013 if (mode == bios_vmode[i].vi_mode) {
1014 *info = bios_vmode[i];
1016 info->vi_buffer_size = info->vi_window_size*info->vi_planes;
1025 * Find a video mode matching the requested parameters.
1026 * Fields filled with 0 are considered "don't care" fields and
1030 vga_query_mode(video_adapter_t *adp, video_info_t *info)
1037 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1038 if (bios_vmode[i].vi_mode == NA)
1041 if ((info->vi_width != 0)
1042 && (info->vi_width != bios_vmode[i].vi_width))
1044 if ((info->vi_height != 0)
1045 && (info->vi_height != bios_vmode[i].vi_height))
1047 if ((info->vi_cwidth != 0)
1048 && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
1050 if ((info->vi_cheight != 0)
1051 && (info->vi_cheight != bios_vmode[i].vi_cheight))
1053 if ((info->vi_depth != 0)
1054 && (info->vi_depth != bios_vmode[i].vi_depth))
1056 if ((info->vi_planes != 0)
1057 && (info->vi_planes != bios_vmode[i].vi_planes))
1059 /* XXX: should check pixel format, memory model */
1060 if ((info->vi_flags != 0)
1061 && (info->vi_flags != bios_vmode[i].vi_flags))
1064 /* verify if this mode is supported on this adapter */
1065 if (vga_get_info(adp, bios_vmode[i].vi_mode, info))
1074 * Change the video mode.
1077 #ifndef VGA_NO_MODE_CHANGE
1080 set_width90(adp_state_t *params)
1083 * Based on code submitted by Kelly Yancey (kbyanc@freedomnet.com)
1084 * and alexv@sui.gda.itesm.mx.
1086 params->regs[5] |= 1; /* toggle 8 pixel wide fonts */
1087 params->regs[10+0x0] = 0x6b;
1088 params->regs[10+0x1] = 0x59;
1089 params->regs[10+0x2] = 0x5a;
1090 params->regs[10+0x3] = 0x8e;
1091 params->regs[10+0x4] = 0x5e;
1092 params->regs[10+0x5] = 0x8a;
1093 params->regs[10+0x13] = 45;
1094 params->regs[35+0x13] = 0;
1096 #endif /* VGA_WIDTH90 */
1097 #endif /* !VGA_NO_MODE_CHANGE */
1100 vga_set_mode(video_adapter_t *adp, int mode)
1102 #ifndef VGA_NO_MODE_CHANGE
1106 prologue(adp, V_ADP_MODECHANGE, ENODEV);
1108 if (vga_get_info(adp, mode, &info))
1112 kprintf("vga_set_mode(): setting mode %d\n", mode);
1115 params.sig = V_STATE_SIG;
1116 bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
1120 case M_VGA_C90x60: case M_VGA_M90x60:
1121 set_width90(¶ms);
1124 case M_VGA_C80x60: case M_VGA_M80x60:
1125 params.regs[2] = 0x08;
1126 params.regs[19] = 0x47;
1130 case M_VGA_C90x30: case M_VGA_M90x30:
1131 set_width90(¶ms);
1134 case M_VGA_C80x30: case M_VGA_M80x30:
1135 params.regs[19] = 0x4f;
1137 params.regs[9] |= 0xc0;
1138 params.regs[16] = 0x08;
1139 params.regs[17] = 0x3e;
1140 params.regs[26] = 0xea;
1141 params.regs[28] = 0xdf;
1142 params.regs[31] = 0xe7;
1143 params.regs[32] = 0x04;
1147 case M_VGA_C90x43: case M_VGA_M90x43:
1148 set_width90(¶ms);
1151 case M_ENH_C80x43: case M_ENH_B80x43:
1152 params.regs[28] = 87;
1156 case M_VGA_C90x50: case M_VGA_M90x50:
1157 set_width90(¶ms);
1160 case M_VGA_C80x50: case M_VGA_M80x50:
1163 params.regs[19] = 7;
1167 case M_VGA_C90x25: case M_VGA_M90x25:
1168 set_width90(¶ms);
1171 case M_VGA_C40x25: case M_VGA_C80x25:
1173 case M_B40x25: case M_C40x25:
1174 case M_B80x25: case M_C80x25:
1175 case M_ENH_B40x25: case M_ENH_C40x25:
1176 case M_ENH_B80x25: case M_ENH_C80x25:
1177 case M_EGAMONO80x25:
1180 vga_load_state(adp, ¶ms);
1184 /* "unchain" the VGA mode */
1185 params.regs[5-1+0x04] &= 0xf7;
1186 params.regs[5-1+0x04] |= 0x04;
1187 /* turn off doubleword mode */
1188 params.regs[10+0x14] &= 0xbf;
1189 /* turn off word addressing */
1190 params.regs[10+0x17] |= 0x40;
1191 /* set logical screen width */
1192 params.regs[10+0x13] = 80;
1194 params.regs[10+0x11] = 0x2c;
1195 params.regs[10+0x06] = 0x0d;
1196 params.regs[10+0x07] = 0x3e;
1197 params.regs[10+0x10] = 0xea;
1198 params.regs[10+0x11] = 0xac;
1199 params.regs[10+0x12] = 0xdf;
1200 params.regs[10+0x15] = 0xe7;
1201 params.regs[10+0x16] = 0x06;
1202 /* set vertical sync polarity to reflect aspect ratio */
1203 params.regs[9] = 0xe3;
1206 case M_BG320: case M_CG320: case M_BG640:
1207 case M_CG320_D: case M_CG640_E:
1208 case M_CG640x350: case M_ENH_CG640:
1209 case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
1212 vga_load_state(adp, ¶ms);
1219 adp->va_mode = mode;
1220 info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
1221 update_adapter_info(adp, &info);
1223 /* move hardware cursor out of the way */
1224 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
1227 #else /* VGA_NO_MODE_CHANGE */
1229 #endif /* VGA_NO_MODE_CHANGE */
1232 #ifndef VGA_NO_FONT_LOADING
1235 set_font_mode(video_adapter_t *adp, u_char *buf)
1239 /* save register values */
1240 outb(TSIDX, 0x02); buf[0] = inb(TSREG);
1241 outb(TSIDX, 0x04); buf[1] = inb(TSREG);
1242 outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
1243 outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
1244 outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
1246 outb(ATC, 0x10); buf[5] = inb(ATC + 1);
1248 /* setup vga for loading fonts */
1249 inb(CRTC + 6); /* reset flip-flop */
1250 outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
1251 inb(CRTC + 6); /* reset flip-flop */
1252 outb(ATC, 0x20); /* enable palette */
1254 #if VGA_SLOW_IOACCESS
1255 #ifdef VGA_ALT_SEQACCESS
1256 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1258 outb(TSIDX, 0x02); outb(TSREG, 0x04);
1259 outb(TSIDX, 0x04); outb(TSREG, 0x07);
1260 #ifdef VGA_ALT_SEQACCESS
1261 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1263 outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
1264 outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
1265 outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
1266 #else /* VGA_SLOW_IOACCESS */
1267 #ifdef VGA_ALT_SEQACCESS
1268 outw(TSIDX, 0x0100);
1270 outw(TSIDX, 0x0402);
1271 outw(TSIDX, 0x0704);
1272 #ifdef VGA_ALT_SEQACCESS
1273 outw(TSIDX, 0x0300);
1275 outw(GDCIDX, 0x0204);
1276 outw(GDCIDX, 0x0005);
1277 outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */
1278 #endif /* VGA_SLOW_IOACCESS */
1284 set_normal_mode(video_adapter_t *adp, u_char *buf)
1288 /* setup vga for normal operation mode again */
1289 inb(CRTC + 6); /* reset flip-flop */
1290 outb(ATC, 0x10); outb(ATC, buf[5]);
1291 inb(CRTC + 6); /* reset flip-flop */
1292 outb(ATC, 0x20); /* enable palette */
1294 #if VGA_SLOW_IOACCESS
1295 #ifdef VGA_ALT_SEQACCESS
1296 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1298 outb(TSIDX, 0x02); outb(TSREG, buf[0]);
1299 outb(TSIDX, 0x04); outb(TSREG, buf[1]);
1300 #ifdef VGA_ALT_SEQACCESS
1301 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1303 outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
1304 outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
1305 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
1306 #else /* VGA_SLOW_IOACCESS */
1307 #ifdef VGA_ALT_SEQACCESS
1308 outw(TSIDX, 0x0100);
1310 outw(TSIDX, 0x0002 | (buf[0] << 8));
1311 outw(TSIDX, 0x0004 | (buf[1] << 8));
1312 #ifdef VGA_ALT_SEQACCESS
1313 outw(TSIDX, 0x0300);
1315 outw(GDCIDX, 0x0004 | (buf[2] << 8));
1316 outw(GDCIDX, 0x0005 | (buf[3] << 8));
1317 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
1318 #endif /* VGA_SLOW_IOACCESS */
1323 #endif /* VGA_NO_FONT_LOADING */
1327 * Read the font data in the requested font page from the video adapter.
1330 vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1333 #ifndef VGA_NO_FONT_LOADING
1334 u_char buf[PARAM_BUFSIZE];
1337 #ifdef VGA_ALT_SEQACCESS
1341 prologue(adp, V_ADP_FONT, ENODEV);
1343 if (fontsize < 14) {
1346 } else if (fontsize >= 32) {
1348 } else if (fontsize >= 16) {
1356 if (page < 0 || page >= 8)
1358 segment = FONT_BUF + 0x4000*page;
1362 #ifdef VGA_ALT_SEQACCESS
1364 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1365 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1366 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1367 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1371 set_font_mode(adp, buf);
1372 if (fontsize == 32) {
1373 bcopy_fromio(segment + ch*32, data, fontsize*count);
1375 for (c = ch; count > 0; ++c, --count) {
1376 bcopy_fromio(segment + c*32, data, fontsize);
1380 set_normal_mode(adp, buf);
1382 #ifdef VGA_ALT_SEQACCESS
1384 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1385 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1386 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1391 #else /* VGA_NO_FONT_LOADING */
1393 #endif /* VGA_NO_FONT_LOADING */
1398 * Set the font data in the requested font page.
1399 * NOTE: it appears that some recent video adapters do not support
1400 * the font page other than 0... XXX
1403 vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1406 #ifndef VGA_NO_FONT_LOADING
1407 u_char buf[PARAM_BUFSIZE];
1410 #ifdef VGA_ALT_SEQACCESS
1414 prologue(adp, V_ADP_FONT, ENODEV);
1416 if (fontsize < 14) {
1419 } else if (fontsize >= 32) {
1421 } else if (fontsize >= 16) {
1429 if (page < 0 || page >= 8)
1431 segment = FONT_BUF + 0x4000*page;
1435 #ifdef VGA_ALT_SEQACCESS
1437 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1438 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1439 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1440 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1444 set_font_mode(adp, buf);
1445 if (fontsize == 32) {
1446 bcopy_toio(data, segment + ch*32, fontsize*count);
1448 for (c = ch; count > 0; ++c, --count) {
1449 bcopy_toio(data, segment + c*32, fontsize);
1453 set_normal_mode(adp, buf);
1455 #ifdef VGA_ALT_SEQACCESS
1457 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1458 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1459 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1464 #else /* VGA_NO_FONT_LOADING */
1466 #endif /* VGA_NO_FONT_LOADING */
1471 * Activate the requested font page.
1472 * NOTE: it appears that some recent video adapters do not support
1473 * the font page other than 0... XXX
1476 vga_show_font(video_adapter_t *adp, int page)
1478 #ifndef VGA_NO_FONT_LOADING
1479 static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
1481 prologue(adp, V_ADP_FONT, ENODEV);
1482 if (page < 0 || page >= 8)
1486 outb(TSIDX, 0x03); outb(TSREG, cg[page]);
1490 #else /* VGA_NO_FONT_LOADING */
1492 #endif /* VGA_NO_FONT_LOADING */
1497 * Read DAC values. The values have expressed in 8 bits.
1502 vga_save_palette(video_adapter_t *adp, u_char *palette)
1506 prologue(adp, V_ADP_PALETTE, ENODEV);
1509 * We store 8 bit values in the palette buffer, while the standard
1510 * VGA has 6 bit DAC .
1512 outb(PALRADR, 0x00);
1513 for (i = 0; i < 256*3; ++i)
1514 palette[i] = inb(PALDATA) << 2;
1515 inb(CRTC + 6); /* reset flip/flop */
1520 vga_save_palette2(video_adapter_t *adp, int base, int count,
1521 u_char *r, u_char *g, u_char *b)
1525 prologue(adp, V_ADP_PALETTE, ENODEV);
1527 outb(PALRADR, base);
1528 for (i = 0; i < count; ++i) {
1529 r[i] = inb(PALDATA) << 2;
1530 g[i] = inb(PALDATA) << 2;
1531 b[i] = inb(PALDATA) << 2;
1533 inb(CRTC + 6); /* reset flip/flop */
1544 vga_load_palette(video_adapter_t *adp, const u_char *palette)
1548 prologue(adp, V_ADP_PALETTE, ENODEV);
1550 outb(PIXMASK, 0xff); /* no pixelmask */
1551 outb(PALWADR, 0x00);
1552 for (i = 0; i < 256*3; ++i)
1553 outb(PALDATA, palette[i] >> 2);
1554 inb(CRTC + 6); /* reset flip/flop */
1555 outb(ATC, 0x20); /* enable palette */
1560 vga_load_palette2(video_adapter_t *adp, int base, int count,
1561 u_char *r, u_char *g, u_char *b)
1565 prologue(adp, V_ADP_PALETTE, ENODEV);
1567 outb(PIXMASK, 0xff); /* no pixelmask */
1568 outb(PALWADR, base);
1569 for (i = 0; i < count; ++i) {
1570 outb(PALDATA, r[i] >> 2);
1571 outb(PALDATA, g[i] >> 2);
1572 outb(PALDATA, b[i] >> 2);
1574 inb(CRTC + 6); /* reset flip/flop */
1575 outb(ATC, 0x20); /* enable palette */
1581 * Change the border color.
1584 vga_set_border(video_adapter_t *adp, int color)
1586 prologue(adp, V_ADP_BORDER, ENODEV);
1588 inb(CRTC + 6); /* reset flip-flop */
1589 outb(ATC, 0x31); outb(ATC, color & 0xff);
1596 * Read video register values.
1597 * NOTE: this function only reads the standard VGA registers.
1598 * any extra/extended registers of SVGA adapters are not saved.
1601 vga_save_state(video_adapter_t *adp, void *p, size_t size)
1609 /* return the required buffer size */
1610 prologue(adp, V_ADP_STATESAVE, 0);
1611 return sizeof(adp_state_t);
1613 prologue(adp, V_ADP_STATESAVE, ENODEV);
1614 if (size < sizeof(adp_state_t))
1617 ((adp_state_t *)p)->sig = V_STATE_SIG;
1618 buf = ((adp_state_t *)p)->regs;
1619 bzero(buf, V_MODE_PARAM_SIZE);
1624 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
1625 for (i = 0, j = 5; i < 4; i++) {
1627 buf[j++] = inb(TSREG);
1629 buf[9] = inb(MISC + 10); /* dot-clock */
1630 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
1632 for (i = 0, j = 10; i < 25; i++) { /* crtc */
1634 buf[j++] = inb(crtc_addr + 1);
1636 for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */
1637 inb(crtc_addr + 6); /* reset flip-flop */
1639 buf[j++] = inb(ATC + 1);
1641 for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */
1643 buf[j++] = inb(GDCREG);
1645 inb(crtc_addr + 6); /* reset flip-flop */
1646 outb(ATC, 0x20); /* enable palette */
1651 if (vga_get_info(adp, adp->va_mode, &info) == 0) {
1652 if (info.vi_flags & V_INFO_GRAPHICS) {
1653 buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
1654 buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
1656 buf[0] = info.vi_width; /* COLS */
1657 buf[1] = info.vi_height - 1; /* ROWS */
1659 buf[2] = info.vi_cheight; /* POINTS */
1661 /* XXX: shouldn't be happening... */
1662 kprintf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n",
1663 adp->va_unit, adp->va_name);
1666 buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */
1667 buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */
1668 buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */
1669 buf[3] = readb(BIOS_PADDRTOVADDR(0x44c));
1670 buf[4] = readb(BIOS_PADDRTOVADDR(0x44d));
1678 * Set video registers at once.
1679 * NOTE: this function only updates the standard VGA registers.
1680 * any extra/extended registers of SVGA adapters are not changed.
1683 vga_load_state(video_adapter_t *adp, void *p)
1689 prologue(adp, V_ADP_STATELOAD, ENODEV);
1690 if (((adp_state_t *)p)->sig != V_STATE_SIG)
1693 buf = ((adp_state_t *)p)->regs;
1697 dump_buffer(buf, V_MODE_PARAM_SIZE);
1702 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
1703 for (i = 0; i < 4; ++i) { /* program sequencer */
1705 outb(TSREG, buf[i + 5]);
1707 outb(MISC, buf[9]); /* set dot-clock */
1708 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
1709 outb(crtc_addr, 0x11);
1710 outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
1711 for (i = 0; i < 25; ++i) { /* program crtc */
1713 outb(crtc_addr + 1, buf[i + 10]);
1715 inb(crtc_addr+6); /* reset flip-flop */
1716 for (i = 0; i < 20; ++i) { /* program attribute ctrl */
1718 outb(ATC, buf[i + 35]);
1720 for (i = 0; i < 9; ++i) { /* program graph data ctrl */
1722 outb(GDCREG, buf[i + 55]);
1724 inb(crtc_addr + 6); /* reset flip-flop */
1725 outb(ATC, 0x20); /* enable palette */
1727 #if notyet /* a temporary workaround for kernel panic, XXX */
1729 if (adp->va_unit == V_ADP_PRIMARY) {
1730 writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */
1731 writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */
1732 writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */
1734 writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]);
1735 writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]);
1738 #endif /* VGA_NO_BIOS */
1747 * Change the origin (window mapping) of the banked frame buffer.
1750 vga_set_origin(video_adapter_t *adp, off_t offset)
1753 * The standard video modes do not require window mapping;
1754 * always return error.
1761 * Read the position of the hardware text cursor.
1764 vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
1771 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
1776 off = inb(CRTC + 1);
1778 off = (off << 8) | inb(CRTC + 1);
1781 *row = off / adp->va_info.vi_width;
1782 *col = off % adp->va_info.vi_width;
1789 * Move the hardware text cursor. If col and row are both -1,
1790 * the cursor won't be shown.
1793 vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
1800 if ((col == -1) && (row == -1)) {
1803 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
1805 off = row*adp->va_info.vi_width + col;
1810 outb(CRTC + 1, off >> 8);
1812 outb(CRTC + 1, off & 0x00ff);
1819 * set_hw_cursor_shape():
1820 * Change the shape of the hardware text cursor. If the height is
1821 * zero or negative, the cursor won't be shown.
1824 vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
1825 int celsize, int blink)
1832 /* make the cursor invisible */
1839 outb(CRTC + 1, celsize - base - height);
1841 outb(CRTC + 1, celsize - base - 1);
1850 * Put the display in power save/power off mode.
1853 vga_blank_display(video_adapter_t *adp, int mode)
1859 case V_DISPLAY_SUSPEND:
1860 case V_DISPLAY_STAND_BY:
1864 outb(TSREG, val | 0x20);
1866 val = inb(CRTC + 1);
1867 outb(CRTC + 1, val & ~0x80);
1873 outb(TSREG, val | 0x20);
1879 outb(TSREG, val & 0xDF);
1881 val = inb(CRTC + 1);
1882 outb(CRTC + 1, val | 0x80);
1892 * Mmap frame buffer.
1895 vga_mmap_buf(video_adapter_t *adp, vm_offset_t offset, int prot)
1897 if (adp->va_info.vi_flags & V_INFO_LINEAR)
1901 kprintf("vga_mmap_buf(): window:0x%x, offset:0x%x\n",
1902 adp->va_info.vi_window, offset);
1905 /* XXX: is this correct? */
1906 if (offset > adp->va_window_size - PAGE_SIZE)
1910 return i386_btop(adp->va_info.vi_window + offset);
1914 #ifndef VGA_NO_MODE_CHANGE
1917 planar_fill(video_adapter_t *adp, int val)
1920 int at; /* position in the frame buffer */
1923 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1924 outw(GDCIDX, 0x0003); /* data rotate/function select */
1925 outw(GDCIDX, 0x0f01); /* set/reset enable */
1926 outw(GDCIDX, 0xff08); /* bit mask */
1927 outw(GDCIDX, (val << 8) | 0x00); /* set/reset */
1929 length = adp->va_line_width*adp->va_info.vi_height;
1930 while (length > 0) {
1931 l = imin(length, adp->va_window_size);
1932 (*vidsw[adp->va_index]->set_win_org)(adp, at);
1933 bzero_io(adp->va_window, l);
1937 outw(GDCIDX, 0x0000); /* set/reset */
1938 outw(GDCIDX, 0x0001); /* set/reset enable */
1942 packed_fill(video_adapter_t *adp, int val)
1945 int at; /* position in the frame buffer */
1949 length = adp->va_line_width*adp->va_info.vi_height;
1950 while (length > 0) {
1951 l = imin(length, adp->va_window_size);
1952 (*vidsw[adp->va_index]->set_win_org)(adp, at);
1953 fill_io(val, adp->va_window, l);
1960 direct_fill(video_adapter_t *adp, int val)
1963 int at; /* position in the frame buffer */
1967 length = adp->va_line_width*adp->va_info.vi_height;
1968 while (length > 0) {
1969 l = imin(length, adp->va_window_size);
1970 (*vidsw[adp->va_index]->set_win_org)(adp, at);
1971 switch (adp->va_info.vi_pixel_size) {
1972 case sizeof(u_int16_t):
1973 fillw_io(val, adp->va_window, l/sizeof(u_int16_t));
1978 case sizeof(u_int32_t):
1979 filll_io(val, adp->va_window, l/sizeof(u_int32_t));
1988 vga_clear(video_adapter_t *adp)
1990 switch (adp->va_info.vi_mem_model) {
1991 case V_INFO_MM_TEXT:
1992 /* do nothing? XXX */
1994 case V_INFO_MM_PLANAR:
1995 planar_fill(adp, 0);
1997 case V_INFO_MM_PACKED:
1998 packed_fill(adp, 0);
2000 case V_INFO_MM_DIRECT:
2001 direct_fill(adp, 0);
2009 planar_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2014 int offset; /* offset within window */
2018 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
2019 outw(GDCIDX, 0x0003); /* data rotate/function select */
2020 outw(GDCIDX, 0x0f01); /* set/reset enable */
2021 outw(GDCIDX, 0xff08); /* bit mask */
2022 outw(GDCIDX, (val << 8) | 0x00); /* set/reset */
2024 banksize = adp->va_window_size;
2027 pos = adp->va_line_width*y + x/8;
2028 if (bank != pos/banksize) {
2029 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2030 bank = pos/banksize;
2032 offset = pos%banksize;
2033 bx = (x + cx)/8 - x/8;
2035 outw(GDCIDX, ((0xff00 >> (x % 8)) & 0xff00) | 0x08);
2036 writeb(adp->va_window + offset, 0);
2039 if (offset >= banksize) {
2041 ++bank; /* next bank */
2042 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2044 outw(GDCIDX, 0xff08); /* bit mask */
2047 l = imin(bx, banksize);
2048 bzero_io(adp->va_window + offset, l);
2051 if (offset >= banksize) {
2053 ++bank; /* next bank */
2054 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2058 outw(GDCIDX, (~(0xff00 >> ((x + cx) % 8)) & 0xff00) | 0x08);
2059 writeb(adp->va_window + offset, 0);
2061 if (offset >= banksize) {
2063 ++bank; /* next bank */
2064 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2066 outw(GDCIDX, 0xff08); /* bit mask */
2072 outw(GDCIDX, 0xff08); /* bit mask */
2073 outw(GDCIDX, 0x0000); /* set/reset */
2074 outw(GDCIDX, 0x0001); /* set/reset enable */
2078 packed_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2083 int offset; /* offset within window */
2086 banksize = adp->va_window_size;
2088 cx *= adp->va_info.vi_pixel_size;
2090 pos = adp->va_line_width*y + x*adp->va_info.vi_pixel_size;
2091 if (bank != pos/banksize) {
2092 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2093 bank = pos/banksize;
2095 offset = pos%banksize;
2096 end = imin(offset + cx, banksize);
2097 fill_io(val, adp->va_window + offset,
2098 (end - offset)/adp->va_info.vi_pixel_size);
2099 /* the line may cross the window boundary */
2100 if (offset + cx > banksize) {
2101 ++bank; /* next bank */
2102 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2103 end = offset + cx - banksize;
2104 fill_io(val, adp->va_window, end/adp->va_info.vi_pixel_size);
2112 direct_fill_rect16(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2117 int offset; /* offset within window */
2121 * XXX: the function assumes that banksize is a muliple of
2122 * sizeof(u_int16_t).
2124 banksize = adp->va_window_size;
2126 cx *= sizeof(u_int16_t);
2128 pos = adp->va_line_width*y + x*sizeof(u_int16_t);
2129 if (bank != pos/banksize) {
2130 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2131 bank = pos/banksize;
2133 offset = pos%banksize;
2134 end = imin(offset + cx, banksize);
2135 fillw_io(val, adp->va_window + offset,
2136 (end - offset)/sizeof(u_int16_t));
2137 /* the line may cross the window boundary */
2138 if (offset + cx > banksize) {
2139 ++bank; /* next bank */
2140 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2141 end = offset + cx - banksize;
2142 fillw_io(val, adp->va_window, end/sizeof(u_int16_t));
2150 direct_fill_rect24(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2155 int offset; /* offset within window */
2161 b[0] = val & 0x0000ff;
2162 b[1] = (val >> 8) & 0x0000ff;
2163 b[2] = (val >> 16) & 0x0000ff;
2164 banksize = adp->va_window_size;
2168 pos = adp->va_line_width*y + x*3;
2169 if (bank != pos/banksize) {
2170 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2171 bank = pos/banksize;
2173 offset = pos%banksize;
2174 end = imin(offset + cx, banksize);
2175 for (i = 0, j = offset; j < end; i = (++i)%3, ++j) {
2176 writeb(adp->va_window + j, b[i]);
2178 /* the line may cross the window boundary */
2179 if (offset + cx >= banksize) {
2180 ++bank; /* next bank */
2181 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2183 end = offset + cx - banksize;
2184 for (; j < end; i = (++i)%3, ++j) {
2185 writeb(adp->va_window + j, b[i]);
2194 direct_fill_rect32(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2199 int offset; /* offset within window */
2203 * XXX: the function assumes that banksize is a muliple of
2204 * sizeof(u_int32_t).
2206 banksize = adp->va_window_size;
2208 cx *= sizeof(u_int32_t);
2210 pos = adp->va_line_width*y + x*sizeof(u_int32_t);
2211 if (bank != pos/banksize) {
2212 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2213 bank = pos/banksize;
2215 offset = pos%banksize;
2216 end = imin(offset + cx, banksize);
2217 filll_io(val, adp->va_window + offset,
2218 (end - offset)/sizeof(u_int32_t));
2219 /* the line may cross the window boundary */
2220 if (offset + cx > banksize) {
2221 ++bank; /* next bank */
2222 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2223 end = offset + cx - banksize;
2224 filll_io(val, adp->va_window, end/sizeof(u_int32_t));
2232 vga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2234 switch (adp->va_info.vi_mem_model) {
2235 case V_INFO_MM_TEXT:
2236 /* do nothing? XXX */
2238 case V_INFO_MM_PLANAR:
2239 planar_fill_rect(adp, val, x, y, cx, cy);
2241 case V_INFO_MM_PACKED:
2242 packed_fill_rect(adp, val, x, y, cx, cy);
2244 case V_INFO_MM_DIRECT:
2245 switch (adp->va_info.vi_pixel_size) {
2246 case sizeof(u_int16_t):
2247 direct_fill_rect16(adp, val, x, y, cx, cy);
2250 direct_fill_rect24(adp, val, x, y, cx, cy);
2252 case sizeof(u_int32_t):
2253 direct_fill_rect32(adp, val, x, y, cx, cy);
2262 vga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2269 vga_bitblt(video_adapter_t *adp,...)
2275 #endif /* !VGA_NO_MODE_CHANGE */
2278 get_palette(video_adapter_t *adp, int base, int count,
2279 u_char *red, u_char *green, u_char *blue, u_char *trans)
2285 if (count < 0 || base < 0 || count > 256 || base > 256 ||
2289 r = kmalloc(count*3, M_DEVBUF, M_WAITOK);
2292 if (vga_save_palette2(adp, base, count, r, g, b)) {
2296 copyout(r, red, count);
2297 copyout(g, green, count);
2298 copyout(b, blue, count);
2299 if (trans != NULL) {
2301 copyout(r, trans, count);
2309 set_palette(video_adapter_t *adp, int base, int count,
2310 u_char *red, u_char *green, u_char *blue, u_char *trans)
2317 if (count < 0 || base < 0 || count > 256 || base > 256 ||
2321 r = kmalloc(count*3, M_DEVBUF, M_WAITOK);
2324 err = copyin(red, r, count);
2326 err = copyin(green, g, count);
2328 err = copyin(blue, b, count);
2330 err = vga_load_palette2(adp, base, count, r, g, b);
2333 return (err ? ENODEV : 0);
2337 vga_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
2340 case FBIO_GETWINORG: /* get frame buffer window origin */
2344 case FBIO_SETWINORG: /* set frame buffer window origin */
2347 case FBIO_SETDISPSTART: /* set display start address */
2348 return (set_display_start(adp,
2349 ((video_display_start_t *)arg)->x,
2350 ((video_display_start_t *)arg)->y)
2353 case FBIO_SETLINEWIDTH: /* set scan line length in pixel */
2354 return (set_line_length(adp, *(u_int *)arg) ? ENODEV : 0);
2356 case FBIO_GETPALETTE: /* get color palette */
2357 return get_palette(adp, ((video_color_palette_t *)arg)->index,
2358 ((video_color_palette_t *)arg)->count,
2359 ((video_color_palette_t *)arg)->red,
2360 ((video_color_palette_t *)arg)->green,
2361 ((video_color_palette_t *)arg)->blue,
2362 ((video_color_palette_t *)arg)->transparent);
2364 case FBIO_SETPALETTE: /* set color palette */
2365 return set_palette(adp, ((video_color_palette_t *)arg)->index,
2366 ((video_color_palette_t *)arg)->count,
2367 ((video_color_palette_t *)arg)->red,
2368 ((video_color_palette_t *)arg)->green,
2369 ((video_color_palette_t *)arg)->blue,
2370 ((video_color_palette_t *)arg)->transparent);
2372 case FBIOGTYPE: /* get frame buffer type info. */
2373 ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type);
2374 ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height;
2375 ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width;
2376 ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth;
2377 if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8))
2378 ((struct fbtype *)arg)->fb_cmsize = 0;
2380 ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth;
2381 ((struct fbtype *)arg)->fb_size = adp->va_buffer_size;
2384 case FBIOGETCMAP: /* get color palette */
2385 return get_palette(adp, ((struct fbcmap *)arg)->index,
2386 ((struct fbcmap *)arg)->count,
2387 ((struct fbcmap *)arg)->red,
2388 ((struct fbcmap *)arg)->green,
2389 ((struct fbcmap *)arg)->blue, NULL);
2391 case FBIOPUTCMAP: /* set color palette */
2392 return set_palette(adp, ((struct fbcmap *)arg)->index,
2393 ((struct fbcmap *)arg)->count,
2394 ((struct fbcmap *)arg)->red,
2395 ((struct fbcmap *)arg)->green,
2396 ((struct fbcmap *)arg)->blue, NULL);
2399 return fb_commonioctl(adp, cmd, arg);
2404 dump_buffer(u_char *buf, size_t len)
2408 for(i = 0; i < len;) {
2409 kprintf("%02x ", buf[i]);
2410 if ((++i % 16) == 0)
2417 * Print some information about the video adapter and video modes,
2418 * with requested level of details.
2421 vga_diag(video_adapter_t *adp, int level)
2434 kprintf("vga: DCC code:0x%02x\n",
2435 readb(BIOS_PADDRTOVADDR(0x488)));
2436 kprintf("vga: CRTC:0x%x, video option:0x%02x, ",
2437 readw(BIOS_PADDRTOVADDR(0x463)),
2438 readb(BIOS_PADDRTOVADDR(0x487)));
2439 kprintf("rows:%d, cols:%d, font height:%d\n",
2440 readb(BIOS_PADDRTOVADDR(0x44a)),
2441 readb(BIOS_PADDRTOVADDR(0x484)) + 1,
2442 readb(BIOS_PADDRTOVADDR(0x485)));
2443 #endif /* VGA_NO_BIOS */
2444 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
2445 kprintf("vga: param table:%p\n", video_mode_ptr);
2446 kprintf("vga: rows_offset:%d\n", rows_offset);
2448 #endif /* FB_DEBUG > 1 */
2450 fb_dump_adp_info(VGA_DRIVER_NAME, adp, level);
2453 if (adp->va_flags & V_ADP_MODECHANGE) {
2454 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
2455 if (bios_vmode[i].vi_mode == NA)
2457 if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
2459 fb_dump_mode_info(VGA_DRIVER_NAME, adp, &bios_vmode[i], level);
2462 vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */
2463 fb_dump_mode_info(VGA_DRIVER_NAME, adp, &info, level);
2465 #endif /* FB_DEBUG > 1 */
2467 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
2468 if (video_mode_ptr == NULL)
2469 kprintf("vga%d: %s: WARNING: video mode switching is not "
2470 "fully supported on this adapter\n",
2471 adp->va_unit, adp->va_name);
2476 kprintf("VGA parameters upon power-up\n");
2477 dump_buffer(adpstate.regs, sizeof(adpstate.regs));
2478 kprintf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
2479 dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
2481 mp = get_mode_param(adp->va_initial_mode);
2482 if (mp == NULL) /* this shouldn't be happening */
2484 kprintf("VGA parameters to be used for mode %d\n", adp->va_initial_mode);
2485 dump_buffer(mp, V_MODE_PARAM_SIZE);