diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 27 | ||||
-rw-r--r-- | src/svga_reg.h | 1433 | ||||
-rw-r--r-- | src/vmware.c | 547 | ||||
-rw-r--r-- | src/vmware_bootstrap.c | 503 | ||||
-rw-r--r-- | src/vmware_bootstrap.h | 59 | ||||
-rw-r--r-- | src/vmware_common.c | 163 | ||||
-rw-r--r-- | src/vmware_common.h | 41 | ||||
-rw-r--r-- | src/vmwaremodule.c | 256 |
8 files changed, 1875 insertions, 1154 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7c972cf..64a9069 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,12 +24,14 @@ # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -vmwlegacy_drv_la_LTLIBRARIES = vmwlegacy_drv.la -vmwlegacy_drv_la_LDFLAGS = -module -avoid-version -vmwlegacy_drv_la_CFLAGS = @XORG_CFLAGS@ -vmwlegacy_drv_ladir = @moduledir@/drivers +vmware_drv_la_LTLIBRARIES = vmware_drv.la +vmware_drv_la_LDFLAGS = -module -avoid-version +vmware_drv_la_CFLAGS = @XORG_CFLAGS@ +vmware_drv_ladir = @moduledir@/drivers +vmware_drv_la_LIBADD = @VMWGFX_LIBADD@ +vmware_drv_la_DEPENDENCIES = @VMWGFX_LIBADD@ -vmwlegacy_drv_la_SOURCES = \ +vmware_drv_la_SOURCES = \ bits2pixels.c \ bits2pixels.h \ guest_os.h \ @@ -50,13 +52,8 @@ vmwlegacy_drv_la_SOURCES = \ vmwarectrlproto.h \ vmwarexinerama.c \ vmwarevideo.c \ - vmwaremodes.c - -vmware_drv_la_LTLIBRARIES = vmware_drv.la -vmware_drv_la_LDFLAGS = -module -avoid-version -vmware_drv_la_CFLAGS = @XORG_CFLAGS@ @LIBDRM_CFLAGS@ -vmware_drv_la_LIBADD = @LIBDRM_LIBS@ -vmware_drv_ladir = @moduledir@/drivers - -vmware_drv_la_SOURCES = \ - vmwaremodule.c + vmwaremodes.c \ + vmware_bootstrap.h \ + vmware_bootstrap.c \ + vmware_common.c \ + vmware_common.h diff --git a/src/svga_reg.h b/src/svga_reg.h index 4fa363a..6757aa6 100644 --- a/src/svga_reg.h +++ b/src/svga_reg.h @@ -1,52 +1,81 @@ -/* ********************************************************** - * Copyright 1998 VMware, Inc. All rights reserved. - * **********************************************************/ +/********************************************************** + * Copyright 1998-2009 VMware, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + **********************************************************/ /* * svga_reg.h -- * - * SVGA hardware definitions + * Virtual hardware definitions for the VMware SVGA II device. */ #ifndef _SVGA_REG_H_ #define _SVGA_REG_H_ -#define INCLUDE_ALLOW_USERLEVEL -#define INCLUDE_ALLOW_VMMEXT -#define INCLUDE_ALLOW_VMCORE -#include "includeCheck.h" +/* + * PCI device IDs. + */ +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 /* - * Memory and port addresses and fundamental constants + * SVGA_REG_ENABLE bit definitions. */ +#define SVGA_REG_ENABLE_DISABLE 0 +#define SVGA_REG_ENABLE_ENABLE 1 +#define SVGA_REG_ENABLE_HIDE 2 +#define SVGA_REG_ENABLE_ENABLE_HIDE (SVGA_REG_ENABLE_ENABLE |\ + SVGA_REG_ENABLE_HIDE) /* - * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code. This - * isn't such a bad thing for forward compatibility. --Jeremy. + * Legal values for the SVGA_REG_CURSOR_ON register in old-fashioned + * cursor bypass mode. This is still supported, but no new guest + * drivers should use it. */ -#define SVGA_MAX_WIDTH 2360 -#define SVGA_MAX_HEIGHT 1770 -#define SVGA_MAX_BITS_PER_PIXEL 32 -#define SVGA_MAX_DEPTH 24 -#define SVGA_MAX_DISPLAYS 10 +#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */ +#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */ +#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */ /* - * The maximum size of the onscreen framebuffer. The size of the - * changeMap in the monitor is proportional to this number since it's - * the amount of memory we need to trace in VESA mode. Therefore, we'd + * The maximum framebuffer size that can traced for e.g. guests in VESA mode. + * The changeMap in the monitor is proportional to this number. Therefore, we'd * like to keep it as small as possible to reduce monitor overhead (using - * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area - * by over 4k!). + * SVGA_VRAM_MAX_SIZE for this increases the size of the shared area by over + * 4k!). + * + * NB: For compatibility reasons, this value must be greater than 0xff0000. + * See bug 335072. */ - -#define SVGA_FB_MAX_SIZE \ - ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \ - SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT) +#define SVGA_FB_MAX_TRACEABLE_SIZE 0x1000000 -#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 -#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) +#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 +#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) #define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS) +/* Base and Offset gets us headed the right way for PCI Base Addr Registers */ +#define SVGA_LEGACY_BASE_PORT 0x4560 + #define SVGA_MAGIC 0x900000UL #define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) @@ -63,19 +92,14 @@ #define SVGA_VERSION_0 0 #define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0) -/* Invalid SVGA_ID_ */ +/* "Invalid" value for all SVGA IDs. (Version ID, screen object ID, surface ID...) */ #define SVGA_ID_INVALID 0xFFFFFFFF -/* More backwards compatibility, old location of color map: */ -#define SVGA_OLD_PALETTE_BASE 17 - -/* Base and Offset gets us headed the right way for PCI Base Addr Registers */ -#define SVGA_LEGACY_BASE_PORT 0x4560 -#define SVGA_INDEX_PORT 0x0 -#define SVGA_VALUE_PORT 0x1 -#define SVGA_BIOS_PORT 0x2 -#define SVGA_NUM_PORTS 0x3 -#define SVGA_IRQSTATUS_PORT 0x8 +/* Port offsets, relative to BAR0 */ +#define SVGA_INDEX_PORT 0x0 +#define SVGA_VALUE_PORT 0x1 +#define SVGA_BIOS_PORT 0x2 +#define SVGA_IRQSTATUS_PORT 0x8 /* * Interrupt source flags for IRQSTATUS_PORT and IRQMASK. @@ -87,15 +111,6 @@ #define SVGA_IRQFLAG_FIFO_PROGRESS 0x2 /* Made forward progress in the FIFO */ #define SVGA_IRQFLAG_FENCE_GOAL 0x4 /* SVGA_FIFO_FENCE_GOAL reached */ -/* This port is deprecated, but retained because of old drivers. */ -#define SVGA_LEGACY_ACCEL_PORT 0x3 - -/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */ -#define SVGA_CURSOR_ON_HIDE 0x0 /* Must be 0 to maintain backward compatibility */ -#define SVGA_CURSOR_ON_SHOW 0x1 /* Must be 1 to maintain backward compatibility */ -#define SVGA_CURSOR_ON_REMOVE_FROM_FB 0x2 /* Remove the cursor from the framebuffer because we need to see what's under it */ -#define SVGA_CURSOR_ON_RESTORE_TO_FB 0x3 /* Put the cursor back in the framebuffer so the user can see it */ - /* * Registers */ @@ -108,13 +123,13 @@ enum { SVGA_REG_MAX_WIDTH = 4, SVGA_REG_MAX_HEIGHT = 5, SVGA_REG_DEPTH = 6, - SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ + SVGA_REG_BITS_PER_PIXEL = 7, /* Current bpp in the guest */ SVGA_REG_PSEUDOCOLOR = 8, SVGA_REG_RED_MASK = 9, SVGA_REG_GREEN_MASK = 10, SVGA_REG_BLUE_MASK = 11, SVGA_REG_BYTES_PER_LINE = 12, - SVGA_REG_FB_START = 13, + SVGA_REG_FB_START = 13, /* (Deprecated) */ SVGA_REG_FB_OFFSET = 14, SVGA_REG_VRAM_SIZE = 15, SVGA_REG_FB_SIZE = 16, @@ -122,33 +137,46 @@ enum { /* ID 0 implementation only had the above registers, then the palette */ SVGA_REG_CAPABILITIES = 17, - SVGA_REG_MEM_START = 18, /* Memory for command FIFO and bitmaps */ + SVGA_REG_MEM_START = 18, /* (Deprecated) */ SVGA_REG_MEM_SIZE = 19, - SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ - SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ - SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ - SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ - SVGA_REG_CURSOR_ID = 24, /* ID of cursor */ - SVGA_REG_CURSOR_X = 25, /* Set cursor X position */ - SVGA_REG_CURSOR_Y = 26, /* Set cursor Y position */ - SVGA_REG_CURSOR_ON = 27, /* Turn cursor on/off */ - SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */ - SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ - SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ - SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */ - SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ - SVGA_REG_IRQMASK = 33, /* Interrupt mask */ + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* See "FIFO Synchronization Registers" */ + SVGA_REG_BUSY = 22, /* See "FIFO Synchronization Registers" */ + SVGA_REG_GUEST_ID = 23, /* Set guest OS identifier */ + SVGA_REG_CURSOR_ID = 24, /* (Deprecated) */ + SVGA_REG_CURSOR_X = 25, /* (Deprecated) */ + SVGA_REG_CURSOR_Y = 26, /* (Deprecated) */ + SVGA_REG_CURSOR_ON = 27, /* (Deprecated) */ + SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* (Deprecated) */ + SVGA_REG_SCRATCH_SIZE = 29, /* Number of scratch registers */ + SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */ + SVGA_REG_NUM_DISPLAYS = 31, /* (Deprecated) */ + SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */ + SVGA_REG_IRQMASK = 33, /* Interrupt mask */ + + /* Legacy multi-monitor support */ SVGA_REG_NUM_GUEST_DISPLAYS = 34,/* Number of guest displays in X/Y direction */ - SVGA_REG_DISPLAY_ID = 35, /* The display ID for the following display attributes */ + SVGA_REG_DISPLAY_ID = 35, /* Display ID for the following display attributes */ SVGA_REG_DISPLAY_IS_PRIMARY = 36,/* Whether this is a primary display */ SVGA_REG_DISPLAY_POSITION_X = 37,/* The display position x */ SVGA_REG_DISPLAY_POSITION_Y = 38,/* The display position y */ SVGA_REG_DISPLAY_WIDTH = 39, /* The display's width */ SVGA_REG_DISPLAY_HEIGHT = 40, /* The display's height */ - SVGA_REG_TOP = 41, /* Must be 1 more than the last register */ - SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ + /* See "Guest memory regions" below. */ + SVGA_REG_GMR_ID = 41, + SVGA_REG_GMR_DESCRIPTOR = 42, + SVGA_REG_GMR_MAX_IDS = 43, + SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH = 44, + + SVGA_REG_TRACES = 45, /* Enable trace-based updates even when FIFO is on */ + SVGA_REG_GMRS_MAX_PAGES = 46, /* Maximum number of 4KB pages for all GMRs */ + SVGA_REG_MEMORY_SIZE = 47, /* Total dedicated device memory excluding FIFO */ + SVGA_REG_TOP = 48, /* Must be 1 more than the last register */ + + SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */ /* Next 768 (== 256*3) registers exist for colormap */ + SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS /* Base of scratch registers */ /* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage: @@ -156,126 +184,264 @@ enum { the use of the current SVGA driver. */ }; +/* + * Macros to compute variable length items (sizes in 32-bit words, except + * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes). + */ +#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h)) +#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h)) +#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) +#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) /* - * Capabilities + * Guest memory regions (GMRs): + * + * This is a new memory mapping feature available in SVGA devices + * which have the SVGA_CAP_GMR bit set. Previously, there were two + * fixed memory regions available with which to share data between the + * device and the driver: the FIFO ('MEM') and the framebuffer. GMRs + * are our name for an extensible way of providing arbitrary DMA + * buffers for use between the driver and the SVGA device. They are a + * new alternative to framebuffer memory, usable for both 2D and 3D + * graphics operations. + * + * Since GMR mapping must be done synchronously with guest CPU + * execution, we use a new pair of SVGA registers: + * + * SVGA_REG_GMR_ID -- + * + * Read/write. + * This register holds the 32-bit ID (a small positive integer) + * of a GMR to create, delete, or redefine. Writing this register + * has no side-effects. + * + * SVGA_REG_GMR_DESCRIPTOR -- + * + * Write-only. + * Writing this register will create, delete, or redefine the GMR + * specified by the above ID register. If this register is zero, + * the GMR is deleted. Any pointers into this GMR (including those + * currently being processed by FIFO commands) will be + * synchronously invalidated. + * + * If this register is nonzero, it must be the physical page + * number (PPN) of a data structure which describes the physical + * layout of the memory region this GMR should describe. The + * descriptor structure will be read synchronously by the SVGA + * device when this register is written. The descriptor need not + * remain allocated for the lifetime of the GMR. + * + * The guest driver should write SVGA_REG_GMR_ID first, then + * SVGA_REG_GMR_DESCRIPTOR. + * + * SVGA_REG_GMR_MAX_IDS -- + * + * Read-only. + * The SVGA device may choose to support a maximum number of + * user-defined GMR IDs. This register holds the number of supported + * IDs. (The maximum supported ID plus 1) + * + * SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH -- + * + * Read-only. + * The SVGA device may choose to put a limit on the total number + * of SVGAGuestMemDescriptor structures it will read when defining + * a single GMR. + * + * The descriptor structure is an array of SVGAGuestMemDescriptor + * structures. Each structure may do one of three things: + * + * - Terminate the GMR descriptor list. + * (ppn==0, numPages==0) + * + * - Add a PPN or range of PPNs to the GMR's virtual address space. + * (ppn != 0, numPages != 0) + * + * - Provide the PPN of the next SVGAGuestMemDescriptor, in order to + * support multi-page GMR descriptor tables without forcing the + * driver to allocate physically contiguous memory. + * (ppn != 0, numPages == 0) + * + * Note that each physical page of SVGAGuestMemDescriptor structures + * can describe at least 2MB of guest memory. If the driver needs to + * use more than one page of descriptor structures, it must use one of + * its SVGAGuestMemDescriptors to point to an additional page. The + * device will never automatically cross a page boundary. + * + * Once the driver has described a GMR, it is immediately available + * for use via any FIFO command that uses an SVGAGuestPtr structure. + * These pointers include a GMR identifier plus an offset into that + * GMR. + * + * The driver must check the SVGA_CAP_GMR bit before using the GMR + * registers. */ -#define SVGA_CAP_NONE 0x00000000 -#define SVGA_CAP_RECT_FILL 0x00000001 -#define SVGA_CAP_RECT_COPY 0x00000002 -#define SVGA_CAP_RECT_PAT_FILL 0x00000004 -#define SVGA_CAP_LEGACY_OFFSCREEN 0x00000008 -#define SVGA_CAP_RASTER_OP 0x00000010 -#define SVGA_CAP_CURSOR 0x00000020 -#define SVGA_CAP_CURSOR_BYPASS 0x00000040 -#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 -#define SVGA_CAP_8BIT_EMULATION 0x00000100 -#define SVGA_CAP_ALPHA_CURSOR 0x00000200 -#define SVGA_CAP_GLYPH 0x00000400 -#define SVGA_CAP_GLYPH_CLIPPING 0x00000800 -#define SVGA_CAP_OFFSCREEN_1 0x00001000 -#define SVGA_CAP_ALPHA_BLEND 0x00002000 -#define SVGA_CAP_3D 0x00004000 -#define SVGA_CAP_EXTENDED_FIFO 0x00008000 -#define SVGA_CAP_MULTIMON 0x00010000 -#define SVGA_CAP_PITCHLOCK 0x00020000 -#define SVGA_CAP_IRQMASK 0x00040000 -#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 +/* + * Special GMR IDs, allowing SVGAGuestPtrs to point to framebuffer + * memory as well. In the future, these IDs could even be used to + * allow legacy memory regions to be redefined by the guest as GMRs. + * + * Using the guest framebuffer (GFB) at BAR1 for general purpose DMA + * is being phased out. Please try to use user-defined GMRs whenever + * possible. + */ +#define SVGA_GMR_NULL ((uint32) -1) +#define SVGA_GMR_FRAMEBUFFER ((uint32) -2) /* Guest Framebuffer (GFB) */ + +typedef +struct SVGAGuestMemDescriptor { + uint32 ppn; + uint32 numPages; +} SVGAGuestMemDescriptor; + +typedef +struct SVGAGuestPtr { + uint32 gmrId; + uint32 offset; +} SVGAGuestPtr; /* - * Raster op codes (same encoding as X) used by FIFO drivers. + * SVGAGMRImageFormat -- + * + * This is a packed representation of the source 2D image format + * for a GMR-to-screen blit. Currently it is defined as an encoding + * of the screen's color depth and bits-per-pixel, however, 16 bits + * are reserved for future use to identify other encodings (such as + * RGBA or higher-precision images). + * + * Currently supported formats: + * + * bpp depth Format Name + * --- ----- ----------- + * 32 24 32-bit BGRX + * 24 24 24-bit BGR + * 16 16 RGB 5-6-5 + * 16 15 RGB 5-5-5 + * */ -#define SVGA_ROP_CLEAR 0x00 /* 0 */ -#define SVGA_ROP_AND 0x01 /* src AND dst */ -#define SVGA_ROP_AND_REVERSE 0x02 /* src AND NOT dst */ -#define SVGA_ROP_COPY 0x03 /* src */ -#define SVGA_ROP_AND_INVERTED 0x04 /* NOT src AND dst */ -#define SVGA_ROP_NOOP 0x05 /* dst */ -#define SVGA_ROP_XOR 0x06 /* src XOR dst */ -#define SVGA_ROP_OR 0x07 /* src OR dst */ -#define SVGA_ROP_NOR 0x08 /* NOT src AND NOT dst */ -#define SVGA_ROP_EQUIV 0x09 /* NOT src XOR dst */ -#define SVGA_ROP_INVERT 0x0a /* NOT dst */ -#define SVGA_ROP_OR_REVERSE 0x0b /* src OR NOT dst */ -#define SVGA_ROP_COPY_INVERTED 0x0c /* NOT src */ -#define SVGA_ROP_OR_INVERTED 0x0d /* NOT src OR dst */ -#define SVGA_ROP_NAND 0x0e /* NOT src OR NOT dst */ -#define SVGA_ROP_SET 0x0f /* 1 */ -#define SVGA_ROP_UNSUPPORTED 0x10 +typedef +struct SVGAGMRImageFormat { + union { + struct { + uint32 bitsPerPixel : 8; + uint32 colorDepth : 8; + uint32 reserved : 16; /* Must be zero */ + }; -#define SVGA_NUM_SUPPORTED_ROPS 16 -#define SVGA_ROP_ALL (MASK(SVGA_NUM_SUPPORTED_ROPS)) -#define SVGA_IS_VALID_ROP(rop) (rop < SVGA_NUM_SUPPORTED_ROPS) + uint32 value; + }; +} SVGAGMRImageFormat; -#define SVGA_INVALID_DISPLAY_ID ((uint32)-1) +typedef +struct SVGAGuestImage { + SVGAGuestPtr ptr; + + /* + * A note on interpretation of pitch: This value of pitch is the + * number of bytes between vertically adjacent image + * blocks. Normally this is the number of bytes between the first + * pixel of two adjacent scanlines. With compressed textures, + * however, this may represent the number of bytes between + * compression blocks rather than between rows of pixels. + * + * XXX: Compressed textures currently must be tightly packed in guest memory. + * + * If the image is 1-dimensional, pitch is ignored. + * + * If 'pitch' is zero, the SVGA3D device calculates a pitch value + * assuming each row of blocks is tightly packed. + */ + uint32 pitch; +} SVGAGuestImage; /* - * Ops - * For each pixel, the four channels of the image are computed with: - * - * C = Ca * Fa + Cb * Fb - * - * where C, Ca, Cb are the values of the respective channels and Fa - * and Fb come from the following table: - * - * BlendOp Fa Fb - * ------------------------------------------ - * Clear 0 0 - * Src 1 0 - * Dst 0 1 - * Over 1 1-Aa - * OverReverse 1-Ab 1 - * In Ab 0 - * InReverse 0 Aa - * Out 1-Ab 0 - * OutReverse 0 1-Aa - * Atop Ab 1-Aa - * AtopReverse 1-Ab Aa - * Xor 1-Ab 1-Aa - * Add 1 1 - * Saturate min(1,(1-Ab)/Aa) 1 - * - * Flags - * You can use the following flags to achieve additional affects: - * - * Flag Effect - * ------------------------------------------ - * ConstantSourceAlpha Ca = Ca * Param0 - * ConstantDestAlpha Cb = Cb * Param1 - * - * Flag effects resolve before the op. For example - * BlendOp == Add && Flags == ConstantSourceAlpha | - * ConstantDestAlpha results in: - * - * C = (Ca * Param0) + (Cb * Param1) - */ - -#define SVGA_BLENDOP_CLEAR 0 -#define SVGA_BLENDOP_SRC 1 -#define SVGA_BLENDOP_DST 2 -#define SVGA_BLENDOP_OVER 3 -#define SVGA_BLENDOP_OVER_REVERSE 4 -#define SVGA_BLENDOP_IN 5 -#define SVGA_BLENDOP_IN_REVERSE 6 -#define SVGA_BLENDOP_OUT 7 -#define SVGA_BLENDOP_OUT_REVERSE 8 -#define SVGA_BLENDOP_ATOP 9 -#define SVGA_BLENDOP_ATOP_REVERSE 10 -#define SVGA_BLENDOP_XOR 11 -#define SVGA_BLENDOP_ADD 12 -#define SVGA_BLENDOP_SATURATE 13 - -#define SVGA_NUM_BLENDOPS 14 -#define SVGA_IS_VALID_BLENDOP(op) (op >= 0 && op < SVGA_NUM_BLENDOPS) - -#define SVGA_BLENDFLAG_CONSTANT_SOURCE_ALPHA 0x01 -#define SVGA_BLENDFLAG_CONSTANT_DEST_ALPHA 0x02 -#define SVGA_NUM_BLENDFLAGS 2 -#define SVGA_BLENDFLAG_ALL (MASK(SVGA_NUM_BLENDFLAGS)) -#define SVGA_IS_VALID_BLENDFLAG(flag) ((flag & ~SVGA_BLENDFLAG_ALL) == 0) + * SVGAColorBGRX -- + * + * A 24-bit color format (BGRX), which does not depend on the + * format of the legacy guest framebuffer (GFB) or the current + * GMRFB state. + */ + +typedef +struct SVGAColorBGRX { + union { + struct { + uint32 b : 8; + uint32 g : 8; + uint32 r : 8; + uint32 x : 8; /* Unused */ + }; + + uint32 value; + }; +} SVGAColorBGRX; + + +/* + * SVGASignedRect -- + * SVGASignedPoint -- + * + * Signed rectangle and point primitives. These are used by the new + * 2D primitives for drawing to Screen Objects, which can occupy a + * signed virtual coordinate space. + * + * SVGASignedRect specifies a half-open interval: the (left, top) + * pixel is part of the rectangle, but the (right, bottom) pixel is + * not. + */ + +typedef +struct SVGASignedRect { + int32 left; + int32 top; + int32 right; + int32 bottom; +} SVGASignedRect; + +typedef +struct SVGASignedPoint { + int32 x; + int32 y; +} SVGASignedPoint; + + +/* + * Capabilities + * + * Note the holes in the bitfield. Missing bits have been deprecated, + * and must not be reused. Those capabilities will never be reported + * by new versions of the SVGA device. + * + * SVGA_CAP_GMR2 -- + * Provides asynchronous commands to define and remap guest memory + * regions. Adds device registers SVGA_REG_GMRS_MAX_PAGES and + * SVGA_REG_MEMORY_SIZE. + * + * SVGA_CAP_SCREEN_OBJECT_2 -- + * Allow screen object support, and require backing stores from the + * guest for each screen object. + */ + +#define SVGA_CAP_NONE 0x00000000 +#define SVGA_CAP_RECT_COPY 0x00000002 +#define SVGA_CAP_CURSOR 0x00000020 +#define SVGA_CAP_CURSOR_BYPASS 0x00000040 /* Legacy (Use Cursor Bypass 3 instead) */ +#define SVGA_CAP_CURSOR_BYPASS_2 0x00000080 /* Legacy (Use Cursor Bypass 3 instead) */ +#define SVGA_CAP_8BIT_EMULATION 0x00000100 +#define SVGA_CAP_ALPHA_CURSOR 0x00000200 +#define SVGA_CAP_3D 0x00004000 +#define SVGA_CAP_EXTENDED_FIFO 0x00008000 +#define SVGA_CAP_MULTIMON 0x00010000 /* Legacy multi-monitor support */ +#define SVGA_CAP_PITCHLOCK 0x00020000 +#define SVGA_CAP_IRQMASK 0x00040000 +#define SVGA_CAP_DISPLAY_TOPOLOGY 0x00080000 /* Legacy multi-monitor support */ +#define SVGA_CAP_GMR 0x00100000 +#define SVGA_CAP_TRACES 0x00200000 +#define SVGA_CAP_GMR2 0x00400000 +#define SVGA_CAP_SCREEN_OBJECT_2 0x00800000 /* @@ -332,19 +498,47 @@ enum { * These in block 3a, the VMX currently considers mandatory for the * extended FIFO. */ - + /* Valid if exists (i.e. if extended FIFO enabled): */ SVGA_FIFO_3D_HWVERSION, /* See SVGA3dHardwareVersion in svga3d_reg.h */ /* Valid with SVGA_FIFO_CAP_PITCHLOCK: */ SVGA_FIFO_PITCHLOCK, + /* Valid with SVGA_FIFO_CAP_CURSOR_BYPASS_3: */ SVGA_FIFO_CURSOR_ON, /* Cursor bypass 3 show/hide register */ SVGA_FIFO_CURSOR_X, /* Cursor bypass 3 x register */ SVGA_FIFO_CURSOR_Y, /* Cursor bypass 3 y register */ SVGA_FIFO_CURSOR_COUNT, /* Incremented when any of the other 3 change */ SVGA_FIFO_CURSOR_LAST_UPDATED,/* Last time the host updated the cursor */ + /* Valid with SVGA_FIFO_CAP_RESERVE: */ SVGA_FIFO_RESERVED, /* Bytes past NEXT_CMD with real contents */ + + /* + * Valid with SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2: + * + * By default this is SVGA_ID_INVALID, to indicate that the cursor + * coordinates are specified relative to the virtual root. If this + * is set to a specific screen ID, cursor position is reinterpreted + * as a signed offset relative to that screen's origin. + */ + SVGA_FIFO_CURSOR_SCREEN_ID, + + /* + * Valid with SVGA_FIFO_CAP_DEAD + * + * An arbitrary value written by the host, drivers should not use it. + */ + SVGA_FIFO_DEAD, + + /* + * Valid with SVGA_FIFO_CAP_3D_HWVERSION_REVISED: + * + * Contains 3D HWVERSION (see SVGA3dHardwareVersion in svga3d_reg.h) + * on platforms that can enforce graphics resource limits. + */ + SVGA_FIFO_3D_HWVERSION_REVISED, + /* * XXX: The gap here, up until SVGA_FIFO_3D_CAPS, can be used for new * registers, but this must be done carefully and with judicious use of @@ -361,6 +555,7 @@ enum { * before 3D_CAPS, needs to reason about something other than * SVGA_FIFO_MIN. */ + /* * 3D caps block space; valid with 3D hardware version >= * SVGA3D_HWVERSION_WS6_B1. @@ -533,6 +728,87 @@ enum { * Pitch Lock -- Pitch lock register is supported * Video -- SVGA Video overlay units are supported * Escape -- Escape command is supported + * + * XXX: Add longer descriptions for each capability, including a list + * of the new features that each capability provides. + * + * SVGA_FIFO_CAP_SCREEN_OBJECT -- + * + * Provides dynamic multi-screen rendering, for improved Unity and + * multi-monitor modes. With Screen Object, the guest can + * dynamically create and destroy 'screens', which can represent + * Unity windows or virtual monitors. Screen Object also provides + * strong guarantees that DMA operations happen only when + * guest-initiated. Screen Object deprecates the BAR1 guest + * framebuffer (GFB) and all commands that work only with the GFB. + * + * New registers: + * FIFO_CURSOR_SCREEN_ID, VIDEO_DATA_GMRID, VIDEO_DST_SCREEN_ID + * + * New 2D commands: + * DEFINE_SCREEN, DESTROY_SCREEN, DEFINE_GMRFB, BLIT_GMRFB_TO_SCREEN, + * BLIT_SCREEN_TO_GMRFB, ANNOTATION_FILL, ANNOTATION_COPY + * + * New 3D commands: + * BLIT_SURFACE_TO_SCREEN + * + * New guarantees: + * + * - The host will not read or write guest memory, including the GFB, + * except when explicitly initiated by a DMA command. + * + * - All DMA, including legacy DMA like UPDATE and PRESENT_READBACK, + * is guaranteed to complete before any subsequent FENCEs. + * + * - All legacy commands which affect a Screen (UPDATE, PRESENT, + * PRESENT_READBACK) as well as new Screen blit commands will + * all behave consistently as blits, and memory will be read + * or written in FIFO order. + * + * For example, if you PRESENT from one SVGA3D surface to multiple + * places on the screen, the data copied will always be from the + * SVGA3D surface at the time the PRESENT was issued in the FIFO. + * This was not necessarily true on devices without Screen Object. + * + * This means that on devices that support Screen Object, the + * PRESENT_READBACK command should not be necessary unless you + * actually want to read back the results of 3D rendering into + * system memory. (And for that, the BLIT_SCREEN_TO_GMRFB + * command provides a strict superset of functionality.) + * + * - When a screen is resized, either using Screen Object commands or + * legacy multimon registers, its contents are preserved. + * + * SVGA_FIFO_CAP_GMR2 -- + * + * Provides new commands to define and remap guest memory regions (GMR). + * + * New 2D commands: + * DEFINE_GMR2, REMAP_GMR2. + * + * SVGA_FIFO_CAP_3D_HWVERSION_REVISED -- + * + * Indicates new register SVGA_FIFO_3D_HWVERSION_REVISED exists. + * This register may replace SVGA_FIFO_3D_HWVERSION on platforms + * that enforce graphics resource limits. This allows the platform + * to clear SVGA_FIFO_3D_HWVERSION and disable 3D in legacy guest + * drivers that do not limit their resources. + * + * Note this is an alias to SVGA_FIFO_CAP_GMR2 because these indicators + * are codependent (and thus we use a single capability bit). + * + * SVGA_FIFO_CAP_SCREEN_OBJECT_2 -- + * + * Modifies the DEFINE_SCREEN command to include a guest provided + * backing store in GMR memory and the bytesPerLine for the backing + * store. This capability requires the use of a backing store when + * creating screen objects. However if SVGA_FIFO_CAP_SCREEN_OBJECT + * is present then backing stores are optional. + * + * SVGA_FIFO_CAP_DEAD -- + * + * Drivers should not use this cap bit. This cap bit can not be + * reused since some hosts already expose it. */ #define SVGA_FIFO_CAP_NONE 0 @@ -543,6 +819,11 @@ enum { #define SVGA_FIFO_CAP_CURSOR_BYPASS_3 (1<<4) #define SVGA_FIFO_CAP_ESCAPE (1<<5) #define SVGA_FIFO_CAP_RESERVE (1<<6) +#define SVGA_FIFO_CAP_SCREEN_OBJECT (1<<7) +#define SVGA_FIFO_CAP_GMR2 (1<<8) +#define SVGA_FIFO_CAP_3D_HWVERSION_REVISED SVGA_FIFO_CAP_GMR2 +#define SVGA_FIFO_CAP_SCREEN_OBJECT_2 (1<<9) +#define SVGA_FIFO_CAP_DEAD (1<<10) /* @@ -586,20 +867,22 @@ enum { SVGA_VIDEO_DATA_OFFSET, SVGA_VIDEO_FORMAT, SVGA_VIDEO_COLORKEY, - SVGA_VIDEO_SIZE, + SVGA_VIDEO_SIZE, /* Deprecated */ SVGA_VIDEO_WIDTH, SVGA_VIDEO_HEIGHT, SVGA_VIDEO_SRC_X, SVGA_VIDEO_SRC_Y, SVGA_VIDEO_SRC_WIDTH, SVGA_VIDEO_SRC_HEIGHT, - SVGA_VIDEO_DST_X, - SVGA_VIDEO_DST_Y, + SVGA_VIDEO_DST_X, /* Signed int32 */ + SVGA_VIDEO_DST_Y, /* Signed int32 */ SVGA_VIDEO_DST_WIDTH, SVGA_VIDEO_DST_HEIGHT, SVGA_VIDEO_PITCH_1, SVGA_VIDEO_PITCH_2, SVGA_VIDEO_PITCH_3, + SVGA_VIDEO_DATA_GMRID, /* Optional, defaults to SVGA_GMR_FRAMEBUFFER */ + SVGA_VIDEO_DST_SCREEN_ID, /* Optional, defaults to virtual coords (SVGA_ID_INVALID) */ SVGA_VIDEO_NUM_REGS }; @@ -625,242 +908,658 @@ typedef struct SVGAOverlayUnit { uint32 srcY; uint32 srcWidth; uint32 srcHeight; - uint32 dstX; - uint32 dstY; + int32 dstX; + int32 dstY; uint32 dstWidth; uint32 dstHeight; uint32 pitches[3]; + uint32 dataGMRId; + uint32 dstScreenId; } SVGAOverlayUnit; /* - * Drawing object ID's, in the range 0 to SVGA_MAX_ID + * SVGAScreenObject -- + * + * This is a new way to represent a guest's multi-monitor screen or + * Unity window. Screen objects are only supported if the + * SVGA_FIFO_CAP_SCREEN_OBJECT capability bit is set. + * + * If Screen Objects are supported, they can be used to fully + * replace the functionality provided by the framebuffer registers + * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY. + * + * The screen object is a struct with guaranteed binary + * compatibility. New flags can be added, and the struct may grow, + * but existing fields must retain their meaning. + * + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2 are required fields of + * a SVGAGuestPtr that is used to back the screen contents. This + * memory must come from the GFB. The guest is not allowed to + * access the memory and doing so will have undefined results. The + * backing store is required to be page aligned and the size is + * padded to the next page boundry. The number of pages is: + * (bytesPerLine * size.width * 4 + PAGE_SIZE - 1) / PAGE_SIZE + * + * The pitch in the backingStore is required to be at least large + * enough to hold a 32bbp scanline. It is recommended that the + * driver pad bytesPerLine for a potential performance win. + * + * The cloneCount field is treated as a hint from the guest that + * the user wants this display to be cloned, countCount times. A + * value of zero means no cloning should happen. */ -#define SVGA_MAX_ID 499 +#define SVGA_SCREEN_MUST_BE_SET (1 << 0) /* Must be set or results undefined */ +#define SVGA_SCREEN_HAS_ROOT SVGA_SCREEN_MUST_BE_SET /* Deprecated */ +#define SVGA_SCREEN_IS_PRIMARY (1 << 1) /* Guest considers this screen to be 'primary' */ +#define SVGA_SCREEN_FULLSCREEN_HINT (1 << 2) /* Guest is running a fullscreen app here */ /* - * Macros to compute variable length items (sizes in 32-bit words, except - * for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes). + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When the screen is + * deactivated the base layer is defined to lose all contents and + * become black. When a screen is deactivated the backing store is + * optional. When set backingPtr and bytesPerLine will be ignored. */ +#define SVGA_SCREEN_DEACTIVATE (1 << 3) + +/* + * Added with SVGA_FIFO_CAP_SCREEN_OBJECT_2. When this flag is set + * the screen contents will be outputted as all black to the user + * though the base layer contents is preserved. The screen base layer + * can still be read and written to like normal though the no visible + * effect will be seen by the user. When the flag is changed the + * screen will be blanked or redrawn to the current contents as needed + * without any extra commands from the driver. This flag only has an + * effect when the screen is not deactivated. + */ +#define SVGA_SCREEN_BLANKING (1 << 4) + +typedef +struct SVGAScreenObject { + uint32 structSize; /* sizeof(SVGAScreenObject) */ + uint32 id; + uint32 flags; + struct { + uint32 width; + uint32 height; + } size; + struct { + int32 x; + int32 y; + } root; + + /* + * Added and required by SVGA_FIFO_CAP_SCREEN_OBJECT_2, optional + * with SVGA_FIFO_CAP_SCREEN_OBJECT. + */ + SVGAGuestImage backingStore; + uint32 cloneCount; +} SVGAScreenObject; -#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h)) -#define SVGA_BITMAP_SCANLINE_SIZE(w) (( (w)+31 ) >> 5) -#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h)) -#define SVGA_PIXMAP_SCANLINE_SIZE(w,bpp) (( ((w)*(bpp))+31 ) >> 5) -#define SVGA_GLYPH_SIZE(w,h) ((((((w) + 7) >> 3) * (h)) + 3) >> 2) -#define SVGA_GLYPH_SCANLINE_SIZE(w) (((w) + 7) >> 3) -#define SVGA_ESCAPE_SIZE(s) (((s) + 3) >> 2) /* - * Increment from one scanline to the next of a bitmap or pixmap + * Commands in the command FIFO: + * + * Command IDs defined below are used for the traditional 2D FIFO + * communication (not all commands are available for all versions of the + * SVGA FIFO protocol). + * + * Note the holes in the command ID numbers: These commands have been + * deprecated, and the old IDs must not be reused. + * + * Command IDs from 1000 to 1999 are reserved for use by the SVGA3D + * protocol. + * + * Each command's parameters are described by the comments and + * structs below. */ -#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) -#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) + +typedef enum { + SVGA_CMD_INVALID_CMD = 0, + SVGA_CMD_UPDATE = 1, + SVGA_CMD_RECT_COPY = 3, + SVGA_CMD_DEFINE_CURSOR = 19, + SVGA_CMD_DEFINE_ALPHA_CURSOR = 22, + SVGA_CMD_UPDATE_VERBOSE = 25, + SVGA_CMD_FRONT_ROP_FILL = 29, + SVGA_CMD_FENCE = 30, + SVGA_CMD_ESCAPE = 33, + SVGA_CMD_DEFINE_SCREEN = 34, + SVGA_CMD_DESTROY_SCREEN = 35, + SVGA_CMD_DEFINE_GMRFB = 36, + SVGA_CMD_BLIT_GMRFB_TO_SCREEN = 37, + SVGA_CMD_BLIT_SCREEN_TO_GMRFB = 38, + SVGA_CMD_ANNOTATION_FILL = 39, + SVGA_CMD_ANNOTATION_COPY = 40, + SVGA_CMD_DEFINE_GMR2 = 41, + SVGA_CMD_REMAP_GMR2 = 42, + SVGA_CMD_MAX +} SVGAFifoCmdId; + +#define SVGA_CMD_MAX_ARGS 64 + /* - * Transparent color for DRAW_GLYPH_CLIPPED + * SVGA_CMD_UPDATE -- + * + * This is a DMA transfer which copies from the Guest Framebuffer + * (GFB) at BAR1 + SVGA_REG_FB_OFFSET to any screens which + * intersect with the provided virtual rectangle. + * + * This command does not support using arbitrary guest memory as a + * data source- it only works with the pre-defined GFB memory. + * This command also does not support signed virtual coordinates. + * If you have defined screens (using SVGA_CMD_DEFINE_SCREEN) with + * negative root x/y coordinates, the negative portion of those + * screens will not be reachable by this command. + * + * This command is not necessary when using framebuffer + * traces. Traces are automatically enabled if the SVGA FIFO is + * disabled, and you may explicitly enable/disable traces using + * SVGA_REG_TRACES. With traces enabled, any write to the GFB will + * automatically act as if a subsequent SVGA_CMD_UPDATE was issued. + * + * Traces and SVGA_CMD_UPDATE are the only supported ways to render + * pseudocolor screen updates. The newer Screen Object commands + * only support true color formats. + * + * Availability: + * Always available. */ -#define SVGA_COLOR_TRANSPARENT (~0) + +typedef +struct SVGAFifoCmdUpdate { + uint32 x; + uint32 y; + uint32 width; + uint32 height; +} SVGAFifoCmdUpdate; + /* - * Commands in the command FIFO + * SVGA_CMD_RECT_COPY -- + * + * Perform a rectangular DMA transfer from one area of the GFB to + * another, and copy the result to any screens which intersect it. + * + * Availability: + * SVGA_CAP_RECT_COPY */ -#define SVGA_CMD_INVALID_CMD 0 - /* FIFO layout: - <nothing> (well, undefined) */ +typedef +struct SVGAFifoCmdRectCopy { + uint32 srcX; + uint32 srcY; + uint32 destX; + uint32 destY; + uint32 width; + uint32 height; +} SVGAFifoCmdRectCopy; -#define SVGA_CMD_UPDATE 1 - /* FIFO layout: - X, Y, Width, Height */ -#define SVGA_CMD_RECT_FILL 2 - /* FIFO layout: - Color, X, Y, Width, Height */ +/* + * SVGA_CMD_DEFINE_CURSOR -- + * + * Provide a new cursor image, as an AND/XOR mask. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_CURSOR + */ -#define SVGA_CMD_RECT_COPY 3 - /* FIFO layout: - Source X, Source Y, Dest X, Dest Y, Width, Height */ +typedef +struct SVGAFifoCmdDefineCursor { + uint32 id; /* Reserved, must be zero. */ + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + uint32 andMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ + uint32 xorMaskDepth; /* Value must be 1 or equal to BITS_PER_PIXEL */ + /* + * Followed by scanline data for AND mask, then XOR mask. + * Each scanline is padded to a 32-bit boundary. + */ +} SVGAFifoCmdDefineCursor; -#define SVGA_CMD_DEFINE_BITMAP 4 - /* FIFO layout: - Pixmap ID, Width, Height, <scanlines> */ -#define SVGA_CMD_DEFINE_BITMAP_SCANLINE 5 - /* FIFO layout: - Pixmap ID, Width, Height, Line #, scanline */ +/* + * SVGA_CMD_DEFINE_ALPHA_CURSOR -- + * + * Provide a new cursor image, in 32-bit BGRA format. + * + * The recommended way to position the cursor overlay is by using + * the SVGA_FIFO_CURSOR_* registers, supported by the + * SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability. + * + * Availability: + * SVGA_CAP_ALPHA_CURSOR + */ -#define SVGA_CMD_DEFINE_PIXMAP 6 - /* FIFO layout: - Pixmap ID, Width, Height, Depth, <scanlines> */ +typedef +struct SVGAFifoCmdDefineAlphaCursor { + uint32 id; /* Reserved, must be zero. */ + uint32 hotspotX; + uint32 hotspotY; + uint32 width; + uint32 height; + /* Followed by scanline data */ +} SVGAFifoCmdDefineAlphaCursor; -#define SVGA_CMD_DEFINE_PIXMAP_SCANLINE 7 - /* FIFO layout: - Pixmap ID, Width, Height, Depth, Line #, scanline */ -#define SVGA_CMD_RECT_BITMAP_FILL 8 - /* FIFO layout: - Bitmap ID, X, Y, Width, Height, Foreground, Background */ +/* + * SVGA_CMD_UPDATE_VERBOSE -- + * + * Just like SVGA_CMD_UPDATE, but also provide a per-rectangle + * 'reason' value, an opaque cookie which is used by internal + * debugging tools. Third party drivers should not use this + * command. + * + * Availability: + * SVGA_CAP_EXTENDED_FIFO + */ -#define SVGA_CMD_RECT_PIXMAP_FILL 9 - /* FIFO layout: - Pixmap ID, X, Y, Width, Height */ +typedef +struct SVGAFifoCmdUpdateVerbose { + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 reason; +} SVGAFifoCmdUpdateVerbose; -#define SVGA_CMD_RECT_BITMAP_COPY 10 - /* FIFO layout: - Bitmap ID, Source X, Source Y, Dest X, Dest Y, - Width, Height, Foreground, Background */ -#define SVGA_CMD_RECT_PIXMAP_COPY 11 - /* FIFO layout: - Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, Height */ +/* + * SVGA_CMD_FRONT_ROP_FILL -- + * + * This is a hint which tells the SVGA device that the driver has + * just filled a rectangular region of the GFB with a solid + * color. Instead of reading these pixels from the GFB, the device + * can assume that they all equal 'color'. This is primarily used + * for remote desktop protocols. + * + * Availability: + * SVGA_FIFO_CAP_ACCELFRONT + */ + +#define SVGA_ROP_COPY 0x03 -#define SVGA_CMD_FREE_OBJECT 12 - /* FIFO layout: - Object (pixmap, bitmap, ...) ID */ +#define SVGA_INVALID_DISPLAY_ID ((uint32)-1) -#define SVGA_CMD_RECT_ROP_FILL 13 - /* FIFO layout: - Color, X, Y, Width, Height, ROP */ +typedef +struct SVGAFifoCmdFrontRopFill { + uint32 color; /* In the same format as the GFB */ + uint32 x; + uint32 y; + uint32 width; + uint32 height; + uint32 rop; /* Must be SVGA_ROP_COPY */ +} SVGAFifoCmdFrontRopFill; -#define SVGA_CMD_RECT_ROP_COPY 14 - /* FIFO layout: - Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */ -#define SVGA_CMD_RECT_ROP_BITMAP_FILL 15 - /* FIFO layout: - ID, X, Y, Width, Height, Foreground, Background, ROP */ +/* + * SVGA_CMD_FENCE -- + * + * Insert a synchronization fence. When the SVGA device reaches + * this command, it will copy the 'fence' value into the + * SVGA_FIFO_FENCE register. It will also compare the fence against + * SVGA_FIFO_FENCE_GOAL. If the fence matches the goal and the + * SVGA_IRQFLAG_FENCE_GOAL interrupt is enabled, the device will + * raise this interrupt. + * + * Availability: + * SVGA_FIFO_FENCE for this command, + * SVGA_CAP_IRQMASK for SVGA_FIFO_FENCE_GOAL. + */ -#define SVGA_CMD_RECT_ROP_PIXMAP_FILL 16 - /* FIFO layout: - ID, X, Y, Width, Height, ROP */ +typedef +struct { + uint32 fence; +} SVGAFifoCmdFence; -#define SVGA_CMD_RECT_ROP_BITMAP_COPY 17 - /* FIFO layout: - ID, Source X, Source Y, - Dest X, Dest Y, Width, Height, Foreground, Background, ROP */ -#define SVGA_CMD_RECT_ROP_PIXMAP_COPY 18 - /* FIFO layout: - ID, Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */ +/* + * SVGA_CMD_ESCAPE -- + * + * Send an extended or vendor-specific variable length command. + * This is used for video overlay, third party plugins, and + * internal debugging tools. See svga_escape.h + * + * Availability: + * SVGA_FIFO_CAP_ESCAPE + */ -#define SVGA_CMD_DEFINE_CURSOR 19 - /* FIFO layout: - ID, Hotspot X, Hotspot Y, Width, Height, - Depth for AND mask, Depth for XOR mask, - <scanlines for AND mask>, <scanlines for XOR mask> */ +typedef +struct SVGAFifoCmdEscape { + uint32 nsid; + uint32 size; + /* followed by 'size' bytes of data */ +} SVGAFifoCmdEscape; -#define SVGA_CMD_DISPLAY_CURSOR 20 - /* FIFO layout: - ID, On/Off (1 or 0) */ -#define SVGA_CMD_MOVE_CURSOR 21 - /* FIFO layout: - X, Y */ +/* + * SVGA_CMD_DEFINE_SCREEN -- + * + * Define or redefine an SVGAScreenObject. See the description of + * SVGAScreenObject above. The video driver is responsible for + * generating new screen IDs. They should be small positive + * integers. The virtual device will have an implementation + * specific upper limit on the number of screen IDs + * supported. Drivers are responsible for recycling IDs. The first + * valid ID is zero. + * + * - Interaction with other registers: + * + * For backwards compatibility, when the GFB mode registers (WIDTH, + * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device + * deletes all screens other than screen #0, and redefines screen + * #0 according to the specified mode. Drivers that use + * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0. + * + * If you use screen objects, do not use the legacy multi-mon + * registers (SVGA_REG_NUM_GUEST_DISPLAYS, SVGA_REG_DISPLAY_*). + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ -#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22 - /* FIFO layout: - ID, Hotspot X, Hotspot Y, Width, Height, - <scanlines> */ +typedef +struct { + SVGAScreenObject screen; /* Variable-length according to version */ +} SVGAFifoCmdDefineScreen; -#define SVGA_CMD_DRAW_GLYPH 23 - /* FIFO layout: - X, Y, W, H, FGCOLOR, <stencil buffer> */ - -#define SVGA_CMD_DRAW_GLYPH_CLIPPED 24 - /* FIFO layout: - X, Y, W, H, FGCOLOR, BGCOLOR, <cliprect>, <stencil buffer> - Transparent color expands are done by setting BGCOLOR to ~0 */ - -#define SVGA_CMD_UPDATE_VERBOSE 25 - /* FIFO layout: - X, Y, Width, Height, Reason */ - -#define SVGA_CMD_SURFACE_FILL 26 - /* FIFO layout: - color, dstSurfaceOffset, x, y, w, h, rop */ - -#define SVGA_CMD_SURFACE_COPY 27 - /* FIFO layout: - srcSurfaceOffset, dstSurfaceOffset, srcX, srcY, - destX, destY, w, h, rop */ - -#define SVGA_CMD_SURFACE_ALPHA_BLEND 28 - /* FIFO layout: - srcSurfaceOffset, dstSurfaceOffset, srcX, srcY, - destX, destY, w, h, op (SVGA_BLENDOP*), flags (SVGA_BLENDFLAGS*), - param1, param2 */ - -#define SVGA_CMD_FRONT_ROP_FILL 29 - /* FIFO layout: - Color, X, Y, Width, Height, ROP */ - -#define SVGA_CMD_FENCE 30 - /* FIFO layout: - Fence value */ - -#define SVGA_CMD_VIDEO_PLAY_OBSOLETE 31 - /* Obsolete; do not use. */ - -#define SVGA_CMD_VIDEO_END_OBSOLETE 32 - /* Obsolete; do not use. */ - -#define SVGA_CMD_ESCAPE 33 - /* FIFO layout: - Namespace ID, size(bytes), data */ - -#define SVGA_CMD_MAX 34 - -#define SVGA_CMD_MAX_ARGS 64 - -/* - * Location and size of SVGA frame buffer and the FIFO. - */ -#define SVGA_VRAM_MIN_SIZE (4 * 640 * 480) /* bytes */ -#define SVGA_VRAM_MAX_SIZE (128 * 1024 * 1024) - -#define SVGA_VRAM_SIZE_WS (16 * 1024 * 1024) /* 16 MB */ -#define SVGA_MEM_SIZE_WS (2 * 1024 * 1024) /* 2 MB */ -#define SVGA_VRAM_SIZE_SERVER (4 * 1024 * 1024) /* 4 MB */ -#define SVGA_MEM_SIZE_SERVER (256 * 1024) /* 256 KB */ - -#if /* defined(VMX86_WGS) || */ defined(VMX86_SERVER) -#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_SERVER -#define SVGA_MEM_SIZE SVGA_MEM_SIZE_SERVER -#else -#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_WS -#define SVGA_MEM_SIZE SVGA_MEM_SIZE_WS -#endif /* - * SVGA_FB_START is the default starting address of the SVGA frame - * buffer in the guest's physical address space. - * SVGA_FB_START_BIGMEM is the starting address of the SVGA frame - * buffer for VMs that have a large amount of physical memory. - * - * The address of SVGA_FB_START is set to 2GB - (SVGA_FB_MAX_SIZE + SVGA_MEM_SIZE), - * thus the SVGA frame buffer sits at [SVGA_FB_START .. 2GB-1] in the - * physical address space. Our older SVGA drivers for NT treat the - * address of the frame buffer as a signed integer. For backwards - * compatibility, we keep the default location of the frame buffer - * at under 2GB in the address space. This restricts VMs to have "only" - * up to ~2031MB (i.e., up to SVGA_FB_START) of physical memory. - * - * For VMs that want more memory than the ~2031MB, we place the SVGA - * frame buffer at SVGA_FB_START_BIGMEM. This allows VMs to have up - * to 3584MB, at least as far as the SVGA frame buffer is concerned - * (note that there may be other issues that limit the VM memory - * size). PCI devices use high memory addresses, so we have to put - * SVGA_FB_START_BIGMEM low enough so that it doesn't overlap with any - * of these devices. Placing SVGA_FB_START_BIGMEM at 0xE0000000 - * should leave plenty of room for the PCI devices. - * - * NOTE: All of that is only true for the 0710 chipset. As of the 0405 - * chipset, the framebuffer start is determined solely based on the value - * the guest BIOS or OS programs into the PCI base address registers. - */ -#define SVGA_FB_LEGACY_START 0x7EFC0000 -#define SVGA_FB_LEGACY_START_BIGMEM 0xE0000000 + * SVGA_CMD_DESTROY_SCREEN -- + * + * Destroy an SVGAScreenObject. Its ID is immediately available for + * re-use. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + uint32 screenId; +} SVGAFifoCmdDestroyScreen; + + +/* + * SVGA_CMD_DEFINE_GMRFB -- + * + * This command sets a piece of SVGA device state called the + * Guest Memory Region Framebuffer, or GMRFB. The GMRFB is a + * piece of light-weight state which identifies the location and + * format of an image in guest memory or in BAR1. The GMRFB has + * an arbitrary size, and it doesn't need to match the geometry + * of the GFB or any screen object. + * + * The GMRFB can be redefined as often as you like. You could + * always use the same GMRFB, you could redefine it before + * rendering from a different guest screen, or you could even + * redefine it before every blit. + * + * There are multiple ways to use this command. The simplest way is + * to use it to move the framebuffer either to elsewhere in the GFB + * (BAR1) memory region, or to a user-defined GMR. This lets a + * driver use a framebuffer allocated entirely out of normal system + * memory, which we encourage. + * + * Another way to use this command is to set up a ring buffer of + * updates in GFB memory. If a driver wants to ensure that no + * frames are skipped by the SVGA device, it is important that the + * driver not modify the source data for a blit until the device is + * done processing the command. One efficient way to accomplish + * this is to use a ring of small DMA buffers. Each buffer is used + * for one blit, then we move on to the next buffer in the + * ring. The FENCE mechanism is used to protect each buffer from + * re-use until the device is finished with that buffer's + * corresponding blit. + * + * This command does not affect the meaning of SVGA_CMD_UPDATE. + * UPDATEs always occur from the legacy GFB memory area. This + * command has no support for pseudocolor GMRFBs. Currently only + * true-color 15, 16, and 24-bit depths are supported. Future + * devices may expose capabilities for additional framebuffer + * formats. + * + * The default GMRFB value is undefined. Drivers must always send + * this command at least once before performing any blit from the + * GMRFB. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAGuestPtr ptr; + uint32 bytesPerLine; + SVGAGMRImageFormat format; +} SVGAFifoCmdDefineGMRFB; + + +/* + * SVGA_CMD_BLIT_GMRFB_TO_SCREEN -- + * + * This is a guest-to-host blit. It performs a DMA operation to + * copy a rectangular region of pixels from the current GMRFB to + * one or more Screen Objects. + * + * The destination coordinate may be specified relative to a + * screen's origin (if a screen ID is specified) or relative to the + * virtual coordinate system's origin (if the screen ID is + * SVGA_ID_INVALID). The actual destination may span zero or more + * screens, in the case of a virtual destination rect or a rect + * which extends off the edge of the specified screen. + * + * This command writes to the screen's "base layer": the underlying + * framebuffer which exists below any cursor or video overlays. No + * action is necessary to explicitly hide or update any overlays + * which exist on top of the updated region. + * + * The SVGA device is guaranteed to finish reading from the GMRFB + * by the time any subsequent FENCE commands are reached. + * + * This command consumes an annotation. See the + * SVGA_CMD_ANNOTATION_* commands for details. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + SVGASignedRect destRect; + uint32 destScreenId; +} SVGAFifoCmdBlitGMRFBToScreen; + + +/* + * SVGA_CMD_BLIT_SCREEN_TO_GMRFB -- + * + * This is a host-to-guest blit. It performs a DMA operation to + * copy a rectangular region of pixels from a single Screen Object + * back to the current GMRFB. + * + * Usage note: This command should be used rarely. It will + * typically be inefficient, but it is necessary for some types of + * synchronization between 3D (GPU) and 2D (CPU) rendering into + * overlapping areas of a screen. + * + * The source coordinate is specified relative to a screen's + * origin. The provided screen ID must be valid. If any parameters + * are invalid, the resulting pixel values are undefined. + * + * This command reads the screen's "base layer". Overlays like + * video and cursor are not included, but any data which was sent + * using a blit-to-screen primitive will be available, no matter + * whether the data's original source was the GMRFB or the 3D + * acceleration hardware. + * + * Note that our guest-to-host blits and host-to-guest blits aren't + * symmetric in their current implementation. While the parameters + * are identical, host-to-guest blits are a lot less featureful. + * They do not support clipping: If the source parameters don't + * fully fit within a screen, the blit fails. They must originate + * from exactly one screen. Virtual coordinates are not directly + * supported. + * + * Host-to-guest blits do support the same set of GMRFB formats + * offered by guest-to-host blits. + * + * The SVGA device is guaranteed to finish writing to the GMRFB by + * the time any subsequent FENCE commands are reached. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint destOrigin; + SVGASignedRect srcRect; + uint32 srcScreenId; +} SVGAFifoCmdBlitScreenToGMRFB; + + +/* + * SVGA_CMD_ANNOTATION_FILL -- + * + * This is a blit annotation. This command stores a small piece of + * device state which is consumed by the next blit-to-screen + * command. The state is only cleared by commands which are + * specifically documented as consuming an annotation. Other + * commands (such as ESCAPEs for debugging) may intervene between + * the annotation and its associated blit. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value, specified here as a color in + * SVGAColorBGRX format. + * + * The SVGA device can still render the blit correctly even if it + * ignores this annotation, but the annotation may allow it to + * perform the blit more efficiently, for example by ignoring the + * source data and performing a fill in hardware. + * + * This annotation is most important for performance when the + * user's display is being remoted over a network connection. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGAColorBGRX color; +} SVGAFifoCmdAnnotationFill; + + +/* + * SVGA_CMD_ANNOTATION_COPY -- + * + * This is a blit annotation. See SVGA_CMD_ANNOTATION_FILL for more + * information about annotations. + * + * This annotation is a promise about the contents of the next + * blit: The video driver is guaranteeing that all pixels in that + * blit will have the same value as those which already exist at an + * identically-sized region on the same or a different screen. + * + * Note that the source pixels for the COPY in this annotation are + * sampled before applying the anqnotation's associated blit. They + * are allowed to overlap with the blit's destination pixels. + * + * The copy source rectangle is specified the same way as the blit + * destination: it can be a rectangle which spans zero or more + * screens, specified relative to either a screen or to the virtual + * coordinate system's origin. If the source rectangle includes + * pixels which are not from exactly one screen, the results are + * undefined. + * + * Availability: + * SVGA_FIFO_CAP_SCREEN_OBJECT or SVGA_FIFO_CAP_SCREEN_OBJECT_2 + */ + +typedef +struct { + SVGASignedPoint srcOrigin; + uint32 srcScreenId; +} SVGAFifoCmdAnnotationCopy; + + +/* + * SVGA_CMD_DEFINE_GMR2 -- + * + * Define guest memory region v2. See the description of GMRs above. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef +struct { + uint32 gmrId; + uint32 numPages; +} SVGAFifoCmdDefineGMR2; + + +/* + * SVGA_CMD_REMAP_GMR2 -- + * + * Remap guest memory region v2. See the description of GMRs above. + * + * This command allows guest to modify a portion of an existing GMR by + * invalidating it or reassigning it to different guest physical pages. + * The pages are identified by physical page number (PPN). The pages + * are assumed to be pinned and valid for DMA operations. + * + * Description of command flags: + * + * SVGA_REMAP_GMR2_VIA_GMR: If enabled, references a PPN list in a GMR. + * The PPN list must not overlap with the remap region (this can be + * handled trivially by referencing a separate GMR). If flag is + * disabled, PPN list is appended to SVGARemapGMR command. + * + * SVGA_REMAP_GMR2_PPN64: If set, PPN list is in PPN64 format, otherwise + * it is in PPN32 format. + * + * SVGA_REMAP_GMR2_SINGLE_PPN: If set, PPN list contains a single entry. + * A single PPN can be used to invalidate a portion of a GMR or + * map it to to a single guest scratch page. + * + * Availability: + * SVGA_CAP_GMR2 + */ + +typedef enum { + SVGA_REMAP_GMR2_PPN32 = 0, + SVGA_REMAP_GMR2_VIA_GMR = (1 << 0), + SVGA_REMAP_GMR2_PPN64 = (1 << 1), + SVGA_REMAP_GMR2_SINGLE_PPN = (1 << 2), +} SVGARemapGMR2Flags; + +typedef +struct { + uint32 gmrId; + SVGARemapGMR2Flags flags; + uint32 offsetPages; /* offset in pages to begin remap */ + uint32 numPages; /* number of pages to remap */ + /* + * Followed by additional data depending on SVGARemapGMR2Flags. + * + * If flag SVGA_REMAP_GMR2_VIA_GMR is set, single SVGAGuestPtr follows. + * Otherwise an array of page descriptors in PPN32 or PPN64 format + * (according to flag SVGA_REMAP_GMR2_PPN64) follows. If flag + * SVGA_REMAP_GMR2_SINGLE_PPN is set, array contains a single entry. + */ +} SVGAFifoCmdRemapGMR2; #endif diff --git a/src/vmware.c b/src/vmware.c index fa01dca..9160cf2 100644 --- a/src/vmware.c +++ b/src/vmware.c @@ -39,195 +39,17 @@ char rcsId_vmware[] = #include "guest_os.h" #include "vm_device_version.h" #include "svga_modes.h" +#include "vmware_bootstrap.h" +#include "vmware_common.h" #ifndef HAVE_XORG_SERVER_1_5_0 #include <xf86_ansic.h> #include <xf86_libc.h> #endif -#ifdef HaveDriverFuncs -#define VMWARE_DRIVER_FUNC HaveDriverFuncs -#else -#define VMWARE_DRIVER_FUNC 0 -#endif - -/* - * So that the file compiles unmodified when dropped in to a < 6.9 source tree. - */ -#ifndef _X_EXPORT -#define _X_EXPORT -#endif -/* - * So that the file compiles unmodified when dropped into an xfree source tree. - */ -#ifndef XORG_VERSION_CURRENT -#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT -#endif - -/* - * Sanity check that xf86PciInfo.h has the correct values (which come from - * the VMware source tree in 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 VMWARE_INCHTOMM 25.4 - -/* - * This is the only way I know to turn a #define of an integer constant into - * a constant string. - */ -#define VMW_INNERSTRINGIFY(s) #s -#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) - -#define VMWARE_NAME "vmwlegacy" -#define VMWARE_DRIVER_NAME "vmwlegacy" -#define VMWARE_DRIVER_VERSION \ - (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) -#define VMWARE_DRIVER_VERSION_STRING \ - VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ - "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) - -static const char VMWAREBuildStr[] = "VMware Guest X Server " - VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n"; - -/* - * Standard four digit version string expected by VMware Tools installer. - * As the driver's version is only {major, minor, patchlevel}, - * The fourth digit may describe the commit number relative to the - * last version tag as output from `git describe` - */ - -#ifdef __GNUC__ -#ifdef VMW_SUBPATCH -const char vmwlegacy_drv_modinfo[] -__attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); -#else -const char vmwlegacy_drv_modinfo[] -__attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING ".0"; -#endif /*VMW_SUBPATCH*/ -#endif - -static SymTabRec VMWAREChipsets[] = { - { PCI_CHIP_VMWARE0405, "vmware0405" }, - { PCI_CHIP_VMWARE0710, "vmware0710" }, - { -1, NULL } -}; - -#ifndef XSERVER_LIBPCIACCESS -static resRange vmwareLegacyRes[] = { - { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, - SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, - _VGA_EXCLUSIVE, _END -}; -#else -#define vmwareLegacyRes NULL -#endif - -#if XSERVER_LIBPCIACCESS - -#define VMWARE_DEVICE_MATCH(d, i) \ - {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } - -static const struct pci_id_match VMwareDeviceMatch[] = { - VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ), - VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ), - { 0, 0, 0 }, -}; -#endif - -/* - * Currently, even the PCI obedient 0405 chip still only obeys IOSE and - * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required. - * - * The 0710 chip also uses hardcoded IO ports that aren't disablable. - */ - -static PciChipsets VMWAREPciChipsets[] = { - { PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA }, - { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes }, - { -1, -1, RES_UNDEFINED } -}; - -#if HAVE_XORG_SERVER_1_7_0 - +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5) #define xf86LoaderReqSymLists(...) do {} while (0) -#define LoaderRefSymLists(...) do {} while (0) - -#else - -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 -}; - -#endif /* HAVE_XORG_SERVER_1_7_0 */ - -#ifdef XFree86LOADER -static XF86ModuleVersionInfo vmwlegacyVersRec = { - VMWARE_DRIVER_NAME, - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - { 0, 0, 0, 0} -}; -#endif /* XFree86LOADER */ - -typedef enum { - OPTION_HW_CURSOR, - OPTION_XINERAMA, - OPTION_STATIC_XINERAMA, - OPTION_DEFAULT_MODE, -} VMWAREOpts; - -static const OptionInfoRec VMWAREOptions[] = { - { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, - { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, - { -1, NULL, OPTV_NONE, {0}, FALSE } -}; +#endif /* Table of default modes to always add to the mode list. */ @@ -466,141 +288,6 @@ RewriteTagString(const char *istr, char *ostr, int osize) } #endif -static void -VMWAREIdentify(int flags) -{ - xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); -} - -static const OptionInfoRec * -VMWAREAvailableOptions(int chipid, int busid) -{ - return VMWAREOptions; -} - -static int -VMWAREParseTopologyElement(ScrnInfoPtr pScrn, - unsigned int output, - const char *elementName, - const char *element, - const char *expectedTerminators, - Bool needTerminator, - unsigned int *outValue) -{ - char buf[10] = {0, }; - size_t i = 0; - int retVal = -1; - const char *str = element; - - for (i = 0; str[i] >= '0' && str[i] <= '9'; i++); - if (i == 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n", - output, elementName); - goto exit; - } - - strncpy(buf, str, i); - *outValue = atoi(buf); - - if (*outValue > (unsigned short)-1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n", - output, elementName, (unsigned short)-1); - goto exit; - } - - str += i; - - if (needTerminator || str[0] != '\0') { - Bool unexpected = TRUE; - - for (i = 0; i < strlen(expectedTerminators); i++) { - if (str[0] == expectedTerminators[i]) { - unexpected = FALSE; - } - } - - if (unexpected) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Output %u: unexpected character '%c' after %s.\n", - output, str[0], elementName); - goto exit; - } else { - str++; - } - } - - retVal = str - element; - - exit: - return retVal; -} - -static xXineramaScreenInfo * -VMWAREParseTopologyString(ScrnInfoPtr pScrn, - const char *topology, - unsigned int *retNumOutputs) -{ - xXineramaScreenInfo *extents = NULL; - unsigned int numOutputs = 0; - const char *str = topology; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Starting...\n"); - - do { - unsigned int x, y, width, height; - int i; - - i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width); - if (i == -1) { - goto error; - } - str += i; - - i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height); - if (i == -1) { - goto error; - } - str += i; - - i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x); - if (i == -1) { - goto error; - } - str += i; - - i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y); - if (i == -1) { - goto error; - } - str += i; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n", - numOutputs, width, height, x, y); - - numOutputs++; - extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo)); - extents[numOutputs - 1].x_org = x; - extents[numOutputs - 1].y_org = y; - extents[numOutputs - 1].width = width; - extents[numOutputs - 1].height = height; - } while (*str != 0); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Succeeded.\n"); - goto exit; - - error: - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing static Xinerama topology: Failed.\n"); - - free(extents); - extents = NULL; - numOutputs = 0; - - exit: - *retNumOutputs = numOutputs; - return extents; -} - - static Bool VMWAREPreInit(ScrnInfoPtr pScrn, int flags) { @@ -899,18 +586,14 @@ VMWAREPreInit(ScrnInfoPtr pScrn, int flags) #endif xf86CollectOptions(pScrn, NULL); - if (!(options = malloc(sizeof(VMWAREOptions)))) + if (!(options = VMWARECopyOptions())) 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, DEVICE_ID(pVMWARE->PciInfo)); - if (!pScrn->chipset) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04x is not recognised\n", DEVICE_ID(pVMWARE->PciInfo)); return FALSE; @@ -1608,46 +1291,6 @@ vmwareIsRegionEqual(const RegionPtr reg1, return TRUE; } -#if VMWARE_DRIVER_FUNC -static Bool -VMWareDriverFunc(ScrnInfoPtr pScrn, - xorgDriverFuncOp op, - pointer data) -{ - CARD32 *flag; - xorgRRModeMM *modemm; - - switch (op) { - case GET_REQUIRED_HW_INTERFACES: - flag = (CARD32 *)data; - - if (flag) { - *flag = HW_IO | HW_MMIO; - } - return TRUE; - case RR_GET_MODE_MM: - modemm = (xorgRRModeMM *)data; - - /* - * Because changing the resolution of the guest is usually changing the size - * of a window on the host desktop, the real physical DPI will not change. To - * keep the guest in sync, we scale the 'physical' screen dimensions to - * keep the DPI constant. - */ - if (modemm && modemm->mode) { - modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM + - pScrn->xDpi / 2) / pScrn->xDpi; - modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM + - pScrn->yDpi / 2) / pScrn->yDpi; - } - return TRUE; - default: - return FALSE; - } -} -#endif - - static Bool VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { @@ -1663,9 +1306,8 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86CollectOptions(pScrn, NULL); - if (!(options = malloc(sizeof(VMWAREOptions)))) + if (!(options = VMWARECopyOptions())) return FALSE; - memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options); /* @@ -1680,11 +1322,25 @@ VMWAREScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } - if (useXinerama && xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { + if (useXinerama && xf86IsOptionSet(options, OPTION_GUI_LAYOUT)) { + char *topology = xf86GetOptValString(options, OPTION_GUI_LAYOUT); + if (topology) { + pVMWARE->xineramaState = + VMWAREParseTopologyString(pScrn, topology, + &pVMWARE->xineramaNumOutputs, "gui"); + + pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; + + free(topology); + } + } else if (useXinerama && + xf86IsOptionSet(options, OPTION_STATIC_XINERAMA)) { char *topology = xf86GetOptValString(options, OPTION_STATIC_XINERAMA); if (topology) { pVMWARE->xineramaState = - VMWAREParseTopologyString(pScrn, topology, &pVMWARE->xineramaNumOutputs); + VMWAREParseTopologyString(pScrn, topology, + &pVMWARE->xineramaNumOutputs, + "static Xinerama"); pVMWARE->xineramaStatic = pVMWARE->xineramaState != NULL; @@ -1986,155 +1642,14 @@ VMWAREValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) return MODE_OK; } -#if XSERVER_LIBPCIACCESS -static Bool -VMwarePciProbe (DriverPtr drv, - int entity_num, - struct pci_device *device, - intptr_t match_data) -{ - ScrnInfoPtr scrn = NULL; - EntityInfoPtr entity; - - scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, - NULL, NULL, NULL, NULL, NULL); - if (scrn != NULL) { - scrn->driverVersion = VMWARE_DRIVER_VERSION; - scrn->driverName = VMWARE_DRIVER_NAME; - scrn->name = VMWARE_NAME; - scrn->Probe = NULL; - } - - entity = xf86GetEntityInfo(entity_num); - switch (DEVICE_ID(device)) { - case PCI_CHIP_VMWARE0405: - case PCI_CHIP_VMWARE0710: - xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); - scrn->PreInit = VMWAREPreInit; - scrn->ScreenInit = VMWAREScreenInit; - scrn->SwitchMode = VMWARESwitchMode; - scrn->EnterVT = VMWAREEnterVT; - scrn->LeaveVT = VMWARELeaveVT; - scrn->FreeScreen = VMWAREFreeScreen; - scrn->ValidMode = VMWAREValidMode; - break; - default: - xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); - } - return scrn != NULL; -} -#else - -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); - free(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 = VMWARE_DRIVER_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; - } - } - free(usedChips); - } - return foundScreen; -} -#endif - - -_X_EXPORT DriverRec vmwlegacy = { - VMWARE_DRIVER_VERSION, - VMWARE_DRIVER_NAME, - VMWAREIdentify, -#if XSERVER_LIBPCIACCESS - NULL, -#else - VMWAREProbe, -#endif - VMWAREAvailableOptions, - NULL, - 0, -#if VMWARE_DRIVER_FUNC - VMWareDriverFunc, -#endif -#if XSERVER_LIBPCIACCESS - VMwareDeviceMatch, - VMwarePciProbe, -#endif -}; - -#ifdef XFree86LOADER -static MODULESETUPPROTO(vmwlegacySetup); - -_X_EXPORT XF86ModuleData vmwlegacyModuleData = { - &vmwlegacyVersRec, - vmwlegacySetup, - NULL -}; - -static pointer -vmwlegacySetup(pointer module, pointer opts, int *errmaj, int *errmin) +void +vmwlegacy_hookup(ScrnInfoPtr pScrn) { - static Bool setupDone = FALSE; - - if (!setupDone) { - setupDone = TRUE; - - xf86AddDriver(&vmwlegacy, module, VMWARE_DRIVER_FUNC); - - LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, - shadowfbSymbols, NULL); - - return (pointer)1; - } - if (errmaj) { - *errmaj = LDR_ONCEONLY; - } - return NULL; + pScrn->PreInit = VMWAREPreInit; + pScrn->ScreenInit = VMWAREScreenInit; + pScrn->SwitchMode = VMWARESwitchMode; + pScrn->EnterVT = VMWAREEnterVT; + pScrn->LeaveVT = VMWARELeaveVT; + pScrn->FreeScreen = VMWAREFreeScreen; + pScrn->ValidMode = VMWAREValidMode; } -#endif /* XFree86LOADER */ diff --git a/src/vmware_bootstrap.c b/src/vmware_bootstrap.c new file mode 100644 index 0000000..522fec0 --- /dev/null +++ b/src/vmware_bootstrap.c @@ -0,0 +1,503 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Unknown at vmware + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "compiler.h" +#include "xf86PciInfo.h" /* pci vendor id */ +#include "xf86Pci.h" /* pci */ +#include "vm_device_version.h" +#include "vmware_bootstrap.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +#ifdef HaveDriverFuncs +#define VMWARE_DRIVER_FUNC HaveDriverFuncs +#else +#define VMWARE_DRIVER_FUNC 0 +#endif + +/* + * So that the file compiles unmodified when dropped in to a < 6.9 source tree. + */ +#ifndef _X_EXPORT +#define _X_EXPORT +#endif +/* + * So that the file compiles unmodified when dropped into an xfree source tree. + */ +#ifndef XORG_VERSION_CURRENT +#define XORG_VERSION_CURRENT XF86_VERSION_CURRENT +#endif + +/* + * Sanity check that xf86PciInfo.h has the correct values (which come from + * the VMware source tree in 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 + +/* + * This is the only way I know to turn a #define of an integer constant into + * a constant string. + */ +#define VMW_INNERSTRINGIFY(s) #s +#define VMW_STRING(str) VMW_INNERSTRINGIFY(str) + +#define VMWARE_NAME "vmware" +#define VMWARE_DRIVER_NAME "vmware" +#define VMWARE_DRIVER_VERSION \ + (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) +#define VMWARE_DRIVER_VERSION_STRING \ + VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ + "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) + +static const char VMWAREBuildStr[] = "VMware Guest X Server " + VMWARE_DRIVER_VERSION_STRING " - build=$Name$\n"; + +/* + * Standard four digit version string expected by VMware Tools installer. + * As the driver's version is only {major, minor, patchlevel}, + * The fourth digit may describe the commit number relative to the + * last version tag as output from `git describe` + */ + +#ifdef __GNUC__ +#ifdef VMW_SUBPATCH +const char vmware_drv_modinfo[] +__attribute__((section(".modinfo"),unused)) = + "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); +#else +const char vmware_drv_modinfo[] +__attribute__((section(".modinfo"),unused)) = + "version=" VMWARE_DRIVER_VERSION_STRING ".0"; +#endif /*VMW_SUBPATCH*/ +#endif + +#ifndef XSERVER_LIBPCIACCESS +static resRange vmwareLegacyRes[] = { + { ResExcIoBlock, SVGA_LEGACY_BASE_PORT, + SVGA_LEGACY_BASE_PORT + SVGA_NUM_PORTS*sizeof(uint32)}, + _VGA_EXCLUSIVE, _END +}; +#else +#define vmwareLegacyRes NULL +#endif + +#if XSERVER_LIBPCIACCESS +#define VENDOR_ID(p) (p)->vendor_id +#define DEVICE_ID(p) (p)->device_id +#define SUBVENDOR_ID(p) (p)->subvendor_id +#define SUBSYS_ID(p) (p)->subdevice_id +#define CHIP_REVISION(p) (p)->revision +#else +#define VENDOR_ID(p) (p)->vendor +#define DEVICE_ID(p) (p)->chipType +#define SUBVENDOR_ID(p) (p)->subsysVendor +#define SUBSYS_ID(p) (p)->subsysCard +#define CHIP_REVISION(p) (p)->chipRev +#endif + +#if XSERVER_LIBPCIACCESS + +#define VMWARE_DEVICE_MATCH(d, i) \ + {PCI_VENDOR_VMWARE, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } + +static const struct pci_id_match VMwareDeviceMatch[] = { + VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0405, 0 ), + VMWARE_DEVICE_MATCH (PCI_CHIP_VMWARE0710, 0 ), + { 0, 0, 0 }, +}; +#endif + +/* + * Currently, even the PCI obedient 0405 chip still only obeys IOSE and + * MEMSE for the SVGA resources. Thus, RES_EXCLUSIVE_VGA is required. + * + * The 0710 chip also uses hardcoded IO ports that aren't disablable. + */ + +static PciChipsets VMWAREPciChipsets[] = { + { PCI_CHIP_VMWARE0405, PCI_CHIP_VMWARE0405, RES_EXCLUSIVE_VGA }, + { PCI_CHIP_VMWARE0710, PCI_CHIP_VMWARE0710, vmwareLegacyRes }, + { -1, -1, RES_UNDEFINED } +}; + +static SymTabRec VMWAREChipsets[] = { + { PCI_CHIP_VMWARE0405, "vmware0405" }, + { PCI_CHIP_VMWARE0710, "vmware0710" }, + { -1, NULL } +}; + +#ifdef XFree86LOADER +static XF86ModuleVersionInfo vmwareVersRec = { + VMWARE_DRIVER_NAME, + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + { 0, 0, 0, 0} +}; +#endif /* XFree86LOADER */ + +static const OptionInfoRec VMWAREOptions[] = { + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_XINERAMA, "Xinerama", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_STATIC_XINERAMA, "StaticXinerama", OPTV_STRING, {0}, FALSE }, + { OPTION_GUI_LAYOUT, "GuiLayout", OPTV_STRING, {0}, FALSE }, + { OPTION_DEFAULT_MODE, "AddDefaultMode", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_RENDER_ACCEL, "RenderAccel", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_DIRECT_PRESENTS, "DirectPresents", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_HW_PRESENTS, "HWPresents", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_RENDERCHECK, "RenderCheck", OPTV_BOOLEAN, {0}, FALSE}, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +OptionInfoPtr VMWARECopyOptions(void) +{ + OptionInfoPtr options; + if (!(options = malloc(sizeof(VMWAREOptions)))) + return NULL; + + memcpy(options, VMWAREOptions, sizeof(VMWAREOptions)); + return options; +} + +static Bool +VMwarePreinitStub(ScrnInfoPtr pScrn, int flags) +{ +#if XSERVER_LIBPCIACCESS + struct pci_device *pciInfo; +#else + pciVideoPtr pciInfo; +#endif /* XSERVER_LIBPCIACCESS */ + EntityInfoPtr pEnt; + + pScrn->PreInit = pScrn->driverPrivate; + +#ifdef BUILD_VMWGFX + pScrn->driverPrivate = NULL; + + /* + * Try vmwgfx path. + */ + if ((*pScrn->PreInit)(pScrn, flags)) + return TRUE; + +#else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Driver was compiled without KMS- and 3D support.\n"); +#endif /* defined(BUILD_VMWGFX) */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling 3D support.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling Render Acceleration.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling RandR12+ support.\n"); + + pScrn->driverPrivate = NULL; + vmwlegacy_hookup(pScrn); + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pEnt->location.type != BUS_PCI) + return FALSE; + + pciInfo = xf86GetPciInfoForEntity(pEnt->index); + if (pciInfo == NULL) + return FALSE; + + pScrn->chipset = (char*)xf86TokenToString(VMWAREChipsets, + DEVICE_ID(pciInfo)); + + return (*pScrn->PreInit)(pScrn, flags); +}; + +#if XSERVER_LIBPCIACCESS +static Bool +VMwarePciProbe (DriverPtr drv, + int entity_num, + struct pci_device *device, + intptr_t match_data) +{ + ScrnInfoPtr scrn = NULL; + EntityInfoPtr entity; + + scrn = xf86ConfigPciEntity(scrn, 0, entity_num, VMWAREPciChipsets, + NULL, NULL, NULL, NULL, NULL); + if (scrn != NULL) { + scrn->driverVersion = VMWARE_DRIVER_VERSION; + scrn->driverName = VMWARE_DRIVER_NAME; + scrn->name = VMWARE_NAME; + scrn->Probe = NULL; + } + + entity = xf86GetEntityInfo(entity_num); + switch (DEVICE_ID(device)) { + case PCI_CHIP_VMWARE0405: + case PCI_CHIP_VMWARE0710: + xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Valid device\n"); + +#ifdef BUILD_VMWGFX + vmwgfx_hookup(scrn); +#else + vmwlegacy_hookup(scrn); +#endif /* defined(BUILD_VMWGFX) */ + + scrn->driverPrivate = scrn->PreInit; + scrn->PreInit = VMwarePreinitStub; + break; + default: + xf86MsgVerb(X_INFO, 4, "VMwarePciProbe: Unknown device\n"); + } + return scrn != NULL; +} +#else + +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); + free(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 = VMWARE_DRIVER_VERSION; + pScrn->driverName = VMWARE_DRIVER_NAME; + pScrn->name = VMWARE_NAME; + pScrn->Probe = VMWAREProbe; + pScrn->PreInit = VMWAREPreInit; + +#ifdef BUILD_VMWGFX + vmwgfx_hookup(scrn); +#else + vmwlegacy_hookup(scrn); +#endif /* defined(BUILD_VMWGFX) */ + + scrn->driverPrivate = scrn->PreInit; + scrn->PreInit = VMwarePreinitStub; + foundScreen = TRUE; + } + } + free(usedChips); + } + return foundScreen; +} +#endif + +static void +VMWAREIdentify(int flags) +{ + xf86PrintChipsets(VMWARE_NAME, "driver for VMware SVGA", VMWAREChipsets); +} + +static const OptionInfoRec * +VMWAREAvailableOptions(int chipid, int busid) +{ + return VMWAREOptions; +} + +#if VMWARE_DRIVER_FUNC +static Bool +VMWareDriverFunc(ScrnInfoPtr pScrn, + xorgDriverFuncOp op, + pointer data) +{ + CARD32 *flag; + xorgRRModeMM *modemm; + + switch (op) { + case GET_REQUIRED_HW_INTERFACES: + flag = (CARD32 *)data; + + if (flag) { + *flag = HW_IO | HW_MMIO; + } + return TRUE; + case RR_GET_MODE_MM: + modemm = (xorgRRModeMM *)data; + + /* + * Because changing the resolution of the guest is usually changing the size + * of a window on the host desktop, the real physical DPI will not change. To + * keep the guest in sync, we scale the 'physical' screen dimensions to + * keep the DPI constant. + */ + if (modemm && modemm->mode) { + modemm->mmWidth = (modemm->mode->HDisplay * VMWARE_INCHTOMM + + pScrn->xDpi / 2) / pScrn->xDpi; + modemm->mmHeight = (modemm->mode->VDisplay * VMWARE_INCHTOMM + + pScrn->yDpi / 2) / pScrn->yDpi; + } + return TRUE; + default: + return FALSE; + } +} +#endif + + +_X_EXPORT DriverRec vmware = { + VMWARE_DRIVER_VERSION, + VMWARE_DRIVER_NAME, + VMWAREIdentify, +#if XSERVER_LIBPCIACCESS + NULL, +#else + VMWAREProbe, +#endif + VMWAREAvailableOptions, + NULL, + 0, +#if VMWARE_DRIVER_FUNC + VMWareDriverFunc, +#endif +#if XSERVER_LIBPCIACCESS + VMwareDeviceMatch, + VMwarePciProbe, +#endif +}; + +#if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 5) + +#define xf86LoaderReqSymLists(...) do {} while (0) +#define LoaderRefSymLists(...) do {} while (0) + +#else + +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 +}; +#endif + +#ifdef XFree86LOADER +static MODULESETUPPROTO(vmwareSetup); + +_X_EXPORT 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, VMWARE_DRIVER_FUNC); + + LoaderRefSymLists(vgahwSymbols, fbSymbols, ramdacSymbols, + shadowfbSymbols, NULL); + + return (pointer)1; + } + if (errmaj) { + *errmaj = LDR_ONCEONLY; + } + return NULL; +} +#endif /* XFree86LOADER */ diff --git a/src/vmware_bootstrap.h b/src/vmware_bootstrap.h new file mode 100644 index 0000000..172deb8 --- /dev/null +++ b/src/vmware_bootstrap.h @@ -0,0 +1,59 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ +#ifndef _VMWARE_BOOTSTRAP_H_ +#define _VMWARE_BOOTSTRAP_H_ + +#include <xf86.h> + +#define VMWARE_INCHTOMM 25.4 + +typedef enum { + OPTION_HW_CURSOR, + OPTION_XINERAMA, + OPTION_STATIC_XINERAMA, + OPTION_GUI_LAYOUT, + OPTION_DEFAULT_MODE, + OPTION_RENDER_ACCEL, + OPTION_DRI, + OPTION_DIRECT_PRESENTS, + OPTION_HW_PRESENTS, + OPTION_RENDERCHECK +} VMWAREOpts; + +OptionInfoPtr VMWARECopyOptions(void); +const char **vgahwSymbols; + +void +vmwlegacy_hookup(ScrnInfoPtr pScrn); + +#ifdef BUILD_VMWGFX +void +vmwgfx_hookup(ScrnInfoPtr pScrn); +#endif /* defined(BUILD_VMWGFX) */ + + +#endif diff --git a/src/vmware_common.c b/src/vmware_common.c new file mode 100644 index 0000000..6ef7ca6 --- /dev/null +++ b/src/vmware_common.c @@ -0,0 +1,163 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Unknown at vmware + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <xf86.h> +#include "vmware_common.h" + +#ifndef HAVE_XORG_SERVER_1_5_0 +#include <xf86_ansic.h> +#include <xf86_libc.h> +#endif + +static int +VMWAREParseTopologyElement(ScrnInfoPtr pScrn, + unsigned int output, + const char *elementName, + const char *element, + const char *expectedTerminators, + Bool needTerminator, + unsigned int *outValue) +{ + char buf[10] = {0, }; + size_t i = 0; + int retVal = -1; + const char *str = element; + + for (i = 0; str[i] >= '0' && str[i] <= '9'; i++); + if (i == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: unable to parse %s.\n", + output, elementName); + goto exit; + } + + strncpy(buf, str, i); + *outValue = atoi(buf); + + if (*outValue > (unsigned short)-1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %s must be less than %hu.\n", + output, elementName, (unsigned short)-1); + goto exit; + } + + str += i; + + if (needTerminator || str[0] != '\0') { + Bool unexpected = TRUE; + + for (i = 0; i < strlen(expectedTerminators); i++) { + if (str[0] == expectedTerminators[i]) { + unexpected = FALSE; + } + } + + if (unexpected) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Output %u: unexpected character '%c' after %s.\n", + output, str[0], elementName); + goto exit; + } else { + str++; + } + } + + retVal = str - element; + + exit: + return retVal; +} + +xXineramaScreenInfo * +VMWAREParseTopologyString(ScrnInfoPtr pScrn, + const char *topology, + unsigned int *retNumOutputs, + const char info[]) +{ + xXineramaScreenInfo *extents = NULL; + unsigned int numOutputs = 0; + const char *str = topology; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Starting...\n", + info); + + do { + unsigned int x, y, width, height; + int i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "width", str, "xX", TRUE, &width); + if (i == -1) { + goto error; + } + str += i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "height", str, "+", TRUE, &height); + if (i == -1) { + goto error; + } + str += i; + + i= VMWAREParseTopologyElement(pScrn, numOutputs, "X offset", str, "+", TRUE, &x); + if (i == -1) { + goto error; + } + str += i; + + i = VMWAREParseTopologyElement(pScrn, numOutputs, "Y offset", str, ";", FALSE, &y); + if (i == -1) { + goto error; + } + str += i; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Output %u: %ux%u+%u+%u\n", + numOutputs, width, height, x, y); + + numOutputs++; + extents = realloc(extents, numOutputs * sizeof (xXineramaScreenInfo)); + extents[numOutputs - 1].x_org = x; + extents[numOutputs - 1].y_org = y; + extents[numOutputs - 1].width = width; + extents[numOutputs - 1].height = height; + } while (*str != 0); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Succeeded.\n", + info); + goto exit; + + error: + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Parsing %s topology: Failed.\n", + info); + + free(extents); + extents = NULL; + numOutputs = 0; + + exit: + *retNumOutputs = numOutputs; + return extents; +} diff --git a/src/vmware_common.h b/src/vmware_common.h new file mode 100644 index 0000000..9cd7194 --- /dev/null +++ b/src/vmware_common.h @@ -0,0 +1,41 @@ +/* + * Copyright 2011 VMWare, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Author: Unknown at vmware + * Author: Thomas Hellstrom <thellstrom@vmware.com> + */ + +#ifndef _VMWARE_COMMON_H_ +#define _VMWARE_COMMON_H_ + +#include <X11/extensions/panoramiXproto.h> +#include <xf86.h> + +xXineramaScreenInfo * +VMWAREParseTopologyString(ScrnInfoPtr pScrn, + const char *topology, + unsigned int *retNumOutputs, + const char info[]); + +#endif diff --git a/src/vmwaremodule.c b/src/vmwaremodule.c deleted file mode 100644 index 0da2440..0000000 --- a/src/vmwaremodule.c +++ /dev/null @@ -1,256 +0,0 @@ -/********************************************************** - * Copyright 2010 VMware, Inc. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - **********************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_LIBDRM -#include <xf86drm.h> -#endif - -#include <xorg-server.h> -#include <xf86.h> - -#ifndef HAVE_XORG_SERVER_1_5_0 -#include <xf86_ansic.h> -#include <xf86_libc.h> -#endif - -/* - * Defines and exported module info. - */ - -#define VMWARE_DRIVER_NAME "vmware" -#define VMWGFX_DRIVER_NAME "vmwgfx" -#define VMWGFX_MODULE_NAME "vmwgfx" -#define VMWGFX_COMPAT_MAJOR 11 -#define VMWGFX_REQUIRED_MAJOR 11 -#define VMWGFX_REQUIRED_MINOR 0 -#define VMWLEGACY_DRIVER_NAME "vmwlegacy" - -#define VMW_STRING_INNER(s) #s -#define VMW_STRING(str) VMW_STRING_INNER(str) - -#define VMWARE_DRIVER_VERSION \ - (PACKAGE_VERSION_MAJOR * 65536 + PACKAGE_VERSION_MINOR * 256 + PACKAGE_VERSION_PATCHLEVEL) -#define VMWARE_DRIVER_VERSION_STRING \ - VMW_STRING(PACKAGE_VERSION_MAJOR) "." VMW_STRING(PACKAGE_VERSION_MINOR) \ - "." VMW_STRING(PACKAGE_VERSION_PATCHLEVEL) - -/* - * Standard four digit version string expected by VMware Tools installer. - * As the driver's version is only {major, minor, patchlevel}, - * the fourth digit may describe the commit number relative to the - * last version tag as output from `git describe` - */ - -#ifdef __GNUC__ -#ifdef VMW_SUBPATCH -const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING "." VMW_STRING(VMW_SUBPATCH); -#else -const char vmware_drv_modinfo[] __attribute__((section(".modinfo"),unused)) = - "version=" VMWARE_DRIVER_VERSION_STRING ".0"; -#endif /*VMW_SUBPATCH*/ -#endif - -static XF86ModuleVersionInfo vmware_version; -static MODULESETUPPROTO(vmware_setup); - -_X_EXPORT XF86ModuleData vmwareModuleData = { - &vmware_version, - vmware_setup, - NULL -}; - -extern XF86ModuleData *VMWGFX_MODULE_DATA; - -/* - * Chain loading functions - */ - -static Bool -vmware_check_kernel_module() -{ -#ifdef HAVE_LIBDRM - /* Super simple way of knowing if the kernel driver is loaded */ - int ret = drmOpen(VMWGFX_MODULE_NAME, NULL); - if (ret < 0) { - /* This shouldn't go in the log as the original message does not */ - fprintf(stderr, "%s: Please ignore above \"FATAL: Module %s not found." - "\"\n", VMWARE_DRIVER_NAME, VMWGFX_MODULE_NAME); - /* This is what goes into the log on the other hand */ - xf86DrvMsg(-1, X_PROBED, "%s: Please ignore above \"[drm] failed to " - "load kernel module \"%s\"\"\n", VMWARE_DRIVER_NAME, - VMWGFX_MODULE_NAME); - return FALSE; - } - - drmClose(ret); - - return TRUE; -#else - return FALSE; -#endif /* HAVE_LIBDRM */ -} - -static Bool -vmware_check_vmwgfx_driver(int matched, pointer opts) -{ -#ifdef HAVE_LIBDRM - int major; int minor; - pointer module; - CARD32 version; - - if (matched) { - xf86DrvMsg(-1, X_PROBED, "%s: X configured to use %s X driver assume " - "who ever did that knows what they are doing\n", - VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - /* Also how did they end up here, if the configured X to use vmwgfx and - * X should load that driver for that hardware. And since there is only - * one SVGA device this driver shouldn't be loaded. Weird... - */ - return TRUE; - } - - module = xf86LoadOneModule(VMWGFX_DRIVER_NAME, opts); - if (!module) { - xf86DrvMsg(-1, X_ERROR, "%s: Please ignore the above warnings about " - "not being able to to load module/driver %s\n", - VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - return FALSE; - } - - version = xf86GetModuleVersion(module); - major = GET_MODULE_MAJOR_VERSION(version); - minor = GET_MODULE_MINOR_VERSION(version); - - if (major > VMWGFX_COMPAT_MAJOR || - major < VMWGFX_REQUIRED_MAJOR || - (major == VMWGFX_REQUIRED_MAJOR && minor < VMWGFX_REQUIRED_MINOR)) { - xf86DrvMsg(-1, X_PROBED, "%s: The %s X driver failed version " - "checking.\n", VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - goto err; - } - - return TRUE; - -err: - /* XXX We should drop the reference on the module here */ -#endif /* HAVE_LIBDRM */ - return FALSE; -} - -static Bool -vmware_chain_module(pointer opts) -{ - int vmwlegacy_devices; - int vmwgfx_devices; - int vmware_devices; - int matched; - char *driver_name; - GDevPtr *gdevs; - GDevPtr gdev; - int i; - - vmware_devices = xf86MatchDevice(VMWARE_DRIVER_NAME, &gdevs); - vmwgfx_devices = xf86MatchDevice(VMWGFX_DRIVER_NAME, NULL); - vmwlegacy_devices = xf86MatchDevice(VMWLEGACY_DRIVER_NAME, NULL); - - if (vmware_check_vmwgfx_driver(vmwgfx_devices, opts) && - vmware_check_kernel_module()) { - xf86DrvMsg(-1, X_INFO, "%s: Using %s X driver.\n", - VMWARE_DRIVER_NAME, VMWGFX_DRIVER_NAME); - driver_name = VMWGFX_DRIVER_NAME; - matched = 1; - } else { - xf86DrvMsg(-1, X_INFO, "%s: Using %s driver everything is fine.\n", - VMWARE_DRIVER_NAME, VMWLEGACY_DRIVER_NAME); - driver_name = VMWLEGACY_DRIVER_NAME; - matched = vmwlegacy_devices; - } - - /* Xorg -configure returns 1 from xf86MatchDevice with NULL gdevs */ - for (i = 0; gdevs && i < vmware_devices; i++) { - gdev = gdevs[i]; - gdev->driver = driver_name; - } - - free(gdevs); - - if (!matched) { - if (xf86LoadOneModule(driver_name, opts) == NULL) { - xf86DrvMsg(-1, X_ERROR, "%s: Unexpected failure while " - "loading the \"%s\" driver. Giving up.\n", - VMWARE_DRIVER_NAME, driver_name); - return FALSE; - } - } - - return TRUE; -} - - -/* - * Module info - */ - -static XF86ModuleVersionInfo vmware_version = { - VMWARE_DRIVER_NAME, - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL, - ABI_CLASS_VIDEODRV, - ABI_VIDEODRV_VERSION, - MOD_CLASS_VIDEODRV, - {0, 0, 0, 0} -}; - -static pointer -vmware_setup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = 0; - - /* This module should be loaded only once, but check to be sure. */ - if (!setupDone) { - setupDone = 1; - - /* Chain load the real driver */ - if (vmware_chain_module(opts)) - return (pointer) 1; - else { - if (errmaj) - *errmaj = LDR_NOSUBENT; - return NULL; - } - } else { - if (errmaj) - *errmaj = LDR_ONCEONLY; - return NULL; - } -} |