summaryrefslogtreecommitdiffstats
path: root/sys/dev/fb
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2009-09-25 18:08:38 +0000
committerjkim <jkim@FreeBSD.org>2009-09-25 18:08:38 +0000
commit730c4fcb79e6e002ffc796d5a49adb0183cce61e (patch)
tree8bf8f353e0c3335befb4001e3c9e14251a6534cd /sys/dev/fb
parent08823d6c8cd476e82138a1ab640a95190c406ca7 (diff)
downloadFreeBSD-src-730c4fcb79e6e002ffc796d5a49adb0183cce61e.zip
FreeBSD-src-730c4fcb79e6e002ffc796d5a49adb0183cce61e.tar.gz
Reject some VESA graphics modes if the controller does not have enough
memory to support them. Some adapters have expansible memory slots but video mode table is static. In this case, unusable modes may be reported. Submitted by: paradox (ddkprog yahoo com) (initial patch)
Diffstat (limited to 'sys/dev/fb')
-rw-r--r--sys/dev/fb/vesa.c84
1 files changed, 50 insertions, 34 deletions
diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c
index 7db4600..8a61368 100644
--- a/sys/dev/fb/vesa.c
+++ b/sys/dev/fb/vesa.c
@@ -194,6 +194,7 @@ static int vesa_bios_set_start(int x, int y);
static int vesa_map_gen_mode_num(int type, int color, int mode);
static int vesa_translate_flags(u_int16_t vflags);
static int vesa_translate_mmodel(u_int8_t vmodel);
+static int vesa_get_line_width(video_info_t *info);
static int vesa_bios_init(void);
static void vesa_clear_modes(video_info_t *info, int color);
static vm_offset_t vesa_map_buffer(u_int paddr, size_t size);
@@ -654,12 +655,44 @@ vesa_translate_mmodel(u_int8_t vmodel)
}
static int
+vesa_get_line_width(video_info_t *info)
+{
+ int len;
+ int width;
+
+ width = info->vi_width;
+
+ if (info->vi_flags & V_INFO_GRAPHICS)
+ switch (info->vi_depth / info->vi_planes) {
+ case 1:
+ return (width / 8);
+ case 2:
+ return (width / 4);
+ case 4:
+ return (width / 2);
+ case 8:
+ return (width);
+ case 15:
+ case 16:
+ return (width * 2);
+ case 24:
+ case 32:
+ return (width * 4);
+ }
+
+ len = vesa_bios_get_line_length();
+
+ return (len > 0 ? len : width);
+}
+
+static int
vesa_bios_init(void)
{
static struct vesa_info buf;
struct vesa_mode vmode;
video_info_t *p;
x86regs_t regs;
+ size_t bsize;
int offs;
u_char *vmbuf;
int is_via_cle266;
@@ -837,6 +870,20 @@ vesa_bios_init(void)
vesa_vmode[modes].vi_flags
= vesa_translate_flags(vmode.v_modeattr) | V_INFO_VESA;
+
+ /* Does it have enough memory to support this mode? */
+ bsize = vesa_get_line_width(&vesa_vmode[modes]);
+ bsize *= vesa_vmode[modes].vi_height;
+ if (bsize > vesa_vmode[modes].vi_buffer_size) {
+#if VESA_DEBUG > 1
+ printf(
+ "Rejecting VESA %s mode: %d x %d x %d bpp attr = %x, not enough memory\n",
+ (vmode.v_modeattr & V_MODEGRAPHICS) != 0 ? "graphics" : "text",
+ vmode.v_width, vmode.v_height, vmode.v_bpp, vmode.v_modeattr);
+#endif
+ continue;
+ }
+
++modes;
}
vesa_vmode[modes].vi_mode = EOT;
@@ -1049,7 +1096,6 @@ static int
vesa_set_mode(video_adapter_t *adp, int mode)
{
video_info_t info;
- int len = 0;
if (adp != vesa_adp)
return (*prevvidsw->set_mode)(adp, mode);
@@ -1132,42 +1178,12 @@ vesa_set_mode(video_adapter_t *adp, int mode)
vesa_adp->va_window_gran = info.vi_window_gran;
}
vesa_adp->va_window_orig = 0;
-
- if (info.vi_flags & V_INFO_GRAPHICS) {
- switch (info.vi_depth/info.vi_planes) {
- case 1:
- vesa_adp->va_line_width = info.vi_width/8;
- break;
- case 2:
- vesa_adp->va_line_width = info.vi_width/4;
- break;
- case 4:
- vesa_adp->va_line_width = info.vi_width/2;
- break;
- case 8:
- default: /* shouldn't happen */
- vesa_adp->va_line_width = info.vi_width;
- break;
- case 15:
- case 16:
- vesa_adp->va_line_width = info.vi_width*2;
- break;
- case 24:
- case 32:
- vesa_adp->va_line_width = info.vi_width*4;
- break;
- }
- } else {
- vesa_adp->va_line_width = info.vi_width;
- len = vesa_bios_get_line_length();
- if (len > 0)
- vesa_adp->va_line_width = len;
- }
+ vesa_adp->va_line_width = vesa_get_line_width(&info);
vesa_adp->va_disp_start.x = 0;
vesa_adp->va_disp_start.y = 0;
#if VESA_DEBUG > 0
- printf("vesa_set_mode(): vi_width:%d, len:%d, line_width:%d\n",
- info.vi_width, len, vesa_adp->va_line_width);
+ printf("vesa_set_mode(): vi_width:%d, line_width:%d\n",
+ info.vi_width, vesa_adp->va_line_width);
#endif
bcopy(&info, &vesa_adp->va_info, sizeof(vesa_adp->va_info));
OpenPOWER on IntegriCloud