Deleted Added
full compact
vesa.c (39287) vesa.c (39591)
1/*-
2 * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
1/*-
2 * Copyright (c) 1998 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id$
29 * $Id: vesa.c,v 1.1 1998/09/15 18:16:38 sos Exp $
30 */
31
32#include "sc.h"
33#include "opt_vesa.h"
34#include "opt_vm86.h"
35
36#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE)
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/malloc.h>
42#include <vm/vm.h>
43#include <vm/pmap.h>
44
45#include <machine/console.h>
46#include <machine/md_var.h>
47#include <machine/vm86.h>
48#include <machine/pc/bios.h>
49#include <machine/pc/vesa.h>
50
51#include <i386/isa/videoio.h>
52
53#ifdef VESA_MODULE
54#include <sys/exec.h>
55#include <sys/sysent.h>
56#include <sys/lkm.h>
57
58MOD_MISC(vesa);
59#endif
60
61/* VESA video adapter state buffer stub */
62struct adp_state {
63 int sig;
64#define V_STATE_SIG 0x61736576
65 u_char regs[1];
66};
67typedef struct adp_state adp_state_t;
68
69/* VESA video adapter */
70static video_adapter_t *vesa_adp = NULL;
71static int vesa_state_buf_size = 0;
72static void *vesa_state_buf = NULL;
73
74/* VESA functions */
75static vi_init_t vesa_init;
76static vi_adapter_t vesa_adapter;
77static vi_get_info_t vesa_get_info;
78static vi_query_mode_t vesa_query_mode;
79static vi_set_mode_t vesa_set_mode;
80static vi_save_font_t vesa_save_font;
81static vi_load_font_t vesa_load_font;
82static vi_show_font_t vesa_show_font;
83static vi_save_palette_t vesa_save_palette;
84static vi_load_palette_t vesa_load_palette;
85static vi_set_border_t vesa_set_border;
86static vi_save_state_t vesa_save_state;
87static vi_load_state_t vesa_load_state;
88static vi_set_win_org_t vesa_set_origin;
89static vi_read_hw_cursor_t vesa_read_hw_cursor;
90static vi_set_hw_cursor_t vesa_set_hw_cursor;
91static vi_diag_t vesa_diag;
92
93static struct vidsw vesavidsw = {
94 vesa_init, vesa_adapter, vesa_get_info, vesa_query_mode,
95 vesa_set_mode, vesa_save_font, vesa_load_font, vesa_show_font,
96 vesa_save_palette,vesa_load_palette,vesa_set_border,vesa_save_state,
97 vesa_load_state,vesa_set_origin,vesa_read_hw_cursor,vesa_set_hw_cursor,
98 vesa_diag,
99};
100
101static struct vidsw prevvidsw;
102
103/* VESA BIOS video modes */
104#define VESA_MAXMODES 64
105#define EOT (-1)
106#define NA (-2)
107
108static video_info_t vesa_vmode[VESA_MAXMODES + 1] = {
109 { EOT, },
110};
111
112static int vesa_init_done = FALSE;
113static int has_vesa_bios = FALSE;
114static struct vesa_info *vesa_adp_info = NULL;
115static u_int16_t *vesa_vmodetab = NULL;
116
117/* local macros and functions */
118#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
119
120static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode);
121static int vesa_bios_set_mode(int mode);
122static int vesa_bios_set_dac(int bits);
123static int vesa_bios_save_palette(int start, int colors, u_char *palette);
124static int vesa_bios_load_palette(int start, int colors, u_char *palette);
125#define STATE_SIZE 0
126#define STATE_SAVE 1
127#define STATE_LOAD 2
128#define STATE_HW (1<<0)
129#define STATE_DATA (1<<1)
130#define STATE_DAC (1<<2)
131#define STATE_REG (1<<3)
132#define STATE_MOST (STATE_HW | STATE_DATA | STATE_REG)
133#define STATE_ALL (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
134static int vesa_bios_state_buf_size(void);
135static int vesa_bios_save_restore(int code, void *p, size_t size);
30 */
31
32#include "sc.h"
33#include "opt_vesa.h"
34#include "opt_vm86.h"
35
36#if (NSC > 0 && defined(VESA) && defined(VM86)) || defined(VESA_MODULE)
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/malloc.h>
42#include <vm/vm.h>
43#include <vm/pmap.h>
44
45#include <machine/console.h>
46#include <machine/md_var.h>
47#include <machine/vm86.h>
48#include <machine/pc/bios.h>
49#include <machine/pc/vesa.h>
50
51#include <i386/isa/videoio.h>
52
53#ifdef VESA_MODULE
54#include <sys/exec.h>
55#include <sys/sysent.h>
56#include <sys/lkm.h>
57
58MOD_MISC(vesa);
59#endif
60
61/* VESA video adapter state buffer stub */
62struct adp_state {
63 int sig;
64#define V_STATE_SIG 0x61736576
65 u_char regs[1];
66};
67typedef struct adp_state adp_state_t;
68
69/* VESA video adapter */
70static video_adapter_t *vesa_adp = NULL;
71static int vesa_state_buf_size = 0;
72static void *vesa_state_buf = NULL;
73
74/* VESA functions */
75static vi_init_t vesa_init;
76static vi_adapter_t vesa_adapter;
77static vi_get_info_t vesa_get_info;
78static vi_query_mode_t vesa_query_mode;
79static vi_set_mode_t vesa_set_mode;
80static vi_save_font_t vesa_save_font;
81static vi_load_font_t vesa_load_font;
82static vi_show_font_t vesa_show_font;
83static vi_save_palette_t vesa_save_palette;
84static vi_load_palette_t vesa_load_palette;
85static vi_set_border_t vesa_set_border;
86static vi_save_state_t vesa_save_state;
87static vi_load_state_t vesa_load_state;
88static vi_set_win_org_t vesa_set_origin;
89static vi_read_hw_cursor_t vesa_read_hw_cursor;
90static vi_set_hw_cursor_t vesa_set_hw_cursor;
91static vi_diag_t vesa_diag;
92
93static struct vidsw vesavidsw = {
94 vesa_init, vesa_adapter, vesa_get_info, vesa_query_mode,
95 vesa_set_mode, vesa_save_font, vesa_load_font, vesa_show_font,
96 vesa_save_palette,vesa_load_palette,vesa_set_border,vesa_save_state,
97 vesa_load_state,vesa_set_origin,vesa_read_hw_cursor,vesa_set_hw_cursor,
98 vesa_diag,
99};
100
101static struct vidsw prevvidsw;
102
103/* VESA BIOS video modes */
104#define VESA_MAXMODES 64
105#define EOT (-1)
106#define NA (-2)
107
108static video_info_t vesa_vmode[VESA_MAXMODES + 1] = {
109 { EOT, },
110};
111
112static int vesa_init_done = FALSE;
113static int has_vesa_bios = FALSE;
114static struct vesa_info *vesa_adp_info = NULL;
115static u_int16_t *vesa_vmodetab = NULL;
116
117/* local macros and functions */
118#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
119
120static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode);
121static int vesa_bios_set_mode(int mode);
122static int vesa_bios_set_dac(int bits);
123static int vesa_bios_save_palette(int start, int colors, u_char *palette);
124static int vesa_bios_load_palette(int start, int colors, u_char *palette);
125#define STATE_SIZE 0
126#define STATE_SAVE 1
127#define STATE_LOAD 2
128#define STATE_HW (1<<0)
129#define STATE_DATA (1<<1)
130#define STATE_DAC (1<<2)
131#define STATE_REG (1<<3)
132#define STATE_MOST (STATE_HW | STATE_DATA | STATE_REG)
133#define STATE_ALL (STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)
134static int vesa_bios_state_buf_size(void);
135static int vesa_bios_save_restore(int code, void *p, size_t size);
136static int translate_flags(u_int16_t vflags);
136static int vesa_map_gen_mode_num(int type, int color, int mode);
137static int vesa_translate_flags(u_int16_t vflags);
137static int vesa_bios_init(void);
138static int vesa_bios_init(void);
138static void clear_modes(video_info_t *info, int color);
139static void vesa_clear_modes(video_info_t *info, int color);
139
140static void
141dump_buffer(u_char *buf, size_t len)
142{
143 int i;
144
145 for(i = 0; i < len;) {
146 printf("%02x ", buf[i]);
147 if ((++i % 16) == 0)
148 printf("\n");
149 }
150}
151
152/* VESA BIOS calls */
153static int
154vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
155{
156 struct vm86frame vmf;
157 u_char buf[256];
158 int err;
159
160 bzero(&vmf, sizeof(vmf));
161 bzero(buf, sizeof(buf));
162 vmf.vmf_eax = 0x4f01;
163 vmf.vmf_ecx = mode;
164 err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
165 &vmf.vmf_es, &vmf.vmf_di);
166 if ((err != 0) || (vmf.vmf_eax != 0x4f))
167 return 1;
168 bcopy(buf, vmode, sizeof(*vmode));
169 return 0;
170}
171
172static int
173vesa_bios_set_mode(int mode)
174{
175 struct vm86frame vmf;
176 int err;
177
178 bzero(&vmf, sizeof(vmf));
179 vmf.vmf_eax = 0x4f02;
180 vmf.vmf_ebx = mode;
181 err = vm86_intcall(0x10, &vmf);
182 return ((err != 0) || (vmf.vmf_eax != 0x4f));
183}
184
185static int
186vesa_bios_set_dac(int bits)
187{
188 struct vm86frame vmf;
189 int err;
190
191 bzero(&vmf, sizeof(vmf));
192 vmf.vmf_eax = 0x4f08;
193 vmf.vmf_ebx = (bits << 8);
194 err = vm86_intcall(0x10, &vmf);
195 return ((err != 0) || (vmf.vmf_eax != 0x4f));
196}
197
198static int
199vesa_bios_save_palette(int start, int colors, u_char *palette)
200{
201 struct vm86frame vmf;
202 u_char *p;
203 int err;
204 int i;
205
206 p = malloc(colors*4, M_DEVBUF, M_WAITOK);
207
208 bzero(&vmf, sizeof(vmf));
209 vmf.vmf_eax = 0x4f09;
210 vmf.vmf_ebx = 1; /* get primary palette data */
211 vmf.vmf_ecx = colors;
212 vmf.vmf_edx = start;
213 err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
214 if ((err != 0) || (vmf.vmf_eax != 0x4f)) {
215 free(p, M_DEVBUF);
216 return 1;
217 }
218
219 for (i = 0; i < colors; ++i) {
220 palette[i*3] = p[i*4 + 1];
221 palette[i*3 + 1] = p[i*4 + 2];
222 palette[i*3 + 2] = p[i*4 + 3];
223 }
224 free(p, M_DEVBUF);
225 return 0;
226}
227
228static int
229vesa_bios_load_palette(int start, int colors, u_char *palette)
230{
231 struct vm86frame vmf;
232 u_char *p;
233 int err;
234 int i;
235
236 p = malloc(colors*4, M_DEVBUF, M_WAITOK);
237 for (i = 0; i < colors; ++i) {
238 p[i*4] = 0;
239 p[i*4 + 1] = palette[i*3];
240 p[i*4 + 2] = palette[i*3 + 1];
241 p[i*4 + 3] = palette[i*3 + 2];
242 }
243
244 bzero(&vmf, sizeof(vmf));
245 vmf.vmf_eax = 0x4f09;
246 vmf.vmf_ebx = 0; /* set primary palette data */
247 vmf.vmf_ecx = colors;
248 vmf.vmf_edx = start;
249 err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
250 free(p, M_DEVBUF);
251 return ((err != 0) || (vmf.vmf_eax != 0x4f));
252}
253
254static int
255vesa_bios_state_buf_size(void)
256{
257 struct vm86frame vmf;
258 int err;
259
260 bzero(&vmf, sizeof(vmf));
261 vmf.vmf_eax = 0x4f04;
262 vmf.vmf_ecx = STATE_MOST;
263 vmf.vmf_edx = STATE_SIZE;
264 err = vm86_intcall(0x10, &vmf);
265 if ((err != 0) || (vmf.vmf_eax != 0x4f))
266 return 0;
267 return vmf.vmf_ebx*64;
268}
269
270static int
271vesa_bios_save_restore(int code, void *p, size_t size)
272{
273 struct vm86frame vmf;
274 int err;
275
276 bzero(&vmf, sizeof(vmf));
277 vmf.vmf_eax = 0x4f04;
278 vmf.vmf_ecx = STATE_MOST;
279 vmf.vmf_edx = code; /* STATE_SAVE/STATE_LOAD */
280 err = vm86_datacall(0x10, &vmf, (char *)p, size,
281 &vmf.vmf_es, &vmf.vmf_bx);
282 return ((err != 0) || (vmf.vmf_eax != 0x4f));
283}
284
140
141static void
142dump_buffer(u_char *buf, size_t len)
143{
144 int i;
145
146 for(i = 0; i < len;) {
147 printf("%02x ", buf[i]);
148 if ((++i % 16) == 0)
149 printf("\n");
150 }
151}
152
153/* VESA BIOS calls */
154static int
155vesa_bios_get_mode(int mode, struct vesa_mode *vmode)
156{
157 struct vm86frame vmf;
158 u_char buf[256];
159 int err;
160
161 bzero(&vmf, sizeof(vmf));
162 bzero(buf, sizeof(buf));
163 vmf.vmf_eax = 0x4f01;
164 vmf.vmf_ecx = mode;
165 err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
166 &vmf.vmf_es, &vmf.vmf_di);
167 if ((err != 0) || (vmf.vmf_eax != 0x4f))
168 return 1;
169 bcopy(buf, vmode, sizeof(*vmode));
170 return 0;
171}
172
173static int
174vesa_bios_set_mode(int mode)
175{
176 struct vm86frame vmf;
177 int err;
178
179 bzero(&vmf, sizeof(vmf));
180 vmf.vmf_eax = 0x4f02;
181 vmf.vmf_ebx = mode;
182 err = vm86_intcall(0x10, &vmf);
183 return ((err != 0) || (vmf.vmf_eax != 0x4f));
184}
185
186static int
187vesa_bios_set_dac(int bits)
188{
189 struct vm86frame vmf;
190 int err;
191
192 bzero(&vmf, sizeof(vmf));
193 vmf.vmf_eax = 0x4f08;
194 vmf.vmf_ebx = (bits << 8);
195 err = vm86_intcall(0x10, &vmf);
196 return ((err != 0) || (vmf.vmf_eax != 0x4f));
197}
198
199static int
200vesa_bios_save_palette(int start, int colors, u_char *palette)
201{
202 struct vm86frame vmf;
203 u_char *p;
204 int err;
205 int i;
206
207 p = malloc(colors*4, M_DEVBUF, M_WAITOK);
208
209 bzero(&vmf, sizeof(vmf));
210 vmf.vmf_eax = 0x4f09;
211 vmf.vmf_ebx = 1; /* get primary palette data */
212 vmf.vmf_ecx = colors;
213 vmf.vmf_edx = start;
214 err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
215 if ((err != 0) || (vmf.vmf_eax != 0x4f)) {
216 free(p, M_DEVBUF);
217 return 1;
218 }
219
220 for (i = 0; i < colors; ++i) {
221 palette[i*3] = p[i*4 + 1];
222 palette[i*3 + 1] = p[i*4 + 2];
223 palette[i*3 + 2] = p[i*4 + 3];
224 }
225 free(p, M_DEVBUF);
226 return 0;
227}
228
229static int
230vesa_bios_load_palette(int start, int colors, u_char *palette)
231{
232 struct vm86frame vmf;
233 u_char *p;
234 int err;
235 int i;
236
237 p = malloc(colors*4, M_DEVBUF, M_WAITOK);
238 for (i = 0; i < colors; ++i) {
239 p[i*4] = 0;
240 p[i*4 + 1] = palette[i*3];
241 p[i*4 + 2] = palette[i*3 + 1];
242 p[i*4 + 3] = palette[i*3 + 2];
243 }
244
245 bzero(&vmf, sizeof(vmf));
246 vmf.vmf_eax = 0x4f09;
247 vmf.vmf_ebx = 0; /* set primary palette data */
248 vmf.vmf_ecx = colors;
249 vmf.vmf_edx = start;
250 err = vm86_datacall(0x10, &vmf, p, colors*4, &vmf.vmf_es, &vmf.vmf_di);
251 free(p, M_DEVBUF);
252 return ((err != 0) || (vmf.vmf_eax != 0x4f));
253}
254
255static int
256vesa_bios_state_buf_size(void)
257{
258 struct vm86frame vmf;
259 int err;
260
261 bzero(&vmf, sizeof(vmf));
262 vmf.vmf_eax = 0x4f04;
263 vmf.vmf_ecx = STATE_MOST;
264 vmf.vmf_edx = STATE_SIZE;
265 err = vm86_intcall(0x10, &vmf);
266 if ((err != 0) || (vmf.vmf_eax != 0x4f))
267 return 0;
268 return vmf.vmf_ebx*64;
269}
270
271static int
272vesa_bios_save_restore(int code, void *p, size_t size)
273{
274 struct vm86frame vmf;
275 int err;
276
277 bzero(&vmf, sizeof(vmf));
278 vmf.vmf_eax = 0x4f04;
279 vmf.vmf_ecx = STATE_MOST;
280 vmf.vmf_edx = code; /* STATE_SAVE/STATE_LOAD */
281 err = vm86_datacall(0x10, &vmf, (char *)p, size,
282 &vmf.vmf_es, &vmf.vmf_bx);
283 return ((err != 0) || (vmf.vmf_eax != 0x4f));
284}
285
286/* map a generic video mode to a known mode */
285static int
287static int
286translate_flags(u_int16_t vflags)
288vesa_map_gen_mode_num(int type, int color, int mode)
287{
289{
290 static struct {
291 int from;
292 int to;
293 } mode_map[] = {
294 { M_TEXT_132x25, M_VESA_C132x25 },
295 { M_TEXT_132x43, M_VESA_C132x43 },
296 { M_TEXT_132x50, M_VESA_C132x50 },
297 { M_TEXT_132x60, M_VESA_C132x60 },
298 };
299 int i;
300
301 for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
302 if (mode_map[i].from == mode)
303 return mode_map[i].to;
304 }
305 return mode;
306}
307
308static int
309vesa_translate_flags(u_int16_t vflags)
310{
288 static struct {
289 u_int16_t mask;
290 int set;
291 int reset;
292 } ftable[] = {
293 { V_MODECOLOR, V_INFO_COLOR, 0 },
294 { V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 },
295 { V_MODELFB, V_INFO_LENEAR, 0 },
296 };
297 int flags;
298 int i;
299
300 for (flags = 0, i = 0; i < sizeof(ftable)/sizeof(ftable[0]); ++i) {
301 flags |= (vflags & ftable[i].mask) ?
302 ftable[i].set : ftable[i].reset;
303 }
304 return flags;
305}
306
307static int
308vesa_bios_init(void)
309{
310 static u_char buf[512];
311 struct vm86frame vmf;
312 struct vesa_mode vmode;
313 u_int32_t p;
314 int modes;
315 int err;
316 int i;
317
318 if (vesa_init_done)
319 return 0;
320
321 has_vesa_bios = FALSE;
322 vesa_adp_info = NULL;
323 vesa_vmode[0].vi_mode = EOT;
324
325 bzero(&vmf, sizeof(vmf)); /* paranoia */
326 bzero(buf, sizeof(buf));
327 bcopy("VBE2", buf, 4); /* try for VBE2 data */
328 vmf.vmf_eax = 0x4f00;
329 err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
330 &vmf.vmf_es, &vmf.vmf_di);
331 if ((err != 0) || (vmf.vmf_eax != 0x4f) || bcmp("VESA", buf, 4))
332 return 1;
333 vesa_adp_info = (struct vesa_info *)buf;
334 if (bootverbose)
335 dump_buffer(buf, 64);
336 if (vesa_adp_info->v_flags & V_NONVGA)
337 return 1;
338
339 /* obtain video mode information */
340 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_modetable);
341 vesa_vmodetab = (u_int16_t *)BIOS_PADDRTOVADDR(p);
342 for (i = 0, modes = 0; vesa_vmodetab[i] != 0xffff; ++i) {
343 if (modes >= VESA_MAXMODES)
344 break;
345 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
346 continue;
347
348 /* reject unsupported modes */
349#if 0
350 if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO
351 | V_MODENONVGA))
352 != (V_MODESUPP | V_MODEOPTINFO))
353 continue;
354#else
355 if ((vmode.v_modeattr & (V_MODEOPTINFO | V_MODENONVGA))
356 != (V_MODEOPTINFO))
357 continue;
358#endif
359
360 /* copy some fields */
361 bzero(&vesa_vmode[modes], sizeof(vesa_vmode[modes]));
362 vesa_vmode[modes].vi_mode = vesa_vmodetab[i];
363 vesa_vmode[modes].vi_width = vmode.v_width;
364 vesa_vmode[modes].vi_height = vmode.v_height;
365 vesa_vmode[modes].vi_depth = vmode.v_bpp;
366 vesa_vmode[modes].vi_planes = vmode.v_planes;
367 vesa_vmode[modes].vi_cwidth = vmode.v_cwidth;
368 vesa_vmode[modes].vi_cheight = vmode.v_cheight;
369 vesa_vmode[modes].vi_window = (u_int)vmode.v_waseg << 4;
370 /* XXX window B */
371 vesa_vmode[modes].vi_window_size = vmode.v_wsize;
372 vesa_vmode[modes].vi_window_gran = vmode.v_wgran;
373 vesa_vmode[modes].vi_buffer = vmode.v_lfb;
374 vesa_vmode[modes].vi_buffer_size = vmode.v_offscreen;
375 /* pixel format, memory model... */
311 static struct {
312 u_int16_t mask;
313 int set;
314 int reset;
315 } ftable[] = {
316 { V_MODECOLOR, V_INFO_COLOR, 0 },
317 { V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 },
318 { V_MODELFB, V_INFO_LENEAR, 0 },
319 };
320 int flags;
321 int i;
322
323 for (flags = 0, i = 0; i < sizeof(ftable)/sizeof(ftable[0]); ++i) {
324 flags |= (vflags & ftable[i].mask) ?
325 ftable[i].set : ftable[i].reset;
326 }
327 return flags;
328}
329
330static int
331vesa_bios_init(void)
332{
333 static u_char buf[512];
334 struct vm86frame vmf;
335 struct vesa_mode vmode;
336 u_int32_t p;
337 int modes;
338 int err;
339 int i;
340
341 if (vesa_init_done)
342 return 0;
343
344 has_vesa_bios = FALSE;
345 vesa_adp_info = NULL;
346 vesa_vmode[0].vi_mode = EOT;
347
348 bzero(&vmf, sizeof(vmf)); /* paranoia */
349 bzero(buf, sizeof(buf));
350 bcopy("VBE2", buf, 4); /* try for VBE2 data */
351 vmf.vmf_eax = 0x4f00;
352 err = vm86_datacall(0x10, &vmf, (char *)buf, sizeof(buf),
353 &vmf.vmf_es, &vmf.vmf_di);
354 if ((err != 0) || (vmf.vmf_eax != 0x4f) || bcmp("VESA", buf, 4))
355 return 1;
356 vesa_adp_info = (struct vesa_info *)buf;
357 if (bootverbose)
358 dump_buffer(buf, 64);
359 if (vesa_adp_info->v_flags & V_NONVGA)
360 return 1;
361
362 /* obtain video mode information */
363 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_modetable);
364 vesa_vmodetab = (u_int16_t *)BIOS_PADDRTOVADDR(p);
365 for (i = 0, modes = 0; vesa_vmodetab[i] != 0xffff; ++i) {
366 if (modes >= VESA_MAXMODES)
367 break;
368 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
369 continue;
370
371 /* reject unsupported modes */
372#if 0
373 if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO
374 | V_MODENONVGA))
375 != (V_MODESUPP | V_MODEOPTINFO))
376 continue;
377#else
378 if ((vmode.v_modeattr & (V_MODEOPTINFO | V_MODENONVGA))
379 != (V_MODEOPTINFO))
380 continue;
381#endif
382
383 /* copy some fields */
384 bzero(&vesa_vmode[modes], sizeof(vesa_vmode[modes]));
385 vesa_vmode[modes].vi_mode = vesa_vmodetab[i];
386 vesa_vmode[modes].vi_width = vmode.v_width;
387 vesa_vmode[modes].vi_height = vmode.v_height;
388 vesa_vmode[modes].vi_depth = vmode.v_bpp;
389 vesa_vmode[modes].vi_planes = vmode.v_planes;
390 vesa_vmode[modes].vi_cwidth = vmode.v_cwidth;
391 vesa_vmode[modes].vi_cheight = vmode.v_cheight;
392 vesa_vmode[modes].vi_window = (u_int)vmode.v_waseg << 4;
393 /* XXX window B */
394 vesa_vmode[modes].vi_window_size = vmode.v_wsize;
395 vesa_vmode[modes].vi_window_gran = vmode.v_wgran;
396 vesa_vmode[modes].vi_buffer = vmode.v_lfb;
397 vesa_vmode[modes].vi_buffer_size = vmode.v_offscreen;
398 /* pixel format, memory model... */
376 vesa_vmode[modes].vi_flags = translate_flags(vmode.v_modeattr)
377 | V_INFO_VESA;
399 vesa_vmode[modes].vi_flags
400 = vesa_translate_flags(vmode.v_modeattr) | V_INFO_VESA;
378 ++modes;
379 }
380 vesa_vmode[modes].vi_mode = EOT;
381 if (bootverbose)
382 printf("VESA: %d mode(s) found\n", modes);
383
384 has_vesa_bios = TRUE;
385 return 0;
386}
387
388static void
401 ++modes;
402 }
403 vesa_vmode[modes].vi_mode = EOT;
404 if (bootverbose)
405 printf("VESA: %d mode(s) found\n", modes);
406
407 has_vesa_bios = TRUE;
408 return 0;
409}
410
411static void
389clear_modes(video_info_t *info, int color)
412vesa_clear_modes(video_info_t *info, int color)
390{
391 while (info->vi_mode != EOT) {
392 if ((info->vi_flags & V_INFO_COLOR) != color)
393 info->vi_mode = NA;
394 ++info;
395 }
396}
397
398/* exported functions */
399
400static int
401vesa_init(void)
402{
403 int adapters;
404 int i;
405
406 adapters = (*prevvidsw.init)();
407 for (i = 0; i < adapters; ++i) {
408 if ((vesa_adp = (*prevvidsw.adapter)(i)) == NULL)
409 continue;
410 if (vesa_adp->va_type == KD_VGA) {
411 vesa_adp->va_flags |= V_ADP_VESA;
412 return adapters;
413 }
414 }
415 vesa_adp = NULL;
416 return adapters;
417}
418
419static video_adapter_t
420*vesa_adapter(int ad)
421{
422 return (*prevvidsw.adapter)(ad);
423}
424
425static int
426vesa_get_info(int ad, int mode, video_info_t *info)
427{
428 int i;
429
430 if ((*prevvidsw.get_info)(ad, mode, info) == 0)
431 return 0;
432
433 if (ad != vesa_adp->va_index)
434 return 1;
413{
414 while (info->vi_mode != EOT) {
415 if ((info->vi_flags & V_INFO_COLOR) != color)
416 info->vi_mode = NA;
417 ++info;
418 }
419}
420
421/* exported functions */
422
423static int
424vesa_init(void)
425{
426 int adapters;
427 int i;
428
429 adapters = (*prevvidsw.init)();
430 for (i = 0; i < adapters; ++i) {
431 if ((vesa_adp = (*prevvidsw.adapter)(i)) == NULL)
432 continue;
433 if (vesa_adp->va_type == KD_VGA) {
434 vesa_adp->va_flags |= V_ADP_VESA;
435 return adapters;
436 }
437 }
438 vesa_adp = NULL;
439 return adapters;
440}
441
442static video_adapter_t
443*vesa_adapter(int ad)
444{
445 return (*prevvidsw.adapter)(ad);
446}
447
448static int
449vesa_get_info(int ad, int mode, video_info_t *info)
450{
451 int i;
452
453 if ((*prevvidsw.get_info)(ad, mode, info) == 0)
454 return 0;
455
456 if (ad != vesa_adp->va_index)
457 return 1;
458
459 mode = vesa_map_gen_mode_num(vesa_adp->va_type,
460 vesa_adp->va_flags & V_ADP_COLOR, mode);
435 for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
436 if (vesa_vmode[i].vi_mode == NA)
437 continue;
438 if (vesa_vmode[i].vi_mode == mode) {
439 *info = vesa_vmode[i];
440 return 0;
441 }
442 }
443 return 1;
444}
445
446static int
447vesa_query_mode(int ad, video_info_t *info)
448{
449 int i;
450
451 if ((i = (*prevvidsw.query_mode)(ad, info)) != -1)
452 return i;
453 if (ad != vesa_adp->va_index)
454 return -1;
455
456 for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
457 if ((info->vi_width != 0)
458 && (info->vi_width != vesa_vmode[i].vi_width))
459 continue;
460 if ((info->vi_height != 0)
461 && (info->vi_height != vesa_vmode[i].vi_height))
462 continue;
463 if ((info->vi_cwidth != 0)
464 && (info->vi_cwidth != vesa_vmode[i].vi_cwidth))
465 continue;
466 if ((info->vi_cheight != 0)
467 && (info->vi_cheight != vesa_vmode[i].vi_cheight))
468 continue;
469 if ((info->vi_depth != 0)
470 && (info->vi_depth != vesa_vmode[i].vi_depth))
471 continue;
472 if ((info->vi_planes != 0)
473 && (info->vi_planes != vesa_vmode[i].vi_planes))
474 continue;
475 /* pixel format, memory model */
476 if ((info->vi_flags != 0)
477 && (info->vi_flags != vesa_vmode[i].vi_flags))
478 continue;
479 return vesa_vmode[i].vi_mode;
480 }
481 return -1;
482}
483
484static int
485vesa_set_mode(int ad, int mode)
486{
487 video_info_t info;
488 size_t len;
489
490 if (ad != vesa_adp->va_index)
491 return (*prevvidsw.set_mode)(ad, mode);
492
461 for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
462 if (vesa_vmode[i].vi_mode == NA)
463 continue;
464 if (vesa_vmode[i].vi_mode == mode) {
465 *info = vesa_vmode[i];
466 return 0;
467 }
468 }
469 return 1;
470}
471
472static int
473vesa_query_mode(int ad, video_info_t *info)
474{
475 int i;
476
477 if ((i = (*prevvidsw.query_mode)(ad, info)) != -1)
478 return i;
479 if (ad != vesa_adp->va_index)
480 return -1;
481
482 for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) {
483 if ((info->vi_width != 0)
484 && (info->vi_width != vesa_vmode[i].vi_width))
485 continue;
486 if ((info->vi_height != 0)
487 && (info->vi_height != vesa_vmode[i].vi_height))
488 continue;
489 if ((info->vi_cwidth != 0)
490 && (info->vi_cwidth != vesa_vmode[i].vi_cwidth))
491 continue;
492 if ((info->vi_cheight != 0)
493 && (info->vi_cheight != vesa_vmode[i].vi_cheight))
494 continue;
495 if ((info->vi_depth != 0)
496 && (info->vi_depth != vesa_vmode[i].vi_depth))
497 continue;
498 if ((info->vi_planes != 0)
499 && (info->vi_planes != vesa_vmode[i].vi_planes))
500 continue;
501 /* pixel format, memory model */
502 if ((info->vi_flags != 0)
503 && (info->vi_flags != vesa_vmode[i].vi_flags))
504 continue;
505 return vesa_vmode[i].vi_mode;
506 }
507 return -1;
508}
509
510static int
511vesa_set_mode(int ad, int mode)
512{
513 video_info_t info;
514 size_t len;
515
516 if (ad != vesa_adp->va_index)
517 return (*prevvidsw.set_mode)(ad, mode);
518
519 mode = vesa_map_gen_mode_num(vesa_adp->va_type,
520 vesa_adp->va_flags & V_ADP_COLOR, mode);
493#ifdef SC_VIDEO_DEBUG
494 printf("VESA: set_mode(): %d(%x) -> %d(%x)\n",
495 vesa_adp->va_mode, vesa_adp->va_mode, mode, mode);
496#endif
497 /*
498 * If the current mode is a VESA mode and the new mode is not,
499 * restore the state of the adapter first, so that non-standard,
500 * extended SVGA registers are set to the state compatible with
501 * the standard VGA modes. Otherwise (*prevvidsw.set_mode)()
502 * may not be able to set up the new mode correctly.
503 */
504 if (VESA_MODE(vesa_adp->va_mode)) {
505 if ((*prevvidsw.get_info)(ad, mode, &info) == 0) {
506 /* assert(vesa_state_buf != NULL); */
507 if ((vesa_state_buf == NULL)
508 || vesa_load_state(ad, vesa_state_buf))
509 return 1;
510 free(vesa_state_buf, M_DEVBUF);
511 vesa_state_buf = NULL;
512#ifdef SC_VIDEO_DEBUG
513 printf("VESA: restored\n");
514#endif
515 }
516 /*
517 * once (*prevvidsw.get_info)() succeeded,
518 * (*prevvidsw.set_mode)() below won't fail...
519 */
520 }
521
522 /* we may not need to handle this mode after all... */
523 if ((*prevvidsw.set_mode)(ad, mode) == 0)
524 return 0;
525
526 /* is the new mode supported? */
527 if (vesa_get_info(ad, mode, &info))
528 return 1;
529 /* assert(VESA_MODE(mode)); */
530
531#ifdef SC_VIDEO_DEBUG
532 printf("VESA: about to set a VESA mode...\n");
533#endif
534 /*
535 * If the current mode is not a VESA mode, save the current state
536 * so that the adapter state can be restored later when a non-VESA
537 * mode is to be set up. See above.
538 */
539 if (!VESA_MODE(vesa_adp->va_mode) && (vesa_state_buf == NULL)) {
540 len = vesa_save_state(ad, NULL, 0);
541 vesa_state_buf = malloc(len, M_DEVBUF, M_WAITOK);
542 if (vesa_save_state(ad, vesa_state_buf, len)) {
543#ifdef SC_VIDEO_DEBUG
544 printf("VESA: state save failed! (len=%d)\n", len);
545#endif
546 free(vesa_state_buf, M_DEVBUF);
547 vesa_state_buf = NULL;
548 return 1;
549 }
550#ifdef SC_VIDEO_DEBUG
551 printf("VESA: saved (len=%d)\n", len);
552 dump_buffer(vesa_state_buf, len);
553#endif
554 }
555
556 if (vesa_bios_set_mode(mode))
557 return 1;
558
559#ifdef SC_VIDEO_DEBUG
560 printf("VESA: mode set!\n");
561#endif
562 vesa_adp->va_mode = mode;
563 vesa_adp->va_flags &= ~V_ADP_COLOR;
564 vesa_adp->va_flags |=
565 (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
566 vesa_adp->va_crtc_addr =
567 (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE;
568 vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
569 vesa_adp->va_window_size = info.vi_window_size;
570 vesa_adp->va_window_gran = info.vi_window_gran;
571 if (info.vi_buffer_size == 0) {
572 vesa_adp->va_buffer = 0;
573 vesa_adp->va_buffer_size = 0;
574 } else {
575 vesa_adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
576 vesa_adp->va_buffer_size = info.vi_buffer_size;
577 }
578
579 return 0;
580}
581
582static int
583vesa_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
584{
585 return (*prevvidsw.save_font)(ad, page, fontsize, data, ch, count);
586}
587
588static int
589vesa_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
590{
591 return (*prevvidsw.load_font)(ad, page, fontsize, data, ch, count);
592}
593
594static int
595vesa_show_font(int ad, int page)
596{
597 return (*prevvidsw.show_font)(ad, page);
598}
599
600static int
601vesa_save_palette(int ad, u_char *palette)
602{
603 if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8)
604 || vesa_bios_set_dac(8))
605 return (*prevvidsw.save_palette)(ad, palette);
606
607 return vesa_bios_save_palette(0, 256, palette);
608}
609
610static int
611vesa_load_palette(int ad, u_char *palette)
612{
613 if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8)
614 || vesa_bios_set_dac(8))
615 return (*prevvidsw.load_palette)(ad, palette);
616
617 return vesa_bios_load_palette(0, 256, palette);
618}
619
620static int
621vesa_set_border(int ad, int color)
622{
623 return (*prevvidsw.set_border)(ad, color);
624}
625
626static int
627vesa_save_state(int ad, void *p, size_t size)
628{
629 if (ad != vesa_adp->va_index)
630 return (*prevvidsw.save_state)(ad, p, size);
631
632 if (vesa_state_buf_size == 0)
633 vesa_state_buf_size = vesa_bios_state_buf_size();
634 if (size == 0)
635 return (sizeof(int) + vesa_state_buf_size);
636 else if (size < (sizeof(int) + vesa_state_buf_size))
637 return 1;
638
639 ((adp_state_t *)p)->sig = V_STATE_SIG;
640 bzero(((adp_state_t *)p)->regs, vesa_state_buf_size);
641 return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs,
642 vesa_state_buf_size);
643}
644
645static int
646vesa_load_state(int ad, void *p)
647{
648 if ((ad != vesa_adp->va_index)
649 || (((adp_state_t *)p)->sig != V_STATE_SIG))
650 return (*prevvidsw.load_state)(ad, p);
651
652 return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs,
653 vesa_state_buf_size);
654}
655
656static int
657vesa_set_origin(int ad, off_t offset)
658{
659 struct vm86frame vmf;
660 int err;
661
662 /*
663 * This function should return as quickly as possible to
664 * maintain good performance of the system. For this reason,
665 * error checking is kept minimal and let the VESA BIOS to
666 * detect error.
667 */
668 if (ad != vesa_adp->va_index)
669 return (*prevvidsw.set_win_org)(ad, offset);
670
671 if (vesa_adp->va_window_gran == 0)
672 return 1;
673 bzero(&vmf, sizeof(vmf));
674 vmf.vmf_eax = 0x4f05;
675 vmf.vmf_ebx = 0; /* WINDOW_A, XXX */
676 vmf.vmf_edx = offset/vesa_adp->va_window_gran;
677 err = vm86_intcall(0x10, &vmf);
678 return ((err != 0) || (vmf.vmf_eax != 0x4f));
679}
680
681static int
682vesa_read_hw_cursor(int ad, int *col, int *row)
683{
684 return (*prevvidsw.read_hw_cursor)(ad, col, row);
685}
686
687static int
688vesa_set_hw_cursor(int ad, int col, int row)
689{
690 return (*prevvidsw.set_hw_cursor)(ad, col, row);
691}
692
693static int
694vesa_diag(int level)
695{
696 struct vesa_mode vmode;
697 u_int32_t p;
698 int i;
699
521#ifdef SC_VIDEO_DEBUG
522 printf("VESA: set_mode(): %d(%x) -> %d(%x)\n",
523 vesa_adp->va_mode, vesa_adp->va_mode, mode, mode);
524#endif
525 /*
526 * If the current mode is a VESA mode and the new mode is not,
527 * restore the state of the adapter first, so that non-standard,
528 * extended SVGA registers are set to the state compatible with
529 * the standard VGA modes. Otherwise (*prevvidsw.set_mode)()
530 * may not be able to set up the new mode correctly.
531 */
532 if (VESA_MODE(vesa_adp->va_mode)) {
533 if ((*prevvidsw.get_info)(ad, mode, &info) == 0) {
534 /* assert(vesa_state_buf != NULL); */
535 if ((vesa_state_buf == NULL)
536 || vesa_load_state(ad, vesa_state_buf))
537 return 1;
538 free(vesa_state_buf, M_DEVBUF);
539 vesa_state_buf = NULL;
540#ifdef SC_VIDEO_DEBUG
541 printf("VESA: restored\n");
542#endif
543 }
544 /*
545 * once (*prevvidsw.get_info)() succeeded,
546 * (*prevvidsw.set_mode)() below won't fail...
547 */
548 }
549
550 /* we may not need to handle this mode after all... */
551 if ((*prevvidsw.set_mode)(ad, mode) == 0)
552 return 0;
553
554 /* is the new mode supported? */
555 if (vesa_get_info(ad, mode, &info))
556 return 1;
557 /* assert(VESA_MODE(mode)); */
558
559#ifdef SC_VIDEO_DEBUG
560 printf("VESA: about to set a VESA mode...\n");
561#endif
562 /*
563 * If the current mode is not a VESA mode, save the current state
564 * so that the adapter state can be restored later when a non-VESA
565 * mode is to be set up. See above.
566 */
567 if (!VESA_MODE(vesa_adp->va_mode) && (vesa_state_buf == NULL)) {
568 len = vesa_save_state(ad, NULL, 0);
569 vesa_state_buf = malloc(len, M_DEVBUF, M_WAITOK);
570 if (vesa_save_state(ad, vesa_state_buf, len)) {
571#ifdef SC_VIDEO_DEBUG
572 printf("VESA: state save failed! (len=%d)\n", len);
573#endif
574 free(vesa_state_buf, M_DEVBUF);
575 vesa_state_buf = NULL;
576 return 1;
577 }
578#ifdef SC_VIDEO_DEBUG
579 printf("VESA: saved (len=%d)\n", len);
580 dump_buffer(vesa_state_buf, len);
581#endif
582 }
583
584 if (vesa_bios_set_mode(mode))
585 return 1;
586
587#ifdef SC_VIDEO_DEBUG
588 printf("VESA: mode set!\n");
589#endif
590 vesa_adp->va_mode = mode;
591 vesa_adp->va_flags &= ~V_ADP_COLOR;
592 vesa_adp->va_flags |=
593 (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
594 vesa_adp->va_crtc_addr =
595 (vesa_adp->va_flags & V_ADP_COLOR) ? COLOR_BASE : MONO_BASE;
596 vesa_adp->va_window = BIOS_PADDRTOVADDR(info.vi_window);
597 vesa_adp->va_window_size = info.vi_window_size;
598 vesa_adp->va_window_gran = info.vi_window_gran;
599 if (info.vi_buffer_size == 0) {
600 vesa_adp->va_buffer = 0;
601 vesa_adp->va_buffer_size = 0;
602 } else {
603 vesa_adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer);
604 vesa_adp->va_buffer_size = info.vi_buffer_size;
605 }
606
607 return 0;
608}
609
610static int
611vesa_save_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
612{
613 return (*prevvidsw.save_font)(ad, page, fontsize, data, ch, count);
614}
615
616static int
617vesa_load_font(int ad, int page, int fontsize, u_char *data, int ch, int count)
618{
619 return (*prevvidsw.load_font)(ad, page, fontsize, data, ch, count);
620}
621
622static int
623vesa_show_font(int ad, int page)
624{
625 return (*prevvidsw.show_font)(ad, page);
626}
627
628static int
629vesa_save_palette(int ad, u_char *palette)
630{
631 if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8)
632 || vesa_bios_set_dac(8))
633 return (*prevvidsw.save_palette)(ad, palette);
634
635 return vesa_bios_save_palette(0, 256, palette);
636}
637
638static int
639vesa_load_palette(int ad, u_char *palette)
640{
641 if ((ad != vesa_adp->va_index) || !(vesa_adp_info->v_flags & V_DAC8)
642 || vesa_bios_set_dac(8))
643 return (*prevvidsw.load_palette)(ad, palette);
644
645 return vesa_bios_load_palette(0, 256, palette);
646}
647
648static int
649vesa_set_border(int ad, int color)
650{
651 return (*prevvidsw.set_border)(ad, color);
652}
653
654static int
655vesa_save_state(int ad, void *p, size_t size)
656{
657 if (ad != vesa_adp->va_index)
658 return (*prevvidsw.save_state)(ad, p, size);
659
660 if (vesa_state_buf_size == 0)
661 vesa_state_buf_size = vesa_bios_state_buf_size();
662 if (size == 0)
663 return (sizeof(int) + vesa_state_buf_size);
664 else if (size < (sizeof(int) + vesa_state_buf_size))
665 return 1;
666
667 ((adp_state_t *)p)->sig = V_STATE_SIG;
668 bzero(((adp_state_t *)p)->regs, vesa_state_buf_size);
669 return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs,
670 vesa_state_buf_size);
671}
672
673static int
674vesa_load_state(int ad, void *p)
675{
676 if ((ad != vesa_adp->va_index)
677 || (((adp_state_t *)p)->sig != V_STATE_SIG))
678 return (*prevvidsw.load_state)(ad, p);
679
680 return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs,
681 vesa_state_buf_size);
682}
683
684static int
685vesa_set_origin(int ad, off_t offset)
686{
687 struct vm86frame vmf;
688 int err;
689
690 /*
691 * This function should return as quickly as possible to
692 * maintain good performance of the system. For this reason,
693 * error checking is kept minimal and let the VESA BIOS to
694 * detect error.
695 */
696 if (ad != vesa_adp->va_index)
697 return (*prevvidsw.set_win_org)(ad, offset);
698
699 if (vesa_adp->va_window_gran == 0)
700 return 1;
701 bzero(&vmf, sizeof(vmf));
702 vmf.vmf_eax = 0x4f05;
703 vmf.vmf_ebx = 0; /* WINDOW_A, XXX */
704 vmf.vmf_edx = offset/vesa_adp->va_window_gran;
705 err = vm86_intcall(0x10, &vmf);
706 return ((err != 0) || (vmf.vmf_eax != 0x4f));
707}
708
709static int
710vesa_read_hw_cursor(int ad, int *col, int *row)
711{
712 return (*prevvidsw.read_hw_cursor)(ad, col, row);
713}
714
715static int
716vesa_set_hw_cursor(int ad, int col, int row)
717{
718 return (*prevvidsw.set_hw_cursor)(ad, col, row);
719}
720
721static int
722vesa_diag(int level)
723{
724 struct vesa_mode vmode;
725 u_int32_t p;
726 int i;
727
728#ifndef VESA_MODULE
729 /* call the previous handler first */
730 (*prevvidsw.diag)(level);
731#endif
732
700 /* general adapter information */
701 printf("VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n",
702 ((vesa_adp_info->v_version & 0xf000) >> 12) * 10
703 + ((vesa_adp_info->v_version & 0x0f00) >> 8),
704 ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10
705 + (vesa_adp_info->v_version & 0x000f),
706 vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags,
707 vesa_vmodetab, vesa_adp_info->v_modetable);
708 /* OEM string */
709 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_oemstr);
710 if (p != 0)
711 printf("VESA: %s\n", (char *)BIOS_PADDRTOVADDR(p));
712
713 if (level <= 0)
714 return 0;
715
716 if (vesa_adp_info->v_version >= 0x0200) {
717 /* vendor name */
718 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_venderstr);
719 if (p != 0)
720 printf("VESA: %s, ", (char *)BIOS_PADDRTOVADDR(p));
721 /* product name */
722 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_prodstr);
723 if (p != 0)
724 printf("%s, ", (char *)BIOS_PADDRTOVADDR(p));
725 /* product revision */
726 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_revstr);
727 if (p != 0)
728 printf("%s\n", (char *)BIOS_PADDRTOVADDR(p));
729 }
730
731 /* mode information */
732 for (i = 0; vesa_vmodetab[i] != 0xffff; ++i) {
733 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
734 continue;
735
736 /* print something for diagnostic purpose */
737 printf("VESA: mode:0x%03x, flags:0x%04x",
738 vesa_vmodetab[i], vmode.v_modeattr);
739 if (vmode.v_modeattr & V_MODEOPTINFO) {
740 if (vmode.v_modeattr & V_MODEGRAPHICS) {
741 printf(", G %dx%dx%d %d, ",
742 vmode.v_width, vmode.v_height,
743 vmode.v_bpp, vmode.v_planes);
744 } else {
745 printf(", T %dx%d, ",
746 vmode.v_width, vmode.v_height);
747 }
748 printf("font:%dx%d",
749 vmode.v_cwidth, vmode.v_cheight);
750 }
751 if (vmode.v_modeattr & V_MODELFB) {
752 printf(", mem:%d, LFB:0x%x, off:0x%x",
753 vmode.v_memmodel, vmode.v_lfb,
754 vmode.v_offscreen);
755 }
756 printf("\n");
757 printf("VESA: window A:0x%x (%x), window B:0x%x (%x), ",
758 vmode.v_waseg, vmode.v_waattr,
759 vmode.v_wbseg, vmode.v_wbattr);
760 printf("size:%dk, gran:%dk\n",
761 vmode.v_wsize, vmode.v_wgran);
762 }
763
764 return 0;
765}
766
767/* module loading */
768
769#ifdef VESA_MODULE
770static int
771vesa_load(struct lkm_table *lkmtp, int cmd)
772#else
773int
774vesa_load(void)
775#endif
776{
777 int adapters;
778 int error;
779 int s;
780 int i;
781
782 if (vesa_init_done)
783 return 0;
784
785 /*
786 * If the VESA module is statically linked to the kernel, or
787 * it has already been loaded, abort loading this module this time.
788 */
789 vesa_adp = NULL;
790 adapters = (*biosvidsw.init)();
791 for (i = 0; i < adapters; ++i) {
792 if ((vesa_adp = (*biosvidsw.adapter)(i)) == NULL)
793 continue;
794 if (vesa_adp->va_flags & V_ADP_VESA)
795 return ENXIO;
796 if (vesa_adp->va_type == KD_VGA)
797 break;
798 }
799 /* if a VGA adapter is not found, abort */
800 if (i >= adapters)
801 return ENXIO;
802
803 if (vesa_bios_init())
804 return ENXIO;
805 vesa_adp->va_flags |= V_ADP_VESA;
806
807 /* remove conflicting modes if we have more than one adapter */
808 if (adapters > 1) {
733 /* general adapter information */
734 printf("VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n",
735 ((vesa_adp_info->v_version & 0xf000) >> 12) * 10
736 + ((vesa_adp_info->v_version & 0x0f00) >> 8),
737 ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10
738 + (vesa_adp_info->v_version & 0x000f),
739 vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags,
740 vesa_vmodetab, vesa_adp_info->v_modetable);
741 /* OEM string */
742 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_oemstr);
743 if (p != 0)
744 printf("VESA: %s\n", (char *)BIOS_PADDRTOVADDR(p));
745
746 if (level <= 0)
747 return 0;
748
749 if (vesa_adp_info->v_version >= 0x0200) {
750 /* vendor name */
751 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_venderstr);
752 if (p != 0)
753 printf("VESA: %s, ", (char *)BIOS_PADDRTOVADDR(p));
754 /* product name */
755 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_prodstr);
756 if (p != 0)
757 printf("%s, ", (char *)BIOS_PADDRTOVADDR(p));
758 /* product revision */
759 p = BIOS_SADDRTOLADDR(vesa_adp_info->v_revstr);
760 if (p != 0)
761 printf("%s\n", (char *)BIOS_PADDRTOVADDR(p));
762 }
763
764 /* mode information */
765 for (i = 0; vesa_vmodetab[i] != 0xffff; ++i) {
766 if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))
767 continue;
768
769 /* print something for diagnostic purpose */
770 printf("VESA: mode:0x%03x, flags:0x%04x",
771 vesa_vmodetab[i], vmode.v_modeattr);
772 if (vmode.v_modeattr & V_MODEOPTINFO) {
773 if (vmode.v_modeattr & V_MODEGRAPHICS) {
774 printf(", G %dx%dx%d %d, ",
775 vmode.v_width, vmode.v_height,
776 vmode.v_bpp, vmode.v_planes);
777 } else {
778 printf(", T %dx%d, ",
779 vmode.v_width, vmode.v_height);
780 }
781 printf("font:%dx%d",
782 vmode.v_cwidth, vmode.v_cheight);
783 }
784 if (vmode.v_modeattr & V_MODELFB) {
785 printf(", mem:%d, LFB:0x%x, off:0x%x",
786 vmode.v_memmodel, vmode.v_lfb,
787 vmode.v_offscreen);
788 }
789 printf("\n");
790 printf("VESA: window A:0x%x (%x), window B:0x%x (%x), ",
791 vmode.v_waseg, vmode.v_waattr,
792 vmode.v_wbseg, vmode.v_wbattr);
793 printf("size:%dk, gran:%dk\n",
794 vmode.v_wsize, vmode.v_wgran);
795 }
796
797 return 0;
798}
799
800/* module loading */
801
802#ifdef VESA_MODULE
803static int
804vesa_load(struct lkm_table *lkmtp, int cmd)
805#else
806int
807vesa_load(void)
808#endif
809{
810 int adapters;
811 int error;
812 int s;
813 int i;
814
815 if (vesa_init_done)
816 return 0;
817
818 /*
819 * If the VESA module is statically linked to the kernel, or
820 * it has already been loaded, abort loading this module this time.
821 */
822 vesa_adp = NULL;
823 adapters = (*biosvidsw.init)();
824 for (i = 0; i < adapters; ++i) {
825 if ((vesa_adp = (*biosvidsw.adapter)(i)) == NULL)
826 continue;
827 if (vesa_adp->va_flags & V_ADP_VESA)
828 return ENXIO;
829 if (vesa_adp->va_type == KD_VGA)
830 break;
831 }
832 /* if a VGA adapter is not found, abort */
833 if (i >= adapters)
834 return ENXIO;
835
836 if (vesa_bios_init())
837 return ENXIO;
838 vesa_adp->va_flags |= V_ADP_VESA;
839
840 /* remove conflicting modes if we have more than one adapter */
841 if (adapters > 1) {
809 clear_modes(vesa_vmode,
810 (vesa_adp->va_flags & V_ADP_COLOR) ?
811 V_INFO_COLOR : 0);
842 vesa_clear_modes(vesa_vmode,
843 (vesa_adp->va_flags & V_ADP_COLOR) ?
844 V_INFO_COLOR : 0);
812 }
813
814#ifdef VESA_MODULE
815 s = spltty();
816#endif
817 if ((error = vesa_load_ioctl()) == 0) {
818 bcopy(&biosvidsw, &prevvidsw, sizeof(prevvidsw));
819 bcopy(&vesavidsw, &biosvidsw, sizeof(vesavidsw));
820 vesa_init_done = TRUE;
821 }
822#ifdef VESA_MODULE
823 splx(s);
824
825 if (error == 0)
826 vesa_diag(bootverbose);
827#endif
828
829 return error;
830}
831
832#ifdef VESA_MODULE
833
834static int
835vesa_unload(struct lkm_table *lkmtp, int cmd)
836{
837 int error;
838 int s;
839
840 /* if the adapter is currently in a VESA mode, don't unload */
841 if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode))
842 return EBUSY;
843 /*
844 * FIXME: if there is at least one vty which is in a VESA mode,
845 * we shouldn't be unloading! XXX
846 */
847
848 s = spltty();
849 if ((error = vesa_unload_ioctl()) == 0) {
850 if (vesa_adp)
851 vesa_adp->va_flags &= ~V_ADP_VESA;
852 bcopy(&prevvidsw, &biosvidsw, sizeof(biosvidsw));
853 }
854 splx(s);
855
856 return error;
857}
858
859int
860vesa_mod(struct lkm_table *lkmtp, int cmd, int ver)
861{
862 MOD_DISPATCH(vesa, lkmtp, cmd, ver,
863 vesa_load, vesa_unload, lkm_nullcmd);
864}
865
866#endif /* VESA_MODULE */
867
868#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */
845 }
846
847#ifdef VESA_MODULE
848 s = spltty();
849#endif
850 if ((error = vesa_load_ioctl()) == 0) {
851 bcopy(&biosvidsw, &prevvidsw, sizeof(prevvidsw));
852 bcopy(&vesavidsw, &biosvidsw, sizeof(vesavidsw));
853 vesa_init_done = TRUE;
854 }
855#ifdef VESA_MODULE
856 splx(s);
857
858 if (error == 0)
859 vesa_diag(bootverbose);
860#endif
861
862 return error;
863}
864
865#ifdef VESA_MODULE
866
867static int
868vesa_unload(struct lkm_table *lkmtp, int cmd)
869{
870 int error;
871 int s;
872
873 /* if the adapter is currently in a VESA mode, don't unload */
874 if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode))
875 return EBUSY;
876 /*
877 * FIXME: if there is at least one vty which is in a VESA mode,
878 * we shouldn't be unloading! XXX
879 */
880
881 s = spltty();
882 if ((error = vesa_unload_ioctl()) == 0) {
883 if (vesa_adp)
884 vesa_adp->va_flags &= ~V_ADP_VESA;
885 bcopy(&prevvidsw, &biosvidsw, sizeof(biosvidsw));
886 }
887 splx(s);
888
889 return error;
890}
891
892int
893vesa_mod(struct lkm_table *lkmtp, int cmd, int ver)
894{
895 MOD_DISPATCH(vesa, lkmtp, cmd, ver,
896 vesa_load, vesa_unload, lkm_nullcmd);
897}
898
899#endif /* VESA_MODULE */
900
901#endif /* (NSC > 0 && VESA && VM86) || VESA_MODULE */