summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/boot/sys/boot/common/gfx_fb.h18
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/vbe.c77
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/vbe.h34
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 */