#ifndef _ARCLIBS_H
#define _ARCLIBS_H

/********************************************************/
/*
/*  Data Structures & Function prototypes for S.M.A.R.T
/*
/********************************************************/

#include "arclib.h"

#ifdef __cplusplus
extern "C" {
#endif


#pragma pack(1)


#define MAX_DATA_LENGTH             512
#define SHORT_SELF_TEST             1
#define EXTENDED_SELF_TEST          2

/*
Attribute ID Numbers
Any non-zero value in the Attribute ID Number indicates an active attribute. The device supports the
following Attribute ID Numbers.

ID Attribute Name
=============================================
199 Ultra DMA CRC Error Count
198 Off-line Scan Uncorrectable Sector Count
197 Current Pending Sector Count
196 Reallocation Event Count
194 Temperature
193 Load Cycle Count
192 Power-off Retract Count
12 Device Power Cycle Count
10 Spin Retry Count
9 Power-on Hours Count
8 Seek Time Performance
7 Seek Error Rate
5 Reallocated Sector Count
4 Start/Stop Count
3 Spin Up Time
2 Throughput Performance
1 Raw Read Error Rate
0 Indicates that this entry in the data structure is not used


Status Flag definitions
Bit Definition
0 Pre-failure/advisory bit
0 An attribute value less than or equal to its corresponding attribute threshold indicates an
advisory condition where the usage or age of the device has exceeded its intended
design life period.
1 An attribute value less than or equal to its corresponding attribute threshold indicates a
pre-Failure condition where imminent loss of data is being predicted.
1 On-line Collective bit
0 The attribute value is updated only during Off-line testing.
1 The attribute value is updated during On-line testing or during both On-line and Off-line
testing.
2 - 5 Vendor specific
6 - 15 Reserved (0)

*/


/*
The following defines the 12 bytes that make up the information for each Attribute entry in the Device
Attribute Data Structure.
*/
typedef struct _DEVICE_ATTR_DATA	// Individual Attribute Data Structure
{
	BYTE	id;				// 0x00, Attribute ID Number (01h to FFh)
	BYTE	status[2];		// 0x01, Status flags
	BYTE	value;			// 0x03, Attribute Value (valid values from 01h to FDh)
	BYTE	vendor_spec[8];	// 0x04, Vendor Specific
}sDEVICE_ATTR_DATA, *pDEVICE_ATTR_DATA;	// total 12 bytes

/*
The following defines the 512 bytes that make up the Attribute Value information. This data structure is
accessed by the host in its entirety using the SMART Read Attribute Values subcommand. All multibyte
fields shown in these data structures are in byte ordering, that is, the least significant byte occupies the
lowest numbered byte address location in the field.
*/
typedef struct _SMART_ATTR_DATA	// Device Attributes Data Structure
{
	BYTE	rev_num[2];							// 0x00 Data Structure Revision Number
	sDEVICE_ATTR_DATA	device_attr_data[30];	// 0x02 Device Attribute, from 1st~30th
	BYTE	dc_status;							// 0x16A, Off¡Vline data collection status
	BYTE	st_status;							// 0x16B, Self¡Vtest execution status
	BYTE	total_time_for_dc[2];				// 0x16C, Total time in seconds to complete off¡Vline data collection activity
	BYTE	vendor_spec1;						// 0x16E, Vendor specific
	BYTE	dc_capability;						// 0x16F, Off¡Vline data collection capability
	BYTE	smart_cap[2];						// 0x170, SMART capability
	BYTE	smart_error_log_cap;				// 0x172, SMART device error logging capability
	BYTE	st_failure_check_point;				// 0x173, Self¡Vtest failure check point
	BYTE	short_st_completion_time;			// 0x174, Short self¡Vtest completion time in minutes
	BYTE	extended_st_completion_time;		// 0x175, Extended self¡Vtest completion time in minutes
	BYTE	reserved[12];						// 0x176, Reserved
	BYTE	vendor_spec2[125];					// 0x182, Vendor specific
	BYTE	checksum;							// 0x1FF, Data structure checksum

}sSMART_ATTR_DATA, *pSMART_ATTR_DATA;			// total 512 bytes

/*
The following defines the 12 bytes that make up the information for each Threshold entry in the Device
Attribute Thresholds Data Structure. Attribute entries in the Individual Threshold Data Structure is in the
same order and correspond to the entries in the Individual Attribute Data Structure.
*/
typedef struct _DEVICE_ATTR_THRE_DATA	// Individual Thresholds Data Structure
{
	BYTE	id;							// 0x00, Attribute ID Number (01h to FFh)
	BYTE	threshold;					// 0x01, Attribute Threshold
	BYTE	reserved[10];				// 0x02, Reserved (00h)
}sDEVICE_ATTR_THRE_DATA, *pDEVICE_ATTR_THRE_DATA;	// total 12 bytes

/*
The following defines the 512 bytes that make up the Attribute Threshold information. This data structure
is accessed by the host in its entirety using the SMART Read Attribute Thresholds. All multibyte fields
shown in these data structures are in byte ordering, that is, the least significant byte occupies the lowest
numbered byte address location in the field.
The sequence of active Attribute Thresholds will appear in the same order as their corresponding
Attribute Values.
*/
typedef struct _SMART_ATTR_THRE_DATA	// Device Attribute Thresholds Data Structure
{
	BYTE	rev_num[2];								// 0x00, Data Structure Revision Number
	sDEVICE_ATTR_THRE_DATA	device_attr_data[30];	// 0x02, Device Attribute, from 1st~30th
	BYTE	reserved[18];							// 0x16A, Reserved
	BYTE	vendor_spec[131];						// 0x17C, Vendor specific
	BYTE	checksum;								// 0x1FF, Data structure checksum
}sSMART_ATTR_THRE_DATA, *pSMART_ATTR_THRE_THRE_DATA;	// total 512 bytes


/*
Command data structure
Data format of each command data structure is shown below.
*/
typedef struct _COMMAND_DATA
{
	BYTE	dev_control_reg;	// 0x00, Device Control register
	BYTE	features_reg;		// 0x01, Features register
	BYTE	sector_count_reg;	// 0x02, Sector count register
	BYTE	sector_number_reg;	// 0x03, Sector number register
	BYTE	cylinder_low_reg;	// 0x04, Cylinder Low register
	BYTE	cylinder_high_reg;	// 0x05, Cylinder High register
	BYTE	head_reg;			// 0x06, Device/Head register
	BYTE	command_reg;		// 0x07, Command register
	BYTE	time_stamp[4];		// 0x08, Timestamp(ms from Power On)
}sCOMMAND_DATA, *pCOMMAND_DATA;	// total 12 bytes

/*
Error data structure:
Data format of error data structure is shown below.
The state field contains a value indicating the device state when the command was issued to the device.
xBh-xFh Vendor specific
x5h-xAh Reserved
x4h SMART Off-line or Self-test
x3h Active/Idle
x2h Standby
x1h Sleep
x0h Unknown
Value
*/

typedef struct _ERROR_DATA
{
	BYTE	reserved;			// 0x00, Reserved
	BYTE	error_reg;			// 0x01, Error register
	BYTE	sector_count_reg;	// 0x02, Sector count register
	BYTE	sector_number_reg;	// 0x03, Sector number register
	BYTE	cylinder_low_reg;	// 0x04, Cylinder Low register
	BYTE	cylinder_high_reg;	// 0x05, Cylinder High register
	BYTE	head_reg;			// 0x06, Device/Head register
	BYTE	status_reg;			// 0x07, Status register
	BYTE	extended_error_data[19]; //0x08, Extended error data (vendor specific)
	BYTE	state;				// 0x1B, State
	BYTE	life_timestamp[2];	// 0x1C Life timestamp (hours)
}sERROR_DATA, *pERROR_DATA;	// total 30 bytes


/*
Error log data structure
Data format of error data structure is shown below.
*/
typedef struct _ERROR_LOG_DATA
{
	sCOMMAND_DATA	command_data[5];	// 0x00, Command data structure, from 1~5
	sERROR_DATA		error_data;			// 0x3C, Error data structure
}sERROR_LOG_DATA, *pERROR_LOG_DATA;		// total 90 bytes


/*
The following figure defines the 512 bytes that make up the SMART error log sector. All multibyte fields
shown in these data structures are in byte ordering.
*/
typedef struct _SMART_ERROR_LOG_SECTOR
{
	BYTE	version;				// 0x00, SMART error log version
	BYTE	pointer;				// 0x01, Error log pointer
	sERROR_LOG_DATA	log_data[5];	// 0x02, 1st~5th error log data structure
	BYTE	device_error_count[2];	// 0x1C4, Device error count
	BYTE	reserved[57];			// 0x1C6, Reserved
	BYTE	checksum;				// 0x1FF, Data structure checksum

}sSMART_ERROR_LOG_SECTOR, *pSMART_ERROR_LOG_SECTOR;	// total 512 bytes


/*
The data structure contains the descriptor of Self-test that the device has performed. Each descriptor is
24 bytes long and the self-test data structure is capable of containing up to 21 descriptors.
After 21 descriptors have been recorded, the oldest descriptor will be overwritten with a new descriptor.
The self-test log pointer points to the most recent descriptor. When there is no descriptor, the value is 0.
When there is descriptor(s) the value is 1 through 21.
*/
typedef struct _SELF_TEST_LOG_DESCRIPTOR
{
	BYTE	number;					// 0x00, Self-test number
	BYTE	exe_status;				// 0x01, Self-test execution status
	BYTE	life_time[2];			// 0x02, Life time power on hours
	BYTE	st_failure_check_point;	// 0x04, Self-test failure check point
	BYTE	lba_of_first_failure[4];// 0x05, LBA of first failure
	BYTE	vendor_spec[15];		// 0x06, Vendor specific

}sSELF_TEST_LOG_DESCRIPTOR, *pSELF_TEST_LOG_DESCRIPTOR;	// total 24 bytes


/*
Self-test log data structure
The following figure defines the 512 bytes that make up the Self-test log sector. All multibyte fields shown
in these data structures are in byte ordering.
*/

typedef struct _SELF_TEST_LOG_DATA
{
	BYTE	reversion[2];						// 0x00, Data structure revision
	sSELF_TEST_LOG_DESCRIPTOR	descriptor[21];	// 0x02, descriptors
	BYTE	vendor_spec[2];						// 0x1FA, Vendor specific
	BYTE	pointer;							// 0x1FC, Self-test log pointer
	BYTE	reserved[2];						// 0x1FD, Reserved
	BYTE	checksum;							// 0x1FF, Data structure checksum
}sSELF_TEST_LOG_DATA, *pSELF_TEST_LOG_DATA;		// total 512 bytes


#ifdef _WIN32
class ARCLIB_API CArclibSMART : public CArclib
{
#else
class CArclibSMART : public CArclib 
{		
#endif
public:	

	// (O): Implemented
	// (X): Not Implemented
	enum
	{
		R_SMART_DATA = 0,		// (O)Read smart data
		R_THLD_DATA,			// (O)Read threshold data
		ED_AUTOSAVE,			// (X)Enable/disable autosave
		S_ATTR,					// (X)Save attribute
		EXE_OFFLINE,			// (O)Execute offline
		R_LOG,					// (X)Read log
		W_LOG,					// (X)Write log
		RESERVED1,
		E_SMART,				// (O)Enable SMART
		D_SMART,				// (O)Disable SMART
		RET_SMART_STATUS,		// (X)Return SMART status
		ED_AUTO_OFFLINE,		// (X)Enable/Disable automatic offline
		RESERVED2,
		RESERVED3,
		RESERVED4,
		RESERVED5,
		RW_TEST,				// (O)Read/Write test
		STOP_RW_TEST,			// (O)Stop Read/Write test
		CHECK_RW_RESULT,		// (O)Check Read/Write Result
		RESERVED6
	};

	//################################################################################################
	// Function: ArcExeSMART
	// Parameters:  (i) cmd: the commands listed above
	//				(i) drv: drive# where the SMART command is being executed
	//				(i) params: The options for EXE_OFFLINE, RW_TEST only.
	//                          for EXE_OFFLINE: value SHORT_SELF_TEST indicates short self-test
	//				                             value EXTENDED_SELF_TEST indicates extended self-test
	//							for RW_TEST: percentage of RW_TEST
	//              (o) data: The option for R_SMART_DATA, R_THLD_DATA, CHECK_RW_RESULT only.
	//						  the SMART data returned from the drive that indicates by drv, 
	//					      the memory allocation of 'data' is the responsibility of the
	//						  calling thread, and it's size should be >= 512 bytes					  
	//################################################################################################
	ARC_STATUS ArcExeSMART(int cmd, BYTE drv, BYTE params, PBYTE data);
};

#pragma pack()

#ifdef __cplusplus
}
#endif

#endif
