You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ra...@apache.org on 2024/01/20 13:10:26 UTC
(nuttx) 02/06: x86_64: qemu: implement pci-e functions and enumerate pci-e devices on boot
This is an automated email from the ASF dual-hosted git repository.
raiden00 pushed a commit to branch pci
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 9a36544539c24b81d0ab9c1cb48e65815b5e9b91
Author: Yang Chung-Fan <so...@gmail.com>
AuthorDate: Mon May 4 18:45:22 2020 +0900
x86_64: qemu: implement pci-e functions and enumerate pci-e devices on
boot
---
boards/x86_64/intel64/qemu-intel64/Kconfig | 8 +
boards/x86_64/intel64/qemu-intel64/include/board.h | 2 +
boards/x86_64/intel64/qemu-intel64/src/Makefile | 4 +
boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c | 6 +
boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c | 398 +++++++++++++++++++++
.../intel64/qemu-intel64/src/qemu_pcie_readwrite.h | 240 +++++++++++++
6 files changed, 658 insertions(+)
diff --git a/boards/x86_64/intel64/qemu-intel64/Kconfig b/boards/x86_64/intel64/qemu-intel64/Kconfig
index f72f3c094c..595127192b 100644
--- a/boards/x86_64/intel64/qemu-intel64/Kconfig
+++ b/boards/x86_64/intel64/qemu-intel64/Kconfig
@@ -2,3 +2,11 @@
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
+#
+config QEMU_PCIE
+ bool "Initialize and enumerate PCI-E Bus"
+ default n
+ select PCIE
+
+ ---help---
+ Enables initialization and scaning of standard x86-64 pcie bus.
diff --git a/boards/x86_64/intel64/qemu-intel64/include/board.h b/boards/x86_64/intel64/qemu-intel64/include/board.h
index 9cb23e995b..ae7b588407 100644
--- a/boards/x86_64/intel64/qemu-intel64/include/board.h
+++ b/boards/x86_64/intel64/qemu-intel64/include/board.h
@@ -66,6 +66,8 @@ extern "C"
* Public Function Prototypes
****************************************************************************/
+void qemu_pcie_init(void);
+
#undef EXTERN
#if defined(__cplusplus)
}
diff --git a/boards/x86_64/intel64/qemu-intel64/src/Makefile b/boards/x86_64/intel64/qemu-intel64/src/Makefile
index 7bdacd1f3c..9ab32d1766 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/Makefile
+++ b/boards/x86_64/intel64/qemu-intel64/src/Makefile
@@ -26,4 +26,8 @@ ifeq ($(CONFIG_BOARDCTL),y)
CSRCS += qemu_appinit.c
endif
+ifeq ($(CONFIG_QEMU_PCIE),y)
+ CSRCS += qemu_pcie.c
+endif
+
include $(TOPDIR)/boards/Board.mk
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c
index 32cdcb33ec..d4b02b1926 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c
@@ -66,6 +66,12 @@ void x86_64_boardinitialize(void)
uart_putreg(CONFIG_16550_UART1_BASE, UART_MCR_OFFSET, UART_MCR_OUT2);
#endif
+#ifdef CONFIG_QEMU_PCIE
+ /* Initialization of system */
+
+ qemu_pcie_init();
+#endif
+
/* Configure on-board LEDs if LED support has been selected. */
#ifdef CONFIG_ARCH_LEDS
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c
new file mode 100644
index 0000000000..0580593fad
--- /dev/null
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c
@@ -0,0 +1,398 @@
+/****************************************************************************
+ * boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* The MSI and MSI-X vector setup function are taken from Jailhouse inmate
+ * library
+ *
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ * Jan Kiszka <ja...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Alternatively, you can use or redistribute this file under the following
+ * BSD license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+
+#include <nuttx/pcie/pcie.h>
+
+#include "qemu_pcie_readwrite.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions Definitions
+ ****************************************************************************/
+
+static int qemu_pci_cfg_write(FAR struct pcie_dev_s *dev, uintptr_t addr,
+ FAR const void *buffer, unsigned int size);
+
+static int qemu_pci_cfg_read(FAR struct pcie_dev_s *dev, uintptr_t addr,
+ FAR void *buffer, unsigned int size);
+
+static int qemu_pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t addr,
+ unsigned long length);
+
+static int qemu_pci_map_bar64(FAR struct pcie_dev_s *dev, uint64_t addr,
+ unsigned long length);
+
+static int qemu_pci_msix_register(FAR struct pcie_dev_s *dev,
+ uint32_t vector, uint32_t index);
+
+static int qemu_pci_msi_register(FAR struct pcie_dev_s *dev,
+ uint16_t vector);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+struct pcie_bus_ops_s qemu_pcie_bus_ops =
+{
+ .pci_cfg_write = qemu_pci_cfg_write,
+ .pci_cfg_read = qemu_pci_cfg_read,
+ .pci_map_bar = qemu_pci_map_bar,
+ .pci_map_bar64 = qemu_pci_map_bar64,
+ .pci_msix_register = qemu_pci_msix_register,
+ .pci_msi_register = qemu_pci_msi_register,
+};
+
+struct pcie_bus_s qemu_pcie_bus =
+{
+ .ops = &qemu_pcie_bus_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: qemu_pci_cfg_write
+ *
+ * Description:
+ * Write 8, 16, 32, 64 bits data to PCI-E configuration space of device
+ * specified by dev
+ *
+ * Input Parameters:
+ * bdf - Device private data
+ * buffer - A pointer to the read-only buffer of data to be written
+ * size - The number of bytes to send from the buffer
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static int qemu_pci_cfg_write(FAR struct pcie_dev_s *dev, uintptr_t addr,
+ FAR const void *buffer, unsigned int size)
+{
+ if (!buffer)
+ return -EINVAL;
+
+ switch (size)
+ {
+ case 1:
+ case 2:
+ case 4:
+ return __qemu_pci_cfg_write(dev->bdf, addr, buffer, size);
+ case 8:
+ return __qemu_pci_cfg_write(dev->bdf, addr, buffer, size);
+ default:
+ return -EINVAL;
+ }
+}
+
+/****************************************************************************
+ * Name: qemu_pci_cfg_read
+ *
+ * Description:
+ * Read 8, 16, 32, 64 bits data from PCI-E configuration space of device
+ * specified by dev
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * buffer - A pointer to a buffer to receive the data from the device
+ * size - The requested number of bytes to be read
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static int qemu_pci_cfg_read(FAR struct pcie_dev_s *dev, uintptr_t addr,
+ FAR void *buffer, unsigned int size)
+{
+ if (!buffer)
+ return -EINVAL;
+
+ switch (size)
+ {
+ case 1:
+ case 2:
+ case 4:
+ return __qemu_pci_cfg_read(dev->bdf, addr, buffer, size);
+ case 8:
+ return __qemu_pci_cfg_read64(dev->bdf, addr, buffer, size);
+ default:
+ return -EINVAL;
+ }
+}
+
+/****************************************************************************
+ * Name: qemu_pci_map_bar
+ *
+ * Description:
+ * Map address in a 32 bits bar in the memory address space
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * length - Map length, multiple of PAGE_SIZE
+ * ret - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static int qemu_pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t addr,
+ unsigned long length)
+{
+ up_map_region((void *)((uintptr_t)addr), length,
+ X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: qemu_pci_map_bar64
+ *
+ * Description:
+ * Map address in a 64 bits bar in the memory address space
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * length - Map length, multiple of PAGE_SIZE
+ * ret - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static int qemu_pci_map_bar64(FAR struct pcie_dev_s *dev, uint64_t addr,
+ unsigned long length)
+{
+ up_map_region((void *)((uintptr_t)addr), length,
+ X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: qemu_pci_msix_register
+ *
+ * Description:
+ * Map a device MSI-X vector to a platform IRQ vector
+ *
+ * Input Parameters:
+ * dev - Device
+ * vector - IRQ number of the platform
+ * index - Device MSI-X vector number
+ *
+ * Returned Value:
+ * <0: Mapping failed
+ * 0: Mapping succeed
+ *
+ ****************************************************************************/
+
+static int qemu_pci_msix_register(FAR struct pcie_dev_s *dev,
+ uint32_t vector, uint32_t index)
+{
+ unsigned int bar;
+ uint16_t message_control;
+ uint32_t table_bar_ind;
+ uint32_t table_addr_32;
+ uint64_t msix_table_addr = 0;
+
+ int cap = pci_find_cap(dev, PCI_CAP_MSIX);
+ if (cap < 0)
+ return -EINVAL;
+
+ __qemu_pci_cfg_read(dev->bdf, cap + PCI_MSIX_MCR,
+ &message_control, PCI_MSIX_MCR_SIZE);
+
+ /* bounds check */
+
+ if (index > (message_control & PCI_MSIX_MCR_TBL_MASK))
+ return -EINVAL;
+
+ __qemu_pci_cfg_read(dev->bdf, cap + PCI_MSIX_TBL,
+ &table_bar_ind, PCI_MSIX_TBL_SIZE);
+
+ bar = (table_bar_ind & PCI_MSIX_BIR_MASK);
+
+ if (!pci_get_bar(dev, bar, &table_addr_32))
+ {
+ /* 32 bit bar */
+
+ msix_table_addr = table_addr_32;
+ }
+ else
+ {
+ pci_get_bar64(dev, bar, &msix_table_addr);
+ }
+
+ msix_table_addr &= ~0xf;
+ msix_table_addr += table_bar_ind & ~PCI_MSIX_BIR_MASK;
+
+ /* enable and mask */
+
+ message_control |= (PCI_MSIX_MCR_EN | PCI_MSIX_MCR_FMASK);
+ __qemu_pci_cfg_write(dev->bdf, cap + PCI_MSIX_MCR,
+ &message_control, PCI_MSIX_MCR_SIZE);
+
+ msix_table_addr += PCI_MSIX_TBL_ENTRY_SIZE * index;
+ mmio_write32((uint32_t *)(msix_table_addr + PCI_MSIX_TBL_LO_ADDR),
+ 0xfee00000 | up_apic_cpu_id() << PCI_MSIX_APIC_ID_OFFSET);
+ mmio_write32((uint32_t *)(msix_table_addr + PCI_MSIX_TBL_HI_ADDR),
+ 0);
+ mmio_write32((uint32_t *)(msix_table_addr + PCI_MSIX_TBL_MSG_DATA),
+ vector);
+ mmio_write32((uint32_t *)(msix_table_addr + PCI_MSIX_TBL_VEC_CTL),
+ 0);
+
+ /* enable and unmask */
+
+ message_control &= ~PCI_MSIX_MCR_FMASK;
+
+ __qemu_pci_cfg_write(dev->bdf, cap + PCI_MSIX_MCR,
+ &message_control, PCI_MSIX_MCR_SIZE);
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: qemu_pci_msi_register
+ *
+ * Description:
+ * Map device MSI vectors to a platform IRQ vector
+ *
+ * Input Parameters:
+ * dev - Device
+ * vector - IRQ number of the platform
+ *
+ * Returned Value:
+ * <0: Mapping failed
+ * 0: Mapping succeed
+ *
+ ****************************************************************************/
+
+static int qemu_pci_msi_register(FAR struct pcie_dev_s *dev, uint16_t vector)
+{
+ uint16_t ctl;
+ uint16_t data;
+
+ int cap = pci_find_cap(dev, PCI_CAP_MSI);
+ if (cap < 0)
+ return -1;
+
+ uint32_t dest = 0xfee00000 | (up_apic_cpu_id() << PCI_MSI_APIC_ID_OFFSET);
+ __qemu_pci_cfg_write(dev->bdf, cap + PCI_MSI_MAR, &dest, PCI_MSI_MAR_SIZE);
+
+ __qemu_pci_cfg_read(dev->bdf, cap + PCI_MSI_MCR, &ctl, PCI_MSI_MCR_SIZE);
+ if ((ctl & PCI_MSI_MCR_64) == PCI_MSI_MCR_64)
+ {
+ uint32_t tmp = 0;
+ __qemu_pci_cfg_write(dev->bdf,
+ cap + PCI_MSI_MAR64_HI, &tmp,
+ PCI_MSI_MAR64_HI_SIZE);
+ data = cap + PCI_MSI_MDR64;
+ }
+ else
+ {
+ data = cap + PCI_MSI_MDR;
+ }
+
+ __qemu_pci_cfg_write(dev->bdf, data, &vector, PCI_MSI_MDR_SIZE);
+
+ __qemu_pci_cfg_write(dev->bdf, cap + PCI_MSI_MCR, &vector,
+ PCI_MSI_MCR_SIZE);
+
+ uint16_t tmp = PCI_MSI_MCR_EN;
+
+ __qemu_pci_cfg_write(dev->bdf, cap + PCI_MSI_MCR, &tmp, PCI_MSI_MCR_SIZE);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: qemu_pcie_init
+ *
+ * Description:
+ * Initialize the PCI-E bus *
+ *
+ ****************************************************************************/
+
+void qemu_pcie_init(void)
+{
+ pcie_initialize(&qemu_pcie_bus);
+}
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie_readwrite.h b/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie_readwrite.h
new file mode 100644
index 0000000000..01fc2712fe
--- /dev/null
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie_readwrite.h
@@ -0,0 +1,240 @@
+/****************************************************************************
+ * boards/x86_64/intel64/qemu-intel64/src/qemu_pcie_readwrite.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* The PCI-E Definitions and part of the access routines are taken from
+ * Jailhouse inmate library
+ *
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014
+ *
+ * Authors:
+ * Jan Kiszka <ja...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Alternatively, you can use or redistribute this file under the following
+ * BSD license:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __INCLUDE_NUTTX_PCIE_PCIE_READWRITE_H
+#define __INCLUDE_NUTTX_PCIE_PCIE_READWRITE_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+
+#include <nuttx/pcie/pcie.h>
+
+#include <nuttx/board.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define PCI_REG_ADDR_PORT 0xcf8
+#define PCI_REG_DATA_PORT 0xcfc
+
+#define PCI_CONE (1 << 31)
+
+/****************************************************************************
+ * Name: __qemu_pci_cfg_write
+ *
+ * Description:
+ * Write 8, 16, 32 bits data to PCI-E configuration space of device
+ * specified by dev
+ *
+ * Input Parameters:
+ * bfd - Device private data
+ * buffer - A pointer to the read-only buffer of data to be written
+ * size - The number of bytes to send from the buffer
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static inline int __qemu_pci_cfg_write(uint16_t bfd, uintptr_t addr,
+ FAR const void *buffer,
+ unsigned int size)
+{
+ if (!buffer)
+ return -EINVAL;
+
+ outl(PCI_CONE | ((uint32_t)bfd << 8) | (addr & 0xfc), PCI_REG_ADDR_PORT);
+
+ switch (size)
+ {
+ case 1:
+ outb(*(uint8_t *)(buffer), PCI_REG_DATA_PORT + (addr & 0x3));
+ break;
+ case 2:
+ outw(*(uint16_t *)(buffer), PCI_REG_DATA_PORT + (addr & 0x3));
+ break;
+ case 4:
+ outl(*(uint32_t *)(buffer), PCI_REG_DATA_PORT);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: __qemu_pci_cfg_write64
+ *
+ * Description:
+ * Write 64 bits data to PCI-E configuration space of device
+ * specified by dev
+ *
+ * Input Parameters:
+ * bfd - Device private data
+ * buffer - A pointer to the read-only buffer of data to be written
+ * size - The number of bytes to send from the buffer
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static inline int __qemu_pci_cfg_write64(uint16_t bfd, uintptr_t addr,
+ FAR const void *buffer,
+ unsigned int size)
+{
+ int ret;
+
+ if (!buffer)
+ return -EINVAL;
+
+ ret = __qemu_pci_cfg_write(bfd, addr + 4, buffer + 4, 4);
+ ret |= __qemu_pci_cfg_write(bfd, addr, buffer, 4);
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: __qemu_pci_cfg_read
+ *
+ * Description:
+ * Read 8, 16, 32 bits data from PCI-E configuration space of device
+ * specified by dev
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * buffer - A pointer to a buffer to receive the data from the device
+ * size - The requested number of bytes to be read
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static inline int __qemu_pci_cfg_read(uint16_t bfd, uintptr_t addr,
+ FAR void *buffer, unsigned int size)
+{
+ if (!buffer)
+ return -EINVAL;
+
+ outl(PCI_CONE | ((uint32_t)bfd << 8) | (addr & 0xfc), PCI_REG_ADDR_PORT);
+
+ switch (size)
+ {
+ case 1:
+ *(uint8_t *)(buffer) = inb(PCI_REG_DATA_PORT + (addr & 0x3));
+ break;
+ case 2:
+ *(uint16_t *)(buffer) = inw(PCI_REG_DATA_PORT + (addr & 0x3));
+ break;
+ case 4:
+ *(uint32_t *)(buffer) = inl(PCI_REG_DATA_PORT);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: __qemu_pci_cfg_read
+ *
+ * Description:
+ * Read 64 bits data from PCI-E configuration space of device
+ * specified by dev
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * buffer - A pointer to a buffer to receive the data from the device
+ * size - The requested number of bytes to be read
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+static inline int __qemu_pci_cfg_read64(uint16_t bfd,
+ uintptr_t addr,
+ FAR void *buffer,
+ unsigned int size)
+{
+ int ret;
+
+ if (!buffer)
+ return -EINVAL;
+
+ ret = __qemu_pci_cfg_read(bfd, addr + 4, buffer + 4, 4);
+ ret |= __qemu_pci_cfg_read(bfd, addr, buffer, 4);
+
+ return ret;
+}
+
+#endif /* __INCLUDE_NUTTX_PCIE_PCIE_READWRITE_H */