diff --git a/Makefile b/Makefile index 0413fc8..d379b0a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -IMAGE_FILE = /run/user/1000/tree-os.img +IMAGE_FILE = /run/user/1000/honey-os.img CC = i686-elf-gcc CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -I src/kernel/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 diff --git a/Makefile b/Makefile index 0413fc8..d379b0a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -IMAGE_FILE = /run/user/1000/tree-os.img +IMAGE_FILE = /run/user/1000/honey-os.img CC = i686-elf-gcc CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -I src/kernel/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 diff --git a/src/userland/lspci/main.c b/src/userland/lspci/main.c index c66e2a9..80c0b6d 100644 --- a/src/userland/lspci/main.c +++ b/src/userland/lspci/main.c @@ -50,26 +50,12 @@ ioOut(0xCFC, data, 2); } -// uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, -// uint8_t offset) { -// return (uint16_t)pciConfigReadByte(bus, device, function, offset) | -// ((uint16_t)pciConfigReadByte(bus, device, function, offset + 1) -// << 8); -//} - void pciConfigWriteWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint16_t data) { pciConfigWriteByte(bus, device, function, offset, (uint8_t)data); pciConfigWriteByte(bus, device, function, offset + 1, (uint8_t)(data >> 8)); } -// uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, -// uint8_t offset) { -// return (uint32_t)pciConfigReadWord(bus, device, function, offset) | -// ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) -// << 16); -//} - uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigRead(bus, device, function, 0x0E) & 0xFF; } diff --git a/Makefile b/Makefile index 0413fc8..d379b0a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -IMAGE_FILE = /run/user/1000/tree-os.img +IMAGE_FILE = /run/user/1000/honey-os.img CC = i686-elf-gcc CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -I src/kernel/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 diff --git a/src/userland/lspci/main.c b/src/userland/lspci/main.c index c66e2a9..80c0b6d 100644 --- a/src/userland/lspci/main.c +++ b/src/userland/lspci/main.c @@ -50,26 +50,12 @@ ioOut(0xCFC, data, 2); } -// uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, -// uint8_t offset) { -// return (uint16_t)pciConfigReadByte(bus, device, function, offset) | -// ((uint16_t)pciConfigReadByte(bus, device, function, offset + 1) -// << 8); -//} - void pciConfigWriteWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint16_t data) { pciConfigWriteByte(bus, device, function, offset, (uint8_t)data); pciConfigWriteByte(bus, device, function, offset + 1, (uint8_t)(data >> 8)); } -// uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, -// uint8_t offset) { -// return (uint32_t)pciConfigReadWord(bus, device, function, offset) | -// ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) -// << 16); -//} - uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigRead(bus, device, function, 0x0E) & 0xFF; } diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 104e08c..8fe12a1 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -21,14 +21,88 @@ REQUEST(enableBusMaster, "lspci", "enableBusMaster"); +uint32_t getPortSpeed(XHCIPortRegister *port) { + return (port->statusControl > 5) & 0xF; +} + +char *getPortSpeedString(XHCIPortRegister *port) { + switch (getPortSpeed(port)) { + case 1: + return "Full Speed (USB 1.0)"; + case 2: + return "Low Speed (USB 1.0)"; + case 3: + return "Full Speed (USB 2.0)"; + case 4: + return "Super Speed (USB 3.0)"; + } + return "unknown speed"; +} + +void resetRootPort(XHCIPortRegister *port) { + if (!(port->statusControl & 1)) { + // this port has nothing connected to it + return; + } + printf("port linkInfo: %x power: %x status: %x, speed: %s\n", + port->linkInfo, port->powerManagement, port->statusControl, + getPortSpeedString(port)); +} + +void resetController(XHCICapabilities *capabilities, + XHCIOperationalRegisters *operational) { + operational->usbCommand &= ~(1); // stop controller + while (!(operational->usbStatus & 1)) + syscall(-1, 0, 0, 0, 0); + operational->usbCommand |= 2; // reset controller + while (operational->usbStatus & 2) + syscall(-1, 0, 0, 0, 0); + printf("XHCI controller reset done\n"); +} + +uint16_t findExtendedCapabilities(XHCICapabilities *capabilities) { + uint16_t extendedCapabilityOffset = + capabilities->capabilityParameters1 >> 16; + uint8_t id = 0; + while (extendedCapabilityOffset) { + id = *(uint8_t *)OFFSET(capabilities, extendedCapabilityOffset); + uint8_t offset = + *(uint8_t *)OFFSET(capabilities, extendedCapabilityOffset + 1); + if (!offset) { + extendedCapabilityOffset = 0; + } else { + extendedCapabilityOffset += offset << 2; + } + } + return extendedCapabilityOffset; +} + +void deactivateXHCILegacy(XHCICapabilities *capabilities) { + uint16_t extendedCapabilityOffset = findExtendedCapabilities(capabilities); + if (!extendedCapabilityOffset) { + printf("XHCI controller already owned by honey-OS\n"); + return; + } + printf("TODO: get XHCI controller ownership from the BIOS\n"); +} + void initializeUSB(uint32_t deviceId) { enableBusMaster(deviceId, 0); uint32_t baseAddress = getBaseAddress(deviceId, 0) & ~0xF; XHCICapabilities *capabilities = requestMemory(1, NULL, PTR(baseAddress)); - uint32_t *ptr = (void *)capabilities; - printf("%x: capSize: 0x%x, version: 0x%x %x\n", capabilities, - capabilities->capabilitiesSize, capabilities->interfaceVersion, - ptr[0]); + XHCIOperationalRegisters *operational = + OFFSET(capabilities, capabilities->capabilitiesSize); + resetController(capabilities, operational); + deactivateXHCILegacy(capabilities); + if (!(operational->usbStatus & 1)) { + printf("controller is not halted, aborting...\n"); + } + XHCIPortRegister *ports = OFFSET(operational, 0x400); + for (uint32_t i = 0; i < 16; i++) { + resetRootPort(&ports[i]); + } + printf("status: %x command: %x\n", operational->usbStatus, + operational->usbCommand); } int32_t main() { diff --git a/Makefile b/Makefile index 0413fc8..d379b0a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -IMAGE_FILE = /run/user/1000/tree-os.img +IMAGE_FILE = /run/user/1000/honey-os.img CC = i686-elf-gcc CCFLAGS = -m32 -mtune=generic -ffreestanding -nostdlib -c -I src/include -I src/kernel/include -Wno-discarded-qualifiers -fms-extensions -Wno-shift-count-overflow -O0 diff --git a/src/userland/lspci/main.c b/src/userland/lspci/main.c index c66e2a9..80c0b6d 100644 --- a/src/userland/lspci/main.c +++ b/src/userland/lspci/main.c @@ -50,26 +50,12 @@ ioOut(0xCFC, data, 2); } -// uint16_t pciConfigReadWord(uint8_t bus, uint8_t device, uint8_t function, -// uint8_t offset) { -// return (uint16_t)pciConfigReadByte(bus, device, function, offset) | -// ((uint16_t)pciConfigReadByte(bus, device, function, offset + 1) -// << 8); -//} - void pciConfigWriteWord(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint16_t data) { pciConfigWriteByte(bus, device, function, offset, (uint8_t)data); pciConfigWriteByte(bus, device, function, offset + 1, (uint8_t)(data >> 8)); } -// uint32_t pciConfigReadInt(uint8_t bus, uint8_t device, uint8_t function, -// uint8_t offset) { -// return (uint32_t)pciConfigReadWord(bus, device, function, offset) | -// ((uint32_t)pciConfigReadWord(bus, device, function, offset + 2) -// << 16); -//} - uint8_t getHeaderType(uint8_t bus, uint8_t device, uint8_t function) { return pciConfigRead(bus, device, function, 0x0E) & 0xFF; } diff --git a/src/userland/usb/main.c b/src/userland/usb/main.c index 104e08c..8fe12a1 100644 --- a/src/userland/usb/main.c +++ b/src/userland/usb/main.c @@ -21,14 +21,88 @@ REQUEST(enableBusMaster, "lspci", "enableBusMaster"); +uint32_t getPortSpeed(XHCIPortRegister *port) { + return (port->statusControl > 5) & 0xF; +} + +char *getPortSpeedString(XHCIPortRegister *port) { + switch (getPortSpeed(port)) { + case 1: + return "Full Speed (USB 1.0)"; + case 2: + return "Low Speed (USB 1.0)"; + case 3: + return "Full Speed (USB 2.0)"; + case 4: + return "Super Speed (USB 3.0)"; + } + return "unknown speed"; +} + +void resetRootPort(XHCIPortRegister *port) { + if (!(port->statusControl & 1)) { + // this port has nothing connected to it + return; + } + printf("port linkInfo: %x power: %x status: %x, speed: %s\n", + port->linkInfo, port->powerManagement, port->statusControl, + getPortSpeedString(port)); +} + +void resetController(XHCICapabilities *capabilities, + XHCIOperationalRegisters *operational) { + operational->usbCommand &= ~(1); // stop controller + while (!(operational->usbStatus & 1)) + syscall(-1, 0, 0, 0, 0); + operational->usbCommand |= 2; // reset controller + while (operational->usbStatus & 2) + syscall(-1, 0, 0, 0, 0); + printf("XHCI controller reset done\n"); +} + +uint16_t findExtendedCapabilities(XHCICapabilities *capabilities) { + uint16_t extendedCapabilityOffset = + capabilities->capabilityParameters1 >> 16; + uint8_t id = 0; + while (extendedCapabilityOffset) { + id = *(uint8_t *)OFFSET(capabilities, extendedCapabilityOffset); + uint8_t offset = + *(uint8_t *)OFFSET(capabilities, extendedCapabilityOffset + 1); + if (!offset) { + extendedCapabilityOffset = 0; + } else { + extendedCapabilityOffset += offset << 2; + } + } + return extendedCapabilityOffset; +} + +void deactivateXHCILegacy(XHCICapabilities *capabilities) { + uint16_t extendedCapabilityOffset = findExtendedCapabilities(capabilities); + if (!extendedCapabilityOffset) { + printf("XHCI controller already owned by honey-OS\n"); + return; + } + printf("TODO: get XHCI controller ownership from the BIOS\n"); +} + void initializeUSB(uint32_t deviceId) { enableBusMaster(deviceId, 0); uint32_t baseAddress = getBaseAddress(deviceId, 0) & ~0xF; XHCICapabilities *capabilities = requestMemory(1, NULL, PTR(baseAddress)); - uint32_t *ptr = (void *)capabilities; - printf("%x: capSize: 0x%x, version: 0x%x %x\n", capabilities, - capabilities->capabilitiesSize, capabilities->interfaceVersion, - ptr[0]); + XHCIOperationalRegisters *operational = + OFFSET(capabilities, capabilities->capabilitiesSize); + resetController(capabilities, operational); + deactivateXHCILegacy(capabilities); + if (!(operational->usbStatus & 1)) { + printf("controller is not halted, aborting...\n"); + } + XHCIPortRegister *ports = OFFSET(operational, 0x400); + for (uint32_t i = 0; i < 16; i++) { + resetRootPort(&ports[i]); + } + printf("status: %x command: %x\n", operational->usbStatus, + operational->usbCommand); } int32_t main() { diff --git a/src/userland/usb/usb.h b/src/userland/usb/usb.h index 2092c14..82a8b3f 100644 --- a/src/userland/usb/usb.h +++ b/src/userland/usb/usb.h @@ -3,6 +3,8 @@ #include +#define OFFSET(ptr, off) (((void *)ptr) + off) + typedef struct { uint8_t capabilitiesSize; uint8_t reserved; @@ -14,4 +16,16 @@ uint32_t capabilityParameters2; } XHCICapabilities; +typedef struct { + uint32_t usbCommand, usbStatus; + uint64_t pageSize; + uint32_t deviceNotificationControl, commandRingControl; + uint64_t deviceContextArrayOffset; + uint32_t configure; +} XHCIOperationalRegisters; + +typedef struct { + uint32_t statusControl, powerManagement, linkInfo, reserved; +} XHCIPortRegister; + #endif