diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-03 23:05:46 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-03 23:05:46 -0400 |
commit | d604f8e93fffc7db05cfe09b16fa1252c8470bc1 (patch) | |
tree | 3e2183d5414706b5ffbee8ffaf9f255a646eec85 /kernel | |
parent | fmt (diff) | |
download | comus-d604f8e93fffc7db05cfe09b16fa1252c8470bc1.tar.gz comus-d604f8e93fffc7db05cfe09b16fa1252c8470bc1.tar.bz2 comus-d604f8e93fffc7db05cfe09b16fa1252c8470bc1.zip |
pci
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/drivers/drivers.c | 7 | ||||
-rw-r--r-- | kernel/drivers/pci.c | 174 | ||||
-rw-r--r-- | kernel/include/comus/drivers.h | 17 | ||||
-rw-r--r-- | kernel/include/comus/drivers/pci.h | 72 | ||||
-rw-r--r-- | kernel/kernel.c | 9 |
5 files changed, 274 insertions, 5 deletions
diff --git a/kernel/drivers/drivers.c b/kernel/drivers/drivers.c new file mode 100644 index 0000000..5b68248 --- /dev/null +++ b/kernel/drivers/drivers.c @@ -0,0 +1,7 @@ +#include <comus/drivers.h> +#include <comus/drivers/pci.h> + +void drivers_init(void) +{ + pci_init(); +} diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c new file mode 100644 index 0000000..83c47f1 --- /dev/null +++ b/kernel/drivers/pci.c @@ -0,0 +1,174 @@ +#include <comus/drivers/pci.h> +#include <comus/asm.h> +#include <lib.h> + +#define CONF_ADDR 0xCF8 +#define CONF_DATA 0xCFC +#define TABLE_LEN 16 + +struct pci_table_entry { + struct pci_device device; + uint16_t device_id; + uint16_t vendor_id; + uint8_t class; + uint8_t subclass; + uint8_t prog_if; + uint8_t revision; +}; + +static struct pci_table_entry pci_table[TABLE_LEN]; +static size_t pci_table_next = 0; + +uint32_t pci_rcfg_d(struct pci_device dev, uint8_t offset) +{ + uint32_t addr = 0x80000000; + addr |= ((uint32_t)dev.bus) << 16; + addr |= ((uint32_t)dev.device) << 11; + addr |= ((uint32_t)dev.function) << 8; + addr |= offset & 0xFC; + + outl(CONF_ADDR, addr); + uint32_t in = inl(CONF_DATA); + return in; +} + +static void print_device(struct pci_table_entry *entry) +{ + printf( + "BUS: %#-4x DEV: %#-4x FUNC: %#-4x ID: %04x:%04x CLASS: %02x:%02x:%02x REV: %#02x\n", + entry->device.bus, entry->device.device, entry->device.function, + entry->vendor_id, entry->device_id, entry->class, entry->subclass, + entry->prog_if, entry->revision); +} + +static struct pci_table_entry *load_device(struct pci_device dev) +{ + if (pci_table_next >= TABLE_LEN) + panic("Too many PCI devices: limit is %d", TABLE_LEN); + struct pci_table_entry *entry = &pci_table[pci_table_next++]; + entry->device = dev; + uint32_t dword0 = pci_rcfg_d(dev, 0); + uint32_t dword2 = pci_rcfg_d(dev, 8); + + entry->device_id = (dword0 >> 16) & 0xFFFF; + entry->vendor_id = dword0 & 0xFFFF; + + entry->class = (dword2 >> 24) & 0xFF; + entry->subclass = (dword2 >> 16) & 0xFF; + entry->prog_if = (dword2 >> 8) & 0xFF; + entry->revision = dword2 & 0xFF; + + return entry; +} + +uint16_t pci_rcfg_w(struct pci_device dev, uint8_t offset) +{ + uint32_t dword = pci_rcfg_d(dev, offset); + return (uint16_t)((dword >> ((offset & 2) * 8)) & 0xFFFF); +} + +uint8_t pci_rcfg_b(struct pci_device dev, uint8_t offset) +{ + uint32_t dword = pci_rcfg_d(dev, offset); + return (uint8_t)((dword >> ((offset & 3) * 8)) & 0xFF); +} + +void pci_wcfg_d(struct pci_device dev, uint8_t offset, uint32_t dword) +{ + uint32_t addr = 0x80000000; + addr |= ((uint32_t)dev.bus) << 16; + addr |= ((uint32_t)dev.device) << 11; + addr |= ((uint32_t)dev.function) << 8; + addr |= offset & 0xFC; + + outl(CONF_ADDR, addr); + outl(CONF_DATA, dword); +} + +void pci_wcfg_w(struct pci_device dev, uint8_t offset, uint16_t word) +{ + size_t shift = (offset & 2) * 8; + uint32_t dword = pci_rcfg_d(dev, offset); + dword &= ~(0xFFFF << shift); + dword |= word << shift; + pci_wcfg_d(dev, offset, dword); +} + +void pci_wcfg_b(struct pci_device dev, uint8_t offset, uint8_t byte) +{ + size_t shift = (offset & 3) * 8; + uint32_t dword = pci_rcfg_d(dev, offset); + dword &= ~(0xFF << shift); + dword |= byte << shift; + pci_wcfg_d(dev, offset, dword); +} + +void pci_init(void) +{ + pci_table_next = 0; + struct pci_device pcidev; + for (int bus = 0; bus < 256; bus++) { + pcidev.bus = bus; + for (int dev = 0; dev < 32; dev++) { + pcidev.device = dev; + pcidev.function = 0; + + uint16_t vendor = pci_rcfg_w(pcidev, 0); + if (vendor == 0xFFFF) + continue; + + load_device(pcidev); + + uint8_t header_type = pci_rcfg_b(pcidev, 14); + + if (!(header_type & 0x80)) + continue; + for (int func = 1; func < 8; func++) { + pcidev.function = func; + + uint16_t vendor = pci_rcfg_w(pcidev, 0); + if (vendor == 0xFFFF) + continue; + + load_device(pcidev); + } + } + } + printf("PCI DEVICES\n"); + for (size_t i = 0; i < pci_table_next; i++) { + print_device(&pci_table[i]); + } + printf("\n"); +} + +bool pci_findby_class(struct pci_device *dest, uint8_t class, uint8_t subclass, + size_t *offset) +{ + size_t o = 0; + if (offset == NULL) + offset = &o; + for (; *offset < pci_table_next; (*offset)++) { + struct pci_table_entry *entry = &pci_table[*offset]; + if (entry->class == class && entry->subclass == subclass) { + *dest = entry->device; + return true; + } + } + return false; +} + +bool pci_findby_id(struct pci_device *dest, uint16_t device, uint16_t vendor, + size_t *offset) +{ + size_t o = 0; + if (offset == NULL) + offset = &o; + for (; *offset < pci_table_next; (*offset)++) { + struct pci_table_entry *entry = &pci_table[*offset]; + if (entry->device_id == device && entry->vendor_id == vendor) { + *dest = entry->device; + return true; + } + } + return false; +} diff --git a/kernel/include/comus/drivers.h b/kernel/include/comus/drivers.h new file mode 100644 index 0000000..3a38d3b --- /dev/null +++ b/kernel/include/comus/drivers.h @@ -0,0 +1,17 @@ +/** + * @file drivers.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * Entrypoint for initalizing all devices + */ + +#ifndef DRIVERS_H_ +#define DRIVERS_H_ + +/** + * Initalize all supported drivers + */ +void drivers_init(void); + +#endif /* drivers.h */ diff --git a/kernel/include/comus/drivers/pci.h b/kernel/include/comus/drivers/pci.h new file mode 100644 index 0000000..34bcdda --- /dev/null +++ b/kernel/include/comus/drivers/pci.h @@ -0,0 +1,72 @@ +/** + * @file pci.h + * + * @author Freya Murphy <freya@freyacaat.org> + * @author Tristan Miller <trimill@trimillxyz.org> + * + * PCI driver + */ + +#ifndef PCI_H_ +#define PCI_H_ + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +// common +#define PCI_VENDOR_W 0x00 +#define PCI_DEVICE_W 0x02 +#define PCI_COMMAND_W 0x04 +#define PCI_STATUS_W 0x06 +#define PCI_REVISION_B 0x08 +#define PCI_PROG_IF_B 0x09 +#define PCI_SUBCLASS_B 0x0A +#define PCI_CLASS_B 0x0B +#define PCI_CACHE_SIZE_B 0x0C +#define PCI_LATENCY_TIMER_B 0x0D +#define PCI_HEADER_TYPE_B 0x0E +#define PCI_BIST_B 0x0F + +// header type 0 +#define PCI_BAR0_D 0x10 +#define PCI_BAR1_D 0x14 +#define PCI_BAR2_D 0x18 +#define PCI_BAR3_D 0x1C +#define PCI_BAR4_D 0x20 +#define PCI_BAR5_D 0x24 +#define PCI_CARDBUS_CIS_D 0x28 +#define PCI_SUBSYSTEM_VENDOR_W 0x2C +#define PCI_SUBSYSTEM_W 0x2E +#define PCI_EXPANSION_ROM_D 0x30 +#define PCI_CAP_PTR_B 0x34 +#define PCI_INT_LINE_B 0x3C +#define PCI_INT_PIN_B 0x3D +#define PCI_MIN_GRANT_B 0x3E +#define PCI_MAX_LATENCY_B 0x3F + +struct pci_device { + uint8_t bus : 8; + uint8_t device : 5; + uint8_t function : 3; +}; + +/** + * Load the PCI driver + */ +void pci_init(void); + +bool pci_findby_class(struct pci_device *dest, uint8_t class, uint8_t subclass, + size_t *offset); +bool pci_findby_id(struct pci_device *dest, uint16_t device, uint16_t vendor, + size_t *offset); + +uint32_t pci_rcfg_d(struct pci_device dev, uint8_t offset); +uint16_t pci_rcfg_w(struct pci_device dev, uint8_t offset); +uint8_t pci_rcfg_b(struct pci_device dev, uint8_t offset); + +void pci_wcfg_d(struct pci_device dev, uint8_t offset, uint32_t dword); +void pci_wcfg_w(struct pci_device dev, uint8_t offset, uint16_t word); +void pci_wcfg_b(struct pci_device dev, uint8_t offset, uint8_t byte); + +#endif /* pci.h */ diff --git a/kernel/kernel.c b/kernel/kernel.c index d817741..4896b38 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,15 +1,14 @@ #include <comus/cpu.h> #include <comus/memory.h> #include <comus/mboot.h> +#include <comus/drivers.h> #include <lib.h> -#include <stdio.h> -#include <stdlib.h> struct memory_map mmap; void main(long magic, volatile void *mboot) { - (void) magic; // TODO: check multiboot magic + (void)magic; // TODO: check multiboot magic // initalize idt and pic // WARNING: must be done before anything else @@ -21,8 +20,8 @@ void main(long magic, volatile void *mboot) // initalize memory memory_init(&mmap); - char *a = malloc(3); - *a = 3; + // initalize devices + drivers_init(); // halt printf("halting...\n"); |