raiden00pl commented on code in PR #11583: URL: https://github.com/apache/nuttx/pull/11583#discussion_r1466113250
########## include/nuttx/pci/pci.h: ########## @@ -0,0 +1,472 @@ +/**************************************************************************** + * 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 +{ + /* Write 8, 16, 32, 64 bits data to PCI-E configuration space of device + * specified by dev. + */ + + CODE void (*pci_cfg_write)(FAR struct pci_dev_s *dev, int reg, + uint32_t val, int width); + + /* Read 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); + + /* Map address in a 32 bits bar in the memory address space */ + + CODE int (*pci_map_bar)(uint64_t addr, uint64_t len); Review Comment: Yes, but I think this is a change for another PR. ########## drivers/virt/qemu_edu.c: ########## @@ -0,0 +1,464 @@ +/***************************************************************************** + * 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 <debug.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); + +static int qemu_edu_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_edu = +{ + .vendor = 0x1234, + .device = 0x11e8, + .class_rev = PCI_ID_ANY, + .name = "Qemu PCI EDU device", + .probe = qemu_edu_probe +}; + +/***************************************************************************** + * 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, + FAR 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, + FAR struct qemu_edu_priv_s *drv_priv) +{ + 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 = 0x40000; Review Comment: this is the value from the doc https://www.qemu.org/docs/master/specs/edu.html#dma-controller -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
