Hey Ken,

this change doesn't compile for me.  See below

Warner

On Apr 19, 2013, at 2:03 PM, Kenneth D. Merry wrote:

> Author: ken
> Date: Fri Apr 19 20:03:51 2013
> New Revision: 249658
> URL: http://svnweb.freebsd.org/changeset/base/249658
> 
> Log:
>  Update chio(1) and ch(4) to support reporting element designators.
> 
>  This allows mapping a tape drive in a changer (as reported by
>  'chio status') to a sa(4) driver instance by comparing the
>  serial numbers.
> 
>  The designators can be ASCII (which is printed out directly), binary
>  (which is printed in hex format) or UTF-8, which is printed in either
>  native UTF-8 format if the terminal can support it, or in %XX notation
>  for non-ASCII characters.  Thanks to Hiroki Sato <hrs@> for the
>  explaining UTF-8 printing and example UTF-8 printing code.
> 
>  chio.h:              Modify the changer_element_status structure to add new
>               fields and definitions from the SMC3r16 spec.
> 
>               Rename the original CHIOGSTATUS ioctl to OCHIOGTATUS and
>               define a new CHIOGSTATUS ioctl.
> 
>               Clean up some tab/space issues.
> 
>  chio.c:      For the 'status' subcommand, print the designator field
>               if it is supplied by a device.
> 
>  scsi_ch.h:   Add new flags for DVCID and CURDATA to the READ
>               ELEMENT STATUS command structure.
> 
>               Add a read_element_status_device_id structure
>               for the data fields in the new standard. Add new
>               unions, dt_or_obsolete and voltage_devid, to hold
>               and address data from either SCSI-2 or newer devices.
> 
>  scsi_ch.c:   Implement support for fetching device IDs with READ
>               ELEMENT STATUS data.
> 
>               Add new arguments to scsi_read_element_status() to
>               allow the user to request the DVCID and CURDATA bits.
>               This isn't compiled into libcam (it's only an internal
>               kernel interface), so we don't need any special
>               handling for the API change.
> 
>               If the user issues the new CHIOGSTATUS ioctl, copy all of
>               the available element status data out.  If he issues the
>               OCHIOGSTATUS ioctl, we don't copy the new fields in the
>               structure.
> 
>               Fix a bug in chopen() that would result in the peripheral
>               never getting unheld if chgetparams() failed.
> 
>  Sponsored by:        Spectra Logic
>  Submitted by:        Po-Li Soong
>  MFC After:   1 week
> 
> Modified:
>  head/bin/chio/chio.c
>  head/sys/cam/scsi/scsi_ch.c
>  head/sys/cam/scsi/scsi_ch.h
>  head/sys/sys/chio.h
> 
> Modified: head/bin/chio/chio.c
> ==============================================================================
> --- head/bin/chio/chio.c      Fri Apr 19 19:45:00 2013        (r249657)
> +++ head/bin/chio/chio.c      Fri Apr 19 20:03:51 2013        (r249658)
> @@ -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, 
> 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, c
>                                       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(">");
> +}
> 
> Modified: head/sys/cam/scsi/scsi_ch.c
> ==============================================================================
> --- head/sys/cam/scsi/scsi_ch.c       Fri Apr 19 19:45:00 2013        
> (r249657)
> +++ head/sys/cam/scsi/scsi_ch.c       Fri Apr 19 20:03:51 2013        
> (r249658)
> @@ -194,12 +194,14 @@ static  int             chexchange(struct cam_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 
>        * 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, ca
>       switch (cmd) {
>       case CHIOGPICKER:
>       case CHIOGPARAMS:
> +     case OCHIOGSTATUS:
>       case CHIOGSTATUS:
>               break;
> 
> @@ -824,10 +828,26 @@ chioctl(struct cdev *dev, u_long cmd, ca
>               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 *uvolt
> }
> 
> /*
> - * 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 *sof
>                       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 *sof
>                              "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));
> -
> -     if (desc->dt_scsi_flags & READ_ELEMENT_STATUS_DT_IDVALID) {
> -             ces->ces_flags |= CES_SCSIID_VALID;
> -             ces->ces_scsi_id = desc->dt_scsi_addr;
> -     }
> +             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 (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';

compiler complains here that this comparison is always false due to data 
ranges. I hacked it in my copy by always using devid->designator_length, but I 
know that's a lame fix. Can you look into it?

Also, just got tinderbox mail.

Warner

> +             }
> +             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 (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_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 (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 *perip
>                                /* 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 *perip
>       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 *perip
>                                /* 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 *perip
>        * 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_scsi
>       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;
> 
> Modified: head/sys/cam/scsi/scsi_ch.h
> ==============================================================================
> --- head/sys/cam/scsi/scsi_ch.h       Fri Apr 19 19:45:00 2013        
> (r249657)
> +++ head/sys/cam/scsi/scsi_ch.h       Fri Apr 19 20:03:51 2013        
> (r249658)
> @@ -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_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_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
> 
>       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;
> -
> -#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        reserved1;
> +     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
> +
> +                     u_int8_t        dt_scsi_addr;
> +                     u_int8_t        reserved1;
> +             } scsi_2;
> +
> +             /* 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
> 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);
> 
> Modified: head/sys/sys/chio.h
> ==============================================================================
> --- head/sys/sys/chio.h       Fri Apr 19 19:45:00 2013        (r249657)
> +++ head/sys/sys/chio.h       Fri Apr 19 20:03:51 2013        (r249658)
> @@ -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_ */

_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to