Lines Matching +full:0 +full:- +full:dev
31 #define PCI_MSI_ADDRESS_LO_MASK (~0x3)
34 #define PCI_MSI_32_SIZEOF 0x0a
35 #define PCI_MSI_64_SIZEOF 0x0e
36 #define PCI_MSI_32M_SIZEOF 0x14
37 #define PCI_MSI_64M_SIZEOF 0x18
42 * Flag for interrupt controllers to declare broken MSI/MSI-X support.
43 * values: false - broken; true - non-broken.
45 * Setting this flag to false will remove MSI/MSI-X capability from all devices.
47 * It is preferable for controllers to set this to true (non-broken) even if
48 * they do not actually support MSI/MSI-X: guests normally probe the controller
49 * type and do not attempt to enable MSI/MSI-X with interrupt controllers not
67 case 0: in msi_cap_sizeof()
73 return 0; in msi_cap_sizeof()
82 # define MSI_DPRINTF(fmt, ...) do { } while (0)
84 #define MSI_DEV_PRINTF(dev, fmt, ...) \ argument
85 MSI_DPRINTF("%s:%x " fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
93 static inline uint8_t msi_flags_off(const PCIDevice* dev) in msi_flags_off() argument
95 return dev->msi_cap + PCI_MSI_FLAGS; in msi_flags_off()
98 static inline uint8_t msi_address_lo_off(const PCIDevice* dev) in msi_address_lo_off() argument
100 return dev->msi_cap + PCI_MSI_ADDRESS_LO; in msi_address_lo_off()
103 static inline uint8_t msi_address_hi_off(const PCIDevice* dev) in msi_address_hi_off() argument
105 return dev->msi_cap + PCI_MSI_ADDRESS_HI; in msi_address_hi_off()
108 static inline uint8_t msi_data_off(const PCIDevice* dev, bool msi64bit) in msi_data_off() argument
110 return dev->msi_cap + (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32); in msi_data_off()
113 static inline uint8_t msi_mask_off(const PCIDevice* dev, bool msi64bit) in msi_mask_off() argument
115 return dev->msi_cap + (msi64bit ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32); in msi_mask_off()
118 static inline uint8_t msi_pending_off(const PCIDevice* dev, bool msi64bit) in msi_pending_off() argument
120 return dev->msi_cap + (msi64bit ? PCI_MSI_PENDING_64 : PCI_MSI_PENDING_32); in msi_pending_off()
127 void msi_set_message(PCIDevice *dev, MSIMessage msg) in msi_set_message() argument
129 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_set_message()
133 pci_set_quad(dev->config + msi_address_lo_off(dev), msg.address); in msi_set_message()
135 pci_set_long(dev->config + msi_address_lo_off(dev), msg.address); in msi_set_message()
137 pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data); in msi_set_message()
140 static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector) in msi_prepare_message() argument
142 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_prepare_message()
150 msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev)); in msi_prepare_message()
152 msg.address = pci_get_long(dev->config + msi_address_lo_off(dev)); in msi_prepare_message()
156 msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit)); in msi_prepare_message()
158 msg.data &= ~(nr_vectors - 1); in msi_prepare_message()
165 MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector) in msi_get_message() argument
167 return dev->msi_prepare_message(dev, vector); in msi_get_message()
170 bool msi_enabled(const PCIDevice *dev) in msi_enabled() argument
172 return msi_present(dev) && in msi_enabled()
173 (pci_get_word(dev->config + msi_flags_off(dev)) & in msi_enabled()
178 * Make PCI device @dev MSI-capable.
179 * Non-zero @offset puts capability MSI at that offset in PCI config
182 * If @msi64bit, make the device capable of sending a 64-bit message
184 * If @msi_per_vector_mask, make the device support per-vector masking.
186 * Return 0 on success; set @errp and return -errno on error.
188 * -ENOTSUP means lacking msi support for a msi-capable platform.
189 * -EINVAL means capability overlap, happens when @offset is non-zero,
193 int msi_init(struct PCIDevice *dev, uint8_t offset, in msi_init() argument
204 return -ENOTSUP; in msi_init()
207 MSI_DEV_PRINTF(dev, in msi_init()
208 "init offset: 0x%"PRIx8" vector: %"PRId8 in msi_init()
212 assert(!(nr_vectors & (nr_vectors - 1))); /* power of 2 */ in msi_init()
213 assert(nr_vectors > 0); in msi_init()
227 config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset, in msi_init()
229 if (config_offset < 0) { in msi_init()
233 dev->msi_cap = config_offset; in msi_init()
234 dev->cap_present |= QEMU_PCI_CAP_MSI; in msi_init()
236 pci_set_word(dev->config + msi_flags_off(dev), flags); in msi_init()
237 pci_set_word(dev->wmask + msi_flags_off(dev), in msi_init()
239 pci_set_long(dev->wmask + msi_address_lo_off(dev), in msi_init()
242 pci_set_long(dev->wmask + msi_address_hi_off(dev), 0xffffffff); in msi_init()
244 pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff); in msi_init()
247 /* Make mask bits 0 to nr_vectors - 1 writable. */ in msi_init()
248 pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit), in msi_init()
249 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors)); in msi_init()
252 dev->msi_prepare_message = msi_prepare_message; in msi_init()
254 return 0; in msi_init()
257 void msi_uninit(struct PCIDevice *dev) in msi_uninit() argument
262 if (!msi_present(dev)) { in msi_uninit()
265 flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_uninit()
267 pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size); in msi_uninit()
268 dev->cap_present &= ~QEMU_PCI_CAP_MSI; in msi_uninit()
269 dev->msi_prepare_message = NULL; in msi_uninit()
271 MSI_DEV_PRINTF(dev, "uninit\n"); in msi_uninit()
274 void msi_reset(PCIDevice *dev) in msi_reset() argument
279 if (!msi_present(dev)) { in msi_reset()
283 flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_reset()
287 pci_set_word(dev->config + msi_flags_off(dev), flags); in msi_reset()
288 pci_set_long(dev->config + msi_address_lo_off(dev), 0); in msi_reset()
290 pci_set_long(dev->config + msi_address_hi_off(dev), 0); in msi_reset()
292 pci_set_word(dev->config + msi_data_off(dev, msi64bit), 0); in msi_reset()
294 pci_set_long(dev->config + msi_mask_off(dev, msi64bit), 0); in msi_reset()
295 pci_set_long(dev->config + msi_pending_off(dev, msi64bit), 0); in msi_reset()
297 MSI_DEV_PRINTF(dev, "reset\n"); in msi_reset()
300 bool msi_is_masked(const PCIDevice *dev, unsigned int vector) in msi_is_masked() argument
302 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_is_masked()
311 data = pci_get_word(dev->config + msi_data_off(dev, msi64bit)); in msi_is_masked()
316 mask = pci_get_long(dev->config + in msi_is_masked()
317 msi_mask_off(dev, flags & PCI_MSI_FLAGS_64BIT)); in msi_is_masked()
321 void msi_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp) in msi_set_mask() argument
323 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_set_mask()
329 vector, (PCI_MSI_VECTORS_MAX - 1)); in msi_set_mask()
335 irq_state = pci_get_long(dev->config + msi_mask_off(dev, msi64bit)); in msi_set_mask()
343 pci_set_long(dev->config + msi_mask_off(dev, msi64bit), irq_state); in msi_set_mask()
345 pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit)); in msi_set_mask()
348 pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending); in msi_set_mask()
349 msi_notify(dev, vector); in msi_set_mask()
353 void msi_notify(PCIDevice *dev, unsigned int vector) in msi_notify() argument
355 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_notify()
361 if (msi_is_masked(dev, vector)) { in msi_notify()
364 dev->config + msi_pending_off(dev, msi64bit), 1U << vector); in msi_notify()
365 MSI_DEV_PRINTF(dev, "pending vector 0x%x\n", vector); in msi_notify()
369 msg = msi_get_message(dev, vector); in msi_notify()
371 MSI_DEV_PRINTF(dev, in msi_notify()
372 "notify vector 0x%x" in msi_notify()
373 " address: 0x%"PRIx64" data: 0x%"PRIx32"\n", in msi_notify()
375 msi_send_message(dev, msg); in msi_notify()
378 void msi_send_message(PCIDevice *dev, MSIMessage msg) in msi_send_message() argument
380 dev->msi_trigger(dev, msg); in msi_send_message()
384 void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) in msi_write_config() argument
386 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_write_config()
395 if (!msi_present(dev) || in msi_write_config()
396 !ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) { in msi_write_config()
401 MSI_DEV_PRINTF(dev, "addr 0x%"PRIx32" val 0x%"PRIx32" len %d\n", in msi_write_config()
403 MSI_DEV_PRINTF(dev, "ctrl: 0x%"PRIx16" address: 0x%"PRIx32, in msi_write_config()
405 pci_get_long(dev->config + msi_address_lo_off(dev))); in msi_write_config()
407 fprintf(stderr, " address-hi: 0x%"PRIx32, in msi_write_config()
408 pci_get_long(dev->config + msi_address_hi_off(dev))); in msi_write_config()
410 fprintf(stderr, " data: 0x%"PRIx16, in msi_write_config()
411 pci_get_word(dev->config + msi_data_off(dev, msi64bit))); in msi_write_config()
413 fprintf(stderr, " mask 0x%"PRIx32" pending 0x%"PRIx32, in msi_write_config()
414 pci_get_long(dev->config + msi_mask_off(dev, msi64bit)), in msi_write_config()
415 pci_get_long(dev->config + msi_pending_off(dev, msi64bit))); in msi_write_config()
421 for (vector = 0; vector < msi_nr_vectors(flags); vector++) { in msi_write_config()
422 MSIMessage msg = msi_prepare_message(dev, vector); in msi_write_config()
424 xen_evtchn_snoop_msi(dev, false, vector, msg.address, msg.data, in msi_write_config()
425 msi_is_masked(dev, vector)); in msi_write_config()
440 * While enabled for MSI or MSI-X operation, a function is prohibited in msi_write_config()
442 * service (MSI, MSI-X, and INTx# are mutually exclusive). in msi_write_config()
444 pci_device_deassert_intx(dev); in msi_write_config()
458 pci_set_word(dev->config + msi_flags_off(dev), flags); in msi_write_config()
470 pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit)); in msi_write_config()
471 pending &= 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors); in msi_write_config()
472 pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending); in msi_write_config()
475 for (vector = 0; vector < nr_vectors; ++vector) { in msi_write_config()
476 if (msi_is_masked(dev, vector) || !(pending & (1U << vector))) { in msi_write_config()
481 dev->config + msi_pending_off(dev, msi64bit), 1U << vector); in msi_write_config()
482 msi_notify(dev, vector); in msi_write_config()
486 unsigned int msi_nr_vectors_allocated(const PCIDevice *dev) in msi_nr_vectors_allocated() argument
488 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); in msi_nr_vectors_allocated()