diff --git a/src/userland/lspci/main.c b/src/userland/lspci/main.c index 80c0b6d..ebd7275 100644 --- a/src/userland/lspci/main.c +++ b/src/userland/lspci/main.c @@ -128,11 +128,13 @@ int32_t getDeviceClass(uint32_t deviceId); int32_t getBaseAddress(uint32_t deviceId, uint32_t n); int32_t enableBusMaster(uint32_t deviceId); +int32_t getPCIInterrupt(uint32_t deviceId); void initializePci() { createFunction("getDeviceClass", (void *)getDeviceClass); createFunction("getBaseAddress", (void *)getBaseAddress); createFunction("enableBusMaster", (void *)enableBusMaster); + createFunction("getInterrupt", (void *)getPCIInterrupt); if (!(getHeaderType(0, 0, 0) & 0x80)) { checkBus(0); } else { @@ -181,6 +183,12 @@ return 0; } +int32_t getPCIInterrupt(uint32_t deviceId) { + GET_HEADER + return pciConfigRead(device->bus, device->device, device->function, 0x3C) & + 0xFF; +} + int32_t main() { if (!initialized) { initializePci(); diff --git a/src/userland/lspci/main.c b/src/userland/lspci/main.c index 80c0b6d..ebd7275 100644 --- a/src/userland/lspci/main.c +++ b/src/userland/lspci/main.c @@ -128,11 +128,13 @@ int32_t getDeviceClass(uint32_t deviceId); int32_t getBaseAddress(uint32_t deviceId, uint32_t n); int32_t enableBusMaster(uint32_t deviceId); +int32_t getPCIInterrupt(uint32_t deviceId); void initializePci() { createFunction("getDeviceClass", (void *)getDeviceClass); createFunction("getBaseAddress", (void *)getBaseAddress); createFunction("enableBusMaster", (void *)enableBusMaster); + createFunction("getInterrupt", (void *)getPCIInterrupt); if (!(getHeaderType(0, 0, 0) & 0x80)) { checkBus(0); } else { @@ -181,6 +183,12 @@ return 0; } +int32_t getPCIInterrupt(uint32_t deviceId) { + GET_HEADER + return pciConfigRead(device->bus, device->device, device->function, 0x3C) & + 0xFF; +} + int32_t main() { if (!initialized) { initializePci(); diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 048fcef..fe2ac39 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -20,6 +20,7 @@ REQUEST(getDeviceClass, "lspci", "getDeviceClass"); REQUEST(enableBusMaster, "lspci", "enableBusMaster"); +REQUEST(getPCIInterrupt, "lspci", "getInterrupt"); uint32_t getPortSpeed(XHCIPortRegister *port) { return (port->statusControl > 5) & 0xF; @@ -39,11 +40,33 @@ return "unknown speed"; } -void resetRootPort(XHCIPortRegister *port) { +void initializePort(XHCIController *controller, uint8_t index) { + XHCIPortRegister *port = &controller->ports[index]; if (!(port->statusControl & 1)) { // this port has nothing connected to it return; } + controller->deviceContexts[index] = malloc(sizeof(DeviceContext)); + controller->deviceContextArray->deviceContextPointer[index] = + U32(getPhysicalAddress(controller->deviceContexts[index])); + controller->inputContexts[index] = malloc(sizeof(XHCIInputContext)); + controller->slots[index] = malloc(sizeof(XHCISlot)); + for (uint32_t endpoint; endpoint < 31; endpoint++) { + XHCITransferRequestBlock *trbs = + malloc(256 * sizeof(XHCITransferRequestBlock)); + controller->trbs[index][endpoint] = trbs; + controller->slots[index]->endpoints[endpoint].trbs = trbs; + controller->slots[index]->endpoints[endpoint].cycleState = true; + controller->slots[index]->endpoints[endpoint].transferCount = 0; + controller->slots[index]->endpoints[endpoint].timeEvent = 0; + + XHCITransferRequestBlock *cycleTrb = &trbs[255]; + cycleTrb->dataLow = U32(getPhysicalAddress(trbs)); + cycleTrb->dataHigh = 0; + cycleTrb->type = 6; + cycleTrb->cycle = 1; + cycleTrb->interruptTarget = 0; + } printf("port linkInfo: %x power: %x status: %x, speed: %s\n", port->linkInfo, port->powerManagement, port->statusControl, getPortSpeedString(port)); @@ -109,6 +132,45 @@ } } +void waitForKeyPress() { + printf("press a key to continue...\n"); + uint32_t ioManager = getService("ioManager"); + await(ioManager, getEvent(ioManager, "keyPress")); +} + +void usbInterrupt() { printf("usb interrupt detected!\n"); } + +void setupEvents(XHCIController *controller) { + printf("setting up events...\n"); + controller->eventSegmentSize = 32; + controller->eventSegmentNumber = 1; + controller->eventRing = + malloc(controller->eventSegmentSize * sizeof(XHCITransferRequestBlock)); + XHCIEventRingTableEntry *eventRingTableEntry = + malloc(sizeof(XHCIEventRingTableEntry)); + eventRingTableEntry->baseLow = + U32(getPhysicalAddress(controller->eventRing)); + eventRingTableEntry->baseHigh = 0; + eventRingTableEntry->ringSegmentSize = controller->eventSegmentSize; + + controller->runtime->interrupterRegisters[0].eventRingSize = + controller->eventSegmentSize; + controller->runtime->interrupterRegisters[0].eventRingDequeueLow = + U32(getPhysicalAddress(controller->eventRing)); + controller->runtime->interrupterRegisters[0].eventRingDequeueHigh = 0; + + controller->runtime->interrupterRegisters[0].eventRingBaseLow = + U32(getPhysicalAddress(eventRingTableEntry)); + controller->runtime->interrupterRegisters[0].eventRingBaseHigh = 0; + + controller->runtime->interrupterRegisters[0].moderationInterval = 4000; + controller->runtime->interrupterRegisters[0].moderationCounter = 0; + + controller->operational->usbCommand |= 1 << 2; + controller->runtime->interrupterRegisters[0].pending = 1; + controller->runtime->interrupterRegisters[0].enabled = 1; +} + void initializeUSB(uint32_t deviceId) { XHCIController *controller = malloc(sizeof(XHCIController)); controller->pciDeviceId = deviceId; @@ -117,11 +179,15 @@ controller->capabilities = requestMemory(1, NULL, PTR(baseAddress)); controller->operational = OFFSET( controller->capabilities, controller->capabilities->capabilitiesSize); + controller->runtime = + OFFSET(controller->capabilities, + controller->capabilities->runtimeRegistersSpaceOffset); resetController(controller); deactivateXHCILegacy(controller); if (!(controller->operational->usbStatus & 1)) { - printf("controller is not halted, aborting...\n"); + return printf("controller is not halted, aborting...\n"); } + syscall(-1, 0, 0, 0, 0); controller->operational->deviceNotificationControl = 2; controller->operational->configure |= 16; controller->deviceContextArray = malloc(sizeof(DeviceContextArray)); @@ -130,8 +196,36 @@ createScratchpadBuffers(controller); controller->ports = OFFSET(controller->operational, 0x400); for (uint32_t i = 0; i < 16; i++) { - resetRootPort(&controller->ports[i]); + initializePort(controller, i); } + controller->commandRing = malloc(256 * sizeof(XHCITransferRequestBlock)); + controller->commandRing[255].dataLow = + U32(getPhysicalAddress(controller->commandRing)); + controller->commandRing[255].type = 6; + controller->commandRing[255].cycle = true; + controller->operational->commandRingControl = + U32(getPhysicalAddress(controller->commandRing)) | 1; + + controller->operational->usbCommand |= 1; + controller->interrupt = getPCIInterrupt(controller->pciDeviceId, 0); + setupEvents(controller); + printf("irq pin : %i\n", controller->interrupt); + uint32_t pic = getService("pic"); + subscribeEvent(pic, getEvent(pic, "irq11"), (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); } int32_t main() { diff --git a/src/userland/lspci/main.c b/src/userland/lspci/main.c index 80c0b6d..ebd7275 100644 --- a/src/userland/lspci/main.c +++ b/src/userland/lspci/main.c @@ -128,11 +128,13 @@ int32_t getDeviceClass(uint32_t deviceId); int32_t getBaseAddress(uint32_t deviceId, uint32_t n); int32_t enableBusMaster(uint32_t deviceId); +int32_t getPCIInterrupt(uint32_t deviceId); void initializePci() { createFunction("getDeviceClass", (void *)getDeviceClass); createFunction("getBaseAddress", (void *)getBaseAddress); createFunction("enableBusMaster", (void *)enableBusMaster); + createFunction("getInterrupt", (void *)getPCIInterrupt); if (!(getHeaderType(0, 0, 0) & 0x80)) { checkBus(0); } else { @@ -181,6 +183,12 @@ return 0; } +int32_t getPCIInterrupt(uint32_t deviceId) { + GET_HEADER + return pciConfigRead(device->bus, device->device, device->function, 0x3C) & + 0xFF; +} + int32_t main() { if (!initialized) { initializePci(); diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 048fcef..fe2ac39 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -20,6 +20,7 @@ REQUEST(getDeviceClass, "lspci", "getDeviceClass"); REQUEST(enableBusMaster, "lspci", "enableBusMaster"); +REQUEST(getPCIInterrupt, "lspci", "getInterrupt"); uint32_t getPortSpeed(XHCIPortRegister *port) { return (port->statusControl > 5) & 0xF; @@ -39,11 +40,33 @@ return "unknown speed"; } -void resetRootPort(XHCIPortRegister *port) { +void initializePort(XHCIController *controller, uint8_t index) { + XHCIPortRegister *port = &controller->ports[index]; if (!(port->statusControl & 1)) { // this port has nothing connected to it return; } + controller->deviceContexts[index] = malloc(sizeof(DeviceContext)); + controller->deviceContextArray->deviceContextPointer[index] = + U32(getPhysicalAddress(controller->deviceContexts[index])); + controller->inputContexts[index] = malloc(sizeof(XHCIInputContext)); + controller->slots[index] = malloc(sizeof(XHCISlot)); + for (uint32_t endpoint; endpoint < 31; endpoint++) { + XHCITransferRequestBlock *trbs = + malloc(256 * sizeof(XHCITransferRequestBlock)); + controller->trbs[index][endpoint] = trbs; + controller->slots[index]->endpoints[endpoint].trbs = trbs; + controller->slots[index]->endpoints[endpoint].cycleState = true; + controller->slots[index]->endpoints[endpoint].transferCount = 0; + controller->slots[index]->endpoints[endpoint].timeEvent = 0; + + XHCITransferRequestBlock *cycleTrb = &trbs[255]; + cycleTrb->dataLow = U32(getPhysicalAddress(trbs)); + cycleTrb->dataHigh = 0; + cycleTrb->type = 6; + cycleTrb->cycle = 1; + cycleTrb->interruptTarget = 0; + } printf("port linkInfo: %x power: %x status: %x, speed: %s\n", port->linkInfo, port->powerManagement, port->statusControl, getPortSpeedString(port)); @@ -109,6 +132,45 @@ } } +void waitForKeyPress() { + printf("press a key to continue...\n"); + uint32_t ioManager = getService("ioManager"); + await(ioManager, getEvent(ioManager, "keyPress")); +} + +void usbInterrupt() { printf("usb interrupt detected!\n"); } + +void setupEvents(XHCIController *controller) { + printf("setting up events...\n"); + controller->eventSegmentSize = 32; + controller->eventSegmentNumber = 1; + controller->eventRing = + malloc(controller->eventSegmentSize * sizeof(XHCITransferRequestBlock)); + XHCIEventRingTableEntry *eventRingTableEntry = + malloc(sizeof(XHCIEventRingTableEntry)); + eventRingTableEntry->baseLow = + U32(getPhysicalAddress(controller->eventRing)); + eventRingTableEntry->baseHigh = 0; + eventRingTableEntry->ringSegmentSize = controller->eventSegmentSize; + + controller->runtime->interrupterRegisters[0].eventRingSize = + controller->eventSegmentSize; + controller->runtime->interrupterRegisters[0].eventRingDequeueLow = + U32(getPhysicalAddress(controller->eventRing)); + controller->runtime->interrupterRegisters[0].eventRingDequeueHigh = 0; + + controller->runtime->interrupterRegisters[0].eventRingBaseLow = + U32(getPhysicalAddress(eventRingTableEntry)); + controller->runtime->interrupterRegisters[0].eventRingBaseHigh = 0; + + controller->runtime->interrupterRegisters[0].moderationInterval = 4000; + controller->runtime->interrupterRegisters[0].moderationCounter = 0; + + controller->operational->usbCommand |= 1 << 2; + controller->runtime->interrupterRegisters[0].pending = 1; + controller->runtime->interrupterRegisters[0].enabled = 1; +} + void initializeUSB(uint32_t deviceId) { XHCIController *controller = malloc(sizeof(XHCIController)); controller->pciDeviceId = deviceId; @@ -117,11 +179,15 @@ controller->capabilities = requestMemory(1, NULL, PTR(baseAddress)); controller->operational = OFFSET( controller->capabilities, controller->capabilities->capabilitiesSize); + controller->runtime = + OFFSET(controller->capabilities, + controller->capabilities->runtimeRegistersSpaceOffset); resetController(controller); deactivateXHCILegacy(controller); if (!(controller->operational->usbStatus & 1)) { - printf("controller is not halted, aborting...\n"); + return printf("controller is not halted, aborting...\n"); } + syscall(-1, 0, 0, 0, 0); controller->operational->deviceNotificationControl = 2; controller->operational->configure |= 16; controller->deviceContextArray = malloc(sizeof(DeviceContextArray)); @@ -130,8 +196,36 @@ createScratchpadBuffers(controller); controller->ports = OFFSET(controller->operational, 0x400); for (uint32_t i = 0; i < 16; i++) { - resetRootPort(&controller->ports[i]); + initializePort(controller, i); } + controller->commandRing = malloc(256 * sizeof(XHCITransferRequestBlock)); + controller->commandRing[255].dataLow = + U32(getPhysicalAddress(controller->commandRing)); + controller->commandRing[255].type = 6; + controller->commandRing[255].cycle = true; + controller->operational->commandRingControl = + U32(getPhysicalAddress(controller->commandRing)) | 1; + + controller->operational->usbCommand |= 1; + controller->interrupt = getPCIInterrupt(controller->pciDeviceId, 0); + setupEvents(controller); + printf("irq pin : %i\n", controller->interrupt); + uint32_t pic = getService("pic"); + subscribeEvent(pic, getEvent(pic, "irq11"), (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); } int32_t main() { diff --git a/src/userland/usb/usb.h b/src/userland/usb/usb.h index d27bcad..6d04df4 100644 --- a/src/userland/usb/usb.h +++ b/src/userland/usb/usb.h @@ -83,6 +83,17 @@ } DeviceContext; typedef struct { + uint32_t D; // drop contextFlags + uint32_t A; // add context flags + uint32_t reserved[5]; + uint8_t configValue; + uint8_t interfaceNumber; + uint8_t alternateSetting; + uint8_t reserved1; + DeviceContext deviceContext; +} XHCIInputContext; + +typedef struct { uint64_t scratchpadBufferBase; uint64_t deviceContextPointer[16]; } DeviceContextArray; @@ -92,6 +103,81 @@ } XHCIPortRegister; typedef struct { + uint32_t dataLow; + uint32_t dataHigh; + + uint32_t dataSize : 17; + uint32_t transferSize : 5; + uint32_t interruptTarget : 10; + + uint32_t cycle : 1; + uint32_t ent : 1; + uint32_t interruptOnShortPacket : 1; + uint32_t noSnoop : 1; + uint32_t chainBit : 1; + uint32_t interruptOnCompletion : 1; + uint32_t immediateData : 1; + uint32_t reserved : 2; + uint32_t blockEventInterrupt : 1; + uint32_t type : 6; + uint32_t reserved1 : 16; +} XHCITransferRequestBlock; + +typedef struct { + uint32_t timeTransfer; + uint32_t timeEvent; + uint8_t epState; + bool pendingTransfer; + uint8_t transferError; + + bool cycleState; + + uint32_t transferCount; + + XHCITransferRequestBlock *trbs; +} XHCIEndpoint; + +typedef struct { + XHCIEndpoint endpoints[31]; + uint8_t slotState; +} XHCISlot; + +typedef struct { + uint32_t baseLow; + uint32_t baseHigh; + uint32_t ringSegmentSize : 16; + uint32_t reserved : 16; + uint32_t reserved1; +} XHCIEventRingTableEntry; + +typedef struct { + uint32_t pending : 1; + uint32_t enabled : 1; + uint32_t reserved : 30; + + uint16_t moderationInterval; + uint16_t moderationCounter; + + uint16_t eventRingSize; + uint16_t reserved1; + + uint32_t reserved2; + + uint32_t eventRingBaseLow; + uint32_t eventRingBaseHigh; + + uint32_t eventRingDequeueLow; + uint32_t eventRingDequeueHigh; +} XHCIInterrupterRegisterSet; + +typedef struct { + uint32_t microframeIndex : 14; + uint32_t reserved : 18; + uint32_t reserved1[7]; + XHCIInterrupterRegisterSet interrupterRegisters[128]; +} XHCIRuntimeRegisters; + +typedef struct { uint32_t pciDeviceId; XHCICapabilities *capabilities; XHCIOperationalRegisters *operational; @@ -99,6 +185,17 @@ void **scratchpadBuffers; uint32_t scratchpadBufferCount; XHCIPortRegister *ports; + DeviceContext *deviceContexts[16]; + XHCIInputContext *inputContexts[16]; + XHCISlot *slots[16]; + XHCITransferRequestBlock *trbs[16][32]; + XHCITransferRequestBlock *commandRing; + uint32_t interrupt; + uint32_t eventSegmentSize; + uint32_t eventSegmentCounter; + uint32_t eventSegmentNumber; + XHCITransferRequestBlock *eventRing; + XHCIRuntimeRegisters *runtime; } XHCIController; #endif