Difference between revisions of "How to hotswap Ultrabay devices"

From ThinkWiki
Jump to: navigation, search
(Choosing the right driver: new style ata_piix vs old style piix/ide-disk)
(Remove hdparm -Y from eject script (see discussion for rationale))
 
(107 intermediate revisions by 17 users not shown)
Line 1: Line 1:
 
The following discusses hotswap (AKA "hotplug") of devices in the [[Ultrabay]].
 
The following discusses hotswap (AKA "hotplug") of devices in the [[Ultrabay]].
  
==Which driver?==
+
This page has a lot of old information.  Some cleanup might be useful.
Since this may be confusing for SATA thinkpad owners, which are likely all the same for now, you have two busses and drivers: one SATA bus which works with the AHCI driver and one IDE bus for the ultrabay for which you should pick <tt>ata_piix</tt> ('''not''' piix/CONFIG_BLK_DEV_PIIX). See below for hotswapping.
 
  
Debian users: at least up the the kernel released with Lenny, Debian applies a patch in the Debian kernel sources which prevents the use of <tt>ata_piix</tt> with PATA devices (like the IDE bus for the ultrabay). You will have to either use an upstream kernel or (re)patch the Debian kernel sources.
 
You may want to have a look at the following Debian bug reports as well: [http://bugs.debian.org/444182 #444182], [http://bugs.debian.org/463833 #463833].
 
  
==Choosing the right driver: new style <tt>ata_piix</tt> vs old style <tt>piix/ide-disk</tt>==
 
For ICH5,6,7,8, systems, whether you have an older IDE only thinkpad, or a newer thinkpad like the T/Z61p, there is one SATA bus for the system hard drive and an IDE bus for the Ultrabay (even if your Ultrabay happens to have a SATA drive, as it'll be seen as an IDE device), you'll have two drivers to chose from for your ultrabay: the old IDE/<tt>piix+ide-disk</tt> driver, and the newer PATA (=IDE) support of the newer <tt>ata_piix</tt> driver.<BR>
 
<tt>piix+ide-disk</tt> are part of the old original IDE driver and your ultrabay device will show up as <tt>/dev/hda</tt>.<BR><tt>ata-piix</tt> is the new SATA/PATA (=IDE) driver that will cause your ultrabay Hard Drive to show up as <tt>/dev/sda</tt> and your CD-Rom as <tt>/dev/sr0</tt>
 
  
The two things to know are: 1) you want to use ata_piix and 2) if you build piix in (CONFIG_BLK_DEV_PIIX enabled), or load it as a module, it'll take over the IDE bus and prevent ATA_PIIX from seeing your ultrabay. You don't want that.
+
==Which driver?==
 +
This may be confusing, so first a quick history lesson.
  
The longer details are:<BR>
+
Older ThinkPads (up to the R51, T42p and X40) were fully IDE (PATA) for both the internal HDD and Ultrabay. For these there are two drivers, the modern libata based {{path|ata_piix}} and the old legacy {{path|piix}}/{{path|ide-disk}} combo. Most modern distributions will default to the {{path|ata_piix}} driver, which is really what you want anyway.
You don't want the piix+ide-disk combo because even as modules, you will not be able to unload piix to reset the bus if there are issues swapping devices (with ata_piix, even if you forget to unregister a drive before removing it, you can unload the module and reload it to reset the bus after the fact if you have a newer thinkpad with a separate AHCI/SATA bus for the boot drive).
 
  
As for hotswap, with piix+ide-disk, you can read the section below, but after more than one day of trying on 2.6.22.15 (as piix+ide-disk was taking over my IDE bus, and stopping me from using ata_piix before I removed it), I was not able to get hotswapping to work with piix+ide-disk (lt_hotswap would not even build on 2.6.22.15).
+
ThinkPads like the R52, T43, T43p, X41 and X41 Tablet are strange hybrids. They have a Serial-ATA (SATA) chipset for the internal disk controller, but the actual disk is still legacy IDE, using a separate SATA-PATA bridge chip. The Ultrabay, though, is still connected to the legacy IDE host controller. This results in a setup where the internal disk is handled by a SATA driver and the Ultrabay is handled by either {{path|ata_piix}} or {{path|piix}}/{{path|ide-disk}}.
  
hotswap just works with ata_pixx on 2.6.22, and reportedly with anything newer than 2.6.18, so you want to get rid of piix+ide-disk.
+
ThinkPads like the R60, T60 and Z60 series are also hybrids, but they use a native SATA HDD internal. Ultrabay still uses legacy IDE (PATA) though. So just like with the previous models you end up with two separate drivers for the internal HDD and the Ultrabay.
There are several ways to do that:
 
* if piix is built in your kernel (CONFIG_BLK_DEV_PIIX):
 
** rebuild your kernel with CONFIG_BLK_DEV_PIIX turned off.
 
** if you don't want to rebuild your kernel, try disabling the IDE bus grabbing by that driver with <tt>ide0=noprobe hda=noprobe hdb=noprobe</tt> in your grub/lilo config (adjust the drive letters as appropriate, but note that this did not work for me on 2.6.22.15: the drive didn't show up on the piix bus, but it didn't show up on the ata_piix bus either).
 
* if piix is built in as a module
 
** you can move out the module in {{path|/lib/modules/ver/kernel/drivers/ide/pci/piix.ko}} and reboot.
 
** or build a new kernel, again with CONFIG_BLK_DEV_PIIX turned off.
 
