forked from Imagelibrary/rtems
This patch changes the license to BSD-2 for all source files where the copyright is held by Aeroflex Gaisler, Cobham Gaisler, or Gaisler Research. Some files also includes copyright right statements from OAR and/or embedded Brains in addition to Gaisler. Updates #3053.
279 lines
8.8 KiB
C
279 lines
8.8 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* @brief PCI Configuration Library
|
|
*/
|
|
|
|
/*
|
|
* COPYRIGHT (c) 2010 Cobham Gaisler AB.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/* Four versions of the library exists:
|
|
* - auto configuration (default)
|
|
* - read configuration from PnP (inherit BIOS set up)
|
|
* - static configuration (user defined config)
|
|
* - peripheral configuration, no CFG space accesses are possible instead a
|
|
* device tree known at compile-time have been built in.
|
|
* all versions are defined through here.
|
|
*/
|
|
|
|
#ifndef __PCI_CFG_H__
|
|
#define __PCI_CFG_H__
|
|
|
|
#include <pci.h>
|
|
|
|
/* PCI Configuration library */
|
|
|
|
/* Return the number of PCI buses in system */
|
|
extern int pci_bus_count(void);
|
|
|
|
/* PCI Address assigned to BARs which failed to fit into the PCI Window or
|
|
* is disabled by any other cause.
|
|
*/
|
|
extern uint32_t pci_invalid_address;
|
|
|
|
/* PCI Configuration Library of the system */
|
|
enum {
|
|
PCI_CONFIG_LIB_NONE = 0,
|
|
PCI_CONFIG_LIB_AUTO = 1,
|
|
PCI_CONFIG_LIB_STATIC = 2,
|
|
PCI_CONFIG_LIB_READ = 3,
|
|
PCI_CONFIG_LIB_PERIPHERAL = 4,
|
|
};
|
|
extern const int pci_config_lib_type;
|
|
|
|
/* Configuration library function pointers, these are set in <rtems/confdefs.h>
|
|
* by project configuration or by the BSP. The configuration will pull in the
|
|
* PCI Library needed and the PCI initialization functions will call these
|
|
* functions on initialization from the host driver.
|
|
*/
|
|
extern int (*pci_config_lib_init)(void);
|
|
extern void (*pci_config_lib_register)(void *config);
|
|
|
|
/* Configure PCI devices and bridges, and setup the RAM data structures
|
|
* describing the PCI devices currently present in the system.
|
|
*
|
|
* Returns 0 on success, -1 on failure.
|
|
*/
|
|
extern int pci_config_init(void);
|
|
|
|
/* Register a config-library specific configuration used by the libarary in
|
|
* pci_config_init().
|
|
*/
|
|
extern void pci_config_register(void *config);
|
|
|
|
/* Print current PCI configuration (C-code) to terminal, can be used in
|
|
* static and peripheral PCI configuration library. The configuration is
|
|
* taken from the current configuration library setup.
|
|
*/
|
|
extern void pci_cfg_print(void);
|
|
|
|
struct pci_bus; /* Bridge Device and secondary bus information */
|
|
struct pci_dev; /* Device/function */
|
|
struct pci_res; /* Resource: BAR, ROM or Bridge Window */
|
|
|
|
/* The Host Bridge and all subdevices (the PCI RAM data structure) */
|
|
extern struct pci_bus pci_hb;
|
|
|
|
/* Arguments for pci_for_each_child() search option */
|
|
#define SEARCH_CHILDREN 0 /* direct children of bus only */
|
|
#define SEARCH_DEPTH 1 /* all children of bus */
|
|
|
|
/* Iterate over all PCI devices on a bus (see search options) and call func(),
|
|
* iteration is stopped if a non-zero value is returned by func().
|
|
*
|
|
* The function iterates over the PCI RAM data structure, it is not
|
|
* available until after all devices have been found and pci_hb is populated,
|
|
* typically after pci_config_init() is called.
|
|
*
|
|
* search options: 0 (no child buses), 1 (depth first, recursive)
|
|
*
|
|
* Return Values
|
|
* 0 All PCI devices were processed, func() returned 0 on every call
|
|
* X func() returned non-zero X value, the search was stopped
|
|
*/
|
|
extern int pci_for_each_child(
|
|
struct pci_bus *bus,
|
|
int (*func)(struct pci_dev *, void *arg),
|
|
void *arg,
|
|
int search);
|
|
|
|
/* Depth first search of all PCI devices in PCI RAM data structure and call
|
|
* func(dev, arg), iteration is stopped if a non-zero value is returned by
|
|
* func().
|
|
*
|
|
* The function iterates over the PCI RAM data structure, it is not
|
|
* available until after all devices have been found and pci_hb is populated,
|
|
* typically after pci_config_init() is called.
|
|
*
|
|
* Return Values
|
|
* 0 All PCI devices were processed, func() returned 0 on every call
|
|
* X func() returned non-zero X value, the search was stopped
|
|
*/
|
|
extern int pci_for_each_dev(
|
|
int (*func)(struct pci_dev *, void *arg),
|
|
void *arg);
|
|
|
|
/* Get PCI device from RAM device tree for a device matching PCI Vendor, Device
|
|
* and instance number 'index'.
|
|
*
|
|
* Return Values
|
|
* -1 pci_find_dev did not find a device matching the criterion.
|
|
* 0 device was found, *ppdev was updated with the PCI device address
|
|
*/
|
|
extern int pci_find_dev(uint16_t ven, uint16_t dev, int index,
|
|
struct pci_dev **ppdev);
|
|
|
|
/* Get PCI device from RAM device tree by BUS|SLOT|FUNC.
|
|
*
|
|
* Return Values
|
|
* -1 pci_get_dev did not find a device matching the criterion
|
|
* 0 device was found, *ppdev was updated with the PCI device address
|
|
*/
|
|
extern int pci_get_dev(pci_dev_t pcidev, struct pci_dev **ppdev);
|
|
|
|
/* Resource flags */
|
|
#define PCI_RES_IO 1
|
|
#define PCI_RES_MEMIO 2
|
|
#define PCI_RES_MEM_PREFETCH 1
|
|
#define PCI_RES_MEM (PCI_RES_MEMIO | PCI_RES_MEM_PREFETCH)
|
|
#define PCI_RES_TYPE_MASK 0x3
|
|
#define PCI_RES_IO32 0x08
|
|
#define PCI_RES_FAIL 0x10 /* Alloc Failed */
|
|
|
|
/* BAR Resouces entry */
|
|
struct pci_res {
|
|
struct pci_res *next;
|
|
uint32_t size;
|
|
uint32_t boundary;
|
|
unsigned char flags; /* I/O, MEM or MEMIO */
|
|
unsigned char bar;
|
|
|
|
/* Assigned Resource (PCI address), zero if not assigned */
|
|
uint32_t start;
|
|
uint32_t end;
|
|
};
|
|
|
|
/* Get Device from resource pointer. bar is the index of the pci_dev.resources
|
|
* array and used to get the device base address of which the resource is
|
|
* associated with.
|
|
*/
|
|
#define RES2DEV(res) ((struct pci_dev *) \
|
|
((uintptr_t)res - (uintptr_t)(res->bar * (sizeof(struct pci_res)))))
|
|
|
|
/* Device flags */
|
|
#define PCI_DEV_BRIDGE 0x01 /* Device is a Bridge (struct pci_bus) */
|
|
#define PCI_DEV_RES_FAIL 0x02 /* Resource alloction for device BARs failed */
|
|
|
|
/* Bus Flags */
|
|
#define PCI_BUS_IO 0x01 /* 16-bit I/O address decoding */
|
|
#define PCI_BUS_MEMIO 0x02 /* Bus support non-prefetchable mem (always) */
|
|
#define PCI_BUS_MEM 0x04 /* Bus support prefetchable memory space */
|
|
#define PCI_BUS_IO32 0x08 /* 32-bit I/O address decoding */
|
|
|
|
#define BRIDGE_RES_COUNT 2 /* Number of BAR resources a bridge can have */
|
|
#define BUS_RES_START BRIDGE_RES_COUNT
|
|
|
|
/* Bus Resources Array */
|
|
enum {
|
|
BUS_RES_IO = 0,
|
|
BUS_RES_MEMIO = 1,
|
|
BUS_RES_MEM = 2,
|
|
};
|
|
|
|
/* Device Resource array index meaning */
|
|
enum {
|
|
/* A Device has up to 6 BARs and an optional ROM BAR */
|
|
DEV_RES_BAR1 = 0,
|
|
DEV_RES_BAR2 = 1,
|
|
DEV_RES_BAR3 = 2,
|
|
DEV_RES_BAR4 = 3,
|
|
DEV_RES_BAR5 = 4,
|
|
DEV_RES_BAR6 = 5,
|
|
DEV_RES_ROM = 6,
|
|
|
|
/* Bridges have 2 BARs (BAR1 and BAR2) and 3 Windows to secondary bus
|
|
* and an optional ROM BAR
|
|
*/
|
|
BRIDGE_RES_BAR1 = 0,
|
|
BRIDGE_RES_BAR2 = 1,
|
|
BRIDGE_RES_IO = 2,
|
|
BRIDGE_RES_MEMIO = 3,
|
|
BRIDGE_RES_MEM = 4,
|
|
BRIDGE_RES_UNUSED1 = 5,
|
|
BRIDGE_RES_ROM = 6,
|
|
};
|
|
|
|
/* Maximum Number of Resources of a device */
|
|
#define DEV_RES_CNT (DEV_RES_ROM + 1)
|
|
|
|
/* PCI Device (Bus|Slot|Function) description */
|
|
struct pci_dev {
|
|
struct pci_res resources[DEV_RES_CNT]; /* must be topmost field */
|
|
struct pci_dev *next;
|
|
struct pci_bus *bus;
|
|
pci_dev_t busdevfun;
|
|
uint8_t flags;
|
|
uint8_t sysirq;
|
|
uint16_t vendor;
|
|
uint16_t device;
|
|
uint16_t subvendor;
|
|
uint16_t subdevice;
|
|
uint32_t classrev;
|
|
|
|
/* static configuration settings */
|
|
uint16_t command;
|
|
};
|
|
|
|
/* PCI Bus description */
|
|
struct pci_bus {
|
|
struct pci_dev dev; /* PCI Bridge */
|
|
struct pci_dev *devs; /* Devices on child (secondary) Bus */
|
|
unsigned int flags;
|
|
|
|
/* Bridge Information */
|
|
int num; /* Bus number (0=Root-PCI-bus) */
|
|
int pri; /* Primary Bus Number */
|
|
int sord; /* Subordinate Buses (Child bus count) */
|
|
|
|
#if defined(PCI_CFG_AUTO_LIB)
|
|
/* Resources of devices on bus. USED INTERNALLY IN AUTO-CFG LIBRARY.
|
|
*
|
|
* BUS_RES_IO = 0: I/O resources
|
|
* BUS_RES_MEMIO = 1: Prefetchable memory resources
|
|
* BUS_RES_MEM = 2: Non-Prefetchable memory resources
|
|
*/
|
|
struct pci_res *busres[3];
|
|
#endif
|
|
};
|
|
|
|
#include <pci/cfg_auto.h>
|
|
#include <pci/cfg_static.h>
|
|
#include <pci/cfg_read.h>
|
|
#include <pci/cfg_peripheral.h>
|
|
|
|
#endif
|