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 2016 Toomas Soome <tsoome@me.com>
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #ifndef _SYS_CMLB_H
  28 #define _SYS_CMLB_H
  29 
  30 #ifdef  __cplusplus
  31 extern "C" {
  32 #endif
  33 
  34 #include <sys/dktp/fdisk.h>
  35 
  36 /*
  37  * structure used for getting phygeom and virtgeom from target driver
  38  */
  39 typedef struct cmlb_geom {
  40         unsigned int    g_ncyl;
  41         unsigned short  g_acyl;
  42         unsigned short  g_nhead;
  43         unsigned short  g_nsect;
  44         unsigned short  g_secsize;
  45         diskaddr_t      g_capacity;
  46         unsigned short  g_intrlv;
  47         unsigned short  g_rpm;
  48 } cmlb_geom_t;
  49 
  50 
  51 typedef struct tg_attribute {
  52         int media_is_writable;
  53         int media_is_solid_state;
  54         int media_is_rotational;
  55 } tg_attribute_t;
  56 
  57 
  58 
  59 /* bit definitions for alter_behavior passed to cmlb_attach */
  60 
  61 #define CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT       0x00000001
  62 #define CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8               0x00000002
  63 #define CMLB_OFF_BY_ONE                                 0x00000004
  64 #define CMLB_FAKE_LABEL_ONE_PARTITION                   0x00000008
  65 #define CMLB_INTERNAL_MINOR_NODES                       0x00000010
  66 #define CMLB_CREATE_P0_MINOR_NODE                       0x00000020
  67 
  68 /* bit definitions of flag passed to cmlb_validate */
  69 #define CMLB_SILENT                                     0x00000001
  70 
  71 /* version for tg_ops */
  72 #define TG_DK_OPS_VERSION_0     0
  73 #define TG_DK_OPS_VERSION_1     1
  74 
  75 /* definitions for cmd passed to tg_rdwr */
  76 #define TG_READ                 0
  77 #define TG_WRITE                1
  78 
  79 /* definitions for cmd passed to tg_getinfo */
  80 #define TG_GETPHYGEOM           1
  81 #define TG_GETVIRTGEOM          2
  82 #define TG_GETCAPACITY          3
  83 #define TG_GETBLOCKSIZE         4
  84 #define TG_GETATTR              5
  85 
  86 #if defined(_SUNOS_VTOC_8)
  87 
  88 #define CMLBUNIT_DFT_SHIFT      3
  89 /* This will support p0 node on sparc */
  90 #define CMLBUNIT_FORCE_P0_SHIFT (CMLBUNIT_DFT_SHIFT + 1)
  91 
  92 #elif defined(_SUNOS_VTOC_16)
  93 
  94 #define CMLBUNIT_DFT_SHIFT      6
  95 #define CMLBUNIT_FORCE_P0_SHIFT (CMLBUNIT_DFT_SHIFT)
  96 
  97 #else   /* defined(_SUNOS_VTOC_16) */
  98 
  99 #error "No VTOC format defined."
 100 
 101 #endif  /* defined(_SUNOS_VTOC_8) */
 102 
 103 /*
 104  * Ops vector including utility functions into target driver that cmlb uses.
 105  */
 106 typedef struct cmlb_tg_ops {
 107         int     tg_version;
 108 
 109         /*
 110          * tg_rdwr:
 111          *      perform read/write on target device associated with devi.
 112          *
 113          * Arguments:
 114          *
 115          *      devi:           pointer to device's dev_info structure.
 116          *
 117          *      cmd:            operation to perform.
 118          *                      Possible values: TG_READ, TG_WRITE
 119          *
 120          *      bufp:           pointer to allocated buffer for transfer
 121          *
 122          *      start_block:    starting block number to read/write (based on
 123          *                      system blocksize, DEV_BSIZE)
 124          *
 125          *      reqlength:      requested transfer length (in bytes)
 126          *
 127          *      tg_cookie       cookie from target driver to be passed back to
 128          *                      target driver when we call back to it through
 129          *                      tg_ops.
 130          *
 131          * Note: It is the responsibility of caller to make sure
 132          *      length of buffer pointed to by bufp is at least equal to
 133          *      requested transfer length
 134          *
 135          * Return values:
 136          *      0               success
 137          *      ENOMEM          can not allocate memory
 138          *      EACCESS         reservation conflict
 139          *      EIO             I/O error
 140          *      EFAULT          copyin/copyout error
 141          *      ENXIO           internal error/ invalid devi
 142          *      EINVAL          invalid command value.
 143          */
 144         int (*tg_rdwr)(dev_info_t *devi, uchar_t cmd, void *bufp,
 145             diskaddr_t start_block, size_t reqlength, void *tg_cookie);
 146 
 147         /*
 148          * tg_getinfo:
 149          *      Report the information requested on device/media and
 150          *      store the requested info in area pointed to by arg.
 151          *
 152          * Arguments:
 153          *      devi:           pointer to device's dev_info structure.
 154          *
 155          *      cmd:            operation to perform
 156          *
 157          *      arg:            arg for the operation for result.
 158          *
 159          *      tg_cookie       cookie from target driver to be passed back to
 160          *                      target driver when we call back to it through
 161          *                      tg_ops.
 162          *
 163          *      Possible commands and the interpretation of arg:
 164          *
 165          *      cmd:
 166          *              TG_GETPHYGEOM
 167          *                      Obtain raw physical geometry from target,
 168          *                      and store in structure pointed to by arg,
 169          *                      a cmlb_geom_t structure.
 170          *
 171          *              TG_GETVIRTGEOM:
 172          *                      Obtain HBA geometry for the target and
 173          *                      store in struct pointed to by arg,
 174          *                      a cmlb_geom_t structure.
 175          *
 176          *              TG_GETCAPACITY:
 177          *                      Report the capacity of the target (in system
 178          *                      blocksize (DEV_BSIZE) and store in the
 179          *                      space pointed to by arg, a diskaddr_t.
 180          *
 181          *              TG_GETBLOCKSIZE:
 182          *                      Report the block size of the target
 183          *                      in the space pointed to by arg, a uint32_t.
 184          *
 185          *              TG_GETATTR:
 186          *                      Report the information requested on
 187          *                      device/media and store in area pointed to by
 188          *                      arg, a tg_attribute_t structure.
 189          *                      Return values:
 190          *
 191          * Return values:
 192          *      0               success
 193          *
 194          *      EACCESS         reservation conflict
 195          *
 196          *      ENXIO           internal error/invalid devi
 197          *
 198          *      EINVAL          When command is TG_GETPHYGEOM or
 199          *                      TG_GETVIRTGEOM, or TG_GETATTR, this return code
 200          *                      indicates the operation is not applicable to
 201          *                      target.
 202          *                      In case of TG_GETCAP, this return code
 203          *                      indicates no media in the drive.
 204          *
 205          *      EIO             An error occurred during obtaining info
 206          *                      from device/media.
 207          *
 208          *      ENOTSUP         In case of TG_GETCAP, target does not
 209          *                      support getting capacity info.
 210          *
 211          *      ENOTTY          Unknown command.
 212          *
 213          *
 214          */
 215         int (*tg_getinfo)(dev_info_t *devi, int cmd, void *arg,
 216             void *tg_cookie);
 217 
 218 } cmlb_tg_ops_t;
 219 
 220 
 221 typedef struct __cmlb_handle *cmlb_handle_t;
 222 
 223 /*
 224  *
 225  * Functions exported from cmlb
 226  *
 227  * Note: Most these functions can callback to target driver through the
 228  * tg_ops functions. Target driver should consider this for synchronization.
 229  * Any functions that may adjust minor nodes should be called when
 230  * the target driver ensures it is safe to do so.
 231  */
 232 
 233 /*
 234  * cmlb_alloc_handle:
 235  *
 236  *      Allocates a handle.
 237  *
 238  * Arguments:
 239  *      cmlbhandlep     pointer to handle
 240  *
 241  * Notes:
 242  *      Allocates a handle and stores the allocated handle in the area
 243  *      pointed to by cmlbhandlep
 244  *
 245  * Context:
 246  *      Kernel thread only (can sleep).
 247  */
 248 void
 249 cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep);
 250 
 251 
 252 /*
 253  * cmlb_attach:
 254  *
 255  *      Attach handle to device, create minor nodes for device.
 256  *
 257  *
 258  * Arguments:
 259  *      devi            pointer to device's dev_info structure.
 260  *      tgopsp          pointer to array of functions cmlb can use to callback
 261  *                      to target driver.
 262  *
 263  *      device_type     Peripheral device type as defined in
 264  *                      scsi/generic/inquiry.h
 265  *
 266  *      is_removable    whether or not device is removable.
 267  *
 268  *      is_hotpluggable whether or not device is hotpluggable.
 269  *
 270  *      node_type       minor node type (as used by ddi_create_minor_node)
 271  *
 272  *      alter_behavior
 273  *                      bit flags:
 274  *
 275  *                      CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create
 276  *                      an alternate slice for the default label, if
 277  *                      device type is DTYPE_DIRECT an architectures default
 278  *                      label type is VTOC16.
 279  *                      Otherwise alternate slice will no be created.
 280  *
 281  *
 282  *                      CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default
 283  *                      geometry and label for DKIOCGGEOM and DKIOCGVTOC
 284  *                      on architecture with VTOC 8 label types.
 285  *
 286  *                      CMLB_OFF_BY_ONE: do the workaround for legacy off-by-
 287  *                      one bug in obtaining capacity (used for sd).
 288  *
 289  *
 290  *      cmlbhandle      cmlb handle associated with device
 291  *
 292  *      tg_cookie       cookie from target driver to be passed back to target
 293  *                      driver when we call back to it through tg_ops.
 294  *
 295  *                      cmlb does not interpret the values. It is currently
 296  *                      used for sd to indicate whether retries are allowed
 297  *                      on commands or not. e.g when cmlb entries are called
 298  *                      from interrupt context on removable media, sd rather
 299  *                      not have retries done.
 300  *
 301  *
 302  *
 303  * Notes:
 304  *      Assumes a default label based on capacity for non-removable devices.
 305  *      If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
 306  *      for the architecture).
 307  *      For removable devices, default label type is assumed to be VTOC
 308  *      type. Create minor nodes based on a default label type.
 309  *      Label on the media is not validated.
 310  *      minor number consists of:
 311  *              if _SUNOS_VTOC_8 is defined
 312  *                      lowest 3 bits is taken as partition number
 313  *                      the rest is instance number
 314  *              if _SUNOS_VTOC_16 is defined
 315  *                      lowest 6 bits is taken as partition number
 316  *                      the rest is instance number
 317  *
 318  *
 319  * Return values:
 320  *      0       Success
 321  *      ENXIO   creating minor nodes failed.
 322  *      EINVAL  invalid arg, unsupported tg_ops version
 323  *
 324  */
 325 int
 326 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
 327     boolean_t is_removable, boolean_t is_hotpluggable, char *node_type,
 328     int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie);
 329 
 330 
 331 /*
 332  * cmlb_validate:
 333  *
 334  *      Validates label.
 335  *
 336  * Arguments
 337  *      cmlbhandle      cmlb handle associated with device.
 338  *
 339  *      int             flags
 340  *                      currently used for verbosity control.
 341  *                      CMLB_SILENT is the only current definition for it
 342  *      tg_cookie       cookie from target driver to be passed back to target
 343  *                      driver when we call back to it through tg_ops.
 344  * Notes:
 345  *      If new label type is different from the current, adjust minor nodes
 346  *      accordingly.
 347  *
 348  * Return values:
 349  *      0               success
 350  *                      Note: having fdisk but no solaris partition is assumed
 351  *                      success.
 352  *
 353  *      ENOMEM          memory allocation failed
 354  *      EIO             i/o errors during read or get capacity
 355  *      EACCESS         reservation conflicts
 356  *      EINVAL          label was corrupt, or no default label was assumed
 357  *      ENXIO           invalid handle
 358  *
 359  */
 360 int
 361 cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie);
 362 
 363 /*
 364  * cmlb_invalidate:
 365  *      Invalidate in core label data
 366  *
 367  * Arguments:
 368  *      cmlbhandle      cmlb handle associated with device.
 369  *      tg_cookie       cookie from target driver to be passed back to target
 370  *                      driver when we call back to it through tg_ops.
 371  */
 372 void
 373 cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie);
 374 
 375 
 376 
 377 /*
 378  * cmlb_is_valid
 379  *       Get status on whether the incore label/geom data is valid
 380  *
 381  * Arguments:
 382  *      cmlbhandle      cmlb handle associated with device.
 383  *
 384  * Return values:
 385  *      TRUE if valid
 386  *      FALSE otherwise.
 387  *
 388  */
 389 boolean_t
 390 cmlb_is_valid(cmlb_handle_t cmlbhandle);
 391 
 392 /*
 393  * cmlb_partinfo:
 394  *      Get partition info for specified partition number.
 395  *
 396  * Arguments:
 397  *      cmlbhandle      cmlb handle associated with device.
 398  *      part            partition number
 399  *                      driver when we call back to it through tg_ops.
 400  *      nblocksp        pointer to number of blocks
 401  *      startblockp     pointer to starting block
 402  *      partnamep       pointer to name of partition
 403  *      tagp            pointer to tag info
 404  *      tg_cookie       cookie from target driver to be passed back to target
 405  *
 406  * Notes:
 407  *      If in-core label is not valid, this functions tries to revalidate
 408  *      the label. If label is valid, it stores the total number of blocks
 409  *      in this partition in the area pointed to by nblocksp, starting
 410  *      block number in area pointed to by startblockp,  pointer to partition
 411  *      name in area pointed to by partnamep, and tag value in area
 412  *      pointed by tagp.
 413  *      For EFI labels, tag value will be set to 0.
 414  *
 415  *      For all nblocksp, startblockp and partnamep, tagp, a value of NULL
 416  *      indicates the corresponding info is not requested.
 417  *
 418  *
 419  * Return values:
 420  *      0       success
 421  *      EINVAL  no valid label or requested partition number is invalid.
 422  *
 423  */
 424 int
 425 cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp,
 426     diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie);
 427 
 428 /*
 429  * cmlb_efi_label_capacity:
 430  *      Get capacity stored in EFI disk label.
 431  *
 432  * Arguments:
 433  *      cmlbhandle      cmlb handle associated with device.
 434  *      capacity        pointer to capacity stored in EFI disk label.
 435  *      tg_cookie       cookie from target driver to be passed back to target
 436  *                      driver when we call back to it through tg_ops.
 437  *
 438  *
 439  * Notes:
 440  *      If in-core label is not valid, this functions tries to revalidate
 441  *      the label. If label is valid and is an EFI label, it stores the capacity
 442  *      in disk label in the area pointed to by capacity.
 443  *
 444  *
 445  * Return values:
 446  *      0       success
 447  *      EINVAL  no valid EFI label or capacity is NULL.
 448  *
 449  */
 450 int
 451 cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity,
 452     void *tg_cookie);
 453 
 454 /*
 455  * cmlb_ioctl:
 456  * Ioctls for label handling will be handled by this function.
 457  * These are:
 458  *      DKIOCGGEOM
 459  *      DKIOCSGEOM
 460  *      DKIOCGAPART
 461  *      DKIOCSAPART
 462  *      DKIOCGVTOC
 463  *      DKIOCGETEFI
 464  *      DKIOCPARTITION
 465  *      DKIOCSVTOC
 466  *      DKIOCSETEFI
 467  *      DKIOCGMBOOT
 468  *      DKIOCSMBOOT
 469  *      DKIOCG_PHYGEOM
 470  *      DKIOCG_VIRTGEOM
 471  *      DKIOCPARTINFO
 472  *
 473  *
 474  *   Arguments:
 475  *      cmlbhandle      handle associated with device.
 476  *      cmd             ioctl operation to be performed
 477  *      arg             user argument, contains data to be set or reference
 478  *                      parameter for get
 479  *      flag            bit flag, indicating open settings, 32/64 bit type
 480  *      cred_p          user credential pointer (not currently used)
 481  *      rval_p          not currently used
 482  *      tg_cookie       cookie from target driver to be passed back to target
 483  *                      driver when we call back to it through tg_ops.
 484  *
 485  *
 486  *
 487  * Return values:
 488  *      0
 489  *      EINVAL
 490  *      ENOTTY
 491  *      ENXIO
 492  *      EIO
 493  *      EFAULT
 494  *      ENOTSUP
 495  *      EPERM
 496  */
 497 int
 498 cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd,
 499     intptr_t arg, int flag, cred_t *cred_p, int *rval_p, void *tg_cookie);
 500 
 501 /*
 502  * cmlb_prop_op:
 503  *      provide common label prop_op(9E) implementation that understands the
 504  *      size(9p) properties.
 505  *
 506  * Arguments:
 507  *      cmlbhandle      cmlb handle associated with device.
 508  *      dev             See prop_op(9E)
 509  *      dip             "
 510  *      prop_op         "
 511  *      mod_flags       "
 512  *      name            "
 513  *      valuep          "
 514  *      lengthp         "
 515  *      part            partition number
 516  *      tg_cookie       cookie from target driver to be passed back to target
 517  */
 518 int
 519 cmlb_prop_op(cmlb_handle_t cmlbhandle,
 520     dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags,
 521     char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie);
 522 
 523 /*
 524  * cmlb_get_devid_block:
 525  *       get the block number where device id is stored.
 526  *
 527  * Arguments:
 528  *      cmlbhandle      cmlb handle associated with device.
 529  *      devidblockp     pointer to block number.
 530  *      tg_cookie       cookie from target driver to be passed back to target
 531  *                      driver when we call back to it through tg_ops.
 532  *
 533  * Notes:
 534  *      It stores the block number of device id in the area pointed to
 535  *      by devidblockp.
 536  *
 537  * Return values:
 538  *      0       success
 539  *      EINVAL  device id does not apply to current label type.
 540  */
 541 int
 542 cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp,
 543     void *tg_cookie);
 544 
 545 
 546 /*
 547  * cmlb_close:
 548  *
 549  * Close the device, revert to a default label minor node for the device,
 550  * if it is removable.
 551  *
 552  * Arguments:
 553  *      cmlbhandle      cmlb handle associated with device.
 554  *
 555  *      tg_cookie       cookie from target driver to be passed back to target
 556  *                      driver when we call back to it through tg_ops.
 557  * Return values:
 558  *      0       Success
 559  *      ENXIO   Re-creating minor node failed.
 560  */
 561 int
 562 cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie);
 563 
 564 /*
 565  * cmlb_detach:
 566  *
 567  * Invalidate in-core labeling data and remove all minor nodes for
 568  * the device associate with handle.
 569  *
 570  * Arguments:
 571  *      cmlbhandle      cmlb handle associated with device.
 572  *      tg_cookie       cookie from target driver to be passed back to target
 573  *                      driver when we call back to it through tg_ops.
 574  *
 575  */
 576 void
 577 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie);
 578 
 579 /*
 580  * cmlb_free_handle
 581  *
 582  *      Frees handle.
 583  *
 584  * Arguments:
 585  *      cmlbhandlep     pointer to handle
 586  *
 587  */
 588 void
 589 cmlb_free_handle(cmlb_handle_t *cmlbhandlep);
 590 
 591 #ifdef  __cplusplus
 592 }
 593 #endif
 594 
 595 #endif /* _SYS_CMLB_H */