vmkdrivers/BLD/build/HEADERS/vmkapi-current/vmkernel64/release/scsi/vmkapi_scsi.h
2015-10-23 15:21:55 -04:00

1259 lines
45 KiB
C

/***************************************************************************
* Copyright 2004 - 2009 VMware, Inc. All rights reserved.
***************************************************************************/
/*
* @VMKAPIMOD_LICENSE@
*/
/*
***********************************************************************
* SCSI */ /**
* \addtogroup Storage
* @{
* \defgroup SCSI SCSI Interfaces
* @{
***********************************************************************
*/
#ifndef _VMKAPI_SCSI_H_
#define _VMKAPI_SCSI_H_
/** \cond never */
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
#error This vmkapi file should never be included directly but only via vmkapi.h
#endif
/** \endcond never */
#include "base/vmkapi_heap.h"
#include "base/vmkapi_memory.h"
#include "base/vmkapi_scatter_gather.h"
#include "base/vmkapi_status.h"
#include "base/vmkapi_types.h"
#include "base/vmkapi_const.h"
#include "base/vmkapi_revision.h"
#include "scsi/vmkapi_scsi_const.h"
#include "scsi/vmkapi_scsi_types.h"
#include "device/vmkapi_vector.h"
/*
* Physical Path
*/
/*
***********************************************************************
* vmk_ScsiDeviceClassToString -- */ /**
*
* \ingroup SCSI
*
* \brief Convert a SCSI class identifier into a human-readable text
* string.
*
* \param[in] sclass SCSI class to convert.
*
* \return The description string.
*
***********************************************************************
*/
const char *vmk_ScsiDeviceClassToString(
vmk_ScsiDeviceClass sclass);
/*
***********************************************************************
* vmk_ScsiScanPaths -- */ /**
*
* \ingroup SCSI
*
* \brief Scan one or more physical paths.
*
* The discovered paths are automatically registered with the
* storage stack.
*
* The sparse luns, max lun id and lun mask settings affect which
* paths are actually scanned.
*
* \note If this routine returns an error, some paths may have been
* sucessfully discovered.
* \note This function may block.
*
* \param[in] adapterName Name of the adapter to scan, or
* VMK_SCSI_PATH_ANY_ADAPTER to scan all
* adapters.
* \param[in] channel Channel to scan, or VMK_SCSI_PATH_ANY_CHANNEL
* to scan all channels.
* \param[in] target Target id to scan, or VMK_SCSI_PATH_ANY_TARGET
* to scan all targets.
* \param[in] lun LUN id to scan, or VMK_SCSI_PATH_ANY_LUN to
* scan all LUNs.
*
*
* \retval VMK_INVALID_NAME The requested adapter was not found.
* \retval VMK_BUSY The requested adapter is currently being
* scanned by some other context.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiScanPaths(
const char *adapterName,
vmk_uint32 channel,
vmk_uint32 target,
vmk_uint32 lun);
/*
***********************************************************************
* vmk_ScsiScanAndClaimPaths -- */ /**
*
* \ingroup SCSI
*
* \brief Scan one or more physical paths and run the plugin claim rules.
*
* The discovered paths are automatically registered with the
* storage stack. Path claim is invoked after a successful scan.
* This may result in new SCSI devices being registered with VMkernel.
*
* The sparse luns, max lun id and lun mask settings affect which
* paths are actually scanned.
*
* \note This function may block.
*
* \param[in] adapterName Name of the adapter to scan, or
* \em VMK_SCSI_PATH_ANY_ADAPTER to scan all
* adapters.
* \param[in] channel Channel to scan, or
* \em VMK_SCSI_PATH_ANY_CHANNEL to scan all
* channels.
* \param[in] target Target id to scan, or
* \em VMK_SCSI_PATH_ANY_TARGET to scan all
* targets.
* \param[in] lun LUN id to scan, or \em VMK_SCSI_PATH_ANY_LUN
* to scan all LUNs.
*
* \return It can return all the errors that vmk_ScsiScanPaths() can return.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiScanAndClaimPaths(
const char *adapterName,
vmk_uint32 channel,
vmk_uint32 target,
vmk_uint32 lun);
/*
***********************************************************************
* vmk_ScsiScanDeleteAdapterPath -- */ /**
*
* \ingroup SCSI
*
* \brief Scan a physical path and remove it if dead
*
* The path will be unclaimed and removed only if it is dead.
* This may result in a SCSI device being unregistered with VMkernel
* in the case where this is the last path backing that device.
* If there are users of the device and it is the last path to the
* device, then the unclaim and deletion of the path will fail.
*
* The sparse luns, max lun id and lun mask settings affect whether
* the path is actually scanned or not.
*
* \note This function may block.
*
* \note Do NOT use a loop around this call to rescan every possible
* path on an adapter. This API is only intended for removal of
* specific paths based on a plugins better knowledge of such a
* path being removed. In general VMware wants the end user to
* know about dead paths so misconfigurations can be fixed and
* a plugin should thus never remove a path if it does not have
* special knowledge from the backing device about the path
* being dead and that this knowledge is irrelevant to the user
* (e.g. because the user removed the device through device
* specific means etc.).
*
* \param[in] adapterName Name of the adapter to scan
* \param[in] channel Channel to scan
* \param[in] target Target id to scan
* \param[in] lun LUN id to scan
*
* \return It can return all the errors that vmk_ScsiScanPaths() can
* return as well as VMK_BAD_PARAM if the channel/target/lun
* is an ANY parameter (you can only scan one specific path).
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiScanDeleteAdapterPath(
const char *adapterName,
vmk_uint32 channel,
vmk_uint32 target,
vmk_uint32 lun);
/*
***********************************************************************
* vmk_ScsiNotifyPathStateChange -- */ /**
*
* \ingroup SCSI
*
* \brief Notify the VMkernel of a possible path state change (sync).
*
* Path is identified by \em vmkAdapter, \em channel, \em target
* and \em lun.
* This interface does the path probe in the calling context.
* The function returns the result from an attempt to probe the
* state of the path(s) without retrying on error conditions.
*
* \note This function may block.
* \note No spin lock may be held when calling this function.
*
* \param[in] vmkAdapter Name of the adapter for state change.
* \param[in] channel Channel for state change.
* \param[in] target Target for state change.
* \param[in] lun LUN for state change. If -1, scan all
* LUNs on the given adapter, channel,
* and target.
*
* \retval VMK_NOT_FOUND Requested path was not found. This will
* be returned only when a specific \em lun
* is mentioned (not for \em lun==-1).
* \retval VMK_BUSY Requested path is already being probed.
*
* \return Any other error indicates some plugin specific error while
* probing for the path.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiNotifyPathStateChange(
vmk_ScsiAdapter *vmkAdapter,
vmk_int32 channel,
vmk_int32 target,
vmk_int32 lun);
/*
***********************************************************************
* vmk_ScsiNotifyPathStateChangeAsync -- */ /**
*
* \ingroup SCSI
*
* \brief Notify the VMkernel of a possible path state change (async).
*
* Path is identified by \em vmkAdapter, \em channel, \em target,
* \em lun. Unlike vmk_ScsiNotifyPathStateChange(), which does the
* path probe in the calling context, this function only schedules
* the path probe to happen in separate context. Hence there is no
* restriction on the calling context (interrupt, or bottom-half,
* or kernel context) and the locks held on entry.
*
* The function returns the result of an attempt to schedule a
* probe of the state of the path(s). The result of the probe
* itself is not returned. In the face of error conditions,
* the probe will be retried a large number of times.
*
* \param[in] vmkAdapter Name of the adapter for state change.
* \param[in] channel Channel for state change.
* \param[in] target Target for state change.
* \param[in] lun LUN for state change. If -1, scan all
* LUNs on the given adapter, channel,
* and target.
*
* \retval VMK_NO_MEMORY Out of memory.
* \retval VMK_NO_RESOURCES Failed to schedule the asynchronous path
* probe due to lack of resources.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiNotifyPathStateChangeAsync(
vmk_ScsiAdapter *vmkAdapter,
vmk_int32 channel,
vmk_int32 target,
vmk_int32 lun);
/*
***********************************************************************
* vmk_ScsiInitTaskMgmt -- */ /**
*
* \ingroup SCSI
*
* \brief Create a task management request filter.
*
* A task management request filter consists of two things:
*
* - A TASK MANAGEMENT action (abort, device reset, bus reset, lun
* reset etc). This is the \em type parameter.
*
* - A rule to define the commands on which the above action should
* be performed. This is defined by the \em cmdId parameter.
*
* A task management request filter thus created can then be used by any
* subsequent functions that expect a \em vmk_ScsiTaskMgmt argument.
*
* \param[in] vmkTask The task management structure to initialize.
* \param[in] type Type of task management request.
* \param[in] cmdId Identifier of the command(s) to abort.
* This field is only valid for abort and virtual
* reset. It is ignored otherwise.
* \em VMK_SCSI_TASKMGMT_ANY_INITIATOR is only
* valid for virtual reset.
* cmdID.initiator may one of the following:
* - cmdID.initiator from the vmk_ScsiCommand
* structure.
* - \em VMK_SCSI_TASKMGMT_ANY_INITIATOR.
* - NULL
* If initiator is from the vmk_ScsiCommand
* structure and type is \em VMK_SCSI_TASKMGMT_ABORT,
* then cmdID.serialNumber can also be obtained
* from vmk_ScsiCommand (cmdID.serialNumber)
* else 0.
* cmdID.serialNumber is only valid for abort.
* It is ignored otherwise.
* \param[in] worldId World on behalf of whom the command was issued.
* This argument is only valid for abort and
* virtual reset. It is ignored otherwise.
*
* \par Examples:
* - Abort a specific I/O:
* \code
* vmk_ScsiInitTaskMgmt(task, VMK_SCSI_TASKMGMT_ABORT,
* vmkCmd->cmdId, vmkCmd->worldId);
* \endcode
* - Abort all i/os issued by a single world:
* \code
* cmdId.initiator = VMK_SCSI_TASKMGMT_ANY_INITIATOR;
* cmdId.serialNumber = 0;
* vmk_ScsiInitTaskMgmt(task, VMK_SCSI_TASKMGMT_VIRT_RESET,
* cmdId, worldId);
* \endcode
* - Abort all i/os issued by a single world from a specific initiator:
* \code
* cmdId.initiator = originalInitiator:
* cmdId.serialNumber = 0;
* vmk_ScsiInitTaskMgmt(task, VMK_SCSI_TASKMGMT_VIRT_RESET,
* cmdId, worldId);
* \endcode
* - Abort all i/os issued by all worlds:
* \code
* cmdId.initiator = NULL;
* cmdId.serialNumber = 0;
* vmk_ScsiInitTaskMgmt(task, VMK_SCSI_TASKMGMT_LUN_RESET,
* cmdId, worldId);
* \endcode
* The worldID should be the World ID of the reset issuer.
*
***********************************************************************
*/
void vmk_ScsiInitTaskMgmt(
vmk_ScsiTaskMgmt *vmkTask,
vmk_ScsiTaskMgmtType type,
vmk_ScsiCommandId cmdId,
vmk_uint32 worldId);
/*
***********************************************************************
* vmk_ScsiQueryTaskMgmt -- */ /**
*
* \ingroup SCSI
*
* \brief Matches a SCSI command against a task management request
* filter, and returns the action to be taken for that command.
*
* The task management request filter is obtained by a call to
* vmk_ScsiInitTaskMgmt()
*
* \param[in] vmkTaskMgmt Task management request.
* \param[in] cmd Command to check.
*
* \retval VMK_SCSI_TASKMGMT_ACTION_IGNORE No task management action to
* be taken for this command.
* \retval VMK_SCSI_TASKMGMT_ACTION_ABORT Complete this command with
* status
* \em vmkTaskMgmt->\em status
*
***********************************************************************
*/
vmk_ScsiTaskMgmtAction vmk_ScsiQueryTaskMgmt(
const vmk_ScsiTaskMgmt *vmkTaskMgmt,
const vmk_ScsiCommand *cmd);
/*
***********************************************************************
* vmk_ScsiGetTaskMgmtTypeName -- */ /**
*
* \ingroup SCSI
*
* \brief Returns a human readable description of the task management
* request.
*
* \param[in] taskMgmtType Task management type to convert to a
* string.
*
* \return The description string.
*
***********************************************************************
*/
const char *vmk_ScsiGetTaskMgmtTypeName(
vmk_ScsiTaskMgmtType taskMgmtType);
/*
***********************************************************************
* vmk_ScsiDebugDropCommand -- */ /**
*
* \ingroup SCSI
*
* \brief Tell whether a command should be dropped.
*
* This is used for fault injection.
*
* \param[in] adapter Adapter the command would be issued to.
* \param[in] cmd Command to check.
*
* \retval VMK_TRUE The command should be dropped.
* \retval VMK_FALSE The command should not be dropped.
*
* \note vmk_ScsiDebugDropCommand() always returns VMK_FALSE for release
* builds.
*
***********************************************************************
*/
vmk_Bool
vmk_ScsiDebugDropCommand(vmk_ScsiAdapter *adapter, vmk_ScsiCommand *cmd);
/*
***********************************************************************
* vmk_ScsiAdapterEvent -- */ /**
*
* \ingroup SCSI
*
* \brief Notifies the VMkernel of a specific event on the
* specified adapter.
*
* \param[in] adapter Pointer to the adapter to signal the event on.
* \param[in] eventType Event to signal.
*
* \retval VMK_BUSY Another adapter event is being processed.
* \retval VMK_NO_MEMORY Out of memory.
*
* \return Any other error value indicates some internal error
* encountered while notifying VMkernel.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_ScsiAdapterEvent(vmk_ScsiAdapter *adapter, vmk_uint32 eventType);
/*
***********************************************************************
* vmk_ScsiAdapterIsPAECapable -- */ /**
*
* \ingroup SCSI
*
* \brief Determines if the adapter supports DMA beyond 32 bits of
* machine-address space.
*
* \param[in] adapter Adapter to check.
*
* \retval VMK_TRUE The adapter supports DMA beyond 32 bits.
* \retval VMK_FALSE The adapter is limited to DMA in the lower
* 32 bits of machine-address space
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiAdapterIsPAECapable(vmk_ScsiAdapter *adapter)
{
return adapter->paeCapable;
}
/*
***********************************************************************
* vmk_ScsiCmdStatusIsGood -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if a command status indicates a successful
* completion. Note that this function returns false
* if the device returns a check condition with a
* recovered error sense code. See vmk_ScsiCmdIsSuccessful()
* to test for both conditions.
*
* \param[in] status Status to check.
*
* \retval VMK_TRUE The status indicates successful completion.
* \retval VMK_FALSE The status indicates some error. Use
* vmk_ScsiCmdStatusIsCheck() and
* vmk_ScsiExtractSenseData() to get the actual
* error.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdStatusIsGood(vmk_ScsiCmdStatus status)
{
return (status.device == VMK_SCSI_DEVICE_GOOD &&
status.host == VMK_SCSI_HOST_OK &&
status.plugin == VMK_SCSI_PLUGIN_GOOD) ? VMK_TRUE : VMK_FALSE;
}
/*
***********************************************************************
* vmk_ScsiCmdIsRecoveredError -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if a command status indicates a recovered
* error.
*
* \param[in] vmkCmd Command to check.
*
* \retval VMK_TRUE The status indicates a command completed with
* a recovered error status.
* \retval VMK_FALSE The status indicates a command did not
* complete with a recovered error status.
*
***********************************************************************
*/
vmk_Bool
vmk_ScsiCmdIsRecoveredError(const vmk_ScsiCommand *vmkCmd);
/*
***********************************************************************
* vmk_ScsiCmdIsSuccessful -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if vmk_ScsiCommand completed successfully.
*
* \param[in] vmkCmd vmkCmd to check
*
* \retval VMK_TRUE The status indicates the i/o completed
* successfully
* \retval VMK_FALSE The status indicates some error. Use
* vmk_ScsiCmdStatusIsCheck() and
* vmk_ScsiExtractSenseData() to get the actual
* error.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdIsSuccessful(const vmk_ScsiCommand *vmkCmd)
{
return vmk_ScsiCmdStatusIsGood(vmkCmd->status) ||
vmk_ScsiCmdIsRecoveredError(vmkCmd);
}
/*
***********************************************************************
* vmk_ScsiCmdStatusIsResvConflict -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if a command status indicates a reservation
* conflict.
*
* \param[in] status Status to check.
*
* \retval VMK_TRUE The status is reservation conflict.
* \retval VMK_FALSE The status is not a reservation conflict.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdStatusIsResvConflict(vmk_ScsiCmdStatus status)
{
return (status.device == VMK_SCSI_DEVICE_RESERVATION_CONFLICT &&
status.host == VMK_SCSI_HOST_OK &&
status.plugin == VMK_SCSI_PLUGIN_GOOD);
}
/*
***********************************************************************
* vmk_ScsiCmdStatusIsCheck -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if a command status indicates a check condition.
*
* \param[in] status Status to check.
*
* \retval VMK_TRUE The status indicates a check condition.
* \retval VMK_FALSE The status is not a check condition.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdStatusIsCheck(vmk_ScsiCmdStatus status)
{
return (status.device == VMK_SCSI_DEVICE_CHECK_CONDITION &&
status.host == VMK_SCSI_HOST_OK &&
status.plugin == VMK_SCSI_PLUGIN_GOOD) ? VMK_TRUE : VMK_FALSE;
}
/*
***********************************************************************
* vmk_ScsiCmdSenseIsPOR -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if sense data is a unit attention with Power-On Reset
* as the additional sense code.
*
* \param[in] senseData sense data to inspect.
*
* \retval VMK_TRUE The status indicates a unit attention with
* power-on reset.
* \retval VMK_FALSE The status is not a power-on reset unit attention.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdSenseIsPOR(const vmk_ScsiSenseData *senseData)
{
return ((senseData->key == VMK_SCSI_SENSE_KEY_UNIT_ATTENTION) &&
(senseData->optLen >= 6) &&
(senseData->asc == VMK_SCSI_ASC_POWER_ON_OR_RESET) &&
(senseData->ascq == 0));
}
/*
***********************************************************************
* vmk_ScsiCmdSenseIsResvReleased -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if sense data is a unit attention with reservation
* released as the additional sense code.
*
* \param[in] senseData sense data to inspect.
*
* \retval VMK_TRUE The senses data is a unit attention with
* reservation released.
* \retval VMK_FALSE The senses data is not a unit attention with
* reservation released.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdSenseIsResvReleased(const vmk_ScsiSenseData *senseData)
{
return ((senseData->key == VMK_SCSI_SENSE_KEY_UNIT_ATTENTION) &&
(senseData->asc == VMK_SCSI_ASC_PARAMS_CHANGED) &&
(senseData->ascq ==
VMK_SCSI_ASC_PARAMS_CHANGED_ASCQ_RESERVATIONS_RELEASED));
}
/*
***********************************************************************
* vmk_ScsiCmdSenseIsMediumNotPresent -- */ /**
*
* \ingroup SCSI
*
* \brief Determine if sense data is a sense key not ready with medium
* not present as the additional sense code.
*
* \param[in] senseData sense data to inspect.
*
* \retval VMK_TRUE The senses data is sense key not ready with
* medium not present.
* \retval VMK_FALSE The senses data is not a sense key not ready
* with medium not present.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiCmdSenseIsMediumNotPresent(const vmk_ScsiSenseData *senseData)
{
return ((senseData->key == VMK_SCSI_SENSE_KEY_NOT_READY) &&
(senseData->asc == VMK_SCSI_ASC_MEDIUM_NOT_PRESENT));
}
/*
***********************************************************************
* vmk_ScsiGetLbaLbc -- */ /**
*
* \ingroup SCSI
*
* \brief Parse a SCSI CDB and pull out lba and lbc.
*
* Determine the lba and lbc for a given cdb. This is most useful
* for READ and WRITE cdb's. This function will deal with converting
* endianness & differences between the sizes of cdbs.
*
* \param[in] cdb SCSI cdb to parse.
* \param[in] cdbLen Length of cdb in bytes.
* \param[in] devClass SCSI Device Class.
* \param[out] lba Logical Block Address.
* \param[out] lbc Logical Block Count.
*
* \retval VMK_NOT_SUPPORTED \em devClass is none of
* \em SCSI_CLASS_DISK, \em SCSI_CLASS_CDROM,
* \em SCSI_CLASS_TAPE, or,
* \em devClass is
* \em SCSI_CLASS_CDROM and \em cdb[0] does
* not contain 10/12 byte READ/WRITE SCSI
* command opcode.
* \retval VMK_BAD_PARAM \em cdb[0] does not contain 6/10/12/16
* byte READ/WRITE SCSI command opcode.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_ScsiGetLbaLbc(unsigned char *cdb, vmk_size_t cdbLen,
vmk_ScsiDeviceClass devClass, vmk_uint64 *lba,
vmk_uint32 *lbc);
/*
***********************************************************************
* vmk_ScsiSetLbaLbc -- */ /**
*
* \ingroup SCSI
*
* \brief Set lba and lbc fields in a given SCSI CDB.
*
* Set the lba and lbc for a given cdb. This is most useful
* for READ and WRITE cdb's. This function will deal with converting
* endianness & differences between the sizes of cdb's. Callers
* must set \em cdb[0] before making this call.
*
* \param[in,out] cdb SCSI cdb to set.
* \param[in] cdbLen Length of cdb in bytes.
* \param[in] devClass SCSI Device Class.
* \param[out] lba Logical Block Address.
* \param[out] lbc Logical Block Count.
*
* \retval VMK_NOT_SUPPORTED \em devClass is none of
* \em SCSI_CLASS_DISK,
* \em SCSI_CLASS_CDROM, or,
* \em devClass is \em SCSI_CLASS_CDROM and
* \em cdb[0] does not contain 10/12 byte
* READ/WRITE SCSI command opcode.
* \retval VMK_BAD_PARAM \em cdb[0] does not contain 6/10/12/16
* byte SCSI READ/WRITE command opcode.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_ScsiSetLbaLbc(unsigned char *cdb, vmk_size_t cdbLen,
vmk_ScsiDeviceClass devClass, vmk_uint64 *lba,
vmk_uint32 *lbc);
/*
***********************************************************************
* vmk_ScsiAllocateAdapter -- */ /**
*
* \ingroup SCSI
*
* \brief Allocate an adapter.
*
* After successful return, the adapter is in \em allocated state.
* Use vmk_ScsiFreeAdapter() to free this adapter structure.
*
* \param[in] heapID Heap to allocate the new adapter from.
*
* \return New adapter.
* \retval NULL Out of memory.
*
***********************************************************************
*/
vmk_ScsiAdapter * vmk_ScsiAllocateAdapter(
vmk_HeapID heapID);
/*
***********************************************************************
* vmk_ScsiRegisterAdapter -- */ /**
*
* \ingroup SCSI
*
* \brief Register an adapter with the VMkernel.
*
* After successful return, the adapter is in \em enabled state and
* drivers can issue a scan on that adapter.
*
* If \em ScanOnDriverLoad config option is set and
* \em vmk_ScsiAdapter->\em flag
* has \em VMK_SCSI_ADAPTER_FLAG_REGISTER_WITHOUT_SCAN bit clear, then
* VMkernel will scan all the LUs connected to this adapter. Path
* claiming will be run which might result in new SCSI devices being
* registered with VMkernel.
*
* If you do not want this autoscan and claim process to happen, you can
* set the \em VMK_SCSI_ADAPTER_FLAG_REGISTER_WITHOUT_SCAN in
* \em vmk_ScsiAdapter->\em flag, before calling vmk_ScsiRegisterAdapter().
* This can be useful for some drivers f.e. iSCSI, where a usual SCSI
* scan does not make sense.
*
* \note The scan and claim is done in a deferred context and hence might
* not have completed when vmk_ScsiRegisterAdapter() returns.
* \note This function does not block.
*
* \param[in] adapter Adapter to register. This should have been
* allocated with a prior call to
* vmk_ScsiAllocateAdapter().
*
* \retval VMK_OK The adapter was successfully registered. Scan
* and path claim might be still running.
* \retval VMK_EXISTS An adapter with same name already registered.
* \retval VMK_BAD_PARAM One or more adapter fields are not initialized
* correctly.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiRegisterAdapter(
vmk_ScsiAdapter *adapter);
/*
***********************************************************************
* vmk_ScsiUnregisterAdapter -- */ /**
*
* \ingroup SCSI
*
* \brief Unregister an adapter previously registered by
* vmk_ScsiRegisterAdapter().
*
* \note This function may block indefinitely, waiting for all the
* references on the adapter to be released.
*
* \param[in] adapter Adapter to unregister.
*
* \retval VMK_OK Successfully unregistered. The adapter will go
* to \em allocated state and can be used for a
* subsequent vmk_ScsiRegisterAdapter() call.
* \retval VMK_BUSY One or more paths originating from this adapter
* are claimed by some plugin.
* \retval VMK_FAILURE Adapter is neither in \em enabled, \em disabled
* or \em allocated state. An appropriate message is
* logged.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiUnregisterAdapter(
vmk_ScsiAdapter *adapter);
/*
***********************************************************************
* vmk_ScsiFreeAdapter -- */ /**
*
* \ingroup SCSI
*
* \brief Free an adapter previously allocated by
* vmk_ScsiAllocateAdapter().
*
* \warning Do not call vmk_ScsiFreeAdapter() for a registered adapter.
* The adapter should be in \em allocated state.
*
* \param[in] adapter Adapter to free.
*
***********************************************************************
*/
void vmk_ScsiFreeAdapter(
vmk_ScsiAdapter *adapter);
/*
***********************************************************************
* vmk_ScsiRemovePath -- */ /**
*
* \ingroup SCSI
*
* \brief Destroy the path identified by \em adapter, \em channel,
* \em targetId and \em lunId.
*
* If the path to be removed is claimed by an MP plugin, VMkernel will
* first try to unclaim the path by calling the plugin's \em unclaim
* entrypoint.
*
* \note This function may block indefinitely, waiting for all the
* references held on the path to be released.
*
* \param[in] adapter Adapter for path to remove.
* \param[in] channel Channel for path to remove.
* \param[in] targetId Target ID for path to remove.
* \param[in] lunId LUN ID for path to remove.
*
* \retval VMK_TRUE The path was removed successfully.
* \retval VMK_FALSE The path doesn't exist or the path exists but is
* claimed by a plugin and could not be successfully
* unclaimed.
*
***********************************************************************
*/
vmk_Bool vmk_ScsiRemovePath(
vmk_ScsiAdapter *adapter,
vmk_uint32 channel,
vmk_uint32 targetId,
vmk_uint32 lunId);
/*
***********************************************************************
* vmk_ScsiRegisterIRQ -- */ /**
*
* \ingroup SCSI
*
* \brief Registers an adapter's interrupt handler and interrupt vector
* with the VMkernel for polling during a core dump.
*
* To unregister, simply call vmk_ScsiRegisterIRQ() with NULL for
* \em intrHandler.
*
* \param[in] adapter Adapter to register on behalf of.
* \param[in] intrVector Interrupt vector number to register.
* \param[in] intrHandler Interrupt handler callback to invoke
* when an interrupt needs to be serviced.
* \param[in] intrHandlerData Private data to pass to the handler.
*
* \return vmk_ScsiRegisterIRQ() always succeeds.
*
***********************************************************************
*/
VMK_ReturnStatus vmk_ScsiRegisterIRQ(
void *adapter,
vmk_uint32 intrVector,
vmk_InterruptHandler intrHandler,
void *intrHandlerData);
/*
***********************************************************************
* vmk_ScsiHostStatusToString -- */ /**
*
* \ingroup SCSI
*
* \brief Take a SCSI host status and return a static string describing it.
*
* \param[in] hostStatus Status to convert.
*
* \return Host status as a human readable string.
*
***********************************************************************
*/
char *
vmk_ScsiHostStatusToString(vmk_ScsiHostStatus hostStatus);
/*
***********************************************************************
* vmk_ScsiDeviceStatusToString -- */ /**
*
* \ingroup SCSI
*
* \brief Take a SCSI device status and return a static string describing
* it.
*
* \param[in] deviceStatus Status to convert.
*
* \return Device status as a human readable string.
*
***********************************************************************
*/
char *
vmk_ScsiDeviceStatusToString(vmk_ScsiDeviceStatus deviceStatus);
/*
***********************************************************************
* vmk_ScsiSenseKeyToString -- */ /**
*
* \ingroup SCSI
*
* \brief Take a SCSI sense key and return a static string describing it.
*
* \param[in] senseKey SCSI sense key to convert.
*
* \return Sense key as a human readable string.
*
***********************************************************************
*/
char *
vmk_ScsiSenseKeyToString(vmk_uint32 senseKey);
/*
***********************************************************************
* vmk_ScsiAdditionalSenseToString -- */ /**
*
* \ingroup SCSI
*
* \brief Take a SCSI ASC/ASCQ and return a static string describing it.
*
* \param[in] asc SCSI ASC value to convert.
* \param[in] ascq SCSI ASCQ value to convert.
*
* \return ASC/ASCQ as a human readable string.
*
***********************************************************************
*/
char *
vmk_ScsiAdditionalSenseToString(vmk_uint32 asc,
vmk_uint32 ascq);
/*
**********************************************************************
* vmk_ScsiExtractSenseData -- */ /**
*
* \ingroup SCSI
*
* \brief Extract the SCSI Check Condition.
*
* Examine the contents of the senseBuffer and return the SCSI check
* condtion key, the Additional Sense Code, and the Additional Sense
* Code Qualifier.
*
* \note The routine only handles sense buffers with a response
* code of 0x70 or 0x71 (Section 4.5.3 in the SCSI-3 spec).
* It does not handle response codes of 0x72, 0x73 or any
* vendor specific response codes.
*
* \param[in] senseBuffer The sense buffer to be examined.
* \param[out] sense_key The sense key to be extracted.
* \param[out] asc The Additional Sense Code to be extracted.
* \param[out] ascq The Additional Sense Code Qualifier to be
* extracted.
*
* \retval VMK_TRUE The sense buffer indicates a SCSI error condition,
* and sense_key, asc and ascq have been correctly
* set.
* \retval VMK_FALSE There was no error indicated on the current or
* previous command.
*
***********************************************************************
*/
vmk_Bool
vmk_ScsiExtractSenseData(vmk_ScsiSenseData *senseBuffer,
vmk_uint8 *sense_key,
vmk_uint8 *asc,
vmk_uint8 *ascq);
/*
***********************************************************************
* vmk_ScsiVPDPageSize -- */ /**
*
* \ingroup SCSI
*
* \brief Get the size of a VPD page.
*
* \param[in] response SCSI VPD Inquiry response header. This is usually
* the SCSI Inquiry response obtained by a prior
* vmk_ScsiGetPathInquiry() call.
*
* \return Size of VPD Page in bytes.
*
* \note The routine assumes that VPD length field is one byte for
* all pages except for page 83 which has 2 byte length.
*
***********************************************************************
*/
vmk_uint16
vmk_ScsiVPDPageSize(vmk_ScsiInquiryVPDResponse *response);
/*
***********************************************************************
* vmk_ScsiIllegalRequest -- */ /**
*
* \ingroup SCSI
*
* \brief Generates "illegal request" sense buffer data.
*
* \param[out] senseBuffer The sense buffer to be modified
* \param[in] asc The Additional Sense Code
* \param[in] ascq The Additional Sense Code Qualifier
*
* \note Status must be set to VMK_SCSI_DEVICE_CHECK_CONDITION
* in order for the sense buffer to be examined.
*
***********************************************************************
*/
void
vmk_ScsiIllegalRequest(vmk_ScsiSenseData *senseBuffer,
vmk_uint8 asc,
vmk_uint8 ascq);
/*
***********************************************************************
* vmk_ScsiIsReadCdb -- */ /**
*
* \ingroup SCSI
*
* \brief Check whether the given SCSI opcode is one of the READ
* commands.
*
* \retval VMK_TRUE Opcode is a READ CDB opcode.
* \retval VMK_FALSE Opcode is not a READ CDB opcode.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiIsReadCdb(vmk_uint8 cdb0)
{
return cdb0 == VMK_SCSI_CMD_READ6
|| cdb0 == VMK_SCSI_CMD_READ10
|| cdb0 == VMK_SCSI_CMD_READ12
|| cdb0 == VMK_SCSI_CMD_READ16;
}
/*
***********************************************************************
* vmk_ScsiIsWriteCdb -- */ /**
*
* \ingroup SCSI
*
* \brief Check whether the given SCSI opcode is one of the WRITE
* commands.
*
* \retval VMK_TRUE Opcode is a WRITE CDB opcode.
* \retval VMK_FALSE Opcode is not a WRITE CDB opcode.
*
***********************************************************************
*/
static inline vmk_Bool
vmk_ScsiIsWriteCdb(vmk_uint8 cdb0)
{
return cdb0 == VMK_SCSI_CMD_WRITE6
|| cdb0 == VMK_SCSI_CMD_WRITE10
|| cdb0 == VMK_SCSI_CMD_WRITE12
|| cdb0 == VMK_SCSI_CMD_WRITE16;
}
/*
**********************************************************************
* vmk_ScsiSetPathXferLimit -- */ /**
*
* \ingroup SCSI
* \brief Set the maximum single transfer size limit for a path.
*
* \param[in] vmkAdapter The target adapter.
* \param[in] channel The target channel.
* \param[in] target The target number.
* \param[in] lun The target LUN.
* \param[in] maxXfer The new maximum transfer size in bytes.
*
* \retval VMK_OK The max transfer size was set successfully.
* \retval VMK_NOT_FOUND The requested path was not found.
*
* \warning Do not set maximum transfer size to 0. This will result
* in undefined behaviour.
*
* \note You should not set maximum transfer size to a value greater
* than the adapter's maximum transfer size. Most adapters
* support a maximum transfer size of 256K, so it is safe to
* set a \em maxXfer value <= 256K.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_ScsiSetPathXferLimit(vmk_ScsiAdapter *vmkAdapter,
vmk_int32 channel,
vmk_int32 target,
vmk_int32 lun,
vmk_uint64 maxXfer);
/*
**********************************************************************
* vmk_ScsiModifyQueueDepth -- */ /**
*
* \ingroup SCSI
*
* \brief Set the queue depth of the path specified by \em vmkAdapter
* \em channel, \em target, and \em lun.
*
* For multiple paths going through the same SCSI adapter, the path
* queue depth controls the share of that path in the adapter's queue.
* Setting path queue depth to a value greater than the underlying
* adapter's queue depth is inconsequential and should not be done.
*
*
* \param[in] vmkAdapter The target adapter.
* \param[in] channel The target channel.
* \param[in] target The target number.
* \param[in] lun The target LUN.
* \param[in] qdepth The new queue depth value.
*
* \retval VMK_OK The queue depth was set successfully.
* \retval VMK_NOT_FOUND The requested path was not found.
*
* \warning Do not set qdepth to 0. This will result in undefined
* behaviour.
*
***********************************************************************
*/
VMK_ReturnStatus
vmk_ScsiModifyQueueDepth(vmk_ScsiAdapter *vmkAdapter,
vmk_int32 channel,
vmk_int32 target,
vmk_int32 lun,
vmk_uint32 qdepth);
/*
***********************************************************************
* vmk_ScsiAllFCPathsDown -- */ /**
*
* \brief Check if all Fibre Channel transport paths are dead.
*
* \retval VMK_TRUE There are one or more Fibre Channel paths but all
* of them are currently down.
* \retval VMK_FALSE There are no Fibre Channel paths or one or more
* Fibre Channel paths are up.
*
***********************************************************************
*/
vmk_Bool vmk_ScsiAllFCPathsDown(void);
/*
***********************************************************************
* vmk_ScsiAdapterUniqueName -- */ /**
*
* \ingroup DeviceName
* \brief Create a new unique adapter name.
*
* This function returns a new unique adapter name.
*
* \param[out] adapterName Pointer to an array of characters at least
* VMK_SCSI_ADAPTER_NAME_LENGTH long, to
* receive the new adapter name.
***********************************************************************
*/
void vmk_ScsiAdapterUniqueName(char *adapterName);
/*
***********************************************************************
* vmk_ScsiGetIdentifierFromPage83Inquiry -- */ /**
*
* \ingroup SCSI
*
* \brief Get the identifier of the given idType from the given page 83
* inquiry data buffer.
*
* \param[in] *inquiryBuf buffer with VPD page 83
* \param[in] inquiryBufLen length of the inquiryBuf buffer
* \param[in] idType
* \param[in] assoc
* \param[out] id[]
* \param[in] idLength
*
* \retval VMK_NOT_FOUND An identifier descriptor of the given idType
* could not be found in the page 83 inquiry
* response
* \retval VMK_OK An identifier descriptor of the given idType
* was found and the identifier was copied into
* the provided id buffer
* \retval VMK_BAD_PARAM An identifier descriptor of the given idType
* was found but the identifier was larger than
* the provided id[] array.
***********************************************************************
*/
VMK_ReturnStatus
vmk_ScsiGetIdentifierFromPage83Inquiry(vmk_uint8 *inquiryBuf,
vmk_uint32 inquiryBufLen,
vmk_uint8 idType,
vmk_uint8 assoc,
vmk_uint8 id[],
vmk_uint32 idLength);
/*
***********************************************************************
* vmk_ScsiGetSystemLimits---- */ /**
*
* \ingroup SCSI
*
* \brief Retrieve the max number of Scsi devices and paths supported
*
* \param[out] limits pointer to a structure containing
* max number of supported devices and paths
*
***********************************************************************
*/
void
vmk_ScsiGetSystemLimits(vmk_ScsiSystemLimits *limits);
#endif /* _VMKAPI_SCSI_H_ */
/** @} */
/** @} */