| package nvme | 
 |  | 
 | import ( | 
 | 	"bytes" | 
 | 	"encoding/binary" | 
 | 	"fmt" | 
 | 	"math/big" | 
 | ) | 
 |  | 
 | // Figure 109 | 
 | type identifyData struct { | 
 | 	// Controller Capabilities and Features | 
 | 	PCIVendorID                 uint16 | 
 | 	PCISubsystemVendorID        uint16 | 
 | 	SerialNumber                [20]byte | 
 | 	ModelNumber                 [40]byte | 
 | 	FirmwareRevision            [8]byte | 
 | 	RecommendedArbitrationBurst uint8 | 
 | 	IEEEOUI                     [3]byte | 
 | 	CMIC                        uint8 | 
 | 	MaximumDataTransferSize     uint8 | 
 | 	ControllerID                uint16 | 
 | 	Version                     uint32 | 
 | 	RuntimeD3ResumeLatency      uint32 | 
 | 	RuntimeD3EntryLatency       uint32 | 
 | 	OAES                        uint32 | 
 | 	CTRATT                      uint32 | 
 | 	_                           [12]byte | 
 | 	FRUGUID                     [16]byte | 
 | 	_                           [128]byte | 
 | 	// Admin Command Set Attributes & Optional Controller Capabilities | 
 | 	OACS                                uint16 | 
 | 	AbortCommandLimit                   uint8 | 
 | 	AsynchronousEventRequestLimit       uint8 | 
 | 	FRMW                                uint8 | 
 | 	LPA                                 uint8 | 
 | 	ErrorLogPageEntries                 uint8 | 
 | 	NumberOfPowerStatesSupport          uint8 | 
 | 	AdminVendorSpecificCmdConfig        uint8 | 
 | 	AutonomousPowerStateTransitionAttrs uint8 | 
 | 	WarningCompositeTempThreshold       uint16 | 
 | 	CriticalCompositeTempThreshold      uint16 | 
 | 	MaximumTimeForFirmwareActivation    uint16 | 
 | 	HostMemoryBufferPreferredSize       uint32 | 
 | 	HostMemoryBufferMinimumSize         uint32 | 
 | 	TotalNVMCapacity                    uint128le | 
 | 	UnallocatedNVMCapacity              uint128le | 
 | 	ReplyProtectedMemoryBlockSupport    uint32 | 
 | 	ExtendedDeviceSelfTestTime          uint16 | 
 | 	DeviceSelfTestOptions               uint8 | 
 | 	FirmwareUpdateGranularity           uint8 | 
 | 	KeepAliveSupport                    uint16 | 
 | 	HostControlledThermalMgmtAttrs      uint16 | 
 | 	MinimumThermalMgmntTemp             uint16 | 
 | 	MaximumThermalMgmntTemp             uint16 | 
 | 	SanitizeCapabilities                uint32 | 
 | 	_                                   [180]byte | 
 | 	// NVM Command Set Attributes | 
 | 	SubmissionQueueEntrySize       uint8 | 
 | 	CompletionQueueEntrySize       uint8 | 
 | 	MaximumOutstandingCommands     uint16 | 
 | 	NumberOfNamespaces             uint32 | 
 | 	OptionalNVMCommandSupport      uint16 | 
 | 	FusedOperationSupport          uint16 | 
 | 	FormatNVMAttributes            uint8 | 
 | 	VolatileWriteCache             uint8 | 
 | 	AtomicWriteUnitNormal          uint16 | 
 | 	AtomicWriteUnitPowerFail       uint16 | 
 | 	NVMVendorSepcificCommandConfig uint8 | 
 | 	AtomicCompareAndWriteUnit      uint16 | 
 | 	_                              [2]byte | 
 | 	SGLSupport                     uint32 | 
 | 	_                              [228]byte | 
 | 	NVMSubsystemNVMeQualifiedName  [256]byte | 
 | 	_                              [1024]byte | 
 | 	// Power State Descriptors | 
 | 	PowerStateDescriptors [32][32]byte | 
 | } | 
 |  | 
 | // IdentifyData contains various identifying information about a NVMe | 
 | // controller. Because the actual data structure is very large, currently not | 
 | // all fields are exposed as properly-typed individual fields. If you need | 
 | // a new field, please add it to this structure. | 
 | type IdentifyData struct { | 
 | 	// PCIVendorID contains the company vendor identifier assigned by the PCI | 
 | 	// SIG. | 
 | 	PCIVendorID uint16 | 
 | 	// PCISubsystemVendorID contains the company vendor identifier that is | 
 | 	// assigned by the PCI SIG for the subsystem. | 
 | 	PCISubsystemVendorID uint16 | 
 | 	// SerialNumber contains the serial number for the NVM subsystem that is | 
 | 	// assigned by the vendor. | 
 | 	SerialNumber string | 
 | 	// ModelNumber contains the model number for the NVM subsystem that is | 
 | 	// assigned by the vendor. | 
 | 	ModelNumber string | 
 | 	// FirmwareRevision contains the currently active firmware revision for the | 
 | 	// NVM subsystem. | 
 | 	FirmwareRevision string | 
 | 	// IEEEOUI contains the Organization Unique Identifier for the controller | 
 | 	// vendor as assigned by the IEEE. | 
 | 	IEEEOUI [3]byte | 
 |  | 
 | 	// IsPCIVirtualFunction indicates if the controller is a virtual controller | 
 | 	// as part of a PCI virtual function. | 
 | 	IsPCIVirtualFunction bool | 
 |  | 
 | 	// SpecVersionMajor/Minor contain the version of the NVMe specification the | 
 | 	// controller supports. Only mandatory from spec version 1.2 onwards. | 
 | 	SpecVersionMajor uint16 | 
 | 	SpecVersionMinor uint8 | 
 |  | 
 | 	// FRUGloballyUniqueIdentifier contains a 128-bit value that is globally | 
 | 	// unique for a given Field Replaceable Unit (FRU). Contains all-zeroes if | 
 | 	// unavailable. | 
 | 	FRUGloballyUniqueIdentifier [16]byte | 
 | 	// VirtualizationManagementSupported indicates if the controller | 
 | 	// supports the Virtualization Management command. | 
 | 	VirtualizationManagementSupported bool | 
 | 	// NVMeMISupported indicates if the controller supports the NVMe-MI | 
 | 	// Send and Receive commands. | 
 | 	NVMeMISupported bool | 
 | 	// DirectivesSupported indicates if the controller supports the | 
 | 	// Directive Send and Receive commands. | 
 | 	DirectivesSupported bool | 
 | 	// SelfTestSupported indicates if the controller supports the Device Self- | 
 | 	// test command. | 
 | 	SelfTestSupported bool | 
 | 	// NamespaceManagementSupported indicates if the controller supports the | 
 | 	// Namespace Management and Attachment commands. | 
 | 	NamespaceManagementSupported bool | 
 | 	// FirmwareUpdateSupported indicates if the controller supports the | 
 | 	// Firmware Commit and Image Download commands. | 
 | 	FirmwareUpdateSupported bool | 
 | 	// FormattingSupported indicates if the controller supports the Format | 
 | 	// command. | 
 | 	FormattingSupported bool | 
 | 	// SecuritySupported indicates if the controller supports the Security Send | 
 | 	// and Receive commands. | 
 | 	SecuritySupported bool | 
 |  | 
 | 	// TotalNVMCapacity contains the total NVM capacity in bytes in the NVM | 
 | 	// subsystem. This can be 0 on devices without NamespaceManagementSupported. | 
 | 	TotalNVMCapacity *big.Int | 
 | 	// UnallocatedNVMCapacity contains the unallocated NVM capacity in bytes in | 
 | 	// the NVM subsystem. This can be 0 on devices without | 
 | 	// NamespaceManagementSupported. | 
 | 	UnallocatedNVMCapacity *big.Int | 
 |  | 
 | 	// MaximumNumberOfNamespace defines the maximum number of namespaces | 
 | 	// supported by the controller. | 
 | 	MaximumNumberOfNamespaces uint32 | 
 | } | 
 |  | 
 | func (d *Device) Identify() (*IdentifyData, error) { | 
 | 	var resp [4096]byte | 
 |  | 
 | 	if err := d.RawCommand(&Command{ | 
 | 		Opcode: 0x06, | 
 | 		Data:   resp[:], | 
 | 		CDW10:  1, | 
 | 	}); err != nil { | 
 | 		return nil, fmt.Errorf("Identify command failed: %w", err) | 
 | 	} | 
 | 	var raw identifyData | 
 | 	binary.Read(bytes.NewReader(resp[:]), binary.LittleEndian, &raw) | 
 |  | 
 | 	var res IdentifyData | 
 | 	res.PCIVendorID = raw.PCIVendorID | 
 | 	res.PCISubsystemVendorID = raw.PCISubsystemVendorID | 
 | 	res.SerialNumber = string(bytes.TrimRight(raw.SerialNumber[:], " ")) | 
 | 	res.ModelNumber = string(bytes.TrimRight(raw.ModelNumber[:], " ")) | 
 | 	res.FirmwareRevision = string(bytes.TrimRight(raw.FirmwareRevision[:], " ")) | 
 | 	// OUIs are traditionally big-endian, but NVMe exposes them in little-endian | 
 | 	res.IEEEOUI[0], res.IEEEOUI[1], res.IEEEOUI[2] = raw.IEEEOUI[2], raw.IEEEOUI[1], raw.IEEEOUI[0] | 
 | 	res.IsPCIVirtualFunction = raw.CMIC&(1<<2) != 0 | 
 | 	res.SpecVersionMajor = uint16(raw.Version >> 16) | 
 | 	res.SpecVersionMinor = uint8((raw.Version >> 8) & 0xFF) | 
 | 	res.FRUGloballyUniqueIdentifier = raw.FRUGUID | 
 | 	res.VirtualizationManagementSupported = raw.OACS&(1<<7) != 0 | 
 | 	res.NVMeMISupported = raw.OACS&(1<<6) != 0 | 
 | 	res.DirectivesSupported = raw.OACS&(1<<5) != 0 | 
 | 	res.SelfTestSupported = raw.OACS&(1<<4) != 0 | 
 | 	res.NamespaceManagementSupported = raw.OACS&(1<<3) != 0 | 
 | 	res.FirmwareUpdateSupported = raw.OACS&(1<<2) != 0 | 
 | 	res.FormattingSupported = raw.OACS&(1<<1) != 0 | 
 | 	res.SecuritySupported = raw.OACS&(1<<0) != 0 | 
 |  | 
 | 	res.TotalNVMCapacity = raw.TotalNVMCapacity.BigInt() | 
 | 	res.UnallocatedNVMCapacity = raw.UnallocatedNVMCapacity.BigInt() | 
 | 	res.MaximumNumberOfNamespaces = raw.NumberOfNamespaces | 
 | 	return &res, nil | 
 | } |