diff --git a/src/include/hlib.h b/src/include/hlib.h index 8bb4ac8..05fc7e0 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -55,6 +55,7 @@ extern uint32_t await(uint32_t service, uint32_t event); extern void gets(char *buffer); +extern void memcpy(void *from, void *to, uint32_t size); #define MAX(x, y) (x > y ? (x) : (y)) diff --git a/src/include/hlib.h b/src/include/hlib.h index 8bb4ac8..05fc7e0 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -55,6 +55,7 @@ extern uint32_t await(uint32_t service, uint32_t event); extern void gets(char *buffer); +extern void memcpy(void *from, void *to, uint32_t size); #define MAX(x, y) (x > y ? (x) : (y)) diff --git a/src/userland/hlib/strings.c b/src/userland/hlib/strings.c index 0c3b420..78fff55 100644 --- a/src/userland/hlib/strings.c +++ b/src/userland/hlib/strings.c @@ -14,6 +14,13 @@ return size; } +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + uintptr_t insertString(char *string) { return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); } diff --git a/src/include/hlib.h b/src/include/hlib.h index 8bb4ac8..05fc7e0 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -55,6 +55,7 @@ extern uint32_t await(uint32_t service, uint32_t event); extern void gets(char *buffer); +extern void memcpy(void *from, void *to, uint32_t size); #define MAX(x, y) (x > y ? (x) : (y)) diff --git a/src/userland/hlib/strings.c b/src/userland/hlib/strings.c index 0c3b420..78fff55 100644 --- a/src/userland/hlib/strings.c +++ b/src/userland/hlib/strings.c @@ -14,6 +14,13 @@ return size; } +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + uintptr_t insertString(char *string) { return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); } diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index fe2ac39..dcc45f9 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -171,9 +171,103 @@ controller->runtime->interrupterRegisters[0].enabled = 1; } +void advanceEnqueuePointer(XHCIController *controller) { + XHCITransferRequestBlock block = {}; + block.cycle = !controller->commandRingCycleState; + memcpy(controller->commandRingEnque, &block, sizeof(block)); +} + +XHCITransferRequestBlock *enqueueCommand(XHCIController *controller, + XHCITransferRequestBlock *block) { + block->cycle = controller->commandRingCycleState; + memcpy(controller->commandRingEnque, block, + sizeof(XHCITransferRequestBlock)); + XHCITransferRequestBlock *commandRing = controller->commandRingEnque; + controller->commandRingEnque++; + if (controller->commandRingEnque->type == 6) { + controller->commandRingEnque->cycle = controller->commandRingCycleState; + controller->commandRingEnque = controller->commandRing; + controller->commandRingCycleState = !controller->commandRingCycleState; + } + advanceEnqueuePointer(controller); + return commandRing; +} + +XHCITransferRequestBlock *enableSlot(XHCIController *controller, uint8_t port) { + XHCITransferRequestBlock block = {0}; + block.type = 9; + return enqueueCommand(controller, &block); +} + +void ringXHCIDoorbellAndWait(XHCIController *controller) { + controller->doorbells[0] = 0; +} + +void resetSlot(XHCIController *controller, uint8_t slotNumber) { + XHCIInputContext *context = controller->inputContexts[slotNumber - 1]; + context->A = 3; + context->D = ~context->A; + SlotContext *slot = &(context->deviceContext.slotContext); + if (slot) { + slot->routeString = 0; + slot->speed = 3; + slot->contextEntries = 1; + slot->rootHubPortNumber = slotNumber; + slot->interrupterTarget = 0; + slot->multiTT = 0; + slot->isHub = 0; + slot->deviceAddress = 0; + } + EndpointContext *endpoints = context->deviceContext.endpoints; + if (endpoints) { + endpoints[0].endpointState = 0; + endpoints[0].endpointType = 4; + endpoints[0].maxPacketSize = 8; + endpoints[0].maxBurstSize = 0; + endpoints[0].TRBDequePointerLow = + U32(getPhysicalAddress( + controller->slots[slotNumber - 1]->endpoints[0].trbs)) >> + 4; + endpoints[0].TRBDequePointerHigh = 0; + endpoints[0].maxPrimaryStreams = 0; + // endpoints[0].mult = 0; + endpoints[0].errorCount = 3; + endpoints[0].dequeueCycleState = 1; + endpoints[0].averageTRBLength = 8; + } +} + +void prepareControlTransfer(XHCIController *controller) { + for (uint8_t i = 0; i < 16; i++) { + controller->portSlotLinks[i].command = enableSlot(controller, i); + resetSlot(controller, i + 1); + XHCITransferRequestBlock block = {0}; + block.type = 4; + enqueueCommand(controller, &block); + } + ringXHCIDoorbellAndWait(controller); +} + +void printControllerStatus(XHCIController *controller) { + printf("status: halted: %i, host system error: %i, internal host " + "controller error: %i save/restore error: %i\n", + controller->operational->usbStatus & 1, + controller->operational->usbStatus >> 2 & 1, + controller->operational->usbStatus >> 12 & 1, + controller->operational->usbStatus >> 10 & 1); + printf("status: event: %i, portChange: %i, saveState: %i, restoreState: %i " + "not ready: %i\n", + controller->operational->usbStatus >> 3 & 1, + controller->operational->usbStatus >> 4 & 1, + controller->operational->usbStatus >> 8 & 1, + controller->operational->usbStatus >> 9 & 1, + controller->operational->usbStatus >> 11 & 1); +} + void initializeUSB(uint32_t deviceId) { XHCIController *controller = malloc(sizeof(XHCIController)); controller->pciDeviceId = deviceId; + controller->commandRingCycleState = true; enableBusMaster(controller->pciDeviceId, 0); uint32_t baseAddress = getBaseAddress(deviceId, 0) & ~0xF; controller->capabilities = requestMemory(1, NULL, PTR(baseAddress)); @@ -182,6 +276,8 @@ controller->runtime = OFFSET(controller->capabilities, controller->capabilities->runtimeRegistersSpaceOffset); + controller->doorbells = OFFSET(controller->capabilities, + controller->capabilities->doorbellOffset); resetController(controller); deactivateXHCILegacy(controller); if (!(controller->operational->usbStatus & 1)) { @@ -199,6 +295,7 @@ initializePort(controller, i); } controller->commandRing = malloc(256 * sizeof(XHCITransferRequestBlock)); + controller->commandRingEnque = controller->commandRing; controller->commandRing[255].dataLow = U32(getPhysicalAddress(controller->commandRing)); controller->commandRing[255].type = 6; @@ -212,20 +309,9 @@ printf("irq pin : %i\n", controller->interrupt); uint32_t pic = getService("pic"); subscribeEvent(pic, getEvent(pic, "irq11"), (void *)usbInterrupt); + subscribeEvent(pic, getEvent(pic, "irq3"), (void *)usbInterrupt); waitForKeyPress(); - printf("status: halted: %i, host system error: %i, internal host " - "controller error: %i save/restore error: %i\n", - controller->operational->usbStatus & 1, - controller->operational->usbStatus >> 2 & 1, - controller->operational->usbStatus >> 12 & 1, - controller->operational->usbStatus >> 10 & 1); - printf("status: event: %i, portChange: %i, saveState: %i, restoreState: %i " - "not ready: %i\n", - controller->operational->usbStatus >> 3 & 1, - controller->operational->usbStatus >> 4 & 1, - controller->operational->usbStatus >> 8 & 1, - controller->operational->usbStatus >> 9 & 1, - controller->operational->usbStatus >> 11 & 1); + prepareControlTransfer(controller); } int32_t main() { diff --git a/src/include/hlib.h b/src/include/hlib.h index 8bb4ac8..05fc7e0 100644 --- a/src/include/hlib.h +++ b/src/include/hlib.h @@ -55,6 +55,7 @@ extern uint32_t await(uint32_t service, uint32_t event); extern void gets(char *buffer); +extern void memcpy(void *from, void *to, uint32_t size); #define MAX(x, y) (x > y ? (x) : (y)) diff --git a/src/userland/hlib/strings.c b/src/userland/hlib/strings.c index 0c3b420..78fff55 100644 --- a/src/userland/hlib/strings.c +++ b/src/userland/hlib/strings.c @@ -14,6 +14,13 @@ return size; } +void memcpy(void *from, void *to, uint32_t size) { + uint8_t *a = from, *b = to; + for (uint32_t i = 0; i < size; i++) { + b[i] = a[i]; + } +} + uintptr_t insertString(char *string) { return syscall(SYS_INSERT_STRING, U32(string), 0, 0, 0); } diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index fe2ac39..dcc45f9 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -171,9 +171,103 @@ controller->runtime->interrupterRegisters[0].enabled = 1; } +void advanceEnqueuePointer(XHCIController *controller) { + XHCITransferRequestBlock block = {}; + block.cycle = !controller->commandRingCycleState; + memcpy(controller->commandRingEnque, &block, sizeof(block)); +} + +XHCITransferRequestBlock *enqueueCommand(XHCIController *controller, + XHCITransferRequestBlock *block) { + block->cycle = controller->commandRingCycleState; + memcpy(controller->commandRingEnque, block, + sizeof(XHCITransferRequestBlock)); + XHCITransferRequestBlock *commandRing = controller->commandRingEnque; + controller->commandRingEnque++; + if (controller->commandRingEnque->type == 6) { + controller->commandRingEnque->cycle = controller->commandRingCycleState; + controller->commandRingEnque = controller->commandRing; + controller->commandRingCycleState = !controller->commandRingCycleState; + } + advanceEnqueuePointer(controller); + return commandRing; +} + +XHCITransferRequestBlock *enableSlot(XHCIController *controller, uint8_t port) { + XHCITransferRequestBlock block = {0}; + block.type = 9; + return enqueueCommand(controller, &block); +} + +void ringXHCIDoorbellAndWait(XHCIController *controller) { + controller->doorbells[0] = 0; +} + +void resetSlot(XHCIController *controller, uint8_t slotNumber) { + XHCIInputContext *context = controller->inputContexts[slotNumber - 1]; + context->A = 3; + context->D = ~context->A; + SlotContext *slot = &(context->deviceContext.slotContext); + if (slot) { + slot->routeString = 0; + slot->speed = 3; + slot->contextEntries = 1; + slot->rootHubPortNumber = slotNumber; + slot->interrupterTarget = 0; + slot->multiTT = 0; + slot->isHub = 0; + slot->deviceAddress = 0; + } + EndpointContext *endpoints = context->deviceContext.endpoints; + if (endpoints) { + endpoints[0].endpointState = 0; + endpoints[0].endpointType = 4; + endpoints[0].maxPacketSize = 8; + endpoints[0].maxBurstSize = 0; + endpoints[0].TRBDequePointerLow = + U32(getPhysicalAddress( + controller->slots[slotNumber - 1]->endpoints[0].trbs)) >> + 4; + endpoints[0].TRBDequePointerHigh = 0; + endpoints[0].maxPrimaryStreams = 0; + // endpoints[0].mult = 0; + endpoints[0].errorCount = 3; + endpoints[0].dequeueCycleState = 1; + endpoints[0].averageTRBLength = 8; + } +} + +void prepareControlTransfer(XHCIController *controller) { + for (uint8_t i = 0; i < 16; i++) { + controller->portSlotLinks[i].command = enableSlot(controller, i); + resetSlot(controller, i + 1); + XHCITransferRequestBlock block = {0}; + block.type = 4; + enqueueCommand(controller, &block); + } + ringXHCIDoorbellAndWait(controller); +} + +void printControllerStatus(XHCIController *controller) { + printf("status: halted: %i, host system error: %i, internal host " + "controller error: %i save/restore error: %i\n", + controller->operational->usbStatus & 1, + controller->operational->usbStatus >> 2 & 1, + controller->operational->usbStatus >> 12 & 1, + controller->operational->usbStatus >> 10 & 1); + printf("status: event: %i, portChange: %i, saveState: %i, restoreState: %i " + "not ready: %i\n", + controller->operational->usbStatus >> 3 & 1, + controller->operational->usbStatus >> 4 & 1, + controller->operational->usbStatus >> 8 & 1, + controller->operational->usbStatus >> 9 & 1, + controller->operational->usbStatus >> 11 & 1); +} + void initializeUSB(uint32_t deviceId) { XHCIController *controller = malloc(sizeof(XHCIController)); controller->pciDeviceId = deviceId; + controller->commandRingCycleState = true; enableBusMaster(controller->pciDeviceId, 0); uint32_t baseAddress = getBaseAddress(deviceId, 0) & ~0xF; controller->capabilities = requestMemory(1, NULL, PTR(baseAddress)); @@ -182,6 +276,8 @@ controller->runtime = OFFSET(controller->capabilities, controller->capabilities->runtimeRegistersSpaceOffset); + controller->doorbells = OFFSET(controller->capabilities, + controller->capabilities->doorbellOffset); resetController(controller); deactivateXHCILegacy(controller); if (!(controller->operational->usbStatus & 1)) { @@ -199,6 +295,7 @@ initializePort(controller, i); } controller->commandRing = malloc(256 * sizeof(XHCITransferRequestBlock)); + controller->commandRingEnque = controller->commandRing; controller->commandRing[255].dataLow = U32(getPhysicalAddress(controller->commandRing)); controller->commandRing[255].type = 6; @@ -212,20 +309,9 @@ printf("irq pin : %i\n", controller->interrupt); uint32_t pic = getService("pic"); subscribeEvent(pic, getEvent(pic, "irq11"), (void *)usbInterrupt); + subscribeEvent(pic, getEvent(pic, "irq3"), (void *)usbInterrupt); waitForKeyPress(); - printf("status: halted: %i, host system error: %i, internal host " - "controller error: %i save/restore error: %i\n", - controller->operational->usbStatus & 1, - controller->operational->usbStatus >> 2 & 1, - controller->operational->usbStatus >> 12 & 1, - controller->operational->usbStatus >> 10 & 1); - printf("status: event: %i, portChange: %i, saveState: %i, restoreState: %i " - "not ready: %i\n", - controller->operational->usbStatus >> 3 & 1, - controller->operational->usbStatus >> 4 & 1, - controller->operational->usbStatus >> 8 & 1, - controller->operational->usbStatus >> 9 & 1, - controller->operational->usbStatus >> 11 & 1); + prepareControlTransfer(controller); } int32_t main() { diff --git a/src/userland/usb/usb.h b/src/userland/usb/usb.h index 6d04df4..e82202d 100644 --- a/src/userland/usb/usb.h +++ b/src/userland/usb/usb.h @@ -59,7 +59,7 @@ uint32_t maxEndpointServiceTime : 8; uint32_t reserved1 : 1; - uint32_t errorCont : 2; + uint32_t errorCount : 2; uint32_t endpointType : 3; uint32_t reserved2 : 1; uint32_t hostInitiateDisable : 1; @@ -68,10 +68,10 @@ uint32_t dequeueCycleState : 1; uint32_t reserved3 : 3; - uint32_t TRDequePointerLow : 28; - uint32_t TRDequePointerHigh; + uint32_t TRBDequePointerLow : 28; + uint32_t TRBDequePointerHigh; - uint32_t everageTRBLength : 16; + uint32_t averageTRBLength : 16; uint32_t maxServiceTimeIntervalPayloadLow : 16; uint32_t reserved4[3]; @@ -178,6 +178,11 @@ } XHCIRuntimeRegisters; typedef struct { + uint8_t slotNumber; + XHCITransferRequestBlock *command; +} PortSlotLink; + +typedef struct { uint32_t pciDeviceId; XHCICapabilities *capabilities; XHCIOperationalRegisters *operational; @@ -190,12 +195,16 @@ XHCISlot *slots[16]; XHCITransferRequestBlock *trbs[16][32]; XHCITransferRequestBlock *commandRing; + XHCITransferRequestBlock *commandRingEnque; + bool commandRingCycleState; + volatile uint32_t *doorbells; uint32_t interrupt; uint32_t eventSegmentSize; uint32_t eventSegmentCounter; uint32_t eventSegmentNumber; XHCITransferRequestBlock *eventRing; XHCIRuntimeRegisters *runtime; + PortSlotLink portSlotLinks[10]; } XHCIController; #endif