2 * Copyright (c) 2005 Christophe Varoqui
11 #include <sys/ioctl.h>
17 #include "../libmultipath/sg_include.h"
19 #define INQUIRY_CMDLEN 6
20 #define INQUIRY_CMD 0x12
21 #define MODE_SENSE_CMD 0x5a
22 #define MODE_SELECT_CMD 0x55
23 #define MODE_SEN_SEL_CMDLEN 10
24 #define SENSE_BUFF_LEN 32
25 #define SCSI_CHECK_CONDITION 0x2
26 #define SCSI_COMMAND_TERMINATED 0x22
27 #define SG_ERR_DRIVER_SENSE 0x08
28 #define RECOVERED_ERROR 0x01
31 #define CURRENT_PAGE_CODE_VALUES 0
32 #define CHANGEABLE_PAGE_CODE_VALUES 1
34 #define MSG_RDAC_DOWN " reports path is down"
35 #define MSG_RDAC_DOWN_TYPE(STR) MSG_RDAC_DOWN": "STR
37 #define RTPG_UNAVAILABLE 0x3
38 #define RTPG_OFFLINE 0xE
39 #define RTPG_TRANSITIONING 0xF
41 #define RTPG_UNAVAIL_NON_RESPONSIVE 0x2
42 #define RTPG_UNAVAIL_IN_RESET 0x3
43 #define RTPG_UNAVAIL_CFW_DL1 0x4
44 #define RTPG_UNAVAIL_CFW_DL2 0x5
45 #define RTPG_UNAVAIL_QUIESCED 0x6
46 #define RTPG_UNAVAIL_SERVICE_MODE 0x7
48 struct control_mode_page {
49 unsigned char header[8];
50 unsigned char page_code;
51 unsigned char page_len;
52 unsigned char dontcare0[3];
53 unsigned char tas_bit;
54 unsigned char dontcare1[6];
57 struct rdac_checker_context {
61 int libcheck_init (struct checker * c)
63 unsigned char cmd[MODE_SEN_SEL_CMDLEN];
64 unsigned char sense_b[SENSE_BUFF_LEN];
65 struct sg_io_hdr io_hdr;
66 struct control_mode_page current, changeable;
69 memset(cmd, 0, MODE_SEN_SEL_CMDLEN);
70 cmd[0] = MODE_SENSE_CMD;
71 cmd[1] = 0x08; /* DBD bit on */
72 cmd[2] = 0xA + (CURRENT_PAGE_CODE_VALUES << 6);
73 cmd[8] = (sizeof(struct control_mode_page) & 0xff);
75 memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
76 memset(sense_b, 0, SENSE_BUFF_LEN);
77 memset(¤t, 0, sizeof(struct control_mode_page));
79 io_hdr.interface_id = 'S';
80 io_hdr.cmd_len = MODE_SEN_SEL_CMDLEN;
81 io_hdr.mx_sb_len = sizeof(sense_b);
82 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
83 io_hdr.dxfer_len = (sizeof(struct control_mode_page) & 0xff);
84 io_hdr.dxferp = ¤t;
87 io_hdr.timeout = c->timeout * 1000;
89 if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
92 /* check the TAS bit to see if it is already set */
93 if ((current.tas_bit >> 6) & 0x1) {
98 /* get the changeble values */
99 cmd[2] = 0xA + (CHANGEABLE_PAGE_CODE_VALUES << 6);
100 io_hdr.dxferp = &changeable;
101 memset(&changeable, 0, sizeof(struct control_mode_page));
103 if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
106 /* if TAS bit is not settable exit */
107 if (((changeable.tas_bit >> 6) & 0x1) == 0)
110 /* Now go ahead and set it */
111 memset(cmd, 0, MODE_SEN_SEL_CMDLEN);
112 cmd[0] = MODE_SELECT_CMD;
113 cmd[1] = 0x1; /* set SP bit on */
114 cmd[8] = (sizeof(struct control_mode_page) & 0xff);
116 /* use the same buffer as current, only set the tas bit */
117 current.page_code = 0xA;
118 current.page_len = 0xA;
119 current.tas_bit |= (1 << 6);
121 io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
122 io_hdr.dxferp = ¤t;
124 if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
131 condlog(3, "rdac checker failed to set TAS bit");
135 void libcheck_free (struct checker * c)
141 do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len,
142 unsigned int timeout)
144 unsigned char inqCmdBlk[INQUIRY_CMDLEN] = { INQUIRY_CMD, 1, 0, 0, 0, 0 };
145 unsigned char sense_b[SENSE_BUFF_LEN];
146 struct sg_io_hdr io_hdr;
150 inqCmdBlk[2] = (unsigned char) pg_op;
151 inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
152 memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
153 memset(sense_b, 0, SENSE_BUFF_LEN);
155 io_hdr.interface_id = 'S';
156 io_hdr.cmd_len = sizeof (inqCmdBlk);
157 io_hdr.mx_sb_len = sizeof (sense_b);
158 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
159 io_hdr.dxfer_len = mx_resp_len;
160 io_hdr.dxferp = resp;
161 io_hdr.cmdp = inqCmdBlk;
162 io_hdr.sbp = sense_b;
163 io_hdr.timeout = timeout * 1000;
165 if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
168 /* treat SG_ERR here to get rid of sg_err.[ch] */
169 io_hdr.status &= 0x7e;
170 if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
171 (0 == io_hdr.driver_status))
174 /* check if we need to retry this error */
175 if (io_hdr.info & SG_INFO_OK_MASK) {
176 switch (io_hdr.host_status) {
180 case DID_TRANSPORT_DISRUPTED:
181 /* Transport error, retry */
190 if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
191 (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
192 (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
193 if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
195 unsigned char * sense_buffer = io_hdr.sbp;
196 if (sense_buffer[0] & 0x2)
197 sense_key = sense_buffer[1] & 0xf;
199 sense_key = sense_buffer[2] & 0xf;
200 if (RECOVERED_ERROR == sense_key)
207 struct volume_access_inq
214 char vendor_specific_cur;
216 char vendor_specific_alt;
221 RDAC_MSGID_NOT_CONN = CHECKER_FIRST_MSGID,
222 RDAC_MSGID_IN_STARTUP,
223 RDAC_MSGID_NON_RESPONSIVE,
225 RDAC_MSGID_FW_DOWNLOADING,
227 RDAC_MSGID_SERVICE_MODE,
228 RDAC_MSGID_UNAVAILABLE,
229 RDAC_MSGID_INQUIRY_FAILED,
232 #define _IDX(x) (RDAC_MSGID_##x - CHECKER_FIRST_MSGID)
233 const char *libcheck_msgtable[] = {
234 [_IDX(NOT_CONN)] = MSG_RDAC_DOWN_TYPE("lun not connected"),
235 [_IDX(IN_STARTUP)] = MSG_RDAC_DOWN_TYPE("ctlr is in startup sequence"),
236 [_IDX(NON_RESPONSIVE)] =
237 MSG_RDAC_DOWN_TYPE("non-responsive to queries"),
238 [_IDX(IN_RESET)] = MSG_RDAC_DOWN_TYPE("ctlr held in reset"),
239 [_IDX(FW_DOWNLOADING)] =
240 MSG_RDAC_DOWN_TYPE("ctlr firmware downloading"),
241 [_IDX(QUIESCED)] = MSG_RDAC_DOWN_TYPE("ctlr quiesced by admin request"),
242 [_IDX(SERVICE_MODE)] = MSG_RDAC_DOWN_TYPE("ctlr is in service mode"),
243 [_IDX(UNAVAILABLE)] = MSG_RDAC_DOWN_TYPE("ctlr is unavailable"),
244 [_IDX(INQUIRY_FAILED)] = MSG_RDAC_DOWN_TYPE("inquiry failed"),
249 checker_msg_string(const struct volume_access_inq *inq)
251 /* lun not connected */
252 if (((inq->PQ_PDT & 0xE0) == 0x20) || (inq->PQ_PDT & 0x7f))
253 return RDAC_MSGID_NOT_CONN;
255 /* if no tpg data is available, give the generic path down message */
256 if (!(inq->avtcvp & 0x10))
257 return CHECKER_MSGID_DOWN;
259 /* controller is booting up */
260 if (((inq->aas_cur & 0x0F) == RTPG_TRANSITIONING) &&
261 (inq->aas_alt & 0x0F) != RTPG_TRANSITIONING)
262 return RDAC_MSGID_IN_STARTUP;
264 /* if not unavailable, give generic message */
265 if ((inq->aas_cur & 0x0F) != RTPG_UNAVAILABLE)
266 return CHECKER_MSGID_DOWN;
268 /* target port group unavailable */
269 switch (inq->vendor_specific_cur) {
270 case RTPG_UNAVAIL_NON_RESPONSIVE:
271 return RDAC_MSGID_NON_RESPONSIVE;
272 case RTPG_UNAVAIL_IN_RESET:
273 return RDAC_MSGID_IN_RESET;
274 case RTPG_UNAVAIL_CFW_DL1:
275 case RTPG_UNAVAIL_CFW_DL2:
276 return RDAC_MSGID_FW_DOWNLOADING;
277 case RTPG_UNAVAIL_QUIESCED:
278 return RDAC_MSGID_QUIESCED;
279 case RTPG_UNAVAIL_SERVICE_MODE:
280 return RDAC_MSGID_SERVICE_MODE;
282 return RDAC_MSGID_UNAVAILABLE;
286 int libcheck_check(struct checker * c)
288 struct volume_access_inq inq;
292 memset(&inq, 0, sizeof(struct volume_access_inq));
293 if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq),
298 } else if (((inq.PQ_PDT & 0xE0) == 0x20) || (inq.PQ_PDT & 0x7f)) {
299 /* LUN not connected*/
304 /* If TPGDE bit set, evaluate TPG information */
305 if ((inq.avtcvp & 0x10)) {
306 switch (inq.aas_cur & 0x0F) {
307 /* Never use the path if it reports unavailable */
308 case RTPG_UNAVAILABLE:
312 * If both controllers report transitioning, it
313 * means mode select or STPG is being processed.
315 * If this controller alone is transitioning, it's
316 * booting and we shouldn't use it yet.
318 case RTPG_TRANSITIONING:
319 if ((inq.aas_alt & 0xF) != RTPG_TRANSITIONING) {
327 /* If owner set or ioship mode is enabled return PATH_UP always */
328 if ((inq.avtcvp & 0x1) || ((inq.avtcvp >> 5) & 0x1))
336 c->msgid = (inqfail ? RDAC_MSGID_INQUIRY_FAILED :
337 checker_msg_string(&inq));
340 c->msgid = CHECKER_MSGID_UP;
343 c->msgid = CHECKER_MSGID_GHOST;