diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index d38b8dfb8ccfb6966bd35a51f266dfe490b87de3..5b44522592ce283fbe82616551aee1125ccfca36 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,43 +1,48 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.449 2004/08/17 19:31:50 chrfranke Exp $
+$Id: CHANGELOG,v 1.450 2004/08/18 19:27:44 likewise Exp $
 
 The most recent version of this file is:
 http://cvs.sourceforge.net/viewcvs.py/smartmontools/sm5/CHANGELOG?sortby=date&view=markup
 
 Maintainers / Developers Key:
 [BA] Bruce Allen
-[EB] Erik Inge Bols�
+[EB] Erik Inge Bols�
 [SB] Stanislav Brabec
 [PC] Peter Cassidy
 [CD] Caper Dik
 [CF] Christian Franke
-[GF] Guilhem Fr�zou
+[GF] Guilhem Fr�zou
 [DG] Douglas Gilbert
 [GG] Guido Guenther
 [GK] Geoff Keating
 [DK] Dr. David Kirkby
-[KM] Kai M�kisara
+[KM] Kai M�kisara
 [EM] Eduard Martinescu
-[FM] Fr�d�ric L. W. Meunier
+[FM] Fr�d�ric L. W. Meunier
 [KS] Keiji Sawada
 [SS] Sergey Svishchev
 [PW] Phil Williams
+[LW] Leon Woestenberg
 [RZ] Richard Zybert
 
 NOTES FOR FUTURE RELEASES: see TODO file.
 
 <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED JUST BELOW HERE, PLEASE>
 
+  [LW] Tested the RELEASE_5_33_WITH_MARVELL_SUPPORT branch on
+       actual Marvell 88SX5041 hardware, with success.
+       Merged into HEAD.
+
   [BA] Fixed nasty DEVICESCAN bug
 
+  [BA] Checked in RELEASE_5_33_WITH_MARVELL_SUPPORT branch with
+       some Marvell support.
+
   [BA] Additional modifications of Ed's controller scheme.  Fixed
        broken 3ware support under linux, problems with scanning
        devices in smartd, and other small problems.
 
-  [CF] Added make targets to build formatted man pages (htmlman, txtman),
-       Windows distribution (dist-win32) and MSVC6 config.h (config-vc6).
-
   [EM] Minor change to FreeBSD inclusion of 'twe' include files.  Add 
        code to check if they exising in /usr/include/sys to use those
        in preference to ones added here
diff --git a/sm5/README b/sm5/README
index 5ecca0b6acbdab96147b8640c002f663f61f6530..04da97428634a077ef794cf3ac56aa7bff170130 100644
--- a/sm5/README
+++ b/sm5/README
@@ -2,7 +2,7 @@
 smartmontools - S.M.A.R.T. utility toolset for Linux
 ====================================================
 
-$Id: README,v 1.50 2004/05/03 15:58:33 ballen4705 Exp $
+$Id: README,v 1.51 2004/08/18 19:27:44 likewise Exp $
 
 == HOME ==
 The home for smartmontools is located at:
@@ -103,3 +103,25 @@ Refer to the "INSTALL" file for installation instructions.
 
 See the "WARNINGS" file for reports of hardware where these utilities
 might cause serious problems such as lockups.
+
+== GETTING STARTED ==
+
+To examine SMART data from a disk, try:
+  smartctl -a /dev/hda
+for ATA disks, or
+  smartctl -a /dev/sda
+for SCSI disks.  See the manual page 'man smartctl' for more
+information.
+
+To start automatic monitoring of your disks with the smartd daemon,
+try:
+  smartd -d
+to start the daemon in foreground (debug) mode, or
+  smartd
+to start the daemon in background mode.  This will log messages to
+SYSLOG.  If you would like to get email warning messages, please set
+up the configuration file smartd.conf with the '-m' mail warning
+Directive.  See the manual page 'man smartd' for more information.
+
+
+
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index b2b8d4cd4216a339e8c577a092a6aca760a8db6f..fca2f62385bc18aeb69df4c08826379df0bd0256 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -35,7 +35,7 @@
 #include "extern.h"
 #include "utility.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.160 2004/08/16 22:44:26 ballen4705 Exp $"
+const char *atacmds_c_cvsid="$Id: atacmds.c,v 1.161 2004/08/18 19:27:44 likewise Exp $"
 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -609,6 +609,9 @@ int smartcommandhandler(int device, smart_command_set command, int select, char
   case CONTROLLER_3WARE_9000_CHAR:
     retval=escalade_command_interface(device, con->controller_port-1, con->controller_type, command, select, data);
     break;
+  case CONTROLLER_MARVELL_SATA:
+    retval=marvell_command_interface(device, command, select, data);
+    break;
   default:
     retval=ata_command_interface(device, command, select, data);
   }
@@ -768,7 +771,7 @@ int ataVersionInfo (const char** description, struct ata_identify_device *drive,
   if (i==0)
     return 1;
   else
-    return i;;
+    return i;
 }
 
 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index 5c1ffd0148b4915890294df9f43dbbef3f82f0da..23fe72580057994bd4240ea3072811c98c387e91 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -35,7 +35,7 @@
 #include "extern.h"
 #include "utility.h"
 
