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>