You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/01/25 17:09:39 UTC
(nuttx) branch master updated (204f4a18a0 -> a12fdd8876)
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
from 204f4a18a0 Support to ARP Address Conflict Detection
new 18f97bf2f8 pcie: add framework
new 69ed5bb67d Various fixes for PCI work
new 0ed4123326 x86_64: Early framebuffer console
new 50f7e96e5e boards/x86_64: refresh earlyfb and pcitest configurations
new 2e758f33ee fix various compilation errors after pci code rebase
new a12fdd8876 cosmetic changes after pci code rebase
The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../x86_64/qemu/boards/qemu-intel64/index.rst | 27 +
Kconfig | 34 +
arch/x86_64/Kconfig | 20 +-
arch/x86_64/src/common/x86_64_internal.h | 8 +-
arch/x86_64/src/intel64/Make.defs | 4 +
arch/x86_64/src/intel64/intel64_createstack.c | 2 +-
arch/x86_64/src/intel64/intel64_head.S | 14 +-
arch/x86_64/src/intel64/intel64_lowsetup.c | 62 ++
arch/x86_64/src/intel64/intel64_mbfb.c | 350 +++++++++
arch/x86_64/src/intel64/intel64_serial.c | 13 +-
boards/x86_64/intel64/qemu-intel64/Kconfig | 8 +
.../intel64/qemu-intel64/configs/earlyfb/defconfig | 65 ++
.../intel64/qemu-intel64/configs/pcitest/defconfig | 70 ++
boards/x86_64/intel64/qemu-intel64/src/Makefile | 4 +
.../x86_64/intel64/qemu-intel64/src/qemu_bringup.c | 5 +
.../x86_64/intel64/qemu-intel64/src/qemu_intel64.h | 2 +
boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c | 229 ++++++
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/pci/Kconfig | 11 +
.../src/Makefile => drivers/pci/Make.defs | 15 +-
drivers/pci/pci.c | 832 +++++++++++++++++++++
drivers/virt/Kconfig | 29 +
.../src/Makefile => drivers/virt/Make.defs | 26 +-
drivers/virt/qemu_edu.c | 470 ++++++++++++
drivers/virt/qemu_pci_test.c | 274 +++++++
include/debug.h | 18 +
include/nuttx/pci/pci.h | 472 ++++++++++++
.../nuttx/virt/qemu_pci.h | 46 +-
29 files changed, 3063 insertions(+), 51 deletions(-)
create mode 100644 arch/x86_64/src/intel64/intel64_mbfb.c
create mode 100644 boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig
create mode 100644 boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
create mode 100644 boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
create mode 100644 drivers/pci/Kconfig
copy boards/x86_64/intel64/qemu-intel64/src/Makefile => drivers/pci/Make.defs (80%)
create mode 100644 drivers/pci/pci.c
create mode 100644 drivers/virt/Kconfig
copy boards/x86_64/intel64/qemu-intel64/src/Makefile => drivers/virt/Make.defs (74%)
create mode 100644 drivers/virt/qemu_edu.c
create mode 100644 drivers/virt/qemu_pci_test.c
create mode 100644 include/nuttx/pci/pci.h
copy boards/x86_64/intel64/qemu-intel64/src/qemu_bringup.c => include/nuttx/virt/qemu_pci.h (66%)
(nuttx) 01/06: pcie: add framework
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 18f97bf2f8f88fe41b77b2ffee8ffb3447ef98fa
Author: Yang Chung-Fan <so...@gmail.com>
AuthorDate: Mon May 4 18:44:11 2020 +0900
pcie: add framework
Squashed commits:
1. x86_64: qemu: implement pci-e functions and enumerate pci-e devices on boot
2. virt: add qemu pci-testdev driver
3. pcie: types array should be null terminated
4. pcie: enable don't take flags, hardcoded enabling flags
5. pcie: checking bar > 4 for 64bit bars are sufficient
6. pcie: qemu: remove not used header
7. pcie: qemu: return -EINVAL if buffer argument is NULL
8. pcie: make pcie enumerate routine as common instead of architecture dependent
9. pcie: cosmetic changes to fit check tools
10. pcie: create MSI/MSIX related marcos and simplify the msi/msix routines
---
Kconfig | 35 ++
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 +++++++++++
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/pcie/Kconfig | 20 +
.../src/Makefile => drivers/pcie/Make.defs | 21 +-
drivers/pcie/pcie_root.c | 446 +++++++++++++++++++++
drivers/virt/Kconfig | 22 +
.../src/Makefile => drivers/virt/Make.defs | 24 +-
drivers/virt/qemu_pci_test.c | 130 ++++++
include/debug.h | 18 +
include/nuttx/pcie/pcie.h | 352 ++++++++++++++++
.../board.h => include/nuttx/virt/qemu_pci.h | 44 +-
18 files changed, 1724 insertions(+), 50 deletions(-)
diff --git a/Kconfig b/Kconfig
index 603c6f924d..a0d8b941c5 100644
--- a/Kconfig
+++ b/Kconfig
@@ -2196,6 +2196,41 @@ config DEBUG_IPC_INFO
endif # DEBUG_IPC
+=======
+config DEBUG_PCIE
+ bool "PCI-E Debug Features"
+ default n
+ depends on PCIE
+ ---help---
+ Enable PCIE driver debug features.
+
+ Support for this debug option is architecture-specific and may not
+ be available for some MCUs.
+
+if DEBUG_PCIE
+
+config DEBUG_PCIE_ERROR
+ bool "PCI-E Error Output"
+ default n
+ depends on DEBUG_ERROR
+ ---help---
+ Enable PCI-E driver error output to SYSLOG.
+
+config DEBUG_PCIE_WARN
+ bool "PCI-E Warnings Output"
+ default n
+ depends on DEBUG_WARN
+ ---help---
+ Enable PCI-E driver warning output to SYSLOG.
+
+config DEBUG_PCIE_INFO
+ bool "PCI-E Informational Output"
+ default n
+ depends on DEBUG_INFO
+ ---help---
+ Enable PCI-E driver informational output to SYSLOG.
+
+endif # DEBUG_PCIE
endif # DEBUG_FEATURES
config ARCH_HAVE_STACKCHECK
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 */
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 328b726641..da93ca190f 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -59,3 +59,5 @@ source "drivers/usrsock/Kconfig"
source "drivers/dma/Kconfig"
source "drivers/devicetree/Kconfig"
source "drivers/reset/Kconfig"
+source "drivers/pcie/Kconfig"
+source "drivers/virt/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 197ceb3215..f5584c5370 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -77,6 +77,8 @@ include rc/Make.defs
include segger/Make.defs
include usrsock/Make.defs
include reset/Make.defs
+include pcie/Make.defs
+include virt/Make.defs
ifeq ($(CONFIG_SPECIFIC_DRIVERS),y)
-include platform/Make.defs
diff --git a/drivers/pcie/Kconfig b/drivers/pcie/Kconfig
new file mode 100644
index 0000000000..7ac9db568b
--- /dev/null
+++ b/drivers/pcie/Kconfig
@@ -0,0 +1,20 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menuconfig PCIE
+ bool "Support for PCI-E Bus"
+ default n
+ ---help---
+ Enables support for the PCI-E bus.
+ Backend bust be provided by per-arch or per-board implementation..
+
+if PCIE
+config PCIE_MAX_BDF
+ hex "Maximum bdf to scan on PCI-E bus"
+ default 0x10000
+ ---help---
+ The maximum bdf number to be scaned on PCI-E bus
+
+endif
diff --git a/boards/x86_64/intel64/qemu-intel64/src/Makefile b/drivers/pcie/Make.defs
similarity index 75%
copy from boards/x86_64/intel64/qemu-intel64/src/Makefile
copy to drivers/pcie/Make.defs
index 7bdacd1f3c..68efee8123 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/Makefile
+++ b/drivers/pcie/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# boards/x86_64/intel64/qemu-intel64/src/Makefile
+# drivers/pcie/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -7,9 +7,9 @@
# 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
@@ -18,12 +18,15 @@
#
############################################################################
-include $(TOPDIR)/Make.defs
+# Don't build anything if there is no CAN support
-CSRCS = qemu_boot.c qemu_bringup.c qemu_freq.c qemu_net.c
+ifeq ($(CONFIG_PCIE),y)
-ifeq ($(CONFIG_BOARDCTL),y)
- CSRCS += qemu_appinit.c
-endif
+CSRCS += pcie_root.c
-include $(TOPDIR)/boards/Board.mk
+# Include PCIE device driver build support
+
+DEPPATH += --dep-path pcie
+VPATH += :pcie
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)pcie}
+endif
diff --git a/drivers/pcie/pcie_root.c b/drivers/pcie/pcie_root.c
new file mode 100644
index 0000000000..b85c5862fa
--- /dev/null
+++ b/drivers/pcie/pcie_root.c
@@ -0,0 +1,446 @@
+/****************************************************************************
+ * nuttx/drivers/pcie/pcie_root.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/pcie/pcie.h>
+#include <nuttx/virt/qemu_pci.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+struct pcie_dev_type_s *pci_device_types[] =
+{
+#ifdef CONFIG_VIRT_QEMU_PCI_TEST
+ &pcie_type_qemu_pci_test,
+#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
+ NULL,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pci_enumerate
+ *
+ * Description:
+ * Scan the PCI bus and enumerate the devices.
+ * Initialize any recognized devices, given in types.
+ *
+ * Input Parameters:
+ * bus - PCI-E bus structure
+ * type - List of pointers to devices types recognized, NULL terminated
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_enumerate(FAR struct pcie_bus_s *bus,
+ FAR struct pcie_dev_type_s **types)
+{
+ unsigned int bdf;
+ uint16_t vid;
+ uint16_t id;
+ uint16_t rev;
+ struct pcie_dev_s tmp_dev;
+ struct pcie_dev_type_s tmp_type =
+ {
+ .name = "Unknown",
+ .vendor = PCI_ID_ANY,
+ .device = PCI_ID_ANY,
+ .class_rev = PCI_ID_ANY,
+ .probe = NULL,
+ };
+
+ if (!bus)
+ return -EINVAL;
+ if (!types)
+ return -EINVAL;
+
+ for (bdf = 0; bdf < CONFIG_PCIE_MAX_BDF; bdf++)
+ {
+ tmp_dev.bus = bus;
+ tmp_dev.type = &tmp_type;
+ tmp_dev.bdf = bdf;
+
+ bus->ops->pci_cfg_read(&tmp_dev, PCI_CFG_VENDOR_ID, &vid, 2);
+ bus->ops->pci_cfg_read(&tmp_dev, PCI_CFG_DEVICE_ID, &id, 2);
+ bus->ops->pci_cfg_read(&tmp_dev, PCI_CFG_REVERSION, &rev, 2);
+
+ if (vid == PCI_ID_ANY)
+ continue;
+
+ pciinfo("[%02x:%02x.%x] Found %04x:%04x, class/reversion %08x\n",
+ bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3,
+ vid, id, rev);
+
+ for (int i = 0; types[i] != NULL; i++)
+ {
+ if (types[i]->vendor == PCI_ID_ANY ||
+ types[i]->vendor == vid)
+ {
+ if (types[i]->device == PCI_ID_ANY ||
+ types[i]->device == id)
+ {
+ if (types[i]->class_rev == PCI_ID_ANY ||
+ types[i]->class_rev == rev)
+ {
+ if (types[i]->probe)
+ {
+ pciinfo("[%02x:%02x.%x] %s\n",
+ bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3,
+ types[i]->name);
+ types[i]->probe(bus, types[i], bdf);
+ }
+ else
+ {
+ pcierr("[%02x:%02x.%x] Error: Invalid \
+ device probe function\n",
+ bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pcie_initialize
+ *
+ * Description:
+ * Initialize the PCI-E bus and enumerate the devices with give devices
+ * type array
+ *
+ * Input Parameters:
+ * bus - An PCIE bus
+ * types - A array of PCIE device types
+ * num - Number of device types
+ *
+ * Returned Value:
+ * OK if the driver was successfully register; A negated errno value is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+int pcie_initialize(FAR struct pcie_bus_s *bus)
+{
+ return pci_enumerate(bus, pci_device_types);
+}
+
+/****************************************************************************
+ * Name: pci_enable_device
+ *
+ * Description:
+ * Enable device with MMIO
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_enable_device(FAR struct pcie_dev_s *dev)
+{
+ uint16_t old_cmd;
+ uint16_t cmd;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_COMMAND, &old_cmd, 2);
+
+ cmd = old_cmd | (PCI_CMD_MASTER | PCI_CMD_MEM);
+
+ dev->bus->ops->pci_cfg_write(dev, PCI_CFG_COMMAND, &cmd, 2);
+
+ pciinfo("%02x:%02x.%x, CMD: %x -> %x\n",
+ dev->bdf >> 8, (dev->bdf >> 3) & 0x1f, dev->bdf & 0x3,
+ old_cmd, cmd);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_find_cap
+ *
+ * Description:
+ * Search through the PCI-e device capability list to find given capability.
+ *
+ * Input Parameters:
+ * dev - Device
+ * cap - Bitmask of capability
+ *
+ * Returned Value:
+ * -1: Capability not supported
+ * other: the offset in PCI configuration space to the capability structure
+ *
+ ****************************************************************************/
+
+int pci_find_cap(FAR struct pcie_dev_s *dev, uint16_t cap)
+{
+ uint8_t pos = PCI_CFG_CAP_PTR - 1;
+ uint16_t status;
+ uint8_t rcap;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_STATUS, &status, 2);
+
+ if (!(status & PCI_STS_CAPS))
+ return -EINVAL;
+
+ while (1)
+ {
+ dev->bus->ops->pci_cfg_read(dev, pos + 1, &pos, 1);
+ if (pos == 0)
+ return -EINVAL;
+
+ dev->bus->ops->pci_cfg_read(dev, pos, &rcap, 1);
+
+ if (rcap == cap)
+ return pos;
+ }
+}
+
+/****************************************************************************
+ * Name: pci_get_bar
+ *
+ * Description:
+ * Get a 32 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * ret - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_get_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint32_t *ret)
+{
+ if (bar > 5)
+ return -EINVAL;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, ret, 4);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_get_bar64
+ *
+ * Description:
+ * Get a 64 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * ret - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_get_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint64_t *ret)
+{
+ if (bar > 4 || ((bar % 2) != 0))
+ return -EINVAL;
+
+ uint32_t barmem1;
+ uint32_t barmem2;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4);
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4);
+
+ *ret = ((uint64_t)barmem2 << 32) | barmem1;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_set_bar
+ *
+ * Description:
+ * Set a 32 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * val - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_set_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint32_t val)
+{
+ if (bar > 5)
+ return -EINVAL;
+
+ dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4, &val, 4);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_set_bar64
+ *
+ * Description:
+ * Set a 64 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * val - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_set_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint64_t val)
+{
+ if (bar > 4 || ((bar % 2) != 0))
+ return -EINVAL;
+
+ uint32_t barmem1 = (uint32_t)val;
+ uint32_t barmem2 = (uint32_t)(val >> 32);
+
+ dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4);
+ dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4);
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_map_bar
+ *
+ * Description:
+ * Map address in a 32 bits bar in the flat memory address space
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * length - Map length, multiple of PAGE_SIZE
+ * ret - Bar Content if not NULL
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
+ unsigned long length, uint32_t *ret)
+{
+ if (bar > 5)
+ return -EINVAL;
+
+ uint32_t barmem;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem, 4);
+
+ if (((bar % 2) == 0 &&
+ (barmem & PCI_BAR_64BIT) == PCI_BAR_64BIT) ||
+ (barmem & PCI_BAR_IO) == PCI_BAR_IO)
+ return -EINVAL;
+
+ if (!dev->bus->ops->pci_map_bar)
+ return -EINVAL;
+
+ dev->bus->ops->pci_map_bar(dev, barmem, length);
+
+ if (ret)
+ *ret = barmem;
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_map_bar64
+ *
+ * Description:
+ * Map address in a 64 bits bar in the flat memory address space
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * length - Map length, multiple of PAGE_SIZE
+ * ret - Bar Content if not NULL
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_map_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
+ unsigned long length, uint64_t *ret)
+{
+ if (bar > 4 || ((bar % 2) != 0))
+ return -EINVAL;
+
+ uint32_t barmem1;
+ uint32_t barmem2;
+ uint64_t barmem;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4);
+
+ if ((barmem1 & PCI_BAR_64BIT) != PCI_BAR_64BIT ||
+ (barmem1 & PCI_BAR_IO) == PCI_BAR_IO)
+ return -EINVAL;
+
+ dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4);
+
+ barmem = ((uint64_t)barmem2 << 32) | barmem1;
+
+ if (!dev->bus->ops->pci_map_bar64)
+ return -EINVAL;
+
+ dev->bus->ops->pci_map_bar64(dev, barmem, length);
+
+ if (ret)
+ *ret = barmem;
+
+ return OK;
+}
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
new file mode 100644
index 0000000000..bf8fb8591c
--- /dev/null
+++ b/drivers/virt/Kconfig
@@ -0,0 +1,22 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+#
+#
+menuconfig VIRT
+ bool "Virtualization"
+ default n
+ ---help---
+ Drivers for virtualized and emulated devices
+
+if VIRT
+
+config VIRT_QEMU_PCI_TEST
+ bool "Driver for QEMU PCI test device"
+ default n
+ select PCIE
+ ---help---
+ Driver for QEMU PCI test device
+
+endif # VIRT
diff --git a/boards/x86_64/intel64/qemu-intel64/src/Makefile b/drivers/virt/Make.defs
similarity index 73%
copy from boards/x86_64/intel64/qemu-intel64/src/Makefile
copy to drivers/virt/Make.defs
index 7bdacd1f3c..8ccfbe06c5 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/Makefile
+++ b/drivers/virt/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# boards/x86_64/intel64/qemu-intel64/src/Makefile
+# drivers/pcie/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -7,9 +7,9 @@
# 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
@@ -18,12 +18,20 @@
#
############################################################################
-include $(TOPDIR)/Make.defs
+# Don't build anything if there is no CAN support
-CSRCS = qemu_boot.c qemu_bringup.c qemu_freq.c qemu_net.c
+ifeq ($(CONFIG_VIRT_QEMU_PCI_TEST),y)
+
+CSRCS += qemu_pci_test.c
-ifeq ($(CONFIG_BOARDCTL),y)
- CSRCS += qemu_appinit.c
endif
-include $(TOPDIR)/boards/Board.mk
+# Include virt device driver build support
+#
+ifeq ($(CONFIG_VIRT),y)
+
+DEPPATH += --dep-path virt
+VPATH += :virt
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)virt}
+
+endif
diff --git a/drivers/virt/qemu_pci_test.c b/drivers/virt/qemu_pci_test.c
new file mode 100644
index 0000000000..d0df753121
--- /dev/null
+++ b/drivers/virt/qemu_pci_test.c
@@ -0,0 +1,130 @@
+/*****************************************************************************
+ * drivers/virt/qemu_pci_test.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.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+
+#include <nuttx/pcie/pcie.h>
+#include <nuttx/virt/qemu_pci.h>
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+struct pci_test_dev_hdr_s
+{
+ volatile uint8_t test; /* write-only, starts a given test number */
+ volatile uint8_t width_type; /* read-only, type and width of access for a given test.
+ * 1,2,4 for byte,word or long write.
+ * any other value if test not supported on this BAR */
+ volatile uint8_t pad0[2];
+ volatile uint32_t offset; /* read-only, offset in this BAR for a given test */
+ volatile uint32_t data; /* read-only, data to use for a given test */
+ volatile uint32_t count; /* for debugging. number of writes detected. */
+ volatile uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
+};
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: qemu_pci_test_probe
+ *
+ * Description:
+ * Initialize device
+ *****************************************************************************/
+
+int qemu_pci_test_probe(FAR struct pcie_bus_s *bus,
+ FAR struct pcie_dev_type_s *type, uint16_t bdf)
+{
+ uint32_t bar[2];
+ struct pcie_dev_s dev =
+ {
+ .bus = bus,
+ .type = type,
+ .bdf = bdf,
+ };
+
+ pci_enable_device(&dev);
+
+ for (int ii = 0; ii < 2; ii++)
+ {
+ pci_get_bar(&dev, ii, bar + ii);
+
+ if ((bar[ii] & PCI_BAR_IO) != PCI_BAR_IO)
+ {
+ pciinfo("Mapping BAR%d: %x\n", ii, bar[ii]);
+
+ pci_map_bar(&dev, ii, 0x1000, NULL);
+
+ struct pci_test_dev_hdr_s *ptr =
+ (struct pci_test_dev_hdr_s *)(uintptr_t)bar[ii];
+
+ int i = 0;
+ while (1)
+ {
+ ptr->test = i;
+
+ if (ptr->width_type != 1 &&
+ ptr->width_type != 2 &&
+ ptr->width_type != 4)
+ break;
+
+ pciinfo("Test[%d] Size:%d %s\n",
+ i, ptr->width_type,
+ ptr->name);
+
+ i++;
+ }
+ }
+ }
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+struct pcie_dev_type_s pcie_type_qemu_pci_test =
+{
+ .vendor = 0x1b36,
+ .device = 0x0005,
+ .class_rev = PCI_ID_ANY,
+ .name = "Qemu PCI test device",
+ .probe = qemu_pci_test_probe
+};
diff --git a/include/debug.h b/include/debug.h
index e6b9163cd7..955ddf6e2c 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -920,6 +920,24 @@
# define ipcinfo _none
#endif
+#ifdef CONFIG_DEBUG_PCIE_ERROR
+# define pcierr _err
+#else
+# define pcierr _none
+#endif
+
+#ifdef CONFIG_DEBUG_PCIE_WARN
+# define pciwarn _warn
+#else
+# define pciwarn _none
+#endif
+
+#ifdef CONFIG_DEBUG_PCIE_INFO
+# define pciinfo _info
+#else
+# define pciinfo _none
+#endif
+
/* Buffer dumping macros do not depend on varargs */
#ifdef CONFIG_DEBUG_ERROR
diff --git a/include/nuttx/pcie/pcie.h b/include/nuttx/pcie/pcie.h
new file mode 100644
index 0000000000..fffc791a2d
--- /dev/null
+++ b/include/nuttx/pcie/pcie.h
@@ -0,0 +1,352 @@
+/****************************************************************************
+ * include/nuttx/pcie/pcie.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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_PCIE_PCIE_H
+#define __INCLUDE_NUTTX_PCIE_PCIE_H
+
+#ifdef CONFIG_PCIE
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <nuttx/fs/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define PCI_CFG_VENDOR_ID 0x000
+#define PCI_CFG_DEVICE_ID 0x002
+#define PCI_CFG_COMMAND 0x004
+# define PCI_CMD_IO (1 << 0)
+# define PCI_CMD_MEM (1 << 1)
+# define PCI_CMD_MASTER (1 << 2)
+# define PCI_CMD_INTX_OFF (1 << 10)
+#define PCI_CFG_STATUS 0x006
+# define PCI_STS_INT (1 << 3)
+# define PCI_STS_CAPS (1 << 4)
+#define PCI_CFG_REVERSION 0x008
+#define PCI_CFG_BAR 0x010
+# define PCI_BAR_IO 0x1
+# define PCI_BAR_1M 0x2
+# define PCI_BAR_64BIT 0x4
+#define PCI_CFG_CAP_PTR 0x034
+
+#define PCI_ID_ANY 0xffff
+#define PCI_DEV_CLASS_OTHER 0xff
+
+#define PCI_CAP_PM 0x01
+
+#define PCI_CAP_MSI 0x05
+# define PCI_MSI_MCR 0x02
+# define PCI_MSI_MCR_SIZE 2
+# define PCI_MSI_MCR_EN (1 << 0)
+# define PCI_MSI_MCR_64 (1 << 7)
+# define PCI_MSI_MAR 0x04
+# define PCI_MSI_MAR_SIZE 4
+# define PCI_MSI_MDR 0x08
+# define PCI_MSI_MDR_SIZE 2
+# define PCI_MSI_MAR64_HI 0x08
+# define PCI_MSI_MAR64_HI_SIZE 4
+# define PCI_MSI_MDR64 0x0c
+# define PCI_MSI_MDR64_SIZE 2
+# define PCI_MSI_APIC_ID_OFFSET 0xc
+
+#define PCI_CAP_MSIX 0x11
+# define PCI_MSIX_MCR 0x02
+# define PCI_MSIX_MCR_SIZE 2
+# define PCI_MSIX_MCR_EN (1 << 15)
+# define PCI_MSIX_MCR_FMASK 0x4000
+# define PCI_MSIX_MCR_TBL_MASK 0x03ff
+# define PCI_MSIX_TBL 0x04
+# define PCI_MSIX_TBL_SIZE 4
+# define PCI_MSIX_PBA 0x08
+# define PCI_MSIX_PBA_SIZE 4
+# define PCI_MSIX_BIR_MASK 0x07
+# define PCI_MSIX_TBL_ENTRY_SIZE 0x10
+# define PCI_MSIX_TBL_LO_ADDR 0x0
+# define PCI_MSIX_TBL_HI_ADDR 0x4
+# define PCI_MSIX_TBL_MSG_DATA 0x8
+# define PCI_MSIX_TBL_VEC_CTL 0xc
+# define PCI_MSIX_APIC_ID_OFFSET 0xc
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* The PCIE driver interface */
+
+struct pcie_bus_s;
+struct pcie_dev_type_s;
+struct pcie_dev_s;
+
+/* Bus related operations */
+
+struct pcie_bus_ops_s
+{
+ CODE int (*pcie_enumerate)(FAR struct pcie_bus_s *bus,
+ FAR struct pcie_dev_type_s **types);
+
+ CODE int (*pci_cfg_write)(FAR struct pcie_dev_s *dev, uintptr_t addr,
+ FAR const void *buffer, unsigned int size);
+
+ CODE int (*pci_cfg_read)(FAR struct pcie_dev_s *dev, uintptr_t addr,
+ FAR void *buffer, unsigned int size);
+
+ CODE int (*pci_map_bar)(FAR struct pcie_dev_s *dev, uint32_t addr,
+ unsigned long length);
+
+ CODE int (*pci_map_bar64)(FAR struct pcie_dev_s *dev, uint64_t addr,
+ unsigned long length);
+
+ CODE int (*pci_msi_register)(FAR struct pcie_dev_s *dev,
+ uint16_t vector);
+
+ CODE int (*pci_msix_register)(FAR struct pcie_dev_s *dev,
+ uint32_t vector, uint32_t index);
+};
+
+/* PCIE bus private data. */
+
+struct pcie_bus_s
+{
+ FAR const struct pcie_bus_ops_s *ops; /* operations */
+};
+
+/* PCIE device type, defines by vendor ID and device ID */
+
+struct pcie_dev_type_s
+{
+ uint16_t vendor; /* Device vendor ID */
+ uint16_t device; /* Device ID */
+ uint32_t class_rev; /* Device reversion */
+ const char *name; /* Human readable name */
+
+ /* Call back function when a device is probed */
+
+ CODE int (*probe)(FAR struct pcie_bus_s *bus,
+ FAR struct pcie_dev_type_s *type, uint16_t bdf);
+};
+
+/* PCIE device private data. */
+
+struct pcie_dev_s
+{
+ FAR struct pcie_bus_s *bus;
+ FAR struct pcie_dev_type_s *type;
+ uint16_t bdf;
+};
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: pcie_initialize
+ *
+ * Description:
+ * Initialize the PCI-E bus and enumerate the devices with give devices
+ * type array
+ *
+ * Input Parameters:
+ * bus - An PCIE bus
+ * types - A array of PCIE device types
+ * num - Number of device types
+ *
+ * Returned Value:
+ * OK if the driver was successfully register; A negated errno value is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+int pcie_initialize(FAR struct pcie_bus_s *bus);
+
+/****************************************************************************
+ * Name: pci_enable_device
+ *
+ * Description:
+ * Enable device with MMIO
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_enable_device(FAR struct pcie_dev_s *dev);
+
+/****************************************************************************
+ * Name: pci_find_cap
+ *
+ * Description:
+ * Search through the PCI-e device capability list to find given capability.
+ *
+ * Input Parameters:
+ * dev - Device
+ * cap - Bitmask of capability
+ *
+ * Returned Value:
+ * -1: Capability not supported
+ * other: the offset in PCI configuration space to the capability structure
+ *
+ ****************************************************************************/
+
+int pci_find_cap(FAR struct pcie_dev_s *dev, uint16_t cap);
+
+/****************************************************************************
+ * Name: pci_map_bar
+ *
+ * Description:
+ * Map address in a 32 bits bar in the flat memory address space
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * length - Map length, multiple of PAGE_SIZE
+ * ret - Bar Contentif not NULL
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
+ unsigned long length, uint32_t *ret);
+
+/****************************************************************************
+ * Name: pci_map_bar64
+ *
+ * Description:
+ * Map address in a 64 bits bar in the flat memory address space
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * length - Map length, multiple of PAGE_SIZE
+ * ret - Bar Content if not NULL
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_map_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
+ unsigned long length, uint64_t *ret);
+
+/****************************************************************************
+ * Name: pci_get_bar
+ *
+ * Description:
+ * Get a 32 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * ret - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_get_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint32_t *ret);
+
+/****************************************************************************
+ * Name: pci_get_bar64
+ *
+ * Description:
+ * Get a 64 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * ret - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_get_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint64_t *ret);
+
+/****************************************************************************
+ * Name: pci_set_bar
+ *
+ * Description:
+ * Set a 32 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * val - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_set_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint32_t val);
+
+/****************************************************************************
+ * Name: pci_set_bar64
+ *
+ * Description:
+ * Set a 64 bits bar
+ *
+ * Input Parameters:
+ * dev - Device private data
+ * bar - Bar number
+ * val - Bar Content
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_set_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
+ uint64_t val);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif
+#endif /* __INCLUDE_NUTTX_I2C_I2C_MASTER_H */
diff --git a/boards/x86_64/intel64/qemu-intel64/include/board.h b/include/nuttx/virt/qemu_pci.h
similarity index 52%
copy from boards/x86_64/intel64/qemu-intel64/include/board.h
copy to include/nuttx/virt/qemu_pci.h
index 9cb23e995b..f8e38f9241 100644
--- a/boards/x86_64/intel64/qemu-intel64/include/board.h
+++ b/include/nuttx/virt/qemu_pci.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * boards/x86_64/intel64/qemu-intel64/include/board.h
+ * include/nuttx/serial/uart_mcs99xx.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,8 +18,8 @@
*
****************************************************************************/
-#ifndef __BOARDS_X86_64_INTEL64_QEMU_INTEL64_INCLUDE_BOARD_H
-#define __BOARDS_X86_64_INTEL64_QEMU_INTEL64_INCLUDE_BOARD_H
+#ifndef __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H
+#define __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H
/****************************************************************************
* Included Files
@@ -27,34 +27,13 @@
#include <nuttx/config.h>
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/* Clocking *****************************************************************/
-
-/* Programmable interval timer (PIT) */
-
-#define PIT_CLOCK 1041816 /* PIT input clock */
-
-/* LED definitions **********************************************************/
-
-/* Button definitions *******************************************************/
-
-/* Alternate pin selections *************************************************/
+#include <stdbool.h>
/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-#ifndef __ASSEMBLY__
-
-/****************************************************************************
- * Public Data
+ * Public Function Prototypes
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
+#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
@@ -62,14 +41,13 @@ extern "C"
#define EXTERN extern
#endif
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
+#ifdef CONFIG_VIRT_QEMU_PCI_TEST
+extern struct pcie_dev_type_s pcie_type_qemu_pci_test;
+#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
#undef EXTERN
-#if defined(__cplusplus)
+#ifdef __cplusplus
}
#endif
-#endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_X86_64_INTEL64_QEMU_INTEL64_INCLUDE_BOARD_H */
+#endif /* __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H */
(nuttx) 05/06: fix various compilation errors after pci code rebase
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2e758f33eea5e8dcd38f6e37061e53a3b6e076de
Author: raiden00pl <ra...@railab.me>
AuthorDate: Mon Jan 22 10:40:16 2024 +0100
fix various compilation errors after pci code rebase
---
arch/x86_64/Kconfig | 1 +
arch/x86_64/src/intel64/Make.defs | 2 +-
arch/x86_64/src/intel64/intel64_createstack.c | 2 +-
arch/x86_64/src/intel64/intel64_lowsetup.c | 14 ++++++++++++++
arch/x86_64/src/intel64/intel64_mbfb.c | 2 +-
arch/x86_64/src/intel64/intel64_serial.c | 17 ++++++++++-------
.../intel64/qemu-intel64/configs/pcitest/defconfig | 1 +
boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c | 3 +--
drivers/virt/qemu_edu.c | 1 +
drivers/virt/qemu_pci_test.c | 1 +
10 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 5e1115ad0e..556f3d01e3 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -71,6 +71,7 @@ config ARCH_MULTIBOOT2
system to enable certain features like the low level framebuffer.
if ARCH_MULTIBOOT2
+
config MULTBOOT2_FB_TERM
bool "Multiboot2 framebuffer terminal"
default n
diff --git a/arch/x86_64/src/intel64/Make.defs b/arch/x86_64/src/intel64/Make.defs
index c2d6db49aa..7274d01e6b 100644
--- a/arch/x86_64/src/intel64/Make.defs
+++ b/arch/x86_64/src/intel64/Make.defs
@@ -38,7 +38,7 @@ CHIP_CSRCS += intel64_serial.c intel64_rng.c intel64_check_capability.c
# Configuration-dependent intel64 files
-ifeq ($(CONFIG_ARCH_MULTIBOOT2),y)
+ifeq ($(CONFIG_MULTBOOT2_FB_TERM),y)
CHIP_CSRCS += intel64_mbfb.c
endif
diff --git a/arch/x86_64/src/intel64/intel64_createstack.c b/arch/x86_64/src/intel64/intel64_createstack.c
index 6649cb06c8..f95086f5ff 100644
--- a/arch/x86_64/src/intel64/intel64_createstack.c
+++ b/arch/x86_64/src/intel64/intel64_createstack.c
@@ -161,7 +161,7 @@ int up_create_stack(struct tcb_s *tcb, size_t stack_size, uint8_t ttype)
if (!tcb->stack_alloc_ptr)
{
- serr("ERROR: Failed to allocate stack, size %d\n", stack_size);
+ serr("ERROR: Failed to allocate stack, size %zu\n", stack_size);
}
#endif
}
diff --git a/arch/x86_64/src/intel64/intel64_lowsetup.c b/arch/x86_64/src/intel64/intel64_lowsetup.c
index 988a9523ff..d28d7f6dcc 100644
--- a/arch/x86_64/src/intel64/intel64_lowsetup.c
+++ b/arch/x86_64/src/intel64/intel64_lowsetup.c
@@ -62,6 +62,15 @@ uint32_t mb_info_struct __attribute__((section(".loader.bss")));
* Private Functions
****************************************************************************/
+#ifdef CONFIG_ARCH_MULTIBOOT2
+/****************************************************************************
+ * Name: x86_64_mb2_config
+ *
+ * Description:
+ * Parse multiboot2 info.
+ *
+ ****************************************************************************/
+
static void x86_64_mb2_config(void)
{
struct multiboot_tag *tag;
@@ -82,18 +91,21 @@ static void x86_64_mb2_config(void)
break;
}
+#ifdef CONFIG_MULTBOOT2_FB_TERM
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
{
x86_64_mb2_fbinitialize(
(struct multiboot_tag_framebuffer *)tag);
break;
}
+#endif
default:
break;
}
}
}
+#endif
/****************************************************************************
* Public Functions
@@ -133,9 +145,11 @@ void up_lowsetup(void)
x86_64_check_and_enable_capability();
+#ifdef CONFIG_ARCH_MULTIBOOT2
/* Handle multiboot2 info */
x86_64_mb2_config();
+#endif
/* Revoke the lower memory */
diff --git a/arch/x86_64/src/intel64/intel64_mbfb.c b/arch/x86_64/src/intel64/intel64_mbfb.c
index f536cffb35..0aacba8be2 100644
--- a/arch/x86_64/src/intel64/intel64_mbfb.c
+++ b/arch/x86_64/src/intel64/intel64_mbfb.c
@@ -34,7 +34,7 @@
#include <nuttx/nx/nxfonts.h>
#endif
-#include "up_internal.h"
+#include "x86_64_internal.h"
/****************************************************************************
* Pre-processor Definitions
diff --git a/arch/x86_64/src/intel64/intel64_serial.c b/arch/x86_64/src/intel64/intel64_serial.c
index dffd6304c9..d8fe7e81ee 100644
--- a/arch/x86_64/src/intel64/intel64_serial.c
+++ b/arch/x86_64/src/intel64/intel64_serial.c
@@ -82,6 +82,11 @@ void uart_putreg(uart_addrwidth_t base, unsigned int offset,
*
****************************************************************************/
+void up_lowputc(char ch)
+{
+ fb_putc(ch);
+}
+
int up_putc(int ch)
{
/* Check for LF */
@@ -90,19 +95,16 @@ int up_putc(int ch)
{
/* Add CR */
- x86_64_lowputc('\r');
+ up_lowputc('\r');
}
- x86_64_lowputc(ch);
+ up_lowputc(ch);
return ch;
}
-
-void up_lowputc(char ch)
-{
- fb_putc(ch);
-}
#endif /* USE_SERIALDRIVER */
+#ifdef USE_EARLYSERIALINIT
+
void x86_64_earlyserialinit(void)
{
u16550_earlyserialinit();
@@ -112,3 +114,4 @@ void x86_64_serialinit(void)
{
u16550_serialinit();
}
+#endif
diff --git a/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig b/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
index 17f6e7cc8a..000ed38c84 100644
--- a/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
+++ b/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
@@ -30,6 +30,7 @@ CONFIG_DEBUG_PCI=y
CONFIG_DEBUG_PCI_ERROR=y
CONFIG_DEBUG_PCI_INFO=y
CONFIG_DEBUG_PCI_WARN=y
+CONFIG_DEBUG_SYMBOLS=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_HELLO_STACKSIZE=4194304
CONFIG_FS_PROCFS=y
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
index d2bbd79102..ed1873633a 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
@@ -29,8 +29,7 @@
#include <nuttx/pci/pci.h>
-#include "up_arch.h"
-#include "up_internal.h"
+#include "x86_64_internal.h"
/****************************************************************************
* Pre-processor Definitions
diff --git a/drivers/virt/qemu_edu.c b/drivers/virt/qemu_edu.c
index 953d161a52..4b71fd9485 100644
--- a/drivers/virt/qemu_edu.c
+++ b/drivers/virt/qemu_edu.c
@@ -27,6 +27,7 @@
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
+#include <debug.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
diff --git a/drivers/virt/qemu_pci_test.c b/drivers/virt/qemu_pci_test.c
index b0556b4d9f..747ea2130a 100644
--- a/drivers/virt/qemu_pci_test.c
+++ b/drivers/virt/qemu_pci_test.c
@@ -25,6 +25,7 @@
#include <nuttx/config.h>
#include <nuttx/arch.h>
+#include <debug.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
(nuttx) 04/06: boards/x86_64: refresh earlyfb and pcitest configurations
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 50f7e96e5e510a89bd1a5dd9b2fe31fb4abcd622
Author: raiden00pl <ra...@railab.me>
AuthorDate: Mon Jan 22 10:23:33 2024 +0100
boards/x86_64: refresh earlyfb and pcitest configurations
---
boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig | 11 ++---------
boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig | 11 ++---------
2 files changed, 4 insertions(+), 18 deletions(-)
diff --git a/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig b/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig
index 3342336c68..c8e3896867 100644
--- a/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig
+++ b/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig
@@ -16,25 +16,21 @@ CONFIG_ARCH_X86_64=y
CONFIG_BOARD_LOOPSPERMSEC=999
CONFIG_BOOT_RUNFROMEXTSRAM=y
CONFIG_BUILTIN=y
-CONFIG_CLOCK_MONOTONIC=y
CONFIG_CONSOLE_SYSLOG=y
-CONFIG_DEBUG_ERROR=y
CONFIG_DEBUG_FEATURES=y
-CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_PCI=y
CONFIG_DEBUG_PCI_ERROR=y
CONFIG_DEBUG_PCI_INFO=y
CONFIG_DEBUG_PCI_WARN=y
CONFIG_DEBUG_SYMBOLS=y
-CONFIG_DEBUG_WARN=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_HELLO_STACKSIZE=4194304
CONFIG_FS_PROCFS=y
CONFIG_IDLETHREAD_STACKSIZE=4194304
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_STACKSIZE=4194304
CONFIG_LIBM=y
-CONFIG_MAX_TASKS=64
CONFIG_MULTBOOT2_FB_TERM=y
-CONFIG_NFILE_DESCRIPTORS=32
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_IFCONFIG=y
@@ -56,7 +52,6 @@ CONFIG_SCHED_TICKLESS=y
CONFIG_SCHED_TICKLESS_ALARM=y
CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y
CONFIG_SCHED_WAITPID=y
-CONFIG_SDCLONE_DISABLE=y
CONFIG_SIG_DEFAULT=y
CONFIG_START_DAY=3
CONFIG_START_MONTH=3
@@ -65,8 +60,6 @@ CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_TIME64=y
CONFIG_USEC_PER_TICK=1
-CONFIG_USERMAIN_STACKSIZE=4194304
-CONFIG_USER_ENTRYPOINT="nsh_main"
CONFIG_VIRT=y
CONFIG_VIRT_QEMU_EDU=y
CONFIG_VIRT_QEMU_PCI_TEST=y
diff --git a/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig b/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
index 61e33fb0eb..17f6e7cc8a 100644
--- a/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
+++ b/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
@@ -24,23 +24,19 @@ CONFIG_ARCH_X86_64=y
CONFIG_BOARD_LOOPSPERMSEC=999
CONFIG_BOOT_RUNFROMEXTSRAM=y
CONFIG_BUILTIN=y
-CONFIG_CLOCK_MONOTONIC=y
CONFIG_CONSOLE_SYSLOG=y
-CONFIG_DEBUG_ERROR=y
CONFIG_DEBUG_FEATURES=y
-CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_PCI=y
CONFIG_DEBUG_PCI_ERROR=y
CONFIG_DEBUG_PCI_INFO=y
CONFIG_DEBUG_PCI_WARN=y
-CONFIG_DEBUG_WARN=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXAMPLES_HELLO_STACKSIZE=4194304
CONFIG_FS_PROCFS=y
CONFIG_IDLETHREAD_STACKSIZE=4194304
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_STACKSIZE=4194304
CONFIG_LIBM=y
-CONFIG_MAX_TASKS=64
-CONFIG_NFILE_DESCRIPTORS=32
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_DISABLE_IFCONFIG=y
@@ -60,7 +56,6 @@ CONFIG_SCHED_TICKLESS=y
CONFIG_SCHED_TICKLESS_ALARM=y
CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y
CONFIG_SCHED_WAITPID=y
-CONFIG_SDCLONE_DISABLE=y
CONFIG_SIG_DEFAULT=y
CONFIG_START_DAY=3
CONFIG_START_MONTH=3
@@ -69,8 +64,6 @@ CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_TIME64=y
CONFIG_USEC_PER_TICK=1
-CONFIG_USERMAIN_STACKSIZE=4194304
-CONFIG_USER_ENTRYPOINT="nsh_main"
CONFIG_VIRT=y
CONFIG_VIRT_QEMU_EDU=y
CONFIG_VIRT_QEMU_PCI_TEST=y
(nuttx) 06/06: cosmetic changes after pci code rebase
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit a12fdd88762a034610684755aaef548ada1fc31f
Author: raiden00pl <ra...@railab.me>
AuthorDate: Mon Jan 22 11:12:09 2024 +0100
cosmetic changes after pci code rebase
---
arch/x86_64/src/intel64/intel64_lowsetup.c | 9 +-
arch/x86_64/src/intel64/intel64_mbfb.c | 195 ++++++++++++--------
boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c | 54 +++---
drivers/pci/Make.defs | 8 +-
drivers/pci/pci.c | 214 +++++++++++++---------
drivers/virt/Make.defs | 10 +-
drivers/virt/qemu_edu.c | 137 ++++++++------
drivers/virt/qemu_pci_test.c | 120 ++++++------
include/nuttx/pci/pci.h | 60 +++---
include/nuttx/virt/qemu_pci.h | 16 +-
10 files changed, 477 insertions(+), 346 deletions(-)
diff --git a/arch/x86_64/src/intel64/intel64_lowsetup.c b/arch/x86_64/src/intel64/intel64_lowsetup.c
index d28d7f6dcc..c61864f6cb 100644
--- a/arch/x86_64/src/intel64/intel64_lowsetup.c
+++ b/arch/x86_64/src/intel64/intel64_lowsetup.c
@@ -78,11 +78,14 @@ static void x86_64_mb2_config(void)
/* Check that we were actually booted by a mulitboot2 bootloader */
if (mb_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
- return;
+ {
+ return;
+ }
for (tag = (struct multiboot_tag *)(uintptr_t)(mb_info_struct + 8);
- tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
+ tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag *)((uint8_t *)tag +
+ ((tag->size + 7) & ~7)))
{
switch (tag->type)
{
diff --git a/arch/x86_64/src/intel64/intel64_mbfb.c b/arch/x86_64/src/intel64/intel64_mbfb.c
index 0aacba8be2..665e79a57a 100644
--- a/arch/x86_64/src/intel64/intel64_mbfb.c
+++ b/arch/x86_64/src/intel64/intel64_mbfb.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/x86_64/src/intel64/intel64_lowsetup.c
+ * arch/x86_64/src/intel64/intel64_mbfb.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -37,44 +37,50 @@
#include "x86_64_internal.h"
/****************************************************************************
- * Pre-processor Definitions
+ * Private Types
****************************************************************************/
struct multiboot_fb_s
{
- void *baseaddr;
- uint32_t height;
- uint32_t width;
- uint32_t pitch;
- uint8_t bpp;
- uint8_t type;
+ void *baseaddr;
+ uint32_t height;
+ uint32_t width;
+ uint32_t pitch;
+ uint8_t bpp;
+ uint8_t type;
};
#ifdef CONFIG_MULTBOOT2_FB_TERM
struct fb_term_s
{
const struct nx_fontpackage_s *font;
- uint32_t cursor_x;
- uint32_t cursor_y;
+ uint32_t cursor_x;
+ uint32_t cursor_y;
};
+#endif
-void fb_term_initialize(void);
-#endif /* CONFIG_MULTBOOT2_FB_TERM */
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
-void fb_clear(void);
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+static void fb_term_initialize(void);
+static void fb_scroll(void);
+#endif
+static void fb_clear(void);
/****************************************************************************
* Private Data
****************************************************************************/
-struct multiboot_fb_s fb =
+static struct multiboot_fb_s g_fb =
{
.baseaddr = NULL
};
#ifdef CONFIG_MULTBOOT2_FB_TERM
-struct fb_term_s fb_term;
-#endif /* CONFIG_MULTBOOT2_FB_TERM */
+static struct fb_term_s g_fb_term;
+#endif
/****************************************************************************
* Public Data
@@ -85,7 +91,7 @@ struct fb_term_s fb_term;
****************************************************************************/
/****************************************************************************
- * Function: fb_draw_pixel
+ * Name: fb_draw_pixel
*
* Description:
* Draw a pixel on the framebuffer. Note that the color paramter must
@@ -97,20 +103,24 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
{
/* Check if we support this type of framebuffer */
- if (fb.type != MULTIBOOT_FRAMEBUFFER_TYPE_RGB)
- return;
+ if (g_fb.type != MULTIBOOT_FRAMEBUFFER_TYPE_RGB)
+ {
+ return;
+ }
/* Make sure we are within the bounds */
- if (x >= fb.width || y >= fb.height)
- return;
+ if (x >= g_fb.width || y >= g_fb.height)
+ {
+ return;
+ }
- switch (fb.bpp)
+ switch (g_fb.bpp)
{
case 8:
{
uint8_t *pixel = (uint8_t *)(
- (uintptr_t)fb.baseaddr + (fb.pitch * y) + x);
+ (uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x);
*pixel = (uint8_t)color;
break;
}
@@ -119,7 +129,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
case 16:
{
uint16_t *pixel = (uint16_t *)(
- (uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 2);
+ (uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x * 2);
*pixel = (uint16_t)color;
break;
}
@@ -131,7 +141,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
*/
uint32_t *pixel = (uint32_t *)(
- (uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 3);
+ (uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x * 3);
*pixel = (color & 0xffffff) | (*pixel & 0xff000000);
break;
}
@@ -139,7 +149,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
case 32:
{
uint32_t *pixel = (uint32_t *)(
- (uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 4);
+ (uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x * 4);
*pixel = color;
break;
}
@@ -148,7 +158,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
#if 0
/****************************************************************************
- * Function: fb_test_line
+ * Name: fb_test_line
*
* Description:
* This is a simple test function that can be used to draw a 45deg
@@ -158,7 +168,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
static void fb_test_line(void)
{
- size_t idx;
+ size_t idx;
uint32_t color;
switch (fb.bpp)
@@ -188,88 +198,114 @@ static void fb_test_line(void)
#endif
#ifdef CONFIG_MULTBOOT2_FB_TERM
+/****************************************************************************
+ * Name: fb_term_initialize
+ ****************************************************************************/
+
+static void fb_term_initialize(void)
+{
+ g_fb_term.font = nxf_getfonthandle(FONTID_DEFAULT);
+ g_fb_term.cursor_x = 0;
+ g_fb_term.cursor_y = 0;
+}
+
+/****************************************************************************
+ * Name: fb_scroll
+ ****************************************************************************/
+
static void fb_scroll(void)
{
- void *destp = fb.baseaddr;
- uint32_t save_rows = ((fb.height / fb_term.font->metrics.mxheight) - 1);
- size_t row_size = fb.pitch * fb_term.font->metrics.mxheight;
- uint32_t pxl_row = 0;
+ void *destp = g_fb.baseaddr;
+ uint32_t save_rows = 0;
+ size_t row_size = 0;
+ uint32_t pxl_row = 0;
+
+ save_rows = ((g_fb.height / g_fb_term.font->metrics.mxheight) - 1);
+ row_size = g_fb.pitch * g_fb_term.font->metrics.mxheight;
- for (; pxl_row < save_rows * fb_term.font->metrics.mxheight; pxl_row++)
+ for (; pxl_row < save_rows * g_fb_term.font->metrics.mxheight; pxl_row++)
{
- memcpy(destp, destp + row_size, fb.pitch);
- destp += fb.pitch;
+ memcpy(destp, destp + row_size, g_fb.pitch);
+ destp += g_fb.pitch;
}
- memset(destp, 0, fb.pitch * (fb.height - pxl_row));
+ memset(destp, 0, g_fb.pitch * (g_fb.height - pxl_row));
- fb_term.cursor_y -= fb_term.font->metrics.mxheight;
+ g_fb_term.cursor_y -= g_fb_term.font->metrics.mxheight;
}
#endif
+/****************************************************************************
+ * Name: fb_clear
+ ****************************************************************************/
+
+static void fb_clear(void)
+{
+ if (g_fb.baseaddr == NULL)
+ {
+ return;
+ }
+
+ memset(g_fb.baseaddr, 0, g_fb.pitch * g_fb.height);
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
+/****************************************************************************
+ * Name: x86_64_mb2_fbinitialize
+ ****************************************************************************/
+
void x86_64_mb2_fbinitialize(struct multiboot_tag_framebuffer *fbt)
{
- fb.baseaddr = (void *)(uintptr_t)fbt->common.framebuffer_addr;
- fb.width = fbt->common.framebuffer_width;
- fb.height = fbt->common.framebuffer_height;
- fb.pitch = fbt->common.framebuffer_pitch;
- fb.bpp = fbt->common.framebuffer_bpp;
- fb.type = fbt->common.framebuffer_type;
-
- up_map_region(fb.baseaddr, fb.pitch * fb.height,
+ g_fb.baseaddr = (void *)(uintptr_t)fbt->common.framebuffer_addr;
+ g_fb.width = fbt->common.framebuffer_width;
+ g_fb.height = fbt->common.framebuffer_height;
+ g_fb.pitch = fbt->common.framebuffer_pitch;
+ g_fb.bpp = fbt->common.framebuffer_bpp;
+ g_fb.type = fbt->common.framebuffer_type;
+
+ up_map_region(g_fb.baseaddr, g_fb.pitch * g_fb.height,
X86_PAGE_WR | X86_PAGE_PRESENT |
X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
fb_clear();
-
+
#ifdef CONFIG_MULTBOOT2_FB_TERM
fb_term_initialize();
#endif
-
-}
-
-void fb_clear(void)
-{
- if (fb.baseaddr == NULL)
- return;
-
- memset(fb.baseaddr, 0, fb.pitch * fb.height);
}
#ifdef CONFIG_MULTBOOT2_FB_TERM
-void fb_term_initialize(void)
-{
- fb_term.font = nxf_getfonthandle(FONTID_DEFAULT);
- fb_term.cursor_x = 0;
- fb_term.cursor_y = 0;
-}
+/****************************************************************************
+ * Name: fb_putc
+ ****************************************************************************/
void fb_putc(char ch)
{
- uint8_t gly_x;
- uint8_t gly_y;
const struct nx_fontbitmap_s *fbm;
+ uint8_t gly_x;
+ uint8_t gly_y;
- if (fb.baseaddr == NULL)
- return;
+ if (g_fb.baseaddr == NULL)
+ {
+ return;
+ }
if (ch == '\n')
{
- fb_term.cursor_y += fb_term.font->metrics.mxheight;
+ g_fb_term.cursor_y += g_fb_term.font->metrics.mxheight;
return;
}
if (ch == '\r')
{
- fb_term.cursor_x = 0;
+ g_fb_term.cursor_x = 0;
return;
}
- fbm = nxf_getbitmap((NXHANDLE)fb_term.font, ch);
+ fbm = nxf_getbitmap((NXHANDLE)g_fb_term.font, ch);
if (fbm == NULL)
{
fb_putc('.');
@@ -278,7 +314,7 @@ void fb_putc(char ch)
for (gly_y = 0; gly_y < fbm->metric.height; gly_y++)
{
- if (fb_term.cursor_y + gly_y >= fb.height)
+ if (g_fb_term.cursor_y + gly_y >= g_fb.height)
{
fb_scroll();
fb_putc(ch);
@@ -287,23 +323,28 @@ void fb_putc(char ch)
for (gly_x = 0; gly_x < fbm->metric.width; gly_x++)
{
- if (fb_term.cursor_x + gly_x >= fb.width)
+ if (g_fb_term.cursor_x + gly_x >= g_fb.width)
{
break;
}
- uint8_t stride = (fbm->metric.width + 7) >> 3;
- uint8_t gly_byte = stride * gly_y + (gly_x >> 3);
- uint8_t gly_bit = gly_x & 0x7;
- uint32_t color = 0; /* Black no matter the color depth */
+ uint8_t stride = (fbm->metric.width + 7) >> 3;
+ uint8_t gly_byte = stride * gly_y + (gly_x >> 3);
+ uint8_t gly_bit = gly_x & 0x7;
+ uint32_t color = 0;
+
if ((fbm->bitmap[gly_byte] >> (7 - gly_bit)) & 0x01)
- color = 0xffffffff; /* Black no matter the color depth */
+ {
+ /* White no matter the color depth */
+
+ color = 0xffffffff;
+ }
fb_draw_pixel(
- color, fb_term.cursor_x + gly_x, fb_term.cursor_y + gly_y);
+ color, g_fb_term.cursor_x + gly_x, g_fb_term.cursor_y + gly_y);
}
}
- fb_term.cursor_x += fbm->metric.width;
+ g_fb_term.cursor_x += fbm->metric.width;
}
#endif /* CONFIG_MULTBOOT2_FB_TERM */
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
index ed1873633a..3e946f01bc 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
@@ -43,35 +43,35 @@
* Private Functions Definitions
****************************************************************************/
-static void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
- uint32_t val, int width);
+static void qemu_pci_cfg_write(struct pci_dev_s *dev, int reg,
+ uint32_t val, int width);
-static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
+static uint32_t qemu_pci_cfg_read(struct pci_dev_s *dev, int reg,
int width);
static int qemu_pci_map_bar(uint64_t addr, uint64_t len);
-static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width);
+static uint32_t qemu_pci_io_read(const volatile void *addr, int width);
-static void qemu_pci_io_write(FAR const volatile void *addr, uint32_t val,
+static void qemu_pci_io_write(const volatile void *addr, uint32_t val,
int width);
/****************************************************************************
- * Public Data
+ * Private Data
****************************************************************************/
-struct pci_bus_ops_s qemu_pci_bus_ops =
+static const struct pci_bus_ops_s g_qemu_pci_bus_ops =
{
- .pci_cfg_write = qemu_pci_cfg_write,
- .pci_cfg_read = qemu_pci_cfg_read,
- .pci_map_bar = qemu_pci_map_bar,
- .pci_io_read = qemu_pci_io_read,
- .pci_io_write = qemu_pci_io_write,
+ .pci_cfg_write = qemu_pci_cfg_write,
+ .pci_cfg_read = qemu_pci_cfg_read,
+ .pci_map_bar = qemu_pci_map_bar,
+ .pci_io_read = qemu_pci_io_read,
+ .pci_io_write = qemu_pci_io_write,
};
-struct pci_bus_s qemu_pci_bus =
+static struct pci_bus_s g_qemu_pci_bus =
{
- .ops = &qemu_pci_bus_ops,
+ .ops = &g_qemu_pci_bus_ops,
};
/****************************************************************************
@@ -86,19 +86,20 @@ struct pci_bus_s qemu_pci_bus =
* specified by dev
*
* Input Parameters:
- * bdf - Device private data
- * reg - A pointer to the read-only buffer of data to be written
- * size - The number of bytes to send from the buffer
+ * bdf - Device private data
+ * reg - 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 void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
+static void qemu_pci_cfg_write(struct pci_dev_s *dev, int reg,
uint32_t val, int width)
{
uint8_t offset_mask = (4 - width);
+
outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
switch (width)
{
@@ -133,11 +134,12 @@ static void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
*
****************************************************************************/
-static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
+static uint32_t qemu_pci_cfg_read(struct pci_dev_s *dev, int reg,
int width)
{
uint32_t ret;
- uint8_t offset_mask = 4 - width;
+ uint8_t offset_mask = 4 - width;
+
outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
switch (width)
@@ -159,9 +161,10 @@ static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
return 0;
}
-static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width)
+static uint32_t qemu_pci_io_read(const volatile void *addr, int width)
{
uint16_t portaddr = (uint16_t)(intptr_t)addr;
+
switch (width)
{
case 1:
@@ -178,20 +181,21 @@ static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width)
return 0;
}
-static void qemu_pci_io_write(FAR const volatile void *addr, uint32_t val,
+static void qemu_pci_io_write(const volatile void *addr, uint32_t val,
int width)
{
uint16_t portaddr = (uint16_t)(intptr_t)addr;
+
switch (width)
{
case 1:
outb((uint8_t)val, portaddr);
return;
case 2:
- outw((uint8_t)val, portaddr);
+ outw((uint16_t)val, portaddr);
return;
case 4:
- outl((uint8_t)val, portaddr);
+ outl((uint32_t)val, portaddr);
return;
default:
pcierr("Invalid write width %d\n", width);
@@ -221,5 +225,5 @@ static int qemu_pci_map_bar(uint64_t addr, uint64_t len)
void qemu_pci_init(void)
{
pciinfo("Initializing PCI Bus\n");
- pci_initialize(&qemu_pci_bus);
+ pci_initialize(&g_qemu_pci_bus);
}
diff --git a/drivers/pci/Make.defs b/drivers/pci/Make.defs
index d890993e62..2b0a4c4901 100644
--- a/drivers/pci/Make.defs
+++ b/drivers/pci/Make.defs
@@ -7,9 +7,9 @@
# 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
@@ -18,8 +18,6 @@
#
############################################################################
-# Don't build anything if there is no CAN support
-
ifeq ($(CONFIG_PCI),y)
CSRCS += pci.c
@@ -28,5 +26,5 @@ CSRCS += pci.c
DEPPATH += --dep-path pci
VPATH += :pci
-CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)pci}
+CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)pci
endif
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0ae67a515d..9e9ba848a1 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * nuttx/drivers/pci/pci.c
+ * drivers/pci/pci.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -51,7 +51,7 @@
static void pci_probe_device(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx, uint8_t slot_idx, uint8_t func,
- FAR struct pci_dev_type_s **types);
+ FAR const struct pci_dev_type_s **types);
static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx, uint8_t slot_idx,
@@ -59,11 +59,11 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
static void pci_scan_device(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx, uint8_t slot_idx,
- FAR struct pci_dev_type_s **types);
+ FAR const struct pci_dev_type_s **types);
static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx,
- FAR struct pci_dev_type_s **types);
+ FAR const struct pci_dev_type_s **types);
static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask);
@@ -73,14 +73,14 @@ static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask);
* Public Data
****************************************************************************/
-struct pci_dev_type_s *pci_device_types[] =
+const struct pci_dev_type_s *g_pci_device_types[] =
{
#ifdef CONFIG_VIRT_QEMU_PCI_TEST
- &pci_type_qemu_pci_test,
-#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
+ &g_pci_type_qemu_pci_test,
+#endif
#ifdef CONFIG_VIRT_QEMU_EDU
- &pci_type_qemu_edu,
-#endif /* CONFIG_VIRT_QEMU_EDU */
+ &g_pci_type_qemu_edu,
+#endif
NULL,
};
@@ -105,12 +105,13 @@ struct pci_dev_type_s *pci_device_types[] =
static void pci_probe_device(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx, uint8_t slot_idx, uint8_t func,
- FAR struct pci_dev_type_s **types)
+ FAR const struct pci_dev_type_s **types)
{
struct pci_dev_s tmp_dev;
- uint16_t vid;
- uint16_t id;
- uint32_t class_rev;
+ uint32_t class_rev;
+ uint16_t vid;
+ uint16_t id;
+ int i;
tmp_dev.bus = root_bus;
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, func);
@@ -124,7 +125,7 @@ static void pci_probe_device(FAR struct pci_bus_s *root_bus,
pci_dev_dump(&tmp_dev);
- for (int i = 0; types[i] != NULL; i++)
+ for (i = 0; types[i] != NULL; i++)
{
if (types[i]->vendor == PCI_ID_ANY ||
types[i]->vendor == vid)
@@ -144,10 +145,11 @@ static void pci_probe_device(FAR struct pci_bus_s *root_bus,
}
else
{
- pcierr("[%02x:%02x.%x] Error: Invalid \
- device probe function\n",
- bus_idx, slot_idx, func);
+ pcierr("[%02x:%02x.%x] Error: Invalid"
+ "device probe function\n",
+ bus_idx, slot_idx, func);
}
+
break;
}
}
@@ -175,9 +177,9 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
uint8_t dev_func)
{
struct pci_dev_s tmp_dev;
- uint8_t base_class;
- uint8_t sub_class;
- uint8_t secondary_bus;
+ uint8_t base_class;
+ uint8_t sub_class;
+ uint8_t secondary_bus;
tmp_dev.bus = root_bus;
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
@@ -187,18 +189,19 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
base_class = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_CLASS, 1);
sub_class = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_SUBCLASS, 1);
- if ((base_class == PCI_CLASS_BASE_BRG_DEV) && \
- (sub_class == PCI_CLASS_SUB_PCI_BRG))
+ if ((base_class == PCI_CLASS_BASE_BRG_DEV) &&
+ (sub_class == PCI_CLASS_SUB_PCI_BRG))
{
- /* This is a bridge device we need to determin the bus idx and
+ /* This is a bridge device we need to determine the bus idx and
* enumerate it just like we do the root.
*/
pciinfo("[%02x:%02x.%x] Found Bridge\n",
- bus_idx, slot_idx, dev_func);
+ bus_idx, slot_idx, dev_func);
secondary_bus = root_bus->ops->pci_cfg_read(
&tmp_dev, PCI_CONFIG_SEC_BUS, 1);
+
return secondary_bus;
}
@@ -222,25 +225,21 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
static void pci_scan_device(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx, uint8_t slot_idx,
- FAR struct pci_dev_type_s **types)
+ FAR const struct pci_dev_type_s **types)
{
struct pci_dev_s tmp_dev;
- uint8_t dev_func = 0;
- uint16_t vid;
- uint8_t sec_bus;
- uint8_t multi_function;
+ uint8_t multi_function;
+ uint8_t dev_func = 0;
+ uint16_t vid;
+ uint8_t sec_bus;
tmp_dev.bus = root_bus;
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
if (vid == 0xffff)
+ {
return;
-
- /* Check if this is a PCI-PCI bridge device */
-
- sec_bus = pci_check_pci_bridge(root_bus, bus_idx, slot_idx, dev_func);
- if (sec_bus)
- pci_scan_bus(root_bus, sec_bus, types);
+ }
multi_function = root_bus->ops->pci_cfg_read(
&tmp_dev, PCI_CONFIG_HEADER_TYPE, 1) & PCI_HEADER_MASK_MULTI;
@@ -258,10 +257,12 @@ static void pci_scan_device(FAR struct pci_bus_s *root_bus,
{
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
+
if (vid != 0xffff)
{
sec_bus = pci_check_pci_bridge(
root_bus, bus_idx, slot_idx, dev_func);
+
if (sec_bus)
{
pci_scan_bus(root_bus, sec_bus, types);
@@ -274,7 +275,17 @@ static void pci_scan_device(FAR struct pci_bus_s *root_bus,
}
else
{
- pci_probe_device(root_bus, bus_idx, slot_idx, dev_func, types);
+ /* Check if this is a PCI-PCI bridge device with MF=0 */
+
+ sec_bus = pci_check_pci_bridge(root_bus, bus_idx, slot_idx, dev_func);
+ if (sec_bus)
+ {
+ pci_scan_bus(root_bus, sec_bus, types);
+ }
+ else
+ {
+ pci_probe_device(root_bus, bus_idx, slot_idx, dev_func, types);
+ }
}
}
@@ -294,7 +305,7 @@ static void pci_scan_device(FAR struct pci_bus_s *root_bus,
static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
uint8_t bus_idx,
- FAR struct pci_dev_type_s **types)
+ FAR const struct pci_dev_type_s **types)
{
uint8_t slot_idx;
@@ -302,8 +313,6 @@ static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
{
pci_scan_device(root_bus, bus_idx, slot_idx, types);
}
-
- return;
}
/****************************************************************************
@@ -320,11 +329,11 @@ static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
{
- uint16_t cmd;
+ uint16_t cmd;
cmd = dev->bus->ops->pci_cfg_read(dev, PCI_CONFIG_COMMAND, 2);
dev->bus->ops->pci_cfg_write(dev, PCI_CONFIG_COMMAND,
- (cmd | bitmask), 2);
+ (cmd | bitmask), 2);
}
/****************************************************************************
@@ -341,11 +350,11 @@ static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
{
- uint16_t cmd;
+ uint16_t cmd;
cmd = dev->bus->ops->pci_cfg_read(dev, PCI_CONFIG_COMMAND, 2);
dev->bus->ops->pci_cfg_write(dev, PCI_CONFIG_COMMAND,
- (cmd & ~bitmask), 2);
+ (cmd & ~bitmask), 2);
}
/****************************************************************************
@@ -369,12 +378,17 @@ static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
****************************************************************************/
int pci_enumerate(FAR struct pci_bus_s *bus,
- FAR struct pci_dev_type_s **types)
+ FAR const struct pci_dev_type_s **types)
{
if (!bus)
+ {
return -EINVAL;
+ }
+
if (!types)
+ {
return -EINVAL;
+ }
pci_scan_bus(bus, 0, types);
return OK;
@@ -400,7 +414,7 @@ int pci_enumerate(FAR struct pci_bus_s *bus,
int pci_initialize(FAR struct pci_bus_s *bus)
{
- return pci_enumerate(bus, pci_device_types);
+ return pci_enumerate(bus, g_pci_device_types);
}
/****************************************************************************
@@ -425,12 +439,17 @@ int pci_enable_io(FAR struct pci_dev_s *dev, int res)
{
switch (res)
{
- case PCI_SYS_RES_IOPORT:
- pci_set_cmd_bit(dev, PCI_CMD_IO_SPACE);
- return OK;
- case PCI_SYS_RES_MEM:
- pci_set_cmd_bit(dev, PCI_CMD_MEM_SPACE);
- return OK;
+ case PCI_SYS_RES_IOPORT:
+ {
+ pci_set_cmd_bit(dev, PCI_CMD_IO_SPACE);
+ return OK;
+ }
+
+ case PCI_SYS_RES_MEM:
+ {
+ pci_set_cmd_bit(dev, PCI_CMD_MEM_SPACE);
+ return OK;
+ }
}
return -EINVAL;
@@ -458,12 +477,17 @@ int pci_disable_io(FAR struct pci_dev_s *dev, int res)
{
switch (res)
{
- case PCI_SYS_RES_IOPORT:
- pci_clear_cmd_bit(dev, PCI_CMD_IO_SPACE);
- return OK;
- case PCI_SYS_RES_MEM:
- pci_clear_cmd_bit(dev, PCI_CMD_MEM_SPACE);
- return OK;
+ case PCI_SYS_RES_IOPORT:
+ {
+ pci_clear_cmd_bit(dev, PCI_CMD_IO_SPACE);
+ return OK;
+ }
+
+ case PCI_SYS_RES_MEM:
+ {
+ pci_clear_cmd_bit(dev, PCI_CMD_MEM_SPACE);
+ return OK;
+ }
}
return -EINVAL;
@@ -530,7 +554,7 @@ int pci_disable_bus_master(FAR struct pci_dev_s *dev)
int pci_bar_valid(FAR struct pci_dev_s *dev, uint8_t bar_id)
{
uint32_t bar = dev->bus->ops->pci_cfg_read(dev,
- PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
+ PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
if (bar == PCI_BAR_INVALID)
{
@@ -559,12 +583,14 @@ int pci_bar_valid(FAR struct pci_dev_s *dev, uint8_t bar_id)
bool pci_bar_is_64(FAR struct pci_dev_s *dev, uint8_t bar_id)
{
uint32_t bar = dev->bus->ops->pci_cfg_read(dev,
- PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
+ PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
/* Check that it is memory and not io port */
if ((bar & PCI_BAR_LAYOUT_MASK) != PCI_BAR_LAYOUT_MEM)
+ {
return false;
+ }
if (((bar & PCI_BAR_TYPE_MASK) >> PCI_BAR_TYPE_OFFSET) == PCI_BAR_TYPE_64)
{
@@ -591,12 +617,13 @@ bool pci_bar_is_64(FAR struct pci_dev_s *dev, uint8_t bar_id)
uint64_t pci_bar_size(FAR struct pci_dev_s *dev, uint8_t bar_id)
{
- uint32_t bar;
- uint32_t size;
- uint64_t full_size;
- uint8_t bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
- const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+ FAR const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+ uint32_t bar;
+ uint32_t size;
+ uint64_t full_size;
+ uint8_t bar_offset;
+ bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
bar = dev_ops->pci_cfg_read(dev, bar_offset, 4);
/* Write all 1 to the BAR. We are looking for which bits will change */
@@ -660,10 +687,11 @@ uint64_t pci_bar_size(FAR struct pci_dev_s *dev, uint8_t bar_id)
uint64_t pci_bar_addr(FAR struct pci_dev_s *dev, uint8_t bar_id)
{
- uint64_t addr;
- uint8_t bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
- const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+ FAR const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+ uint64_t addr;
+ uint8_t bar_offset;
+ bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
addr = dev_ops->pci_cfg_read(dev, bar_offset, 4);
if ((addr & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
@@ -699,25 +727,31 @@ uint64_t pci_bar_addr(FAR struct pci_dev_s *dev, uint8_t bar_id)
void pci_dev_dump(FAR struct pci_dev_s *dev)
{
- uint8_t bar_id;
- uint8_t bar_mem_type = 0;
- uint32_t bar;
- uint64_t bar_size;
- uint64_t bar_addr;
-
- uint8_t cap_id;
- uint8_t cap_offset;
-
- const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
- uint32_t bdf = dev->bdf;
- uint16_t vid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_VENDOR, 2);
- uint16_t pid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_DEVICE, 2);
- uint8_t header = dev_ops->pci_cfg_read(dev, PCI_CONFIG_HEADER_TYPE, 1);
- uint8_t progif = dev_ops->pci_cfg_read(dev, PCI_CONFIG_PROG_IF, 1);
- uint8_t subclass = dev_ops->pci_cfg_read(dev, PCI_CONFIG_SUBCLASS, 1);
- uint8_t class = dev_ops->pci_cfg_read(dev, PCI_CONFIG_CLASS, 1);
- uint8_t int_pin;
- uint8_t int_line;
+ FAR const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+ uint8_t bar_mem_type = 0;
+ uint8_t bar_id;
+ uint32_t bar;
+ uint64_t bar_size;
+ uint64_t bar_addr;
+ uint8_t cap_id;
+ uint8_t cap_offset;
+ uint32_t bdf;
+ uint16_t vid;
+ uint16_t pid;
+ uint8_t header;
+ uint8_t progif;
+ uint8_t subclass;
+ uint8_t class;
+ uint8_t int_pin;
+ uint8_t int_line;
+
+ bdf = dev->bdf;
+ vid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_VENDOR, 2);
+ pid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_DEVICE, 2);
+ header = dev_ops->pci_cfg_read(dev, PCI_CONFIG_HEADER_TYPE, 1);
+ progif = dev_ops->pci_cfg_read(dev, PCI_CONFIG_PROG_IF, 1);
+ subclass = dev_ops->pci_cfg_read(dev, PCI_CONFIG_SUBCLASS, 1);
+ class = dev_ops->pci_cfg_read(dev, PCI_CONFIG_CLASS, 1);
pciinfo("[%02x:%02x.%x] %04x:%04x\n",
bdf >> 8, (bdf & 0xff) >> 3, bdf & 0x7, vid, pid);
@@ -740,7 +774,9 @@ void pci_dev_dump(FAR struct pci_dev_s *dev)
}
if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_NORMAL)
+ {
return;
+ }
int_pin = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_INT_PIN, 1);
int_line = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_INT_LINE, 1);
@@ -749,7 +785,9 @@ void pci_dev_dump(FAR struct pci_dev_s *dev)
for (bar_id = 0; bar_id < PCI_BAR_CNT; bar_id++)
{
if (pci_bar_valid(dev, bar_id) != OK)
- continue;
+ {
+ continue;
+ }
bar = dev_ops->pci_cfg_read(dev,
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
@@ -787,6 +825,8 @@ void pci_dev_dump(FAR struct pci_dev_s *dev)
/* Skip next bar if this one was 64bit */
if (bar_mem_type == 64)
+ {
bar_id++;
+ }
}
}
diff --git a/drivers/virt/Make.defs b/drivers/virt/Make.defs
index a65cce26f4..856a9db7cb 100644
--- a/drivers/virt/Make.defs
+++ b/drivers/virt/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# drivers/pci/Make.defs
+# drivers/virt/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -18,18 +18,12 @@
#
############################################################################
-# Don't build anything if there is no CAN support
-
ifeq ($(CONFIG_VIRT_QEMU_PCI_TEST),y)
-
CSRCS += qemu_pci_test.c
-
endif
ifeq ($(CONFIG_VIRT_QEMU_EDU),y)
-
CSRCS += qemu_edu.c
-
endif
# Include virt device driver build support
@@ -38,6 +32,6 @@ ifeq ($(CONFIG_VIRT),y)
DEPPATH += --dep-path virt
VPATH += :virt
-CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)virt}
+CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)virt
endif
diff --git a/drivers/virt/qemu_edu.c b/drivers/virt/qemu_edu.c
index 4b71fd9485..0117d995eb 100644
--- a/drivers/virt/qemu_edu.c
+++ b/drivers/virt/qemu_edu.c
@@ -60,6 +60,12 @@
#define EDU_CONTROL_BAR_ID 0
#define EDU_CONTROL_BAR_OFFSET PCI_HEADER_NORM_BAR0
+/* One 4096 bytes long buffer at offset 0x40000 is available in the
+ * EDU device
+ */
+
+#define QEMU_EDU_DMABUF_OFFSET 0x40000
+
/*****************************************************************************
* Private Types
*****************************************************************************/
@@ -67,8 +73,8 @@
struct qemu_edu_priv_s
{
uintptr_t base_addr;
- sem_t isr_done;
- uint32_t test_result;
+ sem_t isr_done;
+ uint32_t test_result;
};
/*****************************************************************************
@@ -89,10 +95,23 @@ static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
static int qemu_edu_interrupt(int irq, void *context, FAR void *arg);
+static int qemu_edu_probe(FAR struct pci_bus_s *bus,
+ FAR const struct pci_dev_type_s *type,
+ uint16_t bdf);
+
/*****************************************************************************
- * Private Data
+ * Public Data
*****************************************************************************/
+const struct pci_dev_type_s g_pci_type_qemu_edu =
+{
+ .vendor = 0x1234,
+ .device = 0x11e8,
+ .class_rev = PCI_ID_ANY,
+ .name = "Qemu PCI EDU device",
+ .probe = qemu_edu_probe
+};
+
/*****************************************************************************
* Private Functions
*****************************************************************************/
@@ -206,10 +225,10 @@ static void qemu_edu_test_poll(FAR struct pci_dev_s *dev, uintptr_t base_addr)
*****************************************************************************/
static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
- struct qemu_edu_priv_s *drv_priv)
+ FAR struct qemu_edu_priv_s *drv_priv)
{
uintptr_t base_addr = drv_priv->base_addr;
- uint32_t test_value;
+ uint32_t test_value;
pciinfo("Identification: 0x%08xu\n",
qemu_edu_read_reg32(base_addr + EDU_REG_ID));
@@ -253,16 +272,16 @@ static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
*****************************************************************************/
static void qemu_edu_test_dma(FAR struct pci_dev_s *dev,
- struct qemu_edu_priv_s *drv_priv)
+ FAR struct qemu_edu_priv_s *drv_priv)
{
- uintptr_t base_addr = drv_priv->base_addr;
- void *test_block;
- size_t block_size = 2048;
- int i;
- uint32_t psrand;
- uint32_t tx_checksum;
- uint32_t rx_checksum;
- uint32_t dev_addr = 0x40000;
+ uintptr_t base_addr = drv_priv->base_addr;
+ FAR void *test_block;
+ size_t block_size = 2048;
+ int i;
+ uint32_t psrand;
+ uint32_t tx_checksum;
+ uint32_t rx_checksum;
+ uint32_t dev_addr = QEMU_EDU_DMABUF_OFFSET;
pciinfo("Identification: 0x%08xu\n",
qemu_edu_read_reg32(base_addr + EDU_REG_ID));
@@ -322,58 +341,73 @@ static void qemu_edu_test_dma(FAR struct pci_dev_s *dev,
*
*****************************************************************************/
-static int qemu_edu_interrupt(int irq, void *context, FAR void *arg)
+static int qemu_edu_interrupt(int irq, FAR void *context, FAR void *arg)
{
- struct qemu_edu_priv_s *drv_priv = (struct qemu_edu_priv_s *)arg;
- uintptr_t base_addr = drv_priv->base_addr;
+ FAR struct qemu_edu_priv_s *drv_priv = (struct qemu_edu_priv_s *)arg;
+ uintptr_t base_addr;
+ uint32_t status;
- uint32_t status = qemu_edu_read_reg32(base_addr + EDU_REG_INT_STATUS);
+ base_addr = drv_priv->base_addr;
+ status = qemu_edu_read_reg32(base_addr + EDU_REG_INT_STATUS);
qemu_edu_write_reg32(base_addr + EDU_REG_INT_ACK, ~0U);
switch (status)
{
- case 0x1: /* Factorial triggered */
- drv_priv->test_result = qemu_edu_read_reg32(base_addr + EDU_REG_FAC);
- pciinfo("Computed factorial: %d\n",
- drv_priv->test_result);
- break;
- case 0x100: /* DMA triggered */
- pciinfo("DMA transfer complete\n");
- break;
- default: /* Generic write */
- drv_priv->test_result = status;
- pciinfo("Received value: 0x%08x\n", status);
+ /* Factorial triggered */
+
+ case 0x1:
+ {
+ drv_priv->test_result
+ = qemu_edu_read_reg32(base_addr + EDU_REG_FAC);
+ pciinfo("Computed factorial: %d\n", drv_priv->test_result);
+ break;
+ }
+
+ /* DMA triggered */
+
+ case 0x100:
+ {
+ pciinfo("DMA transfer complete\n");
+ break;
+ }
+
+ /* Generic write */
+
+ default:
+ {
+ drv_priv->test_result = status;
+ pciinfo("Received value: 0x%08x\n", status);
+ break;
+ }
}
sem_post(&drv_priv->isr_done);
return OK;
}
-/*****************************************************************************
- * Public Functions
- *****************************************************************************/
-
/*****************************************************************************
* Name: qemu_edu_probe
*
* Description:
* Initialize device
+ *
*****************************************************************************/
-int qemu_edu_probe(FAR struct pci_bus_s *bus,
- FAR struct pci_dev_type_s *type, uint16_t bdf)
+static int qemu_edu_probe(FAR struct pci_bus_s *bus,
+ FAR const struct pci_dev_type_s *type,
+ uint16_t bdf)
{
- uint32_t bar;
- uintptr_t bar_addr;
- struct pci_dev_s dev =
- {
- .bus = bus,
- .type = type,
- .bdf = bdf,
- };
-
- uint8_t irq;
struct qemu_edu_priv_s drv_priv;
+ struct pci_dev_s dev;
+ uint32_t bar;
+ uintptr_t bar_addr;
+ uint8_t irq;
+
+ /* Get dev */
+
+ dev.bus = bus;
+ dev.type = type;
+ dev.bdf = bdf;
pci_enable_bus_master(&dev);
pciinfo("Enabled bus mastering\n");
@@ -434,16 +468,3 @@ int qemu_edu_probe(FAR struct pci_bus_s *bus,
return OK;
}
-
-/*****************************************************************************
- * Public Data
- *****************************************************************************/
-
-struct pci_dev_type_s pci_type_qemu_edu =
-{
- .vendor = 0x1234,
- .device = 0x11e8,
- .class_rev = PCI_ID_ANY,
- .name = "Qemu PCI EDU device",
- .probe = qemu_edu_probe
-};
diff --git a/drivers/virt/qemu_pci_test.c b/drivers/virt/qemu_pci_test.c
index 747ea2130a..9ab30569b4 100644
--- a/drivers/virt/qemu_pci_test.c
+++ b/drivers/virt/qemu_pci_test.c
@@ -49,19 +49,36 @@ static uint32_t mem_read(FAR const volatile void *addr, int width);
static void mem_write(FAR const volatile void *addr, uint32_t val, int width);
+static int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
+ FAR const struct pci_dev_type_s *type,
+ uint16_t bdf);
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+const struct pci_dev_type_s g_pci_type_qemu_pci_test =
+{
+ .vendor = 0x1b36,
+ .device = 0x0005,
+ .class_rev = PCI_ID_ANY,
+ .name = "Qemu PCI test device",
+ .probe = qemu_pci_test_probe
+};
+
/*****************************************************************************
* Private Types
*****************************************************************************/
struct pci_test_dev_hdr_s
{
- uint8_t test; /* write-only, starts a given test number */
- uint8_t width; /* read-only, type and width of access for a test */
- uint8_t pad0[2];
+ uint8_t test; /* write-only, starts a given test number */
+ uint8_t width; /* read-only, type and width of access for a test */
+ uint8_t pad0[2];
uint32_t offset; /* read-only, offset in this BAR for a given test */
uint32_t data; /* read-only, data to use for a given test */
uint32_t count; /* for debugging. number of writes detected. */
- uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
+ uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
};
/* Structure the read and write helpers */
@@ -76,7 +93,7 @@ struct pci_test_dev_ops_s
* Private Data
*****************************************************************************/
-static struct pci_test_dev_ops_s mem_ops =
+static struct pci_test_dev_ops_s g_mem_ops =
{
.read = mem_read,
.write = mem_write
@@ -100,14 +117,14 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
FAR struct pci_test_dev_hdr_s *test_hdr,
uint16_t test_num)
{
- uint32_t count;
- uint32_t data;
- uint32_t offset;
- uint8_t width;
const int write_limit = 8;
- int write_cnt;
- int i;
- char testname[32];
+ uint32_t count;
+ uint32_t data;
+ uint32_t offset;
+ uint8_t width;
+ int write_cnt;
+ int i;
+ char testname[32];
pciinfo("WRITING Test# %d %p\n", test_num, &test_hdr->test);
test_ops->write(&test_hdr->test, test_num, 1);
@@ -122,7 +139,9 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
{
testname[i] = (char)test_ops->read((void *)&test_hdr->name + i, 1);
if (testname[i] == 0)
- break;
+ {
+ break;
+ }
}
pciinfo("Running test: %s\n", testname);
@@ -130,13 +149,17 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
count = test_ops->read(&test_hdr->count, 4);
pciinfo("COUNT: %04x\n", count);
if (count != 0)
+ {
return false;
+ }
width = test_ops->read(&test_hdr->width, 1);
pciinfo("Width: %d\n", width);
if (width == 0 || width > 4)
+ {
return false;
+ }
data = test_ops->read(&test_hdr->data, 4);
pciinfo("Data: %04x\n", data);
@@ -156,45 +179,44 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
pciinfo("COUNT: %04x\n", count);
if (!count)
+ {
return true;
+ }
return (int)count == write_cnt;
}
-/*****************************************************************************
- * Public Functions
- *****************************************************************************/
-
/*****************************************************************************
* Name: qemu_pci_test_probe
*
* Description:
* Initialize device
+ *
*****************************************************************************/
-int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
- FAR struct pci_dev_type_s *type, uint16_t bdf)
+static int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
+ FAR const struct pci_dev_type_s *type,
+ uint16_t bdf)
{
- uint8_t bar_id;
- uint32_t bar;
- uint64_t bar_addr;
+ struct pci_dev_s dev;
+ struct pci_test_dev_ops_s io_ops;
+ struct pci_test_dev_ops_s *test_ops;
struct pci_test_dev_hdr_s *test_hdr;
- struct pci_dev_s dev =
- {
- .bus = bus,
- .type = type,
- .bdf = bdf,
- };
+ uint8_t bar_id;
+ uint32_t bar;
+ uint64_t bar_addr;
+ uint16_t test_cnt;
- struct pci_test_dev_ops_s io_ops =
- {
- .read = bus->ops->pci_io_read,
- .write = bus->ops->pci_io_write
- };
+ /* Get dev */
- struct pci_test_dev_ops_s *test_ops;
+ dev.bus = bus;
+ dev.type = type;
+ dev.bdf = bdf;
- uint16_t test_cnt;
+ /* Get io ops */
+
+ io_ops.read = bus->ops->pci_io_read;
+ io_ops.write = bus->ops->pci_io_write;
pci_enable_bus_master(&dev);
pciinfo("Enabled bus mastering\n");
@@ -209,7 +231,9 @@ int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
*/
if (pci_bar_valid(&dev, bar_id) != OK)
- continue;
+ {
+ continue;
+ }
bar = bus->ops->pci_cfg_read(&dev,
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
@@ -219,7 +243,7 @@ int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
if ((bar & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
{
- test_ops = &mem_ops;
+ test_ops = &g_mem_ops;
/* If the BAR is MMIO the it must be mapped */
@@ -233,26 +257,18 @@ int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
for (test_cnt = 0; test_cnt < 0xffff; test_cnt++)
{
if (!qemu_pci_test_bar(test_ops, test_hdr, test_cnt))
- break;
+ {
+ break;
+ }
+
pciinfo("Test Completed BAR [%d] TEST [%d]\n", bar_id, test_cnt);
}
if (pci_bar_is_64(&dev, bar_id))
- bar_id++;
+ {
+ bar_id++;
+ }
}
return OK;
}
-
-/*****************************************************************************
- * Public Data
- *****************************************************************************/
-
-struct pci_dev_type_s pci_type_qemu_pci_test =
-{
- .vendor = 0x1b36,
- .device = 0x0005,
- .class_rev = PCI_ID_ANY,
- .name = "Qemu PCI test device",
- .probe = qemu_pci_test_probe
-};
diff --git a/include/nuttx/pci/pci.h b/include/nuttx/pci/pci.h
index 0b420a04c0..72e88a73c0 100644
--- a/include/nuttx/pci/pci.h
+++ b/include/nuttx/pci/pci.h
@@ -40,17 +40,17 @@
/* PCI config common registers */
-#define PCI_CONFIG_VENDOR 0x00
-#define PCI_CONFIG_DEVICE 0x02
-#define PCI_CONFIG_COMMAND 0x04
-#define PCI_CONFIG_REV_ID 0x08
+#define PCI_CONFIG_VENDOR 0x00
+#define PCI_CONFIG_DEVICE 0x02
+#define PCI_CONFIG_COMMAND 0x04
+#define PCI_CONFIG_REV_ID 0x08
#define PCI_CONFIG_PROG_IF 0x09
-#define PCI_CONFIG_SUBCLASS 0x0A
-#define PCI_CONFIG_CLASS 0x0B
-#define PCI_CONFIG_CACHE_LINE_SIZE 0x0C
-#define PCI_CONFIG_LATENCY_TIMER 0x0D
-#define PCI_CONFIG_HEADER_TYPE 0x0E
-#define PCI_CONFIG_BIST 0x0F
+#define PCI_CONFIG_SUBCLASS 0x0A
+#define PCI_CONFIG_CLASS 0x0B
+#define PCI_CONFIG_CACHE_LINE_SIZE 0x0C
+#define PCI_CONFIG_LATENCY_TIMER 0x0D
+#define PCI_CONFIG_HEADER_TYPE 0x0E
+#define PCI_CONFIG_BIST 0x0F
/* PCI config header types */
@@ -109,7 +109,7 @@
/* Reserved 0x14-0x3F */
-#define PCI_CLASS_BASE_CO_PROC 0x40
+#define PCI_CLASS_BASE_CO_PROC 0x40
/* Reserved 0x41-0xFE */
@@ -216,18 +216,32 @@ struct pci_dev_s;
struct pci_bus_ops_s
{
- CODE void (*pci_cfg_write)(FAR struct pci_dev_s *dev, int reg,
- uint32_t val, int width);
+ /* Write 8, 16, 32, 64 bits data to PCI-E configuration space of device
+ * specified by dev.
+ */
- CODE uint32_t (*pci_cfg_read)(FAR struct pci_dev_s *dev, int reg,
- int width);
+ CODE void (*pci_cfg_write)(FAR struct pci_dev_s *dev, int reg,
+ uint32_t val, int width);
- CODE int (*pci_map_bar)(uint64_t addr, uint64_t len);
+ /* Read 8, 16, 32, 64 bits data to PCI-E configuration space of device
+ * specified by dev.
+ */
- CODE uint32_t (*pci_io_read)(FAR const volatile void *addr, int width);
+ CODE uint32_t (*pci_cfg_read)(FAR struct pci_dev_s *dev, int reg,
+ int width);
- CODE void (*pci_io_write)(FAR const volatile void *addr, uint32_t val,
- int width);
+ /* Map address in a 32 bits bar in the memory address space */
+
+ CODE int (*pci_map_bar)(uint64_t addr, uint64_t len);
+
+ /* Read from IO port */
+
+ CODE uint32_t (*pci_io_read)(FAR const volatile void *addr, int width);
+
+ /* Write to IO port */
+
+ CODE void (*pci_io_write)(FAR const volatile void *addr, uint32_t val,
+ int width);
};
/* PCI bus private data. */
@@ -249,16 +263,16 @@ struct pci_dev_type_s
/* Call back function when a device is probed */
CODE int (*probe)(FAR struct pci_bus_s *bus,
- FAR struct pci_dev_type_s *type, uint16_t bdf);
+ FAR const struct pci_dev_type_s *type, uint16_t bdf);
};
/* PCI device private data. */
struct pci_dev_s
{
- FAR struct pci_bus_s *bus;
- FAR struct pci_dev_type_s *type;
- uint32_t bdf;
+ FAR struct pci_bus_s *bus;
+ FAR const struct pci_dev_type_s *type;
+ uint32_t bdf;
};
/****************************************************************************
diff --git a/include/nuttx/virt/qemu_pci.h b/include/nuttx/virt/qemu_pci.h
index 3c3379ed00..6d5568d463 100644
--- a/include/nuttx/virt/qemu_pci.h
+++ b/include/nuttx/virt/qemu_pci.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * include/nuttx/serial/uart_mcs99xx.h
+ * include/nuttx/virt/qemu_pci.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -18,8 +18,8 @@
*
****************************************************************************/
-#ifndef __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H
-#define __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H
+#ifndef __INCLUDE_NUTTX_VIRT_QEMU_PCI_H
+#define __INCLUDE_NUTTX_VIRT_QEMU_PCI_H
/****************************************************************************
* Included Files
@@ -42,16 +42,16 @@ extern "C"
#endif
#ifdef CONFIG_VIRT_QEMU_PCI_TEST
-extern struct pci_dev_type_s pci_type_qemu_pci_test;
-#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
+extern const struct pci_dev_type_s g_pci_type_qemu_pci_test;
+#endif
#ifdef CONFIG_VIRT_QEMU_EDU
-extern struct pci_dev_type_s pci_type_qemu_edu;
-#endif /* CONFIG_VIRT_QEMU_EDU */
+extern const struct pci_dev_type_s g_pci_type_qemu_edu;
+#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif
-#endif /* __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H */
+#endif /* __INCLUDE_NUTTX_VIRT_QEMU_PCI_H */
(nuttx) 03/06: x86_64: Early framebuffer console
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 0ed4123326a2121897f3ae5d8b13d227030df1e4
Author: Brennan Ashton <ba...@brennanashton.com>
AuthorDate: Tue Aug 4 03:29:05 2020 -0700
x86_64: Early framebuffer console
This adds support for creating an early frame buffer and primatives for
writing to this frame buffer as a console. This does require the font
infrastructure as well as multiboot2.
Additionally this can now be used with a UEFI bootloader long as it
boots NuttX via Multiboot2. There does seem to be a PCI interrupt
issue when running in UEFI mode.
I was able to boot my laptop using this and see PCI devices enumerate.
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
x86_64: Add conditionals around the multiboot framebuffer
---
.../x86_64/qemu/boards/qemu-intel64/index.rst | 19 ++
arch/x86_64/Kconfig | 19 +-
arch/x86_64/src/common/x86_64_internal.h | 8 +-
arch/x86_64/src/intel64/Make.defs | 4 +
arch/x86_64/src/intel64/intel64_head.S | 14 +-
arch/x86_64/src/intel64/intel64_lowsetup.c | 45 +++
arch/x86_64/src/intel64/intel64_mbfb.c | 309 +++++++++++++++++++++
arch/x86_64/src/intel64/intel64_serial.c | 4 +
.../intel64/qemu-intel64/configs/earlyfb/defconfig | 72 +++++
9 files changed, 488 insertions(+), 6 deletions(-)
diff --git a/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst b/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst
index d1fe76186d..c927ad922a 100644
--- a/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst
+++ b/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst
@@ -36,6 +36,22 @@ P.S. In some distros, ``grub-mkrescue`` is called ``grub2-mkrescue``::
grub-mkrescue -o boot.iso iso
+Grub with UEFI
+--------------
+
+This flow is very similar except you need to have the BOOTX64.EFI file.
+You can find this in most Linux distributions::
+
+ iso/
+ └── boot
+ ├── efi
+ │ └── EFI
+ │ └── BOOT
+ │ └── BOOTX64.EFI
+ ├── grub
+ │ └── grub.cfg
+ └── nuttx.elf
+
QEMU/KVM
========
@@ -79,6 +95,9 @@ with the pcitest NuttX configuration::
This will enable the QEMU pci-test and edu PCI test devices which test PIO, MMIO, IRQ, and DMA
functions. Additionally it will show detailed information about the enumeration of the PCI bus.
+If you want to boot using UEFI and TianoCore you will need to add a flag like this to
+point at OVMF ``--bios /usr/share/edk2/ovmf/OVMF_CODE.fd``
+
Bochs
=====
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index fac4bb7d61..5e1115ad0e 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -63,10 +63,21 @@ config ARCH_BOARD
endif # ARCH_CHIP_QEMU
-config ARCH_EXCLUDE_MULTIBOOT
- bool "Don't append multiboot2 header"
- default n
+config ARCH_MULTIBOOT2
+ bool "Append multiboot2 header"
+ default y
---help---
- Some platforms, e.g. jailhouse, do not like to have a multiboot header
+ Include a multiboot2 header. This also provides information to the
+ system to enable certain features like the low level framebuffer.
+
+if ARCH_MULTIBOOT2
+config MULTBOOT2_FB_TERM
+ bool "Multiboot2 framebuffer terminal"
+ default n
+ depends on NXFONTS
+ ---help---
+ Enable a framebuffer terminal for early debug printing
+
+endif # ARCH_MULTIBOOT2
endif # ARCH_X86_64
diff --git a/arch/x86_64/src/common/x86_64_internal.h b/arch/x86_64/src/common/x86_64_internal.h
index da5a5a451e..f98d9605bf 100644
--- a/arch/x86_64/src/common/x86_64_internal.h
+++ b/arch/x86_64/src/common/x86_64_internal.h
@@ -32,6 +32,7 @@
# include <nuttx/sched.h>
# include <stdint.h>
# include <arch/io.h>
+# include <arch/multiboot2.h>
#endif
/****************************************************************************
@@ -63,7 +64,7 @@
# undef USE_SERIALDRIVER
# undef USE_EARLYSERIALINIT
# undef CONFIG_DEV_LOWCONSOLE
-# else
+# elif defined(CONFIG_16550_UART)
# define USE_SERIALDRIVER 1
# define USE_EARLYSERIALINIT 1
# endif
@@ -195,6 +196,11 @@ void x86_64_checktasks(void);
void x86_64_syscall(uint64_t *regs);
+#ifdef CONFIG_ARCH_MULTIBOOT2
+void x86_64_mb2_fbinitialize(struct multiboot_tag_framebuffer *tag);
+void fb_putc(char ch);
+#endif
+
/* Defined in up_allocateheap.c */
#if CONFIG_MM_REGIONS > 1
diff --git a/arch/x86_64/src/intel64/Make.defs b/arch/x86_64/src/intel64/Make.defs
index 010b56acd6..c2d6db49aa 100644
--- a/arch/x86_64/src/intel64/Make.defs
+++ b/arch/x86_64/src/intel64/Make.defs
@@ -38,6 +38,10 @@ CHIP_CSRCS += intel64_serial.c intel64_rng.c intel64_check_capability.c
# Configuration-dependent intel64 files
+ifeq ($(CONFIG_ARCH_MULTIBOOT2),y)
+CHIP_CSRCS += intel64_mbfb.c
+endif
+
ifneq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += intel64_timerisr.c
endif
diff --git a/arch/x86_64/src/intel64/intel64_head.S b/arch/x86_64/src/intel64/intel64_head.S
index 34c7bdf8da..f22b8eb322 100644
--- a/arch/x86_64/src/intel64/intel64_head.S
+++ b/arch/x86_64/src/intel64/intel64_head.S
@@ -65,6 +65,8 @@
.global nx_start /* nx_start is defined elsewhere */
.global up_lowsetup /* up_lowsetup is defined elsewhere */
.global g_idle_topstack /* The end of the idle stack, the start of the heap */
+ .global mb_info_struct
+ .global mb_magic
/* These are the page tables */
.global pdpt_low
@@ -89,7 +91,7 @@
.align 8
header_start:
-#ifndef CONFIG_ARCH_EXCLUDE_MULTIBOOT
+#ifdef CONFIG_ARCH_MULTIBOOT2
.long MULTIBOOT2_HEADER_MAGIC
.long MULTIBOOT_ARCHITECTURE_I386
.long HEADER_LENGTH
@@ -97,6 +99,12 @@ header_start:
// multiboot tags go here
+ .short MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
+ .short 0 // flags, none set
+ .long 16 // size, including itself (short + short + long)
+ .long MULTIBOOT_TAG_TYPE_EFI64
+ .long MULTIBOOT_TAG_TYPE_FRAMEBUFFER
+
.short MULTIBOOT_HEADER_TAG_END
.short 0 // flags, none set
.long 8 // size, including itself (short + short + long)
@@ -159,6 +167,10 @@ start32_0:
.type __pmode_entry, @function
__pmode_entry:
start32:
+#ifdef CONFIG_ARCH_MULTIBOOT2
+ movl %ebx, mb_info_struct
+ movl %eax, mb_magic
+#endif
// initialize rest of the page directory
lea pd_low, %edi
diff --git a/arch/x86_64/src/intel64/intel64_lowsetup.c b/arch/x86_64/src/intel64/intel64_lowsetup.c
index 51f04e2009..988a9523ff 100644
--- a/arch/x86_64/src/intel64/intel64_lowsetup.c
+++ b/arch/x86_64/src/intel64/intel64_lowsetup.c
@@ -26,6 +26,7 @@
#include <nuttx/arch.h>
#include <arch/board/board.h>
+#include <arch/multiboot2.h>
#include "x86_64_internal.h"
@@ -52,10 +53,48 @@ volatile uint64_t *pt;
volatile struct ist_s *ist64;
volatile struct gdt_entry_s *gdt64;
+/* This holds information passed by the multiboot2 bootloader */
+
+uint32_t mb_magic __attribute__((section(".loader.bss")));
+uint32_t mb_info_struct __attribute__((section(".loader.bss")));
+
/****************************************************************************
* Private Functions
****************************************************************************/
+static void x86_64_mb2_config(void)
+{
+ struct multiboot_tag *tag;
+
+ /* Check that we were actually booted by a mulitboot2 bootloader */
+
+ if (mb_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
+ return;
+
+ for (tag = (struct multiboot_tag *)(uintptr_t)(mb_info_struct + 8);
+ tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
+ {
+ switch (tag->type)
+ {
+ case MULTIBOOT_TAG_TYPE_EFI64:
+ {
+ break;
+ }
+
+ case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
+ {
+ x86_64_mb2_fbinitialize(
+ (struct multiboot_tag_framebuffer *)tag);
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -94,6 +133,10 @@ void up_lowsetup(void)
x86_64_check_and_enable_capability();
+ /* Handle multiboot2 info */
+
+ x86_64_mb2_config();
+
/* Revoke the lower memory */
__revoke_low_memory();
@@ -102,9 +145,11 @@ void up_lowsetup(void)
x86_64_boardinitialize();
+#ifdef USE_EARLYSERIALINIT
/* Early serial driver initialization */
x86_64_earlyserialinit();
+#endif
x86_64_timer_calibrate_freq();
diff --git a/arch/x86_64/src/intel64/intel64_mbfb.c b/arch/x86_64/src/intel64/intel64_mbfb.c
new file mode 100644
index 0000000000..f536cffb35
--- /dev/null
+++ b/arch/x86_64/src/intel64/intel64_mbfb.c
@@ -0,0 +1,309 @@
+/****************************************************************************
+ * arch/x86_64/src/intel64/intel64_lowsetup.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <string.h>
+
+#include <nuttx/arch.h>
+#include <arch/board/board.h>
+#include <arch/multiboot2.h>
+
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+#include <nuttx/nx/nxfonts.h>
+#endif
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+struct multiboot_fb_s
+{
+ void *baseaddr;
+ uint32_t height;
+ uint32_t width;
+ uint32_t pitch;
+ uint8_t bpp;
+ uint8_t type;
+};
+
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+struct fb_term_s
+{
+ const struct nx_fontpackage_s *font;
+ uint32_t cursor_x;
+ uint32_t cursor_y;
+};
+
+void fb_term_initialize(void);
+#endif /* CONFIG_MULTBOOT2_FB_TERM */
+
+void fb_clear(void);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct multiboot_fb_s fb =
+{
+ .baseaddr = NULL
+};
+
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+struct fb_term_s fb_term;
+#endif /* CONFIG_MULTBOOT2_FB_TERM */
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: fb_draw_pixel
+ *
+ * Description:
+ * Draw a pixel on the framebuffer. Note that the color paramter must
+ * be in the format specified by the bpp of the framebuffer.
+ *
+ ****************************************************************************/
+
+static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
+{
+ /* Check if we support this type of framebuffer */
+
+ if (fb.type != MULTIBOOT_FRAMEBUFFER_TYPE_RGB)
+ return;
+
+ /* Make sure we are within the bounds */
+
+ if (x >= fb.width || y >= fb.height)
+ return;
+
+ switch (fb.bpp)
+ {
+ case 8:
+ {
+ uint8_t *pixel = (uint8_t *)(
+ (uintptr_t)fb.baseaddr + (fb.pitch * y) + x);
+ *pixel = (uint8_t)color;
+ break;
+ }
+
+ case 15:
+ case 16:
+ {
+ uint16_t *pixel = (uint16_t *)(
+ (uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 2);
+ *pixel = (uint16_t)color;
+ break;
+ }
+
+ case 24:
+ {
+ /* We have to be careful here to not overwrite the lower 8bits
+ * of the next pixel in the buffer.
+ */
+
+ uint32_t *pixel = (uint32_t *)(
+ (uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 3);
+ *pixel = (color & 0xffffff) | (*pixel & 0xff000000);
+ break;
+ }
+
+ case 32:
+ {
+ uint32_t *pixel = (uint32_t *)(
+ (uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 4);
+ *pixel = color;
+ break;
+ }
+ }
+}
+
+#if 0
+/****************************************************************************
+ * Function: fb_test_line
+ *
+ * Description:
+ * This is a simple test function that can be used to draw a 45deg
+ * line across the screen.
+ *
+ ****************************************************************************/
+
+static void fb_test_line(void)
+{
+ size_t idx;
+ uint32_t color;
+
+ switch (fb.bpp)
+ {
+ case 8:
+ color = 0xff;
+ break;
+ case 15:
+ case 16:
+ color = 0x7fff;
+ break;
+ case 24:
+ color = 0xffffff;
+ break;
+ case 32:
+ color = 0xffffffff;
+ break;
+ default:
+ return;
+ }
+
+ for (idx = 0; (idx < fb.height) && (idx < fb.width); idx++)
+ {
+ fb_draw_pixel(color, idx, idx);
+ }
+}
+#endif
+
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+static void fb_scroll(void)
+{
+ void *destp = fb.baseaddr;
+ uint32_t save_rows = ((fb.height / fb_term.font->metrics.mxheight) - 1);
+ size_t row_size = fb.pitch * fb_term.font->metrics.mxheight;
+ uint32_t pxl_row = 0;
+
+ for (; pxl_row < save_rows * fb_term.font->metrics.mxheight; pxl_row++)
+ {
+ memcpy(destp, destp + row_size, fb.pitch);
+ destp += fb.pitch;
+ }
+
+ memset(destp, 0, fb.pitch * (fb.height - pxl_row));
+
+ fb_term.cursor_y -= fb_term.font->metrics.mxheight;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void x86_64_mb2_fbinitialize(struct multiboot_tag_framebuffer *fbt)
+{
+ fb.baseaddr = (void *)(uintptr_t)fbt->common.framebuffer_addr;
+ fb.width = fbt->common.framebuffer_width;
+ fb.height = fbt->common.framebuffer_height;
+ fb.pitch = fbt->common.framebuffer_pitch;
+ fb.bpp = fbt->common.framebuffer_bpp;
+ fb.type = fbt->common.framebuffer_type;
+
+ up_map_region(fb.baseaddr, fb.pitch * fb.height,
+ X86_PAGE_WR | X86_PAGE_PRESENT |
+ X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
+
+ fb_clear();
+
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+ fb_term_initialize();
+#endif
+
+}
+
+void fb_clear(void)
+{
+ if (fb.baseaddr == NULL)
+ return;
+
+ memset(fb.baseaddr, 0, fb.pitch * fb.height);
+}
+
+#ifdef CONFIG_MULTBOOT2_FB_TERM
+void fb_term_initialize(void)
+{
+ fb_term.font = nxf_getfonthandle(FONTID_DEFAULT);
+ fb_term.cursor_x = 0;
+ fb_term.cursor_y = 0;
+}
+
+void fb_putc(char ch)
+{
+ uint8_t gly_x;
+ uint8_t gly_y;
+ const struct nx_fontbitmap_s *fbm;
+
+ if (fb.baseaddr == NULL)
+ return;
+
+ if (ch == '\n')
+ {
+ fb_term.cursor_y += fb_term.font->metrics.mxheight;
+ return;
+ }
+
+ if (ch == '\r')
+ {
+ fb_term.cursor_x = 0;
+ return;
+ }
+
+ fbm = nxf_getbitmap((NXHANDLE)fb_term.font, ch);
+ if (fbm == NULL)
+ {
+ fb_putc('.');
+ return;
+ }
+
+ for (gly_y = 0; gly_y < fbm->metric.height; gly_y++)
+ {
+ if (fb_term.cursor_y + gly_y >= fb.height)
+ {
+ fb_scroll();
+ fb_putc(ch);
+ return;
+ }
+
+ for (gly_x = 0; gly_x < fbm->metric.width; gly_x++)
+ {
+ if (fb_term.cursor_x + gly_x >= fb.width)
+ {
+ break;
+ }
+
+ uint8_t stride = (fbm->metric.width + 7) >> 3;
+ uint8_t gly_byte = stride * gly_y + (gly_x >> 3);
+ uint8_t gly_bit = gly_x & 0x7;
+ uint32_t color = 0; /* Black no matter the color depth */
+ if ((fbm->bitmap[gly_byte] >> (7 - gly_bit)) & 0x01)
+ color = 0xffffffff; /* Black no matter the color depth */
+
+ fb_draw_pixel(
+ color, fb_term.cursor_x + gly_x, fb_term.cursor_y + gly_y);
+ }
+ }
+
+ fb_term.cursor_x += fbm->metric.width;
+}
+#endif /* CONFIG_MULTBOOT2_FB_TERM */
diff --git a/arch/x86_64/src/intel64/intel64_serial.c b/arch/x86_64/src/intel64/intel64_serial.c
index 00896fc1f8..dffd6304c9 100644
--- a/arch/x86_64/src/intel64/intel64_serial.c
+++ b/arch/x86_64/src/intel64/intel64_serial.c
@@ -97,6 +97,10 @@ int up_putc(int ch)
return ch;
}
+void up_lowputc(char ch)
+{
+ fb_putc(ch);
+}
#endif /* USE_SERIALDRIVER */
void x86_64_earlyserialinit(void)
diff --git a/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig b/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig
new file mode 100644
index 0000000000..3342336c68
--- /dev/null
+++ b/boards/x86_64/intel64/qemu-intel64/configs/earlyfb/defconfig
@@ -0,0 +1,72 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_SERIAL is not set
+CONFIG_ARCH="x86_64"
+CONFIG_ARCH_BOARD="qemu-intel64"
+CONFIG_ARCH_BOARD_INTEL64_QEMU=y
+CONFIG_ARCH_CHIP="intel64"
+CONFIG_ARCH_INTEL64_CORE_FREQ_KHZ=2600000
+CONFIG_ARCH_SIZET_LONG=y
+CONFIG_ARCH_X86_64=y
+CONFIG_BOARD_LOOPSPERMSEC=999
+CONFIG_BOOT_RUNFROMEXTSRAM=y
+CONFIG_BUILTIN=y
+CONFIG_CLOCK_MONOTONIC=y
+CONFIG_CONSOLE_SYSLOG=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_PCI=y
+CONFIG_DEBUG_PCI_ERROR=y
+CONFIG_DEBUG_PCI_INFO=y
+CONFIG_DEBUG_PCI_WARN=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DEBUG_WARN=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_EXAMPLES_HELLO_STACKSIZE=4194304
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=4194304
+CONFIG_LIBM=y
+CONFIG_MAX_TASKS=64
+CONFIG_MULTBOOT2_FB_TERM=y
+CONFIG_NFILE_DESCRIPTORS=32
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_IFCONFIG=y
+CONFIG_NSH_DISABLE_IFUPDOWN=y
+CONFIG_NSH_READLINE=y
+CONFIG_NXFONTS=y
+CONFIG_NXFONT_MONO5X8=y
+CONFIG_PREALLOC_CHILDSTATUS=16
+CONFIG_PRIORITY_INHERITANCE=y
+CONFIG_PTHREAD_MUTEX_TYPES=y
+CONFIG_PTHREAD_STACK_DEFAULT=4194304
+CONFIG_PTHREAD_STACK_MIN=4194304
+CONFIG_QEMU_PCI=y
+CONFIG_RAM_SIZE=268435456
+CONFIG_SCHED_CHILD_STATUS=y
+CONFIG_SCHED_HAVE_PARENT=y
+CONFIG_SCHED_IRQMONITOR=y
+CONFIG_SCHED_TICKLESS=y
+CONFIG_SCHED_TICKLESS_ALARM=y
+CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_SIG_DEFAULT=y
+CONFIG_START_DAY=3
+CONFIG_START_MONTH=3
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_CLE=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_TIME64=y
+CONFIG_USEC_PER_TICK=1
+CONFIG_USERMAIN_STACKSIZE=4194304
+CONFIG_USER_ENTRYPOINT="nsh_main"
+CONFIG_VIRT=y
+CONFIG_VIRT_QEMU_EDU=y
+CONFIG_VIRT_QEMU_PCI_TEST=y
(nuttx) 02/06: Various fixes for PCI work
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 69ed5bb67de73adae50c3e3afbab34f944eb14a2
Author: Brennan Ashton <ba...@brennanashton.com>
AuthorDate: Thu May 7 02:59:29 2020 -0700
Various fixes for PCI work
Squashed commits:
1. Porting prior PCI work in place of jailhouse code
At this point the PCI enumeration works for x86_64 including over
pci-pci bridges.
Running QEMU with this configuration we see the bridge and the
device on the bridge. It also detected the qemu test device
qemu-system-x86_64 \
-cpu host,+pcid,+x2apic,+tsc-deadline,+xsave,+rdrand \
--enable-kvm -smp 1 -m 2G -cdrom boot.iso --nographic -no-reboot \
-device pci-testdev \
-device pci-bridge,id=bridge0,chassis_nr=2 \
-device e1000,bus=bridge0,addr=0x3
qemu_pci_init: Initializing PCI Bus
pci_probe_device: [00:00.0] Found 8086:1237, class/revision 06000002
pci_probe_device: [00:01.1] Found 8086:7010, class/revision 01018000
pci_probe_device: [00:01.2] Found ffff:ffff, class/revision ffffffff
pci_probe_device: [00:01.3] Found 8086:7113, class/revision 06800003
pci_probe_device: [00:01.4] Found ffff:ffff, class/revision ffffffff
pci_probe_device: [00:01.5] Found ffff:ffff, class/revision ffffffff
pci_probe_device: [00:01.6] Found ffff:ffff, class/revision ffffffff
pci_probe_device: [00:01.7] Found ffff:ffff, class/revision ffffffff
pci_probe_device: [00:02.0] Found 1234:1111, class/revision 03000002
pci_probe_device: [00:03.0] Found 8086:100e, class/revision 02000003
pci_probe_device: [00:04.0] Found 1b36:0005, class/revision 00ff0000
pci_probe_device: [00:04.0] Probing
pci_check_pci_bridge: [00:05.0] Found Bridge
pci_probe_device: [01:03.0] Found 8086:100e, class/revision 02000003
pci_probe_device: [00:05.0] Found 1b36:0001, class/revision 06040000
2. Remove unused CONFIG_PCI_MAX_BDF option
3. Add a workaround for Jailhouse pci scanning
4. Extend BAR parsing and handle PIO and MMIO for pci-testdev
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
5. PCI: Add initial support for QEMU 'edu' test device
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
6. Bring up PCI later in boot process
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
7. Add ISR and DMA support to QEMU edu test pci device
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
8. Fix bad function prototype definition in qemu_edu
9. intel64: Add a pci test configuration and instructions
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
10. PCI: Fix issue in identification of 64bit bar
Signed-off-by: Brennan Ashton <ba...@brennanashton.com>
---
.../x86_64/qemu/boards/qemu-intel64/index.rst | 8 +
Kconfig | 31 +-
boards/x86_64/intel64/qemu-intel64/Kconfig | 8 +-
.../intel64/qemu-intel64/configs/pcitest/defconfig | 76 ++
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 -
.../x86_64/intel64/qemu-intel64/src/qemu_bringup.c | 5 +
.../x86_64/intel64/qemu-intel64/src/qemu_intel64.h | 2 +
boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c | 226 ++++++
boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c | 398 -----------
.../intel64/qemu-intel64/src/qemu_pcie_readwrite.h | 240 -------
drivers/Kconfig | 2 +-
drivers/Makefile | 2 +-
.../intel64/qemu-intel64 => drivers/pci}/Kconfig | 11 +-
drivers/{pcie => pci}/Make.defs | 14 +-
drivers/pci/pci.c | 792 +++++++++++++++++++++
drivers/pcie/Kconfig | 20 -
drivers/pcie/pcie_root.c | 446 ------------
drivers/virt/Kconfig | 9 +-
drivers/virt/Make.defs | 8 +-
drivers/virt/qemu_edu.c | 448 ++++++++++++
drivers/virt/qemu_pci_test.c | 201 +++++-
include/debug.h | 6 +-
include/nuttx/pci/pci.h | 458 ++++++++++++
include/nuttx/pcie/pcie.h | 352 ---------
include/nuttx/virt/qemu_pci.h | 6 +-
27 files changed, 2237 insertions(+), 1544 deletions(-)
diff --git a/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst b/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst
index 74c4349133..d1fe76186d 100644
--- a/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst
+++ b/Documentation/platforms/x86_64/qemu/boards/qemu-intel64/index.rst
@@ -71,6 +71,14 @@ Use control-a x to terminate the emulation.
P.S. Make sure that you CPU supports the mandatory features. Look at Real machine
section for more information.
+For testing the PCI bus and driver layers. This QEMU configuration can be used
+with the pcitest NuttX configuration::
+
+ qemu-system-x86_64 -cpu host,+pcid,+x2apic,+tsc-deadline,+xsave,+rdrand --enable-kvm -smp 1 -m 2G -cdrom boot.iso --nographic -s -no-reboot -device edu -device pci-testdev
+
+This will enable the QEMU pci-test and edu PCI test devices which test PIO, MMIO, IRQ, and DMA
+functions. Additionally it will show detailed information about the enumeration of the PCI bus.
+
Bochs
=====
diff --git a/Kconfig b/Kconfig
index a0d8b941c5..69c13823d9 100644
--- a/Kconfig
+++ b/Kconfig
@@ -2196,41 +2196,40 @@ config DEBUG_IPC_INFO
endif # DEBUG_IPC
-=======
-config DEBUG_PCIE
- bool "PCI-E Debug Features"
+config DEBUG_PCI
+ bool "PCI Debug Features"
default n
- depends on PCIE
+ depends on PCI
---help---
- Enable PCIE driver debug features.
+ Enable PCI driver debug features.
Support for this debug option is architecture-specific and may not
be available for some MCUs.
-if DEBUG_PCIE
+if DEBUG_PCI
-config DEBUG_PCIE_ERROR
- bool "PCI-E Error Output"
+config DEBUG_PCI_ERROR
+ bool "PCI Error Output"
default n
depends on DEBUG_ERROR
---help---
- Enable PCI-E driver error output to SYSLOG.
+ Enable PCI driver error output to SYSLOG.
-config DEBUG_PCIE_WARN
- bool "PCI-E Warnings Output"
+config DEBUG_PCI_WARN
+ bool "PCI Warnings Output"
default n
depends on DEBUG_WARN
---help---
- Enable PCI-E driver warning output to SYSLOG.
+ Enable PCI driver warning output to SYSLOG.
-config DEBUG_PCIE_INFO
- bool "PCI-E Informational Output"
+config DEBUG_PCI_INFO
+ bool "PCI Informational Output"
default n
depends on DEBUG_INFO
---help---
- Enable PCI-E driver informational output to SYSLOG.
+ Enable PCI driver informational output to SYSLOG.
-endif # DEBUG_PCIE
+endif # DEBUG_PCI
endif # DEBUG_FEATURES
config ARCH_HAVE_STACKCHECK
diff --git a/boards/x86_64/intel64/qemu-intel64/Kconfig b/boards/x86_64/intel64/qemu-intel64/Kconfig
index 595127192b..c9c77b73a4 100644
--- a/boards/x86_64/intel64/qemu-intel64/Kconfig
+++ b/boards/x86_64/intel64/qemu-intel64/Kconfig
@@ -3,10 +3,10 @@
# see the file kconfig-language.txt in the NuttX tools repository.
#
#
-config QEMU_PCIE
- bool "Initialize and enumerate PCI-E Bus"
+config QEMU_PCI
+ bool "Initialize and enumerate PCI Bus"
default n
- select PCIE
+ select PCI
---help---
- Enables initialization and scaning of standard x86-64 pcie bus.
+ Enables initialization and scanning of standard x86-64 pci bus.
diff --git a/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig b/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
new file mode 100644
index 0000000000..61e33fb0eb
--- /dev/null
+++ b/boards/x86_64/intel64/qemu-intel64/configs/pcitest/defconfig
@@ -0,0 +1,76 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+CONFIG_16550_ADDRWIDTH=16
+CONFIG_16550_UART0=y
+CONFIG_16550_UART0_BASE=0x3f8
+CONFIG_16550_UART0_CLOCK=1843200
+CONFIG_16550_UART0_IRQ=36
+CONFIG_16550_UART0_RXBUFSIZE=16
+CONFIG_16550_UART0_SERIAL_CONSOLE=y
+CONFIG_16550_UART0_TXBUFSIZE=16
+CONFIG_16550_UART=y
+CONFIG_ARCH="x86_64"
+CONFIG_ARCH_BOARD="qemu-intel64"
+CONFIG_ARCH_BOARD_INTEL64_QEMU=y
+CONFIG_ARCH_CHIP="intel64"
+CONFIG_ARCH_INTEL64_CORE_FREQ_KHZ=2600000
+CONFIG_ARCH_SIZET_LONG=y
+CONFIG_ARCH_X86_64=y
+CONFIG_BOARD_LOOPSPERMSEC=999
+CONFIG_BOOT_RUNFROMEXTSRAM=y
+CONFIG_BUILTIN=y
+CONFIG_CLOCK_MONOTONIC=y
+CONFIG_CONSOLE_SYSLOG=y
+CONFIG_DEBUG_ERROR=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_PCI=y
+CONFIG_DEBUG_PCI_ERROR=y
+CONFIG_DEBUG_PCI_INFO=y
+CONFIG_DEBUG_PCI_WARN=y
+CONFIG_DEBUG_WARN=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_EXAMPLES_HELLO_STACKSIZE=4194304
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=4194304
+CONFIG_LIBM=y
+CONFIG_MAX_TASKS=64
+CONFIG_NFILE_DESCRIPTORS=32
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_IFCONFIG=y
+CONFIG_NSH_DISABLE_IFUPDOWN=y
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_CHILDSTATUS=16
+CONFIG_PRIORITY_INHERITANCE=y
+CONFIG_PTHREAD_MUTEX_TYPES=y
+CONFIG_PTHREAD_STACK_DEFAULT=4194304
+CONFIG_PTHREAD_STACK_MIN=4194304
+CONFIG_QEMU_PCI=y
+CONFIG_RAM_SIZE=268435456
+CONFIG_SCHED_CHILD_STATUS=y
+CONFIG_SCHED_HAVE_PARENT=y
+CONFIG_SCHED_IRQMONITOR=y
+CONFIG_SCHED_TICKLESS=y
+CONFIG_SCHED_TICKLESS_ALARM=y
+CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_SIG_DEFAULT=y
+CONFIG_START_DAY=3
+CONFIG_START_MONTH=3
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEM_CLE=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_TIME64=y
+CONFIG_USEC_PER_TICK=1
+CONFIG_USERMAIN_STACKSIZE=4194304
+CONFIG_USER_ENTRYPOINT="nsh_main"
+CONFIG_VIRT=y
+CONFIG_VIRT_QEMU_EDU=y
+CONFIG_VIRT_QEMU_PCI_TEST=y
diff --git a/boards/x86_64/intel64/qemu-intel64/include/board.h b/boards/x86_64/intel64/qemu-intel64/include/board.h
index ae7b588407..9cb23e995b 100644
--- a/boards/x86_64/intel64/qemu-intel64/include/board.h
+++ b/boards/x86_64/intel64/qemu-intel64/include/board.h
@@ -66,8 +66,6 @@ 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 9ab32d1766..3441ce24e8 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/Makefile
+++ b/boards/x86_64/intel64/qemu-intel64/src/Makefile
@@ -26,8 +26,8 @@ ifeq ($(CONFIG_BOARDCTL),y)
CSRCS += qemu_appinit.c
endif
-ifeq ($(CONFIG_QEMU_PCIE),y)
- CSRCS += qemu_pcie.c
+ifeq ($(CONFIG_QEMU_PCI),y)
+ CSRCS += qemu_pci.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 d4b02b1926..32cdcb33ec 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c
@@ -66,12 +66,6 @@ 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_bringup.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_bringup.c
index 7cd5d55137..bf0112a4e5 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_bringup.c
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_bringup.c
@@ -57,5 +57,10 @@ int qemu_bringup(void)
}
#endif
+#ifdef CONFIG_QEMU_PCI
+ /* Initialization of system */
+
+ qemu_pci_init();
+#endif
return ret;
}
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h b/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h
index 9a711ee577..75989d0e25 100644
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h
@@ -48,6 +48,8 @@
* Public Function Prototypes
****************************************************************************/
+void qemu_pci_init(void);
+
int qemu_bringup(void);
#endif /* __ASSEMBLY__ */
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
new file mode 100644
index 0000000000..d2bbd79102
--- /dev/null
+++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c
@@ -0,0 +1,226 @@
+/****************************************************************************
+ * boards/x86_64/intel64/qemu-intel64/src/qemu_pci.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/pci/pci.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define PCI_CFG_ADDR 0xcf8
+#define PCI_DATA_ADDR 0xcfc
+#define PCI_CFG_EN (1 << 31)
+
+/****************************************************************************
+ * Private Functions Definitions
+ ****************************************************************************/
+
+static void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
+ uint32_t val, int width);
+
+static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
+ int width);
+
+static int qemu_pci_map_bar(uint64_t addr, uint64_t len);
+
+static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width);
+
+static void qemu_pci_io_write(FAR const volatile void *addr, uint32_t val,
+ int width);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+struct pci_bus_ops_s qemu_pci_bus_ops =
+{
+ .pci_cfg_write = qemu_pci_cfg_write,
+ .pci_cfg_read = qemu_pci_cfg_read,
+ .pci_map_bar = qemu_pci_map_bar,
+ .pci_io_read = qemu_pci_io_read,
+ .pci_io_write = qemu_pci_io_write,
+};
+
+struct pci_bus_s qemu_pci_bus =
+{
+ .ops = &qemu_pci_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
+ * reg - 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 void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
+ uint32_t val, int width)
+{
+ uint8_t offset_mask = (4 - width);
+ outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
+ switch (width)
+ {
+ case 1:
+ outb(val, PCI_DATA_ADDR + (reg & offset_mask));
+ return;
+ case 2:
+ outw(val, PCI_DATA_ADDR + (reg & offset_mask));
+ return;
+ case 4:
+ outl(val, PCI_DATA_ADDR);
+ return;
+ default:
+ pcierr("Invalid cfg write width %d\n", width);
+ }
+}
+
+/****************************************************************************
+ * 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 uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
+ int width)
+{
+ uint32_t ret;
+ uint8_t offset_mask = 4 - width;
+ outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
+
+ switch (width)
+ {
+ case 1:
+ ret = inb(PCI_DATA_ADDR + (reg & offset_mask));
+ return ret;
+
+ case 2:
+ ret = inw(PCI_DATA_ADDR + (reg & offset_mask));
+ return ret;
+ case 4:
+ ret = inl(PCI_DATA_ADDR);
+ return ret;
+ default:
+ pcierr("Invalid cfg read width %d\n", width);
+ }
+
+ return 0;
+}
+
+static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width)
+{
+ uint16_t portaddr = (uint16_t)(intptr_t)addr;
+ switch (width)
+ {
+ case 1:
+ return (uint32_t)inb(portaddr);
+ case 2:
+ return (uint32_t)inw(portaddr);
+ case 4:
+ return (uint32_t)inl(portaddr);
+ default:
+ pcierr("Invalid read width %d\n", width);
+ DEBUGPANIC();
+ }
+
+ return 0;
+}
+
+static void qemu_pci_io_write(FAR const volatile void *addr, uint32_t val,
+ int width)
+{
+ uint16_t portaddr = (uint16_t)(intptr_t)addr;
+ switch (width)
+ {
+ case 1:
+ outb((uint8_t)val, portaddr);
+ return;
+ case 2:
+ outw((uint8_t)val, portaddr);
+ return;
+ case 4:
+ outl((uint8_t)val, portaddr);
+ return;
+ default:
+ pcierr("Invalid write width %d\n", width);
+ DEBUGPANIC();
+ }
+}
+
+static int qemu_pci_map_bar(uint64_t addr, uint64_t len)
+{
+ up_map_region((void *)(uintptr_t)addr, len,
+ X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
+ return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: qemu_pci_init
+ *
+ * Description:
+ * Initialize the PCI-E bus *
+ *
+ ****************************************************************************/
+
+void qemu_pci_init(void)
+{
+ pciinfo("Initializing PCI Bus\n");
+ pci_initialize(&qemu_pci_bus);
+}
diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c
deleted file mode 100644
index 0580593fad..0000000000
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie.c
+++ /dev/null
@@ -1,398 +0,0 @@
-/****************************************************************************
- * 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
deleted file mode 100644
index 01fc2712fe..0000000000
--- a/boards/x86_64/intel64/qemu-intel64/src/qemu_pcie_readwrite.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/****************************************************************************
- * 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 */
diff --git a/drivers/Kconfig b/drivers/Kconfig
index da93ca190f..22603be331 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -59,5 +59,5 @@ source "drivers/usrsock/Kconfig"
source "drivers/dma/Kconfig"
source "drivers/devicetree/Kconfig"
source "drivers/reset/Kconfig"
-source "drivers/pcie/Kconfig"
+source "drivers/pci/Kconfig"
source "drivers/virt/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index f5584c5370..40ed2d38af 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -77,7 +77,7 @@ include rc/Make.defs
include segger/Make.defs
include usrsock/Make.defs
include reset/Make.defs
-include pcie/Make.defs
+include pci/Make.defs
include virt/Make.defs
ifeq ($(CONFIG_SPECIFIC_DRIVERS),y)
diff --git a/boards/x86_64/intel64/qemu-intel64/Kconfig b/drivers/pci/Kconfig
similarity index 51%
copy from boards/x86_64/intel64/qemu-intel64/Kconfig
copy to drivers/pci/Kconfig
index 595127192b..85aa4a7988 100644
--- a/boards/x86_64/intel64/qemu-intel64/Kconfig
+++ b/drivers/pci/Kconfig
@@ -2,11 +2,10 @@
# 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
+menuconfig PCI
+ bool "Support for PCI Bus"
+ default n
---help---
- Enables initialization and scaning of standard x86-64 pcie bus.
+ Enables support for the PCI bus.
+ Backend bust be provided by per-arch or per-board implementation.
diff --git a/drivers/pcie/Make.defs b/drivers/pci/Make.defs
similarity index 85%
rename from drivers/pcie/Make.defs
rename to drivers/pci/Make.defs
index 68efee8123..d890993e62 100644
--- a/drivers/pcie/Make.defs
+++ b/drivers/pci/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# drivers/pcie/Make.defs
+# drivers/pci/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -20,13 +20,13 @@
# Don't build anything if there is no CAN support
-ifeq ($(CONFIG_PCIE),y)
+ifeq ($(CONFIG_PCI),y)
-CSRCS += pcie_root.c
+CSRCS += pci.c
-# Include PCIE device driver build support
+# Include PCI device driver build support
-DEPPATH += --dep-path pcie
-VPATH += :pcie
-CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)pcie}
+DEPPATH += --dep-path pci
+VPATH += :pci
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)pci}
endif
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
new file mode 100644
index 0000000000..0ae67a515d
--- /dev/null
+++ b/drivers/pci/pci.c
@@ -0,0 +1,792 @@
+/****************************************************************************
+ * nuttx/drivers/pci/pci.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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/pci/pci.h>
+#include <nuttx/virt/qemu_pci.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* For now hard code jailhouse as a flag. In the future we can determine this
+ * by looking at the CPUID base for "Jailhouse\0\0\0"
+ */
+
+#define JAILHOUSE_ENABLED 1
+
+#define PCI_BDF(bus, slot, func) (((uint32_t)bus << 8) | \
+ ((uint32_t)slot << 3) | \
+ func)
+
+/****************************************************************************
+ * Private Functions Definitions
+ ****************************************************************************/
+
+static void pci_probe_device(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx, uint8_t slot_idx, uint8_t func,
+ FAR struct pci_dev_type_s **types);
+
+static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx, uint8_t slot_idx,
+ uint8_t dev_func);
+
+static void pci_scan_device(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx, uint8_t slot_idx,
+ FAR struct pci_dev_type_s **types);
+
+static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx,
+ FAR struct pci_dev_type_s **types);
+
+static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask);
+
+static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+struct pci_dev_type_s *pci_device_types[] =
+{
+#ifdef CONFIG_VIRT_QEMU_PCI_TEST
+ &pci_type_qemu_pci_test,
+#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
+#ifdef CONFIG_VIRT_QEMU_EDU
+ &pci_type_qemu_edu,
+#endif /* CONFIG_VIRT_QEMU_EDU */
+ NULL,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pci_probe
+ *
+ * Description:
+ * Checks if the specified device is supported and if so calls probe on it
+ *
+ * Input Parameters:
+ * root_bus - The root bus device that lets us address the whole tree
+ * bus - Bus ID
+ * slot - Device Slot
+ * func - Device Function
+ * types - List of pointers to devices types recognized, NULL terminated
+ *
+ ****************************************************************************/
+
+static void pci_probe_device(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx, uint8_t slot_idx, uint8_t func,
+ FAR struct pci_dev_type_s **types)
+{
+ struct pci_dev_s tmp_dev;
+ uint16_t vid;
+ uint16_t id;
+ uint32_t class_rev;
+
+ tmp_dev.bus = root_bus;
+ tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, func);
+
+ vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
+ id = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_DEVICE, 2);
+
+ /* This is reading rev prog_if subclass and class */
+
+ class_rev = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_REV_ID, 4);
+
+ pci_dev_dump(&tmp_dev);
+
+ for (int i = 0; types[i] != NULL; i++)
+ {
+ if (types[i]->vendor == PCI_ID_ANY ||
+ types[i]->vendor == vid)
+ {
+ if (types[i]->device == PCI_ID_ANY ||
+ types[i]->device == id)
+ {
+ if (types[i]->class_rev == PCI_ID_ANY ||
+ types[i]->class_rev == class_rev)
+ {
+ pciinfo("Found: %s\n", types[i]->name);
+ if (types[i]->probe)
+ {
+ pciinfo("[%02x:%02x.%x] Probing\n",
+ bus_idx, slot_idx, func);
+ types[i]->probe(root_bus, types[i], tmp_dev.bdf);
+ }
+ else
+ {
+ pcierr("[%02x:%02x.%x] Error: Invalid \
+ device probe function\n",
+ bus_idx, slot_idx, func);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: pci_check_pci_bridge
+ *
+ * Description:
+ * Checks if the specified device is PCI bridge and return the sub-bridge
+ * idx if found. Otherwise return 0.
+ *
+ * Input Parameters:
+ * root_bus - The root bus device that lets us address the whole tree
+ * bus - Bus ID
+ * slot - Device Slot
+ * func - Device Function
+ *
+ ****************************************************************************/
+
+static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx, uint8_t slot_idx,
+ uint8_t dev_func)
+{
+ struct pci_dev_s tmp_dev;
+ uint8_t base_class;
+ uint8_t sub_class;
+ uint8_t secondary_bus;
+
+ tmp_dev.bus = root_bus;
+ tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
+
+ /* Check if this is a PCI-PCI bridge device */
+
+ base_class = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_CLASS, 1);
+ sub_class = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_SUBCLASS, 1);
+
+ if ((base_class == PCI_CLASS_BASE_BRG_DEV) && \
+ (sub_class == PCI_CLASS_SUB_PCI_BRG))
+ {
+ /* This is a bridge device we need to determin the bus idx and
+ * enumerate it just like we do the root.
+ */
+
+ pciinfo("[%02x:%02x.%x] Found Bridge\n",
+ bus_idx, slot_idx, dev_func);
+
+ secondary_bus = root_bus->ops->pci_cfg_read(
+ &tmp_dev, PCI_CONFIG_SEC_BUS, 1);
+ return secondary_bus;
+ }
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: pci_scan_device
+ *
+ * Description:
+ * Checks if the specified device is a bus and iterates over it or
+ * if it is a real device initializes it if recognized.
+ *
+ * Input Parameters:
+ * root_bus - The root bus device that lets us address the whole tree
+ * bus - Bus ID
+ * slot - Device Slot
+ * types - List of pointers to devices types recognized, NULL terminated
+ *
+ ****************************************************************************/
+
+static void pci_scan_device(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx, uint8_t slot_idx,
+ FAR struct pci_dev_type_s **types)
+{
+ struct pci_dev_s tmp_dev;
+ uint8_t dev_func = 0;
+ uint16_t vid;
+ uint8_t sec_bus;
+ uint8_t multi_function;
+
+ tmp_dev.bus = root_bus;
+ tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
+ vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
+ if (vid == 0xffff)
+ return;
+
+ /* Check if this is a PCI-PCI bridge device */
+
+ sec_bus = pci_check_pci_bridge(root_bus, bus_idx, slot_idx, dev_func);
+ if (sec_bus)
+ pci_scan_bus(root_bus, sec_bus, types);
+
+ multi_function = root_bus->ops->pci_cfg_read(
+ &tmp_dev, PCI_CONFIG_HEADER_TYPE, 1) & PCI_HEADER_MASK_MULTI;
+
+ /* Jailhouse breaks the PCI spec by allowing you to pass individual
+ * functions of a multi-function device. In this case we need to
+ * scan each of the functions not just function 0.
+ */
+
+ if (multi_function || JAILHOUSE_ENABLED)
+ {
+ /* This is a multi-function device that we need to iterate over */
+
+ for (dev_func = 0; dev_func < 8; dev_func++)
+ {
+ tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
+ vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
+ if (vid != 0xffff)
+ {
+ sec_bus = pci_check_pci_bridge(
+ root_bus, bus_idx, slot_idx, dev_func);
+ if (sec_bus)
+ {
+ pci_scan_bus(root_bus, sec_bus, types);
+ continue;
+ }
+
+ pci_probe_device(root_bus, bus_idx, slot_idx, dev_func, types);
+ }
+ }
+ }
+ else
+ {
+ pci_probe_device(root_bus, bus_idx, slot_idx, dev_func, types);
+ }
+}
+
+/****************************************************************************
+ * Name: pci_scan_bus
+ *
+ * Description:
+ * Iterates over all slots on bus looking for devices and buses to
+ * enumerate.
+ *
+ * Input Parameters:
+ * root_bus - The root bus device that lets us address the whole tree
+ * bus - Bus ID
+ * types - List of pointers to devices types recognized, NULL terminated
+ *
+ ****************************************************************************/
+
+static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
+ uint8_t bus_idx,
+ FAR struct pci_dev_type_s **types)
+{
+ uint8_t slot_idx;
+
+ for (slot_idx = 0; slot_idx < 32; slot_idx++)
+ {
+ pci_scan_device(root_bus, bus_idx, slot_idx, types);
+ }
+
+ return;
+}
+
+/****************************************************************************
+ * Name: pci_set_cmd_bit
+ *
+ * Description:
+ * This sets an individual bit in the command register for a device.
+ *
+ * Input Parameters:
+ * dev - device
+ * bit - Bit to set
+ *
+ ****************************************************************************/
+
+static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
+{
+ uint16_t cmd;
+
+ cmd = dev->bus->ops->pci_cfg_read(dev, PCI_CONFIG_COMMAND, 2);
+ dev->bus->ops->pci_cfg_write(dev, PCI_CONFIG_COMMAND,
+ (cmd | bitmask), 2);
+}
+
+/****************************************************************************
+ * Name: pci_clear_cmd_bit
+ *
+ * Description:
+ * This clears an individual bit in the command register for a device.
+ *
+ * Input Parameters:
+ * dev - device
+ * bit - Bit to set
+ *
+ ****************************************************************************/
+
+static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
+{
+ uint16_t cmd;
+
+ cmd = dev->bus->ops->pci_cfg_read(dev, PCI_CONFIG_COMMAND, 2);
+ dev->bus->ops->pci_cfg_write(dev, PCI_CONFIG_COMMAND,
+ (cmd & ~bitmask), 2);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pci_enumerate
+ *
+ * Description:
+ * Scan the PCI bus and enumerate the devices.
+ * Initialize any recognized devices, given in types.
+ *
+ * Input Parameters:
+ * bus - PCI-E bus structure
+ * types - List of pointers to devices types recognized, NULL terminated
+ *
+ * Returned Value:
+ * 0: success, <0: A negated errno
+ *
+ ****************************************************************************/
+
+int pci_enumerate(FAR struct pci_bus_s *bus,
+ FAR struct pci_dev_type_s **types)
+{
+ if (!bus)
+ return -EINVAL;
+ if (!types)
+ return -EINVAL;
+
+ pci_scan_bus(bus, 0, types);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_initialize
+ *
+ * Description:
+ * Initialize the PCI-E bus and enumerate the devices with give devices
+ * type array
+ *
+ * Input Parameters:
+ * bus - An PCIE bus
+ * types - A array of PCIE device types
+ * num - Number of device types
+ *
+ * Returned Value:
+ * OK if the driver was successfully register; A negated errno value is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+int pci_initialize(FAR struct pci_bus_s *bus)
+{
+ return pci_enumerate(bus, pci_device_types);
+}
+
+/****************************************************************************
+ * Name: pci_enable_io
+ *
+ * Description:
+ * Enable MMIO or IOPORT
+ *
+ * Input Parameters:
+ * dev - device
+ * space - which resource is being enabled
+ * PCI_SYS_RES_IOPORT for io port address decoding or
+ * PCI_SYS_RES_MEM for memory
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_enable_io(FAR struct pci_dev_s *dev, int res)
+{
+ switch (res)
+ {
+ case PCI_SYS_RES_IOPORT:
+ pci_set_cmd_bit(dev, PCI_CMD_IO_SPACE);
+ return OK;
+ case PCI_SYS_RES_MEM:
+ pci_set_cmd_bit(dev, PCI_CMD_MEM_SPACE);
+ return OK;
+ }
+
+ return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: pci_disable_io
+ *
+ * Description:
+ * Enable MMIO or IOPORT
+ *
+ * Input Parameters:
+ * dev - device
+ * space - which resource is being disabled
+ * PCI_SYS_RES_IOPORT for io port address decoding or
+ * PCI_SYS_RES_MEM for memory
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_disable_io(FAR struct pci_dev_s *dev, int res)
+{
+ switch (res)
+ {
+ case PCI_SYS_RES_IOPORT:
+ pci_clear_cmd_bit(dev, PCI_CMD_IO_SPACE);
+ return OK;
+ case PCI_SYS_RES_MEM:
+ pci_clear_cmd_bit(dev, PCI_CMD_MEM_SPACE);
+ return OK;
+ }
+
+ return -EINVAL;
+}
+
+/****************************************************************************
+ * Name: pci_enable_bus_master
+ *
+ * Description:
+ * Enable bus mastering for device so it can perform PCI accesses
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_enable_bus_master(FAR struct pci_dev_s *dev)
+{
+ pci_set_cmd_bit(dev, PCI_CMD_BUS_MSTR);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_disable_bus_master
+ *
+ * Description:
+ * Disable bus mastering for device
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_disable_bus_master(FAR struct pci_dev_s *dev)
+{
+ pci_clear_cmd_bit(dev, PCI_CMD_BUS_MSTR);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_bar_valid
+ *
+ * Description:
+ * Determine in if the address in the BAR is valid
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_bar_valid(FAR struct pci_dev_s *dev, uint8_t bar_id)
+{
+ uint32_t bar = dev->bus->ops->pci_cfg_read(dev,
+ PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
+
+ if (bar == PCI_BAR_INVALID)
+ {
+ return -EINVAL;
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: pci_bar_is_64
+ *
+ * Description:
+ * Determine in if the bar address is 64 bit. If it is the address includes
+ * the address in the next bar location.
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * true: 64bit address
+ *
+ ****************************************************************************/
+
+bool pci_bar_is_64(FAR struct pci_dev_s *dev, uint8_t bar_id)
+{
+ uint32_t bar = dev->bus->ops->pci_cfg_read(dev,
+ PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
+
+ /* Check that it is memory and not io port */
+
+ if ((bar & PCI_BAR_LAYOUT_MASK) != PCI_BAR_LAYOUT_MEM)
+ return false;
+
+ if (((bar & PCI_BAR_TYPE_MASK) >> PCI_BAR_TYPE_OFFSET) == PCI_BAR_TYPE_64)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+/****************************************************************************
+ * Name: pci_bar_size
+ *
+ * Description:
+ * Determine the size of the address space required by the BAR
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * Size of address space
+ *
+ ****************************************************************************/
+
+uint64_t pci_bar_size(FAR struct pci_dev_s *dev, uint8_t bar_id)
+{
+ uint32_t bar;
+ uint32_t size;
+ uint64_t full_size;
+ uint8_t bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
+ const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+
+ bar = dev_ops->pci_cfg_read(dev, bar_offset, 4);
+
+ /* Write all 1 to the BAR. We are looking for which bits will change */
+
+ dev_ops->pci_cfg_write(dev, bar_offset, 0xffffffff, 4);
+ full_size = dev_ops->pci_cfg_read(dev, bar_offset, 4);
+
+ /* Resore BAR to original values */
+
+ dev_ops->pci_cfg_write(dev, bar_offset, bar, 4);
+
+ if (full_size == 0)
+ {
+ /* This is not a valid bar */
+
+ return 0;
+ }
+
+ if ((bar & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
+ {
+ full_size &= PCI_BAR_MEM_BASE_MASK;
+ }
+ else
+ {
+ full_size &= PCI_BAR_IO_BASE_MASK;
+ }
+
+ /* If it is 64 bit address check the next bar as well */
+
+ if (pci_bar_is_64(dev, bar_id))
+ {
+ bar_offset += 4;
+ bar = dev_ops->pci_cfg_read(dev, bar_offset, 4);
+ dev_ops->pci_cfg_write(dev, bar_offset, 0xffffffff, 4);
+ size = dev_ops->pci_cfg_read(dev, bar_offset, 4);
+ dev_ops->pci_cfg_write(dev, bar_offset, bar, 4);
+ full_size |= ((uint64_t)size << 32);
+ }
+ else
+ {
+ full_size |= (uint64_t)(0xffffffff) << 32;
+ }
+
+ return ~full_size + 1;
+}
+
+/****************************************************************************
+ * Name: pci_bar_addr
+ *
+ * Description:
+ * Determine the size of the address space required by the BAR
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * full bar address
+ *
+ ****************************************************************************/
+
+uint64_t pci_bar_addr(FAR struct pci_dev_s *dev, uint8_t bar_id)
+{
+ uint64_t addr;
+ uint8_t bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
+ const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+
+ addr = dev_ops->pci_cfg_read(dev, bar_offset, 4);
+
+ if ((addr & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
+ {
+ addr &= PCI_BAR_MEM_BASE_MASK;
+ }
+ else
+ {
+ addr &= PCI_BAR_IO_BASE_MASK;
+ }
+
+ /* If it is 64 bit address check the next bar as well */
+
+ if (pci_bar_is_64(dev, bar_id))
+ {
+ bar_offset += 4;
+ addr |= (uint64_t)(dev_ops->pci_cfg_read(dev, bar_offset, 4)) << 32;
+ }
+
+ return addr;
+}
+
+/****************************************************************************
+ * Name: pci_dev_dump
+ *
+ * Description:
+ * Dump the configuration information for the device
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ ****************************************************************************/
+
+void pci_dev_dump(FAR struct pci_dev_s *dev)
+{
+ uint8_t bar_id;
+ uint8_t bar_mem_type = 0;
+ uint32_t bar;
+ uint64_t bar_size;
+ uint64_t bar_addr;
+
+ uint8_t cap_id;
+ uint8_t cap_offset;
+
+ const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
+ uint32_t bdf = dev->bdf;
+ uint16_t vid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_VENDOR, 2);
+ uint16_t pid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_DEVICE, 2);
+ uint8_t header = dev_ops->pci_cfg_read(dev, PCI_CONFIG_HEADER_TYPE, 1);
+ uint8_t progif = dev_ops->pci_cfg_read(dev, PCI_CONFIG_PROG_IF, 1);
+ uint8_t subclass = dev_ops->pci_cfg_read(dev, PCI_CONFIG_SUBCLASS, 1);
+ uint8_t class = dev_ops->pci_cfg_read(dev, PCI_CONFIG_CLASS, 1);
+ uint8_t int_pin;
+ uint8_t int_line;
+
+ pciinfo("[%02x:%02x.%x] %04x:%04x\n",
+ bdf >> 8, (bdf & 0xff) >> 3, bdf & 0x7, vid, pid);
+ pciinfo("\ttype %02x Prog IF %02x Class %02x Subclass %02x\n",
+ header, progif, class, subclass);
+
+ cap_offset = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_CAP, 1);
+ while (cap_offset)
+ {
+ cap_id = dev_ops->pci_cfg_read(dev, cap_offset, 1);
+ if (cap_id > PCI_CAP_ID_END)
+ {
+ pcierr("Invalid PCI Capability Found, Skipping. %d\n", cap_id);
+ DEBUGPANIC();
+ break;
+ }
+
+ pciinfo("\tCAP %02x\n", cap_id);
+ cap_offset = dev_ops->pci_cfg_read(dev, cap_offset + 1, 1);
+ }
+
+ if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_NORMAL)
+ return;
+
+ int_pin = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_INT_PIN, 1);
+ int_line = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_INT_LINE, 1);
+ pciinfo("\tINT Pin %02x Line %02x\n", int_pin, int_line);
+
+ for (bar_id = 0; bar_id < PCI_BAR_CNT; bar_id++)
+ {
+ if (pci_bar_valid(dev, bar_id) != OK)
+ continue;
+
+ bar = dev_ops->pci_cfg_read(dev,
+ PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
+
+ bar_size = pci_bar_size(dev, bar_id);
+ bar_addr = pci_bar_addr(dev, bar_id);
+ if ((bar & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
+ {
+ switch ((bar & PCI_BAR_TYPE_MASK) >> PCI_BAR_TYPE_OFFSET)
+ {
+ case PCI_BAR_TYPE_64:
+ bar_mem_type = 64;
+ break;
+ case PCI_BAR_TYPE_32:
+ bar_mem_type = 32;
+ break;
+ case PCI_BAR_TYPE_16:
+ bar_mem_type = 16;
+ break;
+ default:
+ bar_mem_type = 0;
+ }
+
+ pciinfo("\tBAR [%d] MEM %db range %p-%p (%p)\n",
+ bar_id, bar_mem_type,
+ bar_addr, bar_addr + bar_size - 1, bar_size);
+ }
+ else
+ {
+ pciinfo("\tBAR [%d] PIO range %p-%p (%p)\n",
+ bar_id,
+ bar_addr, bar_addr + bar_size - 1, bar_size);
+ }
+
+ /* Skip next bar if this one was 64bit */
+
+ if (bar_mem_type == 64)
+ bar_id++;
+ }
+}
diff --git a/drivers/pcie/Kconfig b/drivers/pcie/Kconfig
deleted file mode 100644
index 7ac9db568b..0000000000
--- a/drivers/pcie/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see the file kconfig-language.txt in the NuttX tools repository.
-#
-
-menuconfig PCIE
- bool "Support for PCI-E Bus"
- default n
- ---help---
- Enables support for the PCI-E bus.
- Backend bust be provided by per-arch or per-board implementation..
-
-if PCIE
-config PCIE_MAX_BDF
- hex "Maximum bdf to scan on PCI-E bus"
- default 0x10000
- ---help---
- The maximum bdf number to be scaned on PCI-E bus
-
-endif
diff --git a/drivers/pcie/pcie_root.c b/drivers/pcie/pcie_root.c
deleted file mode 100644
index b85c5862fa..0000000000
--- a/drivers/pcie/pcie_root.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/****************************************************************************
- * nuttx/drivers/pcie/pcie_root.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.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <assert.h>
-#include <errno.h>
-#include <debug.h>
-
-#include <nuttx/pcie/pcie.h>
-#include <nuttx/virt/qemu_pci.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-struct pcie_dev_type_s *pci_device_types[] =
-{
-#ifdef CONFIG_VIRT_QEMU_PCI_TEST
- &pcie_type_qemu_pci_test,
-#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
- NULL,
-};
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: pci_enumerate
- *
- * Description:
- * Scan the PCI bus and enumerate the devices.
- * Initialize any recognized devices, given in types.
- *
- * Input Parameters:
- * bus - PCI-E bus structure
- * type - List of pointers to devices types recognized, NULL terminated
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_enumerate(FAR struct pcie_bus_s *bus,
- FAR struct pcie_dev_type_s **types)
-{
- unsigned int bdf;
- uint16_t vid;
- uint16_t id;
- uint16_t rev;
- struct pcie_dev_s tmp_dev;
- struct pcie_dev_type_s tmp_type =
- {
- .name = "Unknown",
- .vendor = PCI_ID_ANY,
- .device = PCI_ID_ANY,
- .class_rev = PCI_ID_ANY,
- .probe = NULL,
- };
-
- if (!bus)
- return -EINVAL;
- if (!types)
- return -EINVAL;
-
- for (bdf = 0; bdf < CONFIG_PCIE_MAX_BDF; bdf++)
- {
- tmp_dev.bus = bus;
- tmp_dev.type = &tmp_type;
- tmp_dev.bdf = bdf;
-
- bus->ops->pci_cfg_read(&tmp_dev, PCI_CFG_VENDOR_ID, &vid, 2);
- bus->ops->pci_cfg_read(&tmp_dev, PCI_CFG_DEVICE_ID, &id, 2);
- bus->ops->pci_cfg_read(&tmp_dev, PCI_CFG_REVERSION, &rev, 2);
-
- if (vid == PCI_ID_ANY)
- continue;
-
- pciinfo("[%02x:%02x.%x] Found %04x:%04x, class/reversion %08x\n",
- bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3,
- vid, id, rev);
-
- for (int i = 0; types[i] != NULL; i++)
- {
- if (types[i]->vendor == PCI_ID_ANY ||
- types[i]->vendor == vid)
- {
- if (types[i]->device == PCI_ID_ANY ||
- types[i]->device == id)
- {
- if (types[i]->class_rev == PCI_ID_ANY ||
- types[i]->class_rev == rev)
- {
- if (types[i]->probe)
- {
- pciinfo("[%02x:%02x.%x] %s\n",
- bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3,
- types[i]->name);
- types[i]->probe(bus, types[i], bdf);
- }
- else
- {
- pcierr("[%02x:%02x.%x] Error: Invalid \
- device probe function\n",
- bdf >> 8, (bdf >> 3) & 0x1f, bdf & 0x3);
- }
- break;
- }
- }
- }
- }
- }
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pcie_initialize
- *
- * Description:
- * Initialize the PCI-E bus and enumerate the devices with give devices
- * type array
- *
- * Input Parameters:
- * bus - An PCIE bus
- * types - A array of PCIE device types
- * num - Number of device types
- *
- * Returned Value:
- * OK if the driver was successfully register; A negated errno value is
- * returned on any failure.
- *
- ****************************************************************************/
-
-int pcie_initialize(FAR struct pcie_bus_s *bus)
-{
- return pci_enumerate(bus, pci_device_types);
-}
-
-/****************************************************************************
- * Name: pci_enable_device
- *
- * Description:
- * Enable device with MMIO
- *
- * Input Parameters:
- * dev - device
- *
- * Return value:
- * -EINVAL: error
- * OK: OK
- *
- ****************************************************************************/
-
-int pci_enable_device(FAR struct pcie_dev_s *dev)
-{
- uint16_t old_cmd;
- uint16_t cmd;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_COMMAND, &old_cmd, 2);
-
- cmd = old_cmd | (PCI_CMD_MASTER | PCI_CMD_MEM);
-
- dev->bus->ops->pci_cfg_write(dev, PCI_CFG_COMMAND, &cmd, 2);
-
- pciinfo("%02x:%02x.%x, CMD: %x -> %x\n",
- dev->bdf >> 8, (dev->bdf >> 3) & 0x1f, dev->bdf & 0x3,
- old_cmd, cmd);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pci_find_cap
- *
- * Description:
- * Search through the PCI-e device capability list to find given capability.
- *
- * Input Parameters:
- * dev - Device
- * cap - Bitmask of capability
- *
- * Returned Value:
- * -1: Capability not supported
- * other: the offset in PCI configuration space to the capability structure
- *
- ****************************************************************************/
-
-int pci_find_cap(FAR struct pcie_dev_s *dev, uint16_t cap)
-{
- uint8_t pos = PCI_CFG_CAP_PTR - 1;
- uint16_t status;
- uint8_t rcap;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_STATUS, &status, 2);
-
- if (!(status & PCI_STS_CAPS))
- return -EINVAL;
-
- while (1)
- {
- dev->bus->ops->pci_cfg_read(dev, pos + 1, &pos, 1);
- if (pos == 0)
- return -EINVAL;
-
- dev->bus->ops->pci_cfg_read(dev, pos, &rcap, 1);
-
- if (rcap == cap)
- return pos;
- }
-}
-
-/****************************************************************************
- * Name: pci_get_bar
- *
- * Description:
- * Get a 32 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * ret - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_get_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint32_t *ret)
-{
- if (bar > 5)
- return -EINVAL;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, ret, 4);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pci_get_bar64
- *
- * Description:
- * Get a 64 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * ret - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_get_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint64_t *ret)
-{
- if (bar > 4 || ((bar % 2) != 0))
- return -EINVAL;
-
- uint32_t barmem1;
- uint32_t barmem2;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4);
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4);
-
- *ret = ((uint64_t)barmem2 << 32) | barmem1;
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pci_set_bar
- *
- * Description:
- * Set a 32 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * val - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_set_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint32_t val)
-{
- if (bar > 5)
- return -EINVAL;
-
- dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4, &val, 4);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pci_set_bar64
- *
- * Description:
- * Set a 64 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * val - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_set_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint64_t val)
-{
- if (bar > 4 || ((bar % 2) != 0))
- return -EINVAL;
-
- uint32_t barmem1 = (uint32_t)val;
- uint32_t barmem2 = (uint32_t)(val >> 32);
-
- dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4);
- dev->bus->ops->pci_cfg_write(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4);
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pci_map_bar
- *
- * Description:
- * Map address in a 32 bits bar in the flat memory address space
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * length - Map length, multiple of PAGE_SIZE
- * ret - Bar Content if not NULL
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
- unsigned long length, uint32_t *ret)
-{
- if (bar > 5)
- return -EINVAL;
-
- uint32_t barmem;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem, 4);
-
- if (((bar % 2) == 0 &&
- (barmem & PCI_BAR_64BIT) == PCI_BAR_64BIT) ||
- (barmem & PCI_BAR_IO) == PCI_BAR_IO)
- return -EINVAL;
-
- if (!dev->bus->ops->pci_map_bar)
- return -EINVAL;
-
- dev->bus->ops->pci_map_bar(dev, barmem, length);
-
- if (ret)
- *ret = barmem;
-
- return OK;
-}
-
-/****************************************************************************
- * Name: pci_map_bar64
- *
- * Description:
- * Map address in a 64 bits bar in the flat memory address space
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * length - Map length, multiple of PAGE_SIZE
- * ret - Bar Content if not NULL
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_map_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
- unsigned long length, uint64_t *ret)
-{
- if (bar > 4 || ((bar % 2) != 0))
- return -EINVAL;
-
- uint32_t barmem1;
- uint32_t barmem2;
- uint64_t barmem;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4, &barmem1, 4);
-
- if ((barmem1 & PCI_BAR_64BIT) != PCI_BAR_64BIT ||
- (barmem1 & PCI_BAR_IO) == PCI_BAR_IO)
- return -EINVAL;
-
- dev->bus->ops->pci_cfg_read(dev, PCI_CFG_BAR + bar * 4 + 4, &barmem2, 4);
-
- barmem = ((uint64_t)barmem2 << 32) | barmem1;
-
- if (!dev->bus->ops->pci_map_bar64)
- return -EINVAL;
-
- dev->bus->ops->pci_map_bar64(dev, barmem, length);
-
- if (ret)
- *ret = barmem;
-
- return OK;
-}
diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
index bf8fb8591c..6eee0ff10d 100644
--- a/drivers/virt/Kconfig
+++ b/drivers/virt/Kconfig
@@ -15,8 +15,15 @@ if VIRT
config VIRT_QEMU_PCI_TEST
bool "Driver for QEMU PCI test device"
default n
- select PCIE
+ select PCI
---help---
Driver for QEMU PCI test device
+config VIRT_QEMU_EDU
+ bool "Driver for QEMU EDU test device"
+ default n
+ select PCI
+ ---help---
+ Driver for QEMU EDU test device
+
endif # VIRT
diff --git a/drivers/virt/Make.defs b/drivers/virt/Make.defs
index 8ccfbe06c5..a65cce26f4 100644
--- a/drivers/virt/Make.defs
+++ b/drivers/virt/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# drivers/pcie/Make.defs
+# drivers/pci/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -26,6 +26,12 @@ CSRCS += qemu_pci_test.c
endif
+ifeq ($(CONFIG_VIRT_QEMU_EDU),y)
+
+CSRCS += qemu_edu.c
+
+endif
+
# Include virt device driver build support
#
ifeq ($(CONFIG_VIRT),y)
diff --git a/drivers/virt/qemu_edu.c b/drivers/virt/qemu_edu.c
new file mode 100644
index 0000000000..953d161a52
--- /dev/null
+++ b/drivers/virt/qemu_edu.c
@@ -0,0 +1,448 @@
+/*****************************************************************************
+ * drivers/virt/qemu_edu.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.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/kmalloc.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <math.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sched.h>
+
+#include <nuttx/pci/pci.h>
+#include <nuttx/virt/qemu_pci.h>
+
+/*****************************************************************************
+ * Pre-processor Definitions
+ *****************************************************************************/
+
+/* Registers defined for device. Size 4 for < 0x80. Size 8 for >= 0x80. */
+
+#define EDU_REG_ID 0x00 /* Identification */
+#define EDU_REG_LIVE 0x04 /* Liveness Check */
+#define EDU_REG_FAC 0x08 /* Factorial Computation */
+#define EDU_REG_STATUS 0x20 /* Status */
+#define EDU_REG_INT_STATUS 0x24 /* Interupt Status */
+#define EDU_REG_INT_RAISE 0x60 /* Raise an interrupt */
+#define EDU_REG_INT_ACK 0x64 /* Acknowledge interrupt */
+#define EDU_REG_DMA_SOURCE 0x80 /* Source address for DMA transfer */
+#define EDU_REG_DMA_DEST 0x88 /* Destination address for DMA transfer */
+#define EDU_REG_DMA_COUNT 0x90 /* Size of area to transfer with DMA */
+#define EDU_REG_DMA_CMD 0x98 /* Control DMA tranfer */
+
+#define EDU_CONTROL_BAR_ID 0
+#define EDU_CONTROL_BAR_OFFSET PCI_HEADER_NORM_BAR0
+
+/*****************************************************************************
+ * Private Types
+ *****************************************************************************/
+
+struct qemu_edu_priv_s
+{
+ uintptr_t base_addr;
+ sem_t isr_done;
+ uint32_t test_result;
+};
+
+/*****************************************************************************
+ * Private Functions Definitions
+ *****************************************************************************/
+
+static void qemu_edu_write_reg32(uintptr_t addr, uint32_t val);
+
+static uint32_t qemu_edu_read_reg32(uintptr_t addr);
+
+static void qemu_edu_write_reg64(uintptr_t addr, uint64_t val);
+
+static void qemu_edu_test_poll(FAR struct pci_dev_s *dev,
+ uintptr_t base_addr);
+
+static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
+ struct qemu_edu_priv_s *drv_priv);
+
+static int qemu_edu_interrupt(int irq, void *context, FAR void *arg);
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: qemu_edu_write_reg32
+ *
+ * Description:
+ * Provide a write interface for 32bit mapped registers
+ *
+ * Input Parameters:
+ * addr - Register address
+ * val - Value to assign to register
+ *
+ *****************************************************************************/
+
+static void qemu_edu_write_reg32(uintptr_t addr, uint32_t val)
+{
+ *(volatile uint32_t *)addr = val;
+}
+
+/*****************************************************************************
+ * Name: qemu_edu_read_reg32
+ *
+ * Description:
+ * Provide a read interface for 32bit mapped registers
+ *
+ * Returned Value:
+ * Register value
+ *
+ *****************************************************************************/
+
+static uint32_t qemu_edu_read_reg32(uintptr_t addr)
+{
+ return *(volatile uint32_t *)addr;
+}
+
+/*****************************************************************************
+ * Name: qemu_edu_write_reg64
+ *
+ * Description:
+ * Provide a write interface for 64bit mapped registers
+ *
+ * Input Parameters:
+ * addr - Register address
+ * val - Value to assign to register
+ *
+ *****************************************************************************/
+
+static void qemu_edu_write_reg64(uintptr_t addr, uint64_t val)
+{
+ *(volatile uint64_t *)addr = val;
+}
+
+/*****************************************************************************
+ * Name: qemu_edu_test_poll
+ *
+ * Description:
+ * Performs basic functional test of PCI device and MMIO using polling
+ * of mapped register interfaces.
+ *
+ * Input Parameters:
+ * bus - An PCI device
+ * base_addr - Base address of device register space
+ *
+ *****************************************************************************/
+
+static void qemu_edu_test_poll(FAR struct pci_dev_s *dev, uintptr_t base_addr)
+{
+ uint32_t test_value;
+ uint32_t test_read;
+
+ pciinfo("Identification: 0x%08xu\n",
+ qemu_edu_read_reg32(base_addr + EDU_REG_ID));
+
+ /* Test Live Check */
+
+ test_value = 0xdeadbeef;
+ qemu_edu_write_reg32(base_addr + EDU_REG_LIVE, test_value);
+ test_read = qemu_edu_read_reg32(base_addr + EDU_REG_LIVE);
+ pciinfo("Live Check: Wrote: 0x%08x Read: 0x%08x Error Bits 0x%08x\n",
+ test_value, test_read, test_read ^ ~test_value);
+ pciinfo("TEST %s\n", ((test_read ^ ~test_value) == 0) ? "PASS" : "FAIL");
+
+ /* Test Factorial */
+
+ test_value = 10;
+ qemu_edu_write_reg32(base_addr + EDU_REG_STATUS, 0);
+ qemu_edu_write_reg32(base_addr + EDU_REG_FAC, test_value);
+ while (qemu_edu_read_reg32(base_addr + EDU_REG_STATUS) & 0x01)
+ {
+ pciinfo("Waiting to compute factorial...");
+ usleep(10000);
+ }
+
+ test_read = qemu_edu_read_reg32(base_addr + EDU_REG_FAC);
+ pciinfo("Computed factorial of %d as %d\n", test_value, test_read);
+ pciinfo("TEST %s\n", (test_read == 3628800) ? "PASS" : "FAIL");
+}
+
+/*****************************************************************************
+ * Name: qemu_edu_test_intx
+ *
+ * Description:
+ * Performs basic functional test of PCI device and MMIO using INTx
+ *
+ * Input Parameters:
+ * bus - An PCI device
+ * drv_priv - Struct containing internal state of driver
+ *
+ *****************************************************************************/
+
+static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
+ struct qemu_edu_priv_s *drv_priv)
+{
+ uintptr_t base_addr = drv_priv->base_addr;
+ uint32_t test_value;
+
+ pciinfo("Identification: 0x%08xu\n",
+ qemu_edu_read_reg32(base_addr + EDU_REG_ID));
+
+ /* Test Read/Write */
+
+ test_value = 0xdeadbeef;
+ pciinfo("Triggering interrupt with value 0x%08x\n", test_value);
+ qemu_edu_write_reg32(base_addr + EDU_REG_INT_RAISE, test_value);
+ sem_wait(&drv_priv->isr_done);
+ pciinfo("TEST %s\n",
+ (drv_priv->test_result == test_value) ? "PASS" : "FAIL");
+
+ /* Test Factorial */
+
+ test_value = 5;
+ pciinfo("Computing factorial of %d\n", test_value);
+ qemu_edu_write_reg32(base_addr + EDU_REG_STATUS, 0x80);
+ qemu_edu_write_reg32(base_addr + EDU_REG_FAC, test_value);
+ sem_wait(&drv_priv->isr_done);
+ pciinfo("TEST %s\n", (drv_priv->test_result == 120) ? "PASS" : "FAIL");
+
+ /* Test ISR Status Cleanup */
+
+ qemu_edu_write_reg32(base_addr + EDU_REG_INT_RAISE, test_value);
+ sem_wait(&drv_priv->isr_done);
+ pciinfo("TEST %s\n",
+ (drv_priv->test_result == test_value) ? "PASS" : "FAIL");
+}
+
+/*****************************************************************************
+ * Name: qemu_edu_test_dma
+ *
+ * Description:
+ * Performs dma functional test of PCI device
+ *
+ * Input Parameters:
+ * bus - An PCI device
+ * drv_priv - Struct containing internal state of driver
+ *
+ *****************************************************************************/
+
+static void qemu_edu_test_dma(FAR struct pci_dev_s *dev,
+ struct qemu_edu_priv_s *drv_priv)
+{
+ uintptr_t base_addr = drv_priv->base_addr;
+ void *test_block;
+ size_t block_size = 2048;
+ int i;
+ uint32_t psrand;
+ uint32_t tx_checksum;
+ uint32_t rx_checksum;
+ uint32_t dev_addr = 0x40000;
+
+ pciinfo("Identification: 0x%08xu\n",
+ qemu_edu_read_reg32(base_addr + EDU_REG_ID));
+
+ test_block = kmm_malloc(block_size);
+ for (i = 0; i < block_size; i++)
+ {
+ *((uint8_t *)test_block + i) = i & 0xff;
+ }
+
+ tx_checksum = 0;
+ psrand = 0x0011223344;
+ for (i = 0; i < (block_size / 4); i++)
+ {
+ /* Fill the memory block with "random" data */
+
+ psrand ^= psrand << 13;
+ psrand ^= psrand >> 17;
+ psrand ^= psrand << 5;
+ *((uint32_t *)test_block + i) = psrand;
+ tx_checksum += psrand;
+ }
+
+ pciinfo("Test block checksum 0x%08x\n", tx_checksum);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_SOURCE, (uint64_t)test_block);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_DEST, (uint64_t)dev_addr);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_COUNT, (uint64_t)block_size);
+ qemu_edu_write_reg32(base_addr + EDU_REG_STATUS, 0x00);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_CMD, 0x01 | 0x04);
+ sem_wait(&drv_priv->isr_done);
+
+ pciinfo("DMA transfer to device complete.\n");
+
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_DEST, (uint64_t)test_block);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_SOURCE, (uint64_t)dev_addr);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_COUNT, (uint64_t)block_size);
+ qemu_edu_write_reg32(base_addr + EDU_REG_STATUS, 0x00);
+ qemu_edu_write_reg64(base_addr + EDU_REG_DMA_CMD, 0x01 | 0x02 | 0x04);
+ sem_wait(&drv_priv->isr_done);
+
+ pciinfo("DMA transfer from device complete.\n");
+ rx_checksum = 0;
+ for (i = 0; i < block_size / 4; i++)
+ {
+ rx_checksum += *((uint32_t *)test_block + i);
+ }
+
+ pciinfo("Received block checksum 0x%08x\n", rx_checksum);
+ pciinfo("TEST %s\n", (rx_checksum == tx_checksum) ? "PASS" : "FAIL");
+}
+
+/*****************************************************************************
+ * Name: qemu_edu_interrupt
+ *
+ * Description:
+ * EDU interrupt handler
+ *
+ *****************************************************************************/
+
+static int qemu_edu_interrupt(int irq, void *context, FAR void *arg)
+{
+ struct qemu_edu_priv_s *drv_priv = (struct qemu_edu_priv_s *)arg;
+ uintptr_t base_addr = drv_priv->base_addr;
+
+ uint32_t status = qemu_edu_read_reg32(base_addr + EDU_REG_INT_STATUS);
+
+ qemu_edu_write_reg32(base_addr + EDU_REG_INT_ACK, ~0U);
+ switch (status)
+ {
+ case 0x1: /* Factorial triggered */
+ drv_priv->test_result = qemu_edu_read_reg32(base_addr + EDU_REG_FAC);
+ pciinfo("Computed factorial: %d\n",
+ drv_priv->test_result);
+ break;
+ case 0x100: /* DMA triggered */
+ pciinfo("DMA transfer complete\n");
+ break;
+ default: /* Generic write */
+ drv_priv->test_result = status;
+ pciinfo("Received value: 0x%08x\n", status);
+ }
+
+ sem_post(&drv_priv->isr_done);
+ return OK;
+}
+
+/*****************************************************************************
+ * Public Functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: qemu_edu_probe
+ *
+ * Description:
+ * Initialize device
+ *****************************************************************************/
+
+int qemu_edu_probe(FAR struct pci_bus_s *bus,
+ FAR struct pci_dev_type_s *type, uint16_t bdf)
+{
+ uint32_t bar;
+ uintptr_t bar_addr;
+ struct pci_dev_s dev =
+ {
+ .bus = bus,
+ .type = type,
+ .bdf = bdf,
+ };
+
+ uint8_t irq;
+ struct qemu_edu_priv_s drv_priv;
+
+ pci_enable_bus_master(&dev);
+ pciinfo("Enabled bus mastering\n");
+ pci_enable_io(&dev, PCI_SYS_RES_MEM);
+ pciinfo("Enabled memory resources\n");
+
+ if (pci_bar_valid(&dev, EDU_CONTROL_BAR_ID) != OK)
+ {
+ pcierr("Control BAR is not valid\n");
+ DEBUGPANIC();
+ return -EINVAL;
+ }
+
+ bar_addr = pci_bar_addr(&dev, EDU_CONTROL_BAR_ID);
+ bar = bus->ops->pci_cfg_read(&dev, EDU_CONTROL_BAR_OFFSET, 4);
+ if ((bar & PCI_BAR_LAYOUT_MASK) != PCI_BAR_LAYOUT_MEM)
+ {
+ pcierr("Control bar expected to be MMIO\n");
+ DEBUGPANIC();
+ return -EINVAL;
+ }
+
+ if (bus->ops->pci_map_bar(bar_addr,
+ pci_bar_size(&dev, EDU_CONTROL_BAR_ID)) != OK)
+ {
+ pcierr("Failed to map address space\n");
+ DEBUGPANIC();
+ return -EINVAL;
+ }
+
+ pciinfo("Device Initialized\n");
+
+ /* Run Poll Tests */
+
+ qemu_edu_test_poll(&dev, bar_addr);
+
+ /* Run IRQ Tests */
+
+ drv_priv.base_addr = bar_addr;
+ sem_init(&drv_priv.isr_done, 0, 0);
+ sem_setprotocol(&drv_priv.isr_done, SEM_PRIO_NONE);
+
+ irq = IRQ0 + bus->ops->pci_cfg_read(&dev, PCI_HEADER_NORM_INT_LINE, 1);
+ pciinfo("Attaching IRQ %d to %p\n", irq, qemu_edu_interrupt);
+ irq_attach(irq, (xcpt_t)qemu_edu_interrupt, (void *)&drv_priv);
+ up_enable_irq(irq);
+
+ qemu_edu_test_intx(&dev, &drv_priv);
+ qemu_edu_test_dma(&dev, &drv_priv);
+
+ up_disable_irq(irq);
+ irq_detach(irq);
+ sem_destroy(&drv_priv.isr_done);
+
+ /* Run MSI Tests */
+
+ /* Really should be cleaning up the mapped memory */
+
+ return OK;
+}
+
+/*****************************************************************************
+ * Public Data
+ *****************************************************************************/
+
+struct pci_dev_type_s pci_type_qemu_edu =
+{
+ .vendor = 0x1234,
+ .device = 0x11e8,
+ .class_rev = PCI_ID_ANY,
+ .name = "Qemu PCI EDU device",
+ .probe = qemu_edu_probe
+};
diff --git a/drivers/virt/qemu_pci_test.c b/drivers/virt/qemu_pci_test.c
index d0df753121..b0556b4d9f 100644
--- a/drivers/virt/qemu_pci_test.c
+++ b/drivers/virt/qemu_pci_test.c
@@ -33,30 +33,133 @@
#include <errno.h>
#include <sched.h>
-#include <nuttx/pcie/pcie.h>
+#include <nuttx/pci/pci.h>
#include <nuttx/virt/qemu_pci.h>
/*****************************************************************************
* Pre-processor Definitions
*****************************************************************************/
+/*****************************************************************************
+ * Private Functions Definitions
+ *****************************************************************************/
+
+static uint32_t mem_read(FAR const volatile void *addr, int width);
+
+static void mem_write(FAR const volatile void *addr, uint32_t val, int width);
+
/*****************************************************************************
* Private Types
*****************************************************************************/
struct pci_test_dev_hdr_s
{
- volatile uint8_t test; /* write-only, starts a given test number */
- volatile uint8_t width_type; /* read-only, type and width of access for a given test.
- * 1,2,4 for byte,word or long write.
- * any other value if test not supported on this BAR */
- volatile uint8_t pad0[2];
- volatile uint32_t offset; /* read-only, offset in this BAR for a given test */
- volatile uint32_t data; /* read-only, data to use for a given test */
- volatile uint32_t count; /* for debugging. number of writes detected. */
- volatile uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
+ uint8_t test; /* write-only, starts a given test number */
+ uint8_t width; /* read-only, type and width of access for a test */
+ uint8_t pad0[2];
+ uint32_t offset; /* read-only, offset in this BAR for a given test */
+ uint32_t data; /* read-only, data to use for a given test */
+ uint32_t count; /* for debugging. number of writes detected. */
+ uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
+};
+
+/* Structure the read and write helpers */
+
+struct pci_test_dev_ops_s
+{
+ uint32_t (*read)(FAR const volatile void *addr, int width);
+ void (*write)(FAR const volatile void *addr, uint32_t val, int width);
+};
+
+/*****************************************************************************
+ * Private Data
+ *****************************************************************************/
+
+static struct pci_test_dev_ops_s mem_ops =
+{
+ .read = mem_read,
+ .write = mem_write
};
+/*****************************************************************************
+ * Private Functions
+ *****************************************************************************/
+
+static uint32_t mem_read(FAR const volatile void *addr, int unused)
+{
+ return *(volatile uint32_t *)addr;
+}
+
+static void mem_write(FAR const volatile void *addr, uint32_t val, int unused)
+{
+ *(volatile uint32_t *)addr = val;
+}
+
+static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
+ FAR struct pci_test_dev_hdr_s *test_hdr,
+ uint16_t test_num)
+{
+ uint32_t count;
+ uint32_t data;
+ uint32_t offset;
+ uint8_t width;
+ const int write_limit = 8;
+ int write_cnt;
+ int i;
+ char testname[32];
+
+ pciinfo("WRITING Test# %d %p\n", test_num, &test_hdr->test);
+ test_ops->write(&test_hdr->test, test_num, 1);
+
+ /* Reading of the string is a little ugly to handle the case where
+ * we must use the port access methods. For memory map we would
+ * be able to just read directly.
+ */
+
+ testname[sizeof(testname) - 1] = 0;
+ for (i = 0; i < sizeof(testname); i++)
+ {
+ testname[i] = (char)test_ops->read((void *)&test_hdr->name + i, 1);
+ if (testname[i] == 0)
+ break;
+ }
+
+ pciinfo("Running test: %s\n", testname);
+
+ count = test_ops->read(&test_hdr->count, 4);
+ pciinfo("COUNT: %04x\n", count);
+ if (count != 0)
+ return false;
+
+ width = test_ops->read(&test_hdr->width, 1);
+ pciinfo("Width: %d\n", width);
+
+ if (width == 0 || width > 4)
+ return false;
+
+ data = test_ops->read(&test_hdr->data, 4);
+ pciinfo("Data: %04x\n", data);
+
+ offset = test_ops->read(&test_hdr->offset, 4);
+ pciinfo("Offset: %04x\n", offset);
+
+ for (write_cnt = 0; write_cnt < write_limit; write_cnt++)
+ {
+ pciinfo("Issuing WRITE to %p %x %d\n",
+ (void *)test_hdr + offset,
+ data, width);
+ test_ops->write((void *)test_hdr + offset, data, width);
+ }
+
+ count = test_ops->read(&test_hdr->count, 4);
+ pciinfo("COUNT: %04x\n", count);
+
+ if (!count)
+ return true;
+
+ return (int)count == write_cnt;
+}
+
/*****************************************************************************
* Public Functions
*****************************************************************************/
@@ -68,49 +171,73 @@ struct pci_test_dev_hdr_s
* Initialize device
*****************************************************************************/
-int qemu_pci_test_probe(FAR struct pcie_bus_s *bus,
- FAR struct pcie_dev_type_s *type, uint16_t bdf)
+int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
+ FAR struct pci_dev_type_s *type, uint16_t bdf)
{
- uint32_t bar[2];
- struct pcie_dev_s dev =
+ uint8_t bar_id;
+ uint32_t bar;
+ uint64_t bar_addr;
+ struct pci_test_dev_hdr_s *test_hdr;
+ struct pci_dev_s dev =
{
.bus = bus,
.type = type,
.bdf = bdf,
};
- pci_enable_device(&dev);
+ struct pci_test_dev_ops_s io_ops =
+ {
+ .read = bus->ops->pci_io_read,
+ .write = bus->ops->pci_io_write
+ };
+
+ struct pci_test_dev_ops_s *test_ops;
+
+ uint16_t test_cnt;
+
+ pci_enable_bus_master(&dev);
+ pciinfo("Enabled bus mastering\n");
+ pci_enable_io(&dev, PCI_SYS_RES_MEM);
+ pci_enable_io(&dev, PCI_SYS_RES_IOPORT);
+ pciinfo("Enabled i/o port and memory resources\n");
- for (int ii = 0; ii < 2; ii++)
+ for (bar_id = 0; bar_id < PCI_BAR_CNT; bar_id++)
{
- pci_get_bar(&dev, ii, bar + ii);
+ /* Need to query the BAR for IO vs MEM
+ * Also handle if the bar is 64bit address
+ */
- if ((bar[ii] & PCI_BAR_IO) != PCI_BAR_IO)
- {
- pciinfo("Mapping BAR%d: %x\n", ii, bar[ii]);
+ if (pci_bar_valid(&dev, bar_id) != OK)
+ continue;
- pci_map_bar(&dev, ii, 0x1000, NULL);
+ bar = bus->ops->pci_cfg_read(&dev,
+ PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
- struct pci_test_dev_hdr_s *ptr =
- (struct pci_test_dev_hdr_s *)(uintptr_t)bar[ii];
+ bar_addr = pci_bar_addr(&dev, bar_id);
+ test_hdr = (struct pci_test_dev_hdr_s *)bar_addr;
- int i = 0;
- while (1)
- {
- ptr->test = i;
+ if ((bar & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
+ {
+ test_ops = &mem_ops;
- if (ptr->width_type != 1 &&
- ptr->width_type != 2 &&
- ptr->width_type != 4)
- break;
+ /* If the BAR is MMIO the it must be mapped */
- pciinfo("Test[%d] Size:%d %s\n",
- i, ptr->width_type,
- ptr->name);
+ bus->ops->pci_map_bar(bar_addr, pci_bar_size(&dev, bar_id));
+ }
+ else
+ {
+ test_ops = &io_ops;
+ }
- i++;
- }
+ for (test_cnt = 0; test_cnt < 0xffff; test_cnt++)
+ {
+ if (!qemu_pci_test_bar(test_ops, test_hdr, test_cnt))
+ break;
+ pciinfo("Test Completed BAR [%d] TEST [%d]\n", bar_id, test_cnt);
}
+
+ if (pci_bar_is_64(&dev, bar_id))
+ bar_id++;
}
return OK;
@@ -120,7 +247,7 @@ int qemu_pci_test_probe(FAR struct pcie_bus_s *bus,
* Public Data
*****************************************************************************/
-struct pcie_dev_type_s pcie_type_qemu_pci_test =
+struct pci_dev_type_s pci_type_qemu_pci_test =
{
.vendor = 0x1b36,
.device = 0x0005,
diff --git a/include/debug.h b/include/debug.h
index 955ddf6e2c..94b5448b32 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -920,19 +920,19 @@
# define ipcinfo _none
#endif
-#ifdef CONFIG_DEBUG_PCIE_ERROR
+#ifdef CONFIG_DEBUG_PCI_ERROR
# define pcierr _err
#else
# define pcierr _none
#endif
-#ifdef CONFIG_DEBUG_PCIE_WARN
+#ifdef CONFIG_DEBUG_PCI_WARN
# define pciwarn _warn
#else
# define pciwarn _none
#endif
-#ifdef CONFIG_DEBUG_PCIE_INFO
+#ifdef CONFIG_DEBUG_PCI_INFO
# define pciinfo _info
#else
# define pciinfo _none
diff --git a/include/nuttx/pci/pci.h b/include/nuttx/pci/pci.h
new file mode 100644
index 0000000000..0b420a04c0
--- /dev/null
+++ b/include/nuttx/pci/pci.h
@@ -0,0 +1,458 @@
+/****************************************************************************
+ * include/nuttx/pci/pci.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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_PCI_PCI_H
+#define __INCLUDE_NUTTX_PCI_PCI_H
+
+#ifdef CONFIG_PCI
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <nuttx/fs/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* PCI config common registers */
+
+#define PCI_CONFIG_VENDOR 0x00
+#define PCI_CONFIG_DEVICE 0x02
+#define PCI_CONFIG_COMMAND 0x04
+#define PCI_CONFIG_REV_ID 0x08
+#define PCI_CONFIG_PROG_IF 0x09
+#define PCI_CONFIG_SUBCLASS 0x0A
+#define PCI_CONFIG_CLASS 0x0B
+#define PCI_CONFIG_CACHE_LINE_SIZE 0x0C
+#define PCI_CONFIG_LATENCY_TIMER 0x0D
+#define PCI_CONFIG_HEADER_TYPE 0x0E
+#define PCI_CONFIG_BIST 0x0F
+
+/* PCI config header types */
+
+#define PCI_HEADER_NORMAL 0x00
+#define PCI_HEADER_BRIDGE 0x01
+#define PCI_HEADER_CARDBUS 0x02
+#define PCI_HEADER_TYPE_MASK 0x3F
+#define PCI_HEADER_MASK_MULTI 0x80
+
+/* PCI config registers type 0 (Normal devices) */
+
+#define PCI_HEADER_NORM_BAR0 0x10
+#define PCI_HEADER_NORM_BAR1 0x14
+#define PCI_HEADER_NORM_BAR2 0x18
+#define PCI_HEADER_NORM_BAR3 0x1C
+#define PCI_HEADER_NORM_BAR4 0x20
+#define PCI_HEADER_NORM_BAR5 0x24
+#define PCI_HEADER_NORM_CB_CIS 0x28
+#define PCI_HEADER_NORM_SUB_VID 0x2C
+#define PCI_HEADER_NORM_SUB_ID 0x2E
+#define PCI_HEADER_NORM_EXP_ROM 0x30
+#define PCI_HEADER_NORM_CAP 0x34
+#define PCI_HEADER_NORM_INT_LINE 0x3C
+#define PCI_HEADER_NORM_INT_PIN 0x3D
+#define PCI_HEADER_NORM_MIN_GRANT 0x3E
+#define PCI_HEADER_NORM_MAX_LAT 0x3E
+
+/* PCI config registers type 1 (PCI-PCI bridge) */
+
+#define PCI_CONFIG_SEC_BUS 0x19
+
+/* PCI config registers type 2 (CardBus) */
+
+/* PCI Base Class Codes */
+
+#define PCI_CLASS_BASE_UNCLASSIFIED 0x00
+#define PCI_CLASS_BASE_MASS_STORAGE_CTRL 0x01
+#define PCI_CLASS_BASE_NETWORK_CTRL 0x02
+#define PCI_CLASS_BASE_DISPLAY_CTRL 0x03
+#define PCI_CLASS_BASE_MULTIMEDIA_CTRL 0x04
+#define PCI_CLASS_BASE_MEM_CTRL 0x05
+#define PCI_CLASS_BASE_BRG_DEV 0x06
+#define PCI_CLASS_BASE_SMPL_COM_CTRL 0x07
+#define PCI_CLASS_BASE_BSP 0x08
+#define PCI_CLASS_BASE_INPUT_DEV_CTRL 0x09
+#define PCI_CLASS_BASE_DOCK_STN 0x0A
+#define PCI_CLASS_BASE_PROCESSOR 0x0B
+#define PCI_CLASS_BASE_SBC 0x0C
+#define PCI_CLASS_BASE_WIRELESS_CTRL 0x0D
+#define PCI_CLASS_BASE_INTL_CTRL 0x0E
+#define PCI_CLASS_BASE_SAT_COM_CTRL 0x0F
+#define PCI_CLASS_BASE_ENCRYPT_CTRL 0x10
+#define PCI_CLASS_BASE_SPC 0x11
+#define PCI_CLASS_BASE_PROC_ACCEL 0x12
+#define PCI_CLASS_BASE_NON_ES_INST 0x13
+
+/* Reserved 0x14-0x3F */
+
+#define PCI_CLASS_BASE_CO_PROC 0x40
+
+/* Reserved 0x41-0xFE */
+
+#define PCI_CLASS_BASE_UNASSIGNED 0xFF
+
+/* PCI Sub Class Codes (most missing) */
+
+/* Bridge Class */
+
+#define PCI_CLASS_SUB_HOST_BRG 0x00
+#define PCI_CLASS_SUB_ISA_BRG 0x01
+#define PCI_CLASS_SUB_EISA_BRG 0x02
+#define PCI_CLASS_SUB_MCA_BRG 0x03
+#define PCI_CLASS_SUB_PCI_BRG 0x04
+#define PCI_CLASS_SUB_PCMCIA_BRG 0x05
+#define PCI_CLASS_SUB_NUBUS_BRG 0x06
+#define PCI_CLASS_SUB_CARDBUS_BRG 0x07
+#define PCI_CLASS_SUB_RACEWAY_BRG 0x08
+#define PCI_CLASS_SUB_PCI_TRNSP_BRG 0x09
+#define PCI_CLASS_SUB_INFINI_BRG 0x0A
+#define PCI_CLASS_SUB_NUBUS_BRG 0x80
+
+#define PCI_ID_ANY 0xffff
+
+/* PCI Command Register Bitmasks */
+
+#define PCI_CMD_IO_SPACE 0x0001
+#define PCI_CMD_MEM_SPACE 0x0002
+#define PCI_CMD_BUS_MSTR 0x0004
+#define PCI_CMD_SPECIAL_CYC 0x0008
+#define PCI_CMD_MEM_INV 0x0030
+#define PCI_CMD_VGA_PLT 0x0040
+#define PCI_CMD_PAR_ERR 0x0080
+#define PCI_CMD_SERR 0x0100
+#define PCI_CMD_FST_B2B 0x0200
+#define PCI_CMD_INT 0x0400
+
+/* PCI BAR Bitmasks */
+
+#define PCI_BAR_LAYOUT_MASK 0x00000001
+#define PCI_BAR_TYPE_MASK 0x00000006
+#define PCI_BAR_MEM_PF_MASK 0x00000008
+#define PCI_BAR_MEM_BASE_MASK 0xfffffff0
+#define PCI_BAR_IO_BASE_MASK 0xfffffffc
+
+/* PCI BAR OFFSETS */
+
+#define PCI_BAR_LAYOUT_OFFSET 0
+#define PCI_BAR_TYPE_OFFSET 1
+#define PCI_BAR_MEM_PF_OFFSET 3
+#define PCI_BAR_MEM_BASE_OFFSET 4
+#define PCI_BAR_IO_BASE_OFFSET 2
+
+/* PCI BAR */
+
+#define PCI_BAR_CNT 6
+#define PCI_BAR_INVALID 0
+#define PCI_BAR_LAYOUT_MEM 0
+#define PCI_BAR_LAYOUT_IO 1
+#define PCI_BAR_TYPE_32 0x00
+#define PCI_BAR_TYPE_16 0x01 /* This mode is not used */
+#define PCI_BAR_TYPE_64 0x02
+
+/* PCI CAP */
+
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOT 0x04 /* Slot ID */
+#define PCI_CAP_ID_MSI 0x05 /* MSI */
+#define PCI_CAP_ID_CHP 0x06 /* CompactPCI Hot-Swap */
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define PCI_CAP_ID_HT 0x08 /* HyperTransport */
+#define PCI_CAP_ID_VNDR 0x09 /* Vendor */
+#define PCI_CAP_ID_DBG 0x0A /* Debug */
+#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */
+#define PCI_CAP_ID_HOT 0x0C /* Hot-Plug Controller */
+#define PCI_CAP_ID_BRG_VID 0x0D /* Bridge Vendor/Device ID */
+#define PCI_CAP_ID_AGP_BRG 0x0E /* AGP PCI-PCI Bridge */
+#define PCI_CAP_ID_SEC_DEV 0x0F /* Secure Device */
+#define PCI_CAP_ID_PCIE 0x10 /* PCIe */
+#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
+#define PCI_CAP_ID_SATA 0x12 /* SATA */
+#define PCI_CAP_ID_ADVF 0x13 /* Advanced Features */
+
+#define PCI_CAP_ID_END PCI_CAP_ID_ADVF
+
+/* Resource types used by PCI devices */
+
+#define PCI_SYS_RES_IOPORT 0x00
+#define PCI_SYS_RES_MEM 0x01
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* The PCI driver interface */
+
+struct pci_bus_s;
+struct pci_dev_type_s;
+struct pci_dev_s;
+
+/* Bus related operations */
+
+struct pci_bus_ops_s
+{
+ CODE void (*pci_cfg_write)(FAR struct pci_dev_s *dev, int reg,
+ uint32_t val, int width);
+
+ CODE uint32_t (*pci_cfg_read)(FAR struct pci_dev_s *dev, int reg,
+ int width);
+
+ CODE int (*pci_map_bar)(uint64_t addr, uint64_t len);
+
+ CODE uint32_t (*pci_io_read)(FAR const volatile void *addr, int width);
+
+ CODE void (*pci_io_write)(FAR const volatile void *addr, uint32_t val,
+ int width);
+};
+
+/* PCI bus private data. */
+
+struct pci_bus_s
+{
+ FAR const struct pci_bus_ops_s *ops; /* operations */
+};
+
+/* PCI device type, defines by vendor ID and device ID */
+
+struct pci_dev_type_s
+{
+ uint16_t vendor; /* Device vendor ID */
+ uint16_t device; /* Device ID */
+ uint32_t class_rev; /* Device reversion */
+ const char *name; /* Human readable name */
+
+ /* Call back function when a device is probed */
+
+ CODE int (*probe)(FAR struct pci_bus_s *bus,
+ FAR struct pci_dev_type_s *type, uint16_t bdf);
+};
+
+/* PCI device private data. */
+
+struct pci_dev_s
+{
+ FAR struct pci_bus_s *bus;
+ FAR struct pci_dev_type_s *type;
+ uint32_t bdf;
+};
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Name: pci_initialize
+ *
+ * Description:
+ * Initialize the PCI bus and enumerate the devices with give devices
+ * type array
+ *
+ * Input Parameters:
+ * bus - An PCI bus
+ * types - A array of PCI device types
+ *
+ * Returned Value:
+ * OK if the driver was successfully register; A negated errno value is
+ * returned on any failure.
+ *
+ ****************************************************************************/
+
+int pci_initialize(FAR struct pci_bus_s *bus);
+
+/****************************************************************************
+ * Name: pci_enable_io
+ *
+ * Description:
+ * Enable MMIO or IOPORT
+ *
+ * Input Parameters:
+ * dev - device
+ * space - which resource is being enabled
+ * PCI_SYS_RES_IOPORT for io port address decoding or
+ * PCI_RES_MEM for memory
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_enable_io(FAR struct pci_dev_s *dev, int res);
+
+/****************************************************************************
+ * Name: pci_disable_io
+ *
+ * Description:
+ * Enable MMIO or IOPORT
+ *
+ * Input Parameters:
+ * dev - device
+ * space - which resource is being disabled
+ * PCI_SYS_RES_IOPORT for io port address decoding or
+ * PCI_SYS_RES_MEM for memory
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_disable_io(FAR struct pci_dev_s *dev, int res);
+
+/****************************************************************************
+ * Name: pci_enable_bus_master
+ *
+ * Description:
+ * Enable bus mastering for device so it can perform PCI accesses
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_enable_bus_master(FAR struct pci_dev_s *dev);
+
+/****************************************************************************
+ * Name: pci_disable_bus_master
+ *
+ * Description:
+ * Disable bus mastering for device
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_disable_bus_master(FAR struct pci_dev_s *dev);
+
+/****************************************************************************
+ * Name: pci_bar_valid
+ *
+ * Description:
+ * Determine in if the address in the BAR is valid
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * -EINVAL: error
+ * OK: OK
+ *
+ ****************************************************************************/
+
+int pci_bar_valid(FAR struct pci_dev_s *dev, uint8_t bar_id);
+
+/****************************************************************************
+ * Name: pci_bar_is_64
+ *
+ * Description:
+ * Determine in if the bar address is 64 bit. If it is the address includes
+ * the address in the next bar location.
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * true: 64bit address
+ *
+ ****************************************************************************/
+
+bool pci_bar_is_64(FAR struct pci_dev_s *dev, uint8_t bar_id);
+
+/****************************************************************************
+ * Name: pci_bar_size
+ *
+ * Description:
+ * Determine the size of the address space required by the BAR
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * Size of address space
+ *
+ ****************************************************************************/
+
+uint64_t pci_bar_size(FAR struct pci_dev_s *dev, uint8_t bar_id);
+
+/****************************************************************************
+ * Name: pci_bar_addr
+ *
+ * Description:
+ * Determine the size of the address space required by the BAR
+ *
+ * Input Parameters:
+ * dev - device
+ * bar_id - bar number
+ *
+ * Return value:
+ * full bar address
+ *
+ ****************************************************************************/
+
+uint64_t pci_bar_addr(FAR struct pci_dev_s *dev, uint8_t bar_id);
+
+/****************************************************************************
+ * Name: pci_dev_dump
+ *
+ * Description:
+ * Dump the configuration information for the device
+ *
+ * Input Parameters:
+ * dev - device
+ *
+ ****************************************************************************/
+
+void pci_dev_dump(FAR struct pci_dev_s *dev);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+#endif
+#endif /* __INCLUDE_NUTTX_PCI_PCI_H */
diff --git a/include/nuttx/pcie/pcie.h b/include/nuttx/pcie/pcie.h
deleted file mode 100644
index fffc791a2d..0000000000
--- a/include/nuttx/pcie/pcie.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/****************************************************************************
- * include/nuttx/pcie/pcie.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.
- *
- ****************************************************************************/
-
-#ifndef __INCLUDE_NUTTX_PCIE_PCIE_H
-#define __INCLUDE_NUTTX_PCIE_PCIE_H
-
-#ifdef CONFIG_PCIE
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <sys/types.h>
-#include <stdint.h>
-
-#include <nuttx/fs/ioctl.h>
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-#define PCI_CFG_VENDOR_ID 0x000
-#define PCI_CFG_DEVICE_ID 0x002
-#define PCI_CFG_COMMAND 0x004
-# define PCI_CMD_IO (1 << 0)
-# define PCI_CMD_MEM (1 << 1)
-# define PCI_CMD_MASTER (1 << 2)
-# define PCI_CMD_INTX_OFF (1 << 10)
-#define PCI_CFG_STATUS 0x006
-# define PCI_STS_INT (1 << 3)
-# define PCI_STS_CAPS (1 << 4)
-#define PCI_CFG_REVERSION 0x008
-#define PCI_CFG_BAR 0x010
-# define PCI_BAR_IO 0x1
-# define PCI_BAR_1M 0x2
-# define PCI_BAR_64BIT 0x4
-#define PCI_CFG_CAP_PTR 0x034
-
-#define PCI_ID_ANY 0xffff
-#define PCI_DEV_CLASS_OTHER 0xff
-
-#define PCI_CAP_PM 0x01
-
-#define PCI_CAP_MSI 0x05
-# define PCI_MSI_MCR 0x02
-# define PCI_MSI_MCR_SIZE 2
-# define PCI_MSI_MCR_EN (1 << 0)
-# define PCI_MSI_MCR_64 (1 << 7)
-# define PCI_MSI_MAR 0x04
-# define PCI_MSI_MAR_SIZE 4
-# define PCI_MSI_MDR 0x08
-# define PCI_MSI_MDR_SIZE 2
-# define PCI_MSI_MAR64_HI 0x08
-# define PCI_MSI_MAR64_HI_SIZE 4
-# define PCI_MSI_MDR64 0x0c
-# define PCI_MSI_MDR64_SIZE 2
-# define PCI_MSI_APIC_ID_OFFSET 0xc
-
-#define PCI_CAP_MSIX 0x11
-# define PCI_MSIX_MCR 0x02
-# define PCI_MSIX_MCR_SIZE 2
-# define PCI_MSIX_MCR_EN (1 << 15)
-# define PCI_MSIX_MCR_FMASK 0x4000
-# define PCI_MSIX_MCR_TBL_MASK 0x03ff
-# define PCI_MSIX_TBL 0x04
-# define PCI_MSIX_TBL_SIZE 4
-# define PCI_MSIX_PBA 0x08
-# define PCI_MSIX_PBA_SIZE 4
-# define PCI_MSIX_BIR_MASK 0x07
-# define PCI_MSIX_TBL_ENTRY_SIZE 0x10
-# define PCI_MSIX_TBL_LO_ADDR 0x0
-# define PCI_MSIX_TBL_HI_ADDR 0x4
-# define PCI_MSIX_TBL_MSG_DATA 0x8
-# define PCI_MSIX_TBL_VEC_CTL 0xc
-# define PCI_MSIX_APIC_ID_OFFSET 0xc
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-/* The PCIE driver interface */
-
-struct pcie_bus_s;
-struct pcie_dev_type_s;
-struct pcie_dev_s;
-
-/* Bus related operations */
-
-struct pcie_bus_ops_s
-{
- CODE int (*pcie_enumerate)(FAR struct pcie_bus_s *bus,
- FAR struct pcie_dev_type_s **types);
-
- CODE int (*pci_cfg_write)(FAR struct pcie_dev_s *dev, uintptr_t addr,
- FAR const void *buffer, unsigned int size);
-
- CODE int (*pci_cfg_read)(FAR struct pcie_dev_s *dev, uintptr_t addr,
- FAR void *buffer, unsigned int size);
-
- CODE int (*pci_map_bar)(FAR struct pcie_dev_s *dev, uint32_t addr,
- unsigned long length);
-
- CODE int (*pci_map_bar64)(FAR struct pcie_dev_s *dev, uint64_t addr,
- unsigned long length);
-
- CODE int (*pci_msi_register)(FAR struct pcie_dev_s *dev,
- uint16_t vector);
-
- CODE int (*pci_msix_register)(FAR struct pcie_dev_s *dev,
- uint32_t vector, uint32_t index);
-};
-
-/* PCIE bus private data. */
-
-struct pcie_bus_s
-{
- FAR const struct pcie_bus_ops_s *ops; /* operations */
-};
-
-/* PCIE device type, defines by vendor ID and device ID */
-
-struct pcie_dev_type_s
-{
- uint16_t vendor; /* Device vendor ID */
- uint16_t device; /* Device ID */
- uint32_t class_rev; /* Device reversion */
- const char *name; /* Human readable name */
-
- /* Call back function when a device is probed */
-
- CODE int (*probe)(FAR struct pcie_bus_s *bus,
- FAR struct pcie_dev_type_s *type, uint16_t bdf);
-};
-
-/* PCIE device private data. */
-
-struct pcie_dev_s
-{
- FAR struct pcie_bus_s *bus;
- FAR struct pcie_dev_type_s *type;
- uint16_t bdf;
-};
-
-/****************************************************************************
- * Public Functions Prototypes
- ****************************************************************************/
-
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C"
-{
-#else
-#define EXTERN extern
-#endif
-
-/****************************************************************************
- * Name: pcie_initialize
- *
- * Description:
- * Initialize the PCI-E bus and enumerate the devices with give devices
- * type array
- *
- * Input Parameters:
- * bus - An PCIE bus
- * types - A array of PCIE device types
- * num - Number of device types
- *
- * Returned Value:
- * OK if the driver was successfully register; A negated errno value is
- * returned on any failure.
- *
- ****************************************************************************/
-
-int pcie_initialize(FAR struct pcie_bus_s *bus);
-
-/****************************************************************************
- * Name: pci_enable_device
- *
- * Description:
- * Enable device with MMIO
- *
- * Input Parameters:
- * dev - device
- *
- * Return value:
- * -EINVAL: error
- * OK: OK
- *
- ****************************************************************************/
-
-int pci_enable_device(FAR struct pcie_dev_s *dev);
-
-/****************************************************************************
- * Name: pci_find_cap
- *
- * Description:
- * Search through the PCI-e device capability list to find given capability.
- *
- * Input Parameters:
- * dev - Device
- * cap - Bitmask of capability
- *
- * Returned Value:
- * -1: Capability not supported
- * other: the offset in PCI configuration space to the capability structure
- *
- ****************************************************************************/
-
-int pci_find_cap(FAR struct pcie_dev_s *dev, uint16_t cap);
-
-/****************************************************************************
- * Name: pci_map_bar
- *
- * Description:
- * Map address in a 32 bits bar in the flat memory address space
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * length - Map length, multiple of PAGE_SIZE
- * ret - Bar Contentif not NULL
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_map_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
- unsigned long length, uint32_t *ret);
-
-/****************************************************************************
- * Name: pci_map_bar64
- *
- * Description:
- * Map address in a 64 bits bar in the flat memory address space
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * length - Map length, multiple of PAGE_SIZE
- * ret - Bar Content if not NULL
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_map_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
- unsigned long length, uint64_t *ret);
-
-/****************************************************************************
- * Name: pci_get_bar
- *
- * Description:
- * Get a 32 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * ret - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_get_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint32_t *ret);
-
-/****************************************************************************
- * Name: pci_get_bar64
- *
- * Description:
- * Get a 64 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * ret - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_get_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint64_t *ret);
-
-/****************************************************************************
- * Name: pci_set_bar
- *
- * Description:
- * Set a 32 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * val - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_set_bar(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint32_t val);
-
-/****************************************************************************
- * Name: pci_set_bar64
- *
- * Description:
- * Set a 64 bits bar
- *
- * Input Parameters:
- * dev - Device private data
- * bar - Bar number
- * val - Bar Content
- *
- * Returned Value:
- * 0: success, <0: A negated errno
- *
- ****************************************************************************/
-
-int pci_set_bar64(FAR struct pcie_dev_s *dev, uint32_t bar,
- uint64_t val);
-
-#undef EXTERN
-#if defined(__cplusplus)
-}
-#endif
-#endif
-#endif /* __INCLUDE_NUTTX_I2C_I2C_MASTER_H */
diff --git a/include/nuttx/virt/qemu_pci.h b/include/nuttx/virt/qemu_pci.h
index f8e38f9241..3c3379ed00 100644
--- a/include/nuttx/virt/qemu_pci.h
+++ b/include/nuttx/virt/qemu_pci.h
@@ -42,9 +42,13 @@ extern "C"
#endif
#ifdef CONFIG_VIRT_QEMU_PCI_TEST
-extern struct pcie_dev_type_s pcie_type_qemu_pci_test;
+extern struct pci_dev_type_s pci_type_qemu_pci_test;
#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
+#ifdef CONFIG_VIRT_QEMU_EDU
+extern struct pci_dev_type_s pci_type_qemu_edu;
+#endif /* CONFIG_VIRT_QEMU_EDU */
+
#undef EXTERN
#ifdef __cplusplus
}