]> git.proxmox.com Git - mirror_smartmontools-debian.git/commitdiff
Imported Upstream version 5.38+svn2956
authorGiuseppe Iuculano <iuculano@debian.org>
Sun, 11 Oct 2009 06:46:19 +0000 (08:46 +0200)
committerGiuseppe Iuculano <iuculano@debian.org>
Sun, 11 Oct 2009 06:46:19 +0000 (08:46 +0200)
13 files changed:
CHANGELOG
INSTALL
NEWS
atacmds.cpp
configure.in
os_freebsd.cpp
os_freebsd.h
os_linux.cpp
scsiata.cpp
scsicmds.h
smartctl.8.in
smartd.8.in
smartd.conf.5.in

index bf20752d0274a4b6da1c0ba5c20cae8fbeb1d5fd..dfe745f6c7a4f26eae5acd980c6f1fdf233521ce 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG 2918 2009-09-20 11:51:42Z samm2 $
+$Id: CHANGELOG 2951 2009-10-08 23:43:46Z samm2 $
 
 The most recent version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/CHANGELOG?view=markup
@@ -43,6 +43,44 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [AS] Linux: Autodetect DELL PERC and MegaRAID controllers. 
+       Hiding debug messages coming from megaraid code.  
+
+  [AS] Linux: Fixed SATA drives support on megaraid device (see ticket #15).
+
+  [AS] FreeBSD: Removed all old detection code, moving everything to
+       the objects. Now we are using CAM/ATA enumerators to guess device
+       type.
+
+  [AS] FreeBSD: Added autodetection for the ada disks (untested).
+       Code for USB device detection refactored.
+
+  [AS] FreeBSD: cam_get_umassno rewritten using XPT_PATH_INQ
+
+  [AS] FreeBSD: do not open/close cam device on every request for SCSI 
+       disks. Use com->camdev both for SCSI and ATAPICAM.
+
+  [AS] FreeBSD: added support for the ada disks, based on agapon patch
+
+  [CF] Add names for attributes 184 and 188, see ticket #17.
+
+  [CF] configure.in: Change configure date syntax.
+       Add message to '-mno-cygwin' option check.
+
+  [GK] Add names for some attributes used in MLC flash drives:
+       175, 176, 177, 181, 182
+
+  [CF] Windows: Check support of gcc '-mno-cygwin' option in configure.
+       This option has been removed in Cygwin gcc 4.x.  Update INSTALL
+       instructions accordingly.
+
+  [CF] Increase SCSI_TIMEOUT_DEFAULT from 6 to 20 seconds to avoid
+       timeouts when a disk spins up from standby mode.
+
+  [CF] Add USB ID of AcomData 504 (OnSpec USB bridge).
+
+  [AS] Correcting manual pages (FreeBSD related)
+
   [AS] FreeBSD: fix FTBFS on GNU/kFreeBSD (reported by derevko).
 
   [AS] FreeBSD: Add USB autodetection to smartd DEVICESCAN directive.
diff --git a/INSTALL b/INSTALL
index 5a6d880e46a7b7155f29aa213bf06d15f5e994ed..7af41e33a91a5e260d9f9227419f94096159213a 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
 Smartmontools installation instructions
 =======================================
 
-$Id: INSTALL 2844 2009-07-18 12:59:21Z chrfranke $
+$Id: INSTALL 2925 2009-10-02 20:45:54Z chrfranke $
 
 Please also see the smartmontools home page:
 http://smartmontools.sourceforge.net/
@@ -434,16 +434,32 @@ Same as Red Hat:
   instead. This is not necessary for the generated ./configure script.
 
 [10] Guidelines for Windows
-==========================
+===========================
 
-To compile the Windows release with MinGW, use the following on Cygwin:
+To compile the Windows release with MinGW gcc on MSYS, use:
 
-  ./configure --build=mingw32
+  ./configure
   make
 
   Instead of using "make install", copy the .exe files into
   some directory in the PATH.
 
+To compile with MinGW gcc 3.x on Cygwin, use:
+
+  ./configure --build=i686-pc-mingw32
+
+  The above does not work if gcc 4.x is installed and selected as
+  default by /usr/sbin/alternatives.  If the configure command aborts
+  with error message '... does not support -mno-cygwin', select
+  gcc 3.x by:
+
+  CC=gcc-3 CXX=g++-3 ./configure --build=i686-pc-mingw32
+
+  Alternatively, a MinGW-targeted cross-compiler can be used if available:
+
+  ./configure --build=i686-pc-cygwin --host=i686-pc-mingw32
+
+
 To build the Windows binary distribution, use:
 
   make dist-win32
diff --git a/NEWS b/NEWS
index 0591864c0fc12d58469bc02e66c7c95ff5b44e1a..4cc0395783ee2382039f22b8abab77364afc9a10 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
 smartmontools NEWS
 ------------------
-$Id: NEWS 2844 2009-07-18 12:59:21Z chrfranke $
+$Id: NEWS 2956 2009-10-11 00:21:15Z samm2 $
 
 The most up-to-date version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
@@ -10,7 +10,7 @@ Summary: smartmontools release 5.39 (UNSTABLE/EXPERIMENTAL)
 -----------------------------------------------------------
 - Sourcecode repository moved from CVS to SVN
 - Support for USB devices with Cypress, JMicron and Sunplus USB bridges
-- USB device type autodetection for some devices on Linux and Windows
+- USB device type autodetection for some devices on Linux,Windows and FreeBSD
   (http://smartmontools.wiki.sourceforge.net/overview_USB-Support)
 - Support for Areca controllers on Linux
 - Support for MegaRAID controllers on Linux
@@ -38,7 +38,7 @@ Summary: smartmontools release 5.39 (UNSTABLE/EXPERIMENTAL)
 - Option '-s PREFIX' to store smartd internal state until next startup
 - Configure option to enable the above by default
 - Change to an object oriented interface to access ATA and SCSI devices
-- Linux and Win32 modules migrated to new interface
+- Linux, Win32 and FreeBSD modules migrated to new interface
 - Rework of smartd data structures
 - Checkin date and SVN revision and optional BUILD_INFO printed in version info
 - Better support for gSmartControl on Windows
@@ -49,7 +49,8 @@ Summary: smartmontools release 5.39 (UNSTABLE/EXPERIMENTAL)
 - C++ Support for QNX Target, already tested for QNX 6.3.2 on x86 and
   armle target
 - Additional support for Samsung MLC flash drives
-
+- New device type detection algorithm on FreeBSD, not based on filename
+- Support for the adaX (ATA on CAM bus) devices on FreeBSD 8.0 and higher
 
 Date 2008-03-10
 Summary: smartmontools release 5.38 (STABLE)
index b5ecd02a2885c3e7bb817c7191cd7642376bf76b..eebff63531459f58643897d8a9c1dfbbde019c98 100644 (file)
@@ -37,7 +37,7 @@
 #include "utility.h"
 #include "dev_ata_cmd_set.h" // for parsed_ata_device
 
-const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 2872 2009-08-08 19:54:28Z chrfranke $"
+const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 2928 2009-10-03 16:24:53Z chrfranke $"
                                  ATACMDS_H_CVSID;
 
 // for passing global control variables
@@ -1985,6 +1985,15 @@ void ataPrintSmartAttribName(char * out, unsigned char id, const unsigned char *
   case 13:
     name="Read_Soft_Error_Rate";
     break;
+  case 175:
+    name="Program_Fail_Count_Chip";
+    break;
+  case 176:
+    name="Erase_Fail_Count_Chip";
+    break;
+  case 177:
+    name="Wear_Leveling_Count";
+    break;
   case 178:
     name="Used_Rsvd_Blk_Cnt_Chip";
     break;
@@ -1994,12 +2003,24 @@ void ataPrintSmartAttribName(char * out, unsigned char id, const unsigned char *
   case 180:
     name="Unused_Rsvd_Blk_Cnt_Tot";
     break;
+  case 181:
+    name="Program_Fail_Cnt_Total";
+    break;
+  case 182:
+    name="Erase_Fail_Count_Total";
+    break;
   case 183:
     name="Runtime_Bad_Block";
     break;
+  case 184:
+    name="End-to-End_Error";
+    break;
   case 187:
     name="Reported_Uncorrect";
     break;
+  case 188:
+    name="Command_Timeout";
+    break;
   case 189:
     name="High_Fly_Writes";
     break;
index 5c88a58c87d915f79f560fd4e7fecd51ae025e7e..e8ea75a66f016d346c07bc76b58291fad3529e77 100644 (file)
@@ -1,13 +1,13 @@
 #
-# $Id: configure.in 2890 2009-09-03 14:47:38Z samm2 $
+# $Id: configure.in 2927 2009-10-03 16:08:34Z chrfranke $
 #
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ(2.50)
 AC_INIT(smartmontools, 5.39, smartmontools-support@lists.sourceforge.net)
 AC_CONFIG_SRCDIR(smartctl.cpp)
 
-smartmontools_configure_date=`date -u +"%Y/%m/%d %T %Z"`
-smartmontools_cvs_tag=`echo '$Id: configure.in 2890 2009-09-03 14:47:38Z samm2 $'`
+smartmontools_configure_date=`date -u +'%Y-%m-%d %T %Z'`
+smartmontools_cvs_tag=`echo '$Id: configure.in 2927 2009-10-03 16:08:34Z chrfranke $'`
 smartmontools_release_date=2008/03/10
 smartmontools_release_time="10:44:07 GMT"
 
@@ -34,8 +34,23 @@ AC_CANONICAL_HOST
 dnl Set flags which may affect AC_CHECK_*.
 case "${host}" in
        *-*-mingw*)
-               CPPFLAGS="$CPPFLAGS -mno-cygwin"
-               LDFLAGS="$LDFLAGS -mno-cygwin"
+               # If building on Cygwin and not cross-compiling add '-mno-cygwin'
+               # to select MinGW gcc. This does no longer work for gcc 4.x.
+               if test "${build}" = "${host}" && test -x /usr/bin/uname && \
+                  /usr/bin/uname | grep -i '^CYGWIN' >/dev/null; then
+                 AC_MSG_CHECKING([whether C and C++ compiler support -mno-cygwin])
+                 gcc_support_m_no_cygwin=no
+                 if $CC  -v -mno-cygwin >/dev/null 2>&1 && \
+                    $CXX -v -mno-cygwin >/dev/null 2>&1; then
+                   gcc_support_m_no_cygwin=yes
+                 fi
+                 AC_MSG_RESULT([$gcc_support_m_no_cygwin])
+                 if test "$gcc_support_m_no_cygwin" != "yes"; then
+                   AC_MSG_ERROR([$CC and $CXX do not support -mno-cygwin, see INSTALL file for details.])
+                 fi
+                 CPPFLAGS="$CPPFLAGS -mno-cygwin"
+                 LDFLAGS="$LDFLAGS -mno-cygwin"
+               fi
                CPPFLAGS="$CPPFLAGS -idirafter ${srcdir}/posix -idirafter ${srcdir}/os_win32"
                ;;
        *-*-freebsd*)
index f92ab489791ab027753c4db054e4802ff87f2bc9..0f92fc0f023ce0996f769ee15a3006694d4bc36d 100644 (file)
 #include <dev/usb/usbhid.h>
 #endif
 
-#define CONTROLLER_UNKNOWN              0x00
-#define CONTROLLER_ATA                  0x01
-#define CONTROLLER_SCSI                 0x02
-#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_HPT                  0x09  // SATA drives behind HighPoint Raid controllers
-#define CONTROLLER_CCISS  0x10  // CCISS controller 
-
-static __unused const char *filenameandversion="$Id: os_freebsd.cpp 2920 2009-09-20 12:22:41Z samm2 $";
-
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 2920 2009-09-20 12:22:41Z samm2 $" \
-ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
-
-extern smartmonctrl * con;
+#define CONTROLLER_3WARE_9000_CHAR      0x01
+#define CONTROLLER_3WARE_678K_CHAR      0x02
 
-// Private table of open devices: guaranteed zero on startup since
-// part of static data.
-struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV];
+#ifndef PATHINQ_SETTINGS_SIZE
+#define PATHINQ_SETTINGS_SIZE   128
+#endif
 
-// Returns 1 if device not available/open/found else 0.  Also shifts fd into valid range.
-static int isnotopen(int *fd, struct freebsd_dev_channel** fdchan) {
-  // put valid "file descriptor" into range 0...FREEBSD_MAXDEV-1
-  *fd -= FREEBSD_FDOFFSET;
+static __unused const char *filenameandversion="$Id: os_freebsd.cpp 2955 2009-10-10 12:34:08Z samm2 $";
 
-  // check for validity of "file descriptor".
-  if (*fd<0 || *fd>=FREEBSD_MAXDEV || !((*fdchan)=devicetable[*fd])) {
-    errno = ENODEV;
-    return 1;
-  }
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 2955 2009-10-10 12:34:08Z samm2 $" \
+ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
-  return 0;
-}
+extern smartmonctrl * con;
 
 #define NO_RETURN 0
 #define BAD_SMART 1
@@ -141,19 +121,13 @@ void printwarning(int msgNo, const char* extra) {
 // global variable holding byte count of allocated memory
 long long bytes;
 
-const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 2920 2009-09-20 12:22:41Z samm2 $"
+const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 2955 2009-10-10 12:34:08Z samm2 $"
   DEV_INTERFACE_H_CVSID;
 
 extern smartmonctrl * con; // con->reportscsiioctl
 
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_ATA_IDENTIFY_IS_CACHED
-int ata_identify_is_cached(int fd);
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-
 namespace os_freebsd { // No need to publish anything, name provided for Doxygen
 
 /////////////////////////////////////////////////////////////////////////////
@@ -180,6 +154,9 @@ protected:
   int get_fd() const
     { return m_fd; }
 
+  void set_fd(int fd)
+    { m_fd = fd; }
+
 private:
   int m_fd; ///< filedesc, -1 if not open.
   const char * m_mode; ///< Mode string for deviceopen().
@@ -230,324 +207,11 @@ bool freebsd_smart_device::is_open() const
 }
 
 
-static int hpt_hba(const char* name) {
-  int i=0;
-  const char *hpt_node[]={"hptmv", "hptmv6", "hptrr", "hptiop", "hptmviop", "hpt32xx", "rr2320",
-  "rr232x", "rr2310", "rr2310_00", "rr2300", "rr2340", "rr1740", NULL};
-  while (hpt_node[i]) {
-    if (!strncmp(name, hpt_node[i], strlen(hpt_node[i])))
-      return 1;
-    i++;
-  }
-  return 0;
-}
-
-static int get_tw_channel_unit (const char* name, int* unit, int* dev) {
-  const char *p;
-  /* device node sanity check */
-  for (p = name + 3; *p; p++)
-    if (*p < '0' || *p > '9')
-    return -1;
-  if (strlen(name) > 4 && *(name + 3) == '0')
-    return -1;
-
-  if (dev != NULL)
-    *dev=atoi(name + 3);
-
-  /* no need for unit number */
-  if (unit != NULL)
-    *unit=0;
-  return 0;
-}
-
-#ifndef IOCATAREQUEST
-static int get_ata_channel_unit ( const char* name, int* unit, int* dev) {
-#ifndef ATAREQUEST
-  *dev=0;
-  *unit=0;
-  return 0;
-#else
-  // there is no direct correlation between name 'ad0, ad1, ...' and
-  // channel/unit number.  So we need to iterate through the possible
-  // channels and check each unit to see if we match names
-  struct ata_cmd iocmd;
-  int fd,maxunit;
-
-  bzero(&iocmd, sizeof(struct ata_cmd));
-
-  if ((fd = open(ATA_DEVICE, O_RDWR)) < 0)
-    return -errno;
-
-  iocmd.cmd = ATAGMAXCHANNEL;
-  if (ioctl(fd, IOCATA, &iocmd) < 0) {
-    return -errno;
-    close(fd);
-  }
-  maxunit = iocmd.u.maxchan;
-  for (*unit = 0; *unit < maxunit; (*unit)++) {
-    iocmd.channel = *unit;
-    iocmd.device = -1;
-    iocmd.cmd = ATAGPARM;
-    if (ioctl(fd, IOCATA, &iocmd) < 0) {
-      close(fd);
-      return -errno;
-    }
-    if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) {
-      *dev = 0;
-      break;
-    }
-    if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) {
-      *dev = 1;
-      break;
-    }
-  }
-  close(fd);
-  if (*unit == maxunit)
-    return -1;
-  else
-    return 0;
-#endif
-}
-#endif
-
-// Guess device type (ata or scsi) based on device name (FreeBSD
-// specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
-// osst, nosst and sg.
-static const char * fbsd_dev_prefix = _PATH_DEV;
-static const char * fbsd_dev_ata_disk_prefix = "ad";
-static const char * fbsd_dev_scsi_disk_plus = "da";
-static const char * fbsd_dev_scsi_pass = "pass";
-static const char * fbsd_dev_scsi_tape1 = "sa";
-static const char * fbsd_dev_scsi_tape2 = "nsa";
-static const char * fbsd_dev_scsi_tape3 = "esa";
-static const char * fbsd_dev_twe_ctrl = "twe";
-static const char * fbsd_dev_twa_ctrl = "twa";
-static const char * fbsd_dev_cciss = "ciss";
-
-int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan, const char * type) {
-  int len;
-  int dev_prefix_len = strlen(fbsd_dev_prefix);
-
-
-  // No Autodetection if device type was specified by user
-  if (*type){
-    if(!strcmp(type,"ata")) return CONTROLLER_ATA;
-    if(!strcmp(type,"cciss")) return CONTROLLER_CCISS;
-    if(!strcmp(type,"scsi") || !strcmp(type,"sat")) goto handlescsi;
-    if(!strcmp(type,"3ware")){
-      return  parse_ata_chan_dev(dev_name,NULL,"");
-    }
-    if(!strcmp(type,"hpt")) return CONTROLLER_HPT;
-    return CONTROLLER_UNKNOWN;
-    // todo - add other types
-  }
-
-  // if dev_name null, or string length zero
-  if (!dev_name || !(len = strlen(dev_name)))
-    return CONTROLLER_UNKNOWN;
-
-  // Remove the leading /dev/... if it's there
-  if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) {
-    if (len <= dev_prefix_len) 
-      // if nothing else in the string, unrecognized
-    return CONTROLLER_UNKNOWN;
-    // else advance pointer to following characters
-    dev_name += dev_prefix_len;
-  }
-  // form /dev/ad* or ad*
-  if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name,
-    strlen(fbsd_dev_ata_disk_prefix))) {
-#ifndef IOCATAREQUEST
-  if (chan != NULL) {
-    if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
-      return CONTROLLER_UNKNOWN;
-    }
-  }
-#endif
-    return CONTROLLER_ATA;
-  }
-
-  // form /dev/pass* or pass*
-  if (!strncmp(fbsd_dev_scsi_pass, dev_name,
-    strlen(fbsd_dev_scsi_pass)))
-    goto handlescsi;
-
-  // form /dev/da* or da*
-  if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name,
-               strlen(fbsd_dev_scsi_disk_plus)))
-    goto handlescsi;
-
-  // form /dev/sa* or sa*
-  if (!strncmp(fbsd_dev_scsi_tape1, dev_name,
-    strlen(fbsd_dev_scsi_tape1)))
-    goto handlescsi;
-
-  // form /dev/nsa* or nsa*
-  if (!strncmp(fbsd_dev_scsi_tape2, dev_name,
-    strlen(fbsd_dev_scsi_tape2)))
-    goto handlescsi;
-
-  // form /dev/esa* or esa*
-  if (!strncmp(fbsd_dev_scsi_tape3, dev_name,
-    strlen(fbsd_dev_scsi_tape3)))
-    goto handlescsi;
-
-  if (!strncmp(fbsd_dev_twa_ctrl,dev_name,
-    strlen(fbsd_dev_twa_ctrl))) 
-  {
-    if (chan != NULL) {
-      if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
-        return CONTROLLER_UNKNOWN;
-      }
-    }
-    else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) {
-      return CONTROLLER_UNKNOWN;
-    }
-    return CONTROLLER_3WARE_9000_CHAR;
-  }
-
-  if (!strncmp(fbsd_dev_twe_ctrl,dev_name,
-        strlen(fbsd_dev_twe_ctrl))) 
-  {
-    if (chan != NULL) {
-      if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
-        return CONTROLLER_UNKNOWN;
-      }
-    }
-    else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) {
-      return CONTROLLER_UNKNOWN;
-    }
-    return CONTROLLER_3WARE_678K_CHAR;
-  }
-
-  if (hpt_hba(dev_name)) {
-    return CONTROLLER_HPT;
-  }
-
-  // form /dev/ciss*
-  if (!strncmp(fbsd_dev_cciss, dev_name, strlen(fbsd_dev_cciss)))
-    return CONTROLLER_CCISS;
-
-  // we failed to recognize any of the forms
-  return CONTROLLER_UNKNOWN;
-
- handlescsi:
-  if (chan != NULL) {
-    if (!(chan->devname = (char *)calloc(1,DEV_IDLEN+1)))
-      return CONTROLLER_UNKNOWN;
-    if (cam_get_device(dev_name,chan->devname,DEV_IDLEN,&(chan->unitnum)) == -1)
-      return CONTROLLER_UNKNOWN;
-  }
-  return CONTROLLER_SCSI;
-
-}
-
-
 bool freebsd_smart_device::open()
 {
-
   const char *dev = get_dev_name();
-  struct freebsd_dev_channel *fdchan;
-  int parse_ok, i;
-
-  // Search table for a free entry
-  for (i=0; i<FREEBSD_MAXDEV; i++)
-    if (!devicetable[i])
-    break;
-
-  // If no free entry found, return error.  We have max allowed number
-  // of "file descriptors" already allocated.
-  if (i == FREEBSD_MAXDEV) {
-    errno = EMFILE;
-    return false;
-  }
-
-  fdchan = (struct freebsd_dev_channel *)calloc(1,sizeof(struct freebsd_dev_channel));
-  if (fdchan == NULL) {
-    // errno already set by call to malloc()
-    return false;
-  }
-
-  parse_ok = parse_ata_chan_dev(dev,fdchan,get_req_type());
-
-  if (parse_ok == CONTROLLER_UNKNOWN) {
-    free(fdchan);
-    errno = ENOTTY;
-    return false; // can't handle what we don't know
-  }
-
-  if (parse_ok == CONTROLLER_ATA) {
-#ifdef IOCATAREQUEST
-    if ((fdchan->device = ::open(dev,O_RDONLY))<0) {
-#else
-    if ((fdchan->atacommand = ::open("/dev/ata",O_RDWR))<0) {
-#endif
-      int myerror = errno; // preserve across free call
-      free(fdchan);
-      errno = myerror;
-      return false;
-    }
-  }
-
-  if (parse_ok == CONTROLLER_3WARE_678K_CHAR) {
-    char buf[512];
-    sprintf(buf,"/dev/twe%d",fdchan->device);
-#ifdef IOCATAREQUEST
-    if ((fdchan->device = ::open(buf,O_RDWR))<0) {
-#else
-    if ((fdchan->atacommand = ::open(buf,O_RDWR))<0) {
-#endif
-      int myerror = errno; // preserve across free call
-      free(fdchan);
-      errno = myerror;
-      return false;
-    }
-  }
-
-  if (parse_ok == CONTROLLER_3WARE_9000_CHAR) {
-    char buf[512];
-    sprintf(buf,"/dev/twa%d",fdchan->device);
-#ifdef IOCATAREQUEST
-    if ((fdchan->device = ::open(buf,O_RDWR))<0) {
-#else
-    if ((fdchan->atacommand = ::open(buf,O_RDWR))<0) {
-#endif
-      int myerror = errno; // preserve across free call
-      free(fdchan);
-      errno = myerror;
-      return false;
-    }
-  }
-
-  if (parse_ok == CONTROLLER_HPT) {
-    if ((fdchan->device = ::open(dev,O_RDWR))<0) {
-      int myerror = errno; // preserve across free call
-      free(fdchan);
-      errno = myerror;
-      return false;
-    }
-  }
-
-  if (parse_ok == CONTROLLER_CCISS) {
-    if ((fdchan->device = ::open(dev,O_RDWR))<0) {
-      int myerror = errno; // preserve across free call
-      free(fdchan);
-      errno = myerror;
-      return false;
-    }
-  }
-
-  if (parse_ok == CONTROLLER_SCSI) {
-    // this is really a NO-OP, as the parse takes care
-    // of filling in correct details
-  }
-
-  // return pointer to "file descriptor" table entry, properly offset.
-  devicetable[i]=fdchan;
-  m_fd = i+FREEBSD_FDOFFSET;
-  // endofold
-  if (m_fd < 0) {
-    set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno);
+  if ((m_fd = ::open(dev,O_RDONLY))<0) {
+    set_err(errno);
     return false;
   }
   return true;
@@ -555,35 +219,15 @@ bool freebsd_smart_device::open()
 
 bool freebsd_smart_device::close()
 {
-  int fd = m_fd; m_fd = -1;
-  struct freebsd_dev_channel *fdchan;
   int failed = 0;
-
-  // check for valid file descriptor
-  if (isnotopen(&fd, &fdchan))
-    return false;
-
-  // did we allocate a SCSI device name?
-  if (fdchan->devname)
-    free(fdchan->devname);
-
   // close device, if open
-  if (fdchan->device)
-    failed=::close(fdchan->device);
-#ifndef IOCATAREQUEST
-  if (fdchan->atacommand)
-    failed=::close(fdchan->atacommand);
-#endif
+  if (is_open())
+    failed=::close(get_fd());
+
+  set_fd(-1);
 
-  // if close succeeded, then remove from device list
-  // Eduard, should we also remove it from list if close() fails?  I'm
-  // not sure. Here I only remove it from list if close() worked.
-  if (!failed) {
-    free(fdchan);
-    devicetable[fd]=NULL;
-  }
   if(failed) return false;
-  else return true;
+    else return true;
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -596,12 +240,9 @@ class freebsd_ata_device
 public:
   freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
 
-#ifdef HAVE_ATA_IDENTIFY_IS_CACHED
-  virtual bool ata_identify_is_cached() const;
-#endif
-
 protected:
   virtual int ata_command_interface(smart_command_set command, int select, char * data);
+  virtual int do_cmd(struct ata_ioc_request* request);
 };
 
 freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
@@ -610,46 +251,108 @@ freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_
 {
 }
 
+int freebsd_ata_device::do_cmd( struct ata_ioc_request* request)
+{
+  int fd = get_fd();
+  return ioctl(fd, IOCATAREQUEST, request);
+}
+
+#if FREEBSDVER > 800100
+class freebsd_atacam_device : public freebsd_ata_device
+{
+public:
+  freebsd_atacam_device(smart_interface * intf, const char * dev_name, const char * req_type)
+  : smart_device(intf, dev_name, "atacam", req_type), freebsd_ata_device(intf, dev_name, req_type)
+  {}
+  
+  virtual bool open();
+  virtual bool close();
+  
+protected:
+  int m_fd;
+  struct cam_device *m_camdev;
+
+  virtual int do_cmd( struct ata_ioc_request* request);
+};
+
+bool freebsd_atacam_device::open(){
+  const char *dev = get_dev_name();
+  
+  if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
+    set_err(errno);
+    return false;
+  }
+  set_fd(m_camdev->fd);
+  return true;
+}
+
+bool freebsd_atacam_device::close(){
+  cam_close_device(m_camdev);
+  set_fd(-1);
+  return true;
+}
+
+int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request)
+{
+  union ccb ccb;
+  int camflags;
+
+  memset(&ccb, 0, sizeof(ccb));
+
+  if (request->count == 0)
+    camflags = CAM_DIR_NONE;
+  else if (request->flags == ATA_CMD_READ)
+    camflags = CAM_DIR_IN;
+  else
+    camflags = CAM_DIR_OUT;
+
+  cam_fill_ataio(&ccb.ataio,
+                 0,
+                 NULL,
+                 camflags,
+                 MSG_SIMPLE_Q_TAG,
+                 (u_int8_t*)request->data,
+                 request->count,
+                 request->timeout * 1000); // timeout in seconds
+
+  // ata_28bit_cmd
+  ccb.ataio.cmd.flags = 0;
+  ccb.ataio.cmd.command = request->u.ata.command;
+  ccb.ataio.cmd.features = request->u.ata.feature;
+  ccb.ataio.cmd.lba_low = request->u.ata.lba;
+  ccb.ataio.cmd.lba_mid = request->u.ata.lba >> 8;
+  ccb.ataio.cmd.lba_high = request->u.ata.lba >> 16;
+  ccb.ataio.cmd.device = 0x40 | ((request->u.ata.lba >> 24) & 0x0f);
+  ccb.ataio.cmd.sector_count = request->u.ata.count;
+
+  ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+  if (cam_send_ccb(m_camdev, &ccb) < 0) {
+    err(1, "cam_send_ccb");
+    return -1;
+  }
+
+  if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
+    return 0;
+
+  cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+  return -1;
+}
+
+#endif
+
 int freebsd_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
 {
- int fd=get_fd();
-#if !defined(ATAREQUEST) && !defined(IOCATAREQUEST)
- // sorry, but without ATAng, we can't do anything here
- printwarning(BAD_KERNEL,NULL);
- errno = ENOSYS;
- return -1;
-#else
- struct freebsd_dev_channel* con;
  int retval, copydata=0;
-#ifdef IOCATAREQUEST
  struct ata_ioc_request request;
-#else
- struct ata_cmd iocmd;
-#endif
  unsigned char buff[512];
 
- // check that "file descriptor" is valid
- if (isnotopen(&fd,&con))
-  return -1;
-
  bzero(buff,512);
-
-#ifdef IOCATAREQUEST
  bzero(&request,sizeof(struct ata_ioc_request));
-#else
- bzero(&iocmd,sizeof(struct ata_cmd));
-#endif
  bzero(buff,512);
 
-#ifndef IOCATAREQUEST
- iocmd.cmd=ATAREQUEST;
- iocmd.channel=con->channel;
- iocmd.device=con->device;
-#define request iocmd.u.request
-#endif
-
  request.u.ata.command=ATA_SMART_CMD;
- request.timeout=600;
+ request.timeout=SCSI_TIMEOUT_DEFAULT;
  switch (command){
  case READ_VALUES:
   request.u.ata.feature=ATA_SMART_READ_VALUES;
@@ -753,11 +456,7 @@ int freebsd_ata_device::ata_command_interface(smart_command_set command, int sel
   unsigned const char failed_lo=0xf4, failed_hi=0x2c;
   unsigned char low,high;
 
-#ifdef IOCATAREQUEST
-  if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error)
-#else
-  if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error)
-#endif
+  if ((retval=do_cmd(&request)) || request.error)
   return -1;
 
 #if (FREEBSDVER < 502000)
@@ -789,11 +488,7 @@ int freebsd_ata_device::ata_command_interface(smart_command_set command, int sel
   return 0;   
  }
 
-#ifdef IOCATAREQUEST
- if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error)
-#else
- if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error)
-#endif
+ if ((retval=do_cmd(&request)) || request.error)
  {
   return -1;
  }
@@ -805,17 +500,8 @@ int freebsd_ata_device::ata_command_interface(smart_command_set command, int sel
  if (copydata)
   memcpy(data, buff, 512);
 
- return 0;
-#endif
-}
-
-#ifdef HAVE_ATA_IDENTIFY_IS_CACHED
-bool freebsd_ata_device::ata_identify_is_cached() const
-{
-  return !!::ata_identify_is_cached(get_fd());
+  return 0;
 }
-#endif
-
 
 /////////////////////////////////////////////////////////////////////////////
 /// Implement AMCC/3ware RAID support with old functions
@@ -830,6 +516,7 @@ public:
 
 protected:
   virtual int ata_command_interface(smart_command_set command, int select, char * data);
+  virtual bool open();
 
 private:
   int m_escalade_type; ///< Type string for escalade_command_interface().
@@ -848,11 +535,23 @@ freebsd_escalade_device::freebsd_escalade_device(smart_interface * intf, const c
   set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum);
 }
 
