btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / system / kernel / arch / x86 / msi.cpp
blob64dc74ae45c6458eddb21c01567290aa71452419
1 /*
2 * Copyright 2010-2011, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3 * Distributed under the terms of the MIT license.
4 */
6 #include <arch/x86/apic.h>
7 #include <arch/x86/msi.h>
8 #include <arch/x86/arch_smp.h>
10 #include <debug.h>
11 #include <int.h>
12 #include <lock.h>
15 struct MSIConfiguration {
16 uint64* fAddress;
17 uint16* fData;
20 static MSIConfiguration sMSIConfigurations[NUM_IO_VECTORS];
22 static bool sMSISupported = false;
23 static uint32 sBootCPUAPICId = 0;
26 void
27 msi_init(kernel_args* args)
29 if (!apic_available()) {
30 dprintf("disabling msi due to missing apic\n");
31 return;
34 dprintf("msi support enabled\n");
35 sMSISupported = true;
36 sBootCPUAPICId = args->arch_args.cpu_apic_id[0];
40 bool
41 msi_supported()
43 return sMSISupported;
47 status_t
48 msi_allocate_vectors(uint8 count, uint8 *startVector, uint64 *address,
49 uint16 *data)
51 if (!sMSISupported)
52 return B_UNSUPPORTED;
54 long vector;
55 status_t result = allocate_io_interrupt_vectors(count, &vector,
56 INTERRUPT_TYPE_IRQ);
57 if (result != B_OK)
58 return result;
60 if (vector >= NUM_IO_VECTORS) {
61 free_io_interrupt_vectors(count, vector);
62 return B_NO_MEMORY;
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",
76 count, *startVector);
77 return B_OK;
81 void
82 msi_free_vectors(uint8 count, uint8 startVector)
84 if (!sMSISupported) {
85 panic("trying to free msi vectors but msi not supported\n");
86 return;
89 dprintf("msi_free_vectors: freeing %u vectors starting from %u\n", count,
90 startVector);
92 free_io_interrupt_vectors(count, startVector);
96 void
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;