xhci: start on controller driver

This commit is contained in:
K. Lange 2021-07-14 10:44:46 +09:00
parent 1f5e3bb8be
commit 8e4640e1d7
4 changed files with 89 additions and 1 deletions

View File

@ -47,7 +47,10 @@ EMU_ARGS += -soundhw pcspk,ac97
# Configures two network devices on the same network
EMU_ARGS += -net user
EMU_ARGS += -netdev hubport,id=u1,hubid=0, -device e1000e,netdev=u1 -object filter-dump,id=f1,netdev=u1,file=qemu-e1000e.pcap
EMU_ARGS += -netdev hubport,id=u2,hubid=0, -device e1000e,netdev=u2
#EMU_ARGS += -netdev hubport,id=u2,hubid=0, -device e1000e,netdev=u2
# Add an XHCI tablet
#EMU_ARGS += -device qemu-xhci -device usb-tablet
EMU_KVM ?= -enable-kvm

View File

@ -45,6 +45,7 @@ struct {
{0x1234, "Bochs/QEMU"},
{0x1274, "Ensoniq"},
{0x15ad, "VMWare"},
{0x1b36, "Red Hat, Inc."},
{0x8086, "Intel Corporation"},
{0x80EE, "VirtualBox"},
};
@ -63,6 +64,7 @@ struct {
{0x15ad, 0x0405, "SVGA II Adapter"},
{0x15ad, 0x0790, "PCI bridge"},
{0x15ad, 0x07a0, "PCI Express Root Port"},
{0x1b36, 0x000d, "QEMU XHCI Host Controller"},
{0x8086, 0x1004, "82543GC Gigabit Ethernet Controller (e1000)"},
{0x8086, 0x100e, "82540EM Gigabit Ethernet Controller (e1000)"},
{0x8086, 0x100f, "82545EM Gigabit Ethernet Controller (e1000)"},

View File

@ -291,6 +291,9 @@ int kmain(struct multiboot * mboot, uint32_t mboot_mag, void* esp) {
serial_initialize();
portio_initialize();
extern void xhci_initialize(void);
xhci_initialize();
/* Special drivers should probably be modules... */
extern void ac97_install(void);
ac97_install();

80
kernel/usb/xhci.c Normal file
View File

@ -0,0 +1,80 @@
/**
* @brief xHCI Host Controller Driver
*/
#include <kernel/printf.h>
#include <kernel/types.h>
#include <kernel/pci.h>
#include <kernel/mmu.h>
#include <kernel/args.h>
struct xhci_cap_regs {
uint32_t cap_caplen_version;
uint32_t cap_hcsparams1;
uint32_t cap_hcsparams2;
uint32_t cap_hcsparams3;
uint32_t cap_hccparams1;
uint32_t cap_dboff;
uint32_t cap_rtsoff;
uint32_t cap_hccparams2;
};
struct xhci_op_regs {
uint32_t op_usbcmd;
uint32_t op_usbsts;
uint32_t op_pagesize;
uint32_t op__pad1[2];
uint32_t op_dnctrl;
uint32_t op_crcr;
uint32_t op__pad2[5];
uint32_t op_dcbaap;
uint32_t op__pad3[1];
uint32_t op_config;
};
static void find_xhci(uint32_t device, uint16_t v, uint16_t d, void * extra) {
uint16_t device_type = pci_find_type(device);
if (device_type == 0x0C03) {
printf("xhci: found a host controller at %02x:%02x.%d\n",
(int)pci_extract_bus(device),
(int)pci_extract_slot(device),
(int)pci_extract_func(device));
/* The mmio address is 64 bits and combines BAR0 and BAR1... */
uint64_t addr_low = pci_read_field(device, PCI_BAR0, 4) & 0xFFFFFFF0;
uint64_t addr_high = pci_read_field(device, PCI_BAR1, 4) & 0xFFFFFFFF; /* I think this is right? */
uint64_t mmio_addr = (addr_high << 32) | addr_low;
printf("xhci: mmio space is at %#lx\n", mmio_addr);
/* Map mmio space... */
uintptr_t xhci_regs = (uintptr_t)mmu_map_mmio_region(mmio_addr, 0x1000 * 4); /* I don't know. */
volatile struct xhci_cap_regs * cregs = (volatile struct xhci_cap_regs*)xhci_regs;
/* Read some registers */
uint32_t caplength = cregs->cap_caplen_version & 0xFF;
uint32_t hciversion = (cregs->cap_caplen_version >> 16) & 0xFFFF;
printf("xhci: CAPLENGTH = %d\n", caplength);
printf("xhci: HCIVERSION = %d\n", hciversion);
volatile struct xhci_op_regs * oregs = (volatile struct xhci_op_regs*)(xhci_regs + caplength);
printf("xhci: USBSTS = %#x\n", oregs->op_usbsts);
if (oregs->op_usbsts & (1 << 0)) printf("xhci: host controller halt\n");
if (oregs->op_usbsts & (1 << 2)) printf("xhci: host system error\n");
if (oregs->op_usbsts & (1 << 3)) printf("xhci: event interrupt\n");
if (oregs->op_usbsts & (1 << 4)) printf("xhci: port change detect\n");
if (oregs->op_usbsts & (1 << 8)) printf("xhci: save state status\n");
if (oregs->op_usbsts & (1 << 9)) printf("xhci: restore state status\n");
if (oregs->op_usbsts & (1 << 10)) printf("xhci: save restore error\n");
if (oregs->op_usbsts & (1 << 11)) printf("xhci: controller not ready\n");
if (oregs->op_usbsts & (1 << 12)) printf("xhci: host controlelr error\n");
}
}
void xhci_initialize(void) {
pci_scan(find_xhci, -1, NULL);
}