xiaoxiang781216 commented on code in PR #11583: URL: https://github.com/apache/nuttx/pull/11583#discussion_r1465361744
########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_internal.h" + +/**************************************************************************** + * Pre-processor Definitions Review Comment: Private Types ```suggestion * Private Types ``` ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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 + +/**************************************************************************** + * 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 Review Comment: remove the dead code ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = +{ +#ifdef CONFIG_VIRT_QEMU_PCI_TEST + &g_pci_type_qemu_pci_test, +#endif +#ifdef CONFIG_VIRT_QEMU_EDU + &g_pci_type_qemu_edu, +#endif + 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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); + + 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 (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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); Review Comment: dup with line 276 ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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 = Review Comment: ```suggestion static struct multiboot_fb_s g_fb = ``` ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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); Review Comment: ```suggestion static void fb_clear(void); ``` ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = Review Comment: ```suggestion const struct pci_dev_type_s *g_pci_device_types[] = ``` ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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); Review Comment: ```suggestion static void fb_term_initialize(void); ``` ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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; +}; + Review Comment: add private function banner: ```` /**************************************************************************** * Private Function Prototypes ****************************************************************************/ ``` ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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; Review Comment: ```suggestion static struct fb_term_s g_fb_term; ``` ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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 + +/**************************************************************************** + * 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) Review Comment: move to private section ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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 + +/**************************************************************************** + * 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) Review Comment: move to private section ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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 + +/**************************************************************************** + * 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++) Review Comment: ```suggestion for (; pxl_row < save_rows; pxl_row++) ``` ########## boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c: ########## @@ -0,0 +1,229 @@ +/**************************************************************************** + * 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 "x86_64_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(struct pci_dev_s *dev, int reg, + uint32_t val, int width); + +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(const volatile void *addr, int width); + +static void qemu_pci_io_write(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 = Review Comment: ```suggestion static struct pci_bus_s g_qemu_pci_bus = ``` ########## boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c: ########## @@ -0,0 +1,229 @@ +/**************************************************************************** + * 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 "x86_64_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(struct pci_dev_s *dev, int reg, + uint32_t val, int width); + +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(const volatile void *addr, int width); + +static void qemu_pci_io_write(const volatile void *addr, uint32_t val, + int width); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +struct pci_bus_ops_s qemu_pci_bus_ops = Review Comment: ```suggestion static const struct pci_bus_ops_s g_qemu_pci_bus_ops = ``` move to private section ########## boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c: ########## @@ -0,0 +1,229 @@ +/**************************************************************************** + * 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 "x86_64_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(struct pci_dev_s *dev, int reg, + uint32_t val, int width); + +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(const volatile void *addr, int width); + +static void qemu_pci_io_write(const volatile void *addr, uint32_t val, + int width); + +/**************************************************************************** + * Public Data Review Comment: ```suggestion * Private Data ``` ########## boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c: ########## @@ -0,0 +1,229 @@ +/**************************************************************************** + * 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 "x86_64_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(struct pci_dev_s *dev, int reg, + uint32_t val, int width); + +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(const volatile void *addr, int width); + +static void qemu_pci_io_write(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(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(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(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(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); Review Comment: ```suggestion outw((uint16_t)val, portaddr); ``` ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = +{ +#ifdef CONFIG_VIRT_QEMU_PCI_TEST + &g_pci_type_qemu_pci_test, +#endif +#ifdef CONFIG_VIRT_QEMU_EDU + &g_pci_type_qemu_edu, +#endif + 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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); + + 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 (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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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; + + /* 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 const 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; Review Comment: removee ########## arch/x86_64/src/intel64/intel64_mbfb.c: ########## @@ -0,0 +1,321 @@ +/**************************************************************************** + * 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 + * 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 "x86_64_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 + +/**************************************************************************** + * 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) +{ + const struct nx_fontbitmap_s *fbm; + uint8_t gly_x; + uint8_t gly_y; + + 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; + + if ((fbm->bitmap[gly_byte] >> (7 - gly_bit)) & 0x01) + { + /* Black no matter the color depth */ Review Comment: ```suggestion /* White no matter the color depth */ ``` ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = +{ +#ifdef CONFIG_VIRT_QEMU_PCI_TEST + &g_pci_type_qemu_pci_test, +#endif +#ifdef CONFIG_VIRT_QEMU_EDU + &g_pci_type_qemu_edu, +#endif + 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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); + + 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 (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 \ Review Comment: ```suggestion pcierr("[%02x:%02x.%x] Error: Invalid ” “device probe function\n”, ``` ########## boards/x86_64/intel64/qemu-intel64/src/qemu_pci.c: ########## @@ -0,0 +1,229 @@ +/**************************************************************************** + * 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 "x86_64_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(struct pci_dev_s *dev, int reg, + uint32_t val, int width); + +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(const volatile void *addr, int width); + +static void qemu_pci_io_write(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(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(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(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(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); Review Comment: ```suggestion outl((uint32_t)val, portaddr); ``` ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = +{ +#ifdef CONFIG_VIRT_QEMU_PCI_TEST + &g_pci_type_qemu_pci_test, +#endif +#ifdef CONFIG_VIRT_QEMU_EDU + &g_pci_type_qemu_edu, +#endif + 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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); + + 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 (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 Review Comment: ```suggestion /* This is a bridge device we need to determine the bus idx and ``` ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = +{ +#ifdef CONFIG_VIRT_QEMU_PCI_TEST + &g_pci_type_qemu_pci_test, +#endif +#ifdef CONFIG_VIRT_QEMU_EDU + &g_pci_type_qemu_edu, +#endif + 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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); + + 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 (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); Review Comment: ```suggestion bus_idx, slot_idx, dev_func); ``` ########## drivers/pci/pci.c: ########## @@ -0,0 +1,832 @@ +/**************************************************************************** + * 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 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, + 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 const struct pci_dev_type_s **types); + +static void pci_scan_bus(FAR struct pci_bus_s *root_bus, + uint8_t bus_idx, + FAR const 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 + ****************************************************************************/ + +const struct pci_dev_type_s *pci_device_types[] = +{ +#ifdef CONFIG_VIRT_QEMU_PCI_TEST + &g_pci_type_qemu_pci_test, +#endif +#ifdef CONFIG_VIRT_QEMU_EDU + &g_pci_type_qemu_edu, +#endif + 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 const struct pci_dev_type_s **types) +{ + struct pci_dev_s tmp_dev; + 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); + + 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 (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)) Review Comment: ```suggestion (sub_class == PCI_CLASS_SUB_PCI_BRG)) ``` ########## 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: should we support map return a different address? ########## 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: is it good to use a hard code address -- 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]