-const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.160 2004/08/16 22:44:26 ballen4705 Exp $"
+const char *atacmds_c_cvsid="$Id: atacmds.cpp,v 1.161 2004/08/18 19:27:44 likewise Exp $"
 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -609,6 +609,9 @@ int smartcommandhandler(int device, smart_command_set command, int select, char
   case CONTROLLER_3WARE_9000_CHAR:
     retval=escalade_command_interface(device, con->controller_port-1, con->controller_type, command, select, data);
     break;
+  case CONTROLLER_MARVELL_SATA:
+    retval=marvell_command_interface(device, command, select, data);
+    break;
   default:
     retval=ata_command_interface(device, command, select, data);
   }
@@ -768,7 +771,7 @@ int ataVersionInfo (const char** description, struct ata_identify_device *drive,
   if (i==0)
     return 1;
   else
-    return i;;
+    return i;
 }
 
 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
diff --git a/sm5/atacmds.h b/sm5/atacmds.h
index 4b5b710bc12b5427934388aa3a7c8dd0d49f49d1..03593e0f208e9d7ad9fb819be3b8fb20419a9b64 100644
--- a/sm5/atacmds.h
+++ b/sm5/atacmds.h
@@ -25,7 +25,7 @@
 #ifndef ATACMDS_H_
 #define ATACMDS_H_
 
-#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.72 2004/07/26 21:15:21 ballen4705 Exp $\n"
+#define ATACMDS_H_CVSID "$Id: atacmds.h,v 1.73 2004/08/18 19:27:44 likewise Exp $\n"
 
 #include "int64.h"
 
@@ -491,6 +491,7 @@ char *create_vendor_attribute_arg_list(void);
 // to be ported to get smartmontools onto another OS.
 int ata_command_interface(int device, smart_command_set command, int select, char *data);
 int escalade_command_interface(int fd, int escalade_port, int escalade_type, smart_command_set command, int select, char *data);
+int marvell_command_interface(int device, smart_command_set command, int select, char *data);
 
 // This function is exported to give low-level capability
 int smartcommandhandler(int device, smart_command_set command, int select, char *data);
diff --git a/sm5/os_darwin.c b/sm5/os_darwin.c
index 4922a19515b3a67602da4e52c64236d5a4fd0234..81353e3ab5201b80ab2999ffe107ce6dd72671fc 100644
--- a/sm5/os_darwin.c
+++ b/sm5/os_darwin.c
@@ -40,7 +40,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.7 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_darwin.c,v 1.8 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -300,6 +300,10 @@ 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)
diff --git a/sm5/os_darwin.cpp b/sm5/os_darwin.cpp
index 27d67a079e760069a33fca1ba844e0f83663e048..cb6fb61c02603a512fd49f5301f122831460638a 100644
--- a/sm5/os_darwin.cpp
+++ b/sm5/os_darwin.cpp
@@ -40,7 +40,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.7 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_darwin.cpp,v 1.8 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -300,6 +300,10 @@ 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)
diff --git a/sm5/os_freebsd.c b/sm5/os_freebsd.c
index 1cde13c0b01f49242b5b2ad68fce8465a57d57db..a4007596a5e75efffa7a809ba5f261541e4edfad 100644
--- a/sm5/os_freebsd.c
+++ b/sm5/os_freebsd.c
@@ -35,9 +35,9 @@
 #include "utility.h"
 #include "os_freebsd.h"
 
-static const char *filenameandversion="$Id: os_freebsd.c,v 1.40 2004/08/16 22:44:26 ballen4705 Exp $";
+static const char *filenameandversion="$Id: os_freebsd.c,v 1.41 2004/08/18 19:27:44 likewise Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.c,v 1.40 2004/08/16 22:44:26 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.c,v 1.41 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -217,6 +217,10 @@ void printwarning(int msgNo, const char* extra) {
 
 
 // Interface to ATA devices.  See os_linux.c
