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