summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/chio/chio.c70
-rw-r--r--sys/cam/scsi/scsi_ch.c203
-rw-r--r--sys/cam/scsi/scsi_ch.h97
-rw-r--r--sys/sys/chio.h83
4 files changed, 379 insertions, 74 deletions
diff --git a/bin/chio/chio.c b/bin/chio/chio.c
index 9bb11d7..5a2a7ba 100644
--- a/bin/chio/chio.c
+++ b/bin/chio/chio.c
@@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <langinfo.h>
+#include <locale.h>
#include "defs.h"
#include "pathnames.h"
@@ -81,6 +83,7 @@ static int do_status(const char *, int, char **);
static int do_ielem(const char *, int, char **);
static int do_return(const char *, int, char **);
static int do_voltag(const char *, int, char **);
+static void print_designator(const char *, u_int8_t, u_int8_t);
#ifndef CHET_VT
#define CHET_VT 10 /* Completely Arbitrary */
@@ -723,6 +726,10 @@ do_status(const char *cname, int argc, char **argv)
putchar('?');
putchar('>');
}
+ if (ces->ces_designator_length > 0)
+ print_designator(ces->ces_designator,
+ ces->ces_code_set,
+ ces->ces_designator_length);
putchar('\n');
}
@@ -1177,3 +1184,66 @@ usage(void)
"arg1 arg2 [arg3 [...]]\n", getprogname());
exit(1);
}
+
+#define UTF8CODESET "UTF-8"
+
+static void
+print_designator(const char *designator, u_int8_t code_set,
+ u_int8_t designator_length)
+{
+ printf(" serial number: <");
+ switch (code_set) {
+ case CES_CODE_SET_ASCII: {
+ /*
+ * The driver insures that the string is always NUL terminated.
+ */
+ printf("%s", designator);
+ break;
+ }
+ case CES_CODE_SET_UTF_8: {
+ char *cs_native;
+
+ setlocale(LC_ALL, "");
+ cs_native = nl_langinfo(CODESET);
+
+ /* See if we can natively print UTF-8 */
+ if (strcmp(cs_native, UTF8CODESET) == 0)
+ cs_native = NULL;
+
+ if (cs_native == NULL) {
+ /* We can natively print UTF-8, so use printf. */
+ printf("%s", designator);
+ } else {
+ int i;
+
+ /*
+ * We can't natively print UTF-8. We should
+ * convert it to the terminal's codeset, but that
+ * requires iconv(3) and FreeBSD doesn't have
+ * iconv(3) in the base system yet. So we use %XX
+ * notation for non US-ASCII characters instead.
+ */
+ for (i = 0; i < designator_length &&
+ designator[i] != '\0'; i++) {
+ if ((unsigned char)designator[i] < 0x80)
+ printf("%c", designator[i]);
+ else
+ printf("%%%02x",
+ (unsigned char)designator[i]);
+ }
+ }
+ break;
+ }
+ case CES_CODE_SET_BINARY: {
+ int i;
+
+ for (i = 0; i < designator_length; i++)
+ printf("%02X%s", designator[i],
+ (i == designator_length - 1) ? "" : " ");
+ break;
+ }
+ default:
+ break;
+ }
+ printf(">");
+}
diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c
index 38dcd48..03dd5cd 100644
--- a/sys/cam/scsi/scsi_ch.c
+++ b/sys/cam/scsi/scsi_ch.c
@@ -194,12 +194,14 @@ static int chexchange(struct cam_periph *periph,
static int chposition(struct cam_periph *periph,
struct changer_position *cp);
static int chgetelemstatus(struct cam_periph *periph,
+ int scsi_version, u_long cmd,
struct changer_element_status_request *csr);
static int chsetvoltag(struct cam_periph *periph,
struct changer_set_voltag_request *csvr);
static int chielem(struct cam_periph *periph,
unsigned int timeout);
static int chgetparams(struct cam_periph *periph);
+static int chscsiversion(struct cam_periph *periph);
static struct periph_driver chdriver =
{
@@ -474,6 +476,7 @@ chopen(struct cdev *dev, int flags, int fmt, struct thread *td)
* Load information about this changer device into the softc.
*/
if ((error = chgetparams(periph)) != 0) {
+ cam_periph_unhold(periph);
cam_periph_release_locked(periph);
cam_periph_unlock(periph);
return(error);
@@ -772,6 +775,7 @@ chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
switch (cmd) {
case CHIOGPICKER:
case CHIOGPARAMS:
+ case OCHIOGSTATUS:
case CHIOGSTATUS:
break;
@@ -824,10 +828,26 @@ chioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
error = chielem(periph, *(unsigned int *)addr);
break;
+ case OCHIOGSTATUS:
+ {
+ error = chgetelemstatus(periph, SCSI_REV_2, cmd,
+ (struct changer_element_status_request *)addr);
+ break;
+ }
+
case CHIOGSTATUS:
{
- error = chgetelemstatus(periph,
- (struct changer_element_status_request *) addr);
+ int scsi_version;
+
+ scsi_version = chscsiversion(periph);
+ if (scsi_version >= SCSI_REV_0) {
+ error = chgetelemstatus(periph, scsi_version, cmd,
+ (struct changer_element_status_request *)addr);
+ }
+ else { /* unable to determine the SCSI version */
+ cam_periph_unlock(periph);
+ return (ENXIO);
+ }
break;
}
@@ -1034,18 +1054,20 @@ copy_voltag(struct changer_voltag *uvoltag, struct volume_tag *voltag)
}
/*
- * Copy an an element status descriptor to a user-mode
+ * Copy an element status descriptor to a user-mode
* changer_element_status structure.
*/
-
-static void
+static void
copy_element_status(struct ch_softc *softc,
u_int16_t flags,
struct read_element_status_descriptor *desc,
- struct changer_element_status *ces)
+ struct changer_element_status *ces,
+ int scsi_version)
{
u_int16_t eaddr = scsi_2btoul(desc->eaddr);
u_int16_t et;
+ struct volume_tag *pvol_tag = NULL, *avol_tag = NULL;
+ struct read_element_status_device_id *devid = NULL;
ces->ces_int_addr = eaddr;
/* set up logical address in element status */
@@ -1076,7 +1098,7 @@ copy_element_status(struct ch_softc *softc,
if ((softc->sc_firsts[et] <= eaddr)
&& ((softc->sc_firsts[et] + softc->sc_counts[et])
> eaddr)) {
- ces->ces_source_addr =
+ ces->ces_source_addr =
eaddr - softc->sc_firsts[et];
ces->ces_source_type = et;
ces->ces_flags |= CES_SOURCE_VALID;
@@ -1089,27 +1111,92 @@ copy_element_status(struct ch_softc *softc,
"address %ud to a valid element type\n",
eaddr);
}
-
+ /*
+ * pvoltag and avoltag are common between SCSI-2 and later versions
+ */
if (flags & READ_ELEMENT_STATUS_PVOLTAG)
- copy_voltag(&(ces->ces_pvoltag), &(desc->pvoltag));
+ pvol_tag = &desc->voltag_devid.pvoltag;
if (flags & READ_ELEMENT_STATUS_AVOLTAG)
- copy_voltag(&(ces->ces_avoltag), &(desc->avoltag));
+ avol_tag = (flags & READ_ELEMENT_STATUS_PVOLTAG) ?
+ &desc->voltag_devid.voltag[1] :&desc->voltag_devid.pvoltag;
+ /*
+ * For SCSI-3 and later, element status can carry designator and
+ * other information.
+ */
+ if (scsi_version >= SCSI_REV_SPC) {
+ if ((flags & READ_ELEMENT_STATUS_PVOLTAG) ^
+ (flags & READ_ELEMENT_STATUS_AVOLTAG))
+ devid = &desc->voltag_devid.pvol_and_devid.devid;
+ else if (!(flags & READ_ELEMENT_STATUS_PVOLTAG) &&
+ !(flags & READ_ELEMENT_STATUS_AVOLTAG))
+ devid = &desc->voltag_devid.devid;
+ else /* Have both PVOLTAG and AVOLTAG */
+ devid = &desc->voltag_devid.vol_tags_and_devid.devid;
+ }
- if (desc->dt_scsi_flags & READ_ELEMENT_STATUS_DT_IDVALID) {
- ces->ces_flags |= CES_SCSIID_VALID;
- ces->ces_scsi_id = desc->dt_scsi_addr;
+ if (pvol_tag)
+ copy_voltag(&(ces->ces_pvoltag), pvol_tag);
+ if (avol_tag)
+ copy_voltag(&(ces->ces_pvoltag), avol_tag);
+ if (devid != NULL) {
+ if (devid->designator_length > 0) {
+ bcopy((void *)devid->designator,
+ (void *)ces->ces_designator,
+ devid->designator_length);
+ ces->ces_designator_length = devid->designator_length;
+ /*
+ * Make sure we are always NUL terminated. The
+ * buffer should be sized for the maximum
+ * designator length plus 1, but this will make sure
+ * there is always a NUL at the end. This won't
+ * matter for the binary code set, since the user
+ * will only pay attention to the length field.
+ */
+ ces->ces_designator[
+ MIN(sizeof(ces->ces_designator) - 1,
+ devid->designator_length)]= '\0';
+ }
+ if (devid->piv_assoc_designator_type &
+ READ_ELEMENT_STATUS_PIV_SET) {
+ ces->ces_flags |= CES_PIV;
+ ces->ces_protocol_id =
+ READ_ELEMENT_STATUS_PROTOCOL_ID(
+ devid->prot_code_set);
+ }
+ ces->ces_code_set =
+ READ_ELEMENT_STATUS_CODE_SET(devid->prot_code_set);
+ ces->ces_assoc = READ_ELEMENT_STATUS_ASSOCIATION(
+ devid->piv_assoc_designator_type);
+ ces->ces_designator_type = READ_ELEMENT_STATUS_DESIGNATOR_TYPE(
+ devid->piv_assoc_designator_type);
+ } else if (scsi_version > SCSI_REV_2) {
+ /* SCSI-SPC and No devid, no designator */
+ ces->ces_designator_length = 0;
+ ces->ces_designator[0] = '\0';
+ ces->ces_protocol_id = CES_PROTOCOL_ID_FCP_4;
}
- if (desc->dt_scsi_addr & READ_ELEMENT_STATUS_DT_LUVALID) {
- ces->ces_flags |= CES_LUN_VALID;
- ces->ces_scsi_lun =
- desc->dt_scsi_flags & READ_ELEMENT_STATUS_DT_LUNMASK;
+ if (scsi_version <= SCSI_REV_2) {
+ if (desc->dt_or_obsolete.scsi_2.dt_scsi_flags &
+ READ_ELEMENT_STATUS_DT_IDVALID) {
+ ces->ces_flags |= CES_SCSIID_VALID;
+ ces->ces_scsi_id =
+ desc->dt_or_obsolete.scsi_2.dt_scsi_addr;
+ }
+
+ if (desc->dt_or_obsolete.scsi_2.dt_scsi_addr &
+ READ_ELEMENT_STATUS_DT_LUVALID) {
+ ces->ces_flags |= CES_LUN_VALID;
+ ces->ces_scsi_lun =
+ desc->dt_or_obsolete.scsi_2.dt_scsi_flags &
+ READ_ELEMENT_STATUS_DT_LUNMASK;
+ }
}
}
static int
-chgetelemstatus(struct cam_periph *periph,
+chgetelemstatus(struct cam_periph *periph, int scsi_version, u_long cmd,
struct changer_element_status_request *cesr)
{
struct read_element_status_header *st_hdr;
@@ -1155,6 +1242,8 @@ chgetelemstatus(struct cam_periph *periph,
/* tag_action */ MSG_SIMPLE_Q_TAG,
/* voltag */ want_voltags,
/* sea */ softc->sc_firsts[chet],
+ /* dvcid */ 1,
+ /* curdata */ 1,
/* count */ 1,
/* data_ptr */ data,
/* dxfer_len */ 1024,
@@ -1177,7 +1266,6 @@ chgetelemstatus(struct cam_periph *periph,
size = sizeof(struct read_element_status_header) +
sizeof(struct read_element_status_page_header) +
(desclen * cesr->cesr_element_count);
-
/*
* Reallocate storage for descriptors and get them from the
* device.
@@ -1193,12 +1281,14 @@ chgetelemstatus(struct cam_periph *periph,
/* voltag */ want_voltags,
/* sea */ softc->sc_firsts[chet]
+ cesr->cesr_element_base,
+ /* dvcid */ 1,
+ /* curdata */ 1,
/* count */ cesr->cesr_element_count,
/* data_ptr */ data,
/* dxfer_len */ size,
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS);
-
+
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
softc->device_stats);
@@ -1231,18 +1321,41 @@ chgetelemstatus(struct cam_periph *periph,
* Set up the individual element status structures
*/
for (i = 0; i < avail; ++i) {
- struct changer_element_status *ces = &(user_data[i]);
+ struct changer_element_status *ces;
- copy_element_status(softc, pg_hdr->flags, desc, ces);
+ /*
+ * In the changer_element_status structure, fields from
+ * the beginning to the field of ces_scsi_lun are common
+ * between SCSI-2 and SCSI-3, while all the rest are new
+ * from SCSI-3. In order to maintain backward compatibility
+ * of the chio command, the ces pointer, below, is computed
+ * such that it lines up with the structure boundary
+ * corresponding to the SCSI version.
+ */
+ ces = cmd == OCHIOGSTATUS ?
+ (struct changer_element_status *)
+ ((unsigned char *)user_data + i *
+ (offsetof(struct changer_element_status,ces_scsi_lun)+1)):
+ &user_data[i];
+
+ copy_element_status(softc, pg_hdr->flags, desc,
+ ces, scsi_version);
desc = (struct read_element_status_descriptor *)
- ((uintptr_t)desc + desclen);
+ ((unsigned char *)desc + desclen);
}
/* Copy element status structures out to userspace. */
- error = copyout(user_data,
- cesr->cesr_element_status,
- avail * sizeof(struct changer_element_status));
+ if (cmd == OCHIOGSTATUS)
+ error = copyout(user_data,
+ cesr->cesr_element_status,
+ avail* (offsetof(struct changer_element_status,
+ ces_scsi_lun) + 1));
+ else
+ error = copyout(user_data,
+ cesr->cesr_element_status,
+ avail * sizeof(struct changer_element_status));
+
cam_periph_lock(periph);
done:
@@ -1549,6 +1662,39 @@ chgetparams(struct cam_periph *periph)
return(error);
}
+static int
+chscsiversion(struct cam_periph *periph)
+{
+ struct scsi_inquiry_data *inq_data;
+ struct ccb_getdev *cgd;
+ int dev_scsi_version;
+ struct cam_sim *sim;
+
+ sim = xpt_path_sim(periph->path);
+ mtx_assert(sim->mtx, MA_OWNED);
+ if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) == NULL)
+ return (-1);
+ /*
+ * Get the device information.
+ */
+ xpt_setup_ccb(&cgd->ccb_h,
+ periph->path,
+ CAM_PRIORITY_NORMAL);
+ cgd->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)cgd);
+
+ if (cgd->ccb_h.status != CAM_REQ_CMP) {
+ xpt_free_ccb((union ccb *)cgd);
+ return -1;
+ }
+
+ inq_data = &cgd->inq_data;
+ dev_scsi_version = inq_data->version;
+ xpt_free_ccb((union ccb *)cgd);
+
+ return dev_scsi_version;
+}
+
void
scsi_move_medium(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
@@ -1654,6 +1800,7 @@ void
scsi_read_element_status(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, int voltag, u_int32_t sea,
+ int curdata, int dvcid,
u_int32_t count, u_int8_t *data_ptr,
u_int32_t dxfer_len, u_int8_t sense_len,
u_int32_t timeout)
@@ -1668,6 +1815,10 @@ scsi_read_element_status(struct ccb_scsiio *csio, u_int32_t retries,
scsi_ulto2b(sea, scsi_cmd->sea);
scsi_ulto2b(count, scsi_cmd->count);
scsi_ulto3b(dxfer_len, scsi_cmd->len);
+ if (dvcid)
+ scsi_cmd->flags |= READ_ELEMENT_STATUS_DVCID;
+ if (curdata)
+ scsi_cmd->flags |= READ_ELEMENT_STATUS_CURDATA;
if (voltag)
scsi_cmd->byte2 |= READ_ELEMENT_STATUS_VOLTAG;
diff --git a/sys/cam/scsi/scsi_ch.h b/sys/cam/scsi/scsi_ch.h
index 5ee2244..fd317d2 100644
--- a/sys/cam/scsi/scsi_ch.h
+++ b/sys/cam/scsi/scsi_ch.h
@@ -136,11 +136,14 @@ struct scsi_position_to_element {
struct scsi_read_element_status {
u_int8_t opcode;
u_int8_t byte2;
-#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */
+#define READ_ELEMENT_STATUS_VOLTAG 0x10 /* report volume tag info */
/* ...next 4 bits are an element type code... */
u_int8_t sea[2]; /* starting element address */
u_int8_t count[2]; /* number of elements */
- u_int8_t reserved0;
+ u_int8_t flags;
+#define READ_ELEMENT_STATUS_DVCID 0x01 /* report device serial number */
+#define READ_ELEMENT_STATUS_CURDATA 0x02 /* allow motion during command */
+
u_int8_t len[3]; /* length of data buffer */
u_int8_t reserved1;
u_int8_t control;
@@ -149,7 +152,7 @@ struct scsi_read_element_status {
struct scsi_request_volume_element_address {
u_int8_t opcode;
u_int8_t byte2;
-#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10
+#define REQUEST_VOLUME_ELEMENT_ADDRESS_VOLTAG 0x10
/* ...next 4 bits are an element type code... */
u_int8_t eaddr[2]; /* element address */
u_int8_t count[2]; /* number of elements */
@@ -182,8 +185,8 @@ struct read_element_status_header {
struct read_element_status_page_header {
u_int8_t type; /* element type code; see type codes below */
u_int8_t flags;
-#define READ_ELEMENT_STATUS_AVOLTAG 0x40
-#define READ_ELEMENT_STATUS_PVOLTAG 0x80
+#define READ_ELEMENT_STATUS_AVOLTAG 0x40
+#define READ_ELEMENT_STATUS_PVOLTAG 0x80
u_int8_t edl[2]; /* element descriptor length */
u_int8_t reserved;
u_int8_t nbytes[3]; /* byte count of all descriptors */
@@ -199,50 +202,79 @@ struct volume_tag {
u_int8_t vsn[2]; /* volume sequence number */
};
+struct read_element_status_device_id {
+ u_int8_t prot_code_set;
+#define READ_ELEMENT_STATUS_CODE_SET(p) ((p) & 0x0F)
+#define READ_ELEMENT_STATUS_PROTOCOL_ID(p) ((p) >> 4)
+
+ u_int8_t piv_assoc_designator_type;
+#define READ_ELEMENT_STATUS_PIV_SET 0x80
+#define READ_ELEMENT_STATUS_ASSOCIATION(p) ((p) >> 4)
+#define READ_ELEMENT_STATUS_DESIGNATOR_TYPE(p) ((p) & 0x0F)
+
+ u_int8_t reserved2;
+ u_int8_t designator_length;
+ u_int8_t designator[256]; /* Allocate max length */
+};
+
struct read_element_status_descriptor {
u_int8_t eaddr[2]; /* element address */
u_int8_t flags1;
-#define READ_ELEMENT_STATUS_FULL 0x01
-#define READ_ELEMENT_STATUS_IMPEXP 0x02
-#define READ_ELEMENT_STATUS_EXCEPT 0x04
-#define READ_ELEMENT_STATUS_ACCESS 0x08
-#define READ_ELEMENT_STATUS_EXENAB 0x10
-#define READ_ELEMENT_STATUS_INENAB 0x20
+#define READ_ELEMENT_STATUS_FULL 0x01
+#define READ_ELEMENT_STATUS_IMPEXP 0x02
+#define READ_ELEMENT_STATUS_EXCEPT 0x04
+#define READ_ELEMENT_STATUS_ACCESS 0x08
+#define READ_ELEMENT_STATUS_EXENAB 0x10
+#define READ_ELEMENT_STATUS_INENAB 0x20
-#define READ_ELEMENT_STATUS_MT_MASK1 0x05
-#define READ_ELEMENT_STATUS_ST_MASK1 0x0c
-#define READ_ELEMENT_STATUS_IE_MASK1 0x3f
-#define READ_ELEMENT_STATUS_DT_MASK1 0x0c
+#define READ_ELEMENT_STATUS_MT_MASK1 0x05
+#define READ_ELEMENT_STATUS_ST_MASK1 0x0c
+#define READ_ELEMENT_STATUS_IE_MASK1 0x3f
+#define READ_ELEMENT_STATUS_DT_MASK1 0x0c
u_int8_t reserved0;
u_int8_t sense_code;
u_int8_t sense_qual;
- /*
- * dt_scsi_flags and dt_scsi_addr are valid only on data transport
- * elements. These bytes are undefined for all other element types.
- */
- u_int8_t dt_scsi_flags;
+ union {
+ struct {
+ u_int8_t dt_scsi_flags;
-#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07
-#define READ_ELEMENT_STATUS_DT_LUVALID 0x10
-#define READ_ELEMENT_STATUS_DT_IDVALID 0x20
-#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80
+#define READ_ELEMENT_STATUS_DT_LUNMASK 0x07
+#define READ_ELEMENT_STATUS_DT_LUVALID 0x10
+#define READ_ELEMENT_STATUS_DT_IDVALID 0x20
+#define READ_ELEMENT_STATUS_DT_NOTBUS 0x80
- u_int8_t dt_scsi_addr;
+ u_int8_t dt_scsi_addr;
+ u_int8_t reserved1;
+ } scsi_2;
- u_int8_t reserved1;
+ /* reserved and obsolete (as of SCSI-3) fields */
+ u_int8_t reserved_or_obsolete[3];
+ } dt_or_obsolete;
u_int8_t flags2;
-#define READ_ELEMENT_STATUS_INVERT 0x40
-#define READ_ELEMENT_STATUS_SVALID 0x80
- u_int8_t ssea[2]; /* source storage element address */
+#define READ_ELEMENT_STATUS_INVERT 0x40
+#define READ_ELEMENT_STATUS_SVALID 0x80
+#define READ_ELEMENT_STATUS_ED 0x80
+#define READ_ELEMENT_STATUS_MEDIA_TYPE_MASK 0x07
- struct volume_tag pvoltag; /* omitted if PVOLTAG == 0 */
- struct volume_tag avoltag; /* omitted if AVOLTAG == 0 */
+ u_int8_t ssea[2]; /* source storage element address */
- /* Other data may follow */
+ union {
+ struct volume_tag pvoltag;
+ struct volume_tag voltag[2];
+ struct read_element_status_device_id devid;
+ struct {
+ struct volume_tag pvoltag;
+ struct read_element_status_device_id devid;
+ } pvol_and_devid;
+ struct {
+ struct volume_tag voltag[2];
+ struct read_element_status_device_id devid;
+ } vol_tags_and_devid;
+ } voltag_devid;
};
/* XXX add data returned by REQUEST VOLUME ELEMENT ADDRESS */
@@ -457,6 +489,7 @@ void scsi_position_to_element(struct ccb_scsiio *csio, u_int32_t retries,
void scsi_read_element_status(struct ccb_scsiio *csio, u_int32_t retries,
void (*cbfcnp)(struct cam_periph *, union ccb *),
u_int8_t tag_action, int voltag, u_int32_t sea,
+ int curdata, int dvcid,
u_int32_t count, u_int8_t *data_ptr,
u_int32_t dxfer_len, u_int8_t sense_len,
u_int32_t timeout);
diff --git a/sys/sys/chio.h b/sys/sys/chio.h
index aa55f7c..edf1ab7 100644
--- a/sys/sys/chio.h
+++ b/sys/sys/chio.h
@@ -152,7 +152,8 @@ typedef enum {
CES_INVERT = 0x040, /* invert bit */
CES_SOURCE_VALID = 0x080, /* source address (ces_source) valid */
CES_SCSIID_VALID = 0x100, /* ces_scsi_id is valid */
- CES_LUN_VALID = 0x200 /* ces_scsi_lun is valid */
+ CES_LUN_VALID = 0x200, /* ces_scsi_lun is valid */
+ CES_PIV = 0x400 /* ces_protocol_id is valid */
} ces_status_flags;
struct changer_element_status {
@@ -181,6 +182,55 @@ struct changer_element_status {
changer_voltag_t ces_avoltag; /* alternate volume tag */
u_int8_t ces_scsi_id; /* SCSI id of element */
u_int8_t ces_scsi_lun; /* SCSI lun of element */
+
+ /*
+ * Data members for SMC3 and later versions
+ */
+ u_int8_t ces_medium_type;
+#define CES_MEDIUM_TYPE_UNKNOWN 0 /* Medium type unspecified */
+#define CES_MEDIUM_TYPE_DATA 1 /* Data medium */
+#define CES_MEDIUM_TYPE_CLEANING 2 /* Cleaning medium */
+#define CES_MEDIUM_TYPE_DIAGNOSTIC 3 /* Diagnostic medium */
+#define CES_MEDIUM_TYPE_WORM 4 /* WORM medium */
+#define CES_MEDIUM_TYPE_MICROCODE 5 /* Microcode image medium */
+
+ u_int8_t ces_protocol_id;
+#define CES_PROTOCOL_ID_FCP_4 0 /* Fiber channel */
+#define CES_PROTOCOL_ID_SPI_5 1 /* Parallel SCSI */
+#define CES_PROTOCOL_ID_SSA_S3P 2 /* SSA */
+#define CES_PROTOCOL_ID_SBP_3 3 /* IEEE 1394 */
+#define CES_PROTOCOL_ID_SRP 4 /* SCSI Remote DMA */
+#define CES_PROTOCOL_ID_ISCSI 5 /* iSCSI */
+#define CES_PROTOCOL_ID_SPL 6 /* SAS */
+#define CES_PROTOCOL_ID_ADT_2 7 /* Automation/Drive Interface */
+#define CES_PROTOCOL_ID_ACS_2 8 /* ATA */
+
+ u_int8_t ces_assoc;
+#define CES_ASSOC_LOGICAL_UNIT 0
+#define CES_ASSOC_TARGET_PORT 1
+#define CES_ASSOC_TARGET_DEVICE 2
+
+ u_int8_t ces_designator_type;
+#define CES_DESIGNATOR_TYPE_VENDOR_SPECIFIC 0
+#define CES_DESIGNATOR_TYPE_T10_VENDOR_ID 1
+#define CES_DESIGNATOR_TYPE_EUI_64 2
+#define CES_DESIGNATOR_TYPE_NAA 3
+#define CES_DESIGNATOR_TYPE_TARGET_PORT_ID 4
+#define CES_DESIGNATOR_TYPE_TARGET_PORT_GRP 5
+#define CES_DESIGNATOR_TYPE_LOGICAL_UNIT_GRP 6
+#define CES_DESIGNATOR_TYPE_MD5_LOGICAL_UNIT_ID 7
+#define CES_DESIGNATOR_TYPE_SCSI_NAME_STRING 8
+
+ u_int8_t ces_code_set;
+#define CES_CODE_SET_RESERVED 0
+#define CES_CODE_SET_BINARY 1
+#define CES_CODE_SET_ASCII 2
+#define CES_CODE_SET_UTF_8 3
+
+ u_int8_t ces_designator_length;
+
+#define CES_MAX_DESIGNATOR_LENGTH (1 << 8)
+ u_int8_t ces_designator[CES_MAX_DESIGNATOR_LENGTH + 1];
};
struct changer_element_status_request {
@@ -189,7 +239,7 @@ struct changer_element_status_request {
u_int16_t cesr_element_count;
u_int16_t cesr_flags;
-#define CESR_VOLTAGS 0x01
+#define CESR_VOLTAGS 0x01
struct changer_element_status *cesr_element_status;
};
@@ -200,28 +250,29 @@ struct changer_set_voltag_request {
u_int16_t csvr_addr;
u_int16_t csvr_flags;
-#define CSVR_MODE_MASK 0x0f /* mode mask, acceptable modes below: */
+#define CSVR_MODE_MASK 0x0f /* mode mask, acceptable modes below: */
#define CSVR_MODE_SET 0x00 /* set volume tag if not set */
-#define CSVR_MODE_REPLACE 0x01 /* unconditionally replace volume tag */
-#define CSVR_MODE_CLEAR 0x02 /* clear volume tag */
+#define CSVR_MODE_REPLACE 0x01 /* unconditionally replace volume tag */
+#define CSVR_MODE_CLEAR 0x02 /* clear volume tag */
-#define CSVR_ALTERNATE 0x10 /* set to work with alternate voltag */
+#define CSVR_ALTERNATE 0x10 /* set to work with alternate voltag */
changer_voltag_t csvr_voltag;
};
-#define CESTATUS_BITS \
+#define CESTATUS_BITS \
"\20\6INEAB\5EXENAB\4ACCESS\3EXCEPT\2IMPEXP\1FULL"
-#define CHIOMOVE _IOW('c', 0x01, struct changer_move)
-#define CHIOEXCHANGE _IOW('c', 0x02, struct changer_exchange)
-#define CHIOPOSITION _IOW('c', 0x03, struct changer_position)
-#define CHIOGPICKER _IOR('c', 0x04, int)
-#define CHIOSPICKER _IOW('c', 0x05, int)
-#define CHIOGPARAMS _IOR('c', 0x06, struct changer_params)
-#define CHIOIELEM _IOW('c', 0x07, u_int32_t)
-#define CHIOGSTATUS _IOW('c', 0x08, struct changer_element_status_request)
-#define CHIOSETVOLTAG _IOW('c', 0x09, struct changer_set_voltag_request)
+#define CHIOMOVE _IOW('c', 0x01, struct changer_move)
+#define CHIOEXCHANGE _IOW('c', 0x02, struct changer_exchange)
+#define CHIOPOSITION _IOW('c', 0x03, struct changer_position)
+#define CHIOGPICKER _IOR('c', 0x04, int)
+#define CHIOSPICKER _IOW('c', 0x05, int)
+#define CHIOGPARAMS _IOR('c', 0x06, struct changer_params)
+#define CHIOIELEM _IOW('c', 0x07, u_int32_t)
+#define OCHIOGSTATUS _IOW('c', 0x08, struct changer_element_status_request)
+#define CHIOSETVOLTAG _IOW('c', 0x09, struct changer_set_voltag_request)
+#define CHIOGSTATUS _IOW('c', 0x0A, struct changer_element_status_request)
#endif /* !_SYS_CHIO_H_ */
OpenPOWER on IntegriCloud