#!/bin/sh VERSION="0.2.002" MYNAME="ultrabayd" # # This script should be rewritten in C and should be changed # so that it will unregister the secondary IDE interface # either (1) as soon as the IDE device is removed and not # after a polling delay and/or (2) before a suspend during # which the device might be removed; this, so that attempts # to access the still-registered-but-removed secondary IDE # device will not produce errors. # # Some users have experienced filesystem corruption as a # result of using this script in its present form. # # Version 0.2.002 by Thomas Hood # Version 0.2.001 by Thomas Hood # -- No longer unregister IDE interface # Version 0.2.000 by Thomas Hood # -- No longer use idectl script # -- Make smarter and safer # Version 0.1.000 by Christian Lademann # # # This script polls the UltraBay status (using tpctl) and calls # hdparm to reregister the secondary IDE interface when a change # is detected. # # hdparm version 3.8 or later is required. The latest hdparm sources # are available at http://metalab.unc.edu/pub/Linux/system/hardware . # A RedHat RPM is available for version 3.9 : check RedHat's Rawhide # RPM archive. # # RedHat Linux releases 6.1 and 6.2 contain hdparm-3.6-*.*.rpm . # Debian GNU/Linux releases slink and potato contain hdparm_3.6-1.deb . # These aren't new enough. # # The UltraBay battery for the ThinkPad 600E should *not* be hot # swapped but should be warm swapped--i.e., the machine should be # suspended first. # TPCTL="/usr/local/bin/tpctl" HDPARM="/sbin/hdparm" UMOUNT="/bin/umount" LOGGER="/usr/bin/logger" CAT="/bin/cat" AWK="/bin/awk" CDROM_MOUNTPOINT='/mnt/cdrom' INTERVAL=5 typeset -i dev_type=0xffff typeset -i old_dev_type=0xffff typeset -i dev_id=0xffff typeset -i old_dev_id=0xffff get_channel() { channel=`$CAT /proc/ioports | $AWK '/^0170/ {print $3}' | tr -d 'ide'` } # # Sets dev_type, dev_type_n, dev_id and dev_id_n # get_ultrabay_info() { dev_type=$((0xffff)) dev_type_n="" dev_id=$((0xffff)) dev_id_n="" while read w1 w2 w3 wn; do case "$w1" in device ) case "$w2" in type: ) dev_type=$((w3)); dev_type_n="$wn";; ID: ) dev_id=$((w3)); dev_id_n="$wn";; esac ;; esac if [ $dev_type -ne $((0xffff)) ] && [ $dev_id -ne $((0xffff)) ]; then break; fi done <<- END `eval $TPCTL --iU` END } ### Check hdparm version ### read HDPARM_VER_MAJ HDPARM_VER_MIN crud <<- END `$HDPARM -V | tr 'v.' ' ' | awk ' {print $2 " " $3}'` END if [ $[$HDPARM_VER_MAJ] -lt 3 -o $[$HDPARM_VER_MIN] -lt 8 ]; then echo "$MYNAME: Requires hdparm version 3.8 or greater. Exiting." exit 1 fi ### onward ho ### case "$1" in -V ) echo "$MYNAME: Version $VERSION" exit 0 ;; -daemon ) get_ultrabay_info get_channel if [ -n "$channel" -a $dev_type -ne $((0x10)) ]; then $LOGGER "$MYNAME: I'm confused. The ioports belonging to the secondary IDE interface appear in /proc/ioports as having been registered on channel ${channel}; however the device in the UltraBay of type $dev_type does not appear to be an IDE device. Exiting." exit 1 fi case "$channel" in "" ) $LOGGER "$MYNAME: Watching UltraBay device ID $dev_id $dev_id_n." ;; 1 | 2 | 3 ) $LOGGER "$MYNAME: Watching UltraBay device ID $dev_id $dev_id_n which is already registered on IDE channel $channel." ;; * ) esac ### Don't perceive a change on startup ### old_dev_type=$dev_type old_dev_id=$dev_id while true; do # Main loop get_ultrabay_info if [ $dev_type -ne $old_dev_type ] || [ $dev_id -ne $old_dev_id ]; then # The device in the UltraBay appears to have changed old_channel="$channel" sleep 5 # Wait this long before doing anything $LOGGER "$MYNAME: Detected insertion of device of type $dev_type $dev_type_n and ID $dev_id $dev_id_n." ### Un-configure the old UltraBay device ### case $old_dev_type in $((0x00)) ) # floppy drive sync $UMOUNT /dev/floppy if [ $? ]; then $LOGGER "$MYNAME: Error returned trying to unmount floppy." else $LOGGER "$MYNAME: Successfully unmounted floppy." fi ;; $((0x01)) ) # serial device ;; $((0x02)) ) # TV tuner ;; $((0x10)) ) # IDE device ### Unmount any drives on the secondary IDE interface ### case "$old_channel" in "" ) # Wasn't registered device="" ;; 0 ) $LOGGER "$MYNAME: Yikes! We don't want to unregister ide0! Something's awry. Exiting." device="" exit 1 ;; 1 ) device="/dev/hdc" ;; 2 ) device="/dev/hde" ;; 3 ) device="/dev/hdg" ;; * ) $LOGGER "$MYNAME: Unrecognized IDE channel number: $channel. Skipping umount and exiting." device="" exit 1 ;; esac if [ -n "$device" ]; then sync $UMOUNT $device if [ $? ]; then $LOGGER "$MYNAME: Error returned trying to unmount $device ." else $LOGGER "$MYNAME: Successfully unmounted $device ." fi fi ### Unregister the secondary IDE interface ### if [ -n "$old_channel" ]; then sync $HDPARM -U $old_channel /dev/hda sync get_channel if [ -z "$channel" ]; then $LOGGER "$MYNAME: Secondary IDE interface on channel $old_channel unregistered." else sleep 2 if [ -z "$channel" ]; then $LOGGER "$MYNAME: Secondary IDE interface on channel $old_channel unregistered." else $LOGGER "$MYNAME: Secondary IDE interface registered on channel $old_channel could not be unregistered: it still appears to be registered on channel $channel." fi fi fi if [ $old_dev_id -eq $((0x10)) ]; then ### Remove link for CD-ROM device ### if [ -L /dev/cdrom ]; then rm -f /dev/cdrom fi fi ;; $((0x20)) ) # PCMCIA adapter ;; $((0x30)) ) # battery ;; $((0x40)) ) # AC adapter ;; * ) ;; esac old_dev_type=$dev_type old_dev_id=$dev_id ### Configure the new UltraBay device ### case $dev_type in $((0x00)) ) # floppy drive ;; $((0x01)) ) # serial device ;; $((0x02)) ) # TV tuner ;; $((0x10)) ) # IDE device ### register the secondary IDE interface ### sync $HDPARM -R 0x170 0 0 /dev/hda sync get_channel if [ -n "$channel" ]; then $LOGGER "$MYNAME: Secondary IDE interface registered on channel $channel." else $LOGGER "$MYNAME: Secondary IDE interface registration appears to have failed. Exiting." exit 1 fi ### Set up drive on the secondary IDE interface ### case $dev_id in $((0x10)) ) # CD-ROM drive ### link /dev/cdrom to the correct device ### case $channel in 1 ) object="/dev/hdc" ;; 2 ) object="/dev/hde" ;; 3 ) object="/dev/hdg" ;; * ) $LOGGER "$MYNAME: Yipes! CD-ROM was registered on channel ${channel}! Exiting." exit 1 ;; esac if [ "`readlink /dev/cdrom`" != "$object" ]; then sync rm -f /dev/cdrom ln -s $object /dev/cdrom $LOGGER "$MYNAME: Linked $object as /dev/cdrom ." fi ;; $((0x11)) ) # IDE hard disk drive ;; $((0x12)) ) # DVD drive ;; $((0x13)) ) # ZIP drive ;; * ) ;; esac ;; $((0x20)) ) # PCMCIA adapter ;; $((0x30)) ) # battery ;; $((0x40)) ) # AC adapter ;; * ) ;; esac fi sleep $INTERVAL done ;; * ) exec nohup $0 -daemon 2>&1 > /dev/null & ;; esac exit 0