Annotation of embedaddon/smartmontools/cciss.cpp, revision 1.1

1.1     ! misho       1: #include <stdio.h>
        !             2: #include <string.h>
        !             3: #include <sys/types.h>
        !             4: #include <errno.h>
        !             5: 
        !             6: #include "config.h"
        !             7: 
        !             8: #if defined(linux)
        !             9: #  include <sys/ioctl.h>
        !            10: #  ifdef HAVE_LINUX_COMPILER_H
        !            11: #    include <linux/compiler.h>
        !            12: #  endif
        !            13: #  if defined(HAVE_LINUX_CCISS_IOCTL_H)
        !            14: #    include <linux/cciss_ioctl.h>
        !            15: #    define _HAVE_CCISS
        !            16: #  endif
        !            17: #  include <asm/byteorder.h>
        !            18: #  ifndef be32toh
        !            19: #    define be32toh __be32_to_cpu
        !            20: #  endif
        !            21: #elif defined(__FreeBSD__)
        !            22: #  include <sys/endian.h>
        !            23: #  include CISS_LOCATION
        !            24: #  define _HAVE_CCISS
        !            25: #elif defined(__FreeBSD_kernel__)
        !            26: #  include <endian.h>
        !            27: #  include CISS_LOCATION
        !            28: #  define _HAVE_CCISS
        !            29: #endif
        !            30: 
        !            31: #ifdef _HAVE_CCISS
        !            32: #include "cciss.h"
        !            33: #include "int64.h"
        !            34: #include "scsicmds.h"
        !            35: #include "utility.h"
        !            36: 
        !            37: const char * cciss_cpp_cvsid = "$Id: cciss.cpp 3446 2011-10-13 22:36:28Z samm2 $"
        !            38:   CCISS_H_CVSID;
        !            39: 
        !            40: typedef struct _ReportLUNdata_struct
        !            41: {
        !            42:   uint32_t LUNListLength;      /* always big-endian */
        !            43:   uint32_t reserved;
        !            44:   uint8_t LUN[CISS_MAX_LUN][8];
        !            45: } ReportLunData_struct;
        !            46: 
        !            47: /* Structure/defines of Report Physical LUNS of drive */
        !            48: #ifndef CISS_MAX_LUN
        !            49: #define CISS_MAX_LUN        16
        !            50: #endif
        !            51: #define CISS_MAX_PHYS_LUN   1024
        !            52: #define CISS_REPORT_PHYS    0xc3
        !            53: 
        !            54: #define LSCSI_DRIVER_SENSE  0x8                /* alternate CHECK CONDITION indication */
        !            55: #define SEND_IOCTL_RESP_SENSE_LEN 16    /* ioctl limitation */
        !            56: 
        !            57: static int cciss_getlun(int device, int target, unsigned char *physlun, int report);
        !            58: static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB,
        !            59:                        unsigned int CDBlen, char *buff,
        !            60:                        unsigned int size, unsigned int LunID,
        !            61:                        unsigned char *scsi3addr, int fd);
        !            62: 
        !            63: /* 
        !            64:    This is an interface that uses the cciss passthrough to talk to the SMART controller on
        !            65:    the HP system. The cciss driver provides a way to send SCSI cmds through the CCISS passthrough.
        !            66: */
        !            67: int cciss_io_interface(int device, int target, struct scsi_cmnd_io * iop, int report)
        !            68: {
        !            69:      unsigned char pBuf[512] = {0};
        !            70:      unsigned char phylun[8] = {0};
        !            71:      int iBufLen = 512;
        !            72:      int status = -1;
        !            73:      int len = 0; // used later in the code.
        !            74:  
        !            75:      status = cciss_getlun(device, target, phylun, report);
        !            76:      if (report > 0)
        !            77:          printf("  cciss_getlun(%d, %d) = 0x%x; scsi3addr: %02x %02x %02x %02x %02x %02x %02x %02x\n", 
        !            78:             device, target, status, 
        !            79:             phylun[0], phylun[1], phylun[2], phylun[3], phylun[4], phylun[5], phylun[6], phylun[7]);
        !            80:      if (status) {
        !            81:          return -ENXIO;      /* give up, assume no device there */
        !            82:      }
        !            83: 
        !            84:      status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device);
        !            85:  
        !            86:      if (0 == status)
        !            87:      {
        !            88:          if (report > 0)
        !            89:              printf("  status=0\n");
        !            90:          if (DXFER_FROM_DEVICE == iop->dxfer_dir)
        !            91:          {
        !            92:              memcpy(iop->dxferp, pBuf, iop->dxfer_len);
        !            93:              if (report > 1)
        !            94:              {
        !            95:                  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
        !            96:                  printf("  Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
        !            97:                       (trunc ? " [only first 256 bytes shown]" : ""));
        !            98:                  dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
        !            99:              }
        !           100:          }
        !           101:          return 0;
        !           102:      }
        !           103:      iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */
        !           104:      if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf))
        !           105:          iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
        !           106:      len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ?
        !           107:                 SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len;
        !           108:      if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&
        !           109:          iop->sensep && (len > 0))
        !           110:      {
        !           111:          memcpy(iop->sensep, pBuf, len);
        !           112:          iop->resp_sense_len = iBufLen;
        !           113:          if (report > 1)
        !           114:          {
        !           115:              printf("  >>> Sense buffer, len=%d:\n", (int)len);
        !           116:              dStrHex((const char *)pBuf, len , 1);
        !           117:          }
        !           118:      }
        !           119:      if (report)
        !           120:      {
        !           121:          if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) {
        !           122:              printf("  status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff,
        !           123:                   pBuf[2] & 0xf, pBuf[12], pBuf[13]);
        !           124:          }
        !           125:          else
        !           126:              printf("  status=0x%x\n", status);
        !           127:      }
        !           128:      if (iop->scsi_status > 0)
        !           129:          return 0;
        !           130:      else
        !           131:      {
        !           132:          if (report > 0)
        !           133:              printf("  ioctl status=0x%x but scsi status=0, fail with ENXIO\n", status);
        !           134:          return -ENXIO;      /* give up, assume no device there */
        !           135:      }
        !           136: } 
        !           137: 
        !           138: static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB,
        !           139:                        unsigned int CDBlen, char *buff,
        !           140:                        unsigned int size, unsigned int LunID,
        !           141:                        unsigned char *scsi3addr, int fd)
        !           142: {
        !           143:     int err ;
        !           144:     IOCTL_Command_struct iocommand;
        !           145: 
        !           146:     memset(&iocommand, 0, sizeof(iocommand));
        !           147: 
        !           148:     if (cmdtype == 0) 
        !           149:     {
        !           150:         // To controller; nothing to do
        !           151:     }
        !           152:     else if (cmdtype == 1) 
        !           153:     {
        !           154:         iocommand.LUN_info.LogDev.VolId = LunID;
        !           155:         iocommand.LUN_info.LogDev.Mode = 1;
        !           156:     }
        !           157:     else if (cmdtype == 2) 
        !           158:     {
        !           159:         memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8);
        !           160:         iocommand.LUN_info.LogDev.Mode = 0;
        !           161:     }
        !           162:     else 
        !           163:     {
        !           164:         fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n");
        !           165:         return 1;
        !           166:     }
        !           167: 
        !           168:     memcpy(&iocommand.Request.CDB[0], CDB, CDBlen);
        !           169:     iocommand.Request.CDBLen = CDBlen;
        !           170:     iocommand.Request.Type.Type = TYPE_CMD;
        !           171:     iocommand.Request.Type.Attribute = ATTR_SIMPLE;
        !           172:     iocommand.Request.Type.Direction = XFER_READ;
        !           173:     iocommand.Request.Timeout = 0;
        !           174: 
        !           175:     iocommand.buf_size = size;
        !           176:     iocommand.buf = (unsigned char *)buff;
        !           177: 
        !           178:     if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand))) 
        !           179:     {
        !           180:         fprintf(stderr, "CCISS ioctl error %d (fd %d CDBLen %d buf_size %d)\n",
        !           181:            fd, err, CDBlen, size);
        !           182:     }
        !           183:     return err;
        !           184: }
        !           185: 
        !           186: static int cciss_getlun(int device, int target, unsigned char *physlun, int report)
        !           187: {
        !           188:     unsigned char CDB[16]= {0};
        !           189:     ReportLunData_struct *luns;
        !           190:     int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8;
        !           191:     int ret;
        !           192: 
        !           193:     luns = (ReportLunData_struct *)malloc(reportlunsize);
        !           194: 
        !           195:     memset(luns, 0, reportlunsize);
        !           196: 
        !           197:     /* Get Physical LUN Info (for physical device) */
        !           198:     CDB[0] = CISS_REPORT_PHYS;
        !           199:     CDB[6] = (reportlunsize >> 24) & 0xFF;  /* MSB */
        !           200:     CDB[7] = (reportlunsize >> 16) & 0xFF;
        !           201:     CDB[8] = (reportlunsize >> 8) & 0xFF;
        !           202:     CDB[9] = reportlunsize & 0xFF;
        !           203: 
        !           204:     if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device)))
        !           205:     {
        !           206:         free(luns);
        !           207:         return ret;
        !           208:     }
        !           209: 
        !           210:     if (report > 1)
        !           211:     {
        !           212:       unsigned int i,j;
        !           213:       unsigned char *stuff = (unsigned char *)luns;
        !           214: 
        !           215:       pout("\n===== [%s] DATA START (BASE-16) =====\n", "LUN DATA");
        !           216:       for (i=0; i<(sizeof(_ReportLUNdata_struct)+15)/16; i++){
        !           217:        pout("%03d-%03d: ", 16*i, 16*(i+1)-1);
        !           218:        for (j=0; j<15; j++)
        !           219:          pout("%02x ",*stuff++);
        !           220:        pout("%02x\n",*stuff++);
        !           221:       }
        !           222:       pout("===== [%s] DATA END (%u Bytes) =====\n\n", "LUN DATA", (unsigned)sizeof(_ReportLUNdata_struct));
        !           223:     }
        !           224: 
        !           225:     if (target >= 0 && target < (int) be32toh(luns->LUNListLength) / 8)
        !           226:     {
        !           227:        memcpy(physlun, luns->LUN[target], 8);
        !           228:        free(luns);
        !           229:        return 0;
        !           230:     }
        !           231: 
        !           232:     free(luns);
        !           233:     return 1;
        !           234: }
        !           235: #endif 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>