From 14e2198646d92ef52a69d20269580a3fbe7c996b Mon Sep 17 00:00:00 2001
From: Stefan Richter <stefanr@s5r6.in-berlin.de>
Date: Sun, 27 May 2007 13:18:27 +0200
Subject: [PATCH] firewire: fw-sbp2: implement sysfs ieee1394_id
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

The attribute /sys/bus/scsi/devices/*:*:*:*/ieee1394_id, as generated by
the old sbp2 driver, is typically used to create persistently named
links in /dev/disk/by-id.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
---
 drivers/firewire/fw-device.h |  1 +
 drivers/firewire/fw-sbp2.c   | 53 ++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
index 0ba9d64ccf4c..af1723eae4ba 100644
--- a/drivers/firewire/fw-device.h
+++ b/drivers/firewire/fw-device.h
@@ -99,6 +99,7 @@ fw_unit(struct device *dev)
 #define CSR_DEPENDENT_INFO	0x14
 #define CSR_MODEL		0x17
 #define CSR_INSTANCE		0x18
+#define CSR_DIRECTORY_ID	0x20
 
 #define SBP2_COMMAND_SET_SPECIFIER	0x38
 #define SBP2_COMMAND_SET		0x39
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index 68300414e5f4..a98d3915e26f 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -1108,6 +1108,58 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd)
 	return SUCCESS;
 }
 
+/*
+ * Format of /sys/bus/scsi/devices/.../ieee1394_id:
+ * u64 EUI-64 : u24 directory_ID : u16 LUN  (all printed in hexadecimal)
+ *
+ * This is the concatenation of target port identifier and logical unit
+ * identifier as per SAM-2...SAM-4 annex A.
+ */
+static ssize_t
+sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct sbp2_device *sd;
+	struct fw_unit *unit;
+	struct fw_device *device;
+	u32 directory_id;
+	struct fw_csr_iterator ci;
+	int key, value, lun;
+
+	if (!sdev)
+		return 0;
+	sd = (struct sbp2_device *)sdev->host->hostdata;
+	unit = sd->unit;
+	device = fw_device(unit->device.parent);
+
+	/* implicit directory ID */
+	directory_id = ((unit->directory - device->config_rom) * 4
+			+ CSR_CONFIG_ROM) & 0xffffff;
+
+	/* explicit directory ID, overrides implicit ID if present */
+	fw_csr_iterator_init(&ci, unit->directory);
+	while (fw_csr_iterator_next(&ci, &key, &value))
+		if (key == CSR_DIRECTORY_ID) {
+			directory_id = value;
+			break;
+		}
+
+	/* FIXME: Make this work for multi-lun devices. */
+	lun = 0;
+
+	return sprintf(buf, "%08x%08x:%06x:%04x\n",
+			device->config_rom[3], device->config_rom[4],
+			directory_id, lun);
+}
+
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
+
+static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
+	&dev_attr_ieee1394_id,
+	NULL
+};
+
 static struct scsi_host_template scsi_driver_template = {
 	.module			= THIS_MODULE,
 	.name			= "SBP-2 IEEE-1394",
@@ -1121,6 +1173,7 @@ static struct scsi_host_template scsi_driver_template = {
 	.use_clustering		= ENABLE_CLUSTERING,
 	.cmd_per_lun		= 1,
 	.can_queue		= 1,
+	.sdev_attrs		= sbp2_scsi_sysfs_attrs,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
-- 
2.34.1