]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - cciss.cpp
Stop passing arguments to dh_installinit
[mirror_smartmontools-debian.git] / cciss.cpp
CommitLineData
a37e7145
GG
1#include <stdio.h>
2#include <string.h>
3#include <sys/types.h>
cfbba5b9 4#include <errno.h>
a37e7145
GG
5
6#include "config.h"
7
d2e702cf 8#if defined(linux) || defined(__linux__)
a37e7145
GG
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>
e9583e0c
GI
18# ifndef be32toh
19# define be32toh __be32_to_cpu
20# endif
d008864d 21#elif defined(__FreeBSD__)
a37e7145 22# include <sys/endian.h>
d008864d 23# include CISS_LOCATION
a37e7145 24# define _HAVE_CCISS
d008864d 25#elif defined(__FreeBSD_kernel__)
54965743 26# include <endian.h>
ee38a438
GI
27# ifdef __GLIBC__
28# include <bsd/sys/cdefs.h>
29# include <stdint.h>
30# endif
d008864d 31# include CISS_LOCATION
54965743 32# define _HAVE_CCISS
a37e7145
GG
33#endif
34
35#ifdef _HAVE_CCISS
cfbba5b9 36#include "cciss.h"
a37e7145
GG
37#include "int64.h"
38#include "scsicmds.h"
39#include "utility.h"
40
6b80b4d2 41const char * cciss_cpp_cvsid = "$Id: cciss.cpp 4156 2015-10-18 12:20:40Z samm2 $"
cfbba5b9 42 CCISS_H_CVSID;
2127e193 43
a37e7145
GG
44typedef 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
61static int cciss_getlun(int device, int target, unsigned char *physlun, int report);
62static 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*/
71int 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;
a37e7145
GG
76 int len = 0; // used later in the code.
77
6b80b4d2 78 int status = cciss_getlun(device, target, phylun, report);
a37e7145
GG
79 if (report > 0)
80 printf(" cciss_getlun(%d, %d) = 0x%x; scsi3addr: %02x %02x %02x %02x %02x %02x %02x %02x\n",
81 device, target, status,
82 phylun[0], phylun[1], phylun[2], phylun[3], phylun[4], phylun[5], phylun[6], phylun[7]);
83 if (status) {
84 return -ENXIO; /* give up, assume no device there */
85 }
86
87 status = cciss_sendpassthru( 2, iop->cmnd, iop->cmnd_len, (char*) pBuf, iBufLen, 1, phylun, device);
88
89 if (0 == status)
90 {
91 if (report > 0)
92 printf(" status=0\n");
93 if (DXFER_FROM_DEVICE == iop->dxfer_dir)
94 {
95 memcpy(iop->dxferp, pBuf, iop->dxfer_len);
96 if (report > 1)
97 {
98 int trunc = (iop->dxfer_len > 256) ? 1 : 0;
99 printf(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
100 (trunc ? " [only first 256 bytes shown]" : ""));
101 dStrHex((const char*)iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
102 }
103 }
104 return 0;
105 }
106 iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */
107 if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf))
108 iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
109 len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ?
110 SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len;
111 if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&
112 iop->sensep && (len > 0))
113 {
114 memcpy(iop->sensep, pBuf, len);
115 iop->resp_sense_len = iBufLen;
116 if (report > 1)
117 {
118 printf(" >>> Sense buffer, len=%d:\n", (int)len);
119 dStrHex((const char *)pBuf, len , 1);
120 }
121 }
122 if (report)
123 {
124 if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) {
125 printf(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff,
126 pBuf[2] & 0xf, pBuf[12], pBuf[13]);
127 }
128 else
129 printf(" status=0x%x\n", status);
130 }
131 if (iop->scsi_status > 0)
132 return 0;
133 else
134 {
135 if (report > 0)
136 printf(" ioctl status=0x%x but scsi status=0, fail with ENXIO\n", status);
137 return -ENXIO; /* give up, assume no device there */
138 }
139}
140
141static int cciss_sendpassthru(unsigned int cmdtype, unsigned char *CDB,
142 unsigned int CDBlen, char *buff,
143 unsigned int size, unsigned int LunID,
144 unsigned char *scsi3addr, int fd)
145{
146 int err ;
147 IOCTL_Command_struct iocommand;
148
149 memset(&iocommand, 0, sizeof(iocommand));
150
151 if (cmdtype == 0)
152 {
153 // To controller; nothing to do
154 }
155 else if (cmdtype == 1)
156 {
157 iocommand.LUN_info.LogDev.VolId = LunID;
158 iocommand.LUN_info.LogDev.Mode = 1;
159 }
160 else if (cmdtype == 2)
161 {
162 memcpy(&iocommand.LUN_info.LunAddrBytes,scsi3addr,8);
163 iocommand.LUN_info.LogDev.Mode = 0;
164 }
165 else
166 {
167 fprintf(stderr, "cciss_sendpassthru: bad cmdtype\n");
168 return 1;
169 }
170
171 memcpy(&iocommand.Request.CDB[0], CDB, CDBlen);
172 iocommand.Request.CDBLen = CDBlen;
173 iocommand.Request.Type.Type = TYPE_CMD;
174 iocommand.Request.Type.Attribute = ATTR_SIMPLE;
175 iocommand.Request.Type.Direction = XFER_READ;
176 iocommand.Request.Timeout = 0;
177
178 iocommand.buf_size = size;
179 iocommand.buf = (unsigned char *)buff;
180
181 if ((err = ioctl(fd, CCISS_PASSTHRU, &iocommand)))
182 {
6b80b4d2 183 fprintf(stderr, "CCISS ioctl error %d (fd %d CDBLen %u buf_size %u)\n",
a37e7145
GG
184 fd, err, CDBlen, size);
185 }
186 return err;
187}
188
189static int cciss_getlun(int device, int target, unsigned char *physlun, int report)
190{
191 unsigned char CDB[16]= {0};
192 ReportLunData_struct *luns;
193 int reportlunsize = sizeof(*luns) + CISS_MAX_PHYS_LUN * 8;
a37e7145
GG
194 int ret;
195
196 luns = (ReportLunData_struct *)malloc(reportlunsize);
197
198 memset(luns, 0, reportlunsize);
199
200 /* Get Physical LUN Info (for physical device) */
201 CDB[0] = CISS_REPORT_PHYS;
202 CDB[6] = (reportlunsize >> 24) & 0xFF; /* MSB */
203 CDB[7] = (reportlunsize >> 16) & 0xFF;
204 CDB[8] = (reportlunsize >> 8) & 0xFF;
205 CDB[9] = reportlunsize & 0xFF;
206
207 if ((ret = cciss_sendpassthru(0, CDB, 12, (char *)luns, reportlunsize, 0, NULL, device)))
208 {
209 free(luns);
210 return ret;
211 }
212
213 if (report > 1)
214 {
215 unsigned int i,j;
216 unsigned char *stuff = (unsigned char *)luns;
217
218 pout("\n===== [%s] DATA START (BASE-16) =====\n", "LUN DATA");
219 for (i=0; i<(sizeof(_ReportLUNdata_struct)+15)/16; i++){
220 pout("%03d-%03d: ", 16*i, 16*(i+1)-1);
221 for (j=0; j<15; j++)
222 pout("%02x ",*stuff++);
223 pout("%02x\n",*stuff++);
224 }
2127e193 225 pout("===== [%s] DATA END (%u Bytes) =====\n\n", "LUN DATA", (unsigned)sizeof(_ReportLUNdata_struct));
a37e7145
GG
226 }
227
a37e7145
GG
228 if (target >= 0 && target < (int) be32toh(luns->LUNListLength) / 8)
229 {
230 memcpy(physlun, luns->LUN[target], 8);
231 free(luns);
232 return 0;
233 }
a37e7145
GG
234
235 free(luns);
236 return 1;
237}
238#endif