#include <dirent.h>
#include <fcntl.h>
#include <err.h>
+#include <errno.h>
#include <camlib.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
#include "scsicmds.h"
#include "cciss.h"
#include "utility.h"
-#include "extern.h"
#include "os_freebsd.h"
#include "dev_interface.h"
#if (FREEBSDVER >= 800000)
#include <libusb20_desc.h>
#include <libusb20.h>
+#elif defined(__DragonFly__)
+#include <bus/usb/usb.h>
+#include <bus/usb/usbhid.h>
#else
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#define PATHINQ_SETTINGS_SIZE 128
#endif
-static __unused const char *filenameandversion="$Id: os_freebsd.cpp 3098 2010-04-30 17:35:35Z chrfranke $";
-
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3098 2010-04-30 17:35:35Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3264 2011-02-21 15:52:04Z chrfranke $" \
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 NO_RETURN 0
#define BAD_SMART 1
#define NO_DISK_3WARE 2
// global variable holding byte count of allocated memory
long long bytes;
-const char * dev_freebsd_cpp_cvsid = "$Id: os_freebsd.cpp 3098 2010-04-30 17:35:35Z chrfranke $"
- DEV_INTERFACE_H_CVSID;
-
-extern smartmonctrl * con; // con->reportscsiioctl
-
/////////////////////////////////////////////////////////////////////////////
namespace os_freebsd { // No need to publish anything, name provided for Doxygen
request->timeout * 1000); // timeout in seconds
// ata_28bit_cmd
- ccb.ataio.cmd.flags = 0;
+ if (request->flags == ATA_CMD_CONTROL)
+ ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT;
+ else
+ 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;
return -1;
}
- if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
- return 0;
+ if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+ return -1;
+ }
- cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
- return -1;
+ request->u.ata.count = ccb.ataio.res.sector_count;
+ return 0;
}
#endif
bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
{
- int report=con->reportscsiioctl;
+ int report=scsi_debugmode;
union ccb *ccb;
if (report > 0) {
bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop)
{
#ifdef HAVE_DEV_CISS_CISSIO_H
- int status = cciss_io_interface(get_fd(), m_disknum, iop, con->reportscsiioctl);
+ int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode);
if (status < 0)
return set_err(-status);
return true;
// -1: error
// >=0: number of discovered devices
-int get_dev_names_cam(char*** names, bool show_all) {
- int n = 0;
- char** mp = NULL;
- unsigned int i;
- union ccb ccb;
- int bufsize, fd = -1;
- int skip_device = 0, skip_bus = 0, changed = 0;
- char *devname = NULL;
- int serrno=-1;
-
- // in case of non-clean exit
- *names=NULL;
- ccb.cdm.matches = NULL;
-
+bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
+{
+ int fd;
if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
if (errno == ENOENT) /* There are no CAM device on this computer */
return 0;
- serrno = errno;
+ int serrno = errno;
pout("%s control device couldn't opened: %s\n", XPT_DEVICE, strerror(errno));
- n = -1;
- goto end;
+ errno = serrno;
+ return false;
}
- // allocate space for up to MAX_NUM_DEV number of ATA devices
- mp = (char **)calloc(MAX_NUM_DEV, sizeof(char*));
- if (mp == NULL) {
- serrno=errno;
- pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
- n = -1;
- goto end;
- };
-
+ union ccb ccb;
bzero(&ccb, sizeof(union ccb));
ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
ccb.ccb_h.func_code = XPT_DEV_MATCH;
- bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
+ int bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
ccb.cdm.match_buf_len = bufsize;
+ // TODO: Use local buffer instead of malloc() if possible
ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (ccb.cdm.matches == NULL) {
- serrno = errno;
- pout("can't malloc memory for matches on line %d\n", __LINE__);
- n = -1;
- goto end;
+ close(fd);
+ throw std::bad_alloc();
}
ccb.cdm.num_matches = 0;
ccb.cdm.num_patterns = 0;
* We do the ioctl multiple times if necessary, in case there are
* more than MAX_NUM_DEV nodes in the EDT.
*/
+ int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
+ std::string devname;
do {
if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
- serrno = errno;
+ int serrno = errno;
pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
- n = -1;
- break;
+ free(ccb.cdm.matches);
+ close(fd);
+ errno = serrno;
+ return false;
}
if ((ccb.ccb_h.status != CAM_REQ_CMP)
|| ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
- serrno = ENXIO;
- n = -1;
- goto end;
+ free(ccb.cdm.matches);
+ close(fd);
+ errno = ENXIO;
+ return false;
}
- for (i = 0; i < ccb.cdm.num_matches && n < MAX_NUM_DEV; i++) {
+ for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
struct bus_match_result *bus_result;
struct device_match_result *dev_result;
struct periph_match_result *periph_result;
* We are searching for latest name
*/
periph_result = &ccb.cdm.matches[i].result.periph_result;
- free(devname);
- asprintf(&devname, "%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
- if (devname == NULL) {
- serrno=errno;
- pout("Out of memory constructing scan SCSI device list (on line %d)\n", __LINE__);
- n = -1;
- goto end;
- };
+ devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
changed = 0;
};
- if ((changed == 1 || show_all) && devname != NULL) {
- mp[n] = devname;
- devname = NULL;
- bytes+=1+strlen(mp[n]);
- n++;
+ if ((changed == 1 || show_all) && !devname.empty()) {
+ names.push_back(devname);
+ devname.erase();
changed = 0;
};
}
- } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE) && n < MAX_NUM_DEV);
+ } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
- if (devname != NULL) {
- mp[n] = devname;
- devname = NULL;
- bytes+=1+strlen(mp[n]);
- n++;
- };
-
- mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
- bytes += (n)*(sizeof(char*)); // and set allocated byte count
+ if (!devname.empty())
+ names.push_back(devname);
-end:
free(ccb.cdm.matches);
- if (fd>-1)
- close(fd);
- if (n <= 0) {
- free(mp);
- mp = NULL;
- }
-
- *names=mp;
-
- if (serrno>-1)
- errno=serrno;
- return(n);
+ close(fd);
+ return true;
}
// we are using ATA subsystem enumerator to found all ATA devices on system
}
}
- char * * scsinames = 0; int numscsi = 0;
+ std::vector<std::string> scsinames;
if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
- numscsi = get_dev_names_cam(&scsinames,0);
- if (numscsi < 0) {
- set_err(ENOMEM);
+ if (!get_dev_names_cam(scsinames, false)) {
+ set_err(errno);
return false;
}
}
devlist.push_back(atadev);
}
- for (i = 0; i < numscsi; i++) {
+ for (i = 0; i < (int)scsinames.size(); i++) {
if(!*type) { // try USB autodetection if no type specified
- smart_device * smartdev = autodetect_smart_device(scsinames[i]);
+ smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
if(smartdev)
devlist.push_back(smartdev);
}
else {
- scsi_device * scsidev = get_scsi_device(scsinames[i], type);
+ scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
if (scsidev)
devlist.push_back(scsidev);
}
}
// check CAM
- char * * scsinames = 0; int numscsi = 0;
- numscsi = get_dev_names_cam(&scsinames, 1);
- if (numscsi > 0) {
+ std::vector<std::string> scsinames;
+ if (!get_dev_names_cam(scsinames, true))
+ pout("Unable to get CAM device list\n");
+ else if (!scsinames.empty()) {
// check all devices on CAM bus
- for (i = 0; i < numscsi; i++) {
- if(strcmp(scsinames[i],name)==0)
+ for (i = 0; i < (int)scsinames.size(); i++) {
+ if(strcmp(scsinames[i].c_str(), name)==0)
{ // our disk device is CAM
if ((cam_dev = cam_open_device(name, O_RDWR)) == NULL) {
// open failure
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;