mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 10:58:49 +08:00
cosmetic changes after pci code rebase
This commit is contained in:
parent
2e758f33ee
commit
a12fdd8876
10 changed files with 477 additions and 346 deletions
|
@ -78,11 +78,14 @@ static void x86_64_mb2_config(void)
|
|||
/* Check that we were actually booted by a mulitboot2 bootloader */
|
||||
|
||||
if (mb_magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
||||
return;
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (tag = (struct multiboot_tag *)(uintptr_t)(mb_info_struct + 8);
|
||||
tag->type != MULTIBOOT_TAG_TYPE_END;
|
||||
tag = (struct multiboot_tag *)((uint8_t *)tag + ((tag->size + 7) & ~7)))
|
||||
tag->type != MULTIBOOT_TAG_TYPE_END;
|
||||
tag = (struct multiboot_tag *)((uint8_t *)tag +
|
||||
((tag->size + 7) & ~7)))
|
||||
{
|
||||
switch (tag->type)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/x86_64/src/intel64/intel64_lowsetup.c
|
||||
* arch/x86_64/src/intel64/intel64_mbfb.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -37,44 +37,50 @@
|
|||
#include "x86_64_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct multiboot_fb_s
|
||||
{
|
||||
void *baseaddr;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
uint32_t pitch;
|
||||
uint8_t bpp;
|
||||
uint8_t type;
|
||||
void *baseaddr;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
uint32_t pitch;
|
||||
uint8_t bpp;
|
||||
uint8_t type;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MULTBOOT2_FB_TERM
|
||||
struct fb_term_s
|
||||
{
|
||||
const struct nx_fontpackage_s *font;
|
||||
uint32_t cursor_x;
|
||||
uint32_t cursor_y;
|
||||
uint32_t cursor_x;
|
||||
uint32_t cursor_y;
|
||||
};
|
||||
#endif
|
||||
|
||||
void fb_term_initialize(void);
|
||||
#endif /* CONFIG_MULTBOOT2_FB_TERM */
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
void fb_clear(void);
|
||||
#ifdef CONFIG_MULTBOOT2_FB_TERM
|
||||
static void fb_term_initialize(void);
|
||||
static void fb_scroll(void);
|
||||
#endif
|
||||
static void fb_clear(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
struct multiboot_fb_s fb =
|
||||
static struct multiboot_fb_s g_fb =
|
||||
{
|
||||
.baseaddr = NULL
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MULTBOOT2_FB_TERM
|
||||
struct fb_term_s fb_term;
|
||||
#endif /* CONFIG_MULTBOOT2_FB_TERM */
|
||||
static struct fb_term_s g_fb_term;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
|
@ -85,7 +91,7 @@ struct fb_term_s fb_term;
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: fb_draw_pixel
|
||||
* Name: fb_draw_pixel
|
||||
*
|
||||
* Description:
|
||||
* Draw a pixel on the framebuffer. Note that the color paramter must
|
||||
|
@ -97,20 +103,24 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
|
|||
{
|
||||
/* Check if we support this type of framebuffer */
|
||||
|
||||
if (fb.type != MULTIBOOT_FRAMEBUFFER_TYPE_RGB)
|
||||
return;
|
||||
if (g_fb.type != MULTIBOOT_FRAMEBUFFER_TYPE_RGB)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we are within the bounds */
|
||||
|
||||
if (x >= fb.width || y >= fb.height)
|
||||
return;
|
||||
if (x >= g_fb.width || y >= g_fb.height)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fb.bpp)
|
||||
switch (g_fb.bpp)
|
||||
{
|
||||
case 8:
|
||||
{
|
||||
uint8_t *pixel = (uint8_t *)(
|
||||
(uintptr_t)fb.baseaddr + (fb.pitch * y) + x);
|
||||
(uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x);
|
||||
*pixel = (uint8_t)color;
|
||||
break;
|
||||
}
|
||||
|
@ -119,7 +129,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
|
|||
case 16:
|
||||
{
|
||||
uint16_t *pixel = (uint16_t *)(
|
||||
(uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 2);
|
||||
(uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x * 2);
|
||||
*pixel = (uint16_t)color;
|
||||
break;
|
||||
}
|
||||
|
@ -131,7 +141,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
|
|||
*/
|
||||
|
||||
uint32_t *pixel = (uint32_t *)(
|
||||
(uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 3);
|
||||
(uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x * 3);
|
||||
*pixel = (color & 0xffffff) | (*pixel & 0xff000000);
|
||||
break;
|
||||
}
|
||||
|
@ -139,7 +149,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
|
|||
case 32:
|
||||
{
|
||||
uint32_t *pixel = (uint32_t *)(
|
||||
(uintptr_t)fb.baseaddr + (fb.pitch * y) + x * 4);
|
||||
(uintptr_t)g_fb.baseaddr + (g_fb.pitch * y) + x * 4);
|
||||
*pixel = color;
|
||||
break;
|
||||
}
|
||||
|
@ -148,7 +158,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
|
|||
|
||||
#if 0
|
||||
/****************************************************************************
|
||||
* Function: fb_test_line
|
||||
* Name: fb_test_line
|
||||
*
|
||||
* Description:
|
||||
* This is a simple test function that can be used to draw a 45deg
|
||||
|
@ -158,7 +168,7 @@ static void fb_draw_pixel(uint32_t color, uint32_t x, uint32_t y)
|
|||
|
||||
static void fb_test_line(void)
|
||||
{
|
||||
size_t idx;
|
||||
size_t idx;
|
||||
uint32_t color;
|
||||
|
||||
switch (fb.bpp)
|
||||
|
@ -188,88 +198,114 @@ static void fb_test_line(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_MULTBOOT2_FB_TERM
|
||||
/****************************************************************************
|
||||
* Name: fb_term_initialize
|
||||
****************************************************************************/
|
||||
|
||||
static void fb_term_initialize(void)
|
||||
{
|
||||
g_fb_term.font = nxf_getfonthandle(FONTID_DEFAULT);
|
||||
g_fb_term.cursor_x = 0;
|
||||
g_fb_term.cursor_y = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_scroll
|
||||
****************************************************************************/
|
||||
|
||||
static void fb_scroll(void)
|
||||
{
|
||||
void *destp = fb.baseaddr;
|
||||
uint32_t save_rows = ((fb.height / fb_term.font->metrics.mxheight) - 1);
|
||||
size_t row_size = fb.pitch * fb_term.font->metrics.mxheight;
|
||||
uint32_t pxl_row = 0;
|
||||
void *destp = g_fb.baseaddr;
|
||||
uint32_t save_rows = 0;
|
||||
size_t row_size = 0;
|
||||
uint32_t pxl_row = 0;
|
||||
|
||||
for (; pxl_row < save_rows * fb_term.font->metrics.mxheight; pxl_row++)
|
||||
save_rows = ((g_fb.height / g_fb_term.font->metrics.mxheight) - 1);
|
||||
row_size = g_fb.pitch * g_fb_term.font->metrics.mxheight;
|
||||
|
||||
for (; pxl_row < save_rows * g_fb_term.font->metrics.mxheight; pxl_row++)
|
||||
{
|
||||
memcpy(destp, destp + row_size, fb.pitch);
|
||||
destp += fb.pitch;
|
||||
memcpy(destp, destp + row_size, g_fb.pitch);
|
||||
destp += g_fb.pitch;
|
||||
}
|
||||
|
||||
memset(destp, 0, fb.pitch * (fb.height - pxl_row));
|
||||
memset(destp, 0, g_fb.pitch * (g_fb.height - pxl_row));
|
||||
|
||||
fb_term.cursor_y -= fb_term.font->metrics.mxheight;
|
||||
g_fb_term.cursor_y -= g_fb_term.font->metrics.mxheight;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: fb_clear
|
||||
****************************************************************************/
|
||||
|
||||
static void fb_clear(void)
|
||||
{
|
||||
if (g_fb.baseaddr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset(g_fb.baseaddr, 0, g_fb.pitch * g_fb.height);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_64_mb2_fbinitialize
|
||||
****************************************************************************/
|
||||
|
||||
void x86_64_mb2_fbinitialize(struct multiboot_tag_framebuffer *fbt)
|
||||
{
|
||||
fb.baseaddr = (void *)(uintptr_t)fbt->common.framebuffer_addr;
|
||||
fb.width = fbt->common.framebuffer_width;
|
||||
fb.height = fbt->common.framebuffer_height;
|
||||
fb.pitch = fbt->common.framebuffer_pitch;
|
||||
fb.bpp = fbt->common.framebuffer_bpp;
|
||||
fb.type = fbt->common.framebuffer_type;
|
||||
g_fb.baseaddr = (void *)(uintptr_t)fbt->common.framebuffer_addr;
|
||||
g_fb.width = fbt->common.framebuffer_width;
|
||||
g_fb.height = fbt->common.framebuffer_height;
|
||||
g_fb.pitch = fbt->common.framebuffer_pitch;
|
||||
g_fb.bpp = fbt->common.framebuffer_bpp;
|
||||
g_fb.type = fbt->common.framebuffer_type;
|
||||
|
||||
up_map_region(fb.baseaddr, fb.pitch * fb.height,
|
||||
up_map_region(g_fb.baseaddr, g_fb.pitch * g_fb.height,
|
||||
X86_PAGE_WR | X86_PAGE_PRESENT |
|
||||
X86_PAGE_NOCACHE | X86_PAGE_GLOBAL);
|
||||
|
||||
fb_clear();
|
||||
|
||||
|
||||
#ifdef CONFIG_MULTBOOT2_FB_TERM
|
||||
fb_term_initialize();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void fb_clear(void)
|
||||
{
|
||||
if (fb.baseaddr == NULL)
|
||||
return;
|
||||
|
||||
memset(fb.baseaddr, 0, fb.pitch * fb.height);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MULTBOOT2_FB_TERM
|
||||
void fb_term_initialize(void)
|
||||
{
|
||||
fb_term.font = nxf_getfonthandle(FONTID_DEFAULT);
|
||||
fb_term.cursor_x = 0;
|
||||
fb_term.cursor_y = 0;
|
||||
}
|
||||
/****************************************************************************
|
||||
* Name: fb_putc
|
||||
****************************************************************************/
|
||||
|
||||
void fb_putc(char ch)
|
||||
{
|
||||
uint8_t gly_x;
|
||||
uint8_t gly_y;
|
||||
const struct nx_fontbitmap_s *fbm;
|
||||
uint8_t gly_x;
|
||||
uint8_t gly_y;
|
||||
|
||||
if (fb.baseaddr == NULL)
|
||||
return;
|
||||
if (g_fb.baseaddr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\n')
|
||||
{
|
||||
fb_term.cursor_y += fb_term.font->metrics.mxheight;
|
||||
g_fb_term.cursor_y += g_fb_term.font->metrics.mxheight;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\r')
|
||||
{
|
||||
fb_term.cursor_x = 0;
|
||||
g_fb_term.cursor_x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
fbm = nxf_getbitmap((NXHANDLE)fb_term.font, ch);
|
||||
fbm = nxf_getbitmap((NXHANDLE)g_fb_term.font, ch);
|
||||
if (fbm == NULL)
|
||||
{
|
||||
fb_putc('.');
|
||||
|
@ -278,7 +314,7 @@ void fb_putc(char ch)
|
|||
|
||||
for (gly_y = 0; gly_y < fbm->metric.height; gly_y++)
|
||||
{
|
||||
if (fb_term.cursor_y + gly_y >= fb.height)
|
||||
if (g_fb_term.cursor_y + gly_y >= g_fb.height)
|
||||
{
|
||||
fb_scroll();
|
||||
fb_putc(ch);
|
||||
|
@ -287,23 +323,28 @@ void fb_putc(char ch)
|
|||
|
||||
for (gly_x = 0; gly_x < fbm->metric.width; gly_x++)
|
||||
{
|
||||
if (fb_term.cursor_x + gly_x >= fb.width)
|
||||
if (g_fb_term.cursor_x + gly_x >= g_fb.width)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t stride = (fbm->metric.width + 7) >> 3;
|
||||
uint8_t gly_byte = stride * gly_y + (gly_x >> 3);
|
||||
uint8_t gly_bit = gly_x & 0x7;
|
||||
uint32_t color = 0; /* Black no matter the color depth */
|
||||
uint8_t stride = (fbm->metric.width + 7) >> 3;
|
||||
uint8_t gly_byte = stride * gly_y + (gly_x >> 3);
|
||||
uint8_t gly_bit = gly_x & 0x7;
|
||||
uint32_t color = 0;
|
||||
|
||||
if ((fbm->bitmap[gly_byte] >> (7 - gly_bit)) & 0x01)
|
||||
color = 0xffffffff; /* Black no matter the color depth */
|
||||
{
|
||||
/* White no matter the color depth */
|
||||
|
||||
color = 0xffffffff;
|
||||
}
|
||||
|
||||
fb_draw_pixel(
|
||||
color, fb_term.cursor_x + gly_x, fb_term.cursor_y + gly_y);
|
||||
color, g_fb_term.cursor_x + gly_x, g_fb_term.cursor_y + gly_y);
|
||||
}
|
||||
}
|
||||
|
||||
fb_term.cursor_x += fbm->metric.width;
|
||||
g_fb_term.cursor_x += fbm->metric.width;
|
||||
}
|
||||
#endif /* CONFIG_MULTBOOT2_FB_TERM */
|
||||
|
|
|
@ -43,35 +43,35 @@
|
|||
* Private Functions Definitions
|
||||
****************************************************************************/
|
||||
|
||||
static void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
|
||||
uint32_t val, int width);
|
||||
static void qemu_pci_cfg_write(struct pci_dev_s *dev, int reg,
|
||||
uint32_t val, int width);
|
||||
|
||||
static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
|
||||
static uint32_t qemu_pci_cfg_read(struct pci_dev_s *dev, int reg,
|
||||
int width);
|
||||
|
||||
static int qemu_pci_map_bar(uint64_t addr, uint64_t len);
|
||||
|
||||
static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width);
|
||||
static uint32_t qemu_pci_io_read(const volatile void *addr, int width);
|
||||
|
||||
static void qemu_pci_io_write(FAR const volatile void *addr, uint32_t val,
|
||||
static void qemu_pci_io_write(const volatile void *addr, uint32_t val,
|
||||
int width);
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
struct pci_bus_ops_s qemu_pci_bus_ops =
|
||||
static const struct pci_bus_ops_s g_qemu_pci_bus_ops =
|
||||
{
|
||||
.pci_cfg_write = qemu_pci_cfg_write,
|
||||
.pci_cfg_read = qemu_pci_cfg_read,
|
||||
.pci_map_bar = qemu_pci_map_bar,
|
||||
.pci_io_read = qemu_pci_io_read,
|
||||
.pci_io_write = qemu_pci_io_write,
|
||||
.pci_cfg_write = qemu_pci_cfg_write,
|
||||
.pci_cfg_read = qemu_pci_cfg_read,
|
||||
.pci_map_bar = qemu_pci_map_bar,
|
||||
.pci_io_read = qemu_pci_io_read,
|
||||
.pci_io_write = qemu_pci_io_write,
|
||||
};
|
||||
|
||||
struct pci_bus_s qemu_pci_bus =
|
||||
static struct pci_bus_s g_qemu_pci_bus =
|
||||
{
|
||||
.ops = &qemu_pci_bus_ops,
|
||||
.ops = &g_qemu_pci_bus_ops,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -86,19 +86,20 @@ struct pci_bus_s qemu_pci_bus =
|
|||
* specified by dev
|
||||
*
|
||||
* Input Parameters:
|
||||
* bdf - Device private data
|
||||
* reg - A pointer to the read-only buffer of data to be written
|
||||
* size - The number of bytes to send from the buffer
|
||||
* bdf - Device private data
|
||||
* reg - A pointer to the read-only buffer of data to be written
|
||||
* size - The number of bytes to send from the buffer
|
||||
*
|
||||
* Returned Value:
|
||||
* 0: success, <0: A negated errno
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
|
||||
static void qemu_pci_cfg_write(struct pci_dev_s *dev, int reg,
|
||||
uint32_t val, int width)
|
||||
{
|
||||
uint8_t offset_mask = (4 - width);
|
||||
|
||||
outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
|
||||
switch (width)
|
||||
{
|
||||
|
@ -133,11 +134,12 @@ static void qemu_pci_cfg_write(FAR struct pci_dev_s *dev, int reg,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
|
||||
static uint32_t qemu_pci_cfg_read(struct pci_dev_s *dev, int reg,
|
||||
int width)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint8_t offset_mask = 4 - width;
|
||||
uint8_t offset_mask = 4 - width;
|
||||
|
||||
outl(PCI_CFG_EN | (dev->bdf << 8) | reg, PCI_CFG_ADDR);
|
||||
|
||||
switch (width)
|
||||
|
@ -159,9 +161,10 @@ static uint32_t qemu_pci_cfg_read(FAR struct pci_dev_s *dev, int reg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width)
|
||||
static uint32_t qemu_pci_io_read(const volatile void *addr, int width)
|
||||
{
|
||||
uint16_t portaddr = (uint16_t)(intptr_t)addr;
|
||||
|
||||
switch (width)
|
||||
{
|
||||
case 1:
|
||||
|
@ -178,20 +181,21 @@ static uint32_t qemu_pci_io_read(FAR const volatile void *addr, int width)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void qemu_pci_io_write(FAR const volatile void *addr, uint32_t val,
|
||||
static void qemu_pci_io_write(const volatile void *addr, uint32_t val,
|
||||
int width)
|
||||
{
|
||||
uint16_t portaddr = (uint16_t)(intptr_t)addr;
|
||||
|
||||
switch (width)
|
||||
{
|
||||
case 1:
|
||||
outb((uint8_t)val, portaddr);
|
||||
return;
|
||||
case 2:
|
||||
outw((uint8_t)val, portaddr);
|
||||
outw((uint16_t)val, portaddr);
|
||||
return;
|
||||
case 4:
|
||||
outl((uint8_t)val, portaddr);
|
||||
outl((uint32_t)val, portaddr);
|
||||
return;
|
||||
default:
|
||||
pcierr("Invalid write width %d\n", width);
|
||||
|
@ -221,5 +225,5 @@ static int qemu_pci_map_bar(uint64_t addr, uint64_t len)
|
|||
void qemu_pci_init(void)
|
||||
{
|
||||
pciinfo("Initializing PCI Bus\n");
|
||||
pci_initialize(&qemu_pci_bus);
|
||||
pci_initialize(&g_qemu_pci_bus);
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
|
@ -18,8 +18,6 @@
|
|||
#
|
||||
############################################################################
|
||||
|
||||
# Don't build anything if there is no CAN support
|
||||
|
||||
ifeq ($(CONFIG_PCI),y)
|
||||
|
||||
CSRCS += pci.c
|
||||
|
@ -28,5 +26,5 @@ CSRCS += pci.c
|
|||
|
||||
DEPPATH += --dep-path pci
|
||||
VPATH += :pci
|
||||
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)pci}
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)pci
|
||||
endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* nuttx/drivers/pci/pci.c
|
||||
* drivers/pci/pci.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -51,7 +51,7 @@
|
|||
|
||||
static void pci_probe_device(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx, uint8_t slot_idx, uint8_t func,
|
||||
FAR struct pci_dev_type_s **types);
|
||||
FAR const struct pci_dev_type_s **types);
|
||||
|
||||
static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx, uint8_t slot_idx,
|
||||
|
@ -59,11 +59,11 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
|
|||
|
||||
static void pci_scan_device(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx, uint8_t slot_idx,
|
||||
FAR struct pci_dev_type_s **types);
|
||||
FAR const struct pci_dev_type_s **types);
|
||||
|
||||
static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx,
|
||||
FAR struct pci_dev_type_s **types);
|
||||
FAR const struct pci_dev_type_s **types);
|
||||
|
||||
static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask);
|
||||
|
||||
|
@ -73,14 +73,14 @@ static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask);
|
|||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
struct pci_dev_type_s *pci_device_types[] =
|
||||
const struct pci_dev_type_s *g_pci_device_types[] =
|
||||
{
|
||||
#ifdef CONFIG_VIRT_QEMU_PCI_TEST
|
||||
&pci_type_qemu_pci_test,
|
||||
#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
|
||||
&g_pci_type_qemu_pci_test,
|
||||
#endif
|
||||
#ifdef CONFIG_VIRT_QEMU_EDU
|
||||
&pci_type_qemu_edu,
|
||||
#endif /* CONFIG_VIRT_QEMU_EDU */
|
||||
&g_pci_type_qemu_edu,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -105,12 +105,13 @@ struct pci_dev_type_s *pci_device_types[] =
|
|||
|
||||
static void pci_probe_device(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx, uint8_t slot_idx, uint8_t func,
|
||||
FAR struct pci_dev_type_s **types)
|
||||
FAR const struct pci_dev_type_s **types)
|
||||
{
|
||||
struct pci_dev_s tmp_dev;
|
||||
uint16_t vid;
|
||||
uint16_t id;
|
||||
uint32_t class_rev;
|
||||
uint32_t class_rev;
|
||||
uint16_t vid;
|
||||
uint16_t id;
|
||||
int i;
|
||||
|
||||
tmp_dev.bus = root_bus;
|
||||
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, func);
|
||||
|
@ -124,7 +125,7 @@ static void pci_probe_device(FAR struct pci_bus_s *root_bus,
|
|||
|
||||
pci_dev_dump(&tmp_dev);
|
||||
|
||||
for (int i = 0; types[i] != NULL; i++)
|
||||
for (i = 0; types[i] != NULL; i++)
|
||||
{
|
||||
if (types[i]->vendor == PCI_ID_ANY ||
|
||||
types[i]->vendor == vid)
|
||||
|
@ -144,10 +145,11 @@ static void pci_probe_device(FAR struct pci_bus_s *root_bus,
|
|||
}
|
||||
else
|
||||
{
|
||||
pcierr("[%02x:%02x.%x] Error: Invalid \
|
||||
device probe function\n",
|
||||
bus_idx, slot_idx, func);
|
||||
pcierr("[%02x:%02x.%x] Error: Invalid"
|
||||
"device probe function\n",
|
||||
bus_idx, slot_idx, func);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -175,9 +177,9 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
|
|||
uint8_t dev_func)
|
||||
{
|
||||
struct pci_dev_s tmp_dev;
|
||||
uint8_t base_class;
|
||||
uint8_t sub_class;
|
||||
uint8_t secondary_bus;
|
||||
uint8_t base_class;
|
||||
uint8_t sub_class;
|
||||
uint8_t secondary_bus;
|
||||
|
||||
tmp_dev.bus = root_bus;
|
||||
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
|
||||
|
@ -187,18 +189,19 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
|
|||
base_class = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_CLASS, 1);
|
||||
sub_class = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_SUBCLASS, 1);
|
||||
|
||||
if ((base_class == PCI_CLASS_BASE_BRG_DEV) && \
|
||||
(sub_class == PCI_CLASS_SUB_PCI_BRG))
|
||||
if ((base_class == PCI_CLASS_BASE_BRG_DEV) &&
|
||||
(sub_class == PCI_CLASS_SUB_PCI_BRG))
|
||||
{
|
||||
/* This is a bridge device we need to determin the bus idx and
|
||||
/* This is a bridge device we need to determine the bus idx and
|
||||
* enumerate it just like we do the root.
|
||||
*/
|
||||
|
||||
pciinfo("[%02x:%02x.%x] Found Bridge\n",
|
||||
bus_idx, slot_idx, dev_func);
|
||||
bus_idx, slot_idx, dev_func);
|
||||
|
||||
secondary_bus = root_bus->ops->pci_cfg_read(
|
||||
&tmp_dev, PCI_CONFIG_SEC_BUS, 1);
|
||||
|
||||
return secondary_bus;
|
||||
}
|
||||
|
||||
|
@ -222,25 +225,21 @@ static uint8_t pci_check_pci_bridge(FAR struct pci_bus_s *root_bus,
|
|||
|
||||
static void pci_scan_device(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx, uint8_t slot_idx,
|
||||
FAR struct pci_dev_type_s **types)
|
||||
FAR const struct pci_dev_type_s **types)
|
||||
{
|
||||
struct pci_dev_s tmp_dev;
|
||||
uint8_t dev_func = 0;
|
||||
uint16_t vid;
|
||||
uint8_t sec_bus;
|
||||
uint8_t multi_function;
|
||||
uint8_t multi_function;
|
||||
uint8_t dev_func = 0;
|
||||
uint16_t vid;
|
||||
uint8_t sec_bus;
|
||||
|
||||
tmp_dev.bus = root_bus;
|
||||
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
|
||||
vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
|
||||
if (vid == 0xffff)
|
||||
{
|
||||
return;
|
||||
|
||||
/* Check if this is a PCI-PCI bridge device */
|
||||
|
||||
sec_bus = pci_check_pci_bridge(root_bus, bus_idx, slot_idx, dev_func);
|
||||
if (sec_bus)
|
||||
pci_scan_bus(root_bus, sec_bus, types);
|
||||
}
|
||||
|
||||
multi_function = root_bus->ops->pci_cfg_read(
|
||||
&tmp_dev, PCI_CONFIG_HEADER_TYPE, 1) & PCI_HEADER_MASK_MULTI;
|
||||
|
@ -258,10 +257,12 @@ static void pci_scan_device(FAR struct pci_bus_s *root_bus,
|
|||
{
|
||||
tmp_dev.bdf = PCI_BDF(bus_idx, slot_idx, dev_func);
|
||||
vid = root_bus->ops->pci_cfg_read(&tmp_dev, PCI_CONFIG_VENDOR, 2);
|
||||
|
||||
if (vid != 0xffff)
|
||||
{
|
||||
sec_bus = pci_check_pci_bridge(
|
||||
root_bus, bus_idx, slot_idx, dev_func);
|
||||
|
||||
if (sec_bus)
|
||||
{
|
||||
pci_scan_bus(root_bus, sec_bus, types);
|
||||
|
@ -274,7 +275,17 @@ static void pci_scan_device(FAR struct pci_bus_s *root_bus,
|
|||
}
|
||||
else
|
||||
{
|
||||
pci_probe_device(root_bus, bus_idx, slot_idx, dev_func, types);
|
||||
/* Check if this is a PCI-PCI bridge device with MF=0 */
|
||||
|
||||
sec_bus = pci_check_pci_bridge(root_bus, bus_idx, slot_idx, dev_func);
|
||||
if (sec_bus)
|
||||
{
|
||||
pci_scan_bus(root_bus, sec_bus, types);
|
||||
}
|
||||
else
|
||||
{
|
||||
pci_probe_device(root_bus, bus_idx, slot_idx, dev_func, types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,7 +305,7 @@ static void pci_scan_device(FAR struct pci_bus_s *root_bus,
|
|||
|
||||
static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
|
||||
uint8_t bus_idx,
|
||||
FAR struct pci_dev_type_s **types)
|
||||
FAR const struct pci_dev_type_s **types)
|
||||
{
|
||||
uint8_t slot_idx;
|
||||
|
||||
|
@ -302,8 +313,6 @@ static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
|
|||
{
|
||||
pci_scan_device(root_bus, bus_idx, slot_idx, types);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -320,11 +329,11 @@ static void pci_scan_bus(FAR struct pci_bus_s *root_bus,
|
|||
|
||||
static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
|
||||
{
|
||||
uint16_t cmd;
|
||||
uint16_t cmd;
|
||||
|
||||
cmd = dev->bus->ops->pci_cfg_read(dev, PCI_CONFIG_COMMAND, 2);
|
||||
dev->bus->ops->pci_cfg_write(dev, PCI_CONFIG_COMMAND,
|
||||
(cmd | bitmask), 2);
|
||||
(cmd | bitmask), 2);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -341,11 +350,11 @@ static void pci_set_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
|
|||
|
||||
static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
|
||||
{
|
||||
uint16_t cmd;
|
||||
uint16_t cmd;
|
||||
|
||||
cmd = dev->bus->ops->pci_cfg_read(dev, PCI_CONFIG_COMMAND, 2);
|
||||
dev->bus->ops->pci_cfg_write(dev, PCI_CONFIG_COMMAND,
|
||||
(cmd & ~bitmask), 2);
|
||||
(cmd & ~bitmask), 2);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -369,12 +378,17 @@ static void pci_clear_cmd_bit(FAR struct pci_dev_s *dev, uint16_t bitmask)
|
|||
****************************************************************************/
|
||||
|
||||
int pci_enumerate(FAR struct pci_bus_s *bus,
|
||||
FAR struct pci_dev_type_s **types)
|
||||
FAR const struct pci_dev_type_s **types)
|
||||
{
|
||||
if (!bus)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!types)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pci_scan_bus(bus, 0, types);
|
||||
return OK;
|
||||
|
@ -400,7 +414,7 @@ int pci_enumerate(FAR struct pci_bus_s *bus,
|
|||
|
||||
int pci_initialize(FAR struct pci_bus_s *bus)
|
||||
{
|
||||
return pci_enumerate(bus, pci_device_types);
|
||||
return pci_enumerate(bus, g_pci_device_types);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -425,12 +439,17 @@ int pci_enable_io(FAR struct pci_dev_s *dev, int res)
|
|||
{
|
||||
switch (res)
|
||||
{
|
||||
case PCI_SYS_RES_IOPORT:
|
||||
pci_set_cmd_bit(dev, PCI_CMD_IO_SPACE);
|
||||
return OK;
|
||||
case PCI_SYS_RES_MEM:
|
||||
pci_set_cmd_bit(dev, PCI_CMD_MEM_SPACE);
|
||||
return OK;
|
||||
case PCI_SYS_RES_IOPORT:
|
||||
{
|
||||
pci_set_cmd_bit(dev, PCI_CMD_IO_SPACE);
|
||||
return OK;
|
||||
}
|
||||
|
||||
case PCI_SYS_RES_MEM:
|
||||
{
|
||||
pci_set_cmd_bit(dev, PCI_CMD_MEM_SPACE);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
@ -458,12 +477,17 @@ int pci_disable_io(FAR struct pci_dev_s *dev, int res)
|
|||
{
|
||||
switch (res)
|
||||
{
|
||||
case PCI_SYS_RES_IOPORT:
|
||||
pci_clear_cmd_bit(dev, PCI_CMD_IO_SPACE);
|
||||
return OK;
|
||||
case PCI_SYS_RES_MEM:
|
||||
pci_clear_cmd_bit(dev, PCI_CMD_MEM_SPACE);
|
||||
return OK;
|
||||
case PCI_SYS_RES_IOPORT:
|
||||
{
|
||||
pci_clear_cmd_bit(dev, PCI_CMD_IO_SPACE);
|
||||
return OK;
|
||||
}
|
||||
|
||||
case PCI_SYS_RES_MEM:
|
||||
{
|
||||
pci_clear_cmd_bit(dev, PCI_CMD_MEM_SPACE);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
@ -530,7 +554,7 @@ int pci_disable_bus_master(FAR struct pci_dev_s *dev)
|
|||
int pci_bar_valid(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
||||
{
|
||||
uint32_t bar = dev->bus->ops->pci_cfg_read(dev,
|
||||
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
|
||||
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
|
||||
|
||||
if (bar == PCI_BAR_INVALID)
|
||||
{
|
||||
|
@ -559,12 +583,14 @@ int pci_bar_valid(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
|||
bool pci_bar_is_64(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
||||
{
|
||||
uint32_t bar = dev->bus->ops->pci_cfg_read(dev,
|
||||
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
|
||||
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
|
||||
|
||||
/* Check that it is memory and not io port */
|
||||
|
||||
if ((bar & PCI_BAR_LAYOUT_MASK) != PCI_BAR_LAYOUT_MEM)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((bar & PCI_BAR_TYPE_MASK) >> PCI_BAR_TYPE_OFFSET) == PCI_BAR_TYPE_64)
|
||||
{
|
||||
|
@ -591,12 +617,13 @@ bool pci_bar_is_64(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
|||
|
||||
uint64_t pci_bar_size(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
||||
{
|
||||
uint32_t bar;
|
||||
uint32_t size;
|
||||
uint64_t full_size;
|
||||
uint8_t bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
|
||||
const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
|
||||
FAR const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
|
||||
uint32_t bar;
|
||||
uint32_t size;
|
||||
uint64_t full_size;
|
||||
uint8_t bar_offset;
|
||||
|
||||
bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
|
||||
bar = dev_ops->pci_cfg_read(dev, bar_offset, 4);
|
||||
|
||||
/* Write all 1 to the BAR. We are looking for which bits will change */
|
||||
|
@ -660,10 +687,11 @@ uint64_t pci_bar_size(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
|||
|
||||
uint64_t pci_bar_addr(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
||||
{
|
||||
uint64_t addr;
|
||||
uint8_t bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
|
||||
const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
|
||||
FAR const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
|
||||
uint64_t addr;
|
||||
uint8_t bar_offset;
|
||||
|
||||
bar_offset = PCI_HEADER_NORM_BAR0 + (bar_id * 4);
|
||||
addr = dev_ops->pci_cfg_read(dev, bar_offset, 4);
|
||||
|
||||
if ((addr & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
|
||||
|
@ -699,25 +727,31 @@ uint64_t pci_bar_addr(FAR struct pci_dev_s *dev, uint8_t bar_id)
|
|||
|
||||
void pci_dev_dump(FAR struct pci_dev_s *dev)
|
||||
{
|
||||
uint8_t bar_id;
|
||||
uint8_t bar_mem_type = 0;
|
||||
uint32_t bar;
|
||||
uint64_t bar_size;
|
||||
uint64_t bar_addr;
|
||||
FAR const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
|
||||
uint8_t bar_mem_type = 0;
|
||||
uint8_t bar_id;
|
||||
uint32_t bar;
|
||||
uint64_t bar_size;
|
||||
uint64_t bar_addr;
|
||||
uint8_t cap_id;
|
||||
uint8_t cap_offset;
|
||||
uint32_t bdf;
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
uint8_t header;
|
||||
uint8_t progif;
|
||||
uint8_t subclass;
|
||||
uint8_t class;
|
||||
uint8_t int_pin;
|
||||
uint8_t int_line;
|
||||
|
||||
uint8_t cap_id;
|
||||
uint8_t cap_offset;
|
||||
|
||||
const struct pci_bus_ops_s *dev_ops = dev->bus->ops;
|
||||
uint32_t bdf = dev->bdf;
|
||||
uint16_t vid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_VENDOR, 2);
|
||||
uint16_t pid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_DEVICE, 2);
|
||||
uint8_t header = dev_ops->pci_cfg_read(dev, PCI_CONFIG_HEADER_TYPE, 1);
|
||||
uint8_t progif = dev_ops->pci_cfg_read(dev, PCI_CONFIG_PROG_IF, 1);
|
||||
uint8_t subclass = dev_ops->pci_cfg_read(dev, PCI_CONFIG_SUBCLASS, 1);
|
||||
uint8_t class = dev_ops->pci_cfg_read(dev, PCI_CONFIG_CLASS, 1);
|
||||
uint8_t int_pin;
|
||||
uint8_t int_line;
|
||||
bdf = dev->bdf;
|
||||
vid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_VENDOR, 2);
|
||||
pid = dev_ops->pci_cfg_read(dev, PCI_CONFIG_DEVICE, 2);
|
||||
header = dev_ops->pci_cfg_read(dev, PCI_CONFIG_HEADER_TYPE, 1);
|
||||
progif = dev_ops->pci_cfg_read(dev, PCI_CONFIG_PROG_IF, 1);
|
||||
subclass = dev_ops->pci_cfg_read(dev, PCI_CONFIG_SUBCLASS, 1);
|
||||
class = dev_ops->pci_cfg_read(dev, PCI_CONFIG_CLASS, 1);
|
||||
|
||||
pciinfo("[%02x:%02x.%x] %04x:%04x\n",
|
||||
bdf >> 8, (bdf & 0xff) >> 3, bdf & 0x7, vid, pid);
|
||||
|
@ -740,7 +774,9 @@ void pci_dev_dump(FAR struct pci_dev_s *dev)
|
|||
}
|
||||
|
||||
if ((header & PCI_HEADER_TYPE_MASK) != PCI_HEADER_NORMAL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int_pin = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_INT_PIN, 1);
|
||||
int_line = dev_ops->pci_cfg_read(dev, PCI_HEADER_NORM_INT_LINE, 1);
|
||||
|
@ -749,7 +785,9 @@ void pci_dev_dump(FAR struct pci_dev_s *dev)
|
|||
for (bar_id = 0; bar_id < PCI_BAR_CNT; bar_id++)
|
||||
{
|
||||
if (pci_bar_valid(dev, bar_id) != OK)
|
||||
continue;
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bar = dev_ops->pci_cfg_read(dev,
|
||||
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
|
||||
|
@ -787,6 +825,8 @@ void pci_dev_dump(FAR struct pci_dev_s *dev)
|
|||
/* Skip next bar if this one was 64bit */
|
||||
|
||||
if (bar_mem_type == 64)
|
||||
{
|
||||
bar_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
############################################################################
|
||||
# drivers/pci/Make.defs
|
||||
# drivers/virt/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,18 +18,12 @@
|
|||
#
|
||||
############################################################################
|
||||
|
||||
# Don't build anything if there is no CAN support
|
||||
|
||||
ifeq ($(CONFIG_VIRT_QEMU_PCI_TEST),y)
|
||||
|
||||
CSRCS += qemu_pci_test.c
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_VIRT_QEMU_EDU),y)
|
||||
|
||||
CSRCS += qemu_edu.c
|
||||
|
||||
endif
|
||||
|
||||
# Include virt device driver build support
|
||||
|
@ -38,6 +32,6 @@ ifeq ($(CONFIG_VIRT),y)
|
|||
|
||||
DEPPATH += --dep-path virt
|
||||
VPATH += :virt
|
||||
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)virt}
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)virt
|
||||
|
||||
endif
|
||||
|
|
|
@ -60,6 +60,12 @@
|
|||
#define EDU_CONTROL_BAR_ID 0
|
||||
#define EDU_CONTROL_BAR_OFFSET PCI_HEADER_NORM_BAR0
|
||||
|
||||
/* One 4096 bytes long buffer at offset 0x40000 is available in the
|
||||
* EDU device
|
||||
*/
|
||||
|
||||
#define QEMU_EDU_DMABUF_OFFSET 0x40000
|
||||
|
||||
/*****************************************************************************
|
||||
* Private Types
|
||||
*****************************************************************************/
|
||||
|
@ -67,8 +73,8 @@
|
|||
struct qemu_edu_priv_s
|
||||
{
|
||||
uintptr_t base_addr;
|
||||
sem_t isr_done;
|
||||
uint32_t test_result;
|
||||
sem_t isr_done;
|
||||
uint32_t test_result;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -89,10 +95,23 @@ static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
|
|||
|
||||
static int qemu_edu_interrupt(int irq, void *context, FAR void *arg);
|
||||
|
||||
static int qemu_edu_probe(FAR struct pci_bus_s *bus,
|
||||
FAR const struct pci_dev_type_s *type,
|
||||
uint16_t bdf);
|
||||
|
||||
/*****************************************************************************
|
||||
* Private Data
|
||||
* Public Data
|
||||
*****************************************************************************/
|
||||
|
||||
const struct pci_dev_type_s g_pci_type_qemu_edu =
|
||||
{
|
||||
.vendor = 0x1234,
|
||||
.device = 0x11e8,
|
||||
.class_rev = PCI_ID_ANY,
|
||||
.name = "Qemu PCI EDU device",
|
||||
.probe = qemu_edu_probe
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Private Functions
|
||||
*****************************************************************************/
|
||||
|
@ -206,10 +225,10 @@ static void qemu_edu_test_poll(FAR struct pci_dev_s *dev, uintptr_t base_addr)
|
|||
*****************************************************************************/
|
||||
|
||||
static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
|
||||
struct qemu_edu_priv_s *drv_priv)
|
||||
FAR struct qemu_edu_priv_s *drv_priv)
|
||||
{
|
||||
uintptr_t base_addr = drv_priv->base_addr;
|
||||
uint32_t test_value;
|
||||
uint32_t test_value;
|
||||
|
||||
pciinfo("Identification: 0x%08xu\n",
|
||||
qemu_edu_read_reg32(base_addr + EDU_REG_ID));
|
||||
|
@ -253,16 +272,16 @@ static void qemu_edu_test_intx(FAR struct pci_dev_s *dev,
|
|||
*****************************************************************************/
|
||||
|
||||
static void qemu_edu_test_dma(FAR struct pci_dev_s *dev,
|
||||
struct qemu_edu_priv_s *drv_priv)
|
||||
FAR struct qemu_edu_priv_s *drv_priv)
|
||||
{
|
||||
uintptr_t base_addr = drv_priv->base_addr;
|
||||
void *test_block;
|
||||
size_t block_size = 2048;
|
||||
int i;
|
||||
uint32_t psrand;
|
||||
uint32_t tx_checksum;
|
||||
uint32_t rx_checksum;
|
||||
uint32_t dev_addr = 0x40000;
|
||||
uintptr_t base_addr = drv_priv->base_addr;
|
||||
FAR void *test_block;
|
||||
size_t block_size = 2048;
|
||||
int i;
|
||||
uint32_t psrand;
|
||||
uint32_t tx_checksum;
|
||||
uint32_t rx_checksum;
|
||||
uint32_t dev_addr = QEMU_EDU_DMABUF_OFFSET;
|
||||
|
||||
pciinfo("Identification: 0x%08xu\n",
|
||||
qemu_edu_read_reg32(base_addr + EDU_REG_ID));
|
||||
|
@ -322,58 +341,73 @@ static void qemu_edu_test_dma(FAR struct pci_dev_s *dev,
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static int qemu_edu_interrupt(int irq, void *context, FAR void *arg)
|
||||
static int qemu_edu_interrupt(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
struct qemu_edu_priv_s *drv_priv = (struct qemu_edu_priv_s *)arg;
|
||||
uintptr_t base_addr = drv_priv->base_addr;
|
||||
FAR struct qemu_edu_priv_s *drv_priv = (struct qemu_edu_priv_s *)arg;
|
||||
uintptr_t base_addr;
|
||||
uint32_t status;
|
||||
|
||||
uint32_t status = qemu_edu_read_reg32(base_addr + EDU_REG_INT_STATUS);
|
||||
base_addr = drv_priv->base_addr;
|
||||
status = qemu_edu_read_reg32(base_addr + EDU_REG_INT_STATUS);
|
||||
|
||||
qemu_edu_write_reg32(base_addr + EDU_REG_INT_ACK, ~0U);
|
||||
switch (status)
|
||||
{
|
||||
case 0x1: /* Factorial triggered */
|
||||
drv_priv->test_result = qemu_edu_read_reg32(base_addr + EDU_REG_FAC);
|
||||
pciinfo("Computed factorial: %d\n",
|
||||
drv_priv->test_result);
|
||||
break;
|
||||
case 0x100: /* DMA triggered */
|
||||
pciinfo("DMA transfer complete\n");
|
||||
break;
|
||||
default: /* Generic write */
|
||||
drv_priv->test_result = status;
|
||||
pciinfo("Received value: 0x%08x\n", status);
|
||||
/* Factorial triggered */
|
||||
|
||||
case 0x1:
|
||||
{
|
||||
drv_priv->test_result
|
||||
= qemu_edu_read_reg32(base_addr + EDU_REG_FAC);
|
||||
pciinfo("Computed factorial: %d\n", drv_priv->test_result);
|
||||
break;
|
||||
}
|
||||
|
||||
/* DMA triggered */
|
||||
|
||||
case 0x100:
|
||||
{
|
||||
pciinfo("DMA transfer complete\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Generic write */
|
||||
|
||||
default:
|
||||
{
|
||||
drv_priv->test_result = status;
|
||||
pciinfo("Received value: 0x%08x\n", status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sem_post(&drv_priv->isr_done);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public Functions
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: qemu_edu_probe
|
||||
*
|
||||
* Description:
|
||||
* Initialize device
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int qemu_edu_probe(FAR struct pci_bus_s *bus,
|
||||
FAR struct pci_dev_type_s *type, uint16_t bdf)
|
||||
static int qemu_edu_probe(FAR struct pci_bus_s *bus,
|
||||
FAR const struct pci_dev_type_s *type,
|
||||
uint16_t bdf)
|
||||
{
|
||||
uint32_t bar;
|
||||
uintptr_t bar_addr;
|
||||
struct pci_dev_s dev =
|
||||
{
|
||||
.bus = bus,
|
||||
.type = type,
|
||||
.bdf = bdf,
|
||||
};
|
||||
|
||||
uint8_t irq;
|
||||
struct qemu_edu_priv_s drv_priv;
|
||||
struct pci_dev_s dev;
|
||||
uint32_t bar;
|
||||
uintptr_t bar_addr;
|
||||
uint8_t irq;
|
||||
|
||||
/* Get dev */
|
||||
|
||||
dev.bus = bus;
|
||||
dev.type = type;
|
||||
dev.bdf = bdf;
|
||||
|
||||
pci_enable_bus_master(&dev);
|
||||
pciinfo("Enabled bus mastering\n");
|
||||
|
@ -434,16 +468,3 @@ int qemu_edu_probe(FAR struct pci_bus_s *bus,
|
|||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public Data
|
||||
*****************************************************************************/
|
||||
|
||||
struct pci_dev_type_s pci_type_qemu_edu =
|
||||
{
|
||||
.vendor = 0x1234,
|
||||
.device = 0x11e8,
|
||||
.class_rev = PCI_ID_ANY,
|
||||
.name = "Qemu PCI EDU device",
|
||||
.probe = qemu_edu_probe
|
||||
};
|
||||
|
|
|
@ -49,19 +49,36 @@ static uint32_t mem_read(FAR const volatile void *addr, int width);
|
|||
|
||||
static void mem_write(FAR const volatile void *addr, uint32_t val, int width);
|
||||
|
||||
static int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
|
||||
FAR const struct pci_dev_type_s *type,
|
||||
uint16_t bdf);
|
||||
|
||||
/*****************************************************************************
|
||||
* Public Data
|
||||
*****************************************************************************/
|
||||
|
||||
const struct pci_dev_type_s g_pci_type_qemu_pci_test =
|
||||
{
|
||||
.vendor = 0x1b36,
|
||||
.device = 0x0005,
|
||||
.class_rev = PCI_ID_ANY,
|
||||
.name = "Qemu PCI test device",
|
||||
.probe = qemu_pci_test_probe
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Private Types
|
||||
*****************************************************************************/
|
||||
|
||||
struct pci_test_dev_hdr_s
|
||||
{
|
||||
uint8_t test; /* write-only, starts a given test number */
|
||||
uint8_t width; /* read-only, type and width of access for a test */
|
||||
uint8_t pad0[2];
|
||||
uint8_t test; /* write-only, starts a given test number */
|
||||
uint8_t width; /* read-only, type and width of access for a test */
|
||||
uint8_t pad0[2];
|
||||
uint32_t offset; /* read-only, offset in this BAR for a given test */
|
||||
uint32_t data; /* read-only, data to use for a given test */
|
||||
uint32_t count; /* for debugging. number of writes detected. */
|
||||
uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
|
||||
uint8_t name[]; /* for debugging. 0-terminated ASCII string. */
|
||||
};
|
||||
|
||||
/* Structure the read and write helpers */
|
||||
|
@ -76,7 +93,7 @@ struct pci_test_dev_ops_s
|
|||
* Private Data
|
||||
*****************************************************************************/
|
||||
|
||||
static struct pci_test_dev_ops_s mem_ops =
|
||||
static struct pci_test_dev_ops_s g_mem_ops =
|
||||
{
|
||||
.read = mem_read,
|
||||
.write = mem_write
|
||||
|
@ -100,14 +117,14 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
|
|||
FAR struct pci_test_dev_hdr_s *test_hdr,
|
||||
uint16_t test_num)
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t data;
|
||||
uint32_t offset;
|
||||
uint8_t width;
|
||||
const int write_limit = 8;
|
||||
int write_cnt;
|
||||
int i;
|
||||
char testname[32];
|
||||
uint32_t count;
|
||||
uint32_t data;
|
||||
uint32_t offset;
|
||||
uint8_t width;
|
||||
int write_cnt;
|
||||
int i;
|
||||
char testname[32];
|
||||
|
||||
pciinfo("WRITING Test# %d %p\n", test_num, &test_hdr->test);
|
||||
test_ops->write(&test_hdr->test, test_num, 1);
|
||||
|
@ -122,7 +139,9 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
|
|||
{
|
||||
testname[i] = (char)test_ops->read((void *)&test_hdr->name + i, 1);
|
||||
if (testname[i] == 0)
|
||||
break;
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pciinfo("Running test: %s\n", testname);
|
||||
|
@ -130,13 +149,17 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
|
|||
count = test_ops->read(&test_hdr->count, 4);
|
||||
pciinfo("COUNT: %04x\n", count);
|
||||
if (count != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
width = test_ops->read(&test_hdr->width, 1);
|
||||
pciinfo("Width: %d\n", width);
|
||||
|
||||
if (width == 0 || width > 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
data = test_ops->read(&test_hdr->data, 4);
|
||||
pciinfo("Data: %04x\n", data);
|
||||
|
@ -156,45 +179,44 @@ static bool qemu_pci_test_bar(FAR struct pci_test_dev_ops_s *test_ops,
|
|||
pciinfo("COUNT: %04x\n", count);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return (int)count == write_cnt;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public Functions
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: qemu_pci_test_probe
|
||||
*
|
||||
* Description:
|
||||
* Initialize device
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
|
||||
FAR struct pci_dev_type_s *type, uint16_t bdf)
|
||||
static int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
|
||||
FAR const struct pci_dev_type_s *type,
|
||||
uint16_t bdf)
|
||||
{
|
||||
uint8_t bar_id;
|
||||
uint32_t bar;
|
||||
uint64_t bar_addr;
|
||||
struct pci_test_dev_hdr_s *test_hdr;
|
||||
struct pci_dev_s dev =
|
||||
{
|
||||
.bus = bus,
|
||||
.type = type,
|
||||
.bdf = bdf,
|
||||
};
|
||||
|
||||
struct pci_test_dev_ops_s io_ops =
|
||||
{
|
||||
.read = bus->ops->pci_io_read,
|
||||
.write = bus->ops->pci_io_write
|
||||
};
|
||||
|
||||
struct pci_dev_s dev;
|
||||
struct pci_test_dev_ops_s io_ops;
|
||||
struct pci_test_dev_ops_s *test_ops;
|
||||
struct pci_test_dev_hdr_s *test_hdr;
|
||||
uint8_t bar_id;
|
||||
uint32_t bar;
|
||||
uint64_t bar_addr;
|
||||
uint16_t test_cnt;
|
||||
|
||||
uint16_t test_cnt;
|
||||
/* Get dev */
|
||||
|
||||
dev.bus = bus;
|
||||
dev.type = type;
|
||||
dev.bdf = bdf;
|
||||
|
||||
/* Get io ops */
|
||||
|
||||
io_ops.read = bus->ops->pci_io_read;
|
||||
io_ops.write = bus->ops->pci_io_write;
|
||||
|
||||
pci_enable_bus_master(&dev);
|
||||
pciinfo("Enabled bus mastering\n");
|
||||
|
@ -209,7 +231,9 @@ int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
|
|||
*/
|
||||
|
||||
if (pci_bar_valid(&dev, bar_id) != OK)
|
||||
continue;
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bar = bus->ops->pci_cfg_read(&dev,
|
||||
PCI_HEADER_NORM_BAR0 + (bar_id * 4), 4);
|
||||
|
@ -219,7 +243,7 @@ int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
|
|||
|
||||
if ((bar & PCI_BAR_LAYOUT_MASK) == PCI_BAR_LAYOUT_MEM)
|
||||
{
|
||||
test_ops = &mem_ops;
|
||||
test_ops = &g_mem_ops;
|
||||
|
||||
/* If the BAR is MMIO the it must be mapped */
|
||||
|
||||
|
@ -233,26 +257,18 @@ int qemu_pci_test_probe(FAR struct pci_bus_s *bus,
|
|||
for (test_cnt = 0; test_cnt < 0xffff; test_cnt++)
|
||||
{
|
||||
if (!qemu_pci_test_bar(test_ops, test_hdr, test_cnt))
|
||||
break;
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pciinfo("Test Completed BAR [%d] TEST [%d]\n", bar_id, test_cnt);
|
||||
}
|
||||
|
||||
if (pci_bar_is_64(&dev, bar_id))
|
||||
bar_id++;
|
||||
{
|
||||
bar_id++;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Public Data
|
||||
*****************************************************************************/
|
||||
|
||||
struct pci_dev_type_s pci_type_qemu_pci_test =
|
||||
{
|
||||
.vendor = 0x1b36,
|
||||
.device = 0x0005,
|
||||
.class_rev = PCI_ID_ANY,
|
||||
.name = "Qemu PCI test device",
|
||||
.probe = qemu_pci_test_probe
|
||||
};
|
||||
|
|
|
@ -40,17 +40,17 @@
|
|||
|
||||
/* PCI config common registers */
|
||||
|
||||
#define PCI_CONFIG_VENDOR 0x00
|
||||
#define PCI_CONFIG_DEVICE 0x02
|
||||
#define PCI_CONFIG_COMMAND 0x04
|
||||
#define PCI_CONFIG_REV_ID 0x08
|
||||
#define PCI_CONFIG_VENDOR 0x00
|
||||
#define PCI_CONFIG_DEVICE 0x02
|
||||
#define PCI_CONFIG_COMMAND 0x04
|
||||
#define PCI_CONFIG_REV_ID 0x08
|
||||
#define PCI_CONFIG_PROG_IF 0x09
|
||||
#define PCI_CONFIG_SUBCLASS 0x0A
|
||||
#define PCI_CONFIG_CLASS 0x0B
|
||||
#define PCI_CONFIG_CACHE_LINE_SIZE 0x0C
|
||||
#define PCI_CONFIG_LATENCY_TIMER 0x0D
|
||||
#define PCI_CONFIG_HEADER_TYPE 0x0E
|
||||
#define PCI_CONFIG_BIST 0x0F
|
||||
#define PCI_CONFIG_SUBCLASS 0x0A
|
||||
#define PCI_CONFIG_CLASS 0x0B
|
||||
#define PCI_CONFIG_CACHE_LINE_SIZE 0x0C
|
||||
#define PCI_CONFIG_LATENCY_TIMER 0x0D
|
||||
#define PCI_CONFIG_HEADER_TYPE 0x0E
|
||||
#define PCI_CONFIG_BIST 0x0F
|
||||
|
||||
/* PCI config header types */
|
||||
|
||||
|
@ -109,7 +109,7 @@
|
|||
|
||||
/* Reserved 0x14-0x3F */
|
||||
|
||||
#define PCI_CLASS_BASE_CO_PROC 0x40
|
||||
#define PCI_CLASS_BASE_CO_PROC 0x40
|
||||
|
||||
/* Reserved 0x41-0xFE */
|
||||
|
||||
|
@ -216,18 +216,32 @@ struct pci_dev_s;
|
|||
|
||||
struct pci_bus_ops_s
|
||||
{
|
||||
CODE void (*pci_cfg_write)(FAR struct pci_dev_s *dev, int reg,
|
||||
uint32_t val, int width);
|
||||
/* Write 8, 16, 32, 64 bits data to PCI-E configuration space of device
|
||||
* specified by dev.
|
||||
*/
|
||||
|
||||
CODE uint32_t (*pci_cfg_read)(FAR struct pci_dev_s *dev, int reg,
|
||||
int width);
|
||||
CODE void (*pci_cfg_write)(FAR struct pci_dev_s *dev, int reg,
|
||||
uint32_t val, int width);
|
||||
|
||||
CODE int (*pci_map_bar)(uint64_t addr, uint64_t len);
|
||||
/* Read 8, 16, 32, 64 bits data to PCI-E configuration space of device
|
||||
* specified by dev.
|
||||
*/
|
||||
|
||||
CODE uint32_t (*pci_io_read)(FAR const volatile void *addr, int width);
|
||||
CODE uint32_t (*pci_cfg_read)(FAR struct pci_dev_s *dev, int reg,
|
||||
int width);
|
||||
|
||||
CODE void (*pci_io_write)(FAR const volatile void *addr, uint32_t val,
|
||||
int width);
|
||||
/* Map address in a 32 bits bar in the memory address space */
|
||||
|
||||
CODE int (*pci_map_bar)(uint64_t addr, uint64_t len);
|
||||
|
||||
/* Read from IO port */
|
||||
|
||||
CODE uint32_t (*pci_io_read)(FAR const volatile void *addr, int width);
|
||||
|
||||
/* Write to IO port */
|
||||
|
||||
CODE void (*pci_io_write)(FAR const volatile void *addr, uint32_t val,
|
||||
int width);
|
||||
};
|
||||
|
||||
/* PCI bus private data. */
|
||||
|
@ -249,16 +263,16 @@ struct pci_dev_type_s
|
|||
/* Call back function when a device is probed */
|
||||
|
||||
CODE int (*probe)(FAR struct pci_bus_s *bus,
|
||||
FAR struct pci_dev_type_s *type, uint16_t bdf);
|
||||
FAR const struct pci_dev_type_s *type, uint16_t bdf);
|
||||
};
|
||||
|
||||
/* PCI device private data. */
|
||||
|
||||
struct pci_dev_s
|
||||
{
|
||||
FAR struct pci_bus_s *bus;
|
||||
FAR struct pci_dev_type_s *type;
|
||||
uint32_t bdf;
|
||||
FAR struct pci_bus_s *bus;
|
||||
FAR const struct pci_dev_type_s *type;
|
||||
uint32_t bdf;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* include/nuttx/serial/uart_mcs99xx.h
|
||||
* include/nuttx/virt/qemu_pci.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -18,8 +18,8 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H
|
||||
#define __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H
|
||||
#ifndef __INCLUDE_NUTTX_VIRT_QEMU_PCI_H
|
||||
#define __INCLUDE_NUTTX_VIRT_QEMU_PCI_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
|
@ -42,16 +42,16 @@ extern "C"
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_VIRT_QEMU_PCI_TEST
|
||||
extern struct pci_dev_type_s pci_type_qemu_pci_test;
|
||||
#endif /* CONFIG_VIRT_QEMU_PCI_TEST */
|
||||
extern const struct pci_dev_type_s g_pci_type_qemu_pci_test;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VIRT_QEMU_EDU
|
||||
extern struct pci_dev_type_s pci_type_qemu_edu;
|
||||
#endif /* CONFIG_VIRT_QEMU_EDU */
|
||||
extern const struct pci_dev_type_s g_pci_type_qemu_edu;
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_VIRT_QEMU_PCI_TEST_H */
|
||||
#endif /* __INCLUDE_NUTTX_VIRT_QEMU_PCI_H */
|
||||
|
|
Loading…
Reference in a new issue