--- /dev/null
+#ifndef CCISS_H
+#define CCISS_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define CCISS_IOC_MAGIC 'B'
+
+/*
+ * transfer direction
+ */
+#define XFER_NONE 0x00
+#define XFER_WRITE 0x01
+#define XFER_READ 0x02
+#define XFER_RSVD 0x03
+
+/*
+ * task attribute
+ */
+#define ATTR_UNTAGGED 0x00
+#define ATTR_SIMPLE 0x04
+#define ATTR_HEADOFQUEUE 0x05
+#define ATTR_ORDERED 0x06
+#define ATTR_ACA 0x07
+
+/*
+ * cdb type
+ */
+#define TYPE_CMD 0x00
+#define TYPE_MSG 0x01
+
+#define SENSEINFOBYTES 32
+
+/*
+ * Type defs used in the following structs
+ */
+#define BYTE __u8
+#define WORD __u16
+#define HWORD __u16
+#define DWORD __u32
+
+#pragma pack(1)
+
+//Command List Structure
+typedef union _SCSI3Addr_struct {
+ struct {
+ BYTE Dev;
+ BYTE Bus:6;
+ BYTE Mode:2; // b00
+ } PeripDev;
+ struct {
+ BYTE DevLSB;
+ BYTE DevMSB:6;
+ BYTE Mode:2; // b01
+ } LogDev;
+ struct {
+ BYTE Dev:5;
+ BYTE Bus:3;
+ BYTE Targ:6;
+ BYTE Mode:2; // b10
+ } LogUnit;
+} SCSI3Addr_struct;
+
+typedef struct _PhysDevAddr_struct {
+ DWORD TargetId:24;
+ DWORD Bus:6;
+ DWORD Mode:2;
+ SCSI3Addr_struct Target[2]; //2 level target device addr
+} PhysDevAddr_struct;
+
+typedef struct _LogDevAddr_struct {
+ DWORD VolId:30;
+ DWORD Mode:2;
+ BYTE reserved[4];
+} LogDevAddr_struct;
+
+typedef union _LUNAddr_struct {
+ BYTE LunAddrBytes[8];
+ SCSI3Addr_struct SCSI3Lun[4];
+ PhysDevAddr_struct PhysDev;
+ LogDevAddr_struct LogDev;
+} LUNAddr_struct;
+
+typedef struct _RequestBlock_struct {
+ BYTE CDBLen;
+ struct {
+ BYTE Type:3;
+ BYTE Attribute:3;
+ BYTE Direction:2;
+ } Type;
+ HWORD Timeout;
+ BYTE CDB[16];
+} RequestBlock_struct;
+
+typedef union _MoreErrInfo_struct{
+ struct {
+ BYTE Reserved[3];
+ BYTE Type;
+ DWORD ErrorInfo;
+ }Common_Info;
+ struct{
+ BYTE Reserved[2];
+ BYTE offense_size;//size of offending entry
+ BYTE offense_num; //byte # of offense 0-base
+ DWORD offense_value;
+ }Invalid_Cmd;
+}MoreErrInfo_struct;
+
+typedef struct _ErrorInfo_struct {
+ BYTE ScsiStatus;
+ BYTE SenseLen;
+ HWORD CommandStatus;
+ DWORD ResidualCnt;
+ MoreErrInfo_struct MoreErrInfo;
+ BYTE SenseInfo[SENSEINFOBYTES];
+} ErrorInfo_struct;
+
+#pragma pack()
+
+typedef struct _IOCTL_Command_struct {
+ LUNAddr_struct LUN_info;
+ RequestBlock_struct Request;
+ ErrorInfo_struct error_info;
+ WORD buf_size; /* size in bytes of the buf */
+ BYTE *buf;
+} IOCTL_Command_struct;
+
+typedef struct _LogvolInfo_struct{
+ __u32 LunID;
+ int num_opens; /* number of opens on the logical volume */
+ int num_parts; /* number of partitions configured on logvol */
+} LogvolInfo_struct;
+
+#define CCISS_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 11, IOCTL_Command_struct)
+#define CCISS_GETLUNINFO _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_struct)
+
+int cciss_init( struct checker *);
+void cciss_free (struct checker * c);
+int cciss_tur( struct checker *);
+
+#endif
+
--- /dev/null
+/*
+ *****************************************************************************
+ * *
+ * (C) Copyright 2007 Hewlett-Packard Development Company, L.P *
+ * *
+ * This program is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU General Public License as published by the Free*
+ * Software Foundation; either version 2 of the License, or (at your option)*
+ * any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY*
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
+ * for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License along *
+ * with this program; if not, write to the Free Software Foundation, Inc., *
+ * 675 Mass Ave, Cambridge, MA 02139, USA. *
+ * *
+ * The copy of the GNU General Public License is available at *
+ * /opt/hp/HPDMmultipath-tool directoy *
+ * *
+ *****************************************************************************
+*/
+
+/*
+ * This program originally derived from and inspired by
+ * Christophe Varoqui's tur.c, part of libchecker.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "checkers.h"
+
+#include "cciss.h"
+
+#define TUR_CMD_LEN 6
+#define HEAVY_CHECK_COUNT 10
+
+#define MSG_CCISS_TUR_UP "cciss_tur checker reports path is up"
+#define MSG_CCISS_TUR_DOWN "cciss_tur checker reports path is down"
+
+struct cciss_tur_checker_context {
+ void * dummy;
+};
+
+int libcheck_init (struct checker * c)
+{
+ return 0;
+}
+
+void libcheck_free (struct checker * c)
+{
+ return;
+}
+
+extern int
+libcheck_check (struct checker * c)
+{
+ int rc;
+ int ret;
+ unsigned int lun = 0;
+ struct cciss_tur_checker_context * ctxt = NULL;
+ LogvolInfo_struct lvi; // logical "volume" info
+ IOCTL_Command_struct cic; // cciss ioctl command
+
+ if ((c->fd) <= 0) {
+ MSG(c,"no usable fd");
+ ret = -1;
+ goto out;
+ }
+
+ rc = ioctl(c->fd, CCISS_GETLUNINFO, &lvi);
+ if ( rc != 0) {
+ perror("Error: ");
+ fprintf(stderr, "cciss TUR failed in CCISS_GETLUNINFO: %s\n",
+ strerror(errno));
+ MSG(c,MSG_CCISS_TUR_DOWN);
+ ret = PATH_DOWN;
+ goto out;
+ } else {
+ lun = lvi.LunID;
+ }
+
+ memset(&cic, 0, sizeof(cic));
+ cic.LUN_info.LogDev.VolId = lun & 0x3FFFFFFF;
+ cic.LUN_info.LogDev.Mode = 0x01; /* logical volume addressing */
+ cic.Request.CDBLen = 6; /* need to try just 2 bytes here */
+ cic.Request.Type.Type = TYPE_CMD; // It is a command.
+ cic.Request.Type.Attribute = ATTR_SIMPLE;
+ cic.Request.Type.Direction = XFER_NONE;
+ cic.Request.Timeout = 0;
+
+ cic.Request.CDB[0] = 0;
+ cic.Request.CDB[1] = 0;
+ cic.Request.CDB[2] = 0;
+ cic.Request.CDB[3] = 0;
+ cic.Request.CDB[4] = 0;
+ cic.Request.CDB[5] = 0;
+
+ rc = ioctl(c->fd, CCISS_PASSTHRU, &cic);
+ if (rc < 0) {
+ fprintf(stderr, "cciss TUR failed: %s\n",
+ strerror(errno));
+ MSG(c,MSG_CCISS_TUR_DOWN);
+ ret = PATH_DOWN;
+ goto out;
+ }
+
+ if ((cic.error_info.CommandStatus | cic.error_info.ScsiStatus )) {
+ MSG(c,MSG_CCISS_TUR_DOWN);
+ ret = PATH_DOWN;
+ goto out;
+ }
+
+ MSG(c,MSG_CCISS_TUR_UP);
+
+ ret = PATH_UP;
+out:
+ /*
+ * caller told us he doesn't want to keep the context :
+ * free it
+ */
+ if (!c->context)
+ free(ctxt);
+
+ return(ret);
+}