mirror of
git://slackware.nl/current.git
synced 2025-02-14 08:48:37 +01:00
![Patrick J Volkerding](/assets/img/avatar_default.png)
Mon Apr 25 13:37:00 UTC 2011 Slackware 13.37 x86_64 stable is released! Thanks to everyone who pitched in on this release: the Slackware team, the folks producing upstream code, and linuxquestions.org for providing a great forum for collaboration and testing. The ISOs are off to be replicated, a 6 CD-ROM 32-bit set and a dual-sided 32-bit/64-bit x86/x86_64 DVD. Please consider supporting the Slackware project by picking up a copy from store.slackware.com. We're taking pre-orders now, and offer a discount if you sign up for a subscription. As always, thanks to the Slackware community for testing, suggestions, and feedback. :-) Have fun!
305 lines
11 KiB
Diff
305 lines
11 KiB
Diff
From 560de575148b7efda3b34a7f7073abd483c5f08e Mon Sep 17 00:00:00 2001
|
|
From: David Zeuthen <davidz@redhat.com>
|
|
Date: Thu, 4 Nov 2010 08:55:58 -0400
|
|
Subject: [PATCH 1/1] Use ata_id, not scsi_id, on ATAPI devices
|
|
|
|
The major benefit here, is that we get the ATAPI device serial
|
|
number. With SCSI ID we didn't get this since it's not part of the
|
|
SCSI INQUIRY command. Specifically this means that we get symlinks to
|
|
empty optical drives, e.g.
|
|
|
|
/dev/disk/by-id/ata-VBOX_CD-ROM_VB2-01700376
|
|
|
|
which we didn't get earlier. So this is a major win.
|
|
|
|
Also make ata_id work on CD-ROM devices when using /dev/bsg nodes so
|
|
this works on both the scsi_device as well as the block device. We do
|
|
this, basically, by issuing the ATA IDENTIFY PACKET DEVICE command
|
|
instead of the ATA IDENTIFY command. We also use 16-byte pass-through
|
|
ATA passthrough instead of 12-byte passthrough to avoid clashing with
|
|
the MMC BLANK command.
|
|
|
|
This means that we get this output
|
|
|
|
# udevadm info -q all -p /sys/devices/pci0000:00/0000:00:01.1/host3/target3:0:0/3:0:0:0
|
|
P: /devices/pci0000:00/0000:00:01.1/host3/target3:0:0/3:0:0:0
|
|
E: UDEV_LOG=3
|
|
E: DEVPATH=/devices/pci0000:00/0000:00:01.1/host3/target3:0:0/3:0:0:0
|
|
E: DEVTYPE=scsi_device
|
|
E: DRIVER=sr
|
|
E: MODALIAS=scsi:t-0x05
|
|
E: SUBSYSTEM=scsi
|
|
E: ID_ATA=1
|
|
E: ID_TYPE=cd
|
|
E: ID_BUS=ata
|
|
E: ID_MODEL=VBOX_CD-ROM
|
|
E: ID_MODEL_ENC=VBOX\x20CD-ROM\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x 20\x20\x20\x20\x20\x20\x20
|
|
E: ID_REVISION=1.0
|
|
E: ID_SERIAL=VBOX_CD-ROM_VB2-01700376
|
|
E: ID_SERIAL_SHORT=VB2-01700376
|
|
|
|
instead of just
|
|
|
|
# udevadm info -q all -p /sys/devices/pci0000:00/0000:00:01.1/host3/target3:0:0/3:0:0:0
|
|
P: /devices/pci0000:00/0000:00:01.1/host3/target3:0:0/3:0:0:0
|
|
E: UDEV_LOG=3
|
|
E: DEVPATH=/devices/pci0000:00/0000:00:01.1/host3/target3:0:0/3:0:0:0
|
|
E: DEVTYPE=scsi_device
|
|
E: DRIVER=sr
|
|
E: MODALIAS=scsi:t-0x05
|
|
E: SUBSYSTEM=scsi
|
|
E: ID_SCSI=1
|
|
E: ID_VENDOR=VBOX
|
|
E: ID_VENDOR_ENC=VBOX\x20\x20\x20\x20
|
|
E: ID_MODEL=CD-ROM
|
|
E: ID_MODEL_ENC=CD-ROM\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
|
|
E: ID_REVISION=1.0
|
|
E: ID_TYPE=cd
|
|
|
|
Signed-off-by: David Zeuthen <davidz@redhat.com>
|
|
---
|
|
extras/ata_id/ata_id.c | 122 ++++++++++++++++++++++++++---
|
|
rules/rules.d/60-persistent-storage.rules | 4 +
|
|
2 files changed, 114 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/extras/ata_id/ata_id.c b/extras/ata_id/ata_id.c
|
|
index 41544e9..92387e5 100644
|
|
--- a/extras/ata_id/ata_id.c
|
|
+++ b/extras/ata_id/ata_id.c
|
|
@@ -202,6 +202,89 @@ static int disk_identify_command(int fd,
|
|
return ret;
|
|
}
|
|
|
|
+static int disk_identify_packet_device_command(int fd,
|
|
+ void *buf,
|
|
+ size_t buf_len)
|
|
+{
|
|
+ struct sg_io_v4 io_v4;
|
|
+ uint8_t cdb[16];
|
|
+ uint8_t sense[32];
|
|
+ uint8_t *desc = sense+8;
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * ATA Pass-Through 16 byte command, as described in
|
|
+ *
|
|
+ * T10 04-262r8 ATA Command Pass-Through
|
|
+ *
|
|
+ * from http://www.t10.org/ftp/t10/document.04/04-262r8.pdf
|
|
+ */
|
|
+ memset(cdb, 0, sizeof(cdb));
|
|
+ cdb[0] = 0x85; /* OPERATION CODE: 16 byte pass through */
|
|
+ cdb[1] = 4 << 1; /* PROTOCOL: PIO Data-in */
|
|
+ cdb[2] = 0x2e; /* OFF_LINE=0, CK_COND=1, T_DIR=1, BYT_BLOK=1, T_LENGTH=2 */
|
|
+ cdb[3] = 0; /* FEATURES */
|
|
+ cdb[4] = 0; /* FEATURES */
|
|
+ cdb[5] = 0; /* SECTORS */
|
|
+ cdb[6] = 1; /* SECTORS */
|
|
+ cdb[7] = 0; /* LBA LOW */
|
|
+ cdb[8] = 0; /* LBA LOW */
|
|
+ cdb[9] = 0; /* LBA MID */
|
|
+ cdb[10] = 0; /* LBA MID */
|
|
+ cdb[11] = 0; /* LBA HIGH */
|
|
+ cdb[12] = 0; /* LBA HIGH */
|
|
+ cdb[13] = 0; /* DEVICE */
|
|
+ cdb[14] = 0xA1; /* Command: ATA IDENTIFY PACKET DEVICE */;
|
|
+ cdb[15] = 0; /* CONTROL */
|
|
+ memset(sense, 0, sizeof(sense));
|
|
+
|
|
+ memset(&io_v4, 0, sizeof(struct sg_io_v4));
|
|
+ io_v4.guard = 'Q';
|
|
+ io_v4.protocol = BSG_PROTOCOL_SCSI;
|
|
+ io_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD;
|
|
+ io_v4.request_len = sizeof (cdb);
|
|
+ io_v4.request = (uintptr_t) cdb;
|
|
+ io_v4.max_response_len = sizeof (sense);
|
|
+ io_v4.response = (uintptr_t) sense;
|
|
+ io_v4.din_xfer_len = buf_len;
|
|
+ io_v4.din_xferp = (uintptr_t) buf;
|
|
+ io_v4.timeout = COMMAND_TIMEOUT_MSEC;
|
|
+
|
|
+ ret = ioctl(fd, SG_IO, &io_v4);
|
|
+ if (ret != 0) {
|
|
+ /* could be that the driver doesn't do version 4, try version 3 */
|
|
+ if (errno == EINVAL) {
|
|
+ struct sg_io_hdr io_hdr;
|
|
+
|
|
+ memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
|
|
+ io_hdr.interface_id = 'S';
|
|
+ io_hdr.cmdp = (unsigned char*) cdb;
|
|
+ io_hdr.cmd_len = sizeof (cdb);
|
|
+ io_hdr.dxferp = buf;
|
|
+ io_hdr.dxfer_len = buf_len;
|
|
+ io_hdr.sbp = sense;
|
|
+ io_hdr.mx_sb_len = sizeof (sense);
|
|
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
|
|
+ io_hdr.timeout = COMMAND_TIMEOUT_MSEC;
|
|
+
|
|
+ ret = ioctl(fd, SG_IO, &io_hdr);
|
|
+ if (ret != 0)
|
|
+ goto out;
|
|
+ } else {
|
|
+ goto out;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!(sense[0] == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) {
|
|
+ errno = EIO;
|
|
+ ret = -1;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
/**
|
|
* disk_identify_get_string:
|
|
* @identify: A block of IDENTIFY data
|
|
@@ -256,31 +339,36 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offs
|
|
* @udev: The libudev context.
|
|
* @fd: File descriptor for the block device.
|
|
* @out_identify: Return location for IDENTIFY data.
|
|
+ * @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE.
|
|
*
|
|
- * Sends the IDENTIFY DEVICE command to the device represented by
|
|
- * @fd. If successful, then the result will be copied into
|
|
- * @out_identify.
|
|
+ * Sends the IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command to the
|
|
+ * device represented by @fd. If successful, then the result will be
|
|
+ * copied into @out_identify and @out_is_packet_device.
|
|
*
|
|
* This routine is based on code from libatasmart, Copyright 2008
|
|
* Lennart Poettering, LGPL v2.1.
|
|
*
|
|
- * Returns: 0 if the IDENTIFY data was successfully obtained,
|
|
- * otherwise non-zero with errno set.
|
|
+ * Returns: 0 if the data was successfully obtained, otherwise
|
|
+ * non-zero with errno set.
|
|
*/
|
|
static int disk_identify (struct udev *udev,
|
|
int fd,
|
|
- uint8_t out_identify[512])
|
|
+ uint8_t out_identify[512],
|
|
+ int *out_is_packet_device)
|
|
{
|
|
int ret;
|
|
uint8_t inquiry_buf[36];
|
|
int peripheral_device_type;
|
|
int all_nul_bytes;
|
|
int n;
|
|
+ int is_packet_device;
|
|
|
|
assert (out_identify != NULL);
|
|
+
|
|
/* init results */
|
|
ret = -1;
|
|
memset (out_identify, '\0', 512);
|
|
+ is_packet_device = 0;
|
|
|
|
/* If we were to use ATA PASS_THROUGH (12) on an ATAPI device
|
|
* we could accidentally blank media. This is because MMC's BLANK
|
|
@@ -309,6 +397,12 @@ static int disk_identify (struct udev *udev,
|
|
|
|
/* SPC-4, section 6.4.2: Standard INQUIRY data */
|
|
peripheral_device_type = inquiry_buf[0] & 0x1f;
|
|
+ if (peripheral_device_type == 0x05)
|
|
+ {
|
|
+ is_packet_device = 1;
|
|
+ ret = disk_identify_packet_device_command(fd, out_identify, 512);
|
|
+ goto check_nul_bytes;
|
|
+ }
|
|
if (peripheral_device_type != 0x00) {
|
|
ret = -1;
|
|
errno = EIO;
|
|
@@ -320,6 +414,7 @@ static int disk_identify (struct udev *udev,
|
|
if (ret != 0)
|
|
goto out;
|
|
|
|
+ check_nul_bytes:
|
|
/* Check if IDENTIFY data is all NUL bytes - if so, bail */
|
|
all_nul_bytes = 1;
|
|
for (n = 0; n < 512; n++) {
|
|
@@ -336,6 +431,8 @@ static int disk_identify (struct udev *udev,
|
|
}
|
|
|
|
out:
|
|
+ if (out_is_packet_device != NULL)
|
|
+ *out_is_packet_device = is_packet_device;
|
|
return ret;
|
|
}
|
|
|
|
@@ -350,7 +447,7 @@ int main(int argc, char *argv[])
|
|
{
|
|
struct udev *udev;
|
|
struct hd_driveid id;
|
|
- uint8_t identify[512];
|
|
+ uint8_t identify[512];
|
|
char model[41];
|
|
char model_enc[256];
|
|
char serial[21];
|
|
@@ -358,8 +455,9 @@ int main(int argc, char *argv[])
|
|
const char *node = NULL;
|
|
int export = 0;
|
|
int fd;
|
|
- uint16_t word;
|
|
+ uint16_t word;
|
|
int rc = 0;
|
|
+ int is_packet_device = 0;
|
|
static const struct option options[] = {
|
|
{ "export", no_argument, NULL, 'x' },
|
|
{ "help", no_argument, NULL, 'h' },
|
|
@@ -408,7 +506,7 @@ int main(int argc, char *argv[])
|
|
goto exit;
|
|
}
|
|
|
|
- if (disk_identify(udev, fd, identify) == 0) {
|
|
+ if (disk_identify(udev, fd, identify, &is_packet_device) == 0) {
|
|
/*
|
|
* fix up only the fields from the IDENTIFY data that we are going to
|
|
* use and copy it into the hd_driveid struct for convenience
|
|
@@ -416,7 +514,7 @@ int main(int argc, char *argv[])
|
|
disk_identify_fixup_string (identify, 10, 20); /* serial */
|
|
disk_identify_fixup_string (identify, 23, 6); /* fwrev */
|
|
disk_identify_fixup_string (identify, 27, 40); /* model */
|
|
- disk_identify_fixup_uint16 (identify, 0); /* configuration */
|
|
+ disk_identify_fixup_uint16 (identify, 0); /* configuration */
|
|
disk_identify_fixup_uint16 (identify, 75); /* queue depth */
|
|
disk_identify_fixup_uint16 (identify, 75); /* SATA capabilities */
|
|
disk_identify_fixup_uint16 (identify, 82); /* command set supported */
|
|
@@ -457,8 +555,8 @@ int main(int argc, char *argv[])
|
|
udev_util_replace_chars(revision, NULL);
|
|
|
|
if (export) {
|
|
- /* Set this to convey the disk speaks the ATA protocol */
|
|
- printf("ID_ATA=1\n");
|
|
+ /* Set this to convey the disk speaks the ATA protocol */
|
|
+ printf("ID_ATA=1\n");
|
|
|
|
if ((id.config >> 8) & 0x80) {
|
|
/* This is an ATAPI device */
|
|
diff --git a/rules/rules.d/60-persistent-storage.rules b/rules/rules.d/60-persistent-storage.rules
|
|
index d3f2f73..8baabc2 100644
|
|
--- a/rules/rules.d/60-persistent-storage.rules
|
|
+++ b/rules/rules.d/60-persistent-storage.rules
|
|
@@ -12,6 +12,8 @@ ACTION=="remove", GOTO="persistent_storage_end"
|
|
|
|
# run scsi_id and ata_id on the actual SCSI device
|
|
SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", ENV{ID_SERIAL}!="?*", ATTR{vendor}=="ATA", IMPORT{program}="ata_id --export $root/bsg/$kernel"
|
|
+# ATA/ATAPI devices is of type 0x05 and vendor is usually not ATA
|
|
+SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", ENV{ID_SERIAL}!="?*", ATTR{type}=="5", IMPORT{program}="ata_id --export $root/bsg/$kernel"
|
|
SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --whitelisted --export --device $root/bsg/$kernel"
|
|
|
|
# from this point on, only care about block devices
|
|
@@ -40,6 +42,8 @@ KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{program
|
|
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="ata", IMPORT{program}="ata_id --export $tempnode"
|
|
# ATA devices using the "scsi" subsystem
|
|
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $tempnode"
|
|
+# ATA/ATAPI devices using the "scsi" subsystem
|
|
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", IMPORT{program}="ata_id --export $tempnode"
|
|
# scsi devices
|
|
KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $tempnode", ENV{ID_BUS}="scsi"
|
|
KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="scsi_id --export --whitelisted -d $tempnode", ENV{ID_BUS}="cciss"
|
|
--
|
|
1.7.3.4
|
|
|