pvscsi-only/ 0000755 0000000 0000000 00000000000 12025726723 012050 5 ustar root root pvscsi-only/autoconf/ 0000755 0000000 0000000 00000000000 12025726722 013665 5 ustar root root pvscsi-only/autoconf/geninclude.c 0000444 0000000 0000000 00000002264 12025726723 016151 0 ustar root root /*********************************************************
* 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
#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.c 0000444 0000000 0000000 00000003206 12025726723 016260 0 ustar root root /*********************************************************
* 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
#include
/*
* 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
struct kmem_cache *kmemtest(void) {
return kmem_cache_create("test", 12, 0, 0, NULL, NULL);
}
#endif
pvscsi-only/autoconf/cachector.c 0000444 0000000 0000000 00000003266 12025726723 015772 0 ustar root root /*********************************************************
* 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
#include
/*
* 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
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.h 0000444 0000000 0000000 00000004250 12025726723 014756 0 ustar root root /*********************************************************
* 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
#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
# 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
# define _STDINT_H 1
#endif
#ifndef __KERNEL__
# define __KERNEL__
#endif
#endif
pvscsi-only/compat_scsi.h 0000444 0000000 0000000 00000003024 12025726723 014522 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000041575 12025726723 014351 0 ustar root root /*********************************************************
* 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
#ifndef KERNEL_2_1
# include
#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.h 0000444 0000000 0000000 00000004372 12025726723 015055 0 ustar root root /*********************************************************
* 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
/*
* 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.h 0000444 0000000 0000000 00000004041 12025726723 015075 0 ustar root root /*********************************************************
* 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
#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.h 0000444 0000000 0000000 00000006165 12025726723 015257 0 ustar root root /*********************************************************
* 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
/* 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.h 0000444 0000000 0000000 00000003573 12025726723 015626 0 ustar root root /*********************************************************
* 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
#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.kernel 0000444 0000000 0000000 00000002272 12025726723 014770 0 ustar root root #!/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.c 0000444 0000000 0000000 00000106313 12025726723 013525 0 ustar root root /*********************************************************
* 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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.h 0000444 0000000 0000000 00000002220 12025726723 015267 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000010246 12025726723 014603 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000031216 12025726723 014532 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000247631 12025726723 014176 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000024220 12025726723 014222 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000031565 12025726723 015015 0 ustar root root /*********************************************************
* 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 /*
* We re-define offsetof macro from stddef, make
* sure that its already defined before we do it
*/
#include // for Sleep() and LOWORD() etc.
#endif
/*
* Simple macros
*/
#if defined __APPLE__ && !defined KERNEL
# include
#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
#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 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 // 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.h 0000444 0000000 0000000 00000056242 12025726723 015237 0 ustar root root /*********************************************************
* 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
#endif
#ifdef HAVE_SYS_TYPES_H
#include
#endif
#ifdef HAVE_SYS_INTTYPES_H
#include
#endif
#ifdef HAVE_STDINT_H
#include
#endif
#ifdef HAVE_STDLIB_H
#include
#endif
#if !defined(USING_AUTOCONF)
# if defined(__FreeBSD__) || defined(sun)
# ifdef KLD_MODULE
# include
# else
# if (BSD_VERSION >= 50)
# include
# include
# else
# include
# endif
# endif
# elif defined __APPLE__
# if KERNEL
# include
# include /* mostly for size_t */
# include
# else
# include
# include
# include
# include
# 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.h 0000444 0000000 0000000 00000016114 12025726723 015730 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000003644 12025726723 015550 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000002444 12025726723 015666 0 ustar root root /*********************************************************
* 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.h 0000444 0000000 0000000 00000002470 12025726723 015347 0 ustar root root /*********************************************************
* 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/Makefile 0000444 0000000 0000000 00000007264 12025726723 013517 0 ustar root root #!/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/COPYING 0000444 0000000 0000000 00000043103 12025726723 013102 0 ustar root root 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.
Copyright (C)
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.
, 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.