in sdk/linux_kernel_drivers/xdma/xdma_cdev.c [285:388]
static int create_xcdev(struct xdma_pci_dev *xpdev, struct xdma_cdev *xcdev,
int bar, struct xdma_engine *engine,
enum cdev_type type)
{
int rv;
int minor;
struct xdma_dev *xdev = xpdev->xdev;
dev_t dev;
spin_lock_init(&xcdev->lock);
/* new instance? */
if (!xpdev->major) {
/* allocate a dynamically allocated char device node */
int rv = alloc_chrdev_region(&dev, XDMA_MINOR_BASE,
XDMA_MINOR_COUNT, XDMA_NODE_NAME);
if (rv) {
pr_err("unable to allocate cdev region %d.\n", rv);
return rv;
}
xpdev->major = MAJOR(dev);
}
/*
* do not register yet, create kobjects and name them,
*/
xcdev->magic = MAGIC_CHAR;
xcdev->cdev.owner = THIS_MODULE;
xcdev->xpdev = xpdev;
xcdev->xdev = xdev;
xcdev->engine = engine;
xcdev->bar = bar;
rv = config_kobject(xcdev, type);
if (rv < 0)
return rv;
switch (type) {
case CHAR_USER:
case CHAR_CTRL:
/* minor number is type index for non-SGDMA interfaces */
minor = type;
cdev_ctrl_init(xcdev);
break;
case CHAR_XVC:
/* minor number is type index for non-SGDMA interfaces */
minor = type;
cdev_xvc_init(xcdev);
break;
case CHAR_XDMA_H2C:
minor = 32 + engine->channel;
cdev_sgdma_init(xcdev);
break;
case CHAR_XDMA_C2H:
minor = 36 + engine->channel;
cdev_sgdma_init(xcdev);
break;
case CHAR_EVENTS:
minor = 10 + bar;
cdev_event_init(xcdev);
break;
case CHAR_BYPASS_H2C:
minor = 64 + engine->channel;
cdev_bypass_init(xcdev);
break;
case CHAR_BYPASS_C2H:
minor = 68 + engine->channel;
cdev_bypass_init(xcdev);
break;
case CHAR_BYPASS:
minor = 100;
cdev_bypass_init(xcdev);
break;
default:
pr_info("type 0x%x NOT supported.\n", type);
return -EINVAL;
}
xcdev->cdevno = MKDEV(xpdev->major, minor);
/* bring character device live */
rv = cdev_add(&xcdev->cdev, xcdev->cdevno, 1);
if (rv < 0) {
pr_err("cdev_add failed %d, type 0x%x.\n", rv, type);
goto unregister_region;
}
dbg_init("xcdev 0x%p, %u:%u, %s, type 0x%x.\n",
xcdev, xpdev->major, minor, xcdev->cdev.kobj.name, type);
/* create device on our class */
if (g_xdma_class) {
rv = create_sys_device(xcdev, type);
if (rv < 0)
goto del_cdev;
}
return 0;
del_cdev:
cdev_del(&xcdev->cdev);
unregister_region:
unregister_chrdev_region(xcdev->cdevno, XDMA_MINOR_COUNT);
return rv;
}