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