pci-edu.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /*
  2. * Edu PCI device.
  3. *
  4. * Copyright (C) 2016 Red Hat, Inc.
  5. *
  6. * Authors:
  7. * Peter Xu <peterx@redhat.com>,
  8. *
  9. * This work is licensed under the terms of the GNU LGPL, version 2 or
  10. * later.
  11. */
  12. #include "pci-edu.h"
  13. #include "asm/barrier.h"
  14. /* Return true if alive */
  15. static inline bool edu_check_alive(struct pci_edu_dev *dev)
  16. {
  17. static uint32_t live_count = 1;
  18. uint32_t value;
  19. edu_reg_writel(dev, EDU_REG_ALIVE, live_count++);
  20. value = edu_reg_readl(dev, EDU_REG_ALIVE);
  21. return (live_count - 1 == ~value);
  22. }
  23. bool edu_init(struct pci_edu_dev *dev)
  24. {
  25. pcidevaddr_t dev_addr;
  26. dev_addr = pci_find_dev(PCI_VENDOR_ID_QEMU, PCI_DEVICE_ID_EDU);
  27. if (dev_addr == PCIDEVADDR_INVALID)
  28. return false;
  29. pci_dev_init(&dev->pci_dev, dev_addr);
  30. pci_enable_defaults(&dev->pci_dev);
  31. dev->reg_base = ioremap(dev->pci_dev.resource[EDU_BAR], PAGE_SIZE);
  32. assert(edu_check_alive(dev));
  33. return true;
  34. }
  35. void edu_dma(struct pci_edu_dev *dev, iova_t iova,
  36. size_t size, unsigned int dev_offset, bool from_device)
  37. {
  38. uint64_t from, to;
  39. uint32_t cmd = EDU_CMD_DMA_START;
  40. assert(size <= EDU_DMA_SIZE_MAX);
  41. assert(dev_offset < EDU_DMA_SIZE_MAX);
  42. printf("edu device DMA start %s addr %#" PRIx64 " size %lu off %#x\n",
  43. from_device ? "FROM" : "TO",
  44. iova, (ulong)size, dev_offset);
  45. if (from_device) {
  46. from = dev_offset + EDU_DMA_START;
  47. to = iova;
  48. cmd |= EDU_CMD_DMA_FROM;
  49. } else {
  50. from = iova;
  51. to = EDU_DMA_START + dev_offset;
  52. cmd |= EDU_CMD_DMA_TO;
  53. }
  54. edu_reg_writeq(dev, EDU_REG_DMA_SRC, from);
  55. edu_reg_writeq(dev, EDU_REG_DMA_DST, to);
  56. edu_reg_writeq(dev, EDU_REG_DMA_COUNT, size);
  57. edu_reg_writel(dev, EDU_REG_DMA_CMD, cmd);
  58. /* Wait until DMA finished */
  59. while (edu_reg_readl(dev, EDU_REG_DMA_CMD) & EDU_CMD_DMA_START)
  60. cpu_relax();
  61. }