NVMe 裸机代码
时间: 2023-07-02 22:11:19 浏览: 272
NVMe(Non-Volatile Memory Express)是一种高速、低延迟的存储器协议,旨在优化闪存或其他非易失性存储器的性能。以下是一个简单的NVMe裸机代码示例,可以用于初始化NVMe控制器和与NVMe设备通信:
```
#include <stdint.h>
// NVMe寄存器地址
#define NVME_CAP 0x0
#define NVME_VS 0x8
#define NVME_INTMS 0x10
#define NVME_INTMC 0x18
#define NVME_CC 0x14
#define NVME_CSTS 0x1C
#define NVME_ASQ 0x20
#define NVME_ACQ 0x28
// NVMe命令
#define NVME_ADMIN_GET_LOG_PAGE 0x02
#define NVME_ADMIN_IDENTIFY 0x06
#define NVME_IO_READ 0x02
#define NVME_IO_WRITE 0x01
// NVMe命令队列大小
#define QUEUE_SIZE 64
// NVMe命令结构体
typedef struct {
uint32_t dword0;
uint32_t dword1;
uint32_t dword2;
uint32_t dword3;
uint32_t dword4;
uint32_t dword5;
uint32_t dword6;
uint32_t dword7;
} nvme_command_t;
// NVMe队列头结构体
typedef struct {
uint16_t qid;
uint16_t sq_head;
uint16_t sq_tail;
uint16_t cq_head;
uint16_t cq_tail;
uint16_t phase;
uint16_t reserved[3];
} nvme_queue_head_t;
// NVMe控制器初始化
void nvme_init() {
// 初始化NVMe寄存器
uint32_t* nvme = (uint32_t*)0x1000;
nvme[NVME_CAP] = 0x80000000;
nvme[NVME_VS] = 0x1010000;
nvme[NVME_INTMS] = 0;
nvme[NVME_INTMC] = 0;
nvme[NVME_CC] = 0x1;
while ((nvme[NVME_CSTS] & 0x1) != 0x1);
// 初始化命令队列
nvme_queue_head_t* sq = (nvme_queue_head_t*)0x2000;
nvme_queue_head_t* cq = (nvme_queue_head_t*)0x3000;
for (int i = 0; i < QUEUE_SIZE; i++) {
sq[i].qid = 0;
sq[i].sq_head = i;
sq[i].sq_tail = i;
sq[i].cq_head = i;
sq[i].cq_tail = i;
sq[i].phase = 0;
cq[i].qid = 0;
cq[i].sq_head = i;
cq[i].sq_tail = i;
cq[i].cq_head = i;
cq[i].cq_tail = i;
cq[i].phase = 0;
}
nvme[NVME_ASQ] = 0x2000;
nvme[NVME_ACQ] = 0x3000;
}
// 发送NVMe命令
void nvme_send_command(uint64_t lba, uint32_t count, uint8_t* buffer, uint8_t opcode) {
nvme_queue_head_t* sq = (nvme_queue_head_t*)0x2000;
nvme_queue_head_t* cq = (nvme_queue_head_t*)0x3000;
// 选择空闲的命令队列项
int index = -1;
for (int i = 0; i < QUEUE_SIZE; i++) {
if (sq[i].phase == 0 && cq[i].phase == 0) {
index = i;
break;
}
}
// 填充命令项
nvme_command_t* cmd = (nvme_command_t*)(0x4000 + 64 * index);
cmd->dword0 = (count - 1) << 16 | opcode;
cmd->dword1 = 0;
cmd->dword2 = (uint32_t)lba;
cmd->dword3 = (uint32_t)(lba >> 32);
cmd->dword4 = (uint32_t)buffer;
cmd->dword5 = (uint32_t)(buffer >> 32);
cmd->dword6 = 0;
cmd->dword7 = 0;
// 发送命令
sq[index].phase = 1;
uint32_t* nvme = (uint32_t*)0x1000;
nvme[NVME_ASQ] = 0x2000 + index * 64;
nvme[NVME_ACQ] = 0x3000 + index * 64;
nvme[NVME_CC] |= 0x1;
while ((nvme[NVME_CSTS] & 0x1) != 0x1);
}
// 接收NVMe命令完成
void nvme_poll_completion() {
uint32_t* nvme = (uint32_t*)0x1000;
if ((nvme[NVME_CSTS] & 0x2) != 0x2) {
return;
}
nvme[NVME_CSTS] = 0x2;
nvme_queue_head_t* cq = (nvme_queue_head_t*)0x3000;
for (int i = 0; i < QUEUE_SIZE; i++) {
if (cq[i].phase == 1) {
cq[i].phase = 0;
break;
}
}
}
// 读取NVMe设备
void nvme_read(uint64_t lba, uint32_t count, uint8_t* buffer) {
nvme_send_command(lba, count, buffer, NVME_IO_READ);
while (1) {
nvme_poll_completion();
if (count == 0) {
break;
}
lba++;
buffer += 512;
count--;
}
}
// 写入NVMe设备
void nvme_write(uint64_t lba, uint32_t count, uint8_t* buffer) {
nvme_send_command(lba, count, buffer, NVME_IO_WRITE);
while (1) {
nvme_poll_completion();
if (count == 0) {
break;
}
lba++;
buffer += 512;
count--;
}
}
```
以上代码仅作为示例,实际应用中需要考虑更多因素,并进行适当修改。
阅读全文