PatchworkOS  dbbdc99
A non-POSIX operating system.
Loading...
Searching...
No Matches
config.c
Go to the documentation of this file.
2
3#include <kernel/log/log.h>
4#include <kernel/mem/vmm.h>
6
8static mcfg_t* mcfg;
9
10static bool initialized = false;
12
14{
16
17 if (initialized)
18 {
19 return 0;
20 }
21
22 mcfg = (mcfg_t*)acpi_tables_lookup("MCFG", sizeof(mcfg_t), 0);
23 if (mcfg == NULL)
24 {
25 LOG_ERR("no MCFG table found\n");
26 return ERR;
27 }
28
29 uint64_t entriesLength = mcfg->header.length - sizeof(mcfg_t);
30 if (entriesLength % sizeof(pci_config_bar_t) != 0)
31 {
32 LOG_ERR("MCFG table does not contain a whole number of entries\n");
33 return ERR;
34 }
35
36 entryCount = entriesLength / sizeof(pci_config_bar_t);
37
38 for (uint64_t i = 0; i < entryCount; i++)
39 {
40 pci_config_bar_t* entry = &mcfg->entries[i];
41
42 uint64_t busCount = entry->endBus - entry->startBus + 1;
43 uint64_t length = busCount * 256 * 4096;
44
45 void* virtAddr = (void*)PML_LOWER_TO_HIGHER(entry->base);
46 if (vmm_map(NULL, virtAddr, entry->base, length, PML_WRITE | PML_GLOBAL | PML_PRESENT, NULL, NULL) == NULL)
47 {
48 LOG_ERR("failed to map PCI-e configuration space at %p\n", entry->base);
49 return ERR;
50 }
51
52 LOG_INFO("mapped PCI-e config space %p (segment=%u bus=%u-%u)\n", entry->base, entry->segmentGroup,
53 entry->startBus, entry->endBus);
54 }
55
56 errno = EOK;
57 initialized = true;
58 return 0;
59}
60
62{
63 if (pci_config_init() == ERR)
64 {
65 return NULL;
66 }
67
68 for (uint64_t i = 0; i < entryCount; ++i)
69 {
70 if (mcfg->entries[i].segmentGroup == segmentGroup && bus >= mcfg->entries[i].startBus &&
71 bus <= mcfg->entries[i].endBus)
72 {
73 return &mcfg->entries[i];
74 }
75 }
76 return NULL;
77}
78
79static volatile void* pci_config_get_address(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot,
80 uint8_t function, uint16_t offset)
81{
82 if (pci_config_init() == ERR)
83 {
84 return NULL;
85 }
86
87 pci_config_bar_t* region = pci_config_bar_get(segmentGroup, bus);
88 if (region == NULL)
89 {
90 return NULL;
91 }
92
93 // This formula calculates the final address based on the OSDev Wiki page.
95 address += (uint64_t)(bus - region->startBus) << 20;
96 address += (uint64_t)slot << 15;
97 address += (uint64_t)function << 12;
98 address += offset;
99
100 return (void*)address;
101}
102
105{
106 if (pci_config_init() == ERR)
107 {
108 return 0xFF;
109 }
110
111 volatile uint8_t* addr = (volatile uint8_t*)pci_config_get_address(segmentGroup, bus, slot, function, offset);
112 if (addr == NULL)
113 {
114 return 0xFF;
115 }
116 return *addr;
117}
118
121{
122 if (pci_config_init() == ERR)
123 {
124 return 0xFFFF;
125 }
126
127 volatile uint16_t* addr = (volatile uint16_t*)pci_config_get_address(segmentGroup, bus, slot, function, offset);
128 if (addr == NULL)
129 {
130 return 0xFFFF;
131 }
132 return *addr;
133}
134
137{
138 if (pci_config_init() == ERR)
139 {
140 return 0xFFFFFFFF;
141 }
142
143 volatile uint32_t* addr = (volatile uint32_t*)pci_config_get_address(segmentGroup, bus, slot, function, offset);
144 if (addr == NULL)
145 {
146 return 0xFFFFFFFF;
147 }
148 return *addr;
149}
150
152 uint16_t offset, uint8_t value)
153{
154 volatile uint8_t* addr = (volatile uint8_t*)pci_config_get_address(segmentGroup, bus, slot, function, offset);
155 if (addr != NULL)
156 {
157 *addr = value;
158 }
159}
160
162 uint16_t offset, uint16_t value)
163{
164 if (pci_config_init() == ERR)
165 {
166 return;
167 }
168
169 volatile uint16_t* addr = (volatile uint16_t*)pci_config_get_address(segmentGroup, bus, slot, function, offset);
170 if (addr != NULL)
171 {
172 *addr = value;
173 }
174}
175
177 uint16_t offset, uint32_t value)
178{
179 if (pci_config_init() == ERR)
180 {
181 return;
182 }
183
184 volatile uint32_t* addr = (volatile uint32_t*)pci_config_get_address(segmentGroup, bus, slot, function, offset);
185 if (addr != NULL)
186 {
187 *addr = value;
188 }
189}
sdt_header_t * acpi_tables_lookup(const char *signature, uint64_t minSize, uint64_t n)
Lookup the n'th table matching the signature.
Definition tables.c:259
static uintptr_t address
Mapped virtual address of the HPET registers.
Definition hpet.c:96
void pci_config_write8(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, pci_function_t function, uint16_t offset, uint8_t value)
Write a byte to PCI configuration space.
Definition config.c:151
uint8_t pci_function_t
PCI Function Type.
Definition config.h:39
void pci_config_write16(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, pci_function_t function, uint16_t offset, uint16_t value)
Write a word to PCI configuration space.
Definition config.c:161
uint8_t pci_config_read8(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, pci_function_t function, uint16_t offset)
Read a byte from PCI configuration space.
Definition config.c:103
uint8_t pci_slot_t
PCI Slot Type.
Definition config.h:34
uint32_t pci_config_read32(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, pci_function_t function, uint16_t offset)
Read a dword from PCI configuration space.
Definition config.c:135
void pci_config_write32(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, pci_function_t function, uint16_t offset, uint32_t value)
Write a dword to PCI configuration space.
Definition config.c:176
uint8_t pci_bus_t
PCI Bus Type.
Definition config.h:29
uint16_t pci_segment_group_t
PCI Segment Group Type.
Definition config.h:24
uint16_t pci_config_read16(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, pci_function_t function, uint16_t offset)
Read a word from PCI configuration space.
Definition config.c:119
#define LOG_ERR(format,...)
Definition log.h:93
#define LOG_INFO(format,...)
Definition log.h:91
#define PML_LOWER_TO_HIGHER(addr)
Converts an address from the lower half to the higher half.
@ PML_PRESENT
@ PML_WRITE
@ PML_GLOBAL
void * vmm_map(space_t *space, void *virtAddr, phys_addr_t physAddr, size_t length, pml_flags_t flags, space_callback_func_t func, void *data)
Maps physical memory to virtual memory in a given address space.
Definition vmm.c:226
#define LOCK_CREATE()
Create a lock initializer.
Definition lock.h:69
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:58
#define errno
Error number variable.
Definition errno.h:27
#define EOK
No error.
Definition errno.h:32
#define NULL
Pointer error value.
Definition NULL.h:25
#define ERR
Integer error value.
Definition ERR.h:17
static uint64_t offset
Definition screen.c:19
static volatile void * pci_config_get_address(pci_segment_group_t segmentGroup, pci_bus_t bus, pci_slot_t slot, uint8_t function, uint16_t offset)
Definition config.c:79
static uint64_t pci_config_init(void)
Definition config.c:13
static pci_config_bar_t * pci_config_bar_get(pci_segment_group_t segmentGroup, pci_bus_t bus)
Definition config.c:61
static mcfg_t * mcfg
Definition config.c:8
static lock_t initLock
Definition config.c:11
static bool initialized
Definition config.c:10
static uint64_t entryCount
Definition config.c:7
static start_entry_t entries[START_ENTRY_MAX]
Definition start_menu.c:22
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__UINTPTR_TYPE__ uintptr_t
Definition stdint.h:43
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
A simple ticket lock implementation.
Definition lock.h:44
PCI Express Memory-mapped Configuration.
Definition config.h:59
sdt_header_t header
Definition config.h:60
pci_config_bar_t entries[]
Definition config.h:62
PCI-e Configuration Space Base Address Allocation Structure.
Definition config.h:46
pci_segment_group_t segmentGroup
Definition config.h:48
pci_bus_t endBus
Definition config.h:50
uint64_t base
Definition config.h:47
pci_bus_t startBus
Definition config.h:49
uint32_t length
Definition acpi.h:92