Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
msi.c
Go to the documentation of this file.
2#include "libk/serial.h"
3#include <type.h>
4#include "pci.h"
5
7 uint8_t cpu, uint16_t cap) {
8 if (!cap)
9 return;
10
11 uint8_t pci_dev = (uint8_t) pci->pci_dev;
12 uint8_t pci_func = (uint8_t) pci->pci_func;
13 uint8_t pci_bus = (uint8_t) pci->pci_bus;
14
15 // disable msi
16 uint16_t ctrl = pci_read16(pci_bus, pci_dev, pci_func, cap + 0x2);
17 LOG2_INFO("MSI", "ctrl=0x%x", ctrl);
18 pci_write16(pci_bus, pci_dev, pci_func, cap + 0x2, ctrl & ~1);
19
20 // mirip apic
21 uint32_t msg_addr = 0xFEE00000 | (uint32_t)(cpu << 12);
22 uint16_t msg_data = (vector & 0xFF);
23
24 if (ctrl & (1 << 7)) {
25 // 64-bit
26 pci_write32(pci_bus, pci_dev, pci_func, cap + 0x4, msg_addr);
27 pci_write32(pci_bus, pci_dev, pci_func, cap + 0x8,
28 0); // upper addr
29 pci_write16(pci_bus, pci_dev, pci_func, cap + 0xC, msg_data);
30 } else {
31 // 32-bit
32 pci_write32(pci_bus, pci_dev, pci_func, cap + 0x4, msg_addr);
33 pci_write16(pci_bus, pci_dev, pci_func, cap + 0x8, msg_data);
34 }
35
36 // Enable MSI bit
37 __asm__ volatile("mfence" ::: "memory");
38 pci_write16(pci_bus, pci_dev, pci_func, cap + 0x2,
39 (ctrl & ~(0x70)) | 1);
40
41 ctrl = pci_read16(pci_bus, pci_dev, pci_func, cap + 0x2);
42 LOG2_INFO("MSI", "ctrl=0x%x", ctrl);
43
44 LOG2_INFO("PCI", "MSI enabled vector=%d cpu=%d", vector, cpu);
45}
46
49 uint16_t cap) {
50 if (!cap)
51 return 0;
52
53 uint8_t pci_func = (uint8_t) pci->pci_func;
54 uint8_t pci_bus = (uint8_t) pci->pci_bus;
55 uint8_t pci_dev = (uint8_t) pci->pci_dev;
56
57 uint16_t ctrl = pci_read16(pci_bus, pci_dev, pci_func, cap + 0x2);
58 LOG2_INFO("MSIX", "enabled, ctrl=0x%x", ctrl);
59 pci_write16(pci_bus, pci_dev, pci_func, cap + 0x2, ctrl & ~(1 << 15));
60
61 uint32_t table_info = pci_read32(pci_bus, pci_dev, pci_func, cap + 0x4);
62 uint8_t bir = table_info & 0x7;
63 uint32_t offset = table_info & ~0x7UL;
64
65 auto table_size = (ctrl & 0x7FF) + 1; // ← +1: table_size adalah N+1
66 LOG2_INFO("MSIX", "Table size : %d", table_size);
67
68 auto selected_bar = pci->bar[bir].address + offset;
69 LOG2_INFO("MSIX", "bir at 0x%x with offset 0x%x -> 0x%x", bir, offset,
70 selected_bar);
71
72 if (!selected_bar)
73 return 0;
74
75 volatile uint32_t* msix_table = (volatile uint32_t*) selected_bar;
76 for (int i = 0; i < table_size; i++) {
77 msix_table[i * 4 + 0] =
78 0xFEE00000 | (uint32_t)(cpu << 12); // Address Low
79 msix_table[i * 4 + 1] = 0; // Address High
80 msix_table[i * 4 + 2] = (vector & 0xFF); // Data
81 msix_table[i * 4 + 3] =
82 (i == 0)
83 ? 0
84 : 1; // Vector Control (0 = Unmasked, 1 = Masked)
85 }
86
87 __asm__ volatile("mfence" ::: "memory");
88
89 // Bit 15 = enable, Bit 14 harus 0 (Function Mask OFF)
90 pci_write16(pci_bus, pci_dev, pci_func, cap + 0x2,
91 (ctrl | (1 << 15)) & ~(1 << 14));
92
93 LOG2_INFO("MSIX", "enabled, ctrl=0x%x",
94 pci_read16(pci_bus, pci_dev, pci_func, cap + 0x2));
95
96 return selected_bar;
97}
98
100 auto cap_ptr = pci->capability_ptr;
101 uint8_t bus = (uint8_t) pci->pci_bus;
102 uint8_t device = (uint8_t) pci->pci_dev;
103 uint8_t func = (uint8_t) pci->pci_func;
104
105 while (cap_ptr != 0 && cap_ptr >= 0x40 && cap_ptr <= 0xFF) {
106 uint8_t cap_id = pci_read8(bus, device, func,
107 cap_ptr); // ID capability
108 uint8_t next_ptr = pci_read8(
109 bus, device, func,
110 cap_ptr + 1); // pointer ke capability selanjutnya
111
112 if (cap_id == 0x05) {
113 return cap_ptr;
114 }
115
116 cap_ptr = next_ptr;
117 }
118 return 0;
119}
120
122 auto cap_ptr = pci->capability_ptr;
123 uint8_t bus = (uint8_t) pci->pci_bus;
124 uint8_t device = (uint8_t) pci->pci_dev;
125 uint8_t func = (uint8_t) pci->pci_func;
126
127 while (cap_ptr != 0 && cap_ptr >= 0x40 && cap_ptr <= 0xFF) {
128 uint8_t cap_id = pci_read8(bus, device, func,
129 cap_ptr); // ID capability
130 uint8_t next_ptr = pci_read8(
131 bus, device, func,
132 cap_ptr + 1); // pointer ke capability selanjutnya
133
134 if (cap_id == 0x11) {
135 return cap_ptr;
136 }
137
138 cap_ptr = next_ptr;
139 }
140 return 0;
141}
volatile uint32_t cap
Definition ehci.hpp:2
uint16_t pci_cap_find_msi(struct ioforge_pci_device *pci)
void pci_enable_msi(struct ioforge_pci_device *pci, uint8_t vector, uint8_t cpu, uint16_t cap)
uintptr_t pci_enable_msix(struct ioforge_pci_device *pci, uint8_t vector, uint8_t cpu, uint16_t cap)
uint16_t pci_cap_find_msix(struct ioforge_pci_device *pci)
struct ioforge_pci_device pci
void pci_write16(uint8_t bus, uint8_t dev, uint8_t func, uint16_t off, uint16_t val)
Definition scan.c:88
void pci_write32(uint8_t bus, uint8_t dev, uint8_t func, uint16_t off, uint32_t val)
Definition scan.c:72
uint16_t pci_read16(uint8_t bus, uint8_t dev, uint8_t func, uint16_t off)
Definition scan.c:62
uint8_t pci_read8(uint8_t bus, uint8_t dev, uint8_t func, uint16_t off)
Definition scan.c:67
uint32_t pci_read32(uint8_t bus, uint8_t dev, uint8_t func, uint16_t off)
Definition scan.c:49
#define LOG2_INFO(mod, fmt,...)
Definition serial.h:33
unsigned short uint16_t
Definition type.h:13
unsigned int uint32_t
Definition type.h:19
#define KERNEL_API
Definition type.h:93
unsigned long uintptr_t
Definition type.h:73
unsigned char uint8_t
Definition type.h:7
#define vector(T)
Definition vector.h:11
uint32_t offset
Definition virtio.h:6
struct device_id device
Definition vnode.h:13