drivers/char/xilinx_hwicap/xilinx_hwicap.c

Source file repositories/reference/linux-study-clean/drivers/char/xilinx_hwicap/xilinx_hwicap.c

File Facts

System
Linux kernel
Corpus path
drivers/char/xilinx_hwicap/xilinx_hwicap.c
Extension
.c
Size
20215 bytes
Lines
794
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations hwicap_fops = {
	.owner = THIS_MODULE,
	.write = hwicap_write,
	.read = hwicap_read,
	.open = hwicap_open,
	.release = hwicap_release,
	.llseek = noop_llseek,
};

static int hwicap_setup(struct platform_device *pdev, int id,
		const struct hwicap_driver_config *config,
		const struct config_registers *config_regs)
{
	dev_t devt;
	struct hwicap_drvdata *drvdata = NULL;
	struct device *dev = &pdev->dev;
	int retval;

	dev_info(dev, "Xilinx icap port driver\n");

	mutex_lock(&icap_sem);

	if (id < 0) {
		for (id = 0; id < HWICAP_DEVICES; id++)
			if (!probed_devices[id])
				break;
	}
	if (id < 0 || id >= HWICAP_DEVICES) {
		mutex_unlock(&icap_sem);
		dev_err(dev, "%s%i too large\n", DRIVER_NAME, id);
		return -EINVAL;
	}
	if (probed_devices[id]) {
		mutex_unlock(&icap_sem);
		dev_err(dev, "cannot assign to %s%i; it is already in use\n",
			DRIVER_NAME, id);
		return -EBUSY;
	}

	probed_devices[id] = 1;
	mutex_unlock(&icap_sem);

	devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR + id);

	drvdata = devm_kzalloc(dev, sizeof(struct hwicap_drvdata), GFP_KERNEL);
	if (!drvdata) {
		retval = -ENOMEM;
		goto failed;
	}
	dev_set_drvdata(dev, drvdata);

	drvdata->base_address = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(drvdata->base_address)) {
		retval = PTR_ERR(drvdata->base_address);
		goto failed;
	}

	drvdata->devt = devt;
	drvdata->dev = dev;
	drvdata->config = config;
	drvdata->config_regs = config_regs;

	mutex_init(&drvdata->sem);
	drvdata->is_open = 0;

	cdev_init(&drvdata->cdev, &hwicap_fops);
	drvdata->cdev.owner = THIS_MODULE;
	retval = cdev_add(&drvdata->cdev, devt, 1);
	if (retval) {
		dev_err(dev, "cdev_add() failed\n");
		goto failed;
	}

	device_create(&icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
	return 0;		/* success */

 failed:
	mutex_lock(&icap_sem);
	probed_devices[id] = 0;
	mutex_unlock(&icap_sem);

	return retval;
}

static struct hwicap_driver_config buffer_icap_config = {
	.get_configuration = buffer_icap_get_configuration,
	.set_configuration = buffer_icap_set_configuration,
	.get_status = buffer_icap_get_status,
	.reset = buffer_icap_reset,
};

Annotation

Implementation Notes