+bool freebsd_escalade_device::open()
+{
+  const char *dev = get_dev_name();
+  int fd;
+  
+  if ((fd = ::open(dev,O_RDWR))<0) {
+    set_err(errno);
+    return false;
+  }
+  set_fd(fd);
+  return true;
+}
+
 int freebsd_escalade_device::ata_command_interface(smart_command_set command, int select, char * data)
 {
   // to hold true file descriptor
   int fd = get_fd();
-  struct freebsd_dev_channel* con;
 
   // return value and buffer for ioctl()
   int  ioctlreturn, readdata=0;
@@ -868,10 +567,6 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
     return -1;
   }
 
-  // check that "file descriptor" is valid
-  if (isnotopen(&fd,&con))
-    return -1;
-
   memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
 
   if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
@@ -1022,17 +717,9 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
 
   // Now send the command down through an ioctl()
   if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
-#ifdef IOCATAREQUEST
-    ioctlreturn=ioctl(con->device,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
-#else
-    ioctlreturn=ioctl(con->atacommand,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
-#endif
+    ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
   } else {
-#ifdef IOCATAREQUEST
-    ioctlreturn=ioctl(con->device,TWEIO_COMMAND,cmd_twe);
-#else
-    ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd_twe);
-#endif
+    ioctlreturn=ioctl(fd,TWEIO_COMMAND,cmd_twe);
   }
 
   // Deal with the different error cases