+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) {
 #ifndef ATAREQUEST
   // sorry, but without ATAng, we can't do anything here
@@ -767,7 +771,7 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel
   
   // if dev_name null, or string length zero
   if (!dev_name || !(len = strlen(dev_name)))
-    return CONTROLLER_UNKNOWN;;
+    return CONTROLLER_UNKNOWN;
   
   // Remove the leading /dev/... if it's there
   if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) {
diff --git a/sm5/os_freebsd.cpp b/sm5/os_freebsd.cpp
index 1bfc3a1babac2cb63bf91f20f8fc49ec75adda9e..4058bae1958868f19b9bc8e7dd61bc8f6283eb65 100644
--- a/sm5/os_freebsd.cpp
+++ b/sm5/os_freebsd.cpp
@@ -35,9 +35,9 @@
 #include "utility.h"
 #include "os_freebsd.h"
 
-static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.40 2004/08/16 22:44:26 ballen4705 Exp $";
+static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.41 2004/08/18 19:27:44 likewise Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.40 2004/08/16 22:44:26 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.41 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -217,6 +217,10 @@ void printwarning(int msgNo, const char* extra) {
 
 
 // Interface to ATA devices.  See os_linux.c
+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) {
 #ifndef ATAREQUEST
   // sorry, but without ATAng, we can't do anything here
@@ -767,7 +771,7 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel
   
   // if dev_name null, or string length zero
   if (!dev_name || !(len = strlen(dev_name)))
-    return CONTROLLER_UNKNOWN;;
+    return CONTROLLER_UNKNOWN;
   
   // Remove the leading /dev/... if it's there
   if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) {
diff --git a/sm5/os_generic.c b/sm5/os_generic.c
index 0101f3bdfb6e1af445bba9232b2d29a1abef0d2c..0695fa66d5548aa7981c2ac0cfd63391c554c317 100644
--- a/sm5/os_generic.c
+++ b/sm5/os_generic.c
@@ -55,7 +55,7 @@
 #include "os_generic.h"
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_generic.c,v 1.15 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_generic.c,v 1.16 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -187,6 +187,10 @@ int deviceclose(int fd){
 int ata_command_interface(int fd, smart_command_set command, int select, char *data){
   unsupported();
   return -1;
+
+int marvell_command_interface(int fd, smart_command_set command, int select, char *data){
+  unsupported();
+  return -1;
 }
 
 // Interface to ATA devices behind 3ware escalade RAID controller
diff --git a/sm5/os_generic.cpp b/sm5/os_generic.cpp
index 56d5858f7901a24383889cf36d9db438c0b528ad..560c99cd5e3eda007b2fa6a1a2e9273e95426aae 100644
--- a/sm5/os_generic.cpp
+++ b/sm5/os_generic.cpp
@@ -55,7 +55,7 @@
 #include "os_generic.h"
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_generic.cpp,v 1.15 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_generic.cpp,v 1.16 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -187,6 +187,10 @@ int deviceclose(int fd){
 int ata_command_interface(int fd, smart_command_set command, int select, char *data){
   unsupported();
   return -1;
+
+int marvell_command_interface(int fd, smart_command_set command, int select, char *data){
+  unsupported();
+  return -1;
 }
 
 // Interface to ATA devices behind 3ware escalade RAID controller
diff --git a/sm5/os_linux.c b/sm5/os_linux.c
index 28dbfd0ff875cb9cea27d020d77ef41c489dbaab..15cfafd61f51d3bd5f5df012ada2e586ce2520cf 100644
--- a/sm5/os_linux.c
+++ b/sm5/os_linux.c
@@ -70,9 +70,9 @@ typedef unsigned long long u8;
 
 #define ARGUSED(x) ((void)(x))
 
-static const char *filenameandversion="$Id: os_linux.c,v 1.70 2004/08/16 22:44:26 ballen4705 Exp $";
+static const char *filenameandversion="$Id: os_linux.c,v 1.71 2004/08/18 19:27:44 likewise Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.c,v 1.70 2004/08/16 22:44:26 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.c,v 1.71 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -488,7 +488,7 @@ int ata_command_interface(int device, smart_command_set command, int select, cha
     taskfile->feature        = ATA_SMART_WRITE_LOG_SECTOR;
     taskfile->sector_count   = 1;
     taskfile->sector_number  = select;
-    taskfile->low_cylinder   = 0x4f;;
+    taskfile->low_cylinder   = 0x4f;
     taskfile->high_cylinder  = 0xc2;
     taskfile->device_head    = 0;
     taskfile->command        = ATA_SMART_CMD;
@@ -1258,6 +1258,122 @@ int escalade_command_interface(int fd, int disknum, int escalade_type, smart_com
   return 0;
 }
 
+
+
+int marvell_command_interface(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] = ATA_SMART_CMD;
+  switch (command){
+  case READ_VALUES:
+    buff[2]=ATA_SMART_READ_VALUES;
+    copydata=buff[3]=1;
+    break;
+  case READ_THRESHOLDS:
+    buff[2]=ATA_SMART_READ_THRESHOLDS;
+    copydata=buff[1]=buff[3]=1;
+    break;
+  case READ_LOG:
+    buff[2]=ATA_SMART_READ_LOG_SECTOR;
+    buff[1]=select;
+    copydata=buff[3]=1;
+    break;
+  case IDENTIFY:
+    buff[0]=ATA_IDENTIFY_DEVICE;
+    copydata=buff[3]=1;
+    break;
+  case PIDENTIFY:
+    buff[0]=ATA_IDENTIFY_PACKET_DEVICE;
+    copydata=buff[3]=1;
+    break;
+  case ENABLE:
+    buff[2]=ATA_SMART_ENABLE;
+    buff[1]=1;
+    break;
+  case DISABLE:
+    buff[2]=ATA_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] = ATA_SMART_STATUS;
+    break;
+  case AUTO_OFFLINE:
+    buff[2]=ATA_SMART_AUTO_OFFLINE;
+    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
+    break;
+  case AUTOSAVE:
+    buff[2]=ATA_SMART_AUTOSAVE;
+    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
+    break;
+  case IMMEDIATE_OFFLINE:
+    buff[2]=ATA_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",PACKAGE_BUGREPORT);
+    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; 
+}
+
+
 // Utility function for printing warnings
 void printwarning(smart_command_set command){
   static int printed[4]={0,0,0,0};
diff --git a/sm5/os_linux.cpp b/sm5/os_linux.cpp
index 380b3a60c31d30be797d8a02115acec26b17a86b..d80605be9c84c07fcd2ec1c1046b86b58b3bfa4b 100644
--- a/sm5/os_linux.cpp
+++ b/sm5/os_linux.cpp
@@ -70,9 +70,9 @@ typedef unsigned long long u8;
 
 #define ARGUSED(x) ((void)(x))
 
-static const char *filenameandversion="$Id: os_linux.cpp,v 1.70 2004/08/16 22:44:26 ballen4705 Exp $";
+static const char *filenameandversion="$Id: os_linux.cpp,v 1.71 2004/08/18 19:27:44 likewise Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.70 2004/08/16 22:44:26 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.cpp,v 1.71 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
@@ -488,7 +488,7 @@ int ata_command_interface(int device, smart_command_set command, int select, cha
     taskfile->feature        = ATA_SMART_WRITE_LOG_SECTOR;
     taskfile->sector_count   = 1;
     taskfile->sector_number  = select;
-    taskfile->low_cylinder   = 0x4f;;
+    taskfile->low_cylinder   = 0x4f;
     taskfile->high_cylinder  = 0xc2;
     taskfile->device_head    = 0;
     taskfile->command        = ATA_SMART_CMD;
@@ -1258,6 +1258,122 @@ int escalade_command_interface(int fd, int disknum, int escalade_type, smart_com
   return 0;
 }
 
+
+
+int marvell_command_interface(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] = ATA_SMART_CMD;
+  switch (command){
+  case READ_VALUES:
+    buff[2]=ATA_SMART_READ_VALUES;
+    copydata=buff[3]=1;
+    break;
+  case READ_THRESHOLDS:
+    buff[2]=ATA_SMART_READ_THRESHOLDS;
+    copydata=buff[1]=buff[3]=1;
+    break;
+  case READ_LOG:
+    buff[2]=ATA_SMART_READ_LOG_SECTOR;
+    buff[1]=select;
+    copydata=buff[3]=1;
+    break;
+  case IDENTIFY:
+    buff[0]=ATA_IDENTIFY_DEVICE;
+    copydata=buff[3]=1;
+    break;
+  case PIDENTIFY:
+    buff[0]=ATA_IDENTIFY_PACKET_DEVICE;
+    copydata=buff[3]=1;
+    break;
+  case ENABLE:
+    buff[2]=ATA_SMART_ENABLE;
+    buff[1]=1;
+    break;
+  case DISABLE:
+    buff[2]=ATA_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] = ATA_SMART_STATUS;
+    break;
+  case AUTO_OFFLINE:
+    buff[2]=ATA_SMART_AUTO_OFFLINE;
+    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
+    break;
+  case AUTOSAVE:
+    buff[2]=ATA_SMART_AUTOSAVE;
+    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!
+    break;
+  case IMMEDIATE_OFFLINE:
+    buff[2]=ATA_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",PACKAGE_BUGREPORT);
+    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; 
+}
+
+
 // Utility function for printing warnings
 void printwarning(smart_command_set command){
   static int printed[4]={0,0,0,0};
diff --git a/sm5/os_netbsd.c b/sm5/os_netbsd.c
index 0b4cf959fdc561da07d4b4d7efb6333a8dac5d82..4ccb43d512b25cb542447213eef4c39a63069991 100644
--- a/sm5/os_netbsd.c
+++ b/sm5/os_netbsd.c
@@ -22,7 +22,7 @@
 #include "utility.h"
 #include "os_netbsd.h"
 
-const char *os_XXXX_c_cvsid = "$Id: os_netbsd.c,v 1.8 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid = "$Id: os_netbsd.c,v 1.9 2004/08/18 19:27:36 likewise Exp $" \
 ATACMDS_H_CVSID OS_NETBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 /* global variable holding byte count of allocated memory */
@@ -165,6 +165,10 @@ deviceclose(int fd)
   return close(fd);
 }
 
+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)
 {
diff --git a/sm5/os_netbsd.cpp b/sm5/os_netbsd.cpp
index 255ec8ba294c7b84dde97189cffe4331cced18cc..cb6efef99ecbaf1c258131ef807e048700b953a3 100644
--- a/sm5/os_netbsd.cpp
+++ b/sm5/os_netbsd.cpp
@@ -22,7 +22,7 @@
 #include "utility.h"
 #include "os_netbsd.h"
 
-const char *os_XXXX_c_cvsid = "$Id: os_netbsd.cpp,v 1.8 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid = "$Id: os_netbsd.cpp,v 1.9 2004/08/18 19:27:36 likewise Exp $" \
 ATACMDS_H_CVSID OS_NETBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 /* global variable holding byte count of allocated memory */
@@ -165,6 +165,10 @@ deviceclose(int fd)
   return close(fd);
 }
 
+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)
 {
diff --git a/sm5/os_solaris.c b/sm5/os_solaris.c
index 4a74980a168da73c4dc632b133146e614be04a30..d391ed756f2f4a20c207e32bedff9eb937739547 100644
--- a/sm5/os_solaris.c
+++ b/sm5/os_solaris.c
@@ -35,9 +35,9 @@
 
 extern long long bytes;
 
-static const char *filenameandversion="$Id: os_solaris.c,v 1.19 2004/08/13 13:57:12 arvoreen Exp $";
+static const char *filenameandversion="$Id: os_solaris.c,v 1.20 2004/08/18 19:27:44 likewise Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_solaris.c,v 1.19 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_solaris.c,v 1.20 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // The printwarning() function warns about unimplemented functions
@@ -278,6 +278,10 @@ static void swap_sector(void *p)
 }
 
 // Interface to ATA devices.  See os_linux.c
+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){
 #if defined(__sparc)
     int err;
diff --git a/sm5/os_solaris.cpp b/sm5/os_solaris.cpp
index ddf2ab4e6e84f56b113529cdb333951b3487a814..149eef5133b18ecfb57fd6ed8fbc136e34d3f62f 100644
--- a/sm5/os_solaris.cpp
+++ b/sm5/os_solaris.cpp
@@ -35,9 +35,9 @@
 
 extern long long bytes;
 
-static const char *filenameandversion="$Id: os_solaris.cpp,v 1.19 2004/08/13 13:57:12 arvoreen Exp $";
+static const char *filenameandversion="$Id: os_solaris.cpp,v 1.20 2004/08/18 19:27:44 likewise Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp,v 1.19 2004/08/13 13:57:12 arvoreen Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp,v 1.20 2004/08/18 19:27:44 likewise Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // The printwarning() function warns about unimplemented functions
@@ -278,6 +278,10 @@ static void swap_sector(void *p)
 }
 
 // Interface to ATA devices.  See os_linux.c
+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){
 #if defined(__sparc)
     int err;
diff --git a/sm5/os_win32.c b/sm5/os_win32.c
index 7885eda26a09f294ef1503b94dd9dfd0b78568b3..96ef1f962dd29a5178a1e2c12229c1e3e1145b71 100644
--- a/sm5/os_win32.c
+++ b/sm5/os_win32.c
@@ -39,7 +39,7 @@ extern int64_t bytes; // malloc() byte count
 #define ARGUSED(x) ((void)(x))
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_win32.c,v 1.16 2004/08/13 13:57:12 arvoreen Exp $"
+const char *os_XXXX_c_cvsid="$Id: os_win32.c,v 1.17 2004/08/18 19:27:44 likewise Exp $"
 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -658,6 +658,9 @@ static unsigned ata_scan()
 /////////////////////////////////////////////////////////////////////////////
 
 // Interface to ATA devices.  See os_linux.c
+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)
 {
 	IDEREGS regs;
diff --git a/sm5/os_win32.cpp b/sm5/os_win32.cpp
index c21b201d1ed2cac78ccc60820e206d4619e1331c..a78b1a235c374e0c4e53e9b2ba41affd9305cf89 100644
--- a/sm5/os_win32.cpp
+++ b/sm5/os_win32.cpp
@@ -39,7 +39,7 @@ extern int64_t bytes; // malloc() byte count
 #define ARGUSED(x) ((void)(x))
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_win32.cpp,v 1.16 2004/08/13 13:57:12 arvoreen Exp $"
+const char *os_XXXX_c_cvsid="$Id: os_win32.cpp,v 1.17 2004/08/18 19:27:44 likewise Exp $"
 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -658,6 +658,9 @@ static unsigned ata_scan()
 /////////////////////////////////////////////////////////////////////////////
 
 // Interface to ATA devices.  See os_linux.c
+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)
 {
 	IDEREGS regs;
diff --git a/sm5/smartctl.c b/sm5/smartctl.c
index 3cc41e9295c2a49d064d8cec36a22f443402a817..6f23577e84da9ce8ac32d63d39e1fc1938303505 100644
--- a/sm5/smartctl.c
+++ b/sm5/smartctl.c
@@ -51,7 +51,7 @@ extern const char *os_solaris_ata_s_cvsid;
 extern const char *int64_vc6_c_cvsid;
 #endif
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid;
-const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.134 2004/08/16 22:44:27 ballen4705 Exp $"
+const char* smartctl_c_cvsid="$Id: smartctl.c,v 1.135 2004/08/18 19:27:45 likewise Exp $"
 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // This is a block containing all the "control variables".  We declare
@@ -142,7 +142,7 @@ void Usage (void){
 "  -q TYPE, --quietmode=TYPE                                           (ATA)\n"
 "         Set smartctl quiet mode to one of: errorsonly, silent\n\n"
 "  -d TYPE, --device=TYPE\n"
-"         Specify device type to one of: ata, scsi, 3ware,N\n\n"
+"         Specify device type to one of: ata, scsi, marvell, 3ware,N\n\n"
 "  -T TYPE, --tolerance=TYPE                                           (ATA)\n"
 "         Tolerance: normal, conservative, permissive, verypermissive\n\n"
 "  -b TYPE, --badsum=TYPE                                              (ATA)\n"
@@ -370,6 +370,9 @@ void ParseOpts (int argc, char** argv){
       } else if (!strcmp(optarg,"scsi")) {
 	con->controller_type = CONTROLLER_SCSI;
         con->controller_port = 0;
+      } else if (!strcmp(optarg,"marvell")) {
+	con->controller_type = CONTROLLER_MARVELL_SATA;
+        con->controller_port = 0;
       } else {
         // look for RAID-type device
         int i;
@@ -841,18 +844,17 @@ int main (int argc, char **argv){
   case CONTROLLER_SCSI:
     mode="SCSI";
     break;
-  case CONTROLLER_ATA:
-  case CONTROLLER_3WARE_678K:
-    mode="ATA";
-    break;
   case CONTROLLER_3WARE_9000_CHAR:
     mode="ATA_3WARE_9000";
     break;
   case CONTROLLER_3WARE_678K_CHAR:
     mode="ATA_3WARE_678K";
     break;
+  default:
+    mode="ATA";
+    break;
   }
-
+  
   // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the
   // scsi generic device can be used (needs write permission for MODE 
   // SELECT command) plus O_NONBLOCK to stop open hanging if media not
@@ -870,19 +872,18 @@ int main (int argc, char **argv){
 
   // now call appropriate ATA or SCSI routine
   switch (con->controller_type) {
-  case CONTROLLER_ATA:
-  case CONTROLLER_3WARE_678K:
-  case CONTROLLER_3WARE_9000_CHAR:
-  case CONTROLLER_3WARE_678K_CHAR:
-    retval = ataPrintMain(fd);
+  case CONTROLLER_UNKNOWN:
+    // we should never fall into this branch!
+    pout("Smartctl: please specify device type with the -d option.\n");
+    UsageSummary();
+    retval = FAILCMD;
     break;
   case CONTROLLER_SCSI:
     retval = scsiPrintMain(fd);
     break;
   default:
-    pout("Smartctl: specify if this is an ATA or SCSI device with the -d option.\n");
-    UsageSummary();
-    return FAILCMD;
+    retval = ataPrintMain(fd);
+    break;
   }
   
   return retval;
diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp
index 05d2f4964993042f686fd976605b85e1a9df3de9..06b627e79e41223f9aeabb753244f5037a1fe1e1 100644
--- a/sm5/smartctl.cpp
+++ b/sm5/smartctl.cpp
@@ -51,7 +51,7 @@ extern const char *os_solaris_ata_s_cvsid;
 extern const char *int64_vc6_c_cvsid;
 #endif
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid;
-const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.134 2004/08/16 22:44:27 ballen4705 Exp $"
+const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.135 2004/08/18 19:27:45 likewise Exp $"
 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID;
 
 // This is a block containing all the "control variables".  We declare
@@ -142,7 +142,7 @@ void Usage (void){
 "  -q TYPE, --quietmode=TYPE                                           (ATA)\n"
 "         Set smartctl quiet mode to one of: errorsonly, silent\n\n"
 "  -d TYPE, --device=TYPE\n"
-"         Specify device type to one of: ata, scsi, 3ware,N\n\n"
+"         Specify device type to one of: ata, scsi, marvell, 3ware,N\n\n"
 "  -T TYPE, --tolerance=TYPE                                           (ATA)\n"
 "         Tolerance: normal, conservative, permissive, verypermissive\n\n"
 "  -b TYPE, --badsum=TYPE                                              (ATA)\n"
@@ -370,6 +370,9 @@ void ParseOpts (int argc, char** argv){
       } else if (!strcmp(optarg,"scsi")) {
 	con->controller_type = CONTROLLER_SCSI;
         con->controller_port = 0;
+      } else if (!strcmp(optarg,"marvell")) {
+	con->controller_type = CONTROLLER_MARVELL_SATA;
+        con->controller_port = 0;
       } else {
         // look for RAID-type device
         int i;
@@ -841,18 +844,17 @@ int main (int argc, char **argv){
   case CONTROLLER_SCSI:
     mode="SCSI";
     break;
-  case CONTROLLER_ATA:
-  case CONTROLLER_3WARE_678K:
-    mode="ATA";
-    break;
   case CONTROLLER_3WARE_9000_CHAR:
     mode="ATA_3WARE_9000";
     break;
   case CONTROLLER_3WARE_678K_CHAR:
     mode="ATA_3WARE_678K";
     break;
+  default:
+    mode="ATA";
+    break;
   }
-
+  
   // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the
   // scsi generic device can be used (needs write permission for MODE 
   // SELECT command) plus O_NONBLOCK to stop open hanging if media not
@@ -870,19 +872,18 @@ int main (int argc, char **argv){
 
   // now call appropriate ATA or SCSI routine
   switch (con->controller_type) {
-  case CONTROLLER_ATA:
-  case CONTROLLER_3WARE_678K:
-  case CONTROLLER_3WARE_9000_CHAR:
-  case CONTROLLER_3WARE_678K_CHAR:
-    retval = ataPrintMain(fd);
+  case CONTROLLER_UNKNOWN:
+    // we should never fall into this branch!
+    pout("Smartctl: please specify device type with the -d option.\n");
+    UsageSummary();
+    retval = FAILCMD;
     break;
   case CONTROLLER_SCSI:
     retval = scsiPrintMain(fd);
     break;
   default:
-    pout("Smartctl: specify if this is an ATA or SCSI device with the -d option.\n");
-    UsageSummary();
-    return FAILCMD;
+    retval = ataPrintMain(fd);
+    break;
   }
   
   return retval;
diff --git a/sm5/smartd.c b/sm5/smartd.c
index ca7dfad94ea839268b26d69b44d8d6c6fcac6b7b..579d4f3570afc779d7f4fcbab46ef1b1e0fceb48 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -108,7 +108,7 @@ int getdomainname(char *, int); /* no declaration in header files! */
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, 
                   *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
 
-static const char *filenameandversion="$Id: smartd.c,v 1.334 2004/08/17 18:16:59 ballen4705 Exp $";
+static const char *filenameandversion="$Id: smartd.c,v 1.335 2004/08/18 19:27:40 likewise Exp $";
 #ifdef NEED_SOLARIS_ATA_CODE
 extern const char *os_solaris_ata_s_cvsid;
 #endif
@@ -118,7 +118,7 @@ extern const char *daemon_win32_c_cvsid, *hostname_win32_c_cvsid, *syslog_win32_
 extern const char *int64_vc6_c_cvsid;
 #endif
 #endif
-const char *smartd_c_cvsid="$Id: smartd.c,v 1.334 2004/08/17 18:16:59 ballen4705 Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.c,v 1.335 2004/08/18 19:27:40 likewise Exp $" 
 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID
 #ifdef DAEMON_WIN32_H_CVSID
 DAEMON_WIN32_H_CVSID
@@ -707,6 +707,10 @@ void MailWarning(cfgfile *cfg, int which, char *fmt, ...){
     exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "ata");
     exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
     break;
+  case CONTROLLER_MARVELL_SATA:
+    exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "marvell");
+    exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
+    break;
   case CONTROLLER_SCSI:
     exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "scsi");
     exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
@@ -1044,7 +1048,7 @@ void PrintHead(){
 void Directives() {
   PrintOut(LOG_INFO,
            "Configuration file (%s) Directives (after device name):\n"
-           "  -d TYPE Set the device type: ata, scsi, removable, 3ware,N\n"
+           "  -d TYPE Set the device type: ata, scsi, marvell, removable, 3ware,N\n"
            "  -T TYPE Set the tolerance to one of: normal, permissive\n"
            "  -o VAL  Enable/disable automatic offline tests (on/off)\n"
            "  -S VAL  Enable/disable attribute autosave (on/off)\n"
@@ -1235,6 +1239,7 @@ int ATADeviceScan(cfgfile *cfg, int scanning){
   switch (cfg->controller_type) {
   case CONTROLLER_ATA:
   case CONTROLLER_3WARE_678K:
+  case CONTROLLER_MARVELL_SATA:
   case CONTROLLER_UNKNOWN:
     mode="ATA";
     break;
@@ -1500,7 +1505,7 @@ int ATADeviceScan(cfgfile *cfg, int scanning){
   
     // record number of device, type of device, increment device count
   if (cfg->controller_type == CONTROLLER_UNKNOWN)
-    cfg->controller_type=CONTROLLER_ATA;;
+    cfg->controller_type=CONTROLLER_ATA;
   
   // close file descriptor
   CloseDevice(fd, name);
@@ -2460,7 +2465,7 @@ void printoutvaliddirectiveargs(int priority, char d) {
     PrintOut(priority, "valid_regular_expression");
     break;
   case 'd':
-    PrintOut(priority, "ata, scsi, removable, 3ware,N");
+    PrintOut(priority, "ata, scsi, marvell, removable, 3ware,N");
     break;
   case 'T':
     PrintOut(priority, "normal, permissive");
@@ -2618,6 +2623,9 @@ int ParseToken(char *token,cfgfile *cfg){
     } else if (!strcmp(arg, "scsi")) {
       cfg->controller_port =0;
       cfg->controller_type = CONTROLLER_SCSI;
+    } else if (!strcmp(arg, "marvell")) {
+      cfg->controller_port =0;
+      cfg->controller_type = CONTROLLER_MARVELL_SATA;
     } else if (!strcmp(arg, "removable")) {
       cfg->removable = 1;
     } else {
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index 561f8fb83a7a6778f5d482f898ce8649c22a046d..4c7adbe56ee8e6d9e83551f2aa9ed61d957714f4 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -108,7 +108,7 @@ int getdomainname(char *, int); /* no declaration in header files! */
 extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *escalade_c_cvsid, 
                   *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *utility_c_cvsid;
 
-static const char *filenameandversion="$Id: smartd.cpp,v 1.334 2004/08/17 18:16:59 ballen4705 Exp $";
+static const char *filenameandversion="$Id: smartd.cpp,v 1.335 2004/08/18 19:27:40 likewise Exp $";
 #ifdef NEED_SOLARIS_ATA_CODE
 extern const char *os_solaris_ata_s_cvsid;
 #endif
@@ -118,7 +118,7 @@ extern const char *daemon_win32_c_cvsid, *hostname_win32_c_cvsid, *syslog_win32_
 extern const char *int64_vc6_c_cvsid;
 #endif
 #endif
-const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.334 2004/08/17 18:16:59 ballen4705 Exp $" 
+const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.335 2004/08/18 19:27:40 likewise Exp $" 
 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID
 #ifdef DAEMON_WIN32_H_CVSID
 DAEMON_WIN32_H_CVSID
@@ -707,6 +707,10 @@ void MailWarning(cfgfile *cfg, int which, char *fmt, ...){
     exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "ata");
     exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
     break;
+  case CONTROLLER_MARVELL_SATA:
+    exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "marvell");
+    exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
+    break;
   case CONTROLLER_SCSI:
     exportenv(environ_strings[8], "SMARTD_DEVICETYPE", "scsi");
     exportenv(environ_strings[9], "SMARTD_DEVICE", cfg->name);
@@ -1044,7 +1048,7 @@ void PrintHead(){
 void Directives() {
   PrintOut(LOG_INFO,
            "Configuration file (%s) Directives (after device name):\n"
-           "  -d TYPE Set the device type: ata, scsi, removable, 3ware,N\n"
+           "  -d TYPE Set the device type: ata, scsi, marvell, removable, 3ware,N\n"
            "  -T TYPE Set the tolerance to one of: normal, permissive\n"
            "  -o VAL  Enable/disable automatic offline tests (on/off)\n"
            "  -S VAL  Enable/disable attribute autosave (on/off)\n"
@@ -1235,6 +1239,7 @@ int ATADeviceScan(cfgfile *cfg, int scanning){
   switch (cfg->controller_type) {
   case CONTROLLER_ATA:
   case CONTROLLER_3WARE_678K:
+  case CONTROLLER_MARVELL_SATA:
   case CONTROLLER_UNKNOWN:
     mode="ATA";
     break;
@@ -1500,7 +1505,7 @@ int ATADeviceScan(cfgfile *cfg, int scanning){
   
     // record number of device, type of device, increment device count
   if (cfg->controller_type == CONTROLLER_UNKNOWN)
-    cfg->controller_type=CONTROLLER_ATA;;
+    cfg->controller_type=CONTROLLER_ATA;
   
   // close file descriptor
   CloseDevice(fd, name);
@@ -2460,7 +2465,7 @@ void printoutvaliddirectiveargs(int priority, char d) {
     PrintOut(priority, "valid_regular_expression");
     break;
   case 'd':
-    PrintOut(priority, "ata, scsi, removable, 3ware,N");
+    PrintOut(priority, "ata, scsi, marvell, removable, 3ware,N");
     break;
   case 'T':
     PrintOut(priority, "normal, permissive");
@@ -2618,6 +2623,9 @@ int ParseToken(char *token,cfgfile *cfg){
     } else if (!strcmp(arg, "scsi")) {
       cfg->controller_port =0;
       cfg->controller_type = CONTROLLER_SCSI;
+    } else if (!strcmp(arg, "marvell")) {
+      cfg->controller_port =0;
+      cfg->controller_type = CONTROLLER_MARVELL_SATA;
     } else if (!strcmp(arg, "removable")) {
       cfg->removable = 1;
     } else {
diff --git a/sm5/utility.h b/sm5/utility.h
index 6eb82431307cae2d1033d004bf1ba137a8a3e004..1c12940774d242d3bd4fd483fd733932efebff3d 100644
--- a/sm5/utility.h
+++ b/sm5/utility.h
@@ -25,7 +25,7 @@
 #ifndef UTILITY_H_
 #define UTILITY_H_
 
-#define UTILITY_H_CVSID "$Id: utility.h,v 1.37 2004/08/16 22:44:28 ballen4705 Exp $\n"
+#define UTILITY_H_CVSID "$Id: utility.h,v 1.38 2004/08/18 19:27:36 likewise Exp $\n"
 
 #include <time.h>
 #include <sys/types.h> // for regex.h (according to POSIX)
@@ -162,8 +162,10 @@ void MsecToText(unsigned int msec, char *txt);
 #define CONTROLLER_ATA                  0x01
 #define CONTROLLER_SCSI                 0x02
 #define CONTROLLER_3WARE                0x03  // set by -d option, but converted to one of three types below
-#define CONTROLLER_3WARE_678K      0x04  // NOT set by guess_device_type()
-#define CONTROLLER_3WARE_9000_CHAR 0x05  // set by guess_device_type()
-#define CONTROLLER_3WARE_678K_CHAR 0x06  // set by guess_device_type()
+#define CONTROLLER_3WARE_678K           0x04  // NOT set by guess_device_type()
+#define CONTROLLER_3WARE_9000_CHAR      0x05  // set by guess_device_type()
+#define CONTROLLER_3WARE_678K_CHAR      0x06  // set by guess_device_type()
+#define CONTROLLER_MARVELL_SATA         0x07  // SATA drives behind Marvell controllers
+
 
 #endif