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"
137 while [ ! -z "$host_dev_path" ] ; do
138 case "$host_dev_path" in
140 host_dev_path=${host_dev_path%/*}
160 serio_id=${DEV##*/serio}
162 while [ ! -z "$host_dev_path" ] ; do
163 case "$host_dev_path" in
165 host_dev_path=${host_dev_path%/*}
173 d="serio-$serio_id-$d"
184 local port idedev idecontroller
189 idecontroller=${idedev%/*}
190 # port info if the controller has more than one interface
193 : idedev $idedev kernel_port $port
202 echo "Error: $idedev is neither master or slave" >&2
206 offset="`get_port_offset ide ${port%.*}`"
208 : port offset $offset
209 port=$((${port%.*} - $offset))
211 d="ide-${port}:$channel-$d"
213 d="ide-${port}:$channel"
222 local cil controller_port controller_dev
227 target_id=${target_dev##*/target}
230 for tid in ${target_id}* ; do
231 target_num=$(( $target_num + 1 ))
233 controller_port=${target_dev%/*}
234 controller_dev="${controller_port%/*}"
235 : controller_dev $controller_dev
236 : controller_port $controller_port
237 # a host controller may have more than one interface/port
238 controller_port="${controller_port##*/host}"
241 controller_offset=$(get_port_offset host $controller_port)
243 controller_port=$(( $controller_port - $controller_offset))
244 scsi_id="scsi-${controller_port}:${cil}"
257 if [ -f "$D/ieee1394_id" ] ; then
258 read ieee1394_id < $D/ieee1394_id
260 if [ -z "$ieee1394_id" ] ; then
265 fw_host_dev=${DEV%/fw-host*}
266 # IEEE1394 devices are always endpoints
267 d="ieee1394-0x$ieee1394_id"
275 local cil controller_port controller_dev
277 fc_tgt_hcil="${DEV##*/}"
278 fc_tgt_lun="${fc_tgt_hcil##*:}"
279 fc_tgt_path="${DEV%/*}"
280 fc_tgt_num="${fc_tgt_path##*/}"
281 fc_tgt_dev="${fc_tgt_path}/fc_transport/${fc_tgt_num}"
282 if [ -e "$fc_tgt_dev/port_name" ]; then
283 read wwpn < $fc_tgt_dev/port_name
285 if [ -z "$wwpn" ] ; then
291 # Linux currently knows about 32bit luns
292 tmp_lun3=$(printf "%04x" $(($fc_tgt_lun & 0xFFFF)))
293 tmp_lun2=$(printf "%04x" $(( ($fc_tgt_lun >> 16) & 0xFFFF)))
296 if (($fc_tgt_lun == 0)) ; then
297 lun="0x0000000000000000"
299 lun="0x${tmp_lun3}${tmp_lun2}${tmp_lun1}${tmp_lun0}"
301 controller_dev="${fc_tgt_path%/host[0-9]*}"
302 # FC devices are always endpoints
303 d="fc-${wwpn}:${lun}"
311 local cil adapter controller_dev
315 sas_end_path="${DEV%%/target*}"
316 sas_host_path="${sas_end_path%%/port*}"
317 sas_phy_path="${sas_end_path#*/host*/}"
318 sas_phy_path="${sas_phy_path%%/*}"
319 sas_phy_path="${sas_host_path}/${sas_phy_path}"
322 for phy in $sas_phy_path/phy-*/sas_phy/phy-* ; do
323 if [ -d "$phy" ] ; then
324 read phy_id < $phy/phy_identifier
325 if [ $phy_id -lt $sas_phy_id ]; then
331 if [ $sas_phy_id -eq 255 ] ; then
332 : no initiator address
338 sas_port_id="${sas_phy_path##*/port-}"
339 sas_port_dev="/sys/class/sas_port/port-${sas_port_id}"
340 if [ -e "$sas_port_dev/num_phys" ] ; then
341 read phy_port < $sas_port_dev/num_phys
344 sas_end_id="${sas_end_path##*end_device-}"
345 sas_end_dev="/sys/class/sas_device/end_device-${sas_end_id}"
346 if [ -e "$sas_end_dev/sas_address" ]; then
347 read end_address < $sas_end_dev/sas_address
348 read end_id < $sas_end_dev/phy_identifier
350 if [ -z "$end_address" ] ; then
351 : no end device address
356 sas_end_address="$end_address:$end_id"
357 controller_dev="${sas_host_path%/host[0-9]*}"
358 # SAS devices are always endpoints
359 d="sas-phy${sas_phy_id}:${phy_port}-${sas_end_address}-lun$lun"
366 local iscsi_session_dir
367 local iscsi_session iscsi_session_path
368 local iscsi_connection iscsi_connection_path
371 iscsi_session_dir="${DEV%%/target*}"
372 iscsi_session="${iscsi_session_dir##*/}"
373 iscsi_session_path=/sys/class/iscsi_session/${iscsi_session}
374 if [ ! -d "$iscsi_session_path" ] ; then
375 : no iSCSI session path
379 # Currently we're not doing MC/S
380 for conn in ${iscsi_session_dir}/connection* ; do
381 iscsi_conn_num=${conn##*:}
382 if [ "$iscsi_conn_num" = '0' ] ; then
383 iscsi_connection=$(basename $conn)
386 if [ -z "$iscsi_connection" ] ; then
387 : no iSCSI connection found
391 iscsi_connection_path=/sys/class/iscsi_connection/${iscsi_connection}
392 if [ ! -d "$iscsi_connection_path" ] ; then
393 : no iSCSI connection path
397 if [ -e "${iscsi_session_path}/targetname" ]; then
398 read iscsi_tgtname < ${iscsi_session_path}/targetname
400 if [ -z "$iscsi_tgtname" ] ; then
401 : No iSCSI Targetname
405 if [ -e "${iscsi_connection_path}/persistent_address" ] ; then
406 read iscsi_address < ${iscsi_connection_path}/persistent_address
408 if [ -z "$iscsi_address" ] ; then
409 : No iSCSI Target address
413 if [ -e "${iscsi_connection_path}/persistent_port" ] ; then
414 read iscsi_port < ${iscsi_connection_path}/persistent_port
416 iscsi_scsi_lun="${DEV##*:}"
417 d="ip-${iscsi_address}:${iscsi_port}-iscsi-${iscsi_tgtname}-lun-${iscsi_scsi_lun}"
427 port_num=${port_id#*-}
429 while [ ! -z "$host_dev_path" ] ; do
430 case "$host_dev_path" in
432 usb_host_path=$host_dev_path
433 host_dev_path="${host_dev_path%/*}"
440 : host_dev_path $host_dev_path
441 usb_host_num=${usb_host_path##*/usb}
444 usb_host_offset=$(get_port_offset usb $usb_host_num)
445 usb_host_port=$(($usb_host_num - $usb_host_offset))
448 d="usb-$usb_host_port:$port_num-${d}"
450 d="usb-$usb_host_port:$port_num"
457 full_sysfs_path="$SYSFS$DEVPATH"
460 full_sysfs_path="${full_sysfs_path%/*}"
461 # skip parent device of the same subsystem
462 if [ -L $full_sysfs_path/subsystem ]; then
463 cd "$full_sysfs_path/subsystem";
466 subsys="${subsys##*/}"
467 if [ "$subsys" = "$TYPE" ]; then
468 : skip same subsystem parent
469 full_sysfs_path="${full_sysfs_path%/*}"
472 # skip subsystem directory
473 subsys="${full_sysfs_path##*/}"
474 if [ "$subsys" = "$TYPE" ]; then
475 : skip subsystem directory
476 full_sysfs_path="${full_sysfs_path%/*}"
482 if [ ! -L $full_sysfs_path/device ]; then
483 full_sysfs_path="${full_sysfs_path%/*}"
484 : full_sysfs_path "$full_sysfs_path"
485 if [ ! -L $full_sysfs_path/device -o ! -f $full_sysfs_path/dev ]; then
489 if [ -L $full_sysfs_path/device/device ]; then
490 cd $full_sysfs_path/device/device
492 cd $full_sysfs_path/device
496 full_sysfs_device_path="`pwd -P`"
499 D=$full_sysfs_device_path
500 while [ ! -z "$D" ] ; do
502 */ide[0-9]/[0-9].[0-9]*|*/ide[0-9][0-9]/[0-9][0-9].[0-9]*)
506 if [ -r $full_sysfs_device_path/wwpn ]; then
507 read wwpn < $full_sysfs_device_path/wwpn
509 if [ -r $full_sysfs_device_path/fcp_lun ]; then
510 read lun < $full_sysfs_device_path/fcp_lun
512 if [ -r $full_sysfs_device_path/hba_id ]; then
513 read bus_id < $full_sysfs_device_path/hba_id
515 if [ "$bus_id" -a "$wwpn" -a "$lun" ]; then
517 d="ccw-$bus_id-zfcp-$wwpn:$lun"
528 */rport-[0-9]*:[0-9]*-[0-9]*/*)
531 */end_device-[0-9]*:[0-9]*:[0-9]*/*)
541 */host[0-9]*/[0-9]*:[0-9]*:[0-9]*:[0-9]*)
547 */usb[0-9]*/[0-9]*/*)
572 if [ "$TYPE" = "scsi_tape" ] ; then
573 devname=${full_sysfs_path##*/}
574 rewind="${devname%%st*}"
575 mode="${devname##*st}"
591 d="$d-${rewind}st${mode}"