/*************************************************************************** * Copyright 2004 - 2012 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 "scsi/vmkapi_scsi_const.h" #include "scsi/vmkapi_scsi_types.h" /* * Physical Path */ /* *********************************************************************** * vmk_ScsiDeviceClassToString -- */ /** * * \brief Convert a SCSI class identifier into a human-readable text * string. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] sclass SCSI class to convert. * * \return The description string. * *********************************************************************** */ const char *vmk_ScsiDeviceClassToString( vmk_ScsiDeviceClass sclass); /* *********************************************************************** * vmk_ScsiScanPaths -- */ /** * * \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. * \retval VMK_MAX_PATHS_CLAIMED The limit for maximum no. of paths that * can be claimed is reached. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiScanPaths( const vmk_Name *adapterName, vmk_uint32 channel, vmk_uint32 target, vmk_uint32 lun); /* *********************************************************************** * vmk_ScsiScanAndClaimPaths -- */ /** * * \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 vmk_Name *adapterName, vmk_uint32 channel, vmk_uint32 target, vmk_uint32 lun); /* *********************************************************************** * vmk_ScsiScanDeleteAdapterPath -- */ /** * * \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 vmk_Name *adapterName, vmk_uint32 channel, vmk_uint32 target, vmk_uint32 lun); /* *********************************************************************** * vmk_ScsiNotifyPathStateChange -- */ /** * * \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 -- */ /** * * \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. * * \note This function will not block. * * \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_BAD_PARAM Invalid adapter passed. * \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 -- */ /** * * \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. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \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() * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Returns a human readable description of the task management * request. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] taskMgmtType Task management type to convert to a * string. * * \return The description string. * *********************************************************************** */ const char *vmk_ScsiGetTaskMgmtTypeName( vmk_ScsiTaskMgmtType taskMgmtType); /* *********************************************************************** * vmk_ScsiDebugDropCommand -- */ /** * * \brief Tell whether a command should be dropped. * * This is used for fault injection. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Notifies the VMkernel of a specific event on the * specified adapter. * * \note This function will not block. * * \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 -- */ /** * * \brief Determines if the adapter supports DMA beyond 32 bits of * machine-address space. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \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. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Determine if a command status indicates a recovered * error. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Determine if vmk_ScsiCommand completed successfully. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Determine if a command status indicates a reservation * conflict. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Determine if a command status indicates a check condition. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Determine if sense data is a unit attention with Power-On Reset * as the additional sense code. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] senseData sense data to inspect. * * \retval VMK_TRUE The status indicates a unit attention with * POWER ON, RESET, or BUS DEVICE RESET occured. * \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 <= 4)); } /* *********************************************************************** * vmk_ScsiCmdSenseIsResvReleased -- */ /** * * \brief Determine if sense data is a unit attention with reservation * released as the additional sense code. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Determine if sense data is a sense key not ready with medium * not present as the additional sense code. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \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. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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_ByteCount cdbLen, vmk_ScsiDeviceClass devClass, vmk_uint64 *lba, vmk_uint32 *lbc); /* *********************************************************************** * vmk_ScsiSetLbaLbc -- */ /** * * \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. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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_ByteCount cdbLen, vmk_ScsiDeviceClass devClass, vmk_uint64 *lba, vmk_uint32 *lbc); /* *********************************************************************** * vmk_ScsiAllocateAdapter -- */ /** * * \brief Allocate an adapter. * * \note This function may block. * * After successful return, the adapter is in \em allocated state. * Use vmk_ScsiFreeAdapter() to free this adapter structure. * * \return New adapter. * \retval NULL Out of memory. * *********************************************************************** */ vmk_ScsiAdapter *vmk_ScsiAllocateAdapter(void); /* *********************************************************************** * vmk_ScsiRegisterAdapter -- */ /** * * \deprecated This call should no longer be called directly by a * Native Driver as it is only used internally by PSA. * It is likely to go away in a future release. * * \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 may 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 -- */ /** * * \deprecated This call should no longer be called directly by a * Native Driver as it is only used internally by PSA. * It is likely to go away in a future release. * * \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 -- */ /** * * \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. * * \note This function may block. * * \param[in] adapter Adapter to free. * *********************************************************************** */ void vmk_ScsiFreeAdapter( vmk_ScsiAdapter *adapter); /* *********************************************************************** * vmk_ScsiRemovePath -- */ /** * * \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 -- */ /** * * \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. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] adapter Adapter to register on behalf of. * \param[in] intrCookie Interrupt cookie 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_IntrCookie intrCookie, vmk_IntrHandler intrHandler, void *intrHandlerData); /* *********************************************************************** * vmk_ScsiHostStatusToString -- */ /** * * \brief Take a SCSI host status and return a static string describing it. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] hostStatus Status to convert. * * \return Host status as a human readable string. * *********************************************************************** */ char * vmk_ScsiHostStatusToString(vmk_ScsiHostStatus hostStatus); /* *********************************************************************** * vmk_ScsiDeviceStatusToString -- */ /** * * \brief Take a SCSI device status and return a static string describing * it. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] deviceStatus Status to convert. * * \return Device status as a human readable string. * *********************************************************************** */ char * vmk_ScsiDeviceStatusToString(vmk_ScsiDeviceStatus deviceStatus); /* *********************************************************************** * vmk_ScsiSenseKeyToString -- */ /** * * \brief Take a SCSI sense key and return a static string describing it. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] senseKey SCSI sense key to convert. * * \return Sense key as a human readable string. * *********************************************************************** */ char * vmk_ScsiSenseKeyToString(vmk_uint32 senseKey); /* *********************************************************************** * vmk_ScsiAdditionalSenseToString -- */ /** * * \brief Take a SCSI ASC/ASCQ and return a static string describing it. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \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. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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_ScsiCmdGetSenseData -- */ /** * * \brief Obtain sense data associated with the given SCSI command. * * Command is identified by \em vmkCmd. Sense data is identified by * \em buf. This buffer will be filled with the contents of SCSI command's * sense data buffer. The caller passes in the size of the sense buffer in * \em bufLen. Depending on the number of sense data bytes required, the caller * can allocate a buffer of the appropriate size and pass the size of this * buffer in \em bufLen. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \note The max size of SCSI command's sense buffer is obtained by calling * vmk_ScsiGetSupportedCmdSenseDataSize. If the call is made with a buffer * larger than the max supported size, only the max supported number of bytes * will be set. The contents of the input buffer beyond that will be set to 0. * * \note For a small sense buffer, see vmk_ScsiSenseDataSimple. * * \param[in] vmkCmd Address of the SCSI command * \param[out] buf Address of the buffer that will * be filled with sense data * \param[in] bufLen Length of the sense buffer * above. * * \retval VMK_OK Sense data was successfully * obtained. * \retval VMK_BAD_PARAM A bad argument was passed. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiCmdGetSenseData(vmk_ScsiCommand *vmkCmd, vmk_ScsiSenseData *buf, vmk_ByteCount bufLen); /* *********************************************************************** * vmk_ScsiCmdSetSenseData -- */ /** * * \brief Set the sense data of a SCSI command. * * Command is identified by \em vmkCmd. Sense data in \em buf is copied * to the storage area for sense data in \em vmkCmd. The number of bytes * that will be copied is identified by \em bufLen. If \em bufLen * is less than SCSI command's max sense buffer size(obtained by calling * vmk_ScsiGetSupportedCmdSenseDataSize), the remaining bytes in SCSI * command's sense buffer are set to 0. If \em bufLen is larger than * SCSI command's max sense buffer size, only max sense buffer size of * sense data will be written, ie, sense data will be truncated to the max * supported size. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] buf Address of the buffer that * holds sense data bytes to be * copied. * \param[in] vmkCmd Address of the SCSI command * that contains the destination * sense buffer. * \param[in] bufLen The number of bytes to be * copied. * * \retval VMK_OK Sense data was successfully * set. * \retval VMK_BAD_PARAM A bad argument was passed. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiCmdSetSenseData(vmk_ScsiSenseData *buf, vmk_ScsiCommand *vmkCmd, vmk_ByteCount bufLen); /* *********************************************************************** * vmk_ScsiCmdClearSenseData -- */ /** * * \brief Clear the sense data attached to a SCSI command * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * Command is identified by \em vmkCmd. * * \param[in] vmkCmd Address of the SCSI command * * \retval VMK_OK Sense data was successfully * cleared. * \retval VMK_BAD_PARAM A bad argument was passed. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiCmdClearSenseData(vmk_ScsiCommand *vmkCmd); /* *********************************************************************** * vmk_ScsiGetSupportedCmdSenseDataSize -- */ /** * * \brief Get the size of the SCSI command's sense data buffer. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \retval The SCSI command's supported buffer size * *********************************************************************** */ vmk_ByteCount vmk_ScsiGetSupportedCmdSenseDataSize(void); /* *********************************************************************** * vmk_ScsiVPDPageSize -- */ /** * * \brief Get the size of a VPD page. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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_ByteCountSmall vmk_ScsiVPDPageSize(vmk_ScsiInquiryVPDResponse *response); /* *********************************************************************** * vmk_ScsiIllegalRequest -- */ /** * * \brief Generates "illegal request" sense buffer data. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Check whether the given SCSI opcode is one of the READ * commands. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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 -- */ /** * * \brief Check whether the given SCSI opcode is one of the WRITE * commands. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \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_ScsiGetAdapterName -- */ /** * * \brief Return the adapter's name * * \note Spin locks can be held while calling into this function * * \note This function will not block. * *********************************************************************** */ static inline const char * vmk_ScsiGetAdapterName(const vmk_ScsiAdapter *vmkAdapter) { return vmk_NameToString((vmk_Name *)&vmkAdapter->name); } /* ********************************************************************** * vmk_ScsiSetPathXferLimit -- */ /** * * \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. * * \note This function will not block. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSetPathXferLimit(vmk_ScsiAdapter *vmkAdapter, vmk_int32 channel, vmk_int32 target, vmk_int32 lun, vmk_ByteCount maxXfer); /* ********************************************************************** * vmk_ScsiModifyQueueDepth -- */ /** * * \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. * * \note This function will not block. * * \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. * * \note This function will not block. * * \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 * \deprecated This call should no longer be called directly by a * Native Driver as it is only used internally by PSA. * It is likely to go away in a future release. * * \brief Create a new unique adapter name. * * This function returns a new unique adapter name. * * \note This function will not block. * * \param[out] adapterName Pointer to an element of type vmk_Name to * receive the new adapter name. *********************************************************************** */ void vmk_ScsiAdapterUniqueName(vmk_Name *adapterName); /* *********************************************************************** * vmk_ScsiGetIdentifierFromPage83Inquiry -- */ /** * * \brief Get a UID of given type from a page 83 inquiry buffer * * Get the identifier of the given idType from the given page 83 * inquiry data buffer. The id descriptor is returned if parameter * desc is non-NULL. * * \note The returned descriptor is not NULL terminated (many ID types * can contain NULL as valid data). The length of the returned * descriptor is in the desc->idLen field. * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] inquiryBuf Buffer with VPD page 83 * \param[in] inquiryBufLen Length of the inquiryBuf buffer * \param[in] idType SCSI identifier type * \param[in] assoc SCSI association type * \param[out] id Identifier buffer * \param[in] idLength Size of identifier buffer * \param[out] desc * * \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_ByteCountSmall inquiryBufLen, vmk_ScsiIdentifierType idType, vmk_ScsiAssociationType assoc, vmk_uint8 *id, vmk_ByteCountSmall idLength, vmk_ScsiInquiryVPD83IdDesc *desc); /* *********************************************************************** * vmk_ScsiGetSystemLimits -- */ /** * * \brief Retrieve the max number of Scsi devices and paths supported * * \note This function will not block. * * \param[out] limits pointer to a structure containing * max number of supported devices and paths * *********************************************************************** */ void vmk_ScsiGetSystemLimits(vmk_ScsiSystemLimits *limits); /* *********************************************************************** * vmk_ScsiCommandGetCompletionHandle -- */ /** * * \deprecated Do not use in Native Drivers - please see * vmk_ScsiCommandGetCompletionQueue instead * * \brief Get the Completion handle for the SCSI command. * * This function will return the Completion handle which the VMkernel * wants the lower layer to preferably use to process this command. * * \pre Adapter's Completion Objects should have been registered. * * \see vmk_ScsiRegisterCompObjects() * * \note This function will not block. * * \note Spin locks can be held while calling into this function * * \param[in] vmkAdapter SCSI Adapter for which handle is extracted. * \param[in] vmkCmd vmk_ScsiCommand for which handle is extracted. * *********************************************************************** */ vmk_ScsiCompletionHandle vmk_ScsiCommandGetCompletionHandle(vmk_ScsiAdapter *vmkAdapter, vmk_ScsiCommand *vmkCmd); /* *********************************************************************** * vmk_ScsiRegisterCompObjects -- */ /** * * \deprecated Do not use in Native Drivers - please see * vmk_ScsiStartCompletionQueues instead * * \brief Register the completion objects for the adapter with vmkernel * * This function registers the completion objects created by vmkLinux * for the adapter with the VMkernel. The VMkernel will save the handle * for the completion objects internally. * While processing the SCSI command the adapter can ask the VMkernel * for the completion object in the adapter to be used to process the * command. * * \pre The adapter should have been registered with vmkernel * * \see vmk_ScsiCommandGetCompletionHandle() * * \note This function may block. * * \param[in] vmkAdapter ScsiAdapter having the Completion Object * \param[in] numCompObjects number of Completion Objects. * \param[in] compObj array of compObjects created by lower layer * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiRegisterCompObjects(vmk_ScsiAdapter *vmkAdapter, vmk_uint32 numCompObjects, vmk_ScsiCompObjectInfo compObj[]); /* *********************************************************************** * vmk_ScsiGetNumCompObjects -- */ /** * * \deprecated Do not use in Native Drivers - please see * vmk_ScsiGetMaxNumCompletionQueues instead * * \brief Queries VMKernel for number of Completion Objects * * \note This function will not block. * * \return Maximum Number of Completion Objects that can be created * *********************************************************************** */ vmk_uint32 vmk_ScsiGetNumCompObjects(void); /* *********************************************************************** * vmk_ScsiGetMaxNumCompletionQueues -- */ /** * * \brief Provide max number of Completion queues to create for adapter * * \note This function will not block. * * \return Maximum Number of Completion queues that can be created for * any adapter. * *********************************************************************** */ vmk_uint32 vmk_ScsiGetMaxNumCompletionQueues(void); /* *********************************************************************** * vmk_ScsiStartCompletionQueues -- */ /** * * \brief Create Completion queues and completion worlds for an adapter * * PSA will go ahead and create the number of completion queues passed * as well as the associated completion worlds to drive up completions. * This means that the driver can call vmkCmd->done from any context * since the command will simply be queued and driven to completion * by a separate completion world. * * \note This function may block. * * \note There will always be one completion world for native adapters * so the driver never has to create it's own completion worlds. * * \note The number of completion worlds can be raised dynamically, but * cannot currently be decreased. The completion worlds will be * destroyed when the adapter is unregistered, so no special * cleanup has to be done for multiple completion queues. * * \note If anything fails when creating or extending the number of * completion worlds we will leave the number of completion * worlds to what it was previously. * * \param[in] vmkAdapter ScsiAdapter to create/increase queues for * \param[in] numQueues Number of Completion queues to create * * \retval VMK_OK If queues were created, error otherwise * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiStartCompletionQueues(vmk_ScsiAdapter *vmkAdapter, vmk_uint32 numQueues); /* *********************************************************************** * vmk_ScsiCommandGetCompletionQueue -- */ /** * * \brief Get the Completion queue that should be used for a command * * This function is for instance used by the driver before issuing the * command so it can be issued to the right adapter queue (what the * VMkernel would like as it optimizes this dynamically based on what * PCPUs a given VM/issuer is running on). * * \note This function will not block. * * \param[in] vmkAdapter ScsiAdapter having the Completion queue * \param[in] vmkCmd The SCSI command to get queue for * * \returns The queue number to issue this command on * *********************************************************************** */ vmk_uint32 vmk_ScsiCommandGetCompletionQueue(vmk_ScsiAdapter *vmkAdapter, vmk_ScsiCommand *vmkCmd); /* *********************************************************************** * vmk_ScsiCheckPluginRegistered -- */ /** * * \brief Check if Plugin is registered. * * \note This function will not block. * * \retval VMK_OK If plugin is registered. * \retval VMK_NOT_FOUND If plugin is not registered. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiCheckPluginRegistered(const char *plugin); /* *********************************************************************** * vmk_ScsiGetRegisteredModuleName -- */ /** * * \brief Get the the Module name for the Plugin specified. * * \note This function will not block. * * \param[in] plugin Plugin name. * \param[out] name Buffer for module name. * * \retval VMK_OK If plugin module name is copied to "name". * \retval VMK_NOT_FOUND If plugin is not registered. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiGetRegisteredModuleName(const char *plugin, vmk_Name *name); /* *********************************************************************** * vmk_ScsiResolveRegisteredPluginDependencies -- */ /** * * \brief Resolve all dependencies for module "name". * Dependent Modules may get loaded. * * \note This function may block. * * \returns VMK_OK If all dependencies are resolved. * VMK_NOT_FOUND If module "name" is not registered. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiResolveRegisteredPluginDependencies(const char *name); /* *********************************************************************** * vmk_ScsiCmdGetVMUuid -- */ /** * * \brief Get the UUID of the VM associated with the specified command. * * \note This function will not block. * * \param[in] vmkCmd Scsi command whose associated VM UUID is queried. * \param[out] uuid Pointer to a buffer to fill in with the UUID. * \param[in] len Length of the supplied buffer. * * \returns VMK_OK uuid updated with the VM UUID. * VMK_NOT_FOUND VM UUID could not be found. * VMK_NOT_INITIALIZED No VM UUID has been set for this VM. * VMK_BUF_TOO_SMALL Supplied buffer is too small. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiCmdGetVMUuid(vmk_ScsiCommand *vmkCmd, char *uuid, vmk_ByteCount len); /* *********************************************************************** * vmk_ScsiSetPathLostByDevice -- */ /** * * \brief Mark a path as permanently lost by device, triggering PDL * * Path is identified by \em adaperName, \em channel, \em target * and \em lun. * This interface updates the path flags in the calling context. * * \note This function may block. * \note No spin lock may be held when calling this function. * * \param[in] adapterName 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_OK Path state successfully updated. * * \retval VMK_NOT_FOUND Requested adapter or path was not found. * This will be returned for a path only when * a specific \em lun is supplied (not for * \em lun==-1). * * \retval VMK_BAD_PARAM Adapter name is NULL. * *********************************************************************** */ VMK_ReturnStatus vmk_ScsiSetPathLostByDevice(const vmk_Name *adapterName, vmk_int32 channel, vmk_int32 target, vmk_int32 lun); /* *********************************************************************** * vmk_ScsiSchedCommandCompletion -- */ /** * * \brief Schedules a non-blocking context to complete the command. * * This function schedules a non-blocking context to complete a * command. The intent is to use this from the issuing path where * a command cannot be completed directly since that could lead to * stack exhaustion due to recursive calls to the issuing path from * the completion path. * * \note This is a non-blocking call. * * \note Spin locks can be held while calling into this function * * \param[in] command The cmd to complete. * *********************************************************************** */ void vmk_ScsiSchedCommandCompletion( vmk_ScsiCommand *command); #endif /* _VMKAPI_SCSI_H_ */ /** @} */ /** @} */