]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
2008.11.18-130226 2008.11.18-130226
authorMarcelo Vanzin <mvanzin@mvanzin-dev1.eng.vmware.com>
Wed, 19 Nov 2008 01:36:49 +0000 (17:36 -0800)
committerMarcelo Vanzin <mvanzin@mvanzin-dev1.eng.vmware.com>
Wed, 19 Nov 2008 01:36:49 +0000 (17:36 -0800)
32 files changed:
open-vm-tools/lib/hgfs/hgfsEscape.c [new file with mode: 0644]
open-vm-tools/lib/include/hgfsEscape.h [new file with mode: 0644]
open-vm-tools/modules/freebsd/vmhgfs/hgfsEscape.c [new file with mode: 0644]
open-vm-tools/modules/freebsd/vmhgfs/hgfsEscape.h [new file with mode: 0644]
open-vm-tools/modules/linux/dkms.conf [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/COPYING [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/Makefile [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/Makefile.kernel [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/autoconf/cachecreate.c [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/autoconf/cachector.c [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/autoconf/geninclude.c [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/compat_interrupt.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/compat_ioport.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/compat_module.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/compat_pci.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/compat_scsi.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/compat_version.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/driver-config.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/includeCheck.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/pvscsi.c [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/pvscsi_defs.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/pvscsi_version.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/scsi_defs.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vm_assert.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vm_basic_defs.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vm_basic_types.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vm_device_version.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vmware_pack_begin.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vmware_pack_end.h [new file with mode: 0644]
open-vm-tools/modules/linux/pvscsi/vmware_pack_init.h [new file with mode: 0644]
open-vm-tools/modules/linux/vmhgfs/hgfsEscape.c [new file with mode: 0644]
open-vm-tools/modules/linux/vsock/include/vmciHostKernelAPI.h [new file with mode: 0644]

diff --git a/open-vm-tools/lib/hgfs/hgfsEscape.c b/open-vm-tools/lib/hgfs/hgfsEscape.c
new file mode 100644 (file)
index 0000000..7394052
--- /dev/null
@@ -0,0 +1,942 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * hgfsEscape.c --
+ *
+ *    Escape and unescape illegal filenames for different platforms.
+ *
+ */
+
+#ifdef __KERNEL__
+#  include "driver-config.h"
+#  include <linux/string.h>
+#elif defined(__FreeBSD__)
+#   if defined(_KERNEL)
+#      include <sys/libkern.h>
+#      define strchr(s,c)       index(s,c)
+#   else
+#      include <string.h>
+#   endif
+#   define memmove(s1,s2,n) bcopy(s2,s1,n) 
+#elif defined(__APPLE__) && defined(KERNEL)
+#  include <string.h>
+#elif !defined(sun)
+#  include <stdlib.h>
+#  include <string.h>
+#else
+#  include <string.h>
+#endif
+
+#include "vmware.h"
+#include "hgfsEscape.h"
+#include "cpName.h"
+
+#ifdef _WIN32
+
+#define UNREFERENCED_PARAMETER(P) (P)
+
+/* These characters are illegal in Windows file names. */
+const char* HGFS_ILLEGAL_CHARS = "/\\*?:\"<>|";
+const char* HGFS_SUBSTITUTE_CHARS = "!@#$^&(){}";
+/* Last character of a file name in Windows can be neither dot nor space. */
+const char* HGFS_ILLEGAL_LAST_CHARS = ". ";
+
+/* http://msdn.microsoft.com/en-us/library/aa365247.aspx */
+char *HgfsReservedNames[] = {"CON", "PRN", "AUX", "NUL"};
+char *HgfsReservedNamesWithNumber[] = {"COM", "LPT"};
+
+#define HGFS_RESERVED_NAME_CHARS_LENGTH 3
+#define HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH (HGFS_RESERVED_NAME_CHARS_LENGTH + 1)
+/* Check for special escaping cases - reserved names and illegal last characters. */
+#define IS_SPECIAL_CASE_ESCAPE(b,o,l) HgfsIsSpecialCaseEscape(b,o,l)
+/* Process Windows reserved names. */
+#define PROCESS_RESERVED_NAME(b,s,p,o,c) \
+if (!HgfsProcessReservedName(b,s,p,o,c)) \
+{ \
+ return FALSE; \
+}
+/* Process Windows reserved names. */
+#define PROCESS_LAST_CHARACTER(b,s,p,c) \
+if (!HgfsProcessLastCharacter(b,s,p,c)) \
+{ \
+ return FALSE; \
+}
+
+#else // _WIN32
+
+#define UNREFERENCED_PARAMETER(P)
+/* There is no special escape sequences on other than Windows platforms. */
+#define IS_SPECIAL_CASE_ESCAPE(b,o,l) FALSE
+/* There is no reserved names on other then Windows platforms. */
+#define PROCESS_RESERVED_NAME(b,s,p,o,c)
+/* There is no special processing for the last character on non-Windows platforms. */
+#define PROCESS_LAST_CHARACTER(b,s,p,c)
+
+#if defined(__APPLE__)
+/* These characters are illegal in MAC OS file names. */
+const char* HGFS_ILLEGAL_CHARS = "/:";
+const char* HGFS_SUBSTITUTE_CHARS = "!&";
+#else   // __APPLE__
+/* These characters are illegal in Linux file names. */
+const char* HGFS_ILLEGAL_CHARS = "/";
+const char* HGFS_SUBSTITUTE_CHARS = "!";
+#endif  // __APPLE__
+
+#endif  // _WIN32
+
+#define HGFS_ESCAPE_CHAR '%'
+#define HGFS_ESCAPE_SUBSTITUE_CHAR ']'
+
+typedef enum {
+   HGFS_ESCAPE_ILLEGAL_CHARACTER,
+   HGFS_ESCAPE_RESERVED_NAME,
+   HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER,
+   HGFS_ESCAPE_ESCAPE_SEQUENCE,
+   HGFS_ESCAPE_COMPLETE
+} HgfsEscapeReason;
+
+
+typedef Bool (*HgfsEnumCallback)(char const *bufIn,
+                                 uint32 offset,
+                                 HgfsEscapeReason reason,
+                                 void* context);
+
+/*
+ * The structure is used by HgfsAddEscapeCharacter to keep context information between
+ * invocations
+ * All offsets defined in this structure are in characters, not bytes
+ */
+typedef  struct {
+   uint32   processedOffset;     // Offset of the first unprocessed input character
+   uint32   outputBufferLength;  // Number of characters in the output buffer
+   uint32   outputOffset;        // Number of characters that are already in the output
+   char    *outputBuffer;        // Pointer to the output buffer
+} HgfsEscapeContext;
+
+static void HgfsEscapeUndoComponent(char *bufIn, uint32 *totalLength);
+static int HgfsEscapeGetComponentSize(char const *bufIn, uint32 sizeIn);
+static int HgfsEscapeDoComponent(char const *bufIn, uint32 sizeIn, uint32 sizeBufOut,
+                                 char *bufOut);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsAddEscapeCharacter --
+ *
+ *    Callback function that is called by HgfsEnumerate to insert an escape sequence
+ *    into the input name.
+ *
+ * Results:
+ *    TRUE if successful, FALSE if there is an error like the output buffer is
+ *    too small.
+ *
+ * Side effects:
+ *    Updates the output buffer pointer (stored in the context variable).
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsAddEscapeCharacter(char const * bufIn,      // IN: input name
+                       uint32 offset,           // IN: offset that requires escaping
+                       HgfsEscapeReason reason, // IN: reason for esaping
+                       void *context)           // IN/OUT: convertion context
+{
+   HgfsEscapeContext *escapeContext = (HgfsEscapeContext *)context;
+   uint32 charactersToCopy;
+   uint32 outputSpace;
+   char* illegal;
+   Bool result = TRUE;
+
+   ASSERT(offset >= escapeContext->processedOffset); // Scanning forward
+   charactersToCopy = offset - escapeContext->processedOffset;
+
+   if (escapeContext->outputOffset + charactersToCopy >
+       escapeContext->outputBufferLength) {
+      return FALSE;
+   }
+
+   memcpy(escapeContext->outputBuffer + escapeContext->outputOffset,
+          bufIn + escapeContext->processedOffset, charactersToCopy * sizeof *bufIn);
+   escapeContext->outputOffset += charactersToCopy;
+   escapeContext->processedOffset += charactersToCopy;
+
+   outputSpace = escapeContext->outputBufferLength - escapeContext->outputOffset;
+
+   switch(reason) {
+   case HGFS_ESCAPE_ILLEGAL_CHARACTER:
+      if (outputSpace < 2) {
+         return FALSE;
+      }
+      illegal = strchr(HGFS_ILLEGAL_CHARS, bufIn[escapeContext->processedOffset]);
+      escapeContext->processedOffset++;  // Skip illegal input character
+      ASSERT(illegal != NULL);
+      escapeContext->outputBuffer[escapeContext->outputOffset] =
+         HGFS_SUBSTITUTE_CHARS[illegal - HGFS_ILLEGAL_CHARS];
+      escapeContext->outputOffset++;
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_RESERVED_NAME:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_ESCAPE_SEQUENCE:
+      if (outputSpace < 2) {
+         return FALSE;
+      }
+      escapeContext->processedOffset++; // Skip input esape character
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_SUBSTITUE_CHAR;
+      escapeContext->outputOffset++;
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_COMPLETE:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = '\0';
+      break;
+
+   default:
+      result = FALSE;
+      ASSERT(FALSE);
+   }
+   return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsCountEscapeChars --
+ *
+ *    Callback function that is called by HgfsEnumerate to count additional characters
+ *    that need to be inserted in the input name.
+ *
+ * Results:
+ *    TRUE since it never fails.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsCountEscapeChars(char const *bufIn,       // IN: input name
+                     uint32 offset,           // IN: offset where escape is needed
+                     HgfsEscapeReason reason, // IN: reason for escaping
+                     void *context)           // IN/OUT: context info
+{
+   UNREFERENCED_PARAMETER(bufIn);
+   UNREFERENCED_PARAMETER(offset);
+   if (reason != HGFS_ESCAPE_COMPLETE) {
+      uint32 *counter = (uint32*)context;
+      (*counter)++;
+   }
+   return TRUE;
+}
+
+
+#ifdef _WIN32
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsLetterToUpper --
+ *
+ *    Converts lowercase English letters to uppercase.
+ *    If the symbol is not a lowercase English letter returns the original character.
+ *
+ * Results:
+ *    Converted character.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static char
+HgfsLetterToUpper(char letter)
+{
+   if (letter >= 'a' && letter <= 'z') {
+      return letter - ('a' - 'A');
+   }
+   return letter;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsEqualPrefix --
+ *
+ *    Verifies if the string prefix is equal to the given prefix.
+ *    It assumes that the prefix includes only uppercase English letters or numbers
+ *    and it does not have any international characters.
+ *    The string must be either NULL terminated or not shorter then the prefix.
+ *
+ * Results:
+ *    TRUE if the uppcased string starts with the given prefix. False otherwise.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsEqualPrefix(char const *prefix,  // IN: prefix to check
+                  char const *string,  // IN: input string
+                  uint32 prefixLength) // IN: length of the prefix in characters
+{
+   int i;
+   for (i = 0; i < prefixLength; i++) {
+      ASSERT(prefix[i] > 0 && (prefix[i] < 'a' || prefix[i] > 'z' ));
+      if (prefix[i] != HgfsLetterToUpper(string[i])) {
+         return FALSE;
+      }
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsReservedPrefix --
+ *
+ *    Verifies if the name's prefix is one of the reserved names.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsReservedPrefix(char const *bufIn)  // IN: input name
+{
+   uint32 i;
+   for (i = 0; i < ARRAYSIZE(HgfsReservedNames); i++) {
+      if (HgfsIsEqualPrefix(HgfsReservedNames[i], bufIn,
+                            HGFS_RESERVED_NAME_CHARS_LENGTH)) {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsReservedPrefixWithNumber --
+ *
+ *    Verifies if the name's prefix is one of the reserved names with number:
+ *    COM1-9 or LPT1-9.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names with number.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsReservedPrefixWithNumber(char const *bufIn)   // IN: input name
+{
+   uint32 i;
+   for (i = 0; i < ARRAYSIZE(HgfsReservedNamesWithNumber); i++) {
+      if (HgfsIsEqualPrefix(HgfsReservedNamesWithNumber[i], bufIn,
+                            HGFS_RESERVED_NAME_CHARS_LENGTH) &&
+          bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] >= '1' &&
+          bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] <= '9') {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsSpecialCaseEscape --
+ *
+ *    Verifies if the escape character is a part of special case escape sequence
+ *    that exists only in Windows - escaped reserved name or escaped illegal last
+ *    character.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names with number.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsSpecialCaseEscape(char const *bufIn,   // IN: input name
+                        uint32 offset,       // IN: offset of the escape character
+                        uint32 length)       // IN: length of the name in characters
+{
+   if (offset + 1 == length &&
+      strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[offset - 1]) != NULL) {
+      return TRUE;
+   }
+   if (offset == HGFS_RESERVED_NAME_CHARS_LENGTH &&
+      (length == HGFS_RESERVED_NAME_CHARS_LENGTH + 1 || bufIn[offset+1] == '.')) {
+      return HgfsIsReservedPrefix(bufIn);
+   }
+   if (offset == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
+      (length == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH + 1 ||
+      bufIn[offset+1] == '.')) {
+      return HgfsIsReservedPrefixWithNumber(bufIn);
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsProcessReservedName --
+ *
+ *    Verifies if the name is one of reserved Windows file names.
+ *    If it is a reserved name invokes callback that performs required
+ *    processing.
+ *
+ * Results:
+ *    TRUE if no processing is required of if processing succeeded,
+ *    FALSE if processing failed.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsProcessReservedName(char const *bufIn,              // IN:  Unescaped input buffer
+                        uint32 sizeIn,                  // IN:  Length of the input
+                        HgfsEnumCallback processEscape, // IN:  Callack that is invoked
+                                                        //      if input is reserved name
+                        uint32 *offset,                 // OUT: New offset in the input
+                        void *context)                  // IN/OUT: Context for callback
+{
+   /*  Look reserved names: CON, PRN, AUX, NUL. */
+   if (sizeIn >= HGFS_RESERVED_NAME_CHARS_LENGTH && HgfsIsReservedPrefix(bufIn)) {
+      if (HGFS_RESERVED_NAME_CHARS_LENGTH == sizeIn ||
+         bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] == '.') {
+         if (!processEscape(bufIn, HGFS_RESERVED_NAME_CHARS_LENGTH,
+                            HGFS_ESCAPE_RESERVED_NAME, context)) {
+            return FALSE;
+         }
+         *offset = HGFS_RESERVED_NAME_CHARS_LENGTH;
+      }
+   }
+
+   /*  Look reserved names with numbers: COM1-9 and LPT1-9. */
+   if (sizeIn >= HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
+       HgfsIsReservedPrefixWithNumber(bufIn)) {
+      if (HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH == sizeIn ||
+         bufIn[HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH] == '.') {
+         if (!processEscape(bufIn, HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH,
+                            HGFS_ESCAPE_RESERVED_NAME, context)) {
+            return FALSE;
+         }
+         *offset = HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH;
+      }
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsProcessLastCharacter --
+ *
+ *    Verifies if the trailing character in the name is a valid last character.
+ *    In Windows it is illegal to have a file name that ends with dot ('.') or
+ *    space (' '). The only exception is "." and ".." directory names.
+ *    If the last character is invalid the function invokes a callback to process it.
+ *
+ * Results:
+ *    TRUE if no processing is required of if processing succeeded,
+ *    FALSE if processing failed.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsProcessLastCharacter(char const *bufIn,              // IN:  Unescaped input buffer
+                         uint32 sizeIn,                  // IN:  Length of the input
+                         HgfsEnumCallback processEscape, // IN:  Callack that is invoked
+                                                         //      when escaping is needed
+                         void *context)                  // IN/OUT: Callback context
+{
+
+   /* If the filename is '.' or '..' we shouldn't escape it. */
+   if ((sizeIn == 1 && bufIn[0] == '.') ||
+       (sizeIn == 2 && bufIn[0] == '.' && bufIn[1] == '.')) {
+      return TRUE;
+   }
+
+   /* Invoke the callback if the last character is illegal. */
+   if (strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[sizeIn - 1]) != NULL) {
+      if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER, context)) {
+         return FALSE;
+      }
+   }
+   return TRUE;
+}
+
+#endif //  WIN32
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsEscapeSequence --
+ *
+ *    Verifies if input buffer has an escape sequence at the position
+ *    defined by offset.
+ *
+ * Results:
+ *    TRUE if there is an escape sequence at the position defined by offset.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsEscapeSequence(char const *bufIn,   // IN: input name
+                     uint32 offset,       // IN: offset of the escape character
+                     uint32 length)       // IN: length of the name in characters
+{
+   if (bufIn[offset] == HGFS_ESCAPE_CHAR && offset > 0) {
+      char *substitute;
+      if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
+         return TRUE;
+      }
+      substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
+      if (substitute != NULL) {
+         return TRUE;
+      }
+      return IS_SPECIAL_CASE_ESCAPE(bufIn,offset,length);
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeEnumerate --
+ *
+ *    The function scans the input buffer and calls processEscape callback for every
+ *    place in the input buffer which require escaping.
+ *
+ *    Callback does the required processing. There are two different callbacks -
+ *    one counts extra symbols that are needed for escaping and another produces
+ *    escaped output name based on input name.
+ *
+ *    1. The first function calculates number of extra characters. It just increments
+ *    a counter which is passed to it in context variable every time it is called
+ *    for the reason different from "complete processing" assuming that
+ *    exactly one extra  character is required to escape any invalid input.
+ *
+ *    2. The second function produces output name by copying everything from input
+ *    name into the output name up to the place which require escaping and
+ *    then inserts appropriate escape sequence into the output. It keeps track of its
+ *    progress and keeps pointer to the output buffer in the context variable.
+ *    HgfsEscapeEnumerate calls calback function one more time at the end of the
+ *    input buffer to let callback finish processing of the input (for example copy
+ *    the rest of the name after the last escape sequence from input buffer to
+ *    output buffer).
+ *
+ * Results:
+ *    TRUE if the input has been processed successfully by the callback, false otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsEscapeEnumerate(char const *bufIn,              // IN:  Buffer with unescaped input
+                    uint32 sizeIn,                  // IN:  Number of input *characters*
+                    HgfsEnumCallback processEscape, // IN: Callack that is invoked every
+                                                    //     time escaping is required
+                    void *context)                  // IN/OUT: Context for processEscape
+{
+   /*  First look for invalid characters in the input name. */
+   uint32 i, offset = 0;
+   if (sizeIn == 0) {
+      return TRUE;
+   }
+
+   ASSERT(processEscape);
+
+   PROCESS_RESERVED_NAME(bufIn, sizeIn, processEscape, &offset, context);
+
+   for (i = offset; i < sizeIn; i++) {
+      if (strchr(HGFS_ILLEGAL_CHARS, bufIn[i]) != NULL) {
+         if (!processEscape(bufIn, i, HGFS_ESCAPE_ILLEGAL_CHARACTER, context)) {
+            return FALSE;
+         }
+      } else if (HgfsIsEscapeSequence(bufIn, i, sizeIn)) {
+         if (!processEscape(bufIn, i, HGFS_ESCAPE_ESCAPE_SEQUENCE, context)) {
+            return FALSE;
+         }
+      }
+   }
+
+   PROCESS_LAST_CHARACTER(bufIn, sizeIn, processEscape, context);
+
+   if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_COMPLETE, context)) {
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_Do --
+ *
+ *    Escape any characters that are not legal in a windows filename.
+ *    Escape reserved file names that can't be used in Windows.
+ *    We also of course have to escape the escape character, which is "%",
+ *    when it is part of a character sequence that would require unescaping
+ *
+ *    sizeBufOut must account for the NUL terminator.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    On failure (bufOut not big enough to hold result), negative value.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_Do(char const *bufIn, // IN:  Buffer with unescaped input
+                  uint32 sizeIn,     // IN:  Size of input buffer
+                  uint32 sizeBufOut, // IN:  Size of output buffer
+                  char *bufOut)      // OUT: Buffer for escaped output
+{
+   const char *currentComponent = bufIn;
+   uint32 sizeLeft = sizeBufOut;
+   char *outPointer = bufOut;
+   const char *end = bufIn + sizeIn;
+   const char *next;
+   ASSERT(sizeIn > 0);
+   if (bufIn[sizeIn - 1] == '\0') {
+      /*
+       * In some cases a NUL terminated string is passed to HgfsEscape_Do
+       * so it make sense to support such input even if CPName_GetComponent
+       * does not. Detect this case and make the input compliant with
+       * CPName_GetComponent by removing terminating NUL.
+       */
+      end--;
+      sizeIn--;
+   }
+   /*
+    * Absolute symbolic link name starts with the '\0'. HgfsEscapeDo needs to work
+    * with such names. Leading NULL symbols should be skipped here since
+    * CPName_GetComponent does not support such names.
+    */
+   while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
+      currentComponent++;
+      sizeLeft--;
+      *outPointer++ = '\0';
+   }
+   while (currentComponent - bufIn < sizeIn) {
+      int escapedLength;
+      uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
+
+      escapedLength = HgfsEscapeDoComponent(currentComponent, componentSize,
+                                            sizeLeft, outPointer);
+      if (escapedLength < 0) {
+         return escapedLength;
+      }
+      currentComponent = next;
+      sizeLeft -= escapedLength + 1;
+      outPointer += escapedLength + 1;
+   }
+   return (int) (outPointer - bufOut) - 1; // Do not count the last NUL terminator
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_GetSize --
+ *
+ *    Calculates required size in bytes for the buffer that is needed to hold escaped
+ *    cross platform path name. Returns 0 if no escaping is required.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    Returns 0 if the name is a valid Windows file name.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_GetSize(char const *bufIn,    // IN:  Buffer with unescaped input
+                   uint32 sizeIn)        // IN:  Size of the input buffer
+{
+   uint32 result = 0;
+   const char *currentComponent = bufIn;
+   const char *end = bufIn + sizeIn;
+   const char *next;
+
+   if (sizeIn == 0) { // No need toescape empty name.
+      return 0;
+   }
+   if (bufIn[sizeIn - 1] == '\0') {
+      /*
+       * In some cases a NUL terminated string is passed to HgfsEscape_GeSize
+       * so it make sense to support such input even if CPName_GetComponent
+       * does not. Detect this case and make the input compliant with
+       * CPName_GetComponent by removing terminating NUL.
+       */
+      end--;
+      sizeIn--;
+   }
+   /* Skip leading NULs to keep CPName_GetComponent happy. */
+   while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
+      currentComponent++;
+   }
+   while (currentComponent - bufIn < sizeIn) {
+      uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
+      result += HgfsEscapeGetComponentSize(currentComponent, componentSize);
+      currentComponent = next;
+   }
+   return (result == 0) ? 0 : result + sizeIn;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_Undo --
+ *
+ *    Unescape a buffer that was escaped using HgfsEscapeBuffer.
+ *
+ *    The unescaping is done in place in the input buffer, and
+ *    can not fail.
+ *
+ * Results:
+ *    The size (excluding the NUL terminator) of the unescaped, NUL
+ *    terminated buffer.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_Undo(char *bufIn,       // IN: Characters to be unescaped
+                uint32 sizeIn)     // IN: Number of characters in bufIn
+{
+   uint32 componentSize = strlen(bufIn) + 1;
+   uint32 unprocessedSize = sizeIn + 1;
+   uint32 result = 0;
+   char *currentComponent = bufIn;
+   while (currentComponent != NULL) {
+      HgfsEscapeUndoComponent(currentComponent, &unprocessedSize);
+      componentSize = strlen(currentComponent) + 1; // Unescaped size
+      result += componentSize;
+      if (unprocessedSize > 1) {
+         currentComponent = currentComponent + componentSize;
+         componentSize = strlen(currentComponent) + 1; // Size of the next component
+      } else {
+         currentComponent = NULL;
+      }
+   }
+   return result - 1;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeUndoComponent --
+ *
+ *    Unescape a buffer that was escaped using HgfsEscapeBuffer.
+ *
+ *    The unescaping is done in place in the input buffer, and
+ *    can not fail.
+ *
+ * Results:
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsEscapeUndoComponent(char   *bufIn,             // IN: Characters to be unescaped
+                        uint32 *unprocessedLength) // IN: Unprocessed characters
+                                                   //     in the whole name
+{
+   size_t offset;
+   size_t sizeIn = strlen(bufIn);
+   char* curOutBuffer = bufIn;
+   char* escapePointer;
+   ASSERT(bufIn);
+
+   escapePointer = strchr(curOutBuffer, HGFS_ESCAPE_CHAR);
+   while (escapePointer != NULL) {
+      offset = escapePointer - bufIn;
+      if (HgfsIsEscapeSequence(bufIn, offset, sizeIn)) {
+         char* substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
+         if (substitute != NULL) {
+            bufIn[offset - 1] = HGFS_ILLEGAL_CHARS[substitute - HGFS_SUBSTITUTE_CHARS];
+         } else if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
+            bufIn[offset - 1] = HGFS_ESCAPE_CHAR;
+         }
+         memmove(escapePointer, escapePointer + 1, (*unprocessedLength) - offset - 1);
+         (*unprocessedLength)--;
+         sizeIn--;
+         if (sizeIn > 0) {
+            escapePointer = strchr(escapePointer, HGFS_ESCAPE_CHAR);
+         } else {
+            escapePointer = NULL;
+         }
+      } else {
+         escapePointer = strchr(escapePointer + 1, HGFS_ESCAPE_CHAR);
+      }
+   }
+   ASSERT((*unprocessedLength) > sizeIn);
+   (*unprocessedLength) -= sizeIn + 1;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeDoComponent --
+ *
+ *    Escape any characters that are not legal in a windows filename.
+ *    Escape reserved file names that can't be used in Windows.
+ *    We also of course have to escape the escape character, which is "%",
+ *    when it is part of a character sequence that would require unescaping
+ *
+ *    sizeBufOut must account for the NUL terminator.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    On failure (bufOut not big enough to hold result), negative value.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscapeDoComponent(char const *bufIn, // IN:  Buffer with unescaped input
+                          uint32 sizeIn,     // IN:  Size of input buffer
+                          uint32 sizeBufOut, // IN:  Size of output buffer
+                          char *bufOut)      // OUT: Buffer for escaped output
+{
+   HgfsEscapeContext conversionContext;
+   conversionContext.processedOffset = 0;
+   conversionContext.outputBufferLength = sizeBufOut / sizeof *bufOut;
+   conversionContext.outputOffset = 0;
+   conversionContext.outputBuffer = bufOut;
+
+   if (!HgfsEscapeEnumerate(bufIn, sizeIn, HgfsAddEscapeCharacter, &conversionContext)) {
+      return -1;
+   }
+   return conversionContext.outputOffset * sizeof *bufOut;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeGetComponentSize --
+ *
+ *    Calculates number of addtitional characters that are needed to escape
+ *    name for one NUL terminated component of the path.
+ *
+ * Results:
+ *    Number of additional escape characters needed to escape the name.
+ *    Returns 0 if no escaping is required.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscapeGetComponentSize(char const *bufIn, // IN:  Buffer with unescaped input
+                           uint32 sizeIn)     // IN:  Size of the in input buffer
+{
+   int result = 0;
+   HgfsEscapeEnumerate(bufIn, sizeIn, HgfsCountEscapeChars, &result);
+   return result;
+}
diff --git a/open-vm-tools/lib/include/hgfsEscape.h b/open-vm-tools/lib/include/hgfsEscape.h
new file mode 100644 (file)
index 0000000..6805669
--- /dev/null
@@ -0,0 +1,40 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * hgfsEscape.h --
+ *
+ *    Escape and unescape filenames that are not legal on a particular
+ *    platform.
+ *
+ */
+
+#ifndef __HGFS_ESCAPE_H__
+#define __HGFS_ESCAPE_H__
+
+int HgfsEscape_GetSize(char const *bufIn, // IN
+                       uint32 sizeIn);    // IN
+int HgfsEscape_Do(char const *bufIn, // IN
+                  uint32 sizeIn,     // IN
+                  uint32 sizeBufOut, // IN
+                  char *bufOut);     // OUT
+
+int HgfsEscape_Undo(char *bufIn,    // IN
+                    uint32 sizeIn); // IN
+
+#endif // __HGFS_ESCAPE_H__
diff --git a/open-vm-tools/modules/freebsd/vmhgfs/hgfsEscape.c b/open-vm-tools/modules/freebsd/vmhgfs/hgfsEscape.c
new file mode 100644 (file)
index 0000000..fb1e061
--- /dev/null
@@ -0,0 +1,942 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * hgfsEscape.c --
+ *
+ *    Escape and unescape illegal filenames for different platforms.
+ *
+ */
+
+#ifdef __KERNEL__
+#  include "driver-config.h"
+#  include <linux/string.h>
+#elif defined(__FreeBSD__)
+#   if defined(_KERNEL)
+#      include <sys/libkern.h>
+#      define strchr(s,c)       index(s,c)
+#   else
+#      include <string.h>
+#   endif
+#   define memmove(s1,s2,n) bcopy(s2,s1,n) 
+#elif defined(__APPLE__) && defined(KERNEL)
+#  include <string.h>
+#elif !defined(sun)
+#  include <stdlib.h>
+#  include <string.h>
+#else
+#  include <string.h>
+#endif
+
+#include "vmware.h"
+#include "hgfsEscape.h"
+#include "cpName.h"
+
+#ifdef _WIN32
+
+#define UNREFERENCED_PARAMETER(P) (P)
+
+/* These characters are illegal in Windows file names. */
+const char* HGFS_ILLEGAL_CHARS = "/\\*?:\"<>|";
+const char* HGFS_SUBSTITUTE_CHARS = "!@#$^&(){}";
+/* Last character of a file name in Windows can be neither dot nor space. */
+const char* HGFS_ILLEGAL_LAST_CHARS = ". ";
+
+/* http://msdn.microsoft.com/en-us/library/aa365247.aspx */
+char *HgfsReservedNames[] = {"CON", "PRN", "AUX", "NUL"};
+char *HgfsReservedNamesWithNumber[] = {"COM", "LPT"};
+
+#define HGFS_RESERVED_NAME_CHARS_LENGTH 3
+#define HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH (HGFS_RESERVED_NAME_CHARS_LENGTH + 1)
+/* Check for special escaping cases - reserved names and illegal last characters. */
+#define IS_SPECIAL_CASE_ESCAPE(b,o,l) HgfsIsSpecialCaseEscape(b,o,l)
+/* Process Windows reserved names. */
+#define PROCESS_RESERVED_NAME(b,s,p,o,c) \
+if (!HgfsProcessReservedName(b,s,p,o,c)) \
+{ \
+ return FALSE; \
+}
+/* Process Windows reserved names. */
+#define PROCESS_LAST_CHARACTER(b,s,p,c) \
+if (!HgfsProcessLastCharacter(b,s,p,c)) \
+{ \
+ return FALSE; \
+}
+
+#else // _WIN32
+
+#define UNREFERENCED_PARAMETER(P)
+/* There is no special escape sequences on other than Windows platforms. */
+#define IS_SPECIAL_CASE_ESCAPE(b,o,l) FALSE
+/* There is no reserved names on other then Windows platforms. */
+#define PROCESS_RESERVED_NAME(b,s,p,o,c)
+/* There is no special processing for the last character on non-Windows platforms. */
+#define PROCESS_LAST_CHARACTER(b,s,p,c)
+
+#if defined(__APPLE__)
+/* These characters are illegal in MAC OS file names. */
+const char* HGFS_ILLEGAL_CHARS = "/:";
+const char* HGFS_SUBSTITUTE_CHARS = "!&";
+#else   // __APPLE__
+/* These characters are illegal in Linux file names. */
+const char* HGFS_ILLEGAL_CHARS = "/";
+const char* HGFS_SUBSTITUTE_CHARS = "!";
+#endif  // __APPLE__
+
+#endif  // _WIN32
+
+#define HGFS_ESCAPE_CHAR '%'
+#define HGFS_ESCAPE_SUBSTITUE_CHAR ']'
+
+typedef enum {
+   HGFS_ESCAPE_ILLEGAL_CHARACTER,
+   HGFS_ESCAPE_RESERVED_NAME,
+   HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER,
+   HGFS_ESCAPE_ESCAPE_SEQUENCE,
+   HGFS_ESCAPE_COMPLETE
+} HgfsEscapeReason;
+
+
+typedef Bool (*HgfsEnumCallback)(char const *bufIn,
+                                 uint32 offset,
+                                 HgfsEscapeReason reason,
+                                 void* context);
+
+/*
+ * The structure is used by HgfsAddEscapeCharacter to keep context information between
+ * invocations
+ * All offsets defined in this structure are in characters, not bytes
+ */
+typedef  struct {
+   uint32   processedOffset;     // Offset of the first unprocessed input character
+   uint32   outputBufferLength;  // Number of characters in the output buffer
+   uint32   outputOffset;        // Number of characters that are already in the output
+   char    *outputBuffer;        // Pointer to the output buffer
+} HgfsEscapeContext;
+
+static void HgfsEscapeUndoComponent(char *bufIn, uint32 *totalLength);
+static int HgfsEscapeGetComponentSize(char const *bufIn, uint32 sizeIn);
+static int HgfsEscapeDoComponent(char const *bufIn, uint32 sizeIn, uint32 sizeBufOut,
+                                 char *bufOut);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsAddEscapeCharacter --
+ *
+ *    Callback function that is called by HgfsEnumerate to insert an escape sequence
+ *    into the input name.
+ *
+ * Results:
+ *    TRUE if successful, FALSE if there is an error like the output buffer is
+ *    too small.
+ *
+ * Side effects:
+ *    Updates the output buffer pointer (stored in the context variable).
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsAddEscapeCharacter(char const * bufIn,      // IN: input name
+                       uint32 offset,           // IN: offset that requires escaping
+                       HgfsEscapeReason reason, // IN: reason for esaping
+                       void *context)           // IN/OUT: convertion context
+{
+   HgfsEscapeContext *escapeContext = (HgfsEscapeContext *)context;
+   uint32 charactersToCopy;
+   uint32 outputSpace;
+   char* illegal;
+   Bool result = TRUE;
+
+   ASSERT(offset >= escapeContext->processedOffset); // Scanning forward
+   charactersToCopy = offset - escapeContext->processedOffset;
+
+   if (escapeContext->outputOffset + charactersToCopy >
+       escapeContext->outputBufferLength) {
+      return FALSE;
+   }
+
+   memcpy(escapeContext->outputBuffer + escapeContext->outputOffset,
+          bufIn + escapeContext->processedOffset, charactersToCopy * sizeof *bufIn);
+   escapeContext->outputOffset += charactersToCopy;
+   escapeContext->processedOffset += charactersToCopy;
+
+   outputSpace = escapeContext->outputBufferLength - escapeContext->outputOffset;
+
+   switch(reason) {
+   case HGFS_ESCAPE_ILLEGAL_CHARACTER:
+      if (outputSpace < 2) {
+         return FALSE;
+      }
+      illegal = strchr(HGFS_ILLEGAL_CHARS, bufIn[escapeContext->processedOffset]);
+      escapeContext->processedOffset++;  // Skip illegal input character
+      ASSERT(illegal != NULL);
+      escapeContext->outputBuffer[escapeContext->outputOffset] =
+         HGFS_SUBSTITUTE_CHARS[illegal - HGFS_ILLEGAL_CHARS];
+      escapeContext->outputOffset++;
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_RESERVED_NAME:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_ESCAPE_SEQUENCE:
+      if (outputSpace < 2) {
+         return FALSE;
+      }
+      escapeContext->processedOffset++; // Skip input esape character
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_SUBSTITUE_CHAR;
+      escapeContext->outputOffset++;
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_COMPLETE:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = '\0';
+      break;
+
+   default:
+      result = FALSE;
+      ASSERT(FALSE);
+   }
+   return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsCountEscapeChars --
+ *
+ *    Callback function that is called by HgfsEnumerate to count additional characters
+ *    that need to be inserted in the input name.
+ *
+ * Results:
+ *    TRUE since it never fails.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsCountEscapeChars(char const *bufIn,       // IN: input name
+                     uint32 offset,           // IN: offset where escape is needed
+                     HgfsEscapeReason reason, // IN: reason for escaping
+                     void *context)           // IN/OUT: context info
+{
+   UNREFERENCED_PARAMETER(bufIn);
+   UNREFERENCED_PARAMETER(offset);
+   if (reason != HGFS_ESCAPE_COMPLETE) {
+      uint32 *counter = (uint32*)context;
+      (*counter)++;
+   }
+   return TRUE;
+}
+
+
+#ifdef _WIN32
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsLetterToUpper --
+ *
+ *    Converts lowercase English letters to uppercase.
+ *    If the symbol is not a lowercase English letter returns the original character.
+ *
+ * Results:
+ *    Converted character.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static char
+HgfsLetterToUpper(char letter)
+{
+   if (letter >= 'a' && letter <= 'z') {
+      return letter - ('a' - 'A');
+   }
+   return letter;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsEqualPrefix --
+ *
+ *    Verifies if the string prefix is equal to the given prefix.
+ *    It assumes that the prefix includes only uppercase English letters or numbers
+ *    and it does not have any international characters.
+ *    The string must be either NULL terminated or not shorter then the prefix.
+ *
+ * Results:
+ *    TRUE if the uppcased string starts with the given prefix. False otherwise.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsEqualPrefix(char const *prefix,  // IN: prefix to check
+                  char const *string,  // IN: input string
+                  uint32 prefixLength) // IN: length of the prefix in characters
+{
+   int i;
+   for (i = 0; i < prefixLength; i++) {
+      ASSERT(prefix[i] > 0 && (prefix[i] < 'a' || prefix[i] > 'z' ));
+      if (prefix[i] != HgfsLetterToUpper(string[i])) {
+         return FALSE;
+      }
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsReservedPrefix --
+ *
+ *    Verifies if the name's prefix is one of the reserved names.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsReservedPrefix(char const *bufIn)  // IN: input name
+{
+   uint32 i;
+   for (i = 0; i < ARRAYSIZE(HgfsReservedNames); i++) {
+      if (HgfsIsEqualPrefix(HgfsReservedNames[i], bufIn,
+                            HGFS_RESERVED_NAME_CHARS_LENGTH)) {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsReservedPrefixWithNumber --
+ *
+ *    Verifies if the name's prefix is one of the reserved names with number:
+ *    COM1-9 or LPT1-9.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names with number.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsReservedPrefixWithNumber(char const *bufIn)   // IN: input name
+{
+   uint32 i;
+   for (i = 0; i < ARRAYSIZE(HgfsReservedNamesWithNumber); i++) {
+      if (HgfsIsEqualPrefix(HgfsReservedNamesWithNumber[i], bufIn,
+                            HGFS_RESERVED_NAME_CHARS_LENGTH) &&
+          bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] >= '1' &&
+          bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] <= '9') {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsSpecialCaseEscape --
+ *
+ *    Verifies if the escape character is a part of special case escape sequence
+ *    that exists only in Windows - escaped reserved name or escaped illegal last
+ *    character.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names with number.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsSpecialCaseEscape(char const *bufIn,   // IN: input name
+                        uint32 offset,       // IN: offset of the escape character
+                        uint32 length)       // IN: length of the name in characters
+{
+   if (offset + 1 == length &&
+      strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[offset - 1]) != NULL) {
+      return TRUE;
+   }
+   if (offset == HGFS_RESERVED_NAME_CHARS_LENGTH &&
+      (length == HGFS_RESERVED_NAME_CHARS_LENGTH + 1 || bufIn[offset+1] == '.')) {
+      return HgfsIsReservedPrefix(bufIn);
+   }
+   if (offset == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
+      (length == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH + 1 ||
+      bufIn[offset+1] == '.')) {
+      return HgfsIsReservedPrefixWithNumber(bufIn);
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsProcessReservedName --
+ *
+ *    Verifies if the name is one of reserved Windows file names.
+ *    If it is a reserved name invokes callback that performs required
+ *    processing.
+ *
+ * Results:
+ *    TRUE if no processing is required of if processing succeeded,
+ *    FALSE if processing failed.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsProcessReservedName(char const *bufIn,              // IN:  Unescaped input buffer
+                        uint32 sizeIn,                  // IN:  Length of the input
+                        HgfsEnumCallback processEscape, // IN:  Callack that is invoked
+                                                        //      if input is reserved name
+                        uint32 *offset,                 // OUT: New offset in the input
+                        void *context)                  // IN/OUT: Context for callback
+{
+   /*  Look reserved names: CON, PRN, AUX, NUL. */
+   if (sizeIn >= HGFS_RESERVED_NAME_CHARS_LENGTH && HgfsIsReservedPrefix(bufIn)) {
+      if (HGFS_RESERVED_NAME_CHARS_LENGTH == sizeIn ||
+         bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] == '.') {
+         if (!processEscape(bufIn, HGFS_RESERVED_NAME_CHARS_LENGTH,
+                            HGFS_ESCAPE_RESERVED_NAME, context)) {
+            return FALSE;
+         }
+         *offset = HGFS_RESERVED_NAME_CHARS_LENGTH;
+      }
+   }
+
+   /*  Look reserved names with numbers: COM1-9 and LPT1-9. */
+   if (sizeIn >= HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
+       HgfsIsReservedPrefixWithNumber(bufIn)) {
+      if (HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH == sizeIn ||
+         bufIn[HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH] == '.') {
+         if (!processEscape(bufIn, HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH,
+                            HGFS_ESCAPE_RESERVED_NAME, context)) {
+            return FALSE;
+         }
+         *offset = HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH;
+      }
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsProcessLastCharacter --
+ *
+ *    Verifies if the trailing character in the name is a valid last character.
+ *    In Windows it is illegal to have a file name that ends with dot ('.') or
+ *    space (' '). The only exception is "." and ".." directory names.
+ *    If the last character is invalid the function invokes a callback to process it.
+ *
+ * Results:
+ *    TRUE if no processing is required of if processing succeeded,
+ *    FALSE if processing failed.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsProcessLastCharacter(char const *bufIn,              // IN:  Unescaped input buffer
+                         uint32 sizeIn,                  // IN:  Length of the input
+                         HgfsEnumCallback processEscape, // IN:  Callack that is invoked
+                                                         //      when escaping is needed
+                         void *context)                  // IN/OUT: Callback context
+{
+
+   /* If the filename is '.' or '..' we shouldn't escape it. */
+   if ((sizeIn == 1 && bufIn[0] == '.') ||
+       (sizeIn == 2 && bufIn[0] == '.' && bufIn[1] == '.')) {
+      return TRUE;
+   }
+
+   /* Invoke the callback if the last character is illegal. */
+   if (strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[sizeIn - 1]) != NULL) {
+      if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER, context)) {
+         return FALSE;
+      }
+   }
+   return TRUE;
+}
+
+#endif //  WIN32
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsEscapeSequence --
+ *
+ *    Verifies if input buffer has an escape sequence at the position
+ *    defined by offset.
+ *
+ * Results:
+ *    TRUE if there is an escape sequence at the position defined by offset.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsEscapeSequence(char const *bufIn,   // IN: input name
+                     uint32 offset,       // IN: offset of the escape character
+                     uint32 length)       // IN: length of the name in characters
+{
+   if (bufIn[offset] == HGFS_ESCAPE_CHAR && offset > 0) {
+      char *substitute;
+      if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
+         return TRUE;
+      }
+      substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
+      if (substitute != NULL) {
+         return TRUE;
+      }
+      return IS_SPECIAL_CASE_ESCAPE(bufIn,offset,length);
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeEnumerate --
+ *
+ *    The function scans the input buffer and calls processEscape callback for every
+ *    place in the input buffer which require escaping.
+ *
+ *    Callback does the required processing. There are two different callbacks -
+ *    one counts extra symbols that are needed for escaping and another produces
+ *    escaped output name based on input name.
+ *
+ *    1. The first function calculates number of extra characters. It just increments
+ *    a counter which is passed to it in context variable every time it is called
+ *    for the reason different from "complete processing" assuming that
+ *    exactly one extra  character is required to escape any invalid input.
+ *
+ *    2. The second function produces output name by copying everything from input
+ *    name into the output name up to the place which require escaping and
+ *    then inserts appropriate escape sequence into the output. It keeps track of its
+ *    progress and keeps pointer to the output buffer in the context variable.
+ *    HgfsEscapeEnumerate calls calback function one more time at the end of the
+ *    input buffer to let callback finish processing of the input (for example copy
+ *    the rest of the name after the last escape sequence from input buffer to
+ *    output buffer).
+ *
+ * Results:
+ *    TRUE if the input has been processed successfully by the callback, false otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsEscapeEnumerate(char const *bufIn,              // IN:  Buffer with unescaped input
+                    uint32 sizeIn,                  // IN:  Number of input *characters*
+                    HgfsEnumCallback processEscape, // IN: Callack that is invoked every
+                                                    //     time escaping is required
+                    void *context)                  // IN/OUT: Context for processEscape
+{
+   /*  First look for invalid characters in the input name. */
+   uint32 i, offset = 0;
+   if (sizeIn == 0) {
+      return TRUE;
+   }
+
+   ASSERT(processEscape);
+
+   PROCESS_RESERVED_NAME(bufIn, sizeIn, processEscape, &offset, context);
+
+   for (i = offset; i < sizeIn; i++) {
+      if (strchr(HGFS_ILLEGAL_CHARS, bufIn[i]) != NULL) {
+         if (!processEscape(bufIn, i, HGFS_ESCAPE_ILLEGAL_CHARACTER, context)) {
+            return FALSE;
+         }
+      } else if (HgfsIsEscapeSequence(bufIn, i, sizeIn)) {
+         if (!processEscape(bufIn, i, HGFS_ESCAPE_ESCAPE_SEQUENCE, context)) {
+            return FALSE;
+         }
+      }
+   }
+
+   PROCESS_LAST_CHARACTER(bufIn, sizeIn, processEscape, context);
+
+   if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_COMPLETE, context)) {
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_Do --
+ *
+ *    Escape any characters that are not legal in a windows filename.
+ *    Escape reserved file names that can't be used in Windows.
+ *    We also of course have to escape the escape character, which is "%",
+ *    when it is part of a character sequence that would require unescaping
+ *
+ *    sizeBufOut must account for the NUL terminator.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    On failure (bufOut not big enough to hold result), negative value.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_Do(char const *bufIn, // IN:  Buffer with unescaped input
+                  uint32 sizeIn,     // IN:  Size of input buffer
+                  uint32 sizeBufOut, // IN:  Size of output buffer
+                  char *bufOut)      // OUT: Buffer for escaped output
+{
+   const char *currentComponent = bufIn;
+   uint32 sizeLeft = sizeBufOut;
+   char *outPointer = bufOut;
+   const char *end = bufIn + sizeIn;
+   const char *next;
+   ASSERT(sizeIn > 0);
+   if (bufIn[sizeIn - 1] == '\0') {
+      /*
+       * In some cases a NUL terminated string is passed to HgfsEscape_Do
+       * so it make sense to support such input even if CPName_GetComponent
+       * does not. Detect this case and make the input compliant with
+       * CPName_GetComponent by removing terminating NUL.
+       */
+      end--;
+      sizeIn--;
+   }
+   /*
+    * Absolute symbolic link name starts with the '\0'. HgfsEscapeDo needs to work
+    * with such names. Leading NULL symbols should be skipped here since
+    * CPName_GetComponent does not support such names.
+    */
+   while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
+      currentComponent++;
+      sizeLeft--;
+      *outPointer++ = '\0';
+   }
+   while (currentComponent - bufIn < sizeIn) {
+      int escapedLength;
+      uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
+
+      escapedLength = HgfsEscapeDoComponent(currentComponent, componentSize,
+                                            sizeLeft, outPointer);
+      if (escapedLength < 0) {
+         return escapedLength;
+      }
+      currentComponent = next;
+      sizeLeft -= escapedLength + 1;
+      outPointer += escapedLength + 1;
+   }
+   return (int) (outPointer - bufOut) - 1; // Do not count the last NUL terminator
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_GetSize --
+ *
+ *    Calculates required size in bytes for the buffer that is needed to hold escaped
+ *    cross platform path name. Returns 0 if no escaping is required.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    Returns 0 if the name is a valid Windows file name.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_GetSize(char const *bufIn,    // IN:  Buffer with unescaped input
+                   uint32 sizeIn)        // IN:  Size of the input buffer
+{
+   uint32 result = 0;
+   const char *currentComponent = bufIn;
+   const char *end = bufIn + sizeIn;
+   const char *next;
+
+   if (sizeIn == 0) { // No need toescape empty name.
+      return 0;
+   }
+   if (bufIn[sizeIn - 1] == '\0') {
+      /*
+       * In some cases a NUL terminated string is passed to HgfsEscape_GeSize
+       * so it make sense to support such input even if CPName_GetComponent
+       * does not. Detect this case and make the input compliant with
+       * CPName_GetComponent by removing terminating NUL.
+       */
+      end--;
+      sizeIn--;
+   }
+   /* Skip leading NULs to keep CPName_GetComponent happy. */
+   while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
+      currentComponent++;
+   }
+   while (currentComponent - bufIn < sizeIn) {
+      uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
+      result += HgfsEscapeGetComponentSize(currentComponent, componentSize);
+      currentComponent = next;
+   }
+   return (result == 0) ? 0 : result + sizeIn;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_Undo --
+ *
+ *    Unescape a buffer that was escaped using HgfsEscapeBuffer.
+ *
+ *    The unescaping is done in place in the input buffer, and
+ *    can not fail.
+ *
+ * Results:
+ *    The size (excluding the NUL terminator) of the unescaped, NUL
+ *    terminated buffer.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_Undo(char *bufIn,       // IN: Characters to be unescaped
+                uint32 sizeIn)     // IN: Number of characters in bufIn
+{
+   uint32 componentSize = strlen(bufIn) + 1;
+   uint32 unprocessedSize = sizeIn + 1;
+   uint32 result = 0;
+   char *currentComponent = bufIn;
+   while (currentComponent != NULL) {
+      HgfsEscapeUndoComponent(currentComponent, &unprocessedSize);
+      componentSize = strlen(currentComponent) + 1; // Unescaped size
+      result += componentSize;
+      if (unprocessedSize > 1) {
+         currentComponent = currentComponent + componentSize;
+         componentSize = strlen(currentComponent) + 1; // Size of the next component
+      } else {
+         currentComponent = NULL;
+      }
+   }
+   return result - 1;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeUndoComponent --
+ *
+ *    Unescape a buffer that was escaped using HgfsEscapeBuffer.
+ *
+ *    The unescaping is done in place in the input buffer, and
+ *    can not fail.
+ *
+ * Results:
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsEscapeUndoComponent(char   *bufIn,             // IN: Characters to be unescaped
+                        uint32 *unprocessedLength) // IN: Unprocessed characters
+                                                   //     in the whole name
+{
+   size_t offset;
+   size_t sizeIn = strlen(bufIn);
+   char* curOutBuffer = bufIn;
+   char* escapePointer;
+   ASSERT(bufIn);
+
+   escapePointer = strchr(curOutBuffer, HGFS_ESCAPE_CHAR);
+   while (escapePointer != NULL) {
+      offset = escapePointer - bufIn;
+      if (HgfsIsEscapeSequence(bufIn, offset, sizeIn)) {
+         char* substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
+         if (substitute != NULL) {
+            bufIn[offset - 1] = HGFS_ILLEGAL_CHARS[substitute - HGFS_SUBSTITUTE_CHARS];
+         } else if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
+            bufIn[offset - 1] = HGFS_ESCAPE_CHAR;
+         }
+         memmove(escapePointer, escapePointer + 1, (*unprocessedLength) - offset - 1);
+         (*unprocessedLength)--;
+         sizeIn--;
+         if (sizeIn > 0) {
+            escapePointer = strchr(escapePointer, HGFS_ESCAPE_CHAR);
+         } else {
+            escapePointer = NULL;
+         }
+      } else {
+         escapePointer = strchr(escapePointer + 1, HGFS_ESCAPE_CHAR);
+      }
+   }
+   ASSERT((*unprocessedLength) > sizeIn);
+   (*unprocessedLength) -= sizeIn + 1;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeDoComponent --
+ *
+ *    Escape any characters that are not legal in a windows filename.
+ *    Escape reserved file names that can't be used in Windows.
+ *    We also of course have to escape the escape character, which is "%",
+ *    when it is part of a character sequence that would require unescaping
+ *
+ *    sizeBufOut must account for the NUL terminator.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    On failure (bufOut not big enough to hold result), negative value.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscapeDoComponent(char const *bufIn, // IN:  Buffer with unescaped input
+                          uint32 sizeIn,     // IN:  Size of input buffer
+                          uint32 sizeBufOut, // IN:  Size of output buffer
+                          char *bufOut)      // OUT: Buffer for escaped output
+{
+   HgfsEscapeContext conversionContext;
+   conversionContext.processedOffset = 0;
+   conversionContext.outputBufferLength = sizeBufOut / sizeof *bufOut;
+   conversionContext.outputOffset = 0;
+   conversionContext.outputBuffer = bufOut;
+
+   if (!HgfsEscapeEnumerate(bufIn, sizeIn, HgfsAddEscapeCharacter, &conversionContext)) {
+      return -1;
+   }
+   return conversionContext.outputOffset * sizeof *bufOut;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeGetComponentSize --
+ *
+ *    Calculates number of addtitional characters that are needed to escape
+ *    name for one NUL terminated component of the path.
+ *
+ * Results:
+ *    Number of additional escape characters needed to escape the name.
+ *    Returns 0 if no escaping is required.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscapeGetComponentSize(char const *bufIn, // IN:  Buffer with unescaped input
+                           uint32 sizeIn)     // IN:  Size of the in input buffer
+{
+   int result = 0;
+   HgfsEscapeEnumerate(bufIn, sizeIn, HgfsCountEscapeChars, &result);
+   return result;
+}
diff --git a/open-vm-tools/modules/freebsd/vmhgfs/hgfsEscape.h b/open-vm-tools/modules/freebsd/vmhgfs/hgfsEscape.h
new file mode 100644 (file)
index 0000000..66fb58e
--- /dev/null
@@ -0,0 +1,40 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * hgfsEscape.h --
+ *
+ *    Escape and unescape filenames that are not legal on a particular
+ *    platform.
+ *
+ */
+
+#ifndef __HGFS_ESCAPE_H__
+#define __HGFS_ESCAPE_H__
+
+int HgfsEscape_GetSize(char const *bufIn, // IN
+                       uint32 sizeIn);    // IN
+int HgfsEscape_Do(char const *bufIn, // IN
+                  uint32 sizeIn,     // IN
+                  uint32 sizeBufOut, // IN
+                  char *bufOut);     // OUT
+
+int HgfsEscape_Undo(char *bufIn,    // IN
+                    uint32 sizeIn); // IN
+
+#endif // __HGFS_ESCAPE_H__
diff --git a/open-vm-tools/modules/linux/dkms.conf b/open-vm-tools/modules/linux/dkms.conf
new file mode 100644 (file)
index 0000000..ffed427
--- /dev/null
@@ -0,0 +1,48 @@
+PACKAGE_NAME=open-vm-tools
+PACKAGE_VERSION=2008.11.18
+MAKE[0]="make -C pvscsi VM_UNAME=\$kernelver;   \
+         make -C vmblock VM_UNAME=\$kernelver;  \
+         make -C vmhgfs VM_UNAME=\$kernelver;   \
+         make -C vmmemctl VM_UNAME=\$kernelver; \
+         make -C vmsync VM_UNAME=\$kernelver;   \
+         make -C vmxnet VM_UNAME=\$kernelver;   \
+         make -C vsock VM_UNAME=\$kernelver;    \
+         make -C vmci VM_UNAME=\$kernelver;     \
+         make -C vmxnet3 VM_UNAME=\$kernelver"
+CLEAN[0]="make -C pvscsi clean;                 \
+          make -C vmblock clean;                \
+          make -C vmhgfs clean;                 \
+          make -C vmmemctl clean;               \
+          make -C vmsync clean;                 \
+          make -C vmxnet clean;                 \
+          make -C vsock clean;                  \
+          make -C vmci clean;                   \
+          make -C vmxnet3 clean"
+BUILT_MODULE_NAME[0]="pvscsi"
+BUILT_MODULE_NAME[1]="vmblock"
+BUILT_MODULE_NAME[2]="vmci"
+BUILT_MODULE_NAME[3]="vmhgfs"
+BUILT_MODULE_NAME[4]="vmmemctl"
+BUILT_MODULE_NAME[5]="vmsync"
+BUILT_MODULE_NAME[6]="vmxnet"
+BUILT_MODULE_NAME[7]="vmxnet3"
+BUILT_MODULE_NAME[8]="vsock"
+BUILT_MODULE_LOCATION[0]="pvscsi/"
+BUILT_MODULE_LOCATION[1]="vmblock/"
+BUILT_MODULE_LOCATION[2]="vmci/"
+BUILT_MODULE_LOCATION[3]="vmhgfs/"
+BUILT_MODULE_LOCATION[4]="vmmemctl/"
+BUILT_MODULE_LOCATION[5]="vmsync/"
+BUILT_MODULE_LOCATION[6]="vmxnet/"
+BUILT_MODULE_LOCATION[7]="vmxnet3/"
+BUILT_MODULE_LOCATION[8]="vsock/"
+DEST_MODULE_LOCATION[0]="/kernel/drivers/scsi"
+DEST_MODULE_LOCATION[1]="/kernel/fs/vmblock"
+DEST_MODULE_LOCATION[2]="/kernel/drivers/misc"
+DEST_MODULE_LOCATION[3]="/kernel/fs/vmhgfs"
+DEST_MODULE_LOCATION[4]="/kernel/drivers/misc"
+DEST_MODULE_LOCATION[5]="/kernel/drivers/misc"
+DEST_MODULE_LOCATION[6]="/kernel/drivers/net"
+DEST_MODULE_LOCATION[7]="/kernel/drivers/net"
+DEST_MODULE_LOCATION[8]="/kernel/net/vsock"
+AUTOINSTALL="YES"
diff --git a/open-vm-tools/modules/linux/pvscsi/COPYING b/open-vm-tools/modules/linux/pvscsi/COPYING
new file mode 100644 (file)
index 0000000..d511905
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/open-vm-tools/modules/linux/pvscsi/Makefile b/open-vm-tools/modules/linux/pvscsi/Makefile
new file mode 100644 (file)
index 0000000..650fd67
--- /dev/null
@@ -0,0 +1,158 @@
+#!/usr/bin/make -f
+##########################################################
+# Copyright (C) 1998 VMware, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation version 2 and no later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+##########################################################
+
+####
+####  VMware kernel module Makefile to be distributed externally
+####
+
+####
+#### SRCROOT _must_ be a relative path.
+####
+SRCROOT = .
+
+VM_UNAME = $(shell uname -r)
+
+# Header directory for the running kernel
+HEADER_DIR = /lib/modules/$(VM_UNAME)/build/include
+
+BUILD_DIR = $(HEADER_DIR)/..
+
+DRIVER := pvscsi
+PRODUCT := @PRODUCT@
+
+# Grep program
+GREP = /bin/grep
+
+vm_check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
+        > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+vm_check_file = $(shell if test -f $(1); then echo "yes"; else echo "no"; fi)
+
+ifndef VM_KBUILD
+VM_KBUILD := no
+ifeq ($(call vm_check_file,$(BUILD_DIR)/Makefile), yes)
+ifneq ($(call vm_check_file,$(BUILD_DIR)/Rules.make), yes)
+VM_KBUILD := 26
+endif
+endif
+export VM_KBUILD
+endif
+
+ifndef VM_KBUILD_SHOWN
+ifeq ($(VM_KBUILD), no)
+VM_DUMMY := $(shell echo >&2 "Using standalone build system.")
+else
+ifeq ($(VM_KBUILD), 24)
+VM_DUMMY := $(shell echo >&2 "Using 2.4.x kernel build system.")
+else
+VM_DUMMY := $(shell echo >&2 "Using 2.6.x kernel build system.")
+endif
+endif
+VM_KBUILD_SHOWN := yes
+export VM_KBUILD_SHOWN
+endif
+
+ifneq ($(VM_KBUILD), no)
+
+VMCCVER := $(shell $(CC) -dumpversion)
+
+# If there is no version defined, we are in toplevel pass, not yet in kernel makefiles...
+ifeq ($(VERSION),)
+
+ifeq ($(VM_KBUILD), 24)
+DRIVER_KO := $(DRIVER).o
+else
+DRIVER_KO := $(DRIVER).ko
+endif
+
+.PHONY: $(DRIVER_KO)
+
+auto-build: $(DRIVER_KO)
+       cp -f $< $(SRCROOT)/../$(DRIVER).o
+
+# $(DRIVER_KO) is a phony target, so compare file times explicitly
+$(DRIVER): $(DRIVER_KO)
+       if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi
+
+# Pass gcc version down the chain, so we can detect if kernel attempts to use unapproved compiler
+VM_CCVER := $(VMCCVER)
+export VM_CCVER
+VM_CC := $(CC)
+export VM_CC
+
+MAKEOVERRIDES := $(filter-out CC=%,$(MAKEOVERRIDES))
+
+#
+# Define a setup target that gets built before the actual driver.
+# This target may not be used at all, but if it is then it will be defined
+# in Makefile.kernel
+#
+prebuild:: ;
+postbuild:: ;
+
+$(DRIVER_KO): prebuild
+       make -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) modules
+       make -C $$PWD SRCROOT=$$PWD/$(SRCROOT) postbuild
+
+else
+
+ifneq ($(VM_CCVER), $(VMCCVER))
+$(warning *** Inappropriate build environment: you wanted to use gcc \
+ version $(VM_CCVER) while kernel attempts to use gcc version $(VMCCVER).)
+$(error For proper build you'll have to replace $(CC) with symbolic \
+ link to $(VM_CC))
+endif
+
+endif
+
+vm_check_build = $(shell if $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
+       $(CPPFLAGS) $(CFLAGS) $(CFLAGS_KERNEL) \
+       $(EXTRA_CFLAGS) -Iinclude2/asm/mach-default \
+       -DKBUILD_BASENAME=\"$(DRIVER)\" \
+       -Werror -S -o /dev/null -xc $(1) \
+       > /dev/null 2>&1; then echo "$(2)"; else echo "$(3)"; fi)
+
+CC_WARNINGS := -Wall -Wstrict-prototypes
+CC_OPTS := $(GLOBAL_DEFS) $(CC_WARNINGS) -DVMW_USING_KBUILD
+ifdef VMX86_DEVEL
+CC_OPTS += -DVMX86_DEVEL
+endif
+ifdef VMX86_DEBUG
+CC_OPTS += -DVMX86_DEBUG
+endif
+
+include $(SRCROOT)/Makefile.kernel
+
+ifdef TOPDIR
+ifeq ($(VM_KBUILD), 24)
+
+O_TARGET := $(DRIVER).o
+
+obj-y := $($(DRIVER)-y)
+
+include $(TOPDIR)/Rules.make
+endif
+endif
+
+else
+
+include $(SRCROOT)/Makefile.normal
+
+endif
+
+#.SILENT:
diff --git a/open-vm-tools/modules/linux/pvscsi/Makefile.kernel b/open-vm-tools/modules/linux/pvscsi/Makefile.kernel
new file mode 100644 (file)
index 0000000..938d72c
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/make -f
+##########################################################
+# Copyright (C) 1998 VMware, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation version 2 and no later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+#
+##########################################################
+
+####
+####  VMware pvscsi Makefile to be distributed externally
+####
+
+INCLUDE := -I.
+
+EXTRA_CFLAGS := $(CC_OPTS) $(INCLUDE)
+
+obj-m += $(DRIVER).o
+
+clean:
+       rm -rf $(wildcard $(DRIVER).mod.c $(DRIVER).ko .tmp_versions \
+              Module.symvers Modules.symvers Module.markers modules.order \
+              $(foreach dir,./,$(addprefix $(dir),.*.cmd .*.o.flags *.o)))
diff --git a/open-vm-tools/modules/linux/pvscsi/autoconf/cachecreate.c b/open-vm-tools/modules/linux/pvscsi/autoconf/cachecreate.c
new file mode 100644 (file)
index 0000000..88c51c1
--- /dev/null
@@ -0,0 +1,42 @@
+/*********************************************************
+ * Copyright (C) 2006 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#include <linux/autoconf.h>
+#include <linux/version.h>
+
+/*
+ * All kernels before 2.6.22 take 6 arguments.  All kernels since
+ * 2.6.23-rc1 take 5 arguments.  Only kernels between 2.6.22 and
+ * 2.6.23-rc1 are questionable - we could ignore them if we wanted,
+ * nobody cares about them even now.  But unfortunately RedHat is
+ * re-releasing 2.6.X-rc kernels under 2.6.(X-1) name, so they
+ * are releasing 2.6.23-rc1 as 2.6.22-5055-something, so we have
+ * to do autodetection for them.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
+/* Success... */
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+#error "This test intentionally fails on 2.6.23 and newer kernels."
+#else
+#include <linux/slab.h>
+
+struct kmem_cache *kmemtest(void) {
+   return kmem_cache_create("test", 12, 0, 0, NULL, NULL);
+}
+                                               
+#endif
diff --git a/open-vm-tools/modules/linux/pvscsi/autoconf/cachector.c b/open-vm-tools/modules/linux/pvscsi/autoconf/cachector.c
new file mode 100644 (file)
index 0000000..bbc124d
--- /dev/null
@@ -0,0 +1,40 @@
+/*********************************************************
+ * Copyright (C) 2006 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#include <linux/autoconf.h>
+#include <linux/version.h>
+
+/*
+ * Between 2.6.23 and 2.6.24-rc1 ctor prototype was changed from
+ * ctor(ptr, cache, flags) to ctor(cache, ptr).  Unfortunately there
+ * is no typedef for ctor, so we have to redefine kmem_cache_create
+ * to find out ctor prototype.  This assumes that kmem_cache_create
+ * takes 5 arguments and not 6 - that change occured between
+ * 2.6.22 and 2.6.23-rc1.  If prototype matches, then this is old
+ * kernel.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+#error "This test intentionally fails on 2.6.24 and newer kernels."
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
+#include <linux/slab.h>
+
+struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
+                        unsigned long,
+                        void (*)(void *, struct kmem_cache *, unsigned long));
+                                               
+#endif
diff --git a/open-vm-tools/modules/linux/pvscsi/autoconf/geninclude.c b/open-vm-tools/modules/linux/pvscsi/autoconf/geninclude.c
new file mode 100644 (file)
index 0000000..f37a20f
--- /dev/null
@@ -0,0 +1,40 @@
+/*********************************************************
+ * Copyright (C) 2003 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#include <linux/autoconf.h>
+
+#ifdef CONFIG_X86_VOYAGER
+APATH/mach-voyager
+#endif
+#ifdef CONFIG_X86_VISWS
+APATH/mach-visws
+#endif
+#ifdef CONFIG_X86_NUMAQ
+APATH/mach-numaq
+#endif
+#ifdef CONFIG_X86_BIGSMP
+APATH/mach-bigsmp
+#endif
+#ifdef CONFIG_X86_SUMMIT
+APATH/mach-summit
+#endif
+#ifdef CONFIG_X86_GENERICARCH
+APATH/mach-generic
+#endif
+APATH/mach-default
+
diff --git a/open-vm-tools/modules/linux/pvscsi/compat_interrupt.h b/open-vm-tools/modules/linux/pvscsi/compat_interrupt.h
new file mode 100644 (file)
index 0000000..1d72a4b
--- /dev/null
@@ -0,0 +1,55 @@
+/*********************************************************
+ * Copyright (C) 2003 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_INTERRUPT_H__
+#   define __COMPAT_INTERRUPT_H__
+
+
+#include <linux/interrupt.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 69)
+/*
+ * We cannot just define irqreturn_t, as some 2.4.x kernels have
+ * typedef void irqreturn_t; for "increasing" backward compatibility.
+ */
+typedef void compat_irqreturn_t;
+#define COMPAT_IRQ_NONE
+#define COMPAT_IRQ_HANDLED
+#define COMPAT_IRQ_RETVAL(x)
+#else
+typedef irqreturn_t compat_irqreturn_t;
+#define COMPAT_IRQ_NONE                IRQ_NONE
+#define COMPAT_IRQ_HANDLED     IRQ_HANDLED
+#define COMPAT_IRQ_RETVAL(x)   IRQ_RETVAL(x)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+#define COMPAT_IRQF_DISABLED    SA_INTERRUPT
+#define COMPAT_IRQF_SHARED      SA_SHIRQ
+#else
+#define COMPAT_IRQF_DISABLED    IRQF_DISABLED
+#define COMPAT_IRQF_SHARED      IRQF_SHARED
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
+#define COMPAT_IRQ_HANDLER_ARGS(irq, devp) (int irq, void *devp, struct pt_regs *regs)
+#else
+#define COMPAT_IRQ_HANDLER_ARGS(irq, devp) (int irq, void *devp)
+#endif
+
+#endif /* __COMPAT_INTERRUPT_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/compat_ioport.h b/open-vm-tools/modules/linux/pvscsi/compat_ioport.h
new file mode 100644 (file)
index 0000000..bacdb50
--- /dev/null
@@ -0,0 +1,63 @@
+/*********************************************************
+ * Copyright (C) 2003 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_IOPORT_H__
+#   define __COMPAT_IOPORT_H__
+
+
+#include <linux/ioport.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+static inline void *
+compat_request_region(unsigned long start, unsigned long len, const char *name)
+{
+   if (check_region(start, len)) {
+      return NULL;
+   }
+   request_region(start, len, name);
+   return (void*)1;
+}
+#else
+#define compat_request_region(start, len, name) request_region(start, len, name)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 7)
+/* mmap io support starts from 2.3.7, fail the call for kernel prior to that */
+static inline void *
+compat_request_mem_region(unsigned long start, unsigned long len, const char *name)
+{
+   return NULL;
+}
+
+static inline void
+compat_release_mem_region(unsigned long start, unsigned long len)
+{
+   return;
+}
+#else
+#define compat_request_mem_region(start, len, name) request_mem_region(start, len, name)
+#define compat_release_mem_region(start, len)       release_mem_region(start, len)
+#endif
+
+/* these two macro defs are needed by compat_pci_request_region */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 15)
+#   define IORESOURCE_IO    0x00000100
+#   define IORESOURCE_MEM   0x00000200
+#endif
+
+#endif /* __COMPAT_IOPORT_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/compat_module.h b/open-vm-tools/modules/linux/pvscsi/compat_module.h
new file mode 100644 (file)
index 0000000..66fc469
--- /dev/null
@@ -0,0 +1,72 @@
+/*********************************************************
+ * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * compat_module.h --
+ */
+
+#ifndef __COMPAT_MODULE_H__
+#   define __COMPAT_MODULE_H__
+
+
+#include <linux/module.h>
+
+
+/*
+ * Modules wishing to use the GPL license are required to include a
+ * MODULE_LICENSE definition in their module source as of 2.4.10.
+ */
+#ifndef MODULE_LICENSE
+#define MODULE_LICENSE(license)
+#endif
+
+/*
+ * To make use of our own home-brewed MODULE_INFO, we need macros to
+ * concatenate two expressions to "__mod_", and and to convert an
+ * expression into a string. I'm sure we've got these in our codebase,
+ * but I'd rather not introduce such a dependency in a compat header.
+ */
+#ifndef __module_cat
+#define __module_cat_1(a, b) __mod_ ## a ## b
+#define __module_cat(a, b) __module_cat_1(a, b)
+#endif
+
+#ifndef __stringify
+#define __stringify_1(x) #x
+#define __stringify(x) __stringify_1(x)
+#endif
+
+/*
+ * MODULE_INFO was born in 2.5.69.
+ */
+#ifndef MODULE_INFO
+#define MODULE_INFO(tag, info)                                                \
+static const char __module_cat(tag, __LINE__)[]                               \
+  __attribute__((section(".modinfo"), unused)) = __stringify(tag) "=" info
+#endif
+
+/*
+ * MODULE_VERSION was born in 2.6.4. The earlier form appends a long "\0xxx"
+ * string to the module's version, but that was removed in 2.6.10, so we'll
+ * ignore it in our wrapper.
+ */
+#ifndef MODULE_VERSION
+#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
+#endif
+
+#endif /* __COMPAT_MODULE_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/compat_pci.h b/open-vm-tools/modules/linux/pvscsi/compat_pci.h
new file mode 100644 (file)
index 0000000..b499b28
--- /dev/null
@@ -0,0 +1,590 @@
+/*********************************************************
+ * Copyright (C) 1999 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * compat_pci.h: PCI compatibility wrappers.
+ */
+
+#ifndef __COMPAT_PCI_H__
+#define __COMPAT_PCI_H__
+
+#include "compat_ioport.h"
+#include <linux/pci.h>
+#ifndef KERNEL_2_1
+#   include <linux/bios32.h>
+#endif
+
+
+/* 2.0.x has useless struct pci_dev; remap it to our own */
+#ifndef KERNEL_2_1
+#define pci_dev    vmw_pci_driver_instance
+#endif
+
+
+/* 2.0/2.2 does not have pci driver API */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+struct vmw_pci_driver_instance {
+   struct vmw_pci_driver_instance *next;
+   void                   *driver_data;
+   struct pci_driver      *pcidrv;
+#ifdef KERNEL_2_1
+   struct pci_dev         *pcidev;
+#else
+   unsigned char           bus;
+   unsigned char           devfn;
+   unsigned int            irq;
+#endif
+};
+#endif
+
+
+/* 2.0 has pcibios_* calls only...  We have to provide pci_* compatible wrappers. */
+#ifndef KERNEL_2_1
+static inline int
+pci_read_config_byte(struct pci_dev *pdev,  // IN: PCI slot
+                     unsigned char   where, // IN: Byte to read
+                     u8             *value) // OUT: Value read
+{
+   return pcibios_read_config_byte(pdev->bus, pdev->devfn, where, value);
+}
+
+static inline int
+pci_read_config_dword(struct pci_dev *pdev,  // IN: PCI slot
+                      unsigned char   where, // IN: Dword to read
+                      u32            *value) // OUT: Value read
+{
+   return pcibios_read_config_dword(pdev->bus, pdev->devfn, where, value);
+}
+
+static inline int
+pci_write_config_dword(struct pci_dev *pdev,  // IN: PCI slot
+                       unsigned char   where, // IN: Dword to write
+                       u32             value) // IN: Value to write
+{
+   return pcibios_write_config_dword(pdev->bus, pdev->devfn, where, value);
+}
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * compat_pci_name --
+ *
+ *      Return human readable PCI slot name.  Note that some implementations
+ *      return a pointer to the static storage, so returned value may be
+ *      overwritten by subsequent calls to this function.
+ *
+ * Results:
+ *      Returns pointer to the string with slot name.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+#define compat_pci_name(pdev) pci_name(pdev)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+#define compat_pci_name(pdev) (pdev)->slot_name
+#elif defined(KERNEL_2_1)
+static inline const char*
+compat_pci_name(struct pci_dev* pdev)
+{
+   static char slot_name[12];
+   sprintf(slot_name, "%02X:%02X.%X", pdev->bus->number,
+           PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+   return slot_name;
+}
+#else
+static inline const char*
+compat_pci_name(struct pci_dev* pdev)
+{
+   static char slot_name[12];
+   sprintf(slot_name, "%02X:%02X.%X", pdev->bus,
+           PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+   return slot_name;
+}
+#endif
+
+
+/* pci_resource_start comes in 4 flavors - 2.0, 2.2, early 2.3, 2.4+ */
+#ifndef KERNEL_2_1
+static inline unsigned long
+compat_pci_resource_start(struct pci_dev *pdev,
+                          unsigned int    index)
+{
+   u32 addr;
+
+   if (pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + index * 4, &addr)) {
+      printk(KERN_ERR "Unable to read base address %u from PCI slot %s!\n",
+             index, compat_pci_name(pdev));
+      return ~0UL;
+   }
+   if (addr & PCI_BASE_ADDRESS_SPACE) {
+      return addr & PCI_BASE_ADDRESS_IO_MASK;
+   } else {
+      return addr & PCI_BASE_ADDRESS_MEM_MASK;
+   }
+}
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 1)
+#   define compat_pci_resource_start(dev, index) \
+       (((dev)->base_address[index] & PCI_BASE_ADDRESS_SPACE) \
+          ? ((dev)->base_address[index] & PCI_BASE_ADDRESS_IO_MASK) \
+          : ((dev)->base_address[index] & PCI_BASE_ADDRESS_MEM_MASK))
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)
+#   define compat_pci_resource_start(dev, index) \
+       ((dev)->resource[index].start)
+#else
+#   define compat_pci_resource_start(dev, index) \
+       pci_resource_start(dev, index)
+#endif
+
+/* since 2.3.15, a new set of s/w res flags IORESOURCE_ is introduced,
+ * we fake them by returning either IORESOURCE_{IO, MEM} prior to 2.3.15 since
+ * this is what compat_pci_request_region uses
+ */
+#ifndef KERNEL_2_1
+static inline unsigned long
+compat_pci_resource_flags(struct pci_dev *pdev,
+                          unsigned int    index)
+{
+   u32 addr;
+
+   if (pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + index * 4, &addr)) {
+      printk(KERN_ERR "Unable to read base address %u from PCI slot %s!\n",
+             index, compat_pci_name(pdev));
+      return ~0UL;
+   }
+   if (addr & PCI_BASE_ADDRESS_SPACE) {
+      return IORESOURCE_IO;
+   } else {
+      return IORESOURCE_MEM;
+   }
+}
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 1)
+#   define compat_pci_resource_flags(dev, index) \
+       (((dev)->base_address[index] & PCI_BASE_ADDRESS_SPACE) \
+          ? IORESOURCE_IO: IORESOURCE_MEM)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 15)
+    /* IORESOURCE_xxx appeared in 2.3.15 and is set in resource[].flags */
+#   define compat_pci_resource_flags(dev, index) ((dev)->resource[index].flags)
+#else
+#   define compat_pci_resource_flags(dev, index) pci_resource_flags(dev, index)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+static inline unsigned long
+compat_pci_resource_len(struct pci_dev *pdev,  // IN
+                        unsigned int    index) // IN
+{
+   u32 addr, mask;
+   unsigned char reg = PCI_BASE_ADDRESS_0 + index * 4;
+
+   if (pci_read_config_dword(pdev, reg, &addr) || addr == 0xFFFFFFFF) {
+      return 0;
+   }
+
+   pci_write_config_dword(pdev, reg, 0xFFFFFFFF);
+   pci_read_config_dword(pdev, reg, &mask);
+   pci_write_config_dword(pdev, reg, addr);
+
+   if (mask == 0 || mask == 0xFFFFFFFF) {
+      return 0;
+   }
+   if (addr & PCI_BASE_ADDRESS_SPACE) {
+      return 65536 - (mask & PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
+   } else {
+      return -(mask & PCI_BASE_ADDRESS_MEM_MASK);
+   }
+}
+#else
+#define compat_pci_resource_len(dev, index) pci_resource_len(dev, index)
+#endif
+
+/* pci_request_region appears in 2.4.20 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 20)
+static inline int
+compat_pci_request_region(struct pci_dev *pdev, int bar, char *name)
+{
+   if (compat_pci_resource_len(pdev, bar) == 0) {
+      return 0;
+   }
+
+   if (compat_pci_resource_flags(pdev, bar) & IORESOURCE_IO) {
+      if (!compat_request_region(compat_pci_resource_start(pdev, bar),
+                                 compat_pci_resource_len(pdev, bar),
+                                 name)) {
+         return -EBUSY;
+      }
+   } else if (compat_pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
+      if (!compat_request_mem_region(compat_pci_resource_start(pdev, bar),
+                                     compat_pci_resource_len(pdev, bar),
+                                     name)) {
+         return -EBUSY;
+      }
+   }
+
+   return 0;
+}
+
+static inline void
+compat_pci_release_region(struct pci_dev *pdev, int bar)
+{
+   if (compat_pci_resource_len(pdev, bar) != 0) {
+      if (compat_pci_resource_flags(pdev, bar) & IORESOURCE_IO) {
+         release_region(compat_pci_resource_start(pdev, bar),
+                        compat_pci_resource_len(pdev, bar));
+      } else if (compat_pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {
+         compat_release_mem_region(compat_pci_resource_start(pdev, bar),
+                                   compat_pci_resource_len(pdev, bar));
+      }
+   }
+}
+#else
+#define compat_pci_request_region(pdev, bar, name)  pci_request_region(pdev, bar, name)
+#define compat_pci_release_region(pdev, bar)        pci_release_region(pdev, bar)
+#endif
+
+/* pci_request_regions appeears in 2.4.3 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)
+static inline int
+compat_pci_request_regions(struct pci_dev *pdev, char *name)
+{
+   int i;
+   
+   for (i = 0; i < 6; i++) {
+      if (compat_pci_request_region(pdev, i, name)) {
+         goto release;
+      }
+   }
+   return 0;
+
+release:
+   while (--i >= 0) {
+      compat_pci_release_region(pdev, i);
+   }
+   return -EBUSY;
+}
+static inline void
+compat_pci_release_regions(struct pci_dev *pdev)
+{
+   int i;
+   
+   for (i = 0; i < 6; i++) {
+      compat_pci_release_region(pdev, i);
+   }
+}
+#else
+#define compat_pci_request_regions(pdev, name) pci_request_regions(pdev, name)
+#define compat_pci_release_regions(pdev)       pci_release_regions(pdev)
+#endif
+
+/* pci_enable_device is available since 2.4.0 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+#define compat_pci_enable_device(pdev) (0)
+#else
+#define compat_pci_enable_device(pdev) pci_enable_device(pdev)
+#endif
+
+
+/* pci_set_master is available since 2.2.0 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 0)
+#define compat_pci_set_master(pdev) (0)
+#else
+#define compat_pci_set_master(pdev) pci_set_master(pdev)
+#endif
+
+
+/* pci_disable_device is available since 2.4.4 */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 4)
+#define compat_pci_disable_device(pdev) do {} while (0)
+#else
+#define compat_pci_disable_device(pdev) pci_disable_device(pdev)
+#endif
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+/*
+ * Devices supported by particular pci driver.  While 2.4+ kernels
+ * can do match on subsystem and class too, we support match on
+ * vendor/device IDs only.
+ */
+struct pci_device_id {
+   unsigned int vendor, device;
+   unsigned long driver_data;
+};
+#define PCI_DEVICE(vend, dev)   .vendor = (vend), .device = (dev)
+
+/* PCI driver */
+struct pci_driver {
+   const char *name;
+   const struct pci_device_id *id_table;
+   int   (*probe)(struct pci_dev* dev, const struct pci_device_id* id);
+   void  (*remove)(struct pci_dev* dev);
+};
+
+
+/*
+ * Note that this is static variable.  Maybe everything below should be in
+ * separate compat_pci.c file, but currently only user of this file is vmxnet,
+ * and vmxnet has only one file, so it is fine.  Also with vmxnet all
+ * functions below are called just once, so difference between 'inline' and
+ * separate compat_pci.c should be very small.
+ */
+
+static struct vmw_pci_driver_instance *pci_driver_instances = NULL;
+
+#ifdef KERNEL_2_1
+#define vmw_pci_device(instance) (instance)->pcidev
+#else
+#define vmw_pci_device(instance) (instance)
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * pci_register_driver --
+ *
+ *      Create driver instances for all matching PCI devices in the box.
+ *
+ * Results:
+ *      Returns 0 for success, negative error value for failure.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static inline int
+pci_register_driver(struct pci_driver *drv)
+{
+   const struct pci_device_id *chipID;
+
+   for (chipID = drv->id_table; chipID->vendor; chipID++) {
+#ifdef KERNEL_2_1
+      struct pci_dev *pdev;
+
+      for (pdev = NULL;
+           (pdev = pci_find_device(chipID->vendor, chipID->device, pdev)) != NULL; ) {
+#else
+      int adapter;
+      unsigned char bus, devfn, irq;
+
+      for (adapter = 0;
+           pcibios_find_device(chipID->vendor, chipID->device, adapter,
+                               &bus, &devfn) == 0;
+           adapter++) {
+#endif
+         struct vmw_pci_driver_instance *pdi;
+         int err;
+
+         pdi = kmalloc(sizeof *pdi, GFP_KERNEL);
+         if (!pdi) {
+            printk(KERN_ERR "Not enough memory.\n");
+            break;
+         }
+         pdi->pcidrv = drv;
+#ifdef KERNEL_2_1
+         pdi->pcidev = pdev;
+#else
+         pdi->bus = bus;
+         pdi->devfn = devfn;
+         if (pci_read_config_byte(pdi, PCI_INTERRUPT_LINE, &irq)) {
+            pdi->irq = -1;
+         } else {
+            pdi->irq = irq;
+         }
+#endif
+         pdi->driver_data = NULL;
+         pdi->next = pci_driver_instances;
+         pci_driver_instances = pdi;
+         err = drv->probe(vmw_pci_device(pdi), chipID);
+         if (err) {
+            pci_driver_instances = pdi->next;
+            kfree(pdi);
+         }
+      }
+   }
+   return 0;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * compat_pci_unregister_driver --
+ *
+ *      Shut down PCI driver - unbind all device instances from driver.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static inline void
+pci_unregister_driver(struct pci_driver *drv)
+{
+   struct vmw_pci_driver_instance **ppdi;
+
+   ppdi = &pci_driver_instances;
+   while (1) {
+      struct vmw_pci_driver_instance *pdi = *ppdi;
+
+      if (!pdi) {
+         break;
+      }
+      if (pdi->pcidrv == drv) {
+         drv->remove(vmw_pci_device(pdi));
+         *ppdi = pdi->next;
+         kfree(pdi);
+      } else {
+         ppdi = &pdi->next;
+      }
+   }
+}
+#else
+/* provide PCI_DEVICE for early 2.4.x kernels */
+#ifndef PCI_DEVICE
+#define PCI_DEVICE(vend, dev)   .vendor = (vend), .device = (dev), \
+                                .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
+#endif
+#endif
+
+
+/* provide dummy MODULE_DEVICE_TABLE for 2.0/2.2 */
+#ifndef MODULE_DEVICE_TABLE
+#define MODULE_DEVICE_TABLE(bus, devices)
+#endif
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * pci_set_drvdata --
+ *
+ *      Set per-device driver's private data.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * pci_get_drvdata --
+ *
+ *      Retrieve per-device driver's private data.
+ *
+ * Results:
+ *      per-device driver's data previously set by pci_set_drvdata,
+ *      or NULL on failure.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+#ifndef KERNEL_2_1
+/* 2.0.x is simple, we have driver_data directly in pci_dev */
+#define pci_set_drvdata(pdev, data) do { (pdev)->driver_data = (data); } while (0)
+#define pci_get_drvdata(pdev)       (pdev)->driver_data
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
+/* 2.2.x is trickier, we have to find driver instance first */
+static inline void
+pci_set_drvdata(struct pci_dev *pdev, void* data)
+{
+   struct vmw_pci_driver_instance *pdi;
+
+   for (pdi = pci_driver_instances; pdi; pdi = pdi->next) {
+      if (pdi->pcidev == pdev) {
+         pdi->driver_data = data;
+         return;
+      }
+   }
+   printk(KERN_ERR "pci_set_drvdata issued for unknown device %p\n", pdev);
+}
+
+static inline void *
+pci_get_drvdata(struct pci_dev *pdev)
+{
+   struct vmw_pci_driver_instance *pdi;
+
+   for (pdi = pci_driver_instances; pdi; pdi = pdi->next) {
+      if (pdi->pcidev == pdev) {
+         return pdi->driver_data;
+      }
+   }
+   printk(KERN_ERR "pci_get_drvdata issued for unknown device %p\n", pdev);
+   return NULL;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48)
+#   define PCI_DMA_BIDIRECTIONAL        0
+#   define PCI_DMA_TODEVICE             1
+#   define PCI_DMA_FROMDEVICE           2
+#   define PCI_DMA_NONE                 3
+#endif
+
+/*
+ * Power Management related compat wrappers.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
+#   define compat_pci_save_state(pdev)      pci_save_state((pdev), NULL)
+#   define compat_pci_restore_state(pdev)   pci_restore_state((pdev), NULL)
+#else
+#   define compat_pci_save_state(pdev)      pci_save_state((pdev))
+#   define compat_pci_restore_state(pdev)   pci_restore_state((pdev))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
+#   define pm_message_t          u32
+#   define compat_pci_choose_state(pdev, state)  (state)
+#   define PCI_D0               0
+#   define PCI_D3hot            3
+#else
+#   define compat_pci_choose_state(pdev, state)  pci_choose_state((pdev), (state))
+#endif
+
+/* 2.6.14 changed the PCI shutdown callback */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
+#   define COMPAT_PCI_SHUTDOWN(func)               .driver = { .shutdown = (func), }
+#   define COMPAT_PCI_DECLARE_SHUTDOWN(func, var)  (func)(struct device *(var))
+#   define COMPAT_PCI_TO_DEV(dev)                  (to_pci_dev(dev))
+#else
+#   define COMPAT_PCI_SHUTDOWN(func)               .shutdown = (func)
+#   define COMPAT_PCI_DECLARE_SHUTDOWN(func, var)  (func)(struct pci_dev *(var))
+#   define COMPAT_PCI_TO_DEV(dev)                  (dev)
+#endif
+
+
+#endif /* __COMPAT_PCI_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/compat_scsi.h b/open-vm-tools/modules/linux/pvscsi/compat_scsi.h
new file mode 100644 (file)
index 0000000..e0a4ba7
--- /dev/null
@@ -0,0 +1,38 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_SCSI_H__
+#   define __COMPAT_SCSI_H__
+
+
+/* The scsi_bufflen() API appeared somewhere in time --hpreg */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
+#   define scsi_bufflen(cmd) ((cmd)->request_bufflen)
+#   define scsi_sg_count(cmd) ((cmd)->use_sg)
+#   define scsi_sglist(cmd) ((struct scatterlist *)(cmd)->request_buffer)
+#   define scsi_set_resid(cmd, _resid) ((cmd)->resid = _resid)
+#endif
+
+/*
+ * Using scsi_sglist to access the request buffer looks strange
+ * so instead we define this macro.  What happened is later kernel
+ * put all SCSI data in sglists, since it simplifies passing buffers
+ */
+#define scsi_request_buffer(cmd) scsi_sglist(cmd)
+
+#endif /* __COMPAT_SCSI_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/compat_version.h b/open-vm-tools/modules/linux/pvscsi/compat_version.h
new file mode 100644 (file)
index 0000000..baf9634
--- /dev/null
@@ -0,0 +1,121 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef __COMPAT_VERSION_H__
+#   define __COMPAT_VERSION_H__
+
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMNIXMOD
+#define INCLUDE_ALLOW_DISTRIBUTE
+#include "includeCheck.h"
+
+
+#ifndef __linux__
+#   error "linux-version.h"
+#endif
+
+
+#include <linux/version.h>
+
+/* Appeared in 2.1.90 --hpreg */
+#ifndef KERNEL_VERSION
+#   define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+
+/*
+ * Distinguish relevant classes of Linux kernels.
+ *
+ * The convention is that version X defines all
+ * the KERNEL_Y symbols where Y <= X.
+ *
+ * XXX Do not add more definitions here. This way of doing things does not
+ *     scale, and we are going to phase it out soon --hpreg
+ */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 0)
+#   define KERNEL_2_1
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 0)
+#   define KERNEL_2_2
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 1)
+#   define KERNEL_2_3_1
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 15)
+/*   new networking */
+#   define KERNEL_2_3_15
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
+/*  new procfs */
+#   define KERNEL_2_3_25
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 29)
+/*  even newer procfs */
+#   define KERNEL_2_3_29
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 43)
+/*  softnet changes */
+#   define KERNEL_2_3_43
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 47)
+/*  more softnet changes */
+#   define KERNEL_2_3_47
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 99)
+/*  name in netdevice struct is array and not pointer */
+#   define KERNEL_2_3_99
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+/*  New 'owner' member at the beginning of struct file_operations */
+#      define KERNEL_2_4_0
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8)
+/*  New netif_rx_ni() --hpreg */
+#   define KERNEL_2_4_8
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
+/*  New vmap() */
+#   define KERNEL_2_4_22
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 2)
+/*  New kdev_t, major()/minor() API --hpreg */
+#   define KERNEL_2_5_2
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5)
+/*  New sk_alloc(), pte_offset_map()/pte_unmap() --hpreg */
+#   define KERNEL_2_5_5
+#endif
+
+
+#endif /* __COMPAT_VERSION_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/driver-config.h b/open-vm-tools/modules/linux/pvscsi/driver-config.h
new file mode 100644 (file)
index 0000000..95f27de
--- /dev/null
@@ -0,0 +1,78 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * Sets the proper defines from the Linux header files
+ *
+ * This file must be included before the inclusion of any kernel header file,
+ * with the exception of linux/autoconf.h and linux/version.h --hpreg
+ */
+
+#ifndef __VMX_CONFIG_H__
+#define __VMX_CONFIG_H__
+
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMNIXMOD
+#include "includeCheck.h"
+
+#include <linux/autoconf.h>
+#include "compat_version.h"
+
+/*
+ * We rely on Kernel Module support.  Check here.
+ */
+#ifndef CONFIG_MODULES
+#   error "No Module support in this kernel.  Please configure with CONFIG_MODULES"
+#endif
+
+/*
+ * 2.2 kernels still use __SMP__ (derived from CONFIG_SMP
+ * in the main Makefile), so we do it here.
+ */
+
+#ifdef CONFIG_SMP
+#   define __SMP__ 1
+#endif
+
+#if defined(CONFIG_MODVERSIONS) && defined(KERNEL_2_1)
+#   if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
+/*
+ * MODVERSIONS might be already defined when using kernel's Makefiles.
+ */
+#      ifndef MODVERSIONS
+#         define MODVERSIONS
+#      endif
+#      include <linux/modversions.h>
+#   endif
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+/*
+ * Force the uintptr_t definition to come from linux/types.h instead of vm_basic_types.h.
+ */
+#   include <linux/types.h>
+#   define _STDINT_H 1
+#endif
+
+#ifndef __KERNEL__
+#   define __KERNEL__
+#endif
+
+#endif
diff --git a/open-vm-tools/modules/linux/pvscsi/includeCheck.h b/open-vm-tools/modules/linux/pvscsi/includeCheck.h
new file mode 100644 (file)
index 0000000..b3d5bb3
--- /dev/null
@@ -0,0 +1,132 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * includeCheck.h --
+ *
+ *     Restrict include file use.
+ *
+ * In every .h file, define one or more of these
+ *
+ *     INCLUDE_ALLOW_VMX 
+ *     INCLUDE_ALLOW_USERLEVEL 
+ *     INCLUDE_ALLOW_VMMEXT
+ *     INCLUDE_ALLOW_VMCORE
+ *     INCLUDE_ALLOW_MODULE
+ *      INCLUDE_ALLOW_VMNIXMOD 
+ *     INCLUDE_ALLOW_VMKERNEL 
+ *     INCLUDE_ALLOW_DISTRIBUTE
+ *     INCLUDE_ALLOW_VMK_MODULE
+ *      INCLUDE_ALLOW_VMKDRIVERS
+ *      INCLUDE_ALLOW_VMIROM
+ *
+ * Then include this file.
+ *
+ * Any file that has INCLUDE_ALLOW_DISTRIBUTE defined will potentially
+ * be distributed in source form along with GPLed code.  Ensure
+ * that this is acceptable.
+ */
+
+
+/*
+ * Declare a VMCORE-only variable to help classify object
+ * files.  The variable goes in the common block and does
+ * not create multiple definition link-time conflicts.
+ */
+
+#if defined VMCORE && defined VMX86_DEVEL && defined VMX86_DEBUG && \
+    defined linux && !defined MODULE && \
+    !defined COMPILED_WITH_VMCORE
+#define COMPILED_WITH_VMCORE compiled_with_vmcore
+#ifdef ASM
+        .comm   compiled_with_vmcore, 0
+#else
+        asm(".comm compiled_with_vmcore, 0");
+#endif /* ASM */
+#endif
+
+
+#if defined VMCORE && \
+    !(defined VMX86_VMX || defined VMM || \
+      defined MONITOR_APP || defined VMMON)
+#error "Makefile problem: VMCORE without VMX86_VMX or \
+        VMM or MONITOR_APP or MODULE."
+#endif
+
+#if defined VMCORE && !defined INCLUDE_ALLOW_VMCORE
+#error "The surrounding include file is not allowed in vmcore."
+#endif
+#undef INCLUDE_ALLOW_VMCORE
+
+#if defined VMX86_VMX && !defined VMCORE && \
+    !(defined INCLUDE_ALLOW_VMX || defined INCLUDE_ALLOW_USERLEVEL)
+#error "The surrounding include file is not allowed in the VMX."
+#endif
+#undef INCLUDE_ALLOW_VMX
+
+#if defined USERLEVEL && !defined VMX86_VMX && !defined VMCORE && \
+    !defined INCLUDE_ALLOW_USERLEVEL
+#error "The surrounding include file is not allowed at userlevel."
+#endif
+#undef INCLUDE_ALLOW_USERLEVEL
+
+#if defined VMM && !defined VMCORE && \
+    !defined INCLUDE_ALLOW_VMMEXT
+#error "The surrounding include file is not allowed in the monitor."
+#endif
+#undef INCLUDE_ALLOW_VMMEXT
+
+#if defined MODULE && !defined VMKERNEL_MODULE && !defined VMNIXMOD && \
+    !defined VMMON && !defined INCLUDE_ALLOW_MODULE
+#error "The surrounding include file is not allowed in driver modules."
+#endif
+#undef INCLUDE_ALLOW_MODULE
+
+#if defined VMMON && !defined INCLUDE_ALLOW_VMMON
+#error "The surrounding include file is not allowed in vmmon."
+#endif
+#undef INCLUDE_ALLOW_VMMON
+
+#if defined VMKERNEL && !defined INCLUDE_ALLOW_VMKERNEL
+#error "The surrounding include file is not allowed in the vmkernel."
+#endif
+#undef INCLUDE_ALLOW_VMKERNEL
+
+#if defined GPLED_CODE && !defined INCLUDE_ALLOW_DISTRIBUTE
+#error "The surrounding include file is not allowed in GPL code."
+#endif
+#undef INCLUDE_ALLOW_DISTRIBUTE
+
+#if defined VMKERNEL_MODULE && !defined VMKERNEL && \
+    !defined INCLUDE_ALLOW_VMK_MODULE && !defined INCLUDE_ALLOW_VMKDRIVERS
+#error "The surrounding include file is not allowed in vmkernel modules."
+#endif
+#undef INCLUDE_ALLOW_VMK_MODULE
+#undef INCLUDE_ALLOW_VMKDRIVERS
+
+#if defined VMNIXMOD && !defined INCLUDE_ALLOW_VMNIXMOD
+#ifndef VMNIXMOD_VM
+#error "The surrounding include file is not allowed in vmnixmod."
+#endif
+#endif
+#undef INCLUDE_ALLOW_VMNIXMOD
+
+#if defined VMIROM && ! defined INCLUDE_ALLOW_VMIROM
+#error "The surrounding include file is not allowed in vmirom."
+#endif
+#undef INCLUDE_ALLOW_VMIROM
diff --git a/open-vm-tools/modules/linux/pvscsi/pvscsi.c b/open-vm-tools/modules/linux/pvscsi/pvscsi.c
new file mode 100644 (file)
index 0000000..8411a4d
--- /dev/null
@@ -0,0 +1,1301 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * pvscsi.c --
+ *
+ *    This is a driver for the VMware PVSCSI paravirt SCSI device.
+ *    The PVSCSI device is a SCSI adapter for virtual disks which
+ *    is implemented as a PCIe device.
+ */
+
+#include "driver-config.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "compat_scsi.h"
+#include "compat_pci.h"
+#include "compat_interrupt.h"
+
+#include "pvscsi_defs.h"
+#include "pvscsi_version.h"
+#include "scsi_defs.h"
+#include "vm_device_version.h"
+#include "vm_assert.h"
+
+/**************************************************************
+ *
+ *   VMWARE PVSCSI Linux interaction
+ *
+ *   All Linux specific driver routines and operations should
+ *   go here.
+ *
+ **************************************************************/
+
+#define PVSCSI_LINUX_DRIVER_DESC "VMware PVSCSI driver"
+
+/* Module definitions */
+MODULE_DESCRIPTION(PVSCSI_LINUX_DRIVER_DESC);
+MODULE_AUTHOR("VMware, Inc.");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(PVSCSI_DRIVER_VERSION_STRING);
+
+#define PVSCSI_DRIVER_VECTORS_USED     1
+#define DEFAULT_PAGES_PER_RING         8
+#define PVSCSI_LINUX_DEFAULT_QUEUE_DEPTH        64
+
+/* MSI has horrible performance in < 2.6.13 due to needless mask frotzing */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
+#define DISABLE_MSI    0
+#else
+#define DISABLE_MSI    1
+#endif
+
+/* MSI-X has horrible performance in < 2.6.19 due to needless mask frobbing */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
+#define DISABLE_MSIX   0
+#else
+#define DISABLE_MSIX   1
+#endif
+
+/* Command line parameters */
+static int pvscsi_debug_level;
+module_param_call(pvscsi_debug_level, param_set_int, param_get_int,
+                 &pvscsi_debug_level, 0600);
+MODULE_PARM_DESC(pvscsi_debug_level, "Debug logging level - (default=0)");
+
+static int pvscsi_ring_pages = DEFAULT_PAGES_PER_RING;
+module_param_call(pvscsi_ring_pages, param_set_int, param_get_int,
+                 &pvscsi_ring_pages, 0600);
+MODULE_PARM_DESC(pvscsi_ring_pages, "Pages per ring - (default="
+                                   XSTR(DEFAULT_PAGES_PER_RING) ")");
+
+static int pvscsi_cmd_per_lun = PVSCSI_LINUX_DEFAULT_QUEUE_DEPTH;
+module_param_call(pvscsi_cmd_per_lun, param_set_int, param_get_int,
+                 &pvscsi_cmd_per_lun, 0600);
+MODULE_PARM_DESC(pvscsi_cmd_per_lun, "Maximum commands per lun - (default="
+                                    XSTR(PVSCSI_MAX_REQ_QUEUE_DEPTH) ")");
+
+static int pvscsi_disable_msi = DISABLE_MSI;
+module_param_call(pvscsi_disable_msi, param_set_int, param_get_int,
+                 &pvscsi_disable_msi, 0600);
+MODULE_PARM_DESC(pvscsi_disable_msi, "Disable MSI use in driver - (default="
+                                    XSTR(DISABLE_MSI) ")");
+
+static int pvscsi_disable_msix = DISABLE_MSIX;
+module_param_call(pvscsi_disable_msix, param_set_int, param_get_int,
+                 &pvscsi_disable_msix, 0600);
+MODULE_PARM_DESC(pvscsi_disable_msix, "Disable MSI-X use in driver - (default="
+                                     XSTR(DISABLE_MSIX) ")");
+
+static int __init pvscsi_init(void);
+static int __devinit pvscsi_probe(struct pci_dev *pdev,
+                                 const struct pci_device_id *id);
+static const char *pvscsi_info(struct Scsi_Host *host);
+static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
+static int pvscsi_abort(struct scsi_cmnd *cmd);
+static int pvscsi_host_reset(struct scsi_cmnd *cmd);
+static int pvscsi_bus_reset(struct scsi_cmnd *cmd);
+static int pvscsi_device_reset(struct scsi_cmnd *cmd);
+static irqreturn_t pvscsi_isr COMPAT_IRQ_HANDLER_ARGS(irq, devp);
+static void pvscsi_remove(struct pci_dev *pdev);
+static void COMPAT_PCI_DECLARE_SHUTDOWN(pvscsi_shutdown, dev);
+static void __exit pvscsi_exit(void);
+
+static struct pci_device_id pvscsi_pci_tbl[] = {
+       {PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_PVSCSI,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       {0,}
+};
+MODULE_DEVICE_TABLE(pci, pvscsi_pci_tbl);
+
+static struct pci_driver pvscsi_pci_driver = {
+       .name           = "pvscsi",
+       .id_table       = pvscsi_pci_tbl,
+       .probe          = pvscsi_probe,
+       .remove         = __devexit_p(pvscsi_remove),
+       COMPAT_PCI_SHUTDOWN(pvscsi_shutdown)
+};
+
+#ifdef CONFIG_PCI_MSI
+static const struct msix_entry base_entries[PVSCSI_DRIVER_VECTORS_USED] = {
+       { 0, PVSCSI_VECTOR_COMPLETION },
+};
+#endif
+
+static struct scsi_host_template pvscsi_template = {
+       .module                         = THIS_MODULE,
+       .name                           = "VMware PVSCSI Host Adapter",
+       .proc_name                      = "pvscsi",
+       .info                           = pvscsi_info,
+       .queuecommand                   = pvscsi_queue,
+       .this_id                        = -1,
+       .sg_tablesize                   = PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT,
+       .dma_boundary                   = UINT_MAX,
+       .max_sectors                    = 0xffff,
+       .use_clustering                 = ENABLE_CLUSTERING,
+       .eh_abort_handler               = pvscsi_abort,
+       .eh_device_reset_handler        = pvscsi_device_reset,
+       .eh_bus_reset_handler           = pvscsi_bus_reset,
+       .eh_host_reset_handler          = pvscsi_host_reset,
+};
+
+struct PVSCSISGList {
+   PVSCSISGElement sge[PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT];
+};
+
+/* Private per-request struct */
+struct pvscsi_ctx {
+       /*
+        * We use cmd->scsi_done to store the completion callback.
+        * The index of the context in cmd_map serves as the context ID for a
+        * 1-to-1 mapping completions back to requests.
+        */
+       struct scsi_cmnd        *cmd;
+       struct PVSCSISGList     *sgl;
+       struct list_head        list;
+};
+
+/* Private per-adapter struct */
+struct pvscsi_adapter {
+       unsigned long           base;
+       unsigned long           iomap;
+       unsigned int            irq;
+       char                    rev;
+       char                    use_msi;
+       char                    use_msix;
+       char                    log;
+
+       spinlock_t              hw_lock;
+       RingReqDesc             *req_ring;
+       unsigned                req_pages;
+       unsigned                req_depth;
+
+       RingCmpDesc             *cmp_ring;
+       unsigned                cmp_pages;
+       unsigned                cmp_depth;
+
+       RingsState              *ring_state;
+
+       struct pci_dev          *dev;
+       struct Scsi_Host        *host;
+
+       struct list_head        cmd_pool;
+       struct pvscsi_ctx       *cmd_map;
+       unsigned                last_map;
+
+       int                     irq_vectors[PVSCSI_DRIVER_VECTORS_USED];
+};
+
+#define HOST_ADAPTER(host) ((struct pvscsi_adapter *)(host)->hostdata)
+
+/* Low-level adapter function prototypes */
+static inline u32 pvscsi_read_intr_status(const struct pvscsi_adapter *adapter);
+static inline void pvscsi_write_intr_status(const struct pvscsi_adapter *adapter,
+                                           u32 val);
+static inline void pvscsi_write_intr_mask(const struct pvscsi_adapter *adapter,
+                                         u32 val);
+static void pvscsi_abort_cmd(const struct pvscsi_adapter *adapter,
+                            const struct pvscsi_ctx *ctx);
+static void pvscsi_kick_io(const struct pvscsi_adapter *adapter, unsigned char op);
+static void pvscsi_process_request_ring(const struct pvscsi_adapter *adapter);
+static void ll_adapter_reset(const struct pvscsi_adapter *adapter);
+static void ll_bus_reset(const struct pvscsi_adapter *adapter);
+static void ll_device_reset(const struct pvscsi_adapter *adapter, u32 target);
+static void pvscsi_setup_rings(struct pvscsi_adapter *adapter);
+static void pvscsi_process_completion_ring(struct pvscsi_adapter *adapter);
+
+static inline int pvscsi_queue_ring(struct pvscsi_adapter *adapter,
+                                   struct pvscsi_ctx *ctx,
+                                   struct scsi_cmnd *cmd);
+static inline void pvscsi_complete_request(struct pvscsi_adapter *adapter,
+                                          const RingCmpDesc *e);
+
+#define LOG(level, fmt, args...)                               \
+do {                                                           \
+       if (pvscsi_debug_level > level)                         \
+               printk(KERN_DEBUG "pvscsi: " fmt, args);        \
+} while (0)
+
+module_init(pvscsi_init);
+static int __init pvscsi_init(void)
+{
+       printk(KERN_DEBUG "%s - version %s\n",
+              PVSCSI_LINUX_DRIVER_DESC, PVSCSI_DRIVER_VERSION_STRING);
+       return pci_register_driver(&pvscsi_pci_driver);
+}
+
+module_exit(pvscsi_exit);
+static void __exit pvscsi_exit(void)
+{
+       pci_unregister_driver(&pvscsi_pci_driver);
+}
+
+static inline void pvscsi_free_sgls(struct pvscsi_adapter *adapter)
+{
+       unsigned i, max;
+       struct pvscsi_ctx *ctx = adapter->cmd_map;
+
+       max = adapter->req_depth;
+       for (i = 0; i < max; ++i, ++ctx)
+               kfree(ctx->sgl);
+}
+
+static inline int pvscsi_setup_msix(struct pvscsi_adapter *adapter)
+{
+#ifdef CONFIG_PCI_MSI
+       int ret;
+       unsigned i;
+       struct msix_entry entries[PVSCSI_DRIVER_VECTORS_USED];
+
+       memcpy(entries, base_entries, sizeof entries);
+       ret = pci_enable_msix(adapter->dev, entries, ARRAY_SIZE(entries));
+       if (ret != 0)
+               return ret;
+
+       for (i = 0; i < PVSCSI_DRIVER_VECTORS_USED; i++)
+               adapter->irq_vectors[i] = entries[i].vector;
+
+       return 0;
+#else
+       return -1;
+#endif
+}
+
+static inline void pvscsi_shutdown_msi(struct pvscsi_adapter *adapter)
+{
+#ifdef CONFIG_PCI_MSI
+
+       if (adapter->use_msi)
+               pci_disable_msi(adapter->dev);
+
+       if (adapter->use_msix) {
+#if 0
+               /* For when multiple vectors are supported */
+               unsigned i;
+               for (i = 0; i < PVSCSI_DRIVER_VECTORS_USED; i++)
+                       if (adapter->irq_vectors[i] != -1)
+                               free_irq(adapter->irq_vectors[i], adapter);
+#endif
+               pci_disable_msix(adapter->dev);
+       }
+#endif
+}
+
+static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
+{
+       if (adapter->irq)
+               free_irq(adapter->irq, adapter);
+
+       pvscsi_shutdown_msi(adapter);
+
+       if (adapter->iomap)
+               iounmap((void *)adapter->iomap);
+
+       pci_release_regions(adapter->dev);
+
+       if (adapter->cmd_map) {
+               pvscsi_free_sgls(adapter);
+               kfree(adapter->cmd_map);
+       }
+
+       kfree(adapter->ring_state);
+
+       if (adapter->req_ring)
+               vfree(adapter->req_ring);
+
+       if (adapter->cmp_ring)
+               vfree(adapter->cmp_ring);
+}
+
+static int __devinit pvscsi_allocate_rings(struct pvscsi_adapter *adapter)
+{
+       adapter->ring_state = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!adapter->ring_state)
+               return -ENOMEM;
+
+       adapter->req_pages = MIN(PVSCSI_MAX_NUM_PAGES_REQ_RING,
+                                pvscsi_ring_pages);
+       adapter->req_depth = adapter->req_pages *
+                            PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
+       adapter->req_ring = vmalloc(adapter->req_pages * PAGE_SIZE);
+       if (!adapter->req_ring)
+               return -ENOMEM;
+
+       adapter->cmp_pages = MIN(PVSCSI_MAX_NUM_PAGES_CMP_RING,
+                                pvscsi_ring_pages);
+       adapter->cmp_depth = adapter->cmp_pages *
+                            PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE;
+       adapter->cmp_ring = vmalloc(adapter->cmp_pages * PAGE_SIZE);
+       if (!adapter->cmp_ring)
+               return -ENOMEM;
+
+       return 0;
+}
+
+/*
+ * Allocate scatter gather lists.
+ *
+ * These are statically allocated.  Trying to be clever was not worth it.
+ *
+ * Dynamic allocation can fail, and we can't go deeep into the memory
+ * allocator, since we're a SCSI driver, and trying too hard to allocate
+ * memory might generate disk I/O.  We also don't want to fail disk I/O
+ * in that case because we can't get an allocation - the I/O could be
+ * trying to swap out data to free memory.  Since that is pathological,
+ * just use a statically allocated scatter list.
+ *
+ */
+static int __devinit pvscsi_allocate_sg(struct pvscsi_adapter *adapter)
+{
+       unsigned i, max;
+       struct pvscsi_ctx *ctx = adapter->cmd_map;
+
+       max = adapter->req_depth;
+       ASSERT_ON_COMPILE(sizeof(struct PVSCSISGList) <= PAGE_SIZE);
+       for (i = 0; i < max; ++i, ++ctx) {
+               ctx->sgl = kmalloc(PAGE_SIZE, GFP_KERNEL);
+               BUG_ON((long)ctx->sgl & ~PAGE_MASK);
+               if (!ctx->sgl) {
+                       for (; i >= 0; --i, --ctx) {
+                               kfree(ctx->sgl);
+                               ctx->sgl = NULL;
+                       }
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+static int __devinit
+pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       int error = -ENODEV;
+       u8 pci_bus, pci_dev_func, rev;
+       unsigned long base, remap, i;
+       struct Scsi_Host *host;
+       int irq;
+       struct pvscsi_adapter *adapter;
+
+       if (pci_enable_device(pdev))
+               return error;
+
+       if (pdev->vendor != PCI_VENDOR_ID_VMWARE)
+               goto out_disable_device;
+
+       pci_bus = pdev->bus->number;
+       pci_dev_func = pdev->devfn;
+       pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
+
+       if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) ||
+           pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) {
+               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) &&
+                   pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+                       printk(KERN_ERR "pvscsi: unable to set usable DMA mask\n");
+                       goto out_disable_device;
+               }
+       }
+
+       printk(KERN_NOTICE "pvscsi: found VMware PVSCSI rev %d on "
+                          "bus %d:slot %d:func %d\n", rev, pci_bus,
+               PCI_SLOT(pci_dev_func), PCI_FUNC(pci_dev_func));
+
+       pvscsi_template.can_queue =
+               MIN(PVSCSI_MAX_NUM_PAGES_REQ_RING, pvscsi_ring_pages) *
+               PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE;
+       pvscsi_template.cmd_per_lun =
+               MIN(pvscsi_template.can_queue, pvscsi_cmd_per_lun);
+       host = scsi_host_alloc(&pvscsi_template, sizeof(struct pvscsi_adapter));
+       if (!host) {
+               printk(KERN_ERR "pvscsi: failed to allocate host\n");
+               goto out_disable_device;
+       }
+
+       adapter = HOST_ADAPTER(host);
+       memset(adapter, 0, sizeof(*adapter));
+       for (i = 0; i < PVSCSI_DRIVER_VECTORS_USED; i++)
+               adapter->irq_vectors[i] = -1;
+       adapter->dev = pdev;
+       adapter->host = host;
+       adapter->rev = rev;
+
+       spin_lock_init(&adapter->hw_lock);
+
+       host->max_channel = 0;
+       host->max_id = 16;
+       host->max_lun = 1;
+
+       if (pci_request_regions(pdev, "pvscsi")) {
+               printk(KERN_ERR "pvscsi: pci memory selection failed\n");
+               goto out_free_host;
+       }
+
+       /* Find the BARs for memory mapped I/O */
+       base = 0;
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               if ((pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO))
+                       continue;
+
+               /* Skip non-kick memory mapped space */
+               if (pci_resource_len(pdev, i) < PVSCSI_MEM_SPACE_NUM_PAGES * PAGE_SIZE)
+                       continue;
+
+               base = pci_resource_start(pdev, i);
+               break;
+       }
+
+       if (!base) {
+               printk(KERN_ERR "pvscsi: adapter has no suitable MMIO region\n");
+               goto out_release_resources;
+       }
+       remap = (unsigned long)ioremap(base, PVSCSI_MEM_SPACE_SIZE);
+       if (!remap) {
+               printk(KERN_ERR "pvscsi: can't ioremap 0x%lx\n", base);
+               goto out_release_resources;
+       }
+       adapter->iomap = remap;
+
+       pci_set_master(pdev);
+       pci_set_drvdata(pdev, host);
+
+       ll_adapter_reset(adapter);
+       error = pvscsi_allocate_rings(adapter);
+       if (error) {
+               printk(KERN_ERR "pvscsi: unable to allocate ring memory\n");
+               goto out_release_resources;
+       }
+
+       /*
+        * Setup the rings; from this point on we should reset
+        * the adapter if anything goes wrong.
+        */
+       pvscsi_setup_rings(adapter);
+
+       adapter->cmd_map = kmalloc(adapter->req_depth *
+                                  sizeof(struct pvscsi_ctx), GFP_KERNEL);
+       if (!adapter->cmd_map) {
+               printk(KERN_ERR "pvscsi: failed to allocate memory.\n");
+               goto out_reset_adapter;
+       }
+       memset(adapter->cmd_map, 0, adapter->req_depth *
+                                   sizeof(struct pvscsi_ctx));
+
+       INIT_LIST_HEAD(&adapter->cmd_pool);
+       for (i = 0; i < adapter->req_depth; i++) {
+               struct pvscsi_ctx *ctx = adapter->cmd_map + i;
+               list_add(&ctx->list, &adapter->cmd_pool);
+       }
+
+       /* Now allocate a DMA-able cache for SG lists */
+       if (pvscsi_allocate_sg(adapter) != 0) {
+               printk(KERN_WARNING "pvscsi: unable to allocate SG cache\n");
+               printk(KERN_WARNING "pvscsi: disabling scatter/gather.\n");
+               host->sg_tablesize = 1;
+       }
+
+       /* Setup MSI if possible */
+#ifdef CONFIG_PCI_MSI
+       if (!pvscsi_disable_msix && pvscsi_setup_msix(adapter) == 0) {
+               printk(KERN_INFO "pvscsi: enabled MSI-X\n");
+               adapter->use_msix = 1;
+       } else if (!pvscsi_disable_msi && pci_enable_msi(pdev) == 0) {
+               printk(KERN_INFO "pvscsi: enabled MSI\n");
+               adapter->use_msi = 1;
+       } else
+               printk(KERN_INFO "pvscsi: using normal PCI interrupts\n");
+#else
+       printk(KERN_INFO "pvscsi: this kernel does not support MSI, consider enabling it\n");
+#endif
+
+       /* Now get an IRQ. For MSI-X, we only use one vector currently, vector zero */
+       ASSERT_ON_COMPILE(PVSCSI_DRIVER_VECTORS_USED == 1);
+       irq = adapter->use_msix ? adapter->irq_vectors[0] : pdev->irq;
+       if (request_irq(irq, pvscsi_isr, COMPAT_IRQF_SHARED, "pvscsi", adapter)) {
+               printk(KERN_ERR "pvscsi: unable to request IRQ %d\n", irq);
+               goto out_reset_adapter;
+       }
+       adapter->irq = irq;
+
+       error = scsi_add_host(host, &pdev->dev);
+       if (error) {
+               printk(KERN_ERR "pvscsi: scsi_add_host failed: %d\n", error);
+               goto out_reset_adapter;
+       }
+
+       /* Enable device interrupts */
+       pvscsi_write_intr_mask(adapter, PVSCSI_INTR_ALL);
+
+       scsi_scan_host(host);
+
+       return 0;
+
+out_reset_adapter:
+       ll_adapter_reset(adapter);
+out_release_resources:
+       pvscsi_release_resources(adapter);
+out_free_host:
+       scsi_host_put(host);
+out_disable_device:
+       pci_set_drvdata(pdev, NULL);
+       pci_disable_device(pdev);
+
+       return error;
+}
+
+static const char *pvscsi_info(struct Scsi_Host *host)
+{
+       static char buf[512];
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+
+       sprintf(buf, "VMware PVSCSI storage adapter rev %c, %u reqs (%u pages), %u cmps (%u pages), cmd_per_lun=%u",
+               adapter->rev + 'A' - 1,
+               adapter->req_depth, adapter->req_pages,
+               adapter->cmp_depth, adapter->cmp_pages,
+               pvscsi_template.cmd_per_lun);
+       return buf;
+}
+
+static struct pvscsi_ctx *
+pvscsi_find_context(const struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
+{
+       struct pvscsi_ctx *ctx, *end;
+
+       end = &adapter->cmd_map[adapter->req_depth];
+       for (ctx = adapter->cmd_map; ctx < end; ctx++)
+               if (ctx->cmd == cmd)
+                       return ctx;
+
+       return NULL;
+}
+
+static struct pvscsi_ctx *
+pvscsi_allocate_context(struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
+{
+       struct pvscsi_ctx *ctx;
+
+       if (list_empty(&adapter->cmd_pool))
+               return NULL;
+
+       ctx = list_entry(adapter->cmd_pool.next, struct pvscsi_ctx, list);
+       ctx->cmd = cmd;
+       list_del(&ctx->list);
+
+       return ctx;
+}
+
+static inline struct scsi_cmnd *
+pvscsi_free_context(struct pvscsi_adapter *adapter, struct pvscsi_ctx *ctx)
+{
+       struct scsi_cmnd *cmd;
+
+       cmd = ctx->cmd;
+       ctx->cmd = NULL;
+       list_add(&ctx->list, &adapter->cmd_pool);
+
+       return cmd;
+}
+
+/*
+ * Map a pvscsi_ctx struct to a context ID field value; we map to a simple
+ * non-zero integer.
+ */
+static inline u64
+pvscsi_map_context(const struct pvscsi_adapter *adapter, const struct pvscsi_ctx *ctx)
+{
+       return (ctx - adapter->cmd_map) + 1;
+}
+
+static inline struct pvscsi_ctx *
+pvscsi_get_context(const struct pvscsi_adapter *adapter, u64 context)
+{
+       return &adapter->cmd_map[context - 1];
+}
+
+static int pvscsi_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+       struct pvscsi_ctx *ctx;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+
+       ctx = pvscsi_allocate_context(adapter, cmd);
+       if (!ctx || pvscsi_queue_ring(adapter, ctx, cmd) != 0) {
+               if (ctx)
+                       pvscsi_free_context(adapter, ctx);
+               spin_unlock_irqrestore(&adapter->hw_lock, flags);
+               return SCSI_MLQUEUE_HOST_BUSY;
+       }
+
+       cmd->scsi_done = done;
+
+       LOG(3, "queued cmd %p, ctx %p, op=%x\n", cmd, ctx, cmd->cmnd[0]);
+
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+       pvscsi_kick_io(adapter, cmd->cmnd[0]);
+
+       return 0;
+}
+
+static int pvscsi_abort(struct scsi_cmnd *cmd)
+{
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(cmd->device->host);
+       struct pvscsi_ctx *ctx;
+       unsigned long flags;
+
+       printk(KERN_DEBUG "pvscsi: attempting task abort on %p, %p\n",
+               adapter, cmd);
+
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+
+       /*
+        * Poll the completion ring first - we might be trying to abort
+        * a command that is waiting to be dispatched in the completion ring.
+        */
+       pvscsi_process_completion_ring(adapter);
+
+       /*
+        * If there is no context for the command, it either already succeeded
+        * or else was never properly issued.  Not our problem.
+        */
+       ctx = pvscsi_find_context(adapter, cmd);
+       if (!ctx) {
+               LOG(1, "Failed to abort cmd %p\n", cmd);
+               goto out;
+       }
+
+       pvscsi_abort_cmd(adapter, ctx);
+
+       pvscsi_process_completion_ring(adapter);
+
+out:
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+       return SUCCESS;
+}
+
+static inline void
+pvscsi_free_sg(const struct pvscsi_adapter *adapter, struct scsi_cmnd *cmd)
+{
+       unsigned count = scsi_sg_count(cmd);
+
+       if (count) {
+               struct scatterlist *sg = scsi_sglist(cmd);
+               pci_unmap_sg(adapter->dev, sg, count, cmd->sc_data_direction);
+       }
+}
+
+/*
+ * Abort all outstanding requests.  This is only safe to use if the completion
+ * ring will never be walked again or the device has been reset, because it
+ * destroys the 1-1 mapping between context field passed to emulation and our
+ * request structure.
+ */
+static inline void pvscsi_reset_all(struct pvscsi_adapter *adapter)
+{
+       unsigned i;
+
+       for (i = 0; i < adapter->req_depth; i++) {
+               struct pvscsi_ctx *ctx = &adapter->cmd_map[i];
+               struct scsi_cmnd *cmd = ctx->cmd;
+               if (cmd) {
+                       printk(KERN_ERR "pvscsi: forced reset on cmd %p\n", cmd);
+                       pvscsi_free_sg(adapter, cmd);
+                       pvscsi_free_context(adapter, ctx);
+                       cmd->result = (DID_RESET << 16);
+                       cmd->scsi_done(cmd);
+               }
+       }
+}
+
+static int pvscsi_host_reset(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+       unsigned long flags;
+
+       printk(KERN_NOTICE "pvscsi: attempting host reset on %p\n", adapter);
+
+       /*
+        * We're going to tear down the entire ring structure and set it back
+        * up, so stalling new requests until all completions are flushed and
+        * the rings are back in place.
+        */
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+
+       pvscsi_process_request_ring(adapter);
+       ll_adapter_reset(adapter);
+
+       /*
+        * Now process any completions.  Note we do this AFTER adapter reset,
+        * which is strange, but stops races where completions get posted
+        * between processing the ring and issuing the reset.  The backend will
+        * not touch the ring memory after reset, so the immediately pre-reset
+        * completion ring state is still valid.
+        */
+       pvscsi_process_completion_ring(adapter);
+
+       pvscsi_reset_all(adapter);
+       pvscsi_setup_rings(adapter);
+       pvscsi_write_intr_mask(adapter, PVSCSI_INTR_ALL);
+
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+       return SUCCESS;
+}
+
+static int pvscsi_bus_reset(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+       unsigned long flags;
+
+       printk(KERN_NOTICE "pvscsi: attempting bus reset on %p\n", adapter);
+
+       /*
+        * We don't want to queue new requests for this bus after
+        * flushing all pending requests to emulation, since new
+        * requests could then sneak in during this bus reset phase,
+        * so take the lock now.
+        */
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+
+       pvscsi_process_request_ring(adapter);
+       ll_bus_reset(adapter);
+       pvscsi_process_completion_ring(adapter);
+
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+       return SUCCESS;
+}
+
+static int pvscsi_device_reset(struct scsi_cmnd *cmd)
+{
+       struct Scsi_Host *host = cmd->device->host;
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+       unsigned long flags;
+
+       printk(KERN_NOTICE "pvscsi: attempting device reset on %p,%d\n",
+               adapter, cmd->device->id);
+
+       /*
+        * We don't want to queue new requests for this device after flushing
+        * all pending requests to emulation, since new requests could then
+        * sneak in during this device reset phase, so take the lock now.
+        */
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+
+       pvscsi_process_request_ring(adapter);
+       ll_device_reset(adapter, cmd->device->id);
+       pvscsi_process_completion_ring(adapter);
+
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+
+       return SUCCESS;
+}
+
+static irqreturn_t pvscsi_isr COMPAT_IRQ_HANDLER_ARGS(irq, devp)
+{
+       struct pvscsi_adapter *adapter = devp;
+       int handled = FALSE;
+
+       if (adapter->use_msi || adapter->use_msix)
+               handled = TRUE;
+       else {
+               u32 val = pvscsi_read_intr_status(adapter);
+               handled = (val & PVSCSI_INTR_ALL) != 0;
+               if (handled)
+                       pvscsi_write_intr_status(devp, val);
+       }
+
+       if (handled) {
+               unsigned long flags;
+               spin_lock_irqsave(&adapter->hw_lock, flags);
+               pvscsi_process_completion_ring(adapter);
+               spin_unlock_irqrestore(&adapter->hw_lock, flags);
+       }
+
+       LOG(2, "pvscsi_isr %d\n", handled);
+
+       return IRQ_RETVAL(handled);
+}
+
+/* Shutdown an entire device, syncinc all outstanding I/O */
+static void __pvscsi_shutdown(struct pvscsi_adapter *adapter)
+{
+       pvscsi_write_intr_mask(adapter, 0);
+       if (adapter->irq) {
+               free_irq(adapter->irq, adapter);
+               adapter->irq = 0;
+       }
+
+#ifdef CONFIG_PCI_MSI
+       if (adapter->use_msi) {
+               pci_disable_msi(adapter->dev);
+               adapter->use_msi = 0;
+       }
+#endif
+
+       pvscsi_process_request_ring(adapter);
+        pvscsi_process_completion_ring(adapter);
+       ll_adapter_reset(adapter);
+}
+
+static void COMPAT_PCI_DECLARE_SHUTDOWN(pvscsi_shutdown, dev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(COMPAT_PCI_TO_DEV(dev));
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+
+       __pvscsi_shutdown(adapter);
+}
+
+static void pvscsi_remove(struct pci_dev *pdev)
+{
+       struct Scsi_Host *host = pci_get_drvdata(pdev);
+       struct pvscsi_adapter *adapter = HOST_ADAPTER(host);
+
+       scsi_remove_host(host);
+
+       __pvscsi_shutdown(adapter);
+       pvscsi_release_resources(adapter);
+
+       scsi_host_put(host);
+
+       pci_set_drvdata(pdev, NULL);
+       pci_disable_device(pdev);
+}
+
+
+/**************************************************************
+ *
+ *   VMWARE Hypervisor ring / SCSI mid-layer interactions
+ *
+ *   Functions which have to deal with both ring semantics
+ *   and Linux SCSI internals are placed here.
+ *
+ **************************************************************/
+
+static inline struct PVSCSISGList *
+pvscsi_create_sg(struct pvscsi_ctx *ctx, struct scatterlist *sg, unsigned count)
+{
+       unsigned i;
+       struct PVSCSISGList *sgl;
+       struct PVSCSISGElement *sge;
+
+       sgl = ctx->sgl;
+
+       BUG_ON(count > PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT);
+
+       sge = &sgl->sge[0];
+       for (i = 0; i < count; i++, sg++) {
+               sge[i].addr = sg_dma_address(sg);
+               sge[i].length = sg_dma_len(sg);
+               sge[i].flags = 0;
+       }
+
+       return sgl;
+}
+
+/*
+ * Map all data buffers for a command into PCI space and
+ * setup the scatter/gather list if needed.
+ */
+static inline void
+pvscsi_map_buffers(struct pvscsi_adapter *adapter, struct pvscsi_ctx *ctx,
+                  struct scsi_cmnd *cmd, RingReqDesc *e)
+{
+       unsigned count;
+       unsigned bufflen = scsi_bufflen(cmd);
+
+       e->dataLen = bufflen;
+       e->dataAddr = 0;
+       if (bufflen == 0)
+               return;
+
+       count = scsi_sg_count(cmd);
+       if (count != 0) {
+               struct scatterlist *sg = scsi_sglist(cmd);
+               int segs = pci_map_sg(adapter->dev, sg, count,
+                                     cmd->sc_data_direction);
+               if (segs > 1) {
+                       struct PVSCSISGList *sgl;
+
+                       e->flags |= PVSCSI_FLAG_CMD_WITH_SG_LIST;
+                       sgl = pvscsi_create_sg(ctx, sg, segs);
+                       e->dataAddr = __pa(sgl);
+               } else
+                       e->dataAddr = sg_dma_address(sg);
+       } else {
+               e->dataAddr = __pa(scsi_request_buffer(cmd));
+       }
+}
+
+/*
+ * Translate a Linux SCSI request into a request ring entry.
+ */
+static inline int
+pvscsi_queue_ring(struct pvscsi_adapter *adapter, struct pvscsi_ctx *ctx,
+                 struct scsi_cmnd *cmd)
+{
+       RingsState *s;
+       RingReqDesc *e, *ring;
+
+       s = adapter->ring_state;
+       ring = adapter->req_ring;
+
+       /*
+        * If this condition holds, we might have room on the request ring, but
+        * we might not have room on the completion ring for the response.
+        * However, we have already ruled out this possibility - we would not
+        * have successfully allocated a context if it were true, since we only
+        * have one context per request entry.  Check for it anyway, since it
+        * would be a serious bug.
+        */
+       if (s->reqProdIdx - s->cmpConsIdx >= adapter->req_depth) {
+               printk(KERN_ERR "pvscsi: ring full: reqProdIdx=%d cmpConsIdx=%d\n",
+                       s->reqProdIdx, s->cmpConsIdx);
+               return -1;
+       }
+
+       e = ring + (s->reqProdIdx % adapter->req_depth);
+       {
+               struct scsi_device *sdev;
+               sdev = cmd->device;
+               e->bus = sdev->channel;
+               e->target = sdev->id;
+               memset(e->lun, 0, sizeof(e->lun));
+               e->lun[1] = sdev->lun;
+       }
+       if (cmd->sense_buffer) {
+               e->senseLen = SCSI_SENSE_BUFFERSIZE;
+               e->senseAddr = __pa(cmd->sense_buffer);
+       } else {
+               e->senseLen = 0;
+               e->senseAddr = 0;
+       }
+       e->cdbLen = cmd->cmd_len;
+       e->vcpuHint = smp_processor_id();
+       memcpy(e->cdb, cmd->cmnd, e->cdbLen);
+
+       e->tag = SIMPLE_QUEUE_TAG;
+       if (cmd->device->tagged_supported) {
+               if (cmd->tag == HEAD_OF_QUEUE_TAG ||
+                   cmd->tag == ORDERED_QUEUE_TAG)
+                       e->tag = cmd->tag;
+       }
+
+       if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+               e->flags = PVSCSI_FLAG_CMD_DIR_TOHOST;
+       else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+               e->flags = PVSCSI_FLAG_CMD_DIR_TODEVICE;
+       else if (cmd->sc_data_direction == DMA_NONE)
+               e->flags = PVSCSI_FLAG_CMD_DIR_NONE;
+       else
+               e->flags = 0;
+
+       pvscsi_map_buffers(adapter, ctx, cmd, e);
+
+       /*
+        * Fill in the context entry so we can recognize this
+        * request off the completion queue
+        */
+       e->context = pvscsi_map_context(adapter, ctx);
+
+        barrier();
+
+       s->reqProdIdx++;
+
+       return 0;
+}
+
+/*
+ * Pull a completion descriptor off and pass the completion back
+ * to the SCSI mid layer.
+ */
+static inline void
+pvscsi_complete_request(struct pvscsi_adapter *adapter, const RingCmpDesc *e)
+{
+       struct pvscsi_ctx *ctx;
+       struct scsi_cmnd *cmd;
+       u32 btstat = e->hostStatus;
+       u32 sdstat = e->scsiStatus;
+
+       ctx = pvscsi_get_context(adapter, e->context);
+       cmd = pvscsi_free_context(adapter, ctx);
+       cmd->result = 0;
+
+       if (sdstat != SAM_STAT_GOOD &&
+           (btstat == BTSTAT_SUCCESS ||
+            btstat == BTSTAT_LINKED_COMMAND_COMPLETED ||
+            btstat == BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG))
+               switch (sdstat) {
+               case SAM_STAT_CHECK_CONDITION:
+                       /*
+                        * Sense data is set by the emulation.
+                        * Linux seems to want DID_OK despite the error.
+                        */
+                       cmd->result = (DID_OK << 16) | (SAM_STAT_CHECK_CONDITION);
+                       if (cmd->sense_buffer)
+                               cmd->result |= (DRIVER_SENSE << 24);
+                       break;
+               case SAM_STAT_BUSY:
+                       /* Back off. */
+                       cmd->result = (DID_OK << 16) | sdstat;
+                       break;
+               default:
+                       cmd->result = (DID_ERROR << 16);
+                       LOG(0, "Unhandled SCSI status: 0x%x\n", sdstat);
+               }
+
+       else
+               switch (btstat) {
+               case BTSTAT_SUCCESS:
+               case BTSTAT_LINKED_COMMAND_COMPLETED:
+               case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG:
+                       /* If everything went fine, let's move on..  */
+                       cmd->result = (DID_OK << 16);
+                       break;
+
+               case BTSTAT_DATARUN:
+               case BTSTAT_DATA_UNDERRUN:
+                       /* Report residual data in underruns */
+                       scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen);
+                       cmd->result = (DID_ERROR << 16);
+                       break;
+
+               case BTSTAT_SELTIMEO:
+                       /* Our emulation returns this for non-connected devs */
+                       cmd->result = (DID_BAD_TARGET << 16);
+                       break;
+
+               case BTSTAT_LUNMISMATCH:
+               case BTSTAT_TAGREJECT:
+               case BTSTAT_BADMSG:
+                       cmd->result = (DRIVER_INVALID << 24);
+                       /* fall through */
+
+               case BTSTAT_HAHARDWARE:
+               case BTSTAT_INVPHASE:
+               case BTSTAT_HATIMEOUT:
+               case BTSTAT_NORESPONSE:
+               case BTSTAT_DISCONNECT:
+               case BTSTAT_HASOFTWARE:
+               case BTSTAT_BUSFREE:
+               case BTSTAT_SENSFAILED:
+                       cmd->result |= (DID_ERROR << 16);
+                       break;
+
+               case BTSTAT_SENTRST:
+               case BTSTAT_RECVRST:
+               case BTSTAT_BUSRESET:
+                       cmd->result = (DID_RESET << 16);
+                       break;
+
+               case BTSTAT_ABORTQUEUE:
+                       cmd->result = (DID_ABORT << 16);
+                       break;
+
+               case BTSTAT_SCSIPARITY:
+                       cmd->result = (DID_PARITY << 16);
+                       break;
+
+               default:
+                       cmd->result = (DID_ERROR << 16);
+                       LOG(0, "Unknown completion status: 0x%x\n", btstat);
+       }
+
+       LOG(3, "cmd=%p %x ctx=%p result=0x%x status=0x%x,%x\n",
+               cmd, cmd->cmnd[0], ctx, cmd->result, btstat, sdstat);
+
+       pvscsi_free_sg(adapter, cmd);
+
+       cmd->scsi_done(cmd);
+}
+
+
+/**************************************************************
+ *
+ *   VMWARE PVSCSI Hypervisor Communication Implementation
+ *
+ *   This code should be maintained to match the Windows driver
+ *   as closely as possible.  This code is largely independent
+ *   of any Linux internals.
+ *
+ **************************************************************/
+
+static inline void pvscsi_reg_write(const struct pvscsi_adapter *adapter,
+                                   u32 offset, u32 val)
+{
+       writel(val, (void *)(adapter->iomap + offset));
+}
+
+static inline u32 pvscsi_reg_read(const struct pvscsi_adapter *adapter,
+                                   u32 offset)
+{
+       return readl((void *)(adapter->iomap + offset));
+}
+
+static inline u32 pvscsi_read_intr_status(const struct pvscsi_adapter *adapter)
+{
+       return pvscsi_reg_read(adapter, PVSCSI_REG_OFFSET_INTR_STATUS);
+}
+
+static inline void pvscsi_write_intr_status(const struct pvscsi_adapter *adapter,
+                                           u32 val)
+{
+       pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_INTR_STATUS, val);
+}
+
+static inline void pvscsi_write_intr_mask(const struct pvscsi_adapter *adapter,
+                                         u32 val)
+{
+       pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_INTR_MASK, val);
+}
+
+static inline void pvscsi_write_cmd_desc(const struct pvscsi_adapter *adapter,
+                                        u32 cmd, void *desc, size_t len)
+{
+       u32 *ptr = (u32 *)desc;
+       unsigned i;
+
+       len /= sizeof(u32);
+       pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_COMMAND, cmd);
+       for (i = 0; i < len; i++)
+               pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_COMMAND_DATA, ptr[i]);
+}
+
+static void pvscsi_abort_cmd(const struct pvscsi_adapter *adapter,
+                            const struct pvscsi_ctx *ctx)
+{
+       struct CmdDescAbortCmd cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.target = ctx->cmd->device->id;
+       cmd.context = pvscsi_map_context(adapter, ctx);
+
+       pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_ABORT_CMD, &cmd, sizeof(cmd));
+}
+
+static inline void pvscsi_kick_rw_io(const struct pvscsi_adapter *adapter)
+{
+       pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_KICK_RW_IO, 0);
+}
+
+/* Get device to respond immediately */
+static void pvscsi_process_request_ring(const struct pvscsi_adapter *adapter)
+{
+       pvscsi_reg_write(adapter, PVSCSI_REG_OFFSET_KICK_NON_RW_IO, 0);
+}
+
+static inline int scsi_is_rw(unsigned char op)
+{
+       return op == READ_6  || op == WRITE_6 ||
+              op == READ_10 || op == WRITE_10 ||
+              op == READ_12 || op == WRITE_12 ||
+              op == READ_16 || op == WRITE_16;
+}
+
+static void pvscsi_kick_io(const struct pvscsi_adapter *adapter, unsigned char op)
+{
+       if (scsi_is_rw(op))
+               pvscsi_kick_rw_io(adapter);
+       else
+               pvscsi_process_request_ring(adapter);
+}
+
+static void ll_adapter_reset(const struct pvscsi_adapter *adapter)
+{
+       u32 val;
+
+       LOG(0, "Adapter Reset on %p\n", adapter);
+
+       pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_ADAPTER_RESET, NULL, 0);
+       val = pvscsi_read_intr_status(adapter);
+       LOG(0, "Adapter Reset done: %u\n", val);
+}
+
+static void ll_bus_reset(const struct pvscsi_adapter *adapter)
+{
+       LOG(0, "Reseting bus on %p\n", adapter);
+
+       pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_RESET_BUS, NULL, 0);
+}
+
+static void ll_device_reset(const struct pvscsi_adapter *adapter, u32 target)
+{
+       struct CmdDescResetDevice cmd;
+
+       LOG(0, "Reseting device: target=%u\n", target);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.target = target;
+
+       pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_RESET_DEVICE, &cmd, sizeof(cmd));
+}
+
+static void pvscsi_setup_rings(struct pvscsi_adapter *adapter)
+{
+       struct CmdDescSetupRings cmd;
+       unsigned i, pages;
+       void *base;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.ringsStatePPN = __pa(adapter->ring_state) >> PAGE_SHIFT;
+
+       cmd.reqRingNumPages = pages = adapter->req_pages;
+       for (i = 0, base = adapter->req_ring; i < pages; i++, base += PAGE_SIZE)
+               cmd.reqRingPPNs[i] = page_to_pfn(vmalloc_to_page(base));
+
+       cmd.cmpRingNumPages = pages = adapter->cmp_pages;
+       for (i = 0, base = adapter->cmp_ring; i < pages; i++, base += PAGE_SIZE)
+               cmd.cmpRingPPNs[i] = page_to_pfn(vmalloc_to_page(base));
+
+       memset(adapter->ring_state, 0, PAGE_SIZE);
+       memset(adapter->req_ring, 0, adapter->req_pages * PAGE_SIZE);
+       memset(adapter->cmp_ring, 0, adapter->cmp_pages * PAGE_SIZE);
+
+       pvscsi_write_cmd_desc(adapter, PVSCSI_CMD_SETUP_RINGS, &cmd, sizeof(cmd));
+}
+
+static void pvscsi_process_completion_ring(struct pvscsi_adapter *adapter)
+{
+       RingsState *s = adapter->ring_state;
+       RingCmpDesc *ring = adapter->cmp_ring;
+
+       while (s->cmpConsIdx != s->cmpProdIdx) {
+               RingCmpDesc *e = ring + (s->cmpConsIdx % adapter->cmp_depth);
+
+               pvscsi_complete_request(adapter, e);
+               smp_wmb();
+               s->cmpConsIdx++;
+       }
+}
diff --git a/open-vm-tools/modules/linux/pvscsi/pvscsi_defs.h b/open-vm-tools/modules/linux/pvscsi/pvscsi_defs.h
new file mode 100644 (file)
index 0000000..3fa81f5
--- /dev/null
@@ -0,0 +1,432 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef __PVSCSI_DEFS_H__
+#define __PVSCSI_DEFS_H__
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_VMX
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMKERNEL
+#include "includeCheck.h"
+
+#include "vm_basic_types.h"
+
+
+/*
+ * Memory mapped i/o register offsets.
+ */
+
+enum PVSCSIRegOffset {
+   PVSCSI_REG_OFFSET_COMMAND        =    0x0,
+   PVSCSI_REG_OFFSET_COMMAND_DATA   =    0x4,
+   PVSCSI_REG_OFFSET_COMMAND_STATUS =    0x8,
+   PVSCSI_REG_OFFSET_LAST_STS_0     =  0x100,
+   PVSCSI_REG_OFFSET_LAST_STS_1     =  0x104,
+   PVSCSI_REG_OFFSET_LAST_STS_2     =  0x108,
+   PVSCSI_REG_OFFSET_LAST_STS_3     =  0x10C,
+   PVSCSI_REG_OFFSET_INTR_STATUS    = 0x100c,
+   PVSCSI_REG_OFFSET_INTR_MASK      = 0x2010,
+   PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014,
+   PVSCSI_REG_OFFSET_KICK_RW_IO     = 0x4018,
+};
+
+
+/*
+ * I/O space register offsets.
+ */
+
+enum PVSCSIIoRegOffset {
+   PVSCSI_IO_REG_OFFSET_OFFSET = 0,
+   PVSCSI_IO_REG_OFFSET_DATA   = 4,
+};
+
+/*
+ * Configuration pages. Structure sizes are 4 byte multiples.
+ */
+
+enum ConfigPageType {
+   PVSCSI_CONFIG_PAGE_CONTROLLER = 0x1958,
+   PVSCSI_CONFIG_PAGE_PHY        = 0x1959,
+   PVSCSI_CONFIG_PAGE_DEVICE     = 0x195a,
+};
+
+/*
+ * For controller address,
+ *  63                            31                           0
+ * |-----------------------------|------------------------------|
+ *  <--- controller constant----> <--------- All zeros --------->
+ *
+ * For phy address,
+ *  63                            31                           0
+ * |-----------------------------|------------------------------|
+ *  <-- phy type constant  -----> <--------- phy num ----------->
+ *
+ * For device address,
+ *  63                            31             15            0
+ * |-----------------------------|--------------|---------------|
+ * <--bus/target type constant--> <--- bus  ---> <--- target --->
+ */
+
+#define PVSCSI_CONFIG_ADDR_TYPE(addr)   HIDWORD(addr)
+#define PVSCSI_CONFIG_ADDR_PHYNUM(addr) LODWORD(addr)
+#define PVSCSI_CONFIG_ADDR_BUS(addr)    HIWORD(addr)
+#define PVSCSI_CONFIG_ADDR_TARGET(addr) LOWORD(addr)
+
+enum ConfigPageAddressType {
+   PVSCSI_CONFIG_CONTROLLER_ADDRESS = 0x2120,
+   PVSCSI_CONFIG_BUSTARGET_ADDRESS  = 0x2121,
+   PVSCSI_CONFIG_PHY_ADDRESS        = 0x2122,
+};
+
+typedef
+#include "vmware_pack_begin.h"
+struct PVSCSIConfigPageHeader {
+   uint32 pageNum;
+   uint16 numDwords; /* Including the header. */
+   uint16 hostStatus;
+   uint16 scsiStatus;
+   uint16 reserved[3];
+}
+#include "vmware_pack_end.h"
+PVSCSIConfigPageHeader;
+
+typedef
+#include "vmware_pack_begin.h"
+struct PVSCSIConfigPageController {
+   PVSCSIConfigPageHeader header;
+   uint64                 nodeWWN; /* Device name as defined in the SAS spec. */
+   uint16                 manufacturer[64];
+   uint16                 serialNumber[64];
+   uint16                 opromVersion[32];
+   uint16                 hwVersion[32];
+   uint16                 firmwareVersion[32];
+   uint32                 numPhys;
+   uint8                  useConsecutivePhyWWNs;
+   uint8                  reserved[3];
+}
+#include "vmware_pack_end.h"
+PVSCSIConfigPageController;
+
+enum AttachedDeviceType {
+   PVSCSI_SAS_DEVICE    = 1,
+   PVSCSI_SATA_DEVICE   = 2,
+};
+
+typedef
+#include "vmware_pack_begin.h"
+struct PVSCSIConfigPagePhy {
+   PVSCSIConfigPageHeader header;
+   uint64                 phyWWN;
+   uint64                 attachedDeviceWWN; /* 0 => no attached device. */
+   uint8                  attachedDeviceType;
+   uint8                  reserved[7];
+}
+#include "vmware_pack_end.h"
+PVSCSIConfigPagePhy;
+
+typedef
+#include "vmware_pack_begin.h"
+struct PVSCSIConfigPageDevice {
+   PVSCSIConfigPageHeader header;
+   uint64                 deviceWWN;
+   uint64                 phyWWN;
+   uint32                 phyNum;
+   uint8                  target;
+   uint8                  bus;
+   uint8                  reserved[2];
+}
+#include "vmware_pack_end.h"
+PVSCSIConfigPageDevice;
+
+/*
+ * Virtual h/w commands.
+ */
+
+enum PVSCSICommands {
+   PVSCSI_CMD_FIRST             = 0, /* NB: has to be first */
+
+   PVSCSI_CMD_ADAPTER_RESET     = 1,
+   PVSCSI_CMD_ISSUE_SCSI        = 2,
+   PVSCSI_CMD_SETUP_RINGS       = 3,
+   PVSCSI_CMD_RESET_BUS         = 4,
+   PVSCSI_CMD_RESET_DEVICE      = 5,
+   PVSCSI_CMD_ABORT_CMD         = 6,
+   PVSCSI_CMD_CONFIG            = 7,
+
+   PVSCSI_CMD_LAST              = 8  /* NB: has to be last */
+};
+
+
+/*
+ * Command descriptors.
+ */
+
+struct CmdDescIssueSCSI {
+   PA     reqAddr;
+   PA     cmpAddr;
+};
+
+struct CmdDescResetDevice {
+   uint32 target;
+   uint8  lun[8];
+};
+
+struct CmdDescAbortCmd {
+   uint64 context;
+   uint32 target;
+   uint32 _pad;
+};
+
+
+#define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES        32
+struct CmdDescSetupRings {
+   uint32 reqRingNumPages;
+   uint32 cmpRingNumPages;
+   PPN64  ringsStatePPN;
+   PPN64  reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
+   PPN64  cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
+};
+
+#include "vmware_pack_begin.h"
+struct CmdDescConfigCmd {
+   PA     cmpAddr;
+   uint64 configPageAddress;
+   uint32 configPageNum;
+   uint32 _pad;
+}
+#include "vmware_pack_end.h"
+;
+
+/*
+ * Rings state.
+ */
+
+typedef struct RingsState {
+   uint32       reqProdIdx;
+   uint32       reqConsIdx;
+   uint32       reqNumEntriesLog2;
+
+   uint32       cmpProdIdx;
+   uint32       cmpConsIdx;
+   uint32       cmpNumEntriesLog2;
+} RingsState;
+
+
+/*
+ * Request descriptor.
+ *
+ * sizeof(RingReqDesc) = 128
+ *
+ * - context: is a unique identifier of a command. It could normally be any
+ *   64bit value, however we currently store it in the serialNumber variable
+ *   of struct SCSI_Command, so we have the following restrictions due to the
+ *   way this field is handled in the vmkernel storage stack:
+ *    * this value can't be 0,
+ *    * the upper 32bit need to be 0 since serialNumber is as a uint32.
+ *   Currently tracked as PR 292060.
+ * - dataLen: contains the total number of bytes that need to be transferred.
+ * - dataAddr:
+ *   * if PVSCSI_FLAG_CMD_WITH_SG_LIST is set: dataAddr is the PA of the first
+ *     s/g table segment, each s/g segment is entirely contained on a single
+ *     page of physical memory,
+ *   * if PVSCSI_FLAG_CMD_WITH_SG_LIST is NOT set, then dataAddr is the PA of
+ *     the buffer used for the DMA transfer,
+ * - flags:
+ *   * PVSCSI_FLAG_CMD_WITH_SG_LIST: see dataAddr above,
+ *   * PVSCSI_FLAG_CMD_DIR_NONE: no DMA involved,
+ *   * PVSCSI_FLAG_CMD_DIR_TOHOST: transfer from device to main memory,
+ *   * PVSCSI_FLAG_CMD_DIR_TODEVICE: transfer from main memory to device,
+ *   * PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB: reserved to handle CDBs larger than
+ *     16bytes. To be specified.
+ * - vcpuHint: vcpuId of the processor that will be most likely waiting for the
+ *   completion of the i/o. For guest OSes that use lowest priority message
+ *   delivery mode (such as windows), we use this "hint" to deliver the
+ *   completion action to the proper vcpu. For now, we can use the vcpuId of
+ *   the processor that initiated the i/o as a likely candidate for the vcpu
+ *   that will be waiting for the completion..
+ */
+
+#define PVSCSI_FLAG_CMD_WITH_SG_LIST        (1 << 0)
+#define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB     (1 << 1)
+#define PVSCSI_FLAG_CMD_DIR_NONE            (1 << 2)
+#define PVSCSI_FLAG_CMD_DIR_TOHOST          (1 << 3)
+#define PVSCSI_FLAG_CMD_DIR_TODEVICE        (1 << 4)
+
+typedef
+#include "vmware_pack_begin.h"
+struct RingReqDesc {
+   uint64       context;
+   PA           dataAddr;
+   uint64       dataLen;
+   PA           senseAddr;
+   uint32       senseLen;
+   uint32       flags;
+   uint8        cdb[16];
+   uint8        cdbLen;
+   uint8        lun[8];
+   uint8        tag;
+   uint8        bus;
+   uint8        target;
+   uint8        vcpuHint;
+   uint8        unused[59];
+}
+#include "vmware_pack_end.h"
+RingReqDesc;
+
+
+/*
+ * Scatter-gather list management.
+ *
+ * As described above, when PVSCSI_FLAG_CMD_WITH_SG_LIST is set in the
+ * RingReqDesc.flags, then RingReqDesc.dataAddr is the PA of the first s/g
+ * table segment.
+ *
+ * - each segment of the s/g table contain a succession of struct
+ *   PVSCSISGElement.
+ * - each segment is entirely contained on a single physical page of memory.
+ * - a "chain" s/g element has the flag PVSCSI_SGE_FLAG_CHAIN_ELEMENT set in
+ *   PVSCSISGElement.flags and in this case:
+ *     * addr is the PA of the next s/g segment,
+ *     * length is undefined, assumed to be 0.
+ */
+
+#define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT       128
+
+/*
+ * MAX_CHAIN_SEGMENTS could probably be much smaller, but if the guest takes
+ * more than 128 pages to give us the SG list, then the guest is pretty clearly
+ * broken.
+ */
+
+#define PVSCSI_MAX_NUM_SG_SEGMENTS       128
+#define PVSCSI_SGE_FLAG_CHAIN_ELEMENT   (1 << 0)
+
+typedef struct PVSCSISGElement {
+   PA           addr;
+   uint32       length;
+   uint32       flags;
+} PVSCSISGElement;
+
+
+/*
+ * Completion descriptor.
+ *
+ * sizeof(RingCmpDesc) = 32
+ *
+ * - context: identifier of the command. The same thing that was specified
+ *   under "context" as part of struct RingReqDesc at initiation time,
+ * - dataLen: number of bytes transferred for the actual i/o operation,
+ * - senseLen: number of bytes written into the sense buffer,
+ * - hostStatus: adapter status,
+ * - scsiStatus: device status,
+ */
+
+typedef struct RingCmpDesc {
+   uint64     context;
+   uint64     dataLen;
+   uint32     senseLen;
+   uint16     hostStatus;
+   uint16     scsiStatus;
+   uint32     _pad[2];
+} RingCmpDesc;
+
+
+/*
+ * Interrupt status / IRQ bits.
+ */
+
+#define PVSCSI_INTR_CMPL_0      (1 << 0)
+#define PVSCSI_INTR_CMPL_1      (1 << 1)
+#define PVSCSI_INTR_CMPL_MASK   MASK(2)
+
+#define PVSCSI_INTR_ALL         PVSCSI_INTR_CMPL_MASK
+#define PVSCSI_MAX_INTRS        24
+
+
+/*
+ * Enumeration of supported MSI-X vectors
+ */
+#define PVSCSI_VECTOR_COMPLETION   0
+
+
+/*
+ * Misc constants for the rings.
+ */
+
+#define PVSCSI_MAX_NUM_PAGES_REQ_RING   PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
+#define PVSCSI_MAX_NUM_PAGES_CMP_RING   PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
+
+#define PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE   (PAGE_SIZE / sizeof(RingReqDesc))
+#define PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE   (PAGE_SIZE / sizeof(RingCmpDesc))
+
+#define PVSCSI_MAX_REQ_QUEUE_DEPTH \
+   (PVSCSI_MAX_NUM_PAGES_REQ_RING * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE)
+#define PVSCSI_MAX_CMP_QUEUE_DEPTH \
+   (PVSCSI_MAX_NUM_PAGES_CMP_RING * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE)
+#define PVSCSI_MAX_QUEUE_DEPTH \
+   MAX(PVSCSI_MAX_REQ_QUEUE_DEPTH, PVSCSI_MAX_CMP_QUEUE_DEPTH)
+
+/*
+ * Misc constants related to the BARs.
+ */
+
+#define PVSCSI_NUM_REGS              7
+#define PVSCSI_NUM_IO_REGS           2
+
+/*
+ * The following only gives a functional number if the result is a power of
+ * two.
+ */
+#define PVSCSI_IO_SPACE_MASK              (PVSCSI_NUM_IO_REGS * sizeof(uint32) - 1)
+
+#define PVSCSI_MEM_SPACE_COMMAND_NUM_PAGES     1
+#define PVSCSI_MEM_SPACE_INTR_STATUS_NUM_PAGES 1
+#define PVSCSI_MEM_SPACE_MISC_NUM_PAGES        2
+#define PVSCSI_MEM_SPACE_KICK_IO_NUM_PAGES     2
+#define PVSCSI_MEM_SPACE_MSIX_NUM_PAGES        2
+
+#define PVSCSI_MEM_SPACE_COMMAND_PAGE          0
+#define PVSCSI_MEM_SPACE_INTR_STATUS_PAGE      1
+#define PVSCSI_MEM_SPACE_MISC_PAGE             2
+#define PVSCSI_MEM_SPACE_KICK_IO_PAGE          4
+#define PVSCSI_MEM_SPACE_MSIX_TABLE_PAGE       6
+#define PVSCSI_MEM_SPACE_MSIX_PBA_PAGE         7
+
+
+#define PVSCSI_MEM_SPACE_NUM_PAGES \
+   (PVSCSI_MEM_SPACE_COMMAND_NUM_PAGES +       \
+    PVSCSI_MEM_SPACE_INTR_STATUS_NUM_PAGES +   \
+    PVSCSI_MEM_SPACE_MISC_NUM_PAGES +          \
+    PVSCSI_MEM_SPACE_KICK_IO_NUM_PAGES +       \
+    PVSCSI_MEM_SPACE_MSIX_NUM_PAGES)
+
+#define PVSCSI_MEM_SPACE_SIZE        (PVSCSI_MEM_SPACE_NUM_PAGES * PAGE_SIZE)
+#define PVSCSI_MEM_SPACE_MASK        (CONST64U(PVSCSI_MEM_SPACE_SIZE - 1))
+
+/*
+ * For simplicity of implementation, the MSI-X array is combined into
+ * the single 64-bit memory BAR; these values are used to initialize the
+ * MSI-X capability PCIe field.
+ */
+#define PVSCSI_MSIX_TABLE_OFF      (PVSCSI_MEM_SPACE_MSIX_TABLE_PAGE * PAGE_SIZE)
+#define PVSCSI_MSIX_PBA_OFF        (PVSCSI_MEM_SPACE_MSIX_PBA_PAGE * PAGE_SIZE)
+#define PVSCSI_MSIX_BIR            1
+
+#endif /* __PVSCSI_DEFS_H__ */
diff --git a/open-vm-tools/modules/linux/pvscsi/pvscsi_version.h b/open-vm-tools/modules/linux/pvscsi/pvscsi_version.h
new file mode 100644 (file)
index 0000000..ee3edde
--- /dev/null
@@ -0,0 +1,32 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * pvscsi_version.h --
+ *
+ * Version definitions for the Linux PVSCSI driver.
+ */
+
+#ifndef _PVSCSI_VERSION_H_
+#define _PVSCSI_VERSION_H_
+
+#define PVSCSI_DRIVER_VERSION          0.0.0.6
+#define PVSCSI_DRIVER_VERSION_COMMAS   0,0,0,6
+#define PVSCSI_DRIVER_VERSION_STRING   "0.0.0.6"
+
+#endif /* _PVSCSI_VERSION_H_ */
diff --git a/open-vm-tools/modules/linux/pvscsi/scsi_defs.h b/open-vm-tools/modules/linux/pvscsi/scsi_defs.h
new file mode 100644 (file)
index 0000000..9454ba8
--- /dev/null
@@ -0,0 +1,2104 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * scsi_defs.h
+ *
+ * General SCSI definitions
+ */
+
+#ifndef _SCSI_DEFS_H_
+#define _SCSI_DEFS_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMNIXMOD
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_DISTRIBUTE
+#include "includeCheck.h"
+
+#include "vm_basic_defs.h"  // for offsetof()
+
+/*
+ * Non-exhaustive list of SCSI operation codes.  Note that
+ * some codes are defined differently according to the target
+ * device.  Also, codes may have slightly different meanings
+ * and/or names based on the version of the SCSI spec.
+ *
+ * NB: Command descriptions come from the "SCSI Book" and not
+ *     from the SCSI specifications (YMMV).
+ */
+#define SCSI_CMD_TEST_UNIT_READY       0x00    // test if LUN ready to accept a command
+#define SCSI_CMD_REZERO_UNIT          0x01     // seek to track 0
+#define SCSI_CMD_REQUEST_SENSE        0x03     // return detailed error information
+#define SCSI_CMD_FORMAT_UNIT          0x04     //
+#define SCSI_CMD_READ_BLOCKLIMITS      0x05    //
+#define SCSI_CMD_REASSIGN_BLOCKS       0x07    // 
+#define SCSI_CMD_INIT_ELEMENT_STATUS   0x07     // Media changer
+#define SCSI_CMD_READ6                0x08     // read w/ limited addressing
+#define SCSI_CMD_WRITE6                       0x0a     // write w/ limited addressing
+#define SCSI_CMD_PRINT                0x0a     // print data
+#define SCSI_CMD_SEEK6                0x0b     // seek to LBN
+#define SCSI_CMD_SLEW_AND_PRINT               0x0b     // advance and print
+#define SCSI_CMD_READ_REVERSE         0x0f     // read backwards
+#define SCSI_CMD_WRITE_FILEMARKS       0x10    // 
+#define SCSI_CMD_SYNC_BUFFER          0x10     // print contents of buffer
+#define SCSI_CMD_SPACE                0x11     // 
+#define SCSI_CMD_INQUIRY              0x12     // return LUN-specific information
+#define SCSI_CMD_RECOVER_BUFFERED      0x14    // recover buffered data
+#define SCSI_CMD_MODE_SELECT          0x15     // set device parameters
+#define SCSI_CMD_RESERVE_UNIT         0x16     // make LUN accessible only to certain initiators
+#define SCSI_CMD_RELEASE_UNIT         0x17     // make LUN accessible to other initiators
+#define SCSI_CMD_COPY                 0x18     // autonomous copy from/to another device
+#define SCSI_CMD_ERASE                0x19     // 
+#define SCSI_CMD_MODE_SENSE           0x1a     // read device parameters
+#define SCSI_CMD_START_UNIT           0x1b     // load/unload medium
+#define SCSI_CMD_SCAN                 0x1b     // perform scan
+#define SCSI_CMD_STOP_PRINT           0x1b     // interrupt printing
+#define SCSI_CMD_RECV_DIAGNOSTIC       0x1c    // read self-test results
+#define SCSI_CMD_SEND_DIAGNOSTIC       0x1d    // initiate self-test
+#define SCSI_CMD_MEDIUM_REMOVAL               0x1e     // lock/unlock door
+#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23   // read format capacities
+#define SCSI_CMD_SET_WINDOW           0x24     // set scanning window
+#define SCSI_CMD_GET_WINDOW           0x25     // get scanning window
+#define SCSI_CMD_READ_CAPACITY        0x25     // read number of logical blocks
+#define SCSI_CMD_READ10                       0x28     // read
+#define SCSI_CMD_READ_GENERATION       0x29    // read max generation address of LBN
+#define SCSI_CMD_WRITE10              0x2a     // write
+#define SCSI_CMD_SEEK10                       0x2b     // seek LBN
+#define SCSI_CMD_POSITION_TO_ELEMENT   0x2b     // media changer
+#define SCSI_CMD_ERASE10               0x2c
+#define SCSI_CMD_READ_UPDATED_BLOCK    0x2d    // read specific version of changed block
+#define SCSI_CMD_WRITE_VERIFY         0x2e     // write w/ verify of success
+#define SCSI_CMD_VERIFY                       0x2f     // verify success
+#define SCSI_CMD_SEARCH_DATA_HIGH      0x30    // search for data pattern
+#define SCSI_CMD_SEARCH_DATA_EQUAL     0x31    // search for data pattern
+#define SCSI_CMD_SEARCH_DATA_LOW       0x32    // search for data pattern
+#define SCSI_CMD_SET_LIMITS           0x33     // define logical block boundaries
+#define SCSI_CMD_PREFETCH             0x34     // read data into buffer
+#define SCSI_CMD_READ_POSITION        0x34     // read current tape position
+#define SCSI_CMD_SYNC_CACHE           0x35     // re-read data into buffer
+#define SCSI_CMD_LOCKUNLOCK_CACHE      0x36    // lock/unlock data in cache
+#define SCSI_CMD_READ_DEFECT_DATA      0x37    // 
+#define SCSI_CMD_MEDIUM_SCAN          0x38     // search for free area
+#define SCSI_CMD_COMPARE              0x39     // compare data
+#define SCSI_CMD_COPY_VERIFY          0x3a     // autonomous copy w/ verify
+#define SCSI_CMD_WRITE_BUFFER         0x3b     // write data buffer
+#define SCSI_CMD_READ_BUFFER          0x3c     // read data buffer
+#define SCSI_CMD_UPDATE_BLOCK         0x3d     // substitute block with an updated one
+#define SCSI_CMD_READ_LONG            0x3e     // read data and ECC
+#define SCSI_CMD_WRITE_LONG           0x3f     // write data and ECC
+#define SCSI_CMD_CHANGE_DEF           0x40     // set SCSI version
+#define SCSI_CMD_WRITE_SAME           0x41     // 
+#define SCSI_CMD_READ_SUBCHANNEL       0x42    // read subchannel data and status
+#define SCSI_CMD_READ_TOC             0x43     // read contents table
+#define SCSI_CMD_READ_HEADER          0x44     // read LBN header
+#define SCSI_CMD_PLAY_AUDIO10         0x45     // audio playback
+#define SCSI_CMD_GET_CONFIGURATION     0x46    // get configuration (SCSI-3)
+#define SCSI_CMD_PLAY_AUDIO_MSF               0x47     // audio playback starting at MSF address
+#define SCSI_CMD_PLAY_AUDIO_TRACK      0x48    // audio playback starting at track/index
+#define SCSI_CMD_PLAY_AUDIO_RELATIVE   0x49    // audio playback starting at relative track
+#define SCSI_CMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define SCSI_CMD_PAUSE                0x4b     // audio playback pause/resume
+#define SCSI_CMD_LOG_SELECT           0x4c     // select statistics
+#define SCSI_CMD_LOG_SENSE            0x4d     // read statistics
+#define SCSI_CMD_STOP_PLAY            0x4e     // audio playback stop
+#define SCSI_CMD_READ_DISC_INFO        0x51     // info on CDRs
+#define SCSI_CMD_READ_TRACK_INFO       0x52     // track info on CDRs
+#define SCSI_CMD_RESERVE_TRACK         0x53     // leave space for data on CDRs
+#define SCSI_CMD_SEND_OPC_INFORMATION  0x54     // Optimum Power Calibration
+#define SCSI_CMD_MODE_SELECT10        0x55     // set device parameters
+#define SCSI_CMD_RESERVE_UNIT10        0x56     //
+#define SCSI_CMD_RELEASE_UNIT10        0x57     //
+#define SCSI_CMD_REPAIR_TRACK          0x58
+#define SCSI_CMD_MODE_SENSE10         0x5a     // read device parameters
+#define SCSI_CMD_CLOSE_SESSION         0x5b     // close area/sesssion (recordable)
+#define SCSI_CMD_READ_BUFFER_CAPACITY  0x5c     // CDR burning info.
+#define SCSI_CMD_SEND_CUE_SHEET        0x5d     // (CDR Related?)
+#define SCSI_CMD_PERSISTENT_RESERVE_IN 0x5e     //
+#define SCSI_CMD_PERSISTENT_RESERVE_OUT 0x5f    //
+#define SCSI_CMD_XDWRITE_EXTENDED      0x80
+#define SCSI_CMD_REBUILD               0x81
+#define SCSI_CMD_REGENERATE            0x82
+#define SCSI_CMD_EXTENDED_COPY         0x83     // extended copy
+#define SCSI_CMD_RECEIVE_COPY_RESULTS  0x84     // receive copy results
+#define SCSI_CMD_READ16                       0x88     // read data
+#define SCSI_CMD_WRITE16               0x8a     // write data
+#define SCSI_CMD_ORWRITE16             0x8b
+#define SCSI_CMD_READ_ATTRIBUTE        0x8c     // read attribute
+#define SCSI_CMD_WRITE_ATTRIBUTE       0x8d     // write attribute
+#define SCSI_CMD_WRITE_VERIFY16        0x8e
+#define SCSI_CMD_VERIFY16              0x8f
+#define SCSI_CMD_PREFETCH16            0x90
+#define SCSI_CMD_SYNC_CACHE16          0x91
+#define SCSI_CMD_WRITE_SAME16          0x93
+#define SCSI_CMD_READ_CAPACITY16       0x9e     // read number of logical blocks
+#define SCSI_CMD_WRITE_LONG16          0x9f
+#define SCSI_CMD_REPORT_LUNS           0xa0     // 
+#define SCSI_CMD_BLANK                 0xa1     // erase RW media
+#define SCSI_CMD_SECURITY_PROTOCOL_IN  0xa2     // 
+#define SCSI_CMD_MAINTENANCE_IN        0xa3    // service actions define reports
+#define SCSI_CMD_MAINTENANCE_OUT       0xa4    // service actions define changes
+#define SCSI_CMD_SEND_KEY             0xa3
+#define SCSI_CMD_REPORT_KEY           0xa4     // report key (SCSI-3)
+#define SCSI_CMD_MOVE_MEDIUM          0xa5     // 
+#define SCSI_CMD_PLAY_AUDIO12         0xa5     // audio playback
+#define SCSI_CMD_EXCHANGE_MEDIUM       0xa6     //
+#define SCSI_CMD_LOADCD                       0xa6     //
+#define SCSI_CMD_SET_READ_AHEAD        0xa7
+#define SCSI_CMD_READ12                       0xa8     // read (SCSI-3)
+#define SCSI_CMD_PLAY_TRACK_RELATIVE   0xa9    // audio playback starting at relative track
+#define SCSI_CMD_WRITE12              0xaa     // write data
+#define SCSI_CMD_READ_MEDIA_SERIAL_NUMBER 0xab  //
+#define SCSI_CMD_ERASE12              0xac     // erase logical block
+#define SCSI_CMD_GET_PERFORMANCE       0xac    //
+#define SCSI_CMD_READ_DVD_STRUCTURE    0xad    // read DVD structure (SCSI-3)
+#define SCSI_CMD_WRITE_VERIFY12               0xae     // write logical block, verify success
+#define SCSI_CMD_VERIFY12             0xaf     // verify data
+#define SCSI_CMD_SEARCH_DATA_HIGH12    0xb0    // search data pattern
+#define SCSI_CMD_SEARCH_DATA_EQUAL12   0xb1    // search data pattern
+#define SCSI_CMD_SEARCH_DATA_LOW12     0xb2    // search data pattern
+#define SCSI_CMD_SET_LIMITS12         0xb3     // set block limits
+#define SCSI_CMD_REQUEST_VOLUME_ELEMENT_ADDR 0xb5 //
+#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xb5
+#define SCSI_CMD_SEND_VOLUME_TAG       0xb6     //
+#define SCSI_CMD_SET_STREAMING         0xb6     // For avoiding over/underrun
+#define SCSI_CMD_READ_DEFECT_DATA12    0xb7    // read defect data information
+#define SCSI_CMD_READ_ELEMENT_STATUS   0xb8    // read element status
+#define SCSI_CMD_SELECT_CDROM_SPEED    0xb8    // set data rate
+#define SCSI_CMD_READ_CD_MSF          0xb9     // read CD information (all formats, MSF addresses)
+#define SCSI_CMD_AUDIO_SCAN           0xba     // fast audio playback
+#define SCSI_CMD_SET_CDROM_SPEED       0xbb     // (proposed)
+#define SCSI_CMD_SEND_CDROM_XA_DATA    0xbc
+#define SCSI_CMD_PLAY_CD              0xbc
+#define SCSI_CMD_MECH_STATUS           0xbd
+#define SCSI_CMD_READ_CD              0xbe     // read CD information (all formats, MSF addresses)
+#define SCSI_CMD_SEND_DVD_STRUCTURE    0xbf    // burning DVDs?
+
+/*
+ * A workaround for a specific scanner (NIKON LS-2000).  
+ * Can be removed once Linux backend uses 2.4.x interface
+ */
+#define SCSI_CMD_VENDOR_NIKON_UNKNOWN  0xe1
+
+#define SCSI_SENSE_KEY_NONE           0x0   // there is no sense information
+#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x1   // the last command completed succesfully but used error correction in the process
+#define SCSI_SENSE_KEY_NOT_READY       0x2   // the addressed LUN is not ready to be accessed
+#define SCSI_SENSE_KEY_MEDIUM_ERROR    0x3   // the target detected a data error on the medium
+#define SCSI_SENSE_KEY_HARDWARE_ERROR  0x4   // the target detected a hardware error during a command or self-test
+#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x5   // either the command or the parameter list contains an error
+#define SCSI_SENSE_KEY_UNIT_ATTENTION  0x6   // the LUN has been reset (bus reset of medium change)
+#define SCSI_SENSE_KEY_DATA_PROTECT    0x7   // access to the data is blocked
+#define SCSI_SENSE_KEY_BLANK_CHECK     0x8   // reached an unexpected written or unwritten region of the medium
+#define SCSI_SENSE_KEY_COPY_ABORTED    0xa   // COPY, COMPARE, or COPY AND VERIFY was aborted
+#define SCSI_SENSE_KEY_ABORTED_CMD     0xb   // the target aborted the command
+#define SCSI_SENSE_KEY_EQUAL          0xc   // comparison for SEARCH DATA was unsuccessful
+#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0xd   // the medium is full
+#define SCSI_SENSE_KEY_MISCOMPARE      0xe   // source and data on the medium do not agree
+
+/*
+ * The Additional Sense Code - ASC             and
+ *     Additional Sense Code Qualifiers - ASCQ
+ * always come in pairs. 
+ *
+ * Note:
+ *     These values are found at senseBuffer[12} and senseBuffer[13].
+ *     You may see references to these in legacy code. New code should make an
+ *     attempt to use the ASC/ASCQ syntax.
+ */
+#define SCSI_ASC_LU_NOT_READY                                   0x04  // logical unit not ready
+#define SCSI_ASC_LU_NOT_READY_ASCQ_UNIT_BECOMING_READY               0x01
+#define SCSI_ASC_LU_NOT_READY_ASCQ_INIT_CMD_REQUIRED                 0x02  // initializing command required
+#define SCSI_ASC_LU_NOT_READY_ASCQ_MANUAL_INTERVENTION_REQUIRED      0x03
+#define SCSI_ASC_LU_NOT_READY_ASCQ_TARGET_PORT_IN_TRANSITION        0x0a // an ascq
+#define SCSI_ASC_LU_NOT_READY_ASCQ_TARGET_PORT_IN_STANDBY_MODE       0x0b // an ascq
+#define SCSI_ASC_LU_NO_RESPONSE_TO_SELECTION                    0x05  // logical unit doesn't respond to selection
+#define SCSI_ASC_NO_REFERENCE_POSITION_FOUND                    0x06
+#define SCSI_ASC_WRITE_ERROR                                    0x0c  // Write error
+#define SCSI_ASC_UNRECOVERED_READ_ERROR                         0x11  // Unrecovered read error
+#define SCSI_ASC_PARAM_LIST_LENGTH_ERROR                        0x1a  // parameter list length error
+#define SCSI_ASC_INVALID_COMMAND_OPERATION                     0x20  // invalid command operation code
+#define SCSI_ASC_INVALID_FIELD_IN_CDB                           0x24
+#define SCSI_ASC_LU_NOT_SUPPORTED                               0x25  // LU has been removed
+#define SCSI_ASC_INVALID_FIELD_IN_PARAMETER_LIST                0x26
+#define SCSI_ASC_WRITE_PROTECTED                               0x27  // device is write protected
+#define SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED                        0x28  // after changing medium
+#define SCSI_ASC_POWER_ON_OR_RESET                                     0x29  // device power-on or SCSI reset
+#define SCSI_ASC_ASYMMETRIC_ACCESS_STATE_CHANGED                0x2a
+#define SCSI_ASC_INCOMPATIBLE_MEDIUM                            0x30  // Generic bad medium error
+#define SCSI_ASC_SAVING_PARAMS_NOT_SUPPORTED                    0x39  // Saving parameters not supported
+#define SCSI_ASC_MEDIUM_NOT_PRESENT                             0x3a  // changing medium
+#define SCSI_ASC_MEDIUM_NOT_PRESENT_ASCQ_TRAY_OPEN              0x02 // an ascq
+#define SCSI_ASC_INVALID_MESSAGE_ERROR                          0x49
+#define SCSI_ASC_COMMAND_PHASE_ERROR                            0x4a
+#define SCSI_ASC_DATA_PHASE_ERROR                               0x4b
+#define SCSI_ASC_MEDIUM_REMOVAL_FAILED                          0x53 // w/ 0x4 it is failed, 0x5 is prevented
+#define SCSI_ASC_INSUFFICIENT_REGISTRATION_RESOURCES            0x55 // during persistent reservations
+#define SCSI_ASCQ_INSUFFICIENT_REGISTRATION_RESOURCES           0x04 
+#define SCSI_ASCQ_ASYMMETRIC_ACCESS_STATE_CHANGED               0x06
+#define SCSI_ASCQ_TARGET_PORT_IN_STANDBY_STATE                  0x0b
+#define SCSI_ASCQ_TARGET_PORT_IN_UNAVAILABLE_STATE              0x0c
+#define SCSI_ASC_INVALID_MODE_FOR_THIS_TRACK                    0x64 
+
+#define SCSI_TAG_ENABLE                0x20    // Set to indicate tag is valid
+#define SCSI_TAG_SIMPLE                (SCSI_TAG_ENABLE|0x0)   // No constraint
+#define SCSI_TAG_HEAD          (SCSI_TAG_ENABLE|0x1)   // Always first
+#define SCSI_TAG_ORDER         (SCSI_TAG_ENABLE|0x2)   // Syncronizing
+
+#define SCSI_CMD_START_UNIT_START_BIT 0x01   // Value of Start bit for SCSI_CMD_START_UNIT
+
+/*
+ * SCSI Command Data Blocks (CDBs) come in at least four flavors:
+ *
+ * 1. 6-byte commands were originally spec'd and limit the addressable
+ *    storage to 1GByte (21 bits x 512 bytes/logical block).
+ * 2. 10-byte commands first appeared in SCSI-2; they have a 32-bit
+ *    logical block number range but transfers are limited to 64KB.
+ * 3. 12-byte commands also appeared in SCSI-2; they differ mainly
+ *    int that large amounts of data may be transferred (32-bit data length).
+ * 4. 16-byte commands were added in SCSI-3; they have additional space
+ *    for unspecified command data.
+ *
+ * We do not support 16-byte CDB's, only 6-, 10-, and 12-byte versions.
+ */
+typedef struct {
+   uint32   opcode:8,  // operation code
+           lun:3,      // logical unit number
+           lbn:21;     // logical block number
+   uint8    len;       // data length
+   uint8    ctrl;      // control byte
+} SCSICDB6;
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8       :5,
+           lun:3;
+   uint32   lbn;
+   uint8    reserved;
+   uint16   len;
+   uint8    ctrl;
+}
+#include "vmware_pack_end.h"
+SCSICDB10;
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8       :5,
+           lun:3;
+   uint32   lbn;
+   uint32   len;
+   uint8    reserved;
+   uint8    ctrl;
+}
+#include "vmware_pack_end.h"
+SCSICDB12;
+
+/*
+ * Format of INQUIRY request and response blocks.
+ * These are defined here because many SCSI devices
+ * need them.
+ */
+typedef struct {
+   uint8 opcode;           // INQUIRY (0x12)
+   uint8 evpd  :1,         // enhanced vital product data
+         cmddt :1,         // command support data (new in SCSI-3)
+         resv12:3,
+         lun   :3;
+   uint8 pagecode;         // only valid when cmddt or evdp is set
+   uint8 reserved;        
+   uint8 len;
+   uint8 ctrl;
+} SCSIInquiryCmd;
+
+/* 
+ * Format of the SCSI-3 INQUIRY command as defined in SPC-3 
+ */
+typedef struct {
+   uint8 opcode;           // INQUIRY (0x12)
+   uint8 evpd  :1,         // Enhanced Vital Product Data
+         obslt :1,         // Obsolete as per SPC-3
+         resv  :6;         // The remaining bits are all RESERVED
+   uint8 pagecode;         // Only valid when evpd is set
+   uint8 lenMSB;           // The SPC-3 spec has a 2 byte len field
+   uint8 len;
+   uint8 ctrl;
+} SCSI3InquiryCmd;
+
+typedef struct {
+   uint8 devclass    :5,   // SCSI device class
+#define SCSI_CLASS_DISK           0x00     // disk drive
+#define SCSI_CLASS_TAPE           0x01     // tape drive
+#define SCSI_CLASS_PRINTER 0x02            // printer
+#define SCSI_CLASS_CPU    0x03     // processor device
+#define SCSI_CLASS_WORM           0x04     // WORM drive
+#define SCSI_CLASS_CDROM   0x05            // CD-ROM drive
+#define SCSI_CLASS_SCANNER 0x06            // scanner
+#define SCSI_CLASS_OPTICAL 0x07            // optical disk
+#define SCSI_CLASS_MEDIA   0x08            // media changer
+#define SCSI_CLASS_COM    0x09     // communication device
+#define IDE_CLASS_CDROM    0x0a            // IDE CD-ROM drive
+#define IDE_CLASS_OTHER    0x0b            // Generic IDE
+#define SCSI_CLASS_RAID           0x0c     // RAID controller (SCSI-3, reserved in SCSI-2)
+#define SCSI_CLASS_SES            0x0d     // SCSI Enclosure Services device (t10 SES)
+#define SCSI_CLASS_UNKNOWN 0x1f            // unknown device
+        pqual       :3;   // peripheral qualifier
+#define SCSI_PQUAL_CONNECTED    0  // device described is connected to the LUN
+#define SCSI_PQUAL_NOTCONNECTED         1  // target supports such a device, but none is connected
+#define SCSI_PQUAL_NODEVICE     3  // target does not support a physical device for this LUN
+   uint8    :7,                   // reserved for SCSI-1
+        rmb:1;            // removable bit
+   uint8 ansi       :3,   // ANSI version
+#define SCSI_ANSI_SCSI1             0x0   // device supports SCSI-1
+#define SCSI_ANSI_CCS       0x1   // device supports the CCS
+#define SCSI_ANSI_SCSI2             0x2   // device supports SCSI-2
+#define SCSI_ANSI_SCSI3_SPC  0x3   // device supports SCSI-3 version SPC
+#define SCSI_ANSI_SCSI3_SPC2 0x4   // device supports SCSI-3 version SPC-2
+#define SCSI_ANSI_SCSI3_SPC3 0x5   // device supports SCSI-3 version SPC-3
+#define SCSI_ANSI_SCSI3_SPC4 0x6   // device supports SCSI-3 version SPC-4
+        ecma        :3,   // ECMA version
+        iso         :2;   // ISO version
+   uint8 dataformat  :4,   // format of the following standard data
+                    :1,
+        naca        :1,
+        tio         :1,   // device supports TERMINATE I/O PROCESS message
+        aen         :1;   // asynchronous event notification capability
+   uint8 optlen;          // length of additional data that follows
+   uint8            :8;
+#define SCSI_TPGS_NONE                       0x0
+#define SCSI_TPGS_IMPLICIT_ONLY              0x1
+#define SCSI_TPGS_IMPLICIT                  SCSI_TPGS_IMPLICIT_ONLY 
+#define SCSI_TPGS_EXPLICIT_ONLY              0x2
+#define SCSI_TPGS_EXPLICIT                   SCSI_TPGS_EXPLICIT_ONLY
+#define SCSI_TPGS_BOTH_IMPLICIT_AND_EXPLICIT 0x3
+#define SCSI_TPGS_BOTH                       SCSI_TPGS_BOTH_IMPLICIT_AND_EXPLICIT
+   uint8 adr16      :1,   // device supports 16-bit wide SCSI addresses
+        adr32       :1,   // device supports 32-bit wide SCSI addresses
+        arq         :1,
+        mchngr      :1,   // device has attached media changer (SCSI-3)
+        dualp       :1,   // device is dual-ported (SCSI-3)
+         port       :1,   // port A or port B when dual-ported (SCSI-3)
+                    :2;
+   uint8 sftr       :1,   // device supports soft reset capability
+        que         :1,   // device supports tagged commands
+        trndis      :1,   // device supports transfer disable messages (SCSI-3)
+        link        :1,   // device supports linked commands
+        sync        :1,   // device supports synchronous transfers
+        w16         :1,   // device supports 16-bit wide SCSI data transfers
+         w32        :1,   // device supports 32-bit wide SCSI data transfers
+        rel         :1;   // device supports relative addressing
+   uint8 manufacturer[8];  // manufacturer's name in ascii
+   uint8 product[16];     // product name in ascii
+   uint8 revision[4];     // product version number in ascii
+   uint8 vendor1[20];     // vendor unique data (opaque)
+   uint8 reserved[40];
+} SCSIInquiryResponse;    // standard INQUIRY response format
+
+/*
+ * Same as SCSIInquiryResponse, except that only 36 bytes long.  See above
+ * for some defines.  You should use this one and not one above unless you
+ * need vendor1/reserved fields.
+ */
+typedef struct {
+   uint8 devclass    :5,   // SCSI device class
+        pqual       :3;   // peripheral qualifier
+   uint8    :7,                   // reserved for SCSI-1
+        rmb:1;            // removable bit
+   uint8 ansi       :3,   // ANSI version
+        ecma        :3,   // ECMA version
+        iso         :2;   // ISO version
+   uint8 dataformat  :4,   // format of the following standard data
+                    :1,
+        naca        :1,
+        tio         :1,   // device supports TERMINATE I/O PROCESS message
+        aen         :1;   // asynchronous event notification capability
+   uint8 optlen;          // length of additional data that follows
+   uint8            :8;
+   uint8 adr16      :1,   // device supports 16-bit wide SCSI addresses
+        adr32       :1,   // device supports 32-bit wide SCSI addresses
+        arq         :1,
+        mchngr      :1,   // device has attached media changer (SCSI-3)
+        dualp       :1,   // device is dual-ported (SCSI-3)
+         port       :1,   // port A or port B when dual-ported (SCSI-3)
+                    :2;
+   uint8 sftr       :1,   // device supports soft reset capability
+        que         :1,   // device supports tagged commands
+        trndis      :1,   // device supports transfer disable messages (SCSI-3)
+        link        :1,   // device supports linked commands
+        sync        :1,   // device supports synchronous transfers
+        w16         :1,   // device supports 16-bit wide SCSI data transfers
+         w32        :1,   // device supports 32-bit wide SCSI data transfers
+        rel         :1;   // device supports relative addressing
+   uint8 manufacturer[8];  // manufacturer's name in ascii
+   uint8 product[16];     // product name in ascii
+   uint8 revision[4];     // product version number in ascii
+} SCSIInquiry36Response;   // standard INQUIRY response format
+
+#define SCSI_STANDARD_INQUIRY_MIN_LENGTH 36
+
+#define SCSI_INQ_PAGE_0x00 0x00
+#define SCSI_INQ_PAGE_0x80 0x80
+#define SCSI_INQ_PAGE_0x83 0x83
+
+/*
+ * The following structures define the Page format supported by the
+ * vscsi layer in vmkernel. The SPC-3 r23 spec defines a very generic
+ * layout of these pages, however the structures here are customized 
+ * for vmkernel.
+ */
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIInqPage00ResponseHeader {
+   uint8  devClass     :5,
+         pQual         :3;
+   uint8  pageCode;
+   uint8  reserved1;
+   uint8  pageLength;
+}
+#include "vmware_pack_end.h"
+SCSIInqPage00ResponseHeader;
+
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIInqPage80ResponseHeader {
+   uint8  devClass     :5,
+         pQual         :3;
+   uint8  pageCode;
+   uint8  reserved1;
+   uint8  pageLength;
+}
+#include "vmware_pack_end.h"
+SCSIInqPage80ResponseHeader;
+
+// Inquiry page 0x83: Identifier Type
+#define SCSI_IDENTIFIERTYPE_VENDOR_SPEC        0x0
+#define SCSI_IDENTIFIERTYPE_T10                0x1
+#define SCSI_IDENTIFIERTYPE_EUI                0x2
+#define SCSI_IDENTIFIERTYPE_NAA                0x3
+#define SCSI_IDENTIFIERTYPE_RTPI       0x4
+#define SCSI_IDENTIFIERTYPE_TPG                0x5
+#define SCSI_IDENTIFIERTYPE_LUG                0x6
+#define SCSI_IDENTIFIERTYPE_MD5                0x7
+#define SCSI_IDENTIFIERTYPE_SNS        0x8
+#define SCSI_IDENTIFIERTYPE_RESERVED           0x9
+#define SCSI_IDENTIFIERTYPE_MAX         SCSI_IDENTIFIERTYPE_RESERVED
+
+// Inquiry page 0x83: Transport Layer
+#define SCSI_PROTOCOLID_FCP2           0x0
+#define SCSI_PROTOCOLID_SPI5           0x1
+#define SCSI_PROTOCOLID_SSAS3P         0x2
+#define SCSI_PROTOCOLID_SBP3           0x3
+#define SCSI_PROTOCOLID_SRP            0x4
+#define SCSI_PROTOCOLID_ISCSI          0x5
+#define SCSI_PROTOCOLID_SAS            0x6
+#define SCSI_PROTOCOLID_ADT            0x7
+#define SCSI_PROTOCOLID_ATA            0x8
+#define SCSI_PROTOCOLID_RESERVED       0xE
+#define SCSI_PROTOCOLID_NO_PROTOCOL    0xF
+
+// Inquiry page 0x83: UUID Encoding
+#define SCSI_CODESET_BINARY            0x1
+#define SCSI_CODESET_ASCII             0x2
+#define SCSI_CODESET_UTF8              0x3
+#define SCSI_CODESET_RESERVED          0xF
+
+// Inquiry page 0x83: UUID Entity
+#define SCSI_ASSOCIATION_LUN           0x0
+#define SCSI_ASSOCIATION_TARGET_PORT   0x1
+#define SCSI_ASSOCIATION_TARGET_DEVICE 0x2
+#define SCSI_ASSOCIATION_RESERVED      0x3
+
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIInqPage83ResponseHeader {
+   uint8  devClass     :5,
+          pQual                :3;
+   uint8  pageCode;
+   uint16 pageLength;
+}
+#include "vmware_pack_end.h"
+SCSIInqPage83ResponseHeader;
+
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIInqPage83ResponseDescriptor {
+   /* Identification Descriptor follows */
+   uint8  codeSet     :4,
+          protocolId  :4;
+   uint8  idType      :4,
+          association :2,
+          reserved1   :1,
+          piv         :1;
+   uint8  reserved2;
+   uint8  idLength;
+}
+#include "vmware_pack_end.h"
+SCSIInqPage83ResponseDescriptor;
+
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIInquiryVPDResponseHeader {
+   uint8 devclass    :5,   // SCSI device class
+         pqual       :3;   // peripheral qualifier
+   uint8 pageCode;         // 0
+   uint8 reserved;
+   uint8 payloadLen;       // Number of additional bytes
+}
+#include "vmware_pack_end.h"
+SCSIInquiryVPDResponseHeader;
+
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIReportLunsCmd {
+   uint8 opcode;
+   uint8 reserved1;
+   uint8 selectReport;
+   uint8 reserved2[3];
+   uint32 allocLen;
+   uint16 reserved3;
+}
+#include "vmware_pack_end.h"
+SCSIReportLunsCmd;
+
+typedef
+#include "vmware_pack_begin.h"
+struct SCSIReportLunsResponse {
+   uint32 len;
+   uint32 reserved;
+   struct {
+      uint8  addressMethod:3,
+         busIdentifier:5;
+      uint8  singleLevelLun;
+      uint16 secondLevelLun;
+      uint16 thirdLevelLun;
+      uint16 fourthLevelLun;
+   } lun[1];
+}
+#include "vmware_pack_end.h"
+SCSIReportLunsResponse;
+
+#define SCSI_REPORT_LUNS_RESPONSE_LEN(n) (sizeof(SCSIReportLunsResponse) + ((n)-1) * sizeof(((SCSIReportLunsResponse*)0)->lun[0]))
+
+/*
+ * Format of 6- and 10-byte versions of the MODE SELECT
+ * and MODE SENSE request and response blocks.
+ * These are defined here because multiple SCSI devices
+ * may need them.
+ */
+typedef struct {
+   uint8    opcode;       // operation code
+   uint8         :3,
+           dbd   :1,      // disable block descriptors
+                 :1,
+           lun   :3;      // logical unit number
+   uint8    page         :6,      // page code
+#define SCSI_MS_PAGE_VENDOR   0x00     // vendor-specific (ALL)
+#define SCSI_MS_PAGE_RWERROR  0x01     // read/write error (DISK/TAPE/CDROM/OPTICAL)
+#define SCSI_MS_PAGE_CONNECT  0x02     // disconnect/connect (ALL)
+#define SCSI_MS_PAGE_FORMAT   0x03     // format (DISK)
+#define SCSI_MS_PAGE_PARALLEL 0x03     // parallel interface (PRINTER)
+#define SCSI_MS_PAGE_UNITS    0x03     // measurement units (SCANNER)
+#define SCSI_MS_PAGE_GEOMETRY 0x04     // rigid disk geometry (DISK)
+#define SCSI_MS_PAGE_SERIAL   0x04     // serial interface (PRINTER)
+#define SCSI_MS_PAGE_FLEXIBLE 0x05     // flexible disk geometry (DISK)
+#define SCSI_MS_PAGE_PRINTER  0x05     // printer operations (PRINTER)
+#define SCSI_MS_PAGE_OPTICAL  0x06     // optical memory (OPTICAL)
+#define SCSI_MS_PAGE_VERIFY   0x07     // verification error (DISK/CDROM/OPTICAL)
+#define SCSI_MS_PAGE_CACHE    0x08     // cache (DISK/CDROM/OPTICAL)
+#define SCSI_MS_PAGE_PERIPH   0x09     // peripheral device (ALL)
+#define SCSI_MS_PAGE_CONTROL  0x0a     // control mode (ALL)
+#define SCSI_MS_PAGE_MEDIUM   0x0b     // medium type (DISK/CDROM/OPTICAL)
+#define SCSI_MS_PAGE_NOTCH    0x0c     // notch partitions (DISK)
+#define SCSI_MS_PAGE_CDROM    0x0d     // CD-ROM (CDROM)
+#define SCSI_MS_PAGE_CDAUDIO  0x0e     // CD-ROM audio (CDROM)
+#define SCSI_MS_PAGE_COMPRESS 0x0f     // data compression (TAPE)
+#define SCSI_MS_PAGE_CONFIG   0x10     // device configuration (TAPE)
+#define SCSI_MS_PAGE_EXCEPT   0x1c     // informal exception (ALL:SCSI-3)
+#define SCSI_MS_PAGE_CDCAPS   0x2a     // CD-ROM capabilities and mechanical status (CDROM)
+// more defined...
+#define SCSI_MS_PAGE_ALL      0x3f     // all available pages (ALL)
+           pcf   :2;      // page control field
+#define SCSI_MS_PCF_CURRENT   0x00     // current values
+#define SCSI_MS_PCF_VOLATILE  0x01     // changeable values
+#define SCSI_MS_PCF_DEFAULT   0x02     // default values
+#define SCSI_MS_PCF_SAVED     0x03     // saved values
+   uint8    subpage;
+   uint8    length;  // data length
+   uint8    ctrl;         // control byte
+} SCSIModeSenseCmd;
+
+
+/*
+ * FORMAT UNIT command
+ */
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8  opcode;         // FORMAT UNIT (0x4)
+   uint8  dlf    :3,      // defect list format
+         cmplst :1,       // complete list
+         fmtdata:1,       // format data
+         lun    :3;
+   uint8  vendor;
+   uint16 interleave;
+   uint8  control;
+}
+#include "vmware_pack_end.h"
+SCSIFormatCmd;
+
+/*
+ * Format Defect List header
+ */
+typedef struct {
+   uint8 reserved;        
+   uint8 fov   :1,        // Format options valid
+        dpry  :1,         // disable primary
+        dcrt  :1,         // disable certification
+        stpf  :1,         // stop format
+        ip    :1,         // initialization pattern
+        dsp   :1,         // disable saving parameters
+        immed :1,         // immediate 
+        vs    :1;
+   uint16 length;         // Defect list length
+} SCSIDefectListHdr;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;       // operation code
+   uint8         :3,
+           dbd   :1,      // disable block descriptors
+                 :1,
+           lun   :3;      // logical unit number
+   uint8    page  :6,     // page code
+           pcf   :2;      // page control field
+   uint8    reserved[4];
+   uint16   length;       // data length
+   uint8    ctrl;         // control byte
+}
+#include "vmware_pack_end.h"
+SCSIModeSense10Cmd;
+
+typedef struct {
+   uint8    opcode;       // operation code
+   uint8    sp   :1,      // save pages
+                 :3,
+           pf    :1,      // page format
+           lun   :3;      // logical unit number
+   uint8    reserved[2];
+   uint8    len;          // data length
+   uint8    ctrl;         // control byte
+} SCSIModeSelectCmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;       // operation code
+   uint8    sp   :1,      // save pages
+                 :3,
+           pf    :1,      // page format
+           lun   :3;      // logical unit number
+   uint8    reserved[5];
+   uint16   len;          // data length
+   uint8    ctrl;         // control byte
+}
+#include "vmware_pack_end.h"
+SCSIModeSelect10Cmd;
+
+typedef struct {
+   uint8    len;          // data length
+   uint8    mediaType;
+   uint8    devSpecific;   // device specific
+   uint8    bdLen;        // block descriptor length
+} SCSIModeHeader6;
+
+typedef struct {
+   uint16   len;          // data length
+   uint8    mediaType;
+   uint8    devSpecific;   // device specific
+   uint16   reserved;
+   uint16   bdLen;        // block descriptor length
+} SCSIModeHeader10;
+
+typedef struct {
+   uint8 reserved1:4;
+   uint8 dpofua:1;         // disable page out / force unit access
+   uint8 reserved2:2;
+   uint8 wp:1;             // write protected
+} SCSIBlockModeSenseDeviceParameter;
+
+/*
+ * Command structure for a SCSI Reserve command.
+ */
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode:8;     // operation code
+   uint8 ext:1,
+      tid:3,
+      tparty:1,
+      lun:3;           // logical unit number
+   uint8    resid;
+   uint16   extlen;
+   uint8    control;
+}
+#include "vmware_pack_end.h"
+SCSIReserveCmd;
+
+/*
+ * There are three mandatory mode parameter pages for all device
+ * types (a fourth is added in SCSI-3).  The following structures
+ * define these pages as sent+received with MODE SENSE and SELECT.
+ */
+typedef struct {          // connect/disconnect page
+   uint8    page  :6,     // page code: 0x02
+                 :1,
+           ps    :1;
+   uint8    len;          // page length (0x0e)
+   uint8    bufFull;
+   uint8    bufEmpty;
+   uint16   maxBusInactiveTime;
+   uint16   maxBusFreeTime;
+   uint16   maxConnectTime;
+   uint16   maxBurstLength;
+   uint8    dtdc  :3,
+           dimm  :1,      // disconnect immediate (SCSI-3)
+                 :3,
+           emdp  :1;      // enable MODIFY DATA POINTER (SCSI-3)
+} SCSIConnectPage;
+
+typedef struct {          // peripheral device page
+   uint8    page  :6,     // page code: 0x09
+                 :1,
+           ps    :1;
+   uint8    len;          // page length (n-1)
+   uint16   ifID;         // physical interface identifier
+   uint8    reserved[4];
+   uint8    undefined[1];  // variable-length vendor-specific data
+} SCSIPeriphPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x0a
+                 :1,
+           ps    :1;
+   uint8    len;          // page length (0x06)
+   uint8    rlec  :1,
+           gltsd :1,
+                 :2,
+                 :4;
+   uint8    dque  :1,     // disable tagged queuing
+           qerr  :1,      // 
+                 :2,
+           qalg  :4;      // queue algorithm
+   uint8    eaenp :1,     // error AEN permission
+           uaaenp:1,      // unit attention AEN permission
+           raenp :1,      // ready AEN permission
+                 :4,
+           eeca  :1;      // 
+   uint8    reserved;
+   uint16   aenWaitTime;   // AEN waiting time after initialization
+   uint16   busyTimeout;   // busy timeout in 100ms (SCSI-3)
+} SCSIControlPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x09
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x06
+   uint8    dcr          :1,      // error recover parameters
+           dte   :1,      // diable transfer on seeing recovered error
+           per   :1,      // post error: report recovered errors
+                 :1,
+           rc    :1,      // read continuous: don't delay data transfer to correct errors
+           tb    :1,      // transfer block when unrecovered
+                 :2;
+   uint8    readRetries;   // read retry count
+   uint8    reserved[4];
+} SCSIRWErrorPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x0d
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x06
+   uint8         :8;
+   uint8    inactive:4,           // head inactivity timeout
+                 :4;
+   uint16   secsPerMinute; // number of MSF seconds per MSF minute
+   uint16   framesPerSec;  // number of MSF frames per MSF second
+} SCSICDROMPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x0e
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x0e
+   uint8         :1,
+           sotb  :1,
+           immediate:1,
+                 :5;
+   uint8         :8;
+   uint8         :8;
+   uint8    lbaFactor:4,
+                 :3,
+           aprv  :1;
+   uint16   lbaPerSec;    // number of LBAs per second
+   uint8    port0 :4,     // output port 0 select
+                 :4;
+   uint8    port0Volume;
+   uint8    port1 :4,     // output port 1 select
+                 :4;
+   uint8    port1Volume;
+   uint8    port2 :4,     // output port 2 select
+                 :4;
+   uint8    port2Volume;
+   uint8    port3 :4,     // output port 3 select
+                 :4;
+   uint8    port3Volume;
+} SCSICDROMAudioPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x2a
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x12
+   uint8    cdrRd      :1,// CD-R read per Orange Book Part II
+           cdeRd       :1,// CD-E read per Orange Book Part III
+           method2     :1,// CD-R media w/ Addressing Method 2
+                       :5;
+   uint8    cdrWr      :1,// CD-R write per Orange Book Part II
+           cdeWr       :1,// CD-E write per Orange Book Part III
+                       :6;
+   uint8    audioPlay  :1,// drive is capable of audio play
+           composite   :1,// drive is capable of delivering composite audio+video
+           digPort1    :1,// drive supports digital output (IEC958) on port 1
+           digPort2    :1,// drive supports digital output on port 2
+           mode2Form1  :1,// drive reads Mode 2 Form 1 (XA) format
+           mode2Form2  :1,// drive reads Mode 2 Form 2 format
+           multiSession:1,// drive reads multi-session or Photo-CD discs
+                       :1;
+   uint8    cdDA       :1,// CD-DA commands (Red Book) supported
+           daAccu      :1,// CD-DA stream is accurate
+           rwSupported :1,// R-W supported
+           rwDeinter   :1,// R-W subchannel data de-interleaved and corrected
+           c2Ptrs      :1,// C2 Error Pointers supported
+           isrc        :1,// drive returns International Standard Recording Code Info
+           upc         :1,// drive returns Media Catalog Number
+                       :1;
+   uint8    lock       :1,// PREVENT/ALLOW commands lock media into drive
+           lockState   :1,// current state of drive
+           jumpers     :1,// state of prevent/allow jumpers
+           eject       :1,// drive can eject disc via START/STOP command
+                       :1,
+           loadType    :3;// loading mechanism type
+   uint8    sv         :1,// separate volume
+           scm         :1,// separate channel mute
+           sdp         :1,// supports disc present in MECHANISM STATUS command
+           sss         :1,// s/w slot selection w/ LOAD/UNLOCK command
+                       :4;
+   uint16   maxSpeed;     // maximum speed supported (in KB/s)
+   uint16   numVolLevels;  // number of volume levels supported
+   uint16   bufSize;      // buffer size supported by drive (KBytes)
+   uint16   curSpeed;     // current speed selected (in KB/s)
+   uint8    reserved;
+   uint8               :1,// format of digital data output
+           bck         :1,// data is valid on the falling edge of BCK
+           rck         :1,// HIGH on LRCK indicates left channel
+           lsbf        :1,// LSB first
+           length      :2,
+                       :2;
+   uint8    reserved2[2];
+} SCSICDROMCapabilitiesPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x03
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x16
+   uint16   tracksPerZone;
+   uint16   repSectorsPerZone;
+   uint16   repTracksPerZone;
+   uint16   replTracksPerLUN;
+   uint16   sectorsPerTrack;
+   uint16   bytesPerSector;
+   uint16   interleave;
+   uint16   trackSkew;
+   uint16   cylinderSkew;
+   uint8         :3,
+           surf  :1,
+           rmb   :1,
+           hsec  :1,
+           ssec  :1;
+   uint8    reserved[3];
+} SCSIFormatPage;
+
+typedef uint8 uint24[3];
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x04
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x16
+   uint24   cylinders;    // number of cylinders
+   uint8    heads;        // number of heads
+   uint24   writeCompCylinder; // starting cylinder for write compensation
+   uint24   writeCurCylinder; // starting cylinder for reduce write current
+   uint16   stepRate;
+   uint24   landingZone;   // cylinder number of landing zone
+   uint8    rpl          :1,
+                 :7;
+   uint8    rotOffset;    // rotational offset
+   uint8         :8;
+   uint16   rotRate;      // medium rotation rate
+   uint8    reserved[2];
+} SCSIGeometryPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x08
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x0a (0x12 for SCSI-3)
+   uint8    rcd          :1,
+           mf    :1,
+           wce   :1,
+                 :5;
+   uint8    readPri:4,    // read retention priority
+           writePri:4;    // write retention priority
+   uint16   prefetchDisable;// disable pre-fetch transfer length
+   uint16   prefetchMin;   // pre-fetch minimum
+   uint16   prefetchMax;   // pre-fetch maximum
+   uint16   prefetchAbsMax;// absolute pre-fetch maximum
+} SCSICachePage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x08
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x16
+   uint8         :6,
+           lpn   :1,
+           nd    :1;
+   uint8         :8;
+   uint16   maxNotches;           // maximum number of notches
+   uint16   activeNotch;
+   uint32   activeStart;   // beginning of active notch
+   uint32   activeEnd;    // end of active notch
+} SCSINotchPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x06
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x02
+   uint8    rubr  :1,
+                 :7;
+   uint8         :8;
+} SCSIOpticalPage;
+typedef struct {
+   uint8    page  :6,     // page code: 0x0f
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x0e
+   uint8         :6,
+           dcc   :1,
+           dce   :1;
+   uint8         :5,
+           red   :2,
+           dde   :1;
+   uint8  compAlg[4];
+   uint8  decompAlg[4];
+   uint8  reserved[4];
+} SCSICompressionPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x10
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x0e
+   uint8    format:5,     // active format
+           car   :1,
+           cap   :1,
+                 :1;
+   uint8    partition;    // active partition
+   uint8    wbeRatio;     // write buffer empty ratio
+   uint8    rbeRatio;     // read buffer empty ratio
+   uint16   writeDelay;
+   uint8    rew          :1,
+           rb0   :1,
+           sofc  :2,
+           avc   :1,
+           rsmk  :1,
+           bis   :1,
+           dbr   :1;
+   uint8    gapSize;
+   uint8         :3,
+           sew   :1,
+           eeg   :1,
+           eod   :3;
+   uint24   bufSizeAtEW;
+   uint8    compression;
+   uint8         :8;
+} SCSIDeviceConfigPage;
+
+typedef struct {
+   uint8    page  :6,     // page code: 0x03
+                 :1,
+           ps    :1;
+   uint8    len;          // page length 0x06
+   uint8    unit;         // measurement unit
+   uint8         :8;
+   uint16   divisor;
+   uint16        :16;
+} SCSIUnitsPage;
+
+
+/*
+ * Format of START STOP UNIT (0x1b).
+ */
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;       // 0x1b
+   uint8 immed:1,
+          rsvd:7;
+   uint8 reserved[2];
+   uint8  start:1,
+           loej:1,      // load/eject
+          rsvd1:2,
+          power:4;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIStartStopUnitCmd;
+
+
+/*
+ * Format of ALLOW PREVENT MEDIUM REMOVAL (0x1e).
+ */
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;       // 0x1e
+   uint8 reserved[3];
+   uint8 prevent:2,
+                :6;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIMediumRemovalCmd;
+
+
+/*
+ * Format of READ CAPACITY (10) and (16) request and response blocks.
+ * These are defined here because multiple SCSI devices
+ * need them.
+ */
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;       // 0x25
+   uint8 rel   :1,
+              :4,
+        lun   :3;
+#define SCSI_RW10_MAX_LBN 0xffffffffu
+   uint32 lbn;
+   uint8 reserved[2];
+   uint8 pmi   :1,
+              :7;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIReadCapacityCmd;
+
+typedef struct {
+   uint32 lbn;
+   uint32 blocksize;
+} SCSIReadCapacityResponse;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;       // 0x9e
+#define SCSI_READ_CAPACITY16_SERVICE_ACTION 0x10
+   uint8 action:5,
+              :3;
+   uint64 lbn;
+   uint32 len;
+   uint8 pmi   :1,
+        rel   :1,
+              :6;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIReadCapacity16Cmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint64 lbn;
+   uint32 blocksize;
+}
+#include "vmware_pack_end.h"
+SCSIReadCapacity16Response;
+
+/*
+ * Format of READ/WRITE (6), (10), (12) and (16)
+ * request. These are defined here because multiple SCSI
+ * devices need them.
+ */
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint32 opcode:8,
+         lun:3,
+         lbn:21;
+   uint8  length;
+   uint8  control;
+}
+#include "vmware_pack_end.h"
+SCSIReadWrite6Cmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;
+   uint8 rel   :1,
+              :2,
+        flua  :1,
+        dpo   :1,
+        lun   :3;
+   uint32 lbn;
+   uint8 reserved;
+   uint16 length;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIReadWrite10Cmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;
+   uint8 rel   :1,
+              :2,
+        flua  :1,
+        dpo   :1,
+        lun   :3;
+   uint32 lbn;
+   uint32 length;
+   uint8 reserved;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIReadWrite12Cmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 opcode;
+   uint8 rel   :1,
+              :2,
+        flua  :1,
+        dpo   :1,
+              :3;
+   uint64 lbn;
+   uint32 length;
+   uint8 reserved;
+   uint8 control;
+}
+#include "vmware_pack_end.h"
+SCSIReadWrite16Cmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8    xtnt  :1,           // extent-based reservation
+            ptyID :3,           // 3rd party reservation ID
+            pty          :1,    // 3rd party reservation
+            lun          :3;    // logical unit number
+   uint8    resvID;             // SCSI-3: reservation ID
+   uint16   resvListLen;        // SCSI-3: reservation list length
+   uint8    ctrl;               // control byte
+}
+#include "vmware_pack_end.h"
+SCSIReserveUnitCmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8    xtnt  :1,           // extent-based reservation
+            ptyID :3,           // 3rd party reservation ID
+            pty   :1,           // 3rd party reservation
+            lun   :3;           // logical unit number
+   uint8    resvID;             // SCSI-3: reservation ID
+   uint8    reserved[2];
+   uint8    ctrl;               // control byte
+} 
+#include "vmware_pack_end.h"
+SCSIReleaseUnitCmd;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8    uniO  :1,           // unit offline
+            devO  :1,           // device offline
+            st    :1,           // self-test
+                  :1,
+            pf    :1,           // page format
+            lun   :3;           // logical unit number
+   uint8    reserved;
+   uint16   len;                // data length
+   uint8    ctrl;               // control byte
+}
+#include "vmware_pack_end.h"
+SCSISendDiagnosticCmd;
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8    relAdr  :1,         // relative address
+            bytChk  :1,         // byte
+            blkvfy  :1,         // blank blocks verification, scsi-3
+                    :1,
+            dpo     :1,         // cache control bit
+            lun     :3;         // logical unit number
+   uint32   lbn;                // logical block address
+   uint8    reserved;
+   uint16   len;                // verification length
+   uint8    ctrl;               // control byte
+}
+#include "vmware_pack_end.h"
+SCSIVerify10Cmd;
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8    opcode;
+   uint8    polled   :1,        // asynchronous or not
+                     :7;
+   uint8    reserved0[2];
+#define SCSI_GESN_CLASS_RSVD0           (1 << 0)
+#define SCSI_GESN_CLASS_OP_CHANGE       (1 << 1)
+#define SCSI_GESN_CLASS_POW_MGMT        (1 << 2)
+#define SCSI_GESN_CLASS_EXT_REQ         (1 << 3)
+#define SCSI_GESN_CLASS_MEDIA           (1 << 4)
+#define SCSI_GESN_CLASS_MULTI_HOST      (1 << 5)
+#define SCSI_GESN_CLASS_DEV_BUSY        (1 << 6)
+#define SCSI_GESN_CLASS_RSVD1           (1 << 7)
+   uint8    notifyClassReq;      // the class of events we are interested in
+   uint8    reserved1[2];
+   uint16   length;             // allocation length
+   uint8    control;
+}
+#include "vmware_pack_end.h"
+SCSIGetEventStatusNotificationCmd;
+
+/*
+ * Format of Persistent Reservation Commands per SPC-3 r23, required for 
+ * virtualizing reservations.
+ */
+
+/* Persistent Reserve IN service actions */
+typedef enum {
+   READ_KEYS                      = 0x0,
+   READ_RESERVATION               = 0x1,
+   REPORT_CAPABILITIES            = 0x2,
+   READ_FULL_STATUS               = 0x3
+} SCSIPersistentReserveInServiceAction;
+
+/* 
+ * Persistent reservation type codes 
+ */
+typedef enum {
+   WRITE_EXCL                     = 0x1,
+   EXCL_ACCESS                    = 0x3,
+   WRITE_EXCL_REG_ONLY            = 0x5,
+   EXCL_ACCESS_REG_ONLY           = 0x6,
+   WRITE_EXCL_ALL_REG             = 0x7,
+   EXCL_ACCESS_ALL_REG            = 0x8
+} SCSIPersistentReserveTypeCode;
+
+typedef 
+#include "vmware_pack_begin.h"
+struct { 
+   uint8  opcode; 
+   uint8  serviceAction :5,
+          reserved      :3;
+   uint8  reserved1[5];
+   uint16 allocationLength;
+   uint8  control;
+} 
+#include "vmware_pack_end.h"
+SCSIPersistentReserveInCmd;
+
+/* Persistent Reserve Out Service Actions */
+typedef enum {
+   REGISTER                          = 0x0,
+   PRESERVE                          = 0x1,
+   PRELEASE                          = 0x2,
+   CLEAR                             = 0x3,
+   PREEMPT                           = 0x4,
+   PREEMPT_AND_ABORT                 = 0x5,
+   REGISTER_AND_IGNORE_EXISTING_KEY  = 0x6,
+   REGISTER_AND_MOVE                 = 0x7
+} SCSIPersistentReserveOutServiceAction;
+
+
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8  opcode;
+   uint8  serviceAction :5,
+          reserved      :3;
+   uint8  type          :4,
+          scope         :4;
+   uint8  reserved1[2];
+   uint32 parameterListLength; 
+   uint8  control;
+} 
+#include "vmware_pack_end.h"
+SCSIPersistentReserveOutCmd;
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint64 reservationKey;
+   uint64 serviceActionResKey;
+   uint8  obsolete1[4];
+   uint8  aptpl          :1,
+          reserved1      :1,
+          all_tg_pt      :1,
+          spec_i_pt      :1,
+          reserved2      :4;
+   uint8  reserved3;
+   uint8  obsolete2[2];
+   /*
+    * Per SPC-3 r23, the parameter list length shall be 24 bytes in length if the
+    * following are true:
+    *  a. the SPEC_I_PT but is set to 0
+    *  b. service action is not REGISTER AND MOVE
+    * 
+    * This is currently the only supported mode in the vmkernel,
+    * so no additional parameter data is included in this struct
+    */
+} 
+#include "vmware_pack_end.h"
+SCSIPersistentReserveOutPList;
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint32 prGeneration;
+   uint32 additionalLength;
+   uint64 reservationKey;
+   uint8  obsolete[4];
+   uint8  reserved;
+   uint8  type      :4,
+          scope     :4;
+   uint8 obsolete1[2];
+} 
+#include "vmware_pack_end.h"
+SCSIPRReadReservationResp;
+
+
+/*
+ * Format of the sense data structure maintained in each SCSI
+ * device.  Devices should fill in this data structure whenever
+ * they return a CHECK status for a SCSI command.  The contents
+ * is returned to the initiator either through the adapter doing
+ * an auto-sense request or the initiator doing an explicit
+ * REQUEST SENSE SCSI operation.  A device keeps only one copy
+ * of sense data at a time; the base SCSI device support invalidates
+ * this data structure before each SCSI operation as needed.
+ */
+typedef 
+#include "vmware_pack_begin.h"
+struct {
+   uint8 error   :7,      // 0x70 for current command, 0x71 for earlier command
+#define SCSI_SENSE_ERROR_CURCMD  0x70      // sense data is for "current command"
+#define SCSI_SENSE_ERROR_PREVCMD 0x71      // sense data is for an earlier command
+        valid    :1;      // sense data valid
+/* NB: Please Note that the valid bit above does NOT tell you whether
+ * the sense is actually valid and thus the name is really badly chosen
+ * (even though it is the official name from the SCSI II specification).
+ * The SCSI II spec. states "A valid bit of zero indicates that the
+ * information field is not as defined in this International Standard".
+ * we have seen that many tape drives are capable of returning sense
+ * without this bit set....
+ */
+   uint8 segment;         // segment number
+   uint8 key     :4,      // sense key
+                 :1,
+        ili      :1,
+        eom      :1,
+        filmrk   :1;
+   uint8 info[4];         // general information
+   uint8 optLen;          // length of optional data that follows
+   uint8 cmdInfo[4];      // command-specific information
+   uint8 code;            // sense code
+   uint8 xcode;                   // extended sense code
+   uint8 fru;             // 
+   uint8 bitpos          :3,
+        bpv      :1,
+                 :2,
+        cd       :1,      // 1 if error in command, 0 if in data
+        sksv     :1;      // sense key specific data is valid
+   uint16 epos;                   // offset of first byte in error
+   
+   // Some vendors want to return additional data which
+   // requires a sense buffer of up to 64 bytes.
+   uint8 additional[46];
+}
+#include "vmware_pack_end.h"
+SCSISenseData;
+
+
+/*
+ * Read (DVD) Disc Structure definitions.
+ */
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint8  opcode;
+#define SCSI_RDS_MT_DVD  0x0
+#define SCSI_RDS_MT_BD   0x1
+   uint8  mediaType:4,
+                   :4;
+   uint32 address;
+   uint8  layerNumber;
+                                                /* Layer, Address */
+#define SCSI_RDS_GDS_AACS_VOLUME_ID        0x80
+#define SCSI_RDS_GDS_AACS_MEDIA_SERIAL_NUM 0x81
+#define SCSI_RDS_GDS_AACS_MEDIA_ID         0x82
+#define SCSI_RDS_GDS_AACS_MEDIA_KEY        0x83 /* Layer number, Pack Number */
+#define SCSI_RDS_GDS_LAYERS_LIST           0x90
+#define SCSI_RDS_GDS_WRITE_PROTECT         0xC0
+#define SCSI_RDS_GDS_CAPABILITY_LIST       0xFF
+
+#define SCSI_RDS_DVD_PHYSICAL_INFO_LEADIN  0x00 /* Layer, - */
+#define SCSI_RDS_DVD_COPYRIGHT_INFO_LEADIN 0x01 /* Layer, - */
+#define SCSI_RDS_DVD_DISC_KEY              0x02
+#define SCSI_RDS_DVD_BURST_CUTTING_AREA    0x03
+#define SCSI_RDS_DVD_DISC_MANUFACTURING    0x04 /* Layer, - */
+#define SCSI_RDS_DVD_COPYRIGHT_INFO_SECTOR 0x05 /* -, LBA */
+#define SCSI_RDS_DVD_MEDIA_ID              0x06
+#define SCSI_RDS_DVD_MEDIA_KEY             0x07 /* -, Pack Number */
+#define SCSI_RDS_DVD_DVDRAM_DDS_INFO       0x08
+#define SCSI_RDS_DVD_DVDRAM_MEDIUM_STATUS  0x09
+#define SCSI_RDS_DVD_DVDRAM_SPARE_AREA     0x0A
+#define SCSI_RDS_DVD_DVDRAM_RECORDING_TYPE 0x0B
+#define SCSI_RDS_DVD_RMD_BORDEROUT         0x0C
+#define SCSI_RDS_DVD_RMD_SECTOR            0x0D /* -, Start Field Number of RMA blocks */
+#define SCSI_RDS_DVD_PRERECORDED_LEADIN    0x0E
+#define SCSI_RDS_DVD_DVDR_MEDIA_ID         0x0F
+#define SCSI_RDS_DVD_DVDR_PHYSICAL_INFO    0x10 /* Layer, - */
+#define SCSI_RDS_DVD_ADIP_INFO             0x11 /* Layer, - */
+#define SCSI_RDS_DVD_HDDVD_CPI             0x12 /* Layer, - */
+#define SCSI_RDS_DVD_HDVD_COPYRIGHT_DATA   0x15 /* Layer, Start Copyright Sector */
+#define SCSI_RDS_DVD_HDDVDR_MEDIUM_STATUS  0x19
+#define SCSI_RDS_DVD_HDDVDR_RMD            0x1A
+
+#define SCSI_RDS_DVD_DL_LAYER_CAPACITY     0x20
+#define SCSI_RDS_DVD_DL_MIDDLE_ZONE_START  0x21
+#define SCSI_RDS_DVD_DL_JUMP_INTERVAL_SIZE 0x22
+#define SCSI_RDS_DVD_DL_MANUAL_LAYER_JUMP  0x23
+#define SCSI_RDS_DVD_DL_REMAPPING          0x24 /* -, Anchor Point Number */
+
+#define SCSI_RDS_DVD_DCB_IDENTIFIER        0x30 /* Session Number, Content Descriptor */
+#define SCSI_RDS_DVD_MTA_ECC               0x31 /* -, PSN */
+
+#define SCSI_RDS_BD_DI                     0x00
+#define SCSI_RDS_BD_DDS                    0x08
+#define SCSI_RDS_BD_CARTRIDGE_STATUS       0x09
+#define SCSI_RDS_BD_SPARE_AREA             0x0A
+#define SCSI_RDS_BD_RAW_DFL                0x12 /* -, Offset */
+#define SCSI_RDS_BD_PAC                    0x30 /* -, ID and Format Number */
+   uint8  format;
+   uint16 length;
+   uint8      :6,
+          agid:2;
+   uint8  control;
+}
+#include "vmware_pack_end.h"
+SCSIReadDiscStructureCmd;
+
+typedef
+#include "vmware_pack_begin.h"
+struct {
+   uint16 length;
+   uint16 rsvd;
+   uint8  partVersion:4,
+#define SCSI_RDS_DC_DVD_ROM        0x0
+#define SCSI_RDS_DC_DVD_RAM        0x1
+#define SCSI_RDS_DC_DVD_R          0x2
+#define SCSI_RDS_DC_DVD_RW         0x3
+#define SCSI_RDS_DC_HD_DVD_ROM     0x4
+#define SCSI_RDS_DC_HD_DVD_RAM     0x5
+#define SCSI_RDS_DC_HD_DVD_R       0x6
+#define SCSI_RDS_DC_DVD_PLUS_RW    0x9
+#define SCSI_RDS_DC_DVD_PLUS_R     0xA
+#define SCSI_RDS_DC_DVD_PLUS_RW_DL 0xD
+#define SCSI_RDS_DC_DVD_PLUS_R_DL  0xE
+          diskCategory:4;
+#define SCSI_RDS_MR_1X             0x0
+#define SCSI_RDS_MR_2X             0x1
+#define SCSI_RDS_MR_4X             0x2
+#define SCSI_RDS_MR_8X             0x3
+#define SCSI_RDS_MR_16X            0x4
+#define SCSI_RDS_MR_UNSPECIFIED    0xF
+   uint8  maximumRate:4,
+#define SCSI_RDS_DS_120MM          0x0
+#define SCSI_RDS_DS_80MM           0x1
+          discSize:4;
+/* layerType is bitvector */
+#define SCSI_RDS_LT_EMBOSSED       0x1
+#define SCSI_RDS_LT_RECORDABLE     0x2
+#define SCSI_RDS_LT_REWRITEABLE    0x4
+   uint8  layerType:4,
+          track:1,
+#define SCSI_RDS_LAYERS_SL         0x0
+#define SCSI_RDS_LAYERS_DL         0x1
+          layers:2,
+          :1;
+#define SCSI_RDS_TD_740NM          0x0
+#define SCSI_RDS_TD_800NM          0x1
+#define SCSI_RDS_TD_615NM          0x2
+#define SCSI_RDS_TD_400NM          0x3
+#define SCSI_RDS_TD_340NM          0x4
+   uint8  trackDensity:4,
+#define SCSI_RDS_LD_267NM          0x0
+#define SCSI_RDS_LD_293NM          0x1
+#define SCSI_RDS_LD_420NM          0x2
+#define SCSI_RDS_LD_285NM          0x4
+#define SCSI_RDS_LD_153NM          0x5
+#define SCSI_RDS_LD_135NM          0x6
+#define SCSI_RDS_LD_353NM          0x8
+          linearDensity:4;
+#define SCSI_RDS_STARTPSN_DVD      0x030000
+#define SCSI_RDS_STARTPSN_DVDRAM   0x031000
+#define SCSI_RDS_MAXSIZE_DVD       0xF80000
+   uint32 startPSN;
+   uint32 endPSN;
+   uint32 endPSNLayer0;
+   uint8  :7,
+          bca:1;
+   uint8  rsvd2[2048 - 17];
+}
+#include "vmware_pack_end.h"
+SCSIRDSDVDPhysicalInfoLeadin;
+
+
+/*
+ * Host and device status definitions.
+ *
+ * These mimic the BusLogic adapter-specific definitions but are
+ * intended to be adapter-independent (i.e. adapters that don't
+ * define these values directly or define them with different values
+ * must map them to known values).
+ */
+
+/*
+ * host adapter status/error codes
+ */
+typedef enum {
+   BTSTAT_SUCCESS       = 0x00,  // CCB complete normally with no errors
+   BTSTAT_LINKED_COMMAND_COMPLETED           = 0x0a,
+   BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG = 0x0b,
+   BTSTAT_DATA_UNDERRUN = 0x0c,
+   BTSTAT_SELTIMEO      = 0x11,  // SCSI selection timeout
+   BTSTAT_DATARUN       = 0x12,  // data overrun/underrun
+   BTSTAT_BUSFREE       = 0x13,  // unexpected bus free
+   BTSTAT_INVPHASE      = 0x14,  // invalid bus phase or sequence requested by target
+   BTSTAT_INVCODE       = 0x15,  // invalid action code in outgoing mailbox
+   BTSTAT_INVOPCODE     = 0x16,  // invalid operation code in CCB
+   BTSTAT_LUNMISMATCH   = 0x17,  // linked CCB has different LUN from first CCB
+   BTSTAT_INVPARAM      = 0x1a,  // invalid parameter in CCB or segment list
+   BTSTAT_SENSFAILED    = 0x1b,  // auto request sense failed
+   BTSTAT_TAGREJECT     = 0x1c,  // SCSI II tagged queueing message rejected by target
+   BTSTAT_BADMSG        = 0x1d,  // unsupported message received by the host adapter
+   BTSTAT_HAHARDWARE    = 0x20,  // host adapter hardware failed
+   BTSTAT_NORESPONSE    = 0x21,  // target did not respond to SCSI ATN, sent a SCSI RST
+   BTSTAT_SENTRST       = 0x22,  // host adapter asserted a SCSI RST
+   BTSTAT_RECVRST       = 0x23,  // other SCSI devices asserted a SCSI RST
+   BTSTAT_DISCONNECT    = 0x24,  // target device reconnected improperly (w/o tag)
+   BTSTAT_BUSRESET      = 0x25,  // host adapter issued BUS device reset
+   BTSTAT_ABORTQUEUE    = 0x26,  // abort queue generated
+   BTSTAT_HASOFTWARE    = 0x27,  // host adapter software error
+   BTSTAT_HATIMEOUT     = 0x30,  // host adapter hardware timeout error
+   BTSTAT_SCSIPARITY    = 0x34,  // SCSI parity error detected
+} HostBusAdapterStatus;
+
+// scsi device status values
+typedef enum {
+   SDSTAT_GOOD                    = 0x00, // no errors
+   SDSTAT_CHECK                   = 0x02, // check condition
+   SDSTAT_CONDITION_MET           = 0x04, // condition met
+   SDSTAT_BUSY                    = 0x08, // device busy
+   SDSTAT_INTERMEDIATE            = 0x10, 
+   SDSTAT_INTERMEDIATE_CONDITION  = 0x14,
+   SDSTAT_RESERVATION_CONFLICT    = 0x18, // device reserved by another host
+   SDSTAT_COMMAND_TERMINATED      = 0x22,
+   SDSTAT_TASK_SET_FULL           = 0x28, 
+   SDSTAT_ACA_ACTIVE              = 0x30, 
+   SDSTAT_TASK_ABORTED            = 0x40, 
+} SCSIDeviceStatus;
+
+typedef enum {
+   SCSI_XFER_AUTO     = 0,    // transfer direction depends on opcode
+   SCSI_XFER_TOHOST   = 1,    // data is from device -> adapter
+   SCSI_XFER_TODEVICE = 2,    // data is from adapter -> device
+   SCSI_XFER_NONE     = 3     // data transfer is suppressed
+} SCSIXferType;
+
+typedef enum {
+   SCSI_EMULATE               = 0,   // emulate this command
+   SCSI_DONT_EMULATE          = 1,   // do not emulate this command but log a message
+   SCSI_DONT_EMULATE_DONT_LOG = 2    // do not emulate this command or log a message
+} SCSIEmulation;
+
+#define HBA_SCSI_ID  7                    //default HBA SCSI ID
+
+/*
+ *---------------------------------------------------------------------------
+ * 
+ * SCSICdb_IsRead --
+ *
+ *      This function returns TRUE if the scsi command passed as an argument is
+ *      a read.
+ *
+ * Results:
+ *      TRUE/FALSE
+ *
+ * Side effects:
+ *      None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+SCSICdb_IsRead(uint8 cdb0)        // IN
+{
+   return cdb0 == SCSI_CMD_READ6 
+       || cdb0 == SCSI_CMD_READ10
+       || cdb0 == SCSI_CMD_READ12
+       || cdb0 == SCSI_CMD_READ16;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ * 
+ * SCSICdb_IsWrite --
+ *
+ *      This function returns TRUE if the scsi command passed as an argument is
+ *      a write.
+ *
+ * Results:
+ *      TRUE/FALSE
+ *
+ * Side effects:
+ *      None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+SCSICdb_IsWrite(uint8 cdb0)       // IN
+{
+   return cdb0 == SCSI_CMD_WRITE6 
+       || cdb0 == SCSI_CMD_WRITE10
+       || cdb0 == SCSI_CMD_WRITE12
+       || cdb0 == SCSI_CMD_WRITE16;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SCSICdb_IsRW --
+ *
+ *      This function returns TRUE if the scsi command passed as an argument is
+ *      a read or write.
+ *
+ * Results:
+ *      TRUE/FALSE
+ *
+ * Side effects:
+ *      None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+SCSICdb_IsRW(uint8 cdb0)        // IN
+{
+   return SCSICdb_IsRead(cdb0) || SCSICdb_IsWrite(cdb0);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ * 
+ * SCSICdb_GetLengthFieldOffset --
+ *
+ *      Returns the offset in bytes of the 'length' field in the CDB
+ *      of a given command.
+ *
+ * Results:
+ *      Offset of 'length' field.
+ *
+ * Side effects:
+ *      None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+SCSICdb_GetLengthFieldOffset(uint8 cmd)
+{
+   switch (cmd) {
+   case SCSI_CMD_READ10:
+   case SCSI_CMD_WRITE10:
+      return offsetof(SCSIReadWrite10Cmd, length);
+   case SCSI_CMD_READ6:
+   case SCSI_CMD_WRITE6:
+      return offsetof(SCSIReadWrite6Cmd, length);
+   case SCSI_CMD_READ16:
+   case SCSI_CMD_WRITE16:
+      return offsetof(SCSIReadWrite16Cmd, length);
+   case SCSI_CMD_READ12:
+   case SCSI_CMD_WRITE12:
+      return offsetof(SCSIReadWrite12Cmd, length);
+   default:
+      return 0;
+   }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SCSI3InquiryLen --
+ *
+ *      Returns 16-bit allocation length specified in SCSI3 Inquriy CMD cmd 
+ *
+ * Results:
+ *      16-bit allocation length.
+ *
+ * Side effects:
+ *      None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static INLINE uint16
+SCSI3InquiryLen(SCSI3InquiryCmd *inqCmd)        // IN
+{
+  return (inqCmd->lenMSB << 8) + inqCmd->len;
+}
+
+
+typedef 
+#include "vmware_pack_begin.h"
+struct SCSICmdInfo {
+   uint8 code;
+   uint8 xferType;
+   char *name;
+   uint8 emulation;
+}
+#include "vmware_pack_end.h"
+SCSICmdInfo;
+
+/* This array contains the data below defined in SCSI_CMD_INFO_DATA, but
+ * can't assign the data here because it would be included in all .o, so
+ * it should be initialized in one .o file for each part of the product.
+ * In vmm, this is currently initialized in buslogicMdev.c.
+ * In vmx, this is currently initialized in usbAnalyzer.c.
+ * In vmkernel, this is currently initialized in vmk_scsi.c.
+ */
+extern SCSICmdInfo scsiCmdInfo[256];
+#define SCSI_CMD_GET_CODE(cmd)     (scsiCmdInfo[cmd].code)
+#define SCSI_CMD_GET_XFERTYPE(cmd) (scsiCmdInfo[cmd].xferType)
+#define SCSI_CMD_GET_NAME(cmd)     (scsiCmdInfo[cmd].name)
+#define SCSI_CMD_GET_EMULATION(cmd) (scsiCmdInfo[cmd].emulation)
+
+#define SCSI_CMD_INFO_DATA \
+   {SCSI_CMD_TEST_UNIT_READY,  SCSI_XFER_NONE,     "TEST UNIT READY", SCSI_EMULATE}, \
+   {SCSI_CMD_REZERO_UNIT,      SCSI_XFER_NONE,     "REWIND/REZERO UNIT", SCSI_DONT_EMULATE}, \
+   {0x02,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_REQUEST_SENSE,    SCSI_XFER_TOHOST,   "REQUEST SENSE", SCSI_EMULATE},     \
+   {SCSI_CMD_FORMAT_UNIT,      SCSI_XFER_TODEVICE, "FORMAT UNIT", SCSI_EMULATE},       \
+   {SCSI_CMD_READ_BLOCKLIMITS, SCSI_XFER_TOHOST,   "READ BLOCK LIMITS", SCSI_DONT_EMULATE},\
+   {0x06,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_INIT_ELEMENT_STATUS, SCSI_XFER_AUTO,  NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ6,            SCSI_XFER_TOHOST,   "READ(6)", SCSI_EMULATE},           \
+   {0x09,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_WRITE6,           SCSI_XFER_TODEVICE, "WRITE(6)", SCSI_EMULATE},  \
+   {SCSI_CMD_SLEW_AND_PRINT,   SCSI_XFER_TODEVICE, NULL, SCSI_DONT_EMULATE},               \
+   {0x0c,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x0d,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x0e,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_REVERSE,     SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_SYNC_BUFFER,      SCSI_XFER_NONE,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_SPACE,            SCSI_XFER_NONE,     "SPACE", SCSI_DONT_EMULATE},            \
+   {SCSI_CMD_INQUIRY,          SCSI_XFER_TOHOST,   "INQUIRY", SCSI_EMULATE}, \
+   {0x13,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_RECOVER_BUFFERED, SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_MODE_SELECT,      SCSI_XFER_TODEVICE, "MODE SELECT(6)", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_RESERVE_UNIT,     SCSI_XFER_NONE,     "RESERVE(6)", SCSI_EMULATE},        \
+   {SCSI_CMD_RELEASE_UNIT,     SCSI_XFER_NONE,     "RELEASE(6)", SCSI_EMULATE},        \
+   {SCSI_CMD_COPY,             SCSI_XFER_AUTO,     "COPY AND VERIFY", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_ERASE,            SCSI_XFER_NONE,     "ERASE", SCSI_DONT_EMULATE},            \
+   {SCSI_CMD_MODE_SENSE,       SCSI_XFER_TOHOST,   "MODE SENSE(6)", SCSI_EMULATE},   \
+   {SCSI_CMD_SCAN,             SCSI_XFER_TODEVICE, NULL, SCSI_EMULATE},                \
+   {SCSI_CMD_RECV_DIAGNOSTIC,  SCSI_XFER_AUTO,     "RECEIVE DIAGNOSTIC RESULTS", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_SEND_DIAGNOSTIC,  SCSI_XFER_TODEVICE, "SEND DIAGNOSTIC", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_MEDIUM_REMOVAL,   SCSI_XFER_NONE,     "LOCK/UNLOCK DOOR", SCSI_DONT_EMULATE_DONT_LOG}, \
+   {0x1f,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x20,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x21,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x22,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_FORMAT_CAPACITIES, SCSI_XFER_TOHOST, "READ FORMAT CAPACITIES", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_SET_WINDOW,       SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_CAPACITY,    SCSI_XFER_TOHOST,   "READ CAPACITY", SCSI_EMULATE},     \
+   {0x26,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x27,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ10,           SCSI_XFER_TOHOST,   "READ(10)", SCSI_EMULATE},  \
+   {SCSI_CMD_READ_GENERATION,  SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_WRITE10,          SCSI_XFER_TODEVICE, "WRITE(10)", SCSI_EMULATE}, \
+   {SCSI_CMD_SEEK10,           SCSI_XFER_NONE,     NULL, SCSI_DONT_EMULATE},               \
+   {0x2c,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_UPDATED_BLOCK, SCSI_XFER_AUTO,   NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_WRITE_VERIFY,     SCSI_XFER_AUTO,     "WRITE VERIFY", SCSI_DONT_EMULATE},     \
+   {SCSI_CMD_VERIFY,           SCSI_XFER_NONE,     "VERIFY", SCSI_EMULATE},            \
+   {SCSI_CMD_SEARCH_DATA_HIGH, SCSI_XFER_AUTO,     "SEARCH HIGH", SCSI_DONT_EMULATE},      \
+   {SCSI_CMD_SEARCH_DATA_EQUAL, SCSI_XFER_AUTO,     "SEARCH EQUAL", SCSI_DONT_EMULATE},    \
+   {SCSI_CMD_SEARCH_DATA_LOW,  SCSI_XFER_AUTO,     "SEARCH LOW", SCSI_DONT_EMULATE},       \
+   {SCSI_CMD_SET_LIMITS,       SCSI_XFER_AUTO,     "SET LIMITS", SCSI_DONT_EMULATE},       \
+   {SCSI_CMD_READ_POSITION,    SCSI_XFER_TOHOST,   NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_SYNC_CACHE,       SCSI_XFER_NONE,     "SYNC CACHE", SCSI_EMULATE},        \
+   {SCSI_CMD_LOCKUNLOCK_CACHE, SCSI_XFER_AUTO,     "LOCK/UNLOCK CACHE", SCSI_DONT_EMULATE},\
+   {SCSI_CMD_READ_DEFECT_DATA, SCSI_XFER_AUTO,     "READ DEFECT DATA", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_MEDIUM_SCAN,      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_COMPARE,          SCSI_XFER_AUTO,     "COMPARE", SCSI_DONT_EMULATE},          \
+   {SCSI_CMD_COPY_VERIFY,      SCSI_XFER_AUTO,     "COPY AND VERIFY", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_WRITE_BUFFER,     SCSI_XFER_AUTO,     "WRITE BUFFER", SCSI_DONT_EMULATE_DONT_LOG},        \
+   {SCSI_CMD_READ_BUFFER,      SCSI_XFER_AUTO,     "READ BUFFER", SCSI_DONT_EMULATE_DONT_LOG}, \
+   {SCSI_CMD_UPDATE_BLOCK,     SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_LONG,        SCSI_XFER_AUTO,     "READ LONG", SCSI_DONT_EMULATE},        \
+   {SCSI_CMD_WRITE_LONG,       SCSI_XFER_AUTO,     "WRITE LONG", SCSI_DONT_EMULATE},       \
+   {SCSI_CMD_CHANGE_DEF,       SCSI_XFER_NONE,     "CHANGE DEFINITION", SCSI_DONT_EMULATE},\
+   {SCSI_CMD_WRITE_SAME,       SCSI_XFER_AUTO,     "WRITE SAME", SCSI_DONT_EMULATE},       \
+   {SCSI_CMD_READ_SUBCHANNEL,  SCSI_XFER_TOHOST,   "READ SUBCHANNEL", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_READ_TOC,         SCSI_XFER_TOHOST,   "READ TOC", SCSI_DONT_EMULATE},         \
+   {SCSI_CMD_READ_HEADER,      SCSI_XFER_TOHOST,   "READ HEADER", SCSI_DONT_EMULATE},      \
+   {SCSI_CMD_PLAY_AUDIO10,     SCSI_XFER_NONE,     "PLAY AUDIO(10)", SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_GET_CONFIGURATION, SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},              \
+   {SCSI_CMD_PLAY_AUDIO_MSF,   SCSI_XFER_NONE,     "PLAY AUDIO MSF", SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_PLAY_AUDIO_TRACK, SCSI_XFER_AUTO,     "PLAY AUDIO TRACK", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_PLAY_AUDIO_RELATIVE, SCSI_XFER_AUTO,  "PLAY AUDIO RELATIVE", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_GET_EVENT_STATUS_NOTIFICATION,    SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_PAUSE,            SCSI_XFER_NONE,     "PAUSE/RESUME", SCSI_DONT_EMULATE},     \
+   {SCSI_CMD_LOG_SELECT,       SCSI_XFER_TODEVICE, "LOG SELECT", SCSI_DONT_EMULATE},       \
+   {SCSI_CMD_LOG_SENSE,        SCSI_XFER_TOHOST,   "LOG SENSE", SCSI_DONT_EMULATE},        \
+   {SCSI_CMD_STOP_PLAY,        SCSI_XFER_NONE,     "STOP PLAY", SCSI_DONT_EMULATE},        \
+   {0x4f,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x50,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_DISC_INFO,   SCSI_XFER_TOHOST,   "CDR INFO", SCSI_DONT_EMULATE},         \
+   {SCSI_CMD_READ_TRACK_INFO,  SCSI_XFER_TOHOST,   "TRACK INFO", SCSI_DONT_EMULATE},       \
+   {SCSI_CMD_RESERVE_TRACK,    SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x54,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_MODE_SELECT10,    SCSI_XFER_TODEVICE, "MODE SELECT(10)", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_RESERVE_UNIT10,   SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_RELEASE_UNIT10,   SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x58,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0x59,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_MODE_SENSE10,     SCSI_XFER_TOHOST,   "MODE SENSE(10)", SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_CLOSE_SESSION,    SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_READ_BUFFER_CAPACITY, SCSI_XFER_AUTO, NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_SEND_CUE_SHEET,   SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {SCSI_CMD_PERSISTENT_RESERVE_IN, SCSI_XFER_TOHOST,     "PERSISTENT RESERVE IN", SCSI_EMULATE}, \
+   {SCSI_CMD_PERSISTENT_RESERVE_OUT, SCSI_XFER_TODEVICE,     "PERSISTENT RESERVE OUT", SCSI_EMULATE},         \
+   {0x60,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x61,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x62,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x63,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x64,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x65,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x66,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x67,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x68,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x69,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x6a,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x6b,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x6c,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x6d,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x6e,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x6f,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x70,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x71,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x72,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x73,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x74,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x75,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x76,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x77,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x78,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x79,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x7a,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x7b,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x7c,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x7d,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x7e,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x7f,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x80,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x81,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x82,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x83,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x84,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x85,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x86,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x87,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_READ16,           SCSI_XFER_TOHOST,   "READ(16)", SCSI_EMULATE},          \
+   {0x89,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},           \
+   {SCSI_CMD_WRITE16,          SCSI_XFER_TODEVICE, "WRITE(16)", SCSI_EMULATE},         \
+   {0x8b,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x8c,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x8d,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x8e,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_VERIFY16,         SCSI_XFER_NONE,     "VERIFY(16)", SCSI_EMULATE},        \
+   {0x90,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x91,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x92,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x93,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x94,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x95,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x96,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x97,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x98,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x99,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x9a,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x9b,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x9c,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0x9d,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_READ_CAPACITY16,  SCSI_XFER_TOHOST,   "READ CAPACITY 16", SCSI_EMULATE},          \
+   {0x9f,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_REPORT_LUNS,      SCSI_XFER_AUTO,     "REPORT LUNS", SCSI_EMULATE},\
+   {SCSI_CMD_BLANK,            SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xa2,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SEND_KEY,         SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_REPORT_KEY,       SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_PLAY_AUDIO12,     SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_LOADCD,           SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xa7,                      SCSI_XFER_AUTO,     "MOVE MEDIUM", SCSI_DONT_EMULATE},  \
+   {SCSI_CMD_READ12,           SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_PLAY_TRACK_RELATIVE, SCSI_XFER_AUTO,  NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_WRITE12,          SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xab,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_ERASE12,          SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_READ_DVD_STRUCTURE, SCSI_XFER_AUTO,   NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_WRITE_VERIFY12,   SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_VERIFY12,         SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SEARCH_DATA_HIGH12, SCSI_XFER_AUTO,   NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SEARCH_DATA_EQUAL12, SCSI_XFER_AUTO,  NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SEARCH_DATA_LOW12, SCSI_XFER_AUTO,    NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SET_LIMITS12,     SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xb4,                      SCSI_XFER_AUTO,     "READ ELEMENT STATUS", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_REQUEST_VOLUME_ELEMENT_ADDR, SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},    \
+   {SCSI_CMD_SET_STREAMING,    SCSI_XFER_TODEVICE, "SET STREAMING", SCSI_DONT_EMULATE},        \
+   {SCSI_CMD_READ_DEFECT_DATA12, SCSI_XFER_AUTO,   NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SELECT_CDROM_SPEED, SCSI_XFER_AUTO,   NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_READ_CD_MSF,      SCSI_XFER_TOHOST,   "READ CD MSF", SCSI_DONT_EMULATE},      \
+   {SCSI_CMD_AUDIO_SCAN,       SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_SET_CDROM_SPEED,  SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_PLAY_CD,          SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {SCSI_CMD_MECH_STATUS,      SCSI_XFER_TOHOST,   "MECHANISM STATUS", SCSI_DONT_EMULATE}, \
+   {SCSI_CMD_READ_CD,          SCSI_XFER_TOHOST,   "READ CD MSF", SCSI_DONT_EMULATE},      \
+   {SCSI_CMD_SEND_DVD_STRUCTURE, SCSI_XFER_AUTO,   NULL, SCSI_DONT_EMULATE},   \
+   {0xc0,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc1,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc2,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc3,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc4,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc5,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc6,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc7,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc8,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xc9,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xca,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xcb,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xcc,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xcd,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xce,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xcf,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd0,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd1,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd2,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd3,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd4,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd5,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd6,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd7,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd8,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xd9,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xda,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xdb,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xdc,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xdd,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xde,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xdf,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe0,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe1,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe2,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe3,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe4,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe5,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe6,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe7,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe8,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xe9,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xea,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xeb,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xec,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xed,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xee,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xef,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf0,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf1,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf2,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf3,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf4,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf5,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf6,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf7,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf8,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xf9,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xfa,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xfb,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},   \
+   {0xfc,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0xfd,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0xfe,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               \
+   {0xff,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_EMULATE},               
+
+#endif
diff --git a/open-vm-tools/modules/linux/pvscsi/vm_assert.h b/open-vm-tools/modules/linux/pvscsi/vm_assert.h
new file mode 100644 (file)
index 0000000..2e70ae1
--- /dev/null
@@ -0,0 +1,317 @@
+/*********************************************************
+ * Copyright (C) 1998-2004 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * vm_assert.h --
+ *
+ *     The basic assertion facility for all VMware code.
+ *
+ *     For proper use, see
+ *     http://vmweb.vmware.com/~mts/WebSite/guide/programming/asserts.html
+ */
+
+#ifndef _VM_ASSERT_H_
+#define _VM_ASSERT_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMNIXMOD
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_VMKDRIVERS
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_DISTRIBUTE
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+// XXX not necessary except some places include vm_assert.h improperly
+#include "vm_basic_types.h"
+#include "vm_basic_defs.h"
+
+
+/*
+ * XXX old file code
+ */
+
+#ifdef FILECODEINT
+#error "Don't define FILECODEINT.  It is obsolete."
+#endif
+#ifdef FILECODE
+#error "Don't define FILECODE.  It is obsolete."
+#endif
+
+
+/*
+ * Panic and log functions
+ */
+
+EXTERN void Log(const char *fmt, ...) PRINTF_DECL(1, 2);
+EXTERN void Warning(const char *fmt, ...) PRINTF_DECL(1, 2);
+EXTERN NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
+
+EXTERN void LogThrottled(uint32 *count, const char *fmt, ...)
+            PRINTF_DECL(2, 3);
+EXTERN void WarningThrottled(uint32 *count, const char *fmt, ...)
+            PRINTF_DECL(2, 3);
+
+/* DB family:  messages which are parsed by logfile database system */
+#define WarningDB Warning
+#define LogDB Log
+#define WarningThrottledDB WarningThrottled
+#define LogThrottledDB LogThrottled
+
+
+/*
+ * Stress testing: redefine ASSERT_IFNOT() to taste
+ */
+
+#ifndef ASSERT_IFNOT
+   #ifdef __cplusplus
+      #define ASSERT_IFNOT(cond, panic) (UNLIKELY(!(cond)) ? (panic) : (void)0)
+   #else
+      #define ASSERT_IFNOT(cond, panic) (UNLIKELY(!(cond)) ? (panic) : 0)
+   #endif
+#endif
+
+
+/*
+ * Assert, panic, and log macros
+ *
+ * Some of these are redefined below undef !VMX86_DEBUG.
+ * ASSERT() is special cased because of interaction with Windows DDK.
+ */
+
+#if defined VMX86_DEBUG || defined ASSERT_ALWAYS_AVAILABLE
+#undef ASSERT
+#define ASSERT(cond) \
+           ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertAssert))
+#endif
+#define ASSERT_BUG(bug, cond) \
+           ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG(bug, AssertAssert))
+#define ASSERT_BUG_DEBUGONLY(bug, cond) ASSERT_BUG(bug, cond)
+
+#define PANIC()        _ASSERT_PANIC(AssertPanic)
+#define PANIC_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertPanic)
+
+#define ASSERT_NOT_IMPLEMENTED(cond) \
+           ASSERT_IFNOT(cond, NOT_IMPLEMENTED())
+#define ASSERT_NOT_IMPLEMENTED_BUG(bug, cond) \
+           ASSERT_IFNOT(cond, NOT_IMPLEMENTED_BUG(bug))
+
+#define NOT_IMPLEMENTED()        _ASSERT_PANIC(AssertNotImplemented)
+#define NOT_IMPLEMENTED_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertNotImplemented)
+
+#define NOT_REACHED()            _ASSERT_PANIC(AssertNotReached)
+#define NOT_REACHED_BUG(bug)     _ASSERT_PANIC_BUG(bug, AssertNotReached)
+
+#define ASSERT_MEM_ALLOC(cond) \
+           ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertMemAlloc))
+
+#ifdef VMX86_DEVEL
+   #define ASSERT_LENGTH(real, expected) \
+              ASSERT_IFNOT((real) == (expected), \
+                 Panic(AssertLengthFmt, __FILE__, __LINE__, real, expected))
+#else
+   #define ASSERT_LENGTH(real, expected) ASSERT((real) == (expected))
+#endif
+
+#ifdef VMX86_DEVEL
+   #define ASSERT_DEVEL(cond) ASSERT(cond)
+#else
+   #define ASSERT_DEVEL(cond) ((void) 0)
+#endif
+
+#define ASSERT_NO_INTERRUPTS()  ASSERT(!INTERRUPTS_ENABLED())
+#define ASSERT_HAS_INTERRUPTS() ASSERT(INTERRUPTS_ENABLED())
+
+#define ASSERT_LOG_UNEXPECTED(bug, cond) \
+           (UNLIKELY(!(cond)) ? LOG_UNEXPECTED(bug) : 0)
+#ifdef VMX86_DEVEL
+   #define LOG_UNEXPECTED(bug) \
+              Warning(AssertUnexpectedFmt, __FILE__, __LINE__, bug)
+#else
+   #define LOG_UNEXPECTED(bug) \
+              Log(AssertUnexpectedFmt, __FILE__, __LINE__, bug)
+#endif
+
+#define ASSERT_NOT_TESTED(cond) (UNLIKELY(!(cond)) ? NOT_TESTED() : 0)
+#ifdef VMX86_DEVEL
+   #define NOT_TESTED() Warning(AssertNotTestedFmt, __FILE__, __LINE__)
+#else
+   #define NOT_TESTED() Log(AssertNotTestedFmt, __FILE__, __LINE__)
+#endif
+
+#define NOT_TESTED_ONCE()                                               \
+   do {                                                                 \
+      static Bool alreadyPrinted = FALSE;                               \
+      if (UNLIKELY(!alreadyPrinted)) {                                  \
+        alreadyPrinted = TRUE;                                         \
+        NOT_TESTED();                                                  \
+      }                                                                 \
+   } while (0)
+
+#define NOT_TESTED_1024()                                               \
+   do {                                                                 \
+      static uint16 count = 0;                                          \
+      if (UNLIKELY(count == 0)) { NOT_TESTED(); }                       \
+      count = (count + 1) & 1023;                                       \
+   } while (0)
+
+#define LOG_ONCE(_s)                                                    \
+   do {                                                                 \
+      static Bool logged = FALSE;                                       \
+      if (!logged) {                                                    \
+        Log _s;                                                        \
+         logged = TRUE;                                                 \
+      }                                                                 \
+   } while (0)
+
+
+/*
+ * Redefine macros that are only in debug versions
+ */
+
+#if !defined VMX86_DEBUG && !defined ASSERT_ALWAYS_AVAILABLE // {
+
+#undef  ASSERT
+#define ASSERT(cond) ((void) 0)
+
+#undef  ASSERT_BUG_DEBUGONLY
+#define ASSERT_BUG_DEBUGONLY(bug, cond) ((void) 0)
+
+#undef  ASSERT_LENGTH
+#define ASSERT_LENGTH(real, expected) ((void) 0)
+
+/*
+ * Expand NOT_REACHED() as appropriate for each situation.
+ *
+ * Mainly, we want the compiler to infer the same control-flow
+ * information as it would from Panic().  Otherwise, different
+ * compilation options will lead to different control-flow-derived
+ * errors, causing some make targets to fail while others succeed.
+ *
+ * VC++ has the __assume() built-in function which we don't trust
+ * (see bug 43485); gcc has no such construct; we just panic in
+ * userlevel code.  The monitor doesn't want to pay the size penalty
+ * (measured at 212 bytes for the release vmm for a minimal infinite
+ * loop; panic would cost even more) so it does without and lives
+ * with the inconsistency.
+ */
+
+#ifdef VMM
+#undef  NOT_REACHED
+#define NOT_REACHED() ((void) 0)
+#else
+// keep debug definition
+#endif
+
+#undef  ASSERT_LOG_UNEXPECTED
+#define ASSERT_LOG_UNEXPECTED(bug, cond) ((void) 0)
+
+#undef LOG_UNEXPECTED
+#define LOG_UNEXPECTED(bug) ((void) 0)
+
+#undef  ASSERT_NOT_TESTED
+#define ASSERT_NOT_TESTED(cond) ((void) 0)
+#undef  NOT_TESTED
+#define NOT_TESTED() ((void) 0)
+#undef  NOT_TESTED_ONCE
+#define NOT_TESTED_ONCE() ((void) 0)
+#undef  NOT_TESTED_1024
+#define NOT_TESTED_1024() ((void) 0)
+
+#endif // !VMX86_DEBUG }
+
+
+/*
+ * Compile-time assertions.
+ *
+ * ASSERT_ON_COMPILE does not use the common
+ * switch (0) { case 0: case (e): ; } trick because some compilers (e.g. MSVC)
+ * generate code for it.
+ *
+ * The implementation uses both enum and typedef because the typedef alone is
+ * insufficient; gcc allows arrays to be declared with non-constant expressions
+ * (even in typedefs, where it makes no sense).
+ */
+
+#define ASSERT_ON_COMPILE(e) \
+   do { \
+      enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
+      typedef char AssertOnCompileFailed[AssertOnCompileMisused]; \
+   } while (0)
+
+
+/*
+ * To put an ASSERT_ON_COMPILE() outside a function, wrap it
+ * in MY_ASSERTS().  The first parameter must be unique in
+ * each .c file where it appears.  For example,
+ *
+ * MY_ASSERTS(FS3_INT,
+ *    ASSERT_ON_COMPILE(sizeof(FS3_DiskLock) == 128);
+ *    ASSERT_ON_COMPILE(sizeof(FS3_DiskLockReserved) == DISK_BLOCK_SIZE);
+ *    ASSERT_ON_COMPILE(sizeof(FS3_DiskBlock) == DISK_BLOCK_SIZE);
+ *    ASSERT_ON_COMPILE(sizeof(Hardware_DMIUUID) == 16);
+ * )
+ *
+ * Caution: ASSERT() within MY_ASSERTS() is silently ignored.
+ * The same goes for anything else not evaluated at compile time.
+ */
+
+#define MY_ASSERTS(name, assertions) \
+   static INLINE void name(void) { \
+      assertions \
+   }
+
+
+/*
+ * Internal macros, functions, and strings
+ *
+ * The monitor wants to save space at call sites, so it has specialized
+ * functions for each situation.  User level wants to save on implementation
+ * so it uses generic functions.
+ */
+
+#if !defined VMM || defined MONITOR_APP // {
+
+#define _ASSERT_PANIC(name) \
+           Panic(_##name##Fmt "\n", __FILE__, __LINE__)
+#define _ASSERT_PANIC_BUG(bug, name) \
+           Panic(_##name##Fmt " bugNr=%d\n", __FILE__, __LINE__, bug)
+
+#define AssertLengthFmt     _AssertLengthFmt
+#define AssertUnexpectedFmt _AssertUnexpectedFmt
+#define AssertNotTestedFmt  _AssertNotTestedFmt
+
+#endif // }
+
+// these don't have newline so a bug can be tacked on
+#define _AssertPanicFmt            "PANIC %s:%d"
+#define _AssertAssertFmt           "ASSERT %s:%d"
+#define _AssertNotImplementedFmt   "NOT_IMPLEMENTED %s:%d"
+#define _AssertNotReachedFmt       "NOT_REACHED %s:%d"
+#define _AssertMemAllocFmt         "MEM_ALLOC %s:%d"
+
+// these are complete formats with newline
+#define _AssertLengthFmt           "LENGTH %s:%d r=%#x e=%#x\n"
+#define _AssertUnexpectedFmt       "UNEXPECTED %s:%d bugNr=%d\n"
+#define _AssertNotTestedFmt        "NOT_TESTED %s:%d\n"
+
+#endif /* ifndef _VM_ASSERT_H_ */
diff --git a/open-vm-tools/modules/linux/pvscsi/vm_basic_defs.h b/open-vm-tools/modules/linux/pvscsi/vm_basic_defs.h
new file mode 100644 (file)
index 0000000..c307fa7
--- /dev/null
@@ -0,0 +1,610 @@
+/*********************************************************
+ * Copyright (C) 2003 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * vm_basic_defs.h --
+ *
+ *     Standard macros for VMware source code.
+ */
+
+#ifndef _VM_BASIC_DEFS_H_
+#define _VM_BASIC_DEFS_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMNIXMOD
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_VMKDRIVERS
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_DISTRIBUTE
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+#include "vm_basic_types.h" // For INLINE.
+
+/* Checks for FreeBSD, filtering out VMKERNEL. */
+#define __IS_FREEBSD__ (!defined(VMKERNEL) && defined(__FreeBSD__))
+#define __IS_FREEBSD_VER__(ver) (__IS_FREEBSD__ && __FreeBSD_version >= (ver))
+
+#if defined _WIN32 && defined USERLEVEL
+   #include <stddef.h>  /*
+                         * We re-define offsetof macro from stddef, make 
+                         * sure that its already defined before we do it
+                         */
+   #include <windows.h>        // for Sleep() and LOWORD() etc.
+#endif
+
+
+/*
+ * Simple macros
+ */
+
+#if (defined __APPLE__ || defined __FreeBSD__) && \
+    (!defined KERNEL && !defined _KERNEL && !defined VMKERNEL && !defined __KERNEL__)
+#   include <stddef.h>
+#else
+// XXX the __cplusplus one matches that of VC++, to prevent redefinition warning
+// XXX the other one matches that of gcc3.3.3/glibc2.2.4 to prevent redefinition warnings
+#ifndef offsetof
+#ifdef __cplusplus
+#define offsetof(s,m)   (size_t)&(((s *)0)->m)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#endif
+#endif // __APPLE__
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(a) (sizeof (a) / sizeof *(a))
+#endif
+
+#ifndef MIN
+#define MIN(_a, _b)   (((_a) < (_b)) ? (_a) : (_b))
+#endif
+
+/* The Solaris 9 cross-compiler complains about these not being used */
+#ifndef sun
+static INLINE int 
+Min(int a, int b)
+{
+   return a < b ? a : b;
+}
+#endif
+
+#ifndef MAX
+#define MAX(_a, _b)   (((_a) > (_b)) ? (_a) : (_b))
+#endif
+
+#ifndef sun
+static INLINE int 
+Max(int a, int b)
+{
+   return a > b ? a : b;
+}
+#endif
+
+#define ROUNDUP(x,y)           (((x) + (y) - 1) / (y) * (y))
+#define ROUNDDOWN(x,y)         ((x) / (y) * (y))
+#define ROUNDUPBITS(x, bits)   (((uintptr_t) (x) + MASK(bits)) & ~MASK(bits))
+#define ROUNDDOWNBITS(x, bits) ((uintptr_t) (x) & ~MASK(bits))
+#define CEILING(x, y)          (((x) + (y) - 1) / (y))
+#if defined __APPLE__
+#include <machine/param.h>
+#undef MASK
+#endif
+#define MASK(n)                        ((1 << (n)) - 1)        /* make an n-bit mask */
+#define DWORD_ALIGN(x)          ((((x)+3) >> 2) << 2)
+#define QWORD_ALIGN(x)          ((((x)+4) >> 3) << 3)
+
+#define IMPLIES(a,b) (!(a) || (b))
+
+/*
+ * Not everybody (e.g., the monitor) has NULL
+ */
+
+#ifndef NULL
+#ifdef  __cplusplus
+#define NULL    0
+#else
+#define NULL    ((void *)0)
+#endif
+#endif
+
+
+/* 
+ * Token concatenation
+ *
+ * The C preprocessor doesn't prescan arguments when they are
+ * concatenated or stringified.  So we need extra levels of
+ * indirection to convince the preprocessor to expand its
+ * arguments.
+ */
+
+#define CONC(x, y)              x##y
+#define XCONC(x, y)             CONC(x, y)
+#define XXCONC(x, y)            XCONC(x, y)
+#define MAKESTR(x)              #x
+#define XSTR(x)                 MAKESTR(x)
+
+
+/*
+ * Page operations
+ *
+ * It has been suggested that these definitions belong elsewhere
+ * (like x86types.h).  However, I deem them common enough
+ * (since even regular user-level programs may want to do
+ * page-based memory manipulation) to be here.
+ * -- edward
+ */
+
+#ifndef PAGE_SHIFT // {
+#if defined VM_I386
+   #define PAGE_SHIFT    12
+#elif defined __APPLE__
+   #define PAGE_SHIFT    12
+#else
+   #error
+#endif
+#endif // }
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE     (1<<PAGE_SHIFT)
+#endif
+
+#ifndef PAGE_MASK
+#define PAGE_MASK     (PAGE_SIZE - 1)
+#endif
+
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET(_addr)  ((uintptr_t)(_addr)&(PAGE_SIZE-1))
+#endif
+
+#ifndef VM_PAGE_BASE
+#define VM_PAGE_BASE(_addr)  ((_addr)&~(PAGE_SIZE-1))
+#endif
+
+#ifndef VM_PAGES_SPANNED
+#define VM_PAGES_SPANNED(_addr, _size) \
+   ((((_addr) & (PAGE_SIZE - 1)) + (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+#endif
+
+#ifndef BYTES_2_PAGES
+#define BYTES_2_PAGES(_nbytes) ((_nbytes) >> PAGE_SHIFT)
+#endif
+
+#ifndef PAGES_2_BYTES
+#define PAGES_2_BYTES(_npages) (((uint64)(_npages)) << PAGE_SHIFT)
+#endif
+
+#ifndef MBYTES_2_PAGES
+#define MBYTES_2_PAGES(_nbytes) ((_nbytes) << (20 - PAGE_SHIFT))
+#endif
+
+#ifndef PAGES_2_MBYTES
+#define PAGES_2_MBYTES(_npages) ((_npages) >> (20 - PAGE_SHIFT))
+#endif
+
+#ifndef VM_PAE_LARGE_PAGE_SHIFT
+#define VM_PAE_LARGE_PAGE_SHIFT 21
+#endif 
+
+#ifndef VM_PAE_LARGE_PAGE_SIZE
+#define VM_PAE_LARGE_PAGE_SIZE (1 << VM_PAE_LARGE_PAGE_SHIFT)
+#endif
+
+#ifndef VM_PAE_LARGE_PAGE_MASK
+#define VM_PAE_LARGE_PAGE_MASK (VM_PAE_LARGE_PAGE_SIZE - 1)
+#endif
+
+#ifndef VM_PAE_LARGE_2_SMALL_PAGES
+#define VM_PAE_LARGE_2_SMALL_PAGES (BYTES_2_PAGES(VM_PAE_LARGE_PAGE_SIZE))
+#endif
+
+/*
+ * Word operations
+ */
+
+#ifndef LOWORD
+#define LOWORD(_dw)   ((_dw) & 0xffff)
+#endif
+#ifndef HIWORD
+#define HIWORD(_dw)   (((_dw) >> 16) & 0xffff)
+#endif
+
+#ifndef LOBYTE
+#define LOBYTE(_w)    ((_w) & 0xff)
+#endif
+#ifndef HIBYTE
+#define HIBYTE(_w)    (((_w) >> 8) & 0xff)
+#endif
+
+#define HIDWORD(_qw)   ((uint32)((_qw) >> 32))
+#define LODWORD(_qw)   ((uint32)(_qw))
+#define QWORD(_hi, _lo)   ((((uint64)(_hi)) << 32) | ((uint32)(_lo)))
+
+
+/*
+ * Deposit a field _src at _pos bits from the right,
+ * with a length of _len, into the integer _target.
+ */
+
+#define DEPOSIT_BITS(_src,_pos,_len,_target) { \
+       unsigned mask = ((1 << _len) - 1); \
+       unsigned shiftedmask = ((1 << _len) - 1) << _pos; \
+       _target = (_target & ~shiftedmask) | ((_src & mask) << _pos); \
+}
+
+
+/*
+ * Get return address.
+ */
+
+#ifdef _MSC_VER
+#ifdef __cplusplus
+extern "C"
+#endif 
+void *_ReturnAddress(void);
+#pragma intrinsic(_ReturnAddress)
+#define GetReturnAddress() _ReturnAddress()
+#elif __GNUC__
+#define GetReturnAddress() __builtin_return_address(0)
+#endif
+
+
+#ifdef __GNUC__
+#ifndef sun
+
+/*
+ * Get the frame pointer. We use this assembly hack instead of
+ * __builtin_frame_address() due to a bug introduced in gcc 4.1.1
+ */
+static INLINE_SINGLE_CALLER uintptr_t
+GetFrameAddr(void)
+{
+   uintptr_t bp;
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
+   bp = (uintptr_t)__builtin_frame_address(0);
+#elif (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 3)
+#  if defined(VMM64) || defined(VM_X86_64)
+     __asm__ __volatile__("movq %%rbp, %0\n" : "=g" (bp));
+#  else
+     __asm__ __volatile__("movl %%ebp, %0\n" : "=g" (bp));
+#  endif
+#else
+   __asm__ __volatile__(
+#ifdef __linux__
+      ".print \"This newer version of GCC may or may not have the "
+               "__builtin_frame_address bug.  Need to update this. "
+               "See bug 147638.\"\n"
+      ".abort"
+#else /* MacOS */
+      ".abort \"This newer version of GCC may or may not have the "
+               "__builtin_frame_address bug.  Need to update this. "
+               "See bug 147638.\"\n"
+#endif
+      : "=g" (bp)
+   );
+#endif
+   return bp;
+}
+
+
+/*
+ * Returns the frame pointer of the calling function.
+ * Equivalent to __builtin_frame_address(1).
+ */
+static INLINE_SINGLE_CALLER uintptr_t
+GetCallerFrameAddr(void)
+{
+   return *(uintptr_t*)GetFrameAddr();
+}
+
+#endif // sun
+#endif // __GNUC__
+
+/*
+ * Data prefetch was added in gcc 3.1.1
+ * http://www.gnu.org/software/gcc/gcc-3.1/changes.html
+ */
+#ifdef __GNUC__
+#  if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 1) || \
+       (__GNUC__ == 3 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 1))
+#     define PREFETCH_R(var) __builtin_prefetch((var), 0 /* read */, \
+                                                3 /* high temporal locality */)
+#     define PREFETCH_W(var) __builtin_prefetch((var), 1 /* write */, \
+                                                3 /* high temporal locality */)
+#  else
+#     define PREFETCH_R(var) ((void)(var))
+#     define PREFETCH_W(var) ((void)(var))
+#  endif
+#endif /* __GNUC__ */
+
+
+#ifdef USERLEVEL // {
+
+/*
+ * Note this might be a problem on NT b/c while sched_yield guarantees it
+ * moves you to the end of your priority list, Sleep(0) offers no such
+ * guarantee.  Bummer.  --Jeremy.
+ */
+
+#if defined(N_PLAT_NLM)
+/* We do not have YIELD() as we do not need it yet... */
+#elif defined(_WIN32)
+#      define YIELD()          Sleep(0)
+#else
+#      include <sched.h>        // For sched_yield.  Don't ask.  --Jeremy.
+#      define YIELD()          sched_yield()
+#endif 
+
+
+/*
+ * Standardize some Posix names on Windows.
+ */
+
+#ifdef _WIN32 // {
+
+#define snprintf  _snprintf
+#define        vsnprintf _vsnprintf
+#define strtok_r  strtok_s
+
+typedef int uid_t;
+typedef int gid_t;
+
+static INLINE void
+sleep(unsigned int sec)
+{
+   Sleep(sec * 1000);
+}
+
+static INLINE void
+usleep(unsigned long usec)
+{
+   Sleep(CEILING(usec, 1000));
+}
+
+typedef int pid_t;
+#define       F_OK          0
+#define       X_OK          1
+#define       W_OK          2
+#define       R_OK          4
+
+#endif // }
+
+/*
+ * Macro for username comparison.
+ */
+
+#ifdef _WIN32 // {
+#define USERCMP(x,y)  Str_Strcasecmp(x,y)
+#else
+#define USERCMP(x,y)  strcmp(x,y)
+#endif // }
+
+
+#endif // }
+
+#ifndef va_copy
+
+#ifdef _WIN32
+
+/*
+ * Windows needs va_copy. This works for both 32 and 64-bit Windows
+ * based on inspection of how varags.h from the Visual C CRTL is
+ * implemented. (Future versions of the RTL may break this).
+ */
+
+#define va_copy(dest, src) ((dest) = (src))
+
+#elif defined(__APPLE__) && defined(KERNEL)
+
+/*
+ * MacOS kernel-mode needs va_copy. Based on inspection of stdarg.h
+ * from the MacOSX10.4u.sdk kernel framework, this should work.
+ * (Future versions of the SDK may break this).
+ */
+
+#define va_copy(dest, src) ((dest) = (src))
+
+#elif defined(__GNUC__) && (__GNUC__ < 3)
+
+/*
+ * Old versions of gcc recognize __va_copy, but not va_copy.
+ */
+
+#define va_copy(dest, src) __va_copy(dest, src)
+
+#endif // _WIN32
+
+#endif // va_copy
+
+/*
+ * This one is outside USERLEVEL because it's used by
+ * files compiled into the Windows hgfs driver or the display
+ * driver.
+ */
+
+#ifdef _WIN32
+#define PATH_MAX 256
+#ifndef strcasecmp
+#define strcasecmp(_s1,_s2)   _stricmp((_s1),(_s2))
+#endif
+#ifndef strncasecmp
+#define strncasecmp(_s1,_s2,_n)   _strnicmp((_s1),(_s2),(_n))
+#endif
+#endif
+
+/* 
+ * Convenience macro for COMMUNITY_SOURCE
+ */
+#undef EXCLUDE_COMMUNITY_SOURCE
+#ifdef COMMUNITY_SOURCE
+   #define EXCLUDE_COMMUNITY_SOURCE(x) 
+#else
+   #define EXCLUDE_COMMUNITY_SOURCE(x) x
+#endif
+
+#undef COMMUNITY_SOURCE_INTEL_SECRET
+#if !defined(COMMUNITY_SOURCE) || defined(INTEL_SOURCE)
+/*
+ * It's ok to include INTEL_SECRET source code for non-commsrc,
+ * or for drops directed at Intel.
+ */
+   #define COMMUNITY_SOURCE_INTEL_SECRET
+#endif
+
+/*
+ * Convenience macros and definitions. Can often be used instead of #ifdef.
+ */
+
+#undef DEBUG_ONLY
+#undef SL_DEBUG_ONLY
+#undef VMX86_SL_DEBUG
+#ifdef VMX86_DEBUG
+#define vmx86_debug      1
+#define DEBUG_ONLY(x)    x
+/*
+ * Be very, very, very careful with SL_DEBUG. Pls ask ganesh or min before 
+ * using it.
+ */
+#define VMX86_SL_DEBUG
+#define vmx86_sl_debug   1
+#define SL_DEBUG_ONLY(x) x
+#else
+#define vmx86_debug      0
+#define DEBUG_ONLY(x)
+#define vmx86_sl_debug   0
+#define SL_DEBUG_ONLY(x)
+#endif
+
+#ifdef VMX86_STATS
+#define vmx86_stats   1
+#define STATS_ONLY(x) x
+#else
+#define vmx86_stats   0
+#define STATS_ONLY(x)
+#endif
+
+#ifdef VMX86_DEVEL
+#define vmx86_devel   1
+#define DEVEL_ONLY(x) x
+#else
+#define vmx86_devel   0
+#define DEVEL_ONLY(x)
+#endif
+
+#ifdef VMX86_LOG
+#define vmx86_log     1
+#define LOG_ONLY(x)   x
+#else
+#define vmx86_log     0
+#define LOG_ONLY(x)
+#endif
+
+#ifdef VMX86_VMM_SERIAL_LOGGING
+#define vmx86_vmm_serial_log     1
+#define VMM_SERIAL_LOG_ONLY(x)   x
+#else
+#define vmx86_vmm_serial_log     0
+#define VMM_SERIAL_LOG_ONLY(x)
+#endif
+
+#ifdef VMX86_SERVER
+#define vmx86_server 1
+#define SERVER_ONLY(x) x
+#define HOSTED_ONLY(x)
+#else
+#define vmx86_server 0
+#define SERVER_ONLY(x)
+#define HOSTED_ONLY(x) x
+#endif
+
+#ifdef VMX86_WGS
+#define vmx86_wgs 1
+#define WGS_ONLY(x) x
+#else
+#define vmx86_wgs 0
+#define WGS_ONLY(x) 
+#endif
+
+#ifdef VMKERNEL
+#define vmkernel 1
+#define VMKERNEL_ONLY(x) x
+#else
+#define vmkernel 0
+#define VMKERNEL_ONLY(x)
+#endif
+
+#ifdef _WIN32
+#define WIN32_ONLY(x) x
+#define POSIX_ONLY(x)
+#else
+#define WIN32_ONLY(x)
+#define POSIX_ONLY(x) x
+#endif
+
+#ifdef VMM
+#define VMM_ONLY(x) x
+#define USER_ONLY(x)
+#else
+#define VMM_ONLY(x)
+#define USER_ONLY(x) x
+#endif
+
+/* VMVISOR ifdef only allowed in the vmkernel */
+#ifdef VMKERNEL
+#ifdef VMVISOR
+#define vmvisor 1
+#define VMVISOR_ONLY(x) x
+#else
+#define vmvisor 0
+#define VMVISOR_ONLY(x)
+#endif
+#endif
+
+#ifdef _WIN32
+#define VMW_INVALID_HANDLE INVALID_HANDLE_VALUE
+#else
+#define VMW_INVALID_HANDLE (-1)
+#endif
+
+#ifdef _WIN32
+#define fsync(fd) _commit(fd)
+#define fileno(f) _fileno(f)
+#else
+#endif
+
+/*
+ * Debug output macros for Windows drivers (the Eng variant is for
+ * display/printer drivers only.
+ */
+#ifdef _WIN32
+#ifndef USES_OLD_WINDDK
+#if defined(VMX86_DEBUG) || defined(ASSERT_ALWAYS_AVAILABLE)
+#define WinDrvPrint(arg, ...) DbgPrint(arg, __VA_ARGS__)
+#define WinDrvEngPrint(arg, ...) EngDbgPrint(arg, __VA_ARGS__)
+#else
+#define WinDrvPrint(arg, ...)
+#define WinDrvEngPrint(arg, ...)
+#endif
+#endif
+#endif // _WIN32
+
+#endif // ifndef _VM_BASIC_DEFS_H_
diff --git a/open-vm-tools/modules/linux/pvscsi/vm_basic_types.h b/open-vm-tools/modules/linux/pvscsi/vm_basic_types.h
new file mode 100644 (file)
index 0000000..5e5e7cd
--- /dev/null
@@ -0,0 +1,912 @@
+/*********************************************************
+ * Copyright (C) 1998-2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ *
+ * vm_basic_types.h --
+ *
+ *    basic data types.
+ */
+
+
+#ifndef _VM_BASIC_TYPES_H_
+#define _VM_BASIC_TYPES_H_
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMNIXMOD
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_VMKDRIVERS
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_DISTRIBUTE
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMIROM
+#include "includeCheck.h"
+
+/* STRICT ANSI means the Xserver build and X defines Bool differently. */
+#if !defined(__STRICT_ANSI__) || defined(__FreeBSD__)
+typedef char           Bool;
+#endif
+
+#ifndef FALSE
+#define FALSE          0
+#endif
+
+#ifndef TRUE
+#define TRUE           1
+#endif
+
+#define IsBool(x)      (((x) & ~1) == 0)
+#define IsBool2(x, y)  ((((x) | (y)) & ~1) == 0)
+
+/*
+ * Macros __i386__ and __ia64 are intrinsically defined by GCC
+ */
+#ifdef __i386__
+#define VM_I386
+#endif
+
+#ifdef _WIN64
+#define __x86_64__
+#endif
+
+#ifdef __x86_64__
+#define VM_X86_64
+#define VM_I386
+#define vm_x86_64 (1)
+#else
+#define vm_x86_64 (0)
+#endif
+
+
+
+#ifdef _WIN32
+/* safe assumption for a while */
+#define VM_I386
+#endif
+
+#ifdef _MSC_VER
+typedef unsigned __int64 uint64;
+typedef signed __int64 int64;
+
+#pragma warning (3 :4505) // unreferenced local function
+#pragma warning (disable :4018) // signed/unsigned mismatch
+#pragma warning (disable :4761) // integral size mismatch in argument; conversion supplied
+#pragma warning (disable :4305) // truncation from 'const int' to 'short'
+#pragma warning (disable :4244) // conversion from 'unsigned short' to 'unsigned char'
+#pragma warning (disable :4267) // truncation of 'size_t'
+#pragma warning (disable :4146) // unary minus operator applied to unsigned type, result still unsigned
+#pragma warning (disable :4142) // benign redefinition of type
+
+#elif __GNUC__
+/* The Xserver source compiles with -ansi -pendantic */
+#ifndef __STRICT_ANSI__
+#if defined(VM_X86_64)
+typedef unsigned long uint64;
+typedef long int64;
+#else
+typedef unsigned long long uint64;
+typedef long long int64;
+#endif
+#elif __FreeBSD__
+typedef unsigned long long uint64;
+typedef long long int64;
+#endif
+#else
+#error - Need compiler define for int64/uint64
+#endif
+
+typedef unsigned int       uint32;
+typedef unsigned short     uint16;
+typedef unsigned char      uint8;
+
+typedef int       int32;
+typedef short     int16;
+typedef char      int8;
+
+/*
+ * FreeBSD (for the tools build) unconditionally defines these in
+ * sys/inttypes.h so don't redefine them if this file has already
+ * been included. [greg]
+ *
+ * This applies to Solaris as well.
+ */
+
+/*
+ * Before trying to do the includes based on OS defines, see if we can use
+ * feature-based defines to get as much functionality as possible
+ */
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_INTTYPES_H
+#include <sys/inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <sys/param.h> /* For __FreeBSD_version */         
+#endif
+
+#if !defined(USING_AUTOCONF)
+#   if defined(__FreeBSD__) || defined(sun)
+#      ifdef KLD_MODULE
+#         include <sys/types.h>
+#      else
+#         if !defined(VMKERNEL) && (__FreeBSD_version >= 500043)
+#            include <inttypes.h>
+#            include <sys/types.h>
+#         else
+#            include <sys/inttypes.h>
+#         endif
+#      endif
+#   elif defined __APPLE__
+#      if KERNEL
+#         include <sys/unistd.h>
+#         include <sys/types.h> /* mostly for size_t */
+#         include <stdint.h>
+#      else
+#         include <unistd.h>
+#         include <inttypes.h>
+#         include <stdlib.h>
+#         include <stdint.h>
+#      endif
+#   else
+#      if !defined(__intptr_t_defined) && !defined(intptr_t)
+#         define __intptr_t_defined
+#         define intptr_t  intptr_t
+#         ifdef VM_I386
+#            ifdef VM_X86_64
+typedef int64     intptr_t;
+#            else
+typedef int32     intptr_t;
+#            endif
+#         endif
+#      endif
+
+#      ifndef _STDINT_H
+#         ifdef VM_I386
+#            ifdef VM_X86_64
+typedef uint64    uintptr_t;
+#            else
+typedef uint32    uintptr_t;
+#            endif
+#         endif
+#      endif
+#   endif
+#endif
+
+
+/*
+ * Time
+ * XXX These should be cleaned up.  -- edward
+ */
+
+typedef int64 VmTimeType;          /* Time in microseconds */
+typedef int64 VmTimeRealClock;     /* Real clock kept in microseconds */
+typedef int64 VmTimeVirtualClock;  /* Virtual Clock kept in CPU cycles */
+
+/*
+ * Printf format specifiers for size_t and 64-bit number.
+ * Use them like this:
+ *    printf("%"FMT64"d\n", big);
+ *
+ * FMTH is for handles/fds.
+ */
+
+#ifdef _MSC_VER
+   #define FMT64      "I64"
+   #ifdef VM_X86_64
+      #define FMTSZ      "I64"
+      #define FMTPD      "I64"
+      #define FMTH       "I64"
+   #else
+      #define FMTSZ      "I"
+      #define FMTPD      "I"
+      #define FMTH       "I"
+   #endif
+#elif __GNUC__
+   #define FMTH ""
+   #if defined(N_PLAT_NLM) || defined(sun) || \
+       (defined(__FreeBSD__) && (__FreeBSD__ + 0) && ((__FreeBSD__ + 0) < 5))
+      /*
+       * Why (__FreeBSD__ + 0)?  See bug 141008.
+       * Yes, we really need to test both (__FreeBSD__ + 0) and
+       * ((__FreeBSD__ + 0) < 5).  No, we can't remove "+ 0" from
+       * ((__FreeBSD__ + 0) < 5).
+       */
+      #ifdef VM_X86_64
+         #define FMTSZ  "l"
+         #define FMTPD  "l"
+      #else
+         #define FMTSZ  ""
+         #define FMTPD  ""
+      #endif
+   #elif defined(__linux__) \
+      || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
+      || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \
+      || (defined(_POSIX2_VERSION) && _POSIX2_VERSION >= 200112L)
+      /* BSD/Darwin, Linux */
+      #define FMTSZ     "z"
+
+      #if defined(VM_X86_64) || defined(__APPLE__)
+         #define FMTPD  "l"
+      #else
+         #define FMTPD  ""
+      #endif
+   #else
+      /* Systems with a pre-C99 libc */
+      #define FMTSZ     "Z"
+      #ifdef VM_X86_64
+         #define FMTPD  "l"
+      #else
+         #define FMTPD  ""
+      #endif
+   #endif
+   #ifdef VM_X86_64
+      #define FMT64     "l"
+   #elif defined(sun) || defined(__APPLE__) || defined(__FreeBSD__)
+      #define FMT64     "ll"
+   #else
+      #define FMT64     "L"
+   #endif
+#else
+   #error - Need compiler define for FMT64 and FMTSZ
+#endif
+
+/*
+ * Suffix for 64-bit constants.  Use it like this:
+ *    CONST64(0x7fffffffffffffff) for signed or
+ *    CONST64U(0x7fffffffffffffff) for unsigned.
+ *
+ * 2004.08.30(thutt):
+ *   The vmcore/asm64/gen* programs are compiled as 32-bit
+ *   applications, but must handle 64 bit constants.  If the
+ *   64-bit-constant defining macros are already defined, the
+ *   definition will not be overwritten.
+ */
+
+#if !defined(CONST64) || !defined(CONST64U)
+#ifdef _MSC_VER
+#define CONST64(c) c##I64
+#define CONST64U(c) c##uI64
+#elif __GNUC__
+#ifdef VM_X86_64
+#define CONST64(c) c##L
+#define CONST64U(c) c##uL
+#else
+#define CONST64(c) c##LL
+#define CONST64U(c) c##uLL
+#endif
+#else
+#error - Need compiler define for CONST64
+#endif
+#endif
+
+/*
+ * Use CONST3264/CONST3264U if you want a constant to be
+ * treated as a 32-bit number on 32-bit compiles and
+ * a 64-bit number on 64-bit compiles. Useful in the case
+ * of shifts, like (CONST3264U(1) << x), where x could be
+ * more than 31 on a 64-bit compile.
+ */
+
+#ifdef VM_X86_64
+    #define CONST3264(a) CONST64(a)
+    #define CONST3264U(a) CONST64U(a)
+#else
+    #define CONST3264(a) (a)
+    #define CONST3264U(a) (a)
+#endif
+
+#define MIN_INT32  ((int32)0x80000000)
+#define MAX_INT32  ((int32)0x7fffffff)
+
+#define MIN_UINT32 ((uint32)0)
+#define MAX_UINT32 ((uint32)0xffffffff)
+
+#define MIN_INT64  (CONST64(0x8000000000000000))
+#define MAX_INT64  (CONST64(0x7fffffffffffffff))
+
+#define MIN_UINT64 (CONST64U(0))
+#define MAX_UINT64 (CONST64U(0xffffffffffffffff))
+
+typedef uint8 *TCA;  /* Pointer into TC (usually). */
+
+/*
+ * Type big enough to hold an integer between 0..100
+ */
+typedef uint8 Percent;
+#define AsPercent(v)   ((Percent)(v))
+#define CHOOSE_PERCENT  AsPercent(101)
+
+
+typedef uintptr_t VA;
+typedef uintptr_t VPN;
+
+typedef uint64    PA;
+typedef uint32    PPN;
+
+typedef uint64    PhysMemOff;
+typedef uint64    PhysMemSize;
+
+/* The Xserver source compiles with -ansi -pendantic */
+#ifndef __STRICT_ANSI__
+typedef uint64    BA;
+#endif
+typedef uint32    BPN;
+typedef uint32    PageNum;
+typedef unsigned  MemHandle;
+typedef int32     World_ID;
+
+#define INVALID_WORLD_ID ((World_ID)-1)
+
+typedef World_ID User_CartelID;
+#define INVALID_CARTEL_ID INVALID_WORLD_ID
+
+typedef User_CartelID User_SessionID;
+#define INVALID_SESSION_ID INVALID_CARTEL_ID
+
+typedef User_CartelID User_CartelGroupID;
+#define INVALID_CARTELGROUP_ID INVALID_CARTEL_ID
+
+typedef uint32 Worldlet_ID;
+#define INVALID_WORLDLET_ID ((Worldlet_ID)-1)
+
+/* world page number */
+typedef uint32    WPN;
+
+/* The Xserver source compiles with -ansi -pendantic */
+#ifndef __STRICT_ANSI__
+typedef uint64     MA;
+typedef uint32     MPN;
+#endif
+
+/*
+ * This type should be used for variables that contain sector
+ * position/quantity.
+ */
+typedef uint64 SectorType;
+
+/*
+ * Linear address
+ */
+
+typedef uintptr_t LA;
+typedef uintptr_t LPN;
+#define LA_2_LPN(_la)     ((_la) >> PAGE_SHIFT)
+#define LPN_2_LA(_lpn)    ((_lpn) << PAGE_SHIFT)
+
+#define LAST_LPN   ((((LA)  1) << (8 * sizeof(LA)   - PAGE_SHIFT)) - 1)
+#define LAST_LPN32 ((((LA32)1) << (8 * sizeof(LA32) - PAGE_SHIFT)) - 1)
+#define LAST_LPN64 ((((LA64)1) << (8 * sizeof(LA64) - PAGE_SHIFT)) - 1)
+
+/* Valid bits in a LPN. */
+#define LPN_MASK   LAST_LPN
+#define LPN_MASK32 LAST_LPN32
+#define LPN_MASK64 LAST_LPN64
+
+/*
+ * On 64 bit platform, address and page number types default
+ * to 64 bit. When we need to represent a 32 bit address, we use
+ * types defined below.
+ *
+ * On 32 bit platform, the following types are the same as the
+ * default types.
+ */
+typedef uint32 VA32;
+typedef uint32 VPN32;
+typedef uint32 LA32;
+typedef uint32 LPN32;
+typedef uint32 PA32;
+typedef uint32 PPN32;
+typedef uint32 MA32;
+typedef uint32 MPN32;
+
+/*
+ * On 64 bit platform, the following types are the same as the
+ * default types.
+ */
+typedef uint64 VA64;
+typedef uint64 VPN64;
+typedef uint64 LA64;
+typedef uint64 LPN64;
+typedef uint64 PA64;
+typedef uint64 PPN64;
+typedef uint64 MA64;
+typedef uint64 MPN64;
+
+/*
+ * VA typedefs for user world apps.
+ */
+typedef VA32 UserVA32;
+typedef VA64 UserVA64;
+typedef UserVA32 UserVAConst; /* Userspace ptr to data that we may only read. */
+typedef UserVA64 UserVA64Const; /* Used by 64-bit syscalls until conversion is finished. */
+#ifdef VMKERNEL
+typedef UserVA32 UserVA;
+#else
+typedef void * UserVA;
+#endif
+
+
+/*
+ * Maximal possible PPN value (errors too) that PhysMem can handle.
+ * Must be at least as large as MAX_PPN which is the maximum PPN
+ * for any region other than buserror.
+ */
+#define PHYSMEM_MAX_PPN ((PPN)0xffffffff)
+#define MAX_PPN         ((PPN)0x1fffffff)   /* Maximal observable PPN value. */
+#define INVALID_PPN     ((PPN)0xffffffff)
+
+#define INVALID_BPN  ((BPN) 0x1fffffff)
+
+#define INVALID_MPN  ((MPN)-1)
+#define MEMREF_MPN   ((MPN)-2)
+#define RESERVED_MPN ((MPN) 0)
+/* Support 43 bits of address space. */
+#define MAX_MPN      ((MPN)0x7fffffff)
+
+#define INVALID_LPN ((LPN)-1)
+#define INVALID_VPN ((VPN)-1)
+#define INVALID_LPN64 ((LPN64)-1)
+#define INVALID_PAGENUM ((PageNum)-1)
+#define INVALID_WPN ((WPN) -1)
+
+
+/*
+ * Format modifier for printing VA, LA, and VPN.
+ * Use them like this: Log("%#"FMTLA"x\n", laddr)
+ */
+
+#if defined(VMM64) || defined(FROBOS64) || vm_x86_64 || defined __APPLE__
+#   define FMTLA "l"
+#   define FMTVA "l"
+#   define FMTVPN "l"
+#else
+#   define FMTLA ""
+#   define FMTVA ""
+#   define FMTVPN ""
+#endif
+
+#ifndef EXTERN
+#define EXTERN        extern
+#endif
+#define CONST         const
+
+
+#ifndef INLINE
+#   ifdef _MSC_VER
+#      define INLINE        __inline
+#   else
+#      define INLINE        inline
+#   endif
+#endif
+
+
+/*
+ * Annotation for data that may be exported into a DLL and used by other
+ * apps that load that DLL and import the data.
+ */
+#if defined(_WIN32) && defined(VMX86_IMPORT_DLLDATA)
+#  define VMX86_EXTERN_DATA       extern __declspec(dllimport)
+#else // !_WIN32
+#  define VMX86_EXTERN_DATA       extern
+#endif
+
+#if defined(_WIN32) && !defined(VMX86_NO_THREADS)
+#define THREADSPECIFIC __declspec(thread)
+#else
+#define THREADSPECIFIC
+#endif
+
+/*
+ * Due to the wonderful "registry redirection" feature introduced in
+ * 64-bit Windows, if you access any key under HKLM\Software in 64-bit
+ * code, you need to open/create/delete that key with
+ * VMKEY_WOW64_32KEY if you want a consistent view with 32-bit code.
+ */
+
+#ifdef _WIN32
+#ifdef _WIN64
+#define VMW_KEY_WOW64_32KEY KEY_WOW64_32KEY
+#else
+#define VMW_KEY_WOW64_32KEY 0x0
+#endif
+#endif
+
+
+/*
+ * Consider the following reasons functions are inlined:
+ *
+ *  1) inlined for performance reasons
+ *  2) inlined because it's a single-use function
+ *
+ * Functions which meet only condition 2 should be marked with this
+ * inline macro; It is not critical to be inlined (but there is a
+ * code-space & runtime savings by doing so), so when other callers
+ * are added the inline-ness should be removed.
+ */
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+/*
+ * Starting at version 3.3, gcc does not always inline functions marked
+ * 'inline' (it depends on their size). To force gcc to do so, one must use the
+ * extra __always_inline__ attribute.
+ */
+#   define INLINE_SINGLE_CALLER INLINE __attribute__((__always_inline__))
+#   if    defined(VMM) \
+       && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1))
+#      warning Verify INLINE_SINGLE_CALLER '__always_inline__' attribute (did \
+             monitor size change?)
+#   endif
+#else
+#   define INLINE_SINGLE_CALLER INLINE
+#endif
+
+/*
+ * Used when a hard guaranteed of no inlining is needed. Very few
+ * instances need this since the absence of INLINE is a good hint
+ * that gcc will not do inlining.
+ */
+
+#if defined(__GNUC__) && defined(VMM)
+#define ABSOLUTELY_NOINLINE __attribute__((__noinline__))
+#endif
+
+/*
+ * Attributes placed on function declarations to tell the compiler
+ * that the function never returns.
+ */
+
+#ifdef _MSC_VER
+#define NORETURN __declspec(noreturn)
+#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 9)
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#endif
+
+/*
+ * GCC 3.2 inline asm needs the + constraint for input/ouput memory operands.
+ * Older GCCs don't know about it --hpreg
+ */
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
+#   define VM_ASM_PLUS 1
+#else
+#   define VM_ASM_PLUS 0
+#endif
+
+/*
+ * Branch prediction hints:
+ *     LIKELY(exp)   - Expression exp is likely TRUE.
+ *     UNLIKELY(exp) - Expression exp is likely FALSE.
+ *   Usage example:
+ *        if (LIKELY(excCode == EXC_NONE)) {
+ *               or
+ *        if (UNLIKELY(REAL_MODE(vc))) {
+ *
+ * We know how to predict branches on gcc3 and later (hopefully),
+ * all others we don't so we do nothing.
+ */
+
+#if (__GNUC__ >= 3)
+/*
+ * gcc3 uses __builtin_expect() to inform the compiler of an expected value.
+ * We use this to inform the static branch predictor. The '!!' in LIKELY
+ * will convert any !=0 to a 1.
+ */
+#define LIKELY(_exp)     __builtin_expect(!!(_exp), 1)
+#define UNLIKELY(_exp)   __builtin_expect((_exp), 0)
+#else
+#define LIKELY(_exp)      (_exp)
+#define UNLIKELY(_exp)    (_exp)
+#endif
+
+/*
+ * GCC's argument checking for printf-like functions
+ * This is conditional until we have replaced all `"%x", void *'
+ * with `"0x%08x", (uint32) void *'. Note that %p prints different things
+ * on different platforms.  Argument checking is enabled for the
+ * vmkernel, which has already been cleansed.
+ *
+ * fmtPos is the position of the format string argument, beginning at 1
+ * varPos is the position of the variable argument, beginning at 1
+ */
+
+#if defined(__GNUC__)
+# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos)))
+#else
+# define PRINTF_DECL(fmtPos, varPos)
+#endif
+
+#if defined(__GNUC__)
+# define SCANF_DECL(fmtPos, varPos) __attribute__((__format__(__scanf__, fmtPos, varPos)))
+#else
+# define SCANF_DECL(fmtPos, varPos)
+#endif
+
+/*
+ * UNUSED_PARAM should surround the parameter name and type declaration,
+ * e.g. "int MyFunction(int var1, UNUSED_PARAM(int var2))"
+ *
+ */
+
+#ifndef UNUSED_PARAM
+# if defined(__GNUC__)
+#  define UNUSED_PARAM(_parm) _parm  __attribute__((__unused__))
+# else
+#  define UNUSED_PARAM(_parm) _parm
+# endif
+#endif
+
+/*
+ * REGPARM defaults to REGPARM3, i.e., a requent that gcc
+ * puts the first three arguments in registers.  (It is fine
+ * if the function has fewer than three args.)  Gcc only.
+ * Syntactically, put REGPARM where you'd put INLINE or NORETURN.
+ */
+
+#if defined(__GNUC__)
+# define REGPARM0 __attribute__((regparm(0)))
+# define REGPARM1 __attribute__((regparm(1)))
+# define REGPARM2 __attribute__((regparm(2)))
+# define REGPARM3 __attribute__((regparm(3)))
+# define REGPARM REGPARM3
+#else
+# define REGPARM0
+# define REGPARM1
+# define REGPARM2
+# define REGPARM3
+# define REGPARM
+#endif
+
+/*
+ * ALIGNED specifies minimum alignment in "n" bytes.
+ */
+
+#ifdef __GNUC__
+#define ALIGNED(n) __attribute__((__aligned__(n)))
+#else
+#define ALIGNED(n)
+#endif
+
+/*
+ ***********************************************************************
+ * STRUCT_OFFSET_CHECK --                                    */ /**
+ *
+ * \brief Check if the actual offsef of a member in a structure 
+ *        is what is expected
+ * 
+ *
+ * \param[in]  STRUCT       Structure the member is a part of.
+ * \param[in]  MEMBER       Member to check the offset of.
+ * \param[in]  OFFSET       Expected offset of MEMBER in STRUCTURE.
+ * \param[in]  DEBUG_EXTRA  Additional bytes to be added to OFFSET to
+ *                          compensate for extra info in debug builds.
+ *
+ ***********************************************************************
+ */
+#ifdef VMX86_DEBUG
+#define STRUCT_OFFSET_CHECK(STRUCT, MEMBER, OFFSET, DEBUG_EXTRA) \
+  ASSERT_ON_COMPILE(vmk_offsetof(STRUCT, MEMBER) == (OFFSET + DEBUG_EXTRA))
+#else
+#define STRUCT_OFFSET_CHECK(STRUCT, MEMBER, OFFSET, DEBUG_EXTRA) \
+  ASSERT_ON_COMPILE(vmk_offsetof(STRUCT, MEMBER) == OFFSET)
+#endif
+
+/*
+ ***********************************************************************
+ * STRUCT_SIZE_CHECK --                                      */ /**
+ *
+ * \brief Check if the actual size of a structure is what is expected
+ * 
+ *
+ * \param[in]  STRUCT       Structure whose size is to be checked.
+ * \param[in]  SIZE         Expected size of STRUCT.
+ * \param[in]  DEBUG_EXTRA  Additional bytes to be added to SIZE to
+ *                          compensate for extra info in debug builds.
+ *
+ ***********************************************************************
+ */
+#ifdef VMX86_DEBUG
+#define STRUCT_SIZE_CHECK(STRUCT, SIZE, DEBUG_EXTRA) \
+  ASSERT_ON_COMPILE(sizeof(STRUCT) == (SIZE + DEBUG_EXTRA))
+#else
+#define STRUCT_SIZE_CHECK(STRUCT, SIZE, DEBUG_EXTRA) \
+  ASSERT_ON_COMPILE(sizeof(STRUCT) == SIZE)
+#endif
+
+/*
+ * __func__ is a stringified function name that is part of the C99 standard. The block
+ * below defines __func__ on older systems where the compiler does not support that
+ * macro.
+ */
+#if defined(__GNUC__) \
+   && ((__GNUC__ == 2 && __GNUC_MINOR < 96) \
+       || (__GNUC__ < 2))
+#   define __func__ __FUNCTION__
+#endif
+
+/*
+ * Once upon a time, this was used to silence compiler warnings that
+ * get generated when the compiler thinks that a function returns
+ * when it is marked noreturn.  Don't do it.  Use NOT_REACHED().
+ */
+
+#define INFINITE_LOOP()           do { } while (1)
+
+/*
+ * On FreeBSD (for the tools build), size_t is typedef'd if _BSD_SIZE_T_
+ * is defined. Use the same logic here so we don't define it twice. [greg]
+ */
+#ifdef __FreeBSD__
+#   ifdef _BSD_SIZE_T_
+#      undef _BSD_SIZE_T_
+#      ifdef VM_I386
+#         ifdef VM_X86_64
+             typedef uint64 size_t;
+#         else
+             typedef uint32 size_t;
+#         endif
+#      endif /* VM_I386 */
+#   endif
+
+#   ifdef _BSD_SSIZE_T_
+#      undef _BSD_SSIZE_T_
+#      define _SSIZE_T
+#      define __ssize_t_defined
+#      define _SSIZE_T_DECLARED
+#      ifdef VM_I386
+#         ifdef VM_X86_64
+             typedef int64 ssize_t;
+#         else
+             typedef int32 ssize_t;
+#         endif
+#      endif /* VM_I386 */
+#   endif
+
+#else
+#   ifndef _SIZE_T
+#      define _SIZE_T
+#      ifdef VM_I386
+#         ifdef VM_X86_64
+             typedef uint64 size_t;
+#         else
+             typedef uint32 size_t;
+#         endif
+#      endif /* VM_I386 */
+#   endif
+
+#   if !defined(FROBOS) && !defined(_SSIZE_T) && !defined(ssize_t) && \
+       !defined(__ssize_t_defined) && !defined(_SSIZE_T_DECLARED)
+#      define _SSIZE_T
+#      define __ssize_t_defined
+#      define _SSIZE_T_DECLARED
+#      ifdef VM_I386
+#         ifdef VM_X86_64
+             typedef int64 ssize_t;
+#         else
+             typedef int32 ssize_t;
+#         endif
+#      endif /* VM_I386 */
+#   endif
+
+#endif
+
+/*
+ * Format modifier for printing pid_t.  On sun the pid_t is a ulong, but on
+ * Linux it's an int.
+ * Use this like this: printf("The pid is %"FMTPID".\n", pid);
+ */
+#ifdef sun
+#   ifdef VM_X86_64
+#      define FMTPID "d"
+#   else
+#      define FMTPID "lu"
+#   endif
+#else
+# define FMTPID "d"
+#endif
+
+/*
+ * Format modifier for printing uid_t.  On sun the uid_t is a ulong, but on
+ * Linux it's an int.
+ * Use this like this: printf("The uid is %"FMTUID".\n", uid);
+ */
+#ifdef sun
+#   ifdef VM_X86_64
+#      define FMTUID "u"
+#   else
+#      define FMTUID "lu"
+#   endif
+#else
+# define FMTUID "u"
+#endif
+
+/*
+ * Format modifier for printing mode_t.  On sun the mode_t is a ulong, but on
+ * Linux it's an int.
+ * Use this like this: printf("The mode is %"FMTMODE".\n", mode);
+ */
+#ifdef sun
+#   ifdef VM_X86_64
+#      define FMTMODE "o"
+#   else
+#      define FMTMODE "lo"
+#   endif
+#else
+# define FMTMODE "o"
+#endif
+
+/*
+ * Format modifier for printing time_t. Most platforms define a time_t to be
+ * a long int, but on FreeBSD (as of 5.0, it seems), the time_t is a signed
+ * size quantity. Refer to the definition of FMTSZ to see why we need silly
+ * preprocessor arithmetic.
+ * Use this like this: printf("The mode is %"FMTTIME".\n", time);
+ */
+#if defined(__FreeBSD__) && (__FreeBSD__ + 0) && ((__FreeBSD__ + 0) >= 5)
+#   define FMTTIME FMTSZ"d"
+#else
+#   define FMTTIME "ld"
+#endif
+
+/*
+ * Define MXSemaHandle here so both vmmon and vmx see this definition.
+ */
+
+#ifdef _WIN32
+typedef uintptr_t MXSemaHandle;
+#else
+typedef int MXSemaHandle;
+#endif
+
+/*
+ * Define type for poll device handles.
+ */
+
+#ifdef _WIN32
+typedef uintptr_t PollDevHandle;
+#else
+typedef int PollDevHandle;
+#endif
+
+/*
+ * Define the utf16_t type.
+ */
+
+#if defined(_WIN32) && defined(_NATIVE_WCHAR_T_DEFINED)
+typedef wchar_t utf16_t;
+#else
+typedef uint16 utf16_t;
+#endif
+
+#endif  /* _VM_BASIC_TYPES_H_ */
diff --git a/open-vm-tools/modules/linux/pvscsi/vm_device_version.h b/open-vm-tools/modules/linux/pvscsi/vm_device_version.h
new file mode 100644 (file)
index 0000000..083fbcd
--- /dev/null
@@ -0,0 +1,188 @@
+/*********************************************************
+ * Copyright (C) 1998 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef VM_DEVICE_VERSION_H
+#define VM_DEVICE_VERSION_H
+
+#define INCLUDE_ALLOW_USERLEVEL
+#define INCLUDE_ALLOW_VMMEXT
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_VMCORE
+#include "includeCheck.h"
+
+#ifdef _WIN32
+#include "guiddef.h"
+#endif
+
+/* Our own PCI IDs
+ *    VMware SVGA II (Unified VGA)
+ *    VMware SVGA (PCI Accelerator)
+ *    VMware vmxnet (Idealized NIC)
+ *    VMware vmxscsi (Abortive idealized SCSI controller)
+ *    VMware chipset (Subsystem ID for our motherboards)
+ *    VMware e1000 (Subsystem ID)
+ *    VMware vmxnet3 (Uniform Pass Through NIC)
+ */
+#define PCI_VENDOR_ID_VMWARE            0x15AD
+#define PCI_DEVICE_ID_VMWARE_SVGA2      0x0405
+#define PCI_DEVICE_ID_VMWARE_SVGA       0x0710
+#define PCI_DEVICE_ID_VMWARE_NET        0x0720
+#define PCI_DEVICE_ID_VMWARE_SCSI       0x0730
+#define PCI_DEVICE_ID_VMWARE_VMCI       0x0740
+#define PCI_DEVICE_ID_VMWARE_CHIPSET    0x1976
+#define PCI_DEVICE_ID_VMWARE_82545EM    0x0750 /* single port */
+#define PCI_DEVICE_ID_VMWARE_82546EB    0x0760 /* dual port   */
+#define PCI_DEVICE_ID_VMWARE_EHCI       0x0770
+#define PCI_DEVICE_ID_VMWARE_1394       0x0780
+#define PCI_DEVICE_ID_VMWARE_BRIDGE     0x0790
+#define PCI_DEVICE_ID_VMWARE_ROOTPORT   0x07A0
+#define PCI_DEVICE_ID_VMWARE_VMXNET3    0x07B0
+#define PCI_DEVICE_ID_VMWARE_PVSCSI     0x07C0
+
+/* The hypervisor device might grow.  Please leave room
+ * for 7 more subfunctions.
+ */
+#define PCI_DEVICE_ID_VMWARE_HYPER      0x0800
+#define PCI_DEVICE_ID_VMWARE_VMI        0x0801
+
+#define PCI_DEVICE_VMI_CLASS            0x05
+#define PCI_DEVICE_VMI_SUBCLASS         0x80
+#define PCI_DEVICE_VMI_INTERFACE        0x00
+#define PCI_DEVICE_VMI_REVISION         0x01
+
+/* From linux/pci_ids.h:
+ *   AMD Lance Ethernet controller
+ *   BusLogic SCSI controller
+ *   Ensoniq ES1371 sound controller
+ */
+#define PCI_VENDOR_ID_AMD               0x1022
+#define PCI_DEVICE_ID_AMD_VLANCE        0x2000
+#define PCI_VENDOR_ID_BUSLOGIC                 0x104B
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC  0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER     0x1040
+#define PCI_VENDOR_ID_ENSONIQ           0x1274
+#define PCI_DEVICE_ID_ENSONIQ_ES1371    0x1371
+
+/* From linux/pci_ids.h:
+ *    Intel 82439TX (430 HX North Bridge)
+ *    Intel 82371AB (PIIX4 South Bridge)
+ *    Intel 82443BX (440 BX North Bridge and AGP Bridge)
+ *    Intel 82545EM (e1000, server adapter, single port)
+ *    Intel 82546EB (e1000, server adapter, dual port)
+ *    Intel ICH7_16 (Hight Definition Audio controller)
+ */
+#define PCI_VENDOR_ID_INTEL             0x8086
+#define PCI_DEVICE_ID_INTEL_82439TX     0x7100
+#define PCI_DEVICE_ID_INTEL_82371AB_0   0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB_2   0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3   0x7113
+#define PCI_DEVICE_ID_INTEL_82371AB     0x7111
+#define PCI_DEVICE_ID_INTEL_82443BX     0x7190
+#define PCI_DEVICE_ID_INTEL_82443BX_1   0x7191
+#define PCI_DEVICE_ID_INTEL_82443BX_2   0x7192 /* Used when no AGP support */
+#define PCI_DEVICE_ID_INTEL_82545EM     0x100f
+#define PCI_DEVICE_ID_INTEL_82546EB     0x1010
+#define PCI_DEVICE_ID_INTEL_ICH7_16     0x27d8
+
+
+/************* Strings for IDE Identity Fields **************************/
+#define VIDE_ID_SERIAL_STR     "00000000000000000001"  /* Must be 20 Bytes */
+#define VIDE_ID_FIRMWARE_STR   "00000001"              /* Must be 8 Bytes */
+
+/* No longer than 40 Bytes */
+#define VIDE_ATA_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE Hard Drive"
+#define VIDE_ATAPI_MODEL_STR PRODUCT_GENERIC_NAME " Virtual IDE CDROM Drive"
+
+#define ATAPI_VENDOR_ID        "NECVMWar"              /* Must be 8 Bytes */
+#define ATAPI_PRODUCT_ID PRODUCT_GENERIC_NAME " IDE CDROM"     /* Must be 16 Bytes */
+#define ATAPI_REV_LEVEL        "1.00"                  /* Must be 4 Bytes */
+
+#define IDE_NUM_INTERFACES   2 /* support for two interfaces */
+#define IDE_DRIVES_PER_IF    2
+
+/************* Strings for SCSI Identity Fields **************************/
+#define SCSI_DISK_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI Hard Drive"
+#define SCSI_DISK_VENDOR_NAME COMPANY_NAME
+#define SCSI_DISK_REV_LEVEL "1.0"
+#define SCSI_CDROM_MODEL_STR PRODUCT_GENERIC_NAME " Virtual SCSI CDROM Drive"
+#define SCSI_CDROM_VENDOR_NAME COMPANY_NAME
+#define SCSI_CDROM_REV_LEVEL "1.0"
+
+/************* SCSI implementation limits ********************************/
+#define SCSI_MAX_CONTROLLERS    4        // Need more than 1 for MSCS clustering
+#define        SCSI_MAX_DEVICES         16       // BT-958 emulates only 16
+#define SCSI_IDE_CHANNEL         SCSI_MAX_CONTROLLERS
+#define SCSI_IDE_HOSTED_CHANNEL  (SCSI_MAX_CONTROLLERS + 1)
+#define SCSI_MAX_CHANNELS        (SCSI_MAX_CONTROLLERS + 2)
+
+/************* Strings for the VESA BIOS Identity Fields *****************/
+#define VBE_OEM_STRING COMPANY_NAME " SVGA"
+#define VBE_VENDOR_NAME COMPANY_NAME
+#define VBE_PRODUCT_NAME PRODUCT_GENERIC_NAME
+
+/************* PCI implementation limits ********************************/
+#define PCI_MAX_BRIDGES         15
+
+/************* Ethernet implementation limits ***************************/
+#define MAX_ETHERNET_CARDS      10
+
+/************* PCI Passthrough implementation limits ********************/
+#define MAX_PCI_PASSTHRU_DEVICES 2
+
+/************* USB implementation limits ********************************/
+#define MAX_USB_DEVICES_PER_HOST_CONTROLLER 127
+
+/************* Strings for Host USB Driver *******************************/
+
+#ifdef _WIN32
+
+/*
+ * Globally unique ID for the VMware device interface. Define INITGUID before including
+ * this header file to instantiate the variable.
+ */
+DEFINE_GUID(GUID_DEVICE_INTERFACE_VMWARE_USB_DEVICES, 
+0x2da1fe75, 0xaab3, 0x4d2c, 0xac, 0xdf, 0x39, 0x8, 0x8c, 0xad, 0xa6, 0x65);
+
+/*
+ * Globally unique ID for the VMware device setup class.
+ */
+DEFINE_GUID(GUID_CLASS_VMWARE_USB_DEVICES, 
+0x3b3e62a5, 0x3556, 0x4d7e, 0xad, 0xad, 0xf5, 0xfa, 0x3a, 0x71, 0x2b, 0x56);
+
+/*
+ * This string defines the device ID string of a VMware USB device.
+ * The format is USB\Vid_XXXX&Pid_YYYY, where XXXX and YYYY are the
+ * hexadecimal representations of the vendor and product ids, respectively.
+ *
+ * The official vendor ID for VMware, Inc. is 0x0E0F.
+ * The product id for USB generic devices is 0x0001.
+ */
+#define USB_VMWARE_DEVICE_ID_WIDE L"USB\\Vid_0E0F&Pid_0001"
+#define USB_DEVICE_ID_LENGTH (sizeof(USB_VMWARE_DEVICE_ID_WIDE) / sizeof(WCHAR))
+
+#ifdef UNICODE
+#define USB_PNP_SETUP_CLASS_NAME L"VMwareUSBDevices"
+#define USB_PNP_DRIVER_NAME L"vmusb"
+#else
+#define USB_PNP_SETUP_CLASS_NAME "VMwareUSBDevices"
+#define USB_PNP_DRIVER_NAME "vmusb"
+#endif
+#endif
+
+#endif /* VM_DEVICE_VERSION_H */
diff --git a/open-vm-tools/modules/linux/pvscsi/vmware_pack_begin.h b/open-vm-tools/modules/linux/pvscsi/vmware_pack_begin.h
new file mode 100644 (file)
index 0000000..8bec457
--- /dev/null
@@ -0,0 +1,43 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * vmware_pack_begin.h --
+ *
+ *    Begin of structure packing. See vmware_pack_init.h for details.
+ *
+ *    Note that we do not use the following construct in this include file,
+ *    because we want to emit the code every time the file is included --hpreg
+ *
+ *    #ifndef foo
+ *    #   define foo
+ *    ...
+ *    #endif
+ *
+ */
+
+
+#include "vmware_pack_init.h"
+
+
+#ifdef _MSC_VER
+#   pragma pack(push, 1)
+#elif __GNUC__
+#else
+#   error Compiler packing...
+#endif
diff --git a/open-vm-tools/modules/linux/pvscsi/vmware_pack_end.h b/open-vm-tools/modules/linux/pvscsi/vmware_pack_end.h
new file mode 100644 (file)
index 0000000..c87cda9
--- /dev/null
@@ -0,0 +1,44 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * vmware_pack_end.h --
+ *
+ *    End of structure packing. See vmware_pack_init.h for details.
+ *
+ *    Note that we do not use the following construct in this include file,
+ *    because we want to emit the code every time the file is included --hpreg
+ *
+ *    #ifndef foo
+ *    #   define foo
+ *    ...
+ *    #endif
+ *
+ */
+
+
+#include "vmware_pack_init.h"
+
+
+#ifdef _MSC_VER
+#   pragma pack(pop)
+#elif __GNUC__
+__attribute__((__packed__))
+#else
+#   error Compiler packing...
+#endif
diff --git a/open-vm-tools/modules/linux/pvscsi/vmware_pack_init.h b/open-vm-tools/modules/linux/pvscsi/vmware_pack_init.h
new file mode 100644 (file)
index 0000000..ecb636a
--- /dev/null
@@ -0,0 +1,65 @@
+/*********************************************************
+ * Copyright (C) 2002 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+#ifndef __VMWARE_PACK_INIT_H__
+#   define __VMWARE_PACK_INIT_H__
+
+
+/*
+ * vmware_pack_init.h --
+ *
+ *    Platform-independent code to make the compiler pack (i.e. have them
+ *    occupy the smallest possible space) structure definitions. The following
+ *    constructs are known to work --hpreg
+ *
+ *    #include "vmware_pack_begin.h"
+ *    struct foo {
+ *       ...
+ *    }
+ *    #include "vmware_pack_end.h"
+ *    ;
+ *
+ *    typedef
+ *    #include "vmware_pack_begin.h"
+ *    struct foo {
+ *       ...
+ *    }
+ *    #include "vmware_pack_end.h"
+ *    foo;
+ */
+
+
+#ifdef _MSC_VER
+/*
+ * MSVC 6.0 emits warning 4103 when the pack push and pop pragma pairing is
+ * not balanced within 1 included file. That is annoying because our scheme
+ * is based on the pairing being balanced between 2 included files.
+ *
+ * So we disable this warning, but this is safe because the compiler will also
+ * emit warning 4161 when there is more pops than pushes within 1 main
+ * file --hpreg
+ */
+
+#   pragma warning(disable:4103)
+#elif __GNUC__
+#else
+#   error Compiler packing...
+#endif
+
+
+#endif /* __VMWARE_PACK_INIT_H__ */
diff --git a/open-vm-tools/modules/linux/vmhgfs/hgfsEscape.c b/open-vm-tools/modules/linux/vmhgfs/hgfsEscape.c
new file mode 100644 (file)
index 0000000..fb1e061
--- /dev/null
@@ -0,0 +1,942 @@
+/*********************************************************
+ * Copyright (C) 2008 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/*
+ * hgfsEscape.c --
+ *
+ *    Escape and unescape illegal filenames for different platforms.
+ *
+ */
+
+#ifdef __KERNEL__
+#  include "driver-config.h"
+#  include <linux/string.h>
+#elif defined(__FreeBSD__)
+#   if defined(_KERNEL)
+#      include <sys/libkern.h>
+#      define strchr(s,c)       index(s,c)
+#   else
+#      include <string.h>
+#   endif
+#   define memmove(s1,s2,n) bcopy(s2,s1,n) 
+#elif defined(__APPLE__) && defined(KERNEL)
+#  include <string.h>
+#elif !defined(sun)
+#  include <stdlib.h>
+#  include <string.h>
+#else
+#  include <string.h>
+#endif
+
+#include "vmware.h"
+#include "hgfsEscape.h"
+#include "cpName.h"
+
+#ifdef _WIN32
+
+#define UNREFERENCED_PARAMETER(P) (P)
+
+/* These characters are illegal in Windows file names. */
+const char* HGFS_ILLEGAL_CHARS = "/\\*?:\"<>|";
+const char* HGFS_SUBSTITUTE_CHARS = "!@#$^&(){}";
+/* Last character of a file name in Windows can be neither dot nor space. */
+const char* HGFS_ILLEGAL_LAST_CHARS = ". ";
+
+/* http://msdn.microsoft.com/en-us/library/aa365247.aspx */
+char *HgfsReservedNames[] = {"CON", "PRN", "AUX", "NUL"};
+char *HgfsReservedNamesWithNumber[] = {"COM", "LPT"};
+
+#define HGFS_RESERVED_NAME_CHARS_LENGTH 3
+#define HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH (HGFS_RESERVED_NAME_CHARS_LENGTH + 1)
+/* Check for special escaping cases - reserved names and illegal last characters. */
+#define IS_SPECIAL_CASE_ESCAPE(b,o,l) HgfsIsSpecialCaseEscape(b,o,l)
+/* Process Windows reserved names. */
+#define PROCESS_RESERVED_NAME(b,s,p,o,c) \
+if (!HgfsProcessReservedName(b,s,p,o,c)) \
+{ \
+ return FALSE; \
+}
+/* Process Windows reserved names. */
+#define PROCESS_LAST_CHARACTER(b,s,p,c) \
+if (!HgfsProcessLastCharacter(b,s,p,c)) \
+{ \
+ return FALSE; \
+}
+
+#else // _WIN32
+
+#define UNREFERENCED_PARAMETER(P)
+/* There is no special escape sequences on other than Windows platforms. */
+#define IS_SPECIAL_CASE_ESCAPE(b,o,l) FALSE
+/* There is no reserved names on other then Windows platforms. */
+#define PROCESS_RESERVED_NAME(b,s,p,o,c)
+/* There is no special processing for the last character on non-Windows platforms. */
+#define PROCESS_LAST_CHARACTER(b,s,p,c)
+
+#if defined(__APPLE__)
+/* These characters are illegal in MAC OS file names. */
+const char* HGFS_ILLEGAL_CHARS = "/:";
+const char* HGFS_SUBSTITUTE_CHARS = "!&";
+#else   // __APPLE__
+/* These characters are illegal in Linux file names. */
+const char* HGFS_ILLEGAL_CHARS = "/";
+const char* HGFS_SUBSTITUTE_CHARS = "!";
+#endif  // __APPLE__
+
+#endif  // _WIN32
+
+#define HGFS_ESCAPE_CHAR '%'
+#define HGFS_ESCAPE_SUBSTITUE_CHAR ']'
+
+typedef enum {
+   HGFS_ESCAPE_ILLEGAL_CHARACTER,
+   HGFS_ESCAPE_RESERVED_NAME,
+   HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER,
+   HGFS_ESCAPE_ESCAPE_SEQUENCE,
+   HGFS_ESCAPE_COMPLETE
+} HgfsEscapeReason;
+
+
+typedef Bool (*HgfsEnumCallback)(char const *bufIn,
+                                 uint32 offset,
+                                 HgfsEscapeReason reason,
+                                 void* context);
+
+/*
+ * The structure is used by HgfsAddEscapeCharacter to keep context information between
+ * invocations
+ * All offsets defined in this structure are in characters, not bytes
+ */
+typedef  struct {
+   uint32   processedOffset;     // Offset of the first unprocessed input character
+   uint32   outputBufferLength;  // Number of characters in the output buffer
+   uint32   outputOffset;        // Number of characters that are already in the output
+   char    *outputBuffer;        // Pointer to the output buffer
+} HgfsEscapeContext;
+
+static void HgfsEscapeUndoComponent(char *bufIn, uint32 *totalLength);
+static int HgfsEscapeGetComponentSize(char const *bufIn, uint32 sizeIn);
+static int HgfsEscapeDoComponent(char const *bufIn, uint32 sizeIn, uint32 sizeBufOut,
+                                 char *bufOut);
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsAddEscapeCharacter --
+ *
+ *    Callback function that is called by HgfsEnumerate to insert an escape sequence
+ *    into the input name.
+ *
+ * Results:
+ *    TRUE if successful, FALSE if there is an error like the output buffer is
+ *    too small.
+ *
+ * Side effects:
+ *    Updates the output buffer pointer (stored in the context variable).
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsAddEscapeCharacter(char const * bufIn,      // IN: input name
+                       uint32 offset,           // IN: offset that requires escaping
+                       HgfsEscapeReason reason, // IN: reason for esaping
+                       void *context)           // IN/OUT: convertion context
+{
+   HgfsEscapeContext *escapeContext = (HgfsEscapeContext *)context;
+   uint32 charactersToCopy;
+   uint32 outputSpace;
+   char* illegal;
+   Bool result = TRUE;
+
+   ASSERT(offset >= escapeContext->processedOffset); // Scanning forward
+   charactersToCopy = offset - escapeContext->processedOffset;
+
+   if (escapeContext->outputOffset + charactersToCopy >
+       escapeContext->outputBufferLength) {
+      return FALSE;
+   }
+
+   memcpy(escapeContext->outputBuffer + escapeContext->outputOffset,
+          bufIn + escapeContext->processedOffset, charactersToCopy * sizeof *bufIn);
+   escapeContext->outputOffset += charactersToCopy;
+   escapeContext->processedOffset += charactersToCopy;
+
+   outputSpace = escapeContext->outputBufferLength - escapeContext->outputOffset;
+
+   switch(reason) {
+   case HGFS_ESCAPE_ILLEGAL_CHARACTER:
+      if (outputSpace < 2) {
+         return FALSE;
+      }
+      illegal = strchr(HGFS_ILLEGAL_CHARS, bufIn[escapeContext->processedOffset]);
+      escapeContext->processedOffset++;  // Skip illegal input character
+      ASSERT(illegal != NULL);
+      escapeContext->outputBuffer[escapeContext->outputOffset] =
+         HGFS_SUBSTITUTE_CHARS[illegal - HGFS_ILLEGAL_CHARS];
+      escapeContext->outputOffset++;
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_RESERVED_NAME:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_ESCAPE_SEQUENCE:
+      if (outputSpace < 2) {
+         return FALSE;
+      }
+      escapeContext->processedOffset++; // Skip input esape character
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_SUBSTITUE_CHAR;
+      escapeContext->outputOffset++;
+      escapeContext->outputBuffer[escapeContext->outputOffset] = HGFS_ESCAPE_CHAR;
+      escapeContext->outputOffset++;
+      break;
+
+   case HGFS_ESCAPE_COMPLETE:
+      if (outputSpace < 1) {
+         return FALSE;
+      }
+      escapeContext->outputBuffer[escapeContext->outputOffset] = '\0';
+      break;
+
+   default:
+      result = FALSE;
+      ASSERT(FALSE);
+   }
+   return result;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsCountEscapeChars --
+ *
+ *    Callback function that is called by HgfsEnumerate to count additional characters
+ *    that need to be inserted in the input name.
+ *
+ * Results:
+ *    TRUE since it never fails.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsCountEscapeChars(char const *bufIn,       // IN: input name
+                     uint32 offset,           // IN: offset where escape is needed
+                     HgfsEscapeReason reason, // IN: reason for escaping
+                     void *context)           // IN/OUT: context info
+{
+   UNREFERENCED_PARAMETER(bufIn);
+   UNREFERENCED_PARAMETER(offset);
+   if (reason != HGFS_ESCAPE_COMPLETE) {
+      uint32 *counter = (uint32*)context;
+      (*counter)++;
+   }
+   return TRUE;
+}
+
+
+#ifdef _WIN32
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsLetterToUpper --
+ *
+ *    Converts lowercase English letters to uppercase.
+ *    If the symbol is not a lowercase English letter returns the original character.
+ *
+ * Results:
+ *    Converted character.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static char
+HgfsLetterToUpper(char letter)
+{
+   if (letter >= 'a' && letter <= 'z') {
+      return letter - ('a' - 'A');
+   }
+   return letter;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsEqualPrefix --
+ *
+ *    Verifies if the string prefix is equal to the given prefix.
+ *    It assumes that the prefix includes only uppercase English letters or numbers
+ *    and it does not have any international characters.
+ *    The string must be either NULL terminated or not shorter then the prefix.
+ *
+ * Results:
+ *    TRUE if the uppcased string starts with the given prefix. False otherwise.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsEqualPrefix(char const *prefix,  // IN: prefix to check
+                  char const *string,  // IN: input string
+                  uint32 prefixLength) // IN: length of the prefix in characters
+{
+   int i;
+   for (i = 0; i < prefixLength; i++) {
+      ASSERT(prefix[i] > 0 && (prefix[i] < 'a' || prefix[i] > 'z' ));
+      if (prefix[i] != HgfsLetterToUpper(string[i])) {
+         return FALSE;
+      }
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsReservedPrefix --
+ *
+ *    Verifies if the name's prefix is one of the reserved names.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsReservedPrefix(char const *bufIn)  // IN: input name
+{
+   uint32 i;
+   for (i = 0; i < ARRAYSIZE(HgfsReservedNames); i++) {
+      if (HgfsIsEqualPrefix(HgfsReservedNames[i], bufIn,
+                            HGFS_RESERVED_NAME_CHARS_LENGTH)) {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsReservedPrefixWithNumber --
+ *
+ *    Verifies if the name's prefix is one of the reserved names with number:
+ *    COM1-9 or LPT1-9.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names with number.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsReservedPrefixWithNumber(char const *bufIn)   // IN: input name
+{
+   uint32 i;
+   for (i = 0; i < ARRAYSIZE(HgfsReservedNamesWithNumber); i++) {
+      if (HgfsIsEqualPrefix(HgfsReservedNamesWithNumber[i], bufIn,
+                            HGFS_RESERVED_NAME_CHARS_LENGTH) &&
+          bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] >= '1' &&
+          bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] <= '9') {
+         return TRUE;
+      }
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsSpecialCaseEscape --
+ *
+ *    Verifies if the escape character is a part of special case escape sequence
+ *    that exists only in Windows - escaped reserved name or escaped illegal last
+ *    character.
+ *
+ * Results:
+ *    TRUE if the name's prefix is one of the reserved names with number.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsSpecialCaseEscape(char const *bufIn,   // IN: input name
+                        uint32 offset,       // IN: offset of the escape character
+                        uint32 length)       // IN: length of the name in characters
+{
+   if (offset + 1 == length &&
+      strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[offset - 1]) != NULL) {
+      return TRUE;
+   }
+   if (offset == HGFS_RESERVED_NAME_CHARS_LENGTH &&
+      (length == HGFS_RESERVED_NAME_CHARS_LENGTH + 1 || bufIn[offset+1] == '.')) {
+      return HgfsIsReservedPrefix(bufIn);
+   }
+   if (offset == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
+      (length == HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH + 1 ||
+      bufIn[offset+1] == '.')) {
+      return HgfsIsReservedPrefixWithNumber(bufIn);
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsProcessReservedName --
+ *
+ *    Verifies if the name is one of reserved Windows file names.
+ *    If it is a reserved name invokes callback that performs required
+ *    processing.
+ *
+ * Results:
+ *    TRUE if no processing is required of if processing succeeded,
+ *    FALSE if processing failed.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsProcessReservedName(char const *bufIn,              // IN:  Unescaped input buffer
+                        uint32 sizeIn,                  // IN:  Length of the input
+                        HgfsEnumCallback processEscape, // IN:  Callack that is invoked
+                                                        //      if input is reserved name
+                        uint32 *offset,                 // OUT: New offset in the input
+                        void *context)                  // IN/OUT: Context for callback
+{
+   /*  Look reserved names: CON, PRN, AUX, NUL. */
+   if (sizeIn >= HGFS_RESERVED_NAME_CHARS_LENGTH && HgfsIsReservedPrefix(bufIn)) {
+      if (HGFS_RESERVED_NAME_CHARS_LENGTH == sizeIn ||
+         bufIn[HGFS_RESERVED_NAME_CHARS_LENGTH] == '.') {
+         if (!processEscape(bufIn, HGFS_RESERVED_NAME_CHARS_LENGTH,
+                            HGFS_ESCAPE_RESERVED_NAME, context)) {
+            return FALSE;
+         }
+         *offset = HGFS_RESERVED_NAME_CHARS_LENGTH;
+      }
+   }
+
+   /*  Look reserved names with numbers: COM1-9 and LPT1-9. */
+   if (sizeIn >= HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH &&
+       HgfsIsReservedPrefixWithNumber(bufIn)) {
+      if (HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH == sizeIn ||
+         bufIn[HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH] == '.') {
+         if (!processEscape(bufIn, HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH,
+                            HGFS_ESCAPE_RESERVED_NAME, context)) {
+            return FALSE;
+         }
+         *offset = HGFS_RESERVED_NAME_WITH_NUMBER_CHARS_LENGTH;
+      }
+   }
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsProcessLastCharacter --
+ *
+ *    Verifies if the trailing character in the name is a valid last character.
+ *    In Windows it is illegal to have a file name that ends with dot ('.') or
+ *    space (' '). The only exception is "." and ".." directory names.
+ *    If the last character is invalid the function invokes a callback to process it.
+ *
+ * Results:
+ *    TRUE if no processing is required of if processing succeeded,
+ *    FALSE if processing failed.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsProcessLastCharacter(char const *bufIn,              // IN:  Unescaped input buffer
+                         uint32 sizeIn,                  // IN:  Length of the input
+                         HgfsEnumCallback processEscape, // IN:  Callack that is invoked
+                                                         //      when escaping is needed
+                         void *context)                  // IN/OUT: Callback context
+{
+
+   /* If the filename is '.' or '..' we shouldn't escape it. */
+   if ((sizeIn == 1 && bufIn[0] == '.') ||
+       (sizeIn == 2 && bufIn[0] == '.' && bufIn[1] == '.')) {
+      return TRUE;
+   }
+
+   /* Invoke the callback if the last character is illegal. */
+   if (strchr(HGFS_ILLEGAL_LAST_CHARS, bufIn[sizeIn - 1]) != NULL) {
+      if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_ILLEGAL_LAST_CHARACTER, context)) {
+         return FALSE;
+      }
+   }
+   return TRUE;
+}
+
+#endif //  WIN32
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsIsEscapeSequence --
+ *
+ *    Verifies if input buffer has an escape sequence at the position
+ *    defined by offset.
+ *
+ * Results:
+ *    TRUE if there is an escape sequence at the position defined by offset.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsIsEscapeSequence(char const *bufIn,   // IN: input name
+                     uint32 offset,       // IN: offset of the escape character
+                     uint32 length)       // IN: length of the name in characters
+{
+   if (bufIn[offset] == HGFS_ESCAPE_CHAR && offset > 0) {
+      char *substitute;
+      if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
+         return TRUE;
+      }
+      substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
+      if (substitute != NULL) {
+         return TRUE;
+      }
+      return IS_SPECIAL_CASE_ESCAPE(bufIn,offset,length);
+   }
+   return FALSE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeEnumerate --
+ *
+ *    The function scans the input buffer and calls processEscape callback for every
+ *    place in the input buffer which require escaping.
+ *
+ *    Callback does the required processing. There are two different callbacks -
+ *    one counts extra symbols that are needed for escaping and another produces
+ *    escaped output name based on input name.
+ *
+ *    1. The first function calculates number of extra characters. It just increments
+ *    a counter which is passed to it in context variable every time it is called
+ *    for the reason different from "complete processing" assuming that
+ *    exactly one extra  character is required to escape any invalid input.
+ *
+ *    2. The second function produces output name by copying everything from input
+ *    name into the output name up to the place which require escaping and
+ *    then inserts appropriate escape sequence into the output. It keeps track of its
+ *    progress and keeps pointer to the output buffer in the context variable.
+ *    HgfsEscapeEnumerate calls calback function one more time at the end of the
+ *    input buffer to let callback finish processing of the input (for example copy
+ *    the rest of the name after the last escape sequence from input buffer to
+ *    output buffer).
+ *
+ * Results:
+ *    TRUE if the input has been processed successfully by the callback, false otherwise.
+ *
+ * Side effects:
+ *    None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static Bool
+HgfsEscapeEnumerate(char const *bufIn,              // IN:  Buffer with unescaped input
+                    uint32 sizeIn,                  // IN:  Number of input *characters*
+                    HgfsEnumCallback processEscape, // IN: Callack that is invoked every
+                                                    //     time escaping is required
+                    void *context)                  // IN/OUT: Context for processEscape
+{
+   /*  First look for invalid characters in the input name. */
+   uint32 i, offset = 0;
+   if (sizeIn == 0) {
+      return TRUE;
+   }
+
+   ASSERT(processEscape);
+
+   PROCESS_RESERVED_NAME(bufIn, sizeIn, processEscape, &offset, context);
+
+   for (i = offset; i < sizeIn; i++) {
+      if (strchr(HGFS_ILLEGAL_CHARS, bufIn[i]) != NULL) {
+         if (!processEscape(bufIn, i, HGFS_ESCAPE_ILLEGAL_CHARACTER, context)) {
+            return FALSE;
+         }
+      } else if (HgfsIsEscapeSequence(bufIn, i, sizeIn)) {
+         if (!processEscape(bufIn, i, HGFS_ESCAPE_ESCAPE_SEQUENCE, context)) {
+            return FALSE;
+         }
+      }
+   }
+
+   PROCESS_LAST_CHARACTER(bufIn, sizeIn, processEscape, context);
+
+   if (!processEscape(bufIn, sizeIn, HGFS_ESCAPE_COMPLETE, context)) {
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_Do --
+ *
+ *    Escape any characters that are not legal in a windows filename.
+ *    Escape reserved file names that can't be used in Windows.
+ *    We also of course have to escape the escape character, which is "%",
+ *    when it is part of a character sequence that would require unescaping
+ *
+ *    sizeBufOut must account for the NUL terminator.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    On failure (bufOut not big enough to hold result), negative value.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_Do(char const *bufIn, // IN:  Buffer with unescaped input
+                  uint32 sizeIn,     // IN:  Size of input buffer
+                  uint32 sizeBufOut, // IN:  Size of output buffer
+                  char *bufOut)      // OUT: Buffer for escaped output
+{
+   const char *currentComponent = bufIn;
+   uint32 sizeLeft = sizeBufOut;
+   char *outPointer = bufOut;
+   const char *end = bufIn + sizeIn;
+   const char *next;
+   ASSERT(sizeIn > 0);
+   if (bufIn[sizeIn - 1] == '\0') {
+      /*
+       * In some cases a NUL terminated string is passed to HgfsEscape_Do
+       * so it make sense to support such input even if CPName_GetComponent
+       * does not. Detect this case and make the input compliant with
+       * CPName_GetComponent by removing terminating NUL.
+       */
+      end--;
+      sizeIn--;
+   }
+   /*
+    * Absolute symbolic link name starts with the '\0'. HgfsEscapeDo needs to work
+    * with such names. Leading NULL symbols should be skipped here since
+    * CPName_GetComponent does not support such names.
+    */
+   while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
+      currentComponent++;
+      sizeLeft--;
+      *outPointer++ = '\0';
+   }
+   while (currentComponent - bufIn < sizeIn) {
+      int escapedLength;
+      uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
+
+      escapedLength = HgfsEscapeDoComponent(currentComponent, componentSize,
+                                            sizeLeft, outPointer);
+      if (escapedLength < 0) {
+         return escapedLength;
+      }
+      currentComponent = next;
+      sizeLeft -= escapedLength + 1;
+      outPointer += escapedLength + 1;
+   }
+   return (int) (outPointer - bufOut) - 1; // Do not count the last NUL terminator
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_GetSize --
+ *
+ *    Calculates required size in bytes for the buffer that is needed to hold escaped
+ *    cross platform path name. Returns 0 if no escaping is required.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    Returns 0 if the name is a valid Windows file name.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_GetSize(char const *bufIn,    // IN:  Buffer with unescaped input
+                   uint32 sizeIn)        // IN:  Size of the input buffer
+{
+   uint32 result = 0;
+   const char *currentComponent = bufIn;
+   const char *end = bufIn + sizeIn;
+   const char *next;
+
+   if (sizeIn == 0) { // No need toescape empty name.
+      return 0;
+   }
+   if (bufIn[sizeIn - 1] == '\0') {
+      /*
+       * In some cases a NUL terminated string is passed to HgfsEscape_GeSize
+       * so it make sense to support such input even if CPName_GetComponent
+       * does not. Detect this case and make the input compliant with
+       * CPName_GetComponent by removing terminating NUL.
+       */
+      end--;
+      sizeIn--;
+   }
+   /* Skip leading NULs to keep CPName_GetComponent happy. */
+   while (*currentComponent == '\0' && currentComponent - bufIn < sizeIn) {
+      currentComponent++;
+   }
+   while (currentComponent - bufIn < sizeIn) {
+      uint32 componentSize = CPName_GetComponent(currentComponent, end, &next);
+      result += HgfsEscapeGetComponentSize(currentComponent, componentSize);
+      currentComponent = next;
+   }
+   return (result == 0) ? 0 : result + sizeIn;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscape_Undo --
+ *
+ *    Unescape a buffer that was escaped using HgfsEscapeBuffer.
+ *
+ *    The unescaping is done in place in the input buffer, and
+ *    can not fail.
+ *
+ * Results:
+ *    The size (excluding the NUL terminator) of the unescaped, NUL
+ *    terminated buffer.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscape_Undo(char *bufIn,       // IN: Characters to be unescaped
+                uint32 sizeIn)     // IN: Number of characters in bufIn
+{
+   uint32 componentSize = strlen(bufIn) + 1;
+   uint32 unprocessedSize = sizeIn + 1;
+   uint32 result = 0;
+   char *currentComponent = bufIn;
+   while (currentComponent != NULL) {
+      HgfsEscapeUndoComponent(currentComponent, &unprocessedSize);
+      componentSize = strlen(currentComponent) + 1; // Unescaped size
+      result += componentSize;
+      if (unprocessedSize > 1) {
+         currentComponent = currentComponent + componentSize;
+         componentSize = strlen(currentComponent) + 1; // Size of the next component
+      } else {
+         currentComponent = NULL;
+      }
+   }
+   return result - 1;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeUndoComponent --
+ *
+ *    Unescape a buffer that was escaped using HgfsEscapeBuffer.
+ *
+ *    The unescaping is done in place in the input buffer, and
+ *    can not fail.
+ *
+ * Results:
+ *    None
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+HgfsEscapeUndoComponent(char   *bufIn,             // IN: Characters to be unescaped
+                        uint32 *unprocessedLength) // IN: Unprocessed characters
+                                                   //     in the whole name
+{
+   size_t offset;
+   size_t sizeIn = strlen(bufIn);
+   char* curOutBuffer = bufIn;
+   char* escapePointer;
+   ASSERT(bufIn);
+
+   escapePointer = strchr(curOutBuffer, HGFS_ESCAPE_CHAR);
+   while (escapePointer != NULL) {
+      offset = escapePointer - bufIn;
+      if (HgfsIsEscapeSequence(bufIn, offset, sizeIn)) {
+         char* substitute = strchr(HGFS_SUBSTITUTE_CHARS, bufIn[offset - 1]);
+         if (substitute != NULL) {
+            bufIn[offset - 1] = HGFS_ILLEGAL_CHARS[substitute - HGFS_SUBSTITUTE_CHARS];
+         } else if (bufIn[offset - 1] == HGFS_ESCAPE_SUBSTITUE_CHAR) {
+            bufIn[offset - 1] = HGFS_ESCAPE_CHAR;
+         }
+         memmove(escapePointer, escapePointer + 1, (*unprocessedLength) - offset - 1);
+         (*unprocessedLength)--;
+         sizeIn--;
+         if (sizeIn > 0) {
+            escapePointer = strchr(escapePointer, HGFS_ESCAPE_CHAR);
+         } else {
+            escapePointer = NULL;
+         }
+      } else {
+         escapePointer = strchr(escapePointer + 1, HGFS_ESCAPE_CHAR);
+      }
+   }
+   ASSERT((*unprocessedLength) > sizeIn);
+   (*unprocessedLength) -= sizeIn + 1;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeDoComponent --
+ *
+ *    Escape any characters that are not legal in a windows filename.
+ *    Escape reserved file names that can't be used in Windows.
+ *    We also of course have to escape the escape character, which is "%",
+ *    when it is part of a character sequence that would require unescaping
+ *
+ *    sizeBufOut must account for the NUL terminator.
+ *
+ * Results:
+ *    On success, the size (excluding the NUL terminator) of the
+ *    escaped, NUL terminated buffer.
+ *    On failure (bufOut not big enough to hold result), negative value.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscapeDoComponent(char const *bufIn, // IN:  Buffer with unescaped input
+                          uint32 sizeIn,     // IN:  Size of input buffer
+                          uint32 sizeBufOut, // IN:  Size of output buffer
+                          char *bufOut)      // OUT: Buffer for escaped output
+{
+   HgfsEscapeContext conversionContext;
+   conversionContext.processedOffset = 0;
+   conversionContext.outputBufferLength = sizeBufOut / sizeof *bufOut;
+   conversionContext.outputOffset = 0;
+   conversionContext.outputBuffer = bufOut;
+
+   if (!HgfsEscapeEnumerate(bufIn, sizeIn, HgfsAddEscapeCharacter, &conversionContext)) {
+      return -1;
+   }
+   return conversionContext.outputOffset * sizeof *bufOut;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsEscapeGetComponentSize --
+ *
+ *    Calculates number of addtitional characters that are needed to escape
+ *    name for one NUL terminated component of the path.
+ *
+ * Results:
+ *    Number of additional escape characters needed to escape the name.
+ *    Returns 0 if no escaping is required.
+ *
+ * Side effects:
+ *    None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+int
+HgfsEscapeGetComponentSize(char const *bufIn, // IN:  Buffer with unescaped input
+                           uint32 sizeIn)     // IN:  Size of the in input buffer
+{
+   int result = 0;
+   HgfsEscapeEnumerate(bufIn, sizeIn, HgfsCountEscapeChars, &result);
+   return result;
+}
diff --git a/open-vm-tools/modules/linux/vsock/include/vmciHostKernelAPI.h b/open-vm-tools/modules/linux/vsock/include/vmciHostKernelAPI.h
new file mode 100644 (file)
index 0000000..e8e25a9
--- /dev/null
@@ -0,0 +1,141 @@
+/*********************************************************
+ * Copyright (C) 2007 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 and no later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ *********************************************************/
+
+/* 
+ * vmciHostKernelAPI.h --
+ *
+ *    Kernel API exported from the VMCI host driver.
+ */
+
+#ifndef __VMCI_HOSTKERNELAPI_H__
+#define __VMCI_HOSTKERNELAPI_H__
+
+#define INCLUDE_ALLOW_MODULE
+#define INCLUDE_ALLOW_VMMON
+#define INCLUDE_ALLOW_VMCORE
+#define INCLUDE_ALLOW_VMK_MODULE
+#define INCLUDE_ALLOW_VMKERNEL
+#define INCLUDE_ALLOW_DISTRIBUTE
+#include "includeCheck.h"
+
+
+/* VMCI host kernel API version number. */
+#define VMCI_HOST_KERNEL_API_VERSION  1
+
+/* Macros to operate on the driver version number. */
+#define VMCI_MAJOR_VERSION(v)       (((v) >> 16) & 0xffff)
+#define VMCI_MINOR_VERSION(v)       ((v) & 0xffff)
+
+#include "vmci_defs.h"
+#ifdef VMKERNEL
+#include "vm_atomic.h"
+#include "return_status.h"
+#include "util_copy_dist.h"
+#endif
+#include "vmci_defs.h"
+#include "vmci_call_defs.h"
+
+
+#ifdef VMKERNEL
+#endif
+
+
+/* VMCI Datagram API. */
+
+int VMCIHost_DatagramCreateHnd(VMCIId resourceID, uint32 flags,
+                              VMCIDatagramRecvCB recvCB, void *clientData,
+                              VMCIHandle *outHandle);
+int VMCIDatagram_CreateHnd(VMCIId resourceID, uint32 flags,
+                          VMCIDatagramRecvCB recvCB, void *clientData,
+                          VMCIHandle *outHandle);
+int VMCIDatagram_CreateHndPriv(VMCIId resourceID, uint32 flags,
+                              VMCIPrivilegeFlags privFlags,
+                              VMCIDatagramRecvCB recvCB, void *clientData,
+                              VMCIHandle *outHandle);
+int VMCIDatagram_DestroyHnd(VMCIHandle handle);
+int VMCIDatagram_Send(VMCIDatagram *msg);
+
+
+/* VMCI Event API  */
+
+typedef void (*VMCI_EventCB)(VMCIId subID, VMCI_EventData *ed,
+                            void *clientData);
+
+int VMCIEvent_Subscribe(VMCI_Event event, VMCI_EventCB callback, 
+                        void *callbackData, VMCIId *subID);
+int VMCIEvent_Unsubscribe(VMCIId subID);
+
+/* 
+ * Since QP API for non-VMKernel hosts is defined in vmci_queue_pair.h, here
+ * declarations are included only for VMKERNEL
+ */
+#ifdef VMKERNEL
+
+/*
+ * For guest kernels, the VMCIQueue is directly mapped onto the
+ * metadata page of the queue. In vmkernel, we use the VMCIQueue
+ * structure to store the information necessary to retrieve the MPNs
+ * of the queue. By redefining the structure, queue pair code using
+ * the API below will be portable between guests and host kernels.
+ */
+
+typedef struct VMCIQueue {
+   uint32 offset;                // Start page of queue in backing store
+   uint32 len;                   // Number of pages in the queue 
+   struct QueuePairEntry *entry; // Endpoint state for the queue pair
+} VMCIQueue;
+
+
+/* VMCI Queuepair API  */
+void VMCIQueue_Init(const VMCIHandle handle, VMCIQueue *queue);
+void VMCIQueue_GetPointers(const VMCIQueue *produceQ, const VMCIQueue *consumeQ,
+                           uint64 *producerTail, uint64 *consumerHead);
+int VMCIQueuePair_Alloc(VMCIHandle *handle, VMCIQueue **produceQ,
+                        uint64 produceSize, VMCIQueue **consumeQ,
+                        uint64 consumeSize, VMCIId peer, uint32 flags);
+int VMCIQueuePair_Detach(VMCIHandle handle);
+int64 VMCIQueue_FreeSpace(const VMCIQueue *produceQueue,
+                          const VMCIQueue *consumeQueue,
+                          const uint64 produceQSize);
+int64 VMCIQueue_BufReady(const VMCIQueue *consumeQueue,
+                         const VMCIQueue *produceQueue,
+                         const uint64 consumeQSize);
+ssize_t VMCIQueue_Enqueue(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                          const uint64 produceQSize, const void *buf,
+                          size_t bufSize, Util_BufferType bufType);
+ssize_t VMCIQueue_Peek(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                       const uint64 consumeQSize, void *buf,
+                       size_t bufSize, Util_BufferType bufType);
+ssize_t VMCIQueue_PeekV(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                        const uint64 consumeQSize, void *buf,
+                        size_t bufSize, Util_BufferType bufType);
+ssize_t VMCIQueue_Discard(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                          const uint64 consumeQSize, size_t bufSize);
+ssize_t VMCIQueue_Dequeue(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                          const uint64 consumeQSize, void *buf,
+                          size_t bufSize, Util_BufferType bufType);
+ssize_t VMCIQueue_EnqueueV(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                           const uint64 produceQSize, const void *buf,
+                           size_t bufSize, Util_BufferType bufType);
+ssize_t VMCIQueue_DequeueV(VMCIQueue *produceQueue, const VMCIQueue *consumeQueue,
+                           const uint64 consumeQSize, void *buf,
+                           size_t bufSize, Util_BufferType bufType);
+#endif /* VMKERNEL  */
+
+#endif /* !__VMCI_HOSTKERNELAPI_H__ */
+