From 63167f223e1f54910f6b80e698390ee60aec79ee Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Tue, 11 Aug 2020 11:33:21 -0400 Subject: lots of progress currently, BAR fields of IDE drives are all returning zero, and the ATA read function isn't working. i'm not sure why. i'm going to work on VESA next, and come back to the IDE driver later --- src/kernel/pci.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/kernel/pci.c (limited to 'src/kernel/pci.c') diff --git a/src/kernel/pci.c b/src/kernel/pci.c new file mode 100644 index 0000000..fe96c4c --- /dev/null +++ b/src/kernel/pci.c @@ -0,0 +1,77 @@ +#include "boot.h" +#include "mem.h" +#include "util.h" +#include "pci.h" +#include "panic.h" + +enum { + PCP_SELECT = 0x0cf8, + PCP_READ = 0x0cfc +}; + +uint16_t n_pci_devices = 0; +struct pci_device *pci_device_pages[256]; + +#define PCI_DEVICES_PER_PAGE (4096 / sizeof(struct pci_device)) + +struct pci_device *nth_pci_device(uint16_t n) { + return pci_device_pages[n / PCI_DEVICES_PER_PAGE] + (n % PCI_DEVICES_PER_PAGE); +} + +struct pci_device *find_pci_device_from_class_and_subclass(uint8_t class, uint8_t subclass, uint16_t start, uint16_t *index) { + for (uint16_t n = start; n < n_pci_devices; ++n) { + struct pci_device *p = nth_pci_device(n); + if ((p->class == class) && (p->subclass == subclass)) { + *index = n; + return p; + } + } + return 0; +} + +struct pci_device *next_pci_device() { + if (!(n_pci_devices % PCI_DEVICES_PER_PAGE)) + pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_pages(1); + return nth_pci_device(n_pci_devices++); +} + +static inline uint32_t pci_read_config(uint16_t number, uint8_t reg) { + uint32_t cspace_addr = 0x80000000 | (number << 8) | (reg << 2); + outd(PCP_SELECT, cspace_addr); + + return ind(PCP_READ); +} + +void pci_device_check(uint16_t number) { + uint32_t id = pci_read_config(number, 0); + if ((id & 0xffff) == 0xffff) + return; + + struct pci_device *next_device = next_pci_device(); + + next_device->number = number; + + next_device->id_vendor = id; + next_device->id_device = id >> 16; + + uint32_t class = pci_read_config(number, 2); + + next_device->class = class >> 24; + next_device->subclass = class >> 16; + next_device->iface = class >> 8; + + next_device->bar0 = pci_read_config(number, 4); + next_device->bar1 = pci_read_config(number, 5); + next_device->bar2 = pci_read_config(number, 6); + next_device->bar3 = pci_read_config(number, 7); +} + +void pci_init() { + if (!(BOOT_INFO->support_flags & BIS_PCI)) + panic("No PCI support detected."); + if (!(BOOT_INFO->pci_hw_char & PHC_CS_M1)) + panic("No PCI Mechanism 1 support"); + + for (uint32_t number = 0; number < (BOOT_INFO->last_pci_bus + 1) * 256; ++number) + pci_device_check(number); +} \ No newline at end of file -- cgit v1.2.3