Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8e07aae
Start of xHCI driver for USB
olsner Feb 15, 2015
14ad20d
ACPICA/PCI code for finding devices by class
olsner Feb 15, 2015
11b05d1
Add an xhci and a USB mouse to qemu configuration
olsner Feb 15, 2015
99177ed
Workaround for weird m2c error from Make
olsner Feb 17, 2015
fbda97c
xhci: Initialize everything(?), at least it doesn't explode
olsner Feb 18, 2015
2094943
Use the correct option format to actually the USB mouse
olsner Feb 20, 2015
a8709ec
Reset all ports after initialization
olsner Feb 20, 2015
2240a33
xhci: Get number of ports from protocol capabilities
olsner Feb 21, 2015
6966b7d
Handle IRQs and process the event ring
olsner Feb 21, 2015
54d008f
Start of device enumeration
olsner Feb 22, 2015
730a2b2
Issue EnableSlot command and handle the completion event
olsner Feb 22, 2015
ad19155
Do AddressDevice on connected devices
olsner Feb 22, 2015
e31f5c8
Start the "main USB" driver, tell it about new devices
olsner Feb 22, 2015
a2aaf96
Start of enumeration API
olsner Apr 10, 2015
1a66a54
Add USB audio device
olsner Apr 10, 2015
710f1a6
Start of new controller/bus/system API
olsner Jun 8, 2015
4244ba8
Code for sending control messages, try to GET_DESCRIPTOR
olsner Jun 17, 2015
79340aa
Make return-type (missing return) warning an error
olsner Jun 17, 2015
27fc742
Extract dma_buffer code to separate header
olsner Jun 21, 2015
b232bf2
Add an array of transfer datas to be used as parameters to EventDatas
olsner Jun 22, 2015
e161380
Address the device after getting the first 8 bytes of the descriptor
olsner Jun 22, 2015
6540a86
TODO was implemented
olsner Jun 22, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,16 @@ ASMFILES := kstart.asm $(MOD_ASMFILES)
MOD_CFILES := cuser/helloworld.c cuser/physmem.c cuser/zeropage.c
MOD_CFILES += cuser/test_maps.c cuser/e1000.c cuser/apic.c cuser/timer_test.c
MOD_CFILES += cuser/bochsvga.c cuser/fbtest.c cuser/acpi_debugger.c
MOD_CFILES += cuser/usb/xhci.c
MOD_OFILES := $(MOD_CFILES:%.c=$(OUTDIR)/%.o)
MOD_ELFS := $(MOD_CFILES:%.c=$(OUTDIR)/%.elf)
MOD_ELFS += $(OUTDIR)/cuser/acpica.elf $(OUTDIR)/cuser/lwip.elf
MODFILES := $(MOD_ASMFILES:%.asm=$(GRUBDIR)/%.mod) $(MOD_CFILES:%.c=$(GRUBDIR)/%.mod) $(GRUBDIR)/cuser/acpica.mod $(GRUBDIR)/cuser/lwip.mod
BIG_MODS := acpica lwip usb
MOD_ELFS += $(BIG_MODS:%=$(OUTDIR)/cuser/%.elf)

MODFILES := $(MOD_ASMFILES:%.asm=$(GRUBDIR)/%.mod)
MODFILES += $(MOD_CFILES:%.c=$(GRUBDIR)/%.mod)
MODFILES += $(BIG_MODS:%=$(GRUBDIR)/cuser/%.mod)

DEPFILES := $(ASMFILES:%.asm=$(OUTDIR)/%.d) $(MOD_OFILES:.o=.d)
ASMOUTS := \
$(GRUBDIR)/kstart.b \
Expand All @@ -66,7 +72,7 @@ ASMOUTS := \
$(DEPFILES)

all: cpuid rflags $(OUTDIR)/grub.iso
all: $(MOD_ELFS)
all: $(MOD_ELFS) $(MODFILES)

.SECONDARY: $(ASMFILES:%.asm=$(OUTDIR)/%.b) $(MOD_OFILES)