@@ -1115,6 +802,7 @@ public:
 
 protected:
   virtual int ata_command_interface(smart_command_set command, int select, char * data);
+  virtual bool open();
 
 private:
   unsigned char m_hpt_data[3]; ///< controller/channel/port
@@ -1130,20 +818,28 @@ freebsd_highpoint_device::freebsd_highpoint_device(smart_interface * intf, const
   set_info().info_name = strprintf("%s [hpt_disk_%u/%u/%u]", dev_name, m_hpt_data[0], m_hpt_data[1], m_hpt_data[2]);
 }
 
+bool freebsd_highpoint_device::open()
+{
+  const char *dev = get_dev_name();
+  int fd;
+  
+  if ((fd = ::open(dev,O_RDWR))<0) {
+    set_err(errno);
+    return false;
+  }
+  set_fd(fd);
+  return true;
+}
+
 int freebsd_highpoint_device::ata_command_interface(smart_command_set command, int select, char * data)
 {
   int fd=get_fd(); 
   int ids[2];
-  struct freebsd_dev_channel* fbcon;
   HPT_IOCTL_PARAM param;
   HPT_CHANNEL_INFO_V2 info;
   unsigned char* buff[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER)];
   PHPT_PASS_THROUGH_HEADER pide_pt_hdr, pide_pt_hdr_out;
 
