3 # provide the shortest possible unique hardware path to a device
4 # for the Linux Persistent Device Naming scheme
6 # Copyright (C) 2005-2006 SUSE Linux Products GmbH
8 # Hannes Reinecke <hare@suse.de>
10 # This program is free software; you can redistribute it and/or modify it
11 # under the terms of the GNU General Public License as published by the
12 # Free Software Foundation version 2 of the License.
19 full_sysfs_device_path=
21 if [ -z "$DEVPATH" -a -z "$1" ] ; then
25 if [ -z "$DEVPATH" ] ; then
36 if [ ! -e $SYSFS$DEVPATH/dev ] ; then
42 cd "$SYSFS$DEVPATH/subsystem";
48 TYPE="${DEVPATH#/class/}"
60 local type offset port
63 for i in $type[0-9]* ; do
66 if [ "$port" -lt "$offset" ] ; then offset=$port ; fi
78 # cciss devices don't have a separate sysfs node
79 for blk_link in block*; do
80 if [ -L "$blk_link" ]; then
83 d=cciss-${blk_link#*cciss\!}
88 while [ ! -z "$host_dev_path" ] ; do
89 case "$host_dev_path" in
91 host_dev_path=${host_dev_path%/*}
111 platform_id=${DEV##*/}
113 while [ ! -z "$host_dev_path" ] ; do
114 case "$host_dev_path" in
116 host_dev_path=${host_dev_path%/*}
124 d="platform-$platform_id-$d"
126 d="platform-$platform_id"
136 serio_id=${DEV##*/serio}
138 while [ ! -z "$host_dev_path" ] ; do
139 case "$host_dev_path" in
141 host_dev_path=${host_dev_path%/*}
149 d="serio-$serio_id-$d"
160 local port idedev idecontroller
165 idecontroller=${idedev%/*}
166 # port info if the controller has more than one interface
169 : idedev $idedev kernel_port $port
178 echo "Error: $idedev is neither master or slave" >&2
182 offset="`get_port_offset ide ${port%.*}`"
184 : port offset $offset
185 port=$((${port%.*} - $offset))
187 d="ide-${port}:$channel-$d"
189 d="ide-${port}:$channel"
198 local cil controller_port controller_dev
203 target_id=${target_dev##*/target}
206 for tid in ${target_id}* ; do
207 target_num=$(( $target_num + 1 ))
209 controller_port=${target_dev%/*}
210 controller_dev="${controller_port%/*}"
211 : controller_dev $controller_dev
212 : controller_port $controller_port
213 # a host controller may have more than one interface/port
214 controller_port="${controller_port##*/host}"
217 controller_offset=$(get_port_offset host $controller_port)
219 controller_port=$(( $controller_port - $controller_offset))
220 scsi_id="scsi-${controller_port}:${cil}"
233 if [ -f "$D/ieee1394_id" ] ; then
234 read ieee1394_id < $D/ieee1394_id
236 if [ -z "$ieee1394_id" ] ; then
241 fw_host_dev=${DEV%/fw-host*}
242 # IEEE1394 devices are always endpoints
243 d="ieee1394-0x$ieee1394_id"
251 local cil controller_port controller_dev
253 fc_tgt_hcil="${DEV##*/}"
254 fc_tgt_lun="${fc_tgt_hcil##*:}"
255 fc_tgt_path="${DEV%/*}"
256 fc_tgt_num="${fc_tgt_path##*/}"
257 fc_tgt_dev="${fc_tgt_path}/fc_transport/${fc_tgt_num}"
258 if [ -e "$fc_tgt_dev/port_name" ]; then
259 read wwpn < $fc_tgt_dev/port_name
261 if [ -z "$wwpn" ] ; then
267 # Linux currently knows about 32bit luns
268 tmp_lun3=$(printf "%04x" $(($fc_tgt_lun & 0xFFFF)))
269 tmp_lun2=$(printf "%04x" $(( ($fc_tgt_lun >> 16) & 0xFFFF)))
272 if (($fc_tgt_lun == 0)) ; then
273 lun="0x0000000000000000"
275 lun="0x${tmp_lun3}${tmp_lun2}${tmp_lun1}${tmp_lun0}"
277 controller_dev="${fc_tgt_path%/host[0-9]*}"
278 # FC devices are always endpoints
279 d="fc-${wwpn}:${lun}"
287 local cil adapter controller_dev
291 sas_end_path="${DEV%%/target*}"
292 sas_host_path="${sas_end_path%%/port*}"
293 sas_phy_path="${sas_end_path#*/host*/}"
294 sas_phy_path="${sas_phy_path%%/*}"
295 sas_phy_path="${sas_host_path}/${sas_phy_path}"
298 for phy in $sas_phy_path/phy-*/sas_phy/phy-* ; do
299 if [ -d "$phy" ] ; then
300 read phy_id < $phy/phy_identifier
301 if [ $phy_id -lt $sas_phy_id ]; then
307 if [ $sas_phy_id -eq 255 ] ; then
308 : no initiator address
314 sas_port_id="${sas_phy_path##*/port-}"
315 sas_port_dev="/sys/class/sas_port/port-${sas_port_id}"
316 if [ -e "$sas_port_dev/num_phys" ] ; then
317 read phy_port < $sas_port_dev/num_phys
320 sas_end_id="${sas_end_path##*end_device-}"
321 sas_end_dev="/sys/class/sas_device/end_device-${sas_end_id}"
322 if [ -e "$sas_end_dev/sas_address" ]; then
323 read end_address < $sas_end_dev/sas_address
324 read end_id < $sas_end_dev/phy_identifier
326 if [ -z "$end_address" ] ; then
327 : no end device address
332 sas_end_address="$end_address:$end_id"
333 controller_dev="${sas_host_path%/host[0-9]*}"
334 # SAS devices are always endpoints
335 d="sas-phy${sas_phy_id}:${phy_port}-${sas_end_address}-lun$lun"
342 local iscsi_session_dir
343 local iscsi_session iscsi_session_path
344 local iscsi_connection iscsi_connection_path
347 iscsi_session_dir="${DEV%%/target*}"
348 iscsi_session="${iscsi_session_dir##*/}"
349 iscsi_session_path=/sys/class/iscsi_session/${iscsi_session}
350 if [ ! -d "$iscsi_session_path" ] ; then
351 : no iSCSI session path
355 # Currently we're not doing MC/S
356 for conn in ${iscsi_session_dir}/connection* ; do
357 iscsi_conn_num=${conn##*:}
358 if [ "$iscsi_conn_num" = '0' ] ; then
359 iscsi_connection=$(basename $conn)
362 if [ -z "$iscsi_connection" ] ; then
363 : no iSCSI connection found
367 iscsi_connection_path=/sys/class/iscsi_connection/${iscsi_connection}
368 if [ ! -d "$iscsi_connection_path" ] ; then
369 : no iSCSI connection path
373 if [ -e "${iscsi_session_path}/targetname" ]; then
374 read iscsi_tgtname < ${iscsi_session_path}/targetname
376 if [ -z "$iscsi_tgtname" ] ; then
377 : No iSCSI Targetname
381 if [ -e "${iscsi_connection_path}/persistent_address" ] ; then
382 read iscsi_address < ${iscsi_connection_path}/persistent_address
384 if [ -z "$iscsi_address" ] ; then
385 : No iSCSI Target address
389 if [ -e "${iscsi_connection_path}/persistent_port" ] ; then
390 read iscsi_port < ${iscsi_connection_path}/persistent_port
392 iscsi_scsi_lun="${DEV##*:}"
393 d="ip-${iscsi_address}:${iscsi_port}-iscsi-${iscsi_tgtname}-lun-${iscsi_scsi_lun}"
403 port_num=${port_id#*-}
405 while [ ! -z "$host_dev_path" ] ; do
406 case "$host_dev_path" in
408 usb_host_path=$host_dev_path
409 host_dev_path="${host_dev_path%/*}"
416 : host_dev_path $host_dev_path
417 usb_host_num=${usb_host_path##*/usb}
420 usb_host_offset=$(get_port_offset usb $usb_host_num)
421 usb_host_port=$(($usb_host_num - $usb_host_offset))
424 d="usb-$usb_host_port:$port_num-${d}"
426 d="usb-$usb_host_port:$port_num"
433 full_sysfs_path="$SYSFS$DEVPATH"
436 full_sysfs_path="${full_sysfs_path%/*}"
437 # skip parent device of the same subsystem
438 if [ -L $full_sysfs_path/subsystem ]; then
439 cd "$full_sysfs_path/subsystem";
442 subsys="${subsys##*/}"
443 if [ "$subsys" = "$TYPE" ]; then
444 : skip same subsystem parent
445 full_sysfs_path="${full_sysfs_path%/*}"
448 # skip subsystem directory
449 subsys="${full_sysfs_path##*/}"
450 if [ "$subsys" = "$TYPE" ]; then
451 : skip subsystem directory
452 full_sysfs_path="${full_sysfs_path%/*}"
458 if [ ! -L $full_sysfs_path/device ]; then
459 full_sysfs_path="${full_sysfs_path%/*}"
460 : full_sysfs_path "$full_sysfs_path"
461 if [ ! -L $full_sysfs_path/device -o ! -f $full_sysfs_path/dev ]; then
465 if [ -L $full_sysfs_path/device/device ]; then
466 cd $full_sysfs_path/device/device
468 cd $full_sysfs_path/device
472 full_sysfs_device_path="`pwd -P`"
475 D=$full_sysfs_device_path
476 while [ ! -z "$D" ] ; do
478 */ide[0-9]/[0-9].[0-9]*|*/ide[0-9][0-9]/[0-9][0-9].[0-9]*)
482 if [ -r $full_sysfs_device_path/wwpn ]; then
483 read wwpn < $full_sysfs_device_path/wwpn
485 if [ -r $full_sysfs_device_path/fcp_lun ]; then
486 read lun < $full_sysfs_device_path/fcp_lun
488 if [ -r $full_sysfs_device_path/hba_id ]; then
489 read bus_id < $full_sysfs_device_path/hba_id
491 if [ "$bus_id" -a "$wwpn" -a "$lun" ]; then
493 d="ccw-$bus_id-zfcp-$wwpn:$lun"
504 */rport-[0-9]*:[0-9]*-[0-9]*/*)
507 */end_device-[0-9]*:[0-9]*:[0-9]*/*)
517 */host[0-9]*/[0-9]*:[0-9]*:[0-9]*:[0-9]*)
523 */usb[0-9]*/[0-9]*/*)
545 if [ "$TYPE" = "scsi_tape" ] ; then
546 devname=${full_sysfs_path##*/}
547 rewind="${devname%%st*}"
548 mode="${devname##*st}"
564 d="$d-${rewind}st${mode}"