FreeBSD/Linux Kernel Cross Reference
sys/dev/fb/vga.c
1 /*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * Copyright (c) 1992-1998 Søren Schmidt
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
17 *
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.
28 *
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD: releng/5.2/sys/dev/fb/vga.c 119418 2003-08-24 17:55:58Z obrien $");
33
34 #include "opt_vga.h"
35 #include "opt_fb.h"
36 #include "opt_syscons.h" /* should be removed in the future, XXX */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/conf.h>
42 #include <sys/fcntl.h>
43 #include <sys/malloc.h>
44 #include <sys/fbio.h>
45
46 #include <vm/vm.h>
47 #include <vm/vm_param.h>
48 #include <vm/pmap.h>
49
50 #include <machine/md_var.h>
51 #ifdef __i386__
52 #include <machine/pc/bios.h>
53 #endif
54 #include <machine/bus.h>
55
56 #include <dev/fb/fbreg.h>
57 #include <dev/fb/vgareg.h>
58
59 #include <isa/isareg.h>
60
61 #ifndef VGA_DEBUG
62 #define VGA_DEBUG 0
63 #endif
64
65 /* XXX machine/pc/bios.h has got too much i386-specific stuff in it */
66 #ifndef BIOS_PADDRTOVADDR
67 #if !defined(__amd64__)
68 #define BIOS_PADDRTOVADDR(x) (x)
69 #else
70 #define BIOS_PADDRTOVADDR(x) (((x) - ISA_HOLE_START) + atdevbase)
71 #endif
72 #endif
73
74 int
75 vga_probe_unit(int unit, video_adapter_t *buf, int flags)
76 {
77 video_adapter_t *adp;
78 video_switch_t *sw;
79 int error;
80
81 sw = vid_get_switch(VGA_DRIVER_NAME);
82 if (sw == NULL)
83 return 0;
84 error = (*sw->probe)(unit, &adp, NULL, flags);
85 if (error)
86 return error;
87 bcopy(adp, buf, sizeof(*buf));
88 return 0;
89 }
90
91 int
92 vga_attach_unit(int unit, vga_softc_t *sc, int flags)
93 {
94 video_switch_t *sw;
95 int error;
96
97 sw = vid_get_switch(VGA_DRIVER_NAME);
98 if (sw == NULL)
99 return ENXIO;
100
101 error = (*sw->probe)(unit, &sc->adp, NULL, flags);
102 if (error)
103 return error;
104 return (*sw->init)(unit, sc->adp, flags);
105 }
106
107 /* cdev driver functions */
108
109 #ifdef FB_INSTALL_CDEV
110
111 int
112 vga_open(dev_t dev, vga_softc_t *sc, int flag, int mode, struct thread *td)
113 {
114 if (sc == NULL)
115 return ENXIO;
116 if (mode & (O_CREAT | O_APPEND | O_TRUNC))
117 return ENODEV;
118
119 return genfbopen(&sc->gensc, sc->adp, flag, mode, td);
120 }
121
122 int
123 vga_close(dev_t dev, vga_softc_t *sc, int flag, int mode, struct thread *td)
124 {
125 return genfbclose(&sc->gensc, sc->adp, flag, mode, td);
126 }
127
128 int
129 vga_read(dev_t dev, vga_softc_t *sc, struct uio *uio, int flag)
130 {
131 return genfbread(&sc->gensc, sc->adp, uio, flag);
132 }
133
134 int
135 vga_write(dev_t dev, vga_softc_t *sc, struct uio *uio, int flag)
136 {
137 return genfbread(&sc->gensc, sc->adp, uio, flag);
138 }
139
140 int
141 vga_ioctl(dev_t dev, vga_softc_t *sc, u_long cmd, caddr_t arg, int flag,
142 struct thread *td)
143 {
144 return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, td);
145 }
146
147 int
148 vga_mmap(dev_t dev, vga_softc_t *sc, vm_offset_t offset, vm_offset_t *paddr,
149 int prot)
150 {
151 return genfbmmap(&sc->gensc, sc->adp, offset, paddr, prot);
152 }
153
154 #endif /* FB_INSTALL_CDEV */
155
156 /* LOW-LEVEL */
157
158 #include <machine/clock.h>
159 #ifdef __i386__
160 #include <machine/pc/vesa.h>
161 #endif
162
163 #define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
164 #define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
165 #define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
166
167 /* for compatibility with old kernel options */
168 #ifdef SC_ALT_SEQACCESS
169 #undef SC_ALT_SEQACCESS
170 #undef VGA_ALT_SEQACCESS
171 #define VGA_ALT_SEQACCESS 1
172 #endif
173
174 #ifdef SLOW_VGA
175 #undef SLOW_VGA
176 #undef VGA_SLOW_IOACCESS
177 #define VGA_SLOW_IOACCESS 1
178 #endif
179
180 /* architecture dependent option */
181 #ifndef __i386__
182 #define VGA_NO_BIOS 1
183 #endif
184
185 /* this should really be in `rtc.h' */
186 #define RTC_EQUIPMENT 0x14
187
188 /* various sizes */
189 #define V_MODE_MAP_SIZE (M_VGA_CG320 + 1)
190 #define V_MODE_PARAM_SIZE 64
191
192 /* video adapter state buffer */
193 struct adp_state {
194 int sig;
195 #define V_STATE_SIG 0x736f6962
196 u_char regs[V_MODE_PARAM_SIZE];
197 };
198 typedef struct adp_state adp_state_t;
199
200 /* video adapter information */
201 #define DCC_MONO 0
202 #define DCC_CGA40 1
203 #define DCC_CGA80 2
204 #define DCC_EGAMONO 3
205 #define DCC_EGA40 4
206 #define DCC_EGA80 5
207
208 /*
209 * NOTE: `va_window' should have a virtual address, but is initialized
210 * with a physical address in the following table, as verify_adapter()
211 * will perform address conversion at run-time.
212 */
213 static video_adapter_t adapter_init_value[] = {
214 /* DCC_MONO */
215 { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC,
216 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
217 0, 0, 0, 0, 7, 0, },
218 /* DCC_CGA40 */
219 { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
220 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
221 0, 0, 0, 0, 3, 0, },
222 /* DCC_CGA80 */
223 { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
224 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
225 0, 0, 0, 0, 3, 0, },
226 /* DCC_EGAMONO */
227 { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC,
228 EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
229 0, 0, 0, 0, 7, 0, },
230 /* DCC_EGA40 */
231 { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
232 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
233 0, 0, 0, 0, 3, 0, },
234 /* DCC_EGA80 */
235 { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
236 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
237 0, 0, 0, 0, 3, 0, },
238 };
239
240 static video_adapter_t biosadapter[2];
241 static int biosadapters = 0;
242
243 /* video driver declarations */
244 static int vga_configure(int flags);
245 int (*vga_sub_configure)(int flags);
246 #if 0
247 static int vga_nop(void);
248 #endif
249 static int vga_error(void);
250 static vi_probe_t vga_probe;
251 static vi_init_t vga_init;
252 static vi_get_info_t vga_get_info;
253 static vi_query_mode_t vga_query_mode;
254 static vi_set_mode_t vga_set_mode;
255 static vi_save_font_t vga_save_font;
256 static vi_load_font_t vga_load_font;
257 static vi_show_font_t vga_show_font;
258 static vi_save_palette_t vga_save_palette;
259 static vi_load_palette_t vga_load_palette;
260 static vi_set_border_t vga_set_border;
261 static vi_save_state_t vga_save_state;
262 static vi_load_state_t vga_load_state;
263 static vi_set_win_org_t vga_set_origin;
264 static vi_read_hw_cursor_t vga_read_hw_cursor;
265 static vi_set_hw_cursor_t vga_set_hw_cursor;
266 static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape;
267 static vi_blank_display_t vga_blank_display;
268 static vi_mmap_t vga_mmap_buf;
269 static vi_ioctl_t vga_dev_ioctl;
270 #ifndef VGA_NO_MODE_CHANGE
271 static vi_clear_t vga_clear;
272 static vi_fill_rect_t vga_fill_rect;
273 static vi_bitblt_t vga_bitblt;
274 #else /* VGA_NO_MODE_CHANGE */
275 #define vga_clear (vi_clear_t *)vga_error
276 #define vga_fill_rect (vi_fill_rect_t *)vga_error
277 #define vga_bitblt (vi_bitblt_t *)vga_error
278 #endif
279 static vi_diag_t vga_diag;
280
281 static video_switch_t vgavidsw = {
282 vga_probe,
283 vga_init,
284 vga_get_info,
285 vga_query_mode,
286 vga_set_mode,
287 vga_save_font,
288 vga_load_font,
289 vga_show_font,
290 vga_save_palette,
291 vga_load_palette,
292 vga_set_border,
293 vga_save_state,
294 vga_load_state,
295 vga_set_origin,
296 vga_read_hw_cursor,
297 vga_set_hw_cursor,
298 vga_set_hw_cursor_shape,
299 vga_blank_display,
300 vga_mmap_buf,
301 vga_dev_ioctl,
302 vga_clear,
303 vga_fill_rect,
304 vga_bitblt,
305 vga_error,
306 vga_error,
307 vga_diag,
308 };
309
310 VIDEO_DRIVER(mda, vgavidsw, NULL);
311 VIDEO_DRIVER(cga, vgavidsw, NULL);
312 VIDEO_DRIVER(ega, vgavidsw, NULL);
313 VIDEO_DRIVER(vga, vgavidsw, vga_configure);
314
315 /* VGA BIOS standard video modes */
316 #define EOT (-1)
317 #define NA (-2)
318
319 static video_info_t bios_vmode[] = {
320 /* CGA */
321 { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1,
322 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
323 { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1,
324 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
325 { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1,
326 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
327 { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1,
328 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
329 /* EGA */
330 { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1,
331 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
332 { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1,
333 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
334 { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1,
335 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
336 { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1,
337 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
338 /* VGA */
339 { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1,
340 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
341 { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1,
342 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
343 { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
344 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
345 /* MDA */
346 { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1,
347 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
348 /* EGA */
349 { M_ENH_B80x43, 0, 80, 43, 8, 8, 2, 1,
350 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
351 { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1,
352 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
353 /* VGA */
354 { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1,
355 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
356 { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
357 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
358 { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1,
359 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
360 { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1,
361 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
362 { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1,
363 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
364 { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1,
365 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
366
367 #ifndef VGA_NO_MODE_CHANGE
368
369 #ifdef VGA_WIDTH90
370 { M_VGA_M90x25, 0, 90, 25, 8, 16, 2, 1,
371 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
372 { M_VGA_C90x25, V_INFO_COLOR, 90, 25, 8, 16, 4, 1,
373 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
374 { M_VGA_M90x30, 0, 90, 30, 8, 16, 2, 1,
375 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
376 { M_VGA_C90x30, V_INFO_COLOR, 90, 30, 8, 16, 4, 1,
377 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
378 { M_VGA_M90x43, 0, 90, 43, 8, 8, 2, 1,
379 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
380 { M_VGA_C90x43, V_INFO_COLOR, 90, 43, 8, 8, 4, 1,
381 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
382 { M_VGA_M90x50, 0, 90, 50, 8, 8, 2, 1,
383 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
384 { M_VGA_C90x50, V_INFO_COLOR, 90, 50, 8, 8, 4, 1,
385 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
386 { M_VGA_M90x60, 0, 90, 60, 8, 8, 2, 1,
387 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
388 { M_VGA_C90x60, V_INFO_COLOR, 90, 60, 8, 8, 4, 1,
389 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT },
390 #endif /* VGA_WIDTH90 */
391
392 /* CGA */
393 { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
394 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
395 { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
396 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
397 { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1,
398 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA },
399 /* EGA */
400 { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4,
401 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
402 V_INFO_MM_PLANAR },
403 { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4,
404 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
405 V_INFO_MM_PLANAR },
406 { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
407 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 ,
408 V_INFO_MM_PLANAR },
409 { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
410 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
411 V_INFO_MM_PLANAR },
412 { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2,
413 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
414 V_INFO_MM_PLANAR },
415 { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
416 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
417 V_INFO_MM_PLANAR },
418 /* VGA */
419 { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
420 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
421 V_INFO_MM_PLANAR },
422 { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
423 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 ,
424 V_INFO_MM_PLANAR },
425 { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1,
426 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
427 V_INFO_MM_PACKED, 1 },
428 { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 4,
429 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0,
430 V_INFO_MM_VGAX, 1 },
431 #endif /* VGA_NO_MODE_CHANGE */
432
433 { EOT },
434 };
435
436 static int vga_init_done = FALSE;
437 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
438 static u_char *video_mode_ptr = NULL; /* EGA/VGA */
439 static u_char *video_mode_ptr2 = NULL; /* CGA/MDA */
440 #endif
441 static u_char *mode_map[V_MODE_MAP_SIZE];
442 static adp_state_t adpstate;
443 static adp_state_t adpstate2;
444 static int rows_offset = 1;
445
446 /* local macros and functions */
447 #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
448
449 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
450 static void map_mode_table(u_char *map[], u_char *table, int max);
451 #endif
452 static void clear_mode_map(video_adapter_t *adp, u_char *map[], int max,
453 int color);
454 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
455 static int map_mode_num(int mode);
456 #endif
457 static int map_gen_mode_num(int type, int color, int mode);
458 static int map_bios_mode_num(int type, int color, int bios_mode);
459 static u_char *get_mode_param(int mode);
460 #ifndef VGA_NO_BIOS
461 static void fill_adapter_param(int code, video_adapter_t *adp);
462 #endif
463 static int verify_adapter(video_adapter_t *adp);
464 static void update_adapter_info(video_adapter_t *adp, video_info_t *info);
465 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
466 #define COMP_IDENTICAL 0
467 #define COMP_SIMILAR 1
468 #define COMP_DIFFERENT 2
469 static int comp_adpregs(u_char *buf1, u_char *buf2);
470 #endif
471 static int probe_adapters(void);
472 static int set_line_length(video_adapter_t *adp, int pixel);
473 static int set_display_start(video_adapter_t *adp, int x, int y);
474 static void filll_io(int val, vm_offset_t d, size_t size);
475
476 #ifndef VGA_NO_MODE_CHANGE
477 #ifdef VGA_WIDTH90
478 static void set_width90(adp_state_t *params);
479 #endif
480 #endif /* !VGA_NO_MODE_CHANGE */
481
482 #ifndef VGA_NO_FONT_LOADING
483 #define PARAM_BUFSIZE 6
484 static void set_font_mode(video_adapter_t *adp, u_char *buf);
485 static void set_normal_mode(video_adapter_t *adp, u_char *buf);
486 #endif
487
488 #ifndef VGA_NO_MODE_CHANGE
489 static void planar_fill(video_adapter_t *adp, int val);
490 static void packed_fill(video_adapter_t *adp, int val);
491 static void direct_fill(video_adapter_t *adp, int val);
492 #ifdef notyet
493 static void planar_fill_rect(video_adapter_t *adp, int val, int x, int y,
494 int cx, int cy);
495 static void packed_fill_rect(video_adapter_t *adp, int val, int x, int y,
496 int cx, int cy);
497 static void direct_fill_rect16(video_adapter_t *adp, int val, int x, int y,
498 int cx, int cy);
499 static void direct_fill_rect24(video_adapter_t *adp, int val, int x, int y,
500 int cx, int cy);
501 static void direct_fill_rect32(video_adapter_t *adp, int val, int x, int y,
502 int cx, int cy);
503 #endif /* notyet */
504 #endif /* !VGA_NO_MODE_CHANGE */
505
506 static void dump_buffer(u_char *buf, size_t len);
507
508 #define ISMAPPED(pa, width) \
509 (((pa) <= (u_long)0x1000 - (width)) \
510 || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width)))
511
512 #define prologue(adp, flag, err) \
513 if (!vga_init_done || !((adp)->va_flags & (flag))) \
514 return (err)
515
516 /* a backdoor for the console driver */
517 static int
518 vga_configure(int flags)
519 {
520 int i;
521
522 probe_adapters();
523 for (i = 0; i < biosadapters; ++i) {
524 if (!probe_done(&biosadapter[i]))
525 continue;
526 biosadapter[i].va_flags |= V_ADP_INITIALIZED;
527 if (!config_done(&biosadapter[i])) {
528 if (vid_register(&biosadapter[i]) < 0)
529 continue;
530 biosadapter[i].va_flags |= V_ADP_REGISTERED;
531 }
532 }
533 if (vga_sub_configure != NULL)
534 (*vga_sub_configure)(flags);
535
536 return biosadapters;
537 }
538
539 /* local subroutines */
540
541 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
542 /* construct the mode parameter map */
543 static void
544 map_mode_table(u_char *map[], u_char *table, int max)
545 {
546 int i;
547
548 for(i = 0; i < max; ++i)
549 map[i] = table + i*V_MODE_PARAM_SIZE;
550 for(; i < V_MODE_MAP_SIZE; ++i)
551 map[i] = NULL;
552 }
553 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
554
555 static void
556 clear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color)
557 {
558 video_info_t info;
559 int i;
560
561 /*
562 * NOTE: we don't touch `bios_vmode[]' because it is shared
563 * by all adapters.
564 */
565 for(i = 0; i < max; ++i) {
566 if (vga_get_info(adp, i, &info))
567 continue;
568 if ((info.vi_flags & V_INFO_COLOR) != color)
569 map[i] = NULL;
570 }
571 }
572
573 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
574 /* map the non-standard video mode to a known mode number */
575 static int
576 map_mode_num(int mode)
577 {
578 static struct {
579 int from;
580 int to;
581 } mode_map[] = {
582 { M_ENH_B80x43, M_ENH_B80x25 },
583 { M_ENH_C80x43, M_ENH_C80x25 },
584 { M_VGA_M80x30, M_VGA_M80x25 },
585 { M_VGA_C80x30, M_VGA_C80x25 },
586 { M_VGA_M80x50, M_VGA_M80x25 },
587 { M_VGA_C80x50, M_VGA_C80x25 },
588 { M_VGA_M80x60, M_VGA_M80x25 },
589 { M_VGA_C80x60, M_VGA_C80x25 },
590 #ifdef VGA_WIDTH90
591 { M_VGA_M90x25, M_VGA_M80x25 },
592 { M_VGA_C90x25, M_VGA_C80x25 },
593 { M_VGA_M90x30, M_VGA_M80x25 },
594 { M_VGA_C90x30, M_VGA_C80x25 },
595 { M_VGA_M90x43, M_ENH_B80x25 },
596 { M_VGA_C90x43, M_ENH_C80x25 },
597 { M_VGA_M90x50, M_VGA_M80x25 },
598 { M_VGA_C90x50, M_VGA_C80x25 },
599 { M_VGA_M90x60, M_VGA_M80x25 },
600 { M_VGA_C90x60, M_VGA_C80x25 },
601 #endif
602 { M_VGA_MODEX, M_VGA_CG320 },
603 };
604 int i;
605
606 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
607 if (mode_map[i].from == mode)
608 return mode_map[i].to;
609 }
610 return mode;
611 }
612 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
613
614 /* map a generic video mode to a known mode number */
615 static int
616 map_gen_mode_num(int type, int color, int mode)
617 {
618 static struct {
619 int from;
620 int to_color;
621 int to_mono;
622 } mode_map[] = {
623 { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, },
624 { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, },
625 { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, },
626 { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, },
627 };
628 int i;
629
630 if (mode == M_TEXT_80x25) {
631 switch (type) {
632
633 case KD_VGA:
634 if (color)
635 return M_VGA_C80x25;
636 else
637 return M_VGA_M80x25;
638 break;
639
640 case KD_EGA:
641 if (color)
642 return M_ENH_C80x25;
643 else
644 return M_EGAMONO80x25;
645 break;
646
647 case KD_CGA:
648 return M_C80x25;
649
650 case KD_MONO:
651 case KD_HERCULES:
652 return M_EGAMONO80x25; /* XXX: this name is confusing */
653
654 default:
655 return -1;
656 }
657 }
658
659 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
660 if (mode_map[i].from == mode)
661 return ((color) ? mode_map[i].to_color : mode_map[i].to_mono);
662 }
663 return mode;
664 }
665
666 /* turn the BIOS video number into our video mode number */
667 static int
668 map_bios_mode_num(int type, int color, int bios_mode)
669 {
670 static int cga_modes[7] = {
671 M_B40x25, M_C40x25, /* 0, 1 */
672 M_B80x25, M_C80x25, /* 2, 3 */
673 M_BG320, M_CG320,
674 M_BG640,
675 };
676 static int ega_modes[17] = {
677 M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */
678 M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */
679 M_BG320, M_CG320,
680 M_BG640,
681 M_EGAMONO80x25, /* 7 */
682 8, 9, 10, 11, 12,
683 M_CG320_D,
684 M_CG640_E,
685 M_ENHMONOAPA2, /* XXX: video momery > 64K */
686 M_ENH_CG640, /* XXX: video momery > 64K */
687 };
688 static int vga_modes[20] = {
689 M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */
690 M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */
691 M_BG320, M_CG320,
692 M_BG640,
693 M_VGA_M80x25, /* 7 */
694 8, 9, 10, 11, 12,
695 M_CG320_D,
696 M_CG640_E,
697 M_ENHMONOAPA2,
698 M_ENH_CG640,
699 M_BG640x480, M_CG640x480,
700 M_VGA_CG320,
701 };
702
703 switch (type) {
704
705 case KD_VGA:
706 if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
707 return vga_modes[bios_mode];
708 else if (color)
709 return M_VGA_C80x25;
710 else
711 return M_VGA_M80x25;
712 break;
713
714 case KD_EGA:
715 if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0]))
716 return ega_modes[bios_mode];
717 else if (color)
718 return M_ENH_C80x25;
719 else
720 return M_EGAMONO80x25;
721 break;
722
723 case KD_CGA:
724 if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0]))
725 return cga_modes[bios_mode];
726 else
727 return M_C80x25;
728 break;
729
730 case KD_MONO:
731 case KD_HERCULES:
732 return M_EGAMONO80x25; /* XXX: this name is confusing */
733
734 default:
735 break;
736 }
737 return -1;
738 }
739
740 /* look up a parameter table entry */
741 static u_char
742 *get_mode_param(int mode)
743 {
744 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
745 if (mode >= V_MODE_MAP_SIZE)
746 mode = map_mode_num(mode);
747 #endif
748 if ((mode >= 0) && (mode < V_MODE_MAP_SIZE))
749 return mode_map[mode];
750 else
751 return NULL;
752 }
753
754 #ifndef VGA_NO_BIOS
755 static void
756 fill_adapter_param(int code, video_adapter_t *adp)
757 {
758 static struct {
759 int primary;
760 int secondary;
761 } dcc[] = {
762 { DCC_MONO, DCC_EGA40 /* CGA monitor */ },
763 { DCC_MONO, DCC_EGA80 /* CGA monitor */ },
764 { DCC_MONO, DCC_EGA80 },
765 { DCC_MONO, DCC_EGA80 },
766 { DCC_CGA40, DCC_EGAMONO },
767 { DCC_CGA80, DCC_EGAMONO },
768 { DCC_EGA40 /* CGA monitor */, DCC_MONO},
769 { DCC_EGA80 /* CGA monitor */, DCC_MONO},
770 { DCC_EGA80, DCC_MONO },
771 { DCC_EGA80, DCC_MONO },
772 { DCC_EGAMONO, DCC_CGA40 },
773 { DCC_EGAMONO, DCC_CGA80 },
774 };
775
776 if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) {
777 adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
778 adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
779 } else {
780 adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary];
781 adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary];
782 }
783 }
784 #endif /* VGA_NO_BIOS */
785
786 static int
787 verify_adapter(video_adapter_t *adp)
788 {
789 vm_offset_t buf;
790 u_int16_t v;
791 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
792 u_int32_t p;
793 #endif
794
795 buf = BIOS_PADDRTOVADDR(adp->va_window);
796 v = readw(buf);
797 writew(buf, 0xA55A);
798 if (readw(buf) != 0xA55A)
799 return ENXIO;
800 writew(buf, v);
801
802 switch (adp->va_type) {
803
804 case KD_EGA:
805 outb(adp->va_crtc_addr, 7);
806 if (inb(adp->va_crtc_addr) == 7) {
807 adp->va_type = KD_VGA;
808 adp->va_name = "vga";
809 adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE;
810 }
811 adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER;
812 /* the color adapter may be in the 40x25 mode... XXX */
813
814 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
815 /* get the BIOS video mode pointer */
816 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
817 p = BIOS_SADDRTOLADDR(p);
818 if (ISMAPPED(p, sizeof(u_int32_t))) {
819 p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
820 p = BIOS_SADDRTOLADDR(p);
821 if (ISMAPPED(p, V_MODE_PARAM_SIZE))
822 video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
823 }
824 #endif
825 break;
826
827 case KD_CGA:
828 adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER;
829 /* may be in the 40x25 mode... XXX */
830 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
831 /* get the BIOS video mode pointer */
832 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
833 p = BIOS_SADDRTOLADDR(p);
834 video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
835 #endif
836 break;
837
838 case KD_MONO:
839 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
840 /* get the BIOS video mode pointer */
841 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
842 p = BIOS_SADDRTOLADDR(p);
843 video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
844 #endif
845 break;
846 }
847
848 return 0;
849 }
850
851 static void
852 update_adapter_info(video_adapter_t *adp, video_info_t *info)
853 {
854 adp->va_flags &= ~V_ADP_COLOR;
855 adp->va_flags |=
856 (info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
857 adp->va_crtc_addr =
858 (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
859 adp->va_window = BIOS_PADDRTOVADDR(info->vi_window);
860 adp->va_window_size = info->vi_window_size;
861 adp->va_window_gran = info->vi_window_gran;
862 adp->va_window_orig = 0;
863 /* XXX */
864 adp->va_buffer = info->vi_buffer;
865 adp->va_buffer_size = info->vi_buffer_size;
866 if (info->vi_mem_model == V_INFO_MM_VGAX) {
867 adp->va_line_width = info->vi_width/2;
868 } else if (info->vi_flags & V_INFO_GRAPHICS) {
869 switch (info->vi_depth/info->vi_planes) {
870 case 1:
871 adp->va_line_width = info->vi_width/8;
872 break;
873 case 2:
874 adp->va_line_width = info->vi_width/4;
875 break;
876 case 4:
877 adp->va_line_width = info->vi_width/2;
878 break;
879 case 8:
880 default: /* shouldn't happen */
881 adp->va_line_width = info->vi_width;
882 break;
883 }
884 } else {
885 adp->va_line_width = info->vi_width;
886 }
887 adp->va_disp_start.x = 0;
888 adp->va_disp_start.y = 0;
889 bcopy(info, &adp->va_info, sizeof(adp->va_info));
890 }
891
892 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
893 /* compare two parameter table entries */
894 static int
895 comp_adpregs(u_char *buf1, u_char *buf2)
896 {
897 static struct {
898 u_char mask;
899 } params[V_MODE_PARAM_SIZE] = {
900 {0xff}, {0x00}, {0xff}, /* COLS}, ROWS}, POINTS */
901 {0x00}, {0x00}, /* page length */
902 {0xfe}, {0xff}, {0xff}, {0xff}, /* sequencer registers */
903 {0xf3}, /* misc register */
904 {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, /* CRTC */
905 {0xff}, {0xff}, {0xff}, {0x7f}, {0xff},
906 {0x00}, {0x00}, {0x00}, {0x00}, {0x00},
907 {0x00}, {0xff}, {0x7f}, {0xff}, {0xff},
908 {0x7f}, {0xff}, {0xff}, {0xef}, {0xff},
909 {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* attribute controller regs */
910 {0xff}, {0xff}, {0xff}, {0xff}, {0xff},
911 {0xff}, {0xff}, {0xff}, {0xff}, {0xff},
912 {0xff}, {0xff}, {0xff}, {0xff}, {0xf0},
913 {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* GDC register */
914 {0xff}, {0xff}, {0xff}, {0xff},
915 };
916 int identical = TRUE;
917 int i;
918
919 if ((buf1 == NULL) || (buf2 == NULL))
920 return COMP_DIFFERENT;
921
922 for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
923 if (params[i].mask == 0) /* don't care */
924 continue;
925 if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
926 return COMP_DIFFERENT;
927 if (buf1[i] != buf2[i])
928 identical = FALSE;
929 }
930 return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
931 }
932 #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
933
934 /* probe video adapters and return the number of detected adapters */
935 static int
936 probe_adapters(void)
937 {
938 video_adapter_t *adp;
939 video_info_t info;
940 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
941 u_char *mp;
942 #endif
943 int i;
944
945 /* do this test only once */
946 if (vga_init_done)
947 return biosadapters;
948 vga_init_done = TRUE;
949
950 /*
951 * Locate display adapters.
952 * The AT architecture supports upto two adapters. `syscons' allows
953 * the following combinations of adapters:
954 * 1) MDA + CGA
955 * 2) MDA + EGA/VGA color
956 * 3) CGA + EGA/VGA mono
957 * Note that `syscons' doesn't bother with MCGA as it is only
958 * avaiable for low end PS/2 models which has 80286 or earlier CPUs,
959 * thus, they are not running FreeBSD!
960 * When there are two adapaters in the system, one becomes `primary'
961 * and the other `secondary'. The EGA adapter has a set of DIP
962 * switches on board for this information and the EGA BIOS copies
963 * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88).
964 * The VGA BIOS has more sophisticated mechanism and has this
965 * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains
966 * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
967 */
968
969 /*
970 * Check rtc and BIOS data area.
971 * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead
972 * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are
973 * zeros for EGA and VGA. However, the EGA/VGA BIOS sets
974 * these bits in BIOSDATA_EQUIPMENT according to the monitor
975 * type detected.
976 */
977 #ifndef VGA_NO_BIOS
978 if (*(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8)) {
979 /* EGA/VGA BIOS is present */
980 fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f,
981 biosadapter);
982 } else {
983 switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */
984 case 0:
985 /* EGA/VGA: shouldn't be happening */
986 fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f,
987 biosadapter);
988 break;
989 case 1:
990 /* CGA 40x25 */
991 /* FIXME: switch to the 80x25 mode? XXX */
992 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40];
993 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
994 break;
995 case 2:
996 /* CGA 80x25 */
997 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80];
998 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
999 break;
1000 case 3:
1001 /* MDA */
1002 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
1003 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
1004 break;
1005 }
1006 }
1007 #else
1008 /* assume EGA/VGA? XXX */
1009 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80];
1010 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
1011 #endif /* VGA_NO_BIOS */
1012
1013 biosadapters = 0;
1014 if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) {
1015 ++biosadapters;
1016 biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED;
1017 biosadapter[V_ADP_SECONDARY].va_mode =
1018 biosadapter[V_ADP_SECONDARY].va_initial_mode =
1019 map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type,
1020 biosadapter[V_ADP_SECONDARY].va_flags
1021 & V_ADP_COLOR,
1022 biosadapter[V_ADP_SECONDARY].va_initial_bios_mode);
1023 } else {
1024 biosadapter[V_ADP_SECONDARY].va_type = -1;
1025 }
1026 if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) {
1027 ++biosadapters;
1028 biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED;
1029 #ifndef VGA_NO_BIOS
1030 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode =
1031 readb(BIOS_PADDRTOVADDR(0x449));
1032 #else
1033 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */
1034 #endif
1035 biosadapter[V_ADP_PRIMARY].va_mode =
1036 biosadapter[V_ADP_PRIMARY].va_initial_mode =
1037 map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type,
1038 biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR,
1039 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode);
1040 } else {
1041 biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY];
1042 biosadapter[V_ADP_SECONDARY].va_type = -1;
1043 }
1044 if (biosadapters == 0)
1045 return biosadapters;
1046 biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY;
1047 biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY;
1048
1049 #if 0 /* we don't need these... */
1050 fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...);
1051 fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...);
1052 #endif
1053
1054 #if notyet
1055 /*
1056 * We cannot have two video adapter of the same type; there must be
1057 * only one of color or mono adapter, or one each of them.
1058 */
1059 if (biosadapters > 1) {
1060 if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags)
1061 & V_ADP_COLOR))
1062 /* we have two mono or color adapters!! */
1063 return (biosadapters = 0);
1064 }
1065 #endif
1066
1067 /*
1068 * Ensure a zero start address. The registers are w/o
1069 * for old hardware so it's too hard to relocate the active screen
1070 * memory.
1071 * This must be done before vga_save_state() for VGA.
1072 */
1073 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12);
1074 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
1075 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13);
1076 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
1077
1078 /* the video mode parameter table in EGA/VGA BIOS */
1079 /* NOTE: there can be only one EGA/VGA, wheather color or mono,
1080 * recognized by the video BIOS.
1081 */
1082 if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) ||
1083 (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) {
1084 adp = &biosadapter[V_ADP_PRIMARY];
1085 } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) ||
1086 (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) {
1087 adp = &biosadapter[V_ADP_SECONDARY];
1088 } else {
1089 adp = NULL;
1090 }
1091 bzero(mode_map, sizeof(mode_map));
1092 if (adp != NULL) {
1093 if (adp->va_type == KD_VGA) {
1094 vga_save_state(adp, &adpstate, sizeof(adpstate));
1095 #if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
1096 mode_map[adp->va_initial_mode] = adpstate.regs;
1097 rows_offset = 1;
1098 #else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1099 if (video_mode_ptr == NULL) {
1100 mode_map[adp->va_initial_mode] = adpstate.regs;
1101 rows_offset = 1;
1102 } else {
1103 /* discard the table if we are not familiar with it... */
1104 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
1105 mp = get_mode_param(adp->va_initial_mode);
1106 if (mp != NULL)
1107 bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
1108 switch (comp_adpregs(adpstate.regs, mp)) {
1109 case COMP_IDENTICAL:
1110 /*
1111 * OK, this parameter table looks reasonably familiar
1112 * to us...
1113 */
1114 /*
1115 * This is a kludge for Toshiba DynaBook SS433
1116 * whose BIOS video mode table entry has the actual #
1117 * of rows at the offset 1; BIOSes from other
1118 * manufacturers store the # of rows - 1 there. XXX
1119 */
1120 rows_offset = adpstate.regs[1] + 1 - mp[1];
1121 break;
1122
1123 case COMP_SIMILAR:
1124 /*
1125 * Not exactly the same, but similar enough to be
1126 * trusted. However, use the saved register values
1127 * for the initial mode and other modes which are
1128 * based on the initial mode.
1129 */
1130 mode_map[adp->va_initial_mode] = adpstate.regs;
1131 rows_offset = adpstate.regs[1] + 1 - mp[1];
1132 adpstate.regs[1] -= rows_offset - 1;
1133 break;
1134
1135 case COMP_DIFFERENT:
1136 default:
1137 /*
1138 * Don't use the paramter table in BIOS. It doesn't
1139 * look familiar to us. Video mode switching is allowed
1140 * only if the new mode is the same as or based on
1141 * the initial mode.
1142 */
1143 video_mode_ptr = NULL;
1144 bzero(mode_map, sizeof(mode_map));
1145 mode_map[adp->va_initial_mode] = adpstate.regs;
1146 rows_offset = 1;
1147 break;
1148 }
1149 }
1150 #endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1151
1152 #ifndef VGA_NO_MODE_CHANGE
1153 adp->va_flags |= V_ADP_MODECHANGE;
1154 #endif
1155 #ifndef VGA_NO_FONT_LOADING
1156 adp->va_flags |= V_ADP_FONT;
1157 #endif
1158 } else if (adp->va_type == KD_EGA) {
1159 #if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
1160 rows_offset = 1;
1161 #else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1162 if (video_mode_ptr == NULL) {
1163 rows_offset = 1;
1164 } else {
1165 map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1);
1166 /* XXX how can one validate the EGA table... */
1167 mp = get_mode_param(adp->va_initial_mode);
1168 if (mp != NULL) {
1169 adp->va_flags |= V_ADP_MODECHANGE;
1170 #ifndef VGA_NO_FONT_LOADING
1171 adp->va_flags |= V_ADP_FONT;
1172 #endif
1173 rows_offset = 1;
1174 } else {
1175 /*
1176 * This is serious. We will not be able to switch video
1177 * modes at all...
1178 */
1179 video_mode_ptr = NULL;
1180 bzero(mode_map, sizeof(mode_map));
1181 rows_offset = 1;
1182 }
1183 }
1184 #endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1185 }
1186 }
1187
1188 /* remove conflicting modes if we have more than one adapter */
1189 if (biosadapters > 0) {
1190 for (i = 0; i < biosadapters; ++i) {
1191 if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE))
1192 continue;
1193 clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1,
1194 (biosadapter[i].va_flags & V_ADP_COLOR) ?
1195 V_INFO_COLOR : 0);
1196 if ((biosadapter[i].va_type == KD_VGA)
1197 || (biosadapter[i].va_type == KD_EGA)) {
1198 biosadapter[i].va_io_base =
1199 (biosadapter[i].va_flags & V_ADP_COLOR) ?
1200 IO_VGA : IO_MDA;
1201 biosadapter[i].va_io_size = 32;
1202 }
1203 }
1204 }
1205
1206 /* buffer address */
1207 vga_get_info(&biosadapter[V_ADP_PRIMARY],
1208 biosadapter[V_ADP_PRIMARY].va_initial_mode, &info);
1209 info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
1210 update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info);
1211
1212 if (biosadapters > 1) {
1213 vga_get_info(&biosadapter[V_ADP_SECONDARY],
1214 biosadapter[V_ADP_SECONDARY].va_initial_mode, &info);
1215 info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
1216 update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info);
1217 }
1218
1219 /*
1220 * XXX: we should verify the following values for the primary adapter...
1221 * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
1222 * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02)
1223 * ? 0 : V_ADP_COLOR;
1224 * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
1225 * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
1226 * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
1227 * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
1228 */
1229
1230 return biosadapters;
1231 }
1232
1233 /* set the scan line length in pixel */
1234 static int
1235 set_line_length(video_adapter_t *adp, int pixel)
1236 {
1237 u_char *mp;
1238 int ppw; /* pixels per word */
1239 int bpl; /* bytes per line */
1240 int count;
1241
1242 if ((adp->va_type != KD_VGA) && (adp->va_type != KD_EGA))
1243 return ENODEV;
1244 mp = get_mode_param(adp->va_mode);
1245 if (mp == NULL)
1246 return EINVAL;
1247
1248 switch (adp->va_info.vi_mem_model) {
1249 case V_INFO_MM_PLANAR:
1250 ppw = 16/(adp->va_info.vi_depth/adp->va_info.vi_planes);
1251 count = (pixel + ppw - 1)/ppw/2;
1252 bpl = ((pixel + ppw - 1)/ppw/2)*4;
1253 break;
1254 case V_INFO_MM_PACKED:
1255 count = (pixel + 7)/8;
1256 bpl = ((pixel + 7)/8)*8;
1257 break;
1258 case V_INFO_MM_TEXT:
1259 count = (pixel + 7)/8; /* columns */
1260 bpl = (pixel + 7)/8; /* columns */
1261 break;
1262 default:
1263 return ENODEV;
1264 }
1265
1266 if (mp[10 + 0x17] & 0x40) /* CRTC mode control reg */
1267 count *= 2; /* byte mode */
1268 outb(adp->va_crtc_addr, 0x13);
1269 outb(adp->va_crtc_addr + 1, count);
1270 adp->va_line_width = bpl;
1271
1272 return 0;
1273 }
1274
1275 static int
1276 set_display_start(video_adapter_t *adp, int x, int y)
1277 {
1278 int off; /* byte offset (graphics mode)/word offset (text mode) */
1279 int poff; /* pixel offset */
1280 int roff; /* row offset */
1281 int ppb; /* pixels per byte */
1282
1283 if ((adp->va_type != KD_VGA) && (adp->va_type != KD_EGA))
1284 x &= ~7;
1285 if (adp->va_info.vi_flags & V_INFO_GRAPHICS) {
1286 ppb = 8/(adp->va_info.vi_depth/adp->va_info.vi_planes);
1287 off = y*adp->va_line_width + x/ppb;
1288 roff = 0;
1289 poff = x%ppb;
1290 } else {
1291 if ((adp->va_type == KD_VGA) || (adp->va_type == KD_EGA)) {
1292 outb(TSIDX, 1);
1293 if (inb(TSREG) & 1)
1294 ppb = 9;
1295 else
1296 ppb = 8;
1297 } else {
1298 ppb = 8;
1299 }
1300 off = y/adp->va_info.vi_cheight*adp->va_line_width + x/ppb;
1301 roff = y%adp->va_info.vi_cheight;
1302 /* FIXME: is this correct? XXX */
1303 if (ppb == 8)
1304 poff = x%ppb;
1305 else
1306 poff = (x + 8)%ppb;
1307 }
1308
1309 /* start address */
1310 outb(adp->va_crtc_addr, 0xc); /* high */
1311 outb(adp->va_crtc_addr + 1, off >> 8);
1312 outb(adp->va_crtc_addr, 0xd); /* low */
1313 outb(adp->va_crtc_addr + 1, off & 0xff);
1314
1315 /* horizontal pel pan */
1316 if ((adp->va_type == KD_VGA) || (adp->va_type == KD_EGA)) {
1317 inb(adp->va_crtc_addr + 6);
1318 outb(ATC, 0x13 | 0x20);
1319 outb(ATC, poff);
1320 inb(adp->va_crtc_addr + 6);
1321 outb(ATC, 0x20);
1322 }
1323
1324 /* preset raw scan */
1325 outb(adp->va_crtc_addr, 8);
1326 outb(adp->va_crtc_addr + 1, roff);
1327
1328 adp->va_disp_start.x = x;
1329 adp->va_disp_start.y = y;
1330 return 0;
1331 }
1332
1333 #if defined(__i386__) || defined(__amd64__) /* XXX */
1334 static void
1335 fill(int val, void *d, size_t size)
1336 {
1337 u_char *p = d;
1338
1339 while (size-- > 0)
1340 *p++ = val;
1341 }
1342 #endif /* __i386__ */
1343
1344 static void
1345 filll_io(int val, vm_offset_t d, size_t size)
1346 {
1347 while (size-- > 0) {
1348 writel(d, val);
1349 d += sizeof(u_int32_t);
1350 }
1351 }
1352
1353 /* entry points */
1354
1355 #if 0
1356 static int
1357 vga_nop(void)
1358 {
1359 return 0;
1360 }
1361 #endif
1362
1363 static int
1364 vga_error(void)
1365 {
1366 return ENODEV;
1367 }
1368
1369 static int
1370 vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
1371 {
1372 probe_adapters();
1373 if (unit >= biosadapters)
1374 return ENXIO;
1375
1376 *adpp = &biosadapter[unit];
1377
1378 return 0;
1379 }
1380
1381 static int
1382 vga_init(int unit, video_adapter_t *adp, int flags)
1383 {
1384 if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp))
1385 return ENXIO;
1386
1387 if (!init_done(adp)) {
1388 /* nothing to do really... */
1389 adp->va_flags |= V_ADP_INITIALIZED;
1390 }
1391
1392 if (!config_done(adp)) {
1393 if (vid_register(adp) < 0)
1394 return ENXIO;
1395 adp->va_flags |= V_ADP_REGISTERED;
1396 }
1397 if (vga_sub_configure != NULL)
1398 (*vga_sub_configure)(0);
1399
1400 return 0;
1401 }
1402
1403 /*
1404 * get_info():
1405 * Return the video_info structure of the requested video mode.
1406 *
1407 * all adapters
1408 */
1409 static int
1410 vga_get_info(video_adapter_t *adp, int mode, video_info_t *info)
1411 {
1412 int i;
1413
1414 if (!vga_init_done)
1415 return ENXIO;
1416
1417 mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
1418 #ifndef VGA_NO_MODE_CHANGE
1419 if (adp->va_flags & V_ADP_MODECHANGE) {
1420 /*
1421 * If the parameter table entry for this mode is not found,
1422 * the mode is not supported...
1423 */
1424 if (get_mode_param(mode) == NULL)
1425 return EINVAL;
1426 } else
1427 #endif /* VGA_NO_MODE_CHANGE */
1428 {
1429 /*
1430 * Even if we don't support video mode switching on this adapter,
1431 * the information on the initial (thus current) video mode
1432 * should be made available.
1433 */
1434 if (mode != adp->va_initial_mode)
1435 return EINVAL;
1436 }
1437
1438 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1439 if (bios_vmode[i].vi_mode == NA)
1440 continue;
1441 if (mode == bios_vmode[i].vi_mode) {
1442 *info = bios_vmode[i];
1443 /* XXX */
1444 info->vi_buffer_size = info->vi_window_size*info->vi_planes;
1445 return 0;
1446 }
1447 }
1448 return EINVAL;
1449 }
1450
1451 /*
1452 * query_mode():
1453 * Find a video mode matching the requested parameters.
1454 * Fields filled with 0 are considered "don't care" fields and
1455 * match any modes.
1456 *
1457 * all adapters
1458 */
1459 static int
1460 vga_query_mode(video_adapter_t *adp, video_info_t *info)
1461 {
1462 int i;
1463
1464 if (!vga_init_done)
1465 return ENXIO;
1466
1467 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1468 if (bios_vmode[i].vi_mode == NA)
1469 continue;
1470
1471 if ((info->vi_width != 0)
1472 && (info->vi_width != bios_vmode[i].vi_width))
1473 continue;
1474 if ((info->vi_height != 0)
1475 && (info->vi_height != bios_vmode[i].vi_height))
1476 continue;
1477 if ((info->vi_cwidth != 0)
1478 && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
1479 continue;
1480 if ((info->vi_cheight != 0)
1481 && (info->vi_cheight != bios_vmode[i].vi_cheight))
1482 continue;
1483 if ((info->vi_depth != 0)
1484 && (info->vi_depth != bios_vmode[i].vi_depth))
1485 continue;
1486 if ((info->vi_planes != 0)
1487 && (info->vi_planes != bios_vmode[i].vi_planes))
1488 continue;
1489 /* XXX: should check pixel format, memory model */
1490 if ((info->vi_flags != 0)
1491 && (info->vi_flags != bios_vmode[i].vi_flags))
1492 continue;
1493
1494 /* verify if this mode is supported on this adapter */
1495 if (vga_get_info(adp, bios_vmode[i].vi_mode, info))
1496 continue;
1497 return 0;
1498 }
1499 return ENODEV;
1500 }
1501
1502 /*
1503 * set_mode():
1504 * Change the video mode.
1505 *
1506 * EGA/VGA
1507 */
1508
1509 #ifndef VGA_NO_MODE_CHANGE
1510 #ifdef VGA_WIDTH90
1511 static void
1512 set_width90(adp_state_t *params)
1513 {
1514 /*
1515 * Based on code submitted by Kelly Yancey (kbyanc@freedomnet.com)
1516 * and alexv@sui.gda.itesm.mx.
1517 */
1518 params->regs[5] |= 1; /* toggle 8 pixel wide fonts */
1519 params->regs[10+0x0] = 0x6b;
1520 params->regs[10+0x1] = 0x59;
1521 params->regs[10+0x2] = 0x5a;
1522 params->regs[10+0x3] = 0x8e;
1523 params->regs[10+0x4] = 0x5e;
1524 params->regs[10+0x5] = 0x8a;
1525 params->regs[10+0x13] = 45;
1526 params->regs[35+0x13] = 0;
1527 }
1528 #endif /* VGA_WIDTH90 */
1529 #endif /* !VGA_NO_MODE_CHANGE */
1530
1531 static int
1532 vga_set_mode(video_adapter_t *adp, int mode)
1533 {
1534 #ifndef VGA_NO_MODE_CHANGE
1535 video_info_t info;
1536 adp_state_t params;
1537
1538 prologue(adp, V_ADP_MODECHANGE, ENODEV);
1539
1540 mode = map_gen_mode_num(adp->va_type,
1541 adp->va_flags & V_ADP_COLOR, mode);
1542 if (vga_get_info(adp, mode, &info))
1543 return EINVAL;
1544
1545 #if VGA_DEBUG > 1
1546 printf("vga_set_mode(): setting mode %d\n", mode);
1547 #endif
1548
1549 params.sig = V_STATE_SIG;
1550 bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
1551
1552 switch (mode) {
1553 #ifdef VGA_WIDTH90
1554 case M_VGA_C90x60: case M_VGA_M90x60:
1555 set_width90(¶ms);
1556 /* FALLTHROUGH */
1557 #endif
1558 case M_VGA_C80x60: case M_VGA_M80x60:
1559 params.regs[2] = 0x08;
1560 params.regs[19] = 0x47;
1561 goto special_480l;
1562
1563 #ifdef VGA_WIDTH90
1564 case M_VGA_C90x30: case M_VGA_M90x30:
1565 set_width90(¶ms);
1566 /* FALLTHROUGH */
1567 #endif
1568 case M_VGA_C80x30: case M_VGA_M80x30:
1569 params.regs[19] = 0x4f;
1570 special_480l:
1571 params.regs[9] |= 0xc0;
1572 params.regs[16] = 0x08;
1573 params.regs[17] = 0x3e;
1574 params.regs[26] = 0xea;
1575 params.regs[28] = 0xdf;
1576 params.regs[31] = 0xe7;
1577 params.regs[32] = 0x04;
1578 goto setup_mode;
1579
1580 #ifdef VGA_WIDTH90
1581 case M_VGA_C90x43: case M_VGA_M90x43:
1582 set_width90(¶ms);
1583 /* FALLTHROUGH */
1584 #endif
1585 case M_ENH_C80x43: case M_ENH_B80x43:
1586 params.regs[28] = 87;
1587 goto special_80x50;
1588
1589 #ifdef VGA_WIDTH90
1590 case M_VGA_C90x50: case M_VGA_M90x50:
1591 set_width90(¶ms);
1592 /* FALLTHROUGH */
1593 #endif
1594 case M_VGA_C80x50: case M_VGA_M80x50:
1595 special_80x50:
1596 params.regs[2] = 8;
1597 params.regs[19] = 7;
1598 goto setup_mode;
1599
1600 #ifdef VGA_WIDTH90
1601 case M_VGA_C90x25: case M_VGA_M90x25:
1602 set_width90(¶ms);
1603 /* FALLTHROUGH */
1604 #endif
1605 case M_VGA_C40x25: case M_VGA_C80x25:
1606 case M_VGA_M80x25:
1607 case M_B40x25: case M_C40x25:
1608 case M_B80x25: case M_C80x25:
1609 case M_ENH_B40x25: case M_ENH_C40x25:
1610 case M_ENH_B80x25: case M_ENH_C80x25:
1611 case M_EGAMONO80x25:
1612
1613 setup_mode:
1614 vga_load_state(adp, ¶ms);
1615 break;
1616
1617 case M_VGA_MODEX:
1618 /* "unchain" the VGA mode */
1619 params.regs[5-1+0x04] &= 0xf7;
1620 params.regs[5-1+0x04] |= 0x04;
1621 /* turn off doubleword mode */
1622 params.regs[10+0x14] &= 0xbf;
1623 /* turn off word addressing */
1624 params.regs[10+0x17] |= 0x40;
1625 /* set logical screen width */
1626 params.regs[10+0x13] = 80;
1627 /* set 240 lines */
1628 params.regs[10+0x11] = 0x2c;
1629 params.regs[10+0x06] = 0x0d;
1630 params.regs[10+0x07] = 0x3e;
1631 params.regs[10+0x10] = 0xea;
1632 params.regs[10+0x11] = 0xac;
1633 params.regs[10+0x12] = 0xdf;
1634 params.regs[10+0x15] = 0xe7;
1635 params.regs[10+0x16] = 0x06;
1636 /* set vertical sync polarity to reflect aspect ratio */
1637 params.regs[9] = 0xe3;
1638 goto setup_grmode;
1639
1640 case M_BG320: case M_CG320: case M_BG640:
1641 case M_CG320_D: case M_CG640_E:
1642 case M_CG640x350: case M_ENH_CG640:
1643 case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
1644
1645 setup_grmode:
1646 vga_load_state(adp, ¶ms);
1647 break;
1648
1649 default:
1650 return EINVAL;
1651 }
1652
1653 adp->va_mode = mode;
1654 info.vi_flags &= ~V_INFO_LINEAR; /* XXX */
1655 update_adapter_info(adp, &info);
1656
1657 /* move hardware cursor out of the way */
1658 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
1659
1660 return 0;
1661 #else /* VGA_NO_MODE_CHANGE */
1662 return ENODEV;
1663 #endif /* VGA_NO_MODE_CHANGE */
1664 }
1665
1666 #ifndef VGA_NO_FONT_LOADING
1667
1668 static void
1669 set_font_mode(video_adapter_t *adp, u_char *buf)
1670 {
1671 u_char *mp;
1672 int s;
1673
1674 s = splhigh();
1675
1676 /* save register values */
1677 if (adp->va_type == KD_VGA) {
1678 outb(TSIDX, 0x02); buf[0] = inb(TSREG);
1679 outb(TSIDX, 0x04); buf[1] = inb(TSREG);
1680 outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
1681 outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
1682 outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
1683 inb(adp->va_crtc_addr + 6);
1684 outb(ATC, 0x10); buf[5] = inb(ATC + 1);
1685 } else /* if (adp->va_type == KD_EGA) */ {
1686 /*
1687 * EGA cannot be read; copy parameters from the mode parameter
1688 * table.
1689 */
1690 mp = get_mode_param(adp->va_mode);
1691 buf[0] = mp[5 + 0x02 - 1];
1692 buf[1] = mp[5 + 0x04 - 1];
1693 buf[2] = mp[55 + 0x04];
1694 buf[3] = mp[55 + 0x05];
1695 buf[4] = mp[55 + 0x06];
1696 buf[5] = mp[35 + 0x10];
1697 }
1698
1699 /* setup vga for loading fonts */
1700 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1701 outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
1702 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1703 outb(ATC, 0x20); /* enable palette */
1704
1705 #if VGA_SLOW_IOACCESS
1706 #ifdef VGA_ALT_SEQACCESS
1707 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1708 #endif
1709 outb(TSIDX, 0x02); outb(TSREG, 0x04);
1710 outb(TSIDX, 0x04); outb(TSREG, 0x07);
1711 #ifdef VGA_ALT_SEQACCESS
1712 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1713 #endif
1714 outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
1715 outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
1716 outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
1717 #else /* VGA_SLOW_IOACCESS */
1718 #ifdef VGA_ALT_SEQACCESS
1719 outw(TSIDX, 0x0100);
1720 #endif
1721 outw(TSIDX, 0x0402);
1722 outw(TSIDX, 0x0704);
1723 #ifdef VGA_ALT_SEQACCESS
1724 outw(TSIDX, 0x0300);
1725 #endif
1726 outw(GDCIDX, 0x0204);
1727 outw(GDCIDX, 0x0005);
1728 outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */
1729 #endif /* VGA_SLOW_IOACCESS */
1730
1731 splx(s);
1732 }
1733
1734 static void
1735 set_normal_mode(video_adapter_t *adp, u_char *buf)
1736 {
1737 int s;
1738
1739 s = splhigh();
1740
1741 /* setup vga for normal operation mode again */
1742 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1743 outb(ATC, 0x10); outb(ATC, buf[5]);
1744 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1745 outb(ATC, 0x20); /* enable palette */
1746
1747 #if VGA_SLOW_IOACCESS
1748 #ifdef VGA_ALT_SEQACCESS
1749 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1750 #endif
1751 outb(TSIDX, 0x02); outb(TSREG, buf[0]);
1752 outb(TSIDX, 0x04); outb(TSREG, buf[1]);
1753 #ifdef VGA_ALT_SEQACCESS
1754 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1755 #endif
1756 outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
1757 outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
1758 if (adp->va_crtc_addr == MONO_CRTC) {
1759 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
1760 } else {
1761 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
1762 }
1763 #else /* VGA_SLOW_IOACCESS */
1764 #ifdef VGA_ALT_SEQACCESS
1765 outw(TSIDX, 0x0100);
1766 #endif
1767 outw(TSIDX, 0x0002 | (buf[0] << 8));
1768 outw(TSIDX, 0x0004 | (buf[1] << 8));
1769 #ifdef VGA_ALT_SEQACCESS
1770 outw(TSIDX, 0x0300);
1771 #endif
1772 outw(GDCIDX, 0x0004 | (buf[2] << 8));
1773 outw(GDCIDX, 0x0005 | (buf[3] << 8));
1774 if (adp->va_crtc_addr == MONO_CRTC)
1775 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
1776 else
1777 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
1778 #endif /* VGA_SLOW_IOACCESS */
1779
1780 splx(s);
1781 }
1782
1783 #endif /* VGA_NO_FONT_LOADING */
1784
1785 /*
1786 * save_font():
1787 * Read the font data in the requested font page from the video adapter.
1788 *
1789 * EGA/VGA
1790 */
1791 static int
1792 vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1793 int ch, int count)
1794 {
1795 #ifndef VGA_NO_FONT_LOADING
1796 u_char buf[PARAM_BUFSIZE];
1797 vm_offset_t segment;
1798 int c;
1799 #ifdef VGA_ALT_SEQACCESS
1800 int s;
1801 u_char val = 0;
1802 #endif
1803
1804 prologue(adp, V_ADP_FONT, ENODEV);
1805
1806 if (fontsize < 14) {
1807 /* FONT_8 */
1808 fontsize = 8;
1809 } else if (fontsize >= 32) {
1810 fontsize = 32;
1811 } else if (fontsize >= 16) {
1812 /* FONT_16 */
1813 fontsize = 16;
1814 } else {
1815 /* FONT_14 */
1816 fontsize = 14;
1817 }
1818
1819 if (page < 0 || page >= 8)
1820 return EINVAL;
1821 segment = FONT_BUF + 0x4000*page;
1822 if (page > 3)
1823 segment -= 0xe000;
1824
1825 #ifdef VGA_ALT_SEQACCESS
1826 if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
1827 s = splhigh();
1828 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1829 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1830 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1831 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1832 splx(s);
1833 }
1834 #endif
1835
1836 set_font_mode(adp, buf);
1837 if (fontsize == 32) {
1838 bcopy_fromio((uintptr_t)segment + ch*32, data, fontsize*count);
1839 } else {
1840 for (c = ch; count > 0; ++c, --count) {
1841 bcopy_fromio((uintptr_t)segment + c*32, data, fontsize);
1842 data += fontsize;
1843 }
1844 }
1845 set_normal_mode(adp, buf);
1846
1847 #ifdef VGA_ALT_SEQACCESS
1848 if (adp->va_type == KD_VGA) {
1849 s = splhigh();
1850 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1851 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1852 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1853 splx(s);
1854 }
1855 #endif
1856
1857 return 0;
1858 #else /* VGA_NO_FONT_LOADING */
1859 return ENODEV;
1860 #endif /* VGA_NO_FONT_LOADING */
1861 }
1862
1863 /*
1864 * load_font():
1865 * Set the font data in the requested font page.
1866 * NOTE: it appears that some recent video adapters do not support
1867 * the font page other than 0... XXX
1868 *
1869 * EGA/VGA
1870 */
1871 static int
1872 vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1873 int ch, int count)
1874 {
1875 #ifndef VGA_NO_FONT_LOADING
1876 u_char buf[PARAM_BUFSIZE];
1877 vm_offset_t segment;
1878 int c;
1879 #ifdef VGA_ALT_SEQACCESS
1880 int s;
1881 u_char val = 0;
1882 #endif
1883
1884 prologue(adp, V_ADP_FONT, ENODEV);
1885
1886 if (fontsize < 14) {
1887 /* FONT_8 */
1888 fontsize = 8;
1889 } else if (fontsize >= 32) {
1890 fontsize = 32;
1891 } else if (fontsize >= 16) {
1892 /* FONT_16 */
1893 fontsize = 16;
1894 } else {
1895 /* FONT_14 */
1896 fontsize = 14;
1897 }
1898
1899 if (page < 0 || page >= 8)
1900 return EINVAL;
1901 segment = FONT_BUF + 0x4000*page;
1902 if (page > 3)
1903 segment -= 0xe000;
1904
1905 #ifdef VGA_ALT_SEQACCESS
1906 if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
1907 s = splhigh();
1908 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1909 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1910 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1911 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1912 splx(s);
1913 }
1914 #endif
1915
1916 set_font_mode(adp, buf);
1917 if (fontsize == 32) {
1918 bcopy_toio(data, (uintptr_t)segment + ch*32, fontsize*count);
1919 } else {
1920 for (c = ch; count > 0; ++c, --count) {
1921 bcopy_toio(data, (uintptr_t)segment + c*32, fontsize);
1922 data += fontsize;
1923 }
1924 }
1925 set_normal_mode(adp, buf);
1926
1927 #ifdef VGA_ALT_SEQACCESS
1928 if (adp->va_type == KD_VGA) {
1929 s = splhigh();
1930 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1931 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1932 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1933 splx(s);
1934 }
1935 #endif
1936
1937 return 0;
1938 #else /* VGA_NO_FONT_LOADING */
1939 return ENODEV;
1940 #endif /* VGA_NO_FONT_LOADING */
1941 }
1942
1943 /*
1944 * show_font():
1945 * Activate the requested font page.
1946 * NOTE: it appears that some recent video adapters do not support
1947 * the font page other than 0... XXX
1948 *
1949 * EGA/VGA
1950 */
1951 static int
1952 vga_show_font(video_adapter_t *adp, int page)
1953 {
1954 #ifndef VGA_NO_FONT_LOADING
1955 static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
1956 int s;
1957
1958 prologue(adp, V_ADP_FONT, ENODEV);
1959 if (page < 0 || page >= 8)
1960 return EINVAL;
1961
1962 s = splhigh();
1963 outb(TSIDX, 0x03); outb(TSREG, cg[page]);
1964 splx(s);
1965
1966 return 0;
1967 #else /* VGA_NO_FONT_LOADING */
1968 return ENODEV;
1969 #endif /* VGA_NO_FONT_LOADING */
1970 }
1971
1972 /*
1973 * save_palette():
1974 * Read DAC values. The values have expressed in 8 bits.
1975 *
1976 * VGA
1977 */
1978 static int
1979 vga_save_palette(video_adapter_t *adp, u_char *palette)
1980 {
1981 int i;
1982
1983 prologue(adp, V_ADP_PALETTE, ENODEV);
1984
1985 /*
1986 * We store 8 bit values in the palette buffer, while the standard
1987 * VGA has 6 bit DAC .
1988 */
1989 outb(PALRADR, 0x00);
1990 for (i = 0; i < 256*3; ++i)
1991 palette[i] = inb(PALDATA) << 2;
1992 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
1993 return 0;
1994 }
1995
1996 static int
1997 vga_save_palette2(video_adapter_t *adp, int base, int count,
1998 u_char *r, u_char *g, u_char *b)
1999 {
2000 int i;
2001
2002 prologue(adp, V_ADP_PALETTE, ENODEV);
2003
2004 outb(PALRADR, base);
2005 for (i = 0; i < count; ++i) {
2006 r[i] = inb(PALDATA) << 2;
2007 g[i] = inb(PALDATA) << 2;
2008 b[i] = inb(PALDATA) << 2;
2009 }
2010 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
2011 return 0;
2012 }
2013
2014 /*
2015 * load_palette():
2016 * Set DAC values.
2017 *
2018 * VGA
2019 */
2020 static int
2021 vga_load_palette(video_adapter_t *adp, u_char *palette)
2022 {
2023 int i;
2024
2025 prologue(adp, V_ADP_PALETTE, ENODEV);
2026
2027 outb(PIXMASK, 0xff); /* no pixelmask */
2028 outb(PALWADR, 0x00);
2029 for (i = 0; i < 256*3; ++i)
2030 outb(PALDATA, palette[i] >> 2);
2031 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
2032 outb(ATC, 0x20); /* enable palette */
2033 return 0;
2034 }
2035
2036 static int
2037 vga_load_palette2(video_adapter_t *adp, int base, int count,
2038 u_char *r, u_char *g, u_char *b)
2039 {
2040 int i;
2041
2042 prologue(adp, V_ADP_PALETTE, ENODEV);
2043
2044 outb(PIXMASK, 0xff); /* no pixelmask */
2045 outb(PALWADR, base);
2046 for (i = 0; i < count; ++i) {
2047 outb(PALDATA, r[i] >> 2);
2048 outb(PALDATA, g[i] >> 2);
2049 outb(PALDATA, b[i] >> 2);
2050 }
2051 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
2052 outb(ATC, 0x20); /* enable palette */
2053 return 0;
2054 }
2055
2056 /*
2057 * set_border():
2058 * Change the border color.
2059 *
2060 * CGA/EGA/VGA
2061 */
2062 static int
2063 vga_set_border(video_adapter_t *adp, int color)
2064 {
2065 prologue(adp, V_ADP_BORDER, ENODEV);
2066
2067 switch (adp->va_type) {
2068 case KD_EGA:
2069 case KD_VGA:
2070 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
2071 outb(ATC, 0x31); outb(ATC, color & 0xff);
2072 break;
2073 case KD_CGA:
2074 outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */
2075 break;
2076 case KD_MONO:
2077 case KD_HERCULES:
2078 default:
2079 break;
2080 }
2081 return 0;
2082 }
2083
2084 /*
2085 * save_state():
2086 * Read video register values.
2087 * NOTE: this function only reads the standard EGA/VGA registers.
2088 * any extra/extended registers of SVGA adapters are not saved.
2089 *
2090 * VGA
2091 */
2092 static int
2093 vga_save_state(video_adapter_t *adp, void *p, size_t size)
2094 {
2095 video_info_t info;
2096 u_char *buf;
2097 int crtc_addr;
2098 int i, j;
2099 int s;
2100
2101 if (size == 0) {
2102 /* return the required buffer size */
2103 prologue(adp, V_ADP_STATESAVE, 0);
2104 return sizeof(adp_state_t);
2105 } else {
2106 prologue(adp, V_ADP_STATESAVE, ENODEV);
2107 if (size < sizeof(adp_state_t))
2108 return EINVAL;
2109 }
2110
2111 ((adp_state_t *)p)->sig = V_STATE_SIG;
2112 buf = ((adp_state_t *)p)->regs;
2113 bzero(buf, V_MODE_PARAM_SIZE);
2114 crtc_addr = adp->va_crtc_addr;
2115
2116 s = splhigh();
2117
2118 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
2119 for (i = 0, j = 5; i < 4; i++) {
2120 outb(TSIDX, i + 1);
2121 buf[j++] = inb(TSREG);
2122 }
2123 buf[9] = inb(MISC + 10); /* dot-clock */
2124 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
2125
2126 for (i = 0, j = 10; i < 25; i++) { /* crtc */
2127 outb(crtc_addr, i);
2128 buf[j++] = inb(crtc_addr + 1);
2129 }
2130 for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */
2131 inb(crtc_addr + 6); /* reset flip-flop */
2132 outb(ATC, i);
2133 buf[j++] = inb(ATC + 1);
2134 }
2135 for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */
2136 outb(GDCIDX, i);
2137 buf[j++] = inb(GDCREG);
2138 }
2139 inb(crtc_addr + 6); /* reset flip-flop */
2140 outb(ATC, 0x20); /* enable palette */
2141
2142 splx(s);
2143
2144 #if 1
2145 if (vga_get_info(adp, adp->va_mode, &info) == 0) {
2146 if (info.vi_flags & V_INFO_GRAPHICS) {
2147 buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
2148 buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
2149 } else {
2150 buf[0] = info.vi_width; /* COLS */
2151 buf[1] = info.vi_height - 1; /* ROWS */
2152 }
2153 buf[2] = info.vi_cheight; /* POINTS */
2154 } else {
2155 /* XXX: shouldn't be happening... */
2156 printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n",
2157 adp->va_unit, adp->va_name);
2158 }
2159 #else
2160 buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */
2161 buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */
2162 buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */
2163 buf[3] = readb(BIOS_PADDRTOVADDR(0x44c));
2164 buf[4] = readb(BIOS_PADDRTOVADDR(0x44d));
2165 #endif
2166
2167 return 0;
2168 }
2169
2170 /*
2171 * load_state():
2172 * Set video registers at once.
2173 * NOTE: this function only updates the standard EGA/VGA registers.
2174 * any extra/extended registers of SVGA adapters are not changed.
2175 *
2176 * EGA/VGA
2177 */
2178 static int
2179 vga_load_state(video_adapter_t *adp, void *p)
2180 {
2181 u_char *buf;
2182 int crtc_addr;
2183 int s;
2184 int i;
2185
2186 prologue(adp, V_ADP_STATELOAD, ENODEV);
2187 if (((adp_state_t *)p)->sig != V_STATE_SIG)
2188 return EINVAL;
2189
2190 buf = ((adp_state_t *)p)->regs;
2191 crtc_addr = adp->va_crtc_addr;
2192
2193 #if VGA_DEBUG > 1
2194 dump_buffer(buf, V_MODE_PARAM_SIZE);
2195 #endif
2196
2197 s = splhigh();
2198
2199 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
2200 for (i = 0; i < 4; ++i) { /* program sequencer */
2201 outb(TSIDX, i + 1);
2202 outb(TSREG, buf[i + 5]);
2203 }
2204 outb(MISC, buf[9]); /* set dot-clock */
2205 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
2206 outb(crtc_addr, 0x11);
2207 outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
2208 for (i = 0; i < 25; ++i) { /* program crtc */
2209 outb(crtc_addr, i);
2210 outb(crtc_addr + 1, buf[i + 10]);
2211 }
2212 inb(crtc_addr+6); /* reset flip-flop */
2213 for (i = 0; i < 20; ++i) { /* program attribute ctrl */
2214 outb(ATC, i);
2215 outb(ATC, buf[i + 35]);
2216 }
2217 for (i = 0; i < 9; ++i) { /* program graph data ctrl */
2218 outb(GDCIDX, i);
2219 outb(GDCREG, buf[i + 55]);
2220 }
2221 inb(crtc_addr + 6); /* reset flip-flop */
2222 outb(ATC, 0x20); /* enable palette */
2223
2224 #if notyet /* a temporary workaround for kernel panic, XXX */
2225 #ifndef VGA_NO_BIOS
2226 if (adp->va_unit == V_ADP_PRIMARY) {
2227 writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */
2228 writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */
2229 writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */
2230 #if 0
2231 writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]);
2232 writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]);
2233 #endif
2234 }
2235 #endif /* VGA_NO_BIOS */
2236 #endif /* notyet */
2237
2238 splx(s);
2239 return 0;
2240 }
2241
2242 /*
2243 * set_origin():
2244 * Change the origin (window mapping) of the banked frame buffer.
2245 */
2246 static int
2247 vga_set_origin(video_adapter_t *adp, off_t offset)
2248 {
2249 /*
2250 * The standard video modes do not require window mapping;
2251 * always return error.
2252 */
2253 return ENODEV;
2254 }
2255
2256 /*
2257 * read_hw_cursor():
2258 * Read the position of the hardware text cursor.
2259 *
2260 * all adapters
2261 */
2262 static int
2263 vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
2264 {
2265 u_int16_t off;
2266 int s;
2267
2268 if (!vga_init_done)
2269 return ENXIO;
2270
2271 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
2272 return ENODEV;
2273
2274 s = spltty();
2275 outb(adp->va_crtc_addr, 14);
2276 off = inb(adp->va_crtc_addr + 1);
2277 outb(adp->va_crtc_addr, 15);
2278 off = (off << 8) | inb(adp->va_crtc_addr + 1);
2279 splx(s);
2280
2281 *row = off / adp->va_info.vi_width;
2282 *col = off % adp->va_info.vi_width;
2283
2284 return 0;
2285 }
2286
2287 /*
2288 * set_hw_cursor():
2289 * Move the hardware text cursor. If col and row are both -1,
2290 * the cursor won't be shown.
2291 *
2292 * all adapters
2293 */
2294 static int
2295 vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
2296 {
2297 u_int16_t off;
2298 int s;
2299
2300 if (!vga_init_done)
2301 return ENXIO;
2302
2303 if ((col == -1) && (row == -1)) {
2304 off = -1;
2305 } else {
2306 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
2307 return ENODEV;
2308 off = row*adp->va_info.vi_width + col;
2309 }
2310
2311 s = spltty();
2312 outb(adp->va_crtc_addr, 14);
2313 outb(adp->va_crtc_addr + 1, off >> 8);
2314 outb(adp->va_crtc_addr, 15);
2315 outb(adp->va_crtc_addr + 1, off & 0x00ff);
2316 splx(s);
2317
2318 return 0;
2319 }
2320
2321 /*
2322 * set_hw_cursor_shape():
2323 * Change the shape of the hardware text cursor. If the height is
2324 * zero or negative, the cursor won't be shown.
2325 *
2326 * all adapters
2327 */
2328 static int
2329 vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
2330 int celsize, int blink)
2331 {
2332 int s;
2333
2334 if (!vga_init_done)
2335 return ENXIO;
2336
2337 s = spltty();
2338 switch (adp->va_type) {
2339 case KD_VGA:
2340 case KD_CGA:
2341 case KD_MONO:
2342 case KD_HERCULES:
2343 default:
2344 if (height <= 0) {
2345 /* make the cursor invisible */
2346 outb(adp->va_crtc_addr, 10);
2347 outb(adp->va_crtc_addr + 1, 32);
2348 outb(adp->va_crtc_addr, 11);
2349 outb(adp->va_crtc_addr + 1, 0);
2350 } else {
2351 outb(adp->va_crtc_addr, 10);
2352 outb(adp->va_crtc_addr + 1, celsize - base - height);
2353 outb(adp->va_crtc_addr, 11);
2354 outb(adp->va_crtc_addr + 1, celsize - base - 1);
2355 }
2356 break;
2357 case KD_EGA:
2358 if (height <= 0) {
2359 /* make the cursor invisible */
2360 outb(adp->va_crtc_addr, 10);
2361 outb(adp->va_crtc_addr + 1, celsize);
2362 outb(adp->va_crtc_addr, 11);
2363 outb(adp->va_crtc_addr + 1, 0);
2364 } else {
2365 outb(adp->va_crtc_addr, 10);
2366 outb(adp->va_crtc_addr + 1, celsize - base - height);
2367 outb(adp->va_crtc_addr, 11);
2368 outb(adp->va_crtc_addr + 1, celsize - base);
2369 }
2370 break;
2371 }
2372 splx(s);
2373
2374 return 0;
2375 }
2376
2377 /*
2378 * blank_display()
2379 * Put the display in power save/power off mode.
2380 *
2381 * all adapters
2382 */
2383 static int
2384 vga_blank_display(video_adapter_t *adp, int mode)
2385 {
2386 u_char val;
2387 int s;
2388
2389 s = splhigh();
2390 switch (adp->va_type) {
2391 case KD_VGA:
2392 switch (mode) {
2393 case V_DISPLAY_SUSPEND:
2394 case V_DISPLAY_STAND_BY:
2395 outb(TSIDX, 0x01);
2396 val = inb(TSREG);
2397 outb(TSIDX, 0x01);
2398 outb(TSREG, val | 0x20);
2399 outb(adp->va_crtc_addr, 0x17);
2400 val = inb(adp->va_crtc_addr + 1);
2401 outb(adp->va_crtc_addr + 1, val & ~0x80);
2402 break;
2403 case V_DISPLAY_BLANK:
2404 outb(TSIDX, 0x01);
2405 val = inb(TSREG);
2406 outb(TSIDX, 0x01);
2407 outb(TSREG, val | 0x20);
2408 break;
2409 case V_DISPLAY_ON:
2410 outb(TSIDX, 0x01);
2411 val = inb(TSREG);
2412 outb(TSIDX, 0x01);
2413 outb(TSREG, val & 0xDF);
2414 outb(adp->va_crtc_addr, 0x17);
2415 val = inb(adp->va_crtc_addr + 1);
2416 outb(adp->va_crtc_addr + 1, val | 0x80);
2417 break;
2418 }
2419 break;
2420
2421 case KD_EGA:
2422 /* no support yet */
2423 splx(s);
2424 return ENODEV;
2425
2426 case KD_CGA:
2427 switch (mode) {
2428 case V_DISPLAY_SUSPEND:
2429 case V_DISPLAY_STAND_BY:
2430 case V_DISPLAY_BLANK:
2431 outb(adp->va_crtc_addr + 4, 0x25);
2432 break;
2433 case V_DISPLAY_ON:
2434 outb(adp->va_crtc_addr + 4, 0x2d);
2435 break;
2436 }
2437 break;
2438
2439 case KD_MONO:
2440 case KD_HERCULES:
2441 switch (mode) {
2442 case V_DISPLAY_SUSPEND:
2443 case V_DISPLAY_STAND_BY:
2444 case V_DISPLAY_BLANK:
2445 outb(adp->va_crtc_addr + 4, 0x21);
2446 break;
2447 case V_DISPLAY_ON:
2448 outb(adp->va_crtc_addr + 4, 0x29);
2449 break;
2450 }
2451 break;
2452 default:
2453 break;
2454 }
2455 splx(s);
2456
2457 return 0;
2458 }
2459
2460 /*
2461 * mmap():
2462 * Mmap frame buffer.
2463 *
2464 * all adapters
2465 */
2466 static int
2467 vga_mmap_buf(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr,
2468 int prot)
2469 {
2470 if (adp->va_info.vi_flags & V_INFO_LINEAR)
2471 return -1;
2472
2473 #if VGA_DEBUG > 0
2474 printf("vga_mmap_buf(): window:0x%jx, offset:0x%jx\n",
2475 (uintmax_t)adp->va_info.vi_window, (uintmax_t)offset);
2476 #endif
2477
2478 /* XXX: is this correct? */
2479 if (offset > adp->va_window_size - PAGE_SIZE)
2480 return -1;
2481
2482 *paddr = adp->va_info.vi_window + offset;
2483 return 0;
2484 }
2485
2486 #ifndef VGA_NO_MODE_CHANGE
2487
2488 static void
2489 planar_fill(video_adapter_t *adp, int val)
2490 {
2491 int length;
2492 int at; /* position in the frame buffer */
2493 int l;
2494
2495 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
2496 outw(GDCIDX, 0x0003); /* data rotate/function select */
2497 outw(GDCIDX, 0x0f01); /* set/reset enable */
2498 outw(GDCIDX, 0xff08); /* bit mask */
2499 outw(GDCIDX, (val << 8) | 0x00); /* set/reset */
2500 at = 0;
2501 length = adp->va_line_width*adp->va_info.vi_height;
2502 while (length > 0) {
2503 l = imin(length, adp->va_window_size);
2504 (*vidsw[adp->va_index]->set_win_org)(adp, at);
2505 bzero_io(adp->va_window, l);
2506 length -= l;
2507 at += l;
2508 }
2509 outw(GDCIDX, 0x0000); /* set/reset */
2510 outw(GDCIDX, 0x0001); /* set/reset enable */
2511 }
2512
2513 static void
2514 packed_fill(video_adapter_t *adp, int val)
2515 {
2516 int length;
2517 int at; /* position in the frame buffer */
2518 int l;
2519
2520 at = 0;
2521 length = adp->va_line_width*adp->va_info.vi_height;
2522 while (length > 0) {
2523 l = imin(length, adp->va_window_size);
2524 (*vidsw[adp->va_index]->set_win_org)(adp, at);
2525 fill_io(val, adp->va_window, l);
2526 length -= l;
2527 at += l;
2528 }
2529 }
2530
2531 static void
2532 direct_fill(video_adapter_t *adp, int val)
2533 {
2534 int length;
2535 int at; /* position in the frame buffer */
2536 int l;
2537
2538 at = 0;
2539 length = adp->va_line_width*adp->va_info.vi_height;
2540 while (length > 0) {
2541 l = imin(length, adp->va_window_size);
2542 (*vidsw[adp->va_index]->set_win_org)(adp, at);
2543 switch (adp->va_info.vi_pixel_size) {
2544 case sizeof(u_int16_t):
2545 fillw_io(val, adp->va_window, l/sizeof(u_int16_t));
2546 break;
2547 case 3:
2548 /* FIXME */
2549 break;
2550 case sizeof(u_int32_t):
2551 filll_io(val, adp->va_window, l/sizeof(u_int32_t));
2552 break;
2553 }
2554 length -= l;
2555 at += l;
2556 }
2557 }
2558
2559 static int
2560 vga_clear(video_adapter_t *adp)
2561 {
2562 switch (adp->va_info.vi_mem_model) {
2563 case V_INFO_MM_TEXT:
2564 /* do nothing? XXX */
2565 break;
2566 case V_INFO_MM_PLANAR:
2567 planar_fill(adp, 0);
2568 break;
2569 case V_INFO_MM_PACKED:
2570 packed_fill(adp, 0);
2571 break;
2572 case V_INFO_MM_DIRECT:
2573 direct_fill(adp, 0);
2574 break;
2575 }
2576 return 0;
2577 }
2578
2579 #ifdef notyet
2580 static void
2581 planar_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2582 {
2583 int banksize;
2584 int bank;
2585 int pos;
2586 int offset; /* offset within window */
2587 int bx;
2588 int l;
2589
2590 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
2591 outw(GDCIDX, 0x0003); /* data rotate/function select */
2592 outw(GDCIDX, 0x0f01); /* set/reset enable */
2593 outw(GDCIDX, 0xff08); /* bit mask */
2594 outw(GDCIDX, (val << 8) | 0x00); /* set/reset */
2595
2596 banksize = adp->va_window_size;
2597 bank = -1;
2598 while (cy > 0) {
2599 pos = adp->va_line_width*y + x/8;
2600 if (bank != pos/banksize) {
2601 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2602 bank = pos/banksize;
2603 }
2604 offset = pos%banksize;
2605 bx = (x + cx)/8 - x/8;
2606 if (x % 8) {
2607 outw(GDCIDX, ((0xff00 >> (x % 8)) & 0xff00) | 0x08);
2608 writeb(adp->va_window + offset, 0);
2609 ++offset;
2610 --bx;
2611 if (offset >= banksize) {
2612 offset = 0;
2613 ++bank; /* next bank */
2614 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2615 }
2616 outw(GDCIDX, 0xff08); /* bit mask */
2617 }
2618 while (bx > 0) {
2619 l = imin(bx, banksize);
2620 bzero_io(adp->va_window + offset, l);
2621 offset += l;
2622 bx -= l;
2623 if (offset >= banksize) {
2624 offset = 0;
2625 ++bank; /* next bank */
2626 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2627 }
2628 }
2629 if ((x + cx) % 8) {
2630 outw(GDCIDX, (~(0xff00 >> ((x + cx) % 8)) & 0xff00) | 0x08);
2631 writeb(adp->va_window + offset, 0);
2632 ++offset;
2633 if (offset >= banksize) {
2634 offset = 0;
2635 ++bank; /* next bank */
2636 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2637 }
2638 outw(GDCIDX, 0xff08); /* bit mask */
2639 }
2640 ++y;
2641 --cy;
2642 }
2643
2644 outw(GDCIDX, 0xff08); /* bit mask */
2645 outw(GDCIDX, 0x0000); /* set/reset */
2646 outw(GDCIDX, 0x0001); /* set/reset enable */
2647 }
2648
2649 static void
2650 packed_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2651 {
2652 int banksize;
2653 int bank;
2654 int pos;
2655 int offset; /* offset within window */
2656 int end;
2657
2658 banksize = adp->va_window_size;
2659 bank = -1;
2660 cx *= adp->va_info.vi_pixel_size;
2661 while (cy > 0) {
2662 pos = adp->va_line_width*y + x*adp->va_info.vi_pixel_size;
2663 if (bank != pos/banksize) {
2664 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2665 bank = pos/banksize;
2666 }
2667 offset = pos%banksize;
2668 end = imin(offset + cx, banksize);
2669 fill_io(val, adp->va_window + offset,
2670 (end - offset)/adp->va_info.vi_pixel_size);
2671 /* the line may cross the window boundary */
2672 if (offset + cx > banksize) {
2673 ++bank; /* next bank */
2674 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2675 end = offset + cx - banksize;
2676 fill_io(val, adp->va_window, end/adp->va_info.vi_pixel_size);
2677 }
2678 ++y;
2679 --cy;
2680 }
2681 }
2682
2683 static void
2684 direct_fill_rect16(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2685 {
2686 int banksize;
2687 int bank;
2688 int pos;
2689 int offset; /* offset within window */
2690 int end;
2691
2692 /*
2693 * XXX: the function assumes that banksize is a muliple of
2694 * sizeof(u_int16_t).
2695 */
2696 banksize = adp->va_window_size;
2697 bank = -1;
2698 cx *= sizeof(u_int16_t);
2699 while (cy > 0) {
2700 pos = adp->va_line_width*y + x*sizeof(u_int16_t);
2701 if (bank != pos/banksize) {
2702 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2703 bank = pos/banksize;
2704 }
2705 offset = pos%banksize;
2706 end = imin(offset + cx, banksize);
2707 fillw_io(val, adp->va_window + offset,
2708 (end - offset)/sizeof(u_int16_t));
2709 /* the line may cross the window boundary */
2710 if (offset + cx > banksize) {
2711 ++bank; /* next bank */
2712 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2713 end = offset + cx - banksize;
2714 fillw_io(val, adp->va_window, end/sizeof(u_int16_t));
2715 }
2716 ++y;
2717 --cy;
2718 }
2719 }
2720
2721 static void
2722 direct_fill_rect24(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2723 {
2724 int banksize;
2725 int bank;
2726 int pos;
2727 int offset; /* offset within window */
2728 int end;
2729 int i;
2730 int j;
2731 u_int8_t b[3];
2732
2733 b[0] = val & 0x0000ff;
2734 b[1] = (val >> 8) & 0x0000ff;
2735 b[2] = (val >> 16) & 0x0000ff;
2736 banksize = adp->va_window_size;
2737 bank = -1;
2738 cx *= 3;
2739 while (cy > 0) {
2740 pos = adp->va_line_width*y + x*3;
2741 if (bank != pos/banksize) {
2742 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2743 bank = pos/banksize;
2744 }
2745 offset = pos%banksize;
2746 end = imin(offset + cx, banksize);
2747 for (i = 0, j = offset; j < end; i = (++i)%3, ++j) {
2748 writeb(adp->va_window + j, b[i]);
2749 }
2750 /* the line may cross the window boundary */
2751 if (offset + cx >= banksize) {
2752 ++bank; /* next bank */
2753 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2754 j = 0;
2755 end = offset + cx - banksize;
2756 for (; j < end; i = (++i)%3, ++j) {
2757 writeb(adp->va_window + j, b[i]);
2758 }
2759 }
2760 ++y;
2761 --cy;
2762 }
2763 }
2764
2765 static void
2766 direct_fill_rect32(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2767 {
2768 int banksize;
2769 int bank;
2770 int pos;
2771 int offset; /* offset within window */
2772 int end;
2773
2774 /*
2775 * XXX: the function assumes that banksize is a muliple of
2776 * sizeof(u_int32_t).
2777 */
2778 banksize = adp->va_window_size;
2779 bank = -1;
2780 cx *= sizeof(u_int32_t);
2781 while (cy > 0) {
2782 pos = adp->va_line_width*y + x*sizeof(u_int32_t);
2783 if (bank != pos/banksize) {
2784 (*vidsw[adp->va_index]->set_win_org)(adp, pos);
2785 bank = pos/banksize;
2786 }
2787 offset = pos%banksize;
2788 end = imin(offset + cx, banksize);
2789 filll_io(val, adp->va_window + offset,
2790 (end - offset)/sizeof(u_int32_t));
2791 /* the line may cross the window boundary */
2792 if (offset + cx > banksize) {
2793 ++bank; /* next bank */
2794 (*vidsw[adp->va_index]->set_win_org)(adp, bank*banksize);
2795 end = offset + cx - banksize;
2796 filll_io(val, adp->va_window, end/sizeof(u_int32_t));
2797 }
2798 ++y;
2799 --cy;
2800 }
2801 }
2802
2803 static int
2804 vga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2805 {
2806 switch (adp->va_info.vi_mem_model) {
2807 case V_INFO_MM_TEXT:
2808 /* do nothing? XXX */
2809 break;
2810 case V_INFO_MM_PLANAR:
2811 planar_fill_rect(adp, val, x, y, cx, cy);
2812 break;
2813 case V_INFO_MM_PACKED:
2814 packed_fill_rect(adp, val, x, y, cx, cy);
2815 break;
2816 case V_INFO_MM_DIRECT:
2817 switch (adp->va_info.vi_pixel_size) {
2818 case sizeof(u_int16_t):
2819 direct_fill_rect16(adp, val, x, y, cx, cy);
2820 break;
2821 case 3:
2822 direct_fill_rect24(adp, val, x, y, cx, cy);
2823 break;
2824 case sizeof(u_int32_t):
2825 direct_fill_rect32(adp, val, x, y, cx, cy);
2826 break;
2827 }
2828 break;
2829 }
2830 return 0;
2831 }
2832 #else /* !notyet */
2833 static int
2834 vga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
2835 {
2836 return ENODEV;
2837 }
2838 #endif /* notyet */
2839
2840 static int
2841 vga_bitblt(video_adapter_t *adp,...)
2842 {
2843 /* FIXME */
2844 return ENODEV;
2845 }
2846
2847 #endif /* !VGA_NO_MODE_CHANGE */
2848
2849 static int
2850 get_palette(video_adapter_t *adp, int base, int count,
2851 u_char *red, u_char *green, u_char *blue, u_char *trans)
2852 {
2853 u_char *r;
2854 u_char *g;
2855 u_char *b;
2856
2857 if ((base < 0) || (base >= 256) || (base + count > 256))
2858 return EINVAL;
2859
2860 r = malloc(count*3, M_DEVBUF, M_WAITOK);
2861 g = r + count;
2862 b = g + count;
2863 if (vga_save_palette2(adp, base, count, r, g, b)) {
2864 free(r, M_DEVBUF);
2865 return ENODEV;
2866 }
2867 copyout(r, red, count);
2868 copyout(g, green, count);
2869 copyout(b, blue, count);
2870 if (trans != NULL) {
2871 bzero(r, count);
2872 copyout(r, trans, count);
2873 }
2874 free(r, M_DEVBUF);
2875
2876 return 0;
2877 }
2878
2879 static int
2880 set_palette(video_adapter_t *adp, int base, int count,
2881 u_char *red, u_char *green, u_char *blue, u_char *trans)
2882 {
2883 u_char *r;
2884 u_char *g;
2885 u_char *b;
2886 int err;
2887
2888 if ((base < 0) || (base >= 256) || (base + count > 256))
2889 return EINVAL;
2890
2891 r = malloc(count*3, M_DEVBUF, M_WAITOK);
2892 g = r + count;
2893 b = g + count;
2894 copyin(red, r, count);
2895 copyin(green, g, count);
2896 copyin(blue, b, count);
2897 err = vga_load_palette2(adp, base, count, r, g, b);
2898 free(r, M_DEVBUF);
2899
2900 return (err ? ENODEV : 0);
2901 }
2902
2903 static int
2904 vga_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
2905 {
2906 switch (cmd) {
2907 case FBIO_GETWINORG: /* get frame buffer window origin */
2908 *(u_int *)arg = 0;
2909 return 0;
2910
2911 case FBIO_SETWINORG: /* set frame buffer window origin */
2912 return ENODEV;
2913
2914 case FBIO_SETDISPSTART: /* set display start address */
2915 return (set_display_start(adp,
2916 ((video_display_start_t *)arg)->x,
2917 ((video_display_start_t *)arg)->y)
2918 ? ENODEV : 0);
2919
2920 case FBIO_SETLINEWIDTH: /* set scan line length in pixel */
2921 return (set_line_length(adp, *(u_int *)arg) ? ENODEV : 0);
2922
2923 case FBIO_GETPALETTE: /* get color palette */
2924 return get_palette(adp, ((video_color_palette_t *)arg)->index,
2925 ((video_color_palette_t *)arg)->count,
2926 ((video_color_palette_t *)arg)->red,
2927 ((video_color_palette_t *)arg)->green,
2928 ((video_color_palette_t *)arg)->blue,
2929 ((video_color_palette_t *)arg)->transparent);
2930
2931 case FBIO_SETPALETTE: /* set color palette */
2932 return set_palette(adp, ((video_color_palette_t *)arg)->index,
2933 ((video_color_palette_t *)arg)->count,
2934 ((video_color_palette_t *)arg)->red,
2935 ((video_color_palette_t *)arg)->green,
2936 ((video_color_palette_t *)arg)->blue,
2937 ((video_color_palette_t *)arg)->transparent);
2938
2939 case FBIOGTYPE: /* get frame buffer type info. */
2940 ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type);
2941 ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height;
2942 ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width;
2943 ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth;
2944 if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8))
2945 ((struct fbtype *)arg)->fb_cmsize = 0;
2946 else
2947 ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth;
2948 ((struct fbtype *)arg)->fb_size = adp->va_buffer_size;
2949 return 0;
2950
2951 case FBIOGETCMAP: /* get color palette */
2952 return get_palette(adp, ((struct fbcmap *)arg)->index,
2953 ((struct fbcmap *)arg)->count,
2954 ((struct fbcmap *)arg)->red,
2955 ((struct fbcmap *)arg)->green,
2956 ((struct fbcmap *)arg)->blue, NULL);
2957
2958 case FBIOPUTCMAP: /* set color palette */
2959 return set_palette(adp, ((struct fbcmap *)arg)->index,
2960 ((struct fbcmap *)arg)->count,
2961 ((struct fbcmap *)arg)->red,
2962 ((struct fbcmap *)arg)->green,
2963 ((struct fbcmap *)arg)->blue, NULL);
2964
2965 default:
2966 return fb_commonioctl(adp, cmd, arg);
2967 }
2968 }
2969
2970 static void
2971 dump_buffer(u_char *buf, size_t len)
2972 {
2973 int i;
2974
2975 for(i = 0; i < len;) {
2976 printf("%02x ", buf[i]);
2977 if ((++i % 16) == 0)
2978 printf("\n");
2979 }
2980 }
2981
2982 /*
2983 * diag():
2984 * Print some information about the video adapter and video modes,
2985 * with requested level of details.
2986 *
2987 * all adapters
2988 */
2989 static int
2990 vga_diag(video_adapter_t *adp, int level)
2991 {
2992 u_char *mp;
2993 #if FB_DEBUG > 1
2994 video_info_t info;
2995 int i;
2996 #endif
2997
2998 if (!vga_init_done)
2999 return ENXIO;
3000
3001 #if FB_DEBUG > 1
3002 #ifndef VGA_NO_BIOS
3003 printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n",
3004 rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488)));
3005 printf("vga: CRTC:0x%x, video option:0x%02x, ",
3006 readw(BIOS_PADDRTOVADDR(0x463)),
3007 readb(BIOS_PADDRTOVADDR(0x487)));
3008 printf("rows:%d, cols:%d, font height:%d\n",
3009 readb(BIOS_PADDRTOVADDR(0x44a)),
3010 readb(BIOS_PADDRTOVADDR(0x484)) + 1,
3011 readb(BIOS_PADDRTOVADDR(0x485)));
3012 #endif /* VGA_NO_BIOS */
3013 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
3014 printf("vga: param table EGA/VGA:%p", video_mode_ptr);
3015 printf(", CGA/MDA:%p\n", video_mode_ptr2);
3016 printf("vga: rows_offset:%d\n", rows_offset);
3017 #endif
3018 #endif /* FB_DEBUG > 1 */
3019
3020 fb_dump_adp_info(VGA_DRIVER_NAME, adp, level);
3021
3022 #if FB_DEBUG > 1
3023 if (adp->va_flags & V_ADP_MODECHANGE) {
3024 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
3025 if (bios_vmode[i].vi_mode == NA)
3026 continue;
3027 if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
3028 continue;
3029 fb_dump_mode_info(VGA_DRIVER_NAME, adp, &bios_vmode[i], level);
3030 }
3031 } else {
3032 vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */
3033 fb_dump_mode_info(VGA_DRIVER_NAME, adp, &info, level);
3034 }
3035 #endif /* FB_DEBUG > 1 */
3036
3037 if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA))
3038 return 0;
3039 #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
3040 if (video_mode_ptr == NULL)
3041 printf("vga%d: %s: WARNING: video mode switching is not "
3042 "fully supported on this adapter\n",
3043 adp->va_unit, adp->va_name);
3044 #endif
3045 if (level <= 0)
3046 return 0;
3047
3048 if (adp->va_type == KD_VGA) {
3049 printf("VGA parameters upon power-up\n");
3050 dump_buffer(adpstate.regs, sizeof(adpstate.regs));
3051 printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
3052 dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
3053 }
3054
3055 mp = get_mode_param(adp->va_initial_mode);
3056 if (mp == NULL) /* this shouldn't be happening */
3057 return 0;
3058 printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode);
3059 dump_buffer(mp, V_MODE_PARAM_SIZE);
3060
3061 return 0;
3062 }
Cache object: cdf3d0b4af81e3c58ec9611fa1f09514
|