HEX
Server: Apache
System: Linux sg241.singhost.net 2.6.32-896.16.1.lve1.4.51.el6.x86_64 #1 SMP Wed Jan 17 13:19:23 EST 2018 x86_64
User: honghock (909)
PHP: 8.0.30
Disabled: passthru,system,shell_exec,show_source,exec,popen,proc_open
Upload Files
File: //usr/lib/vmware-tools/modules/source/legacy/pvscsi.tar
pvscsi-only/0000755000000000000000000000000012025726723012050 5ustar  rootrootpvscsi-only/autoconf/0000755000000000000000000000000012025726722013665 5ustar  rootrootpvscsi-only/autoconf/geninclude.c0000444000000000000000000000226412025726723016151 0ustar  rootroot/*********************************************************
 * 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

pvscsi-only/autoconf/cachecreate.c0000444000000000000000000000320612025726723016260 0ustar  rootroot/*********************************************************
 * 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
pvscsi-only/autoconf/cachector.c0000444000000000000000000000326612025726723015772 0ustar  rootroot/*********************************************************
 * 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
pvscsi-only/driver-config.h0000444000000000000000000000425012025726723014756 0ustar  rootroot/*********************************************************
 * 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
pvscsi-only/compat_scsi.h0000444000000000000000000000302412025726723014522 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/compat_pci.h0000444000000000000000000004157512025726723014351 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/compat_module.h0000444000000000000000000000437212025726723015055 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/compat_ioport.h0000444000000000000000000000404112025726723015075 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/compat_version.h0000444000000000000000000000616512025726723015257 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/compat_interrupt.h0000444000000000000000000000357312025726723015626 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/Makefile.kernel0000444000000000000000000000227212025726723014770 0ustar  rootroot#!/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)))
pvscsi-only/pvscsi.c0000444000000000000000000010631312025726723013525 0ustar  rootroot/*********************************************************
 * 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);
/*
 * Starting with SLE10sp2, Novell requires that IHVs sign a support agreement
 * with them and mark their kernel modules as externally supported via a
 * change to the module header. If this isn't done, the module will not load
 * by default (i.e., neither mkinitrd nor modprobe will accept it).
 */
MODULE_INFO(supported, "external");

#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++;
	}
}
pvscsi-only/pvscsi_version.h0000444000000000000000000000222012025726723015267 0ustar  rootroot/*********************************************************
 * 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_ */
pvscsi-only/includeCheck.h0000444000000000000000000001024612025726723014603 0ustar  rootroot/*********************************************************
 * 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
pvscsi-only/pvscsi_defs.h0000444000000000000000000003121612025726723014532 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/scsi_defs.h0000444000000000000000000024763112025726723014176 0ustar  rootroot/*********************************************************
 * 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       :4,
         tpgs  :2,         // Target Portal Group Support
               :2;
#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       :4,
         tpgs  :2,         // Target Portal Group Support
               :2;
   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},	\
   {0x8f,                      SCSI_XFER_AUTO,     NULL, SCSI_DONT_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
pvscsi-only/vm_assert.h0000444000000000000000000002422012025726723014222 0ustar  rootroot/*********************************************************
 * 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_ */
pvscsi-only/vm_basic_defs.h0000444000000000000000000003156512025726723015015 0ustar  rootroot/*********************************************************
 * 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.

#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 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) || defined(__FreeBSD__)
/* 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

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

#endif // ifndef _VM_BASIC_DEFS_H_
pvscsi-only/vm_basic_types.h0000444000000000000000000005624212025726723015237 0ustar  rootroot/*********************************************************
 * 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'
#if !defined VMX86_DEVEL // XXX until we clean up all the code -- edward
#pragma warning (disable :4133) // incompatible types - from 'struct VM *' to 'int *'
#pragma warning (disable :4047) // differs in levels of indirection
#endif
#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

#if !defined(USING_AUTOCONF)
#   if defined(__FreeBSD__) || defined(sun)
#      ifdef KLD_MODULE
#         include <sys/types.h>
#      else
#         if (BSD_VERSION >= 50)
#            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"
      #define FMTPD     "t"
   #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)0)

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)0)

/* 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


#define EXTERN        extern
#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_ */
pvscsi-only/vm_device_version.h0000444000000000000000000001611412025726723015730 0ustar  rootroot/*********************************************************
 * 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)
 */
#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


/************* 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 */
pvscsi-only/vmware_pack_init.h0000444000000000000000000000364412025726723015550 0ustar  rootroot/*********************************************************
 * 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__ */
pvscsi-only/vmware_pack_begin.h0000444000000000000000000000244412025726723015666 0ustar  rootroot/*********************************************************
 * 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
pvscsi-only/vmware_pack_end.h0000444000000000000000000000247012025726723015347 0ustar  rootroot/*********************************************************
 * 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
pvscsi-only/Makefile0000444000000000000000000000726412025726723013517 0ustar  rootroot#!/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
endif

vm_check_build = $(shell if $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
	$(CPPFLAGS) $(CFLAGS) $(CFLAGS_KERNEL) $(LINUXINCLUDE) \
	$(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:
pvscsi-only/COPYING0000444000000000000000000004310312025726723013102 0ustar  rootroot		    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.