-  // check that "file descriptor" is valid
-  if (isnotopen(&fd, &fbcon))
-    return -1;
-
   // get internal deviceid
   ids[0] = m_hpt_data[0] - 1;
   ids[1] = m_hpt_data[1] - 1;
@@ -1161,7 +857,7 @@ int freebsd_highpoint_device::ata_command_interface(smart_command_set command, i
     param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO;
     param.out_size = sizeof(HPT_CHANNEL_INFO);
   }
-  if (ioctl(fbcon->device, HPT_DO_IOCONTROL, &param)!=0 ||
+  if (ioctl(fd, HPT_DO_IOCONTROL, &param)!=0 ||
       info.devices[m_hpt_data[2]-1]==0) {
     return -1;
   }
@@ -1246,7 +942,7 @@ int freebsd_highpoint_device::ata_command_interface(smart_command_set command, i
 
   pide_pt_hdr_out = (PHPT_PASS_THROUGH_HEADER)param.out;
 
-  if ((ioctl(fbcon->device, HPT_DO_IOCONTROL, &param)!=0) ||
+  if ((ioctl(fd, HPT_DO_IOCONTROL, &param)!=0) ||
       (pide_pt_hdr_out->command & 1)) {
     return -1;
   }
@@ -1302,8 +998,33 @@ public:
   virtual smart_device * autodetect_open();
 
   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
+  
+  virtual bool open();
+
+  virtual bool close();
+  
+private:
+  int m_fd;
+  struct cam_device *m_camdev;
 };
 
+bool freebsd_scsi_device::open(){
+  const char *dev = get_dev_name();
+  
+  if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
+    set_err(errno);
+    return false;
+  }
+  set_fd(m_camdev->fd);
+  return true;
+}
+
+bool freebsd_scsi_device::close(){
+  cam_close_device(m_camdev);
+  set_fd(-1);
+  return true;
+}
+
 freebsd_scsi_device::freebsd_scsi_device(smart_interface * intf,
   const char * dev_name, const char * req_type)
 : smart_device(intf, dev_name, "scsi", req_type),
@@ -1311,11 +1032,10 @@ freebsd_scsi_device::freebsd_scsi_device(smart_interface * intf,
 {
 }
 
-// Interface to SCSI devices.  See os_linux.c
-int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
+
+bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
 {
-  struct freebsd_dev_channel* con = NULL;
-  struct cam_device* cam_dev = NULL;
+  int report=con->reportscsiioctl;
   union ccb *ccb;
 
   if (report > 0) {
@@ -1339,17 +1059,12 @@ int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
         pout("]");
   }
 
-  // check that "file descriptor" is valid
-  if (isnotopen(&fd,&con))
+  if(m_camdev==NULL) {
+    warnx("error: camdev=0!");
     return -ENOTTY;
-
-
-  if (!(cam_dev = cam_open_spec_device(con->devname,con->unitnum,O_RDWR,NULL))) {
-    warnx("%s",cam_errbuf);
-    return -EIO;
   }
 
-  if (!(ccb = cam_getccb(cam_dev))) {
+  if (!(ccb = cam_getccb(m_camdev))) {
     warnx("error allocating ccb");
     return -ENOMEM;
   }
@@ -1370,10 +1085,10 @@ int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
     /* timout (converted to seconds) */ iop->timeout*1000);
   memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
 
-  if (cam_send_ccb(cam_dev,ccb) < 0) {
+  if (cam_send_ccb(m_camdev,ccb) < 0) {
     warn("error sending SCSI ccb");
 #if (FREEBSDVER > 500000)
-    cam_error_print(cam_dev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
+    cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
 #endif
     cam_freeccb(ccb);
     return -EIO;
@@ -1381,7 +1096,7 @@ int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
 
   if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)) {
 #if (FREEBSDVER > 500000)
-    cam_error_print(cam_dev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
+    cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
 #endif
     cam_freeccb(ccb);
     return -EIO;
@@ -1396,9 +1111,6 @@ int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
 
   cam_freeccb(ccb);
 
-  if (cam_dev)
-    cam_close_device(cam_dev);
-
   if (report > 0) {
     int trunc;
 
@@ -1409,55 +1121,7 @@ int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
       (trunc ? " [only first 256 bytes shown]" : ""));
     dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
   }
-  return 0;
-}
-
-
-/* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better
-   we can take off this crude way of calling the right interface */
-int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report)
-{
-  struct freebsd_dev_channel *fdchan;
-  switch(m_controller_type)
-  {
-  case CONTROLLER_CCISS:
-#ifdef HAVE_DEV_CISS_CISSIO_H
-    // check that "file descriptor" is valid
-    if (isnotopen(&dev_fd,&fdchan))
-      return -ENOTTY;
 
-    return cciss_io_interface(fdchan->device, m_controller_port-1, iop, report);
-#else
-    {
-      static int warned = 0;
-      if (!warned) {
-        pout("CCISS support is not available in this build of smartmontools,\n"
-          "/usr/src/sys/dev/ciss/cissio.h was not available at build time.\n\n");
-        warned = 1;
-      }
-    }
-    return -ENOSYS;
-#endif
-// not reached
-    break;
-
-  default:
-    return do_normal_scsi_cmnd_io(dev_fd, iop, report);
-    // not reached
-    break;
-  }
-}
-
-bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
-{
-  unsigned char oldtype = m_controller_type, oldport = m_controller_port;
-  m_controller_type = CONTROLLER_SCSI; m_controller_port = 0;
-  int status = do_scsi_cmnd_io(get_fd(), iop, con->reportscsiioctl);
-  m_controller_type = oldtype; m_controller_port = oldport;
-  if (status < 0) {
-    set_err(-status);
-    return false;
-  }
   return true;
 }
 
@@ -1473,11 +1137,28 @@ public:
   freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum);
 
   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
+  virtual bool open();
 
 private:
   unsigned char m_disknum; ///< Disk number.
 };
 
+bool freebsd_cciss_device::open()
+{
+  const char *dev = get_dev_name();
+  int fd;
+#ifndef HAVE_DEV_CISS_CISSIO_H
+  pout("CCISS support is not available in this build of smartmontools,\n"
+    "/usr/src/sys/dev/ciss/cissio.h was not available at build time.\n\n");
+  return false;
+#endif  
+  if ((fd = ::open(dev,O_RDWR))<0) {
+    set_err(errno);
+    return false;
+  }
+  set_fd(fd);
+  return true;
+}
 
 freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf,
   const char * dev_name, unsigned char disknum)
@@ -1490,15 +1171,13 @@ freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf,
 
 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop)
 {
-  // See os_linux.cpp
-  unsigned char oldtype = m_controller_type, oldport = m_controller_port;
-  m_controller_type = CONTROLLER_CCISS; m_controller_port = m_disknum+1;
-  int status = do_scsi_cmnd_io(get_fd(), iop, con->reportscsiioctl);
-  m_controller_type = oldtype; m_controller_port = oldport;
-  if (status < 0) {
-      set_err(-status);
-      return false;
-  }
+#ifdef HAVE_DEV_CISS_CISSIO_H
+  int status = cciss_io_interface(get_fd(), m_disknum, iop, con->reportscsiioctl);
+  if (status < 0)
+      return set_err(-status);
+  return true;
+#endif
+  // not reached
   return true;
 }
 
