drivers/cdrom/gdrom.c

Source file repositories/reference/linux-study-clean/drivers/cdrom/gdrom.c

File Facts

System
Linux kernel
Corpus path
drivers/cdrom/gdrom.c
Extension
.c
Size
22381 bytes
Lines
882
Domain
Driver Families
Bucket
drivers/cdrom
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 blk_mq_ops gdrom_mq_ops = {
	.queue_rq	= gdrom_queue_rq,
};

/*
 * register this as a block device and as compliant with the
 * universal CD Rom driver interface
 */
static int probe_gdrom(struct platform_device *devptr)
{
	struct queue_limits lim = {
		.logical_block_size		= GDROM_HARD_SECTOR,
		/* using DMA so memory will need to be contiguous */
		.max_segments			= 1,
		/* set a large max size to get most from DMA */
		.max_segment_size		= 0x40000,
		.features			= BLK_FEAT_ROTATIONAL,
	};
	int err;

	/*
	 * Ensure our "one" device is initialized properly in case of previous
	 * usages of it
	 */
	memset(&gd, 0, sizeof(gd));

	/* Start the device */
	if (gdrom_execute_diagnostic() != 1) {
		pr_warn("ATA Probe for GDROM failed\n");
		return -ENODEV;
	}
	/* Print out firmware ID */
	if (gdrom_outputversion())
		return -ENOMEM;
	/* Register GDROM */
	gdrom_major = register_blkdev(0, GDROM_DEV_NAME);
	if (gdrom_major <= 0)
		return gdrom_major;
	pr_info("Registered with major number %d\n",
		gdrom_major);
	/* Specify basic properties of drive */
	gd.cd_info = kzalloc_obj(struct cdrom_device_info);
	if (!gd.cd_info) {
		err = -ENOMEM;
		goto probe_fail_no_mem;
	}
	probe_gdrom_setupcd();

	err = blk_mq_alloc_sq_tag_set(&gd.tag_set, &gdrom_mq_ops, 1,
				BLK_MQ_F_BLOCKING);
	if (err)
		goto probe_fail_free_cd_info;

	gd.disk = blk_mq_alloc_disk(&gd.tag_set, &lim, NULL);
	if (IS_ERR(gd.disk)) {
		err = PTR_ERR(gd.disk);
		goto probe_fail_free_tag_set;
	}
	gd.gdrom_rq = gd.disk->queue;
	probe_gdrom_setupdisk();
	if (register_cdrom(gd.disk, gd.cd_info)) {
		err = -ENODEV;
		goto probe_fail_cleanup_disk;
	}
	gd.disk->fops = &gdrom_bdops;
	gd.disk->events = DISK_EVENT_MEDIA_CHANGE;
	/* latch on to the interrupt */
	err = gdrom_set_interrupt_handlers();
	if (err)
		goto probe_fail_cleanup_disk;

	err = probe_gdrom_setupqueue();
	if (err)
		goto probe_fail_free_irqs;

	gd.toc = kzalloc_obj(struct gdromtoc);
	if (!gd.toc) {
		err = -ENOMEM;
		goto probe_fail_free_irqs;
	}
	err = add_disk(gd.disk);
	if (err)
		goto probe_fail_add_disk;

	return 0;

probe_fail_add_disk:
	kfree(gd.toc);
probe_fail_free_irqs:
	free_irq(HW_EVENT_GDROM_DMA, &gd);

Annotation

Implementation Notes