#ifdef VMX86_DEVEL
char rcsId_vmware[] =
"Id: vmware.c,v 1.11 2001/02/23 02:10:39 yoel Exp $";
#endif
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86Resources.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "mipointer.h"
#include "mibstore.h"
#include "micmap.h"
#include "vgaHW.h"
#include "fb.h"
#include "shadowfb.h"
#include "xf86cmap.h"
#include "vmware.h"
#include "guest_os.h"
#include "vm_device_version.h"
#if PCI_CHIP_VMWARE0405 != PCI_DEVICE_ID_VMWARE_SVGA2
#error "PCI_CHIP_VMWARE0405 is wrong, update it from vm_device_version.h"
#endif
#if PCI_CHIP_VMWARE0710 != PCI_DEVICE_ID_VMWARE_SVGA
#error "PCI_CHIP_VMWARE0710 is wrong, update it from vm_device_version.h"
#endif
#if PCI_VENDOR_VMWARE != PCI_VENDOR_ID_VMWARE
#error "PCI_VENDOR_VMWARE is wrong, update it from vm_device_version.h"
#endif
#define VMW_INNERSTRINGIFY(s) #s
#define VMW_STRING(str) VMW_INNERSTRINGIFY(str)
#define VMWARE_NAME "VMWARE"
#define VMWARE_DRIVER_NAME "vmware"
#define VMWARE_MAJOR_VERSION 10
#define VMWARE_MINOR_VERSION 10
#define VMWARE_PATCHLEVEL 2
#define VERSION (VMWARE_MAJOR_VERSION * 65536 + VMWARE_MINOR_VERSION * 256 + VMWARE_PATCHLEVEL)
static const char VMWAREBuildStr[] = "VMware Guest X Server "
VMW_STRING(VMWARE_MAJOR_VERSION) "." VMW_STRING(VMWARE_MINOR_VERSION)
"." VMW_STRING(VMWARE_PATCHLEVEL) " - build=$Name: $\n";
static SymTabRec VMWAREChipsets[] = {
{ PCI_CHIP_VMWARE0405, "vmware0405" },
{ PCI_CHIP_VMWARE0710, "vmware0710" },
{ -1, NULL }
};
static resRange vmwareLegacyRes[] = {
{ ResExcIoBlock, SVGA_LEGACY_BASE_PORT,
SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)},
_VGA_EXCLUSIVE, _END
};
static PciChipsets VMWAREPciChipsets[] = {
{ PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA },
{ PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes },
{ -1, -1, RES_UNDEFINED }
};
static const char *vgahwSymbols[] = {
"vgaHWGetHWRec",
"vgaHWGetIOBase",
"vgaHWGetIndex",
"vgaHWInit",
"vgaHWProtect",
"vgaHWRestore",
"vgaHWSave",
"vgaHWSaveScreen",
"vgaHWUnlock",
NULL
};
static const char *fbSymbols[] = {
"fbCreateDefColormap",
"fbPictureInit",
"fbScreenInit",
NULL
};
static const char *ramdacSymbols[] = {
"xf86CreateCursorInfoRec",
"xf86DestroyCursorInfoRec",
"xf86InitCursor",
NULL
};
static const char *shadowfbSymbols[] = {
"ShadowFBInit2",
NULL
};
#ifdef XFree86LOADER
static XF86ModuleVersionInfo vmwareVersRec = {
"vmware",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XF86_VERSION_CURRENT,
VMWARE_MAJOR_VERSION, VMWARE_MINOR_VERSION, VMWARE_PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{ 0, 0, 0, 0}
};
#endif
typedef enum {
OPTION_HW_CURSOR,
OPTION_NOACCEL
} VMWAREOpts;
static const OptionInfoRec VMWAREOptions[] = {
{ OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
static void VMWAREStopFIFO(ScrnInfoPtr pScrn);
static Bool
VMWAREGetRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate != NULL) {
return TRUE;
}
pScrn->driverPrivate = xnfcalloc(sizeof(VMWARERec), 1);
return TRUE;
}
static void
VMWAREFreeRec(ScrnInfoPtr pScrn)
{
if (pScrn->driverPrivate) {
xfree(pScrn->driverPrivate);
pScrn->driverPrivate = NULL;
}
}
CARD32
vmwareReadReg(VMWAREPtr pVMWARE, int index)
{
int oldsigio, ret;
oldsigio = xf86BlockSIGIO();
outl(pVMWARE->indexReg, index);
ret = inl(pVMWARE->valueReg);
xf86UnblockSIGIO(oldsigio);
return ret;
}
void
vmwareWriteReg(VMWAREPtr pVMWARE, int index, CARD32 value)
{
int oldsigio;
oldsigio = xf86BlockSIGIO();
outl(pVMWARE->indexReg, index);
outl(pVMWARE->valueReg, value);
xf86UnblockSIGIO(oldsigio);
}
void
vmwareWriteWordToFIFO(VMWAREPtr pVMWARE, CARD32 value)
{
CARD32* vmwareFIFO = pVMWARE->vmwareFIFO;
if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(CARD32) == vmwareFIFO[SVGA_FIFO_STOP])
|| (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(CARD32) &&
vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) {
VmwareLog(("Syncing because of full fifo\n"));
vmwareWaitForFB(pVMWARE);
}
vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(CARD32)] = value;
if(vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] -
sizeof(CARD32)) {
vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN];
} else {
vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(CARD32);
}
}
void
vmwareWaitForFB(VMWAREPtr pVMWARE)
{
vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1);
while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY));
}
void
vmwareSendSVGACmdUpdate(VMWAREPtr pVMWARE, BoxPtr pBB)
{
vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE);
vmwareWriteWordToFIFO(pVMWARE, pBB->x1);
vmwareWriteWordToFIFO(pVMWARE, pBB->y1);
vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1);
vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1);
}
static void
vmwareSendSVGACmdUpdateFullScreen(VMWAREPtr pVMWARE)
{
BoxRec BB;
BB.x1 = 0;
BB.y1 = 0;
BB.x2 = pVMWARE->ModeReg.svga_reg_width;
BB.y2 = pVMWARE->ModeReg.svga_reg_height;
vmwareSendSVGACmdUpdate(pVMWARE, &BB);
}
static CARD32
vmwareCalculateWeight(CARD32 mask)
{
CARD32 weight;
for (weight = 0; mask; mask >>= 1) {
if (mask & 1) {
weight++;
}
}
return weight;
}
static uint32
VMXGetVMwareSvgaId(VMWAREPtr pVMWARE)
{
uint32 vmware_svga_id;
vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_2);
vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID);
if (vmware_svga_id == SVGA_ID_2) {
return SVGA_ID_2;
}
vmwareWriteReg(pVMWARE, SVGA_REG_ID, SVGA_ID_1);
vmware_svga_id = vmwareReadReg(pVMWARE, SVGA_REG_ID);
if (vmware_svga_id == SVGA_ID_1) {
return SVGA_ID_1;
}
if (vmware_svga_id == SVGA_ID_0) {
return SVGA_ID_0;
}
return SVGA_ID_INVALID;
}
static void
RewriteTagString(const char *istr, char *ostr, int osize)
{
int chr;
Bool inTag = FALSE;
char *op = ostr;
do {
chr = *istr++;
if (chr == '$') {
if (inTag) {
inTag = FALSE;
for (; op > ostr && op[-1] == ' '; op--) {
}
continue;
}
if (strncmp(istr, "Name:", 5) == 0) {
istr += 5;
istr += strspn(istr, " ");
inTag = TRUE;
continue;
}
}
*op++ = chr;
} while (chr);
}
static void
VMWAREIdentify(int flags)
{
xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets);
}
static const OptionInfoRec *
VMWAREAvailableOptions(int chipid, int busid)
{
return VMWAREOptions;
}
static Bool
VMWAREPreInit(ScrnInfoPtr pScrn, int flags)
{
MessageType from;
VMWAREPtr pVMWARE;
OptionInfoPtr options;
int bpp24flags;
uint32 id;
int i;
ClockRange* clockRanges;
IOADDRESS domainIOBase = 0;
#ifndef BUILD_FOR_420
domainIOBase = pScrn->domainIOBase;
#endif
if (flags & PROBE_DETECT) {
return FALSE;
}
if (pScrn->numEntities != 1) {
return FALSE;
}
if (!VMWAREGetRec(pScrn)) {
return FALSE;
}
pVMWARE = VMWAREPTR(pScrn);
pVMWARE->pvtSema = &pScrn->vtSema;
pVMWARE->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (pVMWARE->pEnt->location.type != BUS_PCI) {
return FALSE;
}
pVMWARE->PciInfo = xf86GetPciInfoForEntity(pVMWARE->pEnt->index);
if (pVMWARE->PciInfo == NULL) {
return FALSE;
}
if (pVMWARE->PciInfo->chipType == PCI_CHIP_VMWARE0710) {
pVMWARE->indexReg = domainIOBase +
SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32);
pVMWARE->valueReg = domainIOBase +
SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32);
} else {
pVMWARE->indexReg = domainIOBase +
pVMWARE->PciInfo->ioBase[0] + SVGA_INDEX_PORT;
pVMWARE->valueReg = domainIOBase +
pVMWARE->PciInfo->ioBase[0] + SVGA_VALUE_PORT;
}
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
"VMware SVGA regs at (0x%04lx, 0x%04lx)\n",
pVMWARE->indexReg, pVMWARE->valueReg);
id = VMXGetVMwareSvgaId(pVMWARE);
if (id == SVGA_ID_0 || id == SVGA_ID_INVALID) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"No supported VMware SVGA found (read ID 0x%08x).\n", id);
return FALSE;
}
if (!xf86LoadSubModule(pScrn, "vgahw")) {
return FALSE;
}
xf86LoaderReqSymLists(vgahwSymbols, NULL);
if (!vgaHWGetHWRec(pScrn)) {
return FALSE;
}
pVMWARE->PciTag = pciTag(pVMWARE->PciInfo->bus, pVMWARE->PciInfo->device,
pVMWARE->PciInfo->func);
pVMWARE->Primary = xf86IsPrimaryPci(pVMWARE->PciInfo);
pScrn->monitor = pScrn->confScreen->monitor;
#ifdef ACCELERATE_OPS
pVMWARE->vmwareCapability = vmwareReadReg(pVMWARE, SVGA_REG_CAPABILITIES);
#else
pVMWARE->vmwareCapability = 0;
#endif
if (pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
pVMWARE->bitsPerPixel =
vmwareReadReg(pVMWARE, SVGA_REG_HOST_BITS_PER_PIXEL);
vmwareWriteReg(pVMWARE,
SVGA_REG_BITS_PER_PIXEL, pVMWARE->bitsPerPixel);
} else {
pVMWARE->bitsPerPixel =
vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
}
pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH);
pVMWARE->videoRam = vmwareReadReg(pVMWARE, SVGA_REG_VRAM_SIZE);
pVMWARE->memPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_FB_START);
pVMWARE->maxWidth = vmwareReadReg(pVMWARE, SVGA_REG_MAX_WIDTH);
pVMWARE->maxHeight = vmwareReadReg(pVMWARE, SVGA_REG_MAX_HEIGHT);
pVMWARE->cursorDefined = FALSE;
pVMWARE->cursorShouldBeHidden = FALSE;
if (pVMWARE->vmwareCapability & SVGA_CAP_CURSOR_BYPASS_2) {
pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_REMOVE_FROM_FB;
pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_RESTORE_TO_FB;
} else {
pVMWARE->cursorRemoveFromFB = SVGA_CURSOR_ON_HIDE;
pVMWARE->cursorRestoreToFB = SVGA_CURSOR_ON_SHOW;
}
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "caps: 0x%08X\n", pVMWARE->vmwareCapability);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "depth: %d\n", pVMWARE->depth);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "bpp: %d\n", pVMWARE->bitsPerPixel);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "vram: %d\n", pVMWARE->videoRam);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "pbase: 0x%08lx\n", pVMWARE->memPhysBase);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mwidt: %d\n", pVMWARE->maxWidth);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED, 2, "mheig: %d\n", pVMWARE->maxHeight);
switch (pVMWARE->depth) {
case 16:
if (pVMWARE->bitsPerPixel == 16 &&
pVMWARE->weight.green == 5)
pVMWARE->depth = 15;
case 8:
case 15:
bpp24flags = NoDepth24Support;
break;
case 32:
if (pVMWARE->bitsPerPixel == 32)
pVMWARE->depth = 24;
case 24:
if (pVMWARE->bitsPerPixel == 24)
bpp24flags = Support24bppFb;
else
bpp24flags = Support32bppFb;
break;
default:
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Adapter is using an unsupported depth (%d).\n",
pVMWARE->depth);
return FALSE;
}
if (!xf86SetDepthBpp(pScrn, pVMWARE->depth, pVMWARE->bitsPerPixel, pVMWARE->bitsPerPixel, bpp24flags)) {
return FALSE;
}
if (pScrn->bitsPerPixel != pVMWARE->bitsPerPixel) {
if (pScrn->bitsPerPixel == 8 &&
pVMWARE->vmwareCapability & SVGA_CAP_8BIT_EMULATION) {
vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL, 8);
pVMWARE->bitsPerPixel =
vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Currently unavailable depth/bpp of %d/%d requested.\n"
"\tThe guest X server must run at the same depth and bpp as the host\n"
"\t(which are currently %d/%d). This is automatically detected. Please\n"
"\tdo not specify a depth on the command line or via the config file.\n",
pScrn->depth, pScrn->bitsPerPixel,
pVMWARE->depth, pVMWARE->bitsPerPixel);
return FALSE;
}
}
pVMWARE->depth = vmwareReadReg(pVMWARE, SVGA_REG_DEPTH);
pVMWARE->weight.red =
vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_RED_MASK));
pVMWARE->weight.green =
vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_GREEN_MASK));
pVMWARE->weight.blue =
vmwareCalculateWeight(vmwareReadReg(pVMWARE, SVGA_REG_BLUE_MASK));
pVMWARE->offset.blue = 0;
pVMWARE->offset.green = pVMWARE->weight.blue;
pVMWARE->offset.red = pVMWARE->weight.green + pVMWARE->offset.green;
pVMWARE->defaultVisual = vmwareReadReg(pVMWARE, SVGA_REG_PSEUDOCOLOR) ?
PseudoColor : TrueColor;
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
2, "depth: %d\n", pVMWARE->depth);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
2, "bpp: %d\n", pVMWARE->bitsPerPixel);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
2, "w.red: %d\n", (int)pVMWARE->weight.red);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
2, "w.grn: %d\n", (int)pVMWARE->weight.green);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
2, "w.blu: %d\n", (int)pVMWARE->weight.blue);
xf86DrvMsgVerb(pScrn->scrnIndex, X_PROBED,
2, "vis: %d\n", pVMWARE->defaultVisual);
if (pScrn->depth != pVMWARE->depth) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Currently unavailable depth of %d requested.\n"
"\tThe guest X server must run at the same depth as the host (which\n"
"\tis currently %d). This is automatically detected. Please do not\n"
"\tspecify a depth on the command line or via the config file.\n",
pScrn->depth, pVMWARE->depth);
return FALSE;
}
xf86PrintDepthBpp(pScrn);
#if 0
if (pScrn->depth == 24 && pix24bpp == 0) {
pix24bpp = xf86GetBppFromDepth(pScrn, 24);
}
#endif
if (pScrn->depth > 8) {
rgb zeros = { 0, 0, 0 };
if (!xf86SetWeight(pScrn, pVMWARE->weight, zeros)) {
return FALSE;
}
}
if (!xf86SetDefaultVisual(pScrn, pVMWARE->defaultVisual)) {
return FALSE;
}
if (pScrn->defaultVisual != pVMWARE->defaultVisual) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given visual (%d) is not supported by this driver (%d is required)\n",
pScrn->defaultVisual, pVMWARE->defaultVisual);
return FALSE;
}
#if 0
bytesPerPixel = pScrn->bitsPerPixel / 8;
#endif
pScrn->progClock = TRUE;
#if 0
if (pScrn->visual != 0) {
return FALSE;
}
#endif
xf86CollectOptions(pScrn, NULL);
if (!(options = xalloc(sizeof(VMWAREOptions))))
return FALSE;
memcpy(options, VMWAREOptions, sizeof(VMWAREOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
if (pScrn->depth <= 8) {
pScrn->rgbBits = 8;
}
from = X_PROBED;
pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, pVMWARE->PciInfo->chipType);
if (!pScrn->chipset) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", pVMWARE->PciInfo->chipType);
return FALSE;
}
from = X_DEFAULT;
pVMWARE->hwCursor = TRUE;
if (xf86GetOptValBool(options, OPTION_HW_CURSOR, &pVMWARE->hwCursor)) {
from = X_CONFIG;
}
if (pVMWARE->hwCursor && !(pVMWARE->vmwareCapability & SVGA_CAP_CURSOR)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported in this configuration\n");
from = X_PROBED;
pVMWARE->hwCursor = FALSE;
}
xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
pVMWARE->hwCursor ? "HW" : "SW");
if (xf86IsOptionSet(options, OPTION_NOACCEL)) {
pVMWARE->noAccel = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
} else {
pVMWARE->noAccel = FALSE;
}
pScrn->videoRam = pVMWARE->videoRam / 1024;
pScrn->memPhysBase = pVMWARE->memPhysBase;
xfree(options);
{
Gamma zeros = { 0.0, 0.0, 0.0 };
if (!xf86SetGamma(pScrn, zeros)) {
return FALSE;
}
}
#if 0
if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) != 1) {
VMWAREFreeRec(pScrn);
if (i > 0) {
xfree(pciList);
}
return FALSE;
}
#endif
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
clockRanges->next = NULL;
clockRanges->minClock = 1;
clockRanges->maxClock = 400000000;
clockRanges->clockIndex = -1;
clockRanges->interlaceAllowed = FALSE;
clockRanges->doubleScanAllowed = FALSE;
clockRanges->ClockMulFactor = 1;
clockRanges->ClockDivFactor = 1;
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes,
clockRanges, NULL, 256, pVMWARE->maxWidth, 32 * 32,
128, pVMWARE->maxHeight,
pScrn->display->virtualX, pScrn->display->virtualY,
pVMWARE->videoRam,
LOOKUP_BEST_REFRESH);
if (i == -1) {
VMWAREFreeRec(pScrn);
return FALSE;
}
xf86PruneDriverModes(pScrn);
if (i == 0 || pScrn->modes == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
VMWAREFreeRec(pScrn);
return FALSE;
}
xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
pScrn->currentMode = pScrn->modes;
xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
if (!xf86LoadSubModule(pScrn, "fb") ||
!xf86LoadSubModule(pScrn, "shadowfb")) {
VMWAREFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(fbSymbols, shadowfbSymbols, NULL);
if (pVMWARE->hwCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
VMWAREFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(ramdacSymbols, NULL);
}
if (!pVMWARE->noAccel) {
if (!xf86LoadSubModule(pScrn, "xaa")) {
VMWAREFreeRec(pScrn);
return FALSE;
}
xf86LoaderReqSymLists(vmwareXaaSymbols, NULL);
}
return TRUE;
}
static Bool
VMWAREMapMem(ScrnInfoPtr pScrn)
{
VMWAREPtr pVMWARE;
pVMWARE = VMWAREPTR(pScrn);
pVMWARE->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
pVMWARE->PciTag,
pVMWARE->memPhysBase,
pVMWARE->videoRam);
if (!pVMWARE->FbBase)
return FALSE;
VmwareLog(("FB Mapped: %p/%u -> %p/%u\n",
pVMWARE->memPhysBase, pVMWARE->videoRam,
pVMWARE->FbBase, pVMWARE->videoRam));
return TRUE;
}
static Bool
VMWAREUnmapMem(ScrnInfoPtr pScrn)
{
VMWAREPtr pVMWARE;
pVMWARE = VMWAREPTR(pScrn);
VmwareLog(("Unmapped: %p/%u\n", pVMWARE->FbBase, pVMWARE->videoRam));
xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->FbBase, pVMWARE->videoRam);
pVMWARE->FbBase = NULL;
return TRUE;
}
static void
VMWARESave(ScrnInfoPtr pScrn)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaRegPtr vgaReg = &hwp->SavedReg;
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
VMWARERegPtr vmwareReg = &pVMWARE->SavedReg;
vgaHWSave(pScrn, vgaReg, VGA_SR_ALL);
vmwareReg->svga_reg_enable = vmwareReadReg(pVMWARE, SVGA_REG_ENABLE);
vmwareReg->svga_reg_width = vmwareReadReg(pVMWARE, SVGA_REG_WIDTH);
vmwareReg->svga_reg_height = vmwareReadReg(pVMWARE, SVGA_REG_HEIGHT);
vmwareReg->svga_reg_bits_per_pixel =
vmwareReadReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL);
if (pVMWARE->hwCursor) {
vmwareReg->svga_reg_cursor_on =
vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ON);
vmwareReg->svga_reg_cursor_x =
vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_X);
vmwareReg->svga_reg_cursor_y =
vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_Y);
vmwareReg->svga_reg_cursor_id =
vmwareReadReg(pVMWARE, SVGA_REG_CURSOR_ID);
}
vmwareReg->svga_fifo_enabled = vmwareReadReg(pVMWARE, SVGA_REG_CONFIG_DONE);
}
static void
VMWARERestoreRegs(ScrnInfoPtr pScrn, VMWARERegPtr vmwareReg)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
VmwareLog(("VMWARERestoreRegs: W: %d, H: %d, BPP: %d, Enable: %d\n",
vmwareReg->svga_reg_width, vmwareReg->svga_reg_height,
vmwareReg->svga_reg_bits_per_pixel, vmwareReg->svga_reg_enable));
if (vmwareReg->svga_reg_enable) {
vmwareWriteReg(pVMWARE, SVGA_REG_WIDTH, vmwareReg->svga_reg_width);
vmwareWriteReg(pVMWARE, SVGA_REG_HEIGHT, vmwareReg->svga_reg_height);
vmwareWriteReg(pVMWARE, SVGA_REG_BITS_PER_PIXEL,
vmwareReg->svga_reg_bits_per_pixel);
vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable);
vmwareWriteReg(pVMWARE, SVGA_REG_GUEST_ID, GUEST_OS_LINUX);
if (pVMWARE->hwCursor) {
vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ID,
vmwareReg->svga_reg_cursor_id);
vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_X,
vmwareReg->svga_reg_cursor_x);
vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_Y,
vmwareReg->svga_reg_cursor_y);
vmwareWriteReg(pVMWARE, SVGA_REG_CURSOR_ON,
vmwareReg->svga_reg_cursor_on);
}
} else {
vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, vmwareReg->svga_reg_enable);
}
}
static void
VMWARERestore(ScrnInfoPtr pScrn)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaRegPtr vgaReg = &hwp->SavedReg;
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
VMWARERegPtr vmwareReg = &pVMWARE->SavedReg;
vmwareWaitForFB(pVMWARE);
if (!vmwareReg->svga_fifo_enabled) {
VMWAREStopFIFO(pScrn);
}
vgaHWProtect(pScrn, TRUE);
VMWARERestoreRegs(pScrn, vmwareReg);
vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
vgaHWProtect(pScrn, FALSE);
}
static Bool
VMWAREModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaRegPtr vgaReg = &hwp->ModeReg;
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
VMWARERegPtr vmwareReg = &pVMWARE->ModeReg;
vgaHWUnlock(hwp);
if (!vgaHWInit(pScrn, mode))
return FALSE;
pScrn->vtSema = TRUE;
vmwareReg->svga_reg_enable = 1;
vmwareReg->svga_reg_width = max(mode->HDisplay, pScrn->virtualX);
vmwareReg->svga_reg_height = max(mode->VDisplay, pScrn->virtualY);
vmwareReg->svga_reg_bits_per_pixel = pVMWARE->bitsPerPixel;
vgaHWProtect(pScrn, TRUE);
vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
VMWARERestoreRegs(pScrn, vmwareReg);
if (pVMWARE->hwCursor) {
vmwareCursorModeInit(pScrn, mode);
}
VmwareLog(("Required mode: %ux%u\n", mode->HDisplay, mode->VDisplay));
VmwareLog(("Virtual: %ux%u\n", pScrn->virtualX, pScrn->virtualY));
VmwareLog(("dispWidth: %u\n", pScrn->displayWidth));
pVMWARE->fbOffset = vmwareReadReg(pVMWARE, SVGA_REG_FB_OFFSET);
pVMWARE->fbPitch = vmwareReadReg(pVMWARE, SVGA_REG_BYTES_PER_LINE);
pVMWARE->FbSize = vmwareReadReg(pVMWARE, SVGA_REG_FB_SIZE);
pScrn->displayWidth = (pVMWARE->fbPitch * 8) / ((pScrn->bitsPerPixel + 7) & ~7);
VmwareLog(("fbOffset: %u\n", pVMWARE->fbOffset));
VmwareLog(("fbPitch: %u\n", pVMWARE->fbPitch));
VmwareLog(("fbSize: %u\n", pVMWARE->FbSize));
VmwareLog(("New dispWidth: %u\n", pScrn->displayWidth));
vgaHWProtect(pScrn, FALSE);
if (!pVMWARE->noAccel) {
if (!vmwareXAAModeInit(pScrn, mode)) {
return FALSE;
}
}
return TRUE;
}
static void
VMWAREAdjustFrame(int scrnIndex, int x, int y, int flags)
{
}
static void
VMWAREInitFIFO(ScrnInfoPtr pScrn)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
CARD32* vmwareFIFO;
TRACEPOINT
pVMWARE->mmioPhysBase = vmwareReadReg(pVMWARE, SVGA_REG_MEM_START);
pVMWARE->mmioSize = vmwareReadReg(pVMWARE, SVGA_REG_MEM_SIZE) & ~3;
pVMWARE->mmioVirtBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
pVMWARE->PciTag,
pVMWARE->mmioPhysBase,
pVMWARE->mmioSize);
vmwareFIFO = pVMWARE->vmwareFIFO = (CARD32*)pVMWARE->mmioVirtBase;
vmwareFIFO[SVGA_FIFO_MIN] = 4 * sizeof(CARD32);
vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->mmioSize;
vmwareFIFO[SVGA_FIFO_NEXT_CMD] = 4 * sizeof(CARD32);
vmwareFIFO[SVGA_FIFO_STOP] = 4 * sizeof(CARD32);
vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1);
}
static void
VMWAREStopFIFO(ScrnInfoPtr pScrn)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
TRACEPOINT
vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0);
xf86UnMapVidMem(pScrn->scrnIndex, pVMWARE->mmioVirtBase, pVMWARE->mmioSize);
}
static Bool
VMWARECloseScreen(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
ScreenPtr save = &pVMWARE->ScrnFuncs;
VmwareLog(("cursorSema: %d\n", pVMWARE->cursorSema));
if (*pVMWARE->pvtSema) {
if (pVMWARE->CursorInfoRec) {
vmwareCursorCloseScreen(pScreen);
}
if (pVMWARE->xaaInfo) {
vmwareXAACloseScreen(pScreen);
}
VMWARERestore(pScrn);
VMWAREUnmapMem(pScrn);
pScrn->vtSema = FALSE;
}
pScreen->CloseScreen = save->CloseScreen;
pScreen->SaveScreen = save->SaveScreen;
return (*pScreen->CloseScreen)(scrnIndex, pScreen);
}
static Bool
VMWARESaveScreen(ScreenPtr pScreen, int mode)
{
VmwareLog(("VMWareSaveScreen() mode = %d\n", mode));
return vgaHWSaveScreen(pScreen, mode);
}
static void
VMWAREPreDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
#ifdef DEBUG_LOG_UPDATES
{
int i;
for (i = 0; i < nboxes; i++) {
VmwareLog(("PreUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes - i,
boxPtr[i].x1, boxPtr[i].y1,
boxPtr[i].x2 - boxPtr[i].x1,
boxPtr[i].y2 - boxPtr[i].y1));
}
}
#endif
while (nboxes--) {
if (BOX_INTERSECT(*boxPtr, pVMWARE->hwcur.box)) {
PRE_OP_HIDE_CURSOR();
pVMWARE->cursorExcludedForUpdate = TRUE;
break;
}
boxPtr++;
}
}
static void
VMWAREPostDirtyBBUpdate(ScrnInfoPtr pScrn, int nboxes, BoxPtr boxPtr)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
while (nboxes--) {
#ifdef DEBUG_LOG_UPDATES
VmwareLog(("PostUpdate #%d (%d, %d, w = %d, h = %d)\n", nboxes,
boxPtr->x1, boxPtr->y1,
boxPtr->x2 - boxPtr->x1, boxPtr->y2 - boxPtr->y1));
#endif
if (boxPtr->y2 >= pVMWARE->ModeReg.svga_reg_height)
boxPtr->y2 = pVMWARE->ModeReg.svga_reg_height;
if (boxPtr->y1 >= pVMWARE->ModeReg.svga_reg_height)
boxPtr->y1 = pVMWARE->ModeReg.svga_reg_height;
if (boxPtr->y1 == boxPtr->y2) {
boxPtr++;
continue;
}
vmwareSendSVGACmdUpdate(pVMWARE, boxPtr++);
}
if (pVMWARE->hwCursor && pVMWARE->cursorExcludedForUpdate) {
POST_OP_SHOW_CURSOR();
pVMWARE->cursorExcludedForUpdate = FALSE;
}
}
static void
VMWARELoadPalette(ScrnInfoPtr pScrn, int numColors, int* indices,
LOCO* colors, VisualPtr pVisual)
{
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
int i;
for (i = 0; i < numColors; i++) {
vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 0, colors[*indices].red);
vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 1, colors[*indices].green);
vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + *indices * 3 + 2, colors[*indices].blue);
indices++;
}
VmwareLog(("Palette loading done\n"));
}
static Bool
VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
ScrnInfoPtr pScrn;
vgaHWPtr hwp;
VMWAREPtr pVMWARE;
pScrn = xf86Screens[pScreen->myNum];
pVMWARE = VMWAREPTR(pScrn);
hwp = VGAHWPTR(pScrn);
vgaHWGetIOBase(hwp);
VMWARESave(pScrn);
VMWAREInitFIFO(pScrn);
VMWAREModeInit(pScrn, pScrn->currentMode);
VMWAREAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
VMWAREMapMem(pScrn);
memset(pVMWARE->FbBase, 0, pVMWARE->FbSize);
vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
miClearVisualTypes();
if (pScrn->bitsPerPixel > 8) {
if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
pScrn->rgbBits, pScrn->defaultVisual)) {
return FALSE;
}
} else {
if (!miSetVisualTypes(pScrn->depth,
miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual)) {
return FALSE;
}
}
miSetPixmapDepths();
if (!fbScreenInit(pScreen, pVMWARE->FbBase + pVMWARE->fbOffset,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi,
pScrn->displayWidth,
pScrn->bitsPerPixel)) {
return FALSE;
}
if (pScrn->bitsPerPixel > 8) {
int i;
VisualPtr visual;
for (i = 0, visual = pScreen->visuals;
i < pScreen->numVisuals; i++, visual++) {
if ((visual->class | DynamicClass) == DirectColor) {
visual->offsetRed = pScrn->offset.red;
visual->offsetGreen = pScrn->offset.green;
visual->offsetBlue = pScrn->offset.blue;
visual->redMask = pScrn->mask.red;
visual->greenMask = pScrn->mask.green;
visual->blueMask = pScrn->mask.blue;
}
}
}
fbPictureInit (pScreen, 0, 0);
pVMWARE->ScrnFuncs = *pScreen;
pScreen->CloseScreen = VMWARECloseScreen;
pScreen->SaveScreen = VMWARESaveScreen;
xf86SetBlackWhitePixels(pScreen);
if (!ShadowFBInit2(pScreen,
pVMWARE->hwCursor ? VMWAREPreDirtyBBUpdate : NULL,
VMWAREPostDirtyBBUpdate)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"ShadowFB initialization failed\n");
return FALSE;
}
if (pVMWARE->hwCursor) {
vmwareCursorHookWrappers(pScreen);
}
if (!pVMWARE->noAccel) {
if (!vmwareXAAScreenInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"XAA initialization failed -- running unaccelerated!\n");
pVMWARE->noAccel = TRUE;
}
}
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
xf86SetSilkenMouse(pScreen);
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
if (pVMWARE->hwCursor) {
if (!vmwareCursorInit(pScreen)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware cursor initialization failed\n");
pVMWARE->hwCursor = FALSE;
}
}
if (!fbCreateDefColormap(pScreen))
return FALSE;
if (!xf86HandleColormaps(pScreen, 256, 8,
VMWARELoadPalette, NULL,
CMAP_PALETTED_TRUECOLOR |
CMAP_RELOAD_ON_MODE_SWITCH)) {
return FALSE;
}
if (serverGeneration == 1) {
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
}
return TRUE;
}
static Bool
VMWARESwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
{
return VMWAREModeInit(xf86Screens[scrnIndex], mode);
}
static Bool
VMWAREEnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
if (!pVMWARE->SavedReg.svga_fifo_enabled) {
VMWAREInitFIFO(pScrn);
}
return VMWAREModeInit(pScrn, pScrn->currentMode);
}
static void
VMWARELeaveVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
VMWARERestore(pScrn);
}
static void
VMWAREFreeScreen(int scrnIndex, int flags)
{
VMWAREFreeRec(xf86Screens[scrnIndex]);
}
static ModeStatus
VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
{
return MODE_OK;
}
static Bool
VMWAREProbe(DriverPtr drv, int flags)
{
int numDevSections, numUsed;
GDevPtr *devSections;
int *usedChips;
int i;
Bool foundScreen = FALSE;
char buildString[sizeof(VMWAREBuildStr)];
RewriteTagString(VMWAREBuildStr, buildString, sizeof(VMWAREBuildStr));
xf86MsgVerb(X_PROBED, 4, "%s", buildString);
numDevSections = xf86MatchDevice(VMWARE_DRIVER_NAME, &devSections);
if (numDevSections <= 0) {
#ifdef DEBUG
xf86MsgVerb(X_ERROR, 0, "No vmware driver section\n");
#endif
return FALSE;
}
if (xf86GetPciVideoInfo()) {
VmwareLog(("Some PCI Video Info Exists\n"));
numUsed = xf86MatchPciInstances(VMWARE_NAME, PCI_VENDOR_VMWARE,
VMWAREChipsets, VMWAREPciChipsets, devSections,
numDevSections, drv, &usedChips);
xfree(devSections);
if (numUsed <= 0)
return FALSE;
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else
for (i = 0; i < numUsed; i++) {
ScrnInfoPtr pScrn = NULL;
VmwareLog(("Even some VMware SVGA PCI instances exists\n"));
pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i],
VMWAREPciChipsets, NULL, NULL, NULL,
NULL, NULL);
if (pScrn) {
VmwareLog(("And even configuration suceeded\n"));
pScrn->driverVersion = VERSION;
pScrn->driverName = VMWARE_DRIVER_NAME;
pScrn->name = VMWARE_NAME;
pScrn->Probe = VMWAREProbe;
pScrn->PreInit = VMWAREPreInit;
pScrn->ScreenInit = VMWAREScreenInit;
pScrn->SwitchMode = VMWARESwitchMode;
pScrn->AdjustFrame = VMWAREAdjustFrame;
pScrn->EnterVT = VMWAREEnterVT;
pScrn->LeaveVT = VMWARELeaveVT;
pScrn->FreeScreen = VMWAREFreeScreen;
pScrn->ValidMode = VMWAREValidMode;
foundScreen = TRUE;
}
}
xfree(usedChips);
}
return foundScreen;
}
DriverRec VMWARE = {
VERSION,
VMWARE_DRIVER_NAME,
VMWAREIdentify,
VMWAREProbe,
VMWAREAvailableOptions,
NULL,
0
};
#ifdef XFree86LOADER
static MODULESETUPPROTO(vmwareSetup);
XF86ModuleData vmwareModuleData = { &vmwareVersRec, vmwareSetup, NULL };
static pointer
vmwareSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = FALSE;
if (!setupDone) {
setupDone = TRUE;
xf86AddDriver(&VMWARE, module, 0);
LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols,
shadowfbSymbols, vmwareXaaSymbols, NULL);
return (pointer)1;
}
if (errmaj) {
*errmaj = LDR_ONCEONLY;
}
return NULL;
}
#endif