/* $Id: ataid.c 76 2015-12-28 01:37:00Z bird $ */ /** @file * Verbose display of the device identify reply. */ /* * Copyright (c) 2015 knut st. osmundsen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with This program. If not, see * */ #include #include #include #include #include #include #include #include "atalib.h" uint8_t AtaCalcIdChecksum(void const *pv512Bytes) { uint8_t uCksum = 0; uint8_t const *pb = (uint8_t const *)pv512Bytes; size_t cbLeft = 511; while (cbLeft-- > 0) uCksum += *pb++; return 0U - uCksum; } static void AtaPrintIdString(const char *pszPrefix, uint16_t const *pawStr, unsigned cWords, const char *pszSuffix) { unsigned i; fputs(pszPrefix, stdout); putchar('\''); for (i = 0; i < cWords; i++) { int j; for (j = 8; j >= 0; j -= 8) { uint8_t b = (uint8_t)(pawStr[i] >> j); if (b < UINT8_C(0x7f) || b >= UINT8_C(0x20)) putchar(b); else printf("\\x%02x", b); } } putchar('\''); fputs(pszSuffix, stdout); } int main(int argc, char **argv) { int rc; unsigned i; uint8_t bCksum; rc = AtaInitFromArgv(1, argc, argv); if (rc != 0) return 2; /* * Format the identify device response already stored in g_awIdentify. */ /* Word[0]: */ i = 0; printf("[%3u]=%#06x", i, g_awIdentify[i]); if ((g_awIdentify[i] >> 7) & 1) fputs(" removable-media", stdout); if ((g_awIdentify[i] >> 6) & 1) fputs(" not-removable", stdout); if ((g_awIdentify[i] >> 2) & 1) fputs(" bit2-maybe-incomplete!", stdout); if ((g_awIdentify[i] >> 15) & 1) fputs(" not-ATA-device!", stdout); putchar('\n'); i = 1; printf("[%3u]=%#06x - obsolete logical cylinders: %d\n", i, g_awIdentify[i], g_awIdentify[i]); i = 2; printf("[%3u]=%#06x (reserved / vendor specific)\n", i, g_awIdentify[i]); i = 3; printf("[%3u]=%#06x - obsolete logical heads: %d\n", i, g_awIdentify[i], g_awIdentify[i]); i = 4; printf("[%3u]=%#06x (vendor specific / retired)\n", i, g_awIdentify[i]); i = 5; printf("[%3u]=%#06x (vendor specific / retired)\n", i, g_awIdentify[i]); i = 6; printf("[%3u]=%#06x - obsolete logical sectors per track: %d\n", i, g_awIdentify[i], g_awIdentify[i]); i = 7; printf("[%3u]=%#06x (vendor specific / reserved for CompactFlash)\n", i, g_awIdentify[i]); i = 8; printf("[%3u]=%#06x (vendor specific / reserved for CompactFlash)\n", i, g_awIdentify[i]); i = 9; printf("[%3u]=%#06x (vendor specific / retired)\n", i, g_awIdentify[i]); i = 10; AtaPrintIdString("[ 10:19] - serial number: ", &g_awIdentify[i], 10, "\n"); i = 20; printf("[%3u]=%#06x (vendor specific / obsolete)\n", i, g_awIdentify[i]); i = 21; printf("[%3u=%#06x (vendor specific / obsolete)\n", i, g_awIdentify[i]); i = 22; printf("[=%#06x - obsolete ECC/vendor bytes for READ/WRITE LONG %d\n", i, g_awIdentify[i], g_awIdentify[i]); i = 23; AtaPrintIdString("[ 23:26] - firmware revision: ", &g_awIdentify[i], 4, "\n"); i = 27; AtaPrintIdString("[ 27:46] - model number: ", &g_awIdentify[i], 20, "\n"); i = 47; printf("[%3u]=%#06x - READ/WRITE MULTIPLE ", i, g_awIdentify[i]); if ((g_awIdentify[i] & 0xff) == 0) fputs("not implemented", stdout); else printf("max %d sectors", g_awIdentify[47] & 0xff); if ((g_awIdentify[i] >> 8) == 0x80) fputs(", ATA-4 top value", stdout); else fputs(", vendor specific top value", stdout); putchar('\n'); i = 48; printf("[%3u]=%#06x - trusted computing group bits ", i, g_awIdentify[i]); if ((g_awIdentify[i] & UINT16_C(0xc001)) == UINT16_C(0x4001)) printf("%#x\n", g_awIdentify[i] & UINT16_C(0x3ffe)); else fputs("not present\n", stdout); i = 49; printf("[%3u]=%#06x - capabilities:", i, g_awIdentify[i]); if (g_awIdentify[i] & UINT16_C(0x0100)) fputs(" DMA", stdout); if (g_awIdentify[i] & UINT16_C(0x0200)) fputs(" LBA", stdout); if (g_awIdentify[i] & UINT16_C(0x0400)) fputs(" IORDY-disable", stdout); if (g_awIdentify[i] & UINT16_C(0x0800)) fputs(" IORDY-supported", stdout); if (g_awIdentify[i] & UINT16_C(0x1000)) fputs(" rsvd12", stdout); if (g_awIdentify[i] & UINT16_C(0x2000)) fputs(" ata2-standby-timer", stdout); if (g_awIdentify[i] & UINT16_C(0x4000)) fputs(" rsvd14", stdout); if (g_awIdentify[i] & UINT16_C(0x8000)) fputs(" rsvd15", stdout); if (g_awIdentify[i] & UINT16_C(0x00ff)) printf(" vendor07=%#x", g_awIdentify[i] & UINT16_C(0x00ff)); putchar('\n'); i = 50; printf("[%3u]=%#06x - capabilities:", i, g_awIdentify[i]); if ((g_awIdentify[i] & UINT16_C(0xc000)) == UINT16_C(0x4000)) { if (g_awIdentify[i] & 1) fputs(" vendor-standby-timer-min", stdout); if (g_awIdentify[i] & 2) fputs(" obsolete1", stdout); if (g_awIdentify[i] & UINT16_C(0x3ffc)) printf(" reserved=%#x", g_awIdentify[i] & UINT16_C(0x3ffc)); putchar('\n'); } else fputs("not present\n", stdout); printf("[ 51]=%#06x - obsolete PIO data transfer cycle timing mode %d", g_awIdentify[51], g_awIdentify[51] >> 8); if (g_awIdentify[51] & UINT16_C(0x00ff)) printf(", vendor specific %#x\n", g_awIdentify[51] & UINT16_C(0x00ff)); else putchar('\n'); printf("[ 52]=%#06x - obsolete DMA data transfer cycle timing mode %d", g_awIdentify[52], g_awIdentify[52] >> 8); if (g_awIdentify[52] & UINT16_C(0x00ff)) printf(", vendor specific %#x\n", g_awIdentify[52] & UINT16_C(0x00ff)); else putchar('\n'); printf("[ 53]=%#06x - ", g_awIdentify[53]); if (g_awIdentify[53] & 1) fputs(" words54-58-obsolete", stdout); if (g_awIdentify[53] & 2) fputs(" words64-70", stdout); if (g_awIdentify[53] & 4) fputs(" word88", stdout); if (g_awIdentify[53] & UINT16_C(0x00f8)) printf(" rsvd=%#x", g_awIdentify[53] & UINT16_C(0x00f8)); printf(" free-fall-sensitivity=%#x\n", g_awIdentify[53] >> 8); i = 54; printf("[%3u]=%#06x - obsolete current logical cylinders %d", i, g_awIdentify[i], g_awIdentify[i]); if (g_awIdentify[54] > 16383) fputs(" (high!)", stdout); putchar('\n'); i = 55; printf("[%3u]=%#06x - obsolete current logical heads %d", i, g_awIdentify[i], g_awIdentify[i]); if (g_awIdentify[55] > 16) fputs(" (high!)", stdout); putchar('\n'); i = 56; printf("[%3u]=%#06x - obsolete current logical sectors per track %d", i, g_awIdentify[i], g_awIdentify[i]); if (g_awIdentify[56] > 63) fputs(" (high!)", stdout); putchar('\n'); printf("[ 57:58] - obsolete current capacity in sectors %lu (%#lx)\n", *(uint32_t *)&g_awIdentify[57], *(uint32_t *)&g_awIdentify[57]); printf("[ 59]=%#06x - sectors per DRQ READ/WRITE MULTIPLE ", g_awIdentify[59]); if (g_awIdentify[59] & UINT16_C(0x0100)) printf("%d", g_awIdentify[59] & UINT16_C(0xff)); else fputs(" not specified", stdout); if (g_awIdentify[59] & UINT16_C(0xfe00)) printf(" rsvd=%#x", g_awIdentify[59] & UINT16_C(0xfe00)); putchar('\n'); printf("[ 60:61] - LBA28 user addressable sectors %lu (%#lx)\n", *(uint32_t *)&g_awIdentify[60], *(uint32_t *)&g_awIdentify[60]); printf("[ 62]=%#06x - obsolete single word DMA:", g_awIdentify[62]); for (i = 0; i < 7; i++) if (g_awIdentify[62] & (UINT16_C(0x0001) << i)) { if (g_awIdentify[62] & (UINT16_C(0x0100) << i)) printf(" swdma%d[active]", i); else printf(" swdma%d", i); } else if (g_awIdentify[62] & (UINT16_C(0x0100) << i)) printf(" swdma%d-unsupported-but-active!", i); putchar('\n'); printf("[ 63]=%#06x - multiword DMA: ", g_awIdentify[63]); for (i = 0; i < 7; i++) if (g_awIdentify[63] & (UINT16_C(0x0001) << i)) { if (g_awIdentify[63] & (UINT16_C(0x0100) << i)) printf(" mwdma%d[active]", i); else printf(" mwdma%d", i); } else if (g_awIdentify[63] & (UINT16_C(0x0100) << i)) printf(" mwdma%d-unsupported-but-active!", i); putchar('\n'); printf("[ 64]=%#06x - Advanced PIO modes: ", g_awIdentify[64]); for (i = 0; i < 7; i++) if (g_awIdentify[64] & (UINT16_C(0x0001) << i)) printf(" pio%d", i+3); if (g_awIdentify[64] & UINT16_C(0xff00)) printf(" rsvd8-15=%#x", g_awIdentify[64] & UINT16_C(0xff00)); putchar('\n'); printf("[ 65]=%#06x - minimum multiword DMA xfer cycle time per word %d ns\n", g_awIdentify[65], g_awIdentify[65]); printf("[ 66]=%#06x - recommended multiword DMA xfer cycle time per word %d ns\n", g_awIdentify[66], g_awIdentify[66]); printf("[ 67]=%#06x - minimum PIO cycle time without IORDY %d ns\n", g_awIdentify[67], g_awIdentify[67]); printf("[ 68]=%#06x - minimum PIO cycle time with IORDY %d ns\n", g_awIdentify[68], g_awIdentify[68]); printf("[ 69]=%#06x (reserved)\n", g_awIdentify[69]); printf("[ 70]=%#06x (reserved)\n", g_awIdentify[70]); printf("[ 71]=%#06x (reserved for identify packet device)\n", g_awIdentify[71]); printf("[ 72]=%#06x (reserved for identify packet device)\n", g_awIdentify[72]); printf("[ 73]=%#06x (reserved for identify packet device)\n", g_awIdentify[73]); printf("[ 74]=%#06x (reserved for identify packet device)\n", g_awIdentify[74]); printf("[ 75]=%#06x - queue depth %d", g_awIdentify[75], (g_awIdentify[75] & 0x1f) + 1); if (g_awIdentify[75] & UINT16_C(0xffe0)) printf(", rsvd5-15=%#x", g_awIdentify[75] & UINT16_C(0xffe0)); putchar('\n'); printf("[ 76]=%#06x - SATA capabilities: ", g_awIdentify[76]); if (!(g_awIdentify[76] & 1)) { if (g_awIdentify[76] & UINT16_C(0x0002)) fputs(" gen1-1.5Gbps", stdout); if (g_awIdentify[76] & UINT16_C(0x0004)) fputs(" gen2-3.0Gbps", stdout); if (g_awIdentify[76] & UINT16_C(0x00f8)) printf(" rsvd3-7=%#x", g_awIdentify[76] & UINT16_C(0x00f8)); if (g_awIdentify[76] & UINT16_C(0x0100)) fputs(" ncq", stdout); if (g_awIdentify[76] & UINT16_C(0x0200)) fputs(" host-power-management", stdout); if (g_awIdentify[76] & UINT16_C(0x0400)) fputs(" phy-event-counters", stdout); if (g_awIdentify[76] & UINT16_C(0xf800)) printf(" rsvd11-16=%#x", g_awIdentify[76] & UINT16_C(0xf800)); putchar('\n'); } else fputs(" probably not SATA\n", stdout); printf("[ 77]=%#06x (reserved for SATA)\n", g_awIdentify[77]); printf("[ 78]=%#06x - SATA features supported: ", g_awIdentify[78]); if (!(g_awIdentify[78] & 1)) { if (g_awIdentify[78] & UINT16_C(0x0002)) fputs(" non-zero-buffer-offsets", stdout); if (g_awIdentify[78] & UINT16_C(0x0004)) fputs(" DMA-setup-auto-activation", stdout); if (g_awIdentify[78] & UINT16_C(0x0008)) fputs(" device-power-management", stdout); if (g_awIdentify[78] & UINT16_C(0x0010)) fputs(" in-order-data-delivery", stdout); if (g_awIdentify[78] & UINT16_C(0x0020)) fputs(" rsvd5", stdout); if (g_awIdentify[78] & UINT16_C(0x0040)) fputs(" software-settings-preservation", stdout); if (g_awIdentify[78] & UINT16_C(0xff80)) printf(" rsvd7-15=%#x", g_awIdentify[78] & UINT16_C(0xff80)); putchar('\n'); } else fputs(" probably not SATA\n", stdout); printf("[ 79]=%#06x - SATA features enabled: ", g_awIdentify[79]); if (!(g_awIdentify[79] & 1)) { if (g_awIdentify[79] & UINT16_C(0x0002)) fputs(" non-zero-buffer-offsets", stdout); if (g_awIdentify[79] & UINT16_C(0x0004)) fputs(" DMA-setup-auto-activation", stdout); if (g_awIdentify[79] & UINT16_C(0x0008)) fputs(" device-power-management", stdout); if (g_awIdentify[79] & UINT16_C(0x0010)) fputs(" in-order-data-delivery", stdout); if (g_awIdentify[79] & UINT16_C(0x0020)) fputs(" rsvd5", stdout); if (g_awIdentify[79] & UINT16_C(0x0040)) fputs(" software-settings-preservation", stdout); if (g_awIdentify[79] & UINT16_C(0xff80)) printf(" rsvd7-15=%#x", g_awIdentify[79] & UINT16_C(0xff80)); putchar('\n'); } else fputs(" probably not SATA\n", stdout); printf("[ 80]=%#06x - Major version number:", g_awIdentify[80]); if (g_awIdentify[80] != 0 && g_awIdentify[80] != UINT16_MAX) { for (i = 0; i < 15; i++) if (g_awIdentify[80] & (UINT16_C(0x0001) << i)) printf(" ata%u", i); putchar('\n'); } else fputs(" not specified\n", stdout); printf("[ 81]=%#06x - Minor version number: %d\n", g_awIdentify[81], g_awIdentify[81]); printf("[ 82]=%#06x - Supports: ", g_awIdentify[82]); if ((g_awIdentify[83] & UINT16_C(0xc000)) == UINT16_C(0x4000)) /* yes, 83; see 7.16.7.38 in ata8. */ { if (g_awIdentify[82] & UINT16_C(0x0001)) fputs(" smart", stdout); if (g_awIdentify[82] & UINT16_C(0x0002)) fputs(" security", stdout); if (g_awIdentify[82] & UINT16_C(0x0004)) fputs(" obsolete2", stdout); if (g_awIdentify[82] & UINT16_C(0x0008)) fputs(" mand-power-management", stdout); if (!(g_awIdentify[82] & UINT16_C(0x0010))) fputs(" no-packet", stdout); if (g_awIdentify[82] & UINT16_C(0x0020)) fputs(" volatile-write-cache", stdout); if (g_awIdentify[82] & UINT16_C(0x0040)) fputs(" look-ahead", stdout); if (g_awIdentify[82] & UINT16_C(0x0080)) fputs(" release-intr", stdout); if (g_awIdentify[82] & UINT16_C(0x0100)) fputs(" service-intr", stdout); if (!(g_awIdentify[82] & UINT16_C(0x0200))) fputs(" no-device-reset", stdout); if (g_awIdentify[82] & UINT16_C(0x0400)) fputs(" hpa", stdout); if (g_awIdentify[82] & UINT16_C(0x0800)) fputs(" obsolete11", stdout); if (g_awIdentify[82] & UINT16_C(0x1000)) fputs(" write-buffer", stdout); if (g_awIdentify[82] & UINT16_C(0x2000)) fputs(" read-buffer", stdout); if (g_awIdentify[82] & UINT16_C(0x4000)) fputs(" nop", stdout); if (g_awIdentify[82] & UINT16_C(0x8000)) fputs(" obsolete15", stdout); putchar('\n'); } else fputs(" not specified\n", stdout); printf("[ 83]=%#06x - Supports: ", g_awIdentify[83]); if ((g_awIdentify[83] & UINT16_C(0xc000)) == UINT16_C(0x4000)) { if (g_awIdentify[83] & UINT16_C(0x0001)) fputs(" download-microcode", stdout); if (g_awIdentify[83] & UINT16_C(0x0002)) fputs(" tcq", stdout); if (g_awIdentify[83] & UINT16_C(0x0004)) fputs(" cfa", stdout); if (g_awIdentify[83] & UINT16_C(0x0008)) fputs(" apm", stdout); if (g_awIdentify[83] & UINT16_C(0x0010)) fputs(" obsolete4", stdout); if (g_awIdentify[83] & UINT16_C(0x0020)) fputs(" puis", stdout); if (g_awIdentify[83] & UINT16_C(0x0040)) fputs(" set-features-spin-up", stdout); if (g_awIdentify[83] & UINT16_C(0x0080)) fputs(" reserved7", stdout); if (g_awIdentify[83] & UINT16_C(0x0100)) fputs(" set-max-security", stdout); if (g_awIdentify[83] & UINT16_C(0x0200)) fputs(" aam", stdout); if (g_awIdentify[83] & UINT16_C(0x0400)) fputs(" lba48", stdout); if (g_awIdentify[83] & UINT16_C(0x0800)) fputs(" dco", stdout); if (g_awIdentify[83] & UINT16_C(0x1000)) fputs(" flush-cache", stdout); if (g_awIdentify[83] & UINT16_C(0x2000)) fputs(" flush-cache-ext", stdout); putchar('\n'); } else fputs(" not specified\n", stdout); printf("[ 84]=%#06x - Supports: ", g_awIdentify[84]); if ((g_awIdentify[84] & UINT16_C(0xc000)) == UINT16_C(0x4000)) { if (g_awIdentify[84] & UINT16_C(0x0001)) fputs(" smart-err-log", stdout); if (g_awIdentify[84] & UINT16_C(0x0002)) fputs(" smart-self-test", stdout); if (g_awIdentify[84] & UINT16_C(0x0004)) fputs(" media-serial-no", stdout); if (g_awIdentify[84] & UINT16_C(0x0008)) fputs(" media-card-passthru", stdout); if (g_awIdentify[84] & UINT16_C(0x0010)) fputs(" streaming", stdout); if (g_awIdentify[84] & UINT16_C(0x0020)) fputs(" gpl", stdout); if (g_awIdentify[84] & UINT16_C(0x0040)) fputs(" write-dma-mult-fua-ext", stdout); if (g_awIdentify[84] & UINT16_C(0x0080)) fputs(" write-dma-queued-fua-ext", stdout); if (g_awIdentify[84] & UINT16_C(0x0100)) fputs(" 64-bit-world-wide-name", stdout); if (g_awIdentify[84] & UINT16_C(0x0200)) fputs(" obsolete9", stdout); if (g_awIdentify[84] & UINT16_C(0x0400)) fputs(" obsolete10", stdout); if (g_awIdentify[84] & UINT16_C(0x0800)) fputs(" reserved11", stdout); if (g_awIdentify[84] & UINT16_C(0x1000)) fputs(" reserved12", stdout); if (g_awIdentify[84] & UINT16_C(0x2000)) fputs(" idle-immediate-unload", stdout); putchar('\n'); } else fputs(" not specified\n", stdout); printf("[ 85]=%#06x - Enabled:", g_awIdentify[85]); if (g_awIdentify[85] & UINT16_C(0x0001)) fputs(" smart", stdout); if (g_awIdentify[85] & UINT16_C(0x0002)) fputs(" security", stdout); if (g_awIdentify[85] & UINT16_C(0x0020)) fputs(" volatile-write-cache", stdout); if (g_awIdentify[85] & UINT16_C(0x0040)) fputs(" look-ahead", stdout); if (g_awIdentify[85] & UINT16_C(0x0080)) fputs(" release-intr", stdout); if (g_awIdentify[85] & UINT16_C(0x0100)) fputs(" service-intr", stdout); fputs(" Supported:", stdout); if (g_awIdentify[85] & UINT16_C(0x0004)) fputs(" obsolete2", stdout); if (g_awIdentify[85] & UINT16_C(0x0008)) fputs(" mand-power-management", stdout); if (!(g_awIdentify[85] & UINT16_C(0x0010))) fputs(" no-packet", stdout); if (!(g_awIdentify[85] & UINT16_C(0x0200))) fputs(" no-device-reset", stdout); if (g_awIdentify[85] & UINT16_C(0x0400)) fputs(" hpa", stdout); if (g_awIdentify[85] & UINT16_C(0x0800)) fputs(" obsolete11", stdout); if (g_awIdentify[85] & UINT16_C(0x1000)) fputs(" write-buffer", stdout); if (g_awIdentify[85] & UINT16_C(0x2000)) fputs(" read-buffer", stdout); if (g_awIdentify[85] & UINT16_C(0x4000)) fputs(" nop", stdout); if (g_awIdentify[85] & UINT16_C(0x8000)) fputs(" obsolete15", stdout); putchar('\n'); if ((g_awIdentify[83] & UINT16_C(0xc000)) == UINT16_C(0x4000)) /* yeah, 83. */ { printf("[ 86]=%#06x - Enabled: ", g_awIdentify[86]); if (g_awIdentify[86] & UINT16_C(0x0008)) fputs(" apm", stdout); if (g_awIdentify[86] & UINT16_C(0x0020)) fputs(" puis", stdout); if (g_awIdentify[86] & UINT16_C(0x0100)) fputs(" set-max-security", stdout); if (g_awIdentify[86] & UINT16_C(0x0200)) fputs(" aam", stdout); fputs(" Supported:", stdout); if (g_awIdentify[86] & UINT16_C(0x0001)) fputs(" download-microcode", stdout); if (g_awIdentify[86] & UINT16_C(0x0002)) fputs(" tcq", stdout); if (g_awIdentify[86] & UINT16_C(0x0004)) fputs(" cfa", stdout); if (g_awIdentify[86] & UINT16_C(0x0010)) fputs(" obsolete4", stdout); if (g_awIdentify[86] & UINT16_C(0x0040)) fputs(" set-features-spin-up", stdout); if (g_awIdentify[86] & UINT16_C(0x0080)) fputs(" reserved7", stdout); if (g_awIdentify[86] & UINT16_C(0x0400)) fputs(" lba48", stdout); if (g_awIdentify[86] & UINT16_C(0x0800)) fputs(" dco", stdout); if (g_awIdentify[86] & UINT16_C(0x1000)) fputs(" flush-cache", stdout); if (g_awIdentify[86] & UINT16_C(0x2000)) fputs(" flush-cache-ext", stdout); if (g_awIdentify[86] & UINT16_C(0x4000)) fputs(" reserved14", stdout); if (g_awIdentify[86] & UINT16_C(0x8000)) fputs(" words119-120", stdout); putchar('\n'); } else printf("[ 86]=%#06x - Enabled & Supports: not specified\n", g_awIdentify[86]); printf("[ 87]=%#06x - Enabled: ", g_awIdentify[87]); if ((g_awIdentify[87] & UINT16_C(0xc000)) == UINT16_C(0x4000)) { if (g_awIdentify[87] & UINT16_C(0x0004)) fputs(" media-serial-no-valid", stdout); fputs(" Supported:", stdout); if (g_awIdentify[87] & UINT16_C(0x0001)) fputs(" smart-err-log", stdout); if (g_awIdentify[87] & UINT16_C(0x0002)) fputs(" smart-self-test", stdout); if (g_awIdentify[87] & UINT16_C(0x0008)) fputs(" media-card-passthru", stdout); if (g_awIdentify[87] & UINT16_C(0x0010)) fputs(" obsolete4", stdout); if (g_awIdentify[87] & UINT16_C(0x0020)) fputs(" gpl", stdout); if (g_awIdentify[87] & UINT16_C(0x0040)) fputs(" write-dma-mult-fua-ext", stdout); if (g_awIdentify[87] & UINT16_C(0x0080)) fputs(" write-dma-queued-fua-ext", stdout); if (g_awIdentify[87] & UINT16_C(0x0100)) fputs(" 64-bit-world-wide-name", stdout); if (g_awIdentify[87] & UINT16_C(0x0200)) fputs(" obsolete9", stdout); if (g_awIdentify[87] & UINT16_C(0x0400)) fputs(" obsolete10", stdout); if (g_awIdentify[87] & UINT16_C(0x0800)) fputs(" reserved11", stdout); if (g_awIdentify[87] & UINT16_C(0x1000)) fputs(" reserved12", stdout); if (g_awIdentify[87] & UINT16_C(0x2000)) fputs(" idle-immediate-unload", stdout); putchar('\n'); } else fputs(" not specified\n", stdout); printf("[ 88]=%#06x - Ultra DMA support: ", g_awIdentify[88]); for (i = 0; i < 8; i++) if (g_awIdentify[88] & (UINT16_C(0x0001) << i)) printf(" <=udma%d", i); fputs(" Selected: ", stdout); for (i = 0; i < 8; i++) if (g_awIdentify[88] & (UINT16_C(0x0100) << i)) printf(" udma%d", i); putchar('\n'); printf("[ 89]=%#06x - time for normal erase mode security erase unit: %d\n", g_awIdentify[88], g_awIdentify[89] & UINT16_C(0x00ff)); printf("[ 90]=%#06x - time for enh. erase mode security erase unit: %d\n", g_awIdentify[90], g_awIdentify[90] & UINT16_C(0x00ff)); printf("[ 91]=%#06x - current APM level value: %d\n", g_awIdentify[91], g_awIdentify[91]); printf("[ 92]=%#06x - master password ID: %d\n", g_awIdentify[92], g_awIdentify[92]); printf("[ 93]=%#06x - hardware reset result:", g_awIdentify[93], g_awIdentify[93]); if ((g_awIdentify[93] & UINT16_C(0xc000)) == UINT16_C(0x4000)) { static const char * const s_apszDevNum[4] = { " rsvd0", " jumper", " csel", " other" }; if (g_awIdentify[93] & UINT16_C(0x00ff)) { fputs(" dev0: ", stdout); fputs(s_apszDevNum[(g_awIdentify[93] >> 1) & 3], stdout); if (!(g_awIdentify[93] & UINT16_C(0x0001))) fputs(" bit0-clear!", stdout); fputs(g_awIdentify[93] & UINT16_C(0x0008) ? "diag-passed" : "diag-failed!", stdout); fputs(g_awIdentify[93] & UINT16_C(0x0010) ? "PDIGA-" : "no-PDIAG-", stdout); fputs(g_awIdentify[93] & UINT16_C(0x0020) ? "DASP-" : "no-DASP-", stdout); fputs(g_awIdentify[93] & UINT16_C(0x0040) ? "responds-when-dev1-selected" : "dev1-can-be-selected", stdout); if (g_awIdentify[93] & UINT16_C(0x0080)) fputs(" rsvd7!", stdout); } if (g_awIdentify[93] & UINT16_C(0x0f00)) { fputs(" dev1: ", stdout); fputs(s_apszDevNum[(g_awIdentify[93] >> 9) & 3], stdout); fputs(g_awIdentify[93] & UINT16_C(0x0800) ? "PDIGA-" : "no-PDIAG-", stdout); if (!(g_awIdentify[93] & UINT16_C(0x0100))) fputs(" bit8-clear!", stdout); if (g_awIdentify[93] & UINT16_C(0x1000)) fputs(" rsvd12!", stdout); } fputs(g_awIdentify[93] & UINT16_C(0x2000) ? "CBLID-below-ViL" : "CBLID-above-ViHB", stdout); putchar('\n'); } else fputs(" not specified\n", stdout); printf("[ 94]=%#06x - recommended AAM value: %#x current: %#x\n", g_awIdentify[94], g_awIdentify[94] >> 8, g_awIdentify[94] & UINT16_C(0x00ff)); printf("[ 95]=%#06x - stream minimum request size: %d\n", g_awIdentify[95], g_awIdentify[95]); printf("[ 96]=%#06x - streaming transfer time, DMA: %d\n", g_awIdentify[96], g_awIdentify[96]); printf("[ 97]=%#06x - streaming access latency, DMA+PIO: %d\n", g_awIdentify[97], g_awIdentify[97]); printf("[ 98:99] - streaming performance granularity: %ld (%#lx)\n", *(uint32_t *)&g_awIdentify[98], *(uint32_t *)&g_awIdentify[98]); printf("[100:103] - LBA48 user addressable sectors: %lld (%#llx)\n", *(uint64_t *)&g_awIdentify[100], *(uint64_t *)&g_awIdentify[100]); printf("[104]=%#06x - streaming transfer time, PIO: %d\n", g_awIdentify[104], g_awIdentify[104]); printf("[105]=%#06x (reserved)\n", g_awIdentify[105]); if ((g_awIdentify[106] & UINT16_C(0xc000)) == UINT16_C(0x4000)) { printf("[106]=%#06x - Physical/logical sector size: %u logical per physical", g_awIdentify[106], 1U << (g_awIdentify[106] & 0xfU)); if (g_awIdentify[106] & UINT16_C(0x1000)) fputs(", more-than-512-byte-logical", stdout); if (g_awIdentify[106] & UINT16_C(0x2000)) fputs(", multiple-logical-per-physical", stdout); if (g_awIdentify[106] & UINT16_C(0x0ff0)) printf("rsvd4-11=%#x", g_awIdentify[106] & UINT16_C(0x0ff0)); putchar('\n'); } else printf("[106]=%#06x - Physical/logical sector size: not specified", g_awIdentify[106]); printf("[107]=%#06x - Inter-seek delay for acoustic testing\n", g_awIdentify[107]); printf("[108:111] - World wide name: %#llx\n", *(uint64_t *)&g_awIdentify[108]); for (i = 112; i <= 116; i++) printf("[%u]=%#06x (reserved)\n", i, g_awIdentify[i]); printf("[117:118] - Logical sector size: %lu bytes (%#lx)\n", *(uint32_t *)&g_awIdentify[117], *(uint32_t *)&g_awIdentify[117]); for (i = 119; i <= 120; i++) printf("[%u]=%#06x - todo\n", i, g_awIdentify[i]); for (i = 121; i <= 126; i++) printf("[%u]=%#06x (reserved)\n", i, g_awIdentify[i]); printf("[127]=%#06x - obsolete\n", g_awIdentify[127]); printf("[128]=%#06x - security status - todo\n", g_awIdentify[128]); for (i = 129; i <= 159; i++) printf("[%u]=%#06x - vendor specific\n", i, g_awIdentify[i]); printf("[160]=%#06x - CFA power mode - todo\n", g_awIdentify[160]); for (i = 161; i <= 167; i++) printf("[%u]=%#06x (reserved for the CompactFlash guys)\n", i, g_awIdentify[i]); printf("[168]=%#06x - Device nominal form factor - todo\n", g_awIdentify[168]); for (i = 169; i <= 175; i++) printf("[%u]=%#06x (reserved)\n", i, g_awIdentify[i]); AtaPrintIdString("[176:205] - current media string: ", &g_awIdentify[176], 30, "\n"); printf("[206]=%#06x - SCT command transport - todo\n", g_awIdentify[206]); printf("[207]=%#06x (reserved for CE-ATA)\n", g_awIdentify[207]); printf("[208]=%#06x (reserved for CE-ATA)\n", g_awIdentify[208]); printf("[209]=%#06x - logical block alignment - todo\n", g_awIdentify[209]); printf("[210:211] - Write-Read-Verify sector count mode 3: %lu (%#lx)\n", *(uint32_t *)&g_awIdentify[210], *(uint32_t *)&g_awIdentify[210]); printf("[212:213] - Write-Read-Verify sector count mode 2: %lu (%#lx)\n", *(uint32_t *)&g_awIdentify[212], *(uint32_t *)&g_awIdentify[212]); printf("[214]=%#06x - NV cache capabilities - todo\n", g_awIdentify[214]); printf("[215:216] - NV cache size: %lu logical blocks (%#lx)\n", *(uint32_t *)&g_awIdentify[215], *(uint32_t *)&g_awIdentify[215]); printf("[217]=%#06x - Nominal media rotation rate: %u\n", g_awIdentify[217], g_awIdentify[217]); printf("[218]=%#06x (reserved)\n", g_awIdentify[218]); printf("[219]=%#06x - NV cache options - todo\n", g_awIdentify[219]); printf("[220]=%#06x - Current write-read-verify mode - todo\n", g_awIdentify[220]); printf("[221]=%#06x (reserved)\n", g_awIdentify[221]); printf("[222]=%#06x - Transport major version number - todo\n", g_awIdentify[222]); printf("[223]=%#06x - Transport minor version number: %u\n", g_awIdentify[223], g_awIdentify[223]); for (i = 224; i <= 233; i++) printf("[%u]=%#06x (reserved for CE-ATA)\n", i, g_awIdentify[i]); printf("[234]=%#06x - Min 512 bytes blocks per download microcode mode 3: %u\n", g_awIdentify[234], g_awIdentify[234]); printf("[235]=%#06x - Max 512 bytes blocks per download microcode mode 3: %u\n", g_awIdentify[235], g_awIdentify[235]); for (i = 236; i <= 254; i++) printf("[%u]=%#06x (reserved)\n", i, g_awIdentify[i]); printf("[255]=%#06x - Integrity word: ", g_awIdentify[255]); bCksum = AtaCalcIdChecksum(g_awIdentify); if ((g_awIdentify[255] & UINT16_C(0xff)) == UINT16_C(0x00A5) /* ATA-8 7.16.7.88 */) { if ((g_awIdentify[255] >> 8) == bCksum) printf("cksum=%#x (correct)\n", g_awIdentify[255] >> 8); else printf("cksum=%#x bad!, correct=%#x\n", g_awIdentify[255] >> 8, bCksum); } else printf(" no checksum (should be %#x)\n", bCksum); return 0; }