SMART IOCTL API Specification

This specification describes the API for an application to issue SMART commands to an IDE drive under Microsoft® Windows® 95 and Windows NT®. Under Windows 95, the API is implemented in a Vendor Specific Driver (VSD), Smartvsd.vxd.

SMART functionality is implemented as a "pass through" mechanism whereby the application sets up the IDE registers in a structure and passes it to the driver through the DeviceIoControl API. The registers are checked for validity and passed to the IDE port driver for execution. Any error from the IDE interface is returned to the application.

SMART stands for Self-Monitoring Analysis and Reporting Technology. You can find more information on SMART in the document SFF8035 version 1.0.

DFP stands for Disk Fault Prediction, and was an early naming of SMART. As you can see, the acronym still occurs in command names.

Software Interface

The interface to the driver is via the Win32® DeviceIoControl API function. Before an application can call the DeviceIoControl API, a handle to the target driver must be obtained by a call to the CreateFile API. Under Windows 95, the driver will be automatically loaded if it is placed it in the \Windows\System\IOsubsys directory, so it will not be necessary for application software to load it.

The DeviceIoControl API is documented in the Win32 online reference guide as follows:

DeviceIOControl


The DeviceIoControl function sends a control code directly to a device driver, causing the given device to perform the specified operation.

Parameters

hDevice

Identifies the device. The CreateFile function returns this handle.

dwIoControlCode

Specifies the control code for the operation. This value identifies the specific operation to be performed and the type of device on which the operation is to be performed. The following values are defined for this driver.

Value Meaning
DFP_GET_VERSION (0x00074080) Gets the version and revision number of the driver.
DFP_SEND_DRIVE_COMMAND (0x0007c084) Sends a command to a drive. Sends a command to a drive that sends data. If a command is sent to a drive that does not send data, no data is transferred.
DFP_RECEIVE_DRIVE_DATA (0x0007c088) Sends a command to the drive that returns data.
pvInBuffer

Points to a buffer containing the data required to perform the operation. This parameter can be NULL if the dwIoControlCode parameter specifies an operation that does not require input data.

cbInBuffer

Specifies the size, in bytes, of the lpvInBuffer buffer.

lpvOutBuffer

Points to a buffer in which the operation's output data is returned. This parameter can be NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.

cbOutBuffer

Specifies the size, in bytes, of the lpvOutBuffer buffer.

lpcbBytesReturned

Points to a 32-bit variable that receives the size, in bytes, of the data returned in the lpvOutBuffer buffer.

lpoOverlapped

Points to an OVERLAPPED structure. This parameter is ignored if the hDevice handle was opened without specifying the FILE_FLAG_OVERLAPPED flag. This parameter can be NULL if you do not want overlapped operation.

OVERLAPPED (asynchronous) I/O will not be used by this driver, so this parameter should be set to NULL.

Return Value

If the function succeeds, the return value is TRUE; otherwise, it is FALSE. To get extended error information, use the GetLastError function.

Functions

The following functions are supported.

Value Meaning
DFP_GET_VERSION Gets the version and revision number of the driver.
DFP_SEND_DRIVE_COMMAND Sends a command to a drive Sends a command to a drive that sends data. If a command is sent to a drive that does not send data, no data is transferred.
DFP_RECEIVE_DRIVE_DATA Sends a command to the drive that returns data.

DFP_GET_VERSION

This function returns the version of the driver and its capabilities.

The input parameters to DeviceIoControl for this function are as follows.

Parameter Value
hDevice Handle returned from CreateFile function
DwIoControlCode DFP_GET_VERSION (see Data Structures section for value)
lpvInBuffer NULL
cbInBuffer 0
LpvOutBuffer Pointer to GetVersionOutParams structure (see Data Structures section for definition)
cbOutBuffer Size of the GetVersionOutParams structure
LpcbBytesReturned Pointer to DWORD to receive number of bytes returned
lpoOverlapped NULL

DFP_SEND_DRIVE_COMMAND

This Ioctl command code is used to send a DFP command to the disk controller when the command will either transfer data to the drive or when the command will not transfer any data.

The input parameters to DeviceIoControl for this function are as follows.

Parameter Value
hDevice Handle returned from CreateFile function
DwIoControlCode DFP_SEND_DRIVE_COMMAND (see "Data Structures" section for value)
lpvInBuffer Pointer to SendCommandInParams (see "Data Structures" section for definition)
cbInBuffer Size of SendCommandInParams (accounting for buffer length)
LpvOutBuffer Pointer to SendCmdOutParams structure (see "Data Structures" section for definition)
cbOutBuffer Size of SendCmdOutParams structure (accounting for buffer length of zero)
LpcbBytesReturned Pointer to DWORD to receive number of bytes returned
lpoOverlapped NULL

DFP_RECEIVE_DRIVE_DATA

Uses same arguments as Send Command to Drive. The field cBufferSize in SENDCMDINPARAMS is the maximum size of the expected output from the command.

This Ioctl command code is used to send a DFP command that will transfer data from the drive, or to send an Identify command to the disk controller.

The input parameters to DeviceIoControl for this function are as follows.

Parameter Value
hDevice Handle returned from CreateFile function
DwIoControlCode DFP_RECEIVE_DRIVE_DATA (see "Data Structures" section for value)
lpvInBuffer Pointer to SendCommandInParams (see "Data Structures" section for definition)
cbInBuffer Size of SendCommandInParams
LpvOutBuffer Pointer to SendCmdOutParams structure (see "Data Structures" section for definition)
cbOutBuffer Size of SendCmdOutParams structure (accounting for buffer length)
LpcbBytesReturned Pointer to DWORD to receive number of bytes returned
lpoOverlapped NULL

