From 1c4810d2e745cbed94d18f2da05030d6898778f6 Mon Sep 17 00:00:00 2001
From: samm2 <samm2@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Mon, 5 Oct 2009 18:30:26 +0000
Subject: [PATCH] FreeBSD: added autodetection code for the ada disks.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2936 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 smartmontools/CHANGELOG      |  3 ++
 smartmontools/os_freebsd.cpp | 97 +++++++++++++++---------------------
 2 files changed, 43 insertions(+), 57 deletions(-)

diff --git a/smartmontools/CHANGELOG b/smartmontools/CHANGELOG
index fcdea8d7f..31afb047a 100644
--- a/smartmontools/CHANGELOG
+++ b/smartmontools/CHANGELOG
@@ -43,6 +43,9 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [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 
diff --git a/smartmontools/os_freebsd.cpp b/smartmontools/os_freebsd.cpp
index fbabb2e7e..baba7b2d6 100644
--- a/smartmontools/os_freebsd.cpp
+++ b/smartmontools/os_freebsd.cpp
@@ -1707,38 +1707,6 @@ scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const
   return new freebsd_scsi_device(this, name, type);
 }
 
-static int 
-cam_get_umassno(const char * devname) {
-  struct cam_device *cam_dev;
-  union ccb ccb;
-  int bus=-1;
-  
-  // open CAM device 
-  if ((cam_dev = cam_open_device(devname,O_RDWR)) == NULL) {
-    // open failue
-    perror("cam_open_device");
-    return -1;
-  }
-  
-  // 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));
-    bus=-1;
-	}
-  else {
-    // now check if we are working with USB device, see umass.c
-    if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) 
-      bus=ccb.cpi.unit_number; // unit_number will match umass number
-  }
-  // close cam device, we don`t need it anymore
-  cam_close_device(cam_dev);
-  return bus;
-}
-
-
 // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
 // devices on system despite of it's names
 //
@@ -1762,7 +1730,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;
@@ -2172,41 +2140,56 @@ static int usbdevlist(int busno,unsigned short & vendor_id,
 #endif
 }
 
-// Get USB bridge ID for the CAM device
-static bool get_usb_id(const char * path, unsigned short & vendor_id,
-  unsigned short & product_id, unsigned short & version)
-{
-  int bus = cam_get_umassno(path);
-
-  if (bus == -1) 
-    return false;
-  // getting product/vendor for the device on bus
-  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;
+  
   switch (guess) {
   case CONTROLLER_ATA : 
     return new freebsd_ata_device(this, name, "");
   case CONTROLLER_ATACAM : 
     return new freebsd_atacam_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, ""));
+    // CAM device type, could be USB/ADA/SCSI
+    // open CAM device 
+    if ((cam_dev = cam_open_device(name, O_RDWR)) == NULL) {
+      // open failue
+      perror("cam_open_device");
+      return 0;
+    }
+    // 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 0;
+        return get_sat_device(usbtype, new freebsd_scsi_device(this, name, ""));
+      }
+    }
+    // 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, "");
     }
-    // non usb device, handle as normal scsi
+    // close cam device, we don`t need it anymore
+    cam_close_device(cam_dev);
+    // handle as normal scsi
     return new freebsd_scsi_device(this, name, "");
   case CONTROLLER_CCISS:
     // device - cciss, but no ID known
-- 
GitLab