diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index 471774084d3e02c763cd063d9e3eecc7d4b3b140..3b4673822d1d25a80e8ef00421e854459d6ce566 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -29,10 +29,11 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include "atacmds.h"
+#include "scsicmds.h"
 #include "utility.h"
 #include "extern.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.100 2003/06/12 12:18:53 ballen4705 Exp $" ATACMDS_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID;
+const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.100.2.1 2004/08/13 00:04:39 likewise Exp $" ATACMDS_H_CVSID EXTERN_H_CVSID UTILITY_H_CVSID;
 
 // for passing global control variables
 extern smartmonctrl *con;
@@ -446,7 +447,7 @@ char *create_vendor_attribute_arg_list(void){
 
 int os_specific_handler(int device, smart_command_set command, int select, char *data){
   unsigned char buff[STRANGE_BUFFER_LENGTH];
-  int retval, copydata=0;
+  int retval = 0, copydata = 0;
 
   // See struct hd_drive_cmd_hdr in hdreg.h
   // buff[0]: ATA COMMAND CODE REGISTER
@@ -562,6 +563,151 @@ int os_specific_handler(int device, smart_command_set command, int select, char
   return 0; 
 }
 
+// PURPOSE
+//   This is an interface routine meant to isolate the OS dependent
+//   parts of the code, and to provide a debugging interface.  Each
+//   different port and OS needs to provide it's own interface.  This
+//   is the linux one.
+// DESCRIPTION
+//   The function sends SCSI vendor-specific command 0xC (6 bytes long)followed
+//   by the data buffer representing ATA registers:
+//      buff[0]: ATA COMMAND CODE REGISTER
+//      buff[1]: ATA SECTOR NUMBER REGISTER
+//      buff[2]: ATA FEATURES REGISTER
+//      buff[3]: ATA SECTOR COUNT REGISTER
+//  (See struct hd_drive_cmd_hdr in hdreg.h)
+//
+// ARGUMENTS
+//   device: is the file descriptor provided by open()
+//   command: defines the different operations.
+//   select: additional input data if needed (which log, which type of
+//           self-test).
+//   data:   location to write output data, if needed (512 bytes).
+//   Note: not all commands use all arguments.
+// RETURN VALUES
+//  -1 if the command failed
+//   0 if the command succeeded,
+//   STATUS_CHECK routine: 
+//  -1 if the command failed
+//   0 if the command succeeded and disk SMART status is "OK"
+//   1 if the command succeeded and disk SMART status is "FAILING"
+
+int mvsata_os_specific_handler(int device, 
+                               smart_command_set command, 
+                               int select, 
+                               char *data)
+{  
+  typedef struct 
+  {  
+    int  inlen;
+    int  outlen;
+    char cmd[540];
+  } mvsata_scsi_cmd;
+
+  int copydata = 0;
+  mvsata_scsi_cmd  smart_command;
+  unsigned char *buff = &smart_command.cmd[6];
+  // See struct hd_drive_cmd_hdr in hdreg.h
+  // buff[0]: ATA COMMAND CODE REGISTER
+  // buff[1]: ATA SECTOR NUMBER REGISTER
+  // buff[2]: ATA FEATURES REGISTER
+  // buff[3]: ATA SECTOR COUNT REGISTER
+  
+  // clear out buff.  Large enough for HDIO_DRIVE_CMD (4+512 bytes)
+  memset(&smart_command, 0, sizeof(smart_command));
+  smart_command.inlen = 540;
+  smart_command.outlen = 540;
+  smart_command.cmd[0] = 0xC;  //Vendor-specific code
+  smart_command.cmd[4] = 6;     //command length
+  
+  buff[0] = WIN_SMART;
+  switch (command){
+  case READ_VALUES:
+    buff[2]=SMART_READ_VALUES;
+    copydata=buff[3]=1;
+    break;
+  case READ_THRESHOLDS:
+    buff[2]=SMART_READ_THRESHOLDS;
+    copydata=buff[1]=buff[3]=1;
+    break;
+  case READ_LOG:
+    buff[2]=SMART_READ_LOG_SECTOR;
+    buff[1]=select;
+    copydata=buff[3]=1;
+    break;
+  case IDENTIFY:
+    buff[0]=WIN_IDENTIFY;
+    copydata=buff[3]=1;
+    break;
+  case PIDENTIFY:
+    buff[0]=WIN_PIDENTIFY;
+    copydata=buff[3]=1;
+    break;
+  case ENABLE:
+    buff[2]=SMART_ENABLE;
+    buff[1]=1;
+    break;
+  case DISABLE:
+    buff[2]=SMART_DISABLE;
+    buff[1]=1;
+    break;
+  case STATUS:
+  case STATUS_CHECK:
+    // this command only says if SMART is working.  It could be
+    // replaced with STATUS_CHECK below.
+    buff[2] = SMART_STATUS;
+    break;
+  case AUTO_OFFLINE:
+    buff[2]=SMART_AUTO_OFFLINE;
+    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
+    break;
+  case AUTOSAVE:
+    buff[2]=SMART_AUTOSAVE;
+    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
+    break;
+  case IMMEDIATE_OFFLINE:
+    buff[2]=SMART_IMMEDIATE_OFFLINE;
+    buff[1]=select;
+    break;
+  default:
+    pout("Unrecognized command %d in mvsata_os_specific_handler()\n", command);
+    exit(1);
+    break;
+  }  
+  // There are two different types of ioctls().  The HDIO_DRIVE_TASK
+  // one is this:
+  // We are now doing the HDIO_DRIVE_CMD type ioctl.
+  if (ioctl(device, SCSI_IOCTL_SEND_COMMAND, (void *)&smart_command))
+      return -1;
+  //Data returned is starting from 0 offset  
+  if (command == STATUS || command == STATUS_CHECK)
+  {
+    // Cyl low and Cyl high unchanged means "Good SMART status"
+    if (buff[4] == 0x4F && buff[5] == 0xC2)
+      return 0;    
+    // These values mean "Bad SMART status"
+    if (buff[4] == 0xF4 && buff[5] == 0x2C)
+      return 1;    
+    // We haven't gotten output that makes sense; print out some debugging info
+    syserror("Error SMART Status command failed");
+    pout("Please get assistance from %s\n",PROJECTHOME);
+    pout("Register values returned from SMART Status command are:\n");
+    pout("CMD =0x%02x\n",(int)buff[0]);
+    pout("FR =0x%02x\n",(int)buff[1]);
+    pout("NS =0x%02x\n",(int)buff[2]);
+    pout("SC =0x%02x\n",(int)buff[3]);
+    pout("CL =0x%02x\n",(int)buff[4]);
+    pout("CH =0x%02x\n",(int)buff[5]);
+    pout("SEL=0x%02x\n",(int)buff[6]);
+    return -1;   
+  }  
+
+  if (copydata)
+    memcpy(data, buff, 512);
+  return 0; 
+}
+
+
 static char *commandstrings[]={
   [ENABLE]=           "SMART ENABLE",
   [DISABLE]=          "SMART DISABLE",
@@ -621,7 +767,15 @@ int smartcommandhandler(int device, smart_command_set command, int select, char
   }
   
   // now execute the command
-  retval=os_specific_handler(device, command, select, data);
+  /*Check for MVSATA controller*/
+  if (con->ismvsata) 
+  {
+    retval = mvsata_os_specific_handler(device, command, select, data);
+  }
+  else
+  {
+    retval = os_specific_handler(device, command, select, data);
+  }
   
   // If reporting is enabled, say what output was produced by the command
   if (con->reportataioctl){