drivers/staging/vme_user/vme_user.c

Source file repositories/reference/linux-study-clean/drivers/staging/vme_user/vme_user.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/vme_user/vme_user.c
Extension
.c
Size
19854 bytes
Lines
791
Domain
Driver Families
Bucket
drivers/staging
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 vme_user_fops = {
	.read = vme_user_read,
	.write = vme_user_write,
	.llseek = vme_user_llseek,
	.unlocked_ioctl = vme_user_unlocked_ioctl,
	.compat_ioctl = compat_ptr_ioctl,
	.mmap_prepare = vme_user_mmap_prepare,
};

static int vme_user_match(struct vme_dev *vdev)
{
	int i;

	int cur_bus = vme_bus_num(vdev);
	int cur_slot = vme_slot_num(vdev);

	for (i = 0; i < bus_num; i++)
		if ((cur_bus == bus[i]) && (cur_slot == vdev->num))
			return 1;

	return 0;
}

/*
 * In this simple access driver, the old behaviour is being preserved as much
 * as practical. We will therefore reserve the buffers and request the images
 * here so that we don't have to do it later.
 */
static int vme_user_probe(struct vme_dev *vdev)
{
	int i, err;
	char *name;

	/* Save pointer to the bridge device */
	if (vme_user_bridge) {
		dev_err(&vdev->dev, "Driver can only be loaded for 1 device\n");
		err = -EINVAL;
		goto err_dev;
	}
	vme_user_bridge = vdev;

	/* Initialise descriptors */
	for (i = 0; i < VME_DEVS; i++) {
		image[i].kern_buf = NULL;
		image[i].pci_buf = 0;
		mutex_init(&image[i].mutex);
		image[i].device = NULL;
		image[i].resource = NULL;
	}

	/* Assign major and minor numbers for the driver */
	err = register_chrdev_region(MKDEV(VME_MAJOR, 0), VME_DEVS, DRIVER_NAME);
	if (err) {
		dev_warn(&vdev->dev, "Error getting Major Number %d for driver.\n",
			 VME_MAJOR);
		goto err_region;
	}

	/* Register the driver as a char device */
	vme_user_cdev = cdev_alloc();
	if (!vme_user_cdev) {
		err = -ENOMEM;
		goto err_char;
	}
	vme_user_cdev->ops = &vme_user_fops;
	vme_user_cdev->owner = THIS_MODULE;
	err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS);
	if (err)
		goto err_class;

	/* Request slave resources and allocate buffers (128kB wide) */
	for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
		/* XXX Need to properly request attributes */
		/* For ca91cx42 bridge there are only two slave windows
		 * supporting A16 addressing, so we request A24 supported
		 * by all windows.
		 */
		image[i].resource = vme_slave_request(vme_user_bridge,
						      VME_A24, VME_SCT);
		if (!image[i].resource) {
			dev_warn(&vdev->dev,
				 "Unable to allocate slave resource\n");
			err = -ENOMEM;
			goto err_slave;
		}
		image[i].size_buf = PCI_BUF_SIZE;
		image[i].kern_buf = vme_alloc_consistent(image[i].resource,
							 image[i].size_buf,
							 &image[i].pci_buf);
		if (!image[i].kern_buf) {

Annotation

Implementation Notes