]> git.proxmox.com Git - mirror_smartmontools-debian.git/blobdiff - os_freebsd.cpp
Imported upstream version 5.38~cvs20071118
[mirror_smartmontools-debian.git] / os_freebsd.cpp
index 43dc2cbfdeac16cda28bfb541c907e3e7d2b81b4..9640a6a1d303d5527ea72362a5cdefadc15b9575 100644 (file)
 #include "int64.h"
 #include "atacmds.h"
 #include "scsicmds.h"
+#include "cciss.h"
 #include "utility.h"
+#include "extern.h"
 #include "os_freebsd.h"
 
-static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.51 2006/09/17 03:17:53 dpgilbert Exp $";
+static const char *filenameandversion="$Id: os_freebsd.cpp,v 1.54 2007/09/06 08:48:55 ballen4705 Exp $";
 
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.51 2006/09/17 03:17:53 dpgilbert Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.54 2007/09/06 08:48:55 ballen4705 Exp $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // to hold onto exit code for atexit routine
 extern int exitstatus;
 
+extern smartmonctrl * con;
+
 // Private table of open devices: guaranteed zero on startup since
 // part of static data.
 struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV];
@@ -85,7 +89,7 @@ void print_smartctl_examples(){
 }
 
 // Like open().  Return positive integer handle, used by functions below only.  mode=="ATA" or "SCSI".
-int deviceopen (const char* dev, char* mode __unused) {
+int deviceopen (const char* dev, __unused char* mode) {
   struct freebsd_dev_channel *fdchan;
   int parse_ok, i;
 
@@ -157,6 +161,15 @@ int deviceopen (const char* dev, char* mode __unused) {
     }
   }
 
+  if (parse_ok == CONTROLLER_CCISS) {
+    if ((fdchan->device = open(dev,O_RDWR))<0) {
+      int myerror = errno; // preserver across free call
+      free(fdchan);
+      errno=myerror;
+      return -1;
+    }
+  }
+
   if (parse_ok == CONTROLLER_SCSI) {
     // this is really a NO-OP, as the parse takes care
     // of filling in correct details
@@ -248,13 +261,13 @@ void printwarning(int msgNo, const char* extra) {
   return;
 }
 
-
 // Interface to ATA devices.  See os_linux.c
-int marvell_command_interface(int fd __unused, smart_command_set command __unused, int select __unused, char *data __unused) {
-       return -1;
+
+int marvell_command_interface(__unused int fd, __unused smart_command_set command, __unused int select, __unused char *data) {
+  return -1;
 }
 
-int highpoint_command_interface(int fd __unused, smart_command_set command __unused, int select __unused, char *data __unused)
+int highpoint_command_interface(__unused int fd, __unused smart_command_set command, __unused int select, __unused char *data) {
 {
   return -1;
 }
@@ -439,7 +452,7 @@ int ata_command_interface(int fd, smart_command_set command, int select, char *d
 
 
 // Interface to SCSI devices.  See os_linux.c
-int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
+int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
 {
   struct freebsd_dev_channel* con = NULL;
   struct cam_device* cam_dev = NULL;
@@ -540,6 +553,40 @@ int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
   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(con->controller_type)
+     {
+         case CONTROLLER_CCISS:
+            // check that "file descriptor" is valid
+            if (isnotopen(&dev_fd,&fdchan))
+                 return -ENOTTY;
+#ifdef HAVE_DEV_CISS_CISSIO_H
+             return cciss_io_interface(fdchan->device, con->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;
+                 }
+             }
+             errno = ENOSYS;
+             return -1;
+#endif
+             // not reached
+             break;
+         default:
+             return do_normal_scsi_cmnd_io(dev_fd, iop, report);
+             // not reached
+             break;
+     }
+}
+
 // Interface to ATA devices behind 3ware escalade RAID controller cards.  See os_linux.c
 
 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
@@ -589,8 +636,7 @@ int escalade_command_interface(int fd, int disknum, int escalade_type, smart_com
 
   // Same for (almost) all commands - but some reset below
   ata->request_id    = 0xFF;
-  ata->unit   = disknum;
-  ata->host_id = 0;
+  ata->unit          = disknum;
   ata->status        = 0;           
   ata->flags         = 0x1;
   ata->drive_head    = 0x0;
@@ -878,6 +924,7 @@ 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";
 
 static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) {
   int len;
@@ -953,6 +1000,10 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel
     }
     return CONTROLLER_3WARE_678K_CHAR;
   }
+  // 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;
@@ -1005,10 +1056,10 @@ int get_dev_names(char*** names, const char* prefix) {
   
   // Use glob to look for any directory entries matching the patterns
   // first call inits with first pattern match, second call appends
-  // to first list. Turn on NOCHECK for second call. This results in no
-  // error if no more matches found, however it does append the actual
-  // pattern to the list of paths....
-  if ((retglob=glob(pattern1, GLOB_ERR, NULL, &globbuf)) ||
+  // to first list. GLOB_NOCHECK results in no error if no more matches 
+  // found, however it does append the actual pattern to the list of 
+  // paths....
+  if ((retglob=glob(pattern1, GLOB_ERR|GLOB_NOCHECK, NULL, &globbuf)) ||
       (retglob=glob(pattern2, GLOB_ERR|GLOB_APPEND|GLOB_NOCHECK,NULL,&globbuf))) {
      int retval = -1;
     // glob failed
@@ -1033,7 +1084,6 @@ int get_dev_names(char*** names, const char* prefix) {
     return retval;
   }
 
-  // did we find too many paths?
   // did we find too many paths?
   lim = globbuf.gl_pathc < MAX_NUM_DEV ? globbuf.gl_pathc : MAX_NUM_DEV;
   if (lim < globbuf.gl_pathc)
@@ -1050,7 +1100,7 @@ int get_dev_names(char*** names, const char* prefix) {
   // now step through the list returned by glob.  No link checking needed
   // in FreeBSD
   for (i=0; i<globbuf.gl_pathc; i++){
-    // becuase of the NO_CHECK on second call to glob,
+    // because of the NO_CHECK in calls to glob,
     // the pattern itself will be added to path list..
     // so ignore any paths that have the ']' from pattern
     if (strchr(globbuf.gl_pathv[i],']') == NULL)