Commit f2169730 authored by Jens Korinth's avatar Jens Korinth
Browse files

WIP: remove tlkm_device_inst and superfluous abstractions

* several changes: tlkm_device contains all device data directly
* tlkm_class contains information relevant to a class of devices
  (e.g., pcie/zynq)
* classes are automatically enumerated at start, only access type
  is checked in create (device instances remain until unloaded)
* added micro-API for status core base queries
parent 4edda0dd
......@@ -15,13 +15,13 @@ tlkm-objs := \
tlkm/tlkm.o \
tlkm/tlkm_ioctl.o \
tlkm/tlkm_device.o \
tlkm/tlkm_status.o \
device/tlkm_perfc.o \
device/tlkm_perfc_miscdev.o \
device/tlkm_control.o \
device/tlkm_device_rw.o \
device/tlkm_device_ioctl.o \
device/tlkm_device_mmap.o \
zynq/zynq_enumerate.o \
zynq/zynq_device.o \
zynq/zynq_ioctl.o \
zynq/zynq_dmamgmt.o \
......
......@@ -21,12 +21,6 @@ struct tlkm_device *device_from_file(struct file *fp)
return tlkm_bus_get_device(c->dev_id);
}
static
struct tlkm_device_inst *device_inst_from_file(struct file *fp)
{
return device_from_file(fp)->inst;
}
long tlkm_device_ioctl_info(struct file *fp, unsigned int ioctl,
struct tlkm_device_info __user *info)
{
......@@ -61,6 +55,6 @@ long tlkm_device_ioctl(struct file *fp, unsigned int ioctl, unsigned long data)
} else {
tlkm_device_ioctl_f ioctl_f = device_from_file(fp)->ioctl;
BUG_ON(!ioctl_f);
return ioctl_f(device_inst_from_file(fp), ioctl, data);
return ioctl_f(device_from_file(fp), ioctl, data);
}
}
......@@ -18,5 +18,5 @@ int tlkm_device_mmap(struct file *fp, struct vm_area_struct *vm)
if (! mmap_f) {
DEVWRN(d->dev_id, "device has no mmap() implementation, register accesses are likely slow!");
}
return mmap_f ? mmap_f(d->inst, vm) : -ENXIO;
return mmap_f ? mmap_f(d, vm) : -ENXIO;
}
......@@ -37,8 +37,8 @@ inline static
dev_id_t get_dev_id_from_file(struct file *file)
{
struct miscdevice *dev = (struct miscdevice *)file->private_data;
struct tlkm_device_inst *inst = container_of(dev,
struct tlkm_device_inst, perfc_dev);
struct tlkm_device *inst = container_of(dev,
struct tlkm_device, perfc_dev);
return inst->dev_id;
}
......@@ -73,7 +73,7 @@ const struct file_operations tlkm_perfc_miscdev_fops = {
.read = tlkm_perfc_miscdev_read,
};
int tlkm_perfc_miscdev_init(struct tlkm_device_inst *dev)
int tlkm_perfc_miscdev_init(struct tlkm_device *dev)
{
int ret = 0;
char fn[256];
......@@ -90,7 +90,7 @@ int tlkm_perfc_miscdev_init(struct tlkm_device_inst *dev)
return 0;
}
void tlkm_perfc_miscdev_exit(struct tlkm_device_inst *dev)
void tlkm_perfc_miscdev_exit(struct tlkm_device *dev)
{
misc_deregister(&dev->perfc_dev);
kfree(dev->perfc_dev.name);
......
......@@ -27,8 +27,8 @@
#include "tlkm_device.h"
int tlkm_perfc_miscdev_init(struct tlkm_device_inst *dev);
void tlkm_perfc_miscdev_exit(struct tlkm_device_inst *dev);
int tlkm_perfc_miscdev_init(struct tlkm_device *dev);
void tlkm_perfc_miscdev_exit(struct tlkm_device *dev);
#else /* NPERFC */
......
......@@ -82,12 +82,11 @@ err_dma_bufs:
void tlkm_dma_exit(struct dma_engine *dma)
{
int i;
dev_id_t dev_id = dma->dev_id;
for (i = 0; i < TLKM_DMA_BUFS; ++i)
kfree(dma->dma_buf[i]);
iounmap(dma->regs);
memset(dma, 0, sizeof(*dma));
DEVLOG(dev_id, TLKM_LF_DMA, "deinitialized DMA engine");
DEVLOG(dma->dev_id, TLKM_LF_DMA, "deinitialized DMA engine");
}
ssize_t tlkm_dma_copy_to(struct dma_engine *dma, dev_addr_t dev_addr, const void __user *usr_addr, size_t len)
......
......@@ -17,7 +17,7 @@ static struct pci_driver tlkm_pcie_driver = {
.remove = tlkm_pcie_remove,
};
int pcie_init()
int pcie_init(struct tlkm_class *cls)
{
int err = 0;
LOG(TLKM_LF_PCIE, "registering TLKM PCIe driver ...");
......@@ -27,7 +27,7 @@ int pcie_init()
return 0;
}
void pcie_deinit()
void pcie_exit(struct tlkm_class *cls)
{
pci_unregister_driver(&tlkm_pcie_driver);
LOG(TLKM_LF_PCIE, "deregistered TLKM PCIe driver");
......
#ifndef PCIE_H__
#define PCIE_H__
#include "tlkm_class.h"
#include "pcie/pcie_device.h"
#define TLKM_PCI_NAME "tlkm"
#define XILINX_VENDOR_ID 0x10EE
#define XILINX_DEVICE_ID 0x7038
int pcie_init(void);
void pcie_deinit(void);
int pcie_init(struct tlkm_class *cls);
void pcie_exit(struct tlkm_class *cls);
static const
struct tlkm_class pcie_cls = {
.name = TLKM_PCI_NAME,
.create = pcie_device_create,
.destroy = pcie_device_destroy,
.probe = pcie_init,
.remove = pcie_exit,
.status_base = 0x02800000ULL,
.npirqs = 4,
.private_data = NULL,
};
#endif /* PCIE_H__ */
......@@ -13,28 +13,11 @@
#include "tlkm_bus.h"
#define TLKM_DEV_ID(pdev) \
(((struct tlkm_pcie_device *)dev_get_drvdata(&(pdev)->dev))->dev_id)
(((struct tlkm_pcie_device *)dev_get_drvdata(&(pdev)->dev))->parent->dev_id)
static size_t num_devices = 0;
ssize_t pcie_enumerate(void) { return num_devices; }
static struct tlkm_device devices[PLATFORM_MAX_DEVS];
static int tlkm_pcie_init(struct tlkm_device_inst *d) { return 0; }
static void tlkm_pcie_exit(struct tlkm_device_inst *d) {}
static struct tlkm_device tlkm_pcie_dev = {
.device = LIST_HEAD_INIT(tlkm_pcie_dev.device),
.vendor_id = XILINX_VENDOR_ID,
.product_id = XILINX_DEVICE_ID,
.status_base = 0x02800000ULL,
.name = TLKM_PCI_NAME,
.init = tlkm_pcie_init,
.exit = tlkm_pcie_exit,
.pirq = pcie_irqs_request_platform_irq,
.rirq = pcie_irqs_release_platform_irq,
};
/**
* @brief Enables pcie-device and claims/remaps neccessary bar resources
* @param pdev Pointer to pci-device, which should be allocated
......@@ -44,11 +27,15 @@ static int claim_device(struct pci_dev *pdev)
{
int err = 0;
struct tlkm_pcie_device *pci_data;
struct tlkm_device *dev = tlkm_bus_new_device((struct tlkm_class *)&pcie_cls,
TLKM_PCI_NAME,
XILINX_VENDOR_ID,
XILINX_DEVICE_ID);
/* wake up the pci device */
err = pci_enable_device(pdev);
if (err) {
WRN("failed to enable PCIe-device: %d", err);
DEVWRN(dev->dev_id, "failed to enable PCIe-device: %d", err);
goto error_pci_en;
}
......@@ -58,19 +45,13 @@ static int claim_device(struct pci_dev *pdev)
/* setup BAR memory regions */
err = pci_request_regions(pdev, TLKM_PCI_NAME);
if (err) {
WRN("failed to setup bar regions for pci device %d", err);
DEVWRN(dev->dev_id, "failed to setup bar regions for pci device %d", err);
goto error_pci_req;
}
pci_data = (struct tlkm_pcie_device *)dev_get_drvdata(&pdev->dev);
if (! pci_data) {
pci_data = (struct tlkm_pcie_device *)kzalloc(sizeof(*pci_data), GFP_KERNEL);
if (! pci_data) {
ERR("could not allocate private PCI data struct");
goto error_pci_req;
}
dev_set_drvdata(&pdev->dev, pci_data);
}
pci_data = (struct tlkm_pcie_device *)dev->private_data;
BUG_ON(! pci_data);
dev_set_drvdata(&pdev->dev, pci_data);
/* read out pci bar 0 settings */
pci_data->pdev = pdev;
......@@ -89,14 +70,11 @@ static int claim_device(struct pci_dev *pdev)
}
LOG(TLKM_LF_PCIE, "remapped bar 0 address: 0x%08llx", (u64)pci_data->kvirt_addr_bar0);
tlkm_pcie_dev.base_offset = pci_data->phy_addr_bar0;
LOG(TLKM_LF_PCIE, "status core base: 0x%08llx", (u64)tlkm_pcie_dev.status_base);
dev->base_offset = pci_data->phy_addr_bar0;
LOG(TLKM_LF_PCIE, "status core base: 0x%08llx", (u64)pcie_cls.status_base);
tlkm_bus_add_device(&tlkm_pcie_dev);
pci_data->dev_id = tlkm_pcie_dev.dev_id;
devices[pci_data->dev_id] = tlkm_pcie_dev;
tlkm_perfc_link_speed_set(pci_data->dev_id, pci_data->link_speed);
tlkm_perfc_link_width_set(pci_data->dev_id, pci_data->link_width);
tlkm_perfc_link_speed_set(dev->dev_id, pci_data->link_speed);
tlkm_perfc_link_width_set(dev->dev_id, pci_data->link_width);
num_devices++;
return 0;
......@@ -155,7 +133,7 @@ static int claim_msi(struct pci_dev *pdev)
struct tlkm_pcie_device *pci_data = (struct tlkm_pcie_device *)dev_get_drvdata(&pdev->dev);
dev_id_t id;
BUG_ON(! pci_data);
id = pci_data->dev_id;
id = TLKM_DEV_ID(pdev);
for (i = 0; i < REQUIRED_INTERRUPTS; i++) {
pci_data->irq_mapping[i] = -1;
......@@ -199,7 +177,7 @@ static void report_link_status(struct pci_dev *pdev)
int gts = 0;
BUG_ON(! dev);
id = dev->dev_id;
id = TLKM_DEV_ID(pdev);
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &ctrl_reg);
dev->link_width = (ctrl_reg & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
......@@ -231,22 +209,8 @@ int tlkm_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
report_link_status(pdev);
if (0/*char_dma_register()*/) {
DEVLOG(TLKM_DEV_ID(pdev), TLKM_LF_PCIE, "could not register dma char device(s)");
goto error_cannot_configure;
}
if (0/*char_user_register()*/) {
DEVLOG(TLKM_DEV_ID(pdev), TLKM_LF_PCIE, "could not register user char device(s)");
goto error_user_register;
}
return 0;
//char_user_unregister();
error_user_register:
//char_dma_unregister();
error_cannot_configure:
release_device(pdev);
error_no_device:
......@@ -256,8 +220,6 @@ error_no_device:
void tlkm_pcie_remove(struct pci_dev *pdev)
{
DEVLOG(TLKM_DEV_ID(pdev), TLKM_LF_PCIE, "unload pcie-device");
//char_dma_unregister();
//char_user_unregister();
pcie_irqs_deinit(pdev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
pci_disable_msix(pdev);
......@@ -266,3 +228,23 @@ void tlkm_pcie_remove(struct pci_dev *pdev)
#endif
release_device(pdev);
}
int pcie_device_create(struct tlkm_device *dev)
{
struct tlkm_pcie_device *pdev;
BUG_ON(! dev);
pdev = (struct tlkm_pcie_device *)kzalloc(sizeof(*pdev), GFP_KERNEL);
pdev->parent = dev;
dev->private_data = pdev;
return 0;
}
void pcie_device_destroy(struct tlkm_device *dev)
{
BUG_ON(! dev);
if (dev->private_data) {
kfree(dev->private_data);
dev->private_data = NULL;
}
}
......@@ -31,25 +31,24 @@
int tlkm_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id);
void tlkm_pcie_remove(struct pci_dev *pdev);
int pcie_device_create(struct tlkm_device *dev);
void pcie_device_destroy(struct tlkm_device *dev);
/* struct to hold data related to the pcie device */
struct tlkm_pcie_device {
dev_id_t dev_id;
struct tlkm_device *parent;
struct pci_dev *pdev;
u64 phy_addr_bar0;
u64 phy_len_bar0;
u64 phy_flags_bar0;
u64 phy_addr_bar2;
u64 phy_len_bar2;
u64 phy_flags_bar2;
int irq_mapping[REQUIRED_INTERRUPTS];
void *kvirt_addr_bar0;
void *kvirt_addr_bar2;
int irq_mapping[REQUIRED_INTERRUPTS];
int link_width;
int link_speed;
struct work_struct irq_work[TLKM_SLOT_INTERRUPTS];
struct tlkm_control *ctrl;
};
ssize_t pcie_enumerate(void);
ssize_t pcie_device_probe(struct tlkm_class *cls);
#endif // PCIE_DEVICE_H__
......@@ -13,8 +13,8 @@
void tlkm_pcie_slot_irq_work_ ## nr(struct work_struct *work) \
{ \
struct tlkm_pcie_device *dev = (struct tlkm_pcie_device *)atomic_long_read(&work->data); \
BUG_ON(! dev->ctrl); \
tlkm_control_signal_slot_interrupt(dev->ctrl, nr); \
BUG_ON(! dev->parent->ctrl); \
tlkm_control_signal_slot_interrupt(dev->parent->ctrl, nr); \
} \
\
irqreturn_t tlkm_pcie_slot_irq_ ## nr(int irq, void *dev_id) \
......@@ -37,7 +37,7 @@ int pcie_irqs_init(struct pci_dev *pdev)
struct tlkm_pcie_device *dev = (struct tlkm_pcie_device *)dev_get_drvdata(&pdev->dev);
int ret = 0, irqn, err[n];
BUG_ON(! dev);
DEVLOG(dev->dev_id, TLKM_LF_PCIE, "registering %zu interrupts ...", n);
DEVLOG(dev->parent->dev_id, TLKM_LF_PCIE, "registering %zu interrupts ...", n);
#define _INTR(nr) \
irqn = nr + TLKM_PLATFORM_INTERRUPTS; \
if ((err[nr] = request_irq(pci_irq_vector(pdev, irqn), \
......@@ -45,12 +45,12 @@ int pcie_irqs_init(struct pci_dev *pdev)
IRQF_EARLY_RESUME, \
TLKM_PCI_NAME, \
pdev))) { \
DEVERR(dev->dev_id, "could not request interrupt %d: %d", irqn, err[nr]); \
DEVERR(dev->parent->dev_id, "could not request interrupt %d: %d", irqn, err[nr]); \
goto irq_error; \
} else { \
dev->irq_mapping[irqn] = pci_irq_vector(pdev, irqn); \
DEVLOG(dev->dev_id, TLKM_LF_PCIE, "created mapping from interrupt %d -> %d", irqn, dev->irq_mapping[irqn]); \
DEVLOG(dev->dev_id, TLKM_LF_PCIE, "interrupt line %d/%d assigned with return value %d", \
DEVLOG(dev->parent->dev_id, TLKM_LF_PCIE, "created mapping from interrupt %d -> %d", irqn, dev->irq_mapping[irqn]); \
DEVLOG(dev->parent->dev_id, TLKM_LF_PCIE, "interrupt line %d/%d assigned with return value %d", \
irqn, pci_irq_vector(pdev, irqn), err[nr]); \
INIT_WORK(&dev->irq_work[nr], tlkm_pcie_slot_irq_work_ ## nr); \
atomic_long_set(&dev->irq_work[nr].data, (long)dev); \
......@@ -81,7 +81,7 @@ void pcie_irqs_deinit(struct pci_dev *pdev)
#define _INTR(nr) \
irqn = nr + TLKM_PLATFORM_INTERRUPTS; \
if (dev->irq_mapping[irqn] != -1) { \
DEVLOG(dev->dev_id, TLKM_LF_PCIE, "freeing interrupt %d with mappping %d", irqn, dev->irq_mapping[irqn]); \
DEVLOG(dev->parent->dev_id, TLKM_LF_PCIE, "freeing interrupt %d with mappping %d", irqn, dev->irq_mapping[irqn]); \
free_irq(dev->irq_mapping[irqn], pdev); \
dev->irq_mapping[irqn] = -1; \
}
......@@ -97,12 +97,14 @@ void pcie_irqs_deinit(struct pci_dev *pdev)
int pcie_irqs_request_platform_irq(struct tlkm_device *dev, int irq_no, irqreturn_t (*intr_handler)(int, void *))
{
int err = 0;
struct tlkm_pcie_device *pdev = (struct tlkm_pcie_device *)dev->inst->private_data;
struct tlkm_pcie_device *pdev = (struct tlkm_pcie_device *)dev->private_data;
BUG_ON(! pdev);
if (irq_no >= TLKM_PLATFORM_INTERRUPTS) {
DEVERR(dev->dev_id, "invalid platform interrupt number: %d (must be < %d)", irq_no, TLKM_PLATFORM_INTERRUPTS);
return -ENXIO;
}
BUG_ON(! pdev->pdev);
DEVLOG(dev->dev_id, TLKM_LF_IRQ, "requesting platform irq #%d", irq_no);
if ((err = request_irq(pci_irq_vector(pdev->pdev, irq_no),
intr_handler,
......@@ -121,7 +123,7 @@ int pcie_irqs_request_platform_irq(struct tlkm_device *dev, int irq_no, irqretur
void pcie_irqs_release_platform_irq(struct tlkm_device *dev, int irq_no)
{
struct tlkm_pcie_device *pdev = (struct tlkm_pcie_device *)dev->inst->private_data;
struct tlkm_pcie_device *pdev = (struct tlkm_pcie_device *)dev->private_data;
if (irq_no >= TLKM_PLATFORM_INTERRUPTS) {
DEVERR(dev->dev_id, "invalid platform interrupt number: %d (must be < %d)", irq_no, TLKM_PLATFORM_INTERRUPTS);
return;
......
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/perf_event.h>
#include "tlkm_bus.h"
#include "tlkm_class.h"
#include "tlkm.h"
#include "tlkm_bus.h"
#include "tlkm_logging.h"
#include "zynq/zynq_enumerate.h"
#include "pcie/pcie.h"
#include "zynq/zynq.h"
#include "pcie/pcie_device.h"
static DEFINE_MUTEX(_tlkm_bus_mtx);
static
struct tlkm_bus {
struct list_head devices;
......@@ -17,58 +24,92 @@ struct tlkm_bus {
.num_devs = 0,
};
static struct tlkm_class *const _tlkm_class[] = {
(struct tlkm_class *)&zynq_cls,
(struct tlkm_class *)&pcie_cls,
};
static
void tlkm_bus_add_device(struct tlkm_device *pdev)
{
mutex_lock(&_tlkm_bus_mtx);
list_add(&pdev->device, &_tlkm_bus.devices);
pdev->dev_id = _tlkm_bus.num_devs++;
mutex_unlock(&_tlkm_bus_mtx);
LOG(TLKM_LF_BUS, "added device '%s' to bus", pdev->name);
}
static
void tlkm_bus_del_device(struct tlkm_device *pdev)
{
mutex_lock(&_tlkm_bus_mtx);
list_del(&_tlkm_bus.devices);
--_tlkm_bus.num_devs;
mutex_unlock(&_tlkm_bus_mtx);
LOG(TLKM_LF_BUS, "removed device '%s' from bus", pdev->name);
}
struct tlkm_device *tlkm_bus_new_device(struct tlkm_class *cls, const char *name, int vendor_id, int product_id)
{
int ret = 0;
struct tlkm_device *dev = (struct tlkm_device *)kzalloc(sizeof(*dev), GFP_KERNEL);
if (dev) {
strncpy(dev->name, name, sizeof(dev->name));
dev->vendor_id = vendor_id;
dev->product_id = product_id;
dev->cls = cls;
tlkm_bus_add_device(dev);
if ((ret = tlkm_device_init(dev))) {
DEVERR(dev->dev_id, "could not initialize device: %d", ret);
tlkm_bus_delete_device(dev);
return NULL;
}
mutex_init(&dev->mtx);
return dev;
}
ERR("could not allocate new tlkm_device");
return NULL;
}
void tlkm_bus_delete_device(struct tlkm_device *dev)
{
if (dev) {
tlkm_bus_del_device(dev);
kfree(dev);
}
}
ssize_t tlkm_bus_enumerate(void)
{
return zynq_enumerate() + pcie_enumerate();
int i;
ssize_t ret = 0;
for (i = 0; i < sizeof(_tlkm_class)/sizeof(*_tlkm_class); ++i) {
ssize_t r = _tlkm_class[i]->probe(_tlkm_class[i]);
if (r < 0)
ERR("error occurred while probing class '%s': %zd", _tlkm_class[i]->name, r);
else
ret += r;
}
return ret;
}
int tlkm_bus_init(void)
{
int ret = 0;
ssize_t n;
struct list_head *lh;
LOG(TLKM_LF_BUS, "registering drivers ...");
if ((ret = pcie_init())) {
ERR("error while registering PCIe driver: %d", ret);
return ret;
}
LOG(TLKM_LF_BUS, "detecting TaPaSCo devices ...");
n = tlkm_bus_enumerate();
if (n < 0) {
ERR("could not detect devices, error: %zd", n);
pcie_deinit();
return n;
}
if (! n) {
ERR("did not find any TaPaSCo devices, cannot proceed");
pcie_deinit();
return -ENXIO;
}
LOG(TLKM_LF_BUS, "found %zd TaPaSCo devices", n);
list_for_each(lh, &_tlkm_bus.devices) {
struct tlkm_device *d = container_of(lh, struct tlkm_device,
device);
LOG(TLKM_LF_BUS, "TaPaSCo device '%s' (%04x:%04x)", d->name,
d->vendor_id, d->product_id);
tlkm_device_create(d, TLKM_ACCESS_MONITOR);
}
if ((ret = tlkm_init())) {
ERR("failed to initialize ioctl file: %d", ret);
pcie_deinit();
ERR("failed to initialize main ioctl file: %d", ret);
}
return ret;
}
......@@ -76,14 +117,17 @@ int tlkm_bus_init(void)
void tlkm_bus_exit(void)
{
struct list_head *lh;
list_for_each(lh, &_tlkm_bus.devices) {
struct tlkm_device *d = container_of(lh, struct tlkm_device,
device);
struct list_head *tmp;
int i;
list_for_each_safe(lh, tmp, &_tlkm_bus.devices) {
struct tlkm_device *d = container_of(lh, struct tlkm_device, device);
LOG(TLKM_LF_BUS, "TaPaSCo device '%s' (%04x:%04x)", d->name,
d->vendor_id, d->product_id);
tlkm_device_remove_all(d);
if (d->cls->destroy)
d->cls->destroy(d);
}
pcie_deinit();
for (i = 0; i < sizeof(_tlkm_class)/sizeof(*_tlkm_class); ++i)
_tlkm_class[i]->remove(_tlkm_class[i]);
tlkm_exit();
LOG(TLKM_LF_BUS, "removed TaPaSCo interfaces, bye");
}
......
......@@ -4,28 +4,17 @@
#include "tlkm_device.h"
struct tlkm_bus;
struct tlkm_class;
int tlkm_bus_init(void);
int tlkm_bus_init(void);
void tlkm_bus_exit(void);
ssize_t tlkm_bus_enumerate(void);
struct tlkm_device *tlkm_bus_new_device(struct tlkm_class *cls, const char *name, int vendor_id, int product_id);
void tlkm_bus_delete_device(struct tlkm_device *dev);
void tlkm_bus_add_device(struct tlkm_device *pdev);
void tlkm_bus_del_device(struct tlkm_device *pdev);
ssize_t tlkm_bus_enumerate(void);
size_t tlkm_bus_num_devices(void);
struct tlkm_device *tlkm_bus_get_device(size_t idx);
inline static
int tlkm_bus_create_device(dev_id_t dev_id, tlkm_access_t access)
{
return tlkm_device_create(tlkm_bus_get_device(dev_id), access);
}
inline static
void tlkm_bus_destroy_device(dev_id_t dev_id, tlkm_access_t access)
{
tlkm_device_destroy(tlkm_bus_get_device(dev_id), access);
}
#endif /* TLKM_BUS_H__ */
#ifndef TLKM_CLASS_H__
#define TLKM_CLASS_H__
#include "tlkm_device.h"
#define TLKM_CLASS_NAME_LEN 32
typedef int (*tlkm_class_create_f)(struct tlkm_device *);
typedef void(*tlkm_class_destroy_f)(struct tlkm_device *);
typedef int (*tlkm_class_probe_f)(struct tlkm_class *);
typedef void(*tlkm_class_remove_f)(struct tlkm_class *);
struct tlkm_class {
char name[TLKM_CLASS_NAME_LEN];
tlkm_class_create_f create;
tlkm_class_destroy_f destroy;
tlkm_class_probe_f probe;
tlkm_class_remove_f remove;
dev_addr_t status_base; /* physical offset of status core in bitstream */
size_t npirqs; /* number of platform interrupts */
void *private_data;
};