version 1.1.1.1, 2012/02/21 16:32:16
|
version 1.1.1.2, 2012/10/09 09:36:45
|
Line 194 static const char smartctl_examples[] =
|
Line 194 static const char smartctl_examples[] =
|
" smartctl -a --device=cciss,0 /dev/ciss0\n" |
" smartctl -a --device=cciss,0 /dev/ciss0\n" |
" (Prints all SMART information for first disk \n" |
" (Prints all SMART information for first disk \n" |
" on Common Interface for SCSI-3 Support driver)\n" |
" on Common Interface for SCSI-3 Support driver)\n" |
" smartctl -a --device=areca,1 /dev/arcmsr0\n" | " smartctl -a --device=areca,3/1 /dev/arcmsr0\n" |
" (Prints all SMART information for first disk \n" | " (Prints all SMART information for 3rd disk in the 1st enclosure \n" |
" on first ARECA RAID controller)\n" |
" on first ARECA RAID controller)\n" |
|
|
; |
; |
Line 931 int freebsd_highpoint_device::ata_command_interface(sm
|
Line 931 int freebsd_highpoint_device::ata_command_interface(sm
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////// |
///////////////////////////////////////////////////////////////////////////// |
/// Implement standard SCSI support with old functions | /// Standard SCSI support |
|
|
class freebsd_scsi_device |
class freebsd_scsi_device |
: public /*implements*/ scsi_device, |
: public /*implements*/ scsi_device, |
Line 1013 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_
|
Line 1013 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_
|
warnx("error allocating ccb"); |
warnx("error allocating ccb"); |
return -ENOMEM; |
return -ENOMEM; |
} |
} |
|
// mfi SAT layer is known to be buggy |
|
if(!strcmp("mfi",m_camdev->sim_name)) { |
|
if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) { |
|
// Controller does not return ATA output registers in SAT sense data |
|
if (iop->cmnd[2] & (1 << 5)) // chk_cond |
|
return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware"); |
|
} |
|
// SMART WRITE LOG SECTOR causing media errors |
|
if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 && iop->cmnd[14] == ATA_SMART_CMD |
|
&& iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || |
|
(iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 && iop->cmnd[9] == ATA_SMART_CMD && |
|
iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) |
|
return set_err(ENOSYS, "SMART WRITE LOG SECTOR command is not supported by controller firmware"); |
|
} |
|
|
// clear out structure, except for header that was filled in for us |
// clear out structure, except for header that was filled in for us |
bzero(&(&ccb->ccb_h)[1], |
bzero(&(&ccb->ccb_h)[1], |
Line 1044 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_
|
Line 1058 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_
|
} |
} |
|
|
if (iop->sensep) { |
if (iop->sensep) { |
memcpy(iop->sensep,&(ccb->csio.sense_data),sizeof(struct scsi_sense_data)); | iop->resp_sense_len = ccb->csio.sense_len - ccb->csio.sense_resid; |
iop->resp_sense_len = sizeof(struct scsi_sense_data); | memcpy(iop->sensep,&(ccb->csio.sense_data),iop->resp_sense_len); |
} |
} |
|
|
iop->scsi_status = ccb->csio.scsi_status; |
iop->scsi_status = ccb->csio.scsi_status; |
Line 1075 class freebsd_areca_device
|
Line 1089 class freebsd_areca_device
|
public /*extends*/ freebsd_smart_device |
public /*extends*/ freebsd_smart_device |
{ |
{ |
public: |
public: |
freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum); | freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); |
|
|
protected: |
protected: |
virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); |
virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); |
|
|
private: |
private: |
int m_disknum; ///< Disk number. |
int m_disknum; ///< Disk number. |
|
int m_encnum; |
}; |
}; |
|
|
|
|
Line 1299 static int arcmsr_command_handler(int fd, unsigned lon
|
Line 1314 static int arcmsr_command_handler(int fd, unsigned lon
|
} |
} |
|
|
|
|
freebsd_areca_device::freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum) | freebsd_areca_device::freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum) |
: smart_device(intf, dev_name, "areca", "areca"), |
: smart_device(intf, dev_name, "areca", "areca"), |
freebsd_smart_device("ATA"), |
freebsd_smart_device("ATA"), |
m_disknum(disknum) | m_disknum(disknum), |
| m_encnum(encnum) |
{ |
{ |
set_info().info_name = strprintf("%s [areca_%02d]", dev_name, disknum); | set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum); |
} |
} |
|
|
// Areca RAID Controller |
// Areca RAID Controller |
Line 1423 if (!ata_cmd_is_ok(in,
|
Line 1439 if (!ata_cmd_is_ok(in,
|
return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type"); |
return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type"); |
} |
} |
|
|
areca_packet[11] = m_disknum - 1; // drive number | areca_packet[11] = m_disknum - 1; // disk # |
| areca_packet[19] = m_encnum - 1; // enc# |
|
|
// ----- BEGIN TO SETUP CHECKSUM ----- |
// ----- BEGIN TO SETUP CHECKSUM ----- |
for ( int loop = 3; loop < areca_packet_len - 1; loop++ ) |
for ( int loop = 3; loop < areca_packet_len - 1; loop++ ) |
Line 1590 smart_device * freebsd_scsi_device::autodetect_open()
|
Line 1607 smart_device * freebsd_scsi_device::autodetect_open()
|
return this; |
return this; |
} |
} |
|
|
// SAT or USB ? | // SAT or USB, skip MFI controllers because of bugs |
{ |
{ |
smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); |
smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); |
if (newdev) | if (newdev) { |
// NOTE: 'this' is now owned by '*newdev' |
// NOTE: 'this' is now owned by '*newdev' |
|
if(!strcmp("mfi",m_camdev->sim_name)) { |
|
newdev->close(); |
|
newdev->set_err(ENOSYS, "SATA device detected,\n" |
|
"MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow"); |
|
} |
return newdev; |
return newdev; |
|
} |
} |
} |
|
|
// Nothing special found |
// Nothing special found |
Line 1749 bool get_dev_names_cam(std::vector<std::string> & name
|
Line 1772 bool get_dev_names_cam(std::vector<std::string> & name
|
if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) { |
if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) { |
bus_result = &ccb.cdm.matches[i].result.bus_result; |
bus_result = &ccb.cdm.matches[i].result.bus_result; |
|
|
if (strcmp(bus_result->dev_name,"ata") == 0 /* ATAPICAM devices will be probed as ATA devices, skip'em there */ | if (strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */ |
|| strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */ | |
skip_bus = 1; |
skip_bus = 1; |
else |
else |
skip_bus = 0; |
skip_bus = 0; |
Line 2079 smart_device * freebsd_smart_interface::autodetect_sma
|
Line 2101 smart_device * freebsd_smart_interface::autodetect_sma
|
int bus=-1; |
int bus=-1; |
int i,c; |
int i,c; |
int len; |
int len; |
|
const char * test_name = name; |
|
|
// if dev_name null, or string length zero |
// if dev_name null, or string length zero |
if (!name || !(len = strlen(name))) |
if (!name || !(len = strlen(name))) |
return 0; |
return 0; |
|
|
|
// Dereference symlinks |
|
struct stat st; |
|
std::string pathbuf; |
|
if (!lstat(name, &st) && S_ISLNK(st.st_mode)) { |
|
char * p = realpath(name, (char *)0); |
|
if (p) { |
|
pathbuf = p; |
|
free(p); |
|
test_name = pathbuf.c_str(); |
|
} |
|
} |
|
|
// check ATA bus |
// check ATA bus |
char * * atanames = 0; int numata = 0; |
char * * atanames = 0; int numata = 0; |
numata = get_dev_names_ata(&atanames); |
numata = get_dev_names_ata(&atanames); |
if (numata > 0) { |
if (numata > 0) { |
// check ATA/ATAPI devices |
// check ATA/ATAPI devices |
for (i = 0; i < numata; i++) { |
for (i = 0; i < numata; i++) { |
if(!strcmp(atanames[i],name)) { | if(!strcmp(atanames[i],test_name)) { |
for (c = i; c < numata; c++) free(atanames[c]); |
for (c = i; c < numata; c++) free(atanames[c]); |
free(atanames); |
free(atanames); |
return new freebsd_ata_device(this, name, ""); | return new freebsd_ata_device(this, test_name, ""); |
} |
} |
else free(atanames[i]); |
else free(atanames[i]); |
} |
} |
Line 2111 smart_device * freebsd_smart_interface::autodetect_sma
|
Line 2146 smart_device * freebsd_smart_interface::autodetect_sma
|
else if (!scsinames.empty()) { |
else if (!scsinames.empty()) { |
// check all devices on CAM bus |
// check all devices on CAM bus |
for (i = 0; i < (int)scsinames.size(); i++) { |
for (i = 0; i < (int)scsinames.size(); i++) { |
if(strcmp(scsinames[i].c_str(), name)==0) | if(strcmp(scsinames[i].c_str(), test_name)==0) |
{ // our disk device is CAM |
{ // our disk device is CAM |
if ((cam_dev = cam_open_device(name, O_RDWR)) == NULL) { | if ((cam_dev = cam_open_device(test_name, O_RDWR)) == NULL) { |
// open failure |
// open failure |
set_err(errno); |
set_err(errno); |
return 0; |
return 0; |
} |
} |
|
|
// zero the payload |
// zero the payload |
bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE); |
bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE); |
ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device |
ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device |
Line 2136 smart_device * freebsd_smart_interface::autodetect_sma
|
Line 2170 smart_device * freebsd_smart_interface::autodetect_sma
|
if(usbdevlist(bus,vendor_id, product_id, version)){ |
if(usbdevlist(bus,vendor_id, product_id, version)){ |
const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version); |
const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version); |
if (usbtype) |
if (usbtype) |
return get_sat_device(usbtype, new freebsd_scsi_device(this, name, "")); | return get_sat_device(usbtype, new freebsd_scsi_device(this, test_name, "")); |
} |
} |
return 0; |
return 0; |
} |
} |
Line 2144 smart_device * freebsd_smart_interface::autodetect_sma
|
Line 2178 smart_device * freebsd_smart_interface::autodetect_sma
|
// check if we have ATA device connected to CAM (ada) |
// check if we have ATA device connected to CAM (ada) |
if(ccb.cpi.protocol == PROTO_ATA){ |
if(ccb.cpi.protocol == PROTO_ATA){ |
cam_close_device(cam_dev); |
cam_close_device(cam_dev); |
return new freebsd_atacam_device(this, name, ""); | return new freebsd_atacam_device(this, test_name, ""); |
} |
} |
#endif |
#endif |
// close cam device, we don`t need it anymore |
// close cam device, we don`t need it anymore |
cam_close_device(cam_dev); |
cam_close_device(cam_dev); |
// handle as usual scsi |
// handle as usual scsi |
return new freebsd_scsi_device(this, name, ""); | return new freebsd_scsi_device(this, test_name, ""); |
} |
} |
} |
} |
} |
} |
// device is LSI raid supported by mfi driver |
// device is LSI raid supported by mfi driver |
if(!strncmp("/dev/mfid", name, strlen("/dev/mfid"))) | if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid"))) |
set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information"); |
set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information"); |
// device type unknown |
// device type unknown |
return 0; |
return 0; |
Line 2230 smart_device * freebsd_smart_interface::get_custom_sma
|
Line 2264 smart_device * freebsd_smart_interface::get_custom_sma
|
set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum); |
set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum); |
return 0; |
return 0; |
} |
} |
return new freebsd_cciss_device(this, name, disknum); | return get_sat_device("sat,auto", new freebsd_cciss_device(this, name, disknum)); |
} |
} |
#if FREEBSDVER > 800100 |
#if FREEBSDVER > 800100 |
// adaX devices ? |
// adaX devices ? |
Line 2239 smart_device * freebsd_smart_interface::get_custom_sma
|
Line 2273 smart_device * freebsd_smart_interface::get_custom_sma
|
#endif |
#endif |
// Areca? |
// Areca? |
disknum = n1 = n2 = -1; |
disknum = n1 = n2 = -1; |
if (sscanf(type, "areca,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) { | int encnum = 1; |
if (n2 != (int)strlen(type)) { | if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) { |
set_err(EINVAL, "Option -d areca,N requires N to be a non-negative integer"); | if (!(1 <= disknum && disknum <= 128)) { |
| set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum); |
return 0; |
return 0; |
} |
} |
if (!(1 <= disknum && disknum <= 24)) { | if (!(1 <= encnum && encnum <= 8)) { |
set_err(EINVAL, "Option -d areca,N (N=%d) must have 1 <= N <= 24", disknum); | set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum); |
return 0; |
return 0; |
} |
} |
return new freebsd_areca_device(this, name, disknum); |
return new freebsd_areca_device(this, name, disknum); |
Line 2256 smart_device * freebsd_smart_interface::get_custom_sma
|
Line 2291 smart_device * freebsd_smart_interface::get_custom_sma
|
|
|
std::string freebsd_smart_interface::get_valid_custom_dev_types_str() |
std::string freebsd_smart_interface::get_valid_custom_dev_types_str() |
{ |
{ |
return "3ware,N, hpt,L/M/N, cciss,N, areca,N" | return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E" |
#if FREEBSDVER > 800100 |
#if FREEBSDVER > 800100 |
", atacam" |
", atacam" |
#endif |
#endif |