Annotation of embedaddon/smartmontools/cciss.cpp, revision 1.1.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>