From 00d65a521d63790f05da2e9bce2bc2285033db8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 14 Jan 2007 14:16:06 +0000 Subject: [PATCH] Added Eric Petit's VMware graphics driver - thanks! Made the following changes from the version I got from Eric: * made BppForSpace() in DriverInterface.h inline to remove some warnings * renamed driver source files to lower case. * removed Be Inc. copyright from kernel driver as I couldn't see anything coming from Be Inc. there - correct me if I was wrong, Eric. * Minor other changes like added missing header guards. * The README provided in the main directory is only included in the accelerant directory. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19793 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../private/graphics/vmware/DriverInterface.h | 119 ++++ headers/private/graphics/vmware/svga_reg.h | 518 +++++++++++++++++ .../graphics/vmware/vm_device_version.h | 14 + src/add-ons/accelerants/Jamfile | 1 + src/add-ons/accelerants/vmware/Acceleration.c | 69 +++ src/add-ons/accelerants/vmware/Cursor.c | 82 +++ .../accelerants/vmware/EngineManagment.c | 66 +++ src/add-ons/accelerants/vmware/Fifo.c | 140 +++++ .../accelerants/vmware/GetAccelerantHook.c | 79 +++ src/add-ons/accelerants/vmware/GetModeInfo.c | 57 ++ src/add-ons/accelerants/vmware/GlobalData.c | 18 + src/add-ons/accelerants/vmware/GlobalData.h | 37 ++ .../accelerants/vmware/InitAccelerant.c | 111 ++++ src/add-ons/accelerants/vmware/Jamfile | 20 + .../accelerants/vmware/ProposeDisplayMode.c | 77 +++ src/add-ons/accelerants/vmware/README | 541 ++++++++++++++++++ .../accelerants/vmware/SetDisplayMode.c | 97 ++++ src/add-ons/accelerants/vmware/generic.h | 54 ++ src/add-ons/kernel/drivers/graphics/Jamfile | 1 + .../kernel/drivers/graphics/vmware/Jamfile | 12 + .../kernel/drivers/graphics/vmware/device.c | 341 +++++++++++ .../kernel/drivers/graphics/vmware/driver.c | 122 ++++ .../kernel/drivers/graphics/vmware/driver.h | 65 +++ 23 files changed, 2641 insertions(+) create mode 100644 headers/private/graphics/vmware/DriverInterface.h create mode 100644 headers/private/graphics/vmware/svga_reg.h create mode 100644 headers/private/graphics/vmware/vm_device_version.h create mode 100644 src/add-ons/accelerants/vmware/Acceleration.c create mode 100644 src/add-ons/accelerants/vmware/Cursor.c create mode 100644 src/add-ons/accelerants/vmware/EngineManagment.c create mode 100644 src/add-ons/accelerants/vmware/Fifo.c create mode 100644 src/add-ons/accelerants/vmware/GetAccelerantHook.c create mode 100644 src/add-ons/accelerants/vmware/GetModeInfo.c create mode 100644 src/add-ons/accelerants/vmware/GlobalData.c create mode 100644 src/add-ons/accelerants/vmware/GlobalData.h create mode 100644 src/add-ons/accelerants/vmware/InitAccelerant.c create mode 100644 src/add-ons/accelerants/vmware/Jamfile create mode 100644 src/add-ons/accelerants/vmware/ProposeDisplayMode.c create mode 100644 src/add-ons/accelerants/vmware/README create mode 100644 src/add-ons/accelerants/vmware/SetDisplayMode.c create mode 100644 src/add-ons/accelerants/vmware/generic.h create mode 100644 src/add-ons/kernel/drivers/graphics/vmware/Jamfile create mode 100644 src/add-ons/kernel/drivers/graphics/vmware/device.c create mode 100644 src/add-ons/kernel/drivers/graphics/vmware/driver.c create mode 100644 src/add-ons/kernel/drivers/graphics/vmware/driver.h diff --git a/headers/private/graphics/vmware/DriverInterface.h b/headers/private/graphics/vmware/DriverInterface.h new file mode 100644 index 0000000000..0b6fda5e1d --- /dev/null +++ b/headers/private/graphics/vmware/DriverInterface.h @@ -0,0 +1,119 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#ifndef DRIVERINTERFACE_H +#define DRIVERINTERFACE_H + +#include +#include +#include +#include +#include + +#include "vm_device_version.h" +#include "svga_reg.h" + +#define MAX_SAMPLE_DEVICE_NAME_LENGTH 32 +#define CURSOR_ID 1 + + +/*--------------------------------------------------------------------*/ +/* Benaphores */ + +typedef struct { + sem_id sem; + int32 ben; +} Benaphore; +#define INIT_BEN(x) x.sem = create_sem(0, "VMware "#x); x.ben = 0; +#define ACQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem); +#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem); +#define DELETE_BEN(x) delete_sem(x.sem); + + +/*--------------------------------------------------------------------*/ +/* Utils */ + +#define ROUND_TO_PAGE_SIZE(x) (((x)+(B_PAGE_SIZE)-1)&~((B_PAGE_SIZE)-1)) + +static inline int +BppForSpace(int space) +{ + switch (space) { + case B_RGB32: + return 32; + case B_RGB24: + return 24; + case B_RGB16: + return 16; + case B_RGB15: + return 15; + case B_CMAP8: + return 8; + } + return 0; +} + + +/*--------------------------------------------------------------------*/ +/* Request codes for ioctl() */ + +enum { + VMWARE_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, + VMWARE_FIFO_START, + VMWARE_FIFO_STOP, + VMWARE_FIFO_SYNC, + VMWARE_SET_MODE, + VMWARE_SHOW_CURSOR, + VMWARE_MOVE_CURSOR, +}; + + +/*--------------------------------------------------------------------*/ +/* Structure shared between the kernel driver and the accelerant */ + +typedef struct { + /* Device info and capabilities */ + uint16 vendorId; + uint16 deviceId; + uint8 revision; + uint32 maxWidth; + uint32 maxHeight; + void *fbDma; + uint32 fbSize; + void *fifoDma; + uint32 fifoSize; + uint32 fifoMin; + uint32 capabilities; + uint32 fifoCapabilities; + uint32 fifoFlags; + + /* For registers access */ + uint16 indexPort; + uint16 valuePort; + + /* Mapped areas */ + area_id fbArea; + void *fb; + area_id fifoArea; + void *fifo; + + /* This changes when we switch to another mode */ + uint32 fbOffset; + uint32 bytesPerRow; + + /* Current display mode */ + display_mode dm; + + Benaphore engineLock; + Benaphore fifoLock; + uint32 fifoNext; +} SharedInfo; + +#endif diff --git a/headers/private/graphics/vmware/svga_reg.h b/headers/private/graphics/vmware/svga_reg.h new file mode 100644 index 0000000000..7aa6620071 --- /dev/null +++ b/headers/private/graphics/vmware/svga_reg.h @@ -0,0 +1,518 @@ +/* + * Copyright 1998-2001, VMware, Inc. + * Distributed under the terms of the MIT License. + * + */ + +/* + * svga_reg.h -- + * + * SVGA hardware definitions + */ + +#ifndef _SVGA_REG_H_ +#define _SVGA_REG_H_ + +/* + * Memory and port addresses and fundamental constants + */ + +/* + * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code. This + * isn't such a bad thing for forward compatibility. --Jeremy. + */ +#define SVGA_MAX_WIDTH 2360 +#define SVGA_MAX_HEIGHT 1770 +#define SVGA_MAX_BITS_PER_PIXEL 32 +#define SVGA_MAX_DEPTH 24 + +#define SVGA_FB_MAX_SIZE \ + ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \ + SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT) + +#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8 +#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH) +#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS) + +#define SVGA_MAGIC 0x900000UL +#define SVGA_MAKE_ID(ver) (SVGA_MAGIC << 8 | (ver)) + +/* Version 2 let the address of the frame buffer be unsigned on Win32 */ +#define SVGA_VERSION_2 2 +#define SVGA_ID_2 SVGA_MAKE_ID(SVGA_VERSION_2) + +/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so + PALETTE_BASE has moved */ +#define SVGA_VERSION_1 1 +#define SVGA_ID_1 SVGA_MAKE_ID(SVGA_VERSION_1) + +/* Version 0 is the initial version */ +#define SVGA_VERSION_0 0 +#define SVGA_ID_0 SVGA_MAKE_ID(SVGA_VERSION_0) + +/* Invalid SVGA_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 + +/* 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 + */ + +enum { + SVGA_REG_ID = 0, + SVGA_REG_ENABLE = 1, + SVGA_REG_WIDTH = 2, + SVGA_REG_HEIGHT = 3, + 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_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_OFFSET = 14, + SVGA_REG_VRAM_SIZE = 15, + SVGA_REG_FB_SIZE = 16, + + /* 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_SIZE = 19, + SVGA_REG_CONFIG_DONE = 20, /* Set when memory area configured */ + SVGA_REG_SYNC = 21, /* Write to force synchronization */ + SVGA_REG_BUSY = 22, /* Read to check if sync is done */ + 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_TOP = 33, /* 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: + First 4 are reserved for VESA BIOS Extension; any remaining are for + the use of the current SVGA driver. */ +}; + + +/* + * Capabilities + */ + +#define SVGA_CAP_NONE 0x00000 +#define SVGA_CAP_RECT_FILL 0x00001 +#define SVGA_CAP_RECT_COPY 0x00002 +#define SVGA_CAP_RECT_PAT_FILL 0x00004 +#define SVGA_CAP_LEGACY_OFFSCREEN 0x00008 +#define SVGA_CAP_RASTER_OP 0x00010 +#define SVGA_CAP_CURSOR 0x00020 +#define SVGA_CAP_CURSOR_BYPASS 0x00040 +#define SVGA_CAP_CURSOR_BYPASS_2 0x00080 +#define SVGA_CAP_8BIT_EMULATION 0x00100 +#define SVGA_CAP_ALPHA_CURSOR 0x00200 +#define SVGA_CAP_GLYPH 0x00400 +#define SVGA_CAP_GLYPH_CLIPPING 0x00800 +#define SVGA_CAP_OFFSCREEN_1 0x01000 +#define SVGA_CAP_ALPHA_BLEND 0x02000 +#define SVGA_CAP_3D 0x04000 +#define SVGA_CAP_EXTENDED_FIFO 0x08000 +#define SVGA_CAP_MULTIMON 0x10000 +#define SVGA_CAP_PITCHLOCK 0x20000 + +/* + * Raster op codes (same encoding as X) used by FIFO drivers. + */ + +#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 + +#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) + +/* + * 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) + + +/* + * FIFO offsets (viewed as an array of 32-bit words) + */ + +enum { + /* + * The original defined FIFO offsets + */ + + SVGA_FIFO_MIN = 0, + SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */ + SVGA_FIFO_NEXT_CMD, + SVGA_FIFO_STOP, + + /* + * Additional offsets added as of SVGA_CAP_EXTENDED_FIFO + */ + + SVGA_FIFO_CAPABILITIES = 4, + SVGA_FIFO_FLAGS, + SVGA_FIFO_FENCE, + SVGA_FIFO_3D_HWVERSION, /* Check SVGA3dHardwareVersion in svga3d_reg.h */ + SVGA_FIFO_PITCHLOCK, + + /* + * Always keep this last. It's not an offset with semantic value, but + * rather a convenient way to produce the value of fifo[SVGA_FIFO_NUM_REGS] + */ + + SVGA_FIFO_NUM_REGS +}; + +/* + * FIFO Capabilities + * + * Fence -- Fence register and command are supported + * Accel Front -- Front buffer only commands are supported + * Pitch Lock -- Pitch lock register is supported + */ + +#define SVGA_FIFO_CAP_NONE 0 +#define SVGA_FIFO_CAP_FENCE (1<<0) +#define SVGA_FIFO_CAP_ACCELFRONT (1<<1) +#define SVGA_FIFO_CAP_PITCHLOCK (1<<2) + + +/* + * FIFO Flags + * + * Accel Front -- Driver should use front buffer only commands + */ + +#define SVGA_FIFO_FLAG_NONE 0 +#define SVGA_FIFO_FLAG_ACCELFRONT (1<<0) + + +/* + * Drawing object ID's, in the range 0 to SVGA_MAX_ID + */ + +#define SVGA_MAX_ID 499 + +/* + * 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_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) + +/* + * Increment from one scanline to the next of a bitmap or pixmap + */ +#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32)) +#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32)) + +/* + * Transparent color for DRAW_GLYPH_CLIPPED + */ +#define SVGA_COLOR_TRANSPARENT (~0) + +/* + * Commands in the command FIFO + */ + +#define SVGA_CMD_INVALID_CMD 0 + /* FIFO layout: + (well, undefined) */ + +#define SVGA_CMD_UPDATE 1 + /* FIFO layout: + X, Y, Width, Height */ + +#define SVGA_CMD_RECT_FILL 2 + /* FIFO layout: + Color, X, Y, Width, Height */ + +#define SVGA_CMD_RECT_COPY 3 + /* FIFO layout: + Source X, Source Y, Dest X, Dest Y, Width, Height */ + +#define SVGA_CMD_DEFINE_BITMAP 4 + /* FIFO layout: + Pixmap ID, Width, Height, */ + +#define SVGA_CMD_DEFINE_BITMAP_SCANLINE 5 + /* FIFO layout: + Pixmap ID, Width, Height, Line #, scanline */ + +#define SVGA_CMD_DEFINE_PIXMAP 6 + /* FIFO layout: + Pixmap ID, Width, Height, Depth, */ + +#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 */ + +#define SVGA_CMD_RECT_PIXMAP_FILL 9 + /* FIFO layout: + Pixmap ID, X, Y, Width, Height */ + +#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 */ + +#define SVGA_CMD_FREE_OBJECT 12 + /* FIFO layout: + Object (pixmap, bitmap, ...) ID */ + +#define SVGA_CMD_RECT_ROP_FILL 13 + /* FIFO layout: + Color, X, Y, Width, Height, ROP */ + +#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 */ + +#define SVGA_CMD_RECT_ROP_PIXMAP_FILL 16 + /* FIFO layout: + ID, X, Y, Width, Height, ROP */ + +#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 */ + +#define SVGA_CMD_DEFINE_CURSOR 19 + /* FIFO layout: + ID, Hotspot X, Hotspot Y, Width, Height, + Depth for AND mask, Depth for XOR mask, + , */ + +#define SVGA_CMD_DISPLAY_CURSOR 20 + /* FIFO layout: + ID, On/Off (1 or 0) */ + +#define SVGA_CMD_MOVE_CURSOR 21 + /* FIFO layout: + X, Y */ + +#define SVGA_CMD_DEFINE_ALPHA_CURSOR 22 + /* FIFO layout: + ID, Hotspot X, Hotspot Y, Width, Height, + */ + +#define SVGA_CMD_DRAW_GLYPH 23 + /* FIFO layout: + X, Y, W, H, FGCOLOR, */ + +#define SVGA_CMD_DRAW_GLYPH_CLIPPED 24 + /* FIFO layout: + X, Y, W, H, FGCOLOR, BGCOLOR, , + 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_MAX 31 + +#define SVGA_CMD_MAX_ARGS 64 + +/* + * Location and size of SVGA frame buffer and the FIFO. + */ +#define SVGA_VRAM_MAX_SIZE (16 * 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 + +#endif diff --git a/headers/private/graphics/vmware/vm_device_version.h b/headers/private/graphics/vmware/vm_device_version.h new file mode 100644 index 0000000000..43514d4afe --- /dev/null +++ b/headers/private/graphics/vmware/vm_device_version.h @@ -0,0 +1,14 @@ +/* + * Copyright 1998-2001, VMware, Inc. + * Distributed under the terms of the MIT License. + * + */ + +#ifndef VM_DEVICE_VERSION_H +#define VM_DEVICE_VERSION_H + +#define PCI_VENDOR_ID_VMWARE 0x15AD +#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 +#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710 + +#endif /* VM_DEVICE_VERSION_H */ diff --git a/src/add-ons/accelerants/Jamfile b/src/add-ons/accelerants/Jamfile index 7aef3e3b59..71bf4d8b88 100644 --- a/src/add-ons/accelerants/Jamfile +++ b/src/add-ons/accelerants/Jamfile @@ -12,5 +12,6 @@ SubInclude HAIKU_TOP src add-ons accelerants tdfx ; SubInclude HAIKU_TOP src add-ons accelerants skeleton ; SubInclude HAIKU_TOP src add-ons accelerants vesa ; SubInclude HAIKU_TOP src add-ons accelerants via ; +SubInclude HAIKU_TOP src add-ons accelerants vmware ; SubIncludeGPL HAIKU_TOP src add-ons accelerants atimach64 ; diff --git a/src/add-ons/accelerants/vmware/Acceleration.c b/src/add-ons/accelerants/vmware/Acceleration.c new file mode 100644 index 0000000000..288e3ff314 --- /dev/null +++ b/src/add-ons/accelerants/vmware/Acceleration.c @@ -0,0 +1,69 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + + +void +SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count) +{ + int i; + blit_params * b; + + for (i = 0; i < count; i++) { + b = &list[i]; +#if 0 + TRACE("BLIT %dx%d, %dx%d->%dx%d\n", b->width + 1, b->height + 1, + b->src_left, b->src_top, b->dest_left, b->dest_top); +#endif + FifoBeginWrite(); + FifoWrite(SVGA_CMD_RECT_COPY); + FifoWrite(b->src_left); + FifoWrite(b->src_top); + FifoWrite(b->dest_left); + FifoWrite(b->dest_top); + FifoWrite(b->width + 1); + FifoWrite(b->height + 1); + FifoEndWrite(); + } +} + + +void +FILL_RECTANGLE(engine_token *et, uint32 colorIndex, + fill_rect_params *list, uint32 count) +{ + int i; + fill_rect_params * f; + + for (i = 0; i < count; i++) { + f = &list[i]; +#if 0 + TRACE("FILL %lX, %dx%d->%dx%d\n", colorIndex, + f->left, f->top, f->right, f->bottom); +#endif + /* TODO */ + } +} + + +void +INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count) +{ + /* TODO */ +} + + +void +FILL_SPAN(engine_token * et, uint32 colorIndex, uint16 * list, uint32 count) +{ + /* TODO */ +} + diff --git a/src/add-ons/accelerants/vmware/Cursor.c b/src/add-ons/accelerants/vmware/Cursor.c new file mode 100644 index 0000000000..db380e78f8 --- /dev/null +++ b/src/add-ons/accelerants/vmware/Cursor.c @@ -0,0 +1,82 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + +status_t +SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, + uint16 hot_y, uint8 * andMask, uint8 * xorMask) +{ + int i, shift; + uint32 * alphaCursor; + + TRACE("SET_CURSOR_SHAPE (%d, %d, %d, %d)\n", width, height, hot_x, hot_y); + + /* Sanity check */ + if (hot_x >= width || hot_y >= height) + return B_ERROR; + + /* Build ARGB image */ + alphaCursor = calloc(1, height * width * sizeof(uint32)); + shift = 7; + for (i = 0; i < height * width; i++) { + if (!((*andMask >> shift) & 1)) { + /* Opaque */ + alphaCursor[i] |= 0xFF000000; + if (!((*xorMask >> shift) & 1)) + /* White */ + alphaCursor[i] |= 0x00FFFFFF; + } + if (--shift < 0) { + shift = 7; + andMask++; + xorMask++; + } + } + + /* Give it to VMware */ + FifoBeginWrite(); + FifoWrite(SVGA_CMD_DEFINE_ALPHA_CURSOR); + FifoWrite(CURSOR_ID); + FifoWrite(hot_x); + FifoWrite(hot_y); + FifoWrite(width); + FifoWrite(height); + for (i = 0; i < height * width; i++) + FifoWrite(alphaCursor[i]); + FifoEndWrite(); + + free(alphaCursor); + + return B_OK; +} + + +void +MOVE_CURSOR(uint16 x, uint16 y) +{ + uint16 pos[2]; + + //TRACE("MOVE_CURSOR (%d, %d)\n", x, y); + + pos[0] = x; + pos[1] = y; + ioctl(gFd, VMWARE_MOVE_CURSOR, pos, sizeof(pos)); +} + + +void +SHOW_CURSOR(bool isVisible) +{ + TRACE("SHOW_CURSOR (%d)\n", isVisible); + + ioctl(gFd, VMWARE_SHOW_CURSOR, &isVisible, sizeof(bool)); +} + diff --git a/src/add-ons/accelerants/vmware/EngineManagment.c b/src/add-ons/accelerants/vmware/EngineManagment.c new file mode 100644 index 0000000000..9790106446 --- /dev/null +++ b/src/add-ons/accelerants/vmware/EngineManagment.c @@ -0,0 +1,66 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + +static engine_token vmwareEngineToken = {1, B_2D_ACCELERATION, NULL}; + +uint32 +ACCELERANT_ENGINE_COUNT() +{ + return 1; +} + + +status_t +ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token * st, + engine_token ** et) +{ + ACQUIRE_BEN(gSi->engineLock); + if (st) + SYNC_TO_TOKEN(st); + *et = &vmwareEngineToken; + return B_OK; +} + + +status_t +RELEASE_ENGINE(engine_token * et, sync_token * st) +{ + if (st) + GET_SYNC_TOKEN(et, st); + RELEASE_BEN(gSi->engineLock); + return B_OK; +} + + +void +WAIT_ENGINE_IDLE() +{ + FifoSync(); +} + + +status_t +GET_SYNC_TOKEN(engine_token * et, sync_token * st) +{ + st->engine_id = et->engine_id; + st->counter = 0; + return B_OK; +} + + +status_t +SYNC_TO_TOKEN(sync_token * st) +{ + WAIT_ENGINE_IDLE(); + return B_OK; +} + diff --git a/src/add-ons/accelerants/vmware/Fifo.c b/src/add-ons/accelerants/vmware/Fifo.c new file mode 100644 index 0000000000..5d1e5cea71 --- /dev/null +++ b/src/add-ons/accelerants/vmware/Fifo.c @@ -0,0 +1,140 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + + +#include "GlobalData.h" + + +/*--------------------------------------------------------------------*/ +/* UpdateThread: we explicitely need to tell VMware what and when + * something should be refreshed from the frame buffer. Since the + * app_server doesn't tell us what it's doing, we simply force a full + * screen update every 1/50 second */ + +static int32 +UpdateThread(void *data) +{ + bigtime_t begin, end, wait; + + while (!gUpdateThreadDie) { + begin = system_time(); + FifoUpdateFullscreen(); + end = system_time(); + + /* 50 Hz refresh */ + wait = 20000 - (end - begin); + if (wait > 0) + snooze(wait); + } + + return B_OK; +} + + +static void +FifoPrintCapabilities(int c) +{ + TRACE("fifo capabilities:\n"); + if (c & SVGA_FIFO_CAP_FENCE) TRACE("FENCE\n"); + if (c & SVGA_FIFO_CAP_ACCELFRONT) TRACE("ACCELFRONT\n"); + if (c & SVGA_FIFO_CAP_PITCHLOCK) TRACE("PITCHLOCK\n"); +} + + +void +FifoInit() +{ + uint32 *fifo = gSi->fifo; + + /* Stop update thread, if any */ + if (gUpdateThread > B_OK) { + status_t exitValue; + gUpdateThreadDie = 1; + wait_for_thread(gUpdateThread, &exitValue); + } + + gSi->fifoCapabilities = 0; + gSi->fifoFlags = 0; + if (gSi->capabilities & SVGA_CAP_EXTENDED_FIFO) { + gSi->fifoCapabilities = fifo[SVGA_FIFO_CAPABILITIES]; + gSi->fifoFlags = fifo[SVGA_FIFO_FLAGS]; + FifoPrintCapabilities(gSi->fifoCapabilities); + } + + fifo[SVGA_FIFO_MIN] = gSi->fifoMin * 4; + fifo[SVGA_FIFO_MAX] = gSi->fifoSize; + fifo[SVGA_FIFO_NEXT_CMD] = fifo[SVGA_FIFO_MIN]; + fifo[SVGA_FIFO_STOP] = fifo[SVGA_FIFO_MIN]; + + gSi->fifoNext = fifo[SVGA_FIFO_NEXT_CMD]; + + /* Launch a new update thread */ + gUpdateThreadDie = 0; + gUpdateThread = spawn_thread(UpdateThread, "VMware", + B_REAL_TIME_DISPLAY_PRIORITY, NULL); + resume_thread(gUpdateThread); + + TRACE("init fifo: %ld -> %ld\n", + fifo[SVGA_FIFO_MIN], fifo[SVGA_FIFO_MAX]); +} + + +void +FifoSync() +{ + ioctl(gFd, VMWARE_FIFO_SYNC, NULL, 0); +} + + +void +FifoBeginWrite() +{ + ACQUIRE_BEN(gSi->fifoLock); +} + + +void +FifoWrite(uint32 value) +{ + uint32 *fifo = gSi->fifo; + uint32 fifoCapacity = fifo[SVGA_FIFO_MAX] - fifo[SVGA_FIFO_MIN]; + + /* If the fifo is full, sync it */ + if (fifo[SVGA_FIFO_STOP] == fifo[SVGA_FIFO_NEXT_CMD] + 4 || + fifo[SVGA_FIFO_STOP] + fifoCapacity == fifo[SVGA_FIFO_NEXT_CMD] + 4) + FifoSync(); + + fifo[gSi->fifoNext / 4] = value; + gSi->fifoNext = (gSi->fifoNext + 4) % fifoCapacity; +} + + +void +FifoEndWrite() +{ + uint32 *fifo = gSi->fifo; + + fifo[SVGA_FIFO_NEXT_CMD] = gSi->fifoNext; + RELEASE_BEN(gSi->fifoLock); +} + + +void +FifoUpdateFullscreen() +{ + FifoBeginWrite(); + FifoWrite(SVGA_CMD_UPDATE); + FifoWrite(0); + FifoWrite(0); + FifoWrite(gSi->dm.virtual_width); + FifoWrite(gSi->dm.virtual_height); + FifoEndWrite(); +} + diff --git a/src/add-ons/accelerants/vmware/GetAccelerantHook.c b/src/add-ons/accelerants/vmware/GetAccelerantHook.c new file mode 100644 index 0000000000..3cebed241e --- /dev/null +++ b/src/add-ons/accelerants/vmware/GetAccelerantHook.c @@ -0,0 +1,79 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + + +void * +get_accelerant_hook(uint32 feature, void *data) +{ + switch (feature) { +#define HOOK(x) case B_##x: return (void *)x +#define ZERO(x) case B_##x: return (void *)0 + + /* initialization */ + HOOK(INIT_ACCELERANT); + HOOK(CLONE_ACCELERANT); + + HOOK(ACCELERANT_CLONE_INFO_SIZE); + HOOK(GET_ACCELERANT_CLONE_INFO); + HOOK(UNINIT_ACCELERANT); + //HOOK(GET_ACCELERANT_DEVICE_INFO); + HOOK(ACCELERANT_RETRACE_SEMAPHORE); + + /* mode configuration */ + HOOK(ACCELERANT_MODE_COUNT); + HOOK(GET_MODE_LIST); + HOOK(PROPOSE_DISPLAY_MODE); + HOOK(SET_DISPLAY_MODE); + HOOK(GET_DISPLAY_MODE); + HOOK(GET_FRAME_BUFFER_CONFIG); + HOOK(GET_PIXEL_CLOCK_LIMITS); + ZERO(MOVE_DISPLAY); + HOOK(SET_INDEXED_COLORS); + ZERO(GET_TIMING_CONSTRAINTS); + + /* Power Managment (SetDisplayMode.c) */ + HOOK(DPMS_CAPABILITIES); + HOOK(DPMS_MODE); + HOOK(SET_DPMS_MODE); + + /* Cursor managment (Cursor.c) */ +#if 0 + if (gSi->capabilities & SVGA_CAP_ALPHA_CURSOR) { + HOOK(SET_CURSOR_SHAPE); + HOOK(MOVE_CURSOR); + HOOK(SHOW_CURSOR); + } +#endif + + /* synchronization */ + HOOK(ACCELERANT_ENGINE_COUNT); + HOOK(ACQUIRE_ENGINE); + HOOK(RELEASE_ENGINE); + HOOK(WAIT_ENGINE_IDLE); + HOOK(GET_SYNC_TOKEN); + HOOK(SYNC_TO_TOKEN); + + /* 2D acceleration (Acceleration.c) */ + if (gSi->capabilities & SVGA_CAP_RECT_COPY) + HOOK(SCREEN_TO_SCREEN_BLIT); + ZERO(FILL_RECTANGLE); + ZERO(INVERT_RECTANGLE); + ZERO(FILL_SPAN); + ZERO(SCREEN_TO_SCREEN_TRANSPARENT_BLIT); + ZERO(SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT); + +#undef HOOK +#undef ZERO + } + + return 0; +} diff --git a/src/add-ons/accelerants/vmware/GetModeInfo.c b/src/add-ons/accelerants/vmware/GetModeInfo.c new file mode 100644 index 0000000000..76f26ace42 --- /dev/null +++ b/src/add-ons/accelerants/vmware/GetModeInfo.c @@ -0,0 +1,57 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + + +status_t +GET_DISPLAY_MODE(display_mode *currentMode) +{ + TRACE("GET_DISPLAY_MODE\n"); + + *currentMode = gSi->dm; + return B_OK; +} + + +status_t +GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb) +{ + TRACE("GET_FRAME_BUFFER_CONFIG\n"); + + afb->frame_buffer = gSi->fb + gSi->fbOffset; + afb->frame_buffer_dma = gSi->fbDma + gSi->fbOffset; + afb->bytes_per_row = gSi->bytesPerRow; + + TRACE("fb: %p, fb_dma: %p, row: %d bytes\n", afb->frame_buffer, + afb->frame_buffer_dma, afb->bytes_per_row); + + return B_OK; +} + + +status_t +GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high) +{ + TRACE("GET_PIXEL_CLOCK_LIMITS\n"); + + /* ? */ + *low = 1; + *high = 0xFFFFFFFF; + return B_OK; +} + + +sem_id +ACCELERANT_RETRACE_SEMAPHORE() +{ + return B_ERROR; +} + diff --git a/src/add-ons/accelerants/vmware/GlobalData.c b/src/add-ons/accelerants/vmware/GlobalData.c new file mode 100644 index 0000000000..6d9eea4770 --- /dev/null +++ b/src/add-ons/accelerants/vmware/GlobalData.c @@ -0,0 +1,18 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + +int gFd; +SharedInfo * gSi; +area_id gSharedArea; +int gAccelerantIsClone; +thread_id gUpdateThread = B_ERROR; +volatile int gUpdateThreadDie; diff --git a/src/add-ons/accelerants/vmware/GlobalData.h b/src/add-ons/accelerants/vmware/GlobalData.h new file mode 100644 index 0000000000..72e817687d --- /dev/null +++ b/src/add-ons/accelerants/vmware/GlobalData.h @@ -0,0 +1,37 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ +#ifndef GLOBAL_DATA_H +#define GLOBAL_DATA_H + + +#include +#undef TRACE +#define TRACE(a...) _sPrintf("VMware: " ##a) + +#include "DriverInterface.h" +#include "generic.h" + +/* Global variables */ +extern int gFd; +extern SharedInfo *gSi; +extern area_id gSharedArea; +extern int gAccelerantIsClone; +extern thread_id gUpdateThread; +extern volatile int gUpdateThreadDie; + +/* Fifo.c */ +void FifoInit(); +void FifoSync(); +void FifoBeginWrite(); +void FifoWrite(uint32 value); +void FifoEndWrite(); +void FifoUpdateFullscreen(); + +#endif // GLOBAL_DATA_H diff --git a/src/add-ons/accelerants/vmware/InitAccelerant.c b/src/add-ons/accelerants/vmware/InitAccelerant.c new file mode 100644 index 0000000000..e274995819 --- /dev/null +++ b/src/add-ons/accelerants/vmware/InitAccelerant.c @@ -0,0 +1,111 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "string.h" +#include "unistd.h" +#include "sys/types.h" +#include "sys/stat.h" +#include "fcntl.h" +#include + +#include "GlobalData.h" + + +/* Initialization code shared between primary and cloned accelerants */ +static +status_t InitCommon(int fd) +{ + status_t ret; + + /* Memorize the file descriptor */ + gFd = fd; + + /* Contact driver and get a pointer to the registers and shared data */ + if ((ret = ioctl(fd, VMWARE_GET_PRIVATE_DATA, &gSharedArea, + sizeof(area_id))) != B_OK) { + TRACE("VMWARE_GET_PRIVATE_DATA failed (%d\n", ret); + return ret; + } + + /* Clone the shared area for our use */ + if ((gSharedArea = clone_area("VMware shared", (void **)&gSi, + B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, gSharedArea)) < 0) { + TRACE("could not clone shared area (%d)\n", gSharedArea); + return gSharedArea; + } + + return B_OK; +} + + +static void +UninitCommon() +{ + delete_area(gSharedArea); +} + + +status_t +INIT_ACCELERANT(int fd) +{ + status_t ret; + + TRACE("INIT_ACCELERANT (%d)\n", fd); + + gAccelerantIsClone = 0; + + /* Common initialization for the primary accelerant and clones */ + if ((ret = InitCommon(fd)) == B_OK) { + /* Init semaphores */ + INIT_BEN(gSi->engineLock); + INIT_BEN(gSi->fifoLock); + } + + TRACE("INIT_ACCELERANT: %d\n", ret); + return ret; +} + + +ssize_t +ACCELERANT_CLONE_INFO_SIZE() +{ + return MAX_SAMPLE_DEVICE_NAME_LENGTH; +} + + +void +GET_ACCELERANT_CLONE_INFO(void *data) +{ + /* TODO */ +} + + +status_t +CLONE_ACCELERANT(void *data) +{ + /* TODO */ + return B_ERROR; +} + + +void +UNINIT_ACCELERANT() +{ + UninitCommon(); + if (gAccelerantIsClone) + close(gFd); + else if (gUpdateThread > B_OK) { + status_t exitValue; + gUpdateThreadDie = 1; + wait_for_thread(gUpdateThread, &exitValue); + } + ioctl(gFd, VMWARE_FIFO_STOP, NULL, 0); +} + diff --git a/src/add-ons/accelerants/vmware/Jamfile b/src/add-ons/accelerants/vmware/Jamfile new file mode 100644 index 0000000000..0e9afb5424 --- /dev/null +++ b/src/add-ons/accelerants/vmware/Jamfile @@ -0,0 +1,20 @@ +SubDir HAIKU_TOP src add-ons accelerants vmware ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders [ FDirName graphics vmware ] ; +UsePrivateHeaders graphics ; + +Addon vmware.accelerant : accelerants : + Acceleration.c + Cursor.c + EngineManagment.c + Fifo.c + GetAccelerantHook.c + GetModeInfo.c + GlobalData.c + InitAccelerant.c + ProposeDisplayMode.c + SetDisplayMode.c + : false +; diff --git a/src/add-ons/accelerants/vmware/ProposeDisplayMode.c b/src/add-ons/accelerants/vmware/ProposeDisplayMode.c new file mode 100644 index 0000000000..a3b47bb623 --- /dev/null +++ b/src/add-ons/accelerants/vmware/ProposeDisplayMode.c @@ -0,0 +1,77 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" +#include + +#define MODE_FLAGS (B_8_BIT_DAC|B_PARALLEL_ACCESS) +#define MODE_COUNT (sizeof(kModeList) / sizeof(display_mode)) + +static const display_mode kModeList[] = +{ { { 19660, 640, 672, 744, 776, 480, 490, 494, 505, 0 }, B_RGB32_LITTLE, 640, 480, 0, 0, MODE_FLAGS }, /* 640x480@50Hz */ + { { 25250, 800, 832, 920, 952, 500, 511, 515, 526, 0 }, B_RGB32_LITTLE, 800, 500, 0, 0, MODE_FLAGS }, /* 800x500@50Hz */ + { { 30970, 800, 832, 944, 976, 600, 613, 618, 631, 0 }, B_RGB32_LITTLE, 800, 600, 0, 0, MODE_FLAGS }, /* 800x600@50Hz */ + { { 41980, 1024, 1056, 1208, 1240, 640, 653, 659, 673, 0 }, B_RGB32_LITTLE, 1024, 640, 0, 0, MODE_FLAGS }, /* 1024x640@50Hz */ + { { 51850, 1024, 1056, 1248, 1280, 768, 784, 791, 807, 0 }, B_RGB32_LITTLE, 1024, 768, 0, 0, MODE_FLAGS }, /* 1024x768@50Hz */ + { { 59420, 1280, 1312, 1536, 1568, 720, 735, 741, 757, 0 }, B_RGB32_LITTLE, 1280, 720, 0, 0, MODE_FLAGS }, /* 1280x720@50Hz */ + { { 64050, 1280, 1312, 1552, 1584, 768, 784, 791, 807, 0 }, B_RGB32_LITTLE, 1280, 768, 0, 0, MODE_FLAGS }, /* 1280x768@50Hz */ + { { 65740, 1152, 1184, 1432, 1464, 854, 872, 879, 897, 0 }, B_RGB32_LITTLE, 1152, 854, 0, 0, MODE_FLAGS }, /* 1152x854@50Hz */ + { { 67260, 1280, 1312, 1560, 1592, 800, 817, 824, 841, 0 }, B_RGB32_LITTLE, 1280, 800, 0, 0, MODE_FLAGS }, /* 1280x800@50Hz */ + { { 86730, 1440, 1472, 1800, 1832, 900, 919, 927, 946, 0 }, B_RGB32_LITTLE, 1440, 900, 0, 0, MODE_FLAGS }, /* 1440x900@50Hz */ + { { 90890, 1280, 1312, 1656, 1688, 1024, 1045, 1054, 1076, 0 }, B_RGB32_LITTLE, 1280, 1024, 0, 0, MODE_FLAGS }, /* 1280x1024@50Hz */ + { { 102150, 1400, 1432, 1816, 1848, 1050, 1072, 1081, 1103, 0 }, B_RGB32_LITTLE, 1400, 1050, 0, 0, MODE_FLAGS }, /* 1400x1050@50Hz */ + { { 121680, 1680, 1712, 2168, 2200, 1050, 1072, 1081, 1103, 0 }, B_RGB32_LITTLE, 1680, 1050, 0, 0, MODE_FLAGS }, /* 1680x1050@50Hz */ + { { 137970, 1600, 1632, 2152, 2184, 1200, 1225, 1235, 1261, 0 }, B_RGB32_LITTLE, 1600, 1200, 0, 0, MODE_FLAGS }, /* 1600x1200@50Hz */ + { { 164500, 1920, 1952, 2576, 2608, 1200, 1225, 1235, 1261, 0 }, B_RGB32_LITTLE, 1920, 1200, 0, 0, MODE_FLAGS }, /* 1920x1200@50Hz */ + { { 179080, 1792, 1824, 2504, 2536, 1344, 1372, 1383, 1412, 0 }, B_RGB32_LITTLE, 1792, 1344, 0, 0, MODE_FLAGS }, /* 1792x1344@50Hz */ + { { 194330, 1856, 1888, 2624, 2656, 1392, 1421, 1432, 1462, 0 }, B_RGB32_LITTLE, 1856, 1392, 0, 0, MODE_FLAGS }, /* 1856x1392@50Hz */ + { { 210640, 1920, 1952, 2752, 2784, 1440, 1470, 1482, 1513, 0 }, B_RGB32_LITTLE, 1920, 1440, 0, 0, MODE_FLAGS }, /* 1920x1440@50Hz */ + { { 245600, 2048, 2080, 3008, 3040, 1536, 1568, 1581, 1613, 0 }, B_RGB32_LITTLE, 2048, 1536, 0, 0, MODE_FLAGS }, /* 2048x1536@50Hz */ +}; + + +status_t +PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, + const display_mode *high) +{ + TRACE("PROPOSE_DISPLAY_MODE\n"); + + /* Arbitrary - I don't know if VMware really has a lower limit */ + if (target->virtual_width < 320 || target->virtual_height < 240) + return B_ERROR; + + if (target->virtual_width > gSi->maxWidth || + target->virtual_height > gSi->maxHeight) + return B_ERROR; + + if (target->space != B_RGB32_LITTLE) + return B_ERROR; + + /* Any such mode is OK, even if it isn't in our propose list */ + return B_OK; +} + + +uint32 +ACCELERANT_MODE_COUNT() +{ + TRACE("ACCELERANT_MODE_COUNT: %d\n", MODE_COUNT); + return MODE_COUNT; +} + + +status_t +GET_MODE_LIST(display_mode * dm) +{ + TRACE("GET_MODE_LIST\n"); + memcpy(dm, kModeList, sizeof(kModeList)); + return B_OK; +} + diff --git a/src/add-ons/accelerants/vmware/README b/src/add-ons/accelerants/vmware/README new file mode 100644 index 0000000000..cf0eebd25b --- /dev/null +++ b/src/add-ons/accelerants/vmware/README @@ -0,0 +1,541 @@ + +Copyright (C) 1999-2002 VMware, Inc. +All Rights Reserved + +The code here may be used/distributed under the terms of the standard +XFree86 license. + + + VMware SVGA Device Interface and Programming Model + -------------------------------------------------- + + +Include Files +------------- + +svga_reg.h + SVGA register definitions, SVGA capabilities, and FIFO command definitions. + +svga_limits.h + Included by svga_reg.h, defines maximum frame buffer and memory region + sizes. + +guest_os.h + Values for the GUEST_ID register. + +vm_basic_types.h + Common type definitions. + +vm_device_version.h + PCI vendor ID's and related information. + + +Programming the VMware SVGA Device +---------------------------------- + +1. Reading/writing a register: + + The SVGA registers are addressed by an index/value pair of 32 bit + registers in the IO address space. + + The 0710 VMware SVGA chipset (PCI device ID PCI_DEVICE_ID_VMWARE_SVGA) has + its index and value ports hardcoded at: + + index: SVGA_LEGACY_BASE_PORT + 4 * SVGA_INDEX_PORT + value: SVGA_LEGACY_BASE_PORT + 4 * SVGA_VALUE_PORT + + The 0405 VMware SVGA chipset (PCI device ID PCI_DEVICE_ID_VMWARE_SVGA2) + determines its index and value ports as a function of the first base + address register in its PCI configuration space as: + + index: + SVGA_INDEX_PORT + value: + SVGA_VALUE_PORT + + To read a register: + Set the index port to the index of the register, using a dword OUT + Do a dword IN from the value port + + To write a register: + Set the index port to the index of the register, using a dword OUT + Do a dword OUT to the value port + + Example, setting the width to 1024: + + mov eax, SVGA_REG_WIDTH + mov edx, + out dx, eax + mov eax, 1024 + mov edx, + out dx, eax + +2. Initialization + Check the version number + loop: + Write into SVGA_REG_ID the maximum SVGA_ID_* the driver supports. + Read from SVGA_REG_ID. + Check if it is the value you wrote. + If yes, VMware SVGA device supports it + If no, decrement SVGA_ID_* and goto loop + This algorithm converges. + + Map the frame buffer and the command FIFO + Read SVGA_REG_FB_START, SVGA_REG_FB_SIZE, SVGA_REG_MEM_START, + SVGA_REG_MEM_SIZE. + Map the frame buffer (FB) and the FIFO memory (MEM) + + Get the device capabilities and frame buffer dimensions + Read SVGA_REG_CAPABILITIES, SVGA_REG_MAX_WIDTH, SVGA_REG_MAX_HEIGHT, + and SVGA_REG_HOST_BITS_PER_PIXEL / SVGA_REG_BITS_PER_PIXEL. + + Note: The capabilities can and do change without the PCI device ID + changing or the SVGA_REG_ID changing. A driver should always check + the capabilities register when loading before expecting any + capabilities-determined feature to be available. See below for a list + of capabilities as of this writing. + + Note: If SVGA_CAP_8BIT_EMULATION is not set, then it is possible that + SVGA_REG_HOST_BITS_PER_PIXEL does not exist and + SVGA_REG_BITS_PER_PIXEL should be read instead. + + Report the Guest Operating System + Write SVGA_REG_GUEST_ID with the appropriate value from . + While not required in any way, this is useful information for the + virtual machine to have available for reporting and sanity checking + purposes. + + SetMode + Set SVGA_REG_WIDTH, SVGA_REG_HEIGHT, SVGA_REG_BITS_PER_PIXEL + Read SVGA_REG_FB_OFFSET + (SVGA_REG_FB_OFFSET is the offset from SVGA_REG_FB_START of the + visible portion of the frame buffer) + Read SVGA_REG_BYTES_PER_LINE, SVGA_REG_DEPTH, SVGA_REG_PSEUDOCOLOR, + SVGA_REG_RED_MASK, SVGA_REG_GREEN_MASK, SVGA_REG_BLUE_MASK + + Note: SVGA_REG_BITS_PER_PIXEL is readonly if + SVGA_CAP_8BIT_EMULATION is not set in the capabilities register. Even + if it is set, values other than 8 and SVGA_REG_HOST_BITS_PER_PIXEL + will be ignored. + + Enable SVGA + Set SVGA_REG_ENABLE to 1 + (to disable SVGA, set SVGA_REG_ENABLE to 0. Setting SVGA_REG_ENABLE + to 0 also enables VGA.) + + Initialize the command FIFO + The FIFO is exclusively dword (32-bit) aligned. The first four + dwords define the portion of the MEM area that is used for the + command FIFO. These are values are all in byte offsets from the + start of the MEM area. + + A minimum sized FIFO would have these values: + mem[SVGA_FIFO_MIN] = 16; + mem[SVGA_FIFO_MAX] = 16 + (10 * 1024); + mem[SVGA_FIFO_NEXT_CMD] = 16; + mem[SVGA_FIFO_STOP] = 16; + + Set SVGA_REG_CONFIG_DONE to 1 after these values have been set. + + Note: Setting SVGA_REG_CONFIG_DONE to 0 will stop the device from + reading the FIFO until it is reinitialized and SVGA_REG_CONFIG_DONE is + set to 1 again. + +3. SVGA command FIFO protocol + The FIFO is empty when SVGA_FIFO_NEXT_CMD == SVGA_FIFO_STOP. The + driver writes commands to the FIFO starting at the offset specified + by SVGA_FIFO_NEXT_CMD, and then increments SVGA_FIFO_NEXT_CMD. + + The FIFO is full when SVGA_FIFO_NEXT_CMD is one word before SVGA_FIFO_STOP. + + When the FIFO becomes full, the FIFO should be sync'd + + To sync the FIFO + Write SVGA_REG_SYNC + Read SVGA_REG_BUSY + Wait for the value in SVGA_REG_BUSY to be 0 + + The FIFO should be sync'd before the driver touches the frame buffer, to + guarantee that any outstanding BLT's are completed. + +4. Cursor + When SVGA_CAP_CURSOR is set, hardware cursor support is available. In + practice, SVGA_CAP_CURSOR will only be set when SVGA_CAP_CURSOR_BYPASS is + also set and drivers supporting a hardware cursor should only worry about + SVGA_CAP_CURSOR_BYPASS and only use the FIFO to define the cursor. See + below for more information. + +5. Pseudocolor + When the read-only register SVGA_REG_PSEUDOCOLOR is 1, the device is in a + colormapped mode whose index width and color width are both SVGA_REG_DEPTH. + Thus far, 8 is the only depth at which pseudocolor is ever used. + + In pseudocolor, the colormap is programmed by writing to the SVGA palette + registers. These start at SVGA_PALETTE_BASE and are interpreted as + follows: + + SVGA_PALETTE_BASE + 3*n - The nth red component + SVGA_PALETTE_BASE + 3*n + 1 - The nth green component + SVGA_PALETTE_BASE + 3*n + 2 - The nth blue component + + And n ranges from 0 to ((1<. What should this be +set to? Likewise with SVGA_CMD_DEFINE_PIXMAP. And when should the +SCANLINE macros be used? + +OK, I'll use pixmaps as an example. First you have to define the pixmap: + +#define SVGA_CMD_DEFINE_PIXMAP 6 + /* FIFO layout: + Pixmap ID, Width, Height, Depth, */ + +The ID is something you choose, which you subsequently use to refer to +this pixmap. It must be an integer between 0 and SVGA_MAX_ID. + +The width and height and depth are the dimensions of the pixmap. For now, +the depth of the pixmap has to match the depth of the screen. + +The scanlines are the pixels that make up the pixmap, arranged one row +at a time. Each row is required to be 32-bit aligned. The macros +SVGA_PIXMAP_SCANLINE_SIZE and SVGA_PIXMAP_SIZE give the size of a +single scanline, and the size of the entire pixmap, respectively, in +32-bit words. + +The second step is to use it: + +#define SVGA_CMD_RECT_PIXMAP_FILL 9 + /* FIFO layout: + Pixmap ID, X, Y, Width, Height */ + +The ID here is the one you chose when defining the pixmap. X, Y, +Width, and Height define a rectangle on the screen that is to be filled +with the pixmap. The pixmap is screen aligned, which means that the +coordinates in the pixmap are defined by the screen coordinates modulo +the pixmap dimensions. + +If you want a different alignment between the screen and the pixmap, +then you can use this command, which allows the pixmap coordinates to +be defined: + +#define SVGA_CMD_RECT_PIXMAP_COPY 11 + /* FIFO layout: + Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, + Height */ + +The Source X and Source Y are pixmap coordinates, and the Dest X and +Dest Y are screen coordinates. + + +5. OK, now it works briefly, then stops displaying anything. Also, +my log file is filled with lines like: + Unknown Command 0xff in SVGA command FIFO +What's happening? + +The most common problem at this point is that the FIFO gets out +of sync. This can happen if the amount of data in the FIFO doesn't +match what the VMware SVGA device expects. To track this down, try +to isolate the particular command which causes the problem. + +Another way this can happen is if the wraparound in the FIFO isn't +done correctly. Here is some example code for writing to the FIFO +(mem is an array of 32-bit integers that points to the FIFO memory +region): + +while (TRUE) { + fifo_min = mem[SVGA_FIFO_MIN] / 4; + fifo_max = mem[SVGA_FIFO_MAX] / 4; + fifo_next = mem[SVGA_FIFO_NEXT_CMD] / 4; + fifo_stop = mem[SVGA_FIFO_STOP] / 4; + + tmp_next = fifo_next+1; + if (tmp_next == fifo_max) + tmp_next = fifo_min; // Wraparound + + if (tmp_next == fifo_stop) { + sync_fifo(); // FIFO full + continue; // retry + } + + mem[fifo_next] = item; + mem[SVGA_FIFO_NEXT_CMD] = tmp_next * 4; + break; +} + +This isn't the most efficient code, but it should work. It's important +to do the increment with wraparound before the FIFO full check, and to +check FIFO full before updating the next command pointer. + + +6. My driver tries to switch modes and either nothing happens or the +display becomes completely garbled. What's going on? + +When you change modes, make very sure you reread all of the registers listed +above under SetMode. Getting the pitch (SVGA_REG_BYTES_PER_LINE) incorrect +will cause a heavily garbled display. Also, if you change +SVGA_REG_BITS_PER_PIXEL, make certain that SVGA_CAP_8BIT_EMULATION is present +in the SVGA_REG_CAPABILITIES register. Also, even with 8 bit emulation, the +driver must still use either 8 bpp or SVGA_REG_HOST_BITS_PER_PIXEL bpp, +nothing else. + + +7. Why does my driver's hardware cursor work when my virtual machine is in +window mode, but draw/erase incorrectly or in garbled locations in fullscreen +mode? + +You need to make sure you use SVGA_CURSOR_ON_REMOVE_FROM_FB and +SVGA_CURSOR_ON_RESTORE_TO_FB _every_ time your driver or the virtual machine +touches a region of the framebuffer that overlaps the cursor. If you forget +to remove it then it can show up when doing save-under operations or get mixed +in with other drawing. If you forget to restore it then can disappear. You +also need to make sure SVGA_CAP_CURSOR_BYPASS2 is available, or else you will +have to use SVGA_CURSOR_ON_SHOW and SVGA_CURSOR_ON_HIDE (which will flicker, +even in window mode), or else a software cursor. Newer version of the virtual +SVGA hardware will never put the hardware cursor in the framebuffer while in +window mode, so everything will appear to work correctly there. + + +8. Why do my accelerated glyphs look funny? OR Why does the fifo complain +about invalid commands when I draw accelerated glyphs? + +The bitmap data passed to SVGA_CMD_DRAW_GLYPH_* must not have any per-scanline +alignment. If there are any remaining bits left in the last byte of a scanline, +the first bits of the next scanline should use them. + +The bitmap data as a whole must be 4 byte aligned. + diff --git a/src/add-ons/accelerants/vmware/SetDisplayMode.c b/src/add-ons/accelerants/vmware/SetDisplayMode.c new file mode 100644 index 0000000000..1d7dc28362 --- /dev/null +++ b/src/add-ons/accelerants/vmware/SetDisplayMode.c @@ -0,0 +1,97 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#include "GlobalData.h" + + +status_t +SET_DISPLAY_MODE(display_mode * modeToSet) +{ + display_mode bounds, target; + int bpp; + + TRACE("SET_DISPLAY_MODE\n"); + + /* Ask for the specific mode */ + target = bounds = *modeToSet; + if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) == B_ERROR) + return B_ERROR; + + bpp = BppForSpace(target.space); + + TRACE("setting %dx%dx%d\n", target.virtual_width, + target.virtual_height, bpp); + + gSi->dm = target; + + /* Disable SVGA while we switch */ + ioctl(gFd, VMWARE_FIFO_STOP, NULL, 0); + + /* Re-init fifo */ + FifoInit(); + + /* Set resolution. This also updates the frame buffer config in the + * shared area */ + ioctl(gFd, VMWARE_SET_MODE, &target, sizeof(target)); + + /* Blank the screen to avoid ugly glitches until the app_server redraws */ + memset(gSi->fb, 0, target.virtual_height * gSi->bytesPerRow); + FifoUpdateFullscreen(); + + /* Re-enable SVGA */ + ioctl(gFd, VMWARE_FIFO_START, NULL, 0); + + return B_OK; +} + + +status_t +MOVE_DISPLAY(uint16 hDisplayStart, uint16 vDisplayStart) +{ + TRACE("MOVE_DISPLAY (%d, %d)\n", hDisplayStart, vDisplayStart); + return B_ERROR; +} + + +void +SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags) +{ + TRACE("SET_INDEXED_COLORS\n"); +} + + +/*--------------------------------------------------------------------*/ +/* DPMS_CAPABILITIES: reports DPMS capabilities (on, stand by, + * suspend, off) */ +uint32 +DPMS_CAPABILITIES() +{ + /* We stay always on */ + return B_DPMS_ON; +} + + +/*--------------------------------------------------------------------*/ +/* DPMS_MODE: reports the current DPMS mode */ +uint32 +DPMS_MODE() +{ + return B_DPMS_ON; +} + + +/*--------------------------------------------------------------------*/ +/* SET_DPMS_MODE: puts the display into one of the DPMS modes */ +status_t +SET_DPMS_MODE(uint32 flags) +{ + return B_ERROR; +} + diff --git a/src/add-ons/accelerants/vmware/generic.h b/src/add-ons/accelerants/vmware/generic.h new file mode 100644 index 0000000000..5cc6f0d2c2 --- /dev/null +++ b/src/add-ons/accelerants/vmware/generic.h @@ -0,0 +1,54 @@ +/* + * Copyright 1999, Be Incorporated. + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Be Incorporated + * Eric Petit + */ + +#ifndef GENERIC_H +#define GENERIC_H + +status_t INIT_ACCELERANT(int fd); +ssize_t ACCELERANT_CLONE_INFO_SIZE(void); +void GET_ACCELERANT_CLONE_INFO(void *data); +status_t CLONE_ACCELERANT(void *data); +void UNINIT_ACCELERANT(void); +status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi); +sem_id ACCELERANT_RETRACE_SEMAPHORE(void); + +uint32 ACCELERANT_MODE_COUNT(void); +status_t GET_MODE_LIST(display_mode *dm); +status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high); +status_t SET_DISPLAY_MODE(display_mode *mode_to_set); +status_t GET_DISPLAY_MODE(display_mode *current_mode); +status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer); +status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high); +status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start); +status_t GET_TIMING_CONSTRAINTS(display_timing_constraints *dtc); +void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags); + +uint32 DPMS_CAPABILITIES(void); +uint32 DPMS_MODE(void); +status_t SET_DPMS_MODE(uint32 dpms_flags); + +status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask); +void MOVE_CURSOR(uint16 x, uint16 y); +void SHOW_CURSOR(bool is_visible); + +uint32 ACCELERANT_ENGINE_COUNT(void); +status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et); +status_t RELEASE_ENGINE(engine_token *et, sync_token *st); +void WAIT_ENGINE_IDLE(void); +status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st); +status_t SYNC_TO_TOKEN(sync_token *st); + +void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count); +void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count); +void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count); + +void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count); + +#endif diff --git a/src/add-ons/kernel/drivers/graphics/Jamfile b/src/add-ons/kernel/drivers/graphics/Jamfile index e1b62d87bf..2e7aa628ff 100644 --- a/src/add-ons/kernel/drivers/graphics/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/Jamfile @@ -12,5 +12,6 @@ SubInclude HAIKU_TOP src add-ons kernel drivers graphics tdfx ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics skeleton ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics vesa ; SubInclude HAIKU_TOP src add-ons kernel drivers graphics via ; +SubInclude HAIKU_TOP src add-ons kernel drivers graphics vmware ; SubIncludeGPL HAIKU_TOP src add-ons kernel drivers graphics atimach64 ; diff --git a/src/add-ons/kernel/drivers/graphics/vmware/Jamfile b/src/add-ons/kernel/drivers/graphics/vmware/Jamfile new file mode 100644 index 0000000000..7195433517 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vmware/Jamfile @@ -0,0 +1,12 @@ +SubDir HAIKU_TOP src add-ons kernel drivers graphics vmware ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders [ FDirName graphics vmware ] ; +UsePrivateHeaders [ FDirName graphics common ] ; +UsePrivateHeaders graphics ; + +KernelAddon vmware : + driver.c + device.c +; diff --git a/src/add-ons/kernel/drivers/graphics/vmware/device.c b/src/add-ons/kernel/drivers/graphics/vmware/device.c new file mode 100644 index 0000000000..9eb9375ba9 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vmware/device.c @@ -0,0 +1,341 @@ +/* + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Eric Petit + */ + + +#include "driver.h" + +#include +#include +#include +#include + +#include +#include +#include + + +#define get_pci(o, s) (*gPciBus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s)) +#define set_pci(o, s, v) (*gPciBus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v)) + + +static void +PrintCapabilities(uint32 c) +{ + TRACE("capabilities:\n"); + if (c & SVGA_CAP_RECT_FILL) TRACE("RECT_FILL\n"); + if (c & SVGA_CAP_RECT_COPY) TRACE("RECT_COPY\n"); + if (c & SVGA_CAP_RECT_PAT_FILL) TRACE("RECT_PAT_FILL\n"); + if (c & SVGA_CAP_LEGACY_OFFSCREEN) TRACE("LEGACY_OFFSCREEN\n"); + if (c & SVGA_CAP_RASTER_OP) TRACE("RASTER_OP\n"); + if (c & SVGA_CAP_CURSOR) TRACE("CURSOR\n"); + if (c & SVGA_CAP_CURSOR_BYPASS) TRACE("CURSOR_BYPASS\n"); + if (c & SVGA_CAP_CURSOR_BYPASS_2) TRACE("CURSOR_BYPASS_2\n"); + if (c & SVGA_CAP_8BIT_EMULATION) TRACE("8BIT_EMULATION\n"); + if (c & SVGA_CAP_ALPHA_CURSOR) TRACE("ALPHA_CURSOR\n"); + if (c & SVGA_CAP_GLYPH) TRACE("GLYPH\n"); + if (c & SVGA_CAP_GLYPH_CLIPPING) TRACE("GLYPH_CLIPPING\n"); + if (c & SVGA_CAP_OFFSCREEN_1) TRACE("OFFSCREEN_1\n"); + if (c & SVGA_CAP_ALPHA_BLEND) TRACE("ALPHA_BLEND\n"); + if (c & SVGA_CAP_3D) TRACE("3D\n"); + if (c & SVGA_CAP_EXTENDED_FIFO) TRACE("EXTENDED_FIFO\n"); +} + + +static status_t +CheckCapabilities() +{ + SharedInfo *si = gPd->si; + uint32 id; + + /* Needed to read/write registers */ + si->indexPort = gPd->pcii.u.h0.base_registers[0] + SVGA_INDEX_PORT; + si->valuePort = gPd->pcii.u.h0.base_registers[0] + SVGA_VALUE_PORT; + TRACE("index port: %d, value port: %d\n", + si->indexPort, si->valuePort); + + /* This should be SVGA II according to the PCI device_id, + * but just in case... */ + WriteReg(SVGA_REG_ID, SVGA_ID_2); + if ((id = ReadReg(SVGA_REG_ID)) != SVGA_ID_2) { + TRACE("SVGA_REG_ID is %ld, not %d\n", id, SVGA_REG_ID); + return B_ERROR; + } + TRACE("SVGA_REG_ID OK\n"); + + /* Grab some info */ + si->maxWidth = ReadReg(SVGA_REG_MAX_WIDTH); + si->maxHeight = ReadReg(SVGA_REG_MAX_HEIGHT); + TRACE("max resolution: %ldx%ld\n", si->maxWidth, si->maxHeight); + si->fbDma = (void *)ReadReg(SVGA_REG_FB_START); + si->fbSize = ReadReg(SVGA_REG_VRAM_SIZE); + TRACE("frame buffer: %p, size %ld\n", si->fbDma, si->fbSize); + si->fifoDma = (void *)ReadReg(SVGA_REG_MEM_START); + si->fifoSize = ReadReg(SVGA_REG_MEM_SIZE) & ~3; + TRACE("fifo: %p, size %ld\n", si->fifoDma, si->fifoSize); + si->capabilities = ReadReg(SVGA_REG_CAPABILITIES); + PrintCapabilities(si->capabilities); + si->fifoMin = (si->capabilities & SVGA_CAP_EXTENDED_FIFO) ? + ReadReg(SVGA_REG_MEM_REGS) : 4; + + return B_OK; +} + + +static status_t +MapDevice() +{ + SharedInfo *si = gPd->si; + int writeCombined = 1; + + /* Map the frame buffer */ + si->fbArea = map_physical_memory("VMware frame buffer", + si->fbDma, si->fbSize, B_ANY_KERNEL_BLOCK_ADDRESS|B_MTR_WC, + B_READ_AREA|B_WRITE_AREA, (void **)&si->fb); + if (si->fbArea < 0) { + /* Try again without write combining */ + writeCombined = 0; + si->fbArea = map_physical_memory("VMware frame buffer", + si->fbDma, si->fbSize, B_ANY_KERNEL_BLOCK_ADDRESS, + B_READ_AREA|B_WRITE_AREA, (void **)&si->fb); + } + if (si->fbArea < 0) { + TRACE("failed to map frame buffer\n"); + return si->fbArea; + } + TRACE("frame buffer mapped: %p->%p, area %ld, size %ld, write " + "combined: %d\n", si->fbDma, si->fb, si->fbArea, + si->fbSize, writeCombined); + + /* Map the fifo */ + si->fifoArea = map_physical_memory("VMware fifo", + si->fifoDma, si->fifoSize, B_ANY_KERNEL_BLOCK_ADDRESS, + B_READ_AREA|B_WRITE_AREA, (void **)&si->fifo); + if (si->fifoArea < 0) { + TRACE("failed to map fifo\n"); + delete_area(si->fbArea); + return si->fifoArea; + } + TRACE("fifo mapped: %p->%p, area %ld, size %ld\n", si->fifoDma, + si->fifo, si->fifoArea, si->fifoSize); + + return B_OK; +} + + +static void +UnmapDevice() +{ + SharedInfo *si = gPd->si; + pci_info *pcii = &gPd->pcii; + uint32 tmpUlong; + + /* Disable memory mapped IO */ + tmpUlong = get_pci(PCI_command, 2); + tmpUlong &= ~PCI_command_memory; + set_pci(PCI_command, 2, tmpUlong); + + /* Delete the areas */ + if (si->fifoArea >= 0) + delete_area(si->fifoArea); + if (si->fbArea >= 0) + delete_area(si->fbArea); + si->fifoArea = si->fbArea = -1; + si->fb = si->fifo = NULL; +} + + +static status_t +CreateShared() +{ + gPd->sharedArea = create_area("VMware shared", (void **)&gPd->si, + B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(SharedInfo)), + B_FULL_LOCK, 0); + if (gPd->sharedArea < B_OK) { + TRACE("failed to create shared area\n"); + return gPd->sharedArea; + } + TRACE("shared area created\n"); + + memset(gPd->si, 0, sizeof(SharedInfo)); + return B_OK; +} + + +static void +FreeShared() +{ + delete_area(gPd->sharedArea); + gPd->sharedArea = -1; + gPd->si = NULL; +} + + +static status_t +OpenHook(const char *name, uint32 flags, void **cookie) +{ + status_t ret = B_OK; + pci_info *pcii = &gPd->pcii; + uint32 tmpUlong; + + TRACE("OpenHook (%s, %ld)\n", name, flags); + ACQUIRE_BEN(gPd->kernel); + + if (gPd->isOpen) + goto markAsOpen; + + /* Enable memory mapped IO and VGA I/O */ + tmpUlong = get_pci(PCI_command, 2); + tmpUlong |= PCI_command_memory; + tmpUlong |= PCI_command_io; + set_pci(PCI_command, 2, tmpUlong); + + if ((ret = CreateShared()) != B_OK) + goto done; + if ((ret = CheckCapabilities()) != B_OK) + goto freeShared; + if ((ret = MapDevice()) != B_OK) + goto freeShared; + +markAsOpen: + gPd->isOpen++; + *cookie = gPd; + goto done; + +freeShared: + FreeShared(); + +done: + RELEASE_BEN(gPd->kernel); + TRACE("OpenHook: %ld\n", ret); + return ret; +} + + +/*--------------------------------------------------------------------*/ +/* ReadHook, WriteHook, CloseHook: do nothing */ + +static status_t +ReadHook(void *dev, off_t pos, void *buf, size_t *len) +{ + *len = 0; + return B_NOT_ALLOWED; +} +static status_t +WriteHook(void *dev, off_t pos, const void *buf, size_t *len) +{ + *len = 0; + return B_NOT_ALLOWED; +} +static status_t +CloseHook(void *dev) +{ + return B_OK; +} + + +/*--------------------------------------------------------------------*/ +/* FreeHook: closes down the device */ + +static status_t +FreeHook(void *dev) +{ + TRACE("FreeHook\n"); + ACQUIRE_BEN(gPd->kernel); + + if (gPd->isOpen < 2) { + UnmapDevice(); + FreeShared(); + } + gPd->isOpen--; + + RELEASE_BEN(gPd->kernel); + TRACE("FreeHook ends\n"); + return B_OK; +} + + +/*--------------------------------------------------------------------*/ +/* ControlHook: responds the the ioctl from the accelerant */ + +static status_t +ControlHook(void *dev, uint32 msg, void *buf, size_t len) +{ + SharedInfo *si = gPd->si; + + switch (msg) { + case B_GET_ACCELERANT_SIGNATURE: + strcpy((char *)buf, "vmware.accelerant"); + return B_OK; + + case VMWARE_GET_PRIVATE_DATA: + *((area_id *)buf) = gPd->sharedArea; + return B_OK; + + case VMWARE_FIFO_START: + WriteReg(SVGA_REG_ENABLE, 1); + WriteReg(SVGA_REG_CONFIG_DONE, 1); + return B_OK; + + case VMWARE_FIFO_STOP: + WriteReg(SVGA_REG_CONFIG_DONE, 0); + WriteReg(SVGA_REG_ENABLE, 0); + return B_OK; + + case VMWARE_FIFO_SYNC: + WriteReg(SVGA_REG_SYNC, 1); + while (ReadReg(SVGA_REG_BUSY)); + return B_OK; + + case VMWARE_SET_MODE: + { + display_mode *dm = buf; + WriteReg(SVGA_REG_WIDTH, dm->virtual_width); + WriteReg(SVGA_REG_HEIGHT, dm->virtual_height); + WriteReg(SVGA_REG_BITS_PER_PIXEL, BppForSpace(dm->space)); + si->fbOffset = ReadReg(SVGA_REG_FB_OFFSET); + si->bytesPerRow = ReadReg(SVGA_REG_BYTES_PER_LINE); + return B_OK; + } + + case VMWARE_MOVE_CURSOR: + { + uint16 *pos = buf; + WriteReg(SVGA_REG_CURSOR_ID, CURSOR_ID); + WriteReg(SVGA_REG_CURSOR_X, pos[0]); + WriteReg(SVGA_REG_CURSOR_Y, pos[1]); + return B_OK; + } + + case VMWARE_SHOW_CURSOR: + { + bool show = *((bool *)buf); + WriteReg(SVGA_REG_CURSOR_ON, show ? SVGA_CURSOR_ON_HIDE : + SVGA_CURSOR_ON_SHOW); + return B_OK; + } + } + + TRACE("ioctl: %ld, %p, %ld\n", msg, buf, len); + return B_DEV_INVALID_IOCTL; +} + + +device_hooks gGraphicsDeviceHooks = +{ + OpenHook, + CloseHook, + FreeHook, + ControlHook, + ReadHook, + WriteHook, + NULL, + NULL, + NULL, + NULL +}; + diff --git a/src/add-ons/kernel/drivers/graphics/vmware/driver.c b/src/add-ons/kernel/drivers/graphics/vmware/driver.c new file mode 100644 index 0000000000..b8e9379d27 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vmware/driver.c @@ -0,0 +1,122 @@ +/* + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Eric Petit + */ + + +#include "driver.h" + +#include +#include +#include + +#include +#include + + +DeviceData *gPd; +pci_module_info *gPciBus; + + +int32 api_version = B_CUR_DRIVER_API_VERSION; + + +status_t +init_hardware(void) +{ + status_t ret = B_ERROR; + pci_info pcii; + int i; + + TRACE("init_hardware\n"); + + if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPciBus) != B_OK) + return B_ERROR; + + for (i = 0; (*gPciBus->get_nth_pci_info)(i, &pcii) == B_OK; i++) { + if (pcii.vendor_id == PCI_VENDOR_ID_VMWARE && + pcii.device_id == PCI_DEVICE_ID_VMWARE_SVGA2) { + ret = B_OK; + break; + } + } + + put_module(B_PCI_MODULE_NAME); + + TRACE("init_hardware: %ld\n", ret); + return ret; +} + + +status_t +init_driver(void) +{ + status_t ret = B_OK; + int i; + + TRACE("init_driver\n"); + + if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPciBus) != B_OK) { + ret = B_ERROR; + goto done; + } + + if (!(gPd = calloc(1, sizeof(DeviceData)))) { + put_module(B_PCI_MODULE_NAME); + ret = B_ERROR; + goto done; + } + + /* Remember the PCI information */ + for (i = 0; (*gPciBus->get_nth_pci_info)(i, &gPd->pcii) == B_OK; i++) + if (gPd->pcii.vendor_id == PCI_VENDOR_ID_VMWARE && + gPd->pcii.device_id == PCI_DEVICE_ID_VMWARE_SVGA2) + break; + + /* Create a benaphore for exclusive access in OpenHook/FreeHook */ + INIT_BEN(gPd->kernel); + + /* The device name */ + gPd->names[0] = strdup("graphics/vmware"); + gPd->names[1] = NULL; + + /* Usual initializations */ + gPd->isOpen = 0; + gPd->sharedArea = -1; + gPd->si = NULL; + +done: + TRACE("init_driver: %ld\n", ret); + return ret; +} + + +const char ** +publish_devices(void) +{ + TRACE("publish_devices\n"); + return (const char **)gPd->names; +} + + +device_hooks * +find_device(const char *name) +{ + TRACE("find_device (%s)\n", name); + if (gPd->names[0] && !strcmp(gPd->names[0], name)) + return &gGraphicsDeviceHooks; + return NULL; +} + + +void +uninit_driver() +{ + TRACE("uninit_driver\n"); + free(gPd); + put_module(B_PCI_MODULE_NAME); +} + diff --git a/src/add-ons/kernel/drivers/graphics/vmware/driver.h b/src/add-ons/kernel/drivers/graphics/vmware/driver.h new file mode 100644 index 0000000000..5639e8a8e9 --- /dev/null +++ b/src/add-ons/kernel/drivers/graphics/vmware/driver.h @@ -0,0 +1,65 @@ +/* + * Copyright 2007, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Eric Petit + */ +#ifndef DRIVER_H +#define DRIVER_H + + +#define TRACE(a...) dprintf("VMware: " ##a) + +#include "DriverInterface.h" + +typedef struct { + char *names[2]; + Benaphore kernel; + uint32 isOpen; + area_id sharedArea; + SharedInfo *si; + pci_info pcii; +} DeviceData; + + +/*--------------------------------------------------------------------*/ +/* Global variables */ + +extern DeviceData *gPd; +extern pci_module_info *gPciBus; +extern device_hooks gGraphicsDeviceHooks; + + +/*--------------------------------------------------------------------*/ +/* Access to 32 bit registers in the IO address space. */ + +static inline uint32 +inl(uint16 port) +{ + uint32 ret; + __asm__ __volatile__("inl %w1, %0" : "=a" (ret) : "Nd" (port)); + return ret; +} + +static inline void +outl(uint16 port, uint32 value) +{ + __asm__ __volatile__("outl %1, %w0" :: "Nd" (port), "a" (value)); +} + +static inline uint32 +ReadReg(uint32 index) +{ + outl(gPd->si->indexPort, index); + return inl(gPd->si->valuePort); +} + +static inline void +WriteReg(uint32 index, uint32 value) +{ + outl(gPd->si->indexPort, index); + outl(gPd->si->valuePort, value); +} + +#endif // DRIVER_H