drivers/block/amiflop.c

Source file repositories/reference/linux-study-clean/drivers/block/amiflop.c

File Facts

System
Linux kernel
Corpus path
drivers/block/amiflop.c
Extension
.c
Size
51538 bytes
Lines
1966
Domain
Driver Families
Bucket
drivers/block
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 amiflop_mq_ops = {
	.queue_rq = amiflop_queue_rq,
};

static int fd_alloc_disk(int drive, int system)
{
	struct queue_limits lim = {
		.features		= BLK_FEAT_ROTATIONAL,
	};
	struct gendisk *disk;
	int err;

	disk = blk_mq_alloc_disk(&unit[drive].tag_set, &lim, NULL);
	if (IS_ERR(disk))
		return PTR_ERR(disk);

	disk->major = FLOPPY_MAJOR;
	disk->first_minor = drive + system;
	disk->minors = 1;
	disk->fops = &floppy_fops;
	disk->flags |= GENHD_FL_NO_PART;
	disk->events = DISK_EVENT_MEDIA_CHANGE;
	if (system)
		sprintf(disk->disk_name, "fd%d_msdos", drive);
	else
		sprintf(disk->disk_name, "fd%d", drive);
	disk->private_data = &unit[drive];
	set_capacity(disk, 880 * 2);

	unit[drive].gendisk[system] = disk;
	err = add_disk(disk);
	if (err)
		put_disk(disk);
	return err;
}

static int fd_alloc_drive(int drive)
{
	unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL);
	if (!unit[drive].trackbuf)
		goto out;

	memset(&unit[drive].tag_set, 0, sizeof(unit[drive].tag_set));
	unit[drive].tag_set.ops = &amiflop_mq_ops;
	unit[drive].tag_set.nr_hw_queues = 1;
	unit[drive].tag_set.nr_maps = 1;
	unit[drive].tag_set.queue_depth = 2;
	unit[drive].tag_set.numa_node = NUMA_NO_NODE;
	if (blk_mq_alloc_tag_set(&unit[drive].tag_set))
		goto out_cleanup_trackbuf;

	pr_cont(" fd%d", drive);

	if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1))
		goto out_cleanup_tagset;
	return 0;

out_cleanup_tagset:
	blk_mq_free_tag_set(&unit[drive].tag_set);
out_cleanup_trackbuf:
	kfree(unit[drive].trackbuf);
out:
	unit[drive].type->code = FD_NODRIVE;
	return -ENOMEM;
}

static int __init fd_probe_drives(void)
{
	int drive,drives,nomem;

	pr_info("FD: probing units\nfound");
	drives=0;
	nomem=0;
	for(drive=0;drive<FD_MAX_UNITS;drive++) {
		fd_probe(drive);
		if (unit[drive].type->code == FD_NODRIVE)
			continue;

		if (fd_alloc_drive(drive) < 0) {
			pr_cont(" no mem for fd%d", drive);
			nomem = 1;
			continue;
		}
		drives++;
	}
	if ((drives > 0) || (nomem == 0)) {
		if (drives == 0)
			pr_cont(" no drives");
		pr_cont("\n");
		return drives;

Annotation

Implementation Notes