#define INCL_DOS #include #include #include #pragma pack(1) #define DSKSP_CAT_SMART 0x80 /* SMART IOCTL category */ #define DSKSP_SMART_ONOFF 0x20 /* turn SMART on or off */ #define DSKSP_SMART_AUTOSAVE_ONOFF 0x21 /* turn SMART autosave on or off */ #define DSKSP_SMART_SAVE 0x22 /* force save of SMART data */ #define DSKSP_SMART_GETSTATUS 0x23 /* get SMART status (pass/fail) */ #define DSKSP_SMART_GET_ATTRIBUTES 0x24 /* get SMART attributes table */ #define DSKSP_SMART_GET_THRESHOLDS 0x25 /* get SMART thresholds table */ #define SMART_CMD_ON 1 /* on value for related SMART functions */ #define SMART_CMD_OFF 0 /* off value for related SMART functions */ #define DSKSP_CAT_GENERIC 0x90 /* generic IOCTL category */ #define DSKSP_GEN_GET_COUNTERS 0x40 /* get general counter values table */ #define DSKSP_GET_UNIT_INFORMATION 0x41 /* get unit configuration and BM DMA c*/ #define DSKSP_GET_INQUIRY_DATA 0x42 /* get ATA/ATAPI inquiry data */ typedef struct _DSKSP_CommandParameters { BYTE byPhysicalUnit; /* physical unit number 0-n */ /* 0 = 1st disk, 1 = 2nd disk, ...*/ /* 0x80 = Pri/Mas, 0x81=Pri/Sla, 0x82=Sec/Mas,*/ } DSKSP_CommandParameters, *PDSKSP_CommandParameters; /* * Parameters for SMART and generic commands */ /* * SMART Attribute table item */ typedef struct _S_Attribute { BYTE byAttribID; /* attribute ID number */ USHORT wFlags; /* flags */ BYTE byValue; /* attribute value */ BYTE byVendorSpecific[8]; /* vendor specific data */ } S_Attribute; /* * SMART Attribute table structure */ typedef struct _DeviceAttributesData { USHORT wRevisionNumber; /* revision number of attribute table */ S_Attribute Attribute[30]; /* attribute table */ BYTE byReserved[6]; /* reserved bytes */ USHORT wSMART_Capability; /* capabilities word */ BYTE byReserved2[16]; /* reserved bytes */ BYTE byVendorSpecific[125]; /* vendor specific data */ BYTE byCheckSum; /* checksum of data in this structure */ } DeviceAttributesData, NEAR *NPDeviceAttributesData, FAR *PDeviceAttributesData; /* * SMART Device Threshold table item */ typedef struct _S_Threshold { BYTE byAttributeID; /* attribute ID number */ BYTE byValue; /* threshold value */ BYTE byReserved[10]; /* reserved bytes */ } S_Threshold; /* * SMART Device Threshold table */ typedef struct _DeviceThresholdsData { USHORT wRevisionNumber; /* table revision number */ S_Threshold Threshold[30]; /* threshold table */ BYTE byReserved[18]; /* reserved bytes */ BYTE VendorSpecific[131]; /* vendor specific data */ BYTE byCheckSum; /* checksum of data in this structure */ } DeviceThresholdsData, NEAR *NPDeviceThresholdsData, FAR *PDeviceThresholdsData; /* * Unit Configuration and Counters */ typedef struct _UnitInformationData { USHORT wRevisionNumber; /* structure revision number */ USHORT wTaskFileBase; /* task file register base addr */ USHORT wAlternateStatusAddress; /* alternate status register addr */ USHORT wIRQ; /* interrupt request level */ USHORT wFlags; /* flags */ BYTE byPIO_Mode; /* PIO transfer mode programmed */ BYTE byDMA_Mode; /* DMA transfer mode programmed */ } UnitInformationData, *PUnitInformationData; /* * Unit Information Flags Definitions */ #define UIF_VALID 0x8000 /* unit information valid */ #define UIF_TIMINGS_VALID 0x4000 /* timing information valid */ #define UIF_RUNNING_BMDMA 0x2000 /* running Bus Master DMA on unit */ #define UIF_RUNNING_DMA 0x1000 /* running slave DMA on unit */ #define UIF_SLAVE 0x0002 /* slave on channel */ #define UIF_ATAPI 0x0001 /* ATAPI device if 1, ATA otherwise */ typedef struct _DeviceCountersData { USHORT wRevisionNumber; /* counter structure revision */ ULONG TotalReadOperations; /* total read operations performed */ ULONG TotalWriteOperations; /* total write operations performed */ ULONG TotalWriteErrors; /* total write errors encountered */ ULONG TotalReadErrors; /* total read errors encountered */ ULONG TotalSeekErrors; /* total seek errors encountered */ ULONG TotalSectorsRead; /* total number of sectors read */ ULONG TotalSectorsWritten; /* total number of sectors written */ ULONG TotalBMReadOperations; /* total bus master DMA read operations */ ULONG TotalBMWriteOperations; /* total bus master DMA write operations */ ULONG ByteMisalignedBuffers; /* total buffers on odd byte boundary */ ULONG TransfersAcross64K; /* total buffers crossing a 64K page boundary */ ULONG Reserved[4]; /* */ } DeviceCountersData, *PDeviceCountersData; /* Identify Data */ typedef struct _IDENTIFYDATA *PIDENTIFYDATA; typedef struct _IDENTIFYDATA { USHORT GeneralConfig; /* 0 General configuration bits */ USHORT TotalCylinders; /* 1 Default Translation - Num cyl */ USHORT Reserved; /* 2 Reserved */ USHORT NumHeads; /* 3 - Num heads */ USHORT NumUnformattedbpt; /* 4 Unformatted Bytes - Per track */ USHORT NumUnformattedbps; /* 5 - Per sector*/ USHORT SectorsPerTrack; /* 6 Default Translation - Sec/Trk */ USHORT NumBytesISG; /* 7 Byte Len - inter-sector gap */ USHORT NumBytesSync; /* 8 - sync field */ USHORT NumWordsVUS; /* 9 Len - Vendor Unique Info */ CHAR SerialNum[20]; /* 10 Serial number */ USHORT CtrlType; /* 20 Controller Type */ USHORT CtrlBufferSize; /* 21 Ctrl buffer size - Sectors */ USHORT NumECCBytes; /* 21 ECC bytes - read/write long */ CHAR FirmwareRN[8]; /* 23 Firmware Revision */ CHAR ModelNum[40]; /* 27 Model number */ USHORT NumSectorsPerInt; /* 47 Multiple Mode - Sec/Blk */ USHORT DoubleWordIO; /* 48 Double Word IO Flag */ USHORT IDECapabilities; /* 49 Capability Flags Word */ USHORT Reserved2; /* 50 */ USHORT PIOCycleTime; /* 51 Transfer Cycle Timing - PIO */ USHORT DMACycleTime; /* 52 - DMA */ USHORT AdditionalWordsValid; /* 53 Additional Words valid */ USHORT LogNumCyl; /* 54 Current Translation - Num Cyl */ USHORT LogNumHeads; /* 55 Num Heads */ USHORT LogSectorsPerTrack; /* 56 Sec/Trk */ ULONG LogTotalSectors; /* 57 Total Sec */ USHORT LogNumSectorsPerInt; /* 59 */ ULONG LBATotalSectors; /* 60 LBA Mode - Sectors */ USHORT DMASWordFlags; /* 62 */ USHORT DMAMWordFlags; /* 63 */ USHORT AdvancedPIOModes; /* 64 Advanced PIO modes supported */ USHORT MinMWDMACycleTime; /* 65 Minimum multiWord DMA cycle time */ USHORT RecMWDMACycleTime; /* 66 Recommended MW DMA cycle time */ USHORT MinPIOCycleTimeWOFC; /* 67 Minimum PIO cycle time without IORDY */ USHORT MinPIOCycleTime; /* 68 Minimum PIO cycle time */ USHORT Reserved3[82-69]; /* 69 */ USHORT CommandSetSupported[3]; /* 82 */ USHORT CommandSetEnabled[3]; /* 85 */ USHORT UltraDMAModes; /* 88 Ultra DMA Modes */ USHORT Reserved4[93-89]; /* 89 */ USHORT HardwareTestResult; /* 93 hardware test result*/ USHORT Reserved5[127-94]; /* 94 */ USHORT MediaStatusWord; /* 127 media status Word */ USHORT Reserved6[256-128]; /* */ }IDENTIFYDATA; int main (int argc, char *argv[]) { APIRET rc; HFILE hDevice; ULONG ActionTaken; UCHAR Options = 0; int i, j; DSKSP_CommandParameters Parms; ULONG PLen = 1; ULONG IDLen = 512; IDENTIFYDATA Id; ULONG UnitInfoLen = sizeof (UnitInformationData); UnitInformationData UnitInfo; char Model[41]; { PCHAR p; if ((p = strrchr (argv[0], '.')) != NULL) *p = '\0'; if ((p = strrchr (argv[0], '\\')) != NULL) p++; else if ((p = strrchr (argv[0], ':')) != NULL) p++; argv[0] = p; } if (argc > 1) { for (i = 1; i < argc; i++) { if (strchr (argv[i], 'i')) Options |= 4; if (strchr (argv[i], 'c')) Options |= 2; if (strchr (argv[i], 'v')) Options |= 1; if (strchr (argv[i], 's')) Options |= 8; } if (Options == 0) { printf ("Usage: %s {i}{c}{v}{s}\n", argv[0]); exit (1); } } rc = DosOpen ("\\DEV\\IBMS506$", &hDevice, &ActionTaken, 0, FILE_SYSTEM, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READONLY, NULL); if (rc) exit (rc); for (i = 0; i < 16; i++) { Parms.byPhysicalUnit = 0x80 + i; memset (&Id, 0, 512); rc = DosDevIOCtl (hDevice, DSKSP_CAT_GENERIC, DSKSP_GET_INQUIRY_DATA, (PVOID)&Parms, PLen, &PLen, (PVOID)&Id, IDLen, &IDLen); if (rc == 0xFF03) break; printf ("%d/%c: ", i / 2, i % 2 ? 's' : 'm'); if (rc == 0xFF02) { printf ("(not present)\n"); continue; } for (j = 0; j < 40; j++) Model[j] = Id.ModelNum[j ^ 1]; Model[40] = '\0'; printf ("%s \n", Model); rc = DosDevIOCtl (hDevice, DSKSP_CAT_GENERIC, DSKSP_GET_UNIT_INFORMATION, (PVOID)&Parms, PLen, &PLen, (PVOID)&UnitInfo, UnitInfoLen, &UnitInfoLen); if (Options & 1) { printf ("Port %4X/%4X, Irq %d", UnitInfo.wTaskFileBase, UnitInfo.wAlternateStatusAddress, UnitInfo.wIRQ); if (UnitInfo.wFlags & UIF_ATAPI) printf (", ATAPI"); if (UnitInfo.wFlags & UIF_RUNNING_BMDMA) printf (", DMA busmaster"); printf (", PIO%d", UnitInfo.byPIO_Mode); if (UnitInfo.wFlags & UIF_RUNNING_BMDMA) if (UnitInfo.byDMA_Mode > 2) printf (", UltraDMA%d", UnitInfo.byDMA_Mode - 3); else printf (", DMA%d", UnitInfo.byDMA_Mode); printf ("\n\n"); } if ((Options & 8) && !(UnitInfo.wFlags & UIF_ATAPI)) { ULONG value; ULONG DataLen = sizeof (value); rc = DosDevIOCtl (hDevice, DSKSP_CAT_SMART, DSKSP_SMART_GETSTATUS, (PVOID)&Parms, PLen, &PLen, (PVOID)&value, DataLen, &DataLen); printf ("SMART: "); if (rc == 0xFF03) printf ("not supported or disabled\n\n"); else printf ("device is%s reliable\n\n", value ? " NOT" : ""); } if ((Options & 2) && !(UnitInfo.wFlags & UIF_ATAPI)) { ULONG CountersLen = sizeof (DeviceCountersData); DeviceCountersData Counters; rc = DosDevIOCtl (hDevice, DSKSP_CAT_GENERIC, DSKSP_GEN_GET_COUNTERS, (PVOID)&Parms, PLen, &PLen, (PVOID)&Counters, CountersLen, &CountersLen); printf ("Device counters\n"); printf ("Total operations : %8d reads, %8d writes\n", Counters.TotalReadOperations, Counters.TotalWriteOperations); printf ("Total sectors : %8d reads, %8d writes\n", Counters.TotalSectorsRead, Counters.TotalSectorsWritten); printf ("Busmaster operations: %8d reads, %8d writes, %8d misaligned\n", Counters.TotalBMReadOperations, Counters.TotalBMWriteOperations, Counters.ByteMisalignedBuffers); printf ("Total errors : %8d reads, %8d writes, %8d seeks \n", Counters.TotalReadErrors, Counters.TotalWriteErrors, Counters.TotalSeekErrors); printf ("\n"); } if (Options & 4) { int k; USHORT *p; printf ("%sIDENTIFY response\n", (UnitInfo.wFlags & UIF_ATAPI) ? "ATAPI " : ""); p = (USHORT *)&Id; for (j = 0; j < 256; j += 8) { printf ("% 4d/%03X: ", j, j); for (k = 0; k < 8; k++) { printf ("%04X ", *(p++)); if (k == 3) printf (" "); } printf ("\n"); } printf ("\n"); } } DosClose (hDevice); if (Options == 0) printf ("\nmore info with %s {i}{c}{v}{s}\n", argv[0]); return (rc); }