@@ -1583,6 +1262,10 @@ public:
 protected:
   virtual ata_device * get_ata_device(const char * name, const char * type);
 
+#if FREEBSDVER > 800100
+  virtual ata_device * get_atacam_device(const char * name, const char * type);
+#endif
+
   virtual scsi_device * get_scsi_device(const char * name, const char * type);
 
   virtual smart_device * autodetect_smart_device(const char * name);
@@ -1614,122 +1297,33 @@ ata_device * freebsd_smart_interface::get_ata_device(const char * name, const ch
   return new freebsd_ata_device(this, name, type);
 }
 
-scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
+#if FREEBSDVER > 800100
+ata_device * freebsd_smart_interface::get_atacam_device(const char * name, const char * type)
 {
-  return new freebsd_scsi_device(this, name, type);
+  return new freebsd_atacam_device(this, name, type);
 }
+#endif
 
-static int 
-cam_getumassno(char * devname) {
-  union ccb ccb;
-  int bufsize, fd;
-  unsigned int i;
-  int error = -1;
-  char devstring[256];
-
-  if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
-    warn("couldn't open %s", XPT_DEVICE);
-    return(1);
-  }
-  bzero(&ccb, sizeof(union ccb));
-
-  ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
-  ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
-  ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
-  ccb.ccb_h.func_code = XPT_DEV_MATCH;
-  bufsize = sizeof(struct dev_match_result) * 100;
-  ccb.cdm.match_buf_len = bufsize;
-  ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
-
-  if (ccb.cdm.matches == NULL) {
-    warnx("can't malloc memory for matches");
-    close(fd);
-    return(1);
-  }
-  ccb.cdm.num_matches = 0;
-  /*
-  * We fetch all nodes, since we display most of them in the default
-  * case, and all in the verbose case.
-  */
-  ccb.cdm.num_patterns = 0;
-  ccb.cdm.pattern_buf_len = 0;
-  /*
-  * We do the ioctl multiple times if necessary, in case there are
-  * more than 100 nodes in the EDT.
-  */
-
-  do {
-    if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
-      warn("error sending CAMIOCOMMAND ioctl");
-      error = -1;
-      break;
-    }
-    if ((ccb.ccb_h.status != CAM_REQ_CMP)
-      || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
-        && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) 
-    {
-      warnx("got CAM error %#x, CDM error %d\n",
-        ccb.ccb_h.status, ccb.cdm.status);
-      error = -1;
-      break;
-    }
-
-    struct bus_match_result *bus_result = 0;
-    for (i = 0; i < ccb.cdm.num_matches; i++) {
-      switch (ccb.cdm.matches[i].type) {
-      case DEV_MATCH_BUS: {
-          // struct bus_match_result *bus_result;
-          bus_result =
-          &ccb.cdm.matches[i].result.bus_result;
-          break;
-      }
-    case DEV_MATCH_DEVICE:   {
-        /* we are not interested in device name */
-        break;
-      }
-    case DEV_MATCH_PERIPH: {
-        struct periph_match_result *periph_result;
-
-        periph_result =
-        &ccb.cdm.matches[i].result.periph_result;
-
-        snprintf(devstring,sizeof(devstring),"%s%d",periph_result->periph_name,periph_result->unit_number);
-        if(strcmp(devstring,devname)==0){ /* found our device */
-          if(strcmp(bus_result->dev_name,"umass-sim")) {
-            close(fd);
-            return -1; /* non usb device found, giving up */
-          }
-          /* return bus number */
-          return  bus_result->unit_number;
-        }
-        break;
-    }
-
-  default:
-    fprintf(stdout, "WARN: unknown match type\n");
-    break;
-      }
-    }
-  } while ((ccb.ccb_h.status == CAM_REQ_CMP)
-    && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
-
-  close(fd);
-  free(ccb.cdm.matches);
-  return(error); /* no device found */
+scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
+{
+  return new freebsd_scsi_device(this, name, type);
 }
 
-
 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
 // devices on system despite of it's names
 //
 // If any errors occur, leave errno set as it was returned by the
 // system call, and return <0.
 //
+// arguments: 
+// names: resulting array
+// show_all - export duplicate device name or not
+//
 // Return values:
 // -1:   error
 // >=0: number of discovered devices
 
-int get_dev_names_cam(char*** names) {
+int get_dev_names_cam(char*** names, bool show_all) {
   int n = 0;
   char** mp = NULL;
   unsigned int i;
@@ -1742,7 +1336,7 @@ int get_dev_names_cam(char*** names) {
   // in case of non-clean exit
   *names=NULL;
   ccb.cdm.matches = NULL;
-
   if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
     if (errno == ENOENT) /* There are no CAM device on this computer */
       return 0;
@@ -1823,12 +1417,13 @@ int get_dev_names_cam(char*** names) {
           skip_device = 1;
         else
           skip_device = 0;
-
+        
         //        /* Shall we skip non T_DIRECT devices ? */
         //        if (dev_result->inq_data.device != T_DIRECT)
         //          skip_device = 1;
         changed = 1;
-      } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH && skip_device == 0) { 
+      } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH && 
+          (skip_device == 0 || show_all)) { 
         /* One device may be populated as many peripherals (pass0 & da0 for example). 
         * We are searching for latest name
         */
@@ -1843,8 +1438,7 @@ int get_dev_names_cam(char*** names) {
         };
         changed = 0;
       };
-
-      if (changed == 1 && devname != NULL) {
+      if ((changed == 1 || show_all) && devname != NULL) {
         mp[n] = devname;
         devname = NULL;
         bytes+=1+strlen(mp[n]);
@@ -1984,8 +1578,8 @@ bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
   }
 
   char * * scsinames = 0; int numscsi = 0;
-  if (!type || !strcmp(type, "scsi")) {
-    numscsi = get_dev_names_cam(&scsinames);
+  if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
+    numscsi = get_dev_names_cam(&scsinames,0);
     if (numscsi < 0) {
       set_err(ENOMEM);
       return false;
@@ -2152,48 +1746,88 @@ static int usbdevlist(int busno,unsigned short & vendor_id,
 #endif
 }
 
-// Get USB bridge ID for "/dev/daX"
-static bool get_usb_id(const char * path, unsigned short & vendor_id,
-  unsigned short & product_id, unsigned short & version)
-{
-  if (strlen(path) < 5)
-    return false;
-  int bus = cam_getumassno((char *)path+5);
-  if (bus == -1) 
-    return false;
-
-  usbdevlist(bus,vendor_id,
-    product_id, version);
-  return true;
-}
-
-
 smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name)
 {
-  int guess = parse_ata_chan_dev(name,NULL,"");
   unsigned short vendor_id = 0, product_id = 0, version = 0;
+  struct cam_device *cam_dev;
+  union ccb ccb;
+  int bus=-1;
+  int i;
+  int len;
 
-  switch (guess) {
-  case CONTROLLER_ATA : 
-    return new freebsd_ata_device(this, name, "");
-  case CONTROLLER_SCSI: 
-    // Try to detect possible USB->(S)ATA bridge
-    if (get_usb_id(name, vendor_id, product_id, version)) {
-      const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
-      if (!usbtype)
-        return 0;
-      // Return SAT/USB device for this type
-      // (Note: freebsd_scsi_device::autodetect_open() will not be called in this case)
-      return get_sat_device(usbtype, new freebsd_scsi_device(this, name, ""));
+  // if dev_name null, or string length zero
+  if (!name || !(len = strlen(name)))
+    return false;
+
+  // check ATA bus
+  char * * atanames = 0; int numata = 0;
+  numata = get_dev_names_ata(&atanames);
+  if (numata > 0) {
+    // check ATA/ATAPI devices
+    for (i = 0; i < numata; i++) {
+      if(!strcmp(atanames[i],name)) {
+        return new freebsd_ata_device(this, name, "");
+      }
     }
-    // non usb device, handle as normal scsi
-    return new freebsd_scsi_device(this, name, "");
-  case CONTROLLER_CCISS:
-    // device - cciss, but no ID known
-    set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
-    return 0;
   }
-  // TODO: Test autodetected device here
+  else {
+    if (numata < 0)
+      pout("Unable to get ATA device list\n");
+  }
+
+  // check CAM
+  char * * scsinames = 0; int numscsi = 0;
+  numscsi = get_dev_names_cam(&scsinames, 1);
+  if (numscsi > 0) {
+    // check all devices on CAM bus
+    for (i = 0; i < numscsi; i++) {
+      if(strcmp(scsinames[i],name)==0)
+      { // our disk device is CAM
+        if ((cam_dev = cam_open_device(name, O_RDWR)) == NULL) {
+          // open failure
+          set_err(errno);
+          return false;
+        }
+        
+        // zero the payload
+        bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE);
+        ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
+        if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
+          warn("Get Transfer Settings CCB failed\n"
+            "%s", strerror(errno));
+          cam_close_device(cam_dev);
+          return 0;
+        }
+        // now check if we are working with USB device, see umass.c
+        if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
+          usbdevlist(bus,vendor_id, product_id, version);
+          int bus=ccb.cpi.unit_number; // unit_number will match umass number
+          cam_close_device(cam_dev);
+          if(usbdevlist(bus,vendor_id, product_id, version)){
+            const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
+            if (!usbtype)
+              return false;
+            return get_sat_device(usbtype, new freebsd_scsi_device(this, name, ""));
+          }
+        }
+#if FREEBSDVER > 800100
+        // check if we have ATA device connected to CAM (ada)
+        if(ccb.cpi.protocol == PROTO_ATA){
+          cam_close_device(cam_dev);
+          return new freebsd_atacam_device(this, name, "");
+        }
+#endif
+        // close cam device, we don`t need it anymore
+        cam_close_device(cam_dev);
+        // handle as usual scsi
+        return new freebsd_scsi_device(this, name, "");      
+      }
+    }
+  } // numscsi > 0
+  else {
+    if(numscsi<0) pout("Unable to get CAM device list\n");
+  }
+  // device type unknown
   return 0;
 }
 
@@ -2201,7 +1835,10 @@ smart_device * freebsd_smart_interface::autodetect_smart_device(const char * nam
 smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type)
 {
   // 3Ware ?
-  int disknum = -1, n1 = -1, n2 = -1;
+  static const char * fbsd_dev_twe_ctrl = "/dev/twe";
+  static const char * fbsd_dev_twa_ctrl = "/dev/twa";
+  int disknum = -1, n1 = -1, n2 = -1, contr = -1;
+
   if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
     if (n2 != (int)strlen(type)) {
       set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
@@ -2211,9 +1848,20 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
       set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
       return 0;
     }
-    int contr = parse_ata_chan_dev(name,NULL,"");
-    if (contr != CONTROLLER_3WARE_9000_CHAR && contr != CONTROLLER_3WARE_678K_CHAR)
-      contr = CONTROLLER_3WARE_678K;
+
+    // guess 3ware device type based on device name
+    if (!strncmp(fbsd_dev_twa_ctrl, name, strlen(fbsd_dev_twa_ctrl))){
+      contr=CONTROLLER_3WARE_9000_CHAR;
+    }
+    if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
+      contr=CONTROLLER_3WARE_678K_CHAR;
+    }
+
+    if(contr == -1){
+      set_err(EINVAL, "3ware controller type unknown, use %sX or %sX devices", 
+        fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl);
+      return 0;
+    }
     return new freebsd_escalade_device(this, name, contr, disknum);
   } 
 
@@ -2254,13 +1902,22 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
     }
     return new freebsd_cciss_device(this, name, disknum);
   }
