first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
+2194
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <drivers/nvme.h>
|
||||
#include <lib/blockdev.h>
|
||||
#include <lib/partition.h>
|
||||
#include <lib/syscfg.h>
|
||||
#include <list.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys.h>
|
||||
#include "nvme_blockdev.h"
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
typedef struct nvme_bdev {
|
||||
struct blockdev blockdev;
|
||||
|
||||
int nvme_id;
|
||||
uint32_t nsid;
|
||||
|
||||
uint32_t max_transfer_blocks;
|
||||
uint32_t dummy_blocks;
|
||||
uint32_t blocks_per_virtual_block;
|
||||
|
||||
struct list_node node;
|
||||
} nvme_bdev_t;
|
||||
|
||||
static struct list_node blockdev_list = LIST_INITIAL_VALUE(blockdev_list);
|
||||
|
||||
static nvme_bdev_t *nvme_bdev_for_blockdev(struct blockdev *blockdev)
|
||||
{
|
||||
nvme_bdev_t *entry;
|
||||
|
||||
list_for_every_entry(&blockdev_list, entry, nvme_bdev_t, node) {
|
||||
if (blockdev == &entry->blockdev)
|
||||
return entry;
|
||||
}
|
||||
|
||||
panic("Unknown block device %p", blockdev);
|
||||
}
|
||||
|
||||
static int nvme_bdev_read(struct blockdev *blockdev, void *ptr, block_addr block, uint32_t count)
|
||||
{
|
||||
nvme_bdev_t *nvme_bdev;
|
||||
uint32_t real_count;
|
||||
uint32_t blocks_read;
|
||||
|
||||
nvme_bdev = nvme_bdev_for_blockdev(blockdev);
|
||||
|
||||
// For special namespaces like NVRAM and SysCfg, we lie about the block size
|
||||
block *= nvme_bdev->blocks_per_virtual_block;
|
||||
count *= nvme_bdev->blocks_per_virtual_block;
|
||||
|
||||
real_count = __min(count, nvme_bdev->max_transfer_blocks);
|
||||
|
||||
// Hack for <rdar://problem/18591842> Maui platforms not loading syscfg in iBoot
|
||||
if (nvme_bdev->dummy_blocks > 0) {
|
||||
if (block < nvme_bdev->dummy_blocks) {
|
||||
return -1;
|
||||
}
|
||||
block -= nvme_bdev->dummy_blocks;
|
||||
}
|
||||
|
||||
blocks_read = nvme_read_blocks(nvme_bdev->nvme_id, nvme_bdev->nsid, ptr, block, real_count);
|
||||
|
||||
if ( blocks_read ) {
|
||||
blocks_read /= nvme_bdev->blocks_per_virtual_block;
|
||||
}
|
||||
|
||||
return blocks_read;
|
||||
}
|
||||
|
||||
static int nvme_bdev_write(struct blockdev *blockdev, const void *ptr, block_addr block, uint32_t count)
|
||||
{
|
||||
nvme_bdev_t *nvme_bdev;
|
||||
uint32_t real_count;
|
||||
uint32_t blocks_written;
|
||||
|
||||
nvme_bdev = nvme_bdev_for_blockdev(blockdev);
|
||||
|
||||
// For special namespaces like NVRAM and SysCfg, we lie about the block size
|
||||
block *= nvme_bdev->blocks_per_virtual_block;
|
||||
count *= nvme_bdev->blocks_per_virtual_block;
|
||||
|
||||
real_count = __min(count, nvme_bdev->max_transfer_blocks);
|
||||
|
||||
// Hack for <rdar://problem/18591842> Maui platforms not loading syscfg in iBoot
|
||||
if (nvme_bdev->dummy_blocks > 0) {
|
||||
if (block < nvme_bdev->dummy_blocks) {
|
||||
return -1;
|
||||
}
|
||||
block -= nvme_bdev->dummy_blocks;
|
||||
}
|
||||
|
||||
blocks_written = nvme_write_blocks(nvme_bdev->nvme_id, nvme_bdev->nsid, ptr, block, real_count);
|
||||
|
||||
if ( blocks_written ) {
|
||||
blocks_written /= nvme_bdev->blocks_per_virtual_block;
|
||||
}
|
||||
|
||||
return blocks_written;
|
||||
}
|
||||
|
||||
#if ((PRODUCT_IBEC || PRODUCT_IBOOT) && !RELEASE_BUILD)
|
||||
static int nvme_bdev_erase(struct blockdev *blockdev, off_t offset, uint64_t length)
|
||||
{
|
||||
nvme_bdev_t *nvme_bdev = NULL;
|
||||
uint32_t buffer_length = 0;
|
||||
uint32_t count = 0;
|
||||
uint32_t real_count = 0;
|
||||
uint32_t blocks_written = 0;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t block = 0;
|
||||
|
||||
nvme_bdev = nvme_bdev_for_blockdev(blockdev);
|
||||
|
||||
if((nvme_bdev->nsid != NVME_NAMESPACE_NAND) && (offset > 0))
|
||||
{
|
||||
dprintf(DEBUG_CRITICAL,"erase should start at offset 0 for nsid %d\n", nvme_bdev->nsid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If offset/length is not a multiple of block size, return error.
|
||||
if((offset % (nvme_bdev->blocks_per_virtual_block * NVME_BLOCK_SIZE))
|
||||
|| (length % (nvme_bdev->blocks_per_virtual_block * NVME_BLOCK_SIZE)))
|
||||
{
|
||||
dprintf(DEBUG_CRITICAL,"offset/length is not a multiple of block size %d\n", (nvme_bdev->blocks_per_virtual_block * NVME_BLOCK_SIZE));
|
||||
return -1;
|
||||
}
|
||||
|
||||
block = offset/(nvme_bdev->blocks_per_virtual_block * NVME_BLOCK_SIZE);
|
||||
|
||||
// For special namespaces like NVRAM and SysCfg, we lie about the block size
|
||||
count = length/(nvme_bdev->blocks_per_virtual_block * NVME_BLOCK_SIZE);
|
||||
|
||||
// allocate buffer
|
||||
buffer_length = count * NVME_BLOCK_SIZE;
|
||||
buffer = memalign(buffer_length, NVME_BLOCK_SIZE);
|
||||
|
||||
real_count = __min(count, nvme_bdev->max_transfer_blocks);
|
||||
|
||||
// Hack for <rdar://problem/18591842> Maui platforms not loading syscfg in iBoot
|
||||
if (nvme_bdev->dummy_blocks > 0) {
|
||||
if (block < nvme_bdev->dummy_blocks) {
|
||||
return -1;
|
||||
}
|
||||
block -= nvme_bdev->dummy_blocks;
|
||||
}
|
||||
|
||||
dprintf(DEBUG_CRITICAL,"nvme: erasing %d blocks from LBA %d for nsid %d\n", real_count, block, nvme_bdev->nsid);
|
||||
blocks_written = nvme_write_blocks(nvme_bdev->nvme_id, nvme_bdev->nsid, buffer, block, real_count);
|
||||
|
||||
if ( blocks_written ) {
|
||||
blocks_written /= nvme_bdev->blocks_per_virtual_block;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
return blocks_written;
|
||||
}
|
||||
#endif
|
||||
|
||||
static nvme_bdev_t *nvme_bdev_create(int nvme_id, uint32_t nsid, uint32_t blocks)
|
||||
{
|
||||
char blockdev_name[16];
|
||||
nvme_bdev_t *nvme_bdev;
|
||||
int result;
|
||||
uint32_t block_size;
|
||||
|
||||
nvme_bdev = calloc(1, sizeof(*nvme_bdev));
|
||||
nvme_bdev->nvme_id = nvme_id;
|
||||
nvme_bdev->nsid = nsid;
|
||||
|
||||
nvme_bdev->max_transfer_blocks = nvme_get_max_transfer_blocks(nvme_id);
|
||||
nvme_bdev->blocks_per_virtual_block = 1;
|
||||
|
||||
switch (nsid) {
|
||||
case NVME_NAMESPACE_NAND:
|
||||
snprintf(blockdev_name, sizeof(blockdev_name), "nvme_nand%d", nvme_id);
|
||||
break;
|
||||
|
||||
case NVME_NAMESPACE_FIRMWARE:
|
||||
snprintf(blockdev_name, sizeof(blockdev_name), "nvme_firmware%d", nvme_id);
|
||||
break;
|
||||
|
||||
case NVME_NAMESPACE_NVRAM:
|
||||
strlcpy(blockdev_name, "nvram", sizeof(blockdev_name));
|
||||
|
||||
// S3E doesn't allow NVRAM partition to be written piecewise, so
|
||||
// we lie about the blocksize to upper layers to force writes to
|
||||
// go through in a single operation. Otherwise the blockdev deblocking
|
||||
// code can generate two writes if the source buffer isn't aligned
|
||||
nvme_bdev->blocks_per_virtual_block = 2;
|
||||
break;
|
||||
|
||||
case NVME_NAMESPACE_SYSCFG:
|
||||
snprintf(blockdev_name, sizeof(blockdev_name), "nvme_syscfg%d", nvme_id);
|
||||
|
||||
// Hack for <rdar://problem/18591842> Maui platforms not loading syscfg in iBoot
|
||||
nvme_bdev->blocks_per_virtual_block = 2;
|
||||
nvme_bdev->dummy_blocks = kSysCfgBdevOffset / NVME_BLOCK_SIZE;
|
||||
blocks += nvme_bdev->dummy_blocks;
|
||||
break;
|
||||
|
||||
case NVME_NAMESPACE_EFFACEABLE:
|
||||
snprintf(blockdev_name, sizeof(blockdev_name), "nvme_efface%d", nvme_id);
|
||||
break;
|
||||
|
||||
case NVME_NAMESPACE_PANICLOG:
|
||||
strlcpy(blockdev_name, "paniclog", sizeof(blockdev_name));
|
||||
nvme_bdev->blocks_per_virtual_block = 256;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("Unknown nvme namespace %d", nsid);
|
||||
}
|
||||
|
||||
ASSERT(nvme_id < 100);
|
||||
ASSERT(sizeof(blockdev_name) == sizeof(nvme_bdev->blockdev.name));
|
||||
|
||||
// For special namespaces like NVRAM and SysCfg, we need to lie about
|
||||
// the block size
|
||||
blocks /= nvme_bdev->blocks_per_virtual_block;
|
||||
block_size = NVME_BLOCK_SIZE * nvme_bdev->blocks_per_virtual_block;
|
||||
|
||||
result = construct_blockdev(&nvme_bdev->blockdev, blockdev_name, (uint64_t)blocks * block_size, block_size);
|
||||
|
||||
if (result != 0)
|
||||
panic("Couldn't construct blockdev for namespace %d", nsid);
|
||||
|
||||
blockdev_set_buffer_alignment(&nvme_bdev->blockdev, NVME_BLOCK_SIZE);
|
||||
|
||||
nvme_bdev->blockdev.read_block_hook = &nvme_bdev_read;
|
||||
|
||||
#if !NVME_ENABLE_WRITES
|
||||
if (nsid == NVME_NAMESPACE_NVRAM || nsid == NVME_NAMESPACE_PANICLOG)
|
||||
#endif
|
||||
nvme_bdev->blockdev.write_block_hook = &nvme_bdev_write;
|
||||
|
||||
#if ((PRODUCT_IBOOT || PRODUCT_IBEC) && !RELEASE_BUILD)
|
||||
if (nsid == NVME_NAMESPACE_FIRMWARE)
|
||||
nvme_bdev->blockdev.erase_hook = &nvme_bdev_erase;
|
||||
#endif
|
||||
|
||||
if (register_blockdev(&nvme_bdev->blockdev) != 0) {
|
||||
free(nvme_bdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_tail(&blockdev_list, &nvme_bdev->node);
|
||||
|
||||
return nvme_bdev;
|
||||
}
|
||||
|
||||
static nvme_bdev_t *nvme_bdev_identify_and_create(int nvme_id, uint32_t nsid)
|
||||
{
|
||||
nvme_namespace_params_t params;
|
||||
int result;
|
||||
|
||||
result = nvme_identify_namespace(nvme_id, nsid, ¶ms);
|
||||
if (result != NVME_SUCCESS) {
|
||||
dprintf(DEBUG_SPEW, "nvme: error %d trying to identify nsid %u\n", result, nsid);
|
||||
return NULL;
|
||||
}
|
||||
if (!params.formatted) {
|
||||
dprintf(DEBUG_SPEW, "nvme: nsid %u not formatted\n", nsid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dprintf(DEBUG_INFO, "nvme: Creating blkdev for NSID %d num_blocks %llu\n", nsid, params.num_blocks);
|
||||
return nvme_bdev_create(nvme_id, nsid, params.num_blocks);
|
||||
}
|
||||
|
||||
int nvme_blockdev_init_boot(int nvme_id)
|
||||
{
|
||||
// In boot mode, we can't determine the size of the namespace ahead of time,
|
||||
// so it's up to callers to not read past the end of the device, and the NVMe
|
||||
// driver to return errors as needed
|
||||
#if !WITH_MASS_STORAGE
|
||||
nvme_bdev_create(nvme_id, NVME_NAMESPACE_FIRMWARE, INT_MAX);
|
||||
|
||||
#endif
|
||||
|
||||
// These other ones are only in iBoot/iBEC, where we're less concerned about speed
|
||||
// and thus can do the identify step
|
||||
#if WITH_MASS_STORAGE
|
||||
nvme_bdev_identify_and_create(nvme_id, NVME_NAMESPACE_FIRMWARE);
|
||||
#endif
|
||||
#if WITH_SYSCFG
|
||||
nvme_bdev_identify_and_create(nvme_id, NVME_NAMESPACE_SYSCFG);
|
||||
#endif
|
||||
#if WITH_NVRAM
|
||||
nvme_bdev_identify_and_create(nvme_id, NVME_NAMESPACE_NVRAM);
|
||||
#endif
|
||||
#if WITH_EFFACEABLE
|
||||
nvme_bdev_identify_and_create(nvme_id, NVME_NAMESPACE_EFFACEABLE);
|
||||
#endif
|
||||
nvme_bdev_identify_and_create(nvme_id, NVME_NAMESPACE_PANICLOG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WITH_MASS_STORAGE
|
||||
int nvme_blockdev_init_normal(int nvme_id)
|
||||
{
|
||||
nvme_bdev_t *nvme_nand_bdev;
|
||||
|
||||
nvme_nand_bdev = nvme_bdev_identify_and_create(nvme_id, NVME_NAMESPACE_NAND);
|
||||
|
||||
if (nvme_nand_bdev != NULL) {
|
||||
const char *name = nvme_nand_bdev->blockdev.name;
|
||||
return partition_scan_and_publish_subdevices(name);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#ifndef NVME_BLOCKDEV_H
|
||||
#define NVME_BLOCKDEV_H
|
||||
|
||||
int nvme_blockdev_init_boot(int nvme_id);
|
||||
int nvme_blockdev_init_normal(int nvme_id);
|
||||
|
||||
#endif // NVME_BLOCKDEV_H
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
#ifndef NVME_PROTOCOL_H
|
||||
#define NVME_PROTOCOL_H
|
||||
|
||||
#include <sys.h>
|
||||
|
||||
#if( !defined( OSCompileAssert ) )
|
||||
# define OSCompileAssert( TEST ) \
|
||||
extern int OSCompileAssertFailed[ ( TEST ) ? 1 : -1 ] __unused;
|
||||
#endif
|
||||
|
||||
typedef union nvme_command {
|
||||
struct {
|
||||
uint8_t opc; // CDW[0] bits 0-7
|
||||
uint8_t fuse:2; // CDW[0] bits 8-9
|
||||
uint8_t reserved0:3; // CDW[0] bits 10-12
|
||||
uint8_t lprp:1; // CDW[0] bit 13
|
||||
uint8_t reserved1:2; // CDW[0] bits 14-15
|
||||
uint16_t cid; // CDW[0] bits 16-31
|
||||
uint32_t nsid; // CDW[1]
|
||||
uint64_t reserved2; // CDW[3:2]
|
||||
uint64_t mptr; // CDW[5:4]
|
||||
uint64_t prp1; // CDW[7:6]
|
||||
uint64_t prp2; // CDW[9:8]
|
||||
};
|
||||
uint32_t cdw[16];
|
||||
} nvme_command_t;
|
||||
|
||||
typedef union nvme_completion {
|
||||
struct {
|
||||
uint32_t cs;
|
||||
uint32_t reserved0;
|
||||
uint16_t sqhd;
|
||||
uint16_t sqid;
|
||||
uint16_t cid;
|
||||
uint16_t p:1;
|
||||
uint16_t sc:8;
|
||||
uint16_t sct:3;
|
||||
uint16_t reserved1:2;
|
||||
uint16_t m:1;
|
||||
uint16_t dnr:1;
|
||||
};
|
||||
uint32_t cdw[4];
|
||||
} nvme_completion_t;
|
||||
|
||||
typedef struct nvme_identify_namespace {
|
||||
uint64_t nsze;
|
||||
uint64_t ncap;
|
||||
uint64_t nuse;
|
||||
uint8_t nfeat;
|
||||
uint8_t nlbaf;
|
||||
uint8_t flbas;
|
||||
uint8_t mc;
|
||||
uint8_t dpc;
|
||||
uint8_t dps;
|
||||
uint8_t reserved1[98];
|
||||
struct {
|
||||
uint16_t ms;
|
||||
uint8_t lbads;
|
||||
uint8_t rp:2;
|
||||
uint8_t reserved:6;
|
||||
} lbaf[16];
|
||||
uint8_t reserved2[192];
|
||||
uint8_t vs[3712];
|
||||
} nvme_identify_namespace_t;
|
||||
|
||||
typedef struct NVMePowerStateDescriptor
|
||||
{
|
||||
uint16_t MAXIMUM_POWER;
|
||||
uint8_t RESERVED1[2];
|
||||
uint32_t ENTRY_LATENCY;
|
||||
uint32_t EXIT_LATENCY;
|
||||
uint8_t RELATIVE_READ_THROUGHPUT;
|
||||
uint8_t RELATIVE_READ_LATENCY;
|
||||
uint8_t RELATIVE_WRITE_THROUGHPUT;
|
||||
uint8_t RELATIVE_WRITE_LATENCY;
|
||||
uint8_t RESERVED2[16];
|
||||
} NVMePowerStateDescriptor;
|
||||
|
||||
OSCompileAssert ( sizeof ( NVMePowerStateDescriptor ) == 32 );
|
||||
|
||||
enum
|
||||
{
|
||||
kNVMeIdentifyControllerSerialNumberLen = 20,
|
||||
kNVMeIdentifyControllerModelNumberLen = 40,
|
||||
kNVMeIdentifyControllerFirmwareRevisionLen = 8,
|
||||
kNVMeIdentifyControllerIEEEOUIIDLen = 3,
|
||||
kNVMeIdentifyControllerMSPRevisionLen = 16,
|
||||
kNVMeIdentifyControllerPTSRevisionLen = 12,
|
||||
kNVMeIdentifyControllerBuildTrainLen = 16,
|
||||
kNVMeIdentifyControllerNANDTypeLen = 32,
|
||||
kNVMeIdentifyControllerNANDVendorLen = 16
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NVME_MODESEL_NORMAL = 0,
|
||||
NVME_MODESEL_BOOT = 1,
|
||||
NVME_MODESEL_READONLY = 2,
|
||||
NVME_MODESEL_RECOVERY = 3,
|
||||
NVME_MODESEL_MAX = 4
|
||||
};
|
||||
|
||||
#define kNVMeIdentifyControllerNumFuses 8
|
||||
|
||||
typedef struct NVMeIdentifyControllerStruct
|
||||
{
|
||||
// Controller Capabilites and Features
|
||||
uint16_t PCI_VID;
|
||||
uint16_t PCI_SSVID;
|
||||
uint8_t SERIAL_NUMBER[kNVMeIdentifyControllerSerialNumberLen];
|
||||
uint8_t MODEL_NUMBER[kNVMeIdentifyControllerModelNumberLen];
|
||||
uint8_t FW_REVISION[kNVMeIdentifyControllerFirmwareRevisionLen];
|
||||
uint8_t RECOMMENDED_ARBITRATION_BURST;
|
||||
uint8_t IEEE_OUI_ID[kNVMeIdentifyControllerIEEEOUIIDLen];
|
||||
uint8_t MIC;
|
||||
uint8_t MAX_DATA_TRANSFER_SIZE;
|
||||
uint16_t CONTROLLER_ID;
|
||||
uint8_t RESERVED1[176];
|
||||
|
||||
// Admin Command Set Attributes
|
||||
uint16_t OPTIONAL_ADMIN_COMMAND_SUPPORT;
|
||||
uint8_t ABORT_COMMAND_LIMIT;
|
||||
uint8_t ASYNC_EVENT_REQUEST_LIMIT;
|
||||
uint8_t FW_UPDATES;
|
||||
uint8_t LOG_PAGE_ATTR;
|
||||
uint8_t ERROR_LOG_PAGE_ENTRIES;
|
||||
uint8_t NUM_OF_POWER_STATE_SUPPORT;
|
||||
uint8_t ADMIN_VENDOR_SPECIFIC_COMMAND_CONFIG;
|
||||
uint8_t AUTONOMOUS_POWER_STATE_TRANSITION_ATTR;
|
||||
uint8_t RESERVED2[246];
|
||||
|
||||
// NVM Command Set Attributes
|
||||
uint8_t SQ_ENTRY_SIZE;
|
||||
uint8_t CQ_ENTRY_SIZE;
|
||||
uint8_t RESERVED3[2];
|
||||
uint32_t NUMBER_OF_NAMESPACES;
|
||||
uint16_t OPTIONAL_NVM_COMMAND_SUPPORT;
|
||||
uint16_t FUSE_OP_SUPPORT;
|
||||
uint8_t FORMAT_NVM_ATTR;
|
||||
uint8_t VOLATILE_WRITE_CACHE;
|
||||
uint16_t ATOMIC_WRITE_UNIT_NORMAL;
|
||||
uint16_t ATOMIC_WRITE_UNIT_POWER_FAIL;
|
||||
uint8_t NVM_VENDOR_SPECIFIC_COMMAND_CONFIG;
|
||||
uint8_t RESERVED4[1];
|
||||
uint16_t ATOMIC_COMPARE_AND_WRITE_UNIT;
|
||||
uint8_t RESERVED5[2];
|
||||
uint32_t SGL_SUPPORT;
|
||||
uint8_t RESERVED6[164];
|
||||
|
||||
// I/O Command Set Attributes
|
||||
uint8_t RESERVED7[1344];
|
||||
|
||||
// Power State Descriptors
|
||||
NVMePowerStateDescriptor POWER_STATE_DESCRIPTORS[32];
|
||||
|
||||
// Vendor Specific Runtime Data
|
||||
uint8_t MSP_REVISION[kNVMeIdentifyControllerMSPRevisionLen];
|
||||
uint32_t TIME_TO_READY;
|
||||
uint32_t TRIMMER_STATUS;
|
||||
uint8_t BOOT_SOURCE;
|
||||
uint8_t BOOT_BLOCK_INDEX;
|
||||
uint8_t RESERVED8[2];
|
||||
uint8_t S3_CHIP_ID;
|
||||
uint8_t S3_CHIP_REVISION;
|
||||
uint16_t S3_DEVICE_DESCRIPTOR;
|
||||
uint8_t S3_ECC_VERSION_NAND_REVISION;
|
||||
uint8_t S3_FTL_MAJOR_VERSION;
|
||||
uint8_t S3_FTL_MINOR_VERSION;
|
||||
uint8_t S3_DM_VERSION;
|
||||
uint8_t S3_CONFIG_VERSION;
|
||||
uint8_t S3_FORMAT_UTIL_MAJOR_VERSION;
|
||||
uint8_t RESERVED9[6];
|
||||
uint8_t ASP_BUILD_TRAIN[kNVMeIdentifyControllerBuildTrainLen];
|
||||
uint8_t MSP_BUILD_TRAIN[kNVMeIdentifyControllerBuildTrainLen];
|
||||
uint8_t RESERVED10[436];
|
||||
// Vendor Specific Production Data
|
||||
uint8_t BOARD_TYPE;
|
||||
uint8_t NAND_TYPE;
|
||||
uint8_t NAND_VENDOR;
|
||||
uint8_t DRAM_VENDOR;
|
||||
uint8_t NOR_VENDOR;
|
||||
uint8_t CHANNELS_BITMAP;
|
||||
uint16_t SSD_CAPACITY;
|
||||
uint8_t CORNER_TYPE;
|
||||
uint8_t ROM_VERSION;
|
||||
uint8_t PTS_REVISION[kNVMeIdentifyControllerPTSRevisionLen];
|
||||
uint16_t PTS_STATUS_BITMAP;
|
||||
uint8_t NAND_TYPE_STRING[kNVMeIdentifyControllerNANDTypeLen];
|
||||
uint8_t NAND_VENDOR_STRING[kNVMeIdentifyControllerNANDVendorLen];
|
||||
uint32_t MAXIMUM_PRIMARY_NS_SIZE;
|
||||
uint8_t RESERVED11[180];
|
||||
uint32_t RAW_FUSES[kNVMeIdentifyControllerNumFuses];
|
||||
uint8_t RESERVED12[224];
|
||||
|
||||
} NVMeIdentifyControllerStruct;
|
||||
|
||||
#define NVME_FUSE_VALUE_FOR_HYNIX 1
|
||||
#define NVME_FUSE_VALUE_FOR_SANDISK 3
|
||||
#define NVME_FUSE_VALUE_FOR_SAMSUNG 4
|
||||
#define NVME_FUSE_VALUE_FOR_TOSHIBA 5
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NVME_NAND_DEVICE_HYNIX = NVME_FUSE_VALUE_FOR_HYNIX,
|
||||
NVME_NAND_DEVICE_SANDISK = NVME_FUSE_VALUE_FOR_SANDISK,
|
||||
NVME_NAND_DEVICE_SAMSUNG = NVME_FUSE_VALUE_FOR_SAMSUNG,
|
||||
NVME_NAND_DEVICE_TOSHIBA = NVME_FUSE_VALUE_FOR_TOSHIBA,
|
||||
NVME_NAND_NUM_VENDORS
|
||||
} NVME_NAND_DEVICE_VENDOR_E;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NVME_LYTH_1X,
|
||||
NVME_LYTH_1Y,
|
||||
NVME_LYTH_1Z,
|
||||
NVME_NAND_NUM_LITHOS
|
||||
} NVME_NAND_DEVICE_LITHOGRAPHY_E;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NVME_NAND_DEV_DENSITY_SLC,
|
||||
NVME_NAND_DEV_DENSITY_MLC,
|
||||
NVME_NAND_DEV_DENSITY_TLC,
|
||||
NVME_NAND_NUM_DENSITIES
|
||||
} NVME_NAND_DEVICE_DENSITY_E;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NVME_SINGLE_DIMENSION,
|
||||
NVME_THREE_DIMENSION,
|
||||
NVME_NAND_NUM_DIMENSIONS
|
||||
} NVME_NAND_DEVICE_TECHNOLOGY_E;
|
||||
|
||||
typedef enum {
|
||||
NVME_CHIP_S3E,
|
||||
NVME_CHIP_S3X,
|
||||
NVME_CHIP_NUM_ID
|
||||
} NVME_IDCMD_ChipID_E;
|
||||
|
||||
typedef enum {
|
||||
NVME_REV_A,
|
||||
NVME_REV_B,
|
||||
NVME_REV_C,
|
||||
NVME_CHIP_NUM_REV_MAJOR
|
||||
} NVME_IDCMD_ChipRevMajor_E;
|
||||
|
||||
typedef enum {
|
||||
B_DIE,
|
||||
C_DIE,
|
||||
NUM_DIE_TYPES
|
||||
} NAND_DEVICE_DIE_TYPE_E;
|
||||
|
||||
const static char *NVME_VENDOR_STRINGS[NVME_NAND_NUM_VENDORS] =
|
||||
{
|
||||
"Invalid",
|
||||
"Hynix",
|
||||
"Invalid",
|
||||
"Sandisk",
|
||||
"Samsung",
|
||||
"Toshiba"
|
||||
};
|
||||
|
||||
const static char *NVME_LITHOGRAPHY_STRINGS[NVME_NAND_NUM_LITHOS] =
|
||||
{
|
||||
"1x",
|
||||
"1y",
|
||||
"1z"
|
||||
};
|
||||
|
||||
const static char *NVME_DENSITY_STRINGS[NVME_NAND_NUM_DENSITIES] =
|
||||
{
|
||||
"SLC",
|
||||
"MLC",
|
||||
"TLC"
|
||||
};
|
||||
|
||||
const static char *NVME_DIMENSIONS_STRINGS[NVME_NAND_NUM_DIMENSIONS] =
|
||||
{
|
||||
"1D",
|
||||
"3D",
|
||||
};
|
||||
|
||||
const static char *NVME_CHIP_STRINGS[NVME_CHIP_NUM_ID] =
|
||||
{
|
||||
"S3E",
|
||||
"S1X",
|
||||
};
|
||||
|
||||
const static char *NVME_CHIP_DIE_STRINGS[NUM_DIE_TYPES] =
|
||||
{
|
||||
"b",
|
||||
"c"
|
||||
};
|
||||
|
||||
|
||||
#define NVME_APPLE_CLASS_CODE (0x018002)
|
||||
#define NVME_APPLE_BAR0_SIZE (0x2000)
|
||||
|
||||
#define NVME_PAGE_SIZE (1<<12)
|
||||
#define NVME_PAGE_MASK (NVME_PAGE_SIZE - 1)
|
||||
|
||||
#define NVME_ADMIN_DELETE_SQ 0x00
|
||||
#define NVME_ADMIN_CREATE_SQ 0x01
|
||||
#define NVME_ADMIN_DELETE_CQ 0x04
|
||||
#define NVME_ADMIN_CREATE_CQ 0x05
|
||||
#define NVME_ADMIN_IDENTIFY 0x06
|
||||
#define NVME_ADMIN_SET_FEATURES 0x09
|
||||
#define NVME_ADMIN_GET_FEATURES 0x0a
|
||||
#define NVME_ADMIN_FW_ACTIVATE 0x10
|
||||
#define NVME_ADMIN_FW_DOWNLOAD 0x11
|
||||
|
||||
#define NVME_IO_CMD_FLUSH 0x00
|
||||
#define NVME_IO_CMD_WRITE 0x01
|
||||
#define NVME_IO_CMD_READ 0x02
|
||||
#define NVME_IO_CMD_DATASET_MANAGEMENT 0x09
|
||||
|
||||
#define NVME_CREATE_SQ_CONTIGUOUS (1<<0)
|
||||
#define NVME_CREATE_CQ_CONTIGUOUS (1<<0)
|
||||
#define NVME_CREATE_CQ_INTERRUPT_EN (1<<1)
|
||||
|
||||
|
||||
#define NVME_REG_CAP (0x0000)
|
||||
#define NVME_REG_VS (0x0008)
|
||||
#define NVME_REG_INTMS (0x000c)
|
||||
#define NVME_REG_INTMC (0x0010)
|
||||
#define NVME_REG_CC (0x0014)
|
||||
#define NVME_REG_CSTS (0x001c)
|
||||
#define NVME_REG_AQA (0x0024)
|
||||
#define NVME_REG_ASQ (0x0028)
|
||||
#define NVME_REG_ACQ (0x0030)
|
||||
#define NVME_REG_SQ0TDBL (0x1000)
|
||||
#define NVME_REG_MODESEL (0x1800)
|
||||
#define NVME_REG_MODESTAT (0x1804)
|
||||
#define NVME_REG_DDRREQSIZE (0x1808)
|
||||
#define NVME_REG_DDRREQALIGN (0x180c)
|
||||
#define NVME_REG_DDRBASE (0x1810)
|
||||
#define NVME_REG_DDRSIZE (0x1818)
|
||||
|
||||
// S3E-specific registers
|
||||
#define NVME_REG_S3E_TIMEOUT_DEBUG (0x0550)
|
||||
#define NVME_REG_S3E_ASSERT_ID (0x1910)
|
||||
#define NVME_REG_S3E_ASSERT_LOG1 (0x1914)
|
||||
#define NVME_REG_S3E_ASSERT_LOG2 (0x1918)
|
||||
#define NVME_REG_S3E_ASSERT_LOG3 (0x191c)
|
||||
#define NVME_REG_S3E_ASSERT_EDD0 (0x1980)
|
||||
#define NVME_REG_S3E_ASSERT_EDD1 (0x1984)
|
||||
#define NVME_REG_S3E_ASSERT_EDD2 (0x1988)
|
||||
#define NVME_REG_S3E_ASSERT_EDD3 (0x198c)
|
||||
#define NVME_REG_S3E_ASSERT_EDD4 (0x1990)
|
||||
#define NVME_REG_S3E_ASSERT_EDD5 (0x1994)
|
||||
#define NVME_REG_S3E_ASSERT_EDD6 (0x1998)
|
||||
#define NVME_REG_S3E_ASSERT_EDD7 (0x199c)
|
||||
|
||||
// S3E FA registers
|
||||
#define NVME_REG_FA_ACTION (0x195C)
|
||||
#define NVME_REG_FA_STATUS (0x1960)
|
||||
#define NVME_REG_FA_SIZE (0x1964)
|
||||
|
||||
// S3E FA actions
|
||||
#define NVME_FA_ACTION_DO_FLUSH 1
|
||||
#define NVME_FA_ACTION_DO_DUMP_FA 2
|
||||
|
||||
// S3E FA status values
|
||||
#define NVME_FA_STATUS_FLUSH_DONE 1
|
||||
#define NVME_FA_STATUS_FA_DONE 2
|
||||
|
||||
#define NVME_CC_EN (1 << 0)
|
||||
#define NVME_CC_MPS(x) (x << 7)
|
||||
#define NVME_CC_SHN_NONE (0 << 14)
|
||||
#define NVME_CC_SHN_NORMAL (1 << 14)
|
||||
#define NVME_CC_SHN_ABRUPT (2 << 14)
|
||||
#define NVME_CC_IOSQES(x) (x << 16)
|
||||
#define NVME_CC_IOCQES(x) (x << 20)
|
||||
|
||||
#define NVME_CSTS_RDY (1 << 0)
|
||||
#define NVME_CSTS_CFS (1 << 1)
|
||||
#define NVME_CSTS_SHST_MASK (3 << 2)
|
||||
#define NVME_CSTS_SHST_NORMAL (0 << 2)
|
||||
#define NVME_CSTS_SHST_PROCESSING (1 << 2)
|
||||
#define NVME_CSTS_SHST_DONE (2 << 2)
|
||||
|
||||
#endif // NVME_PROTOCOL_H
|
||||
@@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2011 Apple Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Inc.
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += WITH_NVME=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/nvme.o \
|
||||
$(LOCAL_DIR)/nvme_blockdev.o
|
||||
Reference in new issue
Block a user