drivers/block/swim.c

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

File Facts

System
Linux kernel
Corpus path
drivers/block/swim.c
Extension
.c
Size
20062 bytes
Lines
971
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 swim_mq_ops = {
	.queue_rq = swim_queue_rq,
};

static void swim_cleanup_floppy_disk(struct floppy_state *fs)
{
	struct gendisk *disk = fs->disk;

	if (!disk)
		return;

	if (fs->registered)
		del_gendisk(fs->disk);

	put_disk(disk);
	blk_mq_free_tag_set(&fs->tag_set);
}

static int swim_floppy_init(struct swim_priv *swd)
{
	struct queue_limits lim = {
		.features		= BLK_FEAT_ROTATIONAL,
	};
	int err;
	int drive;
	struct swim __iomem *base = swd->base;

	/* scan floppy drives */

	swim_drive(base, INTERNAL_DRIVE);
	if (swim_readbit(base, DRIVE_PRESENT) &&
	    !swim_readbit(base, ONEMEG_DRIVE))
		swim_add_floppy(swd, INTERNAL_DRIVE);
	swim_drive(base, EXTERNAL_DRIVE);
	if (swim_readbit(base, DRIVE_PRESENT) &&
	    !swim_readbit(base, ONEMEG_DRIVE))
		swim_add_floppy(swd, EXTERNAL_DRIVE);

	/* register floppy drives */

	err = register_blkdev(FLOPPY_MAJOR, "fd");
	if (err) {
		printk(KERN_ERR "Unable to get major %d for SWIM floppy\n",
		       FLOPPY_MAJOR);
		return -EBUSY;
	}

	spin_lock_init(&swd->lock);

	for (drive = 0; drive < swd->floppy_count; drive++) {
		err = blk_mq_alloc_sq_tag_set(&swd->unit[drive].tag_set,
				&swim_mq_ops, 2, 0);
		if (err)
			goto exit_put_disks;

		swd->unit[drive].disk =
			blk_mq_alloc_disk(&swd->unit[drive].tag_set, &lim,
					  &swd->unit[drive]);
		if (IS_ERR(swd->unit[drive].disk)) {
			blk_mq_free_tag_set(&swd->unit[drive].tag_set);
			err = PTR_ERR(swd->unit[drive].disk);
			goto exit_put_disks;
		}

		swd->unit[drive].swd = swd;
	}

	for (drive = 0; drive < swd->floppy_count; drive++) {
		swd->unit[drive].disk->flags = GENHD_FL_REMOVABLE;
		swd->unit[drive].disk->major = FLOPPY_MAJOR;
		swd->unit[drive].disk->first_minor = drive;
		swd->unit[drive].disk->minors = 1;
		sprintf(swd->unit[drive].disk->disk_name, "fd%d", drive);
		swd->unit[drive].disk->fops = &floppy_fops;
		swd->unit[drive].disk->flags |= GENHD_FL_NO_PART;
		swd->unit[drive].disk->events = DISK_EVENT_MEDIA_CHANGE;
		swd->unit[drive].disk->private_data = &swd->unit[drive];
		set_capacity(swd->unit[drive].disk, 2880);
		err = add_disk(swd->unit[drive].disk);
		if (err)
			goto exit_put_disks;
		swd->unit[drive].registered = true;
	}

	return 0;

exit_put_disks:
	unregister_blkdev(FLOPPY_MAJOR, "fd");
	do {
		swim_cleanup_floppy_disk(&swd->unit[drive]);

Annotation

Implementation Notes