+#if FREEBSDVER > 800100
+  // adaX devices ?
+  if(!strcmp(type,"atacam"))
+    return new freebsd_atacam_device(this, name, "");
+#endif
 
   return 0;
 }
 
 std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
 {
-  return "3ware,N, hpt,L/M/N, cciss,N";
+  return "3ware,N, hpt,L/M/N, cciss,N"
+#if FREEBSDVER > 800100
+  ", atacam"
+#endif
+  ;
 }
 
 } // namespace
index 9a59afb71221debfd6e026458f93bb20a8d7af05..fc6665dbe3b84ed5a6b2b5f5c84592f0ac0d3c2a 100644 (file)
 
 #define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h,v 1.26 2009/01/14 02:39:00 sxzzsf Exp $\n"
 
-struct freebsd_dev_channel {
-  int   channel;                // the ATA channel to work with
-  int   device;                 // the device on the channel
-#ifndef IOCATAREQUEST
-  int   atacommand;             // the ATA Command file descriptor (/dev/ata)
-#endif
-  char* devname;                // the SCSI device name
-  int   unitnum;                // the SCSI unit number
-};
-
-#define FREEBSD_MAXDEV 64
-#define FREEBSD_FDOFFSET 16
 #define MAX_NUM_DEV 26
 
 #ifdef  HAVE_SYS_TWEREG_H
