#include #include #include #include #include "ddekit/assert.h" #include "ddekit/printf.h" #include "ddekit/pci.h" #include "config.h" #define dbg_this 0 /** PCI descriptor */ typedef struct ddekit_pci_dev { struct pci_device *dev; } ddekit_pci_dev_t; typedef struct ddekit_pci_bus { struct { ddekit_pci_dev_t funs[8]; } devs[32]; } ddekit_pci_bus_t; #define MAX_NUM_BUSES 256 static int num_pci_devs; static ddekit_pci_dev_t *ddekit_pci_devs; static ddekit_pci_bus_t *ddekit_pci_buses[MAX_NUM_BUSES]; static inline int invalid_device(ddekit_pci_dev_t *d) { return d->dev == NULL; } /** Initialize DDEKit PCI module. * * \ingroup DDEKit_pci * * This function builds a list of devices by querying L4IO. */ void ddekit_pci_init(void) { int slots_found = 0; int err; struct pci_device *pci_dev; struct pci_device_iterator *dev_iter; err = pci_system_init (); if (err) error (2, err, "pci_system_init"); num_pci_devs = 32; ddekit_pci_devs = malloc (sizeof (ddekit_pci_devs[0]) * num_pci_devs); memset (ddekit_pci_devs, 0, sizeof (ddekit_pci_devs[0]) * num_pci_devs); dev_iter = pci_slot_match_iterator_create (NULL); while ((pci_dev = pci_device_next (dev_iter)) != NULL) { /* store the device in the structured array. */ if (ddekit_pci_buses[pci_dev->bus] == NULL) { ddekit_pci_buses[pci_dev->bus] = calloc (1, sizeof (**ddekit_pci_buses)); assert(ddekit_pci_buses[pci_dev->bus] != NULL); } ddekit_pci_buses[pci_dev->bus]->devs[pci_dev->dev].funs[pci_dev->func].dev = pci_dev; /* We also put the device in the flat array. * The array is increased dynamically. */ if (slots_found >= num_pci_devs) { num_pci_devs *= 2; ddekit_pci_devs = realloc (ddekit_pci_devs, sizeof (ddekit_pci_devs[0]) * num_pci_devs); assert (ddekit_pci_devs != NULL); memset (&ddekit_pci_devs[slots_found], 0, (num_pci_devs - slots_found) * sizeof (ddekit_pci_devs[0])); } ddekit_pci_devs[slots_found].dev = pci_dev; ++slots_found; } num_pci_devs = slots_found; pci_iterator_destroy (dev_iter); } /** * Get PCI device (bus, slot, func) for handle. * * \ingroup DDEKit_pci */ int ddekit_pci_get_device(int nr, int *bus, int *slot, int *func) { ddekit_pci_dev_t *dev; ddekit_printf ("searching for dev #%d", nr); if (nr >= 0 && nr < num_pci_devs && !invalid_device(&ddekit_pci_devs[nr])) { dev = &ddekit_pci_devs[nr]; *bus = dev->dev->bus; *slot = dev->dev->dev; *func = dev->dev->func; return 0; } return -1; } ddekit_pci_dev_t *ddekit_pci_find_device(int *bus, int *slot, int *func, ddekit_pci_dev_t *start) { Assert(bus); Assert(slot); Assert(func); int idx = start ? start->dev->dev + 1 : 0; for ( ; idx < num_pci_devs; ++idx) { ddekit_pci_dev_t *dev = &ddekit_pci_devs[idx]; if (!invalid_device(dev) && (*bus == DDEKIT_PCI_ANY_ID || dev->dev->bus == *bus) && (*slot == DDEKIT_PCI_ANY_ID || dev->dev->dev == *slot) && (*func == DDEKIT_PCI_ANY_ID || dev->dev->func == *func)) { *bus = dev->dev->bus; *slot = dev->dev->dev; *func = dev->dev->func; return dev; } } return NULL; } int ddekit_pci_read(int bus, int slot, int func, int pos, int len, ddekit_uint32_t *val) { switch(len) { case 1: return ddekit_pci_readb(bus, slot, func, pos, (ddekit_uint8_t *)val); case 2: return ddekit_pci_readw(bus, slot, func, pos, (ddekit_uint16_t *)val); case 4: return ddekit_pci_readl(bus, slot, func, pos, val); } return -1; } int ddekit_pci_write(int bus, int slot, int func, int pos, int len, ddekit_uint32_t val) { switch(len) { case 1: return ddekit_pci_writeb(bus, slot, func, pos, val); case 2: return ddekit_pci_writew(bus, slot, func, pos, val); case 4: return ddekit_pci_writel(bus, slot, func, pos, val); } return -1; } /** Find PCI device for a given (bus, slot, func) tuple. * * \ingroup DDEKit_pci * * This function is only used internally by the pci_{read,write}{b,l,w} functions. * It was once called pci_find_device, but this caused confusion with the "real" * find_device() functionality provided by L4IO and the Linux PCI subsystem. */ static inline ddekit_pci_dev_t *ddekit_pci_find_device_fixed(int bus, int slot, int func) { ddekit_pci_dev_t *dev; /* If the bus doesn't exist. */ if (ddekit_pci_buses[bus] == NULL) return NULL; dev = &ddekit_pci_buses[bus]->devs[slot].funs[func]; if (dev && dev->dev) return dev; return NULL; } int ddekit_pci_readb (int bus, int slot, int func, int pos, ddekit_uint8_t *val) { ddekit_pci_dev_t *dev = ddekit_pci_find_device_fixed(bus, slot, func); if (dev) return pci_device_cfg_read_u8 (dev->dev, val, pos); else return -1; } int ddekit_pci_readw (int bus, int slot, int func, int pos, ddekit_uint16_t *val) { ddekit_pci_dev_t *dev = ddekit_pci_find_device_fixed(bus, slot, func); if (dev) return pci_device_cfg_read_u16 (dev->dev, val, pos); else return -1; } int ddekit_pci_readl (int bus, int slot, int func, int pos, ddekit_uint32_t *val) { ddekit_pci_dev_t *dev = ddekit_pci_find_device_fixed(bus, slot, func); if (dev) { assert (dev->dev != NULL); return pci_device_cfg_read_u32 (dev->dev, val, pos); } else return -1; } int ddekit_pci_writeb(int bus, int slot, int func, int pos, ddekit_uint8_t val) { ddekit_pci_dev_t *dev = ddekit_pci_find_device_fixed(bus, slot, func); if (dev) return pci_device_cfg_write_u8 (dev->dev, val, pos); else return -1; } int ddekit_pci_writew(int bus, int slot, int func, int pos, ddekit_uint16_t val) { ddekit_pci_dev_t *dev = ddekit_pci_find_device_fixed(bus, slot, func); if (dev) return pci_device_cfg_write_u16 (dev->dev, val, pos); else return -1; } int ddekit_pci_writel(int bus, int slot, int func, int pos, ddekit_uint32_t val) { ddekit_pci_dev_t *dev = ddekit_pci_find_device_fixed(bus, slot, func); if (dev) return pci_device_cfg_write_u32 (dev->dev, val, pos); else return -1; } int ddekit_pci_enable_device(struct ddekit_pci_dev *dev) { pci_device_enable (dev->dev); return 0; } int ddekit_pci_disable_device(struct ddekit_pci_dev *dev) { // TODO return -1; } /******************************************************************************** ** Accessor functions for the various kinds of information that are available ** ** from struct l4io_pci_dev (which is not handed through to the DDEs, because ** ** it still contains L4 types). ** ********************************************************************************/ /** * Get PCI device vendor ID. * * \param dev device * * \ingroup DDEKit_pci */ unsigned short ddekit_pci_get_vendor(struct ddekit_pci_dev *dev) { return dev->dev->vendor_id; } /** * Get PCI device ID. * * \param dev device * * \ingroup DDEKit_pci */ unsigned short ddekit_pci_get_device_id(struct ddekit_pci_dev *dev) { return dev->dev->device_id; } /** * Get PCI device subvendor ID. * * \param dev device * * \ingroup DDEKit_pci */ unsigned short ddekit_pci_get_sub_vendor(struct ddekit_pci_dev *dev) { return dev->dev->subvendor_id; } /** * Get PCI device subdevice ID. * * \param dev device * * \ingroup DDEKit_pci */ unsigned short ddekit_pci_get_sub_device(struct ddekit_pci_dev *dev) { return dev->dev->subdevice_id; } /** * Get PCI device class ID. * * \param dev device * * \ingroup DDEKit_pci */ unsigned ddekit_pci_get_dev_class(struct ddekit_pci_dev *dev) { return dev->dev->device_class; } /** * Get PCI device IRQ number. * * \param dev device * * \ingroup DDEKit_pci */ unsigned long ddekit_pci_get_irq(struct ddekit_pci_dev *dev) { return dev->dev->irq; } /** * Get PCI device name. * * \param dev device * * \ingroup DDEKit_pci */ char *ddekit_pci_get_name(struct ddekit_pci_dev *dev) { // TODO return NULL; } /** * Get PCI device slot name. * * \param dev device * * \ingroup DDEKit_pci */ char *ddekit_pci_get_slot_name(struct ddekit_pci_dev *dev) { // TODO return NULL; } /** * Get PCI device resource at index. * * \param dev device * \param idx resource index * * \ingroup DDEKit_pci */ ddekit_pci_res_t *ddekit_pci_get_resource(struct ddekit_pci_dev *dev, unsigned int idx) { // TODO // if (idx > L4IO_PCIDEV_RES) return NULL; // return (ddekit_pci_res_t *)(&(dev->l4dev.res[idx])); } /** * Set PCI bus mastering for device. * * \ingroup DDEKit_pci */ void ddekit_pci_set_master(struct ddekit_pci_dev *dev) { //TODO l4io_pci_set_master(dev->l4dev.handle); } int ddekit_pci_irq_enable(int bus, int slot, int func, int pin, int *irq) { return 0; }