nvme.h revision 248739
1240616Sjimharris/*- 2240616Sjimharris * Copyright (C) 2012 Intel Corporation 3240616Sjimharris * All rights reserved. 4240616Sjimharris * 5240616Sjimharris * Redistribution and use in source and binary forms, with or without 6240616Sjimharris * modification, are permitted provided that the following conditions 7240616Sjimharris * are met: 8240616Sjimharris * 1. Redistributions of source code must retain the above copyright 9240616Sjimharris * notice, this list of conditions and the following disclaimer. 10240616Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 11240616Sjimharris * notice, this list of conditions and the following disclaimer in the 12240616Sjimharris * documentation and/or other materials provided with the distribution. 13240616Sjimharris * 14240616Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15240616Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16240616Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17240616Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18240616Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240616Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20240616Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21240616Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22240616Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23240616Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24240616Sjimharris * SUCH DAMAGE. 25240616Sjimharris * 26240616Sjimharris * $FreeBSD: head/sys/dev/nvme/nvme.h 248739 2013-03-26 18:42:05Z jimharris $ 27240616Sjimharris */ 28240616Sjimharris 29240616Sjimharris#ifndef __NVME_H__ 30240616Sjimharris#define __NVME_H__ 31240616Sjimharris 32240616Sjimharris#ifdef _KERNEL 33240616Sjimharris#include <sys/types.h> 34240616Sjimharris#endif 35240616Sjimharris 36240616Sjimharris#define NVME_IDENTIFY_CONTROLLER _IOR('n', 0, struct nvme_controller_data) 37240616Sjimharris#define NVME_IDENTIFY_NAMESPACE _IOR('n', 1, struct nvme_namespace_data) 38240616Sjimharris#define NVME_IO_TEST _IOWR('n', 2, struct nvme_io_test) 39240616Sjimharris#define NVME_BIO_TEST _IOWR('n', 4, struct nvme_io_test) 40240616Sjimharris 41240616Sjimharris/* 42240616Sjimharris * Use to mark a command to apply to all namespaces, or to retrieve global 43240616Sjimharris * log pages. 44240616Sjimharris */ 45240616Sjimharris#define NVME_GLOBAL_NAMESPACE_TAG ((uint32_t)0xFFFFFFFF) 46240616Sjimharris 47240616Sjimharrisunion cap_lo_register { 48240616Sjimharris uint32_t raw; 49240616Sjimharris struct { 50240616Sjimharris /** maximum queue entries supported */ 51240616Sjimharris uint32_t mqes : 16; 52240616Sjimharris 53240616Sjimharris /** contiguous queues required */ 54240616Sjimharris uint32_t cqr : 1; 55240616Sjimharris 56240616Sjimharris /** arbitration mechanism supported */ 57240616Sjimharris uint32_t ams : 2; 58240616Sjimharris 59240616Sjimharris uint32_t reserved1 : 5; 60240616Sjimharris 61240616Sjimharris /** timeout */ 62240616Sjimharris uint32_t to : 8; 63240616Sjimharris } bits __packed; 64240616Sjimharris} __packed; 65240616Sjimharris 66240616Sjimharrisunion cap_hi_register { 67240616Sjimharris uint32_t raw; 68240616Sjimharris struct { 69240616Sjimharris /** doorbell stride */ 70240616Sjimharris uint32_t dstrd : 4; 71240616Sjimharris 72240616Sjimharris uint32_t reserved3 : 1; 73240616Sjimharris 74240616Sjimharris /** command sets supported */ 75240616Sjimharris uint32_t css_nvm : 1; 76240616Sjimharris 77240616Sjimharris uint32_t css_reserved : 3; 78240616Sjimharris uint32_t reserved2 : 7; 79240616Sjimharris 80240616Sjimharris /** memory page size minimum */ 81240616Sjimharris uint32_t mpsmin : 4; 82240616Sjimharris 83240616Sjimharris /** memory page size maximum */ 84240616Sjimharris uint32_t mpsmax : 4; 85240616Sjimharris 86240616Sjimharris uint32_t reserved1 : 8; 87240616Sjimharris } bits __packed; 88240616Sjimharris} __packed; 89240616Sjimharris 90240616Sjimharrisunion cc_register { 91240616Sjimharris uint32_t raw; 92240616Sjimharris struct { 93240616Sjimharris /** enable */ 94240616Sjimharris uint32_t en : 1; 95240616Sjimharris 96240616Sjimharris uint32_t reserved1 : 3; 97240616Sjimharris 98240616Sjimharris /** i/o command set selected */ 99240616Sjimharris uint32_t css : 3; 100240616Sjimharris 101240616Sjimharris /** memory page size */ 102240616Sjimharris uint32_t mps : 4; 103240616Sjimharris 104240616Sjimharris /** arbitration mechanism selected */ 105240616Sjimharris uint32_t ams : 3; 106240616Sjimharris 107240616Sjimharris /** shutdown notification */ 108240616Sjimharris uint32_t shn : 2; 109240616Sjimharris 110240616Sjimharris /** i/o submission queue entry size */ 111240616Sjimharris uint32_t iosqes : 4; 112240616Sjimharris 113240616Sjimharris /** i/o completion queue entry size */ 114240616Sjimharris uint32_t iocqes : 4; 115240616Sjimharris 116240616Sjimharris uint32_t reserved2 : 8; 117240616Sjimharris } bits __packed; 118240616Sjimharris} __packed; 119240616Sjimharris 120240616Sjimharrisenum shn_value { 121240616Sjimharris NVME_SHN_NORMAL = 0x1, 122240616Sjimharris NVME_SHN_ABRUPT = 0x2, 123240616Sjimharris}; 124240616Sjimharris 125240616Sjimharrisunion csts_register { 126240616Sjimharris uint32_t raw; 127240616Sjimharris struct { 128240616Sjimharris /** ready */ 129240616Sjimharris uint32_t rdy : 1; 130240616Sjimharris 131240616Sjimharris /** controller fatal status */ 132240616Sjimharris uint32_t cfs : 1; 133240616Sjimharris 134240616Sjimharris /** shutdown status */ 135240616Sjimharris uint32_t shst : 2; 136240616Sjimharris 137240616Sjimharris uint32_t reserved1 : 28; 138240616Sjimharris } bits __packed; 139240616Sjimharris} __packed; 140240616Sjimharris 141240616Sjimharrisenum shst_value { 142240616Sjimharris NVME_SHST_NORMAL = 0x0, 143240616Sjimharris NVME_SHST_OCCURRING = 0x1, 144240616Sjimharris NVME_SHST_COMPLETE = 0x2, 145240616Sjimharris}; 146240616Sjimharris 147240616Sjimharrisunion aqa_register { 148240616Sjimharris uint32_t raw; 149240616Sjimharris struct { 150240616Sjimharris /** admin submission queue size */ 151240616Sjimharris uint32_t asqs : 12; 152240616Sjimharris 153240616Sjimharris uint32_t reserved1 : 4; 154240616Sjimharris 155240616Sjimharris /** admin completion queue size */ 156240616Sjimharris uint32_t acqs : 12; 157240616Sjimharris 158240616Sjimharris uint32_t reserved2 : 4; 159240616Sjimharris } bits __packed; 160240616Sjimharris} __packed; 161240616Sjimharris 162240616Sjimharrisstruct nvme_registers 163240616Sjimharris{ 164240616Sjimharris /** controller capabilities */ 165240616Sjimharris union cap_lo_register cap_lo; 166240616Sjimharris union cap_hi_register cap_hi; 167240616Sjimharris 168240616Sjimharris uint32_t vs; /* version */ 169240616Sjimharris uint32_t intms; /* interrupt mask set */ 170240616Sjimharris uint32_t intmc; /* interrupt mask clear */ 171240616Sjimharris 172240616Sjimharris /** controller configuration */ 173240616Sjimharris union cc_register cc; 174240616Sjimharris 175240616Sjimharris uint32_t reserved1; 176240616Sjimharris uint32_t csts; /* controller status */ 177240616Sjimharris uint32_t reserved2; 178240616Sjimharris 179240616Sjimharris /** admin queue attributes */ 180240616Sjimharris union aqa_register aqa; 181240616Sjimharris 182240616Sjimharris uint64_t asq; /* admin submission queue base addr */ 183240616Sjimharris uint64_t acq; /* admin completion queue base addr */ 184240616Sjimharris uint32_t reserved3[0x3f2]; 185240616Sjimharris 186240616Sjimharris struct { 187240616Sjimharris uint32_t sq_tdbl; /* submission queue tail doorbell */ 188240616Sjimharris uint32_t cq_hdbl; /* completion queue head doorbell */ 189240616Sjimharris } doorbell[1] __packed; 190240616Sjimharris} __packed; 191240616Sjimharris 192240616Sjimharrisstruct nvme_command 193240616Sjimharris{ 194240616Sjimharris /* dword 0 */ 195240616Sjimharris uint16_t opc : 8; /* opcode */ 196240616Sjimharris uint16_t fuse : 2; /* fused operation */ 197240616Sjimharris uint16_t rsvd1 : 6; 198240616Sjimharris uint16_t cid; /* command identifier */ 199240616Sjimharris 200240616Sjimharris /* dword 1 */ 201240616Sjimharris uint32_t nsid; /* namespace identifier */ 202240616Sjimharris 203240616Sjimharris /* dword 2-3 */ 204240616Sjimharris uint32_t rsvd2; 205240616Sjimharris uint32_t rsvd3; 206240616Sjimharris 207240616Sjimharris /* dword 4-5 */ 208240616Sjimharris uint64_t mptr; /* metadata pointer */ 209240616Sjimharris 210240616Sjimharris /* dword 6-7 */ 211240616Sjimharris uint64_t prp1; /* prp entry 1 */ 212240616Sjimharris 213240616Sjimharris /* dword 8-9 */ 214240616Sjimharris uint64_t prp2; /* prp entry 2 */ 215240616Sjimharris 216240616Sjimharris /* dword 10-15 */ 217240616Sjimharris uint32_t cdw10; /* command-specific */ 218240616Sjimharris uint32_t cdw11; /* command-specific */ 219240616Sjimharris uint32_t cdw12; /* command-specific */ 220240616Sjimharris uint32_t cdw13; /* command-specific */ 221240616Sjimharris uint32_t cdw14; /* command-specific */ 222240616Sjimharris uint32_t cdw15; /* command-specific */ 223240616Sjimharris} __packed; 224240616Sjimharris 225240616Sjimharrisstruct nvme_completion { 226240616Sjimharris 227240616Sjimharris /* dword 0 */ 228240616Sjimharris uint32_t cdw0; /* command-specific */ 229240616Sjimharris 230240616Sjimharris /* dword 1 */ 231240616Sjimharris uint32_t rsvd1; 232240616Sjimharris 233240616Sjimharris /* dword 2 */ 234240616Sjimharris uint16_t sqhd; /* submission queue head pointer */ 235240616Sjimharris uint16_t sqid; /* submission queue identifier */ 236240616Sjimharris 237240616Sjimharris /* dword 3 */ 238240616Sjimharris uint16_t cid; /* command identifier */ 239240616Sjimharris uint16_t p : 1; /* phase tag */ 240240616Sjimharris uint16_t sf_sc : 8; /* status field - status code */ 241240616Sjimharris uint16_t sf_sct : 3; /* status field - status code type */ 242240616Sjimharris uint16_t rsvd2 : 2; 243240616Sjimharris uint16_t sf_m : 1; /* status field - more */ 244240616Sjimharris uint16_t sf_dnr : 1; /* status field - do not retry */ 245240616Sjimharris} __packed; 246240616Sjimharris 247240616Sjimharrisstruct nvme_dsm_range { 248240616Sjimharris 249240616Sjimharris uint32_t attributes; 250240616Sjimharris uint32_t length; 251240616Sjimharris uint64_t starting_lba; 252240616Sjimharris} __packed; 253240616Sjimharris 254240616Sjimharris/* status code types */ 255240616Sjimharrisenum nvme_status_code_type { 256240616Sjimharris NVME_SCT_GENERIC = 0x0, 257240616Sjimharris NVME_SCT_COMMAND_SPECIFIC = 0x1, 258240616Sjimharris NVME_SCT_MEDIA_ERROR = 0x2, 259240616Sjimharris /* 0x3-0x6 - reserved */ 260240616Sjimharris NVME_SCT_VENDOR_SPECIFIC = 0x7, 261240616Sjimharris}; 262240616Sjimharris 263240616Sjimharris/* generic command status codes */ 264240616Sjimharrisenum nvme_generic_command_status_code { 265240616Sjimharris NVME_SC_SUCCESS = 0x00, 266240616Sjimharris NVME_SC_INVALID_OPCODE = 0x01, 267240616Sjimharris NVME_SC_INVALID_FIELD = 0x02, 268240616Sjimharris NVME_SC_COMMAND_ID_CONFLICT = 0x03, 269240616Sjimharris NVME_SC_DATA_TRANSFER_ERROR = 0x04, 270240616Sjimharris NVME_SC_ABORTED_POWER_LOSS = 0x05, 271240616Sjimharris NVME_SC_INTERNAL_DEVICE_ERROR = 0x06, 272240616Sjimharris NVME_SC_ABORTED_BY_REQUEST = 0x07, 273240616Sjimharris NVME_SC_ABORTED_SQ_DELETION = 0x08, 274240616Sjimharris NVME_SC_ABORTED_FAILED_FUSED = 0x09, 275240616Sjimharris NVME_SC_ABORTED_MISSING_FUSED = 0x0a, 276240616Sjimharris NVME_SC_INVALID_NAMESPACE_OR_FORMAT = 0x0b, 277240616Sjimharris NVME_SC_COMMAND_SEQUENCE_ERROR = 0x0c, 278240616Sjimharris 279240616Sjimharris NVME_SC_LBA_OUT_OF_RANGE = 0x80, 280240616Sjimharris NVME_SC_CAPACITY_EXCEEDED = 0x81, 281240616Sjimharris NVME_SC_NAMESPACE_NOT_READY = 0x82, 282240616Sjimharris}; 283240616Sjimharris 284240616Sjimharris/* command specific status codes */ 285240616Sjimharrisenum nvme_command_specific_status_code { 286240616Sjimharris NVME_SC_COMPLETION_QUEUE_INVALID = 0x00, 287240616Sjimharris NVME_SC_INVALID_QUEUE_IDENTIFIER = 0x01, 288240616Sjimharris NVME_SC_MAXIMUM_QUEUE_SIZE_EXCEEDED = 0x02, 289240616Sjimharris NVME_SC_ABORT_COMMAND_LIMIT_EXCEEDED = 0x03, 290240616Sjimharris /* 0x04 - reserved */ 291240616Sjimharris NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED = 0x05, 292240616Sjimharris NVME_SC_INVALID_FIRMWARE_SLOT = 0x06, 293240616Sjimharris NVME_SC_INVALID_FIRMWARE_IMAGE = 0x07, 294240616Sjimharris NVME_SC_INVALID_INTERRUPT_VECTOR = 0x08, 295240616Sjimharris NVME_SC_INVALID_LOG_PAGE = 0x09, 296240616Sjimharris NVME_SC_INVALID_FORMAT = 0x0a, 297240616Sjimharris NVME_SC_FIRMWARE_REQUIRES_RESET = 0x0b, 298240616Sjimharris 299240616Sjimharris NVME_SC_CONFLICTING_ATTRIBUTES = 0x80, 300240616Sjimharris NVME_SC_INVALID_PROTECTION_INFO = 0x81, 301240616Sjimharris NVME_SC_ATTEMPTED_WRITE_TO_RO_PAGE = 0x82, 302240616Sjimharris}; 303240616Sjimharris 304240616Sjimharris/* media error status codes */ 305240616Sjimharrisenum nvme_media_error_status_code { 306240616Sjimharris NVME_SC_WRITE_FAULTS = 0x80, 307240616Sjimharris NVME_SC_UNRECOVERED_READ_ERROR = 0x81, 308240616Sjimharris NVME_SC_GUARD_CHECK_ERROR = 0x82, 309240616Sjimharris NVME_SC_APPLICATION_TAG_CHECK_ERROR = 0x83, 310240616Sjimharris NVME_SC_REFERENCE_TAG_CHECK_ERROR = 0x84, 311240616Sjimharris NVME_SC_COMPARE_FAILURE = 0x85, 312240616Sjimharris NVME_SC_ACCESS_DENIED = 0x86, 313240616Sjimharris}; 314240616Sjimharris 315240616Sjimharris/* admin opcodes */ 316240616Sjimharrisenum nvme_admin_opcode { 317240616Sjimharris NVME_OPC_DELETE_IO_SQ = 0x00, 318240616Sjimharris NVME_OPC_CREATE_IO_SQ = 0x01, 319240616Sjimharris NVME_OPC_GET_LOG_PAGE = 0x02, 320240616Sjimharris /* 0x03 - reserved */ 321240616Sjimharris NVME_OPC_DELETE_IO_CQ = 0x04, 322240616Sjimharris NVME_OPC_CREATE_IO_CQ = 0x05, 323240616Sjimharris NVME_OPC_IDENTIFY = 0x06, 324240616Sjimharris /* 0x07 - reserved */ 325240616Sjimharris NVME_OPC_ABORT = 0x08, 326240616Sjimharris NVME_OPC_SET_FEATURES = 0x09, 327240616Sjimharris NVME_OPC_GET_FEATURES = 0x0a, 328240616Sjimharris /* 0x0b - reserved */ 329240616Sjimharris NVME_OPC_ASYNC_EVENT_REQUEST = 0x0c, 330240616Sjimharris /* 0x0d-0x0f - reserved */ 331240616Sjimharris NVME_OPC_FIRMWARE_ACTIVATE = 0x10, 332240616Sjimharris NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD = 0x11, 333240616Sjimharris 334240616Sjimharris NVME_OPC_FORMAT_NVM = 0x80, 335240616Sjimharris NVME_OPC_SECURITY_SEND = 0x81, 336240616Sjimharris NVME_OPC_SECURITY_RECEIVE = 0x82, 337240616Sjimharris}; 338240616Sjimharris 339240616Sjimharris/* nvme nvm opcodes */ 340240616Sjimharrisenum nvme_nvm_opcode { 341240616Sjimharris NVME_OPC_FLUSH = 0x00, 342240616Sjimharris NVME_OPC_WRITE = 0x01, 343240616Sjimharris NVME_OPC_READ = 0x02, 344240616Sjimharris /* 0x03 - reserved */ 345240616Sjimharris NVME_OPC_WRITE_UNCORRECTABLE = 0x04, 346240616Sjimharris NVME_OPC_COMPARE = 0x05, 347240616Sjimharris /* 0x06-0x07 - reserved */ 348240616Sjimharris NVME_OPC_DATASET_MANAGEMENT = 0x09, 349240616Sjimharris}; 350240616Sjimharris 351240616Sjimharrisenum nvme_feature { 352240616Sjimharris /* 0x00 - reserved */ 353240616Sjimharris NVME_FEAT_ARBITRATION = 0x01, 354240616Sjimharris NVME_FEAT_POWER_MANAGEMENT = 0x02, 355240616Sjimharris NVME_FEAT_LBA_RANGE_TYPE = 0x03, 356240616Sjimharris NVME_FEAT_TEMPERATURE_THRESHOLD = 0x04, 357240616Sjimharris NVME_FEAT_ERROR_RECOVERY = 0x05, 358240616Sjimharris NVME_FEAT_VOLATILE_WRITE_CACHE = 0x06, 359240616Sjimharris NVME_FEAT_NUMBER_OF_QUEUES = 0x07, 360240616Sjimharris NVME_FEAT_INTERRUPT_COALESCING = 0x08, 361240616Sjimharris NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION = 0x09, 362240616Sjimharris NVME_FEAT_WRITE_ATOMICITY = 0x0A, 363248737Sjimharris NVME_FEAT_ASYNC_EVENT_CONFIGURATION = 0x0B, 364240616Sjimharris /* 0x0C-0x7F - reserved */ 365240616Sjimharris NVME_FEAT_SOFTWARE_PROGRESS_MARKER = 0x80, 366240616Sjimharris /* 0x81-0xBF - command set specific (reserved) */ 367240616Sjimharris /* 0xC0-0xFF - vendor specific */ 368240616Sjimharris}; 369240616Sjimharris 370240616Sjimharrisenum nvme_dsm_attribute { 371240616Sjimharris NVME_DSM_ATTR_INTEGRAL_READ = 0x1, 372240616Sjimharris NVME_DSM_ATTR_INTEGRAL_WRITE = 0x2, 373240616Sjimharris NVME_DSM_ATTR_DEALLOCATE = 0x4, 374240616Sjimharris}; 375240616Sjimharris 376240616Sjimharrisstruct nvme_controller_data { 377240616Sjimharris 378240616Sjimharris /* bytes 0-255: controller capabilities and features */ 379240616Sjimharris 380240616Sjimharris /** pci vendor id */ 381240616Sjimharris uint16_t vid; 382240616Sjimharris 383240616Sjimharris /** pci subsystem vendor id */ 384240616Sjimharris uint16_t ssvid; 385240616Sjimharris 386240616Sjimharris /** serial number */ 387240616Sjimharris int8_t sn[20]; 388240616Sjimharris 389240616Sjimharris /** model number */ 390240616Sjimharris int8_t mn[40]; 391240616Sjimharris 392240616Sjimharris /** firmware revision */ 393240616Sjimharris uint8_t fr[8]; 394240616Sjimharris 395240616Sjimharris /** recommended arbitration burst */ 396240616Sjimharris uint8_t rab; 397240616Sjimharris 398240616Sjimharris /** ieee oui identifier */ 399240616Sjimharris uint8_t ieee[3]; 400240616Sjimharris 401240616Sjimharris /** multi-interface capabilities */ 402240616Sjimharris uint8_t mic; 403240616Sjimharris 404240616Sjimharris /** maximum data transfer size */ 405240616Sjimharris uint8_t mdts; 406240616Sjimharris 407240616Sjimharris uint8_t reserved1[178]; 408240616Sjimharris 409240616Sjimharris /* bytes 256-511: admin command set attributes */ 410240616Sjimharris 411240616Sjimharris /** optional admin command support */ 412240616Sjimharris struct { 413240616Sjimharris /* supports security send/receive commands */ 414240616Sjimharris uint16_t security : 1; 415240616Sjimharris 416240616Sjimharris /* supports format nvm command */ 417240616Sjimharris uint16_t format : 1; 418240616Sjimharris 419240616Sjimharris /* supports firmware activate/download commands */ 420240616Sjimharris uint16_t firmware : 1; 421240616Sjimharris 422240616Sjimharris uint16_t oacs_rsvd : 13; 423240616Sjimharris } __packed oacs; 424240616Sjimharris 425240616Sjimharris /** abort command limit */ 426240616Sjimharris uint8_t acl; 427240616Sjimharris 428240616Sjimharris /** asynchronous event request limit */ 429240616Sjimharris uint8_t aerl; 430240616Sjimharris 431240616Sjimharris /** firmware updates */ 432240616Sjimharris struct { 433240616Sjimharris /* first slot is read-only */ 434240616Sjimharris uint8_t slot1_ro : 1; 435240616Sjimharris 436240616Sjimharris /* number of firmware slots */ 437240616Sjimharris uint8_t num_slots : 3; 438240616Sjimharris 439240616Sjimharris uint8_t frmw_rsvd : 4; 440240616Sjimharris } __packed frmw; 441240616Sjimharris 442240616Sjimharris /** log page attributes */ 443240616Sjimharris struct { 444240616Sjimharris /* per namespace smart/health log page */ 445240616Sjimharris uint8_t ns_smart : 1; 446240616Sjimharris 447240616Sjimharris uint8_t lpa_rsvd : 7; 448240616Sjimharris } __packed lpa; 449240616Sjimharris 450240616Sjimharris /** error log page entries */ 451240616Sjimharris uint8_t elpe; 452240616Sjimharris 453240616Sjimharris /** number of power states supported */ 454240616Sjimharris uint8_t npss; 455240616Sjimharris 456240616Sjimharris /** admin vendor specific command configuration */ 457240616Sjimharris struct { 458240616Sjimharris /* admin vendor specific commands use spec format */ 459240616Sjimharris uint8_t spec_format : 1; 460240616Sjimharris 461240616Sjimharris uint8_t avscc_rsvd : 7; 462240616Sjimharris } __packed avscc; 463240616Sjimharris 464240616Sjimharris uint8_t reserved2[247]; 465240616Sjimharris 466240616Sjimharris /* bytes 512-703: nvm command set attributes */ 467240616Sjimharris 468240616Sjimharris /** submission queue entry size */ 469240616Sjimharris struct { 470240616Sjimharris uint8_t min : 4; 471240616Sjimharris uint8_t max : 4; 472240616Sjimharris } __packed sqes; 473240616Sjimharris 474240616Sjimharris /** completion queue entry size */ 475240616Sjimharris struct { 476240616Sjimharris uint8_t min : 4; 477240616Sjimharris uint8_t max : 4; 478240616Sjimharris } __packed cqes; 479240616Sjimharris 480240616Sjimharris uint8_t reserved3[2]; 481240616Sjimharris 482240616Sjimharris /** number of namespaces */ 483240616Sjimharris uint32_t nn; 484240616Sjimharris 485240616Sjimharris /** optional nvm command support */ 486240616Sjimharris struct { 487240616Sjimharris uint16_t compare : 1; 488240616Sjimharris uint16_t write_unc : 1; 489240616Sjimharris uint16_t dsm: 1; 490240616Sjimharris uint16_t reserved: 13; 491240616Sjimharris } __packed oncs; 492240616Sjimharris 493240616Sjimharris /** fused operation support */ 494240616Sjimharris uint16_t fuses; 495240616Sjimharris 496240616Sjimharris /** format nvm attributes */ 497240616Sjimharris uint8_t fna; 498240616Sjimharris 499240616Sjimharris /** volatile write cache */ 500240616Sjimharris struct { 501240616Sjimharris uint8_t present : 1; 502240616Sjimharris uint8_t reserved : 7; 503240616Sjimharris } __packed vwc; 504240616Sjimharris 505240616Sjimharris /* TODO: flesh out remaining nvm command set attributes */ 506240616Sjimharris uint8_t reserved4[178]; 507240616Sjimharris 508240616Sjimharris /* bytes 704-2047: i/o command set attributes */ 509240616Sjimharris uint8_t reserved5[1344]; 510240616Sjimharris 511240616Sjimharris /* bytes 2048-3071: power state descriptors */ 512240616Sjimharris uint8_t reserved6[1024]; 513240616Sjimharris 514240616Sjimharris /* bytes 3072-4095: vendor specific */ 515240616Sjimharris uint8_t reserved7[1024]; 516240671Sjimharris} __packed __aligned(4); 517240616Sjimharris 518240616Sjimharrisstruct nvme_namespace_data { 519240616Sjimharris 520240616Sjimharris /** namespace size */ 521240616Sjimharris uint64_t nsze; 522240616Sjimharris 523240616Sjimharris /** namespace capacity */ 524240616Sjimharris uint64_t ncap; 525240616Sjimharris 526240616Sjimharris /** namespace utilization */ 527240616Sjimharris uint64_t nuse; 528240616Sjimharris 529240616Sjimharris /** namespace features */ 530240616Sjimharris struct { 531240616Sjimharris /** thin provisioning */ 532240616Sjimharris uint8_t thin_prov : 1; 533240616Sjimharris uint8_t reserved1 : 7; 534240616Sjimharris } __packed nsfeat; 535240616Sjimharris 536240616Sjimharris /** number of lba formats */ 537240616Sjimharris uint8_t nlbaf; 538240616Sjimharris 539240616Sjimharris /** formatted lba size */ 540240616Sjimharris struct { 541240616Sjimharris uint8_t format : 4; 542240616Sjimharris uint8_t extended : 1; 543240616Sjimharris uint8_t reserved2 : 3; 544240616Sjimharris } __packed flbas; 545240616Sjimharris 546240616Sjimharris /** metadata capabilities */ 547240616Sjimharris struct { 548240616Sjimharris /* metadata can be transferred as part of data prp list */ 549240616Sjimharris uint8_t extended : 1; 550240616Sjimharris 551240616Sjimharris /* metadata can be transferred with separate metadata pointer */ 552240616Sjimharris uint8_t pointer : 1; 553240616Sjimharris 554240616Sjimharris uint8_t reserved3 : 6; 555240616Sjimharris } __packed mc; 556240616Sjimharris 557240616Sjimharris /** end-to-end data protection capabilities */ 558240616Sjimharris struct { 559240616Sjimharris /* protection information type 1 */ 560240616Sjimharris uint8_t pit1 : 1; 561240616Sjimharris 562240616Sjimharris /* protection information type 2 */ 563240616Sjimharris uint8_t pit2 : 1; 564240616Sjimharris 565240616Sjimharris /* protection information type 3 */ 566240616Sjimharris uint8_t pit3 : 1; 567240616Sjimharris 568240616Sjimharris /* first eight bytes of metadata */ 569240616Sjimharris uint8_t md_start : 1; 570240616Sjimharris 571240616Sjimharris /* last eight bytes of metadata */ 572240616Sjimharris uint8_t md_end : 1; 573240616Sjimharris } __packed dpc; 574240616Sjimharris 575240616Sjimharris /** end-to-end data protection type settings */ 576240616Sjimharris struct { 577240616Sjimharris /* protection information type */ 578240616Sjimharris uint8_t pit : 3; 579240616Sjimharris 580240616Sjimharris /* 1 == protection info transferred at start of metadata */ 581240616Sjimharris /* 0 == protection info transferred at end of metadata */ 582240616Sjimharris uint8_t md_start : 1; 583240616Sjimharris 584240616Sjimharris uint8_t reserved4 : 4; 585240616Sjimharris } __packed dps; 586240616Sjimharris 587240616Sjimharris uint8_t reserved5[98]; 588240616Sjimharris 589240616Sjimharris /** lba format support */ 590240616Sjimharris struct { 591240616Sjimharris /** metadata size */ 592240616Sjimharris uint32_t ms : 16; 593240616Sjimharris 594240616Sjimharris /** lba data size */ 595240616Sjimharris uint32_t lbads : 8; 596240616Sjimharris 597240616Sjimharris /** relative performance */ 598240616Sjimharris uint32_t rp : 2; 599240616Sjimharris 600240616Sjimharris uint32_t reserved6 : 6; 601240616Sjimharris } __packed lbaf[16]; 602240616Sjimharris 603240616Sjimharris uint8_t reserved6[192]; 604240616Sjimharris 605240616Sjimharris uint8_t vendor_specific[3712]; 606240671Sjimharris} __packed __aligned(4); 607240616Sjimharris 608240616Sjimharrisenum nvme_log_page { 609240616Sjimharris 610240616Sjimharris /* 0x00 - reserved */ 611240616Sjimharris NVME_LOG_ERROR = 0x01, 612240616Sjimharris NVME_LOG_HEALTH_INFORMATION = 0x02, 613240616Sjimharris NVME_LOG_FIRMWARE_SLOT = 0x03, 614240616Sjimharris /* 0x04-0x7F - reserved */ 615240616Sjimharris /* 0x80-0xBF - I/O command set specific */ 616240616Sjimharris /* 0xC0-0xFF - vendor specific */ 617240616Sjimharris}; 618240616Sjimharris 619240616Sjimharrisunion nvme_critical_warning_state { 620240616Sjimharris 621240616Sjimharris uint8_t raw; 622240616Sjimharris 623240616Sjimharris struct { 624240616Sjimharris uint8_t available_spare : 1; 625240616Sjimharris uint8_t temperature : 1; 626240616Sjimharris uint8_t device_reliability : 1; 627240616Sjimharris uint8_t read_only : 1; 628240616Sjimharris uint8_t volatile_memory_backup : 1; 629240616Sjimharris uint8_t reserved : 3; 630240616Sjimharris } __packed bits; 631240616Sjimharris} __packed; 632240616Sjimharris 633240616Sjimharrisstruct nvme_health_information_page { 634240616Sjimharris 635240616Sjimharris union nvme_critical_warning_state critical_warning; 636240616Sjimharris 637240616Sjimharris uint16_t temperature; 638240616Sjimharris uint8_t available_spare; 639240616Sjimharris uint8_t available_spare_threshold; 640240616Sjimharris uint8_t percentage_used; 641240616Sjimharris 642240616Sjimharris uint8_t reserved[26]; 643240616Sjimharris 644240616Sjimharris /* 645240616Sjimharris * Note that the following are 128-bit values, but are 646240616Sjimharris * defined as an array of 2 64-bit values. 647240616Sjimharris */ 648240616Sjimharris /* Data Units Read is always in 512-byte units. */ 649240616Sjimharris uint64_t data_units_read[2]; 650240616Sjimharris /* Data Units Written is always in 512-byte units. */ 651240616Sjimharris uint64_t data_units_written[2]; 652240616Sjimharris /* For NVM command set, this includes Compare commands. */ 653240616Sjimharris uint64_t host_read_commands[2]; 654240616Sjimharris uint64_t host_write_commands[2]; 655240616Sjimharris /* Controller Busy Time is reported in minutes. */ 656240616Sjimharris uint64_t controller_busy_time[2]; 657240616Sjimharris uint64_t power_cycles[2]; 658240616Sjimharris uint64_t power_on_hours[2]; 659240616Sjimharris uint64_t unsafe_shutdowns[2]; 660240616Sjimharris uint64_t media_errors[2]; 661240616Sjimharris uint64_t num_error_info_log_entries[2]; 662240616Sjimharris 663240616Sjimharris uint8_t reserved2[320]; 664240671Sjimharris} __packed __aligned(4); 665240616Sjimharris 666240616Sjimharris#define NVME_TEST_MAX_THREADS 128 667240616Sjimharris 668240616Sjimharrisstruct nvme_io_test { 669240616Sjimharris 670240616Sjimharris enum nvme_nvm_opcode opc; 671240616Sjimharris uint32_t size; 672240616Sjimharris uint32_t time; /* in seconds */ 673240616Sjimharris uint32_t num_threads; 674240616Sjimharris uint32_t flags; 675240616Sjimharris uint32_t io_completed[NVME_TEST_MAX_THREADS]; 676240616Sjimharris}; 677240616Sjimharris 678240616Sjimharrisenum nvme_io_test_flags { 679240616Sjimharris 680240616Sjimharris /* 681240616Sjimharris * Specifies whether dev_refthread/dev_relthread should be 682240616Sjimharris * called during NVME_BIO_TEST. Ignored for other test 683240616Sjimharris * types. 684240616Sjimharris */ 685240616Sjimharris NVME_TEST_FLAG_REFTHREAD = 0x1, 686240616Sjimharris}; 687240616Sjimharris 688240616Sjimharris#ifdef _KERNEL 689240616Sjimharris 690240616Sjimharrisstruct bio; 691240616Sjimharris 692240616Sjimharrisstruct nvme_namespace; 693248738Sjimharrisstruct nvme_controller; 694240616Sjimharrisstruct nvme_consumer; 695240616Sjimharris 696240616Sjimharristypedef void (*nvme_cb_fn_t)(void *, const struct nvme_completion *); 697240616Sjimharris 698248738Sjimharristypedef void *(*nvme_cons_ns_fn_t)(struct nvme_namespace *, void *); 699248738Sjimharristypedef void *(*nvme_cons_ctrlr_fn_t)(struct nvme_controller *); 700248738Sjimharristypedef void (*nvme_cons_async_fn_t)(void *, const struct nvme_completion *); 701248738Sjimharris 702240616Sjimharrisenum nvme_namespace_flags { 703240616Sjimharris NVME_NS_DEALLOCATE_SUPPORTED = 0x1, 704240616Sjimharris NVME_NS_FLUSH_SUPPORTED = 0x2, 705240616Sjimharris}; 706240616Sjimharris 707248739Sjimharris/* Admin functions */ 708248739Sjimharrisvoid nvme_ctrlr_cmd_set_feature(struct nvme_controller *ctrlr, 709248739Sjimharris uint8_t feature, uint32_t cdw11, 710248739Sjimharris void *payload, uint32_t payload_size, 711248739Sjimharris nvme_cb_fn_t cb_fn, void *cb_arg); 712248739Sjimharrisvoid nvme_ctrlr_cmd_get_feature(struct nvme_controller *ctrlr, 713248739Sjimharris uint8_t feature, uint32_t cdw11, 714248739Sjimharris void *payload, uint32_t payload_size, 715248739Sjimharris nvme_cb_fn_t cb_fn, void *cb_arg); 716248739Sjimharris 717240616Sjimharris/* NVM I/O functions */ 718241657Sjimharrisint nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload, 719240616Sjimharris uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn, 720240616Sjimharris void *cb_arg); 721241657Sjimharrisint nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload, 722240616Sjimharris uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn, 723240616Sjimharris void *cb_arg); 724241657Sjimharrisint nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload, 725240616Sjimharris uint8_t num_ranges, nvme_cb_fn_t cb_fn, 726240616Sjimharris void *cb_arg); 727241657Sjimharrisint nvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn, 728240616Sjimharris void *cb_arg); 729240616Sjimharris 730240616Sjimharris/* Registration functions */ 731248738Sjimharrisstruct nvme_consumer * nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, 732248738Sjimharris nvme_cons_ctrlr_fn_t ctrlr_fn, 733248738Sjimharris nvme_cons_async_fn_t async_fn); 734240616Sjimharrisvoid nvme_unregister_consumer(struct nvme_consumer *consumer); 735240616Sjimharris 736248738Sjimharris/* Controller helper functions */ 737248738Sjimharrisdevice_t nvme_ctrlr_get_device(struct nvme_controller *ctrlr); 738248738Sjimharris 739240616Sjimharris/* Namespace helper functions */ 740240616Sjimharrisuint32_t nvme_ns_get_max_io_xfer_size(struct nvme_namespace *ns); 741240616Sjimharrisuint32_t nvme_ns_get_sector_size(struct nvme_namespace *ns); 742240616Sjimharrisuint64_t nvme_ns_get_num_sectors(struct nvme_namespace *ns); 743240616Sjimharrisuint64_t nvme_ns_get_size(struct nvme_namespace *ns); 744240616Sjimharrisuint32_t nvme_ns_get_flags(struct nvme_namespace *ns); 745240616Sjimharrisconst char * nvme_ns_get_serial_number(struct nvme_namespace *ns); 746240616Sjimharrisconst char * nvme_ns_get_model_number(struct nvme_namespace *ns); 747240616Sjimharris 748240616Sjimharrisint nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp, 749240616Sjimharris nvme_cb_fn_t cb_fn); 750240616Sjimharris 751240616Sjimharris#endif /* _KERNEL */ 752240616Sjimharris 753240616Sjimharris#endif /* __NVME_H__ */ 754