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
14static bool sMSISupported = false;
15
16
17void
18msi_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
30bool
31msi_supported()
32{
33	return sMSISupported;
34}
35
36
37status_t
38msi_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
66void
67msi_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