Improve kernel logging
Current function name is automatically prepended to all log entries. Helper macros added to log local variables.
This commit is contained in:
+1
-1
@@ -30,7 +30,7 @@ __attribute__((interrupt)) void isr_page_fault(__attribute__((unused)) struct in
|
|||||||
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
|
__asm__ volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||||
|
|
||||||
char msg[80];
|
char msg[80];
|
||||||
string_format("EXCEPTION: page fault; addr=%x err=%x", 80, msg, cr2, error_code);
|
string_format("EXCEPTION: page fault; addr=%lx err=%lx", 80, msg, cr2, error_code);
|
||||||
|
|
||||||
vga_set_string(VGA_HEIGHT - 1, 0, msg, 0x4F);
|
vga_set_string(VGA_HEIGHT - 1, 0, msg, 0x4F);
|
||||||
while (1)
|
while (1)
|
||||||
|
|||||||
+23
-1
@@ -8,7 +8,7 @@ extern stream_t *kernel_log;
|
|||||||
|
|
||||||
#define LOG(fmt, ...) \
|
#define LOG(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
uint64_t _size = string_length(fmt) * 2; \
|
uint64_t _size = string_length(fmt) * 10; \
|
||||||
char *_string = memory_allocate(_size); \
|
char *_string = memory_allocate(_size); \
|
||||||
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
||||||
kernel_log->write(kernel_log, _string, _size); \
|
kernel_log->write(kernel_log, _string, _size); \
|
||||||
@@ -17,4 +17,26 @@ extern stream_t *kernel_log;
|
|||||||
|
|
||||||
#define TRACE(fmt, ...)
|
#define TRACE(fmt, ...)
|
||||||
|
|
||||||
|
#define LOG_LN(fmt, ...) \
|
||||||
|
do { \
|
||||||
|
uint64_t _size = string_length(fmt) * 10; \
|
||||||
|
char *_string = memory_allocate(_size); \
|
||||||
|
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
||||||
|
kernel_log->write(kernel_log, __func__, string_length(__func__)); \
|
||||||
|
kernel_log->write(kernel_log, ": ", 2); \
|
||||||
|
kernel_log->write(kernel_log, _string, _size); \
|
||||||
|
kernel_log->write(kernel_log, "\n", 1); \
|
||||||
|
memory_free(_string); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define LOG_VAL(v) LOG_LN(#v "=%x")
|
||||||
|
|
||||||
|
#define LOG_VAL_F(v, f) LOG_LN(#v "=" f)
|
||||||
|
|
||||||
|
#define TRACE_LN(fmt, ...)
|
||||||
|
|
||||||
|
#define TRACE_VAL(v) TRACE_LN(#v "=%lx")
|
||||||
|
|
||||||
|
#define TRACE_VAL_F(v, f) TRACE_LN(#v "=" f)
|
||||||
|
|
||||||
void log_init(stream_t *log);
|
void log_init(stream_t *log);
|
||||||
|
|||||||
+7
-9
@@ -67,10 +67,10 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) {
|
|||||||
const uint64_t pd_index = (ivirt >> 21) & 0x1FF;
|
const uint64_t pd_index = (ivirt >> 21) & 0x1FF;
|
||||||
const uint64_t pt_index = (ivirt >> 12) & 0x1FF;
|
const uint64_t pt_index = (ivirt >> 12) & 0x1FF;
|
||||||
|
|
||||||
TRACE("memory_page_map: Mapping physical %x to virtual %x / [%u, %u, %u, %u]...\n", phys, virt, pml4_index, pdpt_index, pd_index, pt_index);
|
TRACE_LN("Mapping physical %lx to virtual %lx / [%u, %u, %u, %u]...", phys, virt, pml4_index, pdpt_index, pd_index, pt_index);
|
||||||
|
|
||||||
if (!(pml4[pml4_index] & PAGE_PRESENT)) {
|
if (!(pml4[pml4_index] & PAGE_PRESENT)) {
|
||||||
TRACE("memory_page_map: PML4 entry %u does not exist, creating...\n", pml4_index);
|
TRACE_LN("PML4 entry %u does not exist, creating...", pml4_index);
|
||||||
uint64_t *pdpt = memory_page_allocate();
|
uint64_t *pdpt = memory_page_allocate();
|
||||||
memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pdpt));
|
memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pdpt));
|
||||||
pml4[pml4_index] = (uint64_t)pdpt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
pml4[pml4_index] = (uint64_t)pdpt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
||||||
@@ -78,7 +78,7 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) {
|
|||||||
|
|
||||||
uint64_t *pdpt = PHYS_TO_VIRT(pml4[pml4_index] & ~(uint64_t)0xFFF);
|
uint64_t *pdpt = PHYS_TO_VIRT(pml4[pml4_index] & ~(uint64_t)0xFFF);
|
||||||
if (!(pdpt[pdpt_index] & PAGE_PRESENT)) {
|
if (!(pdpt[pdpt_index] & PAGE_PRESENT)) {
|
||||||
TRACE("memory_page_map: PDPT entry %u does not exist, creating...\n", pdpt_index);
|
TRACE_LN("PDPT entry %u does not exist, creating...", pdpt_index);
|
||||||
uint64_t *pd = memory_page_allocate();
|
uint64_t *pd = memory_page_allocate();
|
||||||
memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pd));
|
memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pd));
|
||||||
pdpt[pdpt_index] = (uint64_t)pd | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
pdpt[pdpt_index] = (uint64_t)pd | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
||||||
@@ -87,7 +87,7 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) {
|
|||||||
uint64_t *pd = PHYS_TO_VIRT(pdpt[pdpt_index] & ~(uint64_t)0xFFF);
|
uint64_t *pd = PHYS_TO_VIRT(pdpt[pdpt_index] & ~(uint64_t)0xFFF);
|
||||||
ASSERT(!(pd[pd_index] & 0x80), "memory_page_map: Huge page in PD.");
|
ASSERT(!(pd[pd_index] & 0x80), "memory_page_map: Huge page in PD.");
|
||||||
if (!(pd[pd_index] & PAGE_PRESENT)) {
|
if (!(pd[pd_index] & PAGE_PRESENT)) {
|
||||||
TRACE("memory_page_map: PD entry %u does not exist, creating...\n", pd_index);
|
TRACE_LN("PD entry %u does not exist, creating...", pd_index);
|
||||||
uint64_t *pt = memory_page_allocate();
|
uint64_t *pt = memory_page_allocate();
|
||||||
memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pt));
|
memory_set(0, PAGE_SIZE, PHYS_TO_VIRT(pt));
|
||||||
pd[pd_index] = (uint64_t)pt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
pd[pd_index] = (uint64_t)pt | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER;
|
||||||
@@ -97,13 +97,11 @@ void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags) {
|
|||||||
|
|
||||||
ASSERT(!(pt[pt_index] & PAGE_PRESENT), "memory_page_map: Page already mapped.")
|
ASSERT(!(pt[pt_index] & PAGE_PRESENT), "memory_page_map: Page already mapped.")
|
||||||
|
|
||||||
TRACE("memory_page_map: PT entry %u does not exist, creating...\n", pt_index);
|
TRACE_LN("PT entry %u does not exist, creating...", pt_index);
|
||||||
|
|
||||||
pt[pt_index] = (uint64_t)phys | flags | PAGE_PRESENT;
|
pt[pt_index] = (uint64_t)phys | flags | PAGE_PRESENT;
|
||||||
|
TRACE_VAL(pt[pt_index]);
|
||||||
|
|
||||||
TRACE("memory_page_map: Created %x.\n", pt[pt_index]);
|
TRACE_LN("Done.");
|
||||||
|
|
||||||
TRACE("memory_page_map: Done.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_page_unmap(uint64_t *pml4, void *virt) {
|
void memory_page_unmap(uint64_t *pml4, void *virt) {
|
||||||
|
|||||||
+64
-69
@@ -5,7 +5,6 @@
|
|||||||
#include "src/kernel/pci.h"
|
#include "src/kernel/pci.h"
|
||||||
#include "src/lib/layout.h"
|
#include "src/lib/layout.h"
|
||||||
#include "src/lib/memory.h"
|
#include "src/lib/memory.h"
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define SECTOR_SIZE 512
|
#define SECTOR_SIZE 512
|
||||||
|
|
||||||
@@ -67,89 +66,83 @@ static uint16_t io_cq_head = 0;
|
|||||||
static void admin_exec_sync(nvme_sqe_t *cmd) {
|
static void admin_exec_sync(nvme_sqe_t *cmd) {
|
||||||
cmd->cid = admin_sq_tail;
|
cmd->cid = admin_sq_tail;
|
||||||
|
|
||||||
TRACE("admin_exec_sync: Queueing submission...\n");
|
TRACE_LN("Queueing submission...");
|
||||||
TRACE("admin_exec_sync: opc=%x\n", cmd->opc);
|
TRACE_VAL_F(cmd->opc, "%hhx");
|
||||||
TRACE("admin_exec_sync: nsid=%x\n", cmd->nsid);
|
TRACE_VAL_F(cmd->nsid, "%x");
|
||||||
TRACE("admin_exec_sync: cdw10=%x\n", cmd->cdw10);
|
TRACE_VAL_F(cmd->cdw10, "%x");
|
||||||
TRACE("admin_exec_sync: cdw11=%x\n", cmd->cdw11);
|
TRACE_VAL_F(cmd->cdw11, "%x");
|
||||||
TRACE("admin_exec_sync: cdw12=%x\n", cmd->cdw12);
|
TRACE_VAL_F(cmd->cdw12, "%x");
|
||||||
TRACE("admin_exec_sync: prp1=%x\n", cmd->prp1);
|
TRACE_VAL_F(cmd->prp1, "%lx");
|
||||||
TRACE("admin_exec_sync: prp2=%x\n", cmd->prp2);
|
TRACE_VAL_F(cmd->prp2, "%lx");
|
||||||
|
|
||||||
memory_copy(cmd, sizeof(nvme_sqe_t), &admin_sq[admin_sq_tail]);
|
memory_copy(cmd, sizeof(nvme_sqe_t), &admin_sq[admin_sq_tail]);
|
||||||
|
|
||||||
TRACE("admin_exec_sync: Advancing submission doorbell...\n");
|
TRACE_LN("Advancing submission doorbell...");
|
||||||
|
|
||||||
*(volatile uint32_t *)((uint8_t *)regs + 0x1000) = admin_sq_tail = (admin_sq_tail + 1) % QUEUE_DEPTH;
|
*(volatile uint32_t *)((uint8_t *)regs + 0x1000) = admin_sq_tail = (admin_sq_tail + 1) % QUEUE_DEPTH;
|
||||||
|
TRACE_VAL_F(admin_sq_tail, "%u");
|
||||||
|
|
||||||
TRACE("admin_exec_sync: Waiting for completion...\n");
|
TRACE_LN("Waiting for completion...");
|
||||||
|
nvme_cqe_t *cmp = &admin_cq[admin_cq_head];
|
||||||
while ((admin_cq[admin_cq_head].status & 1) != admin_cq_phase)
|
while ((cmp->status & 1) != admin_cq_phase)
|
||||||
;
|
;
|
||||||
|
|
||||||
TRACE("admin_exec_sync: Received completion...\n");
|
TRACE_LN("Received completion...");
|
||||||
TRACE("admin_exec_sync: dw0=%x\n", io_cq[io_cq_head].dw0);
|
TRACE_VAL_F(cmp->dw0, "%x");
|
||||||
TRACE("admin_exec_sync: reserved=%x\n", io_cq[io_cq_head].reserved);
|
TRACE_VAL_F(cmp->reserved, "%x");
|
||||||
TRACE("admin_exec_sync: sqhd=%x\n", io_cq[io_cq_head].sqhd);
|
TRACE_VAL_F(cmp->sqhd, "%hx");
|
||||||
TRACE("admin_exec_sync: sqid=%x\n", io_cq[io_cq_head].sqid);
|
TRACE_VAL_F(cmp->sqid, "%hx");
|
||||||
TRACE("admin_exec_sync: cid=%x\n", io_cq[io_cq_head].cid);
|
TRACE_VAL_F(cmp->cid, "%hx");
|
||||||
TRACE("admin_exec_sync: status=%x\n", io_cq[io_cq_head].status);
|
TRACE_VAL_F(cmp->status, "%hx");
|
||||||
|
|
||||||
ASSERT((admin_cq[admin_cq_head].status >> 1) == 0, "admin_exec_sync: NVMe command failed.");
|
ASSERT((admin_cq[admin_cq_head].status >> 1) == 0, "admin_exec_sync: NVMe command failed.");
|
||||||
|
|
||||||
TRACE("admin_exec_sync: Advancing completion doorbell...\n");
|
TRACE_LN("Advancing completion doorbell...");
|
||||||
|
|
||||||
*(volatile uint32_t *)((uint8_t *)regs + 0x1004) = admin_cq_head = (admin_cq_head + 1) % QUEUE_DEPTH; // TODO Get offset from caps.
|
*(volatile uint32_t *)((uint8_t *)regs + 0x1004) = admin_cq_head = (admin_cq_head + 1) % QUEUE_DEPTH; // TODO Get offset from caps.
|
||||||
|
|
||||||
admin_cq_phase ^= (admin_cq_head == 0);
|
admin_cq_phase ^= (admin_cq_head == 0);
|
||||||
|
|
||||||
TRACE("admin_exec_sync: Done.\n");
|
TRACE_LN("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_exec_sync(nvme_sqe_t *cmd) {
|
static void io_exec_sync(nvme_sqe_t *cmd) {
|
||||||
cmd->cid = io_sq_tail;
|
cmd->cid = io_sq_tail;
|
||||||
|
|
||||||
TRACE("io_exec_sync: Queueing submission...\n");
|
TRACE_LN("Queueing submission...");
|
||||||
TRACE("io_exec_sync: opc=%x\n", cmd->opc);
|
TRACE_VAL_F(cmd->opc, "%hhx");
|
||||||
TRACE("io_exec_sync: nsid=%x\n", cmd->nsid);
|
TRACE_VAL_F(cmd->nsid, "%x");
|
||||||
TRACE("io_exec_sync: cdw10=%x\n", cmd->cdw10);
|
TRACE_VAL_F(cmd->cdw10, "%x");
|
||||||
TRACE("io_exec_sync: cdw11=%x\n", cmd->cdw11);
|
TRACE_VAL_F(cmd->cdw11, "%x");
|
||||||
TRACE("io_exec_sync: cdw12=%x\n", cmd->cdw12);
|
TRACE_VAL_F(cmd->cdw12, "%x");
|
||||||
TRACE("io_exec_sync: prp1=%x\n", cmd->prp1);
|
TRACE_VAL_F(cmd->prp1, "%x");
|
||||||
TRACE("io_exec_sync: prp2=%x\n", cmd->prp2);
|
TRACE_VAL_F(cmd->prp2, "%x");
|
||||||
|
|
||||||
memory_copy(cmd, sizeof(nvme_sqe_t), &io_sq[io_sq_tail]);
|
memory_copy(cmd, sizeof(nvme_sqe_t), &io_sq[io_sq_tail]);
|
||||||
|
|
||||||
TRACE("io_exec_sync: Advancing submission doorbell...\n");
|
TRACE_LN("Advancing submission doorbell...");
|
||||||
|
|
||||||
*(volatile uint32_t *)((uint8_t *)regs + 0x1008) = io_sq_tail = (io_sq_tail + 1) % QUEUE_DEPTH; // TODO Get offset from caps.
|
*(volatile uint32_t *)((uint8_t *)regs + 0x1008) = io_sq_tail = (io_sq_tail + 1) % QUEUE_DEPTH; // TODO Get offset from caps.
|
||||||
|
|
||||||
TRACE("io_exec_sync: Waiting for completion...\n");
|
TRACE_LN("Waiting for completion...");
|
||||||
|
nvme_cqe_t *cmp = &io_cq[io_cq_head];
|
||||||
while ((io_cq[io_cq_head].status & 1) != io_cq_phase)
|
while ((cmp->status & 1) != io_cq_phase)
|
||||||
;
|
;
|
||||||
|
|
||||||
TRACE("io_exec_sync: Received completion...\n");
|
TRACE_LN("Received completion...");
|
||||||
TRACE("io_exec_sync: dw0=%x\n", io_cq[io_cq_head].dw0);
|
TRACE_VAL_F(cmp->dw0, "%x");
|
||||||
TRACE("io_exec_sync: reserved=%x\n", io_cq[io_cq_head].reserved);
|
TRACE_VAL_F(cmp->reserved, "%x");
|
||||||
TRACE("io_exec_sync: sqhd=%x\n", io_cq[io_cq_head].sqhd);
|
TRACE_VAL_F(cmp->sqhd, "%hx");
|
||||||
TRACE("io_exec_sync: sqid=%x\n", io_cq[io_cq_head].sqid);
|
TRACE_VAL_F(cmp->sqid, "%hx");
|
||||||
TRACE("io_exec_sync: cid=%x\n", io_cq[io_cq_head].cid);
|
TRACE_VAL_F(cmp->cid, "%hx");
|
||||||
TRACE("io_exec_sync: status=%x\n", io_cq[io_cq_head].status);
|
TRACE_VAL_F(cmp->status, "%hx");
|
||||||
|
|
||||||
ASSERT((io_cq[io_cq_head].status >> 1) == 0, "io_exec_sync: NVMe command failed.");
|
ASSERT((cmp->status >> 1) == 0, "io_exec_sync: NVMe command failed.");
|
||||||
|
|
||||||
TRACE("io_exec_sync: Advancing completion doorbell...\n");
|
|
||||||
|
|
||||||
|
TRACE_LN("Advancing completion doorbell...");
|
||||||
*(volatile uint32_t *)((uint8_t *)regs + 0x100C) = io_cq_head = (io_cq_head + 1) % QUEUE_DEPTH; // TODO Get offset from caps.
|
*(volatile uint32_t *)((uint8_t *)regs + 0x100C) = io_cq_head = (io_cq_head + 1) % QUEUE_DEPTH; // TODO Get offset from caps.
|
||||||
|
|
||||||
io_cq_phase ^= (io_cq_head == 0);
|
io_cq_phase ^= (io_cq_head == 0);
|
||||||
|
|
||||||
TRACE("io_exec_sync: Done.\n");
|
TRACE_LN("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvme_init() {
|
void nvme_init() {
|
||||||
LOG("nvme_init: Searching for suitable device...\n");
|
LOG_LN("Searching for suitable device...");
|
||||||
uint8_t found = 0;
|
uint8_t found = 0;
|
||||||
for (uint16_t bus = 0; bus < 256 && !found; bus++) {
|
for (uint16_t bus = 0; bus < 256 && !found; bus++) {
|
||||||
for (uint8_t device = 0; device < 32 && !found; device++) {
|
for (uint8_t device = 0; device < 32 && !found; device++) {
|
||||||
@@ -169,11 +162,12 @@ void nvme_init() {
|
|||||||
uint32_t bar1 = pci_read((uint8_t)bus, device, function, 0x14);
|
uint32_t bar1 = pci_read((uint8_t)bus, device, function, 0x14);
|
||||||
uint64_t phys = ((uint64_t)bar1 << 32) | bar0;
|
uint64_t phys = ((uint64_t)bar1 << 32) | bar0;
|
||||||
|
|
||||||
LOG("nvme_init: Mapping device to memory, phys %x <-> virt %x\n", phys, regs);
|
LOG_LN("Mapping device to memory, phys %lx <-> virt %lx...", phys, regs);
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
memory_page_map((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)regs + i * PAGE_SIZE), (void *)((uint8_t *)phys + i * PAGE_SIZE),
|
memory_page_map((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)regs + i * PAGE_SIZE), (void *)((uint8_t *)phys + i * PAGE_SIZE),
|
||||||
PAGE_WRITABLE | PAGE_PCD | PAGE_USER);
|
PAGE_WRITABLE | PAGE_PCD | PAGE_USER);
|
||||||
}
|
}
|
||||||
|
|
||||||
found = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,27 +176,29 @@ void nvme_init() {
|
|||||||
ASSERT(found, "nvme_init: No suitable devices found.");
|
ASSERT(found, "nvme_init: No suitable devices found.");
|
||||||
ASSERT(regs->cap & (1ULL << 37), "nvme_init: NVM command set not supported.");
|
ASSERT(regs->cap & (1ULL << 37), "nvme_init: NVM command set not supported.");
|
||||||
|
|
||||||
LOG("nvme_init: Disabling device...\n");
|
LOG_LN("Disabling device...");
|
||||||
|
|
||||||
regs->cc = 0;
|
regs->cc = 0;
|
||||||
|
TRACE_VAL_F(regs->cc, "%lx");
|
||||||
while (regs->csts & 1)
|
while (regs->csts & 1)
|
||||||
;
|
;
|
||||||
|
TRACE_VAL_F(regs->cc, "%lx");
|
||||||
|
|
||||||
LOG("nvme_init: Configuring device...\n");
|
LOG_LN("Configuring device...");
|
||||||
regs->asq = (uint64_t)(VIRT_TO_PHYS(admin_sq));
|
regs->asq = (uint64_t)(VIRT_TO_PHYS(admin_sq));
|
||||||
TRACE("nvme_init: Setting ASQ, expected=%x, set=%x...\n", (uint64_t)(VIRT_TO_PHYS(admin_sq)), regs->asq);
|
|
||||||
regs->acq = (uint64_t)(VIRT_TO_PHYS(admin_cq));
|
regs->acq = (uint64_t)(VIRT_TO_PHYS(admin_cq));
|
||||||
TRACE("nvme_init: Setting ACQ, expected=%x, set=%x...\n", (uint64_t)(VIRT_TO_PHYS(admin_cq)), regs->acq);
|
|
||||||
regs->aqa = (QUEUE_DEPTH - 1) << 16 | (QUEUE_DEPTH - 1);
|
regs->aqa = (QUEUE_DEPTH - 1) << 16 | (QUEUE_DEPTH - 1);
|
||||||
TRACE("nvme_init: Setting AQA, expected=%x, set=%x...\n", (QUEUE_DEPTH - 1) << 16 | (QUEUE_DEPTH - 1), regs->aqa);
|
TRACE_VAL_F(regs->asq, "%lx");
|
||||||
|
TRACE_VAL_F(regs->acq, "%lx");
|
||||||
|
TRACE_VAL_F(regs->aqa, "%lx");
|
||||||
|
|
||||||
|
LOG_LN("Enabling device...");
|
||||||
regs->cc = (4 << 20) | (6 << 16) | (0 << 4) | 1;
|
regs->cc = (4 << 20) | (6 << 16) | (0 << 4) | 1;
|
||||||
LOG("nvme_init: Enabling device, expected=%x, set=%x...\n", (4 << 20) | (6 << 16) | (0 << 4) | 1, regs->cc);
|
TRACE_VAL_F(regs->cc, "%lx");
|
||||||
while (!(regs->csts & 1))
|
while (!(regs->csts & 1))
|
||||||
;
|
;
|
||||||
|
TRACE_VAL_F(regs->cc, "%lx");
|
||||||
|
|
||||||
LOG("nvme_init: Creating I/O completion queue...\n");
|
LOG_LN("Creating I/O completion queue...");
|
||||||
|
|
||||||
nvme_sqe_t create_io_cq = {
|
nvme_sqe_t create_io_cq = {
|
||||||
.opc = 0x05,
|
.opc = 0x05,
|
||||||
.prp1 = (uint64_t)VIRT_TO_PHYS(io_cq),
|
.prp1 = (uint64_t)VIRT_TO_PHYS(io_cq),
|
||||||
@@ -211,8 +207,7 @@ void nvme_init() {
|
|||||||
};
|
};
|
||||||
admin_exec_sync(&create_io_cq);
|
admin_exec_sync(&create_io_cq);
|
||||||
|
|
||||||
LOG("nvme_init: Creating I/O submission queue...\n");
|
LOG_LN("Creating I/O submission queue...");
|
||||||
|
|
||||||
nvme_sqe_t create_io_sq = {
|
nvme_sqe_t create_io_sq = {
|
||||||
.opc = 0x01,
|
.opc = 0x01,
|
||||||
.prp1 = (uint64_t)VIRT_TO_PHYS(io_sq),
|
.prp1 = (uint64_t)VIRT_TO_PHYS(io_sq),
|
||||||
@@ -221,11 +216,11 @@ void nvme_init() {
|
|||||||
};
|
};
|
||||||
admin_exec_sync(&create_io_sq);
|
admin_exec_sync(&create_io_sq);
|
||||||
|
|
||||||
LOG("nvme_init: Done.\n");
|
LOG_LN("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvme_read_sectors(uint32_t index, uint8_t count, void *to) {
|
void nvme_read_sectors(uint32_t index, uint8_t count, void *to) {
|
||||||
TRACE("nvme_read_sectors: Reading %u sectors at %u...\n", count, index);
|
TRACE_LN("Reading %u sectors at %u...", count, index);
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
uint64_t remainder = PAGE_SIZE - (uint64_t)to % PAGE_SIZE;
|
uint64_t remainder = PAGE_SIZE - (uint64_t)to % PAGE_SIZE;
|
||||||
@@ -249,11 +244,11 @@ void nvme_read_sectors(uint32_t index, uint8_t count, void *to) {
|
|||||||
to = (void *)((uint8_t *)to + i_count * SECTOR_SIZE);
|
to = (void *)((uint8_t *)to + i_count * SECTOR_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("nvme_read_sectors: Done.\n", count, index);
|
TRACE_LN("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvme_write_sectors(uint32_t index, uint8_t count, const void *from) {
|
void nvme_write_sectors(uint32_t index, uint8_t count, const void *from) {
|
||||||
TRACE("nvme_write_sectors: Reading %u sectors at %u...\n", count, index);
|
TRACE_LN("Writing %u sectors at %u...", count, index);
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
uint64_t remainder = PAGE_SIZE - (uint64_t)from % PAGE_SIZE;
|
uint64_t remainder = PAGE_SIZE - (uint64_t)from % PAGE_SIZE;
|
||||||
@@ -277,5 +272,5 @@ void nvme_write_sectors(uint32_t index, uint8_t count, const void *from) {
|
|||||||
from = (void *)((uint8_t *)from + i_count * SECTOR_SIZE);
|
from = (void *)((uint8_t *)from + i_count * SECTOR_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("nvme_write_sectors: Done.\n", count, index);
|
TRACE_LN("Done.");
|
||||||
}
|
}
|
||||||
|
|||||||
+193
-56
@@ -73,7 +73,7 @@ uint64_t string_split(char *string, char separator, uint64_t max, char **result)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result) {
|
uint64_t string_uint8_to_hex(uint8_t value, uint64_t max, char *result) {
|
||||||
if (max == 0) {
|
if (max == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result) {
|
|||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
while (value) {
|
while (value) {
|
||||||
uint8_t nibble = value & 0xF;
|
uint8_t nibble = value & 0xF;
|
||||||
tmp[i++] = nibble < 10 ? '0' + nibble : 'a' + nibble - 10;
|
tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
|
||||||
value >>= 4;
|
value >>= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +110,117 @@ uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result) {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t string_uint16_to_hex(uint16_t value, uint64_t max, char *result) {
|
||||||
|
if (max == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 1) {
|
||||||
|
result[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 2) {
|
||||||
|
result[0] = '0';
|
||||||
|
result[1] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp[5] = "0000";
|
||||||
|
|
||||||
|
uint8_t i = 0;
|
||||||
|
while (value) {
|
||||||
|
uint8_t nibble = value & 0xF;
|
||||||
|
tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[0] = '0';
|
||||||
|
result[1] = 'x';
|
||||||
|
|
||||||
|
i = 2;
|
||||||
|
while (i < 6 && i < max - 1) {
|
||||||
|
result[i] = tmp[5 - i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
result[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t string_uint32_to_hex(uint32_t value, uint64_t max, char *result) {
|
||||||
|
if (max == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 1) {
|
||||||
|
result[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 2) {
|
||||||
|
result[0] = '0';
|
||||||
|
result[1] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp[9] = "00000000";
|
||||||
|
|
||||||
|
uint8_t i = 0;
|
||||||
|
while (value) {
|
||||||
|
uint8_t nibble = value & 0xF;
|
||||||
|
tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[0] = '0';
|
||||||
|
result[1] = 'x';
|
||||||
|
|
||||||
|
i = 2;
|
||||||
|
while (i < 10 && i < max - 1) {
|
||||||
|
result[i] = tmp[9 - i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
result[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t string_uint64_to_hex(uint64_t value, uint64_t max, char *result) {
|
||||||
|
if (max == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 1) {
|
||||||
|
result[0] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max == 2) {
|
||||||
|
result[0] = '0';
|
||||||
|
result[1] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp[17] = "0000000000000000";
|
||||||
|
|
||||||
|
uint8_t i = 0;
|
||||||
|
while (value) {
|
||||||
|
uint8_t nibble = value & 0xF;
|
||||||
|
tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
|
||||||
|
value >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[0] = '0';
|
||||||
|
result[1] = 'x';
|
||||||
|
|
||||||
|
i = 2;
|
||||||
|
while (i < 18 && i < max - 1) {
|
||||||
|
result[i] = tmp[17 - i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
result[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t string_uint_to_decimal(uint64_t value, uint64_t max, char *result) {
|
uint64_t string_uint_to_decimal(uint64_t value, uint64_t max, char *result) {
|
||||||
if (max == 0) {
|
if (max == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -149,43 +260,6 @@ uint64_t string_int_to_decimal(int64_t value, uint64_t max, char *result) {
|
|||||||
return 1 + string_uint_to_decimal((uint64_t)(-value), max - 1, result + 1);
|
return 1 + string_uint_to_decimal((uint64_t)(-value), max - 1, result + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result) {
|
|
||||||
if (max == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max == 1) {
|
|
||||||
result[0] = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max == 2) {
|
|
||||||
result[0] = '0';
|
|
||||||
result[1] = '\0';
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char tmp[17] = "0000000000000000";
|
|
||||||
|
|
||||||
uint8_t i = 0;
|
|
||||||
while (value) {
|
|
||||||
uint8_t nibble = value & 0xF;
|
|
||||||
tmp[i++] = nibble < 10 ? '0' + nibble : 'A' + nibble - 10;
|
|
||||||
value >>= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
result[0] = '0';
|
|
||||||
result[1] = 'x';
|
|
||||||
|
|
||||||
i = 2;
|
|
||||||
while (i < 18 && i < max - 1) {
|
|
||||||
result[i] = tmp[17 - i];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
result[i] = '\0';
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t string_format(const char *format, uint64_t max, char *output, ...) {
|
uint64_t string_format(const char *format, uint64_t max, char *output, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, output);
|
va_start(args, output);
|
||||||
@@ -198,31 +272,19 @@ uint64_t string_format(const char *format, uint64_t max, char *output, ...) {
|
|||||||
output[ri++] = format[fi++];
|
output[ri++] = format[fi++];
|
||||||
} else {
|
} else {
|
||||||
switch (format[fi + 1]) {
|
switch (format[fi + 1]) {
|
||||||
case 'c':
|
case 'c': {
|
||||||
output[ri++] = (char)va_arg(args, int);
|
output[ri++] = (char)va_arg(args, int);
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
}
|
||||||
|
case 'd': {
|
||||||
string_int_to_decimal(va_arg(args, int64_t), limit - ri, output + ri);
|
string_int_to_decimal(va_arg(args, int64_t), limit - ri, output + ri);
|
||||||
while (output[ri]) {
|
while (output[ri]) {
|
||||||
ri++;
|
ri++;
|
||||||
}
|
}
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
}
|
||||||
string_uint_to_decimal(va_arg(args, uint64_t), limit - ri, output + ri);
|
|
||||||
while (output[ri]) {
|
|
||||||
ri++;
|
|
||||||
}
|
|
||||||
fi += 2;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
string_uint_to_hex(va_arg(args, uint64_t), limit - ri, output + ri);
|
|
||||||
while (output[ri]) {
|
|
||||||
ri++;
|
|
||||||
}
|
|
||||||
fi += 2;
|
|
||||||
break;
|
|
||||||
case 's': {
|
case 's': {
|
||||||
char *s = va_arg(args, char *);
|
char *s = va_arg(args, char *);
|
||||||
while (*s && ri < limit) {
|
while (*s && ri < limit) {
|
||||||
@@ -232,16 +294,91 @@ uint64_t string_format(const char *format, uint64_t max, char *output, ...) {
|
|||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'u': {
|
||||||
|
string_uint_to_decimal(va_arg(args, uint64_t), limit - ri, output + ri);
|
||||||
|
while (output[ri]) {
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
fi += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x': {
|
||||||
|
string_uint32_to_hex(va_arg(args, uint32_t), limit - ri, output + ri);
|
||||||
|
while (output[ri]) {
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
fi += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case '%': {
|
case '%': {
|
||||||
output[ri++] = '%';
|
output[ri++] = '%';
|
||||||
fi += 2;
|
fi += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
case 'h': {
|
||||||
|
switch (format[fi + 2]) {
|
||||||
|
case 'x': {
|
||||||
|
string_uint16_to_hex(va_arg(args, uint64_t), limit - ri, output + ri);
|
||||||
|
while (output[ri]) {
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
fi += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'h': {
|
||||||
|
switch (format[fi + 3]) {
|
||||||
|
case 'x': {
|
||||||
|
string_uint8_to_hex(va_arg(args, uint64_t), limit - ri, output + ri);
|
||||||
|
while (output[ri]) {
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
fi += 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l': {
|
||||||
|
switch (format[fi + 2]) {
|
||||||
|
case 'x': {
|
||||||
|
string_uint64_to_hex(va_arg(args, uint64_t), limit - ri, output + ri);
|
||||||
|
while (output[ri]) {
|
||||||
|
ri++;
|
||||||
|
}
|
||||||
|
fi += 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
output[ri++] = format[fi++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
output[ri++] = format[fi++];
|
output[ri++] = format[fi++];
|
||||||
output[ri++] = format[fi++];
|
output[ri++] = format[fi++];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output[ri] = '\0';
|
output[ri] = '\0';
|
||||||
|
|||||||
+7
-3
@@ -14,12 +14,16 @@ uint64_t string_trim(char *string, char character, char **result);
|
|||||||
|
|
||||||
uint64_t string_split(char *string, char separator, uint64_t max, char **result);
|
uint64_t string_split(char *string, char separator, uint64_t max, char **result);
|
||||||
|
|
||||||
uint64_t string_byte_to_hex(uint8_t value, uint64_t max, char *result);
|
uint64_t string_uint8_to_hex(uint8_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
|
uint64_t string_uint16_to_hex(uint16_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
|
uint64_t string_uint32_to_hex(uint32_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
|
uint64_t string_uint64_to_hex(uint64_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
uint64_t string_uint_to_decimal(uint64_t value, uint64_t max, char *result);
|
uint64_t string_uint_to_decimal(uint64_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
uint64_t string_int_to_decimal(int64_t value, uint64_t max, char *result);
|
uint64_t string_int_to_decimal(int64_t value, uint64_t max, char *result);
|
||||||
|
|
||||||
uint64_t string_uint_to_hex(uint64_t value, uint64_t max, char *result);
|
|
||||||
|
|
||||||
uint64_t string_format(const char *format, uint64_t max, char *output, ...);
|
uint64_t string_format(const char *format, uint64_t max, char *output, ...);
|
||||||
|
|||||||
Reference in New Issue
Block a user