Remove building with NOCRYPTO option
[minix3.git] / sys / arch / i386 / stand / lib / vbe.c
blobcad36615a730fe0876155baf9bedfaa138a9efb2
1 /* $NetBSD: vbe.c,v 1.8 2013/05/31 15:11:07 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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>
36 #include "libi386.h"
37 #include "vbe.h"
39 extern const uint8_t rasops_cmap[];
40 static uint8_t *vbe_edid = NULL;
41 static int vbe_edid_valid = 0;
43 static struct _vbestate {
44 int available;
45 int modenum;
46 } vbestate;
48 static int
49 vbe_mode_is_supported(struct modeinfoblock *mi)
51 if ((mi->ModeAttributes & 0x01) == 0)
52 return 0; /* mode not supported by hardware */
53 if ((mi->ModeAttributes & 0x08) == 0)
54 return 0; /* linear fb not available */
55 if ((mi->ModeAttributes & 0x10) == 0)
56 return 0; /* text mode */
57 if (mi->NumberOfPlanes != 1)
58 return 0; /* planar mode not supported */
59 if (mi->MemoryModel != 0x04 /* Packed pixel */ &&
60 mi->MemoryModel != 0x06 /* Direct Color */)
61 return 0; /* unsupported pixel format */
62 return 1;
65 static bool
66 vbe_check(void)
68 if (!vbestate.available) {
69 printf("VBE not available\n");
70 return false;
72 return true;
75 void
76 vbe_init(void)
78 struct vbeinfoblock vbe;
80 memset(&vbe, 0, sizeof(vbe));
81 memcpy(vbe.VbeSignature, "VBE2", 4);
82 if (biosvbe_info(&vbe) != 0x004f)
83 return;
84 if (memcmp(vbe.VbeSignature, "VESA", 4) != 0)
85 return;
87 vbestate.available = 1;
88 vbestate.modenum = 0;
91 int
92 vbe_available(void)
94 return vbestate.available;
97 int
98 vbe_set_palette(const uint8_t *cmap, int slot)
100 struct paletteentry pe;
101 int ret;
103 if (!vbe_check())
104 return 1;
106 pe.Blue = cmap[2] >> 2;
107 pe.Green = cmap[1] >> 2;
108 pe.Red = cmap[0] >> 2;
109 pe.Alignment = 0;
111 ret = biosvbe_palette_data(0x0600, slot, &pe);
113 return ret == 0x004f ? 0 : 1;
117 vbe_set_mode(int modenum)
119 struct modeinfoblock mi;
120 struct btinfo_framebuffer fb;
121 int ret, i;
123 if (!vbe_check())
124 return 1;
126 ret = biosvbe_get_mode_info(modenum, &mi);
127 if (ret != 0x004f) {
128 printf("mode 0x%x invalid\n", modenum);
129 return 1;
132 if (!vbe_mode_is_supported(&mi)) {
133 printf("mode 0x%x not supported\n", modenum);
134 return 1;
137 ret = biosvbe_set_mode(modenum);
138 if (ret != 0x004f) {
139 printf("mode 0x%x could not be set\n", modenum);
140 return 1;
143 /* Setup palette for packed pixel mode */
144 if (mi.MemoryModel == 0x04)
145 for (i = 0; i < 256; i++)
146 vbe_set_palette(&rasops_cmap[i * 3], i);
148 fb.physaddr = (uint64_t)mi.PhysBasePtr & 0xffffffff;
149 fb.width = mi.XResolution;
150 fb.height = mi.YResolution;
151 fb.stride = mi.BytesPerScanLine;
152 fb.depth = mi.BitsPerPixel;
153 fb.flags = 0;
154 fb.rnum = mi.RedMaskSize;
155 fb.rpos = mi.RedFieldPosition;
156 fb.gnum = mi.GreenMaskSize;
157 fb.gpos = mi.GreenFieldPosition;
158 fb.bnum = mi.BlueMaskSize;
159 fb.bpos = mi.BlueFieldPosition;
160 fb.vbemode = modenum;
162 framebuffer_configure(&fb);
164 return 0;
168 vbe_commit(void)
170 int ret = 1;
172 if (vbestate.modenum > 0) {
173 ret = vbe_set_mode(vbestate.modenum);
174 if (ret) {
175 printf("WARNING: failed to set VBE mode 0x%x\n",
176 vbestate.modenum);
177 wait_sec(5);
180 return ret;
183 static void *
184 vbe_farptr(uint32_t farptr)
186 return VBEPHYPTR((((farptr & 0xffff0000) >> 12) + (farptr & 0xffff)));
189 static int
190 vbe_parse_mode_str(char *str, int *x, int *y, int *depth)
192 char *p;
194 p = str;
195 *x = strtoul(p, NULL, 0);
196 if (*x == 0)
197 return 0;
198 p = strchr(p, 'x');
199 if (!p)
200 return 0;
201 ++p;
202 *y = strtoul(p, NULL, 0);
203 if (*y == 0)
204 return 0;
205 p = strchr(p, 'x');
206 if (!p)
207 *depth = 8;
208 else {
209 ++p;
210 *depth = strtoul(p, NULL, 0);
211 if (*depth == 0)
212 return 0;
215 return 1;
218 static int
219 vbe_find_mode_xyd(int x, int y, int depth)
221 struct vbeinfoblock vbe;
222 struct modeinfoblock mi;
223 uint32_t farptr;
224 uint16_t mode;
225 int safety = 0;
227 memset(&vbe, 0, sizeof(vbe));
228 memcpy(vbe.VbeSignature, "VBE2", 4);
229 if (biosvbe_info(&vbe) != 0x004f)
230 return 0;
231 if (memcmp(vbe.VbeSignature, "VESA", 4) != 0)
232 return 0;
233 farptr = vbe.VideoModePtr;
234 if (farptr == 0)
235 return 0;
237 while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) {
238 safety++;
239 farptr += 2;
240 if (safety == 100)
241 return 0;
242 if (biosvbe_get_mode_info(mode, &mi) != 0x004f)
243 continue;
244 /* we only care about linear modes here */
245 if (vbe_mode_is_supported(&mi) == 0)
246 continue;
247 safety = 0;
248 if (mi.XResolution == x &&
249 mi.YResolution == y &&
250 mi.BitsPerPixel == depth)
251 return mode;
254 return 0;
257 static int
258 vbe_find_mode(char *str)
260 int x, y, depth;
262 if (!vbe_parse_mode_str(str, &x, &y, &depth))
263 return 0;
265 return vbe_find_mode_xyd(x, y, depth);
268 static void
269 vbe_dump_mode(int modenum, struct modeinfoblock *mi)
271 printf("0x%x=%dx%dx%d", modenum,
272 mi->XResolution, mi->YResolution, mi->BitsPerPixel);
275 static int
276 vbe_get_edid(int *pwidth, int *pheight)
278 const uint8_t magic[] = EDID_MAGIC;
279 int ddc_caps, ret;
281 ddc_caps = biosvbe_ddc_caps();
282 if (ddc_caps == 0) {
283 return 1;
286 if (vbe_edid == NULL) {
287 vbe_edid = alloc(128);
289 if (vbe_edid_valid == 0) {
290 ret = biosvbe_ddc_read_edid(0, vbe_edid);
291 if (ret != 0x004f)
292 return 1;
293 if (memcmp(vbe_edid, magic, sizeof(magic)) != 0)
294 return 1;
295 vbe_edid_valid = 1;
298 *pwidth = vbe_edid[EDID_DESC_BLOCK + 2] |
299 (((int)vbe_edid[EDID_DESC_BLOCK + 4] & 0xf0) << 4);
300 *pheight = vbe_edid[EDID_DESC_BLOCK + 5] |
301 (((int)vbe_edid[EDID_DESC_BLOCK + 7] & 0xf0) << 4);
303 return 0;
306 void
307 vbe_modelist(void)
309 struct vbeinfoblock vbe;
310 struct modeinfoblock mi;
311 uint32_t farptr;
312 uint16_t mode;
313 int nmodes = 0, safety = 0;
314 int ddc_caps, edid_width, edid_height;
316 if (!vbe_check())
317 return;
319 ddc_caps = biosvbe_ddc_caps();
320 if (ddc_caps & 3) {
321 printf("DDC");
322 if (ddc_caps & 1)
323 printf(" [DDC1]");
324 if (ddc_caps & 2)
325 printf(" [DDC2]");
327 if (vbe_get_edid(&edid_width, &edid_height) != 0)
328 printf(": no EDID information\n");
329 else
330 printf(": EDID %dx%d\n", edid_width, edid_height);
333 printf("Modes: ");
334 memset(&vbe, 0, sizeof(vbe));
335 memcpy(vbe.VbeSignature, "VBE2", 4);
336 if (biosvbe_info(&vbe) != 0x004f)
337 goto done;
338 if (memcmp(vbe.VbeSignature, "VESA", 4) != 0)
339 goto done;
340 farptr = vbe.VideoModePtr;
341 if (farptr == 0)
342 goto done;
344 while ((mode = *(uint16_t *)vbe_farptr(farptr)) != 0xffff) {
345 safety++;
346 farptr += 2;
347 if (safety == 100) {
348 printf("[?] ");
349 break;
351 if (biosvbe_get_mode_info(mode, &mi) != 0x004f)
352 continue;
353 /* we only care about linear modes here */
354 if (vbe_mode_is_supported(&mi) == 0)
355 continue;
356 safety = 0;
357 if (nmodes % 4 == 0)
358 printf("\n");
359 else
360 printf(" ");
361 vbe_dump_mode(mode, &mi);
362 nmodes++;
365 done:
366 if (nmodes == 0)
367 printf("none found");
368 printf("\n");
371 void
372 command_vesa(char *cmd)
374 char arg[20];
375 int modenum, edid_width, edid_height;
377 if (!vbe_check())
378 return;
380 strlcpy(arg, cmd, sizeof(arg));
382 if (strcmp(arg, "list") == 0) {
383 vbe_modelist();
384 return;
387 if (strcmp(arg, "disabled") == 0 || strcmp(arg, "off") == 0) {
388 vbestate.modenum = 0;
389 return;
392 if (strcmp(arg, "enabled") == 0 || strcmp(arg, "on") == 0) {
393 if (vbe_get_edid(&edid_width, &edid_height) != 0) {
394 modenum = VBE_DEFAULT_MODE;
395 } else {
396 modenum = vbe_find_mode_xyd(edid_width, edid_height, 8);
397 if (modenum == 0)
398 modenum = VBE_DEFAULT_MODE;
400 } else if (strncmp(arg, "0x", 2) == 0) {
401 modenum = strtoul(arg, NULL, 0);
402 } else if (strchr(arg, 'x') != NULL) {
403 modenum = vbe_find_mode(arg);
404 if (modenum == 0) {
405 printf("mode %s not supported by firmware\n", arg);
406 return;
408 } else {
409 modenum = 0;
412 if (modenum >= 0x100) {
413 vbestate.modenum = modenum;
414 return;
417 printf("invalid flag, must be 'on', 'off', 'list', "
418 "a display mode, or a VBE mode number\n");