1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #ifndef _SPCS_S_IMPL_H
  27 #define _SPCS_S_IMPL_H
  28 
  29 #ifdef __cplusplus
  30 extern "C" {
  31 #endif
  32 
  33 /*
  34  *      The SPCS Unistat private implementation definitions
  35  *
  36  *      Only modules spcs_s_u.c and spcs_s_k.c should be using this
  37  */
  38 
  39 /*
  40  *      For Unistat, here are the definitions of the major and minor revisions:
  41  *
  42  *      Bump major revision and zero minor revision if: Any change made to
  43  *      spcs_s_pinfo_t in terms of size, changed fields, etc, or any user
  44  *      functional change to spcs_s.h definitions that is not backwards
  45  *      compatible.
  46  *
  47  *      Bump minor revision if: Any backwards compatible change to
  48  *      functionality but with no impact on interoperability between kernel and
  49  *      user level Unistat code having differing minor revs.
  50  *
  51  */
  52 
  53 #define SPCS_S_MAJOR_REV 1      /* Unistat major revision */
  54 #define SPCS_S_MINOR_REV 1      /* Unistat minor revision */
  55 /*
  56  *      This is the format of a unistat status code. It must overlay
  57  *      an int.
  58  */
  59 #if defined(__sparc)
  60 typedef struct {
  61         /*
  62          * If this flag is set the last supplemental item in idata is expected
  63          * to be of type SU_BYTESTREAM and offset is a tdata index.
  64          */
  65         unsigned char bytestream: 1;
  66         /*
  67          * count of items of supporting information references in idata
  68          * to accompany this error status code spcs.h define SPCS_S_MAXSUPP
  69          * must be 2 raised to the bit size of this field. Also don't forget
  70          * to update the sprintf in spcs_s_string.
  71          */
  72         unsigned char reserved: 4;      /* reserved for future expansion */
  73         unsigned char sup_count: 3;
  74         unsigned char module:   8;      /* module code (see below) */
  75         unsigned short code:    16;     /* status code number (>0) */
  76 } spcs_s_code_t;
  77 #elif defined(__i386) || (__amd64)
  78 typedef struct {
  79         /*
  80          * count of items of supporting information references in idata
  81          * to accompany this error status code spcs.h define SPCS_S_MAXSUPP
  82          * must be 2 raised to the bit size of this field. Also don't forget
  83          * to update the sprintf in spcs_s_string.
  84          */
  85         unsigned short code:    16;     /* status code number (>0) */
  86         unsigned char module:   8;      /* module code (see below) */
  87         unsigned char sup_count: 3;
  88         unsigned char reserved: 4;      /* reserved for future expansion */
  89         /*
  90          * If this flag is set the last supplemental item in idata is expected
  91          * to be of type SU_BYTESTREAM and offset is a tdata index.
  92          */
  93         unsigned char bytestream: 1;
  94 } spcs_s_code_t;
  95 #else
  96 #error "instruction set architecture error"
  97 #endif
  98 
  99 /*
 100  *      The types of supplemental data references
 101  */
 102 
 103 typedef enum {SU_STRING,                /* character string reference */
 104                 SU_BYTESTREAM,          /* bytestream data reference */
 105                 SU_RES2,
 106                 SU_RES3} suenum;
 107 /*
 108  *      Supplemental data references. These follow status codes that have
 109  *      nonzero sup_count fields. The supplemental data references can
 110  *      currently be either a string reference or a bytestream data reference.
 111  *      In both cases the reference simply contains an offset into the
 112  *      sdata array (string) or tdata array (bytestream). This struct must be
 113  *      the size of an int.
 114  */
 115 
 116 #if defined(__sparc)
 117 typedef struct {
 118         suenum type: 3;                 /* the supplemental data type */
 119         unsigned short reserved: 13;    /* unused, reserved */
 120         unsigned short offset:  16;     /* the sudata array offset of the */
 121                                         /* start of the supplemental data */
 122                                         /* or the tdata array offset for */
 123                                         /* bytestream data */
 124 } spcs_s_sudata_t;
 125 #elif defined(__i386) || (__amd64)
 126 typedef struct {
 127         unsigned short offset:  16;     /* the sudata array offset of the */
 128                                         /* start of the supplemental data */
 129                                         /* or the tdata array offset for */
 130                                         /* bytestream data */
 131         unsigned short reserved: 13;    /* unused, reserved */
 132         suenum type: 3;                 /* the supplemental data type */
 133 } spcs_s_sudata_t;
 134 #else
 135 #error "instruction set architecture error"
 136 #endif
 137 
 138 /*
 139  *      Although bytestream data pointers are only used in the kernel layer
 140  *      and are converted to offsets prior to unistat data being made available
 141  *      to userspace (i.e. this never comes back via an ioctl), it is critical
 142  *      to keep the unistat data structure spcs_s_pinfo_t a constant size
 143  *      whether or not we're using LP64 or a 32 bit model. So we put the
 144  *      pointer in a union with a long long so it is fixed at 64 bits in size.
 145  *
 146  *      Prior to being transported through a pipe, unistat data containing
 147  *      tdata items (see below) must have its pointers eliminated. The pointers
 148  *      are simply nulled out and the actual bytestream data is sent out the
 149  *      pipe following the spcs_s_pinfo_t in the same order as its references
 150  *      in the sequential tdata elements.
 151  */
 152 
 153 typedef union {
 154         uchar_t *data;                  /* the pointer to the bytestream data */
 155         long long _fix_the_size;
 156 } _fixed_char_pointer_t;
 157 
 158 /*
 159  *      The bytestream data descriptor in a tdata array element
 160  */
 161 
 162 typedef struct {
 163         uint32_t size;                  /* byte size of the bytestream data */
 164         _fixed_char_pointer_t u_p;      /* union containing pointer inside */
 165                                         /* fixed length field */
 166 } spcs_s_tdesc_t;
 167 
 168 /*
 169  *      All the types that can occupy an idata array element.
 170  */
 171 
 172 typedef union {
 173         spcs_s_status_t s;      /* as the public status type */
 174         spcs_s_code_t f;        /* as the internal status type */
 175         spcs_s_sudata_t su;     /* the supplemental data reference type */
 176         int i;                  /* as integer: TEMPORARY */
 177 } spcs_s_udata_t;
 178 
 179 /*
 180  *      The number of idata array elements. This is the upper bound for the
 181  *      total status codes and supplemental data reference items that can be
 182  *      held by unistat at one time. It is IMPORTANT that this array be large
 183  *      enough to hold all the status and references for the worst case path
 184  *      through core software. This is currently trivial to do by inspection
 185  *      of the ioctl service code. However once unistat usage is deployed to
 186  *      the underlying layers of core software below the ioctl service call
 187  *      layer it may require special tools to validate this.
 188  */
 189 
 190 #define SPCS_S_IDSIZE   16              /* size of idata array */
 191 /*
 192  *      The number of sdata array elements. This is the upper bound for the
 193  *      total characters of string data added to the unistat structure as
 194  *      supplemental info. Same cautions as for SPCS_S_IDSIZE.
 195  */
 196 
 197 #define SPCS_S_SDSIZE   512             /* size of sdata array */
 198 /*
 199  *      The number of tdata array elements. This is the upper bound for the
 200  *      total bytestream data descriptors that can be held by unistat at one
 201  *      time. Same cautions as for SPCS_S_IDSIZE.
 202  */
 203 
 204 #define SPCS_S_TDSIZE   2               /* size of tdata array */
 205 
 206 /*
 207  *      The Unistat private data structure. This is pointed to by the
 208  *      public opaque pointer spcs_s_info_t and holds all the status codes
 209  *      and supplemental data references. String data is also stored here
 210  *      but the body of bytestream data is stored elsewhere (see below).
 211  *
 212  *      If there is real concern about the overhead of ioctl copyouts they
 213  *      could be optimized such that only the scalars and the "used" elements
 214  *      of the idata, sdata and tdata arrays are moved. If this is done it is
 215  *      recommended that the scalars (i.e. major through spare) be moved into
 216  *      a structure to cut down on the chance of a coding error with manual
 217  *      size arithmetic.
 218  *
 219  *      The major and minor revs are currently supperfulous since unistat and
 220  *      all of its clients are contained within the same private consolidation.
 221  *      There is an assertion to BLOW UP if mismatched major revisions are
 222  *      detected between the kernel and user layers. If the consolidation
 223  *      policies of core software are relaxed in the future the assertion must
 224  *      be replaced by code designed to do something intelligent if possible.
 225  *
 226  */
 227 
 228 #pragma pack()
 229 typedef struct {
 230                                 /* The next two fields must stay shorts and */
 231                                 /* stay at the front and in this order */
 232                                 /* "forever" */
 233         short major;            /* Major unistat revision */
 234         short minor;            /* Minor unistat revision */
 235                                 /* this define should obviously never change */
 236 #define SPCS_S_REVSIZE (sizeof (short) + sizeof (short))
 237         short icount;           /* Number of items currently stored in idata */
 238                                 /* and the "next" index to store a new item */
 239                                 /* into */
 240         short scount;           /* Number of items currently stored in sdata */
 241                                 /* and the "next" index to store a new item */
 242                                 /* into */
 243         short tcount;           /* Number of items currently stored in tdata */
 244                                 /* and the "next" index to store a new item */
 245                                 /* into */
 246         short spare;            /* Unused, reserved */
 247         spcs_s_udata_t idata[SPCS_S_IDSIZE]; /* the status info and supp refs */
 248         char sdata[SPCS_S_SDSIZE]; /* the supplemental string data pool. */
 249                                 /* the supplemental bytestream data pool. */
 250         spcs_s_tdesc_t tdata[SPCS_S_TDSIZE];
 251 } spcs_s_pinfo_t;
 252 
 253 /*
 254  *      Module codes. These can be in any order except that Solaris MUST BE
 255  *      FIRST.
 256  */
 257 
 258 enum    {SPCS_M_Solaris,        /* Solaris module */
 259         SPCS_M_SPCS,            /* SPCS "module" (for codes that apply across */
 260                                 /* all controller modules */
 261         SPCS_M_DSW,             /* InstantImage Module */
 262         SPCS_M_SV,              /* Storage Volume Module */
 263         SPCS_M_RDC,             /* Remote Dual Copy Module */
 264         SPCS_M_SDBC,            /* Storage Device Block Cache Module */
 265         SPCS_M_STE,             /* SCSI Target Emulation Module */
 266         SPCS_M_SDCTL,           /* Storage Device Control Module */
 267         SPCS_M_MC,              /* Memory Channel Module */
 268         SPCS_M_SIMCKD,          /* CKD Simulation (SIMCKD) Module */
 269         SPCS_M_NVM};            /* Non-Volatile Memory Module */
 270 
 271 #define SPCS_M_MAX SPCS_M_NVM /* Highest defined module code */
 272 
 273 /*
 274  *      The SPCS general status values
 275  */
 276 
 277 /* the module name spellings */
 278 
 279 #define SPCS_M_NSOL     "SOLARIS"
 280 #define SPCS_M_NSPCS    "SPCS"
 281 #define SPCS_M_NDSW     "II"
 282 #define SPCS_M_NSV      "SV"
 283 #define SPCS_M_NRDC     "SNDR"
 284 #define SPCS_M_NSDBC    "SDBC"
 285 #define SPCS_M_NSTE     "STE"
 286 #define SPCS_M_NSDCTL   "NSCTL"
 287 #define SPCS_M_NMC      "MC"
 288 #define SPCS_M_NSIM     "SIMCKD"
 289 #define SPCS_M_NNVM     "NVM"
 290 
 291 /* limits */
 292 
 293 #define SPCS_S_MAXKEY   256             /* max msg key length */
 294 #define SPCS_S_MAXTEXT  SPCS_S_MAXLINE  /* max msg text length */
 295 #define SPCS_S_MAXSIG   32              /* max format data signature length */
 296 #define SPCS_S_MAXPRE   32              /* max module prefix length */
 297 #define SPCS_S_MAXMODNAME       16      /* max module name length */
 298 
 299 /* the module names in a lookup array */
 300 #if !defined(_KERNEL)
 301 static char *module_names[] = {SPCS_M_NSOL, SPCS_M_NSPCS, SPCS_M_NDSW,
 302         SPCS_M_NSV, SPCS_M_NRDC, SPCS_M_NSDBC, SPCS_M_NSTE, SPCS_M_NSDCTL,
 303         SPCS_M_NMC, SPCS_M_NSIM, SPCS_M_NNVM, NULL};
 304 #endif
 305 
 306 #ifdef __cplusplus
 307 }
 308 #endif
 309 
 310 #endif /* _SPCS_S_IMPL_H */