summaryrefslogtreecommitdiffstats
path: root/tools/ddcprobe
diff options
context:
space:
mode:
Diffstat (limited to 'tools/ddcprobe')
-rw-r--r--tools/ddcprobe/Makefile27
-rw-r--r--tools/ddcprobe/ddcxinfos.c44
-rw-r--r--tools/ddcprobe/vbe.c353
-rw-r--r--tools/ddcprobe/vbe.h76
4 files changed, 141 insertions, 359 deletions
diff --git a/tools/ddcprobe/Makefile b/tools/ddcprobe/Makefile
index bcbf1464d..83f3e3df5 100644
--- a/tools/ddcprobe/Makefile
+++ b/tools/ddcprobe/Makefile
@@ -6,24 +6,17 @@ ARCH := $(patsubst i%86,i386,$(shell uname -m))
ARCH := $(patsubst sparc%,sparc,$(ARCH))
ifeq (i386,$(ARCH))
-
-ddcxinfos: lrmi.o vesamode.o vbe.o ddcxinfos.o
-
-libvbe.a: lrmi.o vesamode.o vbe.o
- $(AR) cru $@ $^
-
-#install: $(DESTDIR)/usr/include/vbe.h $(DESTDIR)/usr/lib/libvbe.a
-
-$(DESTDIR)/usr/include/vbe.h:
- install -m 644 vbe.h $(DESTDIR)/usr/include/vbe.h
-
-$(DESTDIR)/usr/lib/libvbe.a:
- install -m 644 libvbe.a $(DESTDIR)/usr/lib/libvbe.a
-
-else
-ddcxinfos: not_handled.c
- gcc -o $@ $<
+OBJS = ddcxinfos.o vesamode.o vbe.o lrmi.o
+endif
+ifeq (x86_64,$(ARCH))
+OBJS = ddcxinfos.o vesamode.o vbe.o
endif
+ifeq (,$(OBJS))
+OBJS = not_handled.o
+endif
+
+ddcxinfos: $(OBJS)
+ $(CC) -o $@ $(OBJS) $(CFLAGS) $(LDFLAGS)
clean:
$(RM) $(TARGETS) *.o core
diff --git a/tools/ddcprobe/ddcxinfos.c b/tools/ddcprobe/ddcxinfos.c
index 22ed653b8..c13d803c4 100644
--- a/tools/ddcprobe/ddcxinfos.c
+++ b/tools/ddcprobe/ddcxinfos.c
@@ -2,28 +2,55 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
#include "vbe.h"
#include "vesamode.h"
#ident "$Id$"
#define SQR(x) ((x) * (x))
-int main(int argc, char **argv)
+int main(void)
{
int i, j;
- u_int16_t *mode_list;
+ u_int16_t *mode_list, *mode_list_end;
unsigned char hmin, hmax, vmin, vmax;
struct vbe_info *vbe_info;
struct vbe_edid1_info *edid;
struct vbe_modeline *modelines;
-
+#if KERNEL_BOOT_INFO
+ u_int32_t page_size;
+ int dev_mem_fd;
+ char *mem;
+#endif
if ((vbe_info = vbe_get_vbe_info()) == NULL) return 1;
-
printf("%dKB of video ram\n", vbe_info->memory_size * 64);
+#if KERNEL_BOOT_INFO
+ /* Open /dev/mem for extra information from VGA BIOS. */
+ if ((dev_mem_fd = open("/dev/mem", O_RDONLY)) < 0) {
+ perror("open /dev/mem");
+ return 1;
+ }
+ page_size = getpagesize();
+ mem = malloc(page_size);
+ if (lseek(dev_mem_fd, vbe_info->mode_list.base, SEEK_SET) != vbe_info->mode_list.base)
+ return 1;
+ if (read(dev_mem_fd, mem, page_size) != page_size)
+ return 1;
+ mode_list = (u_int16_t *)mem;
+ mode_list_end = (u_int16_t *)(mem + page_size);
+#endif
+#if defined(__i386__)
+ mode_list = (u_int16_t *)vbe_info->mode_list.ptr;
+ mode_list_end = (u_int16_t *)-2; /* this will always succeed */
+#endif
+
/* List supported standard modes. */
- for (mode_list = vbe_info->mode_list.list; *mode_list != 0xffff; mode_list++)
+ while (mode_list < mode_list_end && *mode_list != 0xffff) {
for (i = 0; known_vesa_modes[i].x; i++)
if (known_vesa_modes[i].number == *mode_list)
printf("%d %d %d\n",
@@ -31,8 +58,15 @@ int main(int argc, char **argv)
known_vesa_modes[i].x,
known_vesa_modes[i].y
);
+ mode_list++;
+ }
printf("\n");
+#if KERNEL_BOOT_INFO
+ free(mem);
+ close(dev_mem_fd);
+#endif
+
if ((edid = vbe_get_edid_info()) == NULL) return 0;
if (edid->version == 255 && edid->revision == 255) return 0;
diff --git a/tools/ddcprobe/vbe.c b/tools/ddcprobe/vbe.c
index a67e56d0b..7a5633c7e 100644
--- a/tools/ddcprobe/vbe.c
+++ b/tools/ddcprobe/vbe.c
@@ -8,69 +8,23 @@
#include <assert.h>
#include <limits.h>
#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#if defined(__i386__)
#include "lrmi.h"
+#endif
#include "vesamode.h"
#include "vbe.h"
-#ident "$Id$"
-/* Return information about a particular video mode. */
-struct vbe_mode_info *vbe_get_mode_info(u_int16_t mode)
+/* Get VBE info. */
+static void normalize_addr(vbe_addr_t *paddr)
{
- struct LRMI_regs regs;
- char *mem;
- struct vbe_mode_info *ret = NULL;
-
- /* Initialize LRMI. */
- if(LRMI_init() == 0) {
- return NULL;
- }
-
- /* Allocate a chunk of memory. */
- mem = LRMI_alloc_real(sizeof(struct vbe_mode_info));
- if(mem == NULL) {
- return NULL;
- }
- memset(mem, 0, sizeof(struct vbe_mode_info));
-
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f01;
- regs.ecx = mode;
- regs.es = ((u_int32_t)mem) >> 4;
- regs.edi = ((u_int32_t)mem) & 0x0f;
-
- /* Do it. */
- iopl(3);
- ioperm(0, 0x400, 1);
-
- if(LRMI_int(0x10, &regs) == 0) {
- LRMI_free_real(mem);
- return NULL;
- }
-
- /* Check for successful return. */
- if((regs.eax & 0xffff) != 0x004f) {
- LRMI_free_real(mem);
- return NULL;
- }
-
- /* Get memory for return. */
- ret = malloc(sizeof(struct vbe_mode_info));
- if(ret == NULL) {
- LRMI_free_real(mem);
- return NULL;
- }
-
- /* Copy the buffer for return. */
- memcpy(ret, mem, sizeof(struct vbe_mode_info));
-
- /* Clean up and return. */
- LRMI_free_real(mem);
- return ret;
+ paddr->base = (paddr->addr.seg << 4) + paddr->addr.ofs;
}
-/* Get VBE info. */
struct vbe_info *vbe_get_vbe_info()
{
+#if defined(__i386__)
struct LRMI_regs regs;
unsigned char *mem;
struct vbe_info *ret = NULL;
@@ -119,101 +73,93 @@ struct vbe_info *vbe_get_vbe_info()
memcpy(ret, mem, sizeof(struct vbe_info));
/* Set up pointers to usable memory. */
- ret->mode_list.list = (u_int16_t*) ((ret->mode_list.addr.seg << 4) +
- (ret->mode_list.addr.ofs));
- ret->oem_name.string = (char*) ((ret->oem_name.addr.seg << 4) +
- (ret->oem_name.addr.ofs));
+ ret->mode_list.ptr = (u_int16_t*) ((ret->mode_list.addr.seg << 4) +
+ (ret->mode_list.addr.ofs));
+ ret->oem_name.ptr = (char*) ((ret->oem_name.addr.seg << 4) +
+ (ret->oem_name.addr.ofs));
/* Snip, snip. */
- mem = strdup(ret->oem_name.string); /* leak */
+ mem = strdup(ret->oem_name.ptr); /* leak */
while(((i = strlen(mem)) > 0) && isspace(mem[i - 1])) {
mem[i - 1] = '\0';
}
- ret->oem_name.string = mem;
+ ret->oem_name.ptr = mem;
/* Set up pointers for VESA 3.0+ strings. */
if(ret->version[1] >= 3) {
/* Vendor name. */
- ret->vendor_name.string = (char*)
+ ret->vendor_name.ptr = (char*)
((ret->vendor_name.addr.seg << 4)
+ (ret->vendor_name.addr.ofs));
- mem = strdup(ret->vendor_name.string); /* leak */
+ mem = strdup(ret->vendor_name.ptr); /* leak */
while(((i = strlen(mem)) > 0) && isspace(mem[i - 1])) {
mem[i - 1] = '\0';
}
- ret->vendor_name.string = mem;
+ ret->vendor_name.ptr = mem;
/* Product name. */
- ret->product_name.string = (char*)
+ ret->product_name.ptr = (char*)
((ret->product_name.addr.seg << 4)
+ (ret->product_name.addr.ofs));
- mem = strdup(ret->product_name.string); /* leak */
+ mem = strdup(ret->product_name.ptr); /* leak */
while(((i = strlen(mem)) > 0) && isspace(mem[i - 1])) {
mem[i - 1] = '\0';
}
- ret->product_name.string = mem;
+ ret->product_name.ptr = mem;
/* Product revision. */
- ret->product_revision.string = (char*)
+ ret->product_revision.ptr = (char*)
((ret->product_revision.addr.seg << 4)
+ (ret->product_revision.addr.ofs));
- mem = strdup(ret->product_revision.string); /* leak */
+ mem = strdup(ret->product_revision.ptr); /* leak */
while(((i = strlen(mem)) > 0) && isspace(mem[i - 1])) {
mem[i - 1] = '\0';
}
- ret->product_revision.string = mem;
+ ret->product_revision.ptr = mem;
}
/* Cleanup. */
LRMI_free_real(mem);
return ret;
-}
-
-/* Check if EDID queries are suorted. */
-int vbe_get_edid_supported()
-{
- struct LRMI_regs regs;
- int ret = 0;
+#endif
+#if KERNEL_BOOT_INFO
+ int vbe_fd;
- /* Initialize LRMI. */
- if(LRMI_init() == 0) {
- return 0;
- }
+ struct vbe_info *ret = NULL;
+ ret = malloc(sizeof(struct vbe_info));
+ if (ret == NULL)
+ return NULL;
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f15;
- regs.ebx = 0x0000;
- regs.es = 0x3000;
- regs.edi = 0x3000;
+ if ((vbe_fd = open(BOOT_VBE_INFO, O_RDONLY)) < 0)
+ return NULL;
- /* Do it. */
- iopl(3);
- ioperm(0, 0x400, 1);
+ if (read(vbe_fd, ret, VBE_BLOCK_SIZE) != VBE_BLOCK_SIZE)
+ return NULL;
- if(LRMI_int(0x10, &regs) == 0) {
- return 0;
- }
+ close(vbe_fd);
- /* Check for successful return. */
- if((regs.eax & 0xff) == 0x4f) {
- /* Supported. */
- ret = 1;
- } else {
- /* Not supported. */
- ret = 0;
+ /* Set up pointers to usable memory. */
+ normalize_addr(&ret->mode_list);
+ normalize_addr(&ret->oem_name);
+ if (ret->version[1] >= 3) {
+ normalize_addr(&ret->vendor_name);
+ normalize_addr(&ret->product_name);
+ normalize_addr(&ret->product_revision);
}
- /* Clean up and return. */
return ret;
+#endif
+ return NULL;
}
/* Get EDID info. */
struct vbe_edid1_info *vbe_get_edid_info()
{
+#if defined(__i386__)
struct LRMI_regs regs;
unsigned char *mem;
struct vbe_edid1_info *ret = NULL;
@@ -276,62 +222,33 @@ struct vbe_edid1_info *vbe_get_edid_info()
LRMI_free_real(mem);
return ret;
-}
-
-/* Figure out what the current video mode is. */
-int32_t vbe_get_mode()
-{
- struct LRMI_regs regs;
- int32_t ret = -1;
+#endif
+#if KERNEL_BOOT_INFO
+ int i, invalid, edid_fd;
- /* Initialize LRMI. */
- if(LRMI_init() == 0) {
- return -1;
- }
+ struct vbe_edid1_info *ret = NULL;
+ ret = malloc(sizeof(struct vbe_edid1_info));
+ if (ret == NULL)
+ return NULL;
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f03;
+ if ((edid_fd = open(BOOT_EDID_INFO, O_RDONLY)) < 0)
+ return NULL;
- /* Do it. */
- iopl(3);
- ioperm(0, 0x400, 1);
+ if (read(edid_fd, ret, EDID_BLOCK_SIZE) != EDID_BLOCK_SIZE)
+ return NULL;
- if(LRMI_int(0x10, &regs) == 0) {
- return -1;
- }
+ close(edid_fd);
- /* Save the returned value. */
- if((regs.eax & 0xffff) == 0x004f) {
- ret = regs.ebx & 0xffff;
- } else {
- ret = -1;
- }
+ /* Check that kernel could actually get something useful. */
+ invalid = 1;
+ for (i = 0; invalid && i < 8; i++)
+ invalid = invalid && (ret->header[i] == EDID_INVALID);
+ if (invalid)
+ return NULL;
- /* Clean up and return. */
return ret;
-}
-
-/* Set the video mode. */
-void vbe_set_mode(u_int16_t mode)
-{
- struct LRMI_regs regs;
-
- /* Initialize LRMI. */
- if(LRMI_init() == 0) {
- return;
- }
-
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f02;
- regs.ebx = mode;
-
- /* Do it. */
- iopl(3);
- ioperm(0, 0x400, 1);
- LRMI_int(0x10, &regs);
-
- /* Return. */
- return;
+#endif
+ return NULL;
}
/* Just read ranges from the EDID. */
@@ -567,143 +484,3 @@ struct vbe_modeline *vbe_get_edid_modelines()
return ret;
}
-
-const void *vbe_save_svga_state()
-{
- struct LRMI_regs regs;
- unsigned char *mem;
- u_int16_t block_size;
- void *data;
-
- /* Initialize LRMI. */
- if(LRMI_init() == 0) {
- return NULL;
- }
-
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f04;
- regs.ecx = 0xffff;
- regs.edx = 0;
-
- iopl(3);
- ioperm(0, 0x400, 1);
-
- if(LRMI_int(0x10, &regs) == 0) {
- return NULL;
- }
-
- if((regs.eax & 0xff) != 0x4f) {
- fprintf(stderr, "Get SuperVGA Video State not supported.\n");
- return NULL;
- }
-
- if((regs.eax & 0xffff) != 0x004f) {
- fprintf(stderr, "Get SuperVGA Video State Info failed.\n");
- return NULL;
- }
-
- block_size = 64 * (regs.ebx & 0xffff);
-
- /* Allocate a chunk of memory. */
- mem = LRMI_alloc_real(block_size);
- if(mem == NULL) {
- return NULL;
- }
- memset(mem, 0, sizeof(block_size));
-
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f04;
- regs.ecx = 0x000f;
- regs.edx = 0x0001;
- regs.es = ((u_int32_t)mem) >> 4;
- regs.ebx = ((u_int32_t)mem) & 0x0f;
- memset(mem, 0, block_size);
- iopl(3);
- ioperm(0, 0x400, 1);
-
- if(LRMI_int(0x10, &regs) == 0) {
- LRMI_free_real(mem);
- return NULL;
- }
-
- if((regs.eax & 0xffff) != 0x004f) {
- fprintf(stderr, "Get SuperVGA Video State Save failed.\n");
- return NULL;
- }
-
- data = malloc(block_size);
- if(data == NULL) {
- LRMI_free_real(mem);
- return NULL;
- }
-
- /* Clean up and return. */
- memcpy(data, mem, block_size);
- LRMI_free_real(mem);
- return data;
-}
-
-void vbe_restore_svga_state(const void *state)
-{
- struct LRMI_regs regs;
- unsigned char *mem;
- u_int16_t block_size;
-
- /* Initialize LRMI. */
- if(LRMI_init() == 0) {
- return;
- }
-
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f04;
- regs.ecx = 0x000f;
- regs.edx = 0;
-
- /* Find out how much memory we need. */
- iopl(3);
- ioperm(0, 0x400, 1);
-
- if(LRMI_int(0x10, &regs) == 0) {
- return;
- }
-
- if((regs.eax & 0xff) != 0x4f) {
- fprintf(stderr, "Get SuperVGA Video State not supported.\n");
- return;
- }
-
- if((regs.eax & 0xffff) != 0x004f) {
- fprintf(stderr, "Get SuperVGA Video State Info failed.\n");
- return;
- }
-
- block_size = 64 * (regs.ebx & 0xffff);
-
- /* Allocate a chunk of memory. */
- mem = LRMI_alloc_real(block_size);
- if(mem == NULL) {
- return;
- }
- memset(mem, 0, sizeof(block_size));
-
- memset(&regs, 0, sizeof(regs));
- regs.eax = 0x4f04;
- regs.ecx = 0x000f;
- regs.edx = 0x0002;
- regs.es = 0x2000;
- regs.ebx = 0x0000;
- memcpy(mem, state, block_size);
-
- iopl(3);
- ioperm(0, 0x400, 1);
-
- if(LRMI_int(0x10, &regs) == 0) {
- LRMI_free_real(mem);
- return;
- }
-
- if((regs.eax & 0xffff) != 0x004f) {
- fprintf(stderr, "Get SuperVGA Video State Restore failed.\n");
- return;
- }
-}
diff --git a/tools/ddcprobe/vbe.h b/tools/ddcprobe/vbe.h
index 338d3bd88..32ccc7902 100644
--- a/tools/ddcprobe/vbe.h
+++ b/tools/ddcprobe/vbe.h
@@ -3,49 +3,41 @@
#ident "$Id$"
#include <sys/types.h>
+#if defined(__x86_64__)
+#define KERNEL_BOOT_INFO 1
+#endif
+#define BOOT_VBE_INFO "/proc/BOOT/vbe"
+#define BOOT_EDID_INFO "/proc/BOOT/edid"
+#define EDID_INVALID 0x13
+#define EDID_BLOCK_SIZE 128
+#define VBE_BLOCK_SIZE 512
+
+union vbe_addr {
+ struct {
+ u_int16_t ofs;
+ u_int16_t seg;
+ } addr;
+ u_int32_t base;
+#if defined(__i386__)
+ char *ptr;
+#endif
+};
+
+typedef union vbe_addr vbe_addr_t;
+
/* Record returned by int 0x10, function 0x4f, subfunction 0x00. */
struct vbe_info {
unsigned char signature[4];
unsigned char version[2];
- union {
- struct {
- u_int16_t ofs;
- u_int16_t seg;
- } addr;
- const char *string;
- } oem_name;
+ vbe_addr_t oem_name;
u_int32_t capabilities;
- union {
- struct {
- u_int16_t ofs;
- u_int16_t seg;
- } addr;
- u_int16_t *list;
- } mode_list;
+ vbe_addr_t mode_list;
u_int16_t memory_size;
/* VESA 3.0+ */
u_int16_t vbe_revision;
- union {
- struct {
- u_int16_t ofs;
- u_int16_t seg;
- } addr;
- const char *string;
- } vendor_name;
- union {
- struct {
- u_int16_t ofs;
- u_int16_t seg;
- } addr;
- const char *string;
- } product_name;
- union {
- struct {
- u_int16_t ofs;
- u_int16_t seg;
- } addr;
- const char *string;
- } product_revision;
+ vbe_addr_t vendor_name;
+ vbe_addr_t product_name;
+ vbe_addr_t product_revision;
char reserved1[222];
char reserved2[256];
} __attribute__ ((packed));
@@ -284,23 +276,9 @@ struct vbe_edid1_info {
/* Get VESA information. */
struct vbe_info *vbe_get_vbe_info();
-/* Get information about a particular video mode, bitwise or with
- VBE_LINEAR_FRAMEBUFFER to check if LFB version is supported. */
-struct vbe_mode_info *vbe_get_mode_info(u_int16_t mode);
-
/* Check if EDID reads are supported, and do them. */
-int vbe_get_edid_supported();
struct vbe_edid1_info *vbe_get_edid_info();
-/* Get the current video mode, -1 on error. */
-int32_t vbe_get_mode();
-/* Set a new video mode, bitwise or with VBE_LINEAR_FRAMEBUFFER. */
-void vbe_set_mode(u_int16_t mode);
-
-/* Save/restore the SVGA state. Call free() on the state record when done. */
-const void *vbe_save_svga_state();
-void vbe_restore_svga_state(const void *state);
-
/* Get the ranges of values suitable for the attached monitor. */
void vbe_get_edid_ranges(struct vbe_edid1_info *edid,
unsigned char *hmin, unsigned char *hmax,