CeDOS - kernel/pci.c

kernel/pci.c (view raw)

#include <stdint.h>

#include "assembly.h"

#include "core.h"

#define CONFIG_ADDR_ENABLE (31)
#define CONFIG_ADDR_BUS (16)
#define CONFIG_ADDR_PORT (11)
#define CONFIG_ADDR_FUNC (8)
#define CONFIG_ADDR_REG (0)

#define VENDOR_DEVICE_ID_REGISTER (0x00)

#define VENDOR_ID_BIT_MASK (0x0000FFFF)
#define VENDOR_ID_BIT_SHIFT (0)

#define DEVICE_ID_BIT_MASK (0xFFFF0000)
#define DEVICE_ID_BIT_SHIFT (16)

struct pci_device {
	uint8_t bus;
	uint8_t port;
};

static int pci_read_register(struct pci_device *dev, uint8_t func, uint8_t reg, uint32_t *res) {
	uint32_t config_addr = 0;

	config_addr |= (1U << CONFIG_ADDR_ENABLE);
	config_addr |= (uint32_t)(dev->bus) << CONFIG_ADDR_BUS;
	config_addr |= (uint32_t)(dev->port) << CONFIG_ADDR_PORT;
	config_addr |= (uint32_t)(func) << CONFIG_ADDR_FUNC;
	config_addr |= (uint32_t)(reg) << CONFIG_ADDR_REG;

	outl(config_addr, 0xCF8);

	*res = inl(0xCFC);

	return 0;
}

int pci_init(void) {
	printk("\n     BUS  :  PORT     VENDOR : DEVICE\n");
	for (int bus = 0; bus < 256; bus++) {
		for (int port = 0; port < 256; port++) {
			struct pci_device dev = {
				.bus = (uint8_t)(bus),
				.port = (uint8_t)(port),
			};

			uint32_t reg_value = 0;
			pci_read_register(&dev, 0, VENDOR_DEVICE_ID_REGISTER, &reg_value);

			uint16_t vendor_id =
				(reg_value & VENDOR_ID_BIT_MASK) >> VENDOR_ID_BIT_SHIFT;
			uint16_t device_id =
				(reg_value & DEVICE_ID_BIT_MASK) >> DEVICE_ID_BIT_SHIFT;

			if (vendor_id != 0xFFFF) {
				printk("- %x:%x  %x:%x\n", dev.bus, dev.port, vendor_id, device_id);
			}
		}
	}

	return 0;
}