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.
- 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/slab.hlinux/fd.hlinux/hdreg.hlinux/delay.hlinux/init.hlinux/major.hlinux/mutex.hlinux/fs.hlinux/blk-mq.hlinux/interrupt.hlinux/platform_device.hasm/setup.hlinux/uaccess.hasm/amigahw.hasm/amigaints.hasm/irq.h
Detected Declarations
struct fd_data_typestruct fd_drive_typestruct amiga_floppy_structstruct headerstruct dos_headerfunction ms_isrfunction ms_delayfunction try_fdcfunction get_fdcfunction rel_fdcfunction fd_selectfunction fd_deselectfunction motor_on_callbackfunction fd_motor_onfunction fd_motor_offfunction floppy_offfunction fd_calibratefunction fd_seekfunction fd_get_drive_idfunction everyfunction fd_block_donefunction raw_readfunction raw_writefunction post_writefunction post_write_callbackfunction scan_syncfunction checksumfunction decodefunction amiga_readfunction encodefunction encode_blockfunction amiga_writefunction dos_crcfunction dos_hdr_crcfunction dos_data_crcfunction dos_decode_bytefunction dos_decodefunction dbgfunction dos_readfunction dos_encode_bytefunction dos_encode_blockfunction dos_writefunction stufffunction non_int_flush_trackfunction get_trackfunction amiflop_rw_cur_segmentfunction amiflop_queue_rqfunction fd_getgeo
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
- Immediate include surface: `linux/module.h`, `linux/slab.h`, `linux/fd.h`, `linux/hdreg.h`, `linux/delay.h`, `linux/init.h`, `linux/major.h`, `linux/mutex.h`.
- Detected declarations: `struct fd_data_type`, `struct fd_drive_type`, `struct amiga_floppy_struct`, `struct header`, `struct dos_header`, `function ms_isr`, `function ms_delay`, `function try_fdc`, `function get_fdc`, `function rel_fdc`.
- Atlas domain: Driver Families / drivers/block.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.