Expand All @@ -80,6 +86,10 @@ clean:
%: %.c
$(HUSH_CC) $(CC) $(CFLAGS) -o $@ $<

# Disable these builtin pattern rules
%.o: %.mod
%: %.mod

-include $(DEPFILES)

$(OUTDIR)/%.d: %.asm $(YASMDEP)
Expand Down Expand Up @@ -120,6 +130,7 @@ GRUB_CFG = $(GRUBDIR)/boot/grub/grub.cfg

USER_CFLAGS := -ffreestanding -g -Os -W -Wall -Wextra -march=native -mno-avx -std=gnu99
USER_CFLAGS += -Wno-unused-function -Wno-unused-parameter
USER_CFLAGS += -Werror=return-type
USER_CFLAGS += -ffunction-sections -fdata-sections

LDFLAGS := --check-sections
Expand Down Expand Up @@ -161,7 +172,7 @@ $(OUTDIR)/%.elf: cuser/linker.ld $(OUTDIR)/%.o

WANT_PRINTF = test_maps zeropage
WANT_PRINTF += timer_test
WANT_REAL_PRINTF = e1000 apic bochsvga fbtest
WANT_REAL_PRINTF = e1000 apic bochsvga fbtest usb/xhci usb

WANT_STRING = acpica

Expand Down Expand Up @@ -315,7 +326,15 @@ $(OUTDIR)/cuser/lwip.elf: cuser/linker.ld $(LWIP_DEP_OBJS)
@mkdir -p $(@D)
$(HUSH_LD) $(LD) $(USER_LDFLAGS) -o $@ -T $^

all: $(GRUBDIR)/cuser/lwip.mod
USB := cuser/usb
USB_SRCS := $(USB)/main.c
USB_OBJS := $(USB_SRCS:%.c=$(OUTDIR)/%.o)

-include $(USB_OBJS:.o=.d)

$(OUTDIR)/cuser/usb.elf: cuser/linker.ld $(USB_OBJS)
@mkdir -p $(@D)
$(HUSH_LD) $(LD) $(USER_LDFLAGS) -o $@ -T $^

yasm/yasm: yasm/Makefile
$(MAKE) -C yasm
Expand Down
9 changes: 7 additions & 2 deletions cuser/acpica/acpica.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,11 +460,16 @@ static void MsgFindPci(uintptr_t rcpt, uintptr_t arg)
u16 vendor = arg >> 16;
u16 device = arg;
uintptr_t addr = -1;
printf("acpica: find pci %#x:%#x.\n", vendor, device);
ACPI_STATUS status = FindPCIDevByVendor(vendor, device, &temp);
ACPI_STATUS status;
if (vendor && device) {
status = FindPCIDevByVendor(vendor, device, &temp);
} else {
status = FindPCIDevByClass(arg >> 32, &temp);
}
if (ACPI_SUCCESS(status)) {
addr = temp.Bus << 16 | temp.Device << 3 | temp.Function;
}

send1(MSG_ACPI_FIND_PCI, rcpt, addr);
}

Expand Down
1 change: 1 addition & 0 deletions cuser/acpica/acpica.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ UINT32 PciReadWord(UINT32 Addr);
UINT32 AddrFromPciId(ACPI_PCI_ID* PciId, UINT32 Register);

ACPI_STATUS FindPCIDevByVendor(u16 vendor, u16 device, ACPI_PCI_ID* id);
ACPI_STATUS FindPCIDevByClass(u32 classcode, ACPI_PCI_ID* id);

void init_heap(void);

