diff options
Diffstat (limited to 'tools/ddcprobe')
-rw-r--r-- | tools/ddcprobe/Makefile | 27 | ||||
-rw-r--r-- | tools/ddcprobe/ddcxinfos.c | 44 | ||||
-rw-r--r-- | tools/ddcprobe/vbe.c | 353 | ||||
-rw-r--r-- | tools/ddcprobe/vbe.h | 76 |
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(®s, 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, ®s) == 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(®s, 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, ®s) == 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(®s, 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, ®s) == 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(®s, 0, sizeof(regs)); - regs.eax = 0x4f02; - regs.ebx = mode; - - /* Do it. */ - iopl(3); - ioperm(0, 0x400, 1); - LRMI_int(0x10, ®s); - - /* 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(®s, 0, sizeof(regs)); - regs.eax = 0x4f04; - regs.ecx = 0xffff; - regs.edx = 0; - - iopl(3); - ioperm(0, 0x400, 1); - - if(LRMI_int(0x10, ®s) == 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(®s, 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, ®s) == 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(®s, 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, ®s) == 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(®s, 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, ®s) == 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, |