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