int vesafb_get_ddc_info(struct vga_pci_softc *sc, struct edid *info) { struct trapframe tf; unsigned char *buf; int res; if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) { printf("%s: kvm86_bios_addpage failed.\n", sc->sc_dev.dv_xname); return 1; } bzero(&tf, sizeof(struct trapframe)); tf.tf_eax = VBE_FUNC_DDC; tf.tf_ebx = VBE_DDC_GET; tf.tf_vm86_es = 0; tf.tf_edi = KVM86_CALL_TASKVA; res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf); if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) { kvm86_bios_delpage(KVM86_CALL_TASKVA, buf); return 1; } memcpy(info, buf, sizeof(struct edid)); kvm86_bios_delpage(KVM86_CALL_TASKVA, buf); return VBECALL_SUCCESS(tf.tf_eax); }
void vesafb_set_palette(struct vga_pci_softc *sc, int reg, struct paletteentry *pe) { struct trapframe tf; int res; char *buf; if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) { printf("%s: kvm86_bios_addpage failed.\n", sc->sc_dev.dv_xname); return; } memcpy(buf, pe, sizeof(struct paletteentry)); /* * this function takes 8 bit per palette as input, but we're * working in 6 bit mode here */ pe = (struct paletteentry *)buf; pe->Red >>= 2; pe->Green >>= 2; pe->Blue >>= 2; /* set palette */ memset(&tf, 0, sizeof(struct trapframe)); tf.tf_eax = VBE_FUNC_PALETTE; tf.tf_ebx = 0x0600; /* 6 bit per primary, set format */ tf.tf_ecx = 1; tf.tf_edx = reg; tf.tf_vm86_es = 0; tf.tf_edi = KVM86_CALL_TASKVA; res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf); if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) printf("%s: vbecall: res=%d, ax=%x\n", sc->sc_dev.dv_xname, res, tf.tf_eax); kvm86_bios_delpage(KVM86_CALL_TASKVA, buf); return; }
int vbegetinfo(struct vbeinfoblock **vip) { unsigned char *buf; struct trapframe tf; int res, error; if ((buf = kvm86_bios_addpage(KVM86_CALL_TASKVA)) == NULL) { printf("vbegetinfo: kvm86_bios_addpage failed\n"); return (ENOMEM); } memcpy(buf, "VBE2", 4); memset(&tf, 0, sizeof(struct trapframe)); tf.tf_eax = VBE_FUNC_CTRLINFO; tf.tf_vm86_es = 0; tf.tf_edi = KVM86_CALL_TASKVA; res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf); if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) { printf("vbecall: res=%d, ax=%x\n", res, tf.tf_eax); error = ENXIO; goto out; } if (memcmp(((struct vbeinfoblock *)buf)->VbeSignature, "VESA", 4)) { error = EIO; goto out; } if (vip) *vip = (struct vbeinfoblock *)buf; return (0); out: kvm86_bios_delpage(KVM86_CALL_TASKVA, buf); return (error); }
void vesabios_attach(struct device *parent, struct device *self, void *aux) { struct vesabios_softc *sc = (struct vesabios_softc *)self; struct vbeinfoblock *vi; unsigned char *buf; struct trapframe tf; int res; char name[256]; #define MAXMODES 60 uint16_t modes[MAXMODES]; int rastermodes[MAXMODES]; int textmodes[MAXMODES]; int nmodes, nrastermodes, ntextmodes, i; uint32_t modeptr; struct modeinfoblock *mi; if (vbegetinfo(&vi)) { printf("\n"); panic("vesabios_attach: disappeared"); } printf(": version %d.%d", VBE_CTRLINFO_VERSION(vi->VbeVersion), VBE_CTRLINFO_REVISION(vi->VbeVersion)); res = kvm86_bios_read(FAR2FLATPTR(vi->OemVendorNamePtr), name, sizeof(name)); sc->sc_size = vi->TotalMemory * 65536; if (res > 0) { name[res - 1] = 0; printf(", %s", name); res = kvm86_bios_read(FAR2FLATPTR(vi->OemProductNamePtr), name, sizeof(name)); if (res > 0) { name[res - 1] = 0; printf(" %s", name); } } printf("\n"); nmodes = 0; modeptr = FAR2FLATPTR(vi->VideoModePtr); while (nmodes < MAXMODES) { res = kvm86_bios_read(modeptr, (char *)&modes[nmodes], 2); if (res != 2 || modes[nmodes] == 0xffff) break; nmodes++; modeptr += 2; } vbefreeinfo(vi); if (nmodes == 0) return; nrastermodes = ntextmodes = 0; buf = kvm86_bios_addpage(KVM86_CALL_TASKVA); if (!buf) { printf("%s: kvm86_bios_addpage failed\n", self->dv_xname); return; } for (i = 0; i < nmodes; i++) { memset(&tf, 0, sizeof(struct trapframe)); tf.tf_eax = VBE_FUNC_MODEINFO; tf.tf_ecx = modes[i]; tf.tf_vm86_es = 0; tf.tf_edi = KVM86_CALL_TASKVA; res = kvm86_bioscall(BIOS_VIDEO_INTR, &tf); if (res || VBECALL_SUPPORT(tf.tf_eax) != VBECALL_SUPPORTED) { printf("%s: vbecall: res=%d, ax=%x\n", self->dv_xname, res, tf.tf_eax); printf("%s: error getting info for mode %04x\n", self->dv_xname, modes[i]); continue; } mi = (struct modeinfoblock *)buf; #ifdef VESABIOSVERBOSE printf("%s: VESA mode %04x: attributes %04x", self->dv_xname, modes[i], mi->ModeAttributes); #endif if (!(mi->ModeAttributes & 1)) { #ifdef VESABIOSVERBOSE printf("\n"); #endif continue; } if (mi->ModeAttributes & 0x10) { /* graphics */ #ifdef VESABIOSVERBOSE printf(", %dx%d %dbbp %s\n", mi->XResolution, mi->YResolution, mi->BitsPerPixel, mm2txt(mi->MemoryModel)); #endif if (mi->ModeAttributes & 0x80) { /* flat buffer */ rastermodes[nrastermodes++] = modes[i]; } } else { /* text */ #ifdef VESABIOSVERBOSE printf(", text %dx%d\n", mi->XResolution, mi->YResolution); #endif if (!(mi->ModeAttributes & 0x20)) /* VGA compatible */ textmodes[ntextmodes++] = modes[i]; } } kvm86_bios_delpage(KVM86_CALL_TASKVA, buf); if (nrastermodes > 0) { sc->sc_modes = (uint16_t *)malloc(sizeof(uint16_t)*nrastermodes, M_DEVBUF, M_NOWAIT); if (sc->sc_modes == NULL) { sc->sc_nmodes = 0; return; } sc->sc_nmodes = nrastermodes; for (i = 0; i < nrastermodes; i++) sc->sc_modes[i] = rastermodes[i]; } vesabios_softc = sc; }