11ae08745Sheppo /* 21ae08745Sheppo * CDDL HEADER START 31ae08745Sheppo * 41ae08745Sheppo * The contents of this file are subject to the terms of the 51ae08745Sheppo * Common Development and Distribution License (the "License"). 61ae08745Sheppo * You may not use this file except in compliance with the License. 71ae08745Sheppo * 81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91ae08745Sheppo * or http://www.opensolaris.org/os/licensing. 101ae08745Sheppo * See the License for the specific language governing permissions 111ae08745Sheppo * and limitations under the License. 121ae08745Sheppo * 131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each 141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the 161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying 171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner] 181ae08745Sheppo * 191ae08745Sheppo * CDDL HEADER END 201ae08745Sheppo */ 211ae08745Sheppo 221ae08745Sheppo /* 23*ca6d1280SAlexandre Chartre * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 241ae08745Sheppo */ 251ae08745Sheppo 261ae08745Sheppo #ifndef _VDSK_COMMON_H 271ae08745Sheppo #define _VDSK_COMMON_H 281ae08745Sheppo 291ae08745Sheppo #ifdef __cplusplus 301ae08745Sheppo extern "C" { 311ae08745Sheppo #endif 321ae08745Sheppo 331ae08745Sheppo /* 341ae08745Sheppo * This header file contains the private LDoms Virtual Disk (vDisk) definitions 351ae08745Sheppo * common to both the server (vds) and the client (vdc) 361ae08745Sheppo */ 371ae08745Sheppo 384bac2208Snarayan #include <sys/efi_partition.h> 391ae08745Sheppo #include <sys/machparam.h> 401ae08745Sheppo #include <sys/vtoc.h> 411ae08745Sheppo 421ae08745Sheppo #include <sys/ldc.h> 431ae08745Sheppo #include <sys/vio_common.h> 441ae08745Sheppo #include <sys/vio_mailbox.h> 451ae08745Sheppo 461ae08745Sheppo /* 471ae08745Sheppo * vDisk definitions 481ae08745Sheppo */ 491ae08745Sheppo 501ae08745Sheppo /* 511ae08745Sheppo * The number of Descriptor Ring entries 521ae08745Sheppo * 531ae08745Sheppo * Constraints: 541ae08745Sheppo * - overall DRing size must be greater than 8K (MMU_PAGESIZE) 551ae08745Sheppo * - overall DRing size should be 8K aligned (desirable but not enforced) 561ae08745Sheppo * - DRing entry must be 8 byte aligned 571ae08745Sheppo */ 581ae08745Sheppo #define VD_DRING_LEN 512 591ae08745Sheppo 601ae08745Sheppo /* 611ae08745Sheppo * 621ae08745Sheppo */ 631ae08745Sheppo #define VD_DRING_ENTRY_SZ (sizeof (vd_dring_entry_t) + \ 641ae08745Sheppo (sizeof (ldc_mem_cookie_t) * (VD_MAX_COOKIES - 1))) 651ae08745Sheppo 661ae08745Sheppo /* 671ae08745Sheppo * The maximum block size we can transmit using one Descriptor Ring entry 681ae08745Sheppo * 691ae08745Sheppo * Currently no FS uses more than 128K and it doesn't look like they 701ae08745Sheppo * will either as there is no perf gain to be had by larger values. 711ae08745Sheppo * ( see ZFS comment at definition of SPA_MAXBLOCKSIZE ). 721ae08745Sheppo * 731ae08745Sheppo * We choose 256K to give us some headroom. 741ae08745Sheppo */ 751ae08745Sheppo #define VD_MAX_BLOCK_SIZE (256 * 1024) 761ae08745Sheppo 771ae08745Sheppo #define VD_MAX_COOKIES ((VD_MAX_BLOCK_SIZE / PAGESIZE) + 1) 781ae08745Sheppo #define VD_USEC_TIMEOUT 20000 791ae08745Sheppo #define VD_LDC_IDS_PROP "ldc-ids" 80e1ebb9ecSlm66018 #define VD_LDC_MTU 256 811ae08745Sheppo 821ae08745Sheppo /* 831ae08745Sheppo * Flags used by ioctl routines to indicate if a copyin/copyout is needed 841ae08745Sheppo */ 851ae08745Sheppo #define VD_COPYOUT 0x1 861ae08745Sheppo #define VD_COPYIN 0x2 871ae08745Sheppo 881ae08745Sheppo /* 891ae08745Sheppo * vDisk operations on physical devices 901ae08745Sheppo */ 911ae08745Sheppo #define VD_OP_BREAD 0x01 /* Block Read */ 921ae08745Sheppo #define VD_OP_BWRITE 0x02 /* Block Write */ 931ae08745Sheppo #define VD_OP_FLUSH 0x03 /* Flush disk write cache contents */ 941ae08745Sheppo #define VD_OP_GET_WCE 0x04 /* Get disk W$ status */ 951ae08745Sheppo #define VD_OP_SET_WCE 0x05 /* Enable/Disable disk W$ */ 961ae08745Sheppo #define VD_OP_GET_VTOC 0x06 /* Get VTOC */ 971ae08745Sheppo #define VD_OP_SET_VTOC 0x07 /* Set VTOC */ 981ae08745Sheppo #define VD_OP_GET_DISKGEOM 0x08 /* Get disk geometry */ 991ae08745Sheppo #define VD_OP_SET_DISKGEOM 0x09 /* Set disk geometry */ 1001ae08745Sheppo #define VD_OP_SCSICMD 0x0a /* SCSI control command */ 1014bac2208Snarayan #define VD_OP_GET_DEVID 0x0b /* Get device id */ 1024bac2208Snarayan #define VD_OP_GET_EFI 0x0c /* Get EFI */ 1034bac2208Snarayan #define VD_OP_SET_EFI 0x0d /* Set EFI */ 1042f5224aeSachartre #define VD_OP_RESET 0x0e /* Reset disk */ 1052f5224aeSachartre #define VD_OP_GET_ACCESS 0x0f /* Get disk access */ 1062f5224aeSachartre #define VD_OP_SET_ACCESS 0x10 /* Set disk access */ 1072f5224aeSachartre #define VD_OP_GET_CAPACITY 0x11 /* Get disk capacity */ 1081ae08745Sheppo #define VD_OP_MASK 0xFF /* mask of all possible operations */ 1092f5224aeSachartre #define VD_OP_COUNT 0x11 /* Number of operations */ 1102f5224aeSachartre 1112f5224aeSachartre /* 1122f5224aeSachartre * Status for the VD_OP_GET_ACCESS operation 1132f5224aeSachartre */ 1142f5224aeSachartre #define VD_ACCESS_DENIED 0x00 /* access is not allowed */ 1152f5224aeSachartre #define VD_ACCESS_ALLOWED 0x01 /* access is allowed */ 1162f5224aeSachartre 1172f5224aeSachartre /* 1182f5224aeSachartre * Flags for the VD_OP_SET_ACCESS operation 1192f5224aeSachartre */ 1202f5224aeSachartre #define VD_ACCESS_SET_CLEAR 0x00 /* clear exclusive access rights */ 1212f5224aeSachartre #define VD_ACCESS_SET_EXCLUSIVE 0x01 /* set exclusive access rights */ 1222f5224aeSachartre #define VD_ACCESS_SET_PREEMPT 0x02 /* forcefully set access rights */ 1232f5224aeSachartre #define VD_ACCESS_SET_PRESERVE 0x04 /* preserve access rights */ 1244bac2208Snarayan 1254bac2208Snarayan /* 12617cadca8Slm66018 * This is a mask of all the basic operations supported by all 12717cadca8Slm66018 * disk types (v1.0). 12817cadca8Slm66018 */ 12917cadca8Slm66018 #define VD_OP_MASK_READ \ 13017cadca8Slm66018 ((1 << VD_OP_BREAD) | \ 13117cadca8Slm66018 (1 << VD_OP_GET_WCE) | \ 13217cadca8Slm66018 (1 << VD_OP_GET_VTOC) | \ 13317cadca8Slm66018 (1 << VD_OP_GET_DISKGEOM) | \ 13417cadca8Slm66018 (1 << VD_OP_GET_DEVID) | \ 13517cadca8Slm66018 (1 << VD_OP_GET_EFI)) 13617cadca8Slm66018 13717cadca8Slm66018 #define VD_OP_MASK_WRITE \ 13817cadca8Slm66018 ((1 << VD_OP_BWRITE) | \ 13917cadca8Slm66018 (1 << VD_OP_FLUSH) | \ 14017cadca8Slm66018 (1 << VD_OP_SET_WCE) | \ 14117cadca8Slm66018 (1 << VD_OP_SET_VTOC) | \ 14217cadca8Slm66018 (1 << VD_OP_SET_DISKGEOM) | \ 14317cadca8Slm66018 (1 << VD_OP_SET_EFI)) 14417cadca8Slm66018 1452f5224aeSachartre /* 1462f5224aeSachartre * Mask for additional operations provided for SCSI disks (v1.1) 1472f5224aeSachartre */ 1482f5224aeSachartre #define VD_OP_MASK_SCSI \ 1492f5224aeSachartre ((1 << VD_OP_SCSICMD) | \ 1502f5224aeSachartre (1 << VD_OP_RESET) | \ 1512f5224aeSachartre (1 << VD_OP_GET_ACCESS) | \ 152de3a5331SRamesh Chitrothu (1 << VD_OP_SET_ACCESS)) 15317cadca8Slm66018 15417cadca8Slm66018 /* 15517cadca8Slm66018 * macro to check if the operation 'op' is supported by checking the list 15617cadca8Slm66018 * of operations supported which is exported by the vDisk server. 15717cadca8Slm66018 */ 15817cadca8Slm66018 #define VD_OP_SUPPORTED(ops_bitmask, op) ((ops_bitmask) & (1 << (op))) 15917cadca8Slm66018 16017cadca8Slm66018 /* 16187a7269eSachartre * Slice for absolute disk transaction. 16287a7269eSachartre */ 16387a7269eSachartre #define VD_SLICE_NONE 0xFF 16487a7269eSachartre 16587a7269eSachartre /* 1664bac2208Snarayan * EFI disks do not have a slice 7. Actually that slice is used to represent 1674bac2208Snarayan * the whole disk. 1684bac2208Snarayan */ 1694bac2208Snarayan #define VD_EFI_WD_SLICE 7 1701ae08745Sheppo 1711ae08745Sheppo /* 1721ae08745Sheppo * Definitions of the various ways vds can export disk support to vdc. 1731ae08745Sheppo */ 1741ae08745Sheppo typedef enum vd_disk_type { 1751ae08745Sheppo VD_DISK_TYPE_UNK = 0, /* Unknown device type */ 1761ae08745Sheppo VD_DISK_TYPE_SLICE, /* slice in block device */ 1771ae08745Sheppo VD_DISK_TYPE_DISK /* entire disk (slice 2) */ 1781ae08745Sheppo } vd_disk_type_t; 1791ae08745Sheppo 1801ae08745Sheppo /* 1814bac2208Snarayan * Definitions of the various disk label that vDisk supports. 1824bac2208Snarayan */ 1834bac2208Snarayan typedef enum vd_disk_label { 1844bac2208Snarayan VD_DISK_LABEL_UNK = 0, /* Unknown disk label */ 1854bac2208Snarayan VD_DISK_LABEL_VTOC, /* VTOC disk label */ 1864bac2208Snarayan VD_DISK_LABEL_EFI /* EFI disk label */ 1874bac2208Snarayan } vd_disk_label_t; 1884bac2208Snarayan 1894bac2208Snarayan /* 1901ae08745Sheppo * vDisk Descriptor payload 1911ae08745Sheppo */ 1921ae08745Sheppo typedef struct vd_dring_payload { 1931ae08745Sheppo uint64_t req_id; /* The request ID being processed */ 1941ae08745Sheppo uint8_t operation; /* operation for server to perform */ 1951ae08745Sheppo uint8_t slice; /* The disk slice being accessed */ 1961ae08745Sheppo uint16_t resv1; /* padding */ 1971ae08745Sheppo uint32_t status; /* "errno" of server operation */ 1981ae08745Sheppo uint64_t addr; /* LP64 diskaddr_t (block I/O) */ 1991ae08745Sheppo uint64_t nbytes; /* LP64 size_t */ 2001ae08745Sheppo uint32_t ncookies; /* Number of cookies used */ 2011ae08745Sheppo uint32_t resv2; /* padding */ 2021ae08745Sheppo 2031ae08745Sheppo ldc_mem_cookie_t cookie[1]; /* variable sized array */ 2041ae08745Sheppo } vd_dring_payload_t; 2051ae08745Sheppo 2061ae08745Sheppo 2071ae08745Sheppo /* 2081ae08745Sheppo * vDisk Descriptor entry 2091ae08745Sheppo */ 2101ae08745Sheppo typedef struct vd_dring_entry { 2111ae08745Sheppo vio_dring_entry_hdr_t hdr; /* common header */ 2121ae08745Sheppo vd_dring_payload_t payload; /* disk specific data */ 2131ae08745Sheppo } vd_dring_entry_t; 2141ae08745Sheppo 215edcc0754Sachartre /* 216edcc0754Sachartre * vDisk logical partition 217edcc0754Sachartre */ 218edcc0754Sachartre typedef struct vd_slice { 219edcc0754Sachartre daddr_t start; /* block number of slice start */ 220edcc0754Sachartre daddr_t nblocks; /* number of blocks in the slice */ 221edcc0754Sachartre } vd_slice_t; 222edcc0754Sachartre 2231ae08745Sheppo 2241ae08745Sheppo /* 2251ae08745Sheppo * vDisk control operation structures 2261ae08745Sheppo */ 2271ae08745Sheppo 2281ae08745Sheppo /* 2290a55fbb7Slm66018 * vDisk geometry definition (VD_OP_GET_DISKGEOM and VD_OP_SET_DISKGEOM) 2300a55fbb7Slm66018 */ 2310a55fbb7Slm66018 typedef struct vd_geom { 2320a55fbb7Slm66018 uint16_t ncyl; /* number of data cylinders */ 2330a55fbb7Slm66018 uint16_t acyl; /* number of alternate cylinders */ 2340a55fbb7Slm66018 uint16_t bcyl; /* cyl offset for fixed head area */ 2350a55fbb7Slm66018 uint16_t nhead; /* number of heads */ 2360a55fbb7Slm66018 uint16_t nsect; /* number of data sectors per track */ 2370a55fbb7Slm66018 uint16_t intrlv; /* interleave factor */ 2380a55fbb7Slm66018 uint16_t apc; /* alternates per cyl (SCSI only) */ 2390a55fbb7Slm66018 uint16_t rpm; /* revolutions per minute */ 2400a55fbb7Slm66018 uint16_t pcyl; /* number of physical cylinders */ 2410a55fbb7Slm66018 uint16_t write_reinstruct; /* # sectors to skip, writes */ 2420a55fbb7Slm66018 uint16_t read_reinstruct; /* # sectors to skip, reads */ 2430a55fbb7Slm66018 } vd_geom_t; 2440a55fbb7Slm66018 2450a55fbb7Slm66018 2460a55fbb7Slm66018 /* 2470a55fbb7Slm66018 * vDisk partition definition 2481ae08745Sheppo */ 2491ae08745Sheppo typedef struct vd_partition { 2500a55fbb7Slm66018 uint16_t id_tag; /* ID tag of partition */ 2510a55fbb7Slm66018 uint16_t perm; /* permission flags for partition */ 2521ae08745Sheppo uint32_t reserved; /* padding */ 2530a55fbb7Slm66018 uint64_t start; /* block number of partition start */ 2540a55fbb7Slm66018 uint64_t nblocks; /* number of blocks in partition */ 2551ae08745Sheppo } vd_partition_t; 2561ae08745Sheppo 2570a55fbb7Slm66018 /* 2580a55fbb7Slm66018 * vDisk VTOC definition (VD_OP_GET_VTOC and VD_OP_SET_VTOC) 2590a55fbb7Slm66018 */ 2600a55fbb7Slm66018 #define VD_VOLNAME_LEN 8 /* length of volume_name field */ 2610a55fbb7Slm66018 #define VD_ASCIILABEL_LEN 128 /* length of ascii_label field */ 2621ae08745Sheppo typedef struct vd_vtoc { 2630a55fbb7Slm66018 char volume_name[VD_VOLNAME_LEN]; /* volume name */ 2640a55fbb7Slm66018 uint16_t sector_size; /* sector size in bytes */ 2650a55fbb7Slm66018 uint16_t num_partitions; /* number of partitions */ 2660a55fbb7Slm66018 char ascii_label[VD_ASCIILABEL_LEN]; /* ASCII label */ 2670a55fbb7Slm66018 vd_partition_t partition[V_NUMPAR]; /* partition headers */ 2681ae08745Sheppo } vd_vtoc_t; 2691ae08745Sheppo 2701ae08745Sheppo 2711ae08745Sheppo /* 2724bac2208Snarayan * vDisk EFI definition (VD_OP_GET_EFI and VD_OP_SET_EFI) 2734bac2208Snarayan */ 2744bac2208Snarayan typedef struct vd_efi { 2754bac2208Snarayan uint64_t lba; /* lba of the request */ 2764bac2208Snarayan uint64_t length; /* length of data */ 2774bac2208Snarayan char data[1]; /* data of the request */ 2784bac2208Snarayan } vd_efi_t; 2794bac2208Snarayan 2804bac2208Snarayan 2814bac2208Snarayan /* 2824bac2208Snarayan * vDisk DEVID definition (VD_OP_GET_DEVID) 2834bac2208Snarayan */ 2844bac2208Snarayan #define VD_DEVID_SIZE(l) (sizeof (vd_devid_t) - 1 + l) 2854bac2208Snarayan #define VD_DEVID_DEFAULT_LEN 128 2864bac2208Snarayan 2874bac2208Snarayan typedef struct vd_devid { 2884bac2208Snarayan uint16_t reserved; /* padding */ 2894bac2208Snarayan uint16_t type; /* type of device id */ 2904bac2208Snarayan uint32_t length; /* length the device id */ 2914bac2208Snarayan char id[1]; /* device id */ 2924bac2208Snarayan } vd_devid_t; 2934bac2208Snarayan 2944bac2208Snarayan /* 2952f5224aeSachartre * vDisk CAPACITY definition (VD_OP_GET_CAPACITY) 2962f5224aeSachartre */ 2972f5224aeSachartre typedef struct vd_capacity { 2982f5224aeSachartre uint32_t vdisk_block_size; /* block size in bytes */ 2992f5224aeSachartre uint32_t reserved; /* reserved */ 3002f5224aeSachartre uint64_t vdisk_size; /* disk size in blocks */ 3012f5224aeSachartre } vd_capacity_t; 3022f5224aeSachartre 3032f5224aeSachartre /* Identifier for unknown disk size */ 3042f5224aeSachartre #define VD_SIZE_UNKNOWN -1 3052f5224aeSachartre 3062f5224aeSachartre /* 3072f5224aeSachartre * vDisk SCSI definition (VD_OP_SCSICMD) 3082f5224aeSachartre */ 3092f5224aeSachartre typedef struct vd_scsi { 3102f5224aeSachartre uint8_t cmd_status; /* command completion status */ 3112f5224aeSachartre uint8_t sense_status; /* sense command completion status */ 3122f5224aeSachartre uint8_t task_attribute; /* task attribute */ 3132f5224aeSachartre uint8_t task_priority; /* task priority */ 3142f5224aeSachartre uint8_t crn; /* command reference number */ 3152f5224aeSachartre uint8_t reserved; /* reserved */ 3162f5224aeSachartre uint16_t timeout; /* command timeout */ 3172f5224aeSachartre uint64_t options; /* options */ 3182f5224aeSachartre uint64_t cdb_len; /* CDB data length */ 3192f5224aeSachartre uint64_t sense_len; /* sense request length */ 3202f5224aeSachartre uint64_t datain_len; /* data in buffer length */ 3212f5224aeSachartre uint64_t dataout_len; /* data out buffer length */ 3222f5224aeSachartre char data[1]; /* data (CDB, sense, data in/out */ 3232f5224aeSachartre } vd_scsi_t; 3242f5224aeSachartre 3252f5224aeSachartre /* Minimum size of the vd_scsi structure */ 3262f5224aeSachartre #define VD_SCSI_SIZE (sizeof (vd_scsi_t) - sizeof (uint64_t)) 3272f5224aeSachartre 3282f5224aeSachartre /* 3292f5224aeSachartre * Macros to access data buffers in a vd_scsi structure. When using these 3302f5224aeSachartre * macros, the vd_scsi structure needs to be populated with the sizes of 3312f5224aeSachartre * data buffers allocated in the structure. 3322f5224aeSachartre */ 3332f5224aeSachartre #define VD_SCSI_DATA_CDB(vscsi) \ 3342f5224aeSachartre ((union scsi_cdb *)(uintptr_t)((vscsi)->data)) 3352f5224aeSachartre 3362f5224aeSachartre #define VD_SCSI_DATA_SENSE(vscsi) \ 3372f5224aeSachartre ((struct scsi_extended_sense *)(uintptr_t)((vscsi)->data + \ 3382f5224aeSachartre P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)))) 3392f5224aeSachartre 3402f5224aeSachartre #define VD_SCSI_DATA_IN(vscsi) \ 3412f5224aeSachartre ((uintptr_t)((vscsi)->data + \ 3422f5224aeSachartre P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + \ 3432f5224aeSachartre P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t)))) 3442f5224aeSachartre 3452f5224aeSachartre #define VD_SCSI_DATA_OUT(vscsi) \ 3462f5224aeSachartre ((uintptr_t)((vscsi)->data + \ 3472f5224aeSachartre P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + \ 3482f5224aeSachartre P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t)) + \ 3492f5224aeSachartre P2ROUNDUP((vscsi)->datain_len, sizeof (uint64_t)))) 3502f5224aeSachartre 3512f5224aeSachartre /* vDisk SCSI task attribute */ 3522f5224aeSachartre #define VD_SCSI_TASK_SIMPLE 0x01 /* simple task */ 3532f5224aeSachartre #define VD_SCSI_TASK_ORDERED 0x02 /* ordered task */ 3542f5224aeSachartre #define VD_SCSI_TASK_HQUEUE 0x03 /* head of queue task */ 3552f5224aeSachartre #define VD_SCSI_TASK_ACA 0x04 /* ACA task */ 3562f5224aeSachartre 3572f5224aeSachartre /* vDisk SCSI options */ 3582f5224aeSachartre #define VD_SCSI_OPT_CRN 0x01 /* request has a CRN */ 3592f5224aeSachartre #define VD_SCSI_OPT_NORETRY 0x02 /* do not attempt any retry */ 3602f5224aeSachartre 3612f5224aeSachartre /* 3620a55fbb7Slm66018 * Copy the contents of a vd_geom_t to the contents of a dk_geom struct 3631ae08745Sheppo */ 3640a55fbb7Slm66018 #define VD_GEOM2DK_GEOM(vd_geom, dk_geom) \ 3650a55fbb7Slm66018 { \ 3660a55fbb7Slm66018 bzero((dk_geom), sizeof (*(dk_geom))); \ 3670a55fbb7Slm66018 (dk_geom)->dkg_ncyl = (vd_geom)->ncyl; \ 3680a55fbb7Slm66018 (dk_geom)->dkg_acyl = (vd_geom)->acyl; \ 3690a55fbb7Slm66018 (dk_geom)->dkg_bcyl = (vd_geom)->bcyl; \ 3700a55fbb7Slm66018 (dk_geom)->dkg_nhead = (vd_geom)->nhead; \ 3710a55fbb7Slm66018 (dk_geom)->dkg_nsect = (vd_geom)->nsect; \ 3720a55fbb7Slm66018 (dk_geom)->dkg_intrlv = (vd_geom)->intrlv; \ 3730a55fbb7Slm66018 (dk_geom)->dkg_apc = (vd_geom)->apc; \ 3740a55fbb7Slm66018 (dk_geom)->dkg_rpm = (vd_geom)->rpm; \ 3750a55fbb7Slm66018 (dk_geom)->dkg_pcyl = (vd_geom)->pcyl; \ 3760a55fbb7Slm66018 (dk_geom)->dkg_write_reinstruct = (vd_geom)->write_reinstruct; \ 3770a55fbb7Slm66018 (dk_geom)->dkg_read_reinstruct = (vd_geom)->read_reinstruct; \ 3780a55fbb7Slm66018 } 3790a55fbb7Slm66018 3800a55fbb7Slm66018 /* 3810a55fbb7Slm66018 * Copy the contents of a vd_vtoc_t to the contents of a vtoc struct 3820a55fbb7Slm66018 */ 3830a55fbb7Slm66018 #define VD_VTOC2VTOC(vd_vtoc, vtoc) \ 3840a55fbb7Slm66018 { \ 3850a55fbb7Slm66018 bzero((vtoc), sizeof (*(vtoc))); \ 3860a55fbb7Slm66018 bcopy((vd_vtoc)->volume_name, (vtoc)->v_volume, \ 3870a55fbb7Slm66018 MIN(sizeof ((vd_vtoc)->volume_name), \ 3880a55fbb7Slm66018 sizeof ((vtoc)->v_volume))); \ 3890a55fbb7Slm66018 bcopy((vd_vtoc)->ascii_label, (vtoc)->v_asciilabel, \ 3900a55fbb7Slm66018 MIN(sizeof ((vd_vtoc)->ascii_label), \ 3910a55fbb7Slm66018 sizeof ((vtoc)->v_asciilabel))); \ 3920a55fbb7Slm66018 (vtoc)->v_sanity = VTOC_SANE; \ 3930a55fbb7Slm66018 (vtoc)->v_version = V_VERSION; \ 3940a55fbb7Slm66018 (vtoc)->v_sectorsz = (vd_vtoc)->sector_size; \ 3950a55fbb7Slm66018 (vtoc)->v_nparts = (vd_vtoc)->num_partitions; \ 3960a55fbb7Slm66018 for (int i = 0; i < (vd_vtoc)->num_partitions; i++) { \ 3970a55fbb7Slm66018 (vtoc)->v_part[i].p_tag = (vd_vtoc)->partition[i].id_tag; \ 3980a55fbb7Slm66018 (vtoc)->v_part[i].p_flag = (vd_vtoc)->partition[i].perm; \ 3990a55fbb7Slm66018 (vtoc)->v_part[i].p_start = (vd_vtoc)->partition[i].start; \ 4000a55fbb7Slm66018 (vtoc)->v_part[i].p_size = (vd_vtoc)->partition[i].nblocks; \ 4010a55fbb7Slm66018 } \ 4020a55fbb7Slm66018 } 4030a55fbb7Slm66018 4040a55fbb7Slm66018 /* 4050a55fbb7Slm66018 * Copy the contents of a dk_geom struct to the contents of a vd_geom_t 4060a55fbb7Slm66018 */ 4070a55fbb7Slm66018 #define DK_GEOM2VD_GEOM(dk_geom, vd_geom) \ 4080a55fbb7Slm66018 { \ 4090a55fbb7Slm66018 bzero((vd_geom), sizeof (*(vd_geom))); \ 4100a55fbb7Slm66018 (vd_geom)->ncyl = (dk_geom)->dkg_ncyl; \ 4110a55fbb7Slm66018 (vd_geom)->acyl = (dk_geom)->dkg_acyl; \ 4120a55fbb7Slm66018 (vd_geom)->bcyl = (dk_geom)->dkg_bcyl; \ 4130a55fbb7Slm66018 (vd_geom)->nhead = (dk_geom)->dkg_nhead; \ 4140a55fbb7Slm66018 (vd_geom)->nsect = (dk_geom)->dkg_nsect; \ 4150a55fbb7Slm66018 (vd_geom)->intrlv = (dk_geom)->dkg_intrlv; \ 4160a55fbb7Slm66018 (vd_geom)->apc = (dk_geom)->dkg_apc; \ 4170a55fbb7Slm66018 (vd_geom)->rpm = (dk_geom)->dkg_rpm; \ 4180a55fbb7Slm66018 (vd_geom)->pcyl = (dk_geom)->dkg_pcyl; \ 4190a55fbb7Slm66018 (vd_geom)->write_reinstruct = (dk_geom)->dkg_write_reinstruct; \ 4200a55fbb7Slm66018 (vd_geom)->read_reinstruct = (dk_geom)->dkg_read_reinstruct; \ 4210a55fbb7Slm66018 } 4220a55fbb7Slm66018 4230a55fbb7Slm66018 /* 4240a55fbb7Slm66018 * Copy the contents of a vtoc struct to the contents of a vd_vtoc_t 4250a55fbb7Slm66018 */ 4260a55fbb7Slm66018 #define VTOC2VD_VTOC(vtoc, vd_vtoc) \ 4270a55fbb7Slm66018 { \ 4280a55fbb7Slm66018 bzero((vd_vtoc), sizeof (*(vd_vtoc))); \ 4290a55fbb7Slm66018 bcopy((vtoc)->v_volume, (vd_vtoc)->volume_name, \ 4300a55fbb7Slm66018 MIN(sizeof ((vtoc)->v_volume), \ 4310a55fbb7Slm66018 sizeof ((vd_vtoc)->volume_name))); \ 4320a55fbb7Slm66018 bcopy((vtoc)->v_asciilabel, (vd_vtoc)->ascii_label, \ 4330a55fbb7Slm66018 MIN(sizeof ((vtoc)->v_asciilabel), \ 4340a55fbb7Slm66018 sizeof ((vd_vtoc)->ascii_label))); \ 4350a55fbb7Slm66018 (vd_vtoc)->sector_size = (vtoc)->v_sectorsz; \ 4360a55fbb7Slm66018 (vd_vtoc)->num_partitions = (vtoc)->v_nparts; \ 4370a55fbb7Slm66018 for (int i = 0; i < (vtoc)->v_nparts; i++) { \ 4380a55fbb7Slm66018 (vd_vtoc)->partition[i].id_tag = (vtoc)->v_part[i].p_tag; \ 4390a55fbb7Slm66018 (vd_vtoc)->partition[i].perm = (vtoc)->v_part[i].p_flag; \ 4400a55fbb7Slm66018 (vd_vtoc)->partition[i].start = (vtoc)->v_part[i].p_start; \ 4410a55fbb7Slm66018 (vd_vtoc)->partition[i].nblocks = (vtoc)->v_part[i].p_size; \ 4420a55fbb7Slm66018 } \ 4430a55fbb7Slm66018 } 4441ae08745Sheppo 4454bac2208Snarayan /* 4464bac2208Snarayan * Copy the contents of a vd_efi_t to the contents of a dk_efi_t. 4474bac2208Snarayan * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly 4484bac2208Snarayan * initialized prior to using this macro. 4494bac2208Snarayan */ 4504bac2208Snarayan #define VD_EFI2DK_EFI(vd_efi, dk_efi) \ 4514bac2208Snarayan { \ 4524bac2208Snarayan (dk_efi)->dki_lba = (vd_efi)->lba; \ 4534bac2208Snarayan (dk_efi)->dki_length = (vd_efi)->length; \ 4544bac2208Snarayan bcopy((vd_efi)->data, (dk_efi)->dki_data, (dk_efi)->dki_length); \ 4554bac2208Snarayan } 4564bac2208Snarayan 4574bac2208Snarayan /* 4584bac2208Snarayan * Copy the contents of dk_efi_t to the contents of vd_efi_t. 4594bac2208Snarayan * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly 4604bac2208Snarayan * initialized prior to using this macro. 4614bac2208Snarayan */ 4624bac2208Snarayan #define DK_EFI2VD_EFI(dk_efi, vd_efi) \ 4634bac2208Snarayan { \ 4644bac2208Snarayan (vd_efi)->lba = (dk_efi)->dki_lba; \ 4654bac2208Snarayan (vd_efi)->length = (dk_efi)->dki_length; \ 4664bac2208Snarayan bcopy((dk_efi)->dki_data, (vd_efi)->data, (vd_efi)->length); \ 4674bac2208Snarayan } 4684bac2208Snarayan 46917cadca8Slm66018 #define VD_MEDIATYPE2DK_MEDIATYPE(mt) \ 47017cadca8Slm66018 ((mt) == VD_MEDIA_FIXED ? DK_FIXED_DISK : \ 47117cadca8Slm66018 (mt) == VD_MEDIA_CD ? DK_CDROM : \ 47217cadca8Slm66018 (mt) == VD_MEDIA_DVD ? DK_DVDROM : \ 47317cadca8Slm66018 DK_UNKNOWN) 47417cadca8Slm66018 47511f54b6eSAlexandre Chartre /* 47611f54b6eSAlexandre Chartre * If the media type returned by the DKIOCGMEDIAINFO ioctl is greater than 47711f54b6eSAlexandre Chartre * 0xFFFF then this is not an optical media and we consider that this is 47811f54b6eSAlexandre Chartre * a fixed media. 47911f54b6eSAlexandre Chartre * 48011f54b6eSAlexandre Chartre * Otherwise, we have an optical media. If this is a SCSI media then the media 48111f54b6eSAlexandre Chartre * type is actually the profile number returned by the SCSI GET CONFIGURATION 48211f54b6eSAlexandre Chartre * command. In that case, the possible values we can have are described in the 48311f54b6eSAlexandre Chartre * SCSI Multi-Media Commands (MMC) documentation. 48411f54b6eSAlexandre Chartre * 48511f54b6eSAlexandre Chartre * Not all SCSI optical media profile numbers are defined in Solaris. However 48611f54b6eSAlexandre Chartre * undefined profiles are essentially different variants of DVD (like Blu-Ray 48711f54b6eSAlexandre Chartre * or HD-DVD). So we consider that any optical media that we can not explicitly 48811f54b6eSAlexandre Chartre * identify is a DVD. 48911f54b6eSAlexandre Chartre */ 49011f54b6eSAlexandre Chartre #define DK_MEDIA_OPTICAL_MAX 0xFFFF 49111f54b6eSAlexandre Chartre 49217cadca8Slm66018 #define DK_MEDIATYPE2VD_MEDIATYPE(mt) \ 49311f54b6eSAlexandre Chartre (((mt) > DK_MEDIA_OPTICAL_MAX)? VD_MEDIA_FIXED : \ 49411f54b6eSAlexandre Chartre (mt) == DK_REMOVABLE_DISK ? VD_MEDIA_FIXED : \ 49517cadca8Slm66018 (mt) == DK_MO_ERASABLE ? VD_MEDIA_FIXED : \ 49617cadca8Slm66018 (mt) == DK_MO_WRITEONCE ? VD_MEDIA_FIXED : \ 49717cadca8Slm66018 (mt) == DK_AS_MO ? VD_MEDIA_FIXED : \ 49817cadca8Slm66018 (mt) == DK_CDROM ? VD_MEDIA_CD : \ 49917cadca8Slm66018 (mt) == DK_CDR ? VD_MEDIA_CD : \ 50017cadca8Slm66018 (mt) == DK_CDRW ? VD_MEDIA_CD : \ 50111f54b6eSAlexandre Chartre VD_MEDIA_DVD) 50217cadca8Slm66018 5034bac2208Snarayan /* 5044bac2208Snarayan * Hooks for EFI support 5054bac2208Snarayan */ 5064bac2208Snarayan 5074bac2208Snarayan /* 5084bac2208Snarayan * The EFI alloc_and_read() function will use some ioctls to get EFI data 5094bac2208Snarayan * but the device reference we will use is different depending if the command 5104bac2208Snarayan * is issued from the vDisk server side (vds) or from the vDisk client side 511edcc0754Sachartre * (vdc). The vd_efi_dev structure is filled by vdc/vds to indicate the ioctl 512edcc0754Sachartre * function to call back and to provide information about the virtual disk. 5134bac2208Snarayan */ 514edcc0754Sachartre typedef int (*vd_efi_ioctl_func)(void *, int, uintptr_t); 5154bac2208Snarayan 516edcc0754Sachartre typedef struct vd_efi_dev { 517edcc0754Sachartre void *vdisk; /* opaque pointer to the vdisk */ 518edcc0754Sachartre size_t block_size; /* vdisk block size */ 519edcc0754Sachartre size_t disk_size; /* vdisk size in blocks */ 520edcc0754Sachartre vd_efi_ioctl_func vdisk_ioctl; /* vdisk ioctl function */ 521edcc0754Sachartre } vd_efi_dev_t; 522edcc0754Sachartre 52365908c77Syu, larry liu - Sun Microsystems - Beijing China #define VDSK_EFI_DEV_SET(efi_dev, vdsk, ioctl, bsize, dsize) \ 524edcc0754Sachartre (efi_dev).vdisk = vdsk; \ 525edcc0754Sachartre (efi_dev).vdisk_ioctl = ioctl; \ 52665908c77Syu, larry liu - Sun Microsystems - Beijing China (efi_dev).block_size = bsize; \ 52765908c77Syu, larry liu - Sun Microsystems - Beijing China (efi_dev).disk_size = dsize; 528edcc0754Sachartre 529edcc0754Sachartre 530edcc0754Sachartre int vd_efi_alloc_and_read(vd_efi_dev_t *dev, efi_gpt_t **gpt, efi_gpe_t **gpe); 531edcc0754Sachartre void vd_efi_free(vd_efi_dev_t *dev, efi_gpt_t *gpt, efi_gpe_t *gpe); 532edcc0754Sachartre 533366a92acSlm66018 /* 534366a92acSlm66018 * Macros to update the I/O statistics kstat consumed by iostat(1m). 535366a92acSlm66018 */ 536366a92acSlm66018 537366a92acSlm66018 /* 538366a92acSlm66018 * Given a pointer to the instance private data of a vDisk driver (vd), 539366a92acSlm66018 * the type of operation and the number of bytes read/written, this macro 540366a92acSlm66018 * updates the I/O statistics in the kstat. 541366a92acSlm66018 */ 542366a92acSlm66018 #define VD_UPDATE_IO_STATS(vd, op, len) \ 543366a92acSlm66018 { \ 544366a92acSlm66018 ASSERT((vd) != NULL); \ 545366a92acSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 546366a92acSlm66018 ASSERT(((op) == VD_OP_BREAD) || ((op) == VD_OP_BWRITE));\ 547366a92acSlm66018 if ((vd)->io_stats != NULL) { \ 548366a92acSlm66018 kstat_io_t *kip = KSTAT_IO_PTR((vd)->io_stats); \ 549366a92acSlm66018 if ((op) == VD_OP_BREAD) { \ 550366a92acSlm66018 kip->reads++; \ 551366a92acSlm66018 kip->nread += (len); \ 552366a92acSlm66018 } else { \ 553366a92acSlm66018 kip->writes++; \ 554366a92acSlm66018 kip->nwritten += (len); \ 555366a92acSlm66018 } \ 556366a92acSlm66018 } \ 557366a92acSlm66018 } 558366a92acSlm66018 559366a92acSlm66018 /* 560366a92acSlm66018 * These wrapper macros take a pointer to the I/O statistics kstat and 561366a92acSlm66018 * update the queue length statistics. These are 'safe' wrappers which 562366a92acSlm66018 * check to see if the kstat was created when the vDisk instance was 563366a92acSlm66018 * added (i.e. is not NULL). 564366a92acSlm66018 */ 56590e2f9dcSlm66018 #define VD_KSTAT_WAITQ_ENTER(vd) \ 56690e2f9dcSlm66018 if ((vd)->io_stats != NULL) { \ 56790e2f9dcSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 56890e2f9dcSlm66018 kstat_waitq_enter(KSTAT_IO_PTR((vd)->io_stats)); \ 569366a92acSlm66018 } 570366a92acSlm66018 57190e2f9dcSlm66018 #define VD_KSTAT_WAITQ_EXIT(vd) \ 57290e2f9dcSlm66018 if ((vd)->io_stats != NULL) { \ 57390e2f9dcSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 57490e2f9dcSlm66018 kstat_waitq_exit(KSTAT_IO_PTR((vd)->io_stats)); \ 575366a92acSlm66018 } 576366a92acSlm66018 57790e2f9dcSlm66018 #define VD_KSTAT_WAITQ_TO_RUNQ(vd) \ 57890e2f9dcSlm66018 if ((vd)->io_stats != NULL) { \ 57990e2f9dcSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 58090e2f9dcSlm66018 kstat_waitq_to_runq(KSTAT_IO_PTR((vd)->io_stats)); \ 581366a92acSlm66018 } 582366a92acSlm66018 583*ca6d1280SAlexandre Chartre #define VD_KSTAT_RUNQ_BACK_TO_WAITQ(vd) \ 584*ca6d1280SAlexandre Chartre if ((vd)->io_stats != NULL) { \ 585*ca6d1280SAlexandre Chartre ASSERT(MUTEX_HELD(&(vd)->lock)); \ 586*ca6d1280SAlexandre Chartre kstat_runq_back_to_waitq(KSTAT_IO_PTR((vd)->io_stats)); \ 587*ca6d1280SAlexandre Chartre } 588*ca6d1280SAlexandre Chartre 58990e2f9dcSlm66018 #define VD_KSTAT_RUNQ_ENTER(vd) \ 59090e2f9dcSlm66018 if ((vd)->io_stats != NULL) { \ 59190e2f9dcSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 59290e2f9dcSlm66018 kstat_runq_enter(KSTAT_IO_PTR((vd)->io_stats)); \ 593366a92acSlm66018 } 594366a92acSlm66018 59590e2f9dcSlm66018 #define VD_KSTAT_RUNQ_EXIT(vd) \ 59690e2f9dcSlm66018 if ((vd)->io_stats != NULL) { \ 59790e2f9dcSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 59890e2f9dcSlm66018 kstat_runq_exit(KSTAT_IO_PTR((vd)->io_stats)); \ 599366a92acSlm66018 } 600366a92acSlm66018 601366a92acSlm66018 /* 602366a92acSlm66018 * Given a pointer to the instance private data of a vDisk driver (vd) and 603366a92acSlm66018 * the name of the error stats entry we wish to update, increment that value 604366a92acSlm66018 */ 605366a92acSlm66018 #define VD_UPDATE_ERR_STATS(vd, stat_entry) \ 606366a92acSlm66018 { \ 607366a92acSlm66018 ASSERT((vd) != NULL); \ 608366a92acSlm66018 ASSERT(MUTEX_HELD(&(vd)->lock)); \ 609366a92acSlm66018 if ((vd)->err_stats != NULL) { \ 610366a92acSlm66018 vd_err_stats_t *stp; \ 611366a92acSlm66018 stp = (vd_err_stats_t *)(vd)->err_stats->ks_data; \ 612366a92acSlm66018 stp->stat_entry.value.ui32++; \ 613366a92acSlm66018 } \ 614366a92acSlm66018 } 615366a92acSlm66018 616366a92acSlm66018 /* Structure to record vDisk error statistics */ 617366a92acSlm66018 typedef struct vd_err_stats { 618366a92acSlm66018 struct kstat_named vd_softerrs; /* Softerrs */ 619366a92acSlm66018 struct kstat_named vd_transerrs; /* Transport errs */ 620366a92acSlm66018 struct kstat_named vd_protoerrs; /* VIO Protocol errs */ 621366a92acSlm66018 struct kstat_named vd_vid; /* Vendor ID */ 622366a92acSlm66018 struct kstat_named vd_pid; /* Product ID */ 623366a92acSlm66018 struct kstat_named vd_capacity; /* Capacity of the disk */ 624366a92acSlm66018 } vd_err_stats_t; 625366a92acSlm66018 6261ae08745Sheppo 6271ae08745Sheppo #ifdef __cplusplus 6281ae08745Sheppo } 6291ae08745Sheppo #endif 6301ae08745Sheppo 6311ae08745Sheppo #endif /* _VDSK_COMMON_H */ 632