1 /* $NetBSD: vbe.c,v 1.4 2009/09/14 11:56:27 jmcneill Exp $ */
4 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
30 * VESA BIOS Extensions routines
33 #include <lib/libsa/stand.h>
34 #include <lib/libkern/libkern.h>
35 #include <machine/bootinfo.h>
39 extern const uint8_t rasops_cmap
[];
41 static struct _vbestate
{
47 vbe_mode_is_supported(struct modeinfoblock
*mi
)
49 if ((mi
->ModeAttributes
& 0x01) == 0)
50 return 0; /* mode not supported by hardware */
51 if ((mi
->ModeAttributes
& 0x08) == 0)
52 return 0; /* linear fb not available */
53 if ((mi
->ModeAttributes
& 0x10) == 0)
54 return 0; /* text mode */
55 if (mi
->NumberOfPlanes
!= 1)
56 return 0; /* planar mode not supported */
57 if (mi
->MemoryModel
!= 0x04 /* Packed pixel */ &&
58 mi
->MemoryModel
!= 0x06 /* Direct Color */)
59 return 0; /* unsupported pixel format */
66 if (!vbestate
.available
) {
67 printf("VBE not available\n");
76 struct vbeinfoblock vbe
;
78 memset(&vbe
, 0, sizeof(vbe
));
79 memcpy(vbe
.VbeSignature
, "VBE2", 4);
80 if (biosvbe_info(&vbe
) != 0x004f)
82 if (memcmp(vbe
.VbeSignature
, "VESA", 4) != 0)
85 vbestate
.available
= 1;
92 return vbestate
.available
;
96 vbe_set_palette(const uint8_t *cmap
, int slot
)
98 struct paletteentry pe
;
104 pe
.Blue
= cmap
[2] >> 2;
105 pe
.Green
= cmap
[1] >> 2;
106 pe
.Red
= cmap
[0] >> 2;
109 ret
= biosvbe_palette_data(0x0600, slot
, &pe
);
111 return ret
== 0x004f ? 0 : 1;
115 vbe_set_mode(int modenum
)
117 struct modeinfoblock mi
;
118 struct btinfo_framebuffer fb
;
124 ret
= biosvbe_get_mode_info(modenum
, &mi
);
126 printf("mode 0x%x invalid\n", modenum
);
130 if (!vbe_mode_is_supported(&mi
)) {
131 printf("mode 0x%x not supported\n", modenum
);
135 ret
= biosvbe_set_mode(modenum
);
137 printf("mode 0x%x could not be set\n", modenum
);
141 /* Setup palette for packed pixel mode */
142 if (mi
.MemoryModel
== 0x04)
143 for (i
= 0; i
< 256; i
++)
144 vbe_set_palette(&rasops_cmap
[i
* 3], i
);
146 fb
.physaddr
= (uint64_t)mi
.PhysBasePtr
& 0xffffffff;
147 fb
.width
= mi
.XResolution
;
148 fb
.height
= mi
.YResolution
;
149 fb
.stride
= mi
.BytesPerScanLine
;
150 fb
.depth
= mi
.BitsPerPixel
;
152 fb
.rnum
= mi
.RedMaskSize
;
153 fb
.rpos
= mi
.RedFieldPosition
;
154 fb
.gnum
= mi
.GreenMaskSize
;
155 fb
.gpos
= mi
.GreenFieldPosition
;
156 fb
.bnum
= mi
.BlueMaskSize
;
157 fb
.bpos
= mi
.BlueFieldPosition
;
158 fb
.vbemode
= modenum
;
160 framebuffer_configure(&fb
);
170 if (vbestate
.modenum
> 0) {
171 ret
= vbe_set_mode(vbestate
.modenum
);
173 printf("WARNING: failed to set VBE mode 0x%x\n",
182 vbe_farptr(uint32_t farptr
)
184 return VBEPHYPTR((((farptr
& 0xffff0000) >> 12) + (farptr
& 0xffff)));
188 vbe_parse_mode_str(char *str
, int *x
, int *y
, int *bpp
)
193 *x
= strtoul(p
, NULL
, 0);
200 *y
= strtoul(p
, NULL
, 0);
208 *bpp
= strtoul(p
, NULL
, 0);
217 vbe_find_mode(char *str
)
219 struct vbeinfoblock vbe
;
220 struct modeinfoblock mi
;
226 if (!vbe_parse_mode_str(str
, &x
, &y
, &bpp
))
229 memset(&vbe
, 0, sizeof(vbe
));
230 memcpy(vbe
.VbeSignature
, "VBE2", 4);
231 if (biosvbe_info(&vbe
) != 0x004f)
233 if (memcmp(vbe
.VbeSignature
, "VESA", 4) != 0)
235 farptr
= vbe
.VideoModePtr
;
239 while ((mode
= *(uint16_t *)vbe_farptr(farptr
)) != 0xffff) {
244 if (biosvbe_get_mode_info(mode
, &mi
) != 0x004f)
246 /* we only care about linear modes here */
247 if (vbe_mode_is_supported(&mi
) == 0)
250 if (mi
.XResolution
== x
&&
251 mi
.YResolution
== y
&&
252 mi
.BitsPerPixel
== bpp
)
260 vbe_dump_mode(int modenum
, struct modeinfoblock
*mi
)
262 printf("0x%x=%dx%dx%d", modenum
,
263 mi
->XResolution
, mi
->YResolution
, mi
->BitsPerPixel
);
269 struct vbeinfoblock vbe
;
270 struct modeinfoblock mi
;
273 int nmodes
= 0, safety
= 0;
279 memset(&vbe
, 0, sizeof(vbe
));
280 memcpy(vbe
.VbeSignature
, "VBE2", 4);
281 if (biosvbe_info(&vbe
) != 0x004f)
283 if (memcmp(vbe
.VbeSignature
, "VESA", 4) != 0)
285 farptr
= vbe
.VideoModePtr
;
289 while ((mode
= *(uint16_t *)vbe_farptr(farptr
)) != 0xffff) {
296 if (biosvbe_get_mode_info(mode
, &mi
) != 0x004f)
298 /* we only care about linear modes here */
299 if (vbe_mode_is_supported(&mi
) == 0)
306 vbe_dump_mode(mode
, &mi
);
312 printf("none found");
317 command_vesa(char *cmd
)
325 strlcpy(arg
, cmd
, sizeof(arg
));
327 if (strcmp(arg
, "list") == 0) {
332 if (strcmp(arg
, "disabled") == 0 || strcmp(arg
, "off") == 0) {
333 vbestate
.modenum
= 0;
337 if (strcmp(arg
, "enabled") == 0 || strcmp(arg
, "on") == 0)
338 modenum
= VBE_DEFAULT_MODE
;
339 else if (strncmp(arg
, "0x", 2) == 0)
340 modenum
= strtoul(arg
, NULL
, 0);
341 else if (strchr(arg
, 'x') != NULL
) {
342 modenum
= vbe_find_mode(arg
);
344 printf("mode %s not supported by firmware\n", arg
);
350 if (modenum
>= 0x100) {
351 vbestate
.modenum
= modenum
;
355 printf("invalid flag, must be 'on', 'off', "
356 "a display mode, or a VBE mode number\n");