diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 5875fee..c6040a0 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -3,13 +3,12 @@ #include "../hlib/include/syscalls.h" #include "xhci/commands.h" +#include "xhci/controller.h" #include "xhci/trbRing.h" #include uint32_t serviceId; -XHCIController *controller; - #define REQUEST(functionName, service, function) \ uint32_t functionName(uint32_t data1, uint32_t data2) { \ static uint32_t serviceId, functionId, initialized = false; \ @@ -32,131 +31,6 @@ REQUEST(enableBusMaster, "lspci", "enableBusMaster"); REQUEST(getPCIInterrupt, "lspci", "getInterrupt"); -void restartXHCIController(XHCIController *controller) { - printf("resetting controller...\n"); - controller->operational->command &= ~1; - while (!(controller->operational->status & (1 << 0))) - syscall(-1, 0, 0, 0, 0); - controller->operational->command |= 1 << 1; - while ((controller->operational->command & (1 << 1))) - ; - while ((controller->operational->status & (1 << 11))) - ; -} - -void setupRuntime(XHCIController *controller) { - controller->runtime = OFFSET(controller->capabilities, - controller->capabilities->runtimeOffset); - controller->runtime->interrupters[0].eventRingSegmentTableSize = 1; - controller->runtime->interrupters[0].eventRingSegmentTableAddress[0] = - U32(controller->eventRingSegmentTablePhysical); - controller->runtime->interrupters[0].eventRingSegmentTableAddress[1] = 0; - controller->runtime->interrupters[0].eventRingDequeuePointer[0] = - U32(&controller->events.physical[controller->events.dequeue]) | - (1 << 3); - controller->runtime->interrupters[0].eventRingDequeuePointer[1] = 0; - - controller->runtime->interrupters[0].management |= 3; - sleep(100); -} - -void setupEventRingSegmentTable(XHCIController *controller) { - // todo: research necessary alignment - controller->eventRingSegmentTable = requestMemory(1, 0, 0); - controller->eventRingSegmentTablePhysical = - getPhysicalAddress((void *)controller->eventRingSegmentTable); - - controller->eventRingSegmentTable[0].ringSegmentBaseAddress[0] = - U32(controller->events.physical); - controller->eventRingSegmentTable[0].ringSegmentSize = - controller->events.size; -} - -void readExtendedCapabilities(XHCIController *controller) { - uintptr_t offset = (controller->capabilities->structuralParameters[0] >> 16) - << 2; - - volatile uint32_t *extendedCapabilities = - OFFSET(controller->capabilities, offset); - - while (1) { - uint32_t value = *extendedCapabilities; - - if ((value & 0xFF) == 2) { - uint8_t revisionMinor = extendedCapabilities[0] >> 16; - uint8_t revisionMajor = extendedCapabilities[0] >> 24; - - uint8_t portOffset = extendedCapabilities[2]; - uint8_t portCount = extendedCapabilities[2] >> 8; - - printf("protocol %i.%i %i port(s) starting from port %i\n", - revisionMajor, revisionMinor, portCount, portOffset); - } - - if (value == 0xFFFFFFFF) - break; - if ((value & 0xFF00) == 0) - break; - extendedCapabilities = - (void *)((uintptr_t)extendedCapabilities + ((value & 0xFF00) >> 6)); - } -} - -void setupOperationalRegisters(XHCIController *controller) { - controller->deviceContextBaseAddressArray = (void *)requestMemory(1, 0, 0); - controller->operational->deviceContextBaseAddressArray[0] = - U32(getPhysicalAddress(controller->deviceContextBaseAddressArray)); - controller->operational->deviceContextBaseAddressArray[1] = 0; - - controller->operational->config = - (controller->operational->config & ~0xFF) | 32; - - controller->operational->commandRingControl[0] = - U32(controller->commands.physical) | 1; - controller->operational->commandRingControl[1] = 0; - controller->operational->config = - controller->capabilities->structuralParameters[0] & 0xFF; -} - -void setupScratchpadBuffers(XHCIController *controller) { - uint32_t hcs2 = controller->capabilities->structuralParameters[1]; - uint32_t scratchpadBufferCountHigh = (hcs2 >> 21) & 0x1f; - uint32_t scratchpadBufferCountLow = (hcs2 >> 27) & 0x1f; - uint32_t scratchpadBufferCount = - (scratchpadBufferCountHigh << 5) | scratchpadBufferCountLow; - - if (scratchpadBufferCount) { - printf("%i scratchpad buffers present\n", scratchpadBufferCount); - - uint64_t *scratchpadBuffer = (uint64_t *)requestMemory(1, 0, 0); - void *scratchpadPhysical = getPhysicalAddress(scratchpadBuffer); - for (unsigned int i = 0; i < scratchpadBufferCount; ++i) { - void *sb_phys = getPhysicalAddress(requestMemory(1, 0, 0)); - scratchpadBuffer[i] = U32(sb_phys); - } - controller->deviceContextBaseAddressArray[0] = U32(scratchpadPhysical); - } -} - -XHCIController *initializeController(uint32_t deviceId) { - XHCIController *controller = malloc(sizeof(XHCIController)); - controller->pciDevice = deviceId; - - controller->capabilities = - requestMemory(4, 0, PTR(U32(getBaseAddress(deviceId, 0)) & ~0xF)); - controller->operational = - OFFSET(controller->capabilities, - controller->capabilities->capabilitiesLength & 0xFF); - controller->doorbells = OFFSET(controller->capabilities, - controller->capabilities->doorbellOffset); - - uint32_t slotInfo = controller->capabilities->structuralParameters[0]; - printf("%i available slots, %i available ports\n", slotInfo & 0xFF, - slotInfo >> 24); - controller->portCount = slotInfo >> 24; - return controller; -} - XHCIInputContext *createInputContext(SlotXHCI *slot) { XHCIInputContext *inputContext = requestMemory(1, 0, 0); inputContext->inputControl.addContextFlags = 3; @@ -194,17 +68,13 @@ slot->controller = controller; slot->slotIndex = requestSlotIndex(controller); slot->port = &controller->operational->ports[portIndex - 1]; + printf("port %i: connecting to slot %i\n", portIndex - 1, slot->slotIndex); - printf("port %i: connected, resetting and setting it up now ...\n", - portIndex - 1); slot->port->status |= 1 << 4; await(serviceId, syscall(SYS_CREATE_EVENT, slot->portIndex << 24, 0, 0, 0)); if (!(slot->port->status & 1 << 1)) { - return printf("port %i reset could not be done, aborting\n", - portIndex - 1); + return printf("port %i reset not succesful, aborting\n", portIndex - 1); } - printf("port %i: reset done, now connecting to slot %i\n", portIndex - 1, - slot->slotIndex); slot->inputContext = createInputContext(slot); slot->controlRing = createSlotTRB(slot); slot->controller->deviceContextBaseAddressArray[slot->slotIndex] = @@ -235,57 +105,16 @@ printf("--------\n"); } -void xhciInterrupt() { - if (controller->runtime->interrupters[0].management & 1) { - controller->runtime->interrupters[0].management |= 1; - XHCITRB *trb; - uint32_t index; - while ((trb = trbRingFetch(&controller->events, &index))) { - controller->runtime->interrupters[0].eventRingDequeuePointer[0] = - U32(&controller->events.physical[controller->events.dequeue]) | - (1 << 3); - uint32_t eventId = - syscall(SYS_GET_EVENT, serviceId, trb->dataLow, 0, 0); - printf("event %i [%x %x %x %x]: %i\n", controller->events.dequeue, - trb->dataLow, trb->dataHigh, trb->status, trb->control, - trb->control >> 10 & 0x3F); - if (eventId) { - fireEvent(eventId, U32(trb)); - } - } - } -} - void initializeUSB(uint32_t deviceId) { - controller = initializeController(deviceId); - restartXHCIController(controller); - - setupTrbRing(&controller->commands, 256); - setupTrbRing(&controller->events, 256); - readExtendedCapabilities(controller); - setupOperationalRegisters(controller); - setupEventRingSegmentTable(controller); - setupRuntime(controller); - setupScratchpadBuffers(controller); - - controller->operational->status |= (1 << 3); - printf("using irq no. %i\n", getPCIInterrupt(deviceId, 0)); - int pic = getService("pic"); - subscribeEvent(pic, getEvent(pic, "irq11"), xhciInterrupt); - controller->operational->command |= (1 << 0) | (1 << 2); - sleep(100); - - if (controller->operational->status & (1 << 2)) { - return printf("critical XHCI problem\n"); - } - + uint32_t interrupt = getPCIInterrupt(deviceId, 0); + XHCIController *controller = + xhciSetup(deviceId, U32(getBaseAddress(deviceId, 0)), interrupt); for (uint32_t i = 0; i < controller->portCount; i++) { if (!(controller->operational->ports[i].status & 1 << 0)) { continue; } resetPort(controller, i + 1); } - return; } int32_t main() { diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 5875fee..c6040a0 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -3,13 +3,12 @@ #include "../hlib/include/syscalls.h" #include "xhci/commands.h" +#include "xhci/controller.h" #include "xhci/trbRing.h" #include uint32_t serviceId; -XHCIController *controller; - #define REQUEST(functionName, service, function) \ uint32_t functionName(uint32_t data1, uint32_t data2) { \ static uint32_t serviceId, functionId, initialized = false; \ @@ -32,131 +31,6 @@ REQUEST(enableBusMaster, "lspci", "enableBusMaster"); REQUEST(getPCIInterrupt, "lspci", "getInterrupt"); -void restartXHCIController(XHCIController *controller) { - printf("resetting controller...\n"); - controller->operational->command &= ~1; - while (!(controller->operational->status & (1 << 0))) - syscall(-1, 0, 0, 0, 0); - controller->operational->command |= 1 << 1; - while ((controller->operational->command & (1 << 1))) - ; - while ((controller->operational->status & (1 << 11))) - ; -} - -void setupRuntime(XHCIController *controller) { - controller->runtime = OFFSET(controller->capabilities, - controller->capabilities->runtimeOffset); - controller->runtime->interrupters[0].eventRingSegmentTableSize = 1; - controller->runtime->interrupters[0].eventRingSegmentTableAddress[0] = - U32(controller->eventRingSegmentTablePhysical); - controller->runtime->interrupters[0].eventRingSegmentTableAddress[1] = 0; - controller->runtime->interrupters[0].eventRingDequeuePointer[0] = - U32(&controller->events.physical[controller->events.dequeue]) | - (1 << 3); - controller->runtime->interrupters[0].eventRingDequeuePointer[1] = 0; - - controller->runtime->interrupters[0].management |= 3; - sleep(100); -} - -void setupEventRingSegmentTable(XHCIController *controller) { - // todo: research necessary alignment - controller->eventRingSegmentTable = requestMemory(1, 0, 0); - controller->eventRingSegmentTablePhysical = - getPhysicalAddress((void *)controller->eventRingSegmentTable); - - controller->eventRingSegmentTable[0].ringSegmentBaseAddress[0] = - U32(controller->events.physical); - controller->eventRingSegmentTable[0].ringSegmentSize = - controller->events.size; -} - -void readExtendedCapabilities(XHCIController *controller) { - uintptr_t offset = (controller->capabilities->structuralParameters[0] >> 16) - << 2; - - volatile uint32_t *extendedCapabilities = - OFFSET(controller->capabilities, offset); - - while (1) { - uint32_t value = *extendedCapabilities; - - if ((value & 0xFF) == 2) { - uint8_t revisionMinor = extendedCapabilities[0] >> 16; - uint8_t revisionMajor = extendedCapabilities[0] >> 24; - - uint8_t portOffset = extendedCapabilities[2]; - uint8_t portCount = extendedCapabilities[2] >> 8; - - printf("protocol %i.%i %i port(s) starting from port %i\n", - revisionMajor, revisionMinor, portCount, portOffset); - } - - if (value == 0xFFFFFFFF) - break; - if ((value & 0xFF00) == 0) - break; - extendedCapabilities = - (void *)((uintptr_t)extendedCapabilities + ((value & 0xFF00) >> 6)); - } -} - -void setupOperationalRegisters(XHCIController *controller) { - controller->deviceContextBaseAddressArray = (void *)requestMemory(1, 0, 0); - controller->operational->deviceContextBaseAddressArray[0] = - U32(getPhysicalAddress(controller->deviceContextBaseAddressArray)); - controller->operational->deviceContextBaseAddressArray[1] = 0; - - controller->operational->config = - (controller->operational->config & ~0xFF) | 32; - - controller->operational->commandRingControl[0] = - U32(controller->commands.physical) | 1; - controller->operational->commandRingControl[1] = 0; - controller->operational->config = - controller->capabilities->structuralParameters[0] & 0xFF; -} - -void setupScratchpadBuffers(XHCIController *controller) { - uint32_t hcs2 = controller->capabilities->structuralParameters[1]; - uint32_t scratchpadBufferCountHigh = (hcs2 >> 21) & 0x1f; - uint32_t scratchpadBufferCountLow = (hcs2 >> 27) & 0x1f; - uint32_t scratchpadBufferCount = - (scratchpadBufferCountHigh << 5) | scratchpadBufferCountLow; - - if (scratchpadBufferCount) { - printf("%i scratchpad buffers present\n", scratchpadBufferCount); - - uint64_t *scratchpadBuffer = (uint64_t *)requestMemory(1, 0, 0); - void *scratchpadPhysical = getPhysicalAddress(scratchpadBuffer); - for (unsigned int i = 0; i < scratchpadBufferCount; ++i) { - void *sb_phys = getPhysicalAddress(requestMemory(1, 0, 0)); - scratchpadBuffer[i] = U32(sb_phys); - } - controller->deviceContextBaseAddressArray[0] = U32(scratchpadPhysical); - } -} - -XHCIController *initializeController(uint32_t deviceId) { - XHCIController *controller = malloc(sizeof(XHCIController)); - controller->pciDevice = deviceId; - - controller->capabilities = - requestMemory(4, 0, PTR(U32(getBaseAddress(deviceId, 0)) & ~0xF)); - controller->operational = - OFFSET(controller->capabilities, - controller->capabilities->capabilitiesLength & 0xFF); - controller->doorbells = OFFSET(controller->capabilities, - controller->capabilities->doorbellOffset); - - uint32_t slotInfo = controller->capabilities->structuralParameters[0]; - printf("%i available slots, %i available ports\n", slotInfo & 0xFF, - slotInfo >> 24); - controller->portCount = slotInfo >> 24; - return controller; -} - XHCIInputContext *createInputContext(SlotXHCI *slot) { XHCIInputContext *inputContext = requestMemory(1, 0, 0); inputContext->inputControl.addContextFlags = 3; @@ -194,17 +68,13 @@ slot->controller = controller; slot->slotIndex = requestSlotIndex(controller); slot->port = &controller->operational->ports[portIndex - 1]; + printf("port %i: connecting to slot %i\n", portIndex - 1, slot->slotIndex); - printf("port %i: connected, resetting and setting it up now ...\n", - portIndex - 1); slot->port->status |= 1 << 4; await(serviceId, syscall(SYS_CREATE_EVENT, slot->portIndex << 24, 0, 0, 0)); if (!(slot->port->status & 1 << 1)) { - return printf("port %i reset could not be done, aborting\n", - portIndex - 1); + return printf("port %i reset not succesful, aborting\n", portIndex - 1); } - printf("port %i: reset done, now connecting to slot %i\n", portIndex - 1, - slot->slotIndex); slot->inputContext = createInputContext(slot); slot->controlRing = createSlotTRB(slot); slot->controller->deviceContextBaseAddressArray[slot->slotIndex] = @@ -235,57 +105,16 @@ printf("--------\n"); } -void xhciInterrupt() { - if (controller->runtime->interrupters[0].management & 1) { - controller->runtime->interrupters[0].management |= 1; - XHCITRB *trb; - uint32_t index; - while ((trb = trbRingFetch(&controller->events, &index))) { - controller->runtime->interrupters[0].eventRingDequeuePointer[0] = - U32(&controller->events.physical[controller->events.dequeue]) | - (1 << 3); - uint32_t eventId = - syscall(SYS_GET_EVENT, serviceId, trb->dataLow, 0, 0); - printf("event %i [%x %x %x %x]: %i\n", controller->events.dequeue, - trb->dataLow, trb->dataHigh, trb->status, trb->control, - trb->control >> 10 & 0x3F); - if (eventId) { - fireEvent(eventId, U32(trb)); - } - } - } -} - void initializeUSB(uint32_t deviceId) { - controller = initializeController(deviceId); - restartXHCIController(controller); - - setupTrbRing(&controller->commands, 256); - setupTrbRing(&controller->events, 256); - readExtendedCapabilities(controller); - setupOperationalRegisters(controller); - setupEventRingSegmentTable(controller); - setupRuntime(controller); - setupScratchpadBuffers(controller); - - controller->operational->status |= (1 << 3); - printf("using irq no. %i\n", getPCIInterrupt(deviceId, 0)); - int pic = getService("pic"); - subscribeEvent(pic, getEvent(pic, "irq11"), xhciInterrupt); - controller->operational->command |= (1 << 0) | (1 << 2); - sleep(100); - - if (controller->operational->status & (1 << 2)) { - return printf("critical XHCI problem\n"); - } - + uint32_t interrupt = getPCIInterrupt(deviceId, 0); + XHCIController *controller = + xhciSetup(deviceId, U32(getBaseAddress(deviceId, 0)), interrupt); for (uint32_t i = 0; i < controller->portCount; i++) { if (!(controller->operational->ports[i].status & 1 << 0)) { continue; } resetPort(controller, i + 1); } - return; } int32_t main() { diff --git a/src/userland/usb/xhci/controller.c b/src/userland/usb/xhci/controller.c new file mode 100644 index 0000000..234384f --- /dev/null +++ b/src/userland/usb/xhci/controller.c @@ -0,0 +1,184 @@ +#include "controller.h" +#include "../../hlib/include/syscalls.h" +#include "commands.h" +#include "trbRing.h" +#include +#include + +void restartXHCIController(XHCIController *controller) { + printf("resetting controller...\n"); + controller->operational->command &= ~1; + while (!(controller->operational->status & (1 << 0))) + syscall(-1, 0, 0, 0, 0); + controller->operational->command |= 1 << 1; + while ((controller->operational->command & (1 << 1))) + ; + while ((controller->operational->status & (1 << 11))) + ; +} + +void setupRuntime(XHCIController *controller) { + controller->runtime = OFFSET(controller->capabilities, + controller->capabilities->runtimeOffset); + controller->runtime->interrupters[0].eventRingSegmentTableSize = 1; + controller->runtime->interrupters[0].eventRingSegmentTableAddress[0] = + U32(controller->eventRingSegmentTablePhysical); + controller->runtime->interrupters[0].eventRingSegmentTableAddress[1] = 0; + controller->runtime->interrupters[0].eventRingDequeuePointer[0] = + U32(&controller->events.physical[controller->events.dequeue]) | + (1 << 3); + controller->runtime->interrupters[0].eventRingDequeuePointer[1] = 0; + + controller->runtime->interrupters[0].management |= 3; + sleep(100); +} + +void setupEventRingSegmentTable(XHCIController *controller) { + // todo: research necessary alignment + controller->eventRingSegmentTable = requestMemory(1, 0, 0); + controller->eventRingSegmentTablePhysical = + getPhysicalAddress((void *)controller->eventRingSegmentTable); + + controller->eventRingSegmentTable[0].ringSegmentBaseAddress[0] = + U32(controller->events.physical); + controller->eventRingSegmentTable[0].ringSegmentSize = + controller->events.size; +} + +void readExtendedCapabilities(XHCIController *controller) { + uintptr_t offset = (controller->capabilities->structuralParameters[0] >> 16) + << 2; + + volatile uint32_t *extendedCapabilities = + OFFSET(controller->capabilities, offset); + + while (1) { + uint32_t value = *extendedCapabilities; + + if ((value & 0xFF) == 2) { + uint8_t revisionMinor = extendedCapabilities[0] >> 16; + uint8_t revisionMajor = extendedCapabilities[0] >> 24; + + uint8_t portOffset = extendedCapabilities[2]; + uint8_t portCount = extendedCapabilities[2] >> 8; + + printf("protocol %i.%i %i port(s) starting from port %i\n", + revisionMajor, revisionMinor, portCount, portOffset); + } + + if (value == 0xFFFFFFFF) + break; + if ((value & 0xFF00) == 0) + break; + extendedCapabilities = + (void *)((uintptr_t)extendedCapabilities + ((value & 0xFF00) >> 6)); + } +} + +void setupOperationalRegisters(XHCIController *controller) { + controller->deviceContextBaseAddressArray = (void *)requestMemory(1, 0, 0); + controller->operational->deviceContextBaseAddressArray[0] = + U32(getPhysicalAddress(controller->deviceContextBaseAddressArray)); + controller->operational->deviceContextBaseAddressArray[1] = 0; + + controller->operational->config = + (controller->operational->config & ~0xFF) | 32; + + controller->operational->commandRingControl[0] = + U32(controller->commands.physical) | 1; + controller->operational->commandRingControl[1] = 0; + controller->operational->config = + controller->capabilities->structuralParameters[0] & 0xFF; +} + +void setupScratchpadBuffers(XHCIController *controller) { + uint32_t hcs2 = controller->capabilities->structuralParameters[1]; + uint32_t scratchpadBufferCountHigh = (hcs2 >> 21) & 0x1f; + uint32_t scratchpadBufferCountLow = (hcs2 >> 27) & 0x1f; + uint32_t scratchpadBufferCount = + (scratchpadBufferCountHigh << 5) | scratchpadBufferCountLow; + + if (scratchpadBufferCount) { + printf("%i scratchpad buffers present\n", scratchpadBufferCount); + + uint64_t *scratchpadBuffer = (uint64_t *)requestMemory(1, 0, 0); + void *scratchpadPhysical = getPhysicalAddress(scratchpadBuffer); + for (unsigned int i = 0; i < scratchpadBufferCount; ++i) { + void *sb_phys = getPhysicalAddress(requestMemory(1, 0, 0)); + scratchpadBuffer[i] = U32(sb_phys); + } + controller->deviceContextBaseAddressArray[0] = U32(scratchpadPhysical); + } +} + +XHCIController *initializeController(uint32_t deviceId, uint32_t bar0) { + XHCIController *controller = malloc(sizeof(XHCIController)); + controller->pciDevice = deviceId; + + controller->capabilities = requestMemory(4, 0, PTR(bar0 & ~0xF)); + controller->operational = + OFFSET(controller->capabilities, + controller->capabilities->capabilitiesLength & 0xFF); + controller->doorbells = OFFSET(controller->capabilities, + controller->capabilities->doorbellOffset); + + uint32_t slotInfo = controller->capabilities->structuralParameters[0]; + printf("%i available slots, %i available ports\n", slotInfo & 0xFF, + slotInfo >> 24); + controller->portCount = slotInfo >> 24; + return controller; +} + +XHCIController *globalController; + +void xhciInterrupt() { + if (globalController->runtime->interrupters[0].management & 1) { + globalController->runtime->interrupters[0].management |= 1; + XHCITRB *trb; + uint32_t index; + while ((trb = trbRingFetch(&globalController->events, &index))) { + globalController->runtime->interrupters[0] + .eventRingDequeuePointer[0] = + U32(&globalController->events + .physical[globalController->events.dequeue]) | + (1 << 3); + uint32_t eventId = + syscall(SYS_GET_EVENT, serviceId, trb->dataLow, 0, 0); + printf("event %i [%x %x %x %x]: %i\n", + globalController->events.dequeue, trb->dataLow, + trb->dataHigh, trb->status, trb->control, + trb->control >> 10 & 0x3F); + if (eventId) { + fireEvent(eventId, U32(trb)); + } + } + } +} + +XHCIController *xhciSetup(uint32_t deviceId, uint32_t bar0, + uint32_t interrupt) { + XHCIController *controller = initializeController(deviceId, bar0); + globalController = controller; + restartXHCIController(controller); + + setupTrbRing(&controller->commands, 256); + setupTrbRing(&controller->events, 256); + readExtendedCapabilities(controller); + setupOperationalRegisters(controller); + setupEventRingSegmentTable(controller); + setupRuntime(controller); + setupScratchpadBuffers(controller); + + controller->operational->status |= (1 << 3); + printf("using irq no. %i\n", interrupt); + int pic = getService("pic"); + subscribeEvent(pic, getEvent(pic, "irq11"), xhciInterrupt); + controller->operational->command |= (1 << 0) | (1 << 2); + sleep(100); + + if (controller->operational->status & (1 << 2)) { + printf("critical XHCI problem\n"); + return NULL; + } + return controller; +} diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 5875fee..c6040a0 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -3,13 +3,12 @@ #include "../hlib/include/syscalls.h" #include "xhci/commands.h" +#include "xhci/controller.h" #include "xhci/trbRing.h" #include uint32_t serviceId; -XHCIController *controller; - #define REQUEST(functionName, service, function) \ uint32_t functionName(uint32_t data1, uint32_t data2) { \ static uint32_t serviceId, functionId, initialized = false; \ @@ -32,131 +31,6 @@ REQUEST(enableBusMaster, "lspci", "enableBusMaster"); REQUEST(getPCIInterrupt, "lspci", "getInterrupt"); -void restartXHCIController(XHCIController *controller) { - printf("resetting controller...\n"); - controller->operational->command &= ~1; - while (!(controller->operational->status & (1 << 0))) - syscall(-1, 0, 0, 0, 0); - controller->operational->command |= 1 << 1; - while ((controller->operational->command & (1 << 1))) - ; - while ((controller->operational->status & (1 << 11))) - ; -} - -void setupRuntime(XHCIController *controller) { - controller->runtime = OFFSET(controller->capabilities, - controller->capabilities->runtimeOffset); - controller->runtime->interrupters[0].eventRingSegmentTableSize = 1; - controller->runtime->interrupters[0].eventRingSegmentTableAddress[0] = - U32(controller->eventRingSegmentTablePhysical); - controller->runtime->interrupters[0].eventRingSegmentTableAddress[1] = 0; - controller->runtime->interrupters[0].eventRingDequeuePointer[0] = - U32(&controller->events.physical[controller->events.dequeue]) | - (1 << 3); - controller->runtime->interrupters[0].eventRingDequeuePointer[1] = 0; - - controller->runtime->interrupters[0].management |= 3; - sleep(100); -} - -void setupEventRingSegmentTable(XHCIController *controller) { - // todo: research necessary alignment - controller->eventRingSegmentTable = requestMemory(1, 0, 0); - controller->eventRingSegmentTablePhysical = - getPhysicalAddress((void *)controller->eventRingSegmentTable); - - controller->eventRingSegmentTable[0].ringSegmentBaseAddress[0] = - U32(controller->events.physical); - controller->eventRingSegmentTable[0].ringSegmentSize = - controller->events.size; -} - -void readExtendedCapabilities(XHCIController *controller) { - uintptr_t offset = (controller->capabilities->structuralParameters[0] >> 16) - << 2; - - volatile uint32_t *extendedCapabilities = - OFFSET(controller->capabilities, offset); - - while (1) { - uint32_t value = *extendedCapabilities; - - if ((value & 0xFF) == 2) { - uint8_t revisionMinor = extendedCapabilities[0] >> 16; - uint8_t revisionMajor = extendedCapabilities[0] >> 24; - - uint8_t portOffset = extendedCapabilities[2]; - uint8_t portCount = extendedCapabilities[2] >> 8; - - printf("protocol %i.%i %i port(s) starting from port %i\n", - revisionMajor, revisionMinor, portCount, portOffset); - } - - if (value == 0xFFFFFFFF) - break; - if ((value & 0xFF00) == 0) - break; - extendedCapabilities = - (void *)((uintptr_t)extendedCapabilities + ((value & 0xFF00) >> 6)); - } -} - -void setupOperationalRegisters(XHCIController *controller) { - controller->deviceContextBaseAddressArray = (void *)requestMemory(1, 0, 0); - controller->operational->deviceContextBaseAddressArray[0] = - U32(getPhysicalAddress(controller->deviceContextBaseAddressArray)); - controller->operational->deviceContextBaseAddressArray[1] = 0; - - controller->operational->config = - (controller->operational->config & ~0xFF) | 32; - - controller->operational->commandRingControl[0] = - U32(controller->commands.physical) | 1; - controller->operational->commandRingControl[1] = 0; - controller->operational->config = - controller->capabilities->structuralParameters[0] & 0xFF; -} - -void setupScratchpadBuffers(XHCIController *controller) { - uint32_t hcs2 = controller->capabilities->structuralParameters[1]; - uint32_t scratchpadBufferCountHigh = (hcs2 >> 21) & 0x1f; - uint32_t scratchpadBufferCountLow = (hcs2 >> 27) & 0x1f; - uint32_t scratchpadBufferCount = - (scratchpadBufferCountHigh << 5) | scratchpadBufferCountLow; - - if (scratchpadBufferCount) { - printf("%i scratchpad buffers present\n", scratchpadBufferCount); - - uint64_t *scratchpadBuffer = (uint64_t *)requestMemory(1, 0, 0); - void *scratchpadPhysical = getPhysicalAddress(scratchpadBuffer); - for (unsigned int i = 0; i < scratchpadBufferCount; ++i) { - void *sb_phys = getPhysicalAddress(requestMemory(1, 0, 0)); - scratchpadBuffer[i] = U32(sb_phys); - } - controller->deviceContextBaseAddressArray[0] = U32(scratchpadPhysical); - } -} - -XHCIController *initializeController(uint32_t deviceId) { - XHCIController *controller = malloc(sizeof(XHCIController)); - controller->pciDevice = deviceId; - - controller->capabilities = - requestMemory(4, 0, PTR(U32(getBaseAddress(deviceId, 0)) & ~0xF)); - controller->operational = - OFFSET(controller->capabilities, - controller->capabilities->capabilitiesLength & 0xFF); - controller->doorbells = OFFSET(controller->capabilities, - controller->capabilities->doorbellOffset); - - uint32_t slotInfo = controller->capabilities->structuralParameters[0]; - printf("%i available slots, %i available ports\n", slotInfo & 0xFF, - slotInfo >> 24); - controller->portCount = slotInfo >> 24; - return controller; -} - XHCIInputContext *createInputContext(SlotXHCI *slot) { XHCIInputContext *inputContext = requestMemory(1, 0, 0); inputContext->inputControl.addContextFlags = 3; @@ -194,17 +68,13 @@ slot->controller = controller; slot->slotIndex = requestSlotIndex(controller); slot->port = &controller->operational->ports[portIndex - 1]; + printf("port %i: connecting to slot %i\n", portIndex - 1, slot->slotIndex); - printf("port %i: connected, resetting and setting it up now ...\n", - portIndex - 1); slot->port->status |= 1 << 4; await(serviceId, syscall(SYS_CREATE_EVENT, slot->portIndex << 24, 0, 0, 0)); if (!(slot->port->status & 1 << 1)) { - return printf("port %i reset could not be done, aborting\n", - portIndex - 1); + return printf("port %i reset not succesful, aborting\n", portIndex - 1); } - printf("port %i: reset done, now connecting to slot %i\n", portIndex - 1, - slot->slotIndex); slot->inputContext = createInputContext(slot); slot->controlRing = createSlotTRB(slot); slot->controller->deviceContextBaseAddressArray[slot->slotIndex] = @@ -235,57 +105,16 @@ printf("--------\n"); } -void xhciInterrupt() { - if (controller->runtime->interrupters[0].management & 1) { - controller->runtime->interrupters[0].management |= 1; - XHCITRB *trb; - uint32_t index; - while ((trb = trbRingFetch(&controller->events, &index))) { - controller->runtime->interrupters[0].eventRingDequeuePointer[0] = - U32(&controller->events.physical[controller->events.dequeue]) | - (1 << 3); - uint32_t eventId = - syscall(SYS_GET_EVENT, serviceId, trb->dataLow, 0, 0); - printf("event %i [%x %x %x %x]: %i\n", controller->events.dequeue, - trb->dataLow, trb->dataHigh, trb->status, trb->control, - trb->control >> 10 & 0x3F); - if (eventId) { - fireEvent(eventId, U32(trb)); - } - } - } -} - void initializeUSB(uint32_t deviceId) { - controller = initializeController(deviceId); - restartXHCIController(controller); - - setupTrbRing(&controller->commands, 256); - setupTrbRing(&controller->events, 256); - readExtendedCapabilities(controller); - setupOperationalRegisters(controller); - setupEventRingSegmentTable(controller); - setupRuntime(controller); - setupScratchpadBuffers(controller); - - controller->operational->status |= (1 << 3); - printf("using irq no. %i\n", getPCIInterrupt(deviceId, 0)); - int pic = getService("pic"); - subscribeEvent(pic, getEvent(pic, "irq11"), xhciInterrupt); - controller->operational->command |= (1 << 0) | (1 << 2); - sleep(100); - - if (controller->operational->status & (1 << 2)) { - return printf("critical XHCI problem\n"); - } - + uint32_t interrupt = getPCIInterrupt(deviceId, 0); + XHCIController *controller = + xhciSetup(deviceId, U32(getBaseAddress(deviceId, 0)), interrupt); for (uint32_t i = 0; i < controller->portCount; i++) { if (!(controller->operational->ports[i].status & 1 << 0)) { continue; } resetPort(controller, i + 1); } - return; } int32_t main() { diff --git a/src/userland/usb/xhci/controller.c b/src/userland/usb/xhci/controller.c new file mode 100644 index 0000000..234384f --- /dev/null +++ b/src/userland/usb/xhci/controller.c @@ -0,0 +1,184 @@ +#include "controller.h" +#include "../../hlib/include/syscalls.h" +#include "commands.h" +#include "trbRing.h" +#include +#include + +void restartXHCIController(XHCIController *controller) { + printf("resetting controller...\n"); + controller->operational->command &= ~1; + while (!(controller->operational->status & (1 << 0))) + syscall(-1, 0, 0, 0, 0); + controller->operational->command |= 1 << 1; + while ((controller->operational->command & (1 << 1))) + ; + while ((controller->operational->status & (1 << 11))) + ; +} + +void setupRuntime(XHCIController *controller) { + controller->runtime = OFFSET(controller->capabilities, + controller->capabilities->runtimeOffset); + controller->runtime->interrupters[0].eventRingSegmentTableSize = 1; + controller->runtime->interrupters[0].eventRingSegmentTableAddress[0] = + U32(controller->eventRingSegmentTablePhysical); + controller->runtime->interrupters[0].eventRingSegmentTableAddress[1] = 0; + controller->runtime->interrupters[0].eventRingDequeuePointer[0] = + U32(&controller->events.physical[controller->events.dequeue]) | + (1 << 3); + controller->runtime->interrupters[0].eventRingDequeuePointer[1] = 0; + + controller->runtime->interrupters[0].management |= 3; + sleep(100); +} + +void setupEventRingSegmentTable(XHCIController *controller) { + // todo: research necessary alignment + controller->eventRingSegmentTable = requestMemory(1, 0, 0); + controller->eventRingSegmentTablePhysical = + getPhysicalAddress((void *)controller->eventRingSegmentTable); + + controller->eventRingSegmentTable[0].ringSegmentBaseAddress[0] = + U32(controller->events.physical); + controller->eventRingSegmentTable[0].ringSegmentSize = + controller->events.size; +} + +void readExtendedCapabilities(XHCIController *controller) { + uintptr_t offset = (controller->capabilities->structuralParameters[0] >> 16) + << 2; + + volatile uint32_t *extendedCapabilities = + OFFSET(controller->capabilities, offset); + + while (1) { + uint32_t value = *extendedCapabilities; + + if ((value & 0xFF) == 2) { + uint8_t revisionMinor = extendedCapabilities[0] >> 16; + uint8_t revisionMajor = extendedCapabilities[0] >> 24; + + uint8_t portOffset = extendedCapabilities[2]; + uint8_t portCount = extendedCapabilities[2] >> 8; + + printf("protocol %i.%i %i port(s) starting from port %i\n", + revisionMajor, revisionMinor, portCount, portOffset); + } + + if (value == 0xFFFFFFFF) + break; + if ((value & 0xFF00) == 0) + break; + extendedCapabilities = + (void *)((uintptr_t)extendedCapabilities + ((value & 0xFF00) >> 6)); + } +} + +void setupOperationalRegisters(XHCIController *controller) { + controller->deviceContextBaseAddressArray = (void *)requestMemory(1, 0, 0); + controller->operational->deviceContextBaseAddressArray[0] = + U32(getPhysicalAddress(controller->deviceContextBaseAddressArray)); + controller->operational->deviceContextBaseAddressArray[1] = 0; + + controller->operational->config = + (controller->operational->config & ~0xFF) | 32; + + controller->operational->commandRingControl[0] = + U32(controller->commands.physical) | 1; + controller->operational->commandRingControl[1] = 0; + controller->operational->config = + controller->capabilities->structuralParameters[0] & 0xFF; +} + +void setupScratchpadBuffers(XHCIController *controller) { + uint32_t hcs2 = controller->capabilities->structuralParameters[1]; + uint32_t scratchpadBufferCountHigh = (hcs2 >> 21) & 0x1f; + uint32_t scratchpadBufferCountLow = (hcs2 >> 27) & 0x1f; + uint32_t scratchpadBufferCount = + (scratchpadBufferCountHigh << 5) | scratchpadBufferCountLow; + + if (scratchpadBufferCount) { + printf("%i scratchpad buffers present\n", scratchpadBufferCount); + + uint64_t *scratchpadBuffer = (uint64_t *)requestMemory(1, 0, 0); + void *scratchpadPhysical = getPhysicalAddress(scratchpadBuffer); + for (unsigned int i = 0; i < scratchpadBufferCount; ++i) { + void *sb_phys = getPhysicalAddress(requestMemory(1, 0, 0)); + scratchpadBuffer[i] = U32(sb_phys); + } + controller->deviceContextBaseAddressArray[0] = U32(scratchpadPhysical); + } +} + +XHCIController *initializeController(uint32_t deviceId, uint32_t bar0) { + XHCIController *controller = malloc(sizeof(XHCIController)); + controller->pciDevice = deviceId; + + controller->capabilities = requestMemory(4, 0, PTR(bar0 & ~0xF)); + controller->operational = + OFFSET(controller->capabilities, + controller->capabilities->capabilitiesLength & 0xFF); + controller->doorbells = OFFSET(controller->capabilities, + controller->capabilities->doorbellOffset); + + uint32_t slotInfo = controller->capabilities->structuralParameters[0]; + printf("%i available slots, %i available ports\n", slotInfo & 0xFF, + slotInfo >> 24); + controller->portCount = slotInfo >> 24; + return controller; +} + +XHCIController *globalController; + +void xhciInterrupt() { + if (globalController->runtime->interrupters[0].management & 1) { + globalController->runtime->interrupters[0].management |= 1; + XHCITRB *trb; + uint32_t index; + while ((trb = trbRingFetch(&globalController->events, &index))) { + globalController->runtime->interrupters[0] + .eventRingDequeuePointer[0] = + U32(&globalController->events + .physical[globalController->events.dequeue]) | + (1 << 3); + uint32_t eventId = + syscall(SYS_GET_EVENT, serviceId, trb->dataLow, 0, 0); + printf("event %i [%x %x %x %x]: %i\n", + globalController->events.dequeue, trb->dataLow, + trb->dataHigh, trb->status, trb->control, + trb->control >> 10 & 0x3F); + if (eventId) { + fireEvent(eventId, U32(trb)); + } + } + } +} + +XHCIController *xhciSetup(uint32_t deviceId, uint32_t bar0, + uint32_t interrupt) { + XHCIController *controller = initializeController(deviceId, bar0); + globalController = controller; + restartXHCIController(controller); + + setupTrbRing(&controller->commands, 256); + setupTrbRing(&controller->events, 256); + readExtendedCapabilities(controller); + setupOperationalRegisters(controller); + setupEventRingSegmentTable(controller); + setupRuntime(controller); + setupScratchpadBuffers(controller); + + controller->operational->status |= (1 << 3); + printf("using irq no. %i\n", interrupt); + int pic = getService("pic"); + subscribeEvent(pic, getEvent(pic, "irq11"), xhciInterrupt); + controller->operational->command |= (1 << 0) | (1 << 2); + sleep(100); + + if (controller->operational->status & (1 << 2)) { + printf("critical XHCI problem\n"); + return NULL; + } + return controller; +} diff --git a/src/userland/usb/xhci/controller.h b/src/userland/usb/xhci/controller.h new file mode 100644 index 0000000..568c274 --- /dev/null +++ b/src/userland/usb/xhci/controller.h @@ -0,0 +1,9 @@ +#ifndef XHCI_CONTROLLER_H +#define XHCI_CONTROLLER_H + +#include + +extern XHCIController *xhciSetup(uint32_t deviceId, uint32_t bar0, + uint32_t interrupt); + +#endif