** or add <tt>options ide_core options="ide0=noprobe hda=noprobe hdb=noprobe"</tt> to your modprobe.conf is supposed to work too (but didn't work on 2.6.22.15, see comment above)
 
  
Then, continue this document to see how to do hotswap with ata_piix (if you are lucky enough to have a newer SATA thinkpad where the ata_piix driver only runs the ultrabay, and you have a separate bus and ahci driver for your main drive, it is recommended to have ata_piix as a module (<tt>CONFIG_ATA_PIIX=m</tt>) so that you can unload/reload it if your bus gets in a bad state after a failed hotswap)
+
The latest generation ThinkPads like the R400, R500, T400, T500, W500, W700, X200, and X301 are all fully SATA for both the internal HDD and the Ultrabay device, so both are handled by the same SATA driver.
 +
{{Todo|Figure out in which category the X60 series ThinkPads truly belong. Some of these machines might have been shipped with a 1.8" HDD which is likely to be PATA, in fact the HMM even states so. But tabook and ltwbook only lists SATA models, so the 1.8" model might never have shipped. But even if it did there will be a SATA-PATA bridge chip, so from the OS it will look like SATA.}}
  
==When using the <tt>ata_piix</tt> driver==
+
{| border="1" cellspacing="0" cellpadding="2"
The following applies when using the <tt>ata_piix</tt> driver, which is necessary for many recent ThinkPad models that use an [[Intel ICH6-M]] controller. See also [[Problems with SATA and Linux]].  
+
|+Overview of disk interface types
 +
! Thinkpad !! internal HDD !! Ultrabay !! Modern Driver !! Old Driver
 +
|-
 +
| {{A20m}}, {{A20p}}, {{A21e}}, {{A21m}}, {{A21p}}, {{A22e}}, {{A22m}}, {{A22p}}, {{A30}}, {{A30p}}, {{A31}}, {{A31p}} || Legacy 2.5" IDE (PATA) || Legacy IDE (PATA) || ata_piix || piix + ide-disk
 +
|-
 +
| {{R30}}, {{R31}}, {{R32}}, {{R40}}, {{R50}}, {{R50e}}, {{R50p}}, {{R51}} || Legacy 2.5" IDE (PATA) || Legacy IDE (PATA) || ata_piix || piix + ide-disk
 +
|-
 +
| {{R52}} || Legacy 2.5" PATA HDD with conversion to SATA || Legacy IDE (PATA) || ahci + ata_piix || -
 +
|-
 +
| {{R60}}, {{R61}} || 2.5" SATA || Legacy IDE (PATA)  || ahci + ata_piix || -
 +
|-
 +
| {{R400}}, {{R500}} ||2.5" SATA || SATA || ahci || -
 +
|-
 +
| {{T20}}, {{T21}}, {{T22}}, {{T23}}, {{T30}}, {{T40}}, {{T40p}}, {{T41}}, {{T41p}}, {{T42}}, {{T42p}} || Legacy 2.5" IDE (PATA) || Legacy IDE (PATA) || ata_piix || piix + ide-disk
 +
|-
 +
| {{T43}}, {{T43p}} || Legacy 2.5" PATA HDD with conversion to SATA || Legacy IDE (PATA) || ahci + ata_piix || -
 +
|-
 +
| {{T60}}, {{T60p}}, {{T61}}, {{T61p}} || 2.5" SATA || Legacy IDE (PATA)  || ahci + ata_piix || -
 +
|-
 +
| {{T400}}, {{T500}} ||2.5" SATA || SATA || ahci || -
 +
|-
 +
| {{X20}}, {{X21}}, {{X22}}, {{X23}}, {{X24}}, {{X30}}, {{X31}}, {{X32}} || Legacy 2.5" IDE (PATA) || Legacy IDE (PATA) || ata_piix || piix + ide-disk
 +
|-
 +
| {{X40}} || Legacy 1.8" IDE (PATA) || Legacy IDE (PATA) || ata_piix || piix + ide-disk
 +
|-
 +
| {{X41}}, {{X41t}} || Legacy 1.8" PATA HDD with conversion to SATA || Legacy IDE (PATA) || ahci + ata_piix || -
 +
|-
 +
| {{X60}}, {{X60s}}, {{x60t}}, {{x61}}, {{x61s}}, {{x61t}} || 2.5" HDD is SATA, 1.8" HDD is PATA with SATA conversion || Legacy IDE (PATA) || ahci + ata_piix || -
 +
|-
 +
| {{X300}} ||2.5" SATA || Legacy IDE (PATA) || ahci + ata_piix || -
 +
|-
 +
| {{X200}}, {{X200 Tablet}}, {{X301}} ||2.5" SATA || SATA || ahci || -
 +
|-
 +
| {{W500}}, {{W700}} ||2.5" SATA || SATA || ahci || -
 +
|-
 +
| {{Z60m}}, {{Z60t}}, {{Z61e}}, {{Z61m}}, {{Z61p}}, {{Z61t}} || 2.5" SATA || Legacy IDE (PATA) || ahci + ata_piix || -
 +
|-
 +
|}
  
Mainline kernels before 2.6.18 cannot reliably recognize newly (re-)inserted UltraBay drives without a reboot. There are experimental hotplug patches against pre-2.6.18 mainline kernels [http://home-tj.org/wiki/index.php/Libata-tj-stable here].
+
{{NOTE|Debian users: at least up the the kernel released with Lenny, Debian applies a patch in the Debian kernel sources which prevents the use of <tt>ata_piix</tt> with PATA devices (like the IDE bus for the Ultrabay). You will have to either use an upstream kernel or (re)patch the Debian kernel sources.
 +
You may want to have a look at the following Debian bug reports as well: [http://bugs.debian.org/444182 #444182], [http://bugs.debian.org/463833 #463833].}}
  
* Available hotplug patches
+
==Modern systems (using the <tt>ahci</tt> or <tt>ata_piix</tt> drivers)==
**[http://home-tj.org/files/libata-tj-stable/libata-tj-2.6.16.16-20060512.tar.bz2 Patch tarball against 2.6.16.16] ([http://lwn.net/Articles/183407/ Announce])
+
The following applies when using the <tt>ahci</tt> or <tt>ata_piix</tt> driver (which supercedes the old <tt>ide_disk</tt> driver).
**[http://home-tj.org/files/libata-tj-stable/libata-tj-2.6.17-20060625-1.tar.bz2 Patch tarball against 2.6.17/2.6.17.1] ([http://article.gmane.org/gmane.linux.ide/11598 Announce])
 
**[http://home-tj.org/files/libata-tj-stable/libata-tj-2.6.17.4-20060710.tar.bz2 Patch tarball against 2.6.17.4]
 
**[http://whoopie.gmxhome.de/linux/patches/2.6.17.14-tj/00-libata-tj-2.6.17.4-20060710.patch Patch against 2.6.17.14]
 
  
* Confirmed to work on the following laptops, with bus the following ID
+
You should at least be using a distribution with kernel 2.6.23. If you have a distribution with an older kernel, please update your distribution, as in addition to a newer kernel, you will need some of the newer userland tools.
**ThinkPad {{T23}}
 
**ThinkPad {{T30}}
 
**ThinkPad {{T43}}, {{T43p}}
 
**ThinkPad {{R52}}
 
**ThinkPad {{T60}} ID=4
 
**ThinkPad {{T61}} ID=0
 
**ThinkPad {{Z61p}} ID=4 (0-3:ahci, 5-6: ata_piix)
 
ID will typically be 1 if you only have an IDE bus (0 is boot drive, 1 is ultrabay), and it'll be 4 if you have a SATA bus your system boots from (ID 0-3) and an IDE bus for your ultrabay (ID 4-5).<BR>
 
<b>Note that even on a given laptop model the ID can vary depending on whether your kernel has drivers that configure your boot drive is using the old style IDE driver (which doesn't add IDs before your ultrabay), or whether your boot drive is using the new style driver (which  adds IDs before your ultrabay)</b>
 
  
Hotplug just works with kernels newer than 2.6.18 ( or older kernels that were patched to support <tt>ata_piix</tt> hotplug (don't try it otherwise!))<BR>
+
===Using libata-acpi and udev===
First, it is recommended you find the right SCSI ID for your drive to hotswap and unregister it before removing it (this works with all recent mainline kernels):
 
{{cmdroot|echo 1 > /sys/class/scsi_device/$ID:0:0:0/device/delete}}
 
{{cmdroot|echo eject >  /proc/acpi/ibm/bay}}
 
The drive can now be ejected (without this, your IDE bus may complain if you just yank a drive, but you can usually recover by unloading/reloading the ata_piix module on a SATA laptop if your main drive is not on the ata_piix bus)
 
  
You can then issue the following after inserting an UltraBay drive to rescan the port:
+
Starting from kernel 2.6.26-rc5, it's possible to use <tt>libata-acpi</tt> in combination with udev to hotswap. Please check if CONFIG_ATA_ACPI is enabled in your kernel configuration.
{{cmdroot|echo 0 0 0 >  /sys/class/scsi_host/host$ID/scan}}
 
The inserted drive should now be recognized by the kernel, and appropriate {{path|/dev/*}} entries created automatically (e.g., by <tt>udev</tt>).
 
  
Ted T'so has also written this hotswap patch, which may or may not be needed for you, see [http://www.mail-archive.com/linux-acpi@vger.kernel.org/msg04716.html hotswap patch] and report back
+
For 2.6.25, you need two patches which can be easily backported ([http://article.gmane.org/gmane.linux.acpi.devel/31159],[http://article.gmane.org/gmane.linux.acpi.devel/31369]).
  
===Scripts for hotswapping===
+
Create a file {{path|/etc/udev/rules.d/50-thinkpad-ultrabay.rules}} with the following contents:
 +
<pre>
 +
ENV{BAY_EVENT}=="3", ACTION=="change", SUBSYSTEM=="scsi", RUN+="/usr/local/sbin/ultrabay_eject"
 +
</pre>
 +
Then ensure it has the right permissions
 +
chown root:root /etc/udev/rules.d/50-thinkpad-ultrabay.rules
 +
chmod 644 /etc/udev/rules.d/50-thinkpad-ultrabay.rules
 +
For Red Hat/Fedora and other systems with selinux, you also need to set the security context:
 +
chcon system_u:object_r:etc_runtime_t:s0 /etc/udev/rules.d/50-thinkpad-ultrabay.rules
  
The following scripts and [[acpid]] daemon configuration files do the following:
+
Now create the below ultrabay-eject script
* Automatically unmounts the relevant filesystems and power off the UltraBay when the UltraBay eject lever is released. Screams if some filesystem can't be unmounted.
 
* Rescans the UltraBay port when then UltraBay eject lever is pushed back in.
 
  
They assumes you're using the <tt>ata_piix</tt> driver with an appropriate kernel (see above).
+
===Script for Ultrabay eject===
  
Create {{path|/usr/local/sbin/ultrabay_insert}} with permissions 755:
+
The following script does the following:
<pre>
+
* Automatically unmounts the relevant filesystems and power off the Ultrabay when the Ultrabay eject lever is released. Screams if some filesystem can't be unmounted.
#!/bin/bash
 
echo 12 > /proc/acpi/ibm/beep
 
sync
 
echo 0 0 0 > /sys/class/scsi_host/host1/scan
 
</pre>
 
  
Create {{path|/usr/local/sbin/ultrabay_eject}} with permissions 755:
+
Create a executable file {{path|/usr/local/sbin/ultrabay_eject}} with the following content. Note if you want to be able to run it directly (not by the UDEV eject script), then you need to manually edit the DEVPATH variable near the top of the script.
 
<pre>
 
<pre>
 
#!/bin/bash
 
#!/bin/bash
ULTRABAY_SYSDIR='/sys/class/scsi_device/1:0:0:0/device'
 
shopt -s nullglob
 
 
# Umount the filesystem(s) backed by the given major:minor device(s)
 
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
 
for $major_minor (@ARGV) {
 
$major_minor =~ m/^(\d+):(\d+)$/ or die;
 
push(@tgt_rdevs, ($1<<8)|$2);
 
}
 
        # Sort by reverse length of mount point, to unmount sub-directories first
 
        open MOUNTS,"</proc/mounts" or die "$!";
 
        @mounts=sort { length($b->[1]) <=> length($a->[1]) } map { [ split ] } <MOUNTS>;
 
        close MOUNTS;
 
        foreach $m (@mounts) {
 
                ($dev,$dir)=@$m;
 
next unless -b $dev;  $rdev=(stat($dev))[6];
 
next unless grep($_==$rdev, @tgt_rdevs);
 
system("umount","-v","$dir")==0  or  $bad=1;
 
}
 
exit 1 if $bad;
 
EOPERL
 
}
 
  
# Get the UltraBay's /dev/foo block device node
+
# Change the following DEVPATH= to match your system, if you want to run this directly instead of having it called by the udev eject script
ultrabay_dev_node() {
+
# To find the right value, insert the UltraBay optical drive and run:
UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block:"*`" || return 1
+
# udevadm info --query=path --name=/dev/sr0 | perl -pe 's!/block/...$!!'
UDEV_NAME="`udevinfo -q name -p $UDEV_PATH`" || return 1
 
echo /dev/$UDEV_NAME
 
}
 
  
if [ -d $ULTRABAY_SYSDIR ]; then
+
# Try to guess DEVPATH. It works with optical drive or Hard disk (or SSD)
sync
+
if [ "$DEVPATH" = "" ]; then
# Unmount filesystems backed by this device
+
        # try to guess for CD
unmount_rdev `cat $ULTRABAY_SYSDIR/block\:*/dev     \
+
        DEVPATH=$(udevadm info --query=path --name=/dev/sr0 | perl -pe 's!/block/...$!!')
                  $ULTRABAY_SYSDIR/block\:*/*/dev`  \
+
        if [ "$DEVPATH" = "" ]; then
|| {
+
                echo "No optical device attached?"
echo 10 > /proc/acpi/ibm/beep;  # error tone
+
                echo "Try for harddisk"
exit 1;
+
                # try to guess for sdb
}
+
                DEVPATH=$(udevadm info --query=path --name=/dev/sdb | perl -pe 's!/block/...$!!')
        sync
+
         fi
        # Nicely power off the device
 
DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE
 
         # Let HAL+KDE notice the unmount and let the disk spin down
 
sleep 0.5
 
# Unregister this SCSI device:
 
sync
 
echo 1 > $ULTRABAY_SYSDIR/delete
 
 
fi
 
fi
sync
 
# We really need a 3 sec pause here otherwise the system will freeze..
 
sleep 3
 
# Turn off power to the UltraBay:
 
if [ -d /sys/devices/platform/bay.0 ]; then
 
echo 1 > /sys/devices/platform/bay.0/eject
 
elif [ -e /proc/acpi/ibm/bay ]; then
 
echo eject > /proc/acpi/ibm/bay
 
fi
 
# Tell the user we're OK
 
echo 12 > /proc/acpi/ibm/beep
 
</pre>
 
  
 +
shopt -s nullglob
 +
export DISPLAY=:0.0 # required for notify-send
 +
ULTRABAY_SYSDIR=/sys$DEVPATH
  
Use the modified version below if the above doesn't work for you (for kernels 2.6.25+ due to "ULTRABAY_SYSDIR/block\:*/dev" path change). It was tested on a Thinkpad X41 with Fedora 9 and kernel 2.6.25.11:
+
# Find generic dock interface for UltraBay
 
+
dock=$( /bin/grep -l ata_bay /sys/devices/platform/dock.?/type )
<pre>
+
dock=${dock%%/type}
#!/bin/bash
+
if [ -n "$dock" -a -d "$dock" ]; then
ULTRABAY_SYSDIR='/sys/class/scsi_device/1:0:0:0/device'
+
        logger ultrabay_eject starting eject of $dock
shopt -s nullglob
+
else
 +
        logger ultrabay_eject cannot locate bay dock device
 +
        notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Cannot locate bay dock device"
 +
fi
  
 
# Umount the filesystem(s) backed by the given major:minor device(s)
 
# Umount the filesystem(s) backed by the given major:minor device(s)
 
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
 
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
for $major_minor (@ARGV) {
+
        for $major_minor (@ARGV) {
$major_minor =~ m/^(\d+):(\d+)$/ or die;
+
                $major_minor =~ m/^(\d+):(\d+)$/ or die;
push(@tgt_rdevs, ($1<<8)|$2);
+
                push(@tgt_rdevs, ($1<<8)|$2);
}
+
        }
 
         # Sort by reverse length of mount point, to unmount sub-directories first
 
         # Sort by reverse length of mount point, to unmount sub-directories first
 
         open MOUNTS,"</proc/mounts" or die "$!";
 
         open MOUNTS,"</proc/mounts" or die "$!";
Line 164: Line 134:
 
         foreach $m (@mounts) {
 
         foreach $m (@mounts) {
 
                 ($dev,$dir)=@$m;
 
                 ($dev,$dir)=@$m;
next unless -b $dev;  $rdev=(stat($dev))[6];
+
                next unless -b $dev;  $rdev=(stat($dev))[6];
next unless grep($_==$rdev, @tgt_rdevs);
+
                next unless grep($_==$rdev, @tgt_rdevs);
system("umount","-v","$dir")==0  or  $bad=1;
+
                system("umount","-v","$dir")==0  or  $bad=1;
}
+
                if ($bad == 1) {
exit 1 if $bad;
+
                        system("logger","ultrabay_eject","ERROR unmounting",$dev,$dir);
 +
                        system("notify-send -u critical -t 100000 \"Error unmounting $dir\" \"Unmounting of $dir on $dev failed!\"");
 +
                } else {
 +
                        system("logger","ultrabay_eject","unmounted",$dev,$dir);
 +
                        system("notify-send -u normal -t 5000 \"Unmounted $dir\"");
 +
                };
 +
        }
 +
        exit 1 if $bad;
 
EOPERL
 
EOPERL
}
 
 
# Get the UltraBay's /dev/foo block device node
 
ultrabay_dev_node() {
 
UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block/"*`" || return 1
 
UDEV_NAME="`udevinfo -q name -p $UDEV_PATH`" || return 1
 
echo /dev/$UDEV_NAME
 
 
}
 
}
  
 
if [ -d $ULTRABAY_SYSDIR ]; then
 
if [ -d $ULTRABAY_SYSDIR ]; then
 +
logger ultrabay_eject dock occupied, shutting down storage device $DEVPATH
 
sync
 
sync
 
# Unmount filesystems backed by this device
 
# Unmount filesystems backed by this device
 +
## This seems to be very inelegant and prone to failure
 
unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev    \
 
unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev    \
                  $ULTRABAY_SYSDIR/block/*/*/dev`  \
+
  $ULTRABAY_SYSDIR/block/*/*/dev`  \
 
|| {
 
|| {
echo 10 > /proc/acpi/ibm/beep; # error tone
+
logger ultrabay_eject umounting failed
 +
echo 2 > /proc/acpi/ibm/beep  # triple error tone
 +
notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Please do not pull the device, doing so could cause file corruption and possibly hang the system. Unmounting of the filesystem on the ThinkPad Ultrabay device failed. Please put the eject leaver back in place, and try to unmount the filesystem manually. If this succeeds you can try the eject again"
 
exit 1;
 
exit 1;
 
}
 
}
        sync
+
sync
        # Nicely power off the device
+
# Let HAL+KDE notice the unmount
DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE
 
        # Let HAL+KDE notice the unmount and let the disk spin down
 
 
sleep 0.5
 
sleep 0.5
 
# Unregister this SCSI device:
 
# Unregister this SCSI device:
 
sync
 
sync
 
echo 1 > $ULTRABAY_SYSDIR/delete
 
echo 1 > $ULTRABAY_SYSDIR/delete
 +
elif [ $( cat $dock/docked ) == 0 ]; then
 +
        logger ultrabay_eject dock reports empty
 +
else
 +
logger ultrabay_eject bay occupied but incorrect device path $DEVPATH
 +
notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Bay occupied but incorrect device path"
 +
echo 2 > /proc/acpi/ibm/beep  # triple error tone
 +
exit 1
 
fi
 
fi
  
# We really need a 3 sec pause here otherwise the system will freeze..
+
# We need sleep here so someone can disconnect the bay and the drive
sleep 3
+
sleep 1
 +
 
 +
# Turn off power to the UltraBay
 +
logger ultrabay_eject undocking $dock
 +
echo 1 > $dock/undock
  
# Turn off power to the UltraBay:
 
dock=$( /bin/grep ata_bay /sys/devices/platform/dock.?/type )
 
dock=${dock%%/type:ata_bay} # needed for 2.6.27 and later
 
if [ -n "$dock" -a -d "$dock" ]; then
 
        echo 1 > $dock/undock
 
elif [ -d /sys/devices/platform/bay.0 ]; then
 
echo 1 > /sys/devices/platform/bay.0/eject
 
elif [ -e /proc/acpi/ibm/bay ]; then
 
echo eject > /proc/acpi/ibm/bay
 
fi
 
 
# Tell the user we're OK
 
# Tell the user we're OK
 +
logger ultrabay_eject done
 
echo 12 > /proc/acpi/ibm/beep
 
echo 12 > /proc/acpi/ibm/beep
 +
notify-send -u normal -t 10000 "Safe to remove device" "The ThinkPad Ultrabay device can now safely be removed"
 
</pre>
 
</pre>
 +
a possible fix for the notify not working thing is here [[Talk:How_to_hotswap_Ultrabay_devices#get_notify-send_working]]
  
 
+
Then make sure ownership and permissions are set correct
Create {{path|/etc/acpi/events/ultrabay-insert}}:
+
chown root:root /usr/local/sbin/ultrabay_eject
<pre>
+
chmod 555 /usr/local/sbin/ultrabay_eject
event=ibm/bay MSTR 00000001 00000000
 
action=/usr/local/sbin/ultrabay_insert
 
</pre>
 
 
 
Create {{path|/etc/acpi/events/ultrabay-eject}}:
 
<pre>
 
event=ibm/bay MSTR 00000003 00000000
 
action=/usr/local/sbin/ultrabay_eject
 
</pre>
 
 
 
Restart <tt>acpid</tt>.
 
  
 
If the <tt>ata_piix</tt> driver is built in the kernel, it will catch bay events and you will see the
 
If the <tt>ata_piix</tt> driver is built in the kernel, it will catch bay events and you will see the
Line 237: Line 202:
 
</pre>
 
</pre>
 
You should load <tt>thinkpad_acpi</tt> before <tt>ata_piix</tt> if you want it to handle bay events.
 
You should load <tt>thinkpad_acpi</tt> before <tt>ata_piix</tt> if you want it to handle bay events.
 +
 +
===Script for Ultrabay insert===
 +
{{WARN|Only needed for kernels prior to 2.6.26}}
 +
Create {{path|/usr/local/sbin/ultrabay_insert}} with the following content:
 +
#!/bin/bash
 +
echo 12 > /proc/acpi/ibm/beep
 +
sync
 +
echo 0 0 0 > /sys/class/scsi_host/host1/scan
 +
 +
and set the right permissions
 +
chown root:root /usr/local/sbin/ultrabay_insert
 +
chmod 555 /usr/local/sbin/ultrabay_insert
 +
 +
  
 
===Using the generic bay driver and udev===
 
===Using the generic bay driver and udev===
 
+
{{WARN|If you have kernel 2.6.26 or newer, please use the above [[#Using libata-acpi and udev]] method instead}}
 
Starting from kernel 2.6.23-rc3, it's possible to use the generic <tt>bay</tt> driver in combination with udev to hotswap. Please check if CONFIG_ACPI_BAY is enabled (module or built-in) in your kernel configuration.
 
Starting from kernel 2.6.23-rc3, it's possible to use the generic <tt>bay</tt> driver in combination with udev to hotswap. Please check if CONFIG_ACPI_BAY is enabled (module or built-in) in your kernel configuration.
  
 
Create {{path|/etc/udev/rules.d/ibm-ultrabay.rules}}:
 
Create {{path|/etc/udev/rules.d/ibm-ultrabay.rules}}:
<pre>
+
ENV{BAY_EVENT}=="3", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject"
ENV{BAY_EVENT}=="3", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject"
+
ENV{BAY_EVENT}=="1", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"
ENV{BAY_EVENT}=="1", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"
+
 
</pre>
+
Starting with kernel 2.6.28, the <tt>bay</tt> driver was removed from the mainline kernel. The <tt>dock</tt> driver replaced it completely. Make sure CONFIG_ACPI_DOCK is enabled in the kernel, and use the following udev rules:
 +
 
 +
ENV{EVENT}=="undock", KERNEL=="dock.2", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject"
 +
ENV{EVENT}=="dock", KERNEL=="dock.2", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"
 +
 
 +
However, the ultra_eject script needs to be changed, otherwise udev goes into an infinite event loop. It will send undock events every few seconds forever. That means as soon as the ultrabay is plugged in again, it will be immediately ejected. For kernels 2.6.28 and higher, the bay cannot be powered off using this method, so change the end of the script to read:
 +
# Turn off power to the UltraBay:
 +
if [ -d /sys/devices/platform/bay.0 ]; then
 +
echo 1 > /sys/devices/platform/bay.0/eject
 +
elif [ -e /proc/acpi/ibm/bay ]; then
 +
echo eject > /proc/acpi/ibm/bay
 +
fi
 +
# Tell the user we're OK
 +
echo 12 > /proc/acpi/ibm/beep
 +
 
 +
Alternatively, instead of modifying the script, use the libata-acpi method below.
 +
This was tested on a T61p running Gentoo with tuxonice 2.6.28-r8 without any issues.
 +
 
 +
===udisks support===
 +
Just like the HAL support mentioned below this is only about marking the device as hotpluggable.
  
===Using libata-acpi and udev===
+
Recently distributions do not use HAL anymore. On these systems Gnome, KDE, etc. use udisks instead to discover installed disks. So today most people will have to tell udisks that the ultrabay device is a removeable device. The HAL configuration described below does not work anymore.
  
Starting from kernel 2.6.26-rc5, it's possible to use <tt>libata-acpi</tt> in combination with udev to hotswap. Please check if CONFIG_ATA_ACPI is enabled in your kernel configuration.
+
Udisks reads device properties from udev. In order to force a device to be considered "removeable" we have to set the udev property "UDISKS_SYSTEM_INTERNAL" to "0". (man 7 udisks)
 +
In order for this to work you need at least version 1.0.3 of udisks.
  
For 2.6.25, you need two patches which can be easily backported ([http://article.gmane.org/gmane.linux.acpi.devel/31159],[http://article.gmane.org/gmane.linux.acpi.devel/31369]).
+
Here is an example of a udev rule that adds the property. You can add it to the file that contains the other utrabay rules (i.e. {{path|/etc/udev/rules.d/50-thinkpad-ultrabay.rules}}). You may have to adjust the DEVPATH.
 +
<pre>
 +
SUBSYSTEMS=="block", DEVPATH=="/devices/pci0000:00/0000:00:1f.1/host4/*", ENV{UDISKS_SYSTEM_INTERNAL}="0"
 +
</pre>
  
Create {{path|/etc/udev/rules.d/ibm-ultrabay.rules}}:
+
Now tell udev to reread the rules:
 
<pre>
 
<pre>
ENV{BAY_EVENT}=="3", ACTION=="change", SUBSYSTEM=="scsi", RUN+="/usr/local/sbin/ultrabay_eject"
+
udevadm control --reload-rules
 
</pre>
 
</pre>
  
===Model-specific notes===
+
Now your window manager should give you a notification when you plug in a disk into the ultrabay.
See the table above for a list of ata_piix supported laptops and the bus ID to use.
 
  
 
===HAL support===
 
===HAL support===
 +
{{HELP| If the script below does not work, please provide your lshal output on the [[Talk:How_to_hotswap_Ultrabay_devices]] page}}
 +
{{NOTE| If your HAL version is older then 0.5.11, you need to replace "info.parent" with "storage.physical_device".}}
  
{{NOTE| Starting from HAL 0.5.11, you need to replace "storage.physical_device" with "info.parent".}}
+
HAL support is only needed for proper notification to your desktop applications, such as Gnome and KDE. You will still require the udev script to handle the proper removal.
  
Many programs, KDE included, rely on [[HAL]] to get notifications and information about device hotplugging. You need to tell HAL that devices connected the UltraBay port are hotpluggable. To do so, create the file {{path|/etc/hal/fdi/information/10-ultrabay.fdi}} as follows:
+
To tell HAL that devices connected to the UltraBay port are hotpluggable, you need to create a file {{path|/etc/hal/fdi/information/10-thinkpad-ultrabay.fdi}} with the following content:
 
<pre>
 
<pre>
<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->  
+
<?xml version="1.0" encoding="ISO-8859-1"?> <!-- -*- SGML -*- -->
 +
 
 +
<!--
 +
HAL config file to set ThinkPad Ultrabay eject capability flag.
 +
Note that ThinkPad model matching is done on a partial match, so T40 will also match T40p, which is what we want.
 +
 
 +
If your ThinkPad model is not listed, please check with lspci what PCI ID your disk controller is
 +
-->
  
 
<deviceinfo version="0.2">
 
<deviceinfo version="0.2">
 
   <device>
 
   <device>
 +
    <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" prefix="ThinkPad">
 +
      <match key="/org/freedesktop/Hal/devices/computer:system.hardware.vendor" string="IBM">
 +
 +
        <!-- IBM ThinkPad A20m, A20p, A21e, A21m, A21p, A22e, A22m, A22p, T20, T21, T22, X20 and X21 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="A20;A21;A22;T20;T21;T22;X20;X21">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_7111_scsi_host_0_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- IBM ThinkPad T23, T30, X22, X23, X24 and X30 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T23;T30;X22;X23;X24;X30">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_0_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- IBM ThinkPad A30, A30p, A31 and A31p - 2 Ultrabay devices-->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="A30;A31">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_scsi_device_lun0_0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_0_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- IBM ThinkPad R50, R51, T40, T40p, T41, T41p, X31, X32 and X40 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R50;R51;T40;T41;T42;X31;X32;X40">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_24ca_scsi_host_0_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- IBM ThinkPad R52, T43, T43p, X41, Z60m and Z60p -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R52;T43;X41;Z60">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
      </match>
 +
      <match key="/org/freedesktop/Hal/devices/computer:system.hardware.vendor" string="LENOVO">
 +
 +
        <!-- Lenovo ThinkPad T60, T60p, Z61m, Z61t and Z61p -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T60;Z61">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_27df_scsi_host_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- Lenovo ThinkPad R60 and X60 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R60;X60">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_27c4_scsi_host_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- Lenovo ThinkPad R61, T61, T61p and X300 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R61;T61;X300">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_2850_scsi_host_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- Lenovo ThinkPad R400, R500, T400, T500, W500, W700, X200 and X301 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R400;R500;T400;T500;W500;W700;X200;X301">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_2929_scsi_host_0_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
 +
        <!-- Lenovo ThinkPad T410, T510 -->
 +
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T410;T510">
 +
          <match key="storage.bus" string_outof="pci;scsi">
 +
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_3b2f_scsi_host_0_scsi_device_lun0">
 +
              <merge key="storage.hotpluggable" type="bool">true</merge>
 +
            </match>
 +
          </match>
 +
        </match>
 +
  
    <!-- UltraBay Devices -->
 
    <match key="storage.bus" string="scsi">
 
      <match key="storage.physical_device" string="/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0">
 
        <merge key="storage.hotpluggable" type="bool">true</merge>
 
 
       </match>
 
       </match>
 
     </match>
 
     </match>
 
 
   </device>
 
   </device>
 
</deviceinfo>
 
</deviceinfo>
 
</pre>
 
</pre>
  
The string "8086_2653" may need to be changed to match your ThinkPad model; see below.
+
Then ensure it has the right permissions
  
====Details====
+
chown root:root /etc/hal/fdi/information/10-thinkpad-ultrabay.fdi
 +
chmod 644 /etc/hal/fdi/information/10-thinkpad-ultrabay.fdi
  
By default, HAL doesn't know that UltraBay devices are hotpluggable:
 
  
# PHYSDEV=/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0
+
To check the effect, look at your lshal output, the section for your optical disk (/dev/sr0 typically) or your 2nd hdd (/dev/sdb typically) should have storage.hotpluggable = true after restarting your hal deamon or rebooting.
# UDI=`hal-find-by-property --key storage.physical_device --string $PHYSDEV` || echo Failed
 
# hal-get-property --udi $UDI --key block.device
 
/dev/sdb
 
# hal-get-property --udi $UDI --key storage.hotpluggable
 
false
 
  
After creating {{path|/etc/hal/fdi/information/10-ultrabay.fdi}} as above and re-plugging the device, it will get marked correctly:
+
===Disable ultrabay at boot time===
 +
To safe some energy you can create an init.d start script to automatically "eject" the ultrabay at boot time<br />
 +
vim /etc/init.d/stop-ultrabay
 +
 +
#! /bin/sh
 +
### BEGIN INIT INFO
 +
# Provides:          stop-ultrabay
 +
# Required-Start:    $remote_fs $syslog
 +
# Required-Stop:    $remote_fs $syslog
 +
# Default-Start:    2 3 4 5
 +
# Default-Stop:      0 1 6
 +
# Short-Description: stops the ultrabay
 +
### END INIT INFO
 +
 +
# Script to shutdown ultrabay at boot time. To reenable, simply push the ultrabay eject lever
 +
# and put it again.
 +
# By Frank Doelitzscher, 2010-08-04
 +
#
 +
 +
# This things will always run
 +
/usr/local/sbin/ultrabay_eject
 +
 +
# Carry out specific functions when asked to by the system
 +
case "$1" in
 +
*)
 +
    echo "This script runs automatically at boot time."
 +
    echo "It does not need any switches like start|stop"
 +
    exit 1
 +
    ;;
 +
esac
 +
exit 0
 +
Then ensure it has the right permissions<br />
 +
chmod 755 /etc/init.d/stop-ultrabay
 +
 +
And make it known to the init subsystem<br />
 +
update-rc.d -f stop-ultrabay start 90 2 3 4 5 .
  
# PHYSDEV=/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0
+
It just gets a start script since it does not make sense to execute it at a shutdown or restart.<br />
# UDI=`hal-find-by-property --key storage.physical_device --string $PHYSDEV` || echo Failed
 
# hal-get-property --udi $UDI --key block.device
 
/dev/sdb
 
# hal-get-property --udi $UDI --key storage.hotpluggable
 
true
 
  
The string "8086_2653" gives the PCI ID of the [[Intel 82801FBM]] southbridge. If your model has a different southbridge, or the UltraBay is attached to a different port, then you can find the appropriate <tt>storage.physical_device</tt> value by finding out the block device of the currently running UltraBay device (<tt>/dev/sdb</tt> in the following example) and then running:
+
This was tested on a T60 running Debian Squeeze with standard 2.6.32-5-686 #1 SMP without any issues.
 
 
# DEVICE=/dev/sdb
 
# UDI=`hal-find-by-property --key block.device --string $DEVICE` || echo Failed
 
# hal-get-property --udi $UDI --key storage.physical_device
 
/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_0_scsi_device_lun0
 
 
 
If you have a different <tt>storage.physical_device</tt> value, please report your findings.
 
 
 
{| border=1
 
|+ Known South Bridge PCI IDs
 
! ID !! ThinkPad model !! South Bridge chip
 
|-
 
| 8086_248a || 2366-83U (T30), 2647-MG3 (T23)|| Intel 82801CAM IDE U100 (rev 2)
 
|-
 
| 8086_2653 || 2525FAG (X41), ? (T43) || Intel 82801FBM (ICH6-M)
 
|-
 
| 8086_24ca || 237358U (T40), 2373KXU (T42p) || Intel 82801DBM (ICH4-M)
 
|-
 
| 8086_27c4 || X60          || Intel 82801GBM (ICH7 Family)
 
|-
 
| 8086_27df || Z61p, T60, T60p || Intel 82801GBM/GHM (ICH7 Family)
 
|-
 
| 8086_2850 || T61, T61p || Intel 82801H (ICH8 Family)
 
|}
 
  
 
==When using the <tt>ide-disk</tt> driver==
 
==When using the <tt>ide-disk</tt> driver==
Line 338: Line 443:
 
Hotswapping is supposed to be supported as well, using either hdparm/[http://packages.debian.org/unstable/admin/hotswap Debian hotswap] or [[lt_hotswap]] to (un)register IDE devices. The latter is the recommended method with kernels from 2.6, since it will leave DMA working. However, for recent models (R52, T43, X41, Z60 and later) no method is known to work while maintaining DMA support; see [[Problems with SATA and Linux]].
 
Hotswapping is supposed to be supported as well, using either hdparm/[http://packages.debian.org/unstable/admin/hotswap Debian hotswap] or [[lt_hotswap]] to (un)register IDE devices. The latter is the recommended method with kernels from 2.6, since it will leave DMA working. However, for recent models (R52, T43, X41, Z60 and later) no method is known to work while maintaining DMA support; see [[Problems with SATA and Linux]].
  
Only IDE devices (HDD's, optical drives, zip drives) require special treatment - batteries, floppies and other devices can just be pulled from the bay, provided they are not mounted or in use at the time. However, you should still power them down first using the [[ibm-acpi]] eject function.
+
Only IDE devices (HDD's, optical drives, zip drives) require special treatment - batteries, floppies and other devices can just be pulled from the bay, provided they are not mounted or in use at the time. However, you should still power them down first using the [[thinkpad-acpi]] eject function.
  
The [[ibm-acpi]] kernel module has an eject function ({{cmdroot|echo eject > /proc/acpi/ibm/bay}}). This only manages the ACPI calls to power down the device and the bay. It does not actually unregister the device from the IDE driver. {{cmdroot|cat /proc/acpi/ibm/bay}} shows "unoccupied" unless an IDE device is present, but the eject function still works and should still be used.
+
The [[thinkpad-acpi]] kernel module has an eject function ({{cmdroot|echo eject > /proc/acpi/ibm/bay}}). This only manages the ACPI calls to power down the device and the bay. It does not actually unregister the device from the IDE driver. {{cmdroot|cat /proc/acpi/ibm/bay}} shows "unoccupied" unless an IDE device is present, but the eject function still works and should still be used.
  
 
To unregister the device, you can either use the [http://packages.debian.org/unstable/admin/hotswap Debian hotswap] package, or [[lt_hotswap]]. Note that lt_hotswap doesn't seem to even build on recent (at 2.6.22 or newer, although it probably broke before 2.6.22) and on newer kernels, you should not build/load the old IDE PIIX (CONFIG_BLK_DEV_PIIX) and use the natively hotswapping ata_piix (CONFIG_ATA_PIIX) as explained on the top of this page.
 
To unregister the device, you can either use the [http://packages.debian.org/unstable/admin/hotswap Debian hotswap] package, or [[lt_hotswap]]. Note that lt_hotswap doesn't seem to even build on recent (at 2.6.22 or newer, although it probably broke before 2.6.22) and on newer kernels, you should not build/load the old IDE PIIX (CONFIG_BLK_DEV_PIIX) and use the natively hotswapping ata_piix (CONFIG_ATA_PIIX) as explained on the top of this page.
Line 346: Line 451:
 
[http://packages.debian.org/unstable/admin/hotswap Debian hotswap] also allows the drive to be swapped as a normal user by default, which is useful. You should use <tt>hotswap</tt> to unregister the device and then {{cmdroot|echo eject > /proc/acpi/ibm/bay}}. However, if you use this method on a 2.6 kernel, you will lose DMA support for the reinserted drive. This is due to kernel issues. This method was reported to work on a ThinkPad {{T23}} (kernels 2.6.8.1, 2.6.14.2 and 2.6.15-arch) and {{T42}} (kernel 2.6.13), but fails on a ThinkPad {{T43}} (kernel 2.6.14.3).
 
[http://packages.debian.org/unstable/admin/hotswap Debian hotswap] also allows the drive to be swapped as a normal user by default, which is useful. You should use <tt>hotswap</tt> to unregister the device and then {{cmdroot|echo eject > /proc/acpi/ibm/bay}}. However, if you use this method on a 2.6 kernel, you will lose DMA support for the reinserted drive. This is due to kernel issues. This method was reported to work on a ThinkPad {{T23}} (kernels 2.6.8.1, 2.6.14.2 and 2.6.15-arch) and {{T42}} (kernel 2.6.13), but fails on a ThinkPad {{T43}} (kernel 2.6.14.3).
  
[[lt_hotswap]] is now the recommended method to un- and reregister the IDE device. It installs as a kernel module and has support for automatically unregistering (if loaded with the auto_eject=1 option) the device when the eject event is generated by [[ibm-acpi]]. It will leave DMA support intact. It has supported to work on a ThinkPad {{T22}} and {{T40}} and should work with many other models (but not recent models which require the <tt>ata_piix</tt> driver for disk DMA support). With the [[lt_hotswap]] kernel module loaded, run: {{cmdroot|modprobe -r ide_cd && modprobe -r cdrom && echo "MSTR eject" > /proc/acpi/lths}}
+
[[lt_hotswap]] is now the recommended method to un- and reregister the IDE device. It installs as a kernel module and has support for automatically unregistering (if loaded with the auto_eject=1 option) the device when the eject event is generated by [[thinkpad-acpi]]. It will leave DMA support intact. It has supported to work on a ThinkPad {{T22}} and {{T40}} and should work with many other models (but not recent models which require the <tt>ata_piix</tt> driver for disk DMA support). With the [[lt_hotswap]] kernel module loaded, run: {{cmdroot|modprobe -r ide_cd && modprobe -r cdrom && echo "MSTR eject" > /proc/acpi/lths}}
  
 
===HAL support===
 
===HAL support===
Line 369: Line 474:
 
For more details see HAL section for ata driver.
 
For more details see HAL section for ata driver.
  
==Other comments==
+
==Password protected HDD==
 +
{{WARN|Do not attempt to set a new HDD password from Linux, if you succeed you may find you can no longer unlock the drive or remove the password in any way}}
 +
There are multiple issues with hotplugging a password protected HDD. In short, it does not work from within the operating system. You will need to reboot, or use the suspend/wakeup procedure below, and let the BIOS do the unlock.
 +
===hdparm===
 +
While in theory you should be a able to use hdparm to unlock a drive, or set or remove a password. In practice none of it works the way it should.
 +
 
 +
First of all, by default the BIOS during POST will freeze the security settings of any drives that are present, preventing you from making changes until the drive is power cycled. You can see this by running the following command
 +
# hdparm -I /dev/sdb|grep frozen
 +
not frozen
 +
If the above command simply returns 'frozen' any hdparm security commands will fail with an IO error. If this is an Ultrabay HDD you can simply remove the drive and hotplug it again to reset the drive.
 +
 
 +
If your drive has a PW set by the BIOS, any attempt to unlock it will result in an IO error.
 +
 
 +
But a fatal flaw is to use hdparm to actually set a password, if you do you will find the following issues
 +
* setting a Master password will appear to succeed, but in fact does nothing
 +
* setting a User password does succeed, but you will no longer be able to unlock or remove the password using either hdparm or the BIOS. hdparm will just give IO errors, and the BIOS will report the password being wrong. It is speculated that the BIOS does some kind of hashing to the password, which is why setting the PW from the BIOS and setting the PW with hdparm is incompatible.
 +
 
 +
# hdparm --verbose --user-master u --security-disable test /dev/sdb
 +
security_password="test"
 +
 +
/dev/sdb:
 +
  Issuing SECURITY_DISABLE command, password="test", user=user
 +
oflags.lob_all=0x82, flags={ feat command }
 +
oflags.hob_all=0x82, flags={ feat }
 +
using LBA48 taskfile
 +
outgoing cdb:  85 0b 26 00 00 00 00 00 00 00 00 00 00 40 f2 00
 +
data:  00 00 74 65 73 74 00 00 00 00 00 00 00 00 00 00
 +
SG_IO: ATA_16 status=0x2, host_status=0x0, driver_status=0x8
 +
SG_IO: sb[]:  72 0b 00 00 00 00 00 0e 09 0c 01 04 00 00 00 00 00 00 00 00 e0 51 00 00 00 00 00 00 00 00 00 00
 +
SG_IO: desc[]:  09 0c 01 04 00 00 00 00 00 00 00 00
 +
      ATA_16 stat=51 err=04 nsect=00 lbal=00 lbam=00 lbah=00 dev=e0
 +
I/O error, ata_op=0xf2 ata_status=0x51 ata_error=0x04
 +
SECURITY_UNLOCK: Input/output error
 +
 
 +
*[https://bugzilla.redhat.com/show_bug.cgi?id=603018 bug report against hdparm]
 +
 
 +
===Letting the BIOS unlock the disk by suspending the computer===
 +
 
 +
A password protected disk can be unlocked by ensuring the laptop has been suspended '''before''' inserting the disk into the Ultrabay.  The device being removed should still be ejected before suspending the laptop.
 +
 
 +
Upon waking up (resuming) the computer the BIOS should prompt for the password, and provided you enter it correctly, will unlock the disk.  Once Linux regains control it may be necessary to re-scan the SCSI bus to find the disk and make it available, using the command "sudo rescan-scsi-bus.sh".
 +
 
 +
This is confirmed to work on a T61 running Ubuntu 8.04, (kernel 2.6.24) with the scsitools package installed.
 +
 
 +
===libata EH going crazy===
 +
hotplugging a password protected HDD causes the libata error handler to go crazy
 +
 
 +
ACPI: \_SB_.PCI0.IDE0.SCND.MSTR - docking
 +
ata2: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xe frozen
 +
ata2: ACPI event
 +
ata2: soft resetting link
 +
ata2.00: ATA-6: HTS726060M9AT00, MH4OA6DA, max UDMA/100
 +
ata2.00: 117210240 sectors, multi 0: LBA
 +
ata2.00: limited to UDMA/33 due to 40-wire cable
 +
ata2.00: configured for UDMA/33
 +
ata2: EH complete
 +
scsi 1:0:0:0: Direct-Access    ATA      HTS726060M9AT00  MH4O PQ: 0 ANSI: 5
 +
sd 1:0:0:0: Attached scsi generic sg1 type 0
 +
sd 1:0:0:0: [sdb] 117210240 512-byte logical blocks: (60.0 GB/55.8 GiB)
 +
sd 1:0:0:0: [sdb] Write Protect is off
 +
sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
 +
sdb:
 +
 
 +
After which there are hundreds of errors such as these...
 +
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
 +
ata2.00: BMDMA stat 0x5
 +
ata2.00: failed command: READ DMA
 +
ata2.00: cmd c8/00:08:00:00:00/00:00:00:00:00/e0 tag 0 dma 4096 in
 +
        res 51/04:08:00:00:00/00:00:00:00:00/e0 Emask 0x1 (device error)
 +
ata2.00: status: { DRDY ERR }
 +
ata2.00: error: { ABRT }
 +
ata2.00: configured for UDMA/33
 +
ata2: EH complete
 +
 
 +
Basically what is happening is that libata is ignoring the ATA IDENTIFY data, that reports that the drive is locked, and just tries to scan for every partition type possible.
 +
*[https://bugzilla.kernel.org/show_bug.cgi?id=16181 Bug report against libata]
 +
 
 +
===udisks===
 +
lastly, there should be some userland support to detect the password protected HDD and prompt you for a password or retrieve the password from gnome-keyring. But that will require hdparm to be able to unlock the HDD first, and to figure out if the BIOS is doing some kind of hashing and how.
  
If you are hot-swapping a hard disk on a disk tray, make sure the disk does not have a password set, otherwise it will not be recognized on reinsertion.
+
*[https://bugs.freedesktop.org/show_bug.cgi?id=23110 bug report against udisks]
  
 
[[Category:Scripts]]
 
[[Category:Scripts]]
 
[[Category:HOWTOs]]
 
[[Category:HOWTOs]]

Latest revision as of 01:58, 11 January 2024

The following discusses hotswap (AKA "hotplug") of devices in the Ultrabay.

This page has a lot of old information. Some cleanup might be useful.


Which driver?

This may be confusing, so first a quick history lesson.

Older ThinkPads (up to the R51, T42p and X40) were fully IDE (PATA) for both the internal HDD and Ultrabay. For these there are two drivers, the modern libata based ata_piix and the old legacy piix/ide-disk combo. Most modern distributions will default to the ata_piix driver, which is really what you want anyway.

ThinkPads like the R52, T43, T43p, X41 and X41 Tablet are strange hybrids. They have a Serial-ATA (SATA) chipset for the internal disk controller, but the actual disk is still legacy IDE, using a separate SATA-PATA bridge chip. The Ultrabay, though, is still connected to the legacy IDE host controller. This results in a setup where the internal disk is handled by a SATA driver and the Ultrabay is handled by either ata_piix or piix/ide-disk.

ThinkPads like the R60, T60 and Z60 series are also hybrids, but they use a native SATA HDD internal. Ultrabay still uses legacy IDE (PATA) though. So just like with the previous models you end up with two separate drivers for the internal HDD and the Ultrabay.

The latest generation ThinkPads like the R400, R500, T400, T500, W500, W700, X200, and X301 are all fully SATA for both the internal HDD and the Ultrabay device, so both are handled by the same SATA driver.

TODO
Figure out in which category the X60 series ThinkPads truly belong. Some of these machines might have been shipped with a 1.8" HDD which is likely to be PATA, in fact the HMM even states so. But tabook and ltwbook only lists SATA models, so the 1.8" model might never have shipped. But even if it did there will be a SATA-PATA bridge chip, so from the OS it will look like SATA.
Overview of disk interface types
Thinkpad internal HDD Ultrabay Modern Driver Old Driver
A20m, A20p, A21e, A21m, A21p, A22e, A22m, A22p, A30, A30p, A31, A31p Legacy 2.5" IDE (PATA) Legacy IDE (PATA) ata_piix piix + ide-disk
R30, R31, R32, R40, R50, R50e, R50p, R51 Legacy 2.5" IDE (PATA) Legacy IDE (PATA) ata_piix piix + ide-disk
R52 Legacy 2.5" PATA HDD with conversion to SATA Legacy IDE (PATA) ahci + ata_piix -
R60, R61 2.5" SATA Legacy IDE (PATA) ahci + ata_piix -
R400, R500 2.5" SATA SATA ahci -
T20, T21, T22, T23, T30, T40, T40p, T41, T41p, T42, T42p Legacy 2.5" IDE (PATA) Legacy IDE (PATA) ata_piix piix + ide-disk
T43, T43p Legacy 2.5" PATA HDD with conversion to SATA Legacy IDE (PATA) ahci + ata_piix -
T60, T60p, T61, T61p 2.5" SATA Legacy IDE (PATA) ahci + ata_piix -
T400, T500 2.5" SATA SATA ahci -
X20, X21, X22, X23, X24, X30, X31, X32 Legacy 2.5" IDE (PATA) Legacy IDE (PATA) ata_piix piix + ide-disk
X40 Legacy 1.8" IDE (PATA) Legacy IDE (PATA) ata_piix piix + ide-disk
X41, X41 Tablet Legacy 1.8" PATA HDD with conversion to SATA Legacy IDE (PATA) ahci + ata_piix -
X60, X60s, X60 Tablet, X61, X61s, X61 Tablet 2.5" HDD is SATA, 1.8" HDD is PATA with SATA conversion Legacy IDE (PATA) ahci + ata_piix -
X300 2.5" SATA Legacy IDE (PATA) ahci + ata_piix -
X200, X200 Tablet, X301 2.5" SATA SATA ahci -
W500, W700 2.5" SATA SATA ahci -
Z60m, Z60t, Z61e, Z61m, Z61p, Z61t 2.5" SATA Legacy IDE (PATA) ahci + ata_piix -
NOTE!
Debian users: at least up the the kernel released with Lenny, Debian applies a patch in the Debian kernel sources which prevents the use of ata_piix with PATA devices (like the IDE bus for the Ultrabay). You will have to either use an upstream kernel or (re)patch the Debian kernel sources. You may want to have a look at the following Debian bug reports as well: #444182, #463833.

Modern systems (using the ahci or ata_piix drivers)

The following applies when using the ahci or ata_piix driver (which supercedes the old ide_disk driver).

You should at least be using a distribution with kernel 2.6.23. If you have a distribution with an older kernel, please update your distribution, as in addition to a newer kernel, you will need some of the newer userland tools.

Using libata-acpi and udev

Starting from kernel 2.6.26-rc5, it's possible to use libata-acpi in combination with udev to hotswap. Please check if CONFIG_ATA_ACPI is enabled in your kernel configuration.

For 2.6.25, you need two patches which can be easily backported ([1],[2]).

Create a file /etc/udev/rules.d/50-thinkpad-ultrabay.rules with the following contents:

ENV{BAY_EVENT}=="3", ACTION=="change", SUBSYSTEM=="scsi", RUN+="/usr/local/sbin/ultrabay_eject"

Then ensure it has the right permissions

chown root:root /etc/udev/rules.d/50-thinkpad-ultrabay.rules
chmod 644 /etc/udev/rules.d/50-thinkpad-ultrabay.rules

For Red Hat/Fedora and other systems with selinux, you also need to set the security context:

chcon system_u:object_r:etc_runtime_t:s0 /etc/udev/rules.d/50-thinkpad-ultrabay.rules

Now create the below ultrabay-eject script

Script for Ultrabay eject

The following script does the following:

  • Automatically unmounts the relevant filesystems and power off the Ultrabay when the Ultrabay eject lever is released. Screams if some filesystem can't be unmounted.

Create a executable file /usr/local/sbin/ultrabay_eject with the following content. Note if you want to be able to run it directly (not by the UDEV eject script), then you need to manually edit the DEVPATH variable near the top of the script.

#!/bin/bash

# Change the following DEVPATH= to match your system, if you want to run this directly instead of having it called by the udev eject script
# To find the right value, insert the UltraBay optical drive and run:
# udevadm info --query=path --name=/dev/sr0 | perl -pe 's!/block/...$!!'

# Try to guess DEVPATH. It works with optical drive or Hard disk (or SSD)
if [ "$DEVPATH" = "" ]; then
        # try to guess for CD
        DEVPATH=$(udevadm info --query=path --name=/dev/sr0 | perl -pe 's!/block/...$!!')
        if [ "$DEVPATH" = "" ]; then
                echo "No optical device attached?"
                echo "Try for harddisk"
                # try to guess for sdb
                DEVPATH=$(udevadm info --query=path --name=/dev/sdb | perl -pe 's!/block/...$!!')
        fi
fi

shopt -s nullglob
export DISPLAY=:0.0 # required for notify-send
ULTRABAY_SYSDIR=/sys$DEVPATH

# Find generic dock interface for UltraBay
dock=$( /bin/grep -l ata_bay /sys/devices/platform/dock.?/type )
dock=${dock%%/type}
if [ -n "$dock" -a -d "$dock" ]; then
        logger ultrabay_eject starting eject of $dock
else
        logger ultrabay_eject cannot locate bay dock device
        notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Cannot locate bay dock device"
fi

# Umount the filesystem(s) backed by the given major:minor device(s)
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
        for $major_minor (@ARGV) {
                $major_minor =~ m/^(\d+):(\d+)$/ or die;
                push(@tgt_rdevs, ($1<<8)|$2);
        }
        # Sort by reverse length of mount point, to unmount sub-directories first
        open MOUNTS,"</proc/mounts" or die "$!";
        @mounts=sort { length($b->[1]) <=> length($a->[1]) } map { [ split ] } <MOUNTS>;
        close MOUNTS;
        foreach $m (@mounts) {
                ($dev,$dir)=@$m;
                next unless -b $dev;  $rdev=(stat($dev))[6];
                next unless grep($_==$rdev, @tgt_rdevs);
                system("umount","-v","$dir")==0  or  $bad=1;
                if ($bad == 1) {
                        system("logger","ultrabay_eject","ERROR unmounting",$dev,$dir);
                        system("notify-send -u critical -t 100000 \"Error unmounting $dir\" \"Unmounting of $dir on $dev failed!\"");
                } else {
                        system("logger","ultrabay_eject","unmounted",$dev,$dir);
                        system("notify-send -u normal -t 5000 \"Unmounted $dir\"");
                };
        }
        exit 1 if $bad;
EOPERL
}

if [ -d $ULTRABAY_SYSDIR ]; then
	logger ultrabay_eject dock occupied, shutting down storage device $DEVPATH
	sync
	# Unmount filesystems backed by this device
	## This seems to be very inelegant and prone to failure
	unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev     \
			  $ULTRABAY_SYSDIR/block/*/*/dev`  \
	|| {
		logger ultrabay_eject umounting failed
		echo 2 > /proc/acpi/ibm/beep  # triple error tone
		notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Please do not pull the device, doing so could cause file corruption and possibly hang the system. Unmounting of the filesystem on the ThinkPad Ultrabay device failed. Please put the eject leaver back in place, and try to unmount the filesystem manually. If this succeeds you can try the eject again"
		exit 1;
	}
	sync
	# Let HAL+KDE notice the unmount
	sleep 0.5
	# Unregister this SCSI device:
	sync
	echo 1 > $ULTRABAY_SYSDIR/delete
elif [ $( cat $dock/docked ) == 0 ]; then
        logger ultrabay_eject dock reports empty
else
	logger ultrabay_eject bay occupied but incorrect device path $DEVPATH
	notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Bay occupied but incorrect device path"
	echo 2 > /proc/acpi/ibm/beep  # triple error tone
	exit 1
fi

# We need sleep here so someone can disconnect the bay and the drive
sleep 1

# Turn off power to the UltraBay
logger ultrabay_eject undocking $dock
echo 1 > $dock/undock

# Tell the user we're OK
logger ultrabay_eject done
echo 12 > /proc/acpi/ibm/beep
notify-send -u normal -t 10000 "Safe to remove device" "The ThinkPad Ultrabay device can now safely be removed"

a possible fix for the notify not working thing is here Talk:How_to_hotswap_Ultrabay_devices#get_notify-send_working

Then make sure ownership and permissions are set correct

chown root:root /usr/local/sbin/ultrabay_eject
chmod 555 /usr/local/sbin/ultrabay_eject

If the ata_piix driver is built in the kernel, it will catch bay events and you will see the following message in your system log:

thinkpad_acpi: another device driver is already handling bay events
thinkpad_acpi: disabling subdriver bay

You should load thinkpad_acpi before ata_piix if you want it to handle bay events.

Script for Ultrabay insert

ATTENTION!
Only needed for kernels prior to 2.6.26

Create /usr/local/sbin/ultrabay_insert with the following content:

#!/bin/bash
echo 12 > /proc/acpi/ibm/beep
sync
echo 0 0 0 > /sys/class/scsi_host/host1/scan

and set the right permissions

chown root:root /usr/local/sbin/ultrabay_insert
chmod 555 /usr/local/sbin/ultrabay_insert


Using the generic bay driver and udev

ATTENTION!
If you have kernel 2.6.26 or newer, please use the above #Using libata-acpi and udev method instead

Starting from kernel 2.6.23-rc3, it's possible to use the generic bay driver in combination with udev to hotswap. Please check if CONFIG_ACPI_BAY is enabled (module or built-in) in your kernel configuration.

Create /etc/udev/rules.d/ibm-ultrabay.rules:

ENV{BAY_EVENT}=="3", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject"
ENV{BAY_EVENT}=="1", KERNEL=="bay.0", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"

Starting with kernel 2.6.28, the bay driver was removed from the mainline kernel. The dock driver replaced it completely. Make sure CONFIG_ACPI_DOCK is enabled in the kernel, and use the following udev rules:

ENV{EVENT}=="undock", KERNEL=="dock.2", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_eject"
ENV{EVENT}=="dock", KERNEL=="dock.2", ACTION=="change", SUBSYSTEM=="platform", RUN+="/usr/local/sbin/ultrabay_insert"

However, the ultra_eject script needs to be changed, otherwise udev goes into an infinite event loop. It will send undock events every few seconds forever. That means as soon as the ultrabay is plugged in again, it will be immediately ejected. For kernels 2.6.28 and higher, the bay cannot be powered off using this method, so change the end of the script to read:

# Turn off power to the UltraBay:
if [ -d /sys/devices/platform/bay.0 ]; then
	echo 1 > /sys/devices/platform/bay.0/eject
elif [ -e /proc/acpi/ibm/bay ]; then
	echo eject > /proc/acpi/ibm/bay
fi
# Tell the user we're OK
echo 12 > /proc/acpi/ibm/beep

Alternatively, instead of modifying the script, use the libata-acpi method below. This was tested on a T61p running Gentoo with tuxonice 2.6.28-r8 without any issues.

udisks support

Just like the HAL support mentioned below this is only about marking the device as hotpluggable.

Recently distributions do not use HAL anymore. On these systems Gnome, KDE, etc. use udisks instead to discover installed disks. So today most people will have to tell udisks that the ultrabay device is a removeable device. The HAL configuration described below does not work anymore.

Udisks reads device properties from udev. In order to force a device to be considered "removeable" we have to set the udev property "UDISKS_SYSTEM_INTERNAL" to "0". (man 7 udisks) In order for this to work you need at least version 1.0.3 of udisks.

Here is an example of a udev rule that adds the property. You can add it to the file that contains the other utrabay rules (i.e. /etc/udev/rules.d/50-thinkpad-ultrabay.rules). You may have to adjust the DEVPATH.

SUBSYSTEMS=="block", DEVPATH=="/devices/pci0000:00/0000:00:1f.1/host4/*", ENV{UDISKS_SYSTEM_INTERNAL}="0"

Now tell udev to reread the rules:

udevadm control --reload-rules

Now your window manager should give you a notification when you plug in a disk into the ultrabay.

HAL support

Help needed
If the script below does not work, please provide your lshal output on the Talk:How_to_hotswap_Ultrabay_devices page
NOTE!
If your HAL version is older then 0.5.11, you need to replace "info.parent" with "storage.physical_device".

HAL support is only needed for proper notification to your desktop applications, such as Gnome and KDE. You will still require the udev script to handle the proper removal.

To tell HAL that devices connected to the UltraBay port are hotpluggable, you need to create a file /etc/hal/fdi/information/10-thinkpad-ultrabay.fdi with the following content:

<?xml version="1.0" encoding="ISO-8859-1"?> <!-- -*- SGML -*- -->

<!--
HAL config file to set ThinkPad Ultrabay eject capability flag.
Note that ThinkPad model matching is done on a partial match, so T40 will also match T40p, which is what we want.

If your ThinkPad model is not listed, please check with lspci what PCI ID your disk controller is
-->

<deviceinfo version="0.2">
  <device>
    <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" prefix="ThinkPad">
      <match key="/org/freedesktop/Hal/devices/computer:system.hardware.vendor" string="IBM">

        <!-- IBM ThinkPad A20m, A20p, A21e, A21m, A21p, A22e, A22m, A22p, T20, T21, T22, X20 and X21 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="A20;A21;A22;T20;T21;T22;X20;X21">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_7111_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- IBM ThinkPad T23, T30, X22, X23, X24 and X30 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T23;T30;X22;X23;X24;X30">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- IBM ThinkPad A30, A30p, A31 and A31p - 2 Ultrabay devices-->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="A30;A31">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_scsi_device_lun0_0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- IBM ThinkPad R50, R51, T40, T40p, T41, T41p, X31, X32 and X40 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R50;R51;T40;T41;T42;X31;X32;X40">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_24ca_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- IBM ThinkPad R52, T43, T43p, X41, Z60m and Z60p -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R52;T43;X41;Z60">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

      </match>
      <match key="/org/freedesktop/Hal/devices/computer:system.hardware.vendor" string="LENOVO">

        <!-- Lenovo ThinkPad T60, T60p, Z61m, Z61t and Z61p -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T60;Z61">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_27df_scsi_host_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- Lenovo ThinkPad R60 and X60 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R60;X60">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_27c4_scsi_host_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- Lenovo ThinkPad R61, T61, T61p and X300 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R61;T61;X300">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_2850_scsi_host_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- Lenovo ThinkPad R400, R500, T400, T500, W500, W700, X200 and X301 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="R400;R500;T400;T500;W500;W700;X200;X301">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_2929_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

        <!-- Lenovo ThinkPad T410, T510 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T410;T510">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_3b2f_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>


      </match>
    </match>
  </device>
</deviceinfo>

Then ensure it has the right permissions

chown root:root /etc/hal/fdi/information/10-thinkpad-ultrabay.fdi
chmod 644 /etc/hal/fdi/information/10-thinkpad-ultrabay.fdi


To check the effect, look at your lshal output, the section for your optical disk (/dev/sr0 typically) or your 2nd hdd (/dev/sdb typically) should have storage.hotpluggable = true after restarting your hal deamon or rebooting.

Disable ultrabay at boot time

To safe some energy you can create an init.d start script to automatically "eject" the ultrabay at boot time
vim /etc/init.d/stop-ultrabay

#! /bin/sh 
### BEGIN INIT INFO
# Provides:          stop-ultrabay
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: stops the ultrabay
### END INIT INFO

# Script to shutdown ultrabay at boot time. To reenable, simply push the ultrabay eject lever
# and put it again.
# By Frank Doelitzscher, 2010-08-04
#

# This things will always run
/usr/local/sbin/ultrabay_eject

# Carry out specific functions when asked to by the system
case "$1" in
*)
   echo "This script runs automatically at boot time."
   echo "It does not need any switches like start|stop"
   exit 1
   ;;
esac 
exit 0

Then ensure it has the right permissions

chmod 755 /etc/init.d/stop-ultrabay

And make it known to the init subsystem

update-rc.d -f stop-ultrabay start 90 2 3 4 5 .

It just gets a start script since it does not make sense to execute it at a shutdown or restart.

This was tested on a T60 running Debian Squeeze with standard 2.6.32-5-686 #1 SMP without any issues.

When using the ide-disk driver

The following applies if you use the ide-disk driver for the UltraBay device.
Note that essentially, you shouldn't be using this driver, and use ata_piix instead unless you're running an older kernel where ata_piix won't work for you

Hotswapping is supposed to be supported as well, using either hdparm/Debian hotswap or lt_hotswap to (un)register IDE devices. The latter is the recommended method with kernels from 2.6, since it will leave DMA working. However, for recent models (R52, T43, X41, Z60 and later) no method is known to work while maintaining DMA support; see Problems with SATA and Linux.

Only IDE devices (HDD's, optical drives, zip drives) require special treatment - batteries, floppies and other devices can just be pulled from the bay, provided they are not mounted or in use at the time. However, you should still power them down first using the thinkpad-acpi eject function.

The thinkpad-acpi kernel module has an eject function (# echo eject > /proc/acpi/ibm/bay). This only manages the ACPI calls to power down the device and the bay. It does not actually unregister the device from the IDE driver. # cat /proc/acpi/ibm/bay shows "unoccupied" unless an IDE device is present, but the eject function still works and should still be used.

To unregister the device, you can either use the Debian hotswap package, or lt_hotswap. Note that lt_hotswap doesn't seem to even build on recent (at 2.6.22 or newer, although it probably broke before 2.6.22) and on newer kernels, you should not build/load the old IDE PIIX (CONFIG_BLK_DEV_PIIX) and use the natively hotswapping ata_piix (CONFIG_ATA_PIIX) as explained on the top of this page.

Debian hotswap also allows the drive to be swapped as a normal user by default, which is useful. You should use hotswap to unregister the device and then # echo eject > /proc/acpi/ibm/bay. However, if you use this method on a 2.6 kernel, you will lose DMA support for the reinserted drive. This is due to kernel issues. This method was reported to work on a ThinkPad T23 (kernels 2.6.8.1, 2.6.14.2 and 2.6.15-arch) and T42 (kernel 2.6.13), but fails on a ThinkPad T43 (kernel 2.6.14.3).

lt_hotswap is now the recommended method to un- and reregister the IDE device. It installs as a kernel module and has support for automatically unregistering (if loaded with the auto_eject=1 option) the device when the eject event is generated by thinkpad-acpi. It will leave DMA support intact. It has supported to work on a ThinkPad T22 and T40 and should work with many other models (but not recent models which require the ata_piix driver for disk DMA support). With the lt_hotswap kernel module loaded, run: # modprobe -r ide_cd && modprobe -r cdrom && echo "MSTR eject" > /proc/acpi/lths

HAL support

HAL support also can also be configured To do so, create the file /etc/hal/fdi/information/10-ultrabay.fdi as follows:

<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->

<deviceinfo version="0.2">
  <device>

    <!-- UltraBay Devices -->
    <match key="storage.bus" string="ide">
      <match key="storage.physical_device" string="/org/freedesktop/Hal/devices/pci_8086_24ca_ide_1_0">
        <merge key="storage.hotpluggable" type="bool">true</merge>
      </match>
    </match>

  </device>
</deviceinfo>

For more details see HAL section for ata driver.

Password protected HDD

ATTENTION!
Do not attempt to set a new HDD password from Linux, if you succeed you may find you can no longer unlock the drive or remove the password in any way

There are multiple issues with hotplugging a password protected HDD. In short, it does not work from within the operating system. You will need to reboot, or use the suspend/wakeup procedure below, and let the BIOS do the unlock.

hdparm

While in theory you should be a able to use hdparm to unlock a drive, or set or remove a password. In practice none of it works the way it should.

First of all, by default the BIOS during POST will freeze the security settings of any drives that are present, preventing you from making changes until the drive is power cycled. You can see this by running the following command

# hdparm -I /dev/sdb|grep frozen
	not	frozen

If the above command simply returns 'frozen' any hdparm security commands will fail with an IO error. If this is an Ultrabay HDD you can simply remove the drive and hotplug it again to reset the drive.

If your drive has a PW set by the BIOS, any attempt to unlock it will result in an IO error.

But a fatal flaw is to use hdparm to actually set a password, if you do you will find the following issues

  • setting a Master password will appear to succeed, but in fact does nothing
  • setting a User password does succeed, but you will no longer be able to unlock or remove the password using either hdparm or the BIOS. hdparm will just give IO errors, and the BIOS will report the password being wrong. It is speculated that the BIOS does some kind of hashing to the password, which is why setting the PW from the BIOS and setting the PW with hdparm is incompatible.
# hdparm --verbose --user-master u --security-disable test /dev/sdb
security_password="test"

/dev/sdb:
 Issuing SECURITY_DISABLE command, password="test", user=user
oflags.lob_all=0x82, flags={ feat command }
oflags.hob_all=0x82, flags={ feat }
using LBA48 taskfile
outgoing cdb:  85 0b 26 00 00 00 00 00 00 00 00 00 00 40 f2 00
data:  00 00 74 65 73 74 00 00 00 00 00 00 00 00 00 00
SG_IO: ATA_16 status=0x2, host_status=0x0, driver_status=0x8
SG_IO: sb[]:  72 0b 00 00 00 00 00 0e 09 0c 01 04 00 00 00 00 00 00 00 00 e0 51 00 00 00 00 00 00 00 00 00 00
SG_IO: desc[]:  09 0c 01 04 00 00 00 00 00 00 00 00
      ATA_16 stat=51 err=04 nsect=00 lbal=00 lbam=00 lbah=00 dev=e0
I/O error, ata_op=0xf2 ata_status=0x51 ata_error=0x04
SECURITY_UNLOCK: Input/output error

Letting the BIOS unlock the disk by suspending the computer

A password protected disk can be unlocked by ensuring the laptop has been suspended before inserting the disk into the Ultrabay. The device being removed should still be ejected before suspending the laptop.

Upon waking up (resuming) the computer the BIOS should prompt for the password, and provided you enter it correctly, will unlock the disk. Once Linux regains control it may be necessary to re-scan the SCSI bus to find the disk and make it available, using the command "sudo rescan-scsi-bus.sh".

This is confirmed to work on a T61 running Ubuntu 8.04, (kernel 2.6.24) with the scsitools package installed.

libata EH going crazy

hotplugging a password protected HDD causes the libata error handler to go crazy

ACPI: \_SB_.PCI0.IDE0.SCND.MSTR - docking
ata2: exception Emask 0x10 SAct 0x0 SErr 0x0 action 0xe frozen
ata2: ACPI event
ata2: soft resetting link
ata2.00: ATA-6: HTS726060M9AT00, MH4OA6DA, max UDMA/100
ata2.00: 117210240 sectors, multi 0: LBA 
ata2.00: limited to UDMA/33 due to 40-wire cable
ata2.00: configured for UDMA/33
ata2: EH complete
scsi 1:0:0:0: Direct-Access     ATA      HTS726060M9AT00  MH4O PQ: 0 ANSI: 5
sd 1:0:0:0: Attached scsi generic sg1 type 0
sd 1:0:0:0: [sdb] 117210240 512-byte logical blocks: (60.0 GB/55.8 GiB)
sd 1:0:0:0: [sdb] Write Protect is off
sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
sdb:

After which there are hundreds of errors such as these...

ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
ata2.00: BMDMA stat 0x5
ata2.00: failed command: READ DMA
ata2.00: cmd c8/00:08:00:00:00/00:00:00:00:00/e0 tag 0 dma 4096 in
        res 51/04:08:00:00:00/00:00:00:00:00/e0 Emask 0x1 (device error)
ata2.00: status: { DRDY ERR }
ata2.00: error: { ABRT }
ata2.00: configured for UDMA/33
ata2: EH complete

Basically what is happening is that libata is ignoring the ATA IDENTIFY data, that reports that the drive is locked, and just tries to scan for every partition type possible.

udisks

lastly, there should be some userland support to detect the password protected HDD and prompt you for a password or retrieve the password from gnome-keyring. But that will require hdparm to be able to unlock the HDD first, and to figure out if the BIOS is doing some kind of hashing and how.