Error Handling

DeviceIoControl returns FALSE when it fails and TRUE when it succeeds. There are many types of failure, both from the DeviceIoControl API and from the driver. In order to determine the exact cause of an error, the application must examine three values: the return code from DeviceIoControl, the value returned from the GetLastError API, and the status value returned by the driver. Unfortunately, the current documentation for DeviceIoControl does not specify the error values from the API. Therefore, the driver will not attempt to pass error information through the GetLastError function but will use the DriverStatusStructure to pass error information back to the caller.

Before calling the IOCTL APIs in the driver, set the bDriverError member of the DriverStatusStructure to zero. Then, if the return code from DeviceIoControl is FALSE, check the bDriverError member of DriverStatusStructure. If it is nonzero, the error is from the driver. If it is zero, the error is from DeviceIoControl and GetLastError must be called to determine the exact error.

IMPORTANT: If the driver cannot validate the DriverStatus structure, it will not attempt to place error codes in it. This might occur when the address is NULL or when the length passed is not valid.

Supported Commands

There are three IDE commands supported in this driver, ID (0xEC), ATAPI ID (0xA1), and SMART (0xB0). The "subcommands" of the SMART commands (features register values) are limited to the currently defined values (0xD0 through 0xD6, 0xD8 through 0xEF). SMART subcommand 0xD7, write threshold value, is not allowed. Any other command or SMART subcommand will result in an error being returned from the driver. Any SMART command that is not currently implemented on the target drive will result in an ABORT error from the IDE interface.

Data Structures

The following data structures and constants are used in the API.

Note All reserved fields should be set to zero. All structures are aligned on DWORD boundaries.

GetVersionOutParams

This structure contains the data returned from the Get Driver Version function.

GetVersionOutParams

The bit positions of the fCapabilities member are defined as follows.

Bit Name Value
0 IDE IDENTIFY Cmd 0 = not supported, 1 = supported
1 ATAPI IDENTIFY Cmd 0 = not supported, 1 = supported
2 SMART command set 0 = not supported, 1 = supported
3-31 Reserved for future 0

The bit positions of the bIDEDeviceMap member are defined as follows.

Bit Meaning
0 IDE device is attached to primary controller, drive 0.
1 IDE device is attached to primary controller, drive 1.
2 IDE device is attached to secondary controller, drive 0.
3 IDE device is attached to secondary controller, drive 1.
4 ATAPI device is attached to primary controller, drive 0.
5 ATAPI device is attached to primary controller, drive 1.
6 ATAPI device is attached to secondary controller, drive 0.
7 ATAPI device is attached to secondary controller, drive 1.

SendCmdInParams

This structure contains the input parameters for the Send Command To Drive functions that will transfer data to the drive:

SendCmdInParams

Note The bDriveNumber parameter corresponds to the four possible IDE drives in an ATA system. 0 is the first drive on the first controller, 1 is the second drive on the first controller, 2 is the first drive on the second controller, and 3 is the third drive on the second controller. An application can determine drive mappings by examining the bIDEDeviceMap member of the GETVERSIONOUTPARAMS structure. If the command will not result in any data being transferred to the drive, cBufferSize should be set to zero.

DriverStatus

This structure contains the result of any command to the SMART driver.

DriverStatus

SendCmdOutParams

SendCmdOutParams

Note cBufferSize is filled in the driver to indicate how much data was returned in the bBuffer location.

IDERegs

This structure contains the values to be written to the IDE registers by the driver. It is used in the SendCmdInParams structure. Although most of these values do not need to be specified by the application, allowing the application to specify them increases the flexibility of the interface. This is subject to review and revision. See each individual command for information on the required register values.

IDERegstypedef struct _IDEREGS {

Error Definitions

This section summarizes the errors that can be returned from the device I/O control

Returned from DeviceIoControl

The following errors are possible on the device I/O control.

Error Meaning
ERROR_ACCESS_DENIED User is not allowed to make this request.
ERROR_NOT_ENOUGH_MEMORY System could not issue request due to resource requirements.
ERROR_INVALID_FUNCTION The IOCTL code passed was invalid.

Returned in Output Buffer

The following driver errors are defined.

Error Value Meaning
NO_ERROR 0 No error.
IDE_ERROR 1 IDE command resulted in an error from the drive/controller. Examine bIDEStatus to determine the error. bIDEStatus will contain the value read from the IDE error register.
INVALID_FLAG 2 An invalid command flag was passed.
INVALID_COMMAND 3 An invalid IDE drive command register was passed. In this version of the driver, only the IDENTIFY (0xEC), ATAPI IDENTIFY (0xA1), and DFP (0xB0) commands are valid.
INVALID_BUFFER 4 A buffer pointer was not valid (bad pointer, bad length, etc.). This could be any pointer passed to the driver.
INVALID_DRIVE 5 The drive number was invalid. Either the drive number or the value in the drive/head register was not valid.
ERROR_NO_MEM 7 Could not lock user's buffer for I/O.
INVALID_REGISTER 8 Some IDE register (besides the command and drive/head register) value not valid. Examples are invalid DFP "subcommands" in the features register.
NOT_SUPPORTED 9 A bit has been set in the fCmdFlags that the driver does not support, or a reserved field is nonzero.
NO_IDE_DEVICE 10 No device attached to the controller that is specified by the drive number passed in the command.
RESERVED 11-255 Reserved for future.

Driver Name

Under Windows 95, the name of the executable is Smartvsd.vxd. This file will reside in the \Windows\System\IOsubsys directory.

© 1997 Microsoft Corporation. All rights reserved. Legal Notices.