index f6d9f2d35f87b0020fd2ddac11ea70fad24f1f43..5635eaa01454552dcd1608f1638e26e80a8d6697 100644 (file)
@@ -90,7 +90,7 @@
 
 #define ARGUSED(x) ((void)(x))
 
-const char *os_XXXX_c_cvsid="$Id: os_linux.cpp 2915 2009-09-18 21:17:37Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_linux.cpp 2951 2009-10-08 23:43:46Z samm2 $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_LINUX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 /* for passing global control variables */
@@ -951,6 +951,7 @@ bool linux_megaraid_device::open()
   char line[128];
   int   mjr, n1;
   FILE *fp;
+  int report = con->reportscsiioctl; 
 
   if (!linux_smart_device::open())
     return false;
@@ -963,7 +964,7 @@ bool linux_megaraid_device::open()
   else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) {
     int err = errno;
     linux_smart_device::close();
-    return set_err(err, "can't get hba");
+    return set_err(err, "can't get bus number");
   }
 
   /* Perform mknod of device ioctl node */
@@ -972,13 +973,15 @@ bool linux_megaraid_device::open()
        n1=0;
        if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
           n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
-          printf("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
+          if(report > 0)
+            printf("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
           if (n1 >= 0 || errno == EEXIST)
              break;
        }
        else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {
           n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0));