57 changes: 38 additions & 19 deletions cuser/acpica/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ typedef struct PCIEnum
{
// Return AE_CTRL_TERMINATE to stop iterating
ACPI_STATUS (*cb)(struct PCIEnum* context);
union {
struct { u16 vendor, device; };
struct {
u16 vendor, device;
u32 class;
} in;
struct {
ACPI_PCI_ID pci_id;
u16 vendor;
u16 device;
u32 class;
} cur;
} PCIEnum;

#define getVendorID(b,d,f) getPCIConfig(b,d,f, 0, 16)
#define getDeviceID(b,d,f) getPCIConfig(b,d,f, 2, 16)
#define getHeaderType(b,d,f) getPCIConfig(b,d,f, 14, 8)
#define getSubClass(b,d,f) getPCIConfig(b,d,f, 10, 8)
#define getBaseClass(b,d,f) getPCIConfig(b,d,f, 11, 8)
#define getSecondaryBus(b,d,f) getPCIConfig(b,d,f, 0x19, 8)

#define ACPI_RETURN_IF(e) \
Expand Down Expand Up @@ -56,8 +56,11 @@ static ACPI_STATUS EnumPCIFunction(u8 bus, u8 dev, u8 func, PCIEnum* cb) {
return AE_OK;
}
u8 headerType = getHeaderType(bus, dev, func);
u8 baseClass = getBaseClass(bus, dev, func);
u8 subClass = getSubClass(bus, dev, func);
u32 classRevision = getPCIConfig(bus, dev, func, 8, 32);
u32 class = classRevision >> 8;
u8 baseClass = (class >> 16) & 0xff;
u8 subClass = (class >> 8) & 0xff;
u8 programInterface = class & 0xff;
u16 device = getDeviceID(bus, dev, func);
ACPI_STATUS status = AE_OK;
if (cb)
Expand All @@ -66,12 +69,14 @@ static ACPI_STATUS EnumPCIFunction(u8 bus, u8 dev, u8 func, PCIEnum* cb) {
cb->cur.pci_id = id;
cb->cur.vendor = vendor;
cb->cur.device = device;
cb->cur.class = class;
status = cb->cb(cb);
}
if (!cb || status == AE_CTRL_TERMINATE)
{
printf("%02x:%02x.%x: Found device %#04x:%#04x class %#x:%#x\n",
bus, dev, func, vendor, device, baseClass, subClass);
printf("%02x:%02x.%x: Found device %#04x:%#04x class %#x:%#x pi %#x\n",
bus, dev, func, vendor, device, baseClass, subClass,
programInterface);
}
ACPI_RETURN_IF(status);
if (baseClass == 6 && subClass == 4)
Expand Down Expand Up @@ -105,32 +110,46 @@ ACPI_STATUS EnumeratePCI(void) {
}

static ACPI_STATUS FindPCIDevCB(PCIEnum* context) {
if (context->cur.vendor == context->in.vendor &&
context->cur.device == context->in.device) {
if ((context->cur.vendor == context->in.vendor &&
context->cur.device == context->in.device) ||
context->cur.class == context->in.class) {
return AE_CTRL_TERMINATE;
}
return AE_OK;
}

ACPI_STATUS FindPCIDevByVendor(u16 vendor, u16 device, ACPI_PCI_ID* id) {
PCIEnum cb;
memset(&cb, 0, sizeof(cb));
cb.cb = FindPCIDevCB;
cb.in.vendor = vendor;
cb.in.device = device;
printf("acpica: Looking for %#04x:%#04x devices...\n", vendor, device);
ACPI_STATUS status = EnumPCIBus(0, &cb);
static ACPI_STATUS FindPCIDev(PCIEnum *cb, ACPI_PCI_ID* id) {
ACPI_STATUS status = EnumPCIBus(0, cb);
if (status == AE_OK)
{
return AE_NOT_FOUND;
}
else if (status == AE_CTRL_TERMINATE)
{
*id = cb.cur.pci_id;
*id = cb->cur.pci_id;
return AE_OK;
}
else
{
return status;
}
}

ACPI_STATUS FindPCIDevByClass(u32 class, ACPI_PCI_ID* id) {
PCIEnum cb;
memset(&cb, 0, sizeof(cb));
cb.cb = FindPCIDevCB;
cb.in.class = class;
printf("acpica: Looking for %#06x devices...\n", class);
return FindPCIDev(&cb, id);
}

ACPI_STATUS FindPCIDevByVendor(u16 vendor, u16 device, ACPI_PCI_ID* id) {
PCIEnum cb;
memset(&cb, 0, sizeof(cb));
cb.cb = FindPCIDevCB;
cb.in.vendor = vendor;
cb.in.device = device;
printf("acpica: Looking for %#04x:%#04x devices...\n", vendor, device);
return FindPCIDev(&cb, id);
}
18 changes: 11 additions & 7 deletions cuser/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ enum msg_irq {
enum msg_acpi {
/* Find (unclaimed) PCI device.
*
* arg1: pci vendor/device
* arg2: index (0..)
* arg1: pci vendor/device or class code
* class code = (arg1 >> 32) & 0xffffff (24-bit class code)
* vendor = (arg >> 16) & 0xffff
* device = arg & 0xffff
* The class code is used for search if both vendor and device are 0.
* Returns:
* arg1: pci bus/device/function, or -1 if not found
*
* Iterate index upwards to find multiple matching PCI devices until -1 is
* returned.
*/
MSG_ACPI_FIND_PCI = MSG_USER,
/* Wrappers around PCI IRQ routing (to PIC or I/O APIC) */
Expand Down Expand Up @@ -546,12 +546,12 @@ static void assert_failed(const char* file, int line, const char* msg) {
#define assert(X) \
do { if (!(X)) assert_failed(__FILE__, __LINE__, #X); } while (0)

static void hexdump(char* data, size_t length) {
static void hexdump(const void* data, size_t length) {
size_t pos = 0;
while (pos < length) {
printf("\n%04x: ", pos);
for (int i = 0; i < 16 && pos < length; i++) {
printf("%02x ", (u8)data[pos++]);
printf("%02x ", ((const u8*)data)[pos++]);
}
}
printf("\n");
Expand Down Expand Up @@ -585,6 +585,10 @@ enum pci_command_bits
PCI_COMMAND_MEMSPACE = 2,
PCI_COMMAND_MASTER = 4,
};
enum pci_status_bits
{
PCI_STATUS_INTERRUPT = 8,
};

/**
* A simple (compiler) barrier. Memory writes to volatile variables before the
Expand Down
45 changes: 45 additions & 0 deletions cuser/dma_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "common.h"

static u64 dma_map(const volatile void* addr, size_t size) {
const enum prot flags = MAP_DMA | PROT_READ | PROT_WRITE | PROT_NO_CACHE;
return (u64)map(0, flags, addr, 0, size);
}
#define dma_map(obj) dma_map(&(obj), sizeof(obj))

#define MAX_DMA_BUFFERS 16
static u8 dma_buffer_space[MAX_DMA_BUFFERS][4096] PLACEHOLDER_SECTION ALIGN(4096);
typedef struct dma_buffer {
u64 phys; // 0 for unmapped buffers
} dma_buffer;
static dma_buffer dma_buffers[MAX_DMA_BUFFERS];
typedef struct dma_buffer_ref {
u64 phys;
u8 *virtual;
} dma_buffer_ref;
static dma_buffer_ref allocate_dma_buffer() {
dma_buffer_ref res = { 0, NULL };
for (unsigned i = 0; i < MAX_DMA_BUFFERS; i++) {
dma_buffer *buf = dma_buffers + i;
if (buf->phys & 1) continue;

if (!buf->phys) {
buf->phys = dma_map(dma_buffer_space[i]);
}
res.phys = buf->phys;
res.virtual = dma_buffer_space[i];
memset(res.virtual, 0, 4096);

buf->phys |= 1;
return res;
}
assert(!"Ran out of DMA buffers...");
return res;
}
static void free_dma_buffer(u64 phys) {
for (unsigned i = 0; i < MAX_DMA_BUFFERS; i++) {
dma_buffer *buf = dma_buffers + i;
if (buf->phys != (phys | 1)) continue;
buf->phys ^= 1;
return;
}
}
Loading