Support nuttx pci endpoint driver framework
Signed-off-by: yangshuyong <yangshuyong@xiaomi.com> Signed-off-by: lipengfei28 <lipengfei28@xiaomi.com>
This commit is contained in:
parent
56308bf202
commit
a537ecdd0f
@ -41,3 +41,11 @@ if(CONFIG_PCI)
|
||||
target_sources(drivers PRIVATE ${SRCS})
|
||||
|
||||
endif() # CONFIG_PCI
|
||||
|
||||
if(CONFIG_PCI_ENDPOINT)
|
||||
|
||||
set(SRCS pci_epc.c pci_epc_mem.c pci_epf.c)
|
||||
|
||||
target_sources(drivers PRIVATE ${SRCS})
|
||||
|
||||
endif() # CONFIG_PCI_ENDPOINT
|
||||
|
@ -74,3 +74,12 @@ config PCI_UIO_IVSHMEM_NPOLLWAITERS
|
||||
depends on PCI_UIO_IVSHMEM
|
||||
|
||||
endif # PCI
|
||||
|
||||
menuconfig PCI_ENDPOINT
|
||||
bool "PCI Endpoint Support"
|
||||
default n
|
||||
---help---
|
||||
Enable this configuration option to support configurable PCI
|
||||
endpoint. This should be enabled if the platform has a PCI
|
||||
controller that can operate in endpoint mode.
|
||||
|
||||
|
@ -37,6 +37,10 @@ ifeq ($(CONFIG_PCI_UIO_IVSHMEM),y)
|
||||
CSRCS += pci_uio_ivshmem.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PCI_ENDPOINT),y)
|
||||
CSRCS += pci_epc.c pci_epc_mem.c pci_epf.c
|
||||
endif
|
||||
|
||||
# Include PCI device driver build support
|
||||
|
||||
DEPPATH += --dep-path pci
|
||||
|
1011
drivers/pci/pci_epc.c
Normal file
1011
drivers/pci/pci_epc.c
Normal file
File diff suppressed because it is too large
Load Diff
289
drivers/pci/pci_epc_mem.c
Normal file
289
drivers/pci/pci_epc_mem.c
Normal file
@ -0,0 +1,289 @@
|
||||
/****************************************************************************
|
||||
* drivers/pci/pci_epc_mem.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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <strings.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <nuttx/bits.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/lib/math32.h>
|
||||
#include <nuttx/pci/pci_epc.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_find
|
||||
*
|
||||
* Description:
|
||||
* Get the matching memory window
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device
|
||||
* phys_addr - Physical address alloced to be matched
|
||||
*
|
||||
* Returned Value:
|
||||
* Memory window alloced if success, NULL if failed
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct pci_epc_mem_s *
|
||||
pci_epc_mem_find(FAR struct pci_epc_ctrl_s *epc,
|
||||
uintptr_t phys_addr)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < epc->num_windows; i++)
|
||||
{
|
||||
if (phys_addr >= epc->mem[i].phys_base &&
|
||||
phys_addr < epc->mem[i].phys_base + epc->mem[i].size)
|
||||
{
|
||||
return &epc->mem[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_multi_init
|
||||
*
|
||||
* Description:
|
||||
* This function is used to initialize the pci_epc_mem_s structure.
|
||||
*
|
||||
* Invoke to initialize the pci_epc_mem_s structure used by the
|
||||
* endpoint functions to allocate mapped PCI address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device that invoked pci_epc_mem_init
|
||||
* windows - Pointer to windows supported by the device
|
||||
* num_windows - Number of windows device supports
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_mem_multi_init(FAR struct pci_epc_ctrl_s *epc,
|
||||
FAR const struct pci_epc_mem_window_s *windows,
|
||||
unsigned int num_windows)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (epc == NULL || windows == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
epc->mem = kmm_calloc(num_windows, sizeof(*epc->mem));
|
||||
if (epc->mem == NULL)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_windows; i++)
|
||||
{
|
||||
size_t pages = windows[i].size / windows[i].page_size;
|
||||
size_t bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
|
||||
|
||||
FAR unsigned long *bitmap = kmm_zalloc(bitmap_size);
|
||||
if (bitmap == NULL)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
epc->mem[i].phys_base = windows[i].phys_base;
|
||||
epc->mem[i].size = windows[i].size;
|
||||
epc->mem[i].page_size = windows[i].page_size;
|
||||
epc->mem[i].bitmap = bitmap;
|
||||
epc->mem[i].pages = pages;
|
||||
nxmutex_init(&epc->mem[i].lock);
|
||||
}
|
||||
|
||||
epc->num_windows = num_windows;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (i-- > 0)
|
||||
{
|
||||
nxmutex_destroy(&epc->mem[i].lock);
|
||||
kmm_free(epc->mem[i].bitmap);
|
||||
}
|
||||
|
||||
kmm_free(epc->mem);
|
||||
epc->mem = NULL;
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_init
|
||||
*
|
||||
* Description:
|
||||
* This function is used to initialize the PCI endpoint controller memory
|
||||
* space.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - PCI EPC device
|
||||
* base - The physical base address of the PCI address window
|
||||
* size - The PCI window size
|
||||
* page_size - Size of each window page
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_mem_init(FAR struct pci_epc_ctrl_s *epc, uintptr_t base,
|
||||
size_t size, size_t page_size)
|
||||
{
|
||||
struct pci_epc_mem_window_s window;
|
||||
|
||||
window.phys_base = base;
|
||||
window.size = size;
|
||||
window.page_size = page_size;
|
||||
|
||||
return pci_epc_mem_multi_init(epc, &window, 1);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_exit
|
||||
*
|
||||
* Description:
|
||||
* This function is used to cleanup the pci_epc_mem_s structure.
|
||||
*
|
||||
* Invoke to cleanup the pci_epc_mem_s structure allocated in
|
||||
* pci_epc_mem_init().
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - EPC device that invoked pci_epc_mem_exit
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_mem_exit(FAR struct pci_epc_ctrl_s *epc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (epc->num_windows == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < epc->num_windows; i++)
|
||||
{
|
||||
nxmutex_destroy(&epc->mem[i].lock);
|
||||
kmm_free(epc->mem[i].bitmap);
|
||||
}
|
||||
|
||||
kmm_free(epc->mem);
|
||||
epc->mem = NULL;
|
||||
epc->num_windows = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_alloc_addr
|
||||
*
|
||||
* Description:
|
||||
* Allocate memory address from EPC addr space
|
||||
*
|
||||
* Invoke to allocate memory address from the EPC address space. This
|
||||
* is usually done to map the remote RC address into the local system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which memory has to be allocated
|
||||
* size - The size of the address space that has to be allocated
|
||||
*
|
||||
* Returned Value:
|
||||
* The memory address alloced if success, 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t pci_epc_mem_alloc_addr(FAR struct pci_epc_ctrl_s *epc, size_t size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < epc->num_windows; i++)
|
||||
{
|
||||
FAR struct pci_epc_mem_s *mem = &epc->mem[i];
|
||||
size_t pages = div_round_up(size, mem->page_size);
|
||||
size_t pageno;
|
||||
|
||||
nxmutex_lock(&mem->lock);
|
||||
pageno = bitmap_find_free_region(mem->bitmap, mem->pages, pages);
|
||||
nxmutex_unlock(&mem->lock);
|
||||
|
||||
if (pageno != mem->pages)
|
||||
{
|
||||
return mem->phys_base + pageno * mem->page_size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_free_addr
|
||||
*
|
||||
* Description:
|
||||
* Free the allocated memory address.
|
||||
*
|
||||
* Invoke to free the memory allocated using pci_epc_mem_alloc_addr.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which memory was allocated
|
||||
* phys_addr - The allocated physical address
|
||||
* size - The size of the allocated address space
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_mem_free_addr(FAR struct pci_epc_ctrl_s *epc,
|
||||
uintptr_t phys_addr, size_t size)
|
||||
{
|
||||
FAR struct pci_epc_mem_s *mem;
|
||||
uintptr_t pageno;
|
||||
size_t pages;
|
||||
|
||||
mem = pci_epc_mem_find(epc, phys_addr);
|
||||
if (mem == NULL)
|
||||
{
|
||||
pcierr("Failed to get matching window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pageno = (phys_addr - mem->phys_base) / mem->page_size;
|
||||
pages = div_round_up(size, mem->page_size);
|
||||
|
||||
nxmutex_lock(&mem->lock);
|
||||
bitmap_release_region(mem->bitmap, pageno, pages);
|
||||
nxmutex_unlock(&mem->lock);
|
||||
}
|
||||
|
522
drivers/pci/pci_epf.c
Normal file
522
drivers/pci/pci_epf.c
Normal file
@ -0,0 +1,522 @@
|
||||
/****************************************************************************
|
||||
* drivers/pci/pci_epf.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 <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/lib/math32.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/pci/pci_epc.h>
|
||||
#include <nuttx/pci/pci_epf.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef ALIGN_UP
|
||||
# define ALIGN_UP(s, a) (((s) + (a) - 1) & ~((a) - 1))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct list_node g_pci_epf_device_list =
|
||||
LIST_INITIAL_VALUE(g_pci_epf_device_list);
|
||||
static struct list_node g_pci_epf_driver_list =
|
||||
LIST_INITIAL_VALUE(g_pci_epf_driver_list);
|
||||
static mutex_t g_pci_epf_lock = NXMUTEX_INITIALIZER;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_match_id
|
||||
****************************************************************************/
|
||||
|
||||
static FAR const struct pci_epf_device_id_s *
|
||||
pci_epf_match_id(FAR const struct pci_epf_device_s *dev,
|
||||
FAR const struct pci_epf_device_id_s *id)
|
||||
{
|
||||
while (id->name[0])
|
||||
{
|
||||
if (strcmp(dev->name, id->name) == 0)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
id++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_match_device
|
||||
****************************************************************************/
|
||||
|
||||
static FAR const struct pci_epf_device_id_s *
|
||||
pci_epf_match_device(FAR struct pci_epf_device_s *dev,
|
||||
FAR struct pci_epf_driver_s *drv)
|
||||
{
|
||||
if (drv->id_table)
|
||||
{
|
||||
return pci_epf_match_id(dev, drv->id_table);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_unbind
|
||||
*
|
||||
* Description:
|
||||
* Notify the function driver that the binding between the EPF device and
|
||||
* EPC device has been lost.
|
||||
*
|
||||
* Invoke to notify the function driver that the binding between the EPF
|
||||
* device and EPC device has been lost.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The EPF device which has lost the binding with the EPC device
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
static void pci_epf_unbind(FAR struct pci_epf_device_s *epf)
|
||||
{
|
||||
if (epf->driver == NULL || epf->driver->ops->unbind == NULL)
|
||||
{
|
||||
pcierr("Invalid epf parameter, unbind failed!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
nxmutex_lock(&epf->lock);
|
||||
if (epf->is_bound)
|
||||
{
|
||||
epf->driver->ops->unbind(epf);
|
||||
epf->is_bound = false;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&epf->lock);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_bind
|
||||
*
|
||||
* Description:
|
||||
* Notify the function driver that the EPF device has been bound to a EPC
|
||||
* device.
|
||||
*
|
||||
* Invoke to notify the function driver that it has been bound to a EPC
|
||||
* device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The EPF device which has been bound to the EPC device
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
static int pci_epf_bind(FAR struct pci_epf_device_s *epf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (epf->driver == NULL || epf->driver->ops->bind == NULL)
|
||||
{
|
||||
pcierr("Invalid epf parameter, bind failed!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nxmutex_lock(&epf->lock);
|
||||
ret = epf->driver->ops->bind(epf);
|
||||
if (ret >= 0)
|
||||
{
|
||||
epf->is_bound = true;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&epf->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_free_space
|
||||
*
|
||||
* Description:
|
||||
* Free the allocated PCI EPF register space
|
||||
*
|
||||
* Invoke to free the allocated PCI EPF register space.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The EPF device from whom to free the memory
|
||||
* barno - The BAR number corresponding to the register space
|
||||
* addr - The virtual address of the PCI EPF register space
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epf_free_space(FAR struct pci_epf_device_s *epf,
|
||||
int barno, FAR void *addr)
|
||||
{
|
||||
FAR struct pci_epf_bar_s *bar;
|
||||
|
||||
if (addr == NULL || barno >= PCI_STD_NUM_BARS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bar = epf->bar;
|
||||
|
||||
kmm_free(addr);
|
||||
|
||||
bar[barno].phys_addr = 0;
|
||||
bar[barno].addr = NULL;
|
||||
bar[barno].size = 0;
|
||||
bar[barno].barno = 0;
|
||||
bar[barno].flags = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_alloc_space
|
||||
*
|
||||
* Description:
|
||||
* This function is used to allocate memory for the PCI EPF register
|
||||
* space.
|
||||
*
|
||||
* Invoke to allocate memory for the PCI EPF register space.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The EPF device to whom allocate the memory
|
||||
* barno - The BAR number corresponding to the allocated register space
|
||||
* size - The size of the memory that has to be allocated
|
||||
* align - Alignment size for the allocation region
|
||||
*
|
||||
* Returned Value:
|
||||
* Return space address malloced if success, otherwise NULL
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *pci_epf_alloc_space(FAR struct pci_epf_device_s *epf, int barno,
|
||||
size_t size, size_t align)
|
||||
{
|
||||
FAR struct pci_epf_bar_s *bar;
|
||||
FAR void *space;
|
||||
uintptr_t phys_addr;
|
||||
|
||||
if (epf == NULL || barno >= PCI_STD_NUM_BARS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size < 128)
|
||||
{
|
||||
size = 128;
|
||||
}
|
||||
|
||||
if (align)
|
||||
{
|
||||
size = ALIGN_UP(size, align);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = roundup_pow_of_two(size);
|
||||
}
|
||||
|
||||
bar = epf->bar;
|
||||
|
||||
space = kmm_zalloc(size);
|
||||
if (space == NULL)
|
||||
{
|
||||
pcierr("Failed to allocate mem space\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
phys_addr = up_addrenv_va_to_pa(space);
|
||||
|
||||
bar[barno].phys_addr = phys_addr;
|
||||
bar[barno].addr = space;
|
||||
bar[barno].size = size;
|
||||
bar[barno].barno = barno;
|
||||
bar[barno].flags |= (size > UINT32_MAX) ?
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_64 :
|
||||
PCI_BASE_ADDRESS_MEM_TYPE_32;
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_device_register
|
||||
*
|
||||
* Description:
|
||||
* This function is used to create a new PCI EPF device.
|
||||
*
|
||||
* Invoke to create a new PCI EPF device by providing the name of the
|
||||
* function device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The name of the PCI EPF device be used to bind the EPF device to
|
||||
* a EPF driver
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_device_register(FAR struct pci_epf_device_s *epf)
|
||||
{
|
||||
FAR struct pci_epf_driver_s *drv;
|
||||
FAR struct pci_epc_ctrl_s *epc;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(epf != NULL || epf->name != NULL);
|
||||
|
||||
ret = nxmutex_lock(&g_pci_epf_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_add_tail(&g_pci_epf_device_list, &epf->node);
|
||||
|
||||
list_for_every_entry(&g_pci_epf_driver_list, drv,
|
||||
struct pci_epf_driver_s, node)
|
||||
{
|
||||
epf->id = pci_epf_match_device(epf, drv);
|
||||
if (epf->id == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the specify EPC by epc_name in epf structure */
|
||||
|
||||
epc = pci_get_epc(epf->epc_name);
|
||||
if (epc == NULL)
|
||||
{
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = drv->probe(epf);
|
||||
if (ret < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
epf->driver = drv;
|
||||
|
||||
/* Added the epc to epf */
|
||||
|
||||
pci_epc_add_epf(epc, epf);
|
||||
|
||||
/* Notify the function driver */
|
||||
|
||||
pci_epf_bind(epf);
|
||||
break;
|
||||
}
|
||||
|
||||
nxmutex_unlock(&g_pci_epf_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_device_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function is used to unregister a PCI EPF device.
|
||||
*
|
||||
* Invoke to unregister the PCI EPF device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The PCI EPF driver that has to be unregistered device
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_device_unregister(FAR struct pci_epf_device_s *epf)
|
||||
{
|
||||
FAR struct pci_epc_ctrl_s *epc;
|
||||
int ret;
|
||||
|
||||
ret = nxmutex_lock(&g_pci_epf_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
pci_epf_unbind(epf);
|
||||
epc = pci_get_epc(epf->epc_name);
|
||||
if (epc)
|
||||
{
|
||||
pci_epc_remove_epf(epc, epf);
|
||||
}
|
||||
|
||||
if (epf->driver && epf->driver->remove)
|
||||
{
|
||||
epf->driver->remove(epf);
|
||||
}
|
||||
|
||||
epf->driver = NULL;
|
||||
list_delete(&epf->node);
|
||||
|
||||
nxmutex_unlock(&g_pci_epf_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_register_driver
|
||||
*
|
||||
* Description:
|
||||
* This function is used to register a new PCI EPF driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* drv - EPF driver
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_register_driver(FAR struct pci_epf_driver_s *drv)
|
||||
{
|
||||
FAR struct pci_epf_device_s *epf;
|
||||
FAR struct pci_epc_ctrl_s *epc;
|
||||
int ret;
|
||||
|
||||
if (drv == NULL || drv->ops == NULL ||
|
||||
drv->ops->bind == NULL || drv->id_table == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = nxmutex_lock(&g_pci_epf_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add the driver to the pci epf driver list */
|
||||
|
||||
list_add_tail(&g_pci_epf_driver_list, &drv->node);
|
||||
|
||||
list_for_every_entry(&g_pci_epf_device_list, epf, struct pci_epf_device_s,
|
||||
node)
|
||||
{
|
||||
if (epf->driver != NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 1. Match epf device and epf driver.
|
||||
* 2. Get the epc by name.
|
||||
* 3. Add epc into epf.
|
||||
* 4. Notify the epf driver be bond.
|
||||
*/
|
||||
|
||||
epf->id = pci_epf_match_device(epf, drv);
|
||||
if (epf->id == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
epc = pci_get_epc(epf->name);
|
||||
if (epc == NULL)
|
||||
{
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = drv->probe(epf);
|
||||
if (ret < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
epf->driver = drv;
|
||||
|
||||
/* Added the epc to epf */
|
||||
|
||||
pci_epc_add_epf(epc, epf);
|
||||
|
||||
/* Notify the function driver */
|
||||
|
||||
pci_epf_bind(epf);
|
||||
}
|
||||
|
||||
nxmutex_unlock(&g_pci_epf_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_unregister_driver
|
||||
*
|
||||
* Description:
|
||||
* This function is used to unregister the PCI EPF driver.
|
||||
*
|
||||
* Invoke to unregister the PCI EPF driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* drv - The PCI EPF driver that has to be unregistered
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_unregister_driver(FAR struct pci_epf_driver_s *drv)
|
||||
{
|
||||
FAR struct pci_epf_device_s *epf;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(drv != NULL || drv->remove != NULL);
|
||||
|
||||
ret = nxmutex_lock(&g_pci_epf_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_for_every_entry(&g_pci_epf_device_list, epf, struct pci_epf_device_s,
|
||||
node)
|
||||
{
|
||||
if (epf->driver == drv)
|
||||
{
|
||||
pci_epf_unbind(epf);
|
||||
drv->remove(epf);
|
||||
epf->driver = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
list_delete(&drv->node);
|
||||
|
||||
nxmutex_unlock(&g_pci_epf_lock);
|
||||
return ret;
|
||||
}
|
813
include/nuttx/pci/pci_epc.h
Normal file
813
include/nuttx/pci/pci_epc.h
Normal file
@ -0,0 +1,813 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/pci/pci_epc.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_EPC_H
|
||||
#define __INCLUDE_NUTTX_PCI_PCI_EPC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/list.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/pci/pci_epf.h>
|
||||
#include <nuttx/pci/pci_regs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
enum pci_epc_irq_type_e
|
||||
{
|
||||
PCI_EPC_IRQ_UNKNOWN,
|
||||
PCI_EPC_IRQ_LEGACY,
|
||||
PCI_EPC_IRQ_MSI,
|
||||
PCI_EPC_IRQ_MSIX,
|
||||
};
|
||||
|
||||
/* struct pci_epc_features_s - Features supported by a EPC device per
|
||||
* function
|
||||
*
|
||||
* linkup_notifier: Indicate if the EPC device can notify EPF driver on link
|
||||
* up
|
||||
* core_init_notifier: Indicate cores that can notify about their
|
||||
* vailability for initialization
|
||||
* msi_capable: Indicate if the endpoint function has MSI capability
|
||||
* msix_capable: Indicate if the endpoint function has MSI-X capability
|
||||
* bar_reserved: Bitmap to indicate reserved BAR unavailable to function
|
||||
* driver
|
||||
* bar_fixed_64bit: Bitmap to indicate fixed 64bit BARs
|
||||
* bar_fixed_size: Array specifying the size supported by each BAR
|
||||
* align: Alignment size required for BAR buffer allocation
|
||||
*/
|
||||
|
||||
struct pci_epc_features_s
|
||||
{
|
||||
unsigned int linkup_notifier : 1;
|
||||
unsigned int core_init_notifier : 1;
|
||||
unsigned int msi_capable : 1;
|
||||
unsigned int msix_capable : 1;
|
||||
uint8_t bar_reserved;
|
||||
uint8_t bar_fixed_64bit;
|
||||
uint64_t bar_fixed_size[PCI_STD_NUM_BARS];
|
||||
size_t align;
|
||||
};
|
||||
|
||||
/* struct pci_epc_ops_s - Set of function pointers for performing EPC
|
||||
* operations
|
||||
*
|
||||
* write_header: Ops to populate configuration space header
|
||||
* set_bar: Ops to configure the BAR
|
||||
* clear_bar: Ops to reset the BAR
|
||||
* map_addr: Ops to map CPU address to PCI address
|
||||
* unmap_addr: Ops to unmap CPU address and PCI address
|
||||
* set_msi: Ops to set the requested number of MSI interrupts in the MSI
|
||||
* capability register
|
||||
* get_msi: Ops to get the number of MSI interrupts allocated by the RC from
|
||||
* the MSI capability register
|
||||
* set_msix: Ops to set the requested number of MSI-X interrupts in the
|
||||
* MSI-X capability register
|
||||
* get_msix: Ops to get the number of MSI-X interrupts allocated by the RC
|
||||
* from the MSI-X capability register
|
||||
* raise_irq: Ops to raise a legacy, MSI or MSI-X interrupt
|
||||
* map_msi_irq: Ops to map physical address to MSI address and return MSI
|
||||
* data
|
||||
* start: Ops to start the PCI link
|
||||
* stop: Ops to stop the PCI link
|
||||
* get_features: Ops to get the features supported by the EPC
|
||||
* dma_xfer: Ops to transfer data between mapped Host memory and device
|
||||
* memory with "System DMA"
|
||||
*/
|
||||
|
||||
struct pci_epc_ops_s
|
||||
{
|
||||
CODE int (*write_header)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
FAR struct pci_epf_header_s *hdr);
|
||||
CODE int (*set_bar)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
FAR struct pci_epf_bar_s *bar);
|
||||
CODE void (*clear_bar)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
FAR struct pci_epf_bar_s *bar);
|
||||
CODE int (*map_addr)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uintptr_t addr, uint64_t pci_addr, size_t size);
|
||||
CODE void (*unmap_addr)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uintptr_t addr);
|
||||
CODE int (*set_msi)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uint8_t interrupts);
|
||||
CODE int (*get_msi)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno);
|
||||
CODE int (*set_msix)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uint16_t interrupts, int barno, uint32_t offset);
|
||||
CODE int (*get_msix)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno);
|
||||
CODE int (*raise_irq)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
enum pci_epc_irq_type_e type,
|
||||
uint16_t interrupt_num);
|
||||
CODE int (*map_msi_irq)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uintptr_t phys_addr, uint8_t interrupt_num,
|
||||
uint32_t entry_size, FAR uint32_t *msi_data,
|
||||
FAR uint32_t *msi_addr_offset);
|
||||
CODE int (*start)(FAR struct pci_epc_ctrl_s *epc);
|
||||
CODE void (*stop)(FAR struct pci_epc_ctrl_s *epc);
|
||||
CODE FAR const struct pci_epc_features_s *
|
||||
(*get_features)(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno);
|
||||
CODE int (*dma_xfer)(FAR struct pci_epc_ctrl_s *epc, uintptr_t mapped_addr,
|
||||
uintptr_t local_addr, uint32_t size, bool fromdev);
|
||||
};
|
||||
|
||||
/* struct pci_epc_mem_window_s - Address window of the endpoint controller
|
||||
*
|
||||
* phys_base: Physical base address of the PCI address window
|
||||
* size: The size of the PCI address window
|
||||
* page_size: Size of each page
|
||||
*/
|
||||
|
||||
struct pci_epc_mem_window_s
|
||||
{
|
||||
uintptr_t phys_base;
|
||||
size_t size;
|
||||
size_t page_size;
|
||||
};
|
||||
|
||||
/* struct pci_epc_mem_s - Address space of the endpoint controller
|
||||
*
|
||||
* phys_base: Physical base address of the PCI address window
|
||||
* size: The size of the PCI address window
|
||||
* page_size: Size of each page
|
||||
* bitmap: Bitmap to manage the PCI address space
|
||||
* pages: Number of bits representing the address region
|
||||
* lock: Mutex to protect bitmap
|
||||
*/
|
||||
|
||||
struct pci_epc_mem_s
|
||||
{
|
||||
uintptr_t phys_base;
|
||||
size_t size;
|
||||
size_t page_size;
|
||||
|
||||
FAR unsigned long *bitmap;
|
||||
int pages;
|
||||
|
||||
/* Mutex to protect against concurrent access for memory allocation */
|
||||
|
||||
mutex_t lock;
|
||||
};
|
||||
|
||||
/* struct pci_epc_ctrl_s - Represents the PCI EPC device
|
||||
*
|
||||
* epf: List of endpoint functions present in this EPC device
|
||||
* ops: Function pointers for performing endpoint operations
|
||||
* mem: Array of address space of the endpoint controlle
|
||||
* num_windows: Number of mem supported by device
|
||||
* max_functions: Max number of functions that can be configured in this EPC
|
||||
* node: The node of epc list
|
||||
* lock: Mutex to protect pci_epc ops
|
||||
* funcno_map: Bitmap to manage physical function number
|
||||
* name: The current epc structure name that used to bind the epf
|
||||
*/
|
||||
|
||||
struct pci_epc_ctrl_s
|
||||
{
|
||||
struct list_node epf;
|
||||
FAR const struct pci_epc_ops_s *ops;
|
||||
FAR struct pci_epc_mem_s *mem;
|
||||
unsigned int num_windows;
|
||||
uint8_t max_functions;
|
||||
struct list_node node;
|
||||
|
||||
/* Mutex to protect against concurrent access of EP controller */
|
||||
|
||||
mutex_t lock;
|
||||
unsigned long funcno_map;
|
||||
char name[0];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_get_epc
|
||||
*
|
||||
* Description:
|
||||
* This function is used to get the PCI endpoint controller.
|
||||
*
|
||||
* Invoke to get struct pci_epc_ctrl_s * corresponding to the device name
|
||||
* of the endpoint controller.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc_name - Device name of the endpoint controller
|
||||
*
|
||||
* Returned Value:
|
||||
* Return epc created if success, NULL if failed
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct pci_epc_ctrl_s *pci_get_epc(FAR const char *epc_name);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_get_next_free_bar
|
||||
*
|
||||
* Description:
|
||||
* Helper to get unreserved BAR starting from bar.
|
||||
*
|
||||
* Invoke to get the next unreserved BAR starting from barno that can be
|
||||
* used for endpoint function. For any incorrect value in bar_reserved return
|
||||
* '0'.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc_features - pci_epc_features_s structure that holds the reserved bar
|
||||
* bitmap
|
||||
* barno - The starting BAR number from where unreserved BAR should
|
||||
* be searched
|
||||
*
|
||||
* Returned Value:
|
||||
* Return the member of if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_get_next_free_bar(
|
||||
FAR const struct pci_epc_features_s *epc_features, int barno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_get_first_free_bar
|
||||
*
|
||||
* Description:
|
||||
* Helper to get first unreserved BAR.
|
||||
*
|
||||
* Invoke to get the first unreserved BAR that can be used by the endpoint
|
||||
* function. For any incorrect value in bar_reserved return '0'.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc_features - pci_epc_features_s structure that holds the reserved bar
|
||||
* bitmap
|
||||
*
|
||||
* Returned Value:
|
||||
* Return the member if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
#define pci_epc_get_first_free_bar(f) pci_epc_get_next_free_bar(f, 0)
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_get_features
|
||||
*
|
||||
* Description:
|
||||
* This function is used to get the features supported by EPC.
|
||||
*
|
||||
* Invoke to get the features provided by the EPC which may be
|
||||
* specific to an endpoint function. Returns pci_epc_features_s on success
|
||||
* and NULL for any failures.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The features supported by *this* EPC device will be returned
|
||||
* funcno - The features supported by the EPC device specific to the
|
||||
* endpoint function with funcno will be returned
|
||||
*
|
||||
* Returned Value:
|
||||
* Epc features if success, NULL if failed
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct pci_epc_features_s *
|
||||
pci_epc_get_features(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_stop
|
||||
*
|
||||
* Description:
|
||||
* This function is used to stop the PCI link.
|
||||
*
|
||||
* Invoke to stop the PCI link.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The link of the EPC device that has to be stopped
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_stop(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_start
|
||||
*
|
||||
* Description:
|
||||
* This function is used to start the PCI link.
|
||||
*
|
||||
* Invoke to start the PCI link.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The link of *this* EPC device has to be started
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_start(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_raise_irq
|
||||
*
|
||||
* Description:
|
||||
* This function is used to interrupt the host system.
|
||||
*
|
||||
* Invoke to raise an legacy, MSI or MSI-X interrupt.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device which has to interrupt the host
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* type - Specify the type of interrupt; legacy, MSI or MSI-X
|
||||
* interrupt_num - The MSI or MSI-X interrupt number with range (1-N)
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_raise_irq(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
enum pci_epc_irq_type_e type, uint16_t interrupt_num);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_map_msi_irq
|
||||
*
|
||||
* Description:
|
||||
* Map physical address to MSI address and return MSI data.
|
||||
*
|
||||
* Invoke to map physical address to MSI address and return MSI data. The
|
||||
* physical address should be an address in the outbound region. This is
|
||||
* required to implement doorbell functionality of NTB wherein EPC on either
|
||||
* side of the interface (primary and secondary) can directly write to the
|
||||
* physical address (in outbound region) of the other interface to ring
|
||||
* doorbell.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device which has to interrupt the host
|
||||
* funcno - The physical endpoint function number in the EPC
|
||||
* device
|
||||
* phys_addr - The physical address of the outbound region
|
||||
* interrupt_num - The MSI or MSI-X interrupt number with range (1-N)
|
||||
* entry_size - Size of Outbound address region for each interrupt
|
||||
* msi_data - The data that should be written in order to raise MSI
|
||||
* interrupt with interrupt number as 'interrupt num'
|
||||
* msi_addr_offset - Offset of MSI address from the aligned outbound
|
||||
* address to which the MSI address is mapped
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_map_msi_irq(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uintptr_t phys_addr, uint8_t interrupt_num,
|
||||
uint32_t entry_size, FAR uint32_t *msi_data,
|
||||
FAR uint32_t *msi_addr_offset);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_get_msi
|
||||
*
|
||||
* Description:
|
||||
* Get the number of MSI interrupt numbers allocated.
|
||||
*
|
||||
* Invoke to get the number of MSI interrupts allocated by the RC.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device to which MSI interrupts was requested
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
*
|
||||
* Returned Value:
|
||||
* Return interrupt number if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_get_msi(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_set_msi
|
||||
*
|
||||
* Description:
|
||||
* Set the number of MSI interrupt numbers required.
|
||||
*
|
||||
* Invoke to set the required number of MSI interrupts.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which MSI has to be configured
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* interrupts - Number of MSI interrupts required by the EPF
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_set_msi(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uint8_t interrupts);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_get_msix
|
||||
*
|
||||
* Description:
|
||||
* Get the number of MSI-X interrupt numbers allocated.
|
||||
*
|
||||
* Invoke to get the number of MSI-X interrupts allocated by the RC.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device to which MSI-X interrupts was requested
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_get_msix(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_set_msix
|
||||
*
|
||||
* Description:
|
||||
* Set the number of MSI-X interrupt numbers required.
|
||||
*
|
||||
* Invoke to set the required number of MSI-X interrupts.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which MSI-X has to be configured
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* interrupts - Number of MSI-X interrupts required by the EPF
|
||||
* barno - BAR where the MSI-X table resides
|
||||
* offset - Offset pointing to the start of MSI-X table
|
||||
*
|
||||
* Returned Value:
|
||||
* Return interrupt + 1 number if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_set_msix(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uint16_t interrupts, int barno, uint32_t offset);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_unmap_addr
|
||||
*
|
||||
* Description:
|
||||
* Unmap CPU address from PCI address.
|
||||
*
|
||||
* Invoke to unmap the CPU address from PCI address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which address is allocated
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* phys_addr - Physical address of the local systeme
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_unmap_addr(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uintptr_t phys_addr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_map_addr
|
||||
*
|
||||
* Description:
|
||||
* Map CPU address to PCI address.
|
||||
*
|
||||
* Invoke to map CPU address with PCI address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which address is allocated
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* phys_addr - Physical address of the local system
|
||||
* pci_addr - PCI address to which the physical address should be mapped
|
||||
* size - The size of the allocation
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_map_addr(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
uintptr_t phys_addr, uint64_t pci_addr, size_t size);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_clear_bar
|
||||
*
|
||||
* Description:
|
||||
* Reset the BAR.
|
||||
*
|
||||
* Invoke to reset the BAR of the endpoint device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device for which the BAR has to be cleared
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* bar - The struct bar that contains the BAR information
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_clear_bar(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
FAR struct pci_epf_bar_s *bar);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_set_bar
|
||||
*
|
||||
* Description:
|
||||
* Configure BAR in order for host to assign PCI addr space.
|
||||
*
|
||||
* Invoke to configure the BAR of the endpoint device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which BAR has to be configured
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* bar - The struct pci_epf_bar_s that contains the BAR information
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_set_bar(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
FAR struct pci_epf_bar_s *bar);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_write_header
|
||||
*
|
||||
* Description:
|
||||
* Write standard configuration header.
|
||||
*
|
||||
* Invoke to write the configuration header to the endpoint controller.
|
||||
* Every endpoint controller will have a dedicated location to which the
|
||||
* standard configuration header would be written. The callback function
|
||||
* should write the header fields to this dedicated location.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device to which the configuration header should be
|
||||
* written
|
||||
* funcno - The physical endpoint function number in the EPC device
|
||||
* header - Standard configuration header fields
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_write_header(FAR struct pci_epc_ctrl_s *epc, uint8_t funcno,
|
||||
FAR struct pci_epf_header_s *header);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_add_epf
|
||||
*
|
||||
* Description:
|
||||
* This function is used to bind PCI endpoint function to an endpoint
|
||||
* controller.
|
||||
*
|
||||
* A PCI endpoint device can have one or more functions In the case of
|
||||
* PCIe,the specification allows up to 8 PCIe endpoint functions Invoke
|
||||
* pci_epc_add_epf() to add a PCI endpoint function to an endpoint
|
||||
* controller.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device to which the endpoint function should be added
|
||||
* epf - The endpoint function to be added
|
||||
*
|
||||
* Returned Value:
|
||||
* Return 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_add_epf(FAR struct pci_epc_ctrl_s *epc,
|
||||
FAR struct pci_epf_device_s *epf);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_remove_epf
|
||||
*
|
||||
* Description:
|
||||
* This function is used to remove PCI endpoint function from endpoint
|
||||
* controller.
|
||||
*
|
||||
* Invoke to remove PCI endpoint function from the endpoint controller.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device from which the endpoint function should be removed
|
||||
* epf - The endpoint function to be removed
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_remove_epf(FAR struct pci_epc_ctrl_s *epc,
|
||||
FAR struct pci_epf_device_s *epf);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_linkup
|
||||
*
|
||||
* Description:
|
||||
* Notify the EPF device that EPC device has established a connection with
|
||||
* the Root Complex.
|
||||
*
|
||||
* Invoke to Notify the EPF device that the EPC device has established a
|
||||
* connection with the Root Complex.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device which has established link with the host
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_linkup(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_linkdown
|
||||
*
|
||||
* Description:
|
||||
* Notify the EPF device that EPC device has dropped the connection with
|
||||
* the Root Complex.
|
||||
*
|
||||
* Invoke to Notify the EPF device that the EPC device has dropped the
|
||||
* connection with the Root Complex.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device which has dropped the link with the host
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_linkdown(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_init_notify
|
||||
*
|
||||
* Description:
|
||||
* Notify the EPF device that EPC device's core initialization is
|
||||
* completed.
|
||||
*
|
||||
* Invoke to Notify the EPF device that the EPC device's initialization
|
||||
* is completed.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device whose core initialization is completed
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_init_notify(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_bme_notify
|
||||
*
|
||||
* Description:
|
||||
* Notify the EPF device that the EPC device has received the BME event
|
||||
* from the Root complex.
|
||||
*
|
||||
* Invoke to Notify the EPF device that the EPC device has received the Bus
|
||||
* Master Enable (BME) event from the Root complex.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device that received the BME event
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_bme_notify(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_create
|
||||
*
|
||||
* Description:
|
||||
* This function is used to destroy the EPC device.
|
||||
*
|
||||
* Invoke to create a new EPC device and add it to pci_epc class.
|
||||
*
|
||||
* Input Parameters:
|
||||
* name - EPC name strings
|
||||
* ops - Function pointers for performing EPC operations
|
||||
*
|
||||
* Returned Value:
|
||||
* Return struct pci_epc_ctrl_s * if success, NULL if failed.
|
||||
****************************************************************************/
|
||||
|
||||
FAR struct pci_epc_ctrl_s *
|
||||
pci_epc_create(FAR const char *name, FAR const struct pci_epc_ops_s *ops);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_destroy
|
||||
*
|
||||
* Description:
|
||||
* This function is used to create a new endpoint controller (EPC) device.
|
||||
*
|
||||
* Invoke to destroy the PCI EPC device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device that has to be destroyed
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_destroy(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_multi_init
|
||||
*
|
||||
* Description:
|
||||
* This function is used to initialize the pci_epc_mem_s structure.
|
||||
*
|
||||
* Invoke to initialize the pci_epc_mem_s structure used by the
|
||||
* endpoint functions to allocate mapped PCI address.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device that invoked pci_epc_mem_init
|
||||
* windows - Pointer to windows supported by the device
|
||||
* num_windows - Number of windows device supports
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_mem_multi_init(FAR struct pci_epc_ctrl_s *epc,
|
||||
FAR const struct pci_epc_mem_window_s *windows,
|
||||
unsigned int num_windows);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_init
|
||||
*
|
||||
* Description:
|
||||
* This function is used to initialize the PCI endpoint controller memory
|
||||
* space.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - PCI EPC device
|
||||
* base - The physical base address of the PCI address window
|
||||
* size - The PCI window size
|
||||
* page_size - Size of each window page
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 if success, negative if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epc_mem_init(FAR struct pci_epc_ctrl_s *epc, uintptr_t base,
|
||||
size_t size, size_t page_size);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_exit
|
||||
*
|
||||
* Description:
|
||||
* This function is used to cleanup the pci_epc_mem_s structure.
|
||||
*
|
||||
* Invoke to cleanup the pci_epc_mem_s structure allocated in
|
||||
* pci_epc_mem_init().
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device that invoked pci_epc_mem_exit
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_mem_exit(FAR struct pci_epc_ctrl_s *epc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_alloc_addr
|
||||
*
|
||||
* Description:
|
||||
* Allocate memory address from EPC addr space
|
||||
*
|
||||
* Invoke to allocate memory address from the EPC address space. This
|
||||
* is usually done to map the remote RC address into the local system.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which memory has to be allocated
|
||||
* size - The size of the address space that has to be allocated
|
||||
*
|
||||
* Returned Value:
|
||||
* The memory address alloced if success, 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t pci_epc_mem_alloc_addr(FAR struct pci_epc_ctrl_s *epc,
|
||||
size_t size);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epc_mem_free_addr
|
||||
*
|
||||
* Description:
|
||||
* Free the allocated memory address.
|
||||
*
|
||||
* Invoke to free the memory allocated using pci_epc_mem_alloc_addr.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epc - The EPC device on which memory was allocated
|
||||
* phys_addr - The allocated physical address
|
||||
* size - The size of the allocated address space
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epc_mem_free_addr(FAR struct pci_epc_ctrl_s *epc,
|
||||
uintptr_t phys_addr, size_t size);
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_PCI_PCI_EPC_H */
|
315
include/nuttx/pci/pci_epf.h
Normal file
315
include/nuttx/pci/pci_epf.h
Normal file
@ -0,0 +1,315 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/pci/pci_epf.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_EPF_H
|
||||
#define __INCLUDE_NUTTX_PCI_PCI_EPF_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/compiler.h>
|
||||
#include <nuttx/list.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/pci/pci_regs.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* struct pci_epf_header_s - Represents standard configuration header
|
||||
*
|
||||
* vendorid: Identifies device manufacturer
|
||||
* deviceid: Identifies a particular device
|
||||
* revid: Specifies a device-specific revision identifier
|
||||
* progif_code: Identifies a specific register-level programming interface
|
||||
* subclass_code: Identifies more specifically the function of the device
|
||||
* baseclass_code: Broadly classifies the type of function the device
|
||||
* performs
|
||||
* cache_line_size: Specifies the system cacheline size in units of DWORDs
|
||||
* interrupt_pin: Interrupt pin the device (or device function) uses
|
||||
* subsys_vendor_id: Vendor of the add-in card or subsystem
|
||||
* subsys_id: Id specific to vendor
|
||||
*/
|
||||
|
||||
struct pci_epf_header_s
|
||||
{
|
||||
uint16_t vendorid;
|
||||
uint16_t deviceid;
|
||||
uint8_t revid;
|
||||
uint8_t progif_code;
|
||||
uint8_t subclass_code;
|
||||
uint8_t baseclass_code;
|
||||
uint8_t cache_line_size;
|
||||
uint8_t interrupt_pin;
|
||||
uint16_t subsys_vendor_id;
|
||||
uint16_t subsys_id;
|
||||
};
|
||||
|
||||
/* struct pci_epf_bar_s - Represents the BAR of EPF device
|
||||
*
|
||||
* phys_addr: Physical address value that should be mapped to the BAR
|
||||
* addr: Virtual address pointer corresponding to the phys_addr
|
||||
* size: The size of the address space present in BAR
|
||||
* barno: BAR number
|
||||
* flags: Flags that are set for the BAR
|
||||
*/
|
||||
|
||||
struct pci_epf_bar_s
|
||||
{
|
||||
uintptr_t phys_addr;
|
||||
FAR void *addr;
|
||||
size_t size;
|
||||
int barno;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct pci_epf_device_id_s
|
||||
{
|
||||
char name[32];
|
||||
unsigned long driver_data;
|
||||
};
|
||||
|
||||
/* struct pci_epf_device_s - Represents the PCI EPF device
|
||||
*
|
||||
* name: The name of the PCI EPF device
|
||||
* header: Represents standard configuration header
|
||||
* bar: Represents the BAR of EPF device
|
||||
* msi_interrupts: Number of MSI interrupts required by this function
|
||||
* msix_interrupts: Number of MSI-X interrupts required by this function
|
||||
* funcno: Unique (physical) function number within this endpoint device
|
||||
* epc: The EPC device to which this EPF device is bound
|
||||
* driver: The EPF driver to which this EPF device is bound
|
||||
* id: Pointer to the EPF device ID
|
||||
* node: To add pci_epf as a list of PCI endpoint functions to pci_epc_ctrl_s
|
||||
* lock: mutex to protect pci_epf_ops_s
|
||||
* is_bound: Indicates if bind notification to function driver has been
|
||||
* invoked
|
||||
* event_ops: Callbacks for capturing the EPC events
|
||||
*/
|
||||
|
||||
struct pci_epf_device_s
|
||||
{
|
||||
FAR const char *name;
|
||||
FAR const char *epc_name;
|
||||
FAR struct pci_epf_header_s *header;
|
||||
struct pci_epf_bar_s bar[PCI_STD_NUM_BARS];
|
||||
uint8_t msi_interrupts;
|
||||
uint16_t msix_interrupts;
|
||||
uint8_t funcno;
|
||||
|
||||
FAR struct pci_epc_ctrl_s *epc;
|
||||
FAR struct pci_epf_driver_s *driver;
|
||||
FAR const struct pci_epf_device_id_s *id;
|
||||
struct list_node node;
|
||||
|
||||
/* Mutex to protect against concurrent access of pci_epf_ops_s */
|
||||
|
||||
mutex_t lock;
|
||||
bool is_bound;
|
||||
FAR const struct pci_epc_event_ops_s *event_ops;
|
||||
};
|
||||
|
||||
/* struct pci_epf_ops_s - Set of function pointers for performing EPF
|
||||
* operations
|
||||
*
|
||||
* bind: Ops to perform when a EPC device has been bound to EPF device
|
||||
* unbind: Ops to perform when a binding has been lost between a EPC device
|
||||
* and EPF device
|
||||
*/
|
||||
|
||||
struct pci_epf_ops_s
|
||||
{
|
||||
CODE int (*bind)(FAR struct pci_epf_device_s *epf);
|
||||
CODE void (*unbind)(FAR struct pci_epf_device_s *epf);
|
||||
};
|
||||
|
||||
/* struct pci_epc_event_ops_s - Callbacks for capturing the EPC events
|
||||
*
|
||||
* core_init: Callback for the EPC initialization complete event
|
||||
* link_up: Callback for the EPC link up event
|
||||
* link_down: Callback for the EPC link down event
|
||||
* bme: Callback for the EPC BME (Bus Master Enable) event
|
||||
*/
|
||||
|
||||
struct pci_epc_event_ops_s
|
||||
{
|
||||
CODE int (*core_init)(FAR struct pci_epf_device_s *epf);
|
||||
CODE int (*link_up)(FAR struct pci_epf_device_s *epf);
|
||||
CODE int (*link_down)(FAR struct pci_epf_device_s *epf);
|
||||
CODE int (*bme)(FAR struct pci_epf_device_s *epf);
|
||||
};
|
||||
|
||||
/* struct pci_epf_driver_s - Represents the PCI EPF driver
|
||||
*
|
||||
* probe: Ops to perform when a new EPF device has been bound to the EPF
|
||||
* driver
|
||||
* remove: Ops to perform when the binding between the EPF device and EPF
|
||||
* driver is broken
|
||||
* node: EPF driver list node
|
||||
* ops: Set of function pointers for performing EPF operations
|
||||
* id_table: Identifies EPF devices for probing
|
||||
*/
|
||||
|
||||
struct pci_epf_driver_s
|
||||
{
|
||||
CODE int (*probe)(FAR struct pci_epf_device_s *epf);
|
||||
CODE void (*remove)(FAR struct pci_epf_device_s *epf);
|
||||
|
||||
struct list_node node;
|
||||
FAR struct pci_epf_ops_s *ops;
|
||||
FAR const struct pci_epf_device_id_s *id_table;
|
||||
};
|
||||
|
||||
/* struct pci_epf_msix_tbl_s - Represents the MSIX table entry structure
|
||||
*
|
||||
* msg_addr: Writes to this address will trigger MSIX interrupt in host
|
||||
* msg_data: Data that should be written to msg_addr to trigger MSIX
|
||||
* interrupt
|
||||
* vector_ctrl: Identifies if the function is prohibited from sending a
|
||||
* message using this MSIX table entry
|
||||
*/
|
||||
|
||||
struct pci_epf_msix_tbl_s
|
||||
{
|
||||
uint64_t msg_addr;
|
||||
uint32_t msg_data;
|
||||
uint32_t vector_ctrl;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_device_register
|
||||
*
|
||||
* Description:
|
||||
* This function is used to create a new PCI EPF device.
|
||||
*
|
||||
* Invoke to create a new PCI EPF device by providing the name of the
|
||||
* function device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The name of the PCI EPF device be used to bind the EPF device to
|
||||
* a EPF driver
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_device_register(FAR struct pci_epf_device_s *epf);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_device_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function is used to unregister a PCI EPF device.
|
||||
*
|
||||
* Invoke to unregister the PCI EPF device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - PCI EPF device
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_device_unregister(FAR struct pci_epf_device_s *epf);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_register_driver
|
||||
*
|
||||
* Description:
|
||||
* This function is used to register a new PCI EPF driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* drv - EPF driver
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_register_driver(FAR struct pci_epf_driver_s *drv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_unregister_driver
|
||||
*
|
||||
* Description:
|
||||
* This function is used to unregister the PCI EPF driver.
|
||||
*
|
||||
* Invoke to unregister the PCI EPF driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* drv - The PCI EPF driver that has to be unregistered
|
||||
*
|
||||
* Returned Value:
|
||||
* Return >= 0 if success, < 0 if failed
|
||||
****************************************************************************/
|
||||
|
||||
int pci_epf_unregister_driver(FAR struct pci_epf_driver_s *drv);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_alloc_space
|
||||
*
|
||||
* Description:
|
||||
* This function is used to allocate memory for the PCI EPF register
|
||||
* space.
|
||||
*
|
||||
* Invoke to allocate memory for the PCI EPF register space.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The EPF device to whom allocate the memory
|
||||
* barno - The BAR number corresponding to the allocated register space
|
||||
* size - The size of the memory that has to be allocated
|
||||
* align - Alignment size for the allocation region
|
||||
*
|
||||
* Returned Value:
|
||||
* Return space address malloced if success, otherwise NULL
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *pci_epf_alloc_space(FAR struct pci_epf_device_s *epf, int barno,
|
||||
size_t size, size_t align);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pci_epf_free_space
|
||||
*
|
||||
* Description:
|
||||
* Free the allocated PCI EPF register space
|
||||
*
|
||||
* Invoke to free the allocated PCI EPF register space.
|
||||
*
|
||||
* Input Parameters:
|
||||
* epf - The EPF device from whom to free the memory
|
||||
* barno - The BAR number corresponding to the register space
|
||||
* addr - The virtual address of the PCI EPF register space
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
****************************************************************************/
|
||||
|
||||
void pci_epf_free_space(FAR struct pci_epf_device_s *epf,
|
||||
int barno, FAR void *addr);
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_PCI_PCI_EPF_H */
|
@ -115,6 +115,11 @@
|
||||
|
||||
#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
|
||||
#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
|
||||
#define PCI_INTERRUPT_UNKNOWN 0
|
||||
#define PCI_INTERRUPT_INTA 1
|
||||
#define PCI_INTERRUPT_INTB 2
|
||||
#define PCI_INTERRUPT_INTC 3
|
||||
#define PCI_INTERRUPT_INTD 4
|
||||
#define PCI_MIN_GNT 0x3e /* 8 bits */
|
||||
#define PCI_MAX_LAT 0x3f /* 8 bits */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user