nvme: identify command and structs

This commit is contained in:
Matheus
2023-02-04 01:26:30 -03:00
parent fae8fa47b2
commit d4f8ed68de
Regular → Executable
+172 -26
View File
@@ -28,6 +28,10 @@
#define OPCODE_IDENTIFY 0x6
#define IDENTIFY_TYPE_CONTROLLER 0
#define IDENTIFY_TYPE_NAMESPACE 1
#define IDENTIFY_TYPE_NAMESPACELIST 2
typedef struct{
uint64_t cap;
uint32_t vs;
@@ -91,7 +95,7 @@ typedef struct{
volatile nvme_bar0* bar0;
queuepair_t adminqueue;
queuepair_t* ioqueue;
} ctlrinfo;
} ctlrinfo_t;
typedef struct{
subqentry sub;
@@ -99,15 +103,135 @@ typedef struct{
event_t completion;
} entrypair_t;
typedef struct{
uint16_t metadatasize;
uint8_t lbadatasize; // power of two
uint8_t relativeperformance : 2;
uint8_t reserved : 6;
} __attribute__((packed)) lbaformat_t;
typedef struct{
uint64_t lbasize;
uint64_t lbacapacity;
uint64_t lbautilized;
uint8_t features;
uint8_t lbaformatcount;
uint8_t lbaformattedsize;
uint8_t metadatacap;
uint8_t endtoendprot;
uint8_t endtoendprotsettings;
uint8_t sharingcap;
uint8_t rescap;
uint8_t fpi;
uint8_t deallocate;
uint8_t atomicwrite;
uint16_t atomicwritepowerfail;
uint16_t atomiccomparewrite;
uint16_t atomicboundarysize;
uint16_t atomicboundaryoffset;
uint16_t atomicboundarypowerfail;
uint16_t optimalioboundary;
uint64_t nvmcapacity[2];
uint16_t preferredwritegranularity;
uint16_t preferredwritealignment;
uint16_t preferreddeallocategranularity;
uint16_t preferreddeallocatealignment;
uint16_t optimalwritesize;
uint8_t _reserved[18];
uint32_t anagrpid;
uint16_t __reserved;
uint8_t namespaceattr;
uint16_t nvmsetid;
uint16_t endgid;
uint64_t namespaceguid[2];
uint64_t eui64;
uint32_t lbaformat[16];
} __attribute__((packed)) namespacedata_t;
typedef struct{
uint16_t pcivendor;
uint16_t pcisubsystemvendor;
uint8_t serialnum[20];
uint8_t modelnum[20];
uint64_t fwrevision;
uint8_t recommendedburst;
uint8_t ouiid[3];
uint8_t namespacesharing;
uint8_t maxdatatransfer; // power of two
uint16_t controllerid;
uint32_t version;
uint32_t rtd3resumelatency;
uint32_t rtd3entrylatency;
uint32_t optionalasyncevents;
uint32_t attributes;
uint16_t rrlsupported;
uint64_t reserved;
uint8_t type;
uint64_t fguid[2];
uint16_t crdt[3];
uint8_t _reserved[106];
uint8_t mi_res[16];
uint16_t admincmdsupport;
uint8_t abortlimit;
uint8_t asynceventrqlimit;
uint8_t firmwareupdates;
uint8_t logpages;
uint8_t errorlogpages;
uint8_t powerstatenum;
uint8_t adminvendorspecific;
uint8_t apsta;
uint16_t wctemp;
uint16_t cctemp;
uint16_t mtfa;
uint32_t hmpre;
uint32_t hmmin;
uint64_t tnvmcap[2];
uint64_t unvmcap[2];
uint32_t rpmbs;
uint16_t edstt;
uint8_t dsto;
uint8_t fwug;
uint16_t kas;
uint16_t hctma;
uint16_t mntmt;
uint16_t mxtmt;
uint32_t sanicap;
uint32_t hmminds;
uint16_t hmmaxd;
uint16_t nsetidmax;
uint16_t endgidmax;
uint8_t anatt;
uint8_t anacap;
uint32_t anagrpmax;
uint32_t nanagrpid;
uint32_t pels;
uint8_t __reserved[156];
uint8_t sqentrysize; // powers of 2
uint8_t cqentrysize;
uint16_t maxcmd;
uint32_t namespacecount;
uint16_t oncs;
uint16_t fuses;
uint8_t fna;
uint8_t vwc;
uint16_t awun;
uint16_t awupf;
uint8_t nvscc;
uint8_t nwpc;
uint16_t acwu;
} __attribute__((packed)) controllerid_t;
#define ASQSIZE PAGE_SIZE / sizeof(subqentry)
#define ACQSIZE PAGE_SIZE / sizeof(compqentry)
static ctlrinfo* ctlrpass;
static ctlrinfo_t* ctlrpass;
static queuepair_t* queuepass;
static int controllercount;
static ctlrinfo** controllers;
static ctlrinfo_t** controllers;
#include <arch/io.h>
@@ -124,7 +248,7 @@ void nvme_irq(){
__attribute__((noreturn)) static void nvme_workerthread(){
ctlrinfo* controller = ctlrpass;
ctlrinfo_t* controller = ctlrpass;
queuepair_t* queuepair = queuepass;
entrypair_t* userentries[256];
int lowestfreepair = 0;
@@ -141,8 +265,6 @@ __attribute__((noreturn)) static void nvme_workerthread(){
if(ringbuffer_datacount(&queuepair->userrequests)){
// process a user request
// get the pair address and store it
int pair = lowestfreepair;
while(userentries[pair]) ++pair;
@@ -206,6 +328,39 @@ static inline void dispatchandwait(entrypair_t* e, queuepair_t* q){
arch_interrupt_enable();
}
#define IDENTIFY_SIZE 4096
int nvme_identify(ctlrinfo_t* ctlr, void* buff, int type, int what){
__assert(type < 3); // anything else is not supported atm
entrypair_t pair;
memset(&pair, 0, sizeof(entrypair_t));
pair.sub.dataptr[0] = pmm_alloc(1);
if(!pair.sub.dataptr[0])
return ENOMEM;
pair.sub.command[0] = type;
pair.sub.d0.opcode = OPCODE_IDENTIFY;
if(type == IDENTIFY_TYPE_NAMESPACE)
pair.sub.namespace = what;
dispatchandwait(&pair, &ctlr->adminqueue);
memcpy(buff, MAKEHHDM(pair.sub.dataptr[0]), IDENTIFY_SIZE);
return pair.comp.status ? EIO : 0;
}
int nvme_identifycontroller(ctlrinfo_t* ctlr, void* buff){
return nvme_identify(ctlr, buff, IDENTIFY_TYPE_CONTROLLER, 0);
}
static void nvme_initctlr(pci_enumeration* pci){
void* bar0p = getbarmemaddr(pci->header, 0);
@@ -300,9 +455,9 @@ static void nvme_initctlr(pci_enumeration* pci){
return;
}
ctlrinfo* info = alloc(sizeof(ctlrinfo));
ctlrinfo_t* info = alloc(sizeof(ctlrinfo_t));
controllers = realloc(controllers, sizeof(ctlrinfo*)*(controllercount+1));
controllers = realloc(controllers, sizeof(ctlrinfo_t*)*(controllercount+1));
if(info == NULL || controllers == NULL)
_panic("Out of memory", NULL);
@@ -324,30 +479,21 @@ static void nvme_initctlr(pci_enumeration* pci){
ctlrpass = info;
queuepass = &info->adminqueue;
info->adminqueue.worker = sched_newkthread(nvme_workerthread, PAGE_SIZE*1000, true, THREAD_PRIORITY_KERNEL);
if(!info->adminqueue.worker)
_panic("Out of memory!", NULL);
entrypair_t pair;
memset(&pair, 0, sizeof(entrypair_t));
pair.sub.dataptr[0] = pmm_alloc(1);
if(!pair.sub.dataptr[0])
_panic("Out of memory!\n", NULL);
pair.sub.command[0] = 1;
pair.sub.d0.opcode = OPCODE_IDENTIFY;
if(msix)
pci_msixadd(pci, 0, arch_getcls()->lapicid, VECTOR_NVME, true, false);
else
pci_msiadd(pci, arch_getcls()->lapicid, VECTOR_NVME, true, false);
dispatchandwait(&pair, &info->adminqueue);
info->adminqueue.worker = sched_newkthread(nvme_workerthread, PAGE_SIZE*1000, true, THREAD_PRIORITY_KERNEL);
if(!info->adminqueue.worker)
_panic("Out of memory!", NULL);
controllerid_t* ctlrid = alloc(4096);
nvme_identifycontroller(info, ctlrid);
}
@@ -358,7 +504,7 @@ void nvme_init(){
controllers = alloc(1);
__assert(controllers);
if(!e)
return;