drivers/block/floppy.c

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

File Facts

System
Linux kernel
Corpus path
drivers/block/floppy.c
Extension
.c
Size
137024 bytes
Lines
5028
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 floppy_mq_ops = {
	.queue_rq = floppy_queue_rq,
};

static struct platform_device floppy_device[N_DRIVE];
static bool registered[N_DRIVE];

static bool floppy_available(int drive)
{
	if (!(allowed_drive_mask & (1 << drive)))
		return false;
	if (fdc_state[FDC(drive)].version == FDC_NONE)
		return false;
	return true;
}

static int floppy_alloc_disk(unsigned int drive, unsigned int type)
{
	struct queue_limits lim = {
		.max_hw_sectors		= 64,
		.features		= BLK_FEAT_ROTATIONAL,
	};
	struct gendisk *disk;

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

	disk->major = FLOPPY_MAJOR;
	disk->first_minor = TOMINOR(drive) | (type << 2);
	disk->minors = 1;
	disk->fops = &floppy_fops;
	disk->flags |= GENHD_FL_NO_PART;
	disk->events = DISK_EVENT_MEDIA_CHANGE;
	if (type)
		sprintf(disk->disk_name, "fd%d_type%d", drive, type);
	else
		sprintf(disk->disk_name, "fd%d", drive);
	/* to be cleaned up... */
	disk->private_data = (void *)(long)drive;
	disk->flags |= GENHD_FL_REMOVABLE;

	disks[drive][type] = disk;
	return 0;
}

static DEFINE_MUTEX(floppy_probe_lock);

static void floppy_probe(dev_t dev)
{
	unsigned int drive = (MINOR(dev) & 3) | ((MINOR(dev) & 0x80) >> 5);
	unsigned int type = (MINOR(dev) >> 2) & 0x1f;

	if (drive >= N_DRIVE || !floppy_available(drive) ||
	    type >= ARRAY_SIZE(floppy_type))
		return;

	mutex_lock(&floppy_probe_lock);
	if (disks[drive][type])
		goto out;
	if (floppy_alloc_disk(drive, type))
		goto out;
	if (add_disk(disks[drive][type]))
		goto cleanup_disk;
out:
	mutex_unlock(&floppy_probe_lock);
	return;

cleanup_disk:
	put_disk(disks[drive][type]);
	disks[drive][type] = NULL;
	mutex_unlock(&floppy_probe_lock);
}

static int __init do_floppy_init(void)
{
	int i, unit, drive, err;

	set_debugt();
	interruptjiffies = resultjiffies = jiffies;

#if defined(CONFIG_PPC)
	if (check_legacy_ioport(FDC1))
		return -ENODEV;
#endif

	raw_cmd = NULL;

	floppy_wq = alloc_ordered_workqueue("floppy", 0);
	if (!floppy_wq)

Annotation

Implementation Notes