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

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

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