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 <[email protected]> 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 <[email protected]> + * + * 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 <[email protected]> + * + * 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 */
