static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE];
+static struct gendisk disks[N_DRIVE];
+static char names[N_DRIVE][4];
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/*
}
UDRS->fd_device = minor(inode->i_rdev);
+ set_capacity(&disks[drive], floppy_sizes[minor(inode->i_rdev)]);
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive)
buffer_track = -1;
poll_drive(0, FD_RAW_NEED_DISK);
process_fd_request();
}
+ set_capacity(&disks[drive], floppy_sizes[minor(dev)]);
return 0;
}
bus_id: "03?0",
};
+static struct gendisk *floppy_find(int minor)
+{
+ int drive = (minor&3) | ((minor&0x80) >> 5);
+ if (drive >= N_DRIVE ||
+ !(allowed_drive_mask & (1 << drive)) ||
+ fdc_state[FDC(drive)].version == FDC_NONE)
+ return NULL;
+ return &disks[drive];
+}
+
int __init floppy_init(void)
{
int i,unit,drive;
return -EBUSY;
}
+ for (i=0; i<N_DRIVE; i++) {
+ disks[i].major = MAJOR_NR;
+ disks[i].first_minor = TOMINOR(i);
+ disks[i].fops = &floppy_fops;
+ sprintf(names[i], "fd%d", i);
+ disks[i].major_name = names[i];
+ }
+
+ blk_set_probe(MAJOR_NR, floppy_find);
+
for (i=0; i<256; i++)
if (ITYPE(i))
floppy_sizes[i] = (floppy_type[ITYPE(i)].size+1) >> 1;
else
floppy_sizes[i] = MAX_DISK_SIZE;
- blk_size[MAJOR_NR] = floppy_sizes;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_fd_request, &floppy_lock);
reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
config_types();
unregister_blkdev(MAJOR_NR,"fd");
del_timer(&fd_timeout);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ blk_set_probe(MAJOR_NR, NULL);
return -ENODEV;
}
#if N_FDC > 1
del_timer(&fd_timeout);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR,"fd");
+ blk_set_probe(MAJOR_NR, NULL);
return -EBUSY;
}
floppy_release_irq_and_dma();
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR,"fd");
+ blk_set_probe(MAJOR_NR, NULL);
}
for (drive = 0; drive < N_DRIVE; drive++) {
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue;
- for (i = 0; i<NUMBER(floppy_type); i++)
- register_disk(NULL, mk_kdev(MAJOR_NR,TOMINOR(drive)+i*4),
- 1, &floppy_fops, 0);
+ add_disk(disks + drive);
}
register_sys_device(&device_floppy);
void cleanup_module(void)
{
- int dummy;
+ int i;
unregister_sys_device(&device_floppy);
devfs_unregister (devfs_handle);
unregister_blkdev(MAJOR_NR, "fd");
+ blk_set_probe(MAJOR_NR, NULL);
+ for (drive = 0; drive < N_DRIVE; drive++) {
+ if ((allowed_drive_mask & (1 << drive)) &&
+ fdc_state[FDC(drive)].version != FDC_NONE)
+ del_gendisk(disks + drive);
+ }
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
/* eject disk, if any */
- dummy = fd_eject(0);
+ fd_eject(0);
}
MODULE_PARM(floppy,"s");
*/
static struct gendisk *gendisk_head;
+/*
+ * TEMPORARY KLUDGE.
+ */
+static struct {
+ struct list_head list;
+ struct gendisk *(*get)(int minor);
+} gendisks[MAX_BLKDEV];
+
+void blk_set_probe(int major, struct gendisk *(p)(int))
+{
+ write_lock(&gendisk_lock);
+ gendisks[major].get = p;
+ write_unlock(&gendisk_lock);
+}
+EXPORT_SYMBOL(blk_set_probe); /* Will go away */
+
+
/**
* add_gendisk - add partitioning information to kernel list
* @gp: per-device partitioning information
*/
static void add_gendisk(struct gendisk *gp)
{
- struct gendisk *sgp;
struct hd_struct *p = NULL;
if (gp->minor_shift) {
gp->part = p;
write_lock(&gendisk_lock);
-
- /*
- * In 2.5 this will go away. Fix the drivers who rely on
- * old behaviour.
- */
-
- for (sgp = gendisk_head; sgp; sgp = sgp->next)
- {
- if (sgp == gp)
- {
- printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
- sgp->major);
- goto out;
- }
- }
+ list_add(&gp->list, &gendisks[gp->major].list);
gp->next = gendisk_head;
gendisk_head = gp;
-out:
write_unlock(&gendisk_lock);
}
break;
if (*p)
*p = (*p)->next;
+ list_del_init(&disk->list);
write_unlock(&gendisk_lock);
}
struct gendisk *
get_gendisk(kdev_t dev)
{
- struct gendisk *gp = NULL;
+ struct gendisk *disk;
+ struct list_head *p;
int major = major(dev);
int minor = minor(dev);
read_lock(&gendisk_lock);
- for (gp = gendisk_head; gp; gp = gp->next) {
- if (gp->major != major)
- continue;
- if (gp->first_minor > minor)
+ if (gendisks[major].get) {
+ disk = gendisks[major].get(minor);
+ read_unlock(&gendisk_lock);
+ return disk;
+ }
+ list_for_each(p, &gendisks[major].list) {
+ disk = list_entry(p, struct gendisk, list);
+ if (disk->first_minor > minor)
continue;
- if (gp->first_minor + (1<<gp->minor_shift) <= minor)
+ if (disk->first_minor + (1<<disk->minor_shift) <= minor)
continue;
read_unlock(&gendisk_lock);
- return gp;
+ return disk;
}
read_unlock(&gendisk_lock);
return NULL;
int __init device_init(void)
{
+ int i;
rwlock_init(&gendisk_lock);
+ for (i = 0; i < MAX_BLKDEV; i++)
+ INIT_LIST_HEAD(&gendisks[i].list);
blk_dev_init();
#ifdef CONFIG_FC4_SOC
/* This has to be done before scsi_dev_init */