* Reading the EDID block for x86 machines
@ 2003-03-11 12:49 Antonino Daplas
2003-03-11 15:49 ` James Simmons
2003-03-12 12:10 ` Ville Syrjälä
0 siblings, 2 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-11 12:49 UTC (permalink / raw)
To: Linux Fbdev development list
[-- Attachment #1: Type: text/plain, Size: 2260 bytes --]
Hi,
I was wondering how to get the EDID block, and my first thought was to
implement DDC. But it is tricky to implement, so why not just get the
EDID using an int 0x10 BIOS call?
The EDID block can be read before the kernel goes into protected mode
(just a short assembly code in arch/i386/boot/video.S) and this can be
saved later on as struct edid_info during the kernel's setup routine.
One catch though is that that the "empty_zero_page" is becoming too
tight, so it will just use the same offset used by the EDD (BIOS
Enhanced Disk Drive). So EDID reading will be disabled if EDD is
enabled under the "Processor Type and Features" option.
Then, we can also make EDID parsing more powerful. I've added some code
in fbmon.c to parse the EDID block in more detail. It should be able to
parse almost everything (except the color point). Currently, it just
prints all the information it can find. However, I haven't tested if
parsing the Detailed Monitor information is correct since the EDID block
of the monitor I'm using is incomplete.
One of the goals is to build a video data structure that also includes a
database of video mode in fb_videomode format. This can be dynamically
created per device using the supported VESA modes, manufacturer's mode
and detailed timings mode information in the EDID block. The EDID block
also contain information on GTF capability. With these types of
displays, a video mode mode database may not be needed since all
possible supported modelines can be calculated.
The advantage of the above is that the driver can switch to different
modes without relying on user input (of course, user-entered modelines
are still preferred).
Anyway, I need help in testing the code (especially the Detailed
Information part). Just apply the attached patch, disable Enhanced Disk
Driver support (under Processor Type and Features), and enable EDID
support (under Graphics option). Finally, add the following line to the
fbdev driver that you use (anywhere, but a good place is the init code):
show_edid(get_EDID(pci_dev))
If using an x86 machine
show_edid(get_EDID(NULL))
should also work.
Reboot, check dmesg, and kindly post the ouput. Thanks.
Tony
PS: The patch is against linux-2.5.64 + fbdev.diff.gz
[-- Attachment #2: edid.diff --]
[-- Type: text/x-patch, Size: 21215 bytes --]
diff -Naur linux-2.5.64-fbdev/arch/i386/boot/compressed/misc.c linux-2.5.64/arch/i386/boot/compressed/misc.c
--- linux-2.5.64-fbdev/arch/i386/boot/compressed/misc.c 2003-02-16 00:47:53.000000000 +0000
+++ linux-2.5.64/arch/i386/boot/compressed/misc.c 2003-03-11 02:39:51.000000000 +0000
@@ -91,6 +91,7 @@
#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
#endif
#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+#define EDID_INFO (*(struct edid_info *)(real_mode+0x600))
extern char input_data[];
extern int input_len;
diff -Naur linux-2.5.64-fbdev/arch/i386/boot/video.S linux-2.5.64/arch/i386/boot/video.S
--- linux-2.5.64-fbdev/arch/i386/boot/video.S 2002-12-16 02:07:50.000000000 +0000
+++ linux-2.5.64/arch/i386/boot/video.S 2003-03-11 02:39:53.000000000 +0000
@@ -135,6 +135,7 @@
#endif /* CONFIG_VIDEO_RETAIN */
#endif /* CONFIG_VIDEO_SELECT */
call mode_params # Store mode parameters
+ call store_edid
popw %ds # Restore original DS
ret
@@ -1887,6 +1888,50 @@
popw %ax
ret
+#if defined(CONFIG_EDID)
+ store_edid:
+ pushw %es # just save all affected
+ pushw %ax # affected registers
+ pushw %bx
+ pushw %cx
+ pushw %dx
+ pushw %di
+
+ pushw %fs
+ popw %es
+
+ call store_edid_magic
+ call read_edid
+
+ popw %di # restore all registers
+ popw %dx
+ popw %cx
+ popw %bx
+ popw %ax
+ popw %es
+ ret
+
+store_edid_magic:
+ movb $0x13, %al
+ movw $128, %cx
+ movw $0x600, %di
+ cld
+ rep
+ stosb
+ ret
+read_edid:
+ movw $0x4f15, %ax
+ movw $0x01, %bx
+ movw $0x00, %cx
+ movw $0x01, %dx
+ movw $0x600, %di
+ int $0x10
+ ret
+#else
+store_edid:
+ ret
+#endif
+
# VIDEO_SELECT-only variables
mt_end: .word 0 # End of video mode table if built
edit_buf: .space 6 # Line editor buffer
diff -Naur linux-2.5.64-fbdev/arch/i386/kernel/setup.c linux-2.5.64/arch/i386/kernel/setup.c
--- linux-2.5.64-fbdev/arch/i386/kernel/setup.c 2003-03-11 02:30:07.000000000 +0000
+++ linux-2.5.64/arch/i386/kernel/setup.c 2003-03-11 02:52:09.000000000 +0000
@@ -80,6 +80,7 @@
*/
struct drive_info_struct { char dummy[32]; } drive_info;
struct screen_info screen_info;
+struct edid_info edid_info;
struct apm_info apm_info;
struct sys_desc_table_struct {
unsigned short length;
@@ -495,6 +496,23 @@
#define copy_edd() do {} while (0)
#endif
+#if defined(CONFIG_EDID)
+/*
+ * Since empty_zero_page has a limited size, we are going to use the
+ * same offset as EDD. Thus, copying of the EDID block will only be
+ * enabled if EDD is disabled.
+ */
+static inline void copy_edid(void)
+{
+ edid_info = EDID_INFO;
+}
+#else
+static inline void copy_edid(void)
+{
+ memset(&edid_info, 0x13, 128);
+}
+#endif
+
/*
* Do NOT EVER look at the BIOS memory size location.
* It does not work on many machines.
@@ -862,6 +880,7 @@
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
+ copy_edid();
apm_info.bios = APM_BIOS_INFO;
saved_videomode = VIDEO_MODE;
printk("Video mode to be used for restore is %lx\n", saved_videomode);
diff -Naur linux-2.5.64-fbdev/drivers/video/Kconfig linux-2.5.64/drivers/video/Kconfig
--- linux-2.5.64-fbdev/drivers/video/Kconfig 2003-03-11 02:30:31.000000000 +0000
+++ linux-2.5.64/drivers/video/Kconfig 2003-03-11 02:41:18.000000000 +0000
@@ -4,6 +4,10 @@
menu "Graphics support"
+config EDID
+ bool "Get EDID block from VBE"
+ depends on X86 && !EDD
+
config FB
bool "Support for frame buffer devices"
---help---
diff -Naur linux-2.5.64-fbdev/drivers/video/fbmon.c linux-2.5.64/drivers/video/fbmon.c
--- linux-2.5.64-fbdev/drivers/video/fbmon.c 2003-03-11 02:30:32.000000000 +0000
+++ linux-2.5.64/drivers/video/fbmon.c 2003-03-11 11:39:19.000000000 +0000
@@ -11,9 +11,6 @@
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
#ifdef CONFIG_ALL_PPC
#include <asm/prom.h>
#endif
@@ -41,11 +38,18 @@
#define EDID_STRUCT_VERSION 0x12
#define EDID_STRUCT_REVISION 0x13
+#define EDID_STRUCT_DISPLAY 0x14
+
#define DPMS_FLAGS 0x18
#define ESTABLISHED_TIMING_1 0x23
#define ESTABLISHED_TIMING_2 0x24
#define MANUFACTURERS_TIMINGS 0x25
+/* standard timings supported */
+#define STD_TIMING 8
+#define STD_TIMING_DESCRIPTION_SIZE 2
+#define STD_TIMING_DESCRIPTIONS_START 0x26
+
#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
#define DETAILED_TIMING_DESCRIPTION_SIZE 18
#define NO_DETAILED_TIMING_DESCRIPTIONS 4
@@ -124,11 +128,32 @@
#define HSYNC_POSITIVE (FLAGS & 4)
#define VSYNC_POSITIVE (FLAGS & 2)
+#define V_MIN_RATE block[ 5 ]
+#define V_MAX_RATE block[ 6 ]
+#define H_MIN_RATE block[ 7 ]
+#define H_MAX_RATE block[ 8 ]
+#define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT block[10]
+
+#define DPMS_ACTIVE_OFF (1 << 5)
+#define DPMS_SUSPEND (1 << 6)
+#define DPMS_STANDBY (1 << 7)
+
const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00
};
const unsigned char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
+static void copy_string(unsigned char *c, unsigned char *s)
+{
+ int i;
+ c = c + 5;
+ for (i = 0; (i < 13 && *c != 0x0A); i++)
+ *(s++) = *(c++);
+ *s = 0;
+ while (i-- && (*--s == 0x20)) *s = 0;
+}
+
static int edid_checksum(unsigned char *edid)
{
unsigned char i, csum = 0;
@@ -157,37 +182,144 @@
return 1;
}
-
-static char *edid_get_vendor(unsigned char *block)
+static void parse_vendor_block(unsigned char *block)
{
- static char sign[4];
- unsigned short h;
-
- h = COMBINE_HI_8LO(block[0], block[1]);
- sign[0] = ((h >> 10) & 0x1f) + 'A' - 1;
- sign[1] = ((h >> 5) & 0x1f) + 'A' - 1;
- sign[2] = (h & 0x1f) + 'A' - 1;
- sign[3] = 0;
+ unsigned char c[4];
- return sign;
+ c[0] = ((block[0] & 0x7c) >> 2) + '@';
+ c[1] = ((block[0] & 0x03) << 3) + ((block[1] & 0xe0) >> 5) + '@';
+ c[2] = (block[1] & 0x1f) + '@';
+ c[3] = 0;
+ printk(" Manufacturer: %s ", c);
+ printk("Model: %x ", block[2] + (block[3] << 8));
+ printk("Serial#: %u\n", block[4] + (block[5] << 8) +
+ (block[6] << 16) + (block[7] << 24));
+ printk(" Year: %u Week %u\n", block[9] + 1990, block[8]);
+}
+
+static void parse_dpms_capabilities(unsigned char flags)
+{
+ printk(" DPMS: Active %s, Suspend %s, Standby %s\n",
+ (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
+ (flags & DPMS_SUSPEND) ? "yes" : "no",
+ (flags & DPMS_STANDBY) ? "yes" : "no");
}
-
-static char *edid_get_monitor(unsigned char *block)
+
+static void parse_display_block(unsigned char *block)
{
- static char name[13];
- unsigned i;
- const unsigned char *ptr = block + DESCRIPTOR_DATA;
+ unsigned char c;
- for (i = 0; i < 13; i++, ptr++) {
- if (*ptr == 0xa) {
- name[i] = 0x00;
- return name;
+ c = (block[0] & 0x80) >> 7;
+ if (c)
+ printk(" Digital Display Input");
+ else {
+ printk(" Analog Display Input: Input Voltage - ");
+ switch ((block[0] & 0x60) >> 5) {
+ case 0:
+ printk("0.700V/0.300V");
+ break;
+ case 1:
+ printk("0.714V/0.286V");
+ break;
+ case 2:
+ printk("1.000V/0.400V");
+ break;
+ case 3:
+ printk("0.700V/0.000V");
+ break;
+ default:
+ printk("unknown");
}
- name[i] = *ptr;
+ printk("\n");
}
- return name;
-}
+ c = (block[0] & 0x10) >> 4;
+ if (c)
+ printk(" Configurable signal level\n");
+ printk(" Sync: ");
+ c = block[0] & 0x0f;
+ if (c & 0x08)
+ printk("Separate ");
+ if (c & 0x04)
+ printk("Composite ");
+ if (c & 0x02)
+ printk("Sync on Green ");
+ if (c & 0x01)
+ printk("Serration on ");
+ printk("\n");
+
+ printk(" Max H-size in cm: ");
+ c = block[1];
+ if (c)
+ printk("%d\n", c);
+ else
+ printk("variable\n");
+
+ printk(" Max V-size in cm: ");
+ c = block[2];
+ if (c)
+ printk("%d\n", c);
+ else
+ printk("variable\n");
+ c = block[3];
+ printk(" Gamma: ");
+ printk("%d.%d\n", (c + 100)/100, (c+100) % 100);
+
+ parse_dpms_capabilities(block[4]);
+
+ switch ((block[4] & 0x18) >> 3) {
+ case 0:
+ printk(" Monochrome/Grayscale\n");
+ break;
+ case 1:
+ printk(" RGB Color Display\n");
+ break;
+ case 2:
+ printk(" Non-RGB Multicolor Display\n");
+ break;
+ default:
+ printk(" Unknown\n");
+ break;
+ }
+ c = block[4] & 0x7;
+ if (c & 0x04)
+ printk(" Default color format is primary\n");
+ if (c & 0x02)
+ printk(" First DETAILED Timing is preferred\n");
+ if (c & 0x01)
+ printk(" Display is GTF capable\n");
+}
+
+static void parse_std_md_block(unsigned char *block)
+{
+ unsigned char c;
+
+ c = block[0];
+ if (c&0x80) printk(" 720x400@70Hz\n");
+ if (c&0x40) printk(" 720x400@88Hz\n");
+ if (c&0x20) printk(" 640x480@60Hz\n");
+ if (c&0x10) printk(" 640x480@67Hz\n");
+ if (c&0x08) printk(" 640x480@72Hz\n");
+ if (c&0x04) printk(" 640x480@75Hz\n");
+ if (c&0x02) printk(" 800x600@56Hz\n");
+ if (c&0x01) printk(" 800x600@60Hz\n");
+
+ c = block[1];
+ if (c&0x80) printk(" 800x600@72Hz\n");
+ if (c&0x40) printk(" 800x600@75Hz\n");
+ if (c&0x20) printk(" 832x624@75Hz\n");
+ if (c&0x10) printk(" 1024x768@87Hz (interlaced)\n");
+ if (c&0x08) printk(" 1024x768@60Hz\n");
+ if (c&0x04) printk(" 1024x768@70Hz\n");
+ if (c&0x02) printk(" 1024x768@75Hz\n");
+ if (c&0x01) printk(" 1280x1024@75Hz\n");
+
+ c = block[2];
+ if (c&0x80) printk(" 1152x870@75Hz\n");
+ printk(" Manufacturer's mask: %x\n",c&0x7F);
+}
+
+
static int edid_is_timing_block(unsigned char *block)
{
if ((block[0] == 0x00) && (block[1] == 0x00))
@@ -196,6 +328,30 @@
return 1;
}
+static int edid_is_serial_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xff))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfe))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfd))
+ return 1;
+ else
+ return 0;
+}
+
static int edid_is_monitor_block(unsigned char *block)
{
if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfc))
@@ -204,65 +360,219 @@
return 0;
}
-static void parse_timing_block(unsigned char *block,
- struct fb_var_screeninfo *var)
+static int edid_is_color_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfb))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_std_timings_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) && (block[3] == 0xfa))
+ return 1;
+ else
+ return 0;
+}
+
+static void parse_serial_block(unsigned char *block)
+{
+ unsigned char c[13];
+
+ copy_string(block, c);
+ printk(" Serial No: %s\n", c);
+}
+
+static void parse_ascii_block(unsigned char *block)
+{
+ unsigned char c[13];
+
+ copy_string(block, c);
+ printk(" %s\n", c);
+}
+
+static void parse_limits_block(unsigned char *block)
+{
+ printk(" HorizSync : %d-%d KHz\n", H_MIN_RATE, H_MAX_RATE);
+ printk(" VertRefresh: %d-%d Hz\n", V_MIN_RATE, V_MAX_RATE);
+ if (MAX_PIXEL_CLOCK != 10*0xff)
+ printk(" Max Pixelclock %d MHz\n", (int) MAX_PIXEL_CLOCK);
+}
+
+static void parse_monitor_block(unsigned char *block)
+{
+ unsigned char c[13];
+
+ copy_string(block, c);
+ printk(" Monitor Name: %s\n", c);
+}
+
+static void parse_color_block(unsigned char *block)
+{
+ printk(" Color Point: unimplemented\n");
+}
+
+static void parse_std_timing_block(unsigned char *block)
{
- var->xres = var->xres_virtual = H_ACTIVE;
- var->yres = var->yres_virtual = V_ACTIVE;
- var->height = var->width = -1;
- var->right_margin = H_SYNC_OFFSET;
- var->left_margin = (H_ACTIVE + H_BLANKING) -
- (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
- var->upper_margin = V_BLANKING - V_SYNC_OFFSET - V_SYNC_WIDTH;
- var->lower_margin = V_SYNC_OFFSET;
- var->hsync_len = H_SYNC_WIDTH;
- var->vsync_len = V_SYNC_WIDTH;
- var->pixclock = PIXEL_CLOCK;
- var->pixclock /= 1000;
- var->pixclock = KHZ2PICOS(var->pixclock);
-
- if (HSYNC_POSITIVE)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (VSYNC_POSITIVE)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ int xres, yres = 0, refresh, ratio, err = 1;
+
+ xres = (block[0] + 31) * 8;
+ ratio = (block[1] & 0xc0) >> 6;
+ switch (ratio) {
+ case 1:
+ yres = xres;
+ break;
+ case 2:
+ yres = (xres * 3)/4;
+ break;
+ case 3:
+ yres = (xres * 4)/5;
+ break;
+ case 4:
+ yres = (xres * 9)/16;
+ break;
+ }
+ refresh = (block[1] & 0x3f) + 60;
+ printk(" %dx%d@%dHz\n", xres, yres, refresh);
+ err = 0;
+}
+
+static void parse_detailed_timing_block(unsigned char *block)
+{
+ printk(" %d MHz ", PIXEL_CLOCK);
+ printk("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+ H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+ printk("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+ V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+ printk("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
+ (VSYNC_POSITIVE) ? "+" : "-");
}
int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
{
- unsigned char *block, *vendor, *monitor = NULL;
int i;
+ unsigned char *block;
+
+ if (edid == NULL || var == NULL)
+ return 1;
if (!(edid_checksum(edid)))
- return 0;
+ return 1;
if (!(edid_check_header(edid)))
- return 0;
-
- printk("EDID ver %d rev %d\n", (int) edid[EDID_STRUCT_VERSION],
- (int) edid[EDID_STRUCT_REVISION]);
-
- vendor = edid_get_vendor(edid + ID_MANUFACTURER_NAME);
+ return 1;
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
- if (edid_is_monitor_block(block)) {
- monitor = edid_get_monitor(block);
+ if (edid_is_timing_block(block)) {
+ var->xres = var->xres_virtual = H_ACTIVE;
+ var->yres = var->yres_virtual = V_ACTIVE;
+ var->height = var->width = -1;
+ var->right_margin = H_SYNC_OFFSET;
+ var->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+ V_SYNC_WIDTH;
+ var->lower_margin = V_SYNC_OFFSET;
+ var->hsync_len = H_SYNC_WIDTH;
+ var->vsync_len = V_SYNC_WIDTH;
+ var->pixclock = PIXEL_CLOCK;
+ var->pixclock /= 1000;
+ var->pixclock = KHZ2PICOS(var->pixclock);
+
+ if (HSYNC_POSITIVE)
+ var->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ var->sync |= FB_SYNC_VERT_HIGH_ACT;
+ return 0;
}
}
+ return 1;
+}
- printk("EDID: detected %s %s\n", vendor, monitor);
+int get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+{
+ int i;
+ unsigned char *block;
+
+ if (edid == NULL || specs == NULL)
+ return 1;
+
+ if (!(edid_checksum(edid)))
+ return 1;
+
+ if (!(edid_check_header(edid)))
+ return 1;
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
- if (edid_is_timing_block(block)) {
- parse_timing_block(block, var);
+ if (edid_is_limits_block(block)) {
+ specs->hfmin = H_MIN_RATE * 1000;
+ specs->hfmax = H_MAX_RATE * 1000;
+ specs->vfmin = V_MIN_RATE;
+ specs->vfmax = V_MAX_RATE;
+ specs->dclkmax = (MAX_PIXEL_CLOCK != 10*0xff) ?
+ MAX_PIXEL_CLOCK * 1000000 : 0;
+ specs->gtf = (GTF_SUPPORT) ? 1 : 0;
+ specs->dpms = edid[DPMS_FLAGS];
+ return 0;
}
}
return 1;
}
+void show_edid(unsigned char *edid)
+{
+ unsigned char *block;
+ int i;
+
+ if (edid == NULL)
+ return;
+
+ if (!(edid_checksum(edid)))
+ return;
+
+ if (!(edid_check_header(edid)))
+ return;
+ printk("========================================\n");
+ printk("Display Information (EDID)\n");
+ printk("========================================\n");
+ printk(" EDID Version %d.%d\n", (int) edid[EDID_STRUCT_VERSION],
+ (int) edid[EDID_STRUCT_REVISION]);
+
+ parse_vendor_block(edid + ID_MANUFACTURER_NAME);
+
+ printk(" Display Characteristics:\n");
+ parse_display_block(edid + EDID_STRUCT_DISPLAY);
+
+ printk(" Supported VESA Modes\n");
+ parse_std_md_block(edid + ESTABLISHED_TIMING_1);
+
+ printk(" Detailed Monitor Information\n");
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (edid_is_serial_block(block)) {
+ parse_serial_block(block);
+ } else if (edid_is_ascii_block(block)) {
+ parse_ascii_block(block);
+ } else if (edid_is_limits_block(block)) {
+ parse_limits_block(block);
+ } else if (edid_is_monitor_block(block)) {
+ parse_monitor_block(block);
+ } else if (edid_is_color_block(block)) {
+ parse_color_block(block);
+ } else if (edid_is_std_timings_block(block)) {
+ parse_std_timing_block(block);
+ } else if (edid_is_timing_block(block)) {
+ parse_detailed_timing_block(block);
+ }
+ }
+ printk("========================================\n");
+}
+
#ifdef CONFIG_PCI
char *get_EDID(struct pci_dev *pdev)
{
@@ -273,6 +583,8 @@
struct device_node *dp;
int i;
+ if (pdev == NULL)
+ return NULL;
dp = pci_device_to_OF_node(pdev);
while (dp != NULL) {
for (i = 0; propnames[i] != NULL; ++i) {
@@ -286,6 +598,9 @@
dp = dp->child;
}
return pedid;
+#elif defined (CONFIG_EDID)
+ return (edid_checksum((char *) &edid_info)) ?
+ (char *) &edid_info : NULL;
#else
return NULL;
#endif
@@ -576,6 +891,10 @@
timings.vfreq = vfmax;
fb_timings_vfreq(&timings);
}
+ if (timings.dclk > dclkmax) {
+ timings.dclk = dclkmax;
+ fb_timings_dclk(&timings);
+ }
break;
case FB_VSYNCTIMINGS: /* vrefresh driven */
timings.vfreq = val;
@@ -669,13 +988,17 @@
vfreq = hfreq/vtotal;
return (vfreq < vfmin || vfreq > vfmax ||
- hfreq < hfmin || hfreq > hfmax) ?
+ hfreq < hfmin || hfreq > hfmax ||
+ pixclock < dclkmin || pixclock > dclkmax) ?
-EINVAL : 0;
}
EXPORT_SYMBOL(parse_edid);
+EXPORT_SYMBOL(show_edid);
#ifdef CONFIG_PCI
EXPORT_SYMBOL(get_EDID);
#endif
+
+EXPORT_SYMBOL(get_monitor_limits);
EXPORT_SYMBOL(fb_get_mode);
EXPORT_SYMBOL(fb_validate_mode);
diff -Naur linux-2.5.64-fbdev/include/asm-i386/setup.h linux-2.5.64/include/asm-i386/setup.h
--- linux-2.5.64-fbdev/include/asm-i386/setup.h 2002-12-16 02:08:12.000000000 +0000
+++ linux-2.5.64/include/asm-i386/setup.h 2003-03-11 02:39:51.000000000 +0000
@@ -39,6 +39,8 @@
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
+/* Note: EDID_INFO uses the same offset as EDD_BUF */
+#define EDID_INFO (*(struct edid_info *) (PARAM+EDDBUF))
#define COMMAND_LINE ((char *) (PARAM+2048))
#define COMMAND_LINE_SIZE 256
diff -Naur linux-2.5.64-fbdev/include/linux/fb.h linux-2.5.64/include/linux/fb.h
--- linux-2.5.64-fbdev/include/linux/fb.h 2003-03-11 02:30:33.000000000 +0000
+++ linux-2.5.64/include/linux/fb.h 2003-03-11 11:39:05.000000000 +0000
@@ -486,6 +486,10 @@
extern int num_registered_fb;
/* drivers/video/fbmon.c */
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+
#define FB_MAXTIMINGS 0
#define FB_VSYNCTIMINGS 1
#define FB_HSYNCTIMINGS 2
@@ -499,6 +503,10 @@
struct fb_info *info);
extern int fb_validate_mode(struct fb_var_screeninfo *var,
struct fb_info *info);
+extern int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
+extern char *get_EDID(struct pci_dev *pdev);
+extern void show_edid(unsigned char *edid);
+extern int get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
/* drivers/video/fbcmap.c */
extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
diff -Naur linux-2.5.64-fbdev/include/linux/tty.h linux-2.5.64/include/linux/tty.h
--- linux-2.5.64-fbdev/include/linux/tty.h 2003-02-16 00:48:02.000000000 +0000
+++ linux-2.5.64/include/linux/tty.h 2003-03-11 02:39:50.000000000 +0000
@@ -93,7 +93,12 @@
/* 0x36 -- 0x3f reserved for future expansion */
};
+struct edid_info {
+ unsigned char data[128];
+};
+
extern struct screen_info screen_info;
+extern struct edid_info edid_info;
#define ORIG_X (screen_info.orig_x)
#define ORIG_Y (screen_info.orig_y)
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 12:49 Reading the EDID block for x86 machines Antonino Daplas
@ 2003-03-11 15:49 ` James Simmons
2003-03-11 20:07 ` Antonino Daplas
2003-03-11 21:33 ` Antonino Daplas
2003-03-12 12:10 ` Ville Syrjälä
1 sibling, 2 replies; 35+ messages in thread
From: James Simmons @ 2003-03-11 15:49 UTC (permalink / raw)
To: Antonino Daplas; +Cc: Linux Fbdev development list
> I was wondering how to get the EDID block, and my first thought was to
> implement DDC. But it is tricky to implement, so why not just get the
> EDID using an int 0x10 BIOS call?
DDC is tricky but the nice thing is it is very portable. We can do the
BIOS call but that limits it support to intel family of processors.
I still like to do the BIOS call still because it allows us quick supprot
of EDID on intel platforms.
> The EDID block can be read before the kernel goes into protected mode
> (just a short assembly code in arch/i386/boot/video.S) and this can be
> saved later on as struct edid_info during the kernel's setup routine.
>
> One catch though is that that the "empty_zero_page" is becoming too
> tight, so it will just use the same offset used by the EDD (BIOS
> Enhanced Disk Drive). So EDID reading will be disabled if EDD is
> enabled under the "Processor Type and Features" option.
I believe it is possible to read the block after we are in protect mode.
Look at vesafb and also the aty128 driver allows you to probe the BIOS
after we are in protect mode. I suggest we add a feild to struct
screeninfo to store the address to the edid pointer.
> One of the goals is to build a video data structure that also includes a
> database of video mode in fb_videomode format. This can be dynamically
> created per device using the supported VESA modes, manufacturer's mode
> and detailed timings mode information in the EDID block. The EDID block
> also contain information on GTF capability. With these types of
> displays, a video mode mode database may not be needed since all
> possible supported modelines can be calculated.
>
> The advantage of the above is that the driver can switch to different
> modes without relying on user input (of course, user-entered modelines
> are still preferred).
Wow. I'm glad we both think alike. I was thinking the same thing except my
hands are tied with working on the upper layer stuff.
> Anyway, I need help in testing the code (especially the Detailed
> Information part). Just apply the attached patch, disable Enhanced Disk
> Driver support (under Processor Type and Features), and enable EDID
> support (under Graphics option). Finally, add the following line to the
> fbdev driver that you use (anywhere, but a good place is the init code):
Diable Enhanced Disk support :-( I have a few suggestions. One we add a
pointer to struct screen_info that points to the edid information. We can
use phys_to_virt to translate that address into virtual memory. I can
create a patch today and store it in the BK tree.
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 15:49 ` James Simmons
@ 2003-03-11 20:07 ` Antonino Daplas
2003-03-11 21:33 ` Antonino Daplas
1 sibling, 0 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-11 20:07 UTC (permalink / raw)
To: James Simmons; +Cc: Linux Fbdev development list
On Tue, 2003-03-11 at 23:49, James Simmons wrote:
>
> > I was wondering how to get the EDID block, and my first thought was to
> > implement DDC. But it is tricky to implement, so why not just get the
> > EDID using an int 0x10 BIOS call?
>
> DDC is tricky but the nice thing is it is very portable. We can do the
> BIOS call but that limits it support to intel family of processors.
> I still like to do the BIOS call still because it allows us quick supprot
> of EDID on intel platforms.
>
That's true. The downside of course is that each driver/hardware has to
have it's own i2c support. So this may not be very lightweight on first
glance.
Also, the int10 method is simple enough to implement and should
theoretically support all x86 graphics card with a reasonably unbroken
BIOS. If ppc can get the EDID via OpenFirmware, the x86 can get it via
VBE int10. Theoretically, other archs that follow some kind of video
standard will have this kind of support also.
The downside of this method is it can only get the EDID block of the
video controller/s initialized at boot time.
> > The EDID block can be read before the kernel goes into protected mode
> > (just a short assembly code in arch/i386/boot/video.S) and this can be
> > saved later on as struct edid_info during the kernel's setup routine.
> >
> > One catch though is that that the "empty_zero_page" is becoming too
> > tight, so it will just use the same offset used by the EDD (BIOS
> > Enhanced Disk Drive). So EDID reading will be disabled if EDD is
> > enabled under the "Processor Type and Features" option.
>
> I believe it is possible to read the block after we are in protect mode.
> Look at vesafb and also the aty128 driver allows you to probe the BIOS
> after we are in protect mode. I suggest we add a feild to struct
> screeninfo to store the address to the edid pointer.
>
Not in this case. I believe there are very few int10 functions that
have a protected mode interface counterpart. One of the reasons vesafb
cannot switch modes is because of this.
Also the int10 function is a request for the VBE to do DDC, and place
the results to a buffer provided by the caller. It's possible, of
course, that the VBE has it's own copy of the EDID block, but I don't
know how to search for that.
> > One of the goals is to build a video data structure that also includes a
> > database of video mode in fb_videomode format. This can be dynamically
> > created per device using the supported VESA modes, manufacturer's mode
> > and detailed timings mode information in the EDID block. The EDID block
> > also contain information on GTF capability. With these types of
> > displays, a video mode mode database may not be needed since all
> > possible supported modelines can be calculated.
> >
> > The advantage of the above is that the driver can switch to different
> > modes without relying on user input (of course, user-entered modelines
> > are still preferred).
>
> Wow. I'm glad we both think alike. I was thinking the same thing except my
> hands are tied with working on the upper layer stuff.
>
> > Anyway, I need help in testing the code (especially the Detailed
> > Information part). Just apply the attached patch, disable Enhanced Disk
> > Driver support (under Processor Type and Features), and enable EDID
> > support (under Graphics option). Finally, add the following line to the
> > fbdev driver that you use (anywhere, but a good place is the init code):
>
> Diable Enhanced Disk support :-( I have a few suggestions. One we add a
> pointer to struct screen_info that points to the edid information. We can
> use phys_to_virt to translate that address into virtual memory. I can
> create a patch today and store it in the BK tree.
>
You can't. The EDID block was placed in the "empty_zero_page", the same
page shared by screen_info (and the EDD, apm, etc) at boottime . This
page will get overwritten later on so an explicit save of the contents
must be done. And because it's only a page (4086 bytes), there may not
be enough room to squeeze in 128 bytes. The EDD already requires a
buffer at offset 0x600, and I'm not sure how large is the block. Of
course, if someone tells me where to squeeze in 128 bytes without
overlapping the others, that is infinitely much better.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 15:49 ` James Simmons
2003-03-11 20:07 ` Antonino Daplas
@ 2003-03-11 21:33 ` Antonino Daplas
2003-03-11 21:47 ` Antonino Daplas
2003-03-11 22:05 ` Jon Smirl
1 sibling, 2 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-11 21:33 UTC (permalink / raw)
To: James Simmons; +Cc: Linux Fbdev development list
On Tue, 2003-03-11 at 23:49, James Simmons wrote:
> > Anyway, I need help in testing the code (especially the Detailed
> > Information part). Just apply the attached patch, disable Enhanced Disk
> > Driver support (under Processor Type and Features), and enable EDID
> > support (under Graphics option). Finally, add the following line to the
> > fbdev driver that you use (anywhere, but a good place is the init code):
>
> Diable Enhanced Disk support :-( I have a few suggestions. One we add a
> pointer to struct screen_info that points to the edid information. We can
> use phys_to_virt to translate that address into virtual memory. I can
> create a patch today and store it in the BK tree.
I think I found a chunk of around 500 bytes between INITRD and EDD, so
we can squeeze in EDID in there :-) Although I'm confident on this,
I'll feel better if someone who boots with initrd can test it.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 21:33 ` Antonino Daplas
@ 2003-03-11 21:47 ` Antonino Daplas
2003-03-11 22:05 ` Jon Smirl
1 sibling, 0 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-11 21:47 UTC (permalink / raw)
To: Antonino Daplas; +Cc: James Simmons, Linux Fbdev development list
On Wed, 2003-03-12 at 05:33, Antonino Daplas wrote:
> I think I found a chunk of around 500 bytes between INITRD and EDD, so
> we can squeeze in EDID in there :-) Although I'm confident on this,
> I'll feel better if someone who boots with initrd can test it.
Forgot the patch :-)
Tony
diff -Naur linux-2.5.64-fbdev/arch/i386/boot/compressed/misc.c linux-2.5.64/arch/i386/boot/compressed/misc.c
--- linux-2.5.64-fbdev/arch/i386/boot/compressed/misc.c 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/arch/i386/boot/compressed/misc.c 2003-03-11 21:07:24.000000000 +0000
@@ -91,7 +91,7 @@
#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
#endif
#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
-#define EDID_INFO (*(struct edid_info *)(real_mode+0x600))
+#define EDID_INFO (*(struct edid_info *)(real_mode+0x440))
extern char input_data[];
extern int input_len;
diff -Naur linux-2.5.64-fbdev/arch/i386/boot/video.S linux-2.5.64/arch/i386/boot/video.S
--- linux-2.5.64-fbdev/arch/i386/boot/video.S 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/arch/i386/boot/video.S 2003-03-11 21:07:24.000000000 +0000
@@ -1888,7 +1888,6 @@
popw %ax
ret
-#if defined(CONFIG_EDID)
store_edid:
pushw %es # just save all affected
pushw %ax # affected registers
@@ -1914,21 +1913,22 @@
store_edid_magic:
movb $0x13, %al
movw $128, %cx
- movw $0x600, %di
+ movw $0x440, %di
cld
rep
stosb
ret
+#if defined(CONFIG_EDID)
read_edid:
movw $0x4f15, %ax
movw $0x01, %bx
movw $0x00, %cx
movw $0x01, %dx
- movw $0x600, %di
+ movw $0x440, %di
int $0x10
ret
#else
-store_edid:
+read_edid:
ret
#endif
diff -Naur linux-2.5.64-fbdev/arch/i386/kernel/setup.c linux-2.5.64/arch/i386/kernel/setup.c
--- linux-2.5.64-fbdev/arch/i386/kernel/setup.c 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/arch/i386/kernel/setup.c 2003-03-11 21:07:24.000000000 +0000
@@ -496,23 +496,6 @@
#define copy_edd() do {} while (0)
#endif
-#if defined(CONFIG_EDID)
-/*
- * Since empty_zero_page has a limited size, we are going to use the
- * same offset as EDD. Thus, copying of the EDID block will only be
- * enabled if EDD is disabled.
- */
-static inline void copy_edid(void)
-{
- edid_info = EDID_INFO;
-}
-#else
-static inline void copy_edid(void)
-{
- memset(&edid_info, 0x13, 128);
-}
-#endif
-
/*
* Do NOT EVER look at the BIOS memory size location.
* It does not work on many machines.
@@ -880,7 +863,7 @@
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
- copy_edid();
+ edid_info = EDID_INFO;
apm_info.bios = APM_BIOS_INFO;
saved_videomode = VIDEO_MODE;
printk("Video mode to be used for restore is %lx\n", saved_videomode);
diff -Naur linux-2.5.64-fbdev/drivers/video/Kconfig linux-2.5.64/drivers/video/Kconfig
--- linux-2.5.64-fbdev/drivers/video/Kconfig 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/drivers/video/Kconfig 2003-03-11 21:07:47.000000000 +0000
@@ -6,7 +6,7 @@
config EDID
bool "Get EDID block from VBE"
- depends on X86 && !EDD
+ depends on X86
config FB
bool "Support for frame buffer devices"
diff -Naur linux-2.5.64-fbdev/include/asm-i386/setup.h linux-2.5.64/include/asm-i386/setup.h
--- linux-2.5.64-fbdev/include/asm-i386/setup.h 2003-03-11 21:19:34.000000000 +0000
+++ linux-2.5.64/include/asm-i386/setup.h 2003-03-11 21:07:25.000000000 +0000
@@ -37,10 +37,10 @@
#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
#define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+#define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
+#define EDID_SIZE 128
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
-/* Note: EDID_INFO uses the same offset as EDD_BUF */
-#define EDID_INFO (*(struct edid_info *) (PARAM+EDDBUF))
#define COMMAND_LINE ((char *) (PARAM+2048))
#define COMMAND_LINE_SIZE 256
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 21:33 ` Antonino Daplas
2003-03-11 21:47 ` Antonino Daplas
@ 2003-03-11 22:05 ` Jon Smirl
2003-03-11 22:33 ` Antonino Daplas
1 sibling, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-11 22:05 UTC (permalink / raw)
To: Antonino Daplas, James Simmons; +Cc: Linux Fbdev development list
If your in messing with the early boot sequence, why
don't you make the kernel initialize all of the video
cards in the system instead of only the primary one.
Alsom is it really better to continue messing with
these real mode X86 BIOS calls, or would it just be
better to try and extract the info from the card
vendors on how to do reset or get the DDC info? If we
had the info about the cards we could just ignore the
VBIOS and write this code into the protected mode FB
drivers where it belongs. This problem just keeps
recurring over and over on the non-X86 platforms; it's
stupid having to carry around an X86 emulator just to
run the VBIOS code.
Personally I'd like to be able to insmod a fb driver
for a secondary card. If the card needs it, it would
get initialized, read the DDC data, and come up in a
mode that makes sense.
I have a user space program that can reset secondary
cards using their VBIOS and emulating X86 real mode.
It can probably be easily modified to get the DDC info
and then IOCTL it into the fb driver. I'll post it if
you want.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 22:05 ` Jon Smirl
@ 2003-03-11 22:33 ` Antonino Daplas
2003-03-11 22:54 ` Jon Smirl
0 siblings, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-11 22:33 UTC (permalink / raw)
To: Jon Smirl; +Cc: James Simmons, Linux Fbdev development list
On Wed, 2003-03-12 at 06:05, Jon Smirl wrote:
> If your in messing with the early boot sequence, why
> don't you make the kernel initialize all of the video
> cards in the system instead of only the primary one.
Because I don't know how to :)? It basically just involves a far call
no, if we know where the VBIOS code actually starts?
Note that this will still be arch-specific. Separate non-primary card
initialization code for each arch is still necessary.
>
> Alsom is it really better to continue messing with
> these real mode X86 BIOS calls, or would it just be
> better to try and extract the info from the card
> vendors on how to do reset or get the DDC info? If we
Initialization can only be done in real mode. Once the kernel is in
protected mode, BIOS code cannot be run again (without extreme
difficulty), so resetting is out of the question.
Unfortunately, we don't have info from manufacturers, so we rely on some
standards, such as VESA, to do it transparently for us. Still VESA code
is mostly 16-bit.
> had the info about the cards we could just ignore the
> VBIOS and write this code into the protected mode FB
> drivers where it belongs. This problem just keeps
> recurring over and over on the non-X86 platforms; it's
> stupid having to carry around an X86 emulator just to
> run the VBIOS code.
Again, most BIOS code cannot run in protected mode, so we need to
emulate a real-mode environment for them. It's doubtful that Linus
would want that in his kernel. Our only chance to do this is during
early boot, or in user space.
>
> I have a user space program that can reset secondary
> cards using their VBIOS and emulating X86 real mode.
> It can probably be easily modified to get the DDC info
> and then IOCTL it into the fb driver. I'll post it if
> you want.
>
Yes, let me see what I can do.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 22:33 ` Antonino Daplas
@ 2003-03-11 22:54 ` Jon Smirl
2003-03-11 23:02 ` Antonino Daplas
0 siblings, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-11 22:54 UTC (permalink / raw)
To: Antonino Daplas; +Cc: James Simmons, Linux Fbdev development list
--- Antonino Daplas <adaplas@pol.net> wrote:
> On Wed, 2003-03-12 at 06:05, Jon Smirl wrote:
> > If your in messing with the early boot sequence,
> why
> > don't you make the kernel initialize all of the
> video
> > cards in the system instead of only the primary
> one.
>
> Because I don't know how to :)? It basically just
> involves a far call
> no, if we know where the VBIOS code actually starts?
It is more complicated. You need to call the PCI Bios
to find the video cards by their PCI class. There is
already code in the kernel that calls PCIBios.
arch/i386/pci/*
Then you need to one by one map their ROMs (via PCI
config registers) into C000:0 and call C000:3. But as
you swap out the other adapters you need to disable
their VGA emulation as there can only be on VGA device
per system. By default the VBIOS code will enable VGA
emulation on all of the adapters and they won't. You
also need to record the INT vectors and make sure they
get set back to the primary ones.
> Note that this will still be arch-specific.
> Separate non-primary card
> initialization code for each arch is still
> necessary.
Having X86 work is better than nothing.
> Again, most BIOS code cannot run in protected mode,
> so we need to
> emulate a real-mode environment for them. It's
> doubtful that Linus
> would want that in his kernel. Our only chance to
> do this is during
> early boot, or in user space.
The right answer is to get the vendors to give us the
info and then write protected mode versions of
reset/DDC into the fb drivers. Until they do this
everything else is a major hack.
It is not possible to enter VM86 mode from a device
driver. Only two choices are: early boot time or as a
user app. I have to send you the app directly, it is
too big for SF list.
Early boot time may be a better solution. A complete
implementation would reset all video adapters in the
system and record their DDC info for retrieval by the
FB drivers.
> Tony
>
>
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 22:54 ` Jon Smirl
@ 2003-03-11 23:02 ` Antonino Daplas
2003-03-11 23:42 ` Jon Smirl
2003-03-11 23:54 ` Jon Smirl
0 siblings, 2 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-11 23:02 UTC (permalink / raw)
To: Jon Smirl; +Cc: James Simmons, Linux Fbdev development list
On Wed, 2003-03-12 at 06:54, Jon Smirl wrote:
> --- Antonino Daplas <adaplas@pol.net> wrote:
> > On Wed, 2003-03-12 at 06:05, Jon Smirl wrote:
> > > If your in messing with the early boot sequence,
> > why
> > > don't you make the kernel initialize all of the
> > video
> > > cards in the system instead of only the primary
> > one.
> >
> > Because I don't know how to :)? It basically just
> > involves a far call
> > no, if we know where the VBIOS code actually starts?
>
> It is more complicated. You need to call the PCI Bios
> to find the video cards by their PCI class. There is
> already code in the kernel that calls PCIBios.
> arch/i386/pci/*
>
> Then you need to one by one map their ROMs (via PCI
> config registers) into C000:0 and call C000:3. But as
> you swap out the other adapters you need to disable
> their VGA emulation as there can only be on VGA device
> per system. By default the VBIOS code will enable VGA
> emulation on all of the adapters and they won't. You
> also need to record the INT vectors and make sure they
> get set back to the primary ones.
>
Yikes! No, it can't be done this way. During the early boot sequence,
the kernel is not yet decompressed and loaded, so all the services the
kernel provides are still unavailable. Unless you want to walk, detect,
enable, etc the PCI subsystem in pure 16-bit assembly...
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 23:02 ` Antonino Daplas
@ 2003-03-11 23:42 ` Jon Smirl
2003-03-12 17:38 ` Antonino Daplas
2003-03-11 23:54 ` Jon Smirl
1 sibling, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-11 23:42 UTC (permalink / raw)
To: Antonino Daplas; +Cc: James Simmons, Linux Fbdev development list
--- Antonino Daplas <adaplas@pol.net> wrote:
> Yikes! No, it can't be done this way. During the
> early boot sequence,
> the kernel is not yet decompressed and loaded, so
> all the services the
> kernel provides are still unavailable. Unless you
> want to walk, detect,
> enable, etc the PCI subsystem in pure 16-bit
> assembly...
You don't Linux to look at the PCI subsys you make
calls into the system BIOS to find the devices.
>
> Tony
>
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 23:02 ` Antonino Daplas
2003-03-11 23:42 ` Jon Smirl
@ 2003-03-11 23:54 ` Jon Smirl
1 sibling, 0 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-11 23:54 UTC (permalink / raw)
To: Antonino Daplas; +Cc: James Simmons, Linux Fbdev development list
Check out:
arch/i386/pci/pcbios.c
http://members.datafast.net.au/dft0802/specs/bios21.pdf
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 12:49 Reading the EDID block for x86 machines Antonino Daplas
2003-03-11 15:49 ` James Simmons
@ 2003-03-12 12:10 ` Ville Syrjälä
2003-03-12 17:38 ` Antonino Daplas
1 sibling, 1 reply; 35+ messages in thread
From: Ville Syrjälä @ 2003-03-12 12:10 UTC (permalink / raw)
To: Linux Fbdev development list
On Tue, Mar 11, 2003 at 08:49:46PM +0800, Antonino Daplas wrote:
> Hi,
>
> I was wondering how to get the EDID block, and my first thought was to
> implement DDC. But it is tricky to implement,
Forgive my ignorance but why is it tricky? As I understand it DDC1 only
involves reading from the monitor or does EDID require something more?
Reading stuff from my monitor via /dev/i2c works fine with matroxfb. I
just tried this and I can see my monitors model in the returned data but
parse-edid doesn't understand the data so I'm not sure it's the EDID.
Also the BIOS solution will fail when someone decides to change their
monitor. This got me thinking that with a real DDC solution would it be
feasible to have the driver re-read the EDID periodically and/or on mode
switch to prevent using bad modes?
--
Ville Syrjälä
syrjala@sci.fi
http://www.sci.fi/~syrjala/
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 12:10 ` Ville Syrjälä
@ 2003-03-12 17:38 ` Antonino Daplas
2003-03-12 18:47 ` Ville Syrjälä
0 siblings, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-12 17:38 UTC (permalink / raw)
To: Ville Syrjälä; +Cc: Linux Fbdev development list
On Wed, 2003-03-12 at 20:10, Ville Syrjälä wrote:
> On Tue, Mar 11, 2003 at 08:49:46PM +0800, Antonino Daplas wrote:
> > Hi,
> >
> > I was wondering how to get the EDID block, and my first thought was to
> > implement DDC. But it is tricky to implement,
>
> Forgive my ignorance but why is it tricky? As I understand it DDC1 only
> involves reading from the monitor or does EDID require something more?
It will require that each driver provide a means of getting the EDID
from the monitor, either via i2c or by some hardware specific means.
Matrox users are the fortunate few since the author implemented an i2c
backend.
>
> Reading stuff from my monitor via /dev/i2c works fine with matroxfb. I
> just tried this and I can see my monitors model in the returned data but
> parse-edid doesn't understand the data so I'm not sure it's the EDID.
>
> Also the BIOS solution will fail when someone decides to change their
> monitor. This got me thinking that with a real DDC solution would it be
> feasible to have the driver re-read the EDID periodically and/or on mode
> switch to prevent using bad modes?
>
That's okay. The get_EDID() function can get the EDID block several
ways.
1. via the driver if it has its own method of getting the EDID block
(1st choice)
2. via userland - EDID block (ie get-edid > edid.dmp) uploaded to
driver via ioctl (2nd choice)
3. through an arch-specific method -- VBE for x86, OF for PPC, etc
(last choice)
When a user changes monitors without rebooting, he/she can upload an
edid block appropriate for the display.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-11 23:42 ` Jon Smirl
@ 2003-03-12 17:38 ` Antonino Daplas
2003-03-12 18:16 ` Jon Smirl
0 siblings, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-12 17:38 UTC (permalink / raw)
To: Jon Smirl; +Cc: James Simmons, Linux Fbdev development list
On Wed, 2003-03-12 at 07:42, Jon Smirl wrote:
> --- Antonino Daplas <adaplas@pol.net> wrote:
> > Yikes! No, it can't be done this way. During the
> > early boot sequence,
> > the kernel is not yet decompressed and loaded, so
> > all the services the
> > kernel provides are still unavailable. Unless you
> > want to walk, detect,
> > enable, etc the PCI subsystem in pure 16-bit
> > assembly...
>
> You don't Linux to look at the PCI subsys you make
> calls into the system BIOS to find the devices.
That's not the only reason. The problem is in 16-bit mode, the code can
only access an address range up to only 1MB. PCI resources are located
above 16MB. So in order to copy the ROM, it might be necessary to
switch to 32-bit mode, copy the ROM, switch back to 16-bit mode, etc.
Unless I missed some imported BIOS calls or other methods to do this or
something similar in real-mode...
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 17:38 ` Antonino Daplas
@ 2003-03-12 18:16 ` Jon Smirl
2003-03-12 22:38 ` Antonino Daplas
0 siblings, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-12 18:16 UTC (permalink / raw)
To: Antonino Daplas; +Cc: James Simmons, Linux Fbdev development list
--- Antonino Daplas <adaplas@pol.net> wrote:
> Unless I missed some imported BIOS calls or other
> methods to do this or
> something similar in real-mode...
You missed something. The address of the VBIOS ROM can
be controlled by writing to the PCI config space. You
can make the ROM appear anywhere you want it to.
This happens even for the boot video device.
Somewhere very early in the boot the system BIOS
enabled the VBIOS ROM and copied it to C000. This is
the "shadow BIOS" option.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 17:38 ` Antonino Daplas
@ 2003-03-12 18:47 ` Ville Syrjälä
0 siblings, 0 replies; 35+ messages in thread
From: Ville Syrjälä @ 2003-03-12 18:47 UTC (permalink / raw)
To: Linux Fbdev development list
On Thu, Mar 13, 2003 at 01:38:19AM +0800, Antonino Daplas wrote:
> Matrox users are the fortunate few since the author implemented an i2c
> backend.
;)
> That's okay. The get_EDID() function can get the EDID block several
> ways.
>
> 1. via the driver if it has its own method of getting the EDID block
> (1st choice)
>
> 2. via userland - EDID block (ie get-edid > edid.dmp) uploaded to
> driver via ioctl (2nd choice)
>
> 3. through an arch-specific method -- VBE for x86, OF for PPC, etc
> (last choice)
>
> When a user changes monitors without rebooting, he/she can upload an
> edid block appropriate for the display.
Sounds good.
BTW are there public docs available about EDID & DDC? VESA doesn't like
poor open-source developers :(
--
Ville Syrjälä
syrjala@sci.fi
http://www.sci.fi/~syrjala/
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 18:16 ` Jon Smirl
@ 2003-03-12 22:38 ` Antonino Daplas
2003-03-12 23:36 ` Jon Smirl
` (2 more replies)
0 siblings, 3 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-12 22:38 UTC (permalink / raw)
To: Jon Smirl; +Cc: James Simmons, Linux Fbdev development list
On Thu, 2003-03-13 at 02:16, Jon Smirl wrote:
> --- Antonino Daplas <adaplas@pol.net> wrote:
> > Unless I missed some imported BIOS calls or other
> > methods to do this or
> > something similar in real-mode...
>
> You missed something. The address of the VBIOS ROM can
> be controlled by writing to the PCI config space. You
> can make the ROM appear anywhere you want it to.
>
> This happens even for the boot video device.
> Somewhere very early in the boot the system BIOS
> enabled the VBIOS ROM and copied it to C000. This is
> the "shadow BIOS" option.
>
So the steps needed would be:
1. scan for pci devices looking for the vga controller type
2. if 1 is found other than the primary, disable the current controller
3. write to PCI config space of secondary controller the address you
want it to appear (ie C000:0000). Can I use other addresses?
4. enable the controller
5. far call c000:0003
6. disable the controller
7. repeat
Besides the finer points, did I miss anything obvious?
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 22:38 ` Antonino Daplas
@ 2003-03-12 23:36 ` Jon Smirl
2003-03-12 23:47 ` Jon Smirl
2003-03-13 6:50 ` Geert Uytterhoeven
2 siblings, 0 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-12 23:36 UTC (permalink / raw)
To: Antonino Daplas; +Cc: fb-devel
--- Antonino Daplas <adaplas@pol.net> wrote:
> 1. scan for pci devices looking for the vga
> controller type
BIOS provide this via INT for find-pci-device-by-class
= 3
> 2. if 1 is found other than the primary, disable
> the current controller
Must disable VGA ports. ROM should already be
disabled. The reset program I sent you had the code
for doing the disable properly. You need to poke some
output ports.
No need to diable primary ROM it is not enabled. C000
is a copy of it.
> 3. write to PCI config space of secondary
> controller the address you
> want it to appear (ie C000:0000). Can I use other
> addresses?
The ROM will need to appear in an address space hole.
Look in your BIOS for where it is leaving a hole in
the 1MB. Map the VBIOS into the hole and then copy it
to C000. The PC has RAM mapped to C000 so you can't
map the ROM there.
I believe there is a standard place for this hole
probably E000 or A000 but I would need to reboot to
look.
> 4. enable the controller
>
> 5. far call c000:0003
This will set up INTs to work on secondary controller.
Now call INT to get EDID data and stick it somewhere
FB can find it.
> 6. disable the controller
>
> 7. repeat
8) Move the default one back and copy it's ROM back.
You will also need to fix up the INT 10 vectors to
point to the correct entry points for the primary ROM.
The reset code did this too.
>
> Besides the finer points, did I miss anything
> obvious?
>
> Tony
>
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 22:38 ` Antonino Daplas
2003-03-12 23:36 ` Jon Smirl
@ 2003-03-12 23:47 ` Jon Smirl
2003-03-13 6:50 ` Geert Uytterhoeven
2 siblings, 0 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-12 23:47 UTC (permalink / raw)
To: Antonino Daplas; +Cc: Linux Fbdev development list
The system BIOS may not map the ROM into the first 1MB
to copy it. It probably maps it to a high address and
then plays with the X86 memory management to map a
segment register to it. I am having vague
recollections about doing this long ago when I worked
at MS.
I seem to recall there is a real mode instruction that
will force a register like ES to point to a high mode
address. This is how an ancient EMM driver (remember
the AboveBoard and Lotus 123?) was implemented on a
386 without special hardware.
So you would map the ROM to a high address, map the
segment register to it, copy to C000, restore segment
register and jump to C000:3.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-12 22:38 ` Antonino Daplas
2003-03-12 23:36 ` Jon Smirl
2003-03-12 23:47 ` Jon Smirl
@ 2003-03-13 6:50 ` Geert Uytterhoeven
2003-03-13 15:42 ` Jon Smirl
2003-03-16 23:00 ` Antonino Daplas
2 siblings, 2 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2003-03-13 6:50 UTC (permalink / raw)
To: Antonino Daplas; +Cc: Jon Smirl, James Simmons, Linux Fbdev development list
On 13 Mar 2003, Antonino Daplas wrote:
> On Thu, 2003-03-13 at 02:16, Jon Smirl wrote:
> > --- Antonino Daplas <adaplas@pol.net> wrote:
> > > Unless I missed some imported BIOS calls or other
> > > methods to do this or
> > > something similar in real-mode...
> >
> > You missed something. The address of the VBIOS ROM can
> > be controlled by writing to the PCI config space. You
> > can make the ROM appear anywhere you want it to.
> >
> > This happens even for the boot video device.
> > Somewhere very early in the boot the system BIOS
> > enabled the VBIOS ROM and copied it to C000. This is
> > the "shadow BIOS" option.
> >
>
> So the steps needed would be:
>
> 1. scan for pci devices looking for the vga controller type
>
> 2. if 1 is found other than the primary, disable the current controller
>
> 3. write to PCI config space of secondary controller the address you
> want it to appear (ie C000:0000). Can I use other addresses?
>
> 4. enable the controller
>
> 5. far call c000:0003
>
> 6. disable the controller
>
> 7. repeat
>
> Besides the finer points, did I miss anything obvious?
Write a portable x86 emulator for non-ia32 platforms. Besides, you may even
want to use it on ia32 to make it less dependent on BIOS quirks (or for
machines without a PC BIOS).
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-13 6:50 ` Geert Uytterhoeven
@ 2003-03-13 15:42 ` Jon Smirl
2003-03-16 23:00 ` Antonino Daplas
1 sibling, 0 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-13 15:42 UTC (permalink / raw)
To: Geert Uytterhoeven, Antonino Daplas
Cc: Jon Smirl, James Simmons, Linux Fbdev development list
--- Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> Write a portable x86 emulator for non-ia32
> platforms. Besides, you may even
> want to use it on ia32 to make it less dependent on
> BIOS quirks (or for
> machines without a PC BIOS).
>
Already have one. It's only 300K of code that needs to
be ported/maintained just to call a hundred lines of
code in a ROM. It also has to run in user space and
can't be run in a device driver.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-13 6:50 ` Geert Uytterhoeven
2003-03-13 15:42 ` Jon Smirl
@ 2003-03-16 23:00 ` Antonino Daplas
2003-03-17 4:00 ` Jon Smirl
1 sibling, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-16 23:00 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: Jon Smirl, James Simmons, Linux Fbdev development list
On Thu, 2003-03-13 at 14:50, Geert Uytterhoeven wrote:
> On 13 Mar 2003, Antonino Daplas wrote:
> > On Thu, 2003-03-13 at 02:16, Jon Smirl wrote:
> > > --- Antonino Daplas <adaplas@pol.net> wrote:
> > > > Unless I missed some imported BIOS calls or other
> > > > methods to do this or
> > > > something similar in real-mode...
> > >
> > > You missed something. The address of the VBIOS ROM can
> > > be controlled by writing to the PCI config space. You
> > > can make the ROM appear anywhere you want it to.
> > >
> > > This happens even for the boot video device.
> > > Somewhere very early in the boot the system BIOS
> > > enabled the VBIOS ROM and copied it to C000. This is
> > > the "shadow BIOS" option.
> > >
> >
> > So the steps needed would be:
> >
> > 1. scan for pci devices looking for the vga controller type
> >
> > 2. if 1 is found other than the primary, disable the current controller
> >
> > 3. write to PCI config space of secondary controller the address you
> > want it to appear (ie C000:0000). Can I use other addresses?
I checked the PCI 2.2 specs, and it doesn't have this capability. It
will give you the address of the expansion ROM, but you still have to
manually copy the ROM and place it in any of the expansion areas.
Unfortunately for VGA controllers, it's always C000:0000.
There's a big problem in real mode:
1. COOO:0000 will be write protected by the BIOS upon initialization of
the first VGA controller. This will prevent copying of the succeeding
ROMS into that segment (unless you have a BIOS that supports read-write
shadow ROM's).
2. Real mode does not support paging (ie copy on write tricks will not
work)
> >
> > 4. enable the controller
> >
> > 5. far call c000:0003
> >
> > 6. disable the controller
> >
> > 7. repeat
> >
> > Besides the finer points, did I miss anything obvious?
>
> Write a portable x86 emulator for non-ia32 platforms. Besides, you may even
> want to use it on ia32 to make it less dependent on BIOS quirks (or for
> machines without a PC BIOS).
>
I read Kendall's thread, and it seems a userspace vm86/vm86emu daemon
might do the job.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-16 23:00 ` Antonino Daplas
@ 2003-03-17 4:00 ` Jon Smirl
2003-03-17 7:00 ` Antonino Daplas
0 siblings, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-17 4:00 UTC (permalink / raw)
To: Antonino Daplas, Geert Uytterhoeven
Cc: Jon Smirl, James Simmons, Linux Fbdev development list
--- Antonino Daplas <adaplas@pol.net> wrote:
> > > 3. write to PCI config space of secondary
> controller the address you
> > > want it to appear (ie C000:0000). Can I use
> other addresses?
>
> I checked the PCI 2.2 specs, and it doesn't have
> this capability. It
> will give you the address of the expansion ROM, but
> you still have to
> manually copy the ROM and place it in any of the
> expansion areas.
> Unfortunately for VGA controllers, it's always
> C000:0000.
You can very definitely move the ROMs to where ever
you want that isn't occupied by something else. I have
written code that does it. Also, the system BIOS must
be moving the ROMs in order to sort things out so that
they don't all appear on top of each other.
You don't even need to move the ROM. Just enable it
and read it's address form PCI space. The system BIOS
will have sorted the addresses out so that they don't
overlap. PCI config Region 6 is always the ROM see
include/linux/pci.h
> 1. COOO:0000 will be write protected by the BIOS
> upon initialization of
> the first VGA controller. This will prevent copying
> of the succeeding
> ROMS into that segment (unless you have a BIOS that
> supports read-write
> shadow ROM's).
How is C000 write protected? I'm pretty sure that the
ATI ROM are writing to C000.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 4:00 ` Jon Smirl
@ 2003-03-17 7:00 ` Antonino Daplas
2003-03-17 19:33 ` Jon Smirl
0 siblings, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-17 7:00 UTC (permalink / raw)
To: Jon Smirl; +Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
On Mon, 2003-03-17 at 12:00, Jon Smirl wrote:
> --- Antonino Daplas <adaplas@pol.net> wrote:
> > > > 3. write to PCI config space of secondary
> > controller the address you
> > > > want it to appear (ie C000:0000). Can I use
> > other addresses?
> >
> > I checked the PCI 2.2 specs, and it doesn't have
> > this capability. It
> > will give you the address of the expansion ROM, but
> > you still have to
> > manually copy the ROM and place it in any of the
> > expansion areas.
> > Unfortunately for VGA controllers, it's always
> > C000:0000.
>
> You can very definitely move the ROMs to where ever
> you want that isn't occupied by something else. I have
> written code that does it. Also, the system BIOS must
> be moving the ROMs in order to sort things out so that
> they don't all appear on top of each other.
>
You're talking about other device's expansion ROM's. VGA ROM's,
especially for the x86, are an exception and has to be always mapped at
c000:0000.
> You don't even need to move the ROM. Just enable it
> and read it's address form PCI space. The system BIOS
> will have sorted the addresses out so that they don't
> overlap. PCI config Region 6 is always the ROM see
> include/linux/pci.h
>
> > 1. COOO:0000 will be write protected by the BIOS
> > upon initialization of
> > the first VGA controller. This will prevent copying
> > of the succeeding
> > ROMS into that segment (unless you have a BIOS that
> > supports read-write
> > shadow ROM's).
>
> How is C000 write protected? I'm pretty sure that the
> ATI ROM are writing to C000.
It is. C000 is write enabled by the BIOS before init. Then it calls
the INIT procedure, which adjusts the initialization size before
returning. Afterwards, the BIOS write-protects the block equivalent to
the initialization size. Suceeding ROM's will then be mapped after this
block.
Remember, ROM's are supposed to be read-only, so even if they are
shadowed, the BIOS write protects it.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 7:00 ` Antonino Daplas
@ 2003-03-17 19:33 ` Jon Smirl
2003-03-17 21:38 ` Antonino Daplas
0 siblings, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-17 19:33 UTC (permalink / raw)
To: Antonino Daplas
Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
--- Antonino Daplas <adaplas@pol.net> wrote:
> You're talking about other device's expansion ROM's.
> VGA ROM's,
> especially for the x86, are an exception and has to
> be always mapped at
> c000:0000.
Reboot and add pci=rom (case sensitive) to your kernel
parameters. That will show you where the video ROMs
are really located.
My x86 PC's boot video ROM is located at dd000000 not
C00000. C00000 is only a copy of the ROM in RAM.
01:00.0 VGA compatible controller: ATI Technologies
Inc Radeon R250 If [Radeon 9
000] (rev 01) (prog-if 00 [VGA])
Subsystem: C.P. Technology Co. Ltd: Unknown
device 2039
Flags: stepping, 66Mhz, medium devsel, IRQ 5
Memory at d0000000 (32-bit, prefetchable)
[disabled] [size=64M]
I/O ports at c000 [disabled] [size=256]
Memory at de000000 (32-bit, non-prefetchable)
[disabled] [size=64K]
Expansion ROM at dd000000 [size=128K]
Capabilities: [58] AGP version 2.0
Capabilities: [50] Power Management version 2
The ROM on my other video card is located here:
00:0b.0 VGA compatible controller: ATI Technologies
Inc Rage 128 PD/PRO TMDS (pr
og-if 00 [VGA])
Subsystem: ATI Technologies Inc Rage 128 AIW
Flags: bus master, stepping, medium devsel,
latency 32, IRQ 10
Memory at d8000000 (32-bit, prefetchable)
[size=64M]
I/O ports at e400 [size=256]
Memory at df000000 (32-bit, non-prefetchable)
[size=16K]
Expansion ROM at 20060000 [size=128K]
Capabilities: [5c] Power Management version 2
> Remember, ROM's are supposed to be read-only, so
> even if they are
> shadowed, the BIOS write protects it.
How is this write protection being achieved? Is it
done via manipulation of the processor descriptor
tables; if so just undo it.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 19:33 ` Jon Smirl
@ 2003-03-17 21:38 ` Antonino Daplas
2003-03-17 22:02 ` Jon Smirl
0 siblings, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-17 21:38 UTC (permalink / raw)
To: Jon Smirl; +Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
On Tue, 2003-03-18 at 03:33, Jon Smirl wrote:
> --- Antonino Daplas <adaplas@pol.net> wrote:
> > You're talking about other device's expansion ROM's.
> > VGA ROM's,
> > especially for the x86, are an exception and has to
> > be always mapped at
> > c000:0000.
>
> Reboot and add pci=rom (case sensitive) to your kernel
> parameters. That will show you where the video ROMs
> are really located.
>
> My x86 PC's boot video ROM is located at dd000000 not
> C00000. C00000 is only a copy of the ROM in RAM.
That's not the problem. I can easily grab a copy of the ROM through
extended memory copy, but it cannot just run anywhere. The VBIOS code
(as with other BIOS code) must run in real mode (address below 1MB) and
VBIOS can only run when at C000:0000 (C000:0000 is in real-mode
segmented addressing, it is C0000 when translated to a linear address).
Check the definition of DEFAULT_V_BIOS in the code you sent me.
> How is this write protection being achieved? Is it
> done via manipulation of the processor descriptor
> tables; if so just undo it.
Possibly through some BIOS specific thing. Usually the BIOS places it
somewhere where it cannot be reached, even by the OS.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 21:38 ` Antonino Daplas
@ 2003-03-17 22:02 ` Jon Smirl
2003-03-17 22:29 ` Antonino Daplas
0 siblings, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-17 22:02 UTC (permalink / raw)
To: Antonino Daplas
Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
The VBIOS should be position independent code and it
will run at any 64K boundary. The PC bus spec simply
says the video BIOS defaults to C000, it is not a
requirement that it be located there. For example if
you look at the aty128fb driver's find ROM routine
your will notice that it is searching a broad address
space for the ROM.
I'm still not convinced that the memory at C000 is
really hardware write protected, I think it is just
RAM with a copy of the ROM in it. For example if I
turn off BIOS shadowing my system will not boot. When
debugging this I spent some time tracing into the ATI
ROM and I was pretty sure that they are dependent on
begin copied into RAM before begin run.
Do you have a DOS floppy around? Just boot into DOS,
start debug and see if you can change C000:0.
If C000:0 is hardware write protected, there is
nothing stopping the ROM from begin copied into 8000:0
or 9000:0 or whatever where there is guaranteed RAM.
We would just need to temporarily get the kernel out
of the way.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 22:02 ` Jon Smirl
@ 2003-03-17 22:29 ` Antonino Daplas
2003-03-17 23:41 ` Jon Smirl
2003-03-18 0:00 ` Jon Smirl
0 siblings, 2 replies; 35+ messages in thread
From: Antonino Daplas @ 2003-03-17 22:29 UTC (permalink / raw)
To: Jon Smirl; +Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
On Tue, 2003-03-18 at 06:02, Jon Smirl wrote:
> The VBIOS should be position independent code and it
> will run at any 64K boundary. The PC bus spec simply
> says the video BIOS defaults to C000, it is not a
> requirement that it be located there. For example if
> you look at the aty128fb driver's find ROM routine
> your will notice that it is searching a broad address
> space for the ROM.
>
> I'm still not convinced that the memory at C000 is
> really hardware write protected, I think it is just
> RAM with a copy of the ROM in it. For example if I
> turn off BIOS shadowing my system will not boot. When
> debugging this I spent some time tracing into the ATI
> ROM and I was pretty sure that they are dependent on
> begin copied into RAM before begin run.
The PC-compatible specific set of steps for the system POST code
when handling each expansion ROM are:
1. Map and enable the expansion ROM to an unoccupied area of the
memory address space.
2. Find the proper image in the ROM and copy it from ROM into the
compatibility area of RAM (typically 0C0000h to 0DFFFFhh) using the
number of bytes specified by Initialization Size.
3. Disable the Expansion ROM Base Address register.
4. Leave the RAM area writable and call the INIT function.
5. Use the byte at offset 02h (which may have been modified) to
determine how much memory is used at runtime.
Before system boot, the POST code must make the RAM area containing
expansion ROM code read-only.
POST code must handle VGA devices with expansion ROMs in a special
way. The VGA device's expansion BIOS must be copied to 0C0000h.
VGA devices can be identified by examining the Class Code field in
the device's Configuration Space.
-- pg. 210 PCI Local Bus Specification Revision 2.2 December 18, 1998
>
> Do you have a DOS floppy around? Just boot into DOS,
> start debug and see if you can change C000:0.
Yes, it's unchangeable.
Tony
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 22:29 ` Antonino Daplas
@ 2003-03-17 23:41 ` Jon Smirl
2003-03-18 9:06 ` Geert Uytterhoeven
2003-03-18 10:00 ` Antonino Daplas
2003-03-18 0:00 ` Jon Smirl
1 sibling, 2 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-17 23:41 UTC (permalink / raw)
To: Antonino Daplas
Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
The C000 must be a PCI restriction, it was not there
during ISA days.
Plan A: how is C000:0 protected; does the chipset
hardware do it or is it done via the descriptor
tables? Descriptor tables can be fixed but there is
probably no general solution to chipset protection.
On the other hand, we may be lucky and the PCI spec
has specified a standard way for enabling write
protect. Could there be a BIOS INT xx function for
this?
Plan B is to copy the ROM to something like 8000 or
9000. But the question there is, are VBIOS ROMs still
written to run position independent give the PCI C000
requirement?
Plan C is go into VM86 mode during early boot and
remap the memory.
Plan D would be to get enough info to write the code
in protected mode.
Are there more ways to do this?
I'll go poke around in google and see what I can come
up with. Let me know if you come up with anything.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 22:29 ` Antonino Daplas
2003-03-17 23:41 ` Jon Smirl
@ 2003-03-18 0:00 ` Jon Smirl
1 sibling, 0 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-18 0:00 UTC (permalink / raw)
To: Antonino Daplas
Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
This describes a BIOS INT for controlling the write
protect on the shadow RAM.
http://216.239.33.100/search?q=cache:ekBz42QrBngC:www.digital-logic.de/support/download/Treiber/misc/pcchip/c%26t/INT1F.TXT+shadow+BIOS+write+protect+int&hl=en&ie=UTF-8
Unsure if this is a standard BIOS feature.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by:Crypto Challenge is now open!
Get cracking and register here for some mind boggling fun and
the chance of winning an Apple iPod:
http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0031en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 23:41 ` Jon Smirl
@ 2003-03-18 9:06 ` Geert Uytterhoeven
2003-03-18 10:00 ` Antonino Daplas
1 sibling, 0 replies; 35+ messages in thread
From: Geert Uytterhoeven @ 2003-03-18 9:06 UTC (permalink / raw)
To: Jon Smirl; +Cc: Antonino Daplas, James Simmons, Linux Fbdev development list
On Mon, 17 Mar 2003, Jon Smirl wrote:
> Plan B is to copy the ROM to something like 8000 or
> 9000. But the question there is, are VBIOS ROMs still
> written to run position independent give the PCI C000
> requirement?
Probably. Some drivers are even compressed, since they don't fit in the ROM.
So they have to be decompressed elsewhere.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
-------------------------------------------------------
This SF.net email is sponsored by: Does your code think in ink?
You could win a Tablet PC. Get a free Tablet PC hat just for playing.
What are you waiting for?
http://ads.sourceforge.net/cgi-bin/redirect.pl?micr5043en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-17 23:41 ` Jon Smirl
2003-03-18 9:06 ` Geert Uytterhoeven
@ 2003-03-18 10:00 ` Antonino Daplas
2003-03-18 17:07 ` Jon Smirl
1 sibling, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-18 10:00 UTC (permalink / raw)
To: Jon Smirl; +Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
On Tue, 2003-03-18 at 07:41, Jon Smirl wrote:
> The C000 must be a PCI restriction, it was not there
> during ISA days.
It's not. It's IBM defining that VGA ROM should be at segment C000.
> Plan A: how is C000:0 protected; does the chipset
> hardware do it or is it done via the descriptor
> tables? Descriptor tables can be fixed but there is
> probably no general solution to chipset protection.
>
This is most probably chipset specific.
> On the other hand, we may be lucky and the PCI spec
> has specified a standard way for enabling write
> protect. Could there be a BIOS INT xx function for
> this?
>
If writable shadow ROM is to be supported, this has to be a specific
implementation by the BIOS vendor. The standard (well, at least by
Phoenix), does not define any BIOS service to do this.
> Plan B is to copy the ROM to something like 8000 or
> 9000. But the question there is, are VBIOS ROMs still
> written to run position independent give the PCI C000
> requirement?
It won't run. I already tried it.
>
> Plan C is go into VM86 mode during early boot and
> remap the memory.
That means go to protected mode first, then vm86, since vm86 can only be
entered in protected mode. Personally, this is too much work.
>
> Plan D would be to get enough info to write the code
> in protected mode.
That's one plan. Emulate real-mode x86 while in real-mode/protected
mode. However, x86emu requires a bunch of functions to parse and
execute the opcodes.
>
> Are there more ways to do this?
I've thought of 2 more things. The first is similar to Unreal Mode or
Voodoo mode. This mode was employed by DOS game developers before the
advent of protected mode DOS. They initialize the GDT to have a segment
limit of 4G, go to protected mode, then immediately switch back to real
mode. Upon return to real mode, they now have a segment:offset of 16:32
instead of 16:16. This is real mode with a 4 Gigabyte address limit.
The variant of what I'm thinking is to do the same thing, but instead of
adjusting the segment limit, adjust the base address of the GDT by an
offset of 1 MB. Copy the memory contents from 0 - 1 MB and place them
at 1 - 2 MB. Then, go to protected mode and back to real mode.
Hopefully, if this works, I can now have an address space that starts at
0x100000 (1MB) but would still appear to everyone as starting at 0
effectively bypassing BIOS protection of expansion segments.
I'm not sure if the above will work though, but should be easy enough to
experiment on. But if anyone knows that it won't work, let me know.
The other one is proposed by Kendall. Let's just have a userspace daemon
that does all BIOS requests.
The second is easy to implement since we already have the tools. Also,
you can literally request for BIOS services anytime. Plus, it can even
run on non-x86 using an emulator.
The first may not work at all, and even if it does, will run only once.
Also, it has to be coded in assembly and though I've done a lot of
assembly before, it takes too long to code. But it does have the
advantage of initializing adapters before the kernel loads, so we can
have multiple framebuffers loaded at boot time.
I'm still weighing which I should look first into. The second seems to
be more useful, the first is much more interesting.
What do you think?
Tony
-------------------------------------------------------
This SF.net email is sponsored by: Does your code think in ink?
You could win a Tablet PC. Get a free Tablet PC hat just for playing.
What are you waiting for?
http://ads.sourceforge.net/cgi-bin/redirect.pl?micr5043en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-18 10:00 ` Antonino Daplas
@ 2003-03-18 17:07 ` Jon Smirl
2003-03-19 5:15 ` Antonino Daplas
0 siblings, 1 reply; 35+ messages in thread
From: Jon Smirl @ 2003-03-18 17:07 UTC (permalink / raw)
To: Antonino Daplas
Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
Here is a description of how to control the shadow
write protect for a SIS chipset. It is done by writing
to PCI config space. There is a slim chance that this
is a standard procedure.
http://www.missl.cs.umd.edu/Projects/sebos/winint/index1.html
When you copied to 8000 ot 9000, did you copy the ROM
or the image at C000? I compared a dump of C000 to the
ROM and they don't match. ATI may have overlaid some
code during the init procedure.
So I guess we are stuck with a user space daemon.
Athlon-64 and IA64 will require the entire VM86
emulator. Last I checked the scitech emulator (ver8)
han't implemented all of the instructions needed to
run the ATI ROMs so it will need some work.
How do the Transmeta tools work? Could we turn the
ROMs into a C program and compile them again? Or use
something like use an emulator to capture the reset
sequence and then compile it for protected mode.
I tried a couple of reverse engineering tools on the
ROMs but I didn't get very far. I don't have access to
the ATI Radeon documentation so it is hard for me to
tell what is going on.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by: Does your code think in ink?
You could win a Tablet PC. Get a free Tablet PC hat just for playing.
What are you waiting for?
http://ads.sourceforge.net/cgi-bin/redirect.pl?micr5043en
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-18 17:07 ` Jon Smirl
@ 2003-03-19 5:15 ` Antonino Daplas
2003-03-19 6:07 ` Jon Smirl
0 siblings, 1 reply; 35+ messages in thread
From: Antonino Daplas @ 2003-03-19 5:15 UTC (permalink / raw)
To: Jon Smirl; +Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
[-- Attachment #1: Type: text/plain, Size: 3120 bytes --]
On Wed, 2003-03-19 at 01:07, Jon Smirl wrote:
> Here is a description of how to control the shadow
> write protect for a SIS chipset. It is done by writing
> to PCI config space. There is a slim chance that this
> is a standard procedure.
>
> http://www.missl.cs.umd.edu/Projects/sebos/winint/index1.html
>
I tried this part, and it doesn't work with the chipset I'm using.
Plus, PCI config space register 0x70 is device specific, only the first
64 bytes is defined generically.
> When you copied to 8000 ot 9000, did you copy the ROM
> or the image at C000? I compared a dump of C000 to the
> ROM and they don't match. ATI may have overlaid some
> code during the init procedure.
I copied the actual ROM (pointed to by Expansion ROM base address 0x30)
and placed it in 0xc000 and 0x8000. 0xc000 of course is write protected
by the BIOS, and it won't run in 0x8000.
Yes, the final BIOS image can be different from the initial image. Most
of the time, the initial image is larger, or needs decompression. Some
of the newer ROM's may even use the POST Memory Manager Specification
(kinda like a POST-specific malloc and family) during INIT, but this is
available only during POST, and memory allocated by the PMM is
unavailable after POST.
>
> So I guess we are stuck with a user space daemon.
> Athlon-64 and IA64 will require the entire VM86
> emulator. Last I checked the scitech emulator (ver8)
> han't implemented all of the instructions needed to
> run the ATI ROMs so it will need some work.
>
> How do the Transmeta tools work? Could we turn the
> ROMs into a C program and compile them again? Or use
> something like use an emulator to capture the reset
> sequence and then compile it for protected mode.
>
That's another problem. Some of the BIOS services used during INIT may
become unavailable after POST, so emulating ROM's can either be caused
by this or by an incomplete emulator.
> I tried a couple of reverse engineering tools on the
> ROMs but I didn't get very far. I don't have access to
> the ATI Radeon documentation so it is hard for me to
> tell what is going on.
>
Our best hope is for graphics manufacturer to drop VGA :-) which should
allow for relocatable ROM's and therefore initialization of multiple
graphics adapters. Second best hope is for manufacturer's to open up
the source for initializing devices without having to initialize the VGA
BIOS.
Anyway, attached is the code I'm using. It basically saves the video
state, disables all VGA controllers, disables VGA routing on PCI-PCI
bridges, searches for valid expansion ROM addresss on VGA class devices,
copies it into a scratch segment, verifies the ROM, copies the verified
ROM to 0xc000 and call 0xc000:0003. Of course, the "copies the verified
ROM to 0xc000" part will fail, so the "call 0xc000:0003" will just
warmboot your primary display again.
You have to place the file in linux/arch/i386/boot
Then in setup.S
add "include detect.S"
and
call init_video #preferably before or after 'call video'
I'll probably drop effort on this (for now) and concentrate on adding a
userspace daemon.
Tony
[-- Attachment #2: detect.S --]
[-- Type: text/plain, Size: 13180 bytes --]
/* detect.S
*
* Scanning and Initialization of all Display adapters (13-Mar-2003)
*
* Copyright (C) 2003 -- 2003 Antonino Daplas <adaplas@pol.net>
*
*/
#define SAVE_SEGMENT 0x8000
#define SCRATCH_SEGMENT 0x7000
#define VROM_SEGMENT 0xc000
#define PCI_SIGNATURE (('P'<<0)+('C'<<8)+('I'<<16)+(' '<< 24))
init_video:
pushw %ds # We use different segments
pushw %ds # FS contains original DS
popw %fs
pushw %cs # DS is equal to CS
popw %ds
pushw %cs # ES is equal to CS
popw %es
xorw %ax, %ax
movw %ax, %gs # GS is zero
call find_pci_bios # check for PCI BIOS directory service
cmpb $0, %ah # not available?
jne init_video_done
call save_video # save video state
call disable_bridge # disable VGA routing on bridges
call disable_all # disable all VGA class devices
call controller_init # warmboot all VGA class devices
call enable_bridge # reenable VGA routing on bridges
call enable_all # reenable VGA class devices
call restore_video # restore video state
init_video_done:
popw %ds
ret
#---------------------------------------------------------------
# -----------------------------------------------------------------------------
# disable_all: disables all VGA class devices
#-----------------------------------------------------------------------------
disable_all:
movw $0, %si
disable_all_loop:
call find_vga_class # find all VGA class devices
cmpb $0, %ah # no more devices?
jne disable_all_done
pushw %si
call disable_dev #disable
popw %si
incw %si
jmp disable_all_loop # do it again
disable_all_done:
ret
# -----------------------------------------------------------------------------
# enable_all: enables all VGA class devices
#-----------------------------------------------------------------------------
enable_all:
movw $0, %si
enable_all_loop:
call find_vga_class # find all VGA class devices
cmpb $0, %ah # no more devices?
jne enable_all_done
pushw %si
call enable_dev # and enable
popw %si
incw %si
jmp enable_all_loop # do it again
enable_all_done:
ret
# -----------------------------------------------------------------------------
# save_video: Saves current state of video controller
#
# USES: cursor, vid_state
#-----------------------------------------------------------------------------
save_video:
movw $0x3, %ax # save cursor position
int $0x10
movw %dx, cursor
pushw %es # disable and save current state
pushw %ds
popw %es
movw $0x1202, %ax
movb $0x35, %bl
leaw vid_state, %dx
int $0x10
popw %es
# save 64K at 0xc000:0000
pushw %ds
pushw %es
pushw $SAVE_SEGMENT # save a copy of original ROM
popw %es
pushw $VROM_SEGMENT
popw %ds
movw $0, %di
movw $0, %si
movw $0x4000, %cx
rep
movsl
popw %es
popw %ds
ret
# -----------------------------------------------------------------------------
# restore_video: Restores saved state of video controller
#
# USES: cursor, vid_state
#-----------------------------------------------------------------------------
restore_video:
pushw %ds # restore ROM
pushw %es
pushw $SAVE_SEGMENT
popw %ds
pushw $VROM_SEGMENT
popw %es
movw $0, %di
movw $0, %si
movw $0x4000, %cx
rep
movsl
popw %es
popw %ds
pushw %es # restore video state
pushw %ds
popw %es
movw $0x1203, %ax
movb $0x35, %bl
leaw vid_state, %dx
int $0x10
popw %es
movw cursor, %dx # restore cursor
movb $2, %ah
int $0x10
ret
# -----------------------------------------------------------------------------
# disable_bridge: disables VGA routing on bridges
#-----------------------------------------------------------------------------
disable_bridge:
movw $0, %si
movl $0x00060400, %ecx # find all PCI-PCI bridges
int $0x1a
cmp $0, %ah # no more devices?
jnz bridge_done
pushw %si
movw $0xb10a, %ax # read command word
movw $0x40, %di
int $0x1a
andl $(~(8 << 16)), %ecx # disable VGA routing
movw $0xb10d, %ax
movw $0x3c, %di
int $0x1a
popw %si
inc %si
jmp disable_bridge # do it again
bridge_done:
ret
# -----------------------------------------------------------------------------
# enable_bridge: enables VGA routing on bridges
#-----------------------------------------------------------------------------
enable_bridge:
movw $0, %si
movl $0x00060400, %ecx # find all PCI-PCI bridges
int $0x1a
cmp $0, %ah # no more devices?
jnz bridge1_done
pushw %si
movw $0xb10a, %ax # read command word
movw $0x3c, %di
int $0x1a
orl $(8 << 16), %ecx # enable VGA routing
movw $0xb10d, %ax
movw $0x3c, %di
int $0x1a
popw %si
inc %si
jmp enable_bridge # do it again
bridge1_done:
ret
# -----------------------------------------------------------------------------
# find_pci_bios: Check if PCI BIOS directory service is available on this
# machine
# RETURNS: AH = 0 - found : 1 - not found
#-----------------------------------------------------------------------------
find_pci_bios:
movw $0xb101, %ax # detect PCI BIOS directory service
int $0x1a
jc bios_no_good # CF set, service not present
cmpl $PCI_SIGNATURE, %edx # check for signature
jne bios_no_good
movb $0, %ah # return success
ret
bios_no_good:
movb $1, %ah # return fail
ret
# ----------------------------------------------------------------------------
# find_vga_class: Check for PCI devices of VGA base class (3)
# ENTRY: SI = index
# RETURNS: AH = 0 - found : 1 - not found
# BH = bus number
# BL = device (3-7) and function number (0-2)
#
#-----------------------------------------------------------------------------
find_vga_class:
movw $0xb103, %ax
movl $0x000030000, %ecx
int $0x1a
ret
# ----------------------------------------------------------------------------
# disable_dev: disables all controllers
# ENTRY: BX = bus, device and function number
#-----------------------------------------------------------------------------
disable_dev:
movw $0xb10a, %ax #read Expansion Rom
movw $0x30, %di
int $0x1a
movw $0xb10d, %ax
movw $0x30, %di
andw $(~1), %cx # disable expansion ROM
int $0x1a
movw $0xb109, %ax # read command word
movw $0x04, %di
int $0x1a
movw $0xb10c, %ax # disable command word
andw $(~3), %cx
movw $0x04, %di
int $0x1a
ret
# ----------------------------------------------------------------------------
# enable_dev: enables all controllers
# ENTRY: BX = bus, device and function number
#-----------------------------------------------------------------------------
enable_dev:
movw $0xb109, %ax #read command word
movw $0x04, %di
int $0x1a
movw $0xb10c, %ax # enable bit 0,1 of command word
orw $3, %cx
movw $0x04, %di
int $0x1a
ret
# ----------------------------------------------------------------------------
# controller_init: searches, verifies, copies and warmboots ROM
#-----------------------------------------------------------------------------
controller_init:
movw $0, %si
coninit_loop:
pushw %si # find all VGA class devices
movw $0xb103, %ax
movl $0x000030000, %ecx
int $0x1a
cmpb $0, %ah # no more devices?
jne coninit_done
movw %bx, dev_num # save bus, device and func number
call enable_dev # enable this device
call check_rom
cmpb $0, %ah # no ROM?
je has_no_rom
call copy_rom
cmpb $0, %ah # copy failed?
je has_no_rom
call verify_rom
cmpb $0, %ah # verify failed?
je has_no_rom
call post_rom
movw dev_num, %bx
call disable_dev # disable this device
has_no_rom:
popw %si
incw %si
jmp coninit_loop # do it again
coninit_done:
popw %si
ret
# ----------------------------------------------------------------------------
# check_rom: searches for valid ROM address
# USES: dev_num - current bus, device and function number
# RETURNS: AH - 0 none found, 1 found
#-----------------------------------------------------------------------------
check_rom:
movw $0xb10a, %ax # read Expansion Rom
movw dev_num, %bx # get current device
movw $0x30, %di
int $0x1a
cmpl $0, %ecx # no ROM, check BAR
je check_base_addr
pushl %ecx
movl %ecx, dev_addr # save ROM address
check_rom_cont:
movw $0xb109, %ax # read command word
movw dev_num, %bx
movw $0x04, %di
int $0x1a
movw $0xb10c, %ax # enabled bit 0,1 of command word
movw dev_num, %bx
movw $0x04, %di
orw $0x3, %cx
int $0x1a
popl %ecx # enable expansion ROM
movw $0xb10d, %ax
movw dev_num, %bx
movw $0x30, %di
orl $1, %ecx
int $0x1a
movb $1, %ah # return success
ret
check_base_addr:
movw $6, %cx # max 6 BAR's supported
movw $0x10, %di # first BAR
check_base_addr_loop:
pushw %di
pushw %cx
movw $0xb10a, %ax # read BAR's
movw dev_num, %bx
int $0x1a
testl $1, %ecx # check for IO
jnz do_have_rom # is IO? assume ROM
popw %cx
popw %di
addw $4, %di # check next BAR
decw %cx
jcxz no_rom_really
jmp check_base_addr_loop
do_have_rom:
andl $(~1), %ecx # assume BAR is ROM
movl %ecx, dev_addr # save BAR address
movw $0xb10d, %ax # write BAR to expansion ROM
movw dev_num, %bx
movw $0x30, %di
int $0x1a
popw %cx
popw %di
jmp check_rom_cont # continue with initialization
no_rom_really:
movb $0, %ah # no ROM at all, return fail
ret
# ----------------------------------------------------------------------------
# copy_rom: copy ROM to SCRATCH_SEGMENT using int 10h, function 0x87
# USES: dev_num - current bus, device and function number
# RETURNS: AH = 0 copy failed, AH = 1 copy successful
#-----------------------------------------------------------------------------
copy_rom:
movl dev_addr, %eax # write ROM addr to GDT
movw %ax, gdt_src1
shrl $16, %eax
movb %al, gdt_src2
movb %ah, gdt_src3
pushw %es
pushw %ds
popw %es
movw $4, %cx # zeroes first 16 bytes of gdt
movl $0, %eax
leaw gdt_p, %di
cld
rep
stosl
movw $4, %cx # zeroes last 16 bytes of gdt
leaw gdt_dummy, %di
cld
rep
stosl
leaw gdt_p, %si # copy extended memory
movw $0x8000, %cx
movw $0x8700, %ax
int $0x15
popw %es
jc extcopy_fail
movw $0xb10a, %ax # read Expansion Rom
movw dev_num, %bx
movw $0x30, %di
int $0x1a
movw $0xb10d, %ax # disable expansion ROM after copy
movw dev_num, %bx
movw $0x30, %di
andw $(~1), %cx
int $0x1a
movb $1, %ah # return success
ret
extcopy_fail:
movb $0, %ah # return failed
ret
# ----------------------------------------------------------------------------
# verify_rom: verifies ROM for signature bytes and size <= 64K
# USES: dev_num - current bus, device and function number
# RETURNS: AH = 0 verify failed, AH = size of ROM in 512-byte blocks
#-----------------------------------------------------------------------------
verify_rom:
pushw %es
movw $SCRATCH_SEGMENT, %ax
movw %ax, %es
movw %es:(0), %ax
cmpw $0xaa55, %ax # check for rom sig bytes
jne corrupt_rom
movb %es:(2), %ah # put ROM size in AH
cmpb $128, %ah # check if init size > 64K
jns corrupt_rom
popw %es
ret
corrupt_rom:
popw %es
movb $0, %ah # return fail
ret
# ----------------------------------------------------------------------------
# post_rom: warmboots ROM
# USES: dev_num - current bus, device and function number
#-----------------------------------------------------------------------------
# FIXME: currently does not work as C000:0000 is write
# protected by BIOS
post_rom:
xorl %ecx, %ecx
movb %ah, %cl # AH has number of 512 bytes to copy
shll $7, %ecx # number of dwords to copy
pushw %ds
pushw %es
pushw $SCRATCH_SEGMENT # copy from scratch segment ...
popw %ds
pushw $VROM_SEGMENT # to 0xC000 - doesn't work as
popw %es # 0xC000 is write-protected
movw $0, %di
movw $0, %si
cld
rep
movsb
popw %es
popw %ds
movw dev_num, %ax # putting device number to ax may help
lcall $VROM_SEGMENT, $0x0003 # warmboot :)
ret
#------------------------------------------------------------
dev_addr: .long 0 # current ROM address
dev_num: .word 0 # current bus, device, func number
cursor: .word 0 # cursor state
vid_state: .fill 128, 0 # video state
# gdt table used for int 10h ah=87 (copy extended memory)
gdt_p: .long 0,0,0,0 # fill with zeroes
gdt_src_seg: .word 0xffff # segment limit
gdt_src1: .word 0 # src address (0-15)
gdt_src2: .byte 0 # src address (16-23)
gdt_src_access: .byte 0x93 # access
gdt_src_x: .byte 0 # extended access/segment limit
gdt_src3: .byte 0 # src address (24-31)
gdt_dst_seg: .word 0xffff
gdt_dst1: .word 0x0000
gdt_dst2: .byte 0x07
gdt_dst_access: .byte 0x93
gdt_dst_x: .byte 0
gdt_dst3: .byte 0
gdt_dummy: .long 0,0,0,0
#------------------------------------------------------------
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: Reading the EDID block for x86 machines
2003-03-19 5:15 ` Antonino Daplas
@ 2003-03-19 6:07 ` Jon Smirl
0 siblings, 0 replies; 35+ messages in thread
From: Jon Smirl @ 2003-03-19 6:07 UTC (permalink / raw)
To: Antonino Daplas
Cc: Geert Uytterhoeven, James Simmons, Linux Fbdev development list
Thanks for making an extreme effort at trying to get
this work. I wish the video card vendors paid
attention to the list so that they would have an idea
of what lengths their customers will take in order to
use their products. It's times like this that made me
abandon the Microsoft world and become a Linux
convert.
Does anyone have a good ATI contact? Maybe they'll at
least see the light and provide us with the info
needed to avoid a user mode solution for their
hardware.
I agree that the user mode solution is the easiest
path from here. V0.6 of the scitech x86emu works to
reset my radeon with a minor tweak - INT 15 needs to
be implement to simply return 1.
I have had no success in getting V0.8 to work but I
didn't try very hard given that V0.6 is working for
me. The emulator hangs on both versions.
Just to report on what I'm doing to keep busy, I have
a full DRI accelerated Mesa running standalone on most
Radeons100-300. The accelerated Mesa uses both DRM and
FB drivers. I'm in the process of modifying embedded
QT (which contains a window manager) to run on it as
an OpenGL application. The goal is to see if OpenGL
would make an effective alternative platform to X.
There is a lot of code to write before this all works,
contributions welcome.
=====
Jon Smirl
jonsmirl@yahoo.com
__________________________________________________
Do you Yahoo!?
Yahoo! Platinum - Watch CBS' NCAA March Madness, live on your desktop!
http://platinum.yahoo.com
-------------------------------------------------------
This SF.net email is sponsored by: Does your code think in ink?
You could win a Tablet PC. Get a free Tablet PC hat just for playing.
What are you waiting for?
http://ads.sourceforge.net/cgi-bin/redirect.pl?micr5043en
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2003-03-19 6:07 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-03-11 12:49 Reading the EDID block for x86 machines Antonino Daplas
2003-03-11 15:49 ` James Simmons
2003-03-11 20:07 ` Antonino Daplas
2003-03-11 21:33 ` Antonino Daplas
2003-03-11 21:47 ` Antonino Daplas
2003-03-11 22:05 ` Jon Smirl
2003-03-11 22:33 ` Antonino Daplas
2003-03-11 22:54 ` Jon Smirl
2003-03-11 23:02 ` Antonino Daplas
2003-03-11 23:42 ` Jon Smirl
2003-03-12 17:38 ` Antonino Daplas
2003-03-12 18:16 ` Jon Smirl
2003-03-12 22:38 ` Antonino Daplas
2003-03-12 23:36 ` Jon Smirl
2003-03-12 23:47 ` Jon Smirl
2003-03-13 6:50 ` Geert Uytterhoeven
2003-03-13 15:42 ` Jon Smirl
2003-03-16 23:00 ` Antonino Daplas
2003-03-17 4:00 ` Jon Smirl
2003-03-17 7:00 ` Antonino Daplas
2003-03-17 19:33 ` Jon Smirl
2003-03-17 21:38 ` Antonino Daplas
2003-03-17 22:02 ` Jon Smirl
2003-03-17 22:29 ` Antonino Daplas
2003-03-17 23:41 ` Jon Smirl
2003-03-18 9:06 ` Geert Uytterhoeven
2003-03-18 10:00 ` Antonino Daplas
2003-03-18 17:07 ` Jon Smirl
2003-03-19 5:15 ` Antonino Daplas
2003-03-19 6:07 ` Jon Smirl
2003-03-18 0:00 ` Jon Smirl
2003-03-11 23:54 ` Jon Smirl
2003-03-12 12:10 ` Ville Syrjälä
2003-03-12 17:38 ` Antonino Daplas
2003-03-12 18:47 ` Ville Syrjälä
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).