Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | /* * Copyright (C) 2003-2004 Intel * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) */ #ifndef MSI_H #define MSI_H #include <asm/msi.h> /* * Assume the maximum number of hot plug slots supported by the system is about * ten. The worstcase is that each of these slots is hot-added with a device, * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined * as below to ensure at least one message is assigned to each detected MSI/ * MSI-X device function. */ #define NR_HP_RESERVED_VECTORS 20 extern int vector_irq[NR_VECTORS]; extern void (*interrupt[NR_IRQS])(void); extern int pci_vector_resources(int last, int nr_released); /* * MSI-X Address Register */ #define PCI_MSIX_FLAGS_QSIZE 0x7FF #define PCI_MSIX_FLAGS_ENABLE (1 << 15) #define PCI_MSIX_FLAGS_BIRMASK (7 << 0) #define PCI_MSIX_FLAGS_BITMASK (1 << 0) #define PCI_MSIX_ENTRY_SIZE 16 #define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 #define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 #define PCI_MSIX_ENTRY_DATA_OFFSET 8 #define PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET 12 #define msi_control_reg(base) (base + PCI_MSI_FLAGS) #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) #define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) #define msi_data_reg(base, is64bit) \ ( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 ) #define msi_mask_bits_reg(base, is64bit) \ ( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4) #define msi_disable(control) control &= ~PCI_MSI_FLAGS_ENABLE #define multi_msi_capable(control) \ (1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1)) #define multi_msi_enable(control, num) \ control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE); #define is_64bit_address(control) (control & PCI_MSI_FLAGS_64BIT) #define is_mask_bit_support(control) (control & PCI_MSI_FLAGS_MASKBIT) #define msi_enable(control, num) multi_msi_enable(control, num); \ control |= PCI_MSI_FLAGS_ENABLE #define msix_table_offset_reg(base) (base + 0x04) #define msix_pba_offset_reg(base) (base + 0x08) #define msix_enable(control) control |= PCI_MSIX_FLAGS_ENABLE #define msix_disable(control) control &= ~PCI_MSIX_FLAGS_ENABLE #define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1) #define multi_msix_capable msix_table_size #define msix_unmask(address) (address & ~PCI_MSIX_FLAGS_BITMASK) #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) /* * MSI Defined Data Structures */ #define MSI_ADDRESS_HEADER 0xfee #define MSI_ADDRESS_HEADER_SHIFT 12 #define MSI_ADDRESS_HEADER_MASK 0xfff000 #define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f #define MSI_TARGET_CPU_MASK 0xff #define MSI_DELIVERY_MODE 0 #define MSI_LEVEL_MODE 1 /* Edge always assert */ #define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */ #define MSI_PHYSICAL_MODE 0 #define MSI_LOGICAL_MODE 1 #define MSI_REDIRECTION_HINT_MODE 0 struct msg_data { #if defined(__LITTLE_ENDIAN_BITFIELD) __u32 vector : 8; __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ __u32 reserved_1 : 3; __u32 level : 1; /* 0: deassert | 1: assert */ __u32 trigger : 1; /* 0: edge | 1: level */ __u32 reserved_2 : 16; #elif defined(__BIG_ENDIAN_BITFIELD) __u32 reserved_2 : 16; __u32 trigger : 1; /* 0: edge | 1: level */ __u32 level : 1; /* 0: deassert | 1: assert */ __u32 reserved_1 : 3; __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ __u32 vector : 8; #else #error "Bitfield endianness not defined! Check your byteorder.h" #endif } __attribute__ ((packed)); struct msg_address { union { struct { #if defined(__LITTLE_ENDIAN_BITFIELD) __u32 reserved_1 : 2; __u32 dest_mode : 1; /*0:physic | 1:logic */ __u32 redirection_hint: 1; /*0: dedicated CPU 1: lowest priority */ __u32 reserved_2 : 4; __u32 dest_id : 24; /* Destination ID */ #elif defined(__BIG_ENDIAN_BITFIELD) __u32 dest_id : 24; /* Destination ID */ __u32 reserved_2 : 4; __u32 redirection_hint: 1; /*0: dedicated CPU 1: lowest priority */ __u32 dest_mode : 1; /*0:physic | 1:logic */ __u32 reserved_1 : 2; #else #error "Bitfield endianness not defined! Check your byteorder.h" #endif }u; __u32 value; }lo_address; __u32 hi_address; } __attribute__ ((packed)); struct msi_desc { struct { __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ __u8 maskbit : 1; /* mask-pending bit supported ? */ __u8 state : 1; /* {0: free, 1: busy} */ __u8 reserved: 1; /* reserved */ __u8 entry_nr; /* specific enabled entry */ __u8 default_vector; /* default pre-assigned vector */ __u8 current_cpu; /* current destination cpu */ }msi_attrib; struct { __u16 head; __u16 tail; }link; void __iomem *mask_base; struct pci_dev *dev; }; #endif /* MSI_H */ |