diff --git a/sm5/os_darwin.c b/sm5/os_darwin.c
index d733290957f24fd32bb5012dd72ef9a394f047b5..369270328e2adf0f033712c18fb1b38cbadb9a72 100644
--- a/sm5/os_darwin.c
+++ b/sm5/os_darwin.c
@@ -24,10 +24,11 @@
 #include <IOKit/IOKitLib.h>
 #include <IOKit/IOReturn.h>
 #include <IOKit/IOBSD.h>
-#include <IOKit/storage/ata/IOATAStorageDefines.h>
-#include <IOKit/storage/ata/ATASMARTLib.h>
+#include <IOKit/storage/IOBlockStorageDevice.h>
 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
 #include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/ata/IOATAStorageDefines.h>
+#include <IOKit/storage/ata/ATASMARTLib.h>
 #include <CoreFoundation/CoreFoundation.h>
 
   // No, I don't know why there isn't a header for this.
@@ -42,7 +43,7 @@
 #include "os_darwin.h"
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_darwin.c,v 1.13 2006/04/12 14:54:28 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_darwin.c,v 1.14 2006/07/26 05:02:29 geoffk1 Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // Print examples for smartctl.
@@ -76,6 +77,46 @@ int guess_device_type (const char* dev_name) {
   return CONTROLLER_ATA;
 }
 
+// Determine whether 'dev' is a SMART-capable device.
+static bool is_smart_capable (io_object_t dev) {
+  CFTypeRef smartCapableKey;
+  CFDictionaryRef diskChars;
+
+  // If the device has kIOPropertySMARTCapableKey, then it's capable,
+  // no matter what it looks like.
+  smartCapableKey = IORegistryEntryCreateCFProperty
+    (dev, CFSTR (kIOPropertySMARTCapableKey),
+     kCFAllocatorDefault, 0);
+  if (smartCapableKey)
+    {
+      CFRelease (smartCapableKey);
+      return true;
+    }
+
+  // If it's an kIOATABlockStorageDeviceClass then we're successful
+  // only if its ATA features indicate it supports SMART.
+  if (IOObjectConformsTo (dev, kIOATABlockStorageDeviceClass)
+      && (diskChars = IORegistryEntryCreateCFProperty
+	  (dev, CFSTR (kIOPropertyDeviceCharacteristicsKey),
+	   kCFAllocatorDefault, kNilOptions)) != NULL)
+    {
+      CFNumberRef diskFeatures = NULL;
+      UInt32 ataFeatures = 0;
+
+      if (CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"),
+					 (const void **)&diskFeatures))
+	CFNumberGetValue (diskFeatures, kCFNumberLongType,
+			  &ataFeatures);
+      CFRelease (diskChars);
+      if (diskFeatures)
+	CFRelease (diskFeatures);
+      
+      return (ataFeatures & kIOATAFeatureSMART) != 0;
+    }
+  return false;
+}
+
+
 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
 // smartd.  Returns number N of devices, or -1 if out of
 // memory. Allocates N+1 arrays: one of N pointers (devlist); the
@@ -85,46 +126,52 @@ int guess_device_type (const char* dev_name) {
 int make_device_names (char*** devlist, const char* name) {
   IOReturn err;
   io_iterator_t i;
-  io_object_t device;
+  io_object_t device = MACH_PORT_NULL;
   int result;
   int index;
-  const char * cls;
 
-  if (strcmp (name, "ATA") == 0)
-    cls = kIOATABlockStorageDeviceClass;
-  else  // only ATA supported right now.
+  // We treat all devices as ATA so long as they support SMARTLib.
+  if (strcmp (name, "ATA") != 0)
     return 0;
 
-  err = IOServiceGetMatchingServices (kIOMasterPortDefault,
-				      IOServiceMatching (cls),
-				      &i);
+  err = IOServiceGetMatchingServices 
+    (kIOMasterPortDefault, IOServiceMatching (kIOBlockStorageDeviceClass), &i);
   if (err != kIOReturnSuccess)
     return -1;
 
   // Count the devices.
-  for (result = 0; (device = IOIteratorNext (i)) != MACH_PORT_NULL; result++)
+  result = 0;
+  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
+    if (is_smart_capable (device))
+      result++;
     IOObjectRelease (device);
+  }
 
   // Create an array of service names.
   IOIteratorReset (i);
   *devlist = Calloc (result, sizeof (char *));
   if (! *devlist)
     goto error;
-  for (index = 0; (device = IOIteratorNext (i)) != MACH_PORT_NULL; index++)
-    {
-      io_string_t devName;
-      IORegistryEntryGetPath(device, kIOServicePlane, devName);
-      IOObjectRelease (device);
+  index = 0;
+  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
+    if (is_smart_capable (device))
+      {
+	io_string_t devName;
+	IORegistryEntryGetPath(device, kIOServicePlane, devName);
+	(*devlist)[index] = CustomStrDup (devName, true, __LINE__, __FILE__);
+	if (! (*devlist)[index])
+	  goto error;
+	index++;
+      }
+    IOObjectRelease (device);
+  }
 
-      (*devlist)[index] = CustomStrDup (devName, true, __LINE__, __FILE__);
-      if (! (*devlist)[index])
-	goto error;
-    }
   IOObjectRelease (i);
