2 * Copyright 2010-2011, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3 * Distributed under the terms of the MIT license.
6 #include <arch/x86/apic.h>
7 #include <arch/x86/msi.h>
8 #include <arch/x86/arch_smp.h>
15 struct MSIConfiguration
{
20 static MSIConfiguration sMSIConfigurations
[NUM_IO_VECTORS
];
22 static bool sMSISupported
= false;
23 static uint32 sBootCPUAPICId
= 0;
27 msi_init(kernel_args
* args
)
29 if (!apic_available()) {
30 dprintf("disabling msi due to missing apic\n");
34 dprintf("msi support enabled\n");
36 sBootCPUAPICId
= args
->arch_args
.cpu_apic_id
[0];
48 msi_allocate_vectors(uint8 count
, uint8
*startVector
, uint64
*address
,
55 status_t result
= allocate_io_interrupt_vectors(count
, &vector
,
60 if (vector
>= NUM_IO_VECTORS
) {
61 free_io_interrupt_vectors(count
, vector
);
65 sMSIConfigurations
[vector
].fAddress
= address
;
66 sMSIConfigurations
[vector
].fData
= data
;
67 x86_set_irq_source(vector
, IRQ_SOURCE_MSI
);
69 *startVector
= (uint8
)vector
;
70 *address
= MSI_ADDRESS_BASE
| (sBootCPUAPICId
<< MSI_DESTINATION_ID_SHIFT
)
71 | MSI_NO_REDIRECTION
| MSI_DESTINATION_MODE_PHYSICAL
;
72 *data
= MSI_TRIGGER_MODE_EDGE
| MSI_DELIVERY_MODE_FIXED
73 | ((uint16
)vector
+ ARCH_INTERRUPT_BASE
);
75 dprintf("msi_allocate_vectors: allocated %u vectors starting from %u\n",
82 msi_free_vectors(uint8 count
, uint8 startVector
)
85 panic("trying to free msi vectors but msi not supported\n");
89 dprintf("msi_free_vectors: freeing %u vectors starting from %u\n", count
,
92 free_io_interrupt_vectors(count
, startVector
);
97 msi_assign_interrupt_to_cpu(uint8 irq
, int32 cpu
)
99 uint32 apic_id
= x86_get_cpu_apic_id(cpu
);
101 uint64
* address
= sMSIConfigurations
[irq
].fAddress
;
102 *address
= MSI_ADDRESS_BASE
| (apic_id
<< MSI_DESTINATION_ID_SHIFT
)
103 | MSI_NO_REDIRECTION
| MSI_DESTINATION_MODE_PHYSICAL
;