X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=os_linux.cpp;h=4a96a821f02393f153f586e0be3a2aa7c2109bd0;hb=d2e702cfb9891eb94c5b32ca86169a49ffe6f77e;hp=164e8f794efdf98532cacaf6018c11b891b94cea;hpb=ee38a438aafef7a04b7df628ca5ad38810a1d63e;p=mirror_smartmontools-debian.git diff --git a/os_linux.cpp b/os_linux.cpp index 164e8f7..4a96a82 100644 --- a/os_linux.cpp +++ b/os_linux.cpp @@ -5,16 +5,23 @@ * * Copyright (C) 2003-11 Bruce Allen * Copyright (C) 2003-11 Doug Gilbert - * Copyright (C) 2008-12 Hank Wu - * Copyright (C) 2008 Oliver Bock - * Copyright (C) 2008-12 Christian Franke - * Copyright (C) 2008 Jordan Hargrave + * Copyright (C) 2008-14 Christian Franke * - * Parts of this file are derived from code that was + * Original AACRaid code: + * Copyright (C) 2014 Raghava Aditya + * + * Original Areca code: + * Copyright (C) 2008-12 Hank Wu + * Copyright (C) 2008 Oliver Bock + * + * Original MegaRAID code: + * Copyright (C) 2008 Jordan Hargrave + * + * 3ware code was derived from code that was: * * Written By: Adam Radford * Modifications By: Joel Jacobson - * Arnaldo Carvalho de Melo + * Arnaldo Carvalho de Melo * Brad Strand * * Copyright (C) 1999-2003 3ware Inc. @@ -80,6 +87,7 @@ #include "utility.h" #include "cciss.h" #include "megaraid.h" +#include "aacraid.h" #include "dev_interface.h" #include "dev_ata_cmd_set.h" @@ -91,7 +99,7 @@ #define ARGUSED(x) ((void)(x)) -const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3738 2012-12-17 12:01:35Z samm2 $" +const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3900 2014-05-01 17:08:59Z chrfranke $" OS_LINUX_H_CVSID; extern unsigned char failuretest_permissive; @@ -859,6 +867,217 @@ bool linux_scsi_device::scsi_pass_through(scsi_cmnd_io * iop) return true; } +///////////////////////////////////////////////////////////////////////////// +/// PMC AacRAID support + +class linux_aacraid_device +:public scsi_device, + public /*extends */ linux_smart_device +{ +public: + linux_aacraid_device(smart_interface *intf, const char *dev_name, + unsigned int host, unsigned int channel, unsigned int device); + + virtual ~linux_aacraid_device() throw(); + + virtual bool open(); + + virtual bool scsi_pass_through(scsi_cmnd_io *iop); + +private: + //Device Host number + int aHost; + + //Channel(Lun) of the device + int aLun; + + //Id of the device + int aId; + +}; + +linux_aacraid_device::linux_aacraid_device(smart_interface *intf, + const char *dev_name, unsigned int host, unsigned int channel, unsigned int device) + : smart_device(intf,dev_name,"aacraid","aacraid"), + linux_smart_device(O_RDWR|O_NONBLOCK), + aHost(host), aLun(channel), aId(device) +{ + set_info().info_name = strprintf("%s [aacraid_disk_%02d_%02d_%d]",dev_name,aHost,aLun,aId); + set_info().dev_type = strprintf("aacraid,%d,%d,%d",aHost,aLun,aId); +} + +linux_aacraid_device::~linux_aacraid_device() throw() +{ +} + +bool linux_aacraid_device::open() +{ + //Create the character device name based on the host number + //Required for get stats from disks connected to different controllers + char dev_name[128]; + snprintf(dev_name, sizeof(dev_name), "/dev/aac%d", aHost); + + //Initial open of dev name to check if it exsists + int afd = ::open(dev_name,O_RDWR); + + if(afd < 0 && errno == ENOENT) { + + FILE *fp = fopen("/proc/devices","r"); + if(NULL == fp) + return set_err(errno,"cannot open /proc/devices:%s", + strerror(errno)); + + char line[256]; + int mjr = -1; + + while(fgets(line,sizeof(line),fp) !=NULL) { + int nc = -1; + if(sscanf(line,"%d aac%n",&mjr,&nc) == 1 + && nc > 0 && '\n' == line[nc]) + break; + mjr = -1; + } + + //work with /proc/devices is done + fclose(fp); + + if (mjr < 0) + return set_err(ENOENT, "aac entry not found in /proc/devices"); + + //Create misc device file in /dev/ used for communication with driver + if(mknod(dev_name,S_IFCHR,makedev(mjr,aHost))) + return set_err(errno,"cannot create %s:%s",dev_name,strerror(errno)); + + afd = ::open(dev_name,O_RDWR); + } + + if(afd < 0) + return set_err(errno,"cannot open %s:%s",dev_name,strerror(errno)); + + set_fd(afd); + return true; +} + +bool linux_aacraid_device::scsi_pass_through(scsi_cmnd_io *iop) +{ + int report = scsi_debugmode; + + if (report > 0) { + int k, j; + const unsigned char * ucp = iop->cmnd; + const char * np; + char buff[256]; + const int sz = (int)sizeof(buff); + + np = scsi_get_opcode_name(ucp[0]); + j = snprintf(buff, sz, " [%s: ", np ? np : ""); + for (k = 0; k < (int)iop->cmnd_len; ++k) + j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]); + if ((report > 1) && + (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { + int trunc = (iop->dxfer_len > 256) ? 1 : 0; + + j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing " + "data, len=%d%s:\n", (int)iop->dxfer_len, + (trunc ? " [only first 256 bytes shown]" : "")); + dStrHex((const char *)iop->dxferp, + (trunc ? 256 : iop->dxfer_len) , 1); + } + else + j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); + + pout("%s", buff); + } + + + //return test commands + if (iop->cmnd[0] == 0x00) + return true; + + user_aac_reply *pReply; + + #ifdef ENVIRONMENT64 + // Create user 64 bit request + user_aac_srb64 *pSrb; + uint8_t aBuff[sizeof(user_aac_srb64) + sizeof(user_aac_reply)] = {0,}; + + pSrb = (user_aac_srb64*)aBuff; + pReply = (user_aac_reply*)(aBuff+sizeof(user_aac_srb64)); + + #elif defined(ENVIRONMENT32) + //Create user 32 bit request + user_aac_srb32 *pSrb; + uint8_t aBuff[sizeof(user_aac_srb32) + sizeof(user_aac_reply)] = {0,}; + + pSrb = (user_aac_srb32*)aBuff; + pReply = (user_aac_reply*)(aBuff+sizeof(user_aac_srb32)); + + #endif + + pSrb->function = SRB_FUNCTION_EXECUTE_SCSI; + //channel is 0 always + pSrb->channel = 0; + pSrb->id = aId; + pSrb->lun = aLun; + pSrb->timeout = 0; + + pSrb->retry_limit = 0; + pSrb->cdb_size = iop->cmnd_len; + + switch(iop->dxfer_dir) { + case DXFER_NONE: + pSrb->flags = SRB_NoDataXfer; + break; + case DXFER_FROM_DEVICE: + pSrb->flags = SRB_DataIn; + break; + case DXFER_TO_DEVICE: + pSrb->flags = SRB_DataOut; + break; + default: + pout("aacraid: bad dxfer_dir\n"); + return set_err(EINVAL, "aacraid: bad dxfer_dir\n"); + } + + if(iop->dxfer_len > 0) { + + #ifdef ENVIRONMENT64 + pSrb->sg64.count = 1; + pSrb->sg64.sg64[0].addr64.lo32 = ((intptr_t)iop->dxferp) & + 0x00000000ffffffff; + pSrb->sg64.sg64[0].addr64.hi32 = ((intptr_t)iop->dxferp) >> 32; + + pSrb->sg64.sg64[0].length = (uint32_t)iop->dxfer_len; + pSrb->count = sizeof(user_aac_srb64) + + (sizeof(user_sgentry64)*(pSrb->sg64.count-1)); + #elif defined(ENVIRONMENT32) + pSrb->sg32.count = 1; + pSrb->sg32.sg32[0].addr32 = (intptr_t)iop->dxferp; + + pSrb->sg32.sg32[0].length = (uint32_t)iop->dxfer_len; + pSrb->count = sizeof(user_aac_srb32) + + (sizeof(user_sgentry32)*(pSrb->sg32.count-1)); + #endif + + } + + memcpy(pSrb->cdb,iop->cmnd,iop->cmnd_len); + + int rc = 0; + errno = 0; + rc = ioctl(get_fd(),FSACTL_SEND_RAW_SRB,pSrb); + if(rc!= 0 || pReply->srb_status != 0x01) { + if(pReply->srb_status == 0x08) { + return set_err(EIO, "aacraid: Device %d %d does not exist\n" ,aLun,aId ); + } + return set_err((errno ? errno : EIO), "aacraid result: %d.%d = %d/%d", + aLun, aId, errno, + pReply->srb_status); + } + return true; +} + + ///////////////////////////////////////////////////////////////////////////// /// LSI MegaRAID support @@ -2488,7 +2707,7 @@ bool linux_smart_interface::get_dev_list(smart_device_list & devlist, } // did we find too many paths? - const int max_pathc = 32; + const int max_pathc = 1024; int n = (int)globbuf.gl_pathc; if (n > max_pathc) { pout("glob(3) found %d > MAX=%d devices matching pattern %s: ignoring %d paths\n", @@ -2908,7 +3127,7 @@ smart_device * linux_smart_interface::get_custom_smart_device(const char * name, set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied"); return 0; } - if (!(1 <= channel && channel <= 16)) { + if (!(1 <= channel && channel <= 128)) { set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied"); return 0; } @@ -2939,12 +3158,23 @@ smart_device * linux_smart_interface::get_custom_smart_device(const char * name, if (sscanf(type, "megaraid,%d", &disknum) == 1) { return new linux_megaraid_device(this, name, 0, disknum); } + + //aacraid? + unsigned int device; + unsigned int host; + if(sscanf(type, "aacraid,%d,%d,%d", &host, &channel, &device)==3) { + //return new linux_aacraid_device(this,name,channel,device); + return get_sat_device("sat,auto", + new linux_aacraid_device(this, name, host, channel, device)); + + } + return 0; } std::string linux_smart_interface::get_valid_custom_dev_types_str() { - return "marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N" + return "marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID" #ifdef HAVE_LINUX_CCISS_IOCTL_H ", cciss,N" #endif