-          printf("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
+          if(report > 0)
+            printf("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
           if (n1 >= 0 || errno == EEXIST)
              break;
        }
@@ -1043,7 +1046,18 @@ bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
   if (iop->cmnd[0] == 0x00)
     return true;
   if (iop->cmnd[0] == 0x85 && iop->cmnd[1] == 0x06) {
-    pout("Rejecting SMART/ATA command to controller\n");
+    if(report > 0)
+      pout("Rejecting SMART/ATA command to controller\n");
+    // Emulate SMART STATUS CHECK drive reply
+    // smartctl fail to work without this
+    if(iop->cmnd[2]==0x2c) {
+      iop->resp_sense_len=22;
+      iop->sensep[0]=0x72; // response code
+      iop->sensep[7]=0x0e; // no idea what it is, copied from sat device answer
+      iop->sensep[8]=0x09; // 
+      iop->sensep[17]=0x4f; // lm
+      iop->sensep[19]=0xc2; // lh
+    }
     return true;
   }
 
@@ -2666,7 +2680,13 @@ smart_device * linux_scsi_device::autodetect_open()
                       "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
       return this;
     }
-
+    // DELL?
+    if (!memcmp(req_buff + 8, "DELL    PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) {
+      close();
+      set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
+      return this;
+    }
+    
     // Marvell ?
     if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) {
       //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
index 64ae81e7d511504c2c23aad2893842237517c8c5..1a02b4ae92b70c350ff880b0e0b1e39525918bbf 100644 (file)
@@ -61,7 +61,7 @@
 #include "dev_ata_cmd_set.h" // ata_device_with_command_set
 #include "dev_tunnelled.h" // tunnelled_device<>
 
-const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 2916 2009-09-19 12:46:26Z chrfranke $";
+const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 2923 2009-09-24 20:10:38Z chrfranke $";
 
 /* for passing global control variables */
 extern smartmonctrl *con;
@@ -1415,7 +1415,9 @@ const usb_id_entry usb_ids[] = {
   // Verbatim
   { 0x18a5, 0x0215, 0x0001, d_sat     }, // Verbatim FW/USB160 - Oxford OXUF934SSA-LQAG (USB+IEE1394->SATA)
   // SunplusIT
-  { 0x1bcf, 0x0c31,     -1, d_sunplus }  // SunplusIT
+  { 0x1bcf, 0x0c31,     -1, d_sunplus }, // SunplusIT
+  // OnSpec
+  { 0x55aa, 0x2b00, 0x0100, d_unsup   }  // OnSpec ? (USB->PATA)
 };
 
 const unsigned num_usb_ids = sizeof(usb_ids)/sizeof(usb_ids[0]);
index 8a7211443d60c60b5063300ad85641222e7e2925..bceb9b8d74b013b4b9b1671ebef5e8442b93ddb2 100644 (file)
@@ -32,7 +32,7 @@
 #ifndef SCSICMDS_H_
 #define SCSICMDS_H_
 
-#define SCSICMDS_H_CVSID "$Id: scsicmds.h,v 1.69 2009/06/24 04:10:10 dpgilbert Exp $\n"
+#define SCSICMDS_H_CVSID "$Id: scsicmds.h 2924 2009-09-26 20:38:40Z chrfranke $\n"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -273,7 +273,8 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
 
 
 /* SCSI command timeout values (units are seconds) */
-#define SCSI_TIMEOUT_DEFAULT    6               /* 6 seconds should be ample */
+#define SCSI_TIMEOUT_DEFAULT    20  // should be longer than the spin up time
+                                    // of a disk in standby mode.
 #define SCSI_TIMEOUT_SELF_TEST  (5 * 60 * 60)   /* allow max 5 hours for */
                                             /* extended foreground self test */
 
index b4a62b613fcf417f2ffedc7d344eb33283690cbd..ed928ddb203fd02eb402c639d12ca49882d1b213 100644 (file)
@@ -1,7 +1,7 @@
 .ig
  Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
- $Id: smartctl.8.in 2883 2009-09-02 12:38:39Z samm2 $
+ $Id: smartctl.8.in 2922 2009-09-22 16:27:33Z chrfranke $
  
  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the Free
@@ -875,11 +875,12 @@ twenty\-one self\-tests, the log shows the type of test (short or
 extended, off\-line or captive) and the final status of the test.  If
 the test did not complete successfully, then the percentage of the
 test remaining is shown.  The time at which the test took place,
-measured in hours of disk lifetime, is also printed.  If any errors
-were detected, the Logical Block Address (LBA) of the first error is
-printed in decimal notation. On Linux systems the smartmontools
-web page has instructions about how to convert this LBA address to the
-name of the disk file containing the erroneous block.
+measured in hours of disk lifetime, is also printed. [Note: this time
+stamp wraps after 2^16 hours, or 2730 days and 16 hours, or about 7.5
+years.] If any errors were detected, the Logical Block Address (LBA)
+of the first error is printed in decimal notation.  On Linux systems the
+smartmontools web page has instructions about how to convert this LBA
+address to the name of the disk file containing the erroneous block.
 
 .I selftest
 \- [SCSI] the self\-test log for a SCSI device has a slightly different
@@ -1769,7 +1770,7 @@ these documents may be found in the References section of the
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartctl.8.in 2883 2009-09-02 12:38:39Z samm2 $
+$Id: smartctl.8.in 2922 2009-09-22 16:27:33Z chrfranke $
 .\" Local Variables:            
 .\" mode: nroff         
 .\" End:
index 011bff98f87a1d8e96ca2170cd6778df4a6d41ec..041e5925f0e7400abea768a31c6f4cfb06a11a2e 100644 (file)
@@ -1,7 +1,7 @@
 .ig
 Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
  
-$Id: smartd.8.in 2870 2009-08-02 20:38:30Z manfred99 $
+$Id: smartd.8.in 2921 2009-09-20 19:19:32Z samm2 $
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -91,8 +91,7 @@ devices that support SMART.  The scanning is done as follows:
 Examine all entries \fB"/dev/hd[a-t]"\fP for IDE/ATA
 devices, and \fB"/dev/sd[a-z]"\fP for SCSI devices.
 .IP \fBFREEBSD:\fP 9
-Examine all entries \fB"/dev/ad[0-9]+"\fP for IDE/ATA
-devices and \fB"/dev/da[0-9]+"\fP for SCSI devices.
+Authoritative list of disk devices is obtained from SCSI (CAM) and ATA subsystems.
 .IP \fBNETBSD/OPENBSD:\fP 9
 Authoritative list of disk devices is obtained from sysctl 
 \'hw.disknames\'.
@@ -496,8 +495,7 @@ Under FreeBSD,
 \fBsmartd\fP
 will try to open all existing ATA devices (with entries in /dev)
 .B /dev/ad[0-9]+
-and all existing SCSI devices
-.B /dev/da[0-9]+.  
+and all existing SCSI devices (using CAM subsystem).  
 Under NetBSD/OpenBSD, 
 \fBsmartd\fP
 will try to open all existing ATA devices (with entries in /dev)
@@ -2151,4 +2149,4 @@ smartmontools home page at \fBhttp://smartmontools.sourceforge.net/#references\f
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartd.8.in 2870 2009-08-02 20:38:30Z manfred99 $
+$Id: smartd.8.in 2921 2009-09-20 19:19:32Z samm2 $
index 6882507ecea7bf73f646c802c3babe6af0de0ffb..9b4ae478fd6cf75695db5d536038b7feac670ea7 100644 (file)
@@ -1,7 +1,7 @@
 .ig
 Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
-$Id: smartd.conf.5.in 2847 2009-07-18 14:58:44Z chrfranke $
+$Id: smartd.conf.5.in 2921 2009-09-20 19:19:32Z samm2 $
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the Free
@@ -394,7 +394,9 @@ inclusive) denotes which disk on the controller is monitored.  In log
 files and email messages this disk will be identified as cciss_disk_XX
 with XX in the range from 00 to 15 inclusive.
 
-.B 3ware, MegaRAID, Areca and cciss controllers are currently ONLY supported under Linux.
+.B 3ware and cciss controllers are currently ONLY supported under Linux and FreeBSD.
+
+.B MegaRAID and Areca controllers are currently ONLY supported under Linux.
 
 .I hpt,L/M/N
 \- the device consists of one or more ATA disks connected to a HighPoint
@@ -1482,4 +1484,4 @@ SEE ALSO:
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartd.conf.5.in 2847 2009-07-18 14:58:44Z chrfranke $
+$Id: smartd.conf.5.in 2921 2009-09-20 19:19:32Z samm2 $