Mercurial > illumos > git > illumos-gate
changeset 20079:f0e4c56a3bb7
13152 loader: add flat panel info query
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Dan McDonald <danmcd@joyent.com>
author | Toomas Soome <tsoome@me.com> |
---|---|
date | Sun, 13 Jan 2019 19:10:19 +0200 |
parents | 3b587ddb3287 |
children | 3988d4e53378 |
files | usr/src/boot/sys/boot/common/gfx_fb.h usr/src/boot/sys/boot/i386/libi386/vbe.c usr/src/boot/sys/boot/i386/libi386/vbe.h |
diffstat | 3 files changed, 98 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/boot/sys/boot/common/gfx_fb.h Mon Sep 14 20:37:35 2020 +0300 +++ b/usr/src/boot/sys/boot/common/gfx_fb.h Sun Jan 13 19:10:19 2019 +0200 @@ -93,15 +93,21 @@ uint8_t checksum; } __packed; +/* + * Number of pixels and lines is 12-bit int, valid values 0-4095. + */ +#define EDID_MAX_PIXELS 4095 +#define EDID_MAX_LINES 4095 + #define GET_EDID_INFO_WIDTH(edid_info, timings_num) \ - ((edid_info)->detailed_timings[(timings_num)].horizontal_active_lo | \ - (((uint_t)(edid_info)->detailed_timings[(timings_num)].horizontal_hi & \ - 0xf0) << 4)) + ((edid_info)->detailed_timings[(timings_num)].horizontal_active_lo | \ + (((uint_t)(edid_info)->detailed_timings[(timings_num)].horizontal_hi & \ + 0xf0) << 4)) #define GET_EDID_INFO_HEIGHT(edid_info, timings_num) \ - ((edid_info)->detailed_timings[(timings_num)].vertical_active_lo | \ - (((uint_t)(edid_info)->detailed_timings[(timings_num)].vertical_hi & \ - 0xf0) << 4)) + ((edid_info)->detailed_timings[(timings_num)].vertical_active_lo | \ + (((uint_t)(edid_info)->detailed_timings[(timings_num)].vertical_hi & \ + 0xf0) << 4)) extern multiboot_tag_framebuffer_t gfx_fb;
--- a/usr/src/boot/sys/boot/i386/libi386/vbe.c Mon Sep 14 20:37:35 2020 +0300 +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c Sun Jan 13 19:10:19 2019 +0200 @@ -180,6 +180,20 @@ return (v86.ebx & 0xffff); } +/* Function 11h BL=01h - Flat Panel status */ +static int +biosvbe_ddc_read_flat_panel_info(void *buf) +{ + v86.ctl = V86_FLAGS; + v86.addr = 0x10; + v86.eax = 0x4f11; /* Flat Panel Interface extensions */ + v86.ebx = 1; /* Return Flat Panel Information */ + v86.es = VTOPSEG(buf); + v86.edi = VTOPOFF(buf); + v86int(); + return (v86.eax & 0xffff); +} + /* Function 15h BL=01h - Read EDID */ static int biosvbe_ddc_read_edid(int blockno, void *buf) @@ -495,6 +509,7 @@ edid_info = bio_alloc(sizeof (*edid_info)); if (edid_info == NULL) return (ret); + memset(edid_info, 0, sizeof (*edid_info)); if (VBE_ERROR(biosvbe_ddc_read_edid(0, edid_info))) goto done; @@ -511,12 +526,37 @@ *pwidth = GET_EDID_INFO_WIDTH(edid_info, 0); *pheight = GET_EDID_INFO_HEIGHT(edid_info, 0); - ret = true; + if (*pwidth > 0 && *pwidth <= EDID_MAX_PIXELS && + *pheight > 0 && *pheight <= EDID_MAX_LINES) + ret = true; done: bio_free(edid_info, sizeof (*edid_info)); return (ret); } +static bool +vbe_get_flatpanel(uint_t *pwidth, uint_t *pheight) +{ + struct flatpanelinfo *fp_info; + bool ret = false; + + fp_info = bio_alloc(sizeof (*fp_info)); + if (fp_info == NULL) + return (ret); + memset(fp_info, 0, sizeof (*fp_info)); + + if (VBE_ERROR(biosvbe_ddc_read_flat_panel_info(fp_info))) + goto done; + + *pwidth = fp_info->HorizontalSize; + *pheight = fp_info->VerticalSize; + ret = true; + +done: + bio_free(fp_info, sizeof (*fp_info)); + return (ret); +} + static void vbe_print_vbe_info(struct vbeinfoblock *vbep) { @@ -554,7 +594,8 @@ uint16_t mode; int nmodes = 0, safety = 0; int ddc_caps; - uint_t edid_width, edid_height; + uint_t width, height; + bool edid = false; if (!vbe_check()) return; @@ -567,11 +608,15 @@ if (ddc_caps & 2) printf(" [DDC2]"); - if (vbe_get_edid(&edid_width, &edid_height)) - printf(": EDID %dx%d\n", edid_width, edid_height); + edid = vbe_get_edid(&width, &height); + if (edid) + printf(": EDID %dx%d\n", width, height); else printf(": no EDID information\n"); } + if (!edid) + if (vbe_get_flatpanel(&width, &height)) + printf(": Panel %dx%d\n", width, height); memset(vbe, 0, sizeof (vbe)); memcpy(vbe->VbeSignature, "VBE2", 4); @@ -691,19 +736,29 @@ } } +/* + * Try EDID preferred mode, if EDID or the suggested mode is not available, + * then try flat panel information. + * Fall back to VBE_DEFAULT_MODE. + */ int vbe_default_mode(void) { int modenum; - uint_t edid_width, edid_height; + uint_t width, height; + + modenum = 0; + if (vbe_get_edid(&width, &height)) + modenum = vbe_find_mode_xydm(width, height, -1, -1); - if (vbe_get_edid(&edid_width, &edid_height)) { - modenum = vbe_find_mode_xydm(edid_width, edid_height, -1, -1); - if (modenum == 0) - modenum = vbe_find_mode(VBE_DEFAULT_MODE); - } else { + if (modenum == 0 && + vbe_get_flatpanel(&width, &height)) { + modenum = vbe_find_mode_xydm(width, height, -1, -1); + } + + /* Still no mode? Fall back to default. */ + if (modenum == 0) modenum = vbe_find_mode(VBE_DEFAULT_MODE); - } return (modenum); }
--- a/usr/src/boot/sys/boot/i386/libi386/vbe.h Mon Sep 14 20:37:35 2020 +0300 +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.h Sun Jan 13 19:10:19 2019 +0200 @@ -33,7 +33,10 @@ * VESA disabled. */ -#define VBE_DEFAULT_MODE "800x600" +#ifndef _VBE_H +#define _VBE_H + +#define VBE_DEFAULT_MODE "800x600" struct vbeinfoblock { char VbeSignature[4]; @@ -61,8 +64,10 @@ uint8_t XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel; uint8_t NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages; uint8_t Reserved1; - /* Direct Color fields - (required for direct/6 and YUV/7 memory models) */ + /* + * Direct Color fields + * (required for direct/6 and YUV/7 memory models) + */ uint8_t RedMaskSize, RedFieldPosition; uint8_t GreenMaskSize, GreenFieldPosition; uint8_t BlueMaskSize, BlueFieldPosition; @@ -108,17 +113,16 @@ struct flatpanelinfo { - uint16_t HorizontalSize; - uint16_t VerticalSize; - uint16_t PanelType; - uint8_t RedBPP; - uint8_t GreenBPP; - uint8_t BlueBPP; - uint8_t ReservedBPP; - uint32_t ReservedOffScreenMemSize; - uint32_t ReservedOffScreenMemPtr; - - uint8_t Reserved[14]; + uint16_t HorizontalSize; /* Horizontal Size in Pixels */ + uint16_t VerticalSize; /* Vertical Size in Lines */ + uint16_t PanelType; /* Flat Panel Type */ + uint8_t RedBPP; /* Red Bits Per Primary */ + uint8_t GreenBPP; /* Green Bits Per Primary */ + uint8_t BlueBPP; /* Blue Bits Per Primary */ + uint8_t ReservedBPP; /* Reserved Bits Per Primary */ + uint32_t RsvdOffScreenMemSize; /* Size in KB of Offscreen Memory */ + uint32_t RsvdOffScreenMemPtr; /* Pointer to reserved offscreen memory */ + uint8_t Reserved[14]; /* remainder of FPInfo */ } __packed; #define VBE_BASE_MODE (0x100) /* VBE 3.0 page 18 */ @@ -143,3 +147,5 @@ int vbe_get_mode(void); int vbe_set_palette(const struct paletteentry *, size_t); void vbe_modelist(int); + +#endif /* _VBE_H */