-
   return result;
 
  error:
+  if (device != MACH_PORT_NULL)
+    IOObjectRelease (device);
   IOObjectRelease (i);
   if (*devlist)
     {
@@ -140,7 +187,6 @@ int make_device_names (char*** devlist, const char* name) {
 
 static struct {
   io_object_t ioob;
-  bool hassmart;
   IOCFPlugInInterface **plugin;
   IOATASMARTInterface **smartIf;
 } devices[20];
@@ -203,44 +249,24 @@ int deviceopen(const char *pathname, char *type){
       return -1;
     }
   
-  // Find the ATA block storage driver that is the parent of this device
-  while (! IOObjectConformsTo (disk, kIOATABlockStorageDeviceClass))
+  // Find a SMART-capable driver which is a parent of this device.
+  while (! is_smart_capable (disk))
     {
       IOReturn err;
-      io_object_t notdisk = disk;
+      io_object_t prevdisk = disk;
 
-      err = IORegistryEntryGetParentEntry (notdisk, kIOServicePlane, &disk);
+      // Find this device's parent and try again.
+      err = IORegistryEntryGetParentEntry (disk, kIOServicePlane, &disk);
       if (err != kIOReturnSuccess || ! disk)
 	{
 	  errno = ENODEV;
-	  IOObjectRelease (notdisk);
+	  IOObjectRelease (prevdisk);
 	  return -1;
 	}
     }
-
-  devices[devnum].ioob = disk;
-  
-  {
-    CFDictionaryRef diskChars = NULL;
-    CFNumberRef diskFeatures = NULL;
-    UInt32 ataFeatures;
-
-    // Determine whether the drive actually supports SMART.
-    if ((diskChars = IORegistryEntryCreateCFProperty (disk, 
-			      CFSTR (kIOPropertyDeviceCharacteristicsKey),
-						      kCFAllocatorDefault,
-						      kNilOptions)) != NULL
-	&& CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"),
-					  (const void **)&diskFeatures)
-	&& CFNumberGetValue (diskFeatures, kCFNumberLongType, &ataFeatures)
-	&& (ataFeatures & kIOATAFeatureSMART))
-      devices[devnum].hassmart = true;
-    else
-      devices[devnum].hassmart = false;
-    if (diskChars)
-      CFRelease (diskChars);
-  }
   
+  devices[devnum].ioob = disk;
+
   {
     SInt32 dummy;
   
@@ -248,12 +274,11 @@ int deviceopen(const char *pathname, char *type){
     devices[devnum].smartIf = NULL;
 
     // Create an interface to the ATA SMART library.
-    if (devices[devnum].hassmart
-	&& IOCreatePlugInInterfaceForService (disk,
-					      kIOATASMARTUserClientTypeID,
-					      kIOCFPlugInInterfaceID,
-					      &devices[devnum].plugin,
-					      &dummy) == kIOReturnSuccess)
+    if (IOCreatePlugInInterfaceForService (disk,
+					   kIOATASMARTUserClientTypeID,
+					   kIOCFPlugInInterfaceID,
+					   &devices[devnum].plugin,
+					   &dummy) == kIOReturnSuccess)
       (*devices[devnum].plugin)->QueryInterface
 	(devices[devnum].plugin,
 	 CFUUIDGetUUIDBytes ( kIOATASMARTInterfaceID),
@@ -301,10 +326,6 @@ int deviceclose(int fd){
 // have a buggy library that treats the boolean value in
 // SMARTEnableDisableOperations, SMARTEnableDisableAutosave, and
 // SMARTExecuteOffLineImmediate as always being true.
-int marvell_command_interface(int fd, smart_command_set command,
-		      int select, char *data)
-{ return -1; }
- 
 int
 ata_command_interface(int fd, smart_command_set command,
 		      int select, char *data)
@@ -312,72 +333,83 @@ ata_command_interface(int fd, smart_command_set command,
   IOATASMARTInterface **ifp = devices[fd].smartIf;
   IOATASMARTInterface *smartIf;
   IOReturn err;
+  int timeoutCount = 2;
   
   if (! ifp)
     return -1;
   smartIf = *ifp;
 
-  switch (command)
-    {
-    case STATUS:
-      return 0;
-    case STATUS_CHECK:
+  do {
+    switch (command)
       {
-	Boolean is_failing;
-	err = smartIf->SMARTReturnStatus (ifp, &is_failing);
-	if (err == kIOReturnSuccess && is_failing)
-	  return 1;
-	break;
-      }
-    case ENABLE:
-    case DISABLE:
-      err = smartIf->SMARTEnableDisableOperations (ifp, command == ENABLE);
-      break;
-    case AUTOSAVE:
-      err = smartIf->SMARTEnableDisableAutosave (ifp, select != 0);
-      break;
-    case IMMEDIATE_OFFLINE:
-      if (select != SHORT_SELF_TEST && select != EXTEND_SELF_TEST)
+      case STATUS:
+	return 0;
+      case STATUS_CHECK:
 	{
-	  errno = EINVAL;
-	  return -1;
+	  Boolean is_failing;
+	  err = smartIf->SMARTReturnStatus (ifp, &is_failing);
+	  if (err == kIOReturnSuccess && is_failing)
+	    return 1;
+	  break;
 	}
-      err = smartIf->SMARTExecuteOffLineImmediate (ifp, 
-						   select == EXTEND_SELF_TEST);
-      break;
-    case READ_VALUES:
-      err = smartIf->SMARTReadData (ifp, (ATASMARTData *)data);
-      break;
-    case READ_THRESHOLDS:
-      err = smartIf->SMARTReadDataThresholds (ifp, 
-					      (ATASMARTDataThresholds *)data);
-      break;
-    case READ_LOG:
-      err = smartIf->SMARTReadLogAtAddress (ifp, select, data, 512);
-      break;
-    case WRITE_LOG:
-      err = smartIf->SMARTWriteLogAtAddress (ifp, select, data, 512);
-      break;
-    case IDENTIFY:
-      {
-	UInt32 dummy;
-	err = smartIf->GetATAIdentifyData (ifp, data, 512, &dummy);
-	if (err == kIOReturnSuccess && isbigendian())
+      case ENABLE:
+      case DISABLE:
+	err = smartIf->SMARTEnableDisableOperations (ifp, command == ENABLE);
+	break;
+      case AUTOSAVE:
+	err = smartIf->SMARTEnableDisableAutosave (ifp, select != 0);
+	break;
+      case IMMEDIATE_OFFLINE:
+	if (select != SHORT_SELF_TEST && select != EXTEND_SELF_TEST)
 	  {
-	    int i;
-	    /* The system has already byte-swapped, undo it.  */
-	    for (i = 0; i < 256; i+=2)
-	      swap2 (data + i);
+	    errno = EINVAL;
+	    return -1;
 	  }
+	err = smartIf->SMARTExecuteOffLineImmediate (ifp, 
+						     select == EXTEND_SELF_TEST);
+	break;
+      case READ_VALUES:
+	err = smartIf->SMARTReadData (ifp, (ATASMARTData *)data);
+	break;
+      case READ_THRESHOLDS:
+	err = smartIf->SMARTReadDataThresholds (ifp, 
+						(ATASMARTDataThresholds *)data);
+	break;
+      case READ_LOG:
+	err = smartIf->SMARTReadLogAtAddress (ifp, select, data, 512);
+	break;
+      case WRITE_LOG:
+	err = smartIf->SMARTWriteLogAtAddress (ifp, select, data, 512);
+	break;
+      case IDENTIFY:
+	{
+	  UInt32 dummy;
+	  err = smartIf->GetATAIdentifyData (ifp, data, 512, &dummy);
+	  if (err != kIOReturnSuccess)
+	    printf ("identify failed: %d\n", (int) err);
+	  if (err == kIOReturnSuccess && isbigendian())
+	    {
+	      int i;
+	      /* The system has already byte-swapped, undo it.  */
+	      for (i = 0; i < 256; i+=2)
+		swap2 (data + i);
+	    }
+	}
+	break;
+      case CHECK_POWER_MODE:
+	// The information is right there in the device registry, but how
+	// to get to it portably?
+      default:
+	errno = ENOTSUP;
+	return -1;
       }
-      break;
-    case CHECK_POWER_MODE:
-      // The information is right there in the device registry, but how
-      // to get to it portably?
-    default:
-      errno = ENOTSUP;
-      return -1;
-    }
+    /* This bit is a bit strange.  Apparently, when the drive is spun
+       down, the intended behaviour of these calls is that they fail,
+       return kIOReturnTimeout and then power the drive up.  So if
+       you get a timeout, you have to try again to get the actual
+       command run, but the drive is already powering up so you can't
+       use this for CHECK_POWER_MODE.  */
+  } while (err == kIOReturnTimeout && timeoutCount-- > 0);
   if (err == kIOReturnExclusiveAccess)
     errno = EBUSY;
   return err == kIOReturnSuccess ? 0 : -1;
@@ -398,7 +430,20 @@ int escalade_command_interface(int fd, int escalade_port, int escalade_type,
   return -1;
 }
 
+int marvell_command_interface(int fd, smart_command_set command,
+		      int select, char *data)
+{ 
+  fd = fd;
+  command = command;
+  select = select;
+  data = data;
+  return -1;
+}
+ 
 // Interface to SCSI devices.  See os_linux.c
 int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) {
+  fd = fd;
+  iop = iop;
+  report = report;
   return -ENOSYS;
 }
diff --git a/sm5/os_darwin.cpp b/sm5/os_darwin.cpp
index d34173a1fd6759a46dea2e08b541491743cac10e..550dc3acc061418328d4770e0a90de2c7ed742d4 100644
--- a/sm5/os_darwin.cpp
+++ b/sm5/os_darwin.cpp
@@ -24,10 +24,11 @@
 #include <IOKit/IOKitLib.h>
 #include <IOKit/IOReturn.h>
 #include <IOKit/IOBSD.h>
-#include <IOKit/storage/ata/IOATAStorageDefines.h>
-#include <IOKit/storage/ata/ATASMARTLib.h>
+#include <IOKit/storage/IOBlockStorageDevice.h>
 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
 #include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/ata/IOATAStorageDefines.h>
+#include <IOKit/storage/ata/ATASMARTLib.h>
 #include <CoreFoundation/CoreFoundation.h>
 
   // No, I don't know why there isn't a header for this.
@@ -42,7 +43,7 @@
 #include "os_darwin.h"
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_darwin.cpp,v 1.13 2006/04/12 14:54:28 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_darwin.cpp,v 1.14 2006/07/26 05:02:29 geoffk1 Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // Print examples for smartctl.
@@ -76,6 +77,46 @@ int guess_device_type (const char* dev_name) {
   return CONTROLLER_ATA;
 }
 
+// Determine whether 'dev' is a SMART-capable device.
+static bool is_smart_capable (io_object_t dev) {
+  CFTypeRef smartCapableKey;
+  CFDictionaryRef diskChars;
+
+  // If the device has kIOPropertySMARTCapableKey, then it's capable,
+  // no matter what it looks like.
+  smartCapableKey = IORegistryEntryCreateCFProperty
+    (dev, CFSTR (kIOPropertySMARTCapableKey),
+     kCFAllocatorDefault, 0);
+  if (smartCapableKey)
+    {
+      CFRelease (smartCapableKey);
+      return true;
+    }
+
+  // If it's an kIOATABlockStorageDeviceClass then we're successful
+  // only if its ATA features indicate it supports SMART.
+  if (IOObjectConformsTo (dev, kIOATABlockStorageDeviceClass)
+      && (diskChars = IORegistryEntryCreateCFProperty
+	  (dev, CFSTR (kIOPropertyDeviceCharacteristicsKey),
+	   kCFAllocatorDefault, kNilOptions)) != NULL)
+    {
+      CFNumberRef diskFeatures = NULL;
+      UInt32 ataFeatures = 0;
+
+      if (CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"),
+					 (const void **)&diskFeatures))
+	CFNumberGetValue (diskFeatures, kCFNumberLongType,
+			  &ataFeatures);
+      CFRelease (diskChars);
+      if (diskFeatures)
+	CFRelease (diskFeatures);
+      
+      return (ataFeatures & kIOATAFeatureSMART) != 0;
+    }
+  return false;
+}
+
+
 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
 // smartd.  Returns number N of devices, or -1 if out of
 // memory. Allocates N+1 arrays: one of N pointers (devlist); the
@@ -85,46 +126,52 @@ int guess_device_type (const char* dev_name) {
 int make_device_names (char*** devlist, const char* name) {
   IOReturn err;
   io_iterator_t i;
-  io_object_t device;
+  io_object_t device = MACH_PORT_NULL;
   int result;
   int index;
-  const char * cls;
 
-  if (strcmp (name, "ATA") == 0)
-    cls = kIOATABlockStorageDeviceClass;
-  else  // only ATA supported right now.
+  // We treat all devices as ATA so long as they support SMARTLib.
+  if (strcmp (name, "ATA") != 0)
     return 0;
 
-  err = IOServiceGetMatchingServices (kIOMasterPortDefault,
-				      IOServiceMatching (cls),
-				      &i);
+  err = IOServiceGetMatchingServices 
+    (kIOMasterPortDefault, IOServiceMatching (kIOBlockStorageDeviceClass), &i);
   if (err != kIOReturnSuccess)
     return -1;
 
   // Count the devices.
-  for (result = 0; (device = IOIteratorNext (i)) != MACH_PORT_NULL; result++)
+  result = 0;
+  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
+    if (is_smart_capable (device))
+      result++;
     IOObjectRelease (device);
+  }
 
   // Create an array of service names.
   IOIteratorReset (i);
   *devlist = Calloc (result, sizeof (char *));
   if (! *devlist)
     goto error;
-  for (index = 0; (device = IOIteratorNext (i)) != MACH_PORT_NULL; index++)
-    {
-      io_string_t devName;
-      IORegistryEntryGetPath(device, kIOServicePlane, devName);
-      IOObjectRelease (device);
+  index = 0;
+  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
+    if (is_smart_capable (device))
+      {
+	io_string_t devName;
+	IORegistryEntryGetPath(device, kIOServicePlane, devName);
+	(*devlist)[index] = CustomStrDup (devName, true, __LINE__, __FILE__);
+	if (! (*devlist)[index])
+	  goto error;
+	index++;
+      }
+    IOObjectRelease (device);
+  }
 
-      (*devlist)[index] = CustomStrDup (devName, true, __LINE__, __FILE__);
-      if (! (*devlist)[index])
-	goto error;
-    }
   IOObjectRelease (i);
-
   return result;
 
  error:
+  if (device != MACH_PORT_NULL)
+    IOObjectRelease (device);
   IOObjectRelease (i);
   if (*devlist)
     {
@@ -140,7 +187,6 @@ int make_device_names (char*** devlist, const char* name) {
 
 static struct {
   io_object_t ioob;
-  bool hassmart;
   IOCFPlugInInterface **plugin;
   IOATASMARTInterface **smartIf;
 } devices[20];
@@ -203,44 +249,24 @@ int deviceopen(const char *pathname, char *type){
       return -1;
     }
   
-  // Find the ATA block storage driver that is the parent of this device
-  while (! IOObjectConformsTo (disk, kIOATABlockStorageDeviceClass))
+  // Find a SMART-capable driver which is a parent of this device.
+  while (! is_smart_capable (disk))
     {
       IOReturn err;
-      io_object_t notdisk = disk;
+      io_object_t prevdisk = disk;
 
-      err = IORegistryEntryGetParentEntry (notdisk, kIOServicePlane, &disk);
+      // Find this device's parent and try again.
+      err = IORegistryEntryGetParentEntry (disk, kIOServicePlane, &disk);
       if (err != kIOReturnSuccess || ! disk)
 	{
 	  errno = ENODEV;
-	  IOObjectRelease (notdisk);
+	  IOObjectRelease (prevdisk);
 	  return -1;
 	}
     }
-
-  devices[devnum].ioob = disk;
-  
-  {
-    CFDictionaryRef diskChars = NULL;
-    CFNumberRef diskFeatures = NULL;
-    UInt32 ataFeatures;
-
-    // Determine whether the drive actually supports SMART.
-    if ((diskChars = IORegistryEntryCreateCFProperty (disk, 
-			      CFSTR (kIOPropertyDeviceCharacteristicsKey),
-						      kCFAllocatorDefault,
-						      kNilOptions)) != NULL
-	&& CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"),
-					  (const void **)&diskFeatures)
-	&& CFNumberGetValue (diskFeatures, kCFNumberLongType, &ataFeatures)
-	&& (ataFeatures & kIOATAFeatureSMART))
-      devices[devnum].hassmart = true;
-    else
-      devices[devnum].hassmart = false;
-    if (diskChars)
-      CFRelease (diskChars);
-  }
   
+  devices[devnum].ioob = disk;
+
   {
     SInt32 dummy;
   
@@ -248,12 +274,11 @@ int deviceopen(const char *pathname, char *type){
     devices[devnum].smartIf = NULL;
 
     // Create an interface to the ATA SMART library.
-    if (devices[devnum].hassmart
-	&& IOCreatePlugInInterfaceForService (disk,
-					      kIOATASMARTUserClientTypeID,
-					      kIOCFPlugInInterfaceID,
-					      &devices[devnum].plugin,
-					      &dummy) == kIOReturnSuccess)
+    if (IOCreatePlugInInterfaceForService (disk,
+					   kIOATASMARTUserClientTypeID,
+					   kIOCFPlugInInterfaceID,
+					   &devices[devnum].plugin,
+					   &dummy) == kIOReturnSuccess)
       (*devices[devnum].plugin)->QueryInterface
 	(devices[devnum].plugin,
 	 CFUUIDGetUUIDBytes ( kIOATASMARTInterfaceID),
@@ -301,10 +326,6 @@ int deviceclose(int fd){
 // have a buggy library that treats the boolean value in
 // SMARTEnableDisableOperations, SMARTEnableDisableAutosave, and
 // SMARTExecuteOffLineImmediate as always being true.
-int marvell_command_interface(int fd, smart_command_set command,
-		      int select, char *data)
-{ return -1; }
- 
 int
 ata_command_interface(int fd, smart_command_set command,
 		      int select, char *data)
@@ -312,72 +333,83 @@ ata_command_interface(int fd, smart_command_set command,
   IOATASMARTInterface **ifp = devices[fd].smartIf;
   IOATASMARTInterface *smartIf;
   IOReturn err;
+  int timeoutCount = 2;
   
   if (! ifp)
     return -1;
   smartIf = *ifp;
 
-  switch (command)
-    {
-    case STATUS:
-      return 0;
-    case STATUS_CHECK:
+  do {
+    switch (command)
       {
-	Boolean is_failing;
-	err = smartIf->SMARTReturnStatus (ifp, &is_failing);
-	if (err == kIOReturnSuccess && is_failing)
-	  return 1;
-	break;
-      }
-    case ENABLE:
-    case DISABLE:
-      err = smartIf->SMARTEnableDisableOperations (ifp, command == ENABLE);
-      break;
-    case AUTOSAVE:
-      err = smartIf->SMARTEnableDisableAutosave (ifp, select != 0);
-      break;
-    case IMMEDIATE_OFFLINE:
-      if (select != SHORT_SELF_TEST && select != EXTEND_SELF_TEST)
+      case STATUS:
+	return 0;
+      case STATUS_CHECK:
 	{
-	  errno = EINVAL;
-	  return -1;
+	  Boolean is_failing;
+	  err = smartIf->SMARTReturnStatus (ifp, &is_failing);
+	  if (err == kIOReturnSuccess && is_failing)
+	    return 1;
+	  break;
 	}
-      err = smartIf->SMARTExecuteOffLineImmediate (ifp, 
-						   select == EXTEND_SELF_TEST);
-      break;
-    case READ_VALUES:
-      err = smartIf->SMARTReadData (ifp, (ATASMARTData *)data);
-      break;
-    case READ_THRESHOLDS:
-      err = smartIf->SMARTReadDataThresholds (ifp, 
-					      (ATASMARTDataThresholds *)data);
-      break;
-    case READ_LOG:
-      err = smartIf->SMARTReadLogAtAddress (ifp, select, data, 512);
-      break;
-    case WRITE_LOG:
-      err = smartIf->SMARTWriteLogAtAddress (ifp, select, data, 512);
-      break;
-    case IDENTIFY:
-      {
-	UInt32 dummy;
-	err = smartIf->GetATAIdentifyData (ifp, data, 512, &dummy);
-	if (err == kIOReturnSuccess && isbigendian())
+      case ENABLE:
+      case DISABLE:
+	err = smartIf->SMARTEnableDisableOperations (ifp, command == ENABLE);
+	break;
+      case AUTOSAVE:
+	err = smartIf->SMARTEnableDisableAutosave (ifp, select != 0);
+	break;
+      case IMMEDIATE_OFFLINE:
+	if (select != SHORT_SELF_TEST && select != EXTEND_SELF_TEST)
 	  {
-	    int i;
-	    /* The system has already byte-swapped, undo it.  */
-	    for (i = 0; i < 256; i+=2)
-	      swap2 (data + i);
+	    errno = EINVAL;
+	    return -1;
 	  }
+	err = smartIf->SMARTExecuteOffLineImmediate (ifp, 
+						     select == EXTEND_SELF_TEST);
+	break;
+      case READ_VALUES:
+	err = smartIf->SMARTReadData (ifp, (ATASMARTData *)data);
+	break;
+      case READ_THRESHOLDS:
+	err = smartIf->SMARTReadDataThresholds (ifp, 
+						(ATASMARTDataThresholds *)data);
+	break;
+      case READ_LOG:
+	err = smartIf->SMARTReadLogAtAddress (ifp, select, data, 512);
+	break;
+      case WRITE_LOG:
+	err = smartIf->SMARTWriteLogAtAddress (ifp, select, data, 512);
+	break;
+      case IDENTIFY:
+	{
+	  UInt32 dummy;
+	  err = smartIf->GetATAIdentifyData (ifp, data, 512, &dummy);
+	  if (err != kIOReturnSuccess)
+	    printf ("identify failed: %d\n", (int) err);
+	  if (err == kIOReturnSuccess && isbigendian())
+	    {
+	      int i;
+	      /* The system has already byte-swapped, undo it.  */
+	      for (i = 0; i < 256; i+=2)
+		swap2 (data + i);
+	    }
+	}
+	break;
+      case CHECK_POWER_MODE:
+	// The information is right there in the device registry, but how
+	// to get to it portably?
+      default:
+	errno = ENOTSUP;
+	return -1;
       }
-      break;
-    case CHECK_POWER_MODE:
-      // The information is right there in the device registry, but how
-      // to get to it portably?
-    default:
-      errno = ENOTSUP;
-      return -1;
-    }
+    /* This bit is a bit strange.  Apparently, when the drive is spun
+       down, the intended behaviour of these calls is that they fail,
+       return kIOReturnTimeout and then power the drive up.  So if
+       you get a timeout, you have to try again to get the actual
+       command run, but the drive is already powering up so you can't
+       use this for CHECK_POWER_MODE.  */
+  } while (err == kIOReturnTimeout && timeoutCount-- > 0);
   if (err == kIOReturnExclusiveAccess)
     errno = EBUSY;
   return err == kIOReturnSuccess ? 0 : -1;
@@ -398,7 +430,20 @@ int escalade_command_interface(int fd, int escalade_port, int escalade_type,
   return -1;
 }
 
+int marvell_command_interface(int fd, smart_command_set command,
+		      int select, char *data)
+{ 
+  fd = fd;
+  command = command;
+  select = select;
+  data = data;
+  return -1;
+}
+ 
 // Interface to SCSI devices.  See os_linux.c
 int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) {
+  fd = fd;
+  iop = iop;
+  report = report;
   return -ENOSYS;
 }