diff options
Diffstat (limited to 'sys/dev/fb')
-rw-r--r-- | sys/dev/fb/vesa.c | 794 |
1 files changed, 490 insertions, 304 deletions
diff --git a/sys/dev/fb/vesa.c b/sys/dev/fb/vesa.c index 8a61368..11b9598 100644 --- a/sys/dev/fb/vesa.c +++ b/sys/dev/fb/vesa.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #ifndef VGA_NO_MODE_CHANGE #include <sys/param.h> +#include <sys/bus.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/module.h> @@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$"); #include <dev/fb/fbreg.h> #include <dev/fb/vgareg.h> +#include <dev/pci/pcivar.h> + #include <isa/isareg.h> #include <compat/x86bios/x86bios.h> @@ -160,7 +163,9 @@ static char *vesa_revstr = NULL; #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) static int int10_set_mode(int mode); +static int vesa_bios_post(void); static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode); +static int vesa_bios_get_current_mode(void); static int vesa_bios_set_mode(int mode); static int vesa_bios_get_dac(void); static int vesa_bios_set_dac(int bits); @@ -222,12 +227,62 @@ int10_set_mode(int mode) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x0000 | mode; + x86bios_init_regs(®s); + regs.R_AL = mode; x86bios_intr(®s, 0x10); - return 0; + return (0); +} + +static int +vesa_bios_post(void) +{ + x86regs_t regs; + devclass_t dc; + device_t *devs; + device_t dev; + int count, i, is_pci; + + if (x86bios_get_orm(0xc0000) == NULL) + return (1); + + dev = NULL; + is_pci = 0; + + /* Find the matching PCI video controller. */ + dc = devclass_find("vgapci"); + if (dc != NULL && devclass_get_devices(dc, &devs, &count) == 0) { + for (dev = NULL, i = 0; dev == NULL && i < count; devs++, i++) + if (x86bios_match_device(0xc0000, *devs) && + device_get_flags(*devs) != 0) { + dev = *devs; + is_pci = 1; + break; + } + free(devs, M_TEMP); + } + + /* Try VGA if a PCI device is not found. */ + if (dev == NULL) { + dc = devclass_find(VGA_DRIVER_NAME); + if (dc != NULL) + dev = devclass_get_device(dc, 0); + } + + if (bootverbose) + printf("%s: calling BIOS POST\n", + dev == NULL ? "VESA" : device_get_nameunit(dev)); + + x86bios_init_regs(®s); + if (is_pci) { + regs.R_AH = pci_get_bus(dev); + regs.R_AL = (pci_get_slot(dev) << 3) | + (pci_get_function(dev) & 0x07); + } + regs.R_DL = 0x80; + x86bios_call(®s, 0xc000, 0x0003); + return (0); } /* VESA BIOS calls */ @@ -235,30 +290,47 @@ static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode) { x86regs_t regs; - int offs; - u_char *buf; + uint32_t offs; + void *buf; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f01; - regs.R_ECX = mode; + buf = x86bios_alloc(&offs, sizeof(*vmode)); + if (buf == NULL) + return (1); - buf = (u_char *)x86bios_alloc(1, &offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f01; + regs.R_CX = mode; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - { - x86bios_free(buf, 1); - return 1; + if (regs.R_AX != 0x004f) { + x86bios_free(buf, sizeof(*vmode)); + return (1); } bcopy(buf, vmode, sizeof(*vmode)); - x86bios_free(buf, 1); + x86bios_free(buf, sizeof(*vmode)); - return 0; + return (0); +} + +static int +vesa_bios_get_current_mode(void) +{ + x86regs_t regs; + + x86bios_init_regs(®s); + regs.R_AX = 0x4f03; + + x86bios_intr(®s, 0x10); + + if (regs.R_AX != 0x004f) + return (-1); + + return (regs.R_BX); } static int @@ -266,13 +338,13 @@ vesa_bios_set_mode(int mode) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f02; - regs.R_EBX = mode; + x86bios_init_regs(®s); + regs.R_AX = 0x4f02; + regs.R_BX = mode; x86bios_intr(®s, 0x10); - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } static int @@ -280,16 +352,16 @@ vesa_bios_get_dac(void) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f08; - regs.R_EBX = 1; + x86bios_init_regs(®s); + regs.R_AX = 0x4f08; + regs.R_BL = 1; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 6; + if (regs.R_AX != 0x004f) + return (6); - return ((regs.R_EBX >> 8) & 0x00ff); + return (regs.R_BH); } static int @@ -297,43 +369,45 @@ vesa_bios_set_dac(int bits) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f08; - regs.R_EBX = (bits << 8); + x86bios_init_regs(®s); + regs.R_AX = 0x4f08; + /* regs.R_BL = 0; */ + regs.R_BH = bits; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 6; + if (regs.R_AX != 0x004f) + return (6); - return ((regs.R_EBX >> 8) & 0x00ff); + return (regs.R_BH); } static int vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 1; - regs.R_ECX = colors; - regs.R_EDX = start; + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); - p = (u_char *)x86bios_alloc(1, &offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + regs.R_BL = 1; + regs.R_CX = colors; + regs.R_DX = start; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - { - x86bios_free(p, 1); - return 1; + if (regs.R_AX != 0x004f) { + x86bios_free(p, colors * 4); + return (1); } bits = 8 - bits; @@ -342,9 +416,9 @@ vesa_bios_save_palette(int start, int colors, u_char *palette, int bits) palette[i*3 + 1] = p[i*4 + 1] << bits; palette[i*3 + 2] = p[i*4] << bits; } + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - return 0; + return (0); } static int @@ -352,27 +426,28 @@ vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 1; - regs.R_ECX = colors; - regs.R_EDX = start; + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); - p = (u_char *)x86bios_alloc(1, &offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + regs.R_BL = 1; + regs.R_CX = colors; + regs.R_DX = start; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - { - x86bios_free(p, 1); - return 1; + if (regs.R_AX != 0x004f) { + x86bios_free(p, colors * 4); + return (1); } bits = 8 - bits; @@ -381,20 +456,31 @@ vesa_bios_save_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, g[i] = p[i*4 + 1] << bits; b[i] = p[i*4] << bits; } + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - return 0; + return (0); } static int vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - p = (u_char *)x86bios_alloc(1, &offs); + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); + + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + /* regs.R_BL = 0; */ + regs.R_CX = colors; + regs.R_DX = start; + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -403,21 +489,10 @@ vesa_bios_load_palette(int start, int colors, u_char *palette, int bits) p[i*4 + 2] = palette[i*3] >> bits; p[i*4 + 3] = 0; } - - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 0; - regs.R_ECX = colors; - regs.R_EDX = start; - - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); - x86bios_intr(®s, 0x10); + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } #ifdef notyet @@ -426,11 +501,22 @@ vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, int bits) { x86regs_t regs; - int offs; + uint32_t offs; u_char *p; int i; - p = (u_char *)x86bios_alloc(1, &offs); + p = (u_char *)x86bios_alloc(&offs, colors * 4); + if (p == NULL) + return (1); + + x86bios_init_regs(®s); + regs.R_AX = 0x4f09; + /* regs.R_BL = 0; */ + regs.R_CX = colors; + regs.R_DX = start; + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); bits = 8 - bits; for (i = 0; i < colors; ++i) { @@ -439,21 +525,10 @@ vesa_bios_load_palette2(int start, int colors, u_char *r, u_char *g, u_char *b, p[i*4 + 2] = r[i] >> bits; p[i*4 + 3] = 0; } - - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f09; - regs.R_EBX = 0; - regs.R_ECX = colors; - regs.R_EDX = start; - - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); - x86bios_intr(®s, 0x10); + x86bios_free(p, colors * 4); - x86bios_free(p, 1); - - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } #endif @@ -462,48 +537,55 @@ vesa_bios_state_buf_size(void) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f04; - regs.R_ECX = STATE_ALL; - regs.R_EDX = STATE_SIZE; + x86bios_init_regs(®s); + regs.R_AX = 0x4f04; + /* regs.R_DL = STATE_SIZE; */ + regs.R_CX = STATE_ALL; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 0; + if (regs.R_AX != 0x004f) + return (0); - return regs.R_BX * 64; + return (regs.R_BX * 64); } static int vesa_bios_save_restore(int code, void *p, size_t size) { x86regs_t regs; - int offs; - u_char *buf; + uint32_t offs; + void *buf; if (size > VESA_BIOS_BUFSIZE) return (1); - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f04; - regs.R_ECX = STATE_ALL; - regs.R_EDX = code; - - buf = (u_char *)x86bios_alloc(1, &offs); - - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); - - bcopy(p, buf, size); - - x86bios_intr(®s, 0x10); - - bcopy(buf, p, size); + if (code != STATE_SAVE && code != STATE_LOAD) + return (1); - x86bios_free(p, 1); + buf = x86bios_alloc(&offs, size); + + x86bios_init_regs(®s); + regs.R_AX = 0x4f04; + regs.R_DL = code; + regs.R_CX = STATE_ALL; + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_BX = X86BIOS_PHYSTOOFF(offs); + + switch (code) { + case STATE_SAVE: + x86bios_intr(®s, 0x10); + bcopy(buf, p, size); + break; + case STATE_LOAD: + bcopy(p, buf, size); + x86bios_intr(®s, 0x10); + break; + } + x86bios_free(buf, size); - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } static int @@ -511,16 +593,16 @@ vesa_bios_get_line_length(void) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f06; - regs.R_EBX = 1; + x86bios_init_regs(®s); + regs.R_AX = 0x4f06; + regs.R_BL = 1; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return -1; + if (regs.R_AX != 0x004f) + return (-1); - return regs.R_BX; + return (regs.R_BX); } static int @@ -528,25 +610,25 @@ vesa_bios_set_line_length(int pixel, int *bytes, int *lines) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f06; - regs.R_EBX = 0; - regs.R_ECX = pixel; + x86bios_init_regs(®s); + regs.R_AX = 0x4f06; + /* regs.R_BL = 0; */ + regs.R_CX = pixel; x86bios_intr(®s, 0x10); #if VESA_DEBUG > 1 printf("bx:%d, cx:%d, dx:%d\n", regs.R_BX, regs.R_CX, regs.R_DX); #endif - if ((regs.R_AX & 0xff) != 0x4f) - return -1; + if (regs.R_AX != 0x004f) + return (-1); - if (bytes) + if (bytes != NULL) *bytes = regs.R_BX; - if (lines) + if (lines != NULL) *lines = regs.R_DX; - return 0; + return (0); } #if 0 @@ -555,19 +637,19 @@ vesa_bios_get_start(int *x, int *y) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f07; - regs.R_EBX = 1; + x86bios_init_regs(®s); + regs.R_AX = 0x4f07; + regs.R_BL = 1; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return -1; + if (regs.R_AX != 0x004f) + return (-1); *x = regs.R_CX; *y = regs.R_DX; - return 0; + return (0); } #endif @@ -576,15 +658,15 @@ vesa_bios_set_start(int x, int y) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f07; - regs.R_EBX = 0x80; - regs.R_EDX = y; - regs.R_ECX = x; + x86bios_init_regs(®s); + regs.R_AX = 0x4f07; + regs.R_BL = 0x80; + regs.R_CX = x; + regs.R_DX = y; x86bios_intr(®s, 0x10); - return ((regs.R_AX & 0xff) != 0x4f); + return (regs.R_AX != 0x004f); } /* map a generic video mode to a known mode */ @@ -604,9 +686,9 @@ vesa_map_gen_mode_num(int type, int color, int mode) for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { if (mode_map[i].from == mode) - return mode_map[i].to; + return (mode_map[i].to); } - return mode; + return (mode); } static int @@ -628,7 +710,7 @@ vesa_translate_flags(u_int16_t vflags) flags |= (vflags & ftable[i].mask) ? ftable[i].set : ftable[i].reset; } - return flags; + return (flags); } static int @@ -649,9 +731,9 @@ vesa_translate_mmodel(u_int8_t vmodel) for (i = 0; mtable[i].mmodel >= 0; ++i) { if (mtable[i].vmodel == vmodel) - return mtable[i].mmodel; + return (mtable[i].mmodel); } - return V_INFO_MM_OTHER; + return (V_INFO_MM_OTHER); } static int @@ -685,6 +767,18 @@ vesa_get_line_width(video_info_t *info) return (len > 0 ? len : width); } +#define VESA_MAXSTR 256 + +#define VESA_STRCPY(dst, src) do { \ + char *str; \ + int i; \ + dst = malloc(VESA_MAXSTR, M_DEVBUF, M_WAITOK); \ + str = x86bios_offset(BIOS_SADDRTOLADDR(src)); \ + for (i = 0; i < VESA_MAXSTR - 1 && str[i] != '\0'; i++) \ + dst[i] = str[i]; \ + dst[i] = '\0'; \ +} while (0) + static int vesa_bios_init(void) { @@ -693,32 +787,50 @@ vesa_bios_init(void) video_info_t *p; x86regs_t regs; size_t bsize; - int offs; - u_char *vmbuf; + void *vmbuf; + uint32_t offs; + uint16_t vers; int is_via_cle266; int modes; int i; if (vesa_init_done) - return 0; + return (0); has_vesa_bios = FALSE; vesa_adp_info = NULL; vesa_vmode_max = 0; vesa_vmode[0].vi_mode = EOT; - vmbuf = (u_char *)x86bios_alloc(1, &offs); - bcopy("VBE2", vmbuf, 4); /* try for VBE2 data */ + /* + * If the VBE real mode interrupt vector is not found, try BIOS POST. + */ + if (x86bios_get_intr(0x10) == 0) { + if (vesa_bios_post() != 0) + return (1); + offs = x86bios_get_intr(0x10); + if (offs == 0) + return (1); + if (bootverbose) + printf("VESA: interrupt vector installed (0x%x)\n", + BIOS_SADDRTOLADDR(offs)); + } - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f00; - regs.R_ES = SEG_ADDR(offs); - regs.R_DI = SEG_OFF(offs); + x86bios_init_regs(®s); + regs.R_AX = 0x4f00; + vmbuf = x86bios_alloc(&offs, sizeof(buf)); + if (vmbuf == NULL) + return (1); + + regs.R_ES = X86BIOS_PHYSTOSEG(offs); + regs.R_DI = X86BIOS_PHYSTOOFF(offs); + + bcopy("VBE2", vmbuf, 4); /* try for VBE2 data */ x86bios_intr(®s, 0x10); - if (((regs.R_AX & 0xff) != 0x4f) || bcmp("VESA", vmbuf, 4)) - return 1; + if (regs.R_AX != 0x004f || bcmp("VESA", vmbuf, 4) != 0) + goto fail; bcopy(vmbuf, &buf, sizeof(buf)); @@ -727,34 +839,43 @@ vesa_bios_init(void) printf("VESA: information block\n"); dump_buffer((u_char *)&buf, sizeof(buf)); } - if (vesa_adp_info->v_version < 0x0102) { + + vers = buf.v_version = le16toh(buf.v_version); + buf.v_oemstr = le32toh(buf.v_oemstr); + buf.v_flags = le32toh(buf.v_flags); + buf.v_modetable = le32toh(buf.v_modetable); + buf.v_memsize = le16toh(buf.v_memsize); + buf.v_revision = le16toh(buf.v_revision); + buf.v_venderstr = le32toh(buf.v_venderstr); + buf.v_prodstr = le32toh(buf.v_prodstr); + buf.v_revstr = le32toh(buf.v_revstr); + + if (vers < 0x0102) { printf("VESA: VBE version %d.%d is not supported; " "version 1.2 or later is required.\n", - ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 - + ((vesa_adp_info->v_version & 0x0f00) >> 8), - ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 - + (vesa_adp_info->v_version & 0x000f)); - return 1; + ((vers & 0xf000) >> 12) * 10 + ((vers & 0x0f00) >> 8), + ((vers & 0x00f0) >> 4) * 10 + (vers & 0x000f)); + return (1); } - vesa_oemstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_oemstr)); - - is_via_cle266 = strcmp(vesa_oemstr, VESA_VIA_CLE266) == 0; - - if (vesa_adp_info->v_version >= 0x0200) { - vesa_venderstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_venderstr)); - vesa_prodstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_prodstr)); - vesa_revstr = (char *)x86bios_offset(FARP(vesa_adp_info->v_revstr)); + VESA_STRCPY(vesa_oemstr, buf.v_oemstr); + if (vers >= 0x0200) { + VESA_STRCPY(vesa_venderstr, buf.v_venderstr); + VESA_STRCPY(vesa_prodstr, buf.v_prodstr); + VESA_STRCPY(vesa_revstr, buf.v_revstr); } + is_via_cle266 = strncmp(vesa_oemstr, VESA_VIA_CLE266, + sizeof(VESA_VIA_CLE266)) == 0; - vesa_vmodetab = (uint16_t *)x86bios_offset(FARP(vesa_adp_info->v_modetable)); + if (buf.v_modetable == 0) + goto fail; - if (vesa_vmodetab == NULL) - return 1; + vesa_vmodetab = x86bios_offset(BIOS_SADDRTOLADDR(buf.v_modetable)); for (i = 0, modes = 0; (i < (M_VESA_MODE_MAX - M_VESA_BASE + 1)) && (vesa_vmodetab[i] != 0xffff); ++i) { + vesa_vmodetab[i] = le16toh(vesa_vmodetab[i]); if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode)) continue; @@ -888,16 +1009,36 @@ vesa_bios_init(void) } vesa_vmode[modes].vi_mode = EOT; - x86bios_free(vmbuf, 1); - if (bootverbose) printf("VESA: %d mode(s) found\n", modes); has_vesa_bios = (modes > 0); if (!has_vesa_bios) - return (1); + goto fail; + x86bios_free(vmbuf, sizeof(buf)); return (0); + +fail: + if (vmbuf != NULL) + x86bios_free(vmbuf, sizeof(buf)); + if (vesa_oemstr != NULL) { + free(vesa_oemstr, M_DEVBUF); + vesa_oemstr = NULL; + } + if (vesa_venderstr != NULL) { + free(vesa_venderstr, M_DEVBUF); + vesa_venderstr = NULL; + } + if (vesa_prodstr != NULL) { + free(vesa_prodstr, M_DEVBUF); + vesa_prodstr = NULL; + } + if (vesa_revstr != NULL) { + free(vesa_revstr, M_DEVBUF); + vesa_revstr = NULL; + } + return (1); } static void @@ -946,9 +1087,9 @@ vesa_configure(int flags) int i; if (vesa_init_done) - return 0; + return (0); if (flags & VIO_PROBE_ONLY) - return 0; /* XXX */ + return (0); /* * If the VESA module has already been loaded, abort loading @@ -956,10 +1097,11 @@ vesa_configure(int flags) */ for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) { if (adp->va_flags & V_ADP_VESA) - return ENXIO; + return (ENXIO); if (adp->va_type == KD_VGA) break; } + /* * The VGA adapter is not found. This is because either * 1) the VGA driver has not been initialized, or 2) the VGA card @@ -968,7 +1110,7 @@ vesa_configure(int flags) */ if (adp == NULL) { vga_sub_configure = vesa_configure; - return ENODEV; + return (ENODEV); } /* count number of registered adapters */ @@ -980,7 +1122,7 @@ vesa_configure(int flags) vesa_adp = adp; if (vesa_bios_init()) { vesa_adp = NULL; - return ENXIO; + return (ENXIO); } vesa_adp->va_flags |= V_ADP_VESA; @@ -997,36 +1139,40 @@ vesa_configure(int flags) vesa_init_done = TRUE; } else { vesa_adp = NULL; - return error; + return (error); } - return 0; + return (0); } #if 0 static int vesa_nop(void) { - return 0; + + return (0); } #endif static int vesa_error(void) { - return 1; + + return (1); } static int vesa_probe(int unit, video_adapter_t **adpp, void *arg, int flags) { - return (*prevvidsw->probe)(unit, adpp, arg, flags); + + return ((*prevvidsw->probe)(unit, adpp, arg, flags)); } static int vesa_init(int unit, video_adapter_t *adp, int flags) { - return (*prevvidsw->init)(unit, adp, flags); + + return ((*prevvidsw->init)(unit, adp, flags)); } static int @@ -1035,10 +1181,10 @@ vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info) int i; if ((*prevvidsw->get_info)(adp, mode, info) == 0) - return 0; + return (0); if (adp != vesa_adp) - return 1; + return (1); mode = vesa_map_gen_mode_num(vesa_adp->va_type, vesa_adp->va_flags & V_ADP_COLOR, mode); @@ -1047,10 +1193,10 @@ vesa_get_info(video_adapter_t *adp, int mode, video_info_t *info) continue; if (vesa_vmode[i].vi_mode == mode) { *info = vesa_vmode[i]; - return 0; + return (0); } } - return 1; + return (1); } static int @@ -1059,9 +1205,9 @@ vesa_query_mode(video_adapter_t *adp, video_info_t *info) int i; if ((*prevvidsw->query_mode)(adp, info) == 0) - return 0; + return (0); if (adp != vesa_adp) - return ENODEV; + return (ENODEV); for (i = 0; vesa_vmode[i].vi_mode != EOT; ++i) { if ((info->vi_width != 0) @@ -1087,9 +1233,9 @@ vesa_query_mode(video_adapter_t *adp, video_info_t *info) && (info->vi_flags != vesa_vmode[i].vi_flags)) continue; *info = vesa_vmode[i]; - return 0; + return (0); } - return ENODEV; + return (ENODEV); } static int @@ -1098,7 +1244,7 @@ vesa_set_mode(video_adapter_t *adp, int mode) video_info_t info; if (adp != vesa_adp) - return (*prevvidsw->set_mode)(adp, mode); + return ((*prevvidsw->set_mode)(adp, mode)); mode = vesa_map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); @@ -1129,11 +1275,11 @@ vesa_set_mode(video_adapter_t *adp, int mode) /* we may not need to handle this mode after all... */ if ((*prevvidsw->set_mode)(adp, mode) == 0) - return 0; + return (0); /* is the new mode supported? */ if (vesa_get_info(adp, mode, &info)) - return 1; + return (1); /* assert(VESA_MODE(mode)); */ #if VESA_DEBUG > 0 @@ -1144,7 +1290,7 @@ vesa_set_mode(video_adapter_t *adp, int mode) info.vi_flags &= ~V_INFO_LINEAR; if (vesa_bios_set_mode(mode | ((info.vi_flags & V_INFO_LINEAR) ? 0x4000 : 0))) - return 1; + return (1); if (adp->va_info.vi_flags & V_INFO_LINEAR) vesa_unmap_buffer(adp->va_buffer, @@ -1190,29 +1336,32 @@ vesa_set_mode(video_adapter_t *adp, int mode) /* move hardware cursor out of the way */ (*vidsw[vesa_adp->va_index]->set_hw_cursor)(vesa_adp, -1, -1); - return 0; + return (0); } static int vesa_save_font(video_adapter_t *adp, int page, int fontsize, int fontwidth, u_char *data, int ch, int count) { - return (*prevvidsw->save_font)(adp, page, fontsize, fontwidth, data, - ch, count); + + return ((*prevvidsw->save_font)(adp, page, fontsize, fontwidth, data, + ch, count)); } static int vesa_load_font(video_adapter_t *adp, int page, int fontsize, int fontwidth, u_char *data, int ch, int count) { - return (*prevvidsw->load_font)(adp, page, fontsize, fontwidth, data, - ch, count); + + return ((*prevvidsw->load_font)(adp, page, fontsize, fontwidth, data, + ch, count)); } static int vesa_show_font(video_adapter_t *adp, int page) { - return (*prevvidsw->show_font)(adp, page); + + return ((*prevvidsw->show_font)(adp, page)); } static int @@ -1226,12 +1375,12 @@ vesa_save_palette(video_adapter_t *adp, u_char *palette) bits = vesa_bios_get_dac(); error = vesa_bios_save_palette(0, 256, palette, bits); if (error == 0) - return 0; + return (0); if (bits != 6) - return error; + return (error); } - return (*prevvidsw->save_palette)(adp, palette); + return ((*prevvidsw->save_palette)(adp, palette)); } static int @@ -1245,48 +1394,67 @@ vesa_load_palette(video_adapter_t *adp, u_char *palette) && VESA_MODE(adp->va_mode) && ((bits = vesa_bios_set_dac(8)) > 6)) { error = vesa_bios_load_palette(0, 256, palette, bits); if (error == 0) - return 0; + return (0); if (vesa_bios_set_dac(6) != 6) - return 1; + return (1); } #endif /* notyet */ - return (*prevvidsw->load_palette)(adp, palette); + return ((*prevvidsw->load_palette)(adp, palette)); } static int vesa_set_border(video_adapter_t *adp, int color) { - return (*prevvidsw->set_border)(adp, color); + + return ((*prevvidsw->set_border)(adp, color)); } static int vesa_save_state(video_adapter_t *adp, void *p, size_t size) { + if (adp != vesa_adp) - return (*prevvidsw->save_state)(adp, p, size); + return ((*prevvidsw->save_state)(adp, p, size)); if (vesa_state_buf_size == 0) vesa_state_buf_size = vesa_bios_state_buf_size(); if (size == 0) return (sizeof(int) + vesa_state_buf_size); else if (size < (sizeof(int) + vesa_state_buf_size)) - return 1; + return (1); ((adp_state_t *)p)->sig = V_STATE_SIG; bzero(((adp_state_t *)p)->regs, vesa_state_buf_size); - return vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, - vesa_state_buf_size); + return (vesa_bios_save_restore(STATE_SAVE, ((adp_state_t *)p)->regs, + vesa_state_buf_size)); } static int vesa_load_state(video_adapter_t *adp, void *p) { + int flags, mode, ret; + if ((adp != vesa_adp) || (((adp_state_t *)p)->sig != V_STATE_SIG)) - return (*prevvidsw->load_state)(adp, p); + return ((*prevvidsw->load_state)(adp, p)); - return vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, - vesa_state_buf_size); + ret = vesa_bios_save_restore(STATE_LOAD, ((adp_state_t *)p)->regs, + vesa_state_buf_size); + + /* + * If the current mode is not restored properly, try BIOS POST and + * force setting the mode. + */ + flags = adp->va_info.vi_flags; + if (!(flags & V_INFO_GRAPHICS)) + flags &= ~V_INFO_LINEAR; + mode = adp->va_mode | ((flags & V_INFO_LINEAR) ? 0x4000 : 0); + if (vesa_bios_get_current_mode() != mode && vesa_bios_post() == 0 && + x86bios_get_intr(0x10) != 0) { + int10_set_mode(adp->va_initial_bios_mode); + vesa_bios_set_mode(mode); + } + return (ret); } #if 0 @@ -1295,17 +1463,17 @@ vesa_get_origin(video_adapter_t *adp, off_t *offset) { x86regs_t regs; - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f05; - regs.R_EBX = 0x10; + x86bios_init_regs(®s); + regs.R_AX = 0x4f05; + regs.R_BL = 0x10; x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 1; + if (regs.R_AX != 0x004f) + return (1); *offset = regs.DX * adp->va_window_gran; - return 0; + return (0); } #endif @@ -1321,99 +1489,107 @@ vesa_set_origin(video_adapter_t *adp, off_t offset) * detect error. */ if (adp != vesa_adp) - return (*prevvidsw->set_win_org)(adp, offset); + return ((*prevvidsw->set_win_org)(adp, offset)); /* if this is a linear frame buffer, do nothing */ if (adp->va_info.vi_flags & V_INFO_LINEAR) - return 0; + return (0); /* XXX */ if (adp->va_window_gran == 0) - return 1; + return (1); - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f05; - regs.R_EBX = 0; - regs.R_EDX = offset / adp->va_window_gran; + x86bios_init_regs(®s); + regs.R_AX = 0x4f05; + regs.R_DX = offset / adp->va_window_gran; + x86bios_intr(®s, 0x10); - if ((regs.R_AX & 0xff) != 0x4f) - return 1; + if (regs.R_AX != 0x004f) + return (1); - bzero(®s, sizeof(regs)); - regs.R_EAX = 0x4f05; - regs.R_EBX = 1; - regs.R_EDX = offset / adp->va_window_gran; + x86bios_init_regs(®s); + regs.R_AX = 0x4f05; + regs.R_BL = 1; + regs.R_DX = offset / adp->va_window_gran; x86bios_intr(®s, 0x10); adp->va_window_orig = (offset/adp->va_window_gran)*adp->va_window_gran; - return 0; /* XXX */ + return (0); /* XXX */ } static int vesa_read_hw_cursor(video_adapter_t *adp, int *col, int *row) { - return (*prevvidsw->read_hw_cursor)(adp, col, row); + + return ((*prevvidsw->read_hw_cursor)(adp, col, row)); } static int vesa_set_hw_cursor(video_adapter_t *adp, int col, int row) { - return (*prevvidsw->set_hw_cursor)(adp, col, row); + + return ((*prevvidsw->set_hw_cursor)(adp, col, row)); } static int vesa_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, int celsize, int blink) { - return (*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize, - blink); + + return ((*prevvidsw->set_hw_cursor_shape)(adp, base, height, celsize, + blink)); } static int vesa_blank_display(video_adapter_t *adp, int mode) { + /* XXX: use VESA DPMS */ - return (*prevvidsw->blank_display)(adp, mode); + return ((*prevvidsw->blank_display)(adp, mode)); } static int vesa_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr, int prot) { + #if VESA_DEBUG > 0 printf("vesa_mmap(): window:0x%tx, buffer:0x%tx, offset:0x%tx\n", adp->va_info.vi_window, adp->va_info.vi_buffer, offset); #endif - if ((adp == vesa_adp) && (adp->va_info.vi_flags & V_INFO_LINEAR)) { + if ((adp == vesa_adp) && + (adp->va_info.vi_flags & V_INFO_LINEAR) != 0) { /* va_window_size == va_buffer_size/vi_planes */ /* XXX: is this correct? */ if (offset > adp->va_window_size - PAGE_SIZE) - return -1; + return (-1); *paddr = adp->va_info.vi_buffer + offset; - return 0; - } else { - return (*prevvidsw->mmap)(adp, offset, paddr, prot); + return (0); } + return ((*prevvidsw->mmap)(adp, offset, paddr, prot)); } static int vesa_clear(video_adapter_t *adp) { - return (*prevvidsw->clear)(adp); + + return ((*prevvidsw->clear)(adp)); } static int vesa_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) { - return (*prevvidsw->fill_rect)(adp, val, x, y, cx, cy); + + return ((*prevvidsw->fill_rect)(adp, val, x, y, cx, cy)); } static int vesa_bitblt(video_adapter_t *adp,...) { + /* FIXME */ - return 1; + return (1); } static int @@ -1427,15 +1603,15 @@ get_palette(video_adapter_t *adp, int base, int count, int error; if ((base < 0) || (base >= 256) || (count < 0) || (count > 256)) - return 1; + return (1); if ((base + count) > 256) - return 1; + return (1); if (!(vesa_adp_info->v_flags & V_DAC8) || !VESA_MODE(adp->va_mode)) - return 1; + return (1); bits = vesa_bios_get_dac(); if (bits <= 6) - return 1; + return (1); r = malloc(count*3, M_DEVBUF, M_WAITOK); g = r + count; @@ -1453,14 +1629,14 @@ get_palette(video_adapter_t *adp, int base, int count, free(r, M_DEVBUF); /* if error && bits != 6 at this point, we are in trouble... XXX */ - return error; + return (error); } static int set_palette(video_adapter_t *adp, int base, int count, u_char *red, u_char *green, u_char *blue, u_char *trans) { - return 1; + return (1); #ifdef notyet u_char *r; u_char *g; @@ -1469,10 +1645,10 @@ set_palette(video_adapter_t *adp, int base, int count, int error; if ((base < 0) || (base >= 256) || (base + count > 256)) - return 1; + return (1); if (!(vesa_adp_info->v_flags & V_DAC8) || !VESA_MODE(adp->va_mode) || ((bits = vesa_bios_set_dac(8)) <= 6)) - return 1; + return (1); r = malloc(count*3, M_DEVBUF, M_WAITOK); g = r + count; @@ -1484,11 +1660,11 @@ set_palette(video_adapter_t *adp, int base, int count, error = vesa_bios_load_palette2(base, count, r, g, b, bits); free(r, M_DEVBUF); if (error == 0) - return 0; + return (0); /* if the following call fails, we are in trouble... XXX */ vesa_bios_set_dac(6); - return 1; + return (1); #endif /* notyet */ } @@ -1498,7 +1674,7 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) int bytes; if (adp != vesa_adp) - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); switch (cmd) { case FBIO_SETWINORG: /* set frame buffer window origin */ @@ -1508,24 +1684,24 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) case FBIO_SETDISPSTART: /* set display start address */ if (!VESA_MODE(adp->va_mode)) - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); if (vesa_bios_set_start(((video_display_start_t *)arg)->x, ((video_display_start_t *)arg)->y)) - return ENODEV; + return (ENODEV); adp->va_disp_start.x = ((video_display_start_t *)arg)->x; adp->va_disp_start.y = ((video_display_start_t *)arg)->y; - return 0; + return (0); case FBIO_SETLINEWIDTH: /* set line length in pixel */ if (!VESA_MODE(adp->va_mode)) - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); if (vesa_bios_set_line_length(*(u_int *)arg, &bytes, NULL)) - return ENODEV; + return (ENODEV); adp->va_line_width = bytes; #if VESA_DEBUG > 1 printf("new line width:%d\n", adp->va_line_width); #endif - return 0; + return (0); case FBIO_GETPALETTE: /* get color palette */ if (get_palette(adp, ((video_color_palette_t *)arg)->index, @@ -1534,8 +1710,8 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((video_color_palette_t *)arg)->green, ((video_color_palette_t *)arg)->blue, ((video_color_palette_t *)arg)->transparent)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); case FBIO_SETPALETTE: /* set color palette */ @@ -1545,8 +1721,8 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((video_color_palette_t *)arg)->green, ((video_color_palette_t *)arg)->blue, ((video_color_palette_t *)arg)->transparent)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); case FBIOGETCMAP: /* get color palette */ if (get_palette(adp, ((struct fbcmap *)arg)->index, @@ -1554,8 +1730,8 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((struct fbcmap *)arg)->red, ((struct fbcmap *)arg)->green, ((struct fbcmap *)arg)->blue, NULL)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); case FBIOPUTCMAP: /* set color palette */ if (set_palette(adp, ((struct fbcmap *)arg)->index, @@ -1563,11 +1739,11 @@ vesa_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) ((struct fbcmap *)arg)->red, ((struct fbcmap *)arg)->green, ((struct fbcmap *)arg)->blue, NULL)) - return (*prevvidsw->ioctl)(adp, cmd, arg); - return 0; + return ((*prevvidsw->ioctl)(adp, cmd, arg)); + return (0); default: - return (*prevvidsw->ioctl)(adp, cmd, arg); + return ((*prevvidsw->ioctl)(adp, cmd, arg)); } } @@ -1579,15 +1755,15 @@ vesa_diag(video_adapter_t *adp, int level) /* call the previous handler first */ error = (*prevvidsw->diag)(adp, level); if (error) - return error; + return (error); if (adp != vesa_adp) - return 1; + return (1); if (level <= 0) - return 0; + return (0); - return 0; + return (0); } static int @@ -1597,15 +1773,16 @@ vesa_bios_info(int level) struct vesa_mode vmode; int i; #endif + uint16_t vers; + + vers = vesa_adp_info->v_version; if (bootverbose) { /* general adapter information */ printf( "VESA: v%d.%d, %dk memory, flags:0x%x, mode table:%p (%x)\n", - ((vesa_adp_info->v_version & 0xf000) >> 12) * 10 + - ((vesa_adp_info->v_version & 0x0f00) >> 8), - ((vesa_adp_info->v_version & 0x00f0) >> 4) * 10 + - (vesa_adp_info->v_version & 0x000f), + (vers >> 12) * 10 + ((vers & 0x0f00) >> 8), + ((vers & 0x00f0) >> 4) * 10 + (vers & 0x000f), vesa_adp_info->v_memsize * 64, vesa_adp_info->v_flags, vesa_vmodetab, vesa_adp_info->v_modetable); @@ -1615,9 +1792,9 @@ vesa_bios_info(int level) } if (level <= 0) - return 0; + return (0); - if (vesa_adp_info->v_version >= 0x0200 && bootverbose) { + if (vers >= 0x0200 && bootverbose) { /* vender name, product name, product revision */ printf("VESA: %s %s %s\n", (vesa_venderstr != NULL) ? vesa_venderstr : "unknown", @@ -1664,7 +1841,7 @@ vesa_bios_info(int level) } #endif /* VESA_DEBUG > 1 */ - return 0; + return (0); } /* module loading */ @@ -1676,7 +1853,7 @@ vesa_load(void) int s; if (vesa_init_done) - return 0; + return (0); /* locate a VGA adapter */ s = spltty(); @@ -1687,7 +1864,7 @@ vesa_load(void) if (error == 0) vesa_bios_info(bootverbose); - return error; + return (error); } static int @@ -1700,7 +1877,7 @@ vesa_unload(void) /* if the adapter is currently in a VESA mode, don't unload */ if ((vesa_adp != NULL) && VESA_MODE(vesa_adp->va_mode)) - return EBUSY; + return (EBUSY); /* * FIXME: if there is at least one vty which is in a VESA mode, * we shouldn't be unloading! XXX @@ -1725,21 +1902,30 @@ vesa_unload(void) } splx(s); - return error; + if (vesa_oemstr != NULL) + free(vesa_oemstr, M_DEVBUF); + if (vesa_venderstr != NULL) + free(vesa_venderstr, M_DEVBUF); + if (vesa_prodstr != NULL) + free(vesa_prodstr, M_DEVBUF); + if (vesa_revstr != NULL) + free(vesa_revstr, M_DEVBUF); + if (vesa_vmode != &vesa_vmode_empty) + free(vesa_vmode, M_DEVBUF); + return (error); } static int vesa_mod_event(module_t mod, int type, void *data) { + switch (type) { case MOD_LOAD: - return vesa_load(); + return (vesa_load()); case MOD_UNLOAD: - return vesa_unload(); - default: - return EOPNOTSUPP; + return (vesa_unload()); } - return 0; + return (EOPNOTSUPP); } static moduledata_t vesa_mod = { |