1717#define PCI_COMMAND_MEMORY 0x2
1818#define PCI_COMMAND_BUS 0x4
1919
20+ #define PCI_BAR_BASE_OFFSET 0x10
21+
22+ #define PCI_CAPABILITY_MSI 0x05
23+ #define PCI_CAPABILITY_PCIE 0x10
24+ #define PCI_CAPABILITY_MSIX 0x11
25+
2026static uint64_t pci_base ;
2127
2228#define NINIT pci_base == 0x0
@@ -198,25 +204,19 @@ uint64_t pci_get_bar_address(uint64_t base, uint8_t offset, uint8_t index){
198204}
199205
200206uint64_t pci_read_address_bar (uintptr_t pci_addr , uint32_t bar_index ){
201- uint64_t bar_addr = pci_get_bar_address (pci_addr , 0x10 , bar_index );
207+ uint64_t bar_addr = pci_get_bar_address (pci_addr , PCI_BAR_BASE_OFFSET , bar_index );
202208 uint32_t original = read32 (bar_addr );
203209 uint64_t full = original ;
204210 if ((original & 0x6 ) == 0x4 ) {
205- uint64_t bar_addr_hi = pci_get_bar_address (pci_addr , 0x10 , bar_index + 1 );
211+ uint64_t bar_addr_hi = pci_get_bar_address (pci_addr , PCI_BAR_BASE_OFFSET , bar_index + 1 );
206212 uint64_t original_hi = read32 (bar_addr_hi );
207213 full |= original_hi << 32 ;
208214 }
209215 return full & ~0xF ;
210216}
211217
212- void debug_read_bar (uint64_t base , uint8_t offset , uint8_t index ){
213- uint64_t addr = pci_get_bar_address (base , offset , index );
214- uint64_t val = read32 (addr );
215- kprintf ("[PCI] Reading@%x (%i) content: " , addr , index , val );
216- }
217-
218218uint64_t pci_setup_bar (uint64_t pci_addr , uint32_t bar_index , uint64_t * mmio_start , uint64_t * mmio_size ) {
219- uint64_t bar_addr = pci_get_bar_address (pci_addr , 0x10 , bar_index );
219+ uint64_t bar_addr = pci_get_bar_address (pci_addr , PCI_BAR_BASE_OFFSET , bar_index );
220220 uint32_t original = read32 (bar_addr );
221221
222222 write32 (bar_addr , 0xFFFFFFFF );
@@ -225,7 +225,7 @@ uint64_t pci_setup_bar(uint64_t pci_addr, uint32_t bar_index, uint64_t *mmio_sta
225225
226226 uint64_t size ;
227227 if ((original & 0x6 ) == 0x4 ) {
228- uint64_t bar_addr_hi = pci_get_bar_address (pci_addr , 0x10 , bar_index + 1 );
228+ uint64_t bar_addr_hi = pci_get_bar_address (pci_addr , PCI_BAR_BASE_OFFSET , bar_index + 1 );
229229 uint32_t original_hi = read32 (bar_addr_hi );
230230
231231 kprintfv ("[PCI] Original second bar %x" ,original_hi );
@@ -314,7 +314,7 @@ bool pci_setup_msi(uint64_t pci_addr, uint8_t irq_line) {
314314 uint8_t cap_ptr = read8 (pci_addr + 0x34 );
315315 while (cap_ptr ) {
316316 uint8_t cap_id = read8 (pci_addr + cap_ptr );
317- if (cap_id == 0x05 ) { // MSI
317+ if (cap_id == PCI_CAPABILITY_MSI ) { // MSI
318318 uint16_t msg_ctrl = read16 (pci_addr + cap_ptr + 0x2 );
319319 bool is_64bit = msg_ctrl & (1 << 7 );
320320
@@ -325,7 +325,7 @@ bool pci_setup_msi(uint64_t pci_addr, uint8_t irq_line) {
325325 offset += 4 ;
326326 }
327327
328- write16 (pci_addr + cap_ptr + offset , 50 + irq_line );
328+ write16 (pci_addr + cap_ptr + offset , MSI_OFFSET + irq_line );
329329 msg_ctrl |= 1 ; // enable MSI
330330 write16 (pci_addr + cap_ptr + 0x2 , msg_ctrl );
331331 return true;
@@ -342,27 +342,46 @@ typedef struct {
342342 uint32_t vector_control ;
343343} msix_table_entry ;
344344
345- bool pci_setup_msix (uint64_t pci_addr , uint8_t irq_line ) {
345+ bool pci_setup_msix (uint64_t pci_addr , msix_irq_line * irq_lines , uint8_t line_size ) {
346346
347347 uint8_t cap_ptr = read8 (pci_addr + 0x34 );
348348 while (cap_ptr ) {
349349 uint8_t cap_id = read8 (pci_addr + cap_ptr );
350- if (cap_id == 0x11 ) { // MSI-X
350+ if (cap_id == PCI_CAPABILITY_MSIX ) { // MSI-X
351351 uint16_t msg_ctrl = read16 (pci_addr + cap_ptr + 0x2 );
352352 msg_ctrl &= ~(1 << 15 ); // Clear MSI-X Enable bit
353353 write16 (pci_addr + cap_ptr + 0x2 , msg_ctrl );
354+ uint16_t table_size = (msg_ctrl & 0x07FF ) + 1 ; // takes the 11 rightmost bits, its value is N-1, so add 1 to it for the full size
355+
356+ if (line_size > table_size ){
357+ kprintf_raw ("[PCI] MSI-X only supports %i interrupts, but you tried to add %i interrupts" , table_size , line_size );
358+ return false;
359+ }
360+
354361 uint32_t table_offset = read32 (pci_addr + cap_ptr + 0x4 );
355362 uint8_t bir = table_offset & 0x7 ;
356363 uint32_t table_addr_offset = table_offset & ~0x7 ;
357364
358365 uint64_t table_addr = pci_read_address_bar (pci_addr , bir );
366+
367+ if (!table_addr ){
368+ kprintf_raw ("[PCI] MSI-X setup error: Table address is null. Did you setup the bar memory before calling this function?" );
369+ return false;
370+ }
359371
360- msix_table_entry * msix_entry = (msix_table_entry * )(uintptr_t )(table_addr + table_addr_offset );
361-
362- msix_entry -> msg_addr_low = 0x8020040 ;
363- msix_entry -> msg_addr_high = 0 ;
364- msix_entry -> msg_data = 50 + irq_line ;
365- msix_entry -> vector_control = 0 ;
372+ msix_table_entry * msix_start = (msix_table_entry * )(uintptr_t )(table_addr + table_addr_offset );
373+
374+ for (uint32_t i = 0 ; i < line_size ; i ++ ){
375+ msix_table_entry * msix_entry = msix_start + i ;
376+
377+ msix_irq_line irq_line = irq_lines [i ];
378+ uint64_t addr_full = 0x8020040 + irq_line .addr_offset ;
379+
380+ msix_entry -> msg_addr_low = addr_full & 0xFFFFFFFF ;
381+ msix_entry -> msg_addr_high = addr_full >> 32 ;
382+ msix_entry -> msg_data = MSI_OFFSET + irq_line .irq_num ;
383+ msix_entry -> vector_control = msix_entry -> vector_control & ~0x1 ; // all bits other then the last one are reserved, so don't chnage it, just set the last bit to 0
384+ }
366385
367386 msg_ctrl |= (1 << 15 ); // MSI-X Enable
368387 msg_ctrl &= ~(1 << 14 ); // Clear Function Mask
0 commit comments