diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/boot/sys/boot/common/gfx_fb.h | 18 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vbe.c | 77 | ||||
-rw-r--r-- | usr/src/boot/sys/boot/i386/libi386/vbe.h | 34 |
3 files changed, 98 insertions, 31 deletions
diff --git a/usr/src/boot/sys/boot/common/gfx_fb.h b/usr/src/boot/sys/boot/common/gfx_fb.h index de199d1472..cb2d37042d 100644 --- a/usr/src/boot/sys/boot/common/gfx_fb.h +++ b/usr/src/boot/sys/boot/common/gfx_fb.h @@ -93,15 +93,21 @@ struct vesa_edid_info { 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; diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.c b/usr/src/boot/sys/boot/i386/libi386/vbe.c index d8ad4ed643..c3cc09dd53 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vbe.c +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.c @@ -180,6 +180,20 @@ biosvbe_ddc_caps(void) 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 @@ vbe_get_edid(uint_t *pwidth, uint_t *pheight) 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 @@ vbe_get_edid(uint_t *pwidth, uint_t *pheight) *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 @@ vbe_modelist(int depth) 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 @@ vbe_modelist(int depth) 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 @@ vbe_print_mode(void) } } +/* + * 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; - 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 { - modenum = vbe_find_mode(VBE_DEFAULT_MODE); + modenum = 0; + if (vbe_get_edid(&width, &height)) + modenum = vbe_find_mode_xydm(width, height, -1, -1); + + 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); } diff --git a/usr/src/boot/sys/boot/i386/libi386/vbe.h b/usr/src/boot/sys/boot/i386/libi386/vbe.h index 7b428b968d..dc732a05bc 100644 --- a/usr/src/boot/sys/boot/i386/libi386/vbe.h +++ b/usr/src/boot/sys/boot/i386/libi386/vbe.h @@ -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 @@ struct modeinfoblock { 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 paletteentry { 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_set_mode(int); int vbe_get_mode(void); int vbe_set_palette(const struct paletteentry *, size_t); void vbe_modelist(int); + +#endif /* _VBE_H */ |