Deleted Added
full compact
vga_isa.c (43674) vga_isa.c (45720)
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 *
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 * $Id: vga_isa.c,v 1.2 1999/02/05 11:52:08 yokota Exp $
29 * $Id: vga_isa.c,v 1.3 1999/02/05 12:58:32 yokota Exp $
30 */
31
32#include "vga.h"
33#include "opt_vga.h"
34#include "opt_fb.h"
35#include "opt_syscons.h" /* should be removed in the future, XXX */
36
37#if NVGA > 0
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/bus.h>
43#include <sys/malloc.h>
44
45#include <vm/vm.h>
46#include <vm/pmap.h>
47
48#include <machine/console.h>
49#include <machine/md_var.h>
50#include <machine/pc/bios.h>
51
52#include <dev/fb/fbreg.h>
53#include <dev/fb/vgareg.h>
54
30 */
31
32#include "vga.h"
33#include "opt_vga.h"
34#include "opt_fb.h"
35#include "opt_syscons.h" /* should be removed in the future, XXX */
36
37#if NVGA > 0
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/bus.h>
43#include <sys/malloc.h>
44
45#include <vm/vm.h>
46#include <vm/pmap.h>
47
48#include <machine/console.h>
49#include <machine/md_var.h>
50#include <machine/pc/bios.h>
51
52#include <dev/fb/fbreg.h>
53#include <dev/fb/vgareg.h>
54
55#ifndef __i386__
55#if 1
56#include <isa/isareg.h>
57#include <isa/isavar.h>
58#else
59#include <i386/isa/isa.h>
60#include <i386/isa/isa_device.h>
61#endif
62
63#define DRIVER_NAME "vga"
64
65/* cdev driver declaration */
66
67#define ISAVGA_UNIT(dev) minor(dev)
68#define ISAVGA_MKMINOR(unit) (unit)
69
70typedef struct isavga_softc {
71 video_adapter_t *adp;
72} isavga_softc_t;
73
56#include <isa/isareg.h>
57#include <isa/isavar.h>
58#else
59#include <i386/isa/isa.h>
60#include <i386/isa/isa_device.h>
61#endif
62
63#define DRIVER_NAME "vga"
64
65/* cdev driver declaration */
66
67#define ISAVGA_UNIT(dev) minor(dev)
68#define ISAVGA_MKMINOR(unit) (unit)
69
70typedef struct isavga_softc {
71 video_adapter_t *adp;
72} isavga_softc_t;
73
74#ifndef __i386__
74#if 1
75
76#define ISAVGA_SOFTC(unit) \
77 ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit))
78
79devclass_t isavga_devclass;
80
81static int isavga_probe(device_t dev);
82static int isavga_attach(device_t dev);
83
84static device_method_t isavga_methods[] = {
85 DEVMETHOD(device_probe, isavga_probe),
86 DEVMETHOD(device_attach, isavga_attach),
87 { 0, 0 }
88};
89
90static driver_t isavga_driver = {
91 DRIVER_NAME,
92 isavga_methods,
93 DRIVER_TYPE_TTY,
94 sizeof(isavga_softc_t),
95};
96
97DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0);
98
99#else /* __i386__ */
100
101#define ISAVGA_SOFTC(unit) (isavga_softc[unit])
102
103static isavga_softc_t *isavga_softc[NVGA];
104
105static int isavga_probe(struct isa_device *dev);
106static int isavga_attach(struct isa_device *dev);
107
108struct isa_driver vgadriver = {
109 isavga_probe,
110 isavga_attach,
111 DRIVER_NAME,
112 0,
113};
114
115#endif /* __i386__ */
116
117static int isavga_probe_unit(int unit, isavga_softc_t *sc,
118 int flags);
119static int isavga_attach_unit(int unit, isavga_softc_t *sc,
120 int flags);
121
122#ifdef FB_INSTALL_CDEV
123
124static d_open_t isavgaopen;
125static d_close_t isavgaclose;
126static d_read_t isavgaread;
127static d_ioctl_t isavgaioctl;
128
129static struct cdevsw vga_cdevsw = {
130 isavgaopen, isavgaclose, noread, nowrite, /* ?? */
131 isavgaioctl, nostop, nullreset, nodevtotty,
132 seltrue, nommap, NULL, DRIVER_NAME,
133 NULL, -1, nodump, nopsize,
134};
135
136#endif /* FB_INSTALL_CDEV */
137
75
76#define ISAVGA_SOFTC(unit) \
77 ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit))
78
79devclass_t isavga_devclass;
80
81static int isavga_probe(device_t dev);
82static int isavga_attach(device_t dev);
83
84static device_method_t isavga_methods[] = {
85 DEVMETHOD(device_probe, isavga_probe),
86 DEVMETHOD(device_attach, isavga_attach),
87 { 0, 0 }
88};
89
90static driver_t isavga_driver = {
91 DRIVER_NAME,
92 isavga_methods,
93 DRIVER_TYPE_TTY,
94 sizeof(isavga_softc_t),
95};
96
97DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0);
98
99#else /* __i386__ */
100
101#define ISAVGA_SOFTC(unit) (isavga_softc[unit])
102
103static isavga_softc_t *isavga_softc[NVGA];
104
105static int isavga_probe(struct isa_device *dev);
106static int isavga_attach(struct isa_device *dev);
107
108struct isa_driver vgadriver = {
109 isavga_probe,
110 isavga_attach,
111 DRIVER_NAME,
112 0,
113};
114
115#endif /* __i386__ */
116
117static int isavga_probe_unit(int unit, isavga_softc_t *sc,
118 int flags);
119static int isavga_attach_unit(int unit, isavga_softc_t *sc,
120 int flags);
121
122#ifdef FB_INSTALL_CDEV
123
124static d_open_t isavgaopen;
125static d_close_t isavgaclose;
126static d_read_t isavgaread;
127static d_ioctl_t isavgaioctl;
128
129static struct cdevsw vga_cdevsw = {
130 isavgaopen, isavgaclose, noread, nowrite, /* ?? */
131 isavgaioctl, nostop, nullreset, nodevtotty,
132 seltrue, nommap, NULL, DRIVER_NAME,
133 NULL, -1, nodump, nopsize,
134};
135
136#endif /* FB_INSTALL_CDEV */
137
138#ifndef __i386__
138#if 1
139
140static int
141isavga_probe(device_t dev)
142{
143 isavga_softc_t *sc;
144
145 device_set_desc(dev, "Generic ISA VGA");
146 sc = device_get_softc(dev);
147 return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev));
148}
149
150static int
151isavga_attach(device_t dev)
152{
153 isavga_softc_t *sc;
154
155 sc = device_get_softc(dev);
156 return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev));
157}
158
159#else /* __i386__ */
160
161static int
162isavga_probe(struct isa_device *dev)
163{
164 isavga_softc_t *sc;
165 int error;
166
167 if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0]))
168 return 0;
169 sc = isavga_softc[dev->id_unit]
170 = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
171 if (sc == NULL)
172 return 0;
173
174 error = isavga_probe_unit(dev->id_unit, sc, dev->id_flags);
175 if (error) {
176 isavga_softc[dev->id_unit] = NULL;
177 free(sc, M_DEVBUF);
178 return 0;
179 }
180
181 dev->id_iobase = sc->adp->va_io_base;
182 dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base);
183 dev->id_msize = sc->adp->va_mem_size;
184
185 return sc->adp->va_io_size;
186}
187
188static int
189isavga_attach(struct isa_device *dev)
190{
191 isavga_softc_t *sc;
192
193 if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0]))
194 return 0;
195 sc = isavga_softc[dev->id_unit];
196 if (sc == NULL)
197 return 0;
198
199 return ((isavga_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1);
200}
201
202#endif /* __i386__ */
203
204static int
205isavga_probe_unit(int unit, isavga_softc_t *sc, int flags)
206{
207 video_switch_t *sw;
208
209 bzero(sc, sizeof(*sc));
210 sw = vid_get_switch(DRIVER_NAME);
211 if (sw == NULL)
212 return 0;
213 return (*sw->probe)(unit, &sc->adp, NULL, flags);
214}
215
216static int
217isavga_attach_unit(int unit, isavga_softc_t *sc, int flags)
218{
219 video_switch_t *sw;
220 int error;
221
222 sw = vid_get_switch(DRIVER_NAME);
223 if (sw == NULL)
224 return ENXIO;
225
226 error = (*sw->init)(unit, sc->adp, flags);
227 if (error)
228 return ENXIO;
229
230#ifdef FB_INSTALL_CDEV
231 /* attach a virtual frame buffer device */
232 error = fb_attach(makedev(0, ISAVGA_MKMINOR(unit)), scp->adp,
233 &vga_cdevsw);
234 if (error)
235 return error;
236#endif /* FB_INSTALL_CDEV */
237
238 if (bootverbose)
239 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
240
241 return 0;
242}
243
244/* LOW-LEVEL */
245
246#include <machine/clock.h>
247#include <machine/pc/vesa.h>
248
249#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
250#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
251#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
252
253/* for compatibility with old kernel options */
254#ifdef SC_ALT_SEQACCESS
255#undef SC_ALT_SEQACCESS
256#undef VGA_ALT_SEQACCESS
257#define VGA_ALT_SEQACCESS 1
258#endif
259
260#ifdef SLOW_VGA
261#undef SLOW_VGA
262#undef VGA_SLOW_IOACCESS
263#define VGA_SLOW_IOACCESS 1
264#endif
265
266/* architecture dependent option */
267#ifdef __alpha__
268#define VGA_NO_BIOS 1
269#endif
270
271/* this should really be in `rtc.h' */
272#define RTC_EQUIPMENT 0x14
273
274/* various sizes */
275#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1)
276#define V_MODE_PARAM_SIZE 64
277
278/* video adapter state buffer */
279struct adp_state {
280 int sig;
281#define V_STATE_SIG 0x736f6962
282 u_char regs[V_MODE_PARAM_SIZE];
283};
284typedef struct adp_state adp_state_t;
285
286/* video adapter information */
287#define DCC_MONO 0
288#define DCC_CGA40 1
289#define DCC_CGA80 2
290#define DCC_EGAMONO 3
291#define DCC_EGA40 4
292#define DCC_EGA80 5
293
294/*
295 * NOTE: `va_window' should have a virtual address, but is initialized
296 * with a physical address in the following table, as verify_adapter()
297 * will perform address conversion at run-time.
298 */
299static video_adapter_t adapter_init_value[] = {
300 /* DCC_MONO */
301 { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC,
302 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
303 0, 0, 0, 7, 0, },
304 /* DCC_CGA40 */
305 { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
306 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
307 0, 0, 0, 3, 0, },
308 /* DCC_CGA80 */
309 { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
310 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
311 0, 0, 0, 3, 0, },
312 /* DCC_EGAMONO */
313 { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC,
314 EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
315 0, 0, 0, 7, 0, },
316 /* DCC_EGA40 */
317 { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
318 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
319 0, 0, 0, 3, 0, },
320 /* DCC_EGA80 */
321 { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
322 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
323 0, 0, 0, 3, 0, },
324};
325
326static video_adapter_t biosadapter[2];
327static int biosadapters = 0;
328
329/* video driver declarations */
330static int vga_configure(int flags);
331 int (*vga_sub_configure)(int flags);
332static int vga_nop(void);
333static vi_probe_t vga_probe;
334static vi_init_t vga_init;
335static vi_get_info_t vga_get_info;
336static vi_query_mode_t vga_query_mode;
337static vi_set_mode_t vga_set_mode;
338static vi_save_font_t vga_save_font;
339static vi_load_font_t vga_load_font;
340static vi_show_font_t vga_show_font;
341static vi_save_palette_t vga_save_palette;
342static vi_load_palette_t vga_load_palette;
343static vi_set_border_t vga_set_border;
344static vi_save_state_t vga_save_state;
345static vi_load_state_t vga_load_state;
346static vi_set_win_org_t vga_set_origin;
347static vi_read_hw_cursor_t vga_read_hw_cursor;
348static vi_set_hw_cursor_t vga_set_hw_cursor;
349static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape;
350static vi_mmap_t vga_mmap;
351static vi_diag_t vga_diag;
352
353static video_switch_t vgavidsw = {
354 vga_probe,
355 vga_init,
356 vga_get_info,
357 vga_query_mode,
358 vga_set_mode,
359 vga_save_font,
360 vga_load_font,
361 vga_show_font,
362 vga_save_palette,
363 vga_load_palette,
364 vga_set_border,
365 vga_save_state,
366 vga_load_state,
367 vga_set_origin,
368 vga_read_hw_cursor,
369 vga_set_hw_cursor,
370 vga_set_hw_cursor_shape,
371 (vi_blank_display_t *)vga_nop,
372 vga_mmap,
373 vga_diag,
374};
375
376VIDEO_DRIVER(mda, vgavidsw, NULL);
377VIDEO_DRIVER(cga, vgavidsw, NULL);
378VIDEO_DRIVER(ega, vgavidsw, NULL);
379VIDEO_DRIVER(vga, vgavidsw, vga_configure);
380
381/* VGA BIOS standard video modes */
382#define EOT (-1)
383#define NA (-2)
384
385static video_info_t bios_vmode[] = {
386 /* CGA */
387 { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1,
388 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
389 { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1,
390 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
391 { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1,
392 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
393 { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1,
394 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
395 /* EGA */
396 { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1,
397 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
398 { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1,
399 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
400 { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1,
401 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
402 { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1,
403 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
404 /* VGA */
405 { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1,
406 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
407 { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1,
408 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
409 { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
410 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
411 /* MDA */
412 { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1,
413 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
414 /* EGA */
415 { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1,
416 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
417 { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1,
418 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
419 /* VGA */
420 { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1,
421 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
422 { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
423 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
424 { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1,
425 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
426 { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1,
427 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
428 { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1,
429 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
430 { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1,
431 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
432#ifndef VGA_NO_MODE_CHANGE
433 /* CGA */
434 { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
435 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
436 { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
437 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
438 { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1,
439 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
440 /* EGA */
441 { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4,
442 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
443 { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4,
444 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
445 { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
446 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 },
447 { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
448 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
449 { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2,
450 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
451 { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
452 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
453 /* VGA */
454 { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
455 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
456 { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
457 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
458 { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1,
459 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
460 { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1,
461 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
462#endif /* VGA_NO_MODE_CHANGE */
463
464 { EOT },
465};
466
467static int init_done = FALSE;
468static u_char *video_mode_ptr = NULL; /* EGA/VGA */
469static u_char *video_mode_ptr2 = NULL; /* CGA/MDA */
470static u_char *mode_map[V_MODE_MAP_SIZE];
471static adp_state_t adpstate;
472static adp_state_t adpstate2;
473static int rows_offset = 1;
474
475/* local macros and functions */
476#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
477
478#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
479static void map_mode_table(u_char *map[], u_char *table, int max);
480#endif
481static void clear_mode_map(video_adapter_t *adp, u_char *map[], int max,
482 int color);
483#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
484static int map_mode_num(int mode);
485#endif
486static int map_gen_mode_num(int type, int color, int mode);
487static int map_bios_mode_num(int type, int color, int bios_mode);
488static u_char *get_mode_param(int mode);
489#ifndef VGA_NO_BIOS
490static void fill_adapter_param(int code, video_adapter_t *adp);
491#endif
492static int verify_adapter(video_adapter_t *adp);
493static void update_adapter_info(video_adapter_t *adp, video_info_t *info);
494#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
495#define COMP_IDENTICAL 0
496#define COMP_SIMILAR 1
497#define COMP_DIFFERENT 2
498static int comp_adpregs(u_char *buf1, u_char *buf2);
499#endif
500static int probe_adapters(void);
501
502#define PARAM_BUFSIZE 6
503static void set_font_mode(video_adapter_t *adp, u_char *buf);
504static void set_normal_mode(video_adapter_t *adp, u_char *buf);
505
506static 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 (!init_done || !((adp)->va_flags & (flag))) \
514 return (err)
515
516/* a backdoor for the console driver */
517static int
518vga_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 */
543static void
544map_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
555static void
556clear_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 */
575static int
576map_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 { M_VGA_MODEX, M_VGA_CG320 },
591 };
592 int i;
593
594 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
595 if (mode_map[i].from == mode)
596 return mode_map[i].to;
597 }
598 return mode;
599}
600#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
601
602/* map a generic video mode to a known mode number */
603static int
604map_gen_mode_num(int type, int color, int mode)
605{
606 static struct {
607 int from;
608 int to_color;
609 int to_mono;
610 } mode_map[] = {
611 { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, },
612 { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, },
613 { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, },
614 { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, },
615 };
616 int i;
617
618 if (mode == M_TEXT_80x25) {
619 switch (type) {
620
621 case KD_VGA:
622 if (color)
623 return M_VGA_C80x25;
624 else
625 return M_VGA_M80x25;
626 break;
627
628 case KD_EGA:
629 if (color)
630 return M_ENH_C80x25;
631 else
632 return M_EGAMONO80x25;
633 break;
634
635 case KD_CGA:
636 return M_C80x25;
637
638 case KD_MONO:
639 case KD_HERCULES:
640 return M_EGAMONO80x25; /* XXX: this name is confusing */
641
642 default:
643 return -1;
644 }
645 }
646
647 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
648 if (mode_map[i].from == mode)
649 return ((color) ? mode_map[i].to_color : mode_map[i].to_mono);
650 }
651 return mode;
652}
653
654/* turn the BIOS video number into our video mode number */
655static int
656map_bios_mode_num(int type, int color, int bios_mode)
657{
658 static int cga_modes[7] = {
659 M_B40x25, M_C40x25, /* 0, 1 */
660 M_B80x25, M_C80x25, /* 2, 3 */
661 M_BG320, M_CG320,
662 M_BG640,
663 };
664 static int ega_modes[17] = {
665 M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */
666 M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */
667 M_BG320, M_CG320,
668 M_BG640,
669 M_EGAMONO80x25, /* 7 */
670 8, 9, 10, 11, 12,
671 M_CG320_D,
672 M_CG640_E,
673 M_ENHMONOAPA2, /* XXX: video momery > 64K */
674 M_ENH_CG640, /* XXX: video momery > 64K */
675 };
676 static int vga_modes[20] = {
677 M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */
678 M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */
679 M_BG320, M_CG320,
680 M_BG640,
681 M_VGA_M80x25, /* 7 */
682 8, 9, 10, 11, 12,
683 M_CG320_D,
684 M_CG640_E,
685 M_ENHMONOAPA2,
686 M_ENH_CG640,
687 M_BG640x480, M_CG640x480,
688 M_VGA_CG320,
689 };
690
691 switch (type) {
692
693 case KD_VGA:
694 if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
695 return vga_modes[bios_mode];
696 else if (color)
697 return M_VGA_C80x25;
698 else
699 return M_VGA_M80x25;
700 break;
701
702 case KD_EGA:
703 if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0]))
704 return ega_modes[bios_mode];
705 else if (color)
706 return M_ENH_C80x25;
707 else
708 return M_EGAMONO80x25;
709 break;
710
711 case KD_CGA:
712 if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0]))
713 return cga_modes[bios_mode];
714 else
715 return M_C80x25;
716 break;
717
718 case KD_MONO:
719 case KD_HERCULES:
720 return M_EGAMONO80x25; /* XXX: this name is confusing */
721
722 default:
723 break;
724 }
725 return -1;
726}
727
728/* look up a parameter table entry */
729static u_char
730*get_mode_param(int mode)
731{
732#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
733 if (mode >= V_MODE_MAP_SIZE)
734 mode = map_mode_num(mode);
735#endif
736 if ((mode >= 0) && (mode < V_MODE_MAP_SIZE))
737 return mode_map[mode];
738 else
739 return NULL;
740}
741
742#ifndef VGA_NO_BIOS
743static void
744fill_adapter_param(int code, video_adapter_t *adp)
745{
746 static struct {
747 int primary;
748 int secondary;
749 } dcc[] = {
750 { DCC_MONO, DCC_EGA40 /* CGA monitor */ },
751 { DCC_MONO, DCC_EGA80 /* CGA monitor */ },
752 { DCC_MONO, DCC_EGA80 /* CGA emulation */ },
753 { DCC_MONO, DCC_EGA80 },
754 { DCC_CGA40, DCC_EGAMONO },
755 { DCC_CGA80, DCC_EGAMONO },
756 { DCC_EGA40 /* CGA monitor */, DCC_MONO},
757 { DCC_EGA80 /* CGA monitor */, DCC_MONO},
758 { DCC_EGA80 /* CGA emulation */,DCC_MONO },
759 { DCC_EGA80, DCC_MONO },
760 { DCC_EGAMONO, DCC_CGA40 },
761 { DCC_EGAMONO, DCC_CGA40 },
762 };
763
764 if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) {
765 adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
766 adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
767 } else {
768 adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary];
769 adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary];
770 }
771}
772#endif /* VGA_NO_BIOS */
773
774static int
775verify_adapter(video_adapter_t *adp)
776{
777 vm_offset_t buf;
778 u_int16_t v;
139
140static int
141isavga_probe(device_t dev)
142{
143 isavga_softc_t *sc;
144
145 device_set_desc(dev, "Generic ISA VGA");
146 sc = device_get_softc(dev);
147 return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev));
148}
149
150static int
151isavga_attach(device_t dev)
152{
153 isavga_softc_t *sc;
154
155 sc = device_get_softc(dev);
156 return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev));
157}
158
159#else /* __i386__ */
160
161static int
162isavga_probe(struct isa_device *dev)
163{
164 isavga_softc_t *sc;
165 int error;
166
167 if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0]))
168 return 0;
169 sc = isavga_softc[dev->id_unit]
170 = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT);
171 if (sc == NULL)
172 return 0;
173
174 error = isavga_probe_unit(dev->id_unit, sc, dev->id_flags);
175 if (error) {
176 isavga_softc[dev->id_unit] = NULL;
177 free(sc, M_DEVBUF);
178 return 0;
179 }
180
181 dev->id_iobase = sc->adp->va_io_base;
182 dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base);
183 dev->id_msize = sc->adp->va_mem_size;
184
185 return sc->adp->va_io_size;
186}
187
188static int
189isavga_attach(struct isa_device *dev)
190{
191 isavga_softc_t *sc;
192
193 if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0]))
194 return 0;
195 sc = isavga_softc[dev->id_unit];
196 if (sc == NULL)
197 return 0;
198
199 return ((isavga_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1);
200}
201
202#endif /* __i386__ */
203
204static int
205isavga_probe_unit(int unit, isavga_softc_t *sc, int flags)
206{
207 video_switch_t *sw;
208
209 bzero(sc, sizeof(*sc));
210 sw = vid_get_switch(DRIVER_NAME);
211 if (sw == NULL)
212 return 0;
213 return (*sw->probe)(unit, &sc->adp, NULL, flags);
214}
215
216static int
217isavga_attach_unit(int unit, isavga_softc_t *sc, int flags)
218{
219 video_switch_t *sw;
220 int error;
221
222 sw = vid_get_switch(DRIVER_NAME);
223 if (sw == NULL)
224 return ENXIO;
225
226 error = (*sw->init)(unit, sc->adp, flags);
227 if (error)
228 return ENXIO;
229
230#ifdef FB_INSTALL_CDEV
231 /* attach a virtual frame buffer device */
232 error = fb_attach(makedev(0, ISAVGA_MKMINOR(unit)), scp->adp,
233 &vga_cdevsw);
234 if (error)
235 return error;
236#endif /* FB_INSTALL_CDEV */
237
238 if (bootverbose)
239 (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
240
241 return 0;
242}
243
244/* LOW-LEVEL */
245
246#include <machine/clock.h>
247#include <machine/pc/vesa.h>
248
249#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)
250#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)
251#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)
252
253/* for compatibility with old kernel options */
254#ifdef SC_ALT_SEQACCESS
255#undef SC_ALT_SEQACCESS
256#undef VGA_ALT_SEQACCESS
257#define VGA_ALT_SEQACCESS 1
258#endif
259
260#ifdef SLOW_VGA
261#undef SLOW_VGA
262#undef VGA_SLOW_IOACCESS
263#define VGA_SLOW_IOACCESS 1
264#endif
265
266/* architecture dependent option */
267#ifdef __alpha__
268#define VGA_NO_BIOS 1
269#endif
270
271/* this should really be in `rtc.h' */
272#define RTC_EQUIPMENT 0x14
273
274/* various sizes */
275#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1)
276#define V_MODE_PARAM_SIZE 64
277
278/* video adapter state buffer */
279struct adp_state {
280 int sig;
281#define V_STATE_SIG 0x736f6962
282 u_char regs[V_MODE_PARAM_SIZE];
283};
284typedef struct adp_state adp_state_t;
285
286/* video adapter information */
287#define DCC_MONO 0
288#define DCC_CGA40 1
289#define DCC_CGA80 2
290#define DCC_EGAMONO 3
291#define DCC_EGA40 4
292#define DCC_EGA80 5
293
294/*
295 * NOTE: `va_window' should have a virtual address, but is initialized
296 * with a physical address in the following table, as verify_adapter()
297 * will perform address conversion at run-time.
298 */
299static video_adapter_t adapter_init_value[] = {
300 /* DCC_MONO */
301 { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC,
302 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
303 0, 0, 0, 7, 0, },
304 /* DCC_CGA40 */
305 { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
306 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
307 0, 0, 0, 3, 0, },
308 /* DCC_CGA80 */
309 { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
310 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
311 0, 0, 0, 3, 0, },
312 /* DCC_EGAMONO */
313 { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC,
314 EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
315 0, 0, 0, 7, 0, },
316 /* DCC_EGA40 */
317 { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
318 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
319 0, 0, 0, 3, 0, },
320 /* DCC_EGA80 */
321 { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC,
322 EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
323 0, 0, 0, 3, 0, },
324};
325
326static video_adapter_t biosadapter[2];
327static int biosadapters = 0;
328
329/* video driver declarations */
330static int vga_configure(int flags);
331 int (*vga_sub_configure)(int flags);
332static int vga_nop(void);
333static vi_probe_t vga_probe;
334static vi_init_t vga_init;
335static vi_get_info_t vga_get_info;
336static vi_query_mode_t vga_query_mode;
337static vi_set_mode_t vga_set_mode;
338static vi_save_font_t vga_save_font;
339static vi_load_font_t vga_load_font;
340static vi_show_font_t vga_show_font;
341static vi_save_palette_t vga_save_palette;
342static vi_load_palette_t vga_load_palette;
343static vi_set_border_t vga_set_border;
344static vi_save_state_t vga_save_state;
345static vi_load_state_t vga_load_state;
346static vi_set_win_org_t vga_set_origin;
347static vi_read_hw_cursor_t vga_read_hw_cursor;
348static vi_set_hw_cursor_t vga_set_hw_cursor;
349static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape;
350static vi_mmap_t vga_mmap;
351static vi_diag_t vga_diag;
352
353static video_switch_t vgavidsw = {
354 vga_probe,
355 vga_init,
356 vga_get_info,
357 vga_query_mode,
358 vga_set_mode,
359 vga_save_font,
360 vga_load_font,
361 vga_show_font,
362 vga_save_palette,
363 vga_load_palette,
364 vga_set_border,
365 vga_save_state,
366 vga_load_state,
367 vga_set_origin,
368 vga_read_hw_cursor,
369 vga_set_hw_cursor,
370 vga_set_hw_cursor_shape,
371 (vi_blank_display_t *)vga_nop,
372 vga_mmap,
373 vga_diag,
374};
375
376VIDEO_DRIVER(mda, vgavidsw, NULL);
377VIDEO_DRIVER(cga, vgavidsw, NULL);
378VIDEO_DRIVER(ega, vgavidsw, NULL);
379VIDEO_DRIVER(vga, vgavidsw, vga_configure);
380
381/* VGA BIOS standard video modes */
382#define EOT (-1)
383#define NA (-2)
384
385static video_info_t bios_vmode[] = {
386 /* CGA */
387 { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1,
388 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
389 { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1,
390 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
391 { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1,
392 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
393 { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1,
394 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
395 /* EGA */
396 { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1,
397 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
398 { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1,
399 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
400 { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1,
401 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
402 { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1,
403 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
404 /* VGA */
405 { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1,
406 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
407 { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1,
408 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
409 { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
410 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
411 /* MDA */
412 { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1,
413 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
414 /* EGA */
415 { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1,
416 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
417 { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1,
418 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
419 /* VGA */
420 { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1,
421 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
422 { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
423 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
424 { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1,
425 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
426 { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1,
427 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
428 { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1,
429 MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
430 { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1,
431 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
432#ifndef VGA_NO_MODE_CHANGE
433 /* CGA */
434 { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
435 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
436 { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1,
437 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
438 { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1,
439 CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
440 /* EGA */
441 { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4,
442 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
443 { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4,
444 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
445 { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
446 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 },
447 { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
448 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
449 { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2,
450 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
451 { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
452 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
453 /* VGA */
454 { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
455 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
456 { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
457 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
458 { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1,
459 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
460 { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1,
461 GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
462#endif /* VGA_NO_MODE_CHANGE */
463
464 { EOT },
465};
466
467static int init_done = FALSE;
468static u_char *video_mode_ptr = NULL; /* EGA/VGA */
469static u_char *video_mode_ptr2 = NULL; /* CGA/MDA */
470static u_char *mode_map[V_MODE_MAP_SIZE];
471static adp_state_t adpstate;
472static adp_state_t adpstate2;
473static int rows_offset = 1;
474
475/* local macros and functions */
476#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
477
478#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
479static void map_mode_table(u_char *map[], u_char *table, int max);
480#endif
481static void clear_mode_map(video_adapter_t *adp, u_char *map[], int max,
482 int color);
483#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
484static int map_mode_num(int mode);
485#endif
486static int map_gen_mode_num(int type, int color, int mode);
487static int map_bios_mode_num(int type, int color, int bios_mode);
488static u_char *get_mode_param(int mode);
489#ifndef VGA_NO_BIOS
490static void fill_adapter_param(int code, video_adapter_t *adp);
491#endif
492static int verify_adapter(video_adapter_t *adp);
493static void update_adapter_info(video_adapter_t *adp, video_info_t *info);
494#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
495#define COMP_IDENTICAL 0
496#define COMP_SIMILAR 1
497#define COMP_DIFFERENT 2
498static int comp_adpregs(u_char *buf1, u_char *buf2);
499#endif
500static int probe_adapters(void);
501
502#define PARAM_BUFSIZE 6
503static void set_font_mode(video_adapter_t *adp, u_char *buf);
504static void set_normal_mode(video_adapter_t *adp, u_char *buf);
505
506static 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 (!init_done || !((adp)->va_flags & (flag))) \
514 return (err)
515
516/* a backdoor for the console driver */
517static int
518vga_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 */
543static void
544map_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
555static void
556clear_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 */
575static int
576map_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 { M_VGA_MODEX, M_VGA_CG320 },
591 };
592 int i;
593
594 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
595 if (mode_map[i].from == mode)
596 return mode_map[i].to;
597 }
598 return mode;
599}
600#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
601
602/* map a generic video mode to a known mode number */
603static int
604map_gen_mode_num(int type, int color, int mode)
605{
606 static struct {
607 int from;
608 int to_color;
609 int to_mono;
610 } mode_map[] = {
611 { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, },
612 { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, },
613 { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, },
614 { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, },
615 };
616 int i;
617
618 if (mode == M_TEXT_80x25) {
619 switch (type) {
620
621 case KD_VGA:
622 if (color)
623 return M_VGA_C80x25;
624 else
625 return M_VGA_M80x25;
626 break;
627
628 case KD_EGA:
629 if (color)
630 return M_ENH_C80x25;
631 else
632 return M_EGAMONO80x25;
633 break;
634
635 case KD_CGA:
636 return M_C80x25;
637
638 case KD_MONO:
639 case KD_HERCULES:
640 return M_EGAMONO80x25; /* XXX: this name is confusing */
641
642 default:
643 return -1;
644 }
645 }
646
647 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
648 if (mode_map[i].from == mode)
649 return ((color) ? mode_map[i].to_color : mode_map[i].to_mono);
650 }
651 return mode;
652}
653
654/* turn the BIOS video number into our video mode number */
655static int
656map_bios_mode_num(int type, int color, int bios_mode)
657{
658 static int cga_modes[7] = {
659 M_B40x25, M_C40x25, /* 0, 1 */
660 M_B80x25, M_C80x25, /* 2, 3 */
661 M_BG320, M_CG320,
662 M_BG640,
663 };
664 static int ega_modes[17] = {
665 M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */
666 M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */
667 M_BG320, M_CG320,
668 M_BG640,
669 M_EGAMONO80x25, /* 7 */
670 8, 9, 10, 11, 12,
671 M_CG320_D,
672 M_CG640_E,
673 M_ENHMONOAPA2, /* XXX: video momery > 64K */
674 M_ENH_CG640, /* XXX: video momery > 64K */
675 };
676 static int vga_modes[20] = {
677 M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */
678 M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */
679 M_BG320, M_CG320,
680 M_BG640,
681 M_VGA_M80x25, /* 7 */
682 8, 9, 10, 11, 12,
683 M_CG320_D,
684 M_CG640_E,
685 M_ENHMONOAPA2,
686 M_ENH_CG640,
687 M_BG640x480, M_CG640x480,
688 M_VGA_CG320,
689 };
690
691 switch (type) {
692
693 case KD_VGA:
694 if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
695 return vga_modes[bios_mode];
696 else if (color)
697 return M_VGA_C80x25;
698 else
699 return M_VGA_M80x25;
700 break;
701
702 case KD_EGA:
703 if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0]))
704 return ega_modes[bios_mode];
705 else if (color)
706 return M_ENH_C80x25;
707 else
708 return M_EGAMONO80x25;
709 break;
710
711 case KD_CGA:
712 if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0]))
713 return cga_modes[bios_mode];
714 else
715 return M_C80x25;
716 break;
717
718 case KD_MONO:
719 case KD_HERCULES:
720 return M_EGAMONO80x25; /* XXX: this name is confusing */
721
722 default:
723 break;
724 }
725 return -1;
726}
727
728/* look up a parameter table entry */
729static u_char
730*get_mode_param(int mode)
731{
732#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
733 if (mode >= V_MODE_MAP_SIZE)
734 mode = map_mode_num(mode);
735#endif
736 if ((mode >= 0) && (mode < V_MODE_MAP_SIZE))
737 return mode_map[mode];
738 else
739 return NULL;
740}
741
742#ifndef VGA_NO_BIOS
743static void
744fill_adapter_param(int code, video_adapter_t *adp)
745{
746 static struct {
747 int primary;
748 int secondary;
749 } dcc[] = {
750 { DCC_MONO, DCC_EGA40 /* CGA monitor */ },
751 { DCC_MONO, DCC_EGA80 /* CGA monitor */ },
752 { DCC_MONO, DCC_EGA80 /* CGA emulation */ },
753 { DCC_MONO, DCC_EGA80 },
754 { DCC_CGA40, DCC_EGAMONO },
755 { DCC_CGA80, DCC_EGAMONO },
756 { DCC_EGA40 /* CGA monitor */, DCC_MONO},
757 { DCC_EGA80 /* CGA monitor */, DCC_MONO},
758 { DCC_EGA80 /* CGA emulation */,DCC_MONO },
759 { DCC_EGA80, DCC_MONO },
760 { DCC_EGAMONO, DCC_CGA40 },
761 { DCC_EGAMONO, DCC_CGA40 },
762 };
763
764 if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) {
765 adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
766 adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
767 } else {
768 adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary];
769 adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary];
770 }
771}
772#endif /* VGA_NO_BIOS */
773
774static int
775verify_adapter(video_adapter_t *adp)
776{
777 vm_offset_t buf;
778 u_int16_t v;
779#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
780 u_int32_t p;
781#endif
779
780 buf = BIOS_PADDRTOVADDR(adp->va_window);
781 v = readw(buf);
782 writew(buf, 0xA55A);
783 if (readw(buf) != 0xA55A)
784 return 1;
785 writew(buf, v);
786
787 switch (adp->va_type) {
788
789 case KD_EGA:
790 outb(adp->va_crtc_addr, 7);
791 if (inb(adp->va_crtc_addr) == 7) {
792 adp->va_type = KD_VGA;
793 adp->va_name = "vga";
794 adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE;
795 }
796 adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER;
797 /* the color adapter may be in the 40x25 mode... XXX */
798
799#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
800 /* get the BIOS video mode pointer */
801 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
802 p = BIOS_SADDRTOLADDR(p);
803 if (ISMAPPED(p, sizeof(u_int32_t))) {
804 p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
805 p = BIOS_SADDRTOLADDR(p);
806 if (ISMAPPED(p, V_MODE_PARAM_SIZE))
807 video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
808 }
809#endif
810 break;
811
812 case KD_CGA:
813 adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER;
814 /* may be in the 40x25 mode... XXX */
815#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
816 /* get the BIOS video mode pointer */
817 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
818 p = BIOS_SADDRTOLADDR(p);
819 video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
820#endif
821 break;
822
823 case KD_MONO:
824#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
825 /* get the BIOS video mode pointer */
826 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
827 p = BIOS_SADDRTOLADDR(p);
828 video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
829#endif
830 break;
831 }
832
833 return 0;
834}
835
836static void
837update_adapter_info(video_adapter_t *adp, video_info_t *info)
838{
839 adp->va_flags &= ~V_ADP_COLOR;
840 adp->va_flags |=
841 (info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
842 adp->va_crtc_addr =
843 (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
844 adp->va_window = BIOS_PADDRTOVADDR(info->vi_window);
845 adp->va_window_size = info->vi_window_size;
846 adp->va_window_gran = info->vi_window_gran;
847 if (info->vi_buffer_size == 0) {
848 adp->va_buffer = 0;
849 adp->va_buffer_size = 0;
850 } else {
851 adp->va_buffer = BIOS_PADDRTOVADDR(info->vi_buffer);
852 adp->va_buffer_size = info->vi_buffer_size;
853 }
854 if (info->vi_flags & V_INFO_GRAPHICS) {
855 switch (info->vi_depth/info->vi_planes) {
856 case 1:
857 adp->va_line_width = info->vi_width/8;
858 break;
859 case 2:
860 adp->va_line_width = info->vi_width/4;
861 break;
862 case 4:
863 adp->va_line_width = info->vi_width/2;
864 break;
865 case 8:
866 default: /* shouldn't happen */
867 adp->va_line_width = info->vi_width;
868 break;
869 }
870 } else {
871 adp->va_line_width = info->vi_width;
872 }
873 bcopy(info, &adp->va_info, sizeof(adp->va_info));
874}
875
876#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
877/* compare two parameter table entries */
878static int
879comp_adpregs(u_char *buf1, u_char *buf2)
880{
881 static struct {
882 u_char mask;
883 } params[V_MODE_PARAM_SIZE] = {
884 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */
885 0x00, 0x00, /* page length */
886 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */
887 0xf3, /* misc register */
888 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */
889 0xff, 0xff, 0xff, 0x7f, 0xff,
890 0x00, 0x00, 0x00, 0x00, 0x00,
891 0x00, 0xff, 0x7f, 0xff, 0xff,
892 0x7f, 0xff, 0xff, 0xef, 0xff,
893 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */
894 0xff, 0xff, 0xff, 0xff, 0xff,
895 0xff, 0xff, 0xff, 0xff, 0xff,
896 0xff, 0xff, 0xff, 0xff, 0xf0,
897 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */
898 0xff, 0xff, 0xff, 0xff,
899 };
900 int identical = TRUE;
901 int i;
902
903 if ((buf1 == NULL) || (buf2 == NULL))
904 return COMP_DIFFERENT;
905
906 for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
907 if (params[i].mask == 0) /* don't care */
908 continue;
909 if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
910 return COMP_DIFFERENT;
911 if (buf1[i] != buf2[i])
912 identical = FALSE;
913 }
914 return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
915}
916#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
917
918/* probe video adapters and return the number of detected adapters */
919static int
920probe_adapters(void)
921{
922 video_adapter_t *adp;
923 video_info_t info;
924 int i;
925
926 /* do this test only once */
927 if (init_done)
928 return biosadapters;
929 init_done = TRUE;
930
931 /*
932 * Locate display adapters.
933 * The AT architecture supports upto two adapters. `syscons' allows
934 * the following combinations of adapters:
935 * 1) MDA + CGA
936 * 2) MDA + EGA/VGA color
937 * 3) CGA + EGA/VGA mono
938 * Note that `syscons' doesn't bother with MCGA as it is only
939 * avaiable for low end PS/2 models which has 80286 or earlier CPUs,
940 * thus, they are not running FreeBSD!
941 * When there are two adapaters in the system, one becomes `primary'
942 * and the other `secondary'. The EGA adapter has a set of DIP
943 * switches on board for this information and the EGA BIOS copies
944 * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88).
945 * The VGA BIOS has more sophisticated mechanism and has this
946 * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains
947 * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
948 */
949
950 /*
951 * Check rtc and BIOS data area.
952 * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead
953 * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are
954 * zeros for EGA and VGA. However, the EGA/VGA BIOS sets
955 * these bits in BIOSDATA_EQUIPMENT according to the monitor
956 * type detected.
957 */
958#ifndef VGA_NO_BIOS
959 switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */
960 case 0:
961 /* EGA/VGA */
962 fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f,
963 biosadapter);
964 break;
965 case 1:
966 /* CGA 40x25 */
967 /* FIXME: switch to the 80x25 mode? XXX */
968 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40];
969 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
970 break;
971 case 2:
972 /* CGA 80x25 */
973 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80];
974 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
975 break;
976 case 3:
977 /* MDA */
978 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
979 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
980 break;
981 }
982#else
983 /* assume EGA/VGA? XXX */
984 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80];
985 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
986#endif /* VGA_NO_BIOS */
987
988 biosadapters = 0;
989 if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) {
990 ++biosadapters;
991 biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED;
992 biosadapter[V_ADP_SECONDARY].va_mode =
993 biosadapter[V_ADP_SECONDARY].va_initial_mode =
994 map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type,
995 biosadapter[V_ADP_SECONDARY].va_flags
996 & V_ADP_COLOR,
997 biosadapter[V_ADP_SECONDARY].va_initial_bios_mode);
998 } else {
999 biosadapter[V_ADP_SECONDARY].va_type = -1;
1000 }
1001 if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) {
1002 ++biosadapters;
1003 biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED;
1004#ifndef VGA_NO_BIOS
1005 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode =
1006 readb(BIOS_PADDRTOVADDR(0x449));
1007#else
1008 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */
1009#endif
1010 biosadapter[V_ADP_PRIMARY].va_mode =
1011 biosadapter[V_ADP_PRIMARY].va_initial_mode =
1012 map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type,
1013 biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR,
1014 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode);
1015 } else {
1016 biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY];
1017 biosadapter[V_ADP_SECONDARY].va_type = -1;
1018 }
1019 if (biosadapters == 0)
1020 return biosadapters;
1021 biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY;
1022 biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY;
1023
1024#if 0 /* we don't need these... */
1025 fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...);
1026 fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...);
1027#endif
1028
1029#if 0
1030 /*
1031 * We cannot have two video adapter of the same type; there must be
1032 * only one of color or mono adapter, or one each of them.
1033 */
1034 if (biosadapters > 1) {
1035 if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags)
1036 & V_ADP_COLOR))
1037 /* we have two mono or color adapters!! */
1038 return (biosadapters = 0);
1039 }
1040#endif
1041
1042 /*
1043 * Ensure a zero start address. This is mainly to recover after
1044 * switching from pcvt using userconfig(). The registers are w/o
1045 * for old hardware so it's too hard to relocate the active screen
1046 * memory.
1047 * This must be done before vga_save_state() for VGA.
1048 */
1049 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12);
1050 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
1051 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13);
1052 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
1053
1054 /* the video mode parameter table in EGA/VGA BIOS */
1055 /* NOTE: there can be only one EGA/VGA, wheather color or mono,
1056 * recognized by the video BIOS.
1057 */
1058 if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) ||
1059 (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) {
1060 adp = &biosadapter[V_ADP_PRIMARY];
1061 } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) ||
1062 (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) {
1063 adp = &biosadapter[V_ADP_SECONDARY];
1064 } else {
1065 adp = NULL;
1066 }
1067 bzero(mode_map, sizeof(mode_map));
1068 if (adp != NULL) {
1069 if (adp->va_type == KD_VGA) {
1070 vga_save_state(adp, &adpstate, sizeof(adpstate));
1071#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
1072 mode_map[adp->va_initial_mode] = adpstate.regs;
1073 rows_offset = 1;
1074#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1075 if (video_mode_ptr == NULL) {
1076 mode_map[adp->va_initial_mode] = adpstate.regs;
1077 rows_offset = 1;
1078 } else {
1079 /* discard the table if we are not familiar with it... */
782
783 buf = BIOS_PADDRTOVADDR(adp->va_window);
784 v = readw(buf);
785 writew(buf, 0xA55A);
786 if (readw(buf) != 0xA55A)
787 return 1;
788 writew(buf, v);
789
790 switch (adp->va_type) {
791
792 case KD_EGA:
793 outb(adp->va_crtc_addr, 7);
794 if (inb(adp->va_crtc_addr) == 7) {
795 adp->va_type = KD_VGA;
796 adp->va_name = "vga";
797 adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE;
798 }
799 adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER;
800 /* the color adapter may be in the 40x25 mode... XXX */
801
802#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
803 /* get the BIOS video mode pointer */
804 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
805 p = BIOS_SADDRTOLADDR(p);
806 if (ISMAPPED(p, sizeof(u_int32_t))) {
807 p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
808 p = BIOS_SADDRTOLADDR(p);
809 if (ISMAPPED(p, V_MODE_PARAM_SIZE))
810 video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
811 }
812#endif
813 break;
814
815 case KD_CGA:
816 adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER;
817 /* may be in the 40x25 mode... XXX */
818#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
819 /* get the BIOS video mode pointer */
820 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
821 p = BIOS_SADDRTOLADDR(p);
822 video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
823#endif
824 break;
825
826 case KD_MONO:
827#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
828 /* get the BIOS video mode pointer */
829 p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
830 p = BIOS_SADDRTOLADDR(p);
831 video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
832#endif
833 break;
834 }
835
836 return 0;
837}
838
839static void
840update_adapter_info(video_adapter_t *adp, video_info_t *info)
841{
842 adp->va_flags &= ~V_ADP_COLOR;
843 adp->va_flags |=
844 (info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
845 adp->va_crtc_addr =
846 (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
847 adp->va_window = BIOS_PADDRTOVADDR(info->vi_window);
848 adp->va_window_size = info->vi_window_size;
849 adp->va_window_gran = info->vi_window_gran;
850 if (info->vi_buffer_size == 0) {
851 adp->va_buffer = 0;
852 adp->va_buffer_size = 0;
853 } else {
854 adp->va_buffer = BIOS_PADDRTOVADDR(info->vi_buffer);
855 adp->va_buffer_size = info->vi_buffer_size;
856 }
857 if (info->vi_flags & V_INFO_GRAPHICS) {
858 switch (info->vi_depth/info->vi_planes) {
859 case 1:
860 adp->va_line_width = info->vi_width/8;
861 break;
862 case 2:
863 adp->va_line_width = info->vi_width/4;
864 break;
865 case 4:
866 adp->va_line_width = info->vi_width/2;
867 break;
868 case 8:
869 default: /* shouldn't happen */
870 adp->va_line_width = info->vi_width;
871 break;
872 }
873 } else {
874 adp->va_line_width = info->vi_width;
875 }
876 bcopy(info, &adp->va_info, sizeof(adp->va_info));
877}
878
879#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
880/* compare two parameter table entries */
881static int
882comp_adpregs(u_char *buf1, u_char *buf2)
883{
884 static struct {
885 u_char mask;
886 } params[V_MODE_PARAM_SIZE] = {
887 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */
888 0x00, 0x00, /* page length */
889 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */
890 0xf3, /* misc register */
891 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */
892 0xff, 0xff, 0xff, 0x7f, 0xff,
893 0x00, 0x00, 0x00, 0x00, 0x00,
894 0x00, 0xff, 0x7f, 0xff, 0xff,
895 0x7f, 0xff, 0xff, 0xef, 0xff,
896 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */
897 0xff, 0xff, 0xff, 0xff, 0xff,
898 0xff, 0xff, 0xff, 0xff, 0xff,
899 0xff, 0xff, 0xff, 0xff, 0xf0,
900 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */
901 0xff, 0xff, 0xff, 0xff,
902 };
903 int identical = TRUE;
904 int i;
905
906 if ((buf1 == NULL) || (buf2 == NULL))
907 return COMP_DIFFERENT;
908
909 for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
910 if (params[i].mask == 0) /* don't care */
911 continue;
912 if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
913 return COMP_DIFFERENT;
914 if (buf1[i] != buf2[i])
915 identical = FALSE;
916 }
917 return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
918}
919#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
920
921/* probe video adapters and return the number of detected adapters */
922static int
923probe_adapters(void)
924{
925 video_adapter_t *adp;
926 video_info_t info;
927 int i;
928
929 /* do this test only once */
930 if (init_done)
931 return biosadapters;
932 init_done = TRUE;
933
934 /*
935 * Locate display adapters.
936 * The AT architecture supports upto two adapters. `syscons' allows
937 * the following combinations of adapters:
938 * 1) MDA + CGA
939 * 2) MDA + EGA/VGA color
940 * 3) CGA + EGA/VGA mono
941 * Note that `syscons' doesn't bother with MCGA as it is only
942 * avaiable for low end PS/2 models which has 80286 or earlier CPUs,
943 * thus, they are not running FreeBSD!
944 * When there are two adapaters in the system, one becomes `primary'
945 * and the other `secondary'. The EGA adapter has a set of DIP
946 * switches on board for this information and the EGA BIOS copies
947 * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88).
948 * The VGA BIOS has more sophisticated mechanism and has this
949 * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains
950 * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
951 */
952
953 /*
954 * Check rtc and BIOS data area.
955 * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead
956 * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are
957 * zeros for EGA and VGA. However, the EGA/VGA BIOS sets
958 * these bits in BIOSDATA_EQUIPMENT according to the monitor
959 * type detected.
960 */
961#ifndef VGA_NO_BIOS
962 switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */
963 case 0:
964 /* EGA/VGA */
965 fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f,
966 biosadapter);
967 break;
968 case 1:
969 /* CGA 40x25 */
970 /* FIXME: switch to the 80x25 mode? XXX */
971 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40];
972 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
973 break;
974 case 2:
975 /* CGA 80x25 */
976 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80];
977 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
978 break;
979 case 3:
980 /* MDA */
981 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
982 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
983 break;
984 }
985#else
986 /* assume EGA/VGA? XXX */
987 biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80];
988 biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
989#endif /* VGA_NO_BIOS */
990
991 biosadapters = 0;
992 if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) {
993 ++biosadapters;
994 biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED;
995 biosadapter[V_ADP_SECONDARY].va_mode =
996 biosadapter[V_ADP_SECONDARY].va_initial_mode =
997 map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type,
998 biosadapter[V_ADP_SECONDARY].va_flags
999 & V_ADP_COLOR,
1000 biosadapter[V_ADP_SECONDARY].va_initial_bios_mode);
1001 } else {
1002 biosadapter[V_ADP_SECONDARY].va_type = -1;
1003 }
1004 if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) {
1005 ++biosadapters;
1006 biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED;
1007#ifndef VGA_NO_BIOS
1008 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode =
1009 readb(BIOS_PADDRTOVADDR(0x449));
1010#else
1011 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */
1012#endif
1013 biosadapter[V_ADP_PRIMARY].va_mode =
1014 biosadapter[V_ADP_PRIMARY].va_initial_mode =
1015 map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type,
1016 biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR,
1017 biosadapter[V_ADP_PRIMARY].va_initial_bios_mode);
1018 } else {
1019 biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY];
1020 biosadapter[V_ADP_SECONDARY].va_type = -1;
1021 }
1022 if (biosadapters == 0)
1023 return biosadapters;
1024 biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY;
1025 biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY;
1026
1027#if 0 /* we don't need these... */
1028 fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...);
1029 fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...);
1030#endif
1031
1032#if 0
1033 /*
1034 * We cannot have two video adapter of the same type; there must be
1035 * only one of color or mono adapter, or one each of them.
1036 */
1037 if (biosadapters > 1) {
1038 if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags)
1039 & V_ADP_COLOR))
1040 /* we have two mono or color adapters!! */
1041 return (biosadapters = 0);
1042 }
1043#endif
1044
1045 /*
1046 * Ensure a zero start address. This is mainly to recover after
1047 * switching from pcvt using userconfig(). The registers are w/o
1048 * for old hardware so it's too hard to relocate the active screen
1049 * memory.
1050 * This must be done before vga_save_state() for VGA.
1051 */
1052 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12);
1053 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
1054 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13);
1055 outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
1056
1057 /* the video mode parameter table in EGA/VGA BIOS */
1058 /* NOTE: there can be only one EGA/VGA, wheather color or mono,
1059 * recognized by the video BIOS.
1060 */
1061 if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) ||
1062 (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) {
1063 adp = &biosadapter[V_ADP_PRIMARY];
1064 } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) ||
1065 (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) {
1066 adp = &biosadapter[V_ADP_SECONDARY];
1067 } else {
1068 adp = NULL;
1069 }
1070 bzero(mode_map, sizeof(mode_map));
1071 if (adp != NULL) {
1072 if (adp->va_type == KD_VGA) {
1073 vga_save_state(adp, &adpstate, sizeof(adpstate));
1074#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
1075 mode_map[adp->va_initial_mode] = adpstate.regs;
1076 rows_offset = 1;
1077#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1078 if (video_mode_ptr == NULL) {
1079 mode_map[adp->va_initial_mode] = adpstate.regs;
1080 rows_offset = 1;
1081 } else {
1082 /* discard the table if we are not familiar with it... */
1083 u_char *mp;
1080 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
1081 mp = get_mode_param(adp->va_initial_mode);
1082 if (mp != NULL)
1083 bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
1084 switch (comp_adpregs(adpstate.regs, mp)) {
1085 case COMP_IDENTICAL:
1086 /*
1087 * OK, this parameter table looks reasonably familiar
1088 * to us...
1089 */
1090 /*
1091 * This is a kludge for Toshiba DynaBook SS433
1092 * whose BIOS video mode table entry has the actual #
1093 * of rows at the offset 1; BIOSes from other
1094 * manufacturers store the # of rows - 1 there. XXX
1095 */
1096 rows_offset = adpstate.regs[1] + 1 - mp[1];
1097 break;
1098
1099 case COMP_SIMILAR:
1100 /*
1101 * Not exactly the same, but similar enough to be
1102 * trusted. However, use the saved register values
1103 * for the initial mode and other modes which are
1104 * based on the initial mode.
1105 */
1106 mode_map[adp->va_initial_mode] = adpstate.regs;
1107 rows_offset = adpstate.regs[1] + 1 - mp[1];
1108 adpstate.regs[1] -= rows_offset - 1;
1109 break;
1110
1111 case COMP_DIFFERENT:
1112 default:
1113 /*
1114 * Don't use the paramter table in BIOS. It doesn't
1115 * look familiar to us. Video mode switching is allowed
1116 * only if the new mode is the same as or based on
1117 * the initial mode.
1118 */
1119 video_mode_ptr = NULL;
1120 bzero(mode_map, sizeof(mode_map));
1121 mode_map[adp->va_initial_mode] = adpstate.regs;
1122 rows_offset = 1;
1123 break;
1124 }
1125 }
1126#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1127
1128#ifndef VGA_NO_MODE_CHANGE
1129 adp->va_flags |= V_ADP_MODECHANGE;
1130#endif
1131#ifndef VGA_NO_FONT_LOADING
1132 adp->va_flags |= V_ADP_FONT;
1133#endif
1134 } else if (adp->va_type == KD_EGA) {
1135#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
1136 rows_offset = 1;
1137#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1138 if (video_mode_ptr == NULL) {
1139 rows_offset = 1;
1140 } else {
1084 map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
1085 mp = get_mode_param(adp->va_initial_mode);
1086 if (mp != NULL)
1087 bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
1088 switch (comp_adpregs(adpstate.regs, mp)) {
1089 case COMP_IDENTICAL:
1090 /*
1091 * OK, this parameter table looks reasonably familiar
1092 * to us...
1093 */
1094 /*
1095 * This is a kludge for Toshiba DynaBook SS433
1096 * whose BIOS video mode table entry has the actual #
1097 * of rows at the offset 1; BIOSes from other
1098 * manufacturers store the # of rows - 1 there. XXX
1099 */
1100 rows_offset = adpstate.regs[1] + 1 - mp[1];
1101 break;
1102
1103 case COMP_SIMILAR:
1104 /*
1105 * Not exactly the same, but similar enough to be
1106 * trusted. However, use the saved register values
1107 * for the initial mode and other modes which are
1108 * based on the initial mode.
1109 */
1110 mode_map[adp->va_initial_mode] = adpstate.regs;
1111 rows_offset = adpstate.regs[1] + 1 - mp[1];
1112 adpstate.regs[1] -= rows_offset - 1;
1113 break;
1114
1115 case COMP_DIFFERENT:
1116 default:
1117 /*
1118 * Don't use the paramter table in BIOS. It doesn't
1119 * look familiar to us. Video mode switching is allowed
1120 * only if the new mode is the same as or based on
1121 * the initial mode.
1122 */
1123 video_mode_ptr = NULL;
1124 bzero(mode_map, sizeof(mode_map));
1125 mode_map[adp->va_initial_mode] = adpstate.regs;
1126 rows_offset = 1;
1127 break;
1128 }
1129 }
1130#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1131
1132#ifndef VGA_NO_MODE_CHANGE
1133 adp->va_flags |= V_ADP_MODECHANGE;
1134#endif
1135#ifndef VGA_NO_FONT_LOADING
1136 adp->va_flags |= V_ADP_FONT;
1137#endif
1138 } else if (adp->va_type == KD_EGA) {
1139#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
1140 rows_offset = 1;
1141#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1142 if (video_mode_ptr == NULL) {
1143 rows_offset = 1;
1144 } else {
1145 u_char *mp;
1141 map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1);
1142 /* XXX how can one validate the EGA table... */
1143 mp = get_mode_param(adp->va_initial_mode);
1144 if (mp != NULL) {
1145 adp->va_flags |= V_ADP_MODECHANGE;
1146#ifndef VGA_NO_FONT_LOADING
1147 adp->va_flags |= V_ADP_FONT;
1148#endif
1149 rows_offset = 1;
1150 } else {
1151 /*
1152 * This is serious. We will not be able to switch video
1153 * modes at all...
1154 */
1155 video_mode_ptr = NULL;
1156 bzero(mode_map, sizeof(mode_map));
1157 rows_offset = 1;
1158 }
1159 }
1160#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1161 }
1162 }
1163
1164 /* remove conflicting modes if we have more than one adapter */
1165 if (biosadapters > 1) {
1166 for (i = 0; i < biosadapters; ++i) {
1167 if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE))
1168 continue;
1169 clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1,
1170 (biosadapter[i].va_flags & V_ADP_COLOR) ?
1171 V_INFO_COLOR : 0);
1172 if ((biosadapter[i].va_type == KD_VGA)
1173 || (biosadapter[i].va_type == KD_EGA)) {
1174 biosadapter[i].va_io_base =
1175 (biosadapter[i].va_flags & V_ADP_COLOR) ?
1176 IO_VGA : IO_MDA;
1177 biosadapter[i].va_io_size = 32;
1178 }
1179 }
1180 }
1181
1182 /* buffer address */
1183 vga_get_info(&biosadapter[V_ADP_PRIMARY],
1184 biosadapter[V_ADP_PRIMARY].va_initial_mode, &info);
1185 update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info);
1186
1187 if (biosadapters > 1) {
1188 vga_get_info(&biosadapter[V_ADP_SECONDARY],
1189 biosadapter[V_ADP_SECONDARY].va_initial_mode, &info);
1190 update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info);
1191 }
1192
1193 /*
1194 * XXX: we should verify the following values for the primary adapter...
1195 * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
1196 * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02)
1197 * ? 0 : V_ADP_COLOR;
1198 * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
1199 * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
1200 * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
1201 * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
1202 */
1203
1204 return biosadapters;
1205}
1206
1207/* entry points */
1208
1209static int
1210vga_nop(void)
1211{
1212 return 0;
1213}
1214
1215static int
1216vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
1217{
1218 probe_adapters();
1219 if (unit >= biosadapters)
1220 return ENXIO;
1221
1222 *adpp = &biosadapter[unit];
1223
1224 return 0;
1225}
1226
1227static int
1228vga_init(int unit, video_adapter_t *adp, int flags)
1229{
1230 if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp))
1231 return ENXIO;
1232
1233 if (!init_done(adp)) {
1234 /* nothing to do really... */
1235 adp->va_flags |= V_ADP_INITIALIZED;
1236 }
1237
1238 if (!config_done(adp)) {
1239 if (vid_register(adp) < 0)
1240 return ENXIO;
1241 adp->va_flags |= V_ADP_REGISTERED;
1242 }
1243 if (vga_sub_configure != NULL)
1244 (*vga_sub_configure)(0);
1245
1246 return 0;
1247}
1248
1249/*
1250 * get_info():
1251 * Return the video_info structure of the requested video mode.
1252 *
1253 * all adapters
1254 */
1255static int
1256vga_get_info(video_adapter_t *adp, int mode, video_info_t *info)
1257{
1258 int i;
1259
1260 if (!init_done)
1261 return 1;
1262
1263 mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
1264#ifndef VGA_NO_MODE_CHANGE
1265 if (adp->va_flags & V_ADP_MODECHANGE) {
1266 /*
1267 * If the parameter table entry for this mode is not found,
1268 * the mode is not supported...
1269 */
1270 if (get_mode_param(mode) == NULL)
1271 return 1;
1272 } else
1273#endif /* VGA_NO_MODE_CHANGE */
1274 {
1275 /*
1276 * Even if we don't support video mode switching on this adapter,
1277 * the information on the initial (thus current) video mode
1278 * should be made available.
1279 */
1280 if (mode != adp->va_initial_mode)
1281 return 1;
1282 }
1283
1284 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1285 if (bios_vmode[i].vi_mode == NA)
1286 continue;
1287 if (mode == bios_vmode[i].vi_mode) {
1288 *info = bios_vmode[i];
1289 return 0;
1290 }
1291 }
1292 return 1;
1293}
1294
1295/*
1296 * query_mode():
1297 * Find a video mode matching the requested parameters.
1298 * Fields filled with 0 are considered "don't care" fields and
1299 * match any modes.
1300 *
1301 * all adapters
1302 */
1303static int
1304vga_query_mode(video_adapter_t *adp, video_info_t *info)
1305{
1306 video_info_t buf;
1307 int i;
1308
1309 if (!init_done)
1310 return -1;
1311
1312 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1313 if (bios_vmode[i].vi_mode == NA)
1314 continue;
1315
1316 if ((info->vi_width != 0)
1317 && (info->vi_width != bios_vmode[i].vi_width))
1318 continue;
1319 if ((info->vi_height != 0)
1320 && (info->vi_height != bios_vmode[i].vi_height))
1321 continue;
1322 if ((info->vi_cwidth != 0)
1323 && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
1324 continue;
1325 if ((info->vi_cheight != 0)
1326 && (info->vi_cheight != bios_vmode[i].vi_cheight))
1327 continue;
1328 if ((info->vi_depth != 0)
1329 && (info->vi_depth != bios_vmode[i].vi_depth))
1330 continue;
1331 if ((info->vi_planes != 0)
1332 && (info->vi_planes != bios_vmode[i].vi_planes))
1333 continue;
1334 /* XXX: should check pixel format, memory model */
1335 if ((info->vi_flags != 0)
1336 && (info->vi_flags != bios_vmode[i].vi_flags))
1337 continue;
1338
1339 /* verify if this mode is supported on this adapter */
1340 if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf))
1341 continue;
1342 return bios_vmode[i].vi_mode;
1343 }
1344 return -1;
1345}
1346
1347/*
1348 * set_mode():
1349 * Change the video mode.
1350 *
1351 * EGA/VGA
1352 */
1353static int
1354vga_set_mode(video_adapter_t *adp, int mode)
1355{
1356#ifndef VGA_NO_MODE_CHANGE
1357 video_info_t info;
1358 adp_state_t params;
1359
1360 prologue(adp, V_ADP_MODECHANGE, 1);
1361
1362 mode = map_gen_mode_num(adp->va_type,
1363 adp->va_flags & V_ADP_COLOR, mode);
1364 if (vga_get_info(adp, mode, &info))
1365 return 1;
1366 params.sig = V_STATE_SIG;
1367 bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
1368
1369 switch (mode) {
1370 case M_VGA_C80x60: case M_VGA_M80x60:
1371 params.regs[2] = 0x08;
1372 params.regs[19] = 0x47;
1373 goto special_480l;
1374
1375 case M_VGA_C80x30: case M_VGA_M80x30:
1376 params.regs[19] = 0x4f;
1377special_480l:
1378 params.regs[9] |= 0xc0;
1379 params.regs[16] = 0x08;
1380 params.regs[17] = 0x3e;
1381 params.regs[26] = 0xea;
1382 params.regs[28] = 0xdf;
1383 params.regs[31] = 0xe7;
1384 params.regs[32] = 0x04;
1385 goto setup_mode;
1386
1387 case M_ENH_C80x43: case M_ENH_B80x43:
1388 params.regs[28] = 87;
1389 goto special_80x50;
1390
1391 case M_VGA_C80x50: case M_VGA_M80x50:
1392special_80x50:
1393 params.regs[2] = 8;
1394 params.regs[19] = 7;
1395 goto setup_mode;
1396
1397 case M_VGA_C40x25: case M_VGA_C80x25:
1398 case M_VGA_M80x25:
1399 case M_B40x25: case M_C40x25:
1400 case M_B80x25: case M_C80x25:
1401 case M_ENH_B40x25: case M_ENH_C40x25:
1402 case M_ENH_B80x25: case M_ENH_C80x25:
1403 case M_EGAMONO80x25:
1404
1405setup_mode:
1406 vga_load_state(adp, &params);
1407 break;
1408
1409 case M_VGA_MODEX:
1410 /* "unchain" the VGA mode */
1411 params.regs[5-1+0x04] &= 0xf7;
1412 params.regs[5-1+0x04] |= 0x04;
1413 /* turn off doubleword mode */
1414 params.regs[10+0x14] &= 0xbf;
1415 /* turn off word adressing */
1416 params.regs[10+0x17] |= 0x40;
1417 /* set logical screen width */
1418 params.regs[10+0x13] = 80;
1419 /* set 240 lines */
1420 params.regs[10+0x11] = 0x2c;
1421 params.regs[10+0x06] = 0x0d;
1422 params.regs[10+0x07] = 0x3e;
1423 params.regs[10+0x10] = 0xea;
1424 params.regs[10+0x11] = 0xac;
1425 params.regs[10+0x12] = 0xdf;
1426 params.regs[10+0x15] = 0xe7;
1427 params.regs[10+0x16] = 0x06;
1428 /* set vertical sync polarity to reflect aspect ratio */
1429 params.regs[9] = 0xe3;
1430 goto setup_grmode;
1431
1432 case M_BG320: case M_CG320: case M_BG640:
1433 case M_CG320_D: case M_CG640_E:
1434 case M_CG640x350: case M_ENH_CG640:
1435 case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
1436
1437setup_grmode:
1438 vga_load_state(adp, &params);
1439 break;
1440
1441 default:
1442 return 1;
1443 }
1444
1445 adp->va_mode = mode;
1446 update_adapter_info(adp, &info);
1447
1448 /* move hardware cursor out of the way */
1449 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
1450
1451 return 0;
1452#else /* VGA_NO_MODE_CHANGE */
1453 return 1;
1454#endif /* VGA_NO_MODE_CHANGE */
1455}
1456
1457#ifndef VGA_NO_FONT_LOADING
1458
1459static void
1460set_font_mode(video_adapter_t *adp, u_char *buf)
1461{
1462 u_char *mp;
1463 int s;
1464
1465 s = splhigh();
1466
1467 /* save register values */
1468 if (adp->va_type == KD_VGA) {
1469 outb(TSIDX, 0x02); buf[0] = inb(TSREG);
1470 outb(TSIDX, 0x04); buf[1] = inb(TSREG);
1471 outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
1472 outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
1473 outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
1474 inb(adp->va_crtc_addr + 6);
1475 outb(ATC, 0x10); buf[5] = inb(ATC + 1);
1476 } else /* if (adp->va_type == KD_EGA) */ {
1477 /*
1478 * EGA cannot be read; copy parameters from the mode parameter
1479 * table.
1480 */
1481 mp = get_mode_param(adp->va_mode);
1482 buf[0] = mp[5 + 0x02 - 1];
1483 buf[1] = mp[5 + 0x04 - 1];
1484 buf[2] = mp[55 + 0x04];
1485 buf[3] = mp[55 + 0x05];
1486 buf[4] = mp[55 + 0x06];
1487 buf[5] = mp[35 + 0x10];
1488 }
1489
1490 /* setup vga for loading fonts */
1491 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1492 outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
1493 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1494 outb(ATC, 0x20); /* enable palette */
1495
1496#if VGA_SLOW_IOACCESS
1497#ifdef VGA_ALT_SEQACCESS
1498 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1499#endif
1500 outb(TSIDX, 0x02); outb(TSREG, 0x04);
1501 outb(TSIDX, 0x04); outb(TSREG, 0x07);
1502#ifdef VGA_ALT_SEQACCESS
1503 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1504#endif
1505 outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
1506 outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
1507 outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
1508#else /* VGA_SLOW_IOACCESS */
1509#ifdef VGA_ALT_SEQACCESS
1510 outw(TSIDX, 0x0100);
1511#endif
1512 outw(TSIDX, 0x0402);
1513 outw(TSIDX, 0x0704);
1514#ifdef VGA_ALT_SEQACCESS
1515 outw(TSIDX, 0x0300);
1516#endif
1517 outw(GDCIDX, 0x0204);
1518 outw(GDCIDX, 0x0005);
1519 outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */
1520#endif /* VGA_SLOW_IOACCESS */
1521
1522 splx(s);
1523}
1524
1525static void
1526set_normal_mode(video_adapter_t *adp, u_char *buf)
1527{
1528 int s;
1529
1530 s = splhigh();
1531
1532 /* setup vga for normal operation mode again */
1533 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1534 outb(ATC, 0x10); outb(ATC, buf[5]);
1535 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1536 outb(ATC, 0x20); /* enable palette */
1537
1538#if VGA_SLOW_IOACCESS
1539#ifdef VGA_ALT_SEQACCESS
1540 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1541#endif
1542 outb(TSIDX, 0x02); outb(TSREG, buf[0]);
1543 outb(TSIDX, 0x04); outb(TSREG, buf[1]);
1544#ifdef VGA_ALT_SEQACCESS
1545 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1546#endif
1547 outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
1548 outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
1549 if (adp->va_crtc_addr == MONO_CRTC) {
1550 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
1551 } else {
1552 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
1553 }
1554#else /* VGA_SLOW_IOACCESS */
1555#ifdef VGA_ALT_SEQACCESS
1556 outw(TSIDX, 0x0100);
1557#endif
1558 outw(TSIDX, 0x0002 | (buf[0] << 8));
1559 outw(TSIDX, 0x0004 | (buf[1] << 8));
1560#ifdef VGA_ALT_SEQACCESS
1561 outw(TSIDX, 0x0300);
1562#endif
1563 outw(GDCIDX, 0x0004 | (buf[2] << 8));
1564 outw(GDCIDX, 0x0005 | (buf[3] << 8));
1565 if (adp->va_crtc_addr == MONO_CRTC)
1566 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
1567 else
1568 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
1569#endif /* VGA_SLOW_IOACCESS */
1570
1571 splx(s);
1572}
1573
1574#endif /* VGA_NO_FONT_LOADING */
1575
1576/*
1577 * save_font():
1578 * Read the font data in the requested font page from the video adapter.
1579 *
1580 * EGA/VGA
1581 */
1582static int
1583vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1584 int ch, int count)
1585{
1586#ifndef VGA_NO_FONT_LOADING
1587 u_char buf[PARAM_BUFSIZE];
1588 u_int32_t segment;
1589 int c;
1590#ifdef VGA_ALT_SEQACCESS
1591 int s;
1592 u_char val = 0;
1593#endif
1594
1595 prologue(adp, V_ADP_FONT, 1);
1596
1597 if (fontsize < 14) {
1598 /* FONT_8 */
1599 fontsize = 8;
1600 } else if (fontsize >= 32) {
1601 fontsize = 32;
1602 } else if (fontsize >= 16) {
1603 /* FONT_16 */
1604 fontsize = 16;
1605 } else {
1606 /* FONT_14 */
1607 fontsize = 14;
1608 }
1609
1610 if (page < 0 || page >= 8)
1611 return 1;
1612 segment = FONT_BUF + 0x4000*page;
1613 if (page > 3)
1614 segment -= 0xe000;
1615
1616#ifdef VGA_ALT_SEQACCESS
1617 if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
1618 s = splhigh();
1619 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1620 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1621 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1622 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1623 splx(s);
1624 }
1625#endif
1626
1627 set_font_mode(adp, buf);
1628 if (fontsize == 32) {
1629 bcopy_fromio(segment + ch*32, data, fontsize*count);
1630 } else {
1631 for (c = ch; count > 0; ++c, --count) {
1632 bcopy_fromio(segment + c*32, data, fontsize);
1633 data += fontsize;
1634 }
1635 }
1636 set_normal_mode(adp, buf);
1637
1638#ifdef VGA_ALT_SEQACCESS
1639 if (adp->va_type == KD_VGA) {
1640 s = splhigh();
1641 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1642 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1643 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1644 splx(s);
1645 }
1646#endif
1647
1648 return 0;
1649#else /* VGA_NO_FONT_LOADING */
1650 return 1;
1651#endif /* VGA_NO_FONT_LOADING */
1652}
1653
1654/*
1655 * load_font():
1656 * Set the font data in the requested font page.
1657 * NOTE: it appears that some recent video adapters do not support
1658 * the font page other than 0... XXX
1659 *
1660 * EGA/VGA
1661 */
1662static int
1663vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1664 int ch, int count)
1665{
1666#ifndef VGA_NO_FONT_LOADING
1667 u_char buf[PARAM_BUFSIZE];
1668 u_int32_t segment;
1669 int c;
1670#ifdef VGA_ALT_SEQACCESS
1671 int s;
1672 u_char val = 0;
1673#endif
1674
1675 prologue(adp, V_ADP_FONT, 1);
1676
1677 if (fontsize < 14) {
1678 /* FONT_8 */
1679 fontsize = 8;
1680 } else if (fontsize >= 32) {
1681 fontsize = 32;
1682 } else if (fontsize >= 16) {
1683 /* FONT_16 */
1684 fontsize = 16;
1685 } else {
1686 /* FONT_14 */
1687 fontsize = 14;
1688 }
1689
1690 if (page < 0 || page >= 8)
1691 return 1;
1692 segment = FONT_BUF + 0x4000*page;
1693 if (page > 3)
1694 segment -= 0xe000;
1695
1696#ifdef VGA_ALT_SEQACCESS
1697 if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
1698 s = splhigh();
1699 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1700 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1701 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1702 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1703 splx(s);
1704 }
1705#endif
1706
1707 set_font_mode(adp, buf);
1708 if (fontsize == 32) {
1709 bcopy_toio(data, segment + ch*32, fontsize*count);
1710 } else {
1711 for (c = ch; count > 0; ++c, --count) {
1712 bcopy_toio(data, segment + c*32, fontsize);
1713 data += fontsize;
1714 }
1715 }
1716 set_normal_mode(adp, buf);
1717
1718#ifdef VGA_ALT_SEQACCESS
1719 if (adp->va_type == KD_VGA) {
1720 s = splhigh();
1721 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1722 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1723 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1724 splx(s);
1725 }
1726#endif
1727
1728 return 0;
1729#else /* VGA_NO_FONT_LOADING */
1730 return 1;
1731#endif /* VGA_NO_FONT_LOADING */
1732}
1733
1734/*
1735 * show_font():
1736 * Activate the requested font page.
1737 * NOTE: it appears that some recent video adapters do not support
1738 * the font page other than 0... XXX
1739 *
1740 * EGA/VGA
1741 */
1742static int
1743vga_show_font(video_adapter_t *adp, int page)
1744{
1745#ifndef VGA_NO_FONT_LOADING
1746 static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
1747 int s;
1748
1749 prologue(adp, V_ADP_FONT, 1);
1750 if (page < 0 || page >= 8)
1751 return 1;
1752
1753 s = splhigh();
1754 outb(TSIDX, 0x03); outb(TSREG, cg[page]);
1755 splx(s);
1756
1757 return 0;
1758#else /* VGA_NO_FONT_LOADING */
1759 return 1;
1760#endif /* VGA_NO_FONT_LOADING */
1761}
1762
1763/*
1764 * save_palette():
1765 * Read DAC values. The values have expressed in 8 bits.
1766 *
1767 * VGA
1768 */
1769static int
1770vga_save_palette(video_adapter_t *adp, u_char *palette)
1771{
1772 int i;
1773
1774 prologue(adp, V_ADP_PALETTE, 1);
1775
1776 /*
1777 * We store 8 bit values in the palette buffer, while the standard
1778 * VGA has 6 bit DAC .
1779 */
1780 outb(PALRADR, 0x00);
1781 for (i = 0; i < 256*3; ++i)
1782 palette[i] = inb(PALDATA) << 2;
1783 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
1784 return 0;
1785}
1786
1787/*
1788 * load_palette():
1789 * Set DAC values.
1790 *
1791 * VGA
1792 */
1793static int
1794vga_load_palette(video_adapter_t *adp, u_char *palette)
1795{
1796 int i;
1797
1798 prologue(adp, V_ADP_PALETTE, 1);
1799
1800 outb(PIXMASK, 0xff); /* no pixelmask */
1801 outb(PALWADR, 0x00);
1802 for (i = 0; i < 256*3; ++i)
1803 outb(PALDATA, palette[i] >> 2);
1804 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
1805 outb(ATC, 0x20); /* enable palette */
1806 return 0;
1807}
1808
1809/*
1810 * set_border():
1811 * Change the border color.
1812 *
1813 * CGA/EGA/VGA
1814 */
1815static int
1816vga_set_border(video_adapter_t *adp, int color)
1817{
1818 prologue(adp, V_ADP_BORDER, 1);
1819
1820 switch (adp->va_type) {
1821 case KD_EGA:
1822 case KD_VGA:
1823 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1824 outb(ATC, 0x31); outb(ATC, color & 0xff);
1825 break;
1826 case KD_CGA:
1827 outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */
1828 break;
1829 case KD_MONO:
1830 case KD_HERCULES:
1831 default:
1832 break;
1833 }
1834 return 0;
1835}
1836
1837/*
1838 * save_state():
1839 * Read video register values.
1840 * NOTE: this function only reads the standard EGA/VGA registers.
1841 * any extra/extended registers of SVGA adapters are not saved.
1842 *
1843 * VGA
1844 */
1845static int
1846vga_save_state(video_adapter_t *adp, void *p, size_t size)
1847{
1848 video_info_t info;
1849 u_char *buf;
1850 int crtc_addr;
1851 int i, j;
1852 int s;
1853
1854 if (size == 0) {
1855 /* return the required buffer size */
1856 prologue(adp, V_ADP_STATESAVE, 0);
1857 return sizeof(adp_state_t);
1858 } else {
1859 prologue(adp, V_ADP_STATESAVE, 1);
1860 if (size < sizeof(adp_state_t))
1861 return 1;
1862 }
1863
1864 ((adp_state_t *)p)->sig = V_STATE_SIG;
1865 buf = ((adp_state_t *)p)->regs;
1866 bzero(buf, V_MODE_PARAM_SIZE);
1867 crtc_addr = adp->va_crtc_addr;
1868
1869 s = splhigh();
1870
1871 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
1872 for (i = 0, j = 5; i < 4; i++) {
1873 outb(TSIDX, i + 1);
1874 buf[j++] = inb(TSREG);
1875 }
1876 buf[9] = inb(MISC + 10); /* dot-clock */
1877 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
1878
1879 for (i = 0, j = 10; i < 25; i++) { /* crtc */
1880 outb(crtc_addr, i);
1881 buf[j++] = inb(crtc_addr + 1);
1882 }
1883 for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */
1884 inb(crtc_addr + 6); /* reset flip-flop */
1885 outb(ATC, i);
1886 buf[j++] = inb(ATC + 1);
1887 }
1888 for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */
1889 outb(GDCIDX, i);
1890 buf[j++] = inb(GDCREG);
1891 }
1892 inb(crtc_addr + 6); /* reset flip-flop */
1893 outb(ATC, 0x20); /* enable palette */
1894
1895 splx(s);
1896
1897#if 1
1898 if (vga_get_info(adp, adp->va_mode, &info) == 0) {
1899 if (info.vi_flags & V_INFO_GRAPHICS) {
1900 buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
1901 buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
1902 } else {
1903 buf[0] = info.vi_width; /* COLS */
1904 buf[1] = info.vi_height - 1; /* ROWS */
1905 }
1906 buf[2] = info.vi_cheight; /* POINTS */
1907 } else {
1908 /* XXX: shouldn't be happening... */
1909 printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n",
1910 adp->va_unit, adp->va_name);
1911 }
1912#else
1913 buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */
1914 buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */
1915 buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */
1916 buf[3] = readb(BIOS_PADDRTOVADDR(0x44c));
1917 buf[4] = readb(BIOS_PADDRTOVADDR(0x44d));
1918#endif
1919
1920 return 0;
1921}
1922
1923/*
1924 * load_state():
1925 * Set video registers at once.
1926 * NOTE: this function only updates the standard EGA/VGA registers.
1927 * any extra/extended registers of SVGA adapters are not changed.
1928 *
1929 * EGA/VGA
1930 */
1931static int
1932vga_load_state(video_adapter_t *adp, void *p)
1933{
1934 u_char *buf;
1935 int crtc_addr;
1936 int s;
1937 int i;
1938
1939 prologue(adp, V_ADP_STATELOAD, 1);
1940 if (((adp_state_t *)p)->sig != V_STATE_SIG)
1941 return 1;
1942
1943 buf = ((adp_state_t *)p)->regs;
1944 crtc_addr = adp->va_crtc_addr;
1945
1946 s = splhigh();
1947
1948 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
1949 for (i = 0; i < 4; ++i) { /* program sequencer */
1950 outb(TSIDX, i + 1);
1951 outb(TSREG, buf[i + 5]);
1952 }
1953 outb(MISC, buf[9]); /* set dot-clock */
1954 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
1955 outb(crtc_addr, 0x11);
1956 outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
1957 for (i = 0; i < 25; ++i) { /* program crtc */
1958 outb(crtc_addr, i);
1959 outb(crtc_addr + 1, buf[i + 10]);
1960 }
1961 inb(crtc_addr+6); /* reset flip-flop */
1962 for (i = 0; i < 20; ++i) { /* program attribute ctrl */
1963 outb(ATC, i);
1964 outb(ATC, buf[i + 35]);
1965 }
1966 for (i = 0; i < 9; ++i) { /* program graph data ctrl */
1967 outb(GDCIDX, i);
1968 outb(GDCREG, buf[i + 55]);
1969 }
1970 inb(crtc_addr + 6); /* reset flip-flop */
1971 outb(ATC, 0x20); /* enable palette */
1972
1973#ifndef VGA_NO_BIOS
1974 if (adp->va_unit == V_ADP_PRIMARY) {
1975 writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */
1976 writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */
1977 writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */
1978#if 0
1979 writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]);
1980 writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]);
1981#endif
1982 }
1983#endif /* VGA_NO_BIOS */
1984
1985 splx(s);
1986 return 0;
1987}
1988
1989/*
1990 * set_origin():
1991 * Change the origin (window mapping) of the banked frame buffer.
1992 */
1993static int
1994vga_set_origin(video_adapter_t *adp, off_t offset)
1995{
1996 /*
1997 * The standard video modes do not require window mapping;
1998 * always return error.
1999 */
2000 return 1;
2001}
2002
2003/*
2004 * read_hw_cursor():
2005 * Read the position of the hardware text cursor.
2006 *
2007 * all adapters
2008 */
2009static int
2010vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
2011{
2012 u_int16_t off;
2013 int s;
2014
2015 if (!init_done)
2016 return 1;
2017
2018 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
2019 return 1;
2020
2021 s = spltty();
2022 outb(adp->va_crtc_addr, 14);
2023 off = inb(adp->va_crtc_addr + 1);
2024 outb(adp->va_crtc_addr, 15);
2025 off = (off << 8) | inb(adp->va_crtc_addr + 1);
2026 splx(s);
2027
2028 *row = off / adp->va_info.vi_width;
2029 *col = off % adp->va_info.vi_width;
2030
2031 return 0;
2032}
2033
2034/*
2035 * set_hw_cursor():
2036 * Move the hardware text cursor. If col and row are both -1,
2037 * the cursor won't be shown.
2038 *
2039 * all adapters
2040 */
2041static int
2042vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
2043{
2044 u_int16_t off;
2045 int s;
2046
2047 if (!init_done)
2048 return 1;
2049
2050 if ((col == -1) && (row == -1)) {
2051 off = -1;
2052 } else {
2053 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
2054 return 1;
2055 off = row*adp->va_info.vi_width + col;
2056 }
2057
2058 s = spltty();
2059 outb(adp->va_crtc_addr, 14);
2060 outb(adp->va_crtc_addr + 1, off >> 8);
2061 outb(adp->va_crtc_addr, 15);
2062 outb(adp->va_crtc_addr + 1, off & 0x00ff);
2063 splx(s);
2064
2065 return 0;
2066}
2067
2068/*
2069 * set_hw_cursor_shape():
2070 * Change the shape of the hardware text cursor. If the height is
2071 * zero or negative, the cursor won't be shown.
2072 *
2073 * all adapters
2074 */
2075static int
2076vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
2077 int celsize, int blink)
2078{
2079 int s;
2080
2081 if (!init_done)
2082 return 1;
2083
2084 s = spltty();
2085 switch (adp->va_type) {
2086 case KD_VGA:
2087 case KD_CGA:
2088 case KD_MONO:
2089 case KD_HERCULES:
2090 default:
2091 if (height <= 0) {
2092 /* make the cursor invisible */
2093 outb(adp->va_crtc_addr, 10);
2094 outb(adp->va_crtc_addr + 1, 32);
2095 outb(adp->va_crtc_addr, 11);
2096 outb(adp->va_crtc_addr + 1, 0);
2097 } else {
2098 outb(adp->va_crtc_addr, 10);
2099 outb(adp->va_crtc_addr + 1, celsize - base - height);
2100 outb(adp->va_crtc_addr, 11);
2101 outb(adp->va_crtc_addr + 1, celsize - base - 1);
2102 }
2103 break;
2104 case KD_EGA:
2105 if (height <= 0) {
2106 /* make the cursor invisible */
2107 outb(adp->va_crtc_addr, 10);
2108 outb(adp->va_crtc_addr + 1, celsize);
2109 outb(adp->va_crtc_addr, 11);
2110 outb(adp->va_crtc_addr + 1, 0);
2111 } else {
2112 outb(adp->va_crtc_addr, 10);
2113 outb(adp->va_crtc_addr + 1, celsize - base - height);
2114 outb(adp->va_crtc_addr, 11);
2115 outb(adp->va_crtc_addr + 1, celsize - base);
2116 }
2117 break;
2118 }
2119 splx(s);
2120
2121 return 0;
2122}
2123
2124/*
2125 * mmap():
2126 * Mmap frame buffer.
2127 *
2128 * all adapters
2129 */
2130static int
2131vga_mmap(video_adapter_t *adp, vm_offset_t offset)
2132{
2133 if (offset > 0x20000 - PAGE_SIZE)
2134 return -1;
2135#ifdef __i386__
2136 return i386_btop((VIDEO_BUF_BASE + offset));
2137#endif
2138#ifdef __alpha__
2139 return alpha_btop((VIDEO_BUF_BASE + offset));
2140#endif
2141}
2142
2143static void
2144dump_buffer(u_char *buf, size_t len)
2145{
2146 int i;
2147
2148 for(i = 0; i < len;) {
2149 printf("%02x ", buf[i]);
2150 if ((++i % 16) == 0)
2151 printf("\n");
2152 }
2153}
2154
2155/*
2156 * diag():
2157 * Print some information about the video adapter and video modes,
2158 * with requested level of details.
2159 *
2160 * all adapters
2161 */
2162static int
2163vga_diag(video_adapter_t *adp, int level)
2164{
2165#if FB_DEBUG > 1
2166 video_info_t info;
2167#endif
2168 u_char *mp;
2169
2170 if (!init_done)
2171 return 1;
2172
2173#if FB_DEBUG > 1
2174#ifndef VGA_NO_BIOS
2175 printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n",
2176 rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488)));
2177 printf("vga: CRTC:0x%x, video option:0x%02x, ",
2178 readw(BIOS_PADDRTOVADDR(0x463)),
2179 readb(BIOS_PADDRTOVADDR(0x487)));
2180 printf("rows:%d, cols:%d, font height:%d\n",
2181 readb(BIOS_PADDRTOVADDR(0x44a)),
2182 readb(BIOS_PADDRTOVADDR(0x484)) + 1,
2183 readb(BIOS_PADDRTOVADDR(0x485)));
2184#endif /* VGA_NO_BIOS */
2185 printf("vga: param table EGA/VGA:%p", video_mode_ptr);
2186 printf(", CGA/MDA:%p\n", video_mode_ptr2);
2187 printf("vga: rows_offset:%d\n", rows_offset);
2188#endif /* FB_DEBUG > 1 */
2189
2190 fb_dump_adp_info(DRIVER_NAME, adp, level);
2191
2192#if FB_DEBUG > 1
2193 if (adp->va_flags & V_ADP_MODECHANGE) {
2194 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
2195 if (bios_vmode[i].vi_mode == NA)
2196 continue;
2197 if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
2198 continue;
2199 fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level);
2200 }
2201 } else {
2202 vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */
2203 fb_dump_mode_info(DRIVER_NAME, adp, &info, level);
2204 }
2205#endif /* FB_DEBUG > 1 */
2206
2207 if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA))
2208 return 0;
2209#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
2210 if (video_mode_ptr == NULL)
2211 printf("vga%d: %s: WARNING: video mode switching is not "
2212 "fully supported on this adapter\n",
2213 adp->va_unit, adp->va_name);
2214#endif
2215 if (level <= 0)
2216 return 0;
2217
2218 if (adp->va_type == KD_VGA) {
2219 printf("VGA parameters upon power-up\n");
2220 dump_buffer(adpstate.regs, sizeof(adpstate.regs));
2221 printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
2222 dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
2223 }
2224
2225 mp = get_mode_param(adp->va_initial_mode);
2226 if (mp == NULL) /* this shouldn't be happening */
2227 return 0;
2228 printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode);
2229 dump_buffer(mp, V_MODE_PARAM_SIZE);
2230
2231 return 0;
2232}
2233
2234#endif /* NVGA > 0 */
1146 map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1);
1147 /* XXX how can one validate the EGA table... */
1148 mp = get_mode_param(adp->va_initial_mode);
1149 if (mp != NULL) {
1150 adp->va_flags |= V_ADP_MODECHANGE;
1151#ifndef VGA_NO_FONT_LOADING
1152 adp->va_flags |= V_ADP_FONT;
1153#endif
1154 rows_offset = 1;
1155 } else {
1156 /*
1157 * This is serious. We will not be able to switch video
1158 * modes at all...
1159 */
1160 video_mode_ptr = NULL;
1161 bzero(mode_map, sizeof(mode_map));
1162 rows_offset = 1;
1163 }
1164 }
1165#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
1166 }
1167 }
1168
1169 /* remove conflicting modes if we have more than one adapter */
1170 if (biosadapters > 1) {
1171 for (i = 0; i < biosadapters; ++i) {
1172 if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE))
1173 continue;
1174 clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1,
1175 (biosadapter[i].va_flags & V_ADP_COLOR) ?
1176 V_INFO_COLOR : 0);
1177 if ((biosadapter[i].va_type == KD_VGA)
1178 || (biosadapter[i].va_type == KD_EGA)) {
1179 biosadapter[i].va_io_base =
1180 (biosadapter[i].va_flags & V_ADP_COLOR) ?
1181 IO_VGA : IO_MDA;
1182 biosadapter[i].va_io_size = 32;
1183 }
1184 }
1185 }
1186
1187 /* buffer address */
1188 vga_get_info(&biosadapter[V_ADP_PRIMARY],
1189 biosadapter[V_ADP_PRIMARY].va_initial_mode, &info);
1190 update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info);
1191
1192 if (biosadapters > 1) {
1193 vga_get_info(&biosadapter[V_ADP_SECONDARY],
1194 biosadapter[V_ADP_SECONDARY].va_initial_mode, &info);
1195 update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info);
1196 }
1197
1198 /*
1199 * XXX: we should verify the following values for the primary adapter...
1200 * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
1201 * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02)
1202 * ? 0 : V_ADP_COLOR;
1203 * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
1204 * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
1205 * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
1206 * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
1207 */
1208
1209 return biosadapters;
1210}
1211
1212/* entry points */
1213
1214static int
1215vga_nop(void)
1216{
1217 return 0;
1218}
1219
1220static int
1221vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
1222{
1223 probe_adapters();
1224 if (unit >= biosadapters)
1225 return ENXIO;
1226
1227 *adpp = &biosadapter[unit];
1228
1229 return 0;
1230}
1231
1232static int
1233vga_init(int unit, video_adapter_t *adp, int flags)
1234{
1235 if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp))
1236 return ENXIO;
1237
1238 if (!init_done(adp)) {
1239 /* nothing to do really... */
1240 adp->va_flags |= V_ADP_INITIALIZED;
1241 }
1242
1243 if (!config_done(adp)) {
1244 if (vid_register(adp) < 0)
1245 return ENXIO;
1246 adp->va_flags |= V_ADP_REGISTERED;
1247 }
1248 if (vga_sub_configure != NULL)
1249 (*vga_sub_configure)(0);
1250
1251 return 0;
1252}
1253
1254/*
1255 * get_info():
1256 * Return the video_info structure of the requested video mode.
1257 *
1258 * all adapters
1259 */
1260static int
1261vga_get_info(video_adapter_t *adp, int mode, video_info_t *info)
1262{
1263 int i;
1264
1265 if (!init_done)
1266 return 1;
1267
1268 mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
1269#ifndef VGA_NO_MODE_CHANGE
1270 if (adp->va_flags & V_ADP_MODECHANGE) {
1271 /*
1272 * If the parameter table entry for this mode is not found,
1273 * the mode is not supported...
1274 */
1275 if (get_mode_param(mode) == NULL)
1276 return 1;
1277 } else
1278#endif /* VGA_NO_MODE_CHANGE */
1279 {
1280 /*
1281 * Even if we don't support video mode switching on this adapter,
1282 * the information on the initial (thus current) video mode
1283 * should be made available.
1284 */
1285 if (mode != adp->va_initial_mode)
1286 return 1;
1287 }
1288
1289 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1290 if (bios_vmode[i].vi_mode == NA)
1291 continue;
1292 if (mode == bios_vmode[i].vi_mode) {
1293 *info = bios_vmode[i];
1294 return 0;
1295 }
1296 }
1297 return 1;
1298}
1299
1300/*
1301 * query_mode():
1302 * Find a video mode matching the requested parameters.
1303 * Fields filled with 0 are considered "don't care" fields and
1304 * match any modes.
1305 *
1306 * all adapters
1307 */
1308static int
1309vga_query_mode(video_adapter_t *adp, video_info_t *info)
1310{
1311 video_info_t buf;
1312 int i;
1313
1314 if (!init_done)
1315 return -1;
1316
1317 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
1318 if (bios_vmode[i].vi_mode == NA)
1319 continue;
1320
1321 if ((info->vi_width != 0)
1322 && (info->vi_width != bios_vmode[i].vi_width))
1323 continue;
1324 if ((info->vi_height != 0)
1325 && (info->vi_height != bios_vmode[i].vi_height))
1326 continue;
1327 if ((info->vi_cwidth != 0)
1328 && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
1329 continue;
1330 if ((info->vi_cheight != 0)
1331 && (info->vi_cheight != bios_vmode[i].vi_cheight))
1332 continue;
1333 if ((info->vi_depth != 0)
1334 && (info->vi_depth != bios_vmode[i].vi_depth))
1335 continue;
1336 if ((info->vi_planes != 0)
1337 && (info->vi_planes != bios_vmode[i].vi_planes))
1338 continue;
1339 /* XXX: should check pixel format, memory model */
1340 if ((info->vi_flags != 0)
1341 && (info->vi_flags != bios_vmode[i].vi_flags))
1342 continue;
1343
1344 /* verify if this mode is supported on this adapter */
1345 if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf))
1346 continue;
1347 return bios_vmode[i].vi_mode;
1348 }
1349 return -1;
1350}
1351
1352/*
1353 * set_mode():
1354 * Change the video mode.
1355 *
1356 * EGA/VGA
1357 */
1358static int
1359vga_set_mode(video_adapter_t *adp, int mode)
1360{
1361#ifndef VGA_NO_MODE_CHANGE
1362 video_info_t info;
1363 adp_state_t params;
1364
1365 prologue(adp, V_ADP_MODECHANGE, 1);
1366
1367 mode = map_gen_mode_num(adp->va_type,
1368 adp->va_flags & V_ADP_COLOR, mode);
1369 if (vga_get_info(adp, mode, &info))
1370 return 1;
1371 params.sig = V_STATE_SIG;
1372 bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
1373
1374 switch (mode) {
1375 case M_VGA_C80x60: case M_VGA_M80x60:
1376 params.regs[2] = 0x08;
1377 params.regs[19] = 0x47;
1378 goto special_480l;
1379
1380 case M_VGA_C80x30: case M_VGA_M80x30:
1381 params.regs[19] = 0x4f;
1382special_480l:
1383 params.regs[9] |= 0xc0;
1384 params.regs[16] = 0x08;
1385 params.regs[17] = 0x3e;
1386 params.regs[26] = 0xea;
1387 params.regs[28] = 0xdf;
1388 params.regs[31] = 0xe7;
1389 params.regs[32] = 0x04;
1390 goto setup_mode;
1391
1392 case M_ENH_C80x43: case M_ENH_B80x43:
1393 params.regs[28] = 87;
1394 goto special_80x50;
1395
1396 case M_VGA_C80x50: case M_VGA_M80x50:
1397special_80x50:
1398 params.regs[2] = 8;
1399 params.regs[19] = 7;
1400 goto setup_mode;
1401
1402 case M_VGA_C40x25: case M_VGA_C80x25:
1403 case M_VGA_M80x25:
1404 case M_B40x25: case M_C40x25:
1405 case M_B80x25: case M_C80x25:
1406 case M_ENH_B40x25: case M_ENH_C40x25:
1407 case M_ENH_B80x25: case M_ENH_C80x25:
1408 case M_EGAMONO80x25:
1409
1410setup_mode:
1411 vga_load_state(adp, &params);
1412 break;
1413
1414 case M_VGA_MODEX:
1415 /* "unchain" the VGA mode */
1416 params.regs[5-1+0x04] &= 0xf7;
1417 params.regs[5-1+0x04] |= 0x04;
1418 /* turn off doubleword mode */
1419 params.regs[10+0x14] &= 0xbf;
1420 /* turn off word adressing */
1421 params.regs[10+0x17] |= 0x40;
1422 /* set logical screen width */
1423 params.regs[10+0x13] = 80;
1424 /* set 240 lines */
1425 params.regs[10+0x11] = 0x2c;
1426 params.regs[10+0x06] = 0x0d;
1427 params.regs[10+0x07] = 0x3e;
1428 params.regs[10+0x10] = 0xea;
1429 params.regs[10+0x11] = 0xac;
1430 params.regs[10+0x12] = 0xdf;
1431 params.regs[10+0x15] = 0xe7;
1432 params.regs[10+0x16] = 0x06;
1433 /* set vertical sync polarity to reflect aspect ratio */
1434 params.regs[9] = 0xe3;
1435 goto setup_grmode;
1436
1437 case M_BG320: case M_CG320: case M_BG640:
1438 case M_CG320_D: case M_CG640_E:
1439 case M_CG640x350: case M_ENH_CG640:
1440 case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
1441
1442setup_grmode:
1443 vga_load_state(adp, &params);
1444 break;
1445
1446 default:
1447 return 1;
1448 }
1449
1450 adp->va_mode = mode;
1451 update_adapter_info(adp, &info);
1452
1453 /* move hardware cursor out of the way */
1454 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
1455
1456 return 0;
1457#else /* VGA_NO_MODE_CHANGE */
1458 return 1;
1459#endif /* VGA_NO_MODE_CHANGE */
1460}
1461
1462#ifndef VGA_NO_FONT_LOADING
1463
1464static void
1465set_font_mode(video_adapter_t *adp, u_char *buf)
1466{
1467 u_char *mp;
1468 int s;
1469
1470 s = splhigh();
1471
1472 /* save register values */
1473 if (adp->va_type == KD_VGA) {
1474 outb(TSIDX, 0x02); buf[0] = inb(TSREG);
1475 outb(TSIDX, 0x04); buf[1] = inb(TSREG);
1476 outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
1477 outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
1478 outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
1479 inb(adp->va_crtc_addr + 6);
1480 outb(ATC, 0x10); buf[5] = inb(ATC + 1);
1481 } else /* if (adp->va_type == KD_EGA) */ {
1482 /*
1483 * EGA cannot be read; copy parameters from the mode parameter
1484 * table.
1485 */
1486 mp = get_mode_param(adp->va_mode);
1487 buf[0] = mp[5 + 0x02 - 1];
1488 buf[1] = mp[5 + 0x04 - 1];
1489 buf[2] = mp[55 + 0x04];
1490 buf[3] = mp[55 + 0x05];
1491 buf[4] = mp[55 + 0x06];
1492 buf[5] = mp[35 + 0x10];
1493 }
1494
1495 /* setup vga for loading fonts */
1496 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1497 outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
1498 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1499 outb(ATC, 0x20); /* enable palette */
1500
1501#if VGA_SLOW_IOACCESS
1502#ifdef VGA_ALT_SEQACCESS
1503 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1504#endif
1505 outb(TSIDX, 0x02); outb(TSREG, 0x04);
1506 outb(TSIDX, 0x04); outb(TSREG, 0x07);
1507#ifdef VGA_ALT_SEQACCESS
1508 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1509#endif
1510 outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
1511 outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
1512 outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
1513#else /* VGA_SLOW_IOACCESS */
1514#ifdef VGA_ALT_SEQACCESS
1515 outw(TSIDX, 0x0100);
1516#endif
1517 outw(TSIDX, 0x0402);
1518 outw(TSIDX, 0x0704);
1519#ifdef VGA_ALT_SEQACCESS
1520 outw(TSIDX, 0x0300);
1521#endif
1522 outw(GDCIDX, 0x0204);
1523 outw(GDCIDX, 0x0005);
1524 outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */
1525#endif /* VGA_SLOW_IOACCESS */
1526
1527 splx(s);
1528}
1529
1530static void
1531set_normal_mode(video_adapter_t *adp, u_char *buf)
1532{
1533 int s;
1534
1535 s = splhigh();
1536
1537 /* setup vga for normal operation mode again */
1538 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1539 outb(ATC, 0x10); outb(ATC, buf[5]);
1540 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1541 outb(ATC, 0x20); /* enable palette */
1542
1543#if VGA_SLOW_IOACCESS
1544#ifdef VGA_ALT_SEQACCESS
1545 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1546#endif
1547 outb(TSIDX, 0x02); outb(TSREG, buf[0]);
1548 outb(TSIDX, 0x04); outb(TSREG, buf[1]);
1549#ifdef VGA_ALT_SEQACCESS
1550 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1551#endif
1552 outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
1553 outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
1554 if (adp->va_crtc_addr == MONO_CRTC) {
1555 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
1556 } else {
1557 outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
1558 }
1559#else /* VGA_SLOW_IOACCESS */
1560#ifdef VGA_ALT_SEQACCESS
1561 outw(TSIDX, 0x0100);
1562#endif
1563 outw(TSIDX, 0x0002 | (buf[0] << 8));
1564 outw(TSIDX, 0x0004 | (buf[1] << 8));
1565#ifdef VGA_ALT_SEQACCESS
1566 outw(TSIDX, 0x0300);
1567#endif
1568 outw(GDCIDX, 0x0004 | (buf[2] << 8));
1569 outw(GDCIDX, 0x0005 | (buf[3] << 8));
1570 if (adp->va_crtc_addr == MONO_CRTC)
1571 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
1572 else
1573 outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
1574#endif /* VGA_SLOW_IOACCESS */
1575
1576 splx(s);
1577}
1578
1579#endif /* VGA_NO_FONT_LOADING */
1580
1581/*
1582 * save_font():
1583 * Read the font data in the requested font page from the video adapter.
1584 *
1585 * EGA/VGA
1586 */
1587static int
1588vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1589 int ch, int count)
1590{
1591#ifndef VGA_NO_FONT_LOADING
1592 u_char buf[PARAM_BUFSIZE];
1593 u_int32_t segment;
1594 int c;
1595#ifdef VGA_ALT_SEQACCESS
1596 int s;
1597 u_char val = 0;
1598#endif
1599
1600 prologue(adp, V_ADP_FONT, 1);
1601
1602 if (fontsize < 14) {
1603 /* FONT_8 */
1604 fontsize = 8;
1605 } else if (fontsize >= 32) {
1606 fontsize = 32;
1607 } else if (fontsize >= 16) {
1608 /* FONT_16 */
1609 fontsize = 16;
1610 } else {
1611 /* FONT_14 */
1612 fontsize = 14;
1613 }
1614
1615 if (page < 0 || page >= 8)
1616 return 1;
1617 segment = FONT_BUF + 0x4000*page;
1618 if (page > 3)
1619 segment -= 0xe000;
1620
1621#ifdef VGA_ALT_SEQACCESS
1622 if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
1623 s = splhigh();
1624 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1625 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1626 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1627 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1628 splx(s);
1629 }
1630#endif
1631
1632 set_font_mode(adp, buf);
1633 if (fontsize == 32) {
1634 bcopy_fromio(segment + ch*32, data, fontsize*count);
1635 } else {
1636 for (c = ch; count > 0; ++c, --count) {
1637 bcopy_fromio(segment + c*32, data, fontsize);
1638 data += fontsize;
1639 }
1640 }
1641 set_normal_mode(adp, buf);
1642
1643#ifdef VGA_ALT_SEQACCESS
1644 if (adp->va_type == KD_VGA) {
1645 s = splhigh();
1646 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1647 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1648 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1649 splx(s);
1650 }
1651#endif
1652
1653 return 0;
1654#else /* VGA_NO_FONT_LOADING */
1655 return 1;
1656#endif /* VGA_NO_FONT_LOADING */
1657}
1658
1659/*
1660 * load_font():
1661 * Set the font data in the requested font page.
1662 * NOTE: it appears that some recent video adapters do not support
1663 * the font page other than 0... XXX
1664 *
1665 * EGA/VGA
1666 */
1667static int
1668vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
1669 int ch, int count)
1670{
1671#ifndef VGA_NO_FONT_LOADING
1672 u_char buf[PARAM_BUFSIZE];
1673 u_int32_t segment;
1674 int c;
1675#ifdef VGA_ALT_SEQACCESS
1676 int s;
1677 u_char val = 0;
1678#endif
1679
1680 prologue(adp, V_ADP_FONT, 1);
1681
1682 if (fontsize < 14) {
1683 /* FONT_8 */
1684 fontsize = 8;
1685 } else if (fontsize >= 32) {
1686 fontsize = 32;
1687 } else if (fontsize >= 16) {
1688 /* FONT_16 */
1689 fontsize = 16;
1690 } else {
1691 /* FONT_14 */
1692 fontsize = 14;
1693 }
1694
1695 if (page < 0 || page >= 8)
1696 return 1;
1697 segment = FONT_BUF + 0x4000*page;
1698 if (page > 3)
1699 segment -= 0xe000;
1700
1701#ifdef VGA_ALT_SEQACCESS
1702 if (adp->va_type == KD_VGA) { /* what about EGA? XXX */
1703 s = splhigh();
1704 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1705 outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */
1706 outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
1707 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1708 splx(s);
1709 }
1710#endif
1711
1712 set_font_mode(adp, buf);
1713 if (fontsize == 32) {
1714 bcopy_toio(data, segment + ch*32, fontsize*count);
1715 } else {
1716 for (c = ch; count > 0; ++c, --count) {
1717 bcopy_toio(data, segment + c*32, fontsize);
1718 data += fontsize;
1719 }
1720 }
1721 set_normal_mode(adp, buf);
1722
1723#ifdef VGA_ALT_SEQACCESS
1724 if (adp->va_type == KD_VGA) {
1725 s = splhigh();
1726 outb(TSIDX, 0x00); outb(TSREG, 0x01);
1727 outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */
1728 outb(TSIDX, 0x00); outb(TSREG, 0x03);
1729 splx(s);
1730 }
1731#endif
1732
1733 return 0;
1734#else /* VGA_NO_FONT_LOADING */
1735 return 1;
1736#endif /* VGA_NO_FONT_LOADING */
1737}
1738
1739/*
1740 * show_font():
1741 * Activate the requested font page.
1742 * NOTE: it appears that some recent video adapters do not support
1743 * the font page other than 0... XXX
1744 *
1745 * EGA/VGA
1746 */
1747static int
1748vga_show_font(video_adapter_t *adp, int page)
1749{
1750#ifndef VGA_NO_FONT_LOADING
1751 static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
1752 int s;
1753
1754 prologue(adp, V_ADP_FONT, 1);
1755 if (page < 0 || page >= 8)
1756 return 1;
1757
1758 s = splhigh();
1759 outb(TSIDX, 0x03); outb(TSREG, cg[page]);
1760 splx(s);
1761
1762 return 0;
1763#else /* VGA_NO_FONT_LOADING */
1764 return 1;
1765#endif /* VGA_NO_FONT_LOADING */
1766}
1767
1768/*
1769 * save_palette():
1770 * Read DAC values. The values have expressed in 8 bits.
1771 *
1772 * VGA
1773 */
1774static int
1775vga_save_palette(video_adapter_t *adp, u_char *palette)
1776{
1777 int i;
1778
1779 prologue(adp, V_ADP_PALETTE, 1);
1780
1781 /*
1782 * We store 8 bit values in the palette buffer, while the standard
1783 * VGA has 6 bit DAC .
1784 */
1785 outb(PALRADR, 0x00);
1786 for (i = 0; i < 256*3; ++i)
1787 palette[i] = inb(PALDATA) << 2;
1788 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
1789 return 0;
1790}
1791
1792/*
1793 * load_palette():
1794 * Set DAC values.
1795 *
1796 * VGA
1797 */
1798static int
1799vga_load_palette(video_adapter_t *adp, u_char *palette)
1800{
1801 int i;
1802
1803 prologue(adp, V_ADP_PALETTE, 1);
1804
1805 outb(PIXMASK, 0xff); /* no pixelmask */
1806 outb(PALWADR, 0x00);
1807 for (i = 0; i < 256*3; ++i)
1808 outb(PALDATA, palette[i] >> 2);
1809 inb(adp->va_crtc_addr + 6); /* reset flip/flop */
1810 outb(ATC, 0x20); /* enable palette */
1811 return 0;
1812}
1813
1814/*
1815 * set_border():
1816 * Change the border color.
1817 *
1818 * CGA/EGA/VGA
1819 */
1820static int
1821vga_set_border(video_adapter_t *adp, int color)
1822{
1823 prologue(adp, V_ADP_BORDER, 1);
1824
1825 switch (adp->va_type) {
1826 case KD_EGA:
1827 case KD_VGA:
1828 inb(adp->va_crtc_addr + 6); /* reset flip-flop */
1829 outb(ATC, 0x31); outb(ATC, color & 0xff);
1830 break;
1831 case KD_CGA:
1832 outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */
1833 break;
1834 case KD_MONO:
1835 case KD_HERCULES:
1836 default:
1837 break;
1838 }
1839 return 0;
1840}
1841
1842/*
1843 * save_state():
1844 * Read video register values.
1845 * NOTE: this function only reads the standard EGA/VGA registers.
1846 * any extra/extended registers of SVGA adapters are not saved.
1847 *
1848 * VGA
1849 */
1850static int
1851vga_save_state(video_adapter_t *adp, void *p, size_t size)
1852{
1853 video_info_t info;
1854 u_char *buf;
1855 int crtc_addr;
1856 int i, j;
1857 int s;
1858
1859 if (size == 0) {
1860 /* return the required buffer size */
1861 prologue(adp, V_ADP_STATESAVE, 0);
1862 return sizeof(adp_state_t);
1863 } else {
1864 prologue(adp, V_ADP_STATESAVE, 1);
1865 if (size < sizeof(adp_state_t))
1866 return 1;
1867 }
1868
1869 ((adp_state_t *)p)->sig = V_STATE_SIG;
1870 buf = ((adp_state_t *)p)->regs;
1871 bzero(buf, V_MODE_PARAM_SIZE);
1872 crtc_addr = adp->va_crtc_addr;
1873
1874 s = splhigh();
1875
1876 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
1877 for (i = 0, j = 5; i < 4; i++) {
1878 outb(TSIDX, i + 1);
1879 buf[j++] = inb(TSREG);
1880 }
1881 buf[9] = inb(MISC + 10); /* dot-clock */
1882 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
1883
1884 for (i = 0, j = 10; i < 25; i++) { /* crtc */
1885 outb(crtc_addr, i);
1886 buf[j++] = inb(crtc_addr + 1);
1887 }
1888 for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */
1889 inb(crtc_addr + 6); /* reset flip-flop */
1890 outb(ATC, i);
1891 buf[j++] = inb(ATC + 1);
1892 }
1893 for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */
1894 outb(GDCIDX, i);
1895 buf[j++] = inb(GDCREG);
1896 }
1897 inb(crtc_addr + 6); /* reset flip-flop */
1898 outb(ATC, 0x20); /* enable palette */
1899
1900 splx(s);
1901
1902#if 1
1903 if (vga_get_info(adp, adp->va_mode, &info) == 0) {
1904 if (info.vi_flags & V_INFO_GRAPHICS) {
1905 buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
1906 buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
1907 } else {
1908 buf[0] = info.vi_width; /* COLS */
1909 buf[1] = info.vi_height - 1; /* ROWS */
1910 }
1911 buf[2] = info.vi_cheight; /* POINTS */
1912 } else {
1913 /* XXX: shouldn't be happening... */
1914 printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n",
1915 adp->va_unit, adp->va_name);
1916 }
1917#else
1918 buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */
1919 buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */
1920 buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */
1921 buf[3] = readb(BIOS_PADDRTOVADDR(0x44c));
1922 buf[4] = readb(BIOS_PADDRTOVADDR(0x44d));
1923#endif
1924
1925 return 0;
1926}
1927
1928/*
1929 * load_state():
1930 * Set video registers at once.
1931 * NOTE: this function only updates the standard EGA/VGA registers.
1932 * any extra/extended registers of SVGA adapters are not changed.
1933 *
1934 * EGA/VGA
1935 */
1936static int
1937vga_load_state(video_adapter_t *adp, void *p)
1938{
1939 u_char *buf;
1940 int crtc_addr;
1941 int s;
1942 int i;
1943
1944 prologue(adp, V_ADP_STATELOAD, 1);
1945 if (((adp_state_t *)p)->sig != V_STATE_SIG)
1946 return 1;
1947
1948 buf = ((adp_state_t *)p)->regs;
1949 crtc_addr = adp->va_crtc_addr;
1950
1951 s = splhigh();
1952
1953 outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */
1954 for (i = 0; i < 4; ++i) { /* program sequencer */
1955 outb(TSIDX, i + 1);
1956 outb(TSREG, buf[i + 5]);
1957 }
1958 outb(MISC, buf[9]); /* set dot-clock */
1959 outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */
1960 outb(crtc_addr, 0x11);
1961 outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
1962 for (i = 0; i < 25; ++i) { /* program crtc */
1963 outb(crtc_addr, i);
1964 outb(crtc_addr + 1, buf[i + 10]);
1965 }
1966 inb(crtc_addr+6); /* reset flip-flop */
1967 for (i = 0; i < 20; ++i) { /* program attribute ctrl */
1968 outb(ATC, i);
1969 outb(ATC, buf[i + 35]);
1970 }
1971 for (i = 0; i < 9; ++i) { /* program graph data ctrl */
1972 outb(GDCIDX, i);
1973 outb(GDCREG, buf[i + 55]);
1974 }
1975 inb(crtc_addr + 6); /* reset flip-flop */
1976 outb(ATC, 0x20); /* enable palette */
1977
1978#ifndef VGA_NO_BIOS
1979 if (adp->va_unit == V_ADP_PRIMARY) {
1980 writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */
1981 writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */
1982 writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */
1983#if 0
1984 writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]);
1985 writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]);
1986#endif
1987 }
1988#endif /* VGA_NO_BIOS */
1989
1990 splx(s);
1991 return 0;
1992}
1993
1994/*
1995 * set_origin():
1996 * Change the origin (window mapping) of the banked frame buffer.
1997 */
1998static int
1999vga_set_origin(video_adapter_t *adp, off_t offset)
2000{
2001 /*
2002 * The standard video modes do not require window mapping;
2003 * always return error.
2004 */
2005 return 1;
2006}
2007
2008/*
2009 * read_hw_cursor():
2010 * Read the position of the hardware text cursor.
2011 *
2012 * all adapters
2013 */
2014static int
2015vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
2016{
2017 u_int16_t off;
2018 int s;
2019
2020 if (!init_done)
2021 return 1;
2022
2023 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
2024 return 1;
2025
2026 s = spltty();
2027 outb(adp->va_crtc_addr, 14);
2028 off = inb(adp->va_crtc_addr + 1);
2029 outb(adp->va_crtc_addr, 15);
2030 off = (off << 8) | inb(adp->va_crtc_addr + 1);
2031 splx(s);
2032
2033 *row = off / adp->va_info.vi_width;
2034 *col = off % adp->va_info.vi_width;
2035
2036 return 0;
2037}
2038
2039/*
2040 * set_hw_cursor():
2041 * Move the hardware text cursor. If col and row are both -1,
2042 * the cursor won't be shown.
2043 *
2044 * all adapters
2045 */
2046static int
2047vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
2048{
2049 u_int16_t off;
2050 int s;
2051
2052 if (!init_done)
2053 return 1;
2054
2055 if ((col == -1) && (row == -1)) {
2056 off = -1;
2057 } else {
2058 if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
2059 return 1;
2060 off = row*adp->va_info.vi_width + col;
2061 }
2062
2063 s = spltty();
2064 outb(adp->va_crtc_addr, 14);
2065 outb(adp->va_crtc_addr + 1, off >> 8);
2066 outb(adp->va_crtc_addr, 15);
2067 outb(adp->va_crtc_addr + 1, off & 0x00ff);
2068 splx(s);
2069
2070 return 0;
2071}
2072
2073/*
2074 * set_hw_cursor_shape():
2075 * Change the shape of the hardware text cursor. If the height is
2076 * zero or negative, the cursor won't be shown.
2077 *
2078 * all adapters
2079 */
2080static int
2081vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
2082 int celsize, int blink)
2083{
2084 int s;
2085
2086 if (!init_done)
2087 return 1;
2088
2089 s = spltty();
2090 switch (adp->va_type) {
2091 case KD_VGA:
2092 case KD_CGA:
2093 case KD_MONO:
2094 case KD_HERCULES:
2095 default:
2096 if (height <= 0) {
2097 /* make the cursor invisible */
2098 outb(adp->va_crtc_addr, 10);
2099 outb(adp->va_crtc_addr + 1, 32);
2100 outb(adp->va_crtc_addr, 11);
2101 outb(adp->va_crtc_addr + 1, 0);
2102 } else {
2103 outb(adp->va_crtc_addr, 10);
2104 outb(adp->va_crtc_addr + 1, celsize - base - height);
2105 outb(adp->va_crtc_addr, 11);
2106 outb(adp->va_crtc_addr + 1, celsize - base - 1);
2107 }
2108 break;
2109 case KD_EGA:
2110 if (height <= 0) {
2111 /* make the cursor invisible */
2112 outb(adp->va_crtc_addr, 10);
2113 outb(adp->va_crtc_addr + 1, celsize);
2114 outb(adp->va_crtc_addr, 11);
2115 outb(adp->va_crtc_addr + 1, 0);
2116 } else {
2117 outb(adp->va_crtc_addr, 10);
2118 outb(adp->va_crtc_addr + 1, celsize - base - height);
2119 outb(adp->va_crtc_addr, 11);
2120 outb(adp->va_crtc_addr + 1, celsize - base);
2121 }
2122 break;
2123 }
2124 splx(s);
2125
2126 return 0;
2127}
2128
2129/*
2130 * mmap():
2131 * Mmap frame buffer.
2132 *
2133 * all adapters
2134 */
2135static int
2136vga_mmap(video_adapter_t *adp, vm_offset_t offset)
2137{
2138 if (offset > 0x20000 - PAGE_SIZE)
2139 return -1;
2140#ifdef __i386__
2141 return i386_btop((VIDEO_BUF_BASE + offset));
2142#endif
2143#ifdef __alpha__
2144 return alpha_btop((VIDEO_BUF_BASE + offset));
2145#endif
2146}
2147
2148static void
2149dump_buffer(u_char *buf, size_t len)
2150{
2151 int i;
2152
2153 for(i = 0; i < len;) {
2154 printf("%02x ", buf[i]);
2155 if ((++i % 16) == 0)
2156 printf("\n");
2157 }
2158}
2159
2160/*
2161 * diag():
2162 * Print some information about the video adapter and video modes,
2163 * with requested level of details.
2164 *
2165 * all adapters
2166 */
2167static int
2168vga_diag(video_adapter_t *adp, int level)
2169{
2170#if FB_DEBUG > 1
2171 video_info_t info;
2172#endif
2173 u_char *mp;
2174
2175 if (!init_done)
2176 return 1;
2177
2178#if FB_DEBUG > 1
2179#ifndef VGA_NO_BIOS
2180 printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n",
2181 rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488)));
2182 printf("vga: CRTC:0x%x, video option:0x%02x, ",
2183 readw(BIOS_PADDRTOVADDR(0x463)),
2184 readb(BIOS_PADDRTOVADDR(0x487)));
2185 printf("rows:%d, cols:%d, font height:%d\n",
2186 readb(BIOS_PADDRTOVADDR(0x44a)),
2187 readb(BIOS_PADDRTOVADDR(0x484)) + 1,
2188 readb(BIOS_PADDRTOVADDR(0x485)));
2189#endif /* VGA_NO_BIOS */
2190 printf("vga: param table EGA/VGA:%p", video_mode_ptr);
2191 printf(", CGA/MDA:%p\n", video_mode_ptr2);
2192 printf("vga: rows_offset:%d\n", rows_offset);
2193#endif /* FB_DEBUG > 1 */
2194
2195 fb_dump_adp_info(DRIVER_NAME, adp, level);
2196
2197#if FB_DEBUG > 1
2198 if (adp->va_flags & V_ADP_MODECHANGE) {
2199 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
2200 if (bios_vmode[i].vi_mode == NA)
2201 continue;
2202 if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
2203 continue;
2204 fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level);
2205 }
2206 } else {
2207 vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */
2208 fb_dump_mode_info(DRIVER_NAME, adp, &info, level);
2209 }
2210#endif /* FB_DEBUG > 1 */
2211
2212 if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA))
2213 return 0;
2214#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
2215 if (video_mode_ptr == NULL)
2216 printf("vga%d: %s: WARNING: video mode switching is not "
2217 "fully supported on this adapter\n",
2218 adp->va_unit, adp->va_name);
2219#endif
2220 if (level <= 0)
2221 return 0;
2222
2223 if (adp->va_type == KD_VGA) {
2224 printf("VGA parameters upon power-up\n");
2225 dump_buffer(adpstate.regs, sizeof(adpstate.regs));
2226 printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
2227 dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
2228 }
2229
2230 mp = get_mode_param(adp->va_initial_mode);
2231 if (mp == NULL) /* this shouldn't be happening */
2232 return 0;
2233 printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode);
2234 dump_buffer(mp, V_MODE_PARAM_SIZE);
2235
2236 return 0;
2237}
2238
2239#endif /* NVGA > 0 */