xref: /haiku/src/system/kernel/arch/x86/msi.cpp (revision 98057dd02a2411868fd4c35f7a48d20acfd92c23)
1 /*
2  * Copyright 2010-2011, Michael Lotz, mmlr@mlotz.ch. All Rights Reserved.
3  * Distributed under the terms of the MIT license.
4  */
5 
6 #include <arch/x86/apic.h>
7 #include <arch/x86/msi.h>
8 
9 #include <debug.h>
10 #include <int.h>
11 #include <lock.h>
12 
13 
14 static bool sMSISupported = false;
15 
16 
17 void
18 msi_init()
19 {
20 	if (!apic_available()) {
21 		dprintf("disabling msi due to missing apic\n");
22 		return;
23 	}
24 
25 	dprintf("msi support enabled\n");
26 	sMSISupported = true;
27 }
28 
29 
30 bool
31 msi_supported()
32 {
33 	return sMSISupported;
34 }
35 
36 
37 status_t
38 msi_allocate_vectors(uint8 count, uint8 *startVector, uint64 *address,
39 	uint16 *data)
40 {
41 	if (!sMSISupported)
42 		return B_UNSUPPORTED;
43 
44 	long vector;
45 	status_t result = allocate_io_interrupt_vectors(count, &vector);
46 	if (result != B_OK)
47 		return result;
48 
49 	if (vector >= 256) {
50 		free_io_interrupt_vectors(count, vector);
51 		return B_NO_MEMORY;
52 	}
53 
54 	*startVector = (uint8)vector;
55 	*address = MSI_ADDRESS_BASE | (0 << MSI_DESTINATION_ID_SHIFT)
56 		| MSI_NO_REDIRECTION | MSI_DESTINATION_MODE_PHYSICAL;
57 	*data = MSI_TRIGGER_MODE_EDGE | MSI_DELIVERY_MODE_FIXED
58 		| ((uint16)vector + ARCH_INTERRUPT_BASE);
59 
60 	dprintf("msi_allocate_vectors: allocated %u vectors starting from %u\n",
61 		count, *startVector);
62 	return B_OK;
63 }
64 
65 
66 void
67 msi_free_vectors(uint8 count, uint8 startVector)
68 {
69 	if (!sMSISupported) {
70 		panic("trying to free msi vectors but msi not supported\n");
71 		return;
72 	}
73 
74 	dprintf("msi_free_vectors: freeing %u vectors starting from %u\n", count,
75 		startVector);
76 
77 	free_io_interrupt_vectors(count, startVector);
78 }
79