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