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>