From 1c5a7e5e52d418af5fb85eb321f2eacdcad5853b Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Mon, 28 Nov 2011 10:16:09 +0100 Subject: LIBPCI: added DRVMGR model for PCI bus --- cpukit/libpci/Makefile.am | 5 + cpukit/libpci/pci_bus.c | 567 ++++++++++++++++++++++++++++++++++++++++++++ cpukit/libpci/pci_bus.h | 159 +++++++++++++ cpukit/libpci/preinstall.am | 9 + 4 files changed, 740 insertions(+) create mode 100644 cpukit/libpci/pci_bus.c create mode 100644 cpukit/libpci/pci_bus.h (limited to 'cpukit/libpci') diff --git a/cpukit/libpci/Makefile.am b/cpukit/libpci/Makefile.am index fd42a6fdcf..d7ca5ccba9 100644 --- a/cpukit/libpci/Makefile.am +++ b/cpukit/libpci/Makefile.am @@ -40,6 +40,11 @@ libpci_a_SOURCES += pci_get_dev.c libpci_a_SOURCES += pci_irq.c libpci_a_SOURCES += pci_print.c +# Driver manager PCI bus +libpci_a_SOURCES += pci_bus.c +include_drvmgrdir = $(includedir)/drvmgr +include_drvmgr_HEADERS = pci_bus.h + endif include $(srcdir)/preinstall.am diff --git a/cpukit/libpci/pci_bus.c b/cpukit/libpci/pci_bus.c new file mode 100644 index 0000000000..ea30dfa99a --- /dev/null +++ b/cpukit/libpci/pci_bus.c @@ -0,0 +1,567 @@ +/* PCI bus driver. + * + * COPYRIGHT (c) 2008. + * Cobham Gaisler AB. + * + * General part of PCI Bus driver. The driver is typically + * initialized from the PCI host driver separating the host + * driver from the common parts in PCI drivers. + * The PCI library must be initialized before starting the + * PCI bus driver. The PCI library have set up BARs and + * assigned system IRQs for targets. + * This PCI bus driver rely on the PCI library (pci.c) for + * interrupt registeration (pci_interrupt_register) and PCI + * target set up. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * 2008-12-03, Daniel Hellstrom + * Created + * + */ + +/* Use PCI Configuration libarary pci_hb RAM device structure to find devices, + * undefine to access PCI configuration space directly. + */ +#define USE_PCI_CFG_LIB + +/* On small systems undefine PCIBUS_INFO to avoid sprintf get dragged in */ +#define PCIBUS_INFO + +#include +#include +#include + +#include +#ifdef USE_PCI_CFG_LIB +#include +#endif +#include + +#include +#include + +#ifdef DEBUG +#define DBG(args...) printk(args) +#else +#define DBG(args...) +#endif + +int pcibus_bus_init1(struct drvmgr_bus *bus); +int pcibus_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev); +int pcibus_int_register( + struct drvmgr_dev *dev, + int index, + const char *info, + drvmgr_isr isr, + void *arg); +int pcibus_int_unregister( + struct drvmgr_dev *dev, + int index, + drvmgr_isr isr, + void *arg); +int pcibus_int_clear( + struct drvmgr_dev *dev, + int index); +int pcibus_freq_get( + struct drvmgr_dev *dev, + int options, + unsigned int *freq_hz); + +int pcibus_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params); + +void pcibus_dev_info( + struct drvmgr_dev *dev, + void (*print_line)(void *p, char *str), + void *p); + +struct drvmgr_bus_ops pcibus_ops = { + .init = { + pcibus_bus_init1, + NULL, + NULL, + NULL + }, + .remove = NULL, + .unite = pcibus_unite, + .int_register = pcibus_int_register, + .int_unregister = pcibus_int_unregister, +#if 0 + .int_enable = pcibus_int_enable, + .int_disable = pcibus_int_disable, +#endif + .int_clear = pcibus_int_clear, + .int_mask = NULL, + .int_unmask = NULL, + .get_params = pcibus_get_params, + .freq_get = pcibus_freq_get, +#ifdef PCIBUS_INFO + .info_dev = pcibus_dev_info, +#endif +}; + +struct drvmgr_func pcibus_funcs[] = { + DRVMGR_FUNC(PCI_FUNC_MREG_R8, NULL), + DRVMGR_FUNC(PCI_FUNC_MREG_R16, NULL), + DRVMGR_FUNC(PCI_FUNC_MREG_R32, NULL), + DRVMGR_FUNC(PCI_FUNC_MREG_W8, NULL), + DRVMGR_FUNC(PCI_FUNC_MREG_W16, NULL), + DRVMGR_FUNC(PCI_FUNC_MREG_W32, NULL), + DRVMGR_FUNC_END +}; + +/* Driver resources configuration for the PCI bus. It is declared weak so that + * the user may override it from the project file, if the default settings are + * not enough. + */ +struct drvmgr_bus_res pcibus_drv_resources __attribute__((weak)) = { + .next = NULL, + .resource = { + RES_EMPTY, + }, +}; + +struct pcibus_priv { + struct drvmgr_dev *dev; +}; + +static int compatible(struct pci_dev_id *id, struct pci_dev_id_match *drv) +{ + if (((drv->vendor==PCI_ID_ANY) || (id->vendor==drv->vendor)) && + ((drv->device==PCI_ID_ANY) || (id->device==drv->device)) && + ((drv->subvendor==PCI_ID_ANY) || (id->subvendor==drv->subvendor)) && + ((drv->subdevice==PCI_ID_ANY) || (id->subdevice==drv->subdevice)) && + ((id->class & drv->class_mask) == drv->class)) + return 1; + else + return 0; +} + +int pcibus_unite(struct drvmgr_drv *drv, + struct drvmgr_dev *dev) +{ + struct pci_drv_info *pdrv; + struct pci_dev_id_match *drvid; + struct pci_dev_info *pci; + + if (!drv || !dev || !dev->parent) + return 0; + + if ((drv->bus_type != DRVMGR_BUS_TYPE_PCI) || + (dev->parent->bus_type != DRVMGR_BUS_TYPE_PCI)) + return 0; + + pci = (struct pci_dev_info *)dev->businfo; + if (!pci) + return 0; + + pdrv = (struct pci_drv_info *)drv; + drvid = pdrv->ids; + if (!drvid) + return 0; + while (drvid->vendor != 0) { + if (compatible(&pci->id, drvid)) { + /* Unite device and driver */ + DBG("DRV %p and DEV %p united\n", drv, dev); + return 1; + } + drvid++; + } + + return 0; +} + +static int pcibus_int_get(struct drvmgr_dev *dev, int index) +{ + int irq; + + /* Relative (positive) or absolute (negative) IRQ number */ + if (index > 0) { + /* PCI devices only have one IRQ per function */ + return -1; + } else if (index == 0) { + /* IRQ Index relative to Cores base IRQ */ + + /* Get Base IRQ */ + irq = ((struct pci_dev_info *)dev->businfo)->irq; + if (irq <= 0) + return -1; + } else { + /* Absolute IRQ number */ + irq = -index; + } + return irq; +} + +/* Use standard PCI facility to register interrupt handler */ +int pcibus_int_register( + struct drvmgr_dev *dev, + int index, + const char *info, + drvmgr_isr isr, + void *arg) +{ +#ifdef DEBUG + struct drvmgr_dev *busdev = dev->parent->dev; +#endif + int irq; + + /* Get IRQ number from index and device information */ + irq = pcibus_int_get(dev, index); + if (irq < 0) + return -1; + + DBG("Register PCI interrupt on %p for dev %p (IRQ: %d)\n", + busdev, dev, irq); + + return pci_interrupt_register(irq, info, isr, arg); +} + +/* Use standard PCI facility to unregister interrupt handler */ +int pcibus_int_unregister( + struct drvmgr_dev *dev, + int index, + drvmgr_isr isr, + void *arg) +{ +#ifdef DEBUG + struct drvmgr_dev *busdev = dev->parent->dev; +#endif + int irq; + + /* Get IRQ number from index and device information */ + irq = pcibus_int_get(dev, index); + if (irq < 0) + return -1; + + DBG("Unregister PCI interrupt on %p for dev %p (IRQ: %d)\n", + busdev, dev, irq); + + return pci_interrupt_unregister(irq, isr, arg); +} + +/* Use standard PCI facility to clear interrupt */ +int pcibus_int_clear( + struct drvmgr_dev *dev, + int index) +{ + int irq; + + /* Get IRQ number from index and device information */ + irq = pcibus_int_get(dev, index); + if (irq < 0) + return -1; + + pci_interrupt_clear(irq); + + return 0; +} + +int pcibus_freq_get( + struct drvmgr_dev *dev, + int options, + unsigned int *freq_hz) +{ + /* Standard PCI Bus frequency */ + *freq_hz = 33000000; + return 0; +} + +int pcibus_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params) +{ + /* No device prefix */ + params->dev_prefix = NULL; + + return 0; +} + +#ifdef PCIBUS_INFO +void pcibus_dev_info( + struct drvmgr_dev *dev, + void (*print_line)(void *p, char *str), + void *p) +{ + struct pci_dev_info *devinfo; + struct pcibus_res *pcibusres; + struct pci_res *res; + char buf[64]; + int i; + char *str1, *res_types[3] = {" IO16", "MEMIO", " MEM"}; + uint32_t pcistart; + + if (!dev) + return; + + devinfo = (struct pci_dev_info *)dev->businfo; + if (!devinfo) + return; + + if ((devinfo->id.class >> 8) == PCI_CLASS_BRIDGE_PCI) + print_line(p, "PCI BRIDGE DEVICE"); + else + print_line(p, "PCI DEVICE"); + sprintf(buf, "LOCATION: BUS:SLOT:FUNCTION [%x:%x:%x]", + PCI_DEV_EXPAND(devinfo->pcidev)); + print_line(p, buf); + sprintf(buf, "PCIID 0x%lx", (uint32_t)devinfo->pcidev); + print_line(p, buf); + sprintf(buf, "VENDOR ID: %04x", devinfo->id.vendor); + print_line(p, buf); + sprintf(buf, "DEVICE ID: %04x", devinfo->id.device); + print_line(p, buf); + sprintf(buf, "SUBVEN ID: %04x", devinfo->id.subvendor); + print_line(p, buf); + sprintf(buf, "SUBDEV ID: %04x", devinfo->id.subdevice); + print_line(p, buf); + sprintf(buf, "CLASS: %lx", devinfo->id.class); + print_line(p, buf); + sprintf(buf, "REVISION: %x", devinfo->rev); + print_line(p, buf); + sprintf(buf, "IRQ: %d", devinfo->irq); + print_line(p, buf); + sprintf(buf, "PCIDEV ptr: %p", devinfo->pci_device); + print_line(p, buf); + + /* List Resources */ + print_line(p, "RESOURCES"); + for (i = 0; i < PCIDEV_RES_CNT; i++) { + pcibusres = &devinfo->resources[i]; + + str1 = " RES"; + pcistart = -1; + res = pcibusres->res; + if (res && (res->flags & PCI_RES_TYPE_MASK)) { + str1 = res_types[(res->flags & PCI_RES_TYPE_MASK) - 1]; + if (res->flags & PCI_RES_IO32) + str1 = " IO32"; + pcistart = res->start; + } + + if (res && (res->flags & PCI_RES_FAIL)) { + sprintf(buf, " %s[%d]: NOT ASSIGNED", str1, i); + print_line(p, buf); + continue; + } + if (!pcibusres->size) + continue; + + sprintf(buf, " %s[%d]: %08lx-%08lx [PCIADR %lx]", + str1, i, pcibusres->address, + pcibusres->address + pcibusres->size - 1, pcistart); + print_line(p, buf); + } +} +#endif + +#ifdef USE_PCI_CFG_LIB + +static int pcibus_dev_register(struct pci_dev *dev, void *arg) +{ + struct drvmgr_bus *pcibus = arg; + struct drvmgr_dev *newdev; + struct pci_dev_info *pciinfo; + int i, type; + struct pcibus_res *pcibusres; + struct pci_res *pcires; + + pci_dev_t pcidev = dev->busdevfun; + + DBG("PCI DEV REGISTER: %x:%x:%x\n", PCI_DEV_EXPAND(pcidev)); + + /* Allocate a device */ + drvmgr_alloc_dev(&newdev, 24 + sizeof(struct pci_dev_info)); + newdev->next = NULL; + newdev->parent = pcibus; /* Ourselfs */ + newdev->minor_drv = 0; + newdev->minor_bus = 0; + newdev->priv = NULL; + newdev->drv = NULL; + newdev->name = (char *)(newdev + 1); + newdev->next_in_drv = NULL; + newdev->bus = NULL; + + /* Init PnP information, Assign Core interfaces with this device */ + pciinfo = (struct pci_dev_info *)((char *)(newdev + 1) + 24); + + /* Read Device and Vendor */ + pciinfo->id.vendor = dev->vendor; + pciinfo->id.device = dev->device; + pciinfo->id.subvendor = dev->subvendor; + pciinfo->id.subdevice = dev->subdevice; + pciinfo->rev = dev->classrev & 0xff; + pciinfo->id.class = (dev->classrev >> 8) & 0xffffff; + + /* Read IRQ information set by PCI layer */ + pciinfo->irq = dev->sysirq; + + /* Save Location on PCI bus */ + pciinfo->pcidev = pcidev; + + /* Connect device with PCI data structure */ + pciinfo->pci_device = dev; + + /* Build resources so that PCI device drivers doesn't have to scan + * configuration space themselves, also the address is translated + * into CPU accessible addresses. + */ + for (i = 0; i < PCIDEV_RES_CNT; i++) { + pcibusres = &pciinfo->resources[i]; + pcires = &dev->resources[i]; + type = pcires->flags & PCI_RES_TYPE_MASK; + if (type == 0 || (pcires->flags & PCI_RES_FAIL)) + continue; /* size=0 */ + + pcibusres->address = pcires->start; + if (pci_pci2cpu(&pcibusres->address, type)) + continue; /* size=0 */ + pcibusres->res = pcires; + pcibusres->size = pcires->end - pcires->start; + } + + /* Connect device with PCI information */ + newdev->businfo = (void *)pciinfo; + + /* Create Device Name */ + sprintf(newdev->name, "PCI_%x:%x:%x_%04x:%04x", + PCI_DEV_BUS(pcidev), PCI_DEV_SLOT(pcidev), PCI_DEV_FUNC(pcidev), + pciinfo->id.vendor, pciinfo->id.device); + + /* Register New Device */ + drvmgr_dev_register(newdev); + + return 0; +} + +#else + +static int pcibus_dev_register(pci_dev_t pcidev, void *arg) +{ + struct drvmgr_bus *pcibus = arg; + struct drvmgr_dev *newdev; + struct pci_dev_info *pciinfo; + + DBG("PCI DEV REGISTER: %x:%x:%x\n", PCI_DEV_EXPAND(pcidev)); + + /* Allocate a device */ + drvmgr_alloc_dev(&newdev, 24 + sizeof(struct pci_dev_info)); + newdev->next = NULL; + newdev->parent = pcibus; /* Ourselfs */ + newdev->minor_drv = 0; + newdev->minor_bus = 0; + newdev->priv = NULL; + newdev->drv = NULL; + newdev->name = (char *)(newdev + 1); + newdev->next_in_drv = NULL; + newdev->bus = NULL; + + /* Init PnP information, Assign Core interfaces with this device */ + pciinfo = (struct pci_dev_info *)((char *)(newdev + 1) + 24); + + /* Read Device and Vendor */ + pci_cfg_r16(pcidev, PCI_VENDOR_ID, &pciinfo->id.vendor); + pci_cfg_r16(pcidev, PCI_DEVICE_ID, &pciinfo->id.device); + pci_cfg_r32(pcidev, PCI_CLASS_REVISION, &pciinfo->id.class); + pciinfo->rev = pciinfo->id.class & 0xff; + pciinfo->id.class = pciinfo->id.class >> 8; + + /* Devices have subsytem device and vendor ID */ + if ((pciinfo->id.class >> 8) != PCI_CLASS_BRIDGE_PCI) { + pci_cfg_r16(pcidev, PCI_SUBSYSTEM_VENDOR_ID, + &pciinfo->id.subvendor); + pci_cfg_r16(pcidev, PCI_SUBSYSTEM_ID, &pciinfo->id.subdevice); + } else { + pciinfo->id.subvendor = 0; + pciinfo->id.subdevice = 0; + } + + /* Read IRQ information set by PCI layer */ + pci_cfg_r8(pcidev, PCI_INTERRUPT_LINE, &pciinfo->irq); + + /* Save Location */ + pciinfo->pcidev = pcidev; + + /* There is no way we can know this information this way */ + pciinfo->pci_device = NULL; + + /* Connect device with PCI information */ + newdev->businfo = (void *)pciinfo; + + /* Create Device Name */ + sprintf(newdev->name, "PCI_%d:%d:%d_%04x:%04x", + PCI_DEV_BUS(pcidev), PCI_DEV_SLOT(pcidev), PCI_DEV_FUNC(pcidev), + pciinfo->id.vendor, pciinfo->id.device); + + /* Register New Device */ + drvmgr_dev_register(newdev); + + return 0; +} + +#endif + +/* Register all AMBA devices available on the AMBAPP bus */ +static int pcibus_devs_register(struct drvmgr_bus *bus) +{ + /* return value 0=DRVMGR_OK works with pci_for_each/pci_for_each_dev */ +#ifdef USE_PCI_CFG_LIB + /* Walk the PCI device tree in RAM */ + return pci_for_each_dev(pcibus_dev_register, bus); +#else + /* Scan PCI Configuration space */ + return pci_for_each(pcibus_dev_register, bus); +#endif +} + +/*** DEVICE FUNCTIONS ***/ + +int pcibus_register(struct drvmgr_dev *dev, struct pcibus_config *config) +{ + struct pcibus_priv *priv; + int i, fid, rc; + + DBG("PCI BUS: initializing\n"); + + /* Create BUS */ + drvmgr_alloc_bus(&dev->bus, sizeof(struct pcibus_priv)); + dev->bus->bus_type = DRVMGR_BUS_TYPE_PCI; + dev->bus->next = NULL; + dev->bus->dev = dev; + dev->bus->children = NULL; + dev->bus->ops = &pcibus_ops; + dev->bus->dev_cnt = 0; + dev->bus->reslist = NULL; + dev->bus->maps_up = config->maps_up; + dev->bus->maps_down = config->maps_down; + dev->bus->funcs = &pcibus_funcs[0]; + + /* Copy function definitions from PCI Layer */ + for (i=0; i<6; i++) { + fid = pcibus_funcs[i].funcid; + rc = pci_access_func(RW_DIR(fid), RW_SIZE(fid), + &pcibus_funcs[i].func, PCI_LITTLE_ENDIAN, 3); + if (rc != 0) + DBG("PCI BUS: MEMREG 0x%x function not defined\n", fid); + } + + /* Add resource configuration if user overrided the default empty cfg */ + if (pcibus_drv_resources.resource[0].drv_id != 0) + drvmgr_bus_res_add(dev->bus, &pcibus_drv_resources); + + /* Init BUS private structures */ + priv = (struct pcibus_priv *)(dev->bus + 1); + dev->bus->priv = priv; + + /* Register BUS */ + drvmgr_bus_register(dev->bus); + + return DRVMGR_OK; +} + +/*** BUS INITIALIZE FUNCTIONS ***/ + +int pcibus_bus_init1(struct drvmgr_bus *bus) +{ + return pcibus_devs_register(bus); +} diff --git a/cpukit/libpci/pci_bus.h b/cpukit/libpci/pci_bus.h new file mode 100644 index 0000000000..f96631f6e5 --- /dev/null +++ b/cpukit/libpci/pci_bus.h @@ -0,0 +1,159 @@ +/* PCI bus driver Interface. + * + * COPYRIGHT (c) 2008. + * Cobham Gaisler AB. + * + * General part of PCI Bus driver. The driver is typically + * initialized from the PCI host driver separating the host + * driver from the common parts in PCI drivers. + * The PCI library must be initialized before starting the + * PCI bus driver. The PCI library have set up BARs and + * assigned system IRQs for targets. + * This PCI bus driver rely on the PCI library (pci.c) for + * interrupt registeration (pci_interrupt_register) and PCI + * target set up. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + */ + +#ifndef __PCI_BUS_H__ +#define __PCI_BUS_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* PCI Driver ID generation (VENDOR: 16-bit, DEVICE: 16-bit) */ +#define DRIVER_PCI_ID(vendor, device) \ + DRIVER_ID(DRVMGR_BUS_TYPE_PCI, \ + ((((vendor) & 0xffff) << 16) | ((device) & 0xffff))) + +/* PCI Driver ID generation (CLASS: 24-bit) */ +#define DRIVER_PCI_CLASS(class) \ + DRIVER_ID(DRVMGR_BUS_TYPE_PCI, ((1 << 32) | ((class) & 0xffffff))) + +/* PCI driver IDs (DRIVER_PCI_VENDOR_DEVICE or DRIVER_PCI_CLASS_NAME) */ +#define DRIVER_PCI_GAISLER_RASTAIO_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_IO) +#define DRIVER_PCI_GAISLER_RASTATMTC_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_TMTC) +#define DRIVER_PCI_GAISLER_GR701_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701) +#define DRIVER_PCI_GAISLER_RASTAADCDAC_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_ADCDAC) +#define DRIVER_PCI_GAISLER_TMTC_1553_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553) +#define DRIVER_PCI_GAISLER_RASTA_SPW_ROUTER_ID DRIVER_PCI_ID(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_SPW_RTR) + +struct pci_dev_id { + uint16_t vendor; + uint16_t device; + uint16_t subvendor; + uint16_t subdevice; + uint32_t class; /* 24 lower bits */ +}; + +struct pci_dev_id_match { + uint16_t vendor; + uint16_t device; + uint16_t subvendor; + uint16_t subdevice; + uint32_t class; /* 24 lower bits */ + uint32_t class_mask; /* 24 lower bits */ +}; +#define PCIID_DEVVEND(vendor, device) \ + {vendor, device, PCI_ID_ANY, PCI_ID_ANY, 0, 0} +#define PCIID_END_TABLE {0, 0, 0, 0, 0, 0} + +enum { + /* A Device has up to 6 BARs and an optional ROM BAR */ + PCIDEV_RES_BAR1 = 0, + PCIDEV_RES_BAR2 = 1, + PCIDEV_RES_BAR3 = 2, + PCIDEV_RES_BAR4 = 3, + PCIDEV_RES_BAR5 = 4, + PCIDEV_RES_BAR6 = 5, + PCIDEV_RES_ROM = 6, +}; +/* Maximum Number of Resources of a device */ +#define PCIDEV_RES_CNT (PCIDEV_RES_ROM + 1) + +/* IO, MEMIO or MEM resource. Can be BAR, ROM or Bridge Window */ +struct pcibus_res { + uint32_t address; /* Base Address, CPU accessible */ + uint32_t size; /* 0=Unimplemented, 0!=Resource Size */ + struct pci_res *res; /* PCI-layer resource */ +}; + +struct pci_dev_info { + struct pci_dev_id id; + uint8_t rev; + uint8_t irq; /* 0 = NO IRQ */ + pci_dev_t pcidev; + struct pcibus_res resources[PCIDEV_RES_CNT]; + struct pci_dev *pci_device; +}; + +struct pci_drv_info { + struct drvmgr_drv general; /* General bus info */ + /* PCI specific bus information */ + struct pci_dev_id_match *ids; /* Supported hardware */ +}; + +/* Access routines */ +struct pcibus_regmem_ops { + drvmgr_r8 r8; + drvmgr_r16 r16; + drvmgr_r32 r32; + drvmgr_r64 r64; + drvmgr_w8 w8; + drvmgr_w16 w16; + drvmgr_w32 w32; + drvmgr_w64 w64; +}; + +/* Let driver configure PCI bus driver */ +struct pcibus_config { + struct drvmgr_map_entry *maps_up; + struct drvmgr_map_entry *maps_down; +}; + +/* PCI Configuration Space Access - Not implemented (use PCI Lib directly) */ +#define PCI_FUNC_CFG_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_CFG) +#define PCI_FUNC_CFG_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_CFG) +#define PCI_FUNC_CFG_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_CFG) +#define PCI_FUNC_CFG_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_CFG) +#define PCI_FUNC_CFG_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_CFG) +#define PCI_FUNC_CFG_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_CFG) + +/* PCI I/O Register Access - Not implemented (use PCI Lib directly) */ +#define PCI_FUNC_IO_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_IO) +#define PCI_FUNC_IO_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_IO) +#define PCI_FUNC_IO_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_IO) +#define PCI_FUNC_IO_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_IO) +#define PCI_FUNC_IO_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_IO) +#define PCI_FUNC_IO_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_IO) + +/* PCI Register Access over Memory Space (Little Endian) */ +#define PCI_FUNC_MREG_R8 DRVMGR_RWFUNC(RW_SIZE_1|RW_READ|RW_MEMREG) +#define PCI_FUNC_MREG_R16 DRVMGR_RWFUNC(RW_SIZE_2|RW_READ|RW_MEMREG|RW_LITTLE) +#define PCI_FUNC_MREG_R32 DRVMGR_RWFUNC(RW_SIZE_4|RW_READ|RW_MEMREG|RW_LITTLE) +#define PCI_FUNC_MREG_W8 DRVMGR_RWFUNC(RW_SIZE_1|RW_WRITE|RW_MEMREG) +#define PCI_FUNC_MREG_W16 DRVMGR_RWFUNC(RW_SIZE_2|RW_WRITE|RW_MEMREG|RW_LITTLE) +#define PCI_FUNC_MREG_W32 DRVMGR_RWFUNC(RW_SIZE_4|RW_WRITE|RW_MEMREG|RW_LITTLE) + +/* Weak default PCI driver resources, override this from project configuration + * to set PCI Bus resources used to configure PCI device drivers. + */ +extern struct drvmgr_bus_res pcibus_drv_resources; + +/* Attach a PCI bus on top of a PCI Host device */ +extern int pcibus_register(struct drvmgr_dev *dev, struct pcibus_config *cfg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/cpukit/libpci/preinstall.am b/cpukit/libpci/preinstall.am index b19d28830f..c76282593f 100644 --- a/cpukit/libpci/preinstall.am +++ b/cpukit/libpci/preinstall.am @@ -63,4 +63,13 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/ids_extra.h $(PROJECT_INCLUDE)/pci/irq.h: pci/irq.h $(PROJECT_INCLUDE)/pci/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci/irq.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci/irq.h + +$(PROJECT_INCLUDE)/drvmgr/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE)/drvmgr + @: > $(PROJECT_INCLUDE)/drvmgr/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/drvmgr/$(dirstamp) + +$(PROJECT_INCLUDE)/drvmgr/pci_bus.h: pci_bus.h $(PROJECT_INCLUDE)/drvmgr/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/pci_bus.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/pci_bus.h endif -- cgit v1.2.3