ata_id.c revision ad29a9f14fa8b1932c0e418bfcf1c10ce6a35a33
fb0951b02ebf51a93acf12721d8857d31ce57ba3Lennart Poettering/*
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * ata_id - reads product/serial number from ATA drives
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering *
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers * Copyright (C) 2005-2008 Kay Sievers <kay.sievers@vrfy.org>
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers * Copyright (C) 2009 Lennart Poettering <lennart@poettering.net>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * Copyright (C) 2009-2010 David Zeuthen <zeuthen@gmail.com>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering *
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * This program is free software: you can redistribute it and/or modify
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * it under the terms of the GNU General Public License as published by
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * the Free Software Foundation, either version 2 of the License, or
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * (at your option) any later version.
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering *
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * This program is distributed in the hope that it will be useful,
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * but WITHOUT ANY WARRANTY; without even the implied warranty of
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * GNU General Public License for more details.
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering *
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * You should have received a copy of the GNU General Public License
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering * along with this program. If not, see <http://www.gnu.org/licenses/>.
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón */
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <stdio.h>
4f9bca639a806e235173ec08e01de8bdcec82f81Lennart Poettering#include <stdlib.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <stdint.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <unistd.h>
4e949c11a1df4547d5f102e4131e07b026369cd7Javier Jardón#include <fcntl.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <ctype.h>
78a825f216d39ee0295b00647b059d45467e1d02Kay Sievers#include <assert.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <string.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <errno.h>
a80db8bd5f7f15859e8891aab9fc3694ce4cd0bdJavier Jardón#include <getopt.h>
a80db8bd5f7f15859e8891aab9fc3694ce4cd0bdJavier Jardón#include <scsi/scsi.h>
4db6d587c37c0357d20c79bf1a7c9afd4c7ced61Kay Sievers#include <scsi/sg.h>
907dd1953b7517534d646f5b2777780020c896e2Kay Sievers#include <scsi/scsi_ioctl.h>
eb7bbee6cd182d5c4eb1e1180631c35158f59379Kay Sievers#include <sys/ioctl.h>
6aad7f2cd75c88f990c7857bb173b3e8d0faee0fUmut Tezduyar Lindskog#include <sys/types.h>
91ca5bf0b6f3b487a16cc262527c9de6744db624Martin Pitt#include <sys/stat.h>
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers#include <linux/types.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <linux/hdreg.h>
22be093ffb403a1c474037939ca9b88b1ee39f77Lennart Poettering#include <linux/fs.h>
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers#include <linux/cdrom.h>
8666abb452db73d9a11ead61251eec42bc531cceKay Sievers#include <linux/bsg.h>
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering#include <arpa/inet.h>
5e63ce78b5018ba612e794a610a6f13c5eefade7Cristian Rodríguez
3d585edbb14b9705c80183aeb16dfd0a28df0ac9Lennart Poettering#include "libudev.h"
5e63ce78b5018ba612e794a610a6f13c5eefade7Cristian Rodríguez#include "libudev-private.h"
0fa2cac4f0cdefaf1addd7f1fe0fd8113db9360bKay Sievers
0fa2cac4f0cdefaf1addd7f1fe0fd8113db9360bKay Sievers#define COMMAND_TIMEOUT_MSEC (30 * 1000)
0fa2cac4f0cdefaf1addd7f1fe0fd8113db9360bKay Sievers
4c6abc93c708762ae3f377eab8dbd357262cc432Koen Kooistatic int disk_scsi_inquiry_command(int fd,
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger void *buf,
0fa2cac4f0cdefaf1addd7f1fe0fd8113db9360bKay Sievers size_t buf_len)
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger{
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger struct sg_io_v4 io_v4;
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger uint8_t cdb[6];
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger uint8_t sense[32];
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger int ret;
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger /*
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger * INQUIRY, see SPC-4 section 6.4
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger */
f15515b5e6a9ebe95c938cc670df6e576fcf9176Filipe Brandenburger memset(cdb, 0, sizeof(cdb));
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger cdb[0] = 0x12; /* OPERATION CODE: INQUIRY */
a59f16ce4a11c440cb2136ad3d5e3184714c545eRobert Schiele cdb[3] = (buf_len >> 8); /* ALLOCATION LENGTH */
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger cdb[4] = (buf_len & 0xff);
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger memset(sense, 0, sizeof(sense));
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger memset(&io_v4, 0, sizeof(struct sg_io_v4));
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger io_v4.guard = 'Q';
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger io_v4.protocol = BSG_PROTOCOL_SCSI;
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
2f96919bcdd0978164c801b21e053fb3b31e8bacFilipe Brandenburger io_v4.request_len = sizeof (cdb);
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera io_v4.request = (uintptr_t) cdb;
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera io_v4.max_response_len = sizeof (sense);
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera io_v4.response = (uintptr_t) sense;
20f56fddcd58c84fa73597486e905c652667214fDidier Roche io_v4.din_xfer_len = buf_len;
1c7dde3e475978c569a982d65fd86d4b4e3caad8Bastien Nocera io_v4.din_xferp = (uintptr_t) buf;
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering io_v4.timeout = COMMAND_TIMEOUT_MSEC;
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering ret = ioctl(fd, SG_IO, &io_v4);
3ce4fad8f548db9edb19869ea540e3192d2123f4Kay Sievers if (ret != 0) {
f975e971accc4d50c73ae53167db3df7a7099cf2Lennart Poettering /* could be that the driver doesn't do version 4, try version 3 */
e9da3678fcfc774b325dc1eaa054d0e00028a1fcLennart Poettering if (errno == EINVAL) {
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering struct sg_io_hdr io_hdr;
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek io_hdr.interface_id = 'S';
92ec4495f76a7a2a6c31f5bb2a5240f78dcfe1d2Javier Jardón io_hdr.cmdp = (unsigned char*) cdb;
2d0efdf1af5ff77441228854343c61d42a89840cSamuli Suominen io_hdr.cmd_len = sizeof (cdb);
2d0efdf1af5ff77441228854343c61d42a89840cSamuli Suominen io_hdr.dxferp = buf;
b51fc639f01ee6194af3e7e944a79accce474fe1Dave Reisner io_hdr.dxfer_len = buf_len;
dd5ae4c36c89da5dbe8d1628939b26c00db98753Przemyslaw Kedzierski io_hdr.sbp = sense;
dd5ae4c36c89da5dbe8d1628939b26c00db98753Przemyslaw Kedzierski io_hdr.mx_sb_len = sizeof (sense);
2d0efdf1af5ff77441228854343c61d42a89840cSamuli Suominen io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
96ede2601f27cd5fe52eed96b873bef55cd0ce23Lennart Poettering io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
2d0efdf1af5ff77441228854343c61d42a89840cSamuli Suominen
edeb68c53f1cdc452016b4c8512586a70b1262e3Tom Gundersen ret = ioctl(fd, SG_IO, &io_hdr);
2d0efdf1af5ff77441228854343c61d42a89840cSamuli Suominen if (ret != 0)
7801356442578ff6e1c65844eb9e65c819af4660Zbigniew Jędrzejewski-Szmek goto out;
66b0e0e0e3652227fe107ab9d09fa14fd4bc4dfaCristian Rodríguez
66b0e0e0e3652227fe107ab9d09fa14fd4bc4dfaCristian Rodríguez /* even if the ioctl succeeds, we need to check the return value */
f00929ad622c978f8ad83590a15a765b4beecac9Dimitri John Ledkov if (!(io_hdr.status == 0 &&
f00929ad622c978f8ad83590a15a765b4beecac9Dimitri John Ledkov io_hdr.host_status == 0 &&
f00929ad622c978f8ad83590a15a765b4beecac9Dimitri John Ledkov io_hdr.driver_status == 0)) {
446883528524429283626208928b51f49f28f810Lennart Poettering errno = EIO;
446883528524429283626208928b51f49f28f810Lennart Poettering ret = -1;
4acbce79798347cddf1e1d42e9be571e0a041873Zbigniew Jędrzejewski-Szmek goto out;
4acbce79798347cddf1e1d42e9be571e0a041873Zbigniew Jędrzejewski-Szmek }
80a5cbace45a6adbf2f9119edc5a4b10db493064Kay Sievers } else {
b37250d661ed67d07c734630617d73e64f6d7e49Zbigniew Jędrzejewski-Szmek goto out;
b37250d661ed67d07c734630617d73e64f6d7e49Zbigniew Jędrzejewski-Szmek }
6581f00f7eabdaccf587a4b6af60ed4696dd2791Zbigniew Jędrzejewski-Szmek }
6581f00f7eabdaccf587a4b6af60ed4696dd2791Zbigniew Jędrzejewski-Szmek
92ec4495f76a7a2a6c31f5bb2a5240f78dcfe1d2Javier Jardón /* even if the ioctl succeeds, we need to check the return value */
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek if (!(io_v4.device_status == 0 &&
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek io_v4.transport_status == 0 &&
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek io_v4.driver_status == 0)) {
fe1fed02c7637a2c18cd575f78be7fda27972148Zbigniew Jędrzejewski-Szmek errno = EIO;
6e92b23f0d6dd398848376bbaf47e54a90ed3389Kay Sievers ret = -1;
0eaeca1f2373a323b98c86b47561d98e59c67b25Kay Sievers goto out;
d66ee73a3dd7b5433fc0da3125bbdff740de7745Zbigniew Jędrzejewski-Szmek }
d66ee73a3dd7b5433fc0da3125bbdff740de7745Zbigniew Jędrzejewski-Szmek
d66ee73a3dd7b5433fc0da3125bbdff740de7745Zbigniew Jędrzejewski-Szmek out:
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers return ret;
c4a77bcb9a50f152557e25c90837d8bfef858729Marc-Antoine Perennou}
ac714a78fdca481488d88f84b6332d28083a4511Martin Jansa
ac714a78fdca481488d88f84b6332d28083a4511Martin Jansastatic int disk_identify_command(int fd,
b62cfcea00862ccbf0e5e297f8a339f70987edefMichael Biebl void *buf,
b62cfcea00862ccbf0e5e297f8a339f70987edefMichael Biebl size_t buf_len)
b62cfcea00862ccbf0e5e297f8a339f70987edefMichael Biebl{
9a60da2834074d970ca063c210fe9d2f05c70532Thierry Reding struct sg_io_v4 io_v4;
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek uint8_t cdb[12];
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek uint8_t sense[32];
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek uint8_t *desc = sense+8;
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek int ret;
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek /*
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek * ATA Pass-Through 12 byte command, as described in
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek *
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek * T10 04-262r8 ATA Command Pass-Through
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek *
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek */
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek memset(cdb, 0, sizeof(cdb));
732bfe09aeffc3cd78b80ee9e20c9c3babd944d6Zbigniew Jędrzejewski-Szmek cdb[0] = 0xa1; /* OPERATION CODE: 12 byte pass through */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[3] = 0; /* FEATURES */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[4] = 1; /* SECTORS */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[5] = 0; /* LBA LOW */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[6] = 0; /* LBA MID */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[7] = 0; /* LBA HIGH */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[8] = 0 & 0x4F; /* SELECT */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[9] = 0xEC; /* Command: ATA IDENTIFY DEVICE */;
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek memset(sense, 0, sizeof(sense));
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek memset(&io_v4, 0, sizeof(struct sg_io_v4));
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek io_v4.guard = 'Q';
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek io_v4.protocol = BSG_PROTOCOL_SCSI;
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek io_v4.request_len = sizeof (cdb);
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek io_v4.request = (uintptr_t) cdb;
eb2e280f9c59b66965c9316eadc4c113a13ca744Lucas De Marchi io_v4.max_response_len = sizeof (sense);
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering io_v4.response = (uintptr_t) sense;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_v4.din_xfer_len = buf_len;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_v4.din_xferp = (uintptr_t) buf;
27765dfc7a32d790badb29e6498b34edb0b60c33Lennart Poettering io_v4.timeout = COMMAND_TIMEOUT_MSEC;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
780040dc2a4b08a2c1fe5bd8db3a70e966c2acb3Kay Sievers ret = ioctl(fd, SG_IO, &io_v4);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering if (ret != 0) {
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering /* could be that the driver doesn't do version 4, try version 3 */
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering if (errno == EINVAL) {
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering struct sg_io_hdr io_hdr;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
03930e48636e86ad84946253ca2bf4f91deeb645Lennart Poettering memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.interface_id = 'S';
693eb9a2d42d71445dad273a76e2470199d1dc5aLennart Poettering io_hdr.cmdp = (unsigned char*) cdb;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.cmd_len = sizeof (cdb);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.dxferp = buf;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.dxfer_len = buf_len;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.sbp = sense;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.mx_sb_len = sizeof (sense);
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering ret = ioctl(fd, SG_IO, &io_hdr);
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering if (ret != 0)
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering goto out;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering } else {
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering goto out;
8745297f9853c4a17bac69e1b7e652fe81bc1940Lennart Poettering }
0a98d66159e474915afd6597d3aa444a698fdd2dDavid Herrmann }
d200735e13c52dcfe36c0e066f9f6c2fbfb85a9cMichal Schmidt
213298fb822258bb69c6b85b7c8d7f019fd2306aLennart Poettering if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) {
693eb9a2d42d71445dad273a76e2470199d1dc5aLennart Poettering errno = EIO;
be1a67d9d63bfdd4a5f8ba9cfc804030f10f5833Lennart Poettering ret = -1;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering goto out;
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering }
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri out:
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri return ret;
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering}
c1663b9daf5a43425e54bbe3daf6b10e64578f80Lennart Poettering
aca33b078cd32c5416a7fa3d5020a5d461c130eeCristian Rodríguezstatic int disk_identify_packet_device_command(int fd,
2a4d1ec1520c926b0160efe14142634e164ddc30Cristian Rodríguez void *buf,
c1663b9daf5a43425e54bbe3daf6b10e64578f80Lennart Poettering size_t buf_len)
4f47bb8c5e5f234c614dc14532a9483328e61002Zbigniew Jędrzejewski-Szmek{
4f47bb8c5e5f234c614dc14532a9483328e61002Zbigniew Jędrzejewski-Szmek struct sg_io_v4 io_v4;
4f47bb8c5e5f234c614dc14532a9483328e61002Zbigniew Jędrzejewski-Szmek uint8_t cdb[16];
65e3a2cf7c3b399853dd309f702ca5078b7d16eaZbigniew Jędrzejewski-Szmek uint8_t sense[32];
65e3a2cf7c3b399853dd309f702ca5078b7d16eaZbigniew Jędrzejewski-Szmek uint8_t *desc = sense+8;
65e3a2cf7c3b399853dd309f702ca5078b7d16eaZbigniew Jędrzejewski-Szmek int ret;
4f47bb8c5e5f234c614dc14532a9483328e61002Zbigniew Jędrzejewski-Szmek
0289f2fb2a64df53b589b771f69c43126b029590Zbigniew Jędrzejewski-Szmek /*
b850b06e1efcc7e27cfd785759a3a913ac9ed196Kay Sievers * ATA Pass-Through 16 byte command, as described in
235c6e628199221b7885f159367614b7105547cfJohn *
b850b06e1efcc7e27cfd785759a3a913ac9ed196Kay Sievers * T10 04-262r8 ATA Command Pass-Through
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek *
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf
0289f2fb2a64df53b589b771f69c43126b029590Zbigniew Jędrzejewski-Szmek */
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek memset(cdb, 0, sizeof(cdb));
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek cdb[0] = 0x85; /* OPERATION CODE: 16 byte pass through */
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
9e7adc3ae1133fa08a468768a490812299fad030Lucas De Marchi cdb[3] = 0; /* FEATURES */
9e7adc3ae1133fa08a468768a490812299fad030Lucas De Marchi cdb[4] = 0; /* FEATURES */
9b85fc6a89386582bfe792dba881800b0a093839Gustavo Sverzut Barbieri cdb[5] = 0; /* SECTORS */
9d2d0fe1e3f28a639c26b62391f79cfd1450d91bEvangelos Foutras cdb[6] = 1; /* SECTORS */
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering cdb[7] = 0; /* LBA LOW */
5a45a93627609451784a04366cfa1150d32611d1Lennart Poettering cdb[8] = 0; /* LBA LOW */
39c4ead2323b45bbe9866e0f97fd8dcfb8a0bedeZbigniew Jędrzejewski-Szmek cdb[9] = 0; /* LBA MID */
2a4d1ec1520c926b0160efe14142634e164ddc30Cristian Rodríguez cdb[10] = 0; /* LBA MID */
39c4ead2323b45bbe9866e0f97fd8dcfb8a0bedeZbigniew Jędrzejewski-Szmek cdb[11] = 0; /* LBA HIGH */
ae0ceefc2f432bc1068889fcff53d929eca8a3c4Zbigniew Jędrzejewski-Szmek cdb[12] = 0; /* LBA HIGH */
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering cdb[13] = 0; /* DEVICE */
ccd06097c79218f7d5ea4c21721bbcbc7c467dcaZbigniew Jędrzejewski-Szmek cdb[14] = 0xA1; /* Command: ATA IDENTIFY PACKET DEVICE */;
ccd06097c79218f7d5ea4c21721bbcbc7c467dcaZbigniew Jędrzejewski-Szmek cdb[15] = 0; /* CONTROL */
1c231f56482546725c4dbd3303f70300bd3c63e9Lennart Poettering memset(sense, 0, sizeof(sense));
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek
de99c9dcbaf6e474551266d8f0b519bf2d8d0522Lennart Poettering memset(&io_v4, 0, sizeof(struct sg_io_v4));
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek io_v4.guard = 'Q';
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek io_v4.protocol = BSG_PROTOCOL_SCSI;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek io_v4.request_len = sizeof (cdb);
ccd06097c79218f7d5ea4c21721bbcbc7c467dcaZbigniew Jędrzejewski-Szmek io_v4.request = (uintptr_t) cdb;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek io_v4.max_response_len = sizeof (sense);
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek io_v4.response = (uintptr_t) sense;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek io_v4.din_xfer_len = buf_len;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek io_v4.din_xferp = (uintptr_t) buf;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek io_v4.timeout = COMMAND_TIMEOUT_MSEC;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek
32dcef3ab1eb91ee469c3246ef859578dccd8a45Zbigniew Jędrzejewski-Szmek ret = ioctl(fd, SG_IO, &io_v4);
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek if (ret != 0) {
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek /* could be that the driver doesn't do version 4, try version 3 */
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger if (errno == EINVAL) {
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger struct sg_io_hdr io_hdr;
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger io_hdr.interface_id = 'S';
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger io_hdr.cmdp = (unsigned char*) cdb;
be8737ae386166d2f279767ac87b226204c0de7eFilipe Brandenburger io_hdr.cmd_len = sizeof (cdb);
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek io_hdr.dxferp = buf;
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek io_hdr.dxfer_len = buf_len;
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek io_hdr.sbp = sense;
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek io_hdr.mx_sb_len = sizeof (sense);
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek
747cf8cdf61cdad068c727e42eac699f2505ae77Zbigniew Jędrzejewski-Szmek ret = ioctl(fd, SG_IO, &io_hdr);
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek if (ret != 0)
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek goto out;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek } else {
25ee45f9953c121fc26a54a85ad7bb3a3180152bMichael Biebl goto out;
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek }
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek }
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek
1864b0e39505cd44a98eee61c97916b86491c0b4Zbigniew Jędrzejewski-Szmek if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) {
1864b0e39505cd44a98eee61c97916b86491c0b4Zbigniew Jędrzejewski-Szmek errno = EIO;
1864b0e39505cd44a98eee61c97916b86491c0b4Zbigniew Jędrzejewski-Szmek ret = -1;
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek goto out;
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek }
1864b0e39505cd44a98eee61c97916b86491c0b4Zbigniew Jędrzejewski-Szmek
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek out:
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek return ret;
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek}
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek/**
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek * disk_identify_get_string:
a6c0b31d509f76023d8efbcd5e912863c8fb254cZbigniew Jędrzejewski-Szmek * @identify: A block of IDENTIFY data
f2ec0646aba7c6703a6c79603957e805b74c3befZbigniew Jędrzejewski-Szmek * @offset_words: Offset of the string to get, in words.
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek * @dest: Destination buffer for the string.
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek * @dest_len: Length of destination buffer, in bytes.
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek *
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek * Copies the ATA string from @identify located at @offset_words into @dest.
c937e0d5c579863677e0fcb5508517f7714c332dZbigniew Jędrzejewski-Szmek */
afea26ad7d406d8b6c95d2642cb5a1d807b87546Lennart Poetteringstatic void disk_identify_get_string (uint8_t identify[512],
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers unsigned int offset_words,
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau char *dest,
27c64db6dff88ebe9761dfe3b0c073d2a9bf2e41Zbigniew Jędrzejewski-Szmek size_t dest_len)
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers{
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers unsigned int c1;
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers unsigned int c2;
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl assert (identify != NULL);
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl assert (dest != NULL);
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering assert ((dest_len & 1) == 0);
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers while (dest_len > 0) {
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers c1 = ((uint16_t *) identify)[offset_words] >> 8;
7959ff9914a6f3a59dbff95c199bcc540b70ac94Kay Sievers c2 = ((uint16_t *) identify)[offset_words] & 0xff;
fba1ea06bb5b653e9eb0cc1b6004af8da273a4abShawn Landden *dest = c1;
fba1ea06bb5b653e9eb0cc1b6004af8da273a4abShawn Landden dest++;
fba1ea06bb5b653e9eb0cc1b6004af8da273a4abShawn Landden *dest = c2;
85f19d825e7504676f3a80c78c1d9a7ec35a3b3fMichael Biebl dest++;
47be870bd83fb3719dffc3ee9348a409ab762a14Lennart Poettering offset_words++;
27c64db6dff88ebe9761dfe3b0c073d2a9bf2e41Zbigniew Jędrzejewski-Szmek dest_len -= 2;
4db17f291c627c885de668200ff8cce2e57c933fZbigniew Jędrzejewski-Szmek }
f7ad54a301e4ae8dceab54d3ab3934e56c1134eaLennart Poettering}
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmekstatic void disk_identify_fixup_string (uint8_t identify[512],
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering unsigned int offset_words,
9388e99e208a6487b26dcbda86005ee9eba8d93dMichael Olbrich size_t len)
3b794314149e40afaf3c456285e1e529747b6560Holger Schurig{
5f381b355a95b953654e46ba3ccdc81bdec165eaLennart Poettering disk_identify_get_string(identify, offset_words,
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek (char *) identify + offset_words * 2, len);
539618a0ddc2dc7f0fbe28de2ae0e07b34c81e60Lennart Poettering}
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmekstatic void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words)
84dd59b51c0db34f0334e90a5da2a45abcc9a52aDjalal Harouni{
84dd59b51c0db34f0334e90a5da2a45abcc9a52aDjalal Harouni uint16_t *p;
c4a5ddc9f29cf910fac9d814cd898b4cc2bd79b1Tom Gundersen
6589d0dba2b1ccf2406db527c2c1b51c7143e117Jean-André Santoni p = (uint16_t *) identify;
75616a1332aff00d27db713cda3bd93c508a5b59Zbigniew Jędrzejewski-Szmek p[offset_words] = le16toh (p[offset_words]);
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek}
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek
583c14fc04a089e9af70a3fa0b8c0a8c27c06ec0Michael Olbrich/**
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * disk_identify:
8ecec322fe6b34b64868d8cc3808b5613f09e8d3Zbigniew Jędrzejewski-Szmek * @udev: The libudev context.
cf1755bac0426132c21fdca519a336ce7d920277Michael Olbrich * @fd: File descriptor for the block device.
34f7b9f98facbf3431c6849622104cee992f2b7dLennart Poettering * @out_identify: Return location for IDENTIFY data.
34f7b9f98facbf3431c6849622104cee992f2b7dLennart Poettering * @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE.
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek *
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * Sends the IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command to the
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * device represented by @fd. If successful, then the result will be
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * copied into @out_identify and @out_is_packet_device.
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek *
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * This routine is based on code from libatasmart, Copyright 2008
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * Lennart Poettering, LGPL v2.1.
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek *
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * Returns: 0 if the data was successfully obtained, otherwise
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek * non-zero with errno set.
34f7b9f98facbf3431c6849622104cee992f2b7dLennart Poettering */
cf1755bac0426132c21fdca519a336ce7d920277Michael Olbrichstatic int disk_identify (struct udev *udev,
81577dc22887debaf9b19bf1034a2887fb9069c7Zbigniew Jędrzejewski-Szmek int fd,
a8348796c0d39435b1c3d85ce6e95dad1ac85fecLennart Poettering uint8_t out_identify[512],
b237ef2cfac7ab0b33170809e8cb64628606207dTollef Fog Heen int *out_is_packet_device)
a9b5b03212f9c854938483b8901e433c2ba6619bMichael Tremer{
d1ab0ca07372649dad70a0348d75e394f254e1b6Lennart Poettering int ret;
2270309471213a3c960543e523130627e9cb10e2Kay Sievers uint8_t inquiry_buf[36];
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek int peripheral_device_type;
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek int all_nul_bytes;
8114dedc5910d9a9cec702f6b6658551a0cd9edeChengwei Yang int n;
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek int is_packet_device;
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek assert (out_identify != NULL);
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek
ac6b760ceedd4b21921b6a682cf1479af3d3024fZbigniew Jędrzejewski-Szmek /* init results */
2270309471213a3c960543e523130627e9cb10e2Kay Sievers ret = -1;
4b357e15876b730343db08719c877fdb45b6ad42Michael Marineau memset (out_identify, '\0', 512);
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing is_packet_device = 0;
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing /* If we were to use ATA PASS_THROUGH (12) on an ATAPI device
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing * we could accidentally blank media. This is because MMC's BLANK
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing * command has the same op-code (0x61).
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing *
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing * To prevent this from happening we bail out if the device
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing * isn't a Direct Access Block Device, e.g. SCSI type 0x00
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing * (CD/DVD devices are type 0x05). So we send a SCSI INQUIRY
37161c5148396448921841ae1026b281c7949652Emil Renner Berthing * command first... libata is handling this via its SCSI
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * emulation layer.
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek *
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * This also ensures that we're actually dealing with a device
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * that understands SCSI commands.
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek *
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * (Yes, it is a bit perverse that we're tunneling the ATA
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * command through SCSI and relying on the ATA driver
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * emulating SCSI well-enough...)
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek *
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * (See commit 160b069c25690bfb0c785994c7c3710289179107 for
53e856e16ac37fe30b8bb59153ff69aad0fa9c27Zbigniew Jędrzejewski-Szmek * the original bug-fix and see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=556635
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen * for the original bug-report.)
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen */
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf));
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen if (ret != 0)
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen goto out;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen /* SPC-4, section 6.4.2: Standard INQUIRY data */
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen peripheral_device_type = inquiry_buf[0] & 0x1f;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen if (peripheral_device_type == 0x05)
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen {
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen is_packet_device = 1;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen ret = disk_identify_packet_device_command(fd, out_identify, 512);
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen goto check_nul_bytes;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen }
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen if (peripheral_device_type != 0x00) {
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen ret = -1;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen errno = EIO;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen goto out;
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen }
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen /* OK, now issue the IDENTIFY DEVICE command */
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen ret = disk_identify_command(fd, out_identify, 512);
6aea6d10f460853111ca8744201ec8dade97de3cThomas H.P. Andersen if (ret != 0)
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen goto out;
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen check_nul_bytes:
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen /* Check if IDENTIFY data is all NUL bytes - if so, bail */
e2ca86cf78f911a8be51f0224796e24883019139Dave Reisner all_nul_bytes = 1;
e2ca86cf78f911a8be51f0224796e24883019139Dave Reisner for (n = 0; n < 512; n++) {
a18535d9e138c525d0443ec9f30a90b3e2184686Tom Gundersen if (out_identify[n] != '\0') {
e2ca86cf78f911a8be51f0224796e24883019139Dave Reisner all_nul_bytes = 0;
70d8320978dcbce022d9acbb953a10a7aca049abDavid Strauss break;
e2ca86cf78f911a8be51f0224796e24883019139Dave Reisner }
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen }
c4955740969d7ba8ba43b024bca1a0a5b56eb8e8Tom Gundersen
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen if (all_nul_bytes) {
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen ret = -1;
e30431623a7d871da123cc37055ac49abf2c20eaTom Gundersen errno = EIO;
f553b3b1074151200187df916427a1468186435eAnders Olofsson goto out;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann }
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmannout:
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann if (out_is_packet_device != NULL)
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann *out_is_packet_device = is_packet_device;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann return ret;
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann}
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmannstatic void log_fn(struct udev *udev, int priority,
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann const char *file, int line, const char *fn,
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann const char *format, va_list args)
d4f5a1f47dbd04f26f2ddf951c97c4cb0ebbbe62David Herrmann{
f553b3b1074151200187df916427a1468186435eAnders Olofsson vsyslog(priority, format, args);
f553b3b1074151200187df916427a1468186435eAnders Olofsson}
f553b3b1074151200187df916427a1468186435eAnders Olofsson
f553b3b1074151200187df916427a1468186435eAnders Olofssonint main(int argc, char *argv[])
d47f6ca5f9b7a0b400d8bdb050151a0284fb4bdbGabriel de Perthuis{
f553b3b1074151200187df916427a1468186435eAnders Olofsson struct udev *udev;
f553b3b1074151200187df916427a1468186435eAnders Olofsson struct hd_driveid id;
f553b3b1074151200187df916427a1468186435eAnders Olofsson uint8_t identify[512];
f553b3b1074151200187df916427a1468186435eAnders Olofsson uint16_t *identify_words;
f553b3b1074151200187df916427a1468186435eAnders Olofsson char model[41];
f553b3b1074151200187df916427a1468186435eAnders Olofsson char model_enc[256];
728beb28a713709f521d374c9f8f3da781969d26Tom Gundersen char serial[21];
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech char revision[9];
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech const char *node = NULL;
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech int export = 0;
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech int fd;
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech uint16_t word;
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech int rc = 0;
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech int is_packet_device = 0;
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech static const struct option options[] = {
8d3ae2bd4c9bf9fc2e57f7b3776325a1c750ca30Chris Leech { "export", no_argument, NULL, 'x' },
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier { "help", no_argument, NULL, 'h' },
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier {}
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier };
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier udev = udev_new();
17df7223be064b1542dbe868e3b35cca977ee639Lennart Poettering if (udev == NULL)
17df7223be064b1542dbe868e3b35cca977ee639Lennart Poettering goto exit;
17df7223be064b1542dbe868e3b35cca977ee639Lennart Poettering
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier udev_log_init("ata_id");
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier udev_set_log_fn(udev, log_fn);
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier while (1) {
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier int option;
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier
c0467cf387548dc98c0254f63553d862b35a84e5Ronny Chevalier option = getopt_long(argc, argv, "xh", options, NULL);
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (option == -1)
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu break;
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu switch (option) {
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu case 'x':
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu export = 1;
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu break;
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu case 'h':
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu printf("Usage: ata_id [--export] [--help] <device>\n"
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu " --export print values as environment keys\n"
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu " --help print this help text\n\n");
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu goto exit;
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu }
816115863962548a9a0d9fbfe429c7f8e685beacRoberto Sassu }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering node = argv[optind];
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering if (node == NULL) {
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering err(udev, "no node specified\n");
3f8cc098d218525710e5cbad9adf37001d3b6060Jan Engelhardt rc = 1;
6a6751fe24bf456cf5c1efad785a4d11e78b42d0Lennart Poettering goto exit;
6a6751fe24bf456cf5c1efad785a4d11e78b42d0Lennart Poettering }
6a6751fe24bf456cf5c1efad785a4d11e78b42d0Lennart Poettering
6a6751fe24bf456cf5c1efad785a4d11e78b42d0Lennart Poettering fd = open(node, O_RDONLY|O_NONBLOCK);
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering if (fd < 0) {
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering err(udev, "unable to open '%s'\n", node);
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering rc = 1;
56cf987fe74270bde4e16c7ec9e0414a9030723bDaniel J Walsh goto exit;
591622d7efbc828f00f190d91b6608148b967ff5Lennart Poettering }
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer if (disk_identify(udev, fd, identify, &is_packet_device) == 0) {
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer /*
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer * fix up only the fields from the IDENTIFY data that we are going to
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer * use and copy it into the hd_driveid struct for convenience
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_string (identify, 10, 20); /* serial */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_string (identify, 23, 6); /* fwrev */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_string (identify, 27, 40); /* model */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 0); /* configuration */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 75); /* queue depth */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 75); /* SATA capabilities */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 82); /* command set supported */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 83); /* command set supported */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 84); /* command set supported */
eef65bf3ee6f73afa4a5de23ae3a794a279f30c0Michael Scherer disk_identify_fixup_uint16 (identify, 85); /* command set supported */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez disk_identify_fixup_uint16 (identify, 86); /* command set supported */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez disk_identify_fixup_uint16 (identify, 87); /* command set supported */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez disk_identify_fixup_uint16 (identify, 89); /* time required for SECURITY ERASE UNIT */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez disk_identify_fixup_uint16 (identify, 90); /* time required for enhanced SECURITY ERASE UNIT */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez disk_identify_fixup_uint16 (identify, 91); /* current APM values */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez disk_identify_fixup_uint16 (identify, 94); /* current AAM value */
5ec6b15b65304d94dc1c8cbad05c8b996b470d3aKay Sievers disk_identify_fixup_uint16 (identify, 128); /* device lock function */
56cf987fe74270bde4e16c7ec9e0414a9030723bDaniel J Walsh disk_identify_fixup_uint16 (identify, 217); /* nominal media rotation rate */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez memcpy(&id, identify, sizeof id);
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez } else {
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez /* If this fails, then try HDIO_GET_IDENTITY */
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) {
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez if (errno == ENOTTY) {
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez info(udev, "HDIO_GET_IDENTITY unsupported for '%s'\n", node);
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez rc = 2;
45df1f2c9a7fee67b37f64ddd00adad5982844faCristian Rodríguez } else {
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek err(udev, "HDIO_GET_IDENTITY failed for '%s': %m\n", node);
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek rc = 3;
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek }
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek goto close;
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek }
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek }
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek identify_words = (uint16_t *) identify;
ad95fd1d2b9c6344864857c2ba7634fd87753f8eZbigniew Jędrzejewski-Szmek
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers memcpy (model, id.model, 40);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering model[40] = '\0';
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering udev_util_encode_string(model, model_enc, sizeof(model_enc));
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering util_replace_whitespace((char *) id.model, model, 40);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering util_replace_chars(model, NULL);
6bf12f55aff33a588a1945d9d06aa31c164984fdLennart Poettering util_replace_whitespace((char *) id.serial_no, serial, 20);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering util_replace_chars(serial, NULL);
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek util_replace_whitespace((char *) id.fw_rev, revision, 8);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering util_replace_chars(revision, NULL);
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering if (export) {
807e17f05e217b474af39503efb9503d81b12596Lennart Poettering /* Set this to convey the disk speaks the ATA protocol */
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering printf("ID_ATA=1\n");
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering if ((id.config >> 8) & 0x80) {
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering /* This is an ATAPI device */
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering switch ((id.config >> 8) & 0x1f) {
6bf12f55aff33a588a1945d9d06aa31c164984fdLennart Poettering case 0:
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering printf("ID_TYPE=cd\n");
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering break;
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering case 1:
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering printf("ID_TYPE=tape\n");
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering break;
edce2aed3aa93b84f7b4c70412bdb665da2977b0Lennart Poettering case 5:
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering printf("ID_TYPE=cd\n");
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering break;
831f18cbf3f250207fcde15ea736639898317d77Lennart Poettering case 7:
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering printf("ID_TYPE=optical\n");
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering break;
831f18cbf3f250207fcde15ea736639898317d77Lennart Poettering default:
831f18cbf3f250207fcde15ea736639898317d77Lennart Poettering printf("ID_TYPE=generic\n");
831f18cbf3f250207fcde15ea736639898317d77Lennart Poettering break;
831f18cbf3f250207fcde15ea736639898317d77Lennart Poettering }
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering } else {
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering printf("ID_TYPE=disk\n");
8af3cf74df03f7528f9e2605ec7896a5daf0f711Lennart Poettering }
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek printf("ID_BUS=ata\n");
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek printf("ID_MODEL=%s\n", model);
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek printf("ID_MODEL_ENC=%s\n", model_enc);
0a7f0fcc79772d257e0c42358ad472a37a8ab151Dave Reisner printf("ID_REVISION=%s\n", revision);
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek if (serial[0] != '\0') {
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek printf("ID_SERIAL=%s_%s\n", model, serial);
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek printf("ID_SERIAL_SHORT=%s\n", serial);
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek } else {
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek printf("ID_SERIAL=%s\n", model);
d89c8fdf48c7bad5816b9f2e77e8361721f22517Zbigniew Jędrzejewski-Szmek }
3b1a55e110ab387a8d213581983e20c0a63d7894Zbigniew Jędrzejewski-Szmek
3b1a55e110ab387a8d213581983e20c0a63d7894Zbigniew Jędrzejewski-Szmek if (id.command_set_1 & (1<<5)) {
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers printf ("ID_ATA_WRITE_CACHE=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf ("ID_ATA_WRITE_CACHE_ENABLED=%d\n", (id.cfs_enable_1 & (1<<5)) ? 1 : 0);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.command_set_1 & (1<<10)) {
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_HPA=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_HPA_ENABLED=%d\n", (id.cfs_enable_1 & (1<<10)) ? 1 : 0);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering /*
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering * TODO: use the READ NATIVE MAX ADDRESS command to get the native max address
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering * so it is easy to check whether the protected area is in use.
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering */
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.command_set_1 & (1<<3)) {
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_PM=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_PM_ENABLED=%d\n", (id.cfs_enable_1 & (1<<3)) ? 1 : 0);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.command_set_1 & (1<<1)) {
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_ENABLED=%d\n", (id.cfs_enable_1 & (1<<1)) ? 1 : 0);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN=%d\n", id.trseuc * 2);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if ((id.cfs_enable_1 & (1<<1))) /* enabled */ {
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.dlf & (1<<8))
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=maximum\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering else
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_LEVEL=high\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.dlf & (1<<5))
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN=%d\n", id.trsEuc * 2);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.dlf & (1<<4))
6a6751fe24bf456cf5c1efad785a4d11e78b42d0Lennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_EXPIRE=1\n");
812cce323db081634f37e4ec6d29f2b9328a3f52Lennart Poettering if (id.dlf & (1<<3))
812cce323db081634f37e4ec6d29f2b9328a3f52Lennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_FROZEN=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.dlf & (1<<2))
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SECURITY_LOCKED=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering if (id.command_set_1 & (1<<0)) {
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SMART=1\n");
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering printf("ID_ATA_FEATURE_SET_SMART_ENABLED=%d\n", (id.cfs_enable_1 & (1<<0)) ? 1 : 0);
5b6319dceedd81f3f1ce7eb70ea5defaef43bcecLennart Poettering }
3e2147858f21943d5f4a781c60f33ac22c6096edKay Sievers if (id.command_set_2 & (1<<9)) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_AAM=1\n");
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_AAM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<9)) ? 1 : 0);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE=%d\n", id.acoustic >> 8);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_AAM_CURRENT_VALUE=%d\n", id.acoustic & 0xff);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering }
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (id.command_set_2 & (1<<5)) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_PUIS=1\n");
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_PUIS_ENABLED=%d\n", (id.cfs_enable_2 & (1<<5)) ? 1 : 0);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering }
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (id.command_set_2 & (1<<3)) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_APM=1\n");
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_APM_ENABLED=%d\n", (id.cfs_enable_2 & (1<<3)) ? 1 : 0);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if ((id.cfs_enable_2 & (1<<3)))
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_FEATURE_SET_APM_CURRENT_VALUE=%d\n", id.CurAPMvalues & 0xff);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering }
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (id.command_set_2 & (1<<0))
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_DOWNLOAD_MICROCODE=1\n");
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /*
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * Word 76 indicates the capabilities of a SATA device. A PATA device shall set
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * word 76 to 0000h or FFFFh. If word 76 is set to 0000h or FFFFh, then
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * the device does not claim compliance with the Serial ATA specification and words
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * 76 through 79 are not valid and shall be ignored.
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering word = *((uint16_t *) identify + 76);
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (word != 0x0000 && word != 0xffff) {
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_SATA=1\n");
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering /*
a48a62a1af02aec4473c9deed98dd5b89d210f93Zbigniew Jędrzejewski-Szmek * If bit 2 of word 76 is set to one, then the device supports the Gen2
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * signaling rate of 3.0 Gb/s (see SATA 2.6).
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering *
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * If bit 1 of word 76 is set to one, then the device supports the Gen1
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering * signaling rate of 1.5 Gb/s (see SATA 2.6).
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering */
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (word & (1<<2))
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_SATA_SIGNAL_RATE_GEN2=1\n");
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering if (word & (1<<1))
5eda94dda25bccda928c4b33c790dbe748573a22Lennart Poettering printf("ID_ATA_SATA_SIGNAL_RATE_GEN1=1\n");
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski }
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski /* Word 217 indicates the nominal media rotation rate of the device */
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski word = *((uint16_t *) identify + 217);
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski if (word != 0x0000) {
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski if (word == 0x0001) {
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski printf ("ID_ATA_ROTATION_RATE_RPM=0\n"); /* non-rotating e.g. SSD */
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski } else if (word >= 0x0401 && word <= 0xfffe) {
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski printf ("ID_ATA_ROTATION_RATE_RPM=%d\n", word);
d2edfae0f9bdbecf6a8518e2a5bcf06f470e0d9eKay Sievers }
d2edfae0f9bdbecf6a8518e2a5bcf06f470e0d9eKay Sievers }
d2edfae0f9bdbecf6a8518e2a5bcf06f470e0d9eKay Sievers
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski /*
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski * Words 108-111 contain a mandatory World Wide Name (WWN) in the NAA IEEE Registered identifier
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok * format. Word 108 bits (15:12) shall contain 5h, indicating that the naming authority is IEEE.
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok * All other values are reserved.
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok */
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok word = *((uint16_t *) identify + 108);
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok if ((word & 0xf000) == 0x5000) {
8b197c3a8a57c3f7c231b39e5660856fd9580c80Auke Kok uint64_t wwwn;
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski wwwn = *((uint16_t *) identify + 108);
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski wwwn <<= 16;
2b3e18de74ca89b374dd4f7a2c30e5731d347841Karol Lewandowski wwwn |= *((uint16_t *) identify + 109);
dd5ae4c36c89da5dbe8d1628939b26c00db98753Przemyslaw Kedzierski wwwn <<= 16;
dd5ae4c36c89da5dbe8d1628939b26c00db98753Przemyslaw Kedzierski wwwn |= *((uint16_t *) identify + 110);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering wwwn <<= 16;
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering wwwn |= *((uint16_t *) identify + 111);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering printf("ID_WWN=0x%llx\n", (unsigned long long int) wwwn);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering /* ATA devices have no vendor extension */
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering printf("ID_WWN_WITH_EXTENSION=0x%llx\n", (unsigned long long int) wwwn);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering /* from Linux's include/linux/ata.h */
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (identify_words[0] == 0x848a || identify_words[0] == 0x844a) {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering printf("ID_ATA_CFA=1\n");
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering } else {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if ((identify_words[83] & 0xc004) == 0x4004) {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering printf("ID_ATA_CFA=1\n");
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering } else {
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering if (serial[0] != '\0')
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering printf("%s_%s\n", model, serial);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering else
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering printf("%s\n", model);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering }
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poetteringclose:
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering close(fd);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poetteringexit:
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering udev_unref(udev);
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering udev_log_close();
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering return rc;
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering}
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering