summaryrefslogtreecommitdiff
path: root/stage3/pci.c
blob: 6839a9b2e4a4b1083d0513eb65418d84e01004e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "pci.h"
#include "def.h"
#include "io.h"
#include "font.h"
#include "heap.h"

#define PCI_CONFIG_ADDRESS 0xCF8
#define PCI_CONFIG_DATA 0xCFC

usize pci_num_devices = 0;
pci_dev *pci_devices = nil;

void pci_init()
{
	typedef struct __attribute__((packed)) {
		u8 offset;
		unsigned int func : 3;
		unsigned int dev : 5;
		u8 bus;
		unsigned int reserved : 7;
		bool enable : 1;
	} pci_config_addr;

	for (int bus = 0; bus < 256; bus++)
	for (int dev = 0; dev < 32; dev++) {
		pci_config_addr addr = {
			.offset = 0,
			.func = 0,
			.dev = dev,
			.bus = bus,
			.enable = true,
		};

		outl(PCI_CONFIG_ADDRESS, BITCAST(addr, pci_config_addr, u32));
		u32 reg_0 = inl(PCI_CONFIG_DATA);
		if (reg_0 == 0xFFFFFFFF)
			continue;

		addr.offset = 0x8;
		outl(PCI_CONFIG_ADDRESS, BITCAST(addr, pci_config_addr, u32));
		u32 reg_2 = inl(PCI_CONFIG_DATA);

		pci_devices = krealloc(pci_devices, ++pci_num_devices * sizeof *pci_devices);
		pci_devices[pci_num_devices-1] = (pci_dev) {
			.bus = addr.bus,
			.dev = addr.dev,
			.vendor = reg_0 & 0xFFFF,
			.id = (reg_0 >> 16) & 0xFFFF,
			.class = reg_2 >> 24,
			.subclass = (reg_2 >> 16) & 0xff,
		};
	}
}