Add more logging levels
This commit is contained in:
@@ -3,7 +3,16 @@ set -euo pipefail
|
|||||||
|
|
||||||
export CC=clang
|
export CC=clang
|
||||||
|
|
||||||
meson setup build --reconfigure
|
LOG_LEVEL=1
|
||||||
|
for arg in "${@}"; do
|
||||||
|
case "${arg}" in
|
||||||
|
-v) LOG_LEVEL=2 ;;
|
||||||
|
-vv) LOG_LEVEL=3 ;;
|
||||||
|
-vvv) LOG_LEVEL=4 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
meson setup build --reconfigure -Dc_args="-DLOG_LEVEL=${LOG_LEVEL}"
|
||||||
meson compile -v -C build
|
meson compile -v -C build
|
||||||
|
|
||||||
sector_size=512
|
sector_size=512
|
||||||
|
|||||||
+40
-14
@@ -6,6 +6,15 @@
|
|||||||
|
|
||||||
extern stream_t *kernel_log;
|
extern stream_t *kernel_log;
|
||||||
|
|
||||||
|
#ifndef LOG_LEVEL
|
||||||
|
#define LOG_LEVEL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOG_LEVEL_INFO 1
|
||||||
|
#define LOG_LEVEL_STEP 2
|
||||||
|
#define LOG_LEVEL_DATA 3
|
||||||
|
#define LOG_LEVEL_TRACE 4
|
||||||
|
|
||||||
#define PRINT(stream, fmt, ...) \
|
#define PRINT(stream, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
uint64_t _size = string_length(fmt) * 10; \
|
uint64_t _size = string_length(fmt) * 10; \
|
||||||
@@ -13,7 +22,7 @@ extern stream_t *kernel_log;
|
|||||||
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
_size = string_format(fmt, _size, _string, ##__VA_ARGS__); \
|
||||||
stream->write(stream, _string, _size); \
|
stream->write(stream, _string, _size); \
|
||||||
memory_free(_string); \
|
memory_free(_string); \
|
||||||
} while (0)
|
} while (0);
|
||||||
|
|
||||||
#define PRINT_LN(stream, fmt, ...) \
|
#define PRINT_LN(stream, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
@@ -25,22 +34,39 @@ extern stream_t *kernel_log;
|
|||||||
stream->write(stream, _string, _size); \
|
stream->write(stream, _string, _size); \
|
||||||
stream->write(stream, "\n", 1); \
|
stream->write(stream, "\n", 1); \
|
||||||
memory_free(_string); \
|
memory_free(_string); \
|
||||||
} while (0)
|
} while (0);
|
||||||
|
|
||||||
#define LOG(fmt, ...) PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
#define PRINT_VAL(stream, v, f) PRINT_LN(#v = f, v)
|
||||||
|
|
||||||
#define TRACE(fmt, ...)
|
#define LOG_INFO(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_INFO) \
|
||||||
|
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_STEP(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_STEP) \
|
||||||
|
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_DATA(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_DATA) \
|
||||||
|
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_TRACE(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_TRACE) \
|
||||||
|
PRINT(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define LOG_LN(fmt, ...) PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
#define LOG_LN_INFO(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_INFO) \
|
||||||
|
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_LN_STEP(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_STEP) \
|
||||||
|
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_LN_DATA(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_DATA) \
|
||||||
|
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
#define LOG_LN_TRACE(fmt, ...) \
|
||||||
|
if (LOG_LEVEL >= LOG_LEVEL_TRACE) \
|
||||||
|
PRINT_LN(kernel_log, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define LOG_VAL(v) LOG_LN(#v "=%x")
|
#define LOG_VAL_INFO(v, f) LOG_LN_INFO(#v "=" f, v)
|
||||||
|
#define LOG_VAL_STEP(v, f) LOG_LN_STEP(#v "=" f, v)
|
||||||
#define LOG_VAL_F(v, f) LOG_LN(#v "=" f, v)
|
#define LOG_VAL_DATA(v, f) LOG_LN_DATA(#v "=" f, v)
|
||||||
|
#define LOG_VAL_TRACE(v, f) LOG_LN_TRACE(#v "=" f, v)
|
||||||
#define TRACE_LN(fmt, ...)
|
|
||||||
|
|
||||||
#define TRACE_VAL(v) TRACE_LN(#v "=%lx")
|
|
||||||
|
|
||||||
#define TRACE_VAL_F(v, f) TRACE_LN(#v "=" f, v)
|
|
||||||
|
|
||||||
void log_init(stream_t *log);
|
void log_init(stream_t *log);
|
||||||
|
|||||||
+7
-7
@@ -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_LN("Mapping physical %lx to virtual %lx / [%u, %u, %u, %u]...", phys, virt, pml4_index, pdpt_index, pd_index, pt_index);
|
LOG_LN_TRACE("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_LN("PML4 entry %u does not exist, creating...", pml4_index);
|
LOG_LN_TRACE("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_LN("PDPT entry %u does not exist, creating...", pdpt_index);
|
LOG_LN_TRACE("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_LN("PD entry %u does not exist, creating...", pd_index);
|
LOG_LN_TRACE("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,11 +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_LN("PT entry %u does not exist, creating...", pt_index);
|
LOG_LN_TRACE("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]);
|
LOG_VAL_TRACE(pt[pt_index], "%lx");
|
||||||
|
|
||||||
TRACE_LN("Done.");
|
LOG_LN_TRACE("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_page_unmap(uint64_t *pml4, void *virt) {
|
void memory_page_unmap(uint64_t *pml4, void *virt) {
|
||||||
|
|||||||
+58
-58
@@ -89,118 +89,118 @@ 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_LN("Queueing submission...");
|
LOG_LN_STEP("Queueing submission...");
|
||||||
TRACE_VAL_F(cmd->opc, "%hhx");
|
LOG_VAL_TRACE(cmd->opc, "%hhx");
|
||||||
TRACE_VAL_F(cmd->nsid, "%x");
|
LOG_VAL_TRACE(cmd->nsid, "%x");
|
||||||
TRACE_VAL_F(cmd->cdw10, "%x");
|
LOG_VAL_TRACE(cmd->cdw10, "%x");
|
||||||
TRACE_VAL_F(cmd->cdw11, "%x");
|
LOG_VAL_TRACE(cmd->cdw11, "%x");
|
||||||
TRACE_VAL_F(cmd->cdw12, "%x");
|
LOG_VAL_TRACE(cmd->cdw12, "%x");
|
||||||
TRACE_VAL_F(cmd->prp1, "%lx");
|
LOG_VAL_TRACE(cmd->prp1, "%lx");
|
||||||
TRACE_VAL_F(cmd->prp2, "%lx");
|
LOG_VAL_TRACE(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_LN("Advancing submission doorbell...");
|
LOG_LN_STEP("Advancing submission doorbell...");
|
||||||
db_regs[0] = admin_sq_tail = (admin_sq_tail + 1) % QUEUE_DEPTH;
|
db_regs[0] = admin_sq_tail = (admin_sq_tail + 1) % QUEUE_DEPTH;
|
||||||
TRACE_VAL_F(admin_sq_tail, "%u");
|
LOG_VAL_TRACE(admin_sq_tail, "%u");
|
||||||
|
|
||||||
TRACE_LN("Waiting for completion...");
|
LOG_LN_STEP("Waiting for completion...");
|
||||||
nvme_cqe_t *cmp = &admin_cq[admin_cq_head];
|
nvme_cqe_t *cmp = &admin_cq[admin_cq_head];
|
||||||
while (NVME_CQE_P(cmp) != admin_cq_phase)
|
while (NVME_CQE_P(cmp) != admin_cq_phase)
|
||||||
;
|
;
|
||||||
|
|
||||||
TRACE_LN("Received completion...");
|
LOG_LN_STEP("Received completion...");
|
||||||
TRACE_VAL_F(cmp->dw0, "%x");
|
LOG_VAL_TRACE(cmp->dw0, "%x");
|
||||||
TRACE_VAL_F(cmp->reserved, "%x");
|
LOG_VAL_TRACE(cmp->reserved, "%x");
|
||||||
TRACE_VAL_F(cmp->sqhd, "%hx");
|
LOG_VAL_TRACE(cmp->sqhd, "%hx");
|
||||||
TRACE_VAL_F(cmp->sqid, "%hx");
|
LOG_VAL_TRACE(cmp->sqid, "%hx");
|
||||||
TRACE_VAL_F(cmp->cid, "%hx");
|
LOG_VAL_TRACE(cmp->cid, "%hx");
|
||||||
TRACE_VAL_F(cmp->status, "%hx");
|
LOG_VAL_TRACE(cmp->status, "%hx");
|
||||||
ASSERT(NVME_CQE_STATUS(cmp) == 0, "admin_exec_sync: NVMe command failed.");
|
ASSERT(NVME_CQE_STATUS(cmp) == 0, "admin_exec_sync: NVMe command failed.");
|
||||||
|
|
||||||
TRACE_LN("Advancing completion doorbell...");
|
LOG_LN_STEP("Advancing completion doorbell...");
|
||||||
db_regs[1] = admin_cq_head = (admin_cq_head + 1) % QUEUE_DEPTH;
|
db_regs[1] = admin_cq_head = (admin_cq_head + 1) % QUEUE_DEPTH;
|
||||||
admin_cq_phase ^= (admin_cq_head == 0);
|
admin_cq_phase ^= (admin_cq_head == 0);
|
||||||
|
|
||||||
TRACE_LN("Done.");
|
LOG_LN_STEP("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_LN("Queueing submission...");
|
LOG_LN_STEP("Queueing submission...");
|
||||||
TRACE_VAL_F(cmd->opc, "%hhx");
|
LOG_VAL_TRACE(cmd->opc, "%hhx");
|
||||||
TRACE_VAL_F(cmd->nsid, "%x");
|
LOG_VAL_TRACE(cmd->nsid, "%x");
|
||||||
TRACE_VAL_F(cmd->cdw10, "%x");
|
LOG_VAL_TRACE(cmd->cdw10, "%x");
|
||||||
TRACE_VAL_F(cmd->cdw11, "%x");
|
LOG_VAL_TRACE(cmd->cdw11, "%x");
|
||||||
TRACE_VAL_F(cmd->cdw12, "%x");
|
LOG_VAL_TRACE(cmd->cdw12, "%x");
|
||||||
TRACE_VAL_F(cmd->prp1, "%x");
|
LOG_VAL_TRACE(cmd->prp1, "%x");
|
||||||
TRACE_VAL_F(cmd->prp2, "%x");
|
LOG_VAL_TRACE(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_LN("Advancing submission doorbell...");
|
LOG_LN_STEP("Advancing submission doorbell...");
|
||||||
db_regs[2] = io_sq_tail = (io_sq_tail + 1) % QUEUE_DEPTH;
|
db_regs[2] = io_sq_tail = (io_sq_tail + 1) % QUEUE_DEPTH;
|
||||||
|
|
||||||
TRACE_LN("Waiting for completion...");
|
LOG_LN_STEP("Waiting for completion...");
|
||||||
nvme_cqe_t *cmp = &io_cq[io_cq_head];
|
nvme_cqe_t *cmp = &io_cq[io_cq_head];
|
||||||
while (NVME_CQE_P(cmp) != io_cq_phase)
|
while (NVME_CQE_P(cmp) != io_cq_phase)
|
||||||
;
|
;
|
||||||
|
|
||||||
TRACE_LN("Received completion...");
|
LOG_LN_STEP("Received completion...");
|
||||||
TRACE_VAL_F(cmp->dw0, "%x");
|
LOG_VAL_TRACE(cmp->dw0, "%x");
|
||||||
TRACE_VAL_F(cmp->reserved, "%x");
|
LOG_VAL_TRACE(cmp->reserved, "%x");
|
||||||
TRACE_VAL_F(cmp->sqhd, "%hx");
|
LOG_VAL_TRACE(cmp->sqhd, "%hx");
|
||||||
TRACE_VAL_F(cmp->sqid, "%hx");
|
LOG_VAL_TRACE(cmp->sqid, "%hx");
|
||||||
TRACE_VAL_F(cmp->cid, "%hx");
|
LOG_VAL_TRACE(cmp->cid, "%hx");
|
||||||
TRACE_VAL_F(cmp->status, "%hx");
|
LOG_VAL_TRACE(cmp->status, "%hx");
|
||||||
|
|
||||||
ASSERT(NVME_CQE_STATUS(cmp) == 0, "io_exec_sync: NVMe command failed.");
|
ASSERT(NVME_CQE_STATUS(cmp) == 0, "io_exec_sync: NVMe command failed.");
|
||||||
|
|
||||||
TRACE_LN("Advancing completion doorbell...");
|
LOG_LN_STEP("Advancing completion doorbell...");
|
||||||
db_regs[3] = io_cq_head = (io_cq_head + 1) % QUEUE_DEPTH;
|
db_regs[3] = io_cq_head = (io_cq_head + 1) % QUEUE_DEPTH;
|
||||||
io_cq_phase ^= (io_cq_head == 0);
|
io_cq_phase ^= (io_cq_head == 0);
|
||||||
|
|
||||||
TRACE_LN("Done.");
|
LOG_LN_STEP("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvme_init() {
|
void nvme_init() {
|
||||||
TRACE_LN("Searching for suitable device...");
|
LOG_LN_INFO("Searching for suitable device...");
|
||||||
pci_bdf_t bdf = pci_find_by_class(NVME_PCI_CLASS, NVME_PCI_SUBCLASS, NUL);
|
pci_bdf_t bdf = pci_find_by_class(NVME_PCI_CLASS, NVME_PCI_SUBCLASS, NUL);
|
||||||
ASSERT(bdf, "nvme_init: No suitable devices found.");
|
ASSERT(bdf, "nvme_init: No suitable devices found.");
|
||||||
|
|
||||||
TRACE_LN("Mapping device to virtual memory...");
|
LOG_LN_INFO("Mapping device to virtual memory...");
|
||||||
pci_map(bdf, regs, 4);
|
pci_map(bdf, regs, 4);
|
||||||
ASSERT(NVME_REGS_NVME_CS_SUPPORTED(regs), "nvme_init: NVM command set not supported.");
|
ASSERT(NVME_REGS_NVME_CS_SUPPORTED(regs), "nvme_init: NVM command set not supported.");
|
||||||
ASSERT(QUEUE_DEPTH <= NVME_REGS_MQES(regs), "nvme_init: Command queues are too big.")
|
ASSERT(QUEUE_DEPTH <= NVME_REGS_MQES(regs), "nvme_init: Command queues are too big.")
|
||||||
|
|
||||||
TRACE_LN("Disabling device...");
|
LOG_LN_INFO("Disabling device...");
|
||||||
regs->cc = 0;
|
regs->cc = 0;
|
||||||
TRACE_VAL_F(regs->cc, "%lx");
|
LOG_VAL_DATA(regs->cc, "%lx");
|
||||||
while (NVME_REGS_RDY(regs))
|
while (NVME_REGS_RDY(regs))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(regs->cc, "%lx");
|
LOG_VAL_DATA(regs->cc, "%lx");
|
||||||
|
|
||||||
TRACE_LN("Configuring device...");
|
LOG_LN_INFO("Configuring device...");
|
||||||
NVME_REGS_ASQS_W(regs, QUEUE_DEPTH - 1);
|
NVME_REGS_ASQS_W(regs, QUEUE_DEPTH - 1);
|
||||||
regs->asq = (uint64_t)(VIRT_TO_PHYS(admin_sq));
|
regs->asq = (uint64_t)(VIRT_TO_PHYS(admin_sq));
|
||||||
NVME_REGS_ACQS_W(regs, QUEUE_DEPTH - 1);
|
NVME_REGS_ACQS_W(regs, QUEUE_DEPTH - 1);
|
||||||
regs->acq = (uint64_t)(VIRT_TO_PHYS(admin_cq));
|
regs->acq = (uint64_t)(VIRT_TO_PHYS(admin_cq));
|
||||||
TRACE_VAL_F(regs->asq, "%lx");
|
LOG_VAL_DATA(regs->asq, "%lx");
|
||||||
TRACE_VAL_F(regs->acq, "%lx");
|
LOG_VAL_DATA(regs->acq, "%lx");
|
||||||
TRACE_VAL_F(regs->aqa, "%lx");
|
LOG_VAL_DATA(regs->aqa, "%lx");
|
||||||
|
|
||||||
TRACE_LN("Enabling device...");
|
LOG_LN_INFO("Enabling device...");
|
||||||
NVME_REGS_IOCQES_W(regs, 4);
|
NVME_REGS_IOCQES_W(regs, 4);
|
||||||
NVME_REGS_IOSQES_W(regs, 6);
|
NVME_REGS_IOSQES_W(regs, 6);
|
||||||
NVME_REGS_CSS_W(regs, 0);
|
NVME_REGS_CSS_W(regs, 0);
|
||||||
NVME_REGS_EN_W(regs, 1);
|
NVME_REGS_EN_W(regs, 1);
|
||||||
TRACE_VAL_F(regs->cc, "%lx");
|
LOG_VAL_DATA(regs->cc, "%lx");
|
||||||
while (!NVME_REGS_RDY(regs))
|
while (!NVME_REGS_RDY(regs))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(regs->cc, "%lx");
|
LOG_VAL_DATA(regs->cc, "%lx");
|
||||||
|
|
||||||
TRACE_LN("Creating I/O completion queue...");
|
LOG_LN_INFO("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),
|
||||||
@@ -209,7 +209,7 @@ void nvme_init() {
|
|||||||
};
|
};
|
||||||
admin_exec_sync(&create_io_cq);
|
admin_exec_sync(&create_io_cq);
|
||||||
|
|
||||||
TRACE_LN("Creating I/O submission queue...");
|
LOG_LN_INFO("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),
|
||||||
@@ -218,11 +218,11 @@ void nvme_init() {
|
|||||||
};
|
};
|
||||||
admin_exec_sync(&create_io_sq);
|
admin_exec_sync(&create_io_sq);
|
||||||
|
|
||||||
TRACE_LN("Done.");
|
LOG_LN_INFO("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_LN("Reading %u sectors at %u...", count, index);
|
LOG_LN_STEP("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;
|
||||||
@@ -246,11 +246,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_LN("Done.");
|
LOG_LN_STEP("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_LN("Writing %u sectors at %u...", count, index);
|
LOG_LN_STEP("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;
|
||||||
@@ -274,5 +274,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_LN("Done.");
|
LOG_LN_STEP("Done.");
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -46,9 +46,9 @@ static void pci_write(pci_bdf_t bdf, uint8_t offset, uint32_t value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pci_init() {
|
void pci_init() {
|
||||||
LOG_LN("Scanning devices...");
|
PRINT_LN(kernel_log, "Scanning devices...");
|
||||||
pci_enumerate(kernel_log);
|
pci_enumerate(kernel_log);
|
||||||
LOG_LN("Done.");
|
PRINT_LN(kernel_log, "Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_enumerate(stream_t *out) {
|
void pci_enumerate(stream_t *out) {
|
||||||
@@ -60,8 +60,8 @@ void pci_enumerate(stream_t *out) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
uint32_t class = pci_read(PCI_BDF(b, d, f), PCI_OFFSET_CLASS_REVISION);
|
uint32_t class = pci_read(PCI_BDF(b, d, f), PCI_OFFSET_CLASS_REVISION);
|
||||||
PRINT_LN(out, "%hx:%hx class=%hhx subclass=%hhx iface=%hhx.", PCI_VENDOR(id), PCI_DEVICE(id), PCI_CLASS(class),
|
PRINT_LN(out, "%hx:%hx class=%hhx subclass=%hhx iface=%hhx.", PCI_VENDOR(id), PCI_DEVICE(id), PCI_CLASS(class), PCI_SUBCLASS(class),
|
||||||
PCI_SUBCLASS(class), PCI_INTERFACE(class));
|
PCI_INTERFACE(class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ void pci_map(pci_bdf_t bdf, volatile void *virt, uint8_t pages) {
|
|||||||
|
|
||||||
uint64_t bar = ((uint64_t)pci_read(bdf, PCI_OFFSET_BAR_1) << 32) | (pci_read(bdf, PCI_OFFSET_BAR_0) & 0xFFFFFFF0);
|
uint64_t bar = ((uint64_t)pci_read(bdf, PCI_OFFSET_BAR_1) << 32) | (pci_read(bdf, PCI_OFFSET_BAR_0) & 0xFFFFFFF0);
|
||||||
|
|
||||||
LOG_LN("Mapping BAR to memory, phys %lx <-> virt %lx...", bar, virt);
|
LOG_LN_STEP("Mapping BAR to memory, phys %lx <-> virt %lx...", bar, virt);
|
||||||
for (uint8_t i = 0; i < pages; i++) {
|
for (uint8_t i = 0; i < pages; i++) {
|
||||||
memory_page_map((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)virt + i * PAGE_SIZE), (void *)((uint8_t *)bar + i * PAGE_SIZE),
|
memory_page_map((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)virt + i * PAGE_SIZE), (void *)((uint8_t *)bar + i * PAGE_SIZE),
|
||||||
PAGE_WRITABLE | PAGE_PCD | PAGE_USER);
|
PAGE_WRITABLE | PAGE_PCD | PAGE_USER);
|
||||||
@@ -101,7 +101,7 @@ void pci_map(pci_bdf_t bdf, volatile void *virt, uint8_t pages) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pci_unmap(pci_bdf_t bdf, volatile void *virt, uint8_t pages) {
|
void pci_unmap(pci_bdf_t bdf, volatile void *virt, uint8_t pages) {
|
||||||
LOG_LN("Unmapping BAR from memory, virt %lx...", virt);
|
LOG_LN_STEP("Unmapping BAR from memory, virt %lx...", virt);
|
||||||
for (uint8_t i = 0; i < pages; i++) {
|
for (uint8_t i = 0; i < pages; i++) {
|
||||||
memory_page_unmap((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)virt + i * PAGE_SIZE));
|
memory_page_unmap((void *)KERNEL_VIRTUAL_PML4, (void *)((uint8_t *)virt + i * PAGE_SIZE));
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -23,9 +23,9 @@ typedef struct __attribute__((packed)) {
|
|||||||
static usb_device_descriptor_t device_descriptor __attribute__((aligned(64)));
|
static usb_device_descriptor_t device_descriptor __attribute__((aligned(64)));
|
||||||
|
|
||||||
void usb_init() {
|
void usb_init() {
|
||||||
LOG_LN("Enumerating devices...");
|
PRINT_LN(kernel_log, "Enumerating devices...");
|
||||||
usb_enumerate(kernel_log);
|
usb_enumerate(kernel_log);
|
||||||
LOG_LN("Done.");
|
PRINT_LN(kernel_log, "Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_enumerate(stream_t *out) {
|
void usb_enumerate(stream_t *out) {
|
||||||
|
|||||||
+92
-81
@@ -199,10 +199,10 @@ static uint8_t tr_i = 0;
|
|||||||
static xhci_trb_t tr[RING_LENGTH + 1] __attribute__((aligned(PAGE_SIZE)));
|
static xhci_trb_t tr[RING_LENGTH + 1] __attribute__((aligned(PAGE_SIZE)));
|
||||||
|
|
||||||
static const xhci_trb_t *command_exec_sync(const xhci_trb_t *cmd) {
|
static const xhci_trb_t *command_exec_sync(const xhci_trb_t *cmd) {
|
||||||
LOG_LN("Queueing command TRB...");
|
LOG_LN_STEP("Queueing command TRB...");
|
||||||
LOG_VAL_F(cmd->parameter, "%lx");
|
LOG_VAL_TRACE(cmd->parameter, "%lx");
|
||||||
LOG_VAL_F(cmd->status, "%x");
|
LOG_VAL_TRACE(cmd->status, "%x");
|
||||||
LOG_VAL_F(cmd->control, "%x");
|
LOG_VAL_TRACE(cmd->control, "%x");
|
||||||
|
|
||||||
xhci_trb_t *cre = &cr[cr_i];
|
xhci_trb_t *cre = &cr[cr_i];
|
||||||
|
|
||||||
@@ -213,12 +213,12 @@ static const xhci_trb_t *command_exec_sync(const xhci_trb_t *cmd) {
|
|||||||
XHCI_TRB_CYCLE_W((&cr[RING_LENGTH]), cr_cycle);
|
XHCI_TRB_CYCLE_W((&cr[RING_LENGTH]), cr_cycle);
|
||||||
cr_cycle ^= (cr_i == 0);
|
cr_cycle ^= (cr_i == 0);
|
||||||
|
|
||||||
LOG_LN("Ringing command doorbell...");
|
LOG_LN_STEP("Ringing command doorbell...");
|
||||||
LOG_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_TRACE(op_regs->usbsts, "%x");
|
||||||
db_regs[0] = 0;
|
db_regs[0] = 0;
|
||||||
LOG_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_TRACE(op_regs->usbsts, "%x");
|
||||||
|
|
||||||
LOG_LN("Waiting for completion...");
|
LOG_LN_STEP("Waiting for completion...");
|
||||||
while (1) {
|
while (1) {
|
||||||
xhci_trb_t *cmp = &er[er_i];
|
xhci_trb_t *cmp = &er[er_i];
|
||||||
while (XHCI_TRB_CYCLE_R(cmp) != er_cycle)
|
while (XHCI_TRB_CYCLE_R(cmp) != er_cycle)
|
||||||
@@ -229,75 +229,77 @@ static const xhci_trb_t *command_exec_sync(const xhci_trb_t *cmd) {
|
|||||||
er_cycle ^= (er_i == 0);
|
er_cycle ^= (er_i == 0);
|
||||||
|
|
||||||
if (XHCI_TRB_TRB_TYPE_R(cmp) != XHCI_TRB_TYPE_EVENT_COMMAND_COMPLETION || (void *)cmp->parameter != VIRT_TO_PHYS(cre)) {
|
if (XHCI_TRB_TRB_TYPE_R(cmp) != XHCI_TRB_TYPE_EVENT_COMMAND_COMPLETION || (void *)cmp->parameter != VIRT_TO_PHYS(cre)) {
|
||||||
LOG_LN("Received irrelevant event, skipping...");
|
LOG_LN_STEP("Received irrelevant event, skipping...");
|
||||||
} else {
|
} else {
|
||||||
LOG_LN("Received command completion event...");
|
LOG_LN_STEP("Received command completion event...");
|
||||||
|
|
||||||
LOG_VAL_F(cmp->parameter, "%lx");
|
LOG_VAL_TRACE(cmp->parameter, "%lx");
|
||||||
LOG_VAL_F(cmp->status, "%x");
|
LOG_VAL_TRACE(cmp->status, "%x");
|
||||||
LOG_VAL_F(cmp->control, "%x");
|
LOG_VAL_TRACE(cmp->control, "%x");
|
||||||
|
|
||||||
ASSERT(XHCI_TRB_COMPLETION_CODE(cmp) == 1, "command_exec_sync: Command failed.");
|
ASSERT(XHCI_TRB_COMPLETION_CODE(cmp) == 1, "command_exec_sync: Command failed.");
|
||||||
|
|
||||||
|
LOG_LN_STEP("Done.");
|
||||||
|
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xhci_init() {
|
void xhci_init() {
|
||||||
TRACE_LN("Searching for suitable controller...");
|
LOG_LN_INFO("Searching for suitable controller...");
|
||||||
pci_bdf_t bdf = pci_find_by_class(XHCI_PCI_CLASS, XHCI_PCI_SUBCLASS, XHCI_PCI_INTERFACE);
|
pci_bdf_t bdf = pci_find_by_class(XHCI_PCI_CLASS, XHCI_PCI_SUBCLASS, XHCI_PCI_INTERFACE);
|
||||||
ASSERT(bdf, "xhci_init: No suitable controllers found.");
|
ASSERT(bdf, "xhci_init: No suitable controllers found.");
|
||||||
|
|
||||||
TRACE_LN("Mapping controller to virtual memory...");
|
LOG_LN_INFO("Mapping controller to virtual memory...");
|
||||||
pci_map(bdf, cap_regs, 4);
|
pci_map(bdf, cap_regs, 4);
|
||||||
op_regs = (xhci_op_regs_t *)((uint8_t *)cap_regs + cap_regs->caplength);
|
op_regs = (xhci_op_regs_t *)((uint8_t *)cap_regs + cap_regs->caplength);
|
||||||
port_regs = (xhci_port_regs_t *)((uint8_t *)cap_regs + cap_regs->caplength + 0x400);
|
port_regs = (xhci_port_regs_t *)((uint8_t *)cap_regs + cap_regs->caplength + 0x400);
|
||||||
intr_regs = (xhci_intr_regs_t *)((uint8_t *)cap_regs + cap_regs->rtsoff + 0x20);
|
intr_regs = (xhci_intr_regs_t *)((uint8_t *)cap_regs + cap_regs->rtsoff + 0x20);
|
||||||
db_regs = (uint32_t *)((uint8_t *)cap_regs + cap_regs->dboff);
|
db_regs = (uint32_t *)((uint8_t *)cap_regs + cap_regs->dboff);
|
||||||
|
|
||||||
TRACE_VAL_F(cap_regs->caplength, "%hhx");
|
LOG_VAL_DATA(cap_regs->caplength, "%hhx");
|
||||||
TRACE_VAL_F(cap_regs->hciversion, "%hx");
|
LOG_VAL_DATA(cap_regs->hciversion, "%hx");
|
||||||
TRACE_VAL_F(cap_regs->hcsparams1, "%x");
|
LOG_VAL_DATA(cap_regs->hcsparams1, "%x");
|
||||||
TRACE_VAL_F(cap_regs->hcsparams2, "%x");
|
LOG_VAL_DATA(cap_regs->hcsparams2, "%x");
|
||||||
TRACE_VAL_F(cap_regs->hcsparams3, "%x");
|
LOG_VAL_DATA(cap_regs->hcsparams3, "%x");
|
||||||
TRACE_VAL_F(cap_regs->hccparams1, "%x");
|
LOG_VAL_DATA(cap_regs->hccparams1, "%x");
|
||||||
TRACE_VAL_F(cap_regs->dboff, "%x");
|
LOG_VAL_DATA(cap_regs->dboff, "%x");
|
||||||
TRACE_VAL_F(cap_regs->rtsoff, "%x");
|
LOG_VAL_DATA(cap_regs->rtsoff, "%x");
|
||||||
TRACE_VAL_F(cap_regs->hccparams2, "%x");
|
LOG_VAL_DATA(cap_regs->hccparams2, "%x");
|
||||||
|
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
TRACE_VAL_F(op_regs->pagesize, "%x");
|
LOG_VAL_DATA(op_regs->pagesize, "%x");
|
||||||
TRACE_VAL_F(op_regs->dnctrl, "%x");
|
LOG_VAL_DATA(op_regs->dnctrl, "%x");
|
||||||
TRACE_VAL_F(op_regs->crcr, "%lx");
|
LOG_VAL_DATA(op_regs->crcr, "%lx");
|
||||||
TRACE_VAL_F(op_regs->dcbaap, "%lx");
|
LOG_VAL_DATA(op_regs->dcbaap, "%lx");
|
||||||
TRACE_VAL_F(op_regs->config, "%x");
|
LOG_VAL_DATA(op_regs->config, "%x");
|
||||||
|
|
||||||
TRACE_LN("Stopping controller...");
|
LOG_LN_INFO("Stopping controller...");
|
||||||
XHCI_OP_REGS_RS_W(op_regs, 0);
|
XHCI_OP_REGS_RS_W(op_regs, 0);
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
while (!XHCI_OP_REGS_HCH(op_regs))
|
while (!XHCI_OP_REGS_HCH(op_regs))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
|
|
||||||
TRACE_LN("Resetting controller...");
|
LOG_LN_INFO("Resetting controller...");
|
||||||
XHCI_OP_REGS_EINT_W(op_regs, 0);
|
XHCI_OP_REGS_EINT_W(op_regs, 0);
|
||||||
XHCI_OP_REGS_HCRST_W(op_regs, 1);
|
XHCI_OP_REGS_HCRST_W(op_regs, 1);
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
while (XHCI_OP_REGS_HCRST_R(op_regs))
|
while (XHCI_OP_REGS_HCRST_R(op_regs))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
while (XHCI_OP_REGS_CNR(op_regs))
|
while (XHCI_OP_REGS_CNR(op_regs))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
|
|
||||||
TRACE_LN("Setting up command ring...");
|
LOG_LN_INFO("Setting up command ring...");
|
||||||
xhci_trb_t *wrapper = &cr[RING_LENGTH];
|
xhci_trb_t *wrapper = &cr[RING_LENGTH];
|
||||||
wrapper->parameter = (uint64_t)VIRT_TO_PHYS(cr);
|
wrapper->parameter = (uint64_t)VIRT_TO_PHYS(cr);
|
||||||
wrapper->status = 0;
|
wrapper->status = 0;
|
||||||
@@ -305,7 +307,7 @@ void xhci_init() {
|
|||||||
XHCI_TRB_TOGGLE_CYCLE_W(wrapper, 1);
|
XHCI_TRB_TOGGLE_CYCLE_W(wrapper, 1);
|
||||||
XHCI_TRB_CYCLE_W(wrapper, cr_cycle);
|
XHCI_TRB_CYCLE_W(wrapper, cr_cycle);
|
||||||
|
|
||||||
TRACE_LN("Configuring controller...");
|
LOG_LN_INFO("Configuring controller...");
|
||||||
XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS);
|
XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS);
|
||||||
op_regs->dcbaap = (uint64_t)VIRT_TO_PHYS(dcbaa);
|
op_regs->dcbaap = (uint64_t)VIRT_TO_PHYS(dcbaa);
|
||||||
op_regs->crcr = (uint64_t)VIRT_TO_PHYS(cr) | cr_cycle;
|
op_regs->crcr = (uint64_t)VIRT_TO_PHYS(cr) | cr_cycle;
|
||||||
@@ -315,30 +317,29 @@ void xhci_init() {
|
|||||||
intr_regs->erstba = (uint64_t)VIRT_TO_PHYS(erst);
|
intr_regs->erstba = (uint64_t)VIRT_TO_PHYS(erst);
|
||||||
intr_regs->erdp = erst[0].base;
|
intr_regs->erdp = erst[0].base;
|
||||||
|
|
||||||
TRACE_VAL_F(op_regs->config, "%x");
|
LOG_VAL_DATA(op_regs->config, "%x");
|
||||||
TRACE_VAL_F(op_regs->dcbaap, "%lx");
|
LOG_VAL_DATA(op_regs->dcbaap, "%lx");
|
||||||
TRACE_VAL_F(op_regs->crcr, "%lx");
|
LOG_VAL_DATA(op_regs->crcr, "%lx");
|
||||||
TRACE_VAL_F(intr_regs->erstba, "%lx");
|
LOG_VAL_DATA(intr_regs->erstba, "%lx");
|
||||||
TRACE_VAL_F(intr_regs->erstsz, "%x");
|
LOG_VAL_DATA(intr_regs->erstsz, "%x");
|
||||||
TRACE_VAL_F(intr_regs->erdp, "%lx");
|
LOG_VAL_DATA(intr_regs->erdp, "%lx");
|
||||||
TRACE_VAL_F(erst[0].size, "%hx");
|
LOG_VAL_DATA(erst[0].size, "%hx");
|
||||||
TRACE_VAL_F(erst[0].base, "%lx");
|
LOG_VAL_DATA(erst[0].base, "%lx");
|
||||||
|
|
||||||
TRACE_LN("Starting controller...");
|
LOG_LN_INFO("Starting controller...");
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
XHCI_OP_REGS_RS_W(op_regs, 1);
|
XHCI_OP_REGS_RS_W(op_regs, 1);
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
while (XHCI_OP_REGS_HCH(op_regs))
|
while (XHCI_OP_REGS_HCH(op_regs))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(op_regs->usbcmd, "%x");
|
LOG_VAL_DATA(op_regs->usbcmd, "%x");
|
||||||
TRACE_VAL_F(op_regs->usbsts, "%x");
|
LOG_VAL_DATA(op_regs->usbsts, "%x");
|
||||||
|
|
||||||
LOG_LN("Enumerating ports...");
|
PRINT_LN(kernel_log, "Enumerating ports...");
|
||||||
xhci_enumerate(kernel_log);
|
xhci_enumerate(kernel_log);
|
||||||
|
PRINT_LN(kernel_log, "Done.");
|
||||||
LOG_LN("Done.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xhci_enumerate(stream_t *out) {
|
void xhci_enumerate(stream_t *out) {
|
||||||
@@ -357,6 +358,8 @@ uint8_t xhci_port_connected(uint8_t port) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xhci_slot_t xhci_attach(uint8_t port) {
|
xhci_slot_t xhci_attach(uint8_t port) {
|
||||||
|
LOG_LN_STEP("Attaching port %d ...", port);
|
||||||
|
|
||||||
ASSERT(!tr_attached_slot, "xhci_attach: Can only attach one port at a time.")
|
ASSERT(!tr_attached_slot, "xhci_attach: Can only attach one port at a time.")
|
||||||
ASSERT(XHCI_PORT_REGS_CCS(&port_regs[port]), "xhci_attach: Port is not connected.");
|
ASSERT(XHCI_PORT_REGS_CCS(&port_regs[port]), "xhci_attach: Port is not connected.");
|
||||||
|
|
||||||
@@ -364,21 +367,21 @@ xhci_slot_t xhci_attach(uint8_t port) {
|
|||||||
tr_i = 0;
|
tr_i = 0;
|
||||||
tr_cycle = 1;
|
tr_cycle = 1;
|
||||||
|
|
||||||
LOG_LN("Resetting device...");
|
LOG_LN_STEP("Resetting device...");
|
||||||
port_regs[port].portsc = 1 << 4;
|
port_regs[port].portsc = 1 << 4;
|
||||||
while (XHCI_PORT_REGS_PR_R(&port_regs[port]))
|
while (XHCI_PORT_REGS_PR_R(&port_regs[port]))
|
||||||
;
|
;
|
||||||
while (!XHCI_PORT_REGS_PED(&port_regs[port]))
|
while (!XHCI_PORT_REGS_PED(&port_regs[port]))
|
||||||
;
|
;
|
||||||
TRACE_VAL_F(XHCI_PORT_REGS_PED(&port_regs[port]), "%hhx");
|
LOG_VAL_TRACE(XHCI_PORT_REGS_PED(&port_regs[port]), "%hhx");
|
||||||
|
|
||||||
LOG_LN("Enabling a slot...");
|
LOG_LN_STEP("Enabling a slot...");
|
||||||
xhci_trb_t cmd_es;
|
xhci_trb_t cmd_es;
|
||||||
memory_set(0, sizeof(xhci_trb_t), &cmd_es);
|
memory_set(0, sizeof(xhci_trb_t), &cmd_es);
|
||||||
XHCI_TRB_TRB_TYPE_W(&cmd_es, XHCI_TRB_TYPE_COMMAND_ENABLE_SLOT);
|
XHCI_TRB_TRB_TYPE_W(&cmd_es, XHCI_TRB_TYPE_COMMAND_ENABLE_SLOT);
|
||||||
xhci_slot_t slot = XHCI_TRB_SLOT_ID_R(command_exec_sync(&cmd_es));
|
xhci_slot_t slot = XHCI_TRB_SLOT_ID_R(command_exec_sync(&cmd_es));
|
||||||
|
|
||||||
LOG_LN("Addressing device...");
|
LOG_LN_STEP("Addressing device...");
|
||||||
memory_set(0, sizeof(input_ctx), &input_ctx);
|
memory_set(0, sizeof(input_ctx), &input_ctx);
|
||||||
input_ctx.control.add_flags = 0b11;
|
input_ctx.control.add_flags = 0b11;
|
||||||
XHCI_SLOT_CTX_CTX_ENTRIES_W(&input_ctx.slot, 1);
|
XHCI_SLOT_CTX_CTX_ENTRIES_W(&input_ctx.slot, 1);
|
||||||
@@ -399,13 +402,15 @@ xhci_slot_t xhci_attach(uint8_t port) {
|
|||||||
|
|
||||||
tr_attached_slot = slot;
|
tr_attached_slot = slot;
|
||||||
|
|
||||||
|
LOG_LN_STEP("Done.");
|
||||||
|
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uint16_t length) {
|
uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uint16_t length) {
|
||||||
ASSERT(tr_attached_slot == slot, "xhci_control_transfer: Can only attach one port at a time.");
|
ASSERT(tr_attached_slot == slot, "xhci_control_transfer: Can only attach one port at a time.");
|
||||||
|
|
||||||
LOG_LN("Queueing transfer TRBs...");
|
LOG_LN_STEP("Queueing transfer TRBs...");
|
||||||
|
|
||||||
tr[tr_i].parameter = setup;
|
tr[tr_i].parameter = setup;
|
||||||
tr[tr_i].status = sizeof(setup);
|
tr[tr_i].status = sizeof(setup);
|
||||||
@@ -414,9 +419,9 @@ uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uin
|
|||||||
BITS_W(tr[tr_i].control, 6, 6, 1);
|
BITS_W(tr[tr_i].control, 6, 6, 1);
|
||||||
XHCI_TRB_CYCLE_W(&tr[tr_i], tr_cycle);
|
XHCI_TRB_CYCLE_W(&tr[tr_i], tr_cycle);
|
||||||
|
|
||||||
LOG_VAL_F(tr[tr_i].parameter, "%lx");
|
LOG_VAL_TRACE(tr[tr_i].parameter, "%lx");
|
||||||
LOG_VAL_F(tr[tr_i].status, "%x");
|
LOG_VAL_TRACE(tr[tr_i].status, "%x");
|
||||||
LOG_VAL_F(tr[tr_i].control, "%x");
|
LOG_VAL_TRACE(tr[tr_i].control, "%x");
|
||||||
|
|
||||||
tr_i = (tr_i + 1) % RING_LENGTH;
|
tr_i = (tr_i + 1) % RING_LENGTH;
|
||||||
XHCI_TRB_CYCLE_W(&tr[RING_LENGTH], tr_cycle);
|
XHCI_TRB_CYCLE_W(&tr[RING_LENGTH], tr_cycle);
|
||||||
@@ -428,9 +433,9 @@ uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uin
|
|||||||
BITS_W(tr[tr_i].control, 16, 16, 1);
|
BITS_W(tr[tr_i].control, 16, 16, 1);
|
||||||
XHCI_TRB_CYCLE_W(&tr[tr_i], tr_cycle);
|
XHCI_TRB_CYCLE_W(&tr[tr_i], tr_cycle);
|
||||||
|
|
||||||
LOG_VAL_F(tr[tr_i].parameter, "%lx");
|
LOG_VAL_TRACE(tr[tr_i].parameter, "%lx");
|
||||||
LOG_VAL_F(tr[tr_i].status, "%x");
|
LOG_VAL_TRACE(tr[tr_i].status, "%x");
|
||||||
LOG_VAL_F(tr[tr_i].control, "%x");
|
LOG_VAL_TRACE(tr[tr_i].control, "%x");
|
||||||
|
|
||||||
tr_i = (tr_i + 1) % RING_LENGTH;
|
tr_i = (tr_i + 1) % RING_LENGTH;
|
||||||
XHCI_TRB_CYCLE_W(&tr[RING_LENGTH], tr_cycle);
|
XHCI_TRB_CYCLE_W(&tr[RING_LENGTH], tr_cycle);
|
||||||
@@ -447,10 +452,10 @@ uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uin
|
|||||||
XHCI_TRB_CYCLE_W(&tr[RING_LENGTH], tr_cycle);
|
XHCI_TRB_CYCLE_W(&tr[RING_LENGTH], tr_cycle);
|
||||||
tr_cycle ^= (tr_i == 0);
|
tr_cycle ^= (tr_i == 0);
|
||||||
|
|
||||||
LOG_LN("Ringing slot doorbell...");
|
LOG_LN_STEP("Ringing slot doorbell...");
|
||||||
db_regs[tr_attached_slot] = 1;
|
db_regs[tr_attached_slot] = 1;
|
||||||
|
|
||||||
LOG_LN("Waiting for completion...");
|
LOG_LN_STEP("Waiting for completion...");
|
||||||
while (1) {
|
while (1) {
|
||||||
xhci_trb_t *cmp = &er[er_i];
|
xhci_trb_t *cmp = &er[er_i];
|
||||||
while (XHCI_TRB_CYCLE_R(cmp) != er_cycle)
|
while (XHCI_TRB_CYCLE_R(cmp) != er_cycle)
|
||||||
@@ -461,22 +466,26 @@ uint64_t xhci_control_transfer(xhci_slot_t slot, uint64_t setup, void *data, uin
|
|||||||
er_cycle ^= (er_i == 0);
|
er_cycle ^= (er_i == 0);
|
||||||
|
|
||||||
if (XHCI_TRB_TRB_TYPE_R(cmp) != XHCI_TRB_TYPE_EVENT_TRANSFER_COMPLETION || (void *)cmp->parameter != VIRT_TO_PHYS(tre)) {
|
if (XHCI_TRB_TRB_TYPE_R(cmp) != XHCI_TRB_TYPE_EVENT_TRANSFER_COMPLETION || (void *)cmp->parameter != VIRT_TO_PHYS(tre)) {
|
||||||
LOG_LN("Received irrelevant event, skipping...");
|
LOG_LN_STEP("Received irrelevant event, skipping...");
|
||||||
} else {
|
} else {
|
||||||
LOG_LN("Received transfer completion event...");
|
LOG_LN_STEP("Received transfer completion event...");
|
||||||
|
|
||||||
LOG_VAL_F(cmp->parameter, "%lx");
|
LOG_VAL_TRACE(cmp->parameter, "%lx");
|
||||||
LOG_VAL_F(cmp->status, "%x");
|
LOG_VAL_TRACE(cmp->status, "%x");
|
||||||
LOG_VAL_F(cmp->control, "%x");
|
LOG_VAL_TRACE(cmp->control, "%x");
|
||||||
|
|
||||||
ASSERT(XHCI_TRB_COMPLETION_CODE(cmp) == 1, "xhci_control_transfer: Transfer failed.");
|
ASSERT(XHCI_TRB_COMPLETION_CODE(cmp) == 1, "xhci_control_transfer: Transfer failed.");
|
||||||
|
|
||||||
|
LOG_LN_STEP("Done.");
|
||||||
|
|
||||||
return length - (cmp->status & 0xFFFFFF);
|
return length - (cmp->status & 0xFFFFFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xhci_detach(xhci_slot_t slot) {
|
void xhci_detach(xhci_slot_t slot) {
|
||||||
|
LOG_LN_STEP("Detaching slot %d...", slot);
|
||||||
|
|
||||||
ASSERT(tr_attached_slot == slot, "xhci_detach: Slot not attached.");
|
ASSERT(tr_attached_slot == slot, "xhci_detach: Slot not attached.");
|
||||||
|
|
||||||
xhci_trb_t cmd_ds;
|
xhci_trb_t cmd_ds;
|
||||||
@@ -487,4 +496,6 @@ void xhci_detach(xhci_slot_t slot) {
|
|||||||
|
|
||||||
dcbaa[slot] = 0;
|
dcbaa[slot] = 0;
|
||||||
tr_attached_slot = 0;
|
tr_attached_slot = 0;
|
||||||
|
|
||||||
|
LOG_LN_STEP("Done.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user