Restore vesa on consoles with an initialized legacy video BIOS. VIS identifier illumos_fb identifies both BIOS VBE and UEFI GOP consoles; it is not evidence that vesa is unusable. Preserve upstream PCI matching and vesa, reserving illumosfb for bitmap consoles without an initialized legacy video BIOS. Do not change selection of existing PCI drivers such as intel. Unknown BIOS capability retains vesa. Explicit Device sections are unchanged. Do not put vesa and illumosfb in the same fallback list: their PCI/framebuffer claims conflict before PreInit. This patch is specific to illumos. --- a/hw/xfree86/common/xf86AutoConfig.c +++ b/hw/xfree86/common/xf86AutoConfig.c @@ -198,6 +198,91 @@ return ret == CONFIG_OK; } +#if defined(__sun) && (defined(__i386__) || defined(__amd64__)) +/* + * Return 1 for an initialized legacy video BIOS, 0 for its absence, and -1 + * when it cannot be inspected. EFI boot and VIS_GETIDENTIFIER do not tell us + * whether vesa is usable (UEFI systems can retain a compatibility video BIOS). + * Match generic int10's primary BIOS selection, including its early rejection + * of an uninitialized INT10 vector. Like int10_check_bios(), accept a bad + * checksum: int10 only warns about it. + */ +static int +sunLegacyVbios(void) +{ +#ifdef XSERVER_LIBPCIACCESS + struct pci_device_iterator *iter = pci_slot_match_iterator_create(NULL); + struct pci_device *dev; + unsigned char *ivt, *rom; + unsigned int segments[3], seg, off, size; + int i, result = 0; + void *map; + + if (!iter) + return -1; + while ((dev = pci_device_next(iter)) != NULL) + if (xf86IsPrimaryPci(dev)) + break; + pci_iterator_destroy(iter); + if (!dev || pci_device_map_legacy(dev, 0, 4096, 0, &map) != 0) + return -1; + ivt = map; + segments[0] = ivt[0x42] | (ivt[0x43] << 8); + segments[1] = ivt[0x10a] | (ivt[0x10b] << 8); + segments[2] = 0xc000; + pci_device_unmap_legacy(dev, map, 4096); + if (segments[0] < 0xc000) + return 0; + if (pci_device_map_legacy(dev, 0xc0000, 0x40000, 0, &map) != 0) + return -1; + rom = map; + for (i = 0; i < 3; i++) { + seg = segments[i]; + if (seg < 0xc000) + break; + if ((seg & 0x1f) || seg >= 0x10000) + continue; + off = (seg << 4) - 0xc0000; + size = rom[off + 2] * 512; + if (rom[off] == 0x55 && rom[off + 1] == 0xaa && size && + off + size <= 0x40000) { + result = 1; + break; + } + } + pci_device_unmap_legacy(dev, map, 0x40000); + return result; +#else + return -1; +#endif +} + +static Bool +sunUseIllumosFb(void) +{ + struct vis_identifier visid; + int fd, iret = -1, bios; + + if (xf86Info.consoleFd >= 0) + SYSCALL(iret = ioctl(xf86Info.consoleFd, VIS_GETIDENTIFIER, &visid)); + if (iret < 0 && (fd = open(xf86SolarisFbDev, O_RDONLY)) >= 0) { + SYSCALL(iret = ioctl(fd, VIS_GETIDENTIFIER, &visid)); + close(fd); + } + if (iret < 0) + return FALSE; + xf86Msg(X_PROBED, "console driver: %s\n", visid.name); + if (strcmp(visid.name, "illumos_fb") != 0) + return FALSE; + bios = sunLegacyVbios(); + xf86Msg(X_PROBED, "illumos framebuffer: legacy video BIOS %s\n", + bios > 0 ? "present; retaining vesa" : + bios == 0 ? "absent; using illumosfb fallback" : + "unknown; retaining vesa"); + return bios == 0; +} +#endif + static void listPossibleVideoDrivers(char *matches[], int nmatches) { @@ -278,6 +363,25 @@ #if defined(__linux__) matches[i++] = xnfstrdup("modesetting"); +#endif + +#if defined(__sun) && (defined(__i386__) || defined(__amd64__)) + if (sunUseIllumosFb()) { + int j, k; + + for (j = k = 0; j < i; j++) { + if (strcmp(matches[j], "vesa") == 0) + free(matches[j]); + else + matches[k++] = matches[j]; + } + for (j = k; j < i; j++) + matches[j] = NULL; + i = k; + if (i < (nmatches - 1)) + matches[i++] = xnfstrdup("illumosfb"); + return; + } #endif #if !defined(__sun)