return 0;
}
-/* Forwarding functions to generic routines. */
-static
-int ide_cdrom_ioctl (ide_drive_t *drive,
- struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct cdrom_info *info = drive->driver_data;
-
- return cdrom_ioctl(&info->devinfo, inode, cmd, arg);
-}
-
-static
-int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- int rc = -ENOMEM;
-
- MOD_INC_USE_COUNT;
- if (!info->buffer)
- info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
- if (!info->buffer || (rc = cdrom_open(&info->devinfo, ip, fp))) {
- drive->usage--;
- MOD_DEC_USE_COUNT;
- }
- return rc;
-}
-
-static
-void ide_cdrom_release (struct inode *inode, struct file *file,
- ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- cdrom_release (&info->devinfo, file);
- MOD_DEC_USE_COUNT;
-}
-
-static
-int ide_cdrom_check_media_change (ide_drive_t *drive)
-{
- struct cdrom_info *info = drive->driver_data;
- return cdrom_media_changed(&info->devinfo);
-}
-
-static
-void ide_cdrom_revalidate (ide_drive_t *drive)
-{
- struct request_sense sense;
- cdrom_read_toc(drive, &sense);
-}
-
static
unsigned long ide_cdrom_capacity (ide_drive_t *drive)
{
kfree(info);
drive->driver_data = NULL;
del_gendisk(g);
+ g->fops = ide_fops;
return 0;
}
#endif
.supports_dsc_overlap = 1,
.cleanup = ide_cdrom_cleanup,
- .standby = NULL,
- .suspend = NULL,
- .resume = NULL,
- .flushcache = NULL,
.do_request = ide_do_rw_cdrom,
- .end_request = NULL,
.sense = ide_cdrom_dump_status,
.error = ide_cdrom_error,
- .ioctl = ide_cdrom_ioctl,
- .open = ide_cdrom_open,
- .release = ide_cdrom_release,
- .media_change = ide_cdrom_check_media_change,
- .revalidate = ide_cdrom_revalidate,
- .pre_reset = NULL,
.capacity = ide_cdrom_capacity,
- .special = NULL,
- .proc = NULL,
.attach = ide_cdrom_attach,
- .ata_prebuilder = NULL,
- .atapi_prebuilder = NULL,
.drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
};
+static int idecd_open(struct inode * inode, struct file * file)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct cdrom_info *info = drive->driver_data;
+ int rc = -ENOMEM;
+ drive->usage++;
+
+ if (!info->buffer)
+ info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
+ if (!info->buffer || (rc = cdrom_open(&info->devinfo, inode, file)))
+ drive->usage--;
+ return rc;
+}
+
+static int idecd_release(struct inode * inode, struct file * file)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ struct cdrom_info *info = drive->driver_data;
+
+ cdrom_release (&info->devinfo, file);
+ drive->usage--;
+ return 0;
+}
+
+static int idecd_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
+ int err = generic_ide_ioctl(bdev, cmd, arg);
+ if (err == -EINVAL) {
+ struct cdrom_info *info = drive->driver_data;
+ err = cdrom_ioctl(&info->devinfo, inode, cmd, arg);
+ }
+ return err;
+}
+
+static int idecd_media_changed(struct gendisk *disk)
+{
+ ide_drive_t *drive = disk->private_data;
+ struct cdrom_info *info = drive->driver_data;
+ return cdrom_media_changed(&info->devinfo);
+}
+
+static int idecd_revalidate_disk(struct gendisk *disk)
+{
+ ide_drive_t *drive = disk->private_data;
+ struct request_sense sense;
+ cdrom_read_toc(drive, &sense);
+ return 0;
+}
+
+static struct block_device_operations idecd_ops = {
+ .owner = THIS_MODULE,
+ .open = idecd_open,
+ .release = idecd_release,
+ .ioctl = idecd_ioctl,
+ .media_changed = idecd_media_changed,
+ .revalidate_disk= idecd_revalidate_disk
+};
+
/* options */
char *ignore = NULL;
DRIVER(drive)->busy--;
cdrom_read_toc(drive, &sense);
+ g->fops = &idecd_ops;
add_disk(g);
return 0;
failed:
#endif /* CONFIG_IDE_TASKFILE_IO */
-static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- MOD_INC_USE_COUNT;
- if (drive->removable && drive->usage == 1) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
- args.command_type = ide_cmd_type_parser(&args);
- check_disk_change(inode->i_bdev);
- /*
- * Ignore the return code from door_lock,
- * since the open() has already succeeded,
- * and the door_lock is irrelevant at this point.
- */
- if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
- drive->doorlocking = 0;
- }
- return 0;
-}
-
static int do_idedisk_flushcache(ide_drive_t *drive);
-static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- if (drive->removable && !drive->usage) {
- ide_task_t args;
- memset(&args, 0, sizeof(ide_task_t));
- args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
- args.command_type = ide_cmd_type_parser(&args);
- invalidate_bdev(inode->i_bdev, 0);
- if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
- drive->doorlocking = 0;
- }
- if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
- if (do_idedisk_flushcache(drive))
- printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
- drive->name);
- MOD_DEC_USE_COUNT;
-}
-
-static int idedisk_media_change (ide_drive_t *drive)
-{
- /* if removable, always assume it was changed */
- return drive->removable;
-}
-
-static void idedisk_revalidate (ide_drive_t *drive)
-{
- ide_revalidate_drive(drive);
-}
-
static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
{
ide_hwif_t *hwif = HWIF(drive);
#endif
}
-
-/* This is just a hook for the overall driver tree.
- */
-
-static int idedisk_ioctl (ide_drive_t *drive, struct inode *inode,
- struct file *file, unsigned int cmd, unsigned long arg)
-{
-#if 0
-HDIO_GET_ADDRESS
-HDIO_SET_ADDRESS
-HDIO_GET_WCACHE
-HDIO_SET_WCACHE
-HDIO_GET_ACOUSTIC
-HDIO_SET_ACOUSTIC
-HDIO_GET_MULTCOUNT
-HDIO_SET_MULTCOUNT
-HDIO_GET_NOWERR
-HDIO_SET_NOWERR
-#endif
- return -EINVAL;
-}
-
static void idedisk_setup (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
if (ide_unregister_subdriver(drive))
return 1;
del_gendisk(g);
+ g->fops = ide_fops;
return 0;
}
.resume = do_idedisk_resume,
.flushcache = do_idedisk_flushcache,
.do_request = do_rw_disk,
- .end_request = NULL,
.sense = idedisk_dump_status,
.error = idedisk_error,
- .ioctl = idedisk_ioctl,
- .open = idedisk_open,
- .release = idedisk_release,
- .media_change = idedisk_media_change,
- .revalidate = idedisk_revalidate,
.pre_reset = idedisk_pre_reset,
.capacity = idedisk_capacity,
.special = idedisk_special,
.proc = idedisk_proc,
.attach = idedisk_attach,
- .ata_prebuilder = NULL,
- .atapi_prebuilder = NULL,
.drives = LIST_HEAD_INIT(idedisk_driver.drives),
};
+static int idedisk_open(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ drive->usage++;
+ if (drive->removable && drive->usage == 1) {
+ ide_task_t args;
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
+ args.command_type = ide_cmd_type_parser(&args);
+ check_disk_change(inode->i_bdev);
+ /*
+ * Ignore the return code from door_lock,
+ * since the open() has already succeeded,
+ * and the door_lock is irrelevant at this point.
+ */
+ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
+ drive->doorlocking = 0;
+ }
+ return 0;
+}
+
+static int idedisk_release(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ if (drive->removable && drive->usage == 1) {
+ ide_task_t args;
+ memset(&args, 0, sizeof(ide_task_t));
+ args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
+ args.command_type = ide_cmd_type_parser(&args);
+ invalidate_bdev(inode->i_bdev, 0);
+ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
+ drive->doorlocking = 0;
+ }
+ if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
+ if (do_idedisk_flushcache(drive))
+ printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
+ drive->name);
+ drive->usage--;
+ return 0;
+}
+
+static int idedisk_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ return generic_ide_ioctl(bdev, cmd, arg);
+}
+
+static int idedisk_media_changed(struct gendisk *disk)
+{
+ ide_drive_t *drive = disk->private_data;
+ /* if removable, always assume it was changed */
+ return drive->removable;
+}
+
+static int idedisk_revalidate_disk(struct gendisk *disk)
+{
+ ide_drive_t *drive = disk->private_data;
+ set_capacity(disk, current_capacity(drive));
+ return 0;
+}
+
+static struct block_device_operations idedisk_ops = {
+ .owner = THIS_MODULE,
+ .open = idedisk_open,
+ .release = idedisk_release,
+ .ioctl = idedisk_ioctl,
+ .media_changed = idedisk_media_changed,
+ .revalidate_disk= idedisk_revalidate_disk
+};
+
MODULE_DESCRIPTION("ATA DISK Driver");
static int idedisk_attach(ide_drive_t *drive)
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
g->flags |= GENHD_FL_DEVFS;
set_capacity(g, current_capacity(drive));
+ g->fops = &idedisk_ops;
add_disk(g);
return 0;
failed:
**
*/
-static int idefloppy_get_format_capacities (ide_drive_t *drive,
- struct inode *inode,
- struct file *file,
- int *arg) /* Cheater */
+static int idefloppy_get_format_capacities(ide_drive_t *drive, int *arg)
{
idefloppy_pc_t pc;
idefloppy_capacity_header_t *header;
** 0x01 - verify media after format.
*/
-static int idefloppy_begin_format(ide_drive_t *drive,
- struct inode *inode,
- struct file *file,
- int *arg)
+static int idefloppy_begin_format(ide_drive_t *drive, int *arg)
{
int blocks;
int length;
** the dsc bit, and return either 0 or 65536.
*/
-static int idefloppy_get_format_progress(ide_drive_t *drive,
- struct inode *inode,
- struct file *file,
- int *arg)
+static int idefloppy_get_format_progress(ide_drive_t *drive, int *arg)
{
idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_pc_t pc;
return (0);
}
-/*
- * Our special ide-floppy ioctl's.
- *
- * Currently there aren't any ioctl's.
- */
-static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- idefloppy_pc_t pc;
- idefloppy_floppy_t *floppy = drive->driver_data;
- int prevent = (arg) ? 1 : 0;
-
- switch (cmd) {
- case CDROMEJECT:
- prevent = 0;
- /* fall through */
- case CDROM_LOCKDOOR:
- if (drive->usage > 1)
- return -EBUSY;
-
- /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
- idefloppy_create_prevent_cmd(&pc, prevent);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
- if (cmd == CDROMEJECT) {
- idefloppy_create_start_stop_cmd(&pc, 2);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
- return 0;
- case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
- return (0);
- case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
- return (idefloppy_get_format_capacities(drive, inode, file,
- (int *)arg));
- case IDEFLOPPY_IOCTL_FORMAT_START:
-
- if (!(file->f_mode & 2))
- return (-EPERM);
-
- {
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- if (drive->usage > 1) {
- /* Don't format if someone is using the disk */
-
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
- &floppy->flags);
- return -EBUSY;
- } else {
- int rc;
-
- set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
- &floppy->flags);
-
- rc=idefloppy_begin_format(drive, inode,
- file,
- (int *)arg);
-
- if (rc)
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
- &floppy->flags);
- return (rc);
-
- /*
- ** Note, the bit will be cleared when the device is
- ** closed. This is the cleanest way to handle the
- ** situation where the drive does not support
- ** format progress reporting.
- */
- }
- }
- case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
- return (idefloppy_get_format_progress(drive, inode, file,
- (int *)arg));
- }
- return -EINVAL;
-}
-
-/*
- * Our open/release functions
- */
-static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
- idefloppy_pc_t pc;
-
-#if IDEFLOPPY_DEBUG_LOG
- printk(KERN_INFO "Reached idefloppy_open\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
-
- MOD_INC_USE_COUNT;
- if (drive->usage == 1) {
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
- /* Just in case */
-
- idefloppy_create_test_unit_ready_cmd(&pc);
- if (idefloppy_queue_pc_tail(drive, &pc)) {
- idefloppy_create_start_stop_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
-
- if (idefloppy_get_capacity (drive)
- && (filp->f_flags & O_NDELAY) == 0
- /*
- ** Allow O_NDELAY to open a drive without a disk, or with
- ** an unreadable disk, so that we can get the format
- ** capacity of the drive or begin the format - Sam
- */
- ) {
- drive->usage--;
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
-
- if (floppy->wp && (filp->f_mode & 2)) {
- drive->usage--;
- MOD_DEC_USE_COUNT;
- return -EROFS;
- }
- set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
- idefloppy_create_prevent_cmd(&pc, 1);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
- check_disk_change(inode->i_bdev);
- } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
- drive->usage--;
- MOD_DEC_USE_COUNT;
- return -EBUSY;
- }
- return 0;
-}
-
-static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- idefloppy_pc_t pc;
-
-#if IDEFLOPPY_DEBUG_LOG
- printk (KERN_INFO "Reached idefloppy_release\n");
-#endif /* IDEFLOPPY_DEBUG_LOG */
-
- if (!drive->usage) {
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- /* IOMEGA Clik! drives do not support lock/unlock commands */
- if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
- idefloppy_create_prevent_cmd(&pc, 0);
- (void) idefloppy_queue_pc_tail(drive, &pc);
- }
-
- clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
- }
- MOD_DEC_USE_COUNT;
-}
-
-/*
- * Check media change. Use a simple algorithm for now.
- */
-static int idefloppy_media_change (ide_drive_t *drive)
-{
- idefloppy_floppy_t *floppy = drive->driver_data;
-
- return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
-}
-
-/*
- * Revalidate the new media. Should set blk_size[]
- */
-static void idefloppy_revalidate (ide_drive_t *drive)
-{
- ide_revalidate_drive(drive);
-}
-
/*
* Return the current floppy capacity to ide.c.
*/
drive->driver_data = NULL;
kfree(floppy);
del_gendisk(g);
+ g->fops = ide_fops;
return 0;
}
#endif
.supports_dsc_overlap = 0,
.cleanup = idefloppy_cleanup,
- .standby = NULL,
- .suspend = NULL,
- .resume = NULL,
- .flushcache = NULL,
.do_request = idefloppy_do_request,
.end_request = idefloppy_do_end_request,
- .sense = NULL,
- .error = NULL,
- .ioctl = idefloppy_ioctl,
- .open = idefloppy_open,
- .release = idefloppy_release,
- .media_change = idefloppy_media_change,
- .revalidate = idefloppy_revalidate,
- .pre_reset = NULL,
.capacity = idefloppy_capacity,
- .special = NULL,
.proc = idefloppy_proc,
.attach = idefloppy_attach,
- .ata_prebuilder = NULL,
- .atapi_prebuilder = NULL,
.drives = LIST_HEAD_INIT(idefloppy_driver.drives),
};
+static int idefloppy_open(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ idefloppy_pc_t pc;
+
+ drive->usage++;
+
+#if IDEFLOPPY_DEBUG_LOG
+ printk(KERN_INFO "Reached idefloppy_open\n");
+#endif /* IDEFLOPPY_DEBUG_LOG */
+
+ if (drive->usage == 1) {
+ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+ /* Just in case */
+
+ idefloppy_create_test_unit_ready_cmd(&pc);
+ if (idefloppy_queue_pc_tail(drive, &pc)) {
+ idefloppy_create_start_stop_cmd(&pc, 1);
+ (void) idefloppy_queue_pc_tail(drive, &pc);
+ }
+
+ if (idefloppy_get_capacity (drive)
+ && (filp->f_flags & O_NDELAY) == 0
+ /*
+ ** Allow O_NDELAY to open a drive without a disk, or with
+ ** an unreadable disk, so that we can get the format
+ ** capacity of the drive or begin the format - Sam
+ */
+ ) {
+ drive->usage--;
+ return -EIO;
+ }
+
+ if (floppy->wp && (filp->f_mode & 2)) {
+ drive->usage--;
+ return -EROFS;
+ }
+ set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+ idefloppy_create_prevent_cmd(&pc, 1);
+ (void) idefloppy_queue_pc_tail(drive, &pc);
+ }
+ check_disk_change(inode->i_bdev);
+ } else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
+ drive->usage--;
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int idefloppy_release(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ idefloppy_pc_t pc;
+
+#if IDEFLOPPY_DEBUG_LOG
+ printk (KERN_INFO "Reached idefloppy_release\n");
+#endif /* IDEFLOPPY_DEBUG_LOG */
+
+ if (drive->usage == 1) {
+ idefloppy_floppy_t *floppy = drive->driver_data;
+
+ /* IOMEGA Clik! drives do not support lock/unlock commands */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+ idefloppy_create_prevent_cmd(&pc, 0);
+ (void) idefloppy_queue_pc_tail(drive, &pc);
+ }
+
+ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+ }
+ drive->usage--;
+ return 0;
+}
+
+static int idefloppy_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+ int err = generic_ide_ioctl(bdev, cmd, arg);
+ int prevent = (arg) ? 1 : 0;
+ idefloppy_pc_t pc;
+ if (err != -EINVAL)
+ return err;
+
+ switch (cmd) {
+ case CDROMEJECT:
+ prevent = 0;
+ /* fall through */
+ case CDROM_LOCKDOOR:
+ if (drive->usage > 1)
+ return -EBUSY;
+
+ /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
+ if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+ idefloppy_create_prevent_cmd(&pc, prevent);
+ (void) idefloppy_queue_pc_tail(drive, &pc);
+ }
+ if (cmd == CDROMEJECT) {
+ idefloppy_create_start_stop_cmd(&pc, 2);
+ (void) idefloppy_queue_pc_tail(drive, &pc);
+ }
+ return 0;
+ case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
+ return 0;
+ case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
+ return idefloppy_get_format_capacities(drive, (int *)arg);
+ case IDEFLOPPY_IOCTL_FORMAT_START:
+
+ if (!(file->f_mode & 2))
+ return -EPERM;
+
+ if (drive->usage > 1) {
+ /* Don't format if someone is using the disk */
+
+ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
+ &floppy->flags);
+ return -EBUSY;
+ }
+
+ set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+
+ err = idefloppy_begin_format(drive, (int *)arg);
+ if (err)
+ clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+ return err;
+ /*
+ ** Note, the bit will be cleared when the device is
+ ** closed. This is the cleanest way to handle the
+ ** situation where the drive does not support
+ ** format progress reporting.
+ */
+ case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
+ return idefloppy_get_format_progress(drive, (int *)arg);
+ }
+ return -EINVAL;
+}
+
+static int idefloppy_media_changed(struct gendisk *disk)
+{
+ ide_drive_t *drive = disk->private_data;
+ idefloppy_floppy_t *floppy = drive->driver_data;
+
+ return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
+}
+
+static int idefloppy_revalidate_disk(struct gendisk *disk)
+{
+ ide_drive_t *drive = disk->private_data;
+ set_capacity(disk, current_capacity(drive));
+ return 0;
+}
+
+static struct block_device_operations idefloppy_ops = {
+ .owner = THIS_MODULE,
+ .open = idefloppy_open,
+ .release = idefloppy_release,
+ .ioctl = idefloppy_ioctl,
+ .media_changed = idefloppy_media_changed,
+ .revalidate_disk= idefloppy_revalidate_disk
+};
+
static int idefloppy_attach (ide_drive_t *drive)
{
idefloppy_floppy_t *floppy;
g->de = drive->de;
g->flags = drive->removable ? GENHD_FL_REMOVABLE : 0;
g->flags |= GENHD_FL_DEVFS;
+ g->fops = &idefloppy_ops;
add_disk(g);
return 0;
failed:
* mtio.h compatible commands should be issued to the character device
* interface.
*/
-static int idetape_blkdev_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
idetape_tape_t *tape = drive->driver_data;
idetape_config_t config;
return 0;
}
-/*
- * The block device interface should not be used for data transfers.
- * However, we still allow opening it so that we can issue general
- * ide driver configuration ioctl's, such as the interrupt unmask feature.
- */
-static int idetape_blkdev_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- MOD_INC_USE_COUNT;
-#if ONSTREAM_DEBUG
- printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_blkdev_open\n");
-#endif
- return 0;
-}
-
-static void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- MOD_DEC_USE_COUNT;
-#if ONSTREAM_DEBUG
- printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_blkdev_release\n");
-#endif
-}
-
/*
* idetape_pre_reset is called before an ATAPI/ATA software reset.
*/
default:
if (tape->chrdev_direction == idetape_direction_read)
idetape_discard_read_pipeline(drive, 1);
- return (idetape_blkdev_ioctl(drive,inode,file,cmd,arg));
+ return idetape_blkdev_ioctl(drive, cmd, arg);
}
}
if (test_and_set_bit(IDETAPE_BUSY, &tape->flags))
return -EBUSY;
- MOD_INC_USE_COUNT;
if (!tape->onstream) {
idetape_read_position(drive);
if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
if (idetape_wait_ready(drive, 60 * HZ)) {
clear_bit(IDETAPE_BUSY, &tape->flags);
printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
- MOD_DEC_USE_COUNT;
return -EBUSY;
}
idetape_read_position(drive);
- MOD_DEC_USE_COUNT;
clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
if (tape->chrdev_direction == idetape_direction_none) {
- MOD_INC_USE_COUNT;
if (idetape_create_prevent_cmd(drive, &pc, 1)) {
if (!idetape_queue_pc_tail(drive, &pc)) {
if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
if (!idetape_queue_pc_tail(drive, &pc))
tape->door_locked = DOOR_UNLOCKED;
}
- MOD_DEC_USE_COUNT;
}
clear_bit(IDETAPE_BUSY, &tape->flags);
unlock_kernel();
devfs_unregister(tape->de_r);
devfs_unregister(tape->de_n);
kfree (tape);
+ drive->disk->fops = ide_fops;
return 0;
}
#endif
.supports_dsc_overlap = 1,
.cleanup = idetape_cleanup,
- .standby = NULL,
- .suspend = NULL,
- .resume = NULL,
- .flushcache = NULL,
.do_request = idetape_do_request,
.end_request = idetape_end_request,
- .sense = NULL,
- .error = NULL,
- .ioctl = idetape_blkdev_ioctl,
- .open = idetape_blkdev_open,
- .release = idetape_blkdev_release,
- .media_change = NULL,
- .revalidate = NULL,
.pre_reset = idetape_pre_reset,
- .capacity = NULL,
- .special = NULL,
.proc = idetape_proc,
.attach = idetape_attach,
- .ata_prebuilder = NULL,
- .atapi_prebuilder = NULL,
.drives = LIST_HEAD_INIT(idetape_driver.drives),
};
.release = idetape_chrdev_release,
};
+static int idetape_open(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ drive->usage++;
+ return 0;
+}
+
+static int idetape_release(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ drive->usage--;
+ return 0;
+}
+
+static int idetape_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ ide_drive_t *drive = bdev->bd_disk->private_data;
+ int err = generic_ide_ioctl(bdev, cmd, arg);
+ if (err == -EINVAL)
+ err = idetape_blkdev_ioctl(drive, cmd, arg);
+ return err;
+}
+
+static struct block_device_operations idetape_block_ops = {
+ .owner = THIS_MODULE,
+ .open = idetape_open,
+ .release = idetape_release,
+ .ioctl = idetape_ioctl,
+};
+
static int idetape_attach (ide_drive_t *drive)
{
idetape_tape_t *tape;
S_IFCHR | S_IRUGO | S_IWUGO,
&idetape_fops, NULL);
devfs_register_tape(tape->de_r);
+ drive->disk->fops = &idetape_block_ops;
return 0;
failed:
return 1;
EXPORT_SYMBOL(ide_do_drive_cmd);
-void ide_revalidate_drive (ide_drive_t *drive)
-{
- set_capacity(drive->disk, current_capacity(drive));
-}
-
-EXPORT_SYMBOL(ide_revalidate_drive);
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed disk, and then re-read the new partition table.
- * If we are revalidating a disk because of a media change, then we
- * enter with usage == 0. If we are using an ioctl, we automatically have
- * usage == 1 (we need an open channel to use an ioctl :-), so this
- * is our limit.
- */
-static int ide_revalidate_disk(struct gendisk *disk)
-{
- ide_drive_t *drive = disk->private_data;
- if (DRIVER(drive)->revalidate)
- DRIVER(drive)->revalidate(drive);
- return 0;
-}
-
void ide_probe_module (void)
{
if (!ide_probe) {
static int ide_open (struct inode * inode, struct file * filp)
{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
- drive->usage++;
- return DRIVER(drive)->open(inode, filp, drive);
-}
-
-/*
- * Releasing a block device means we sync() it, so that it can safely
- * be forgotten about...
- */
-static int ide_release (struct inode * inode, struct file * file)
-{
- ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
- DRIVER(drive)->release(inode, file, drive);
- drive->usage--;
- return 0;
+ return -ENXIO;
}
static LIST_HEAD(ata_unused);
EXPORT_SYMBOL(generic_ide_ioctl);
-static int ide_ioctl (struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct block_device *bdev = inode->i_bdev;
- ide_drive_t *drive = bdev->bd_disk->private_data;
- int err = generic_ide_ioctl(bdev, cmd, arg);
-
- if (err == -EINVAL && drive->driver)
- err = DRIVER(drive)->ioctl(drive, inode, file, cmd, arg);
- return err;
-}
-
-static int ide_check_media_change(struct gendisk *disk)
-{
- ide_drive_t *drive = disk->private_data;
- if (drive->driver != NULL)
- return DRIVER(drive)->media_change(drive);
- return 0;
-}
-
/*
* stridx() returns the offset of c within s,
* or -1 if c is '\0' or not found within s.
#endif
}
-static int default_cleanup (ide_drive_t *drive)
-{
- return ide_unregister_subdriver(drive);
-}
-
static int default_standby (ide_drive_t *drive)
{
return 0;
return ide_error(drive, msg, stat);
}
-static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -EINVAL;
-}
-
-static int default_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- drive->usage--;
- return -EIO;
-}
-
-static void default_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
-}
-
-static int default_check_media_change (ide_drive_t *drive)
-{
- return 1;
-}
-
static void default_pre_reset (ide_drive_t *drive)
{
}
{
ide_driver_t *d = drive->driver;
- if (d->cleanup == NULL) d->cleanup = default_cleanup;
if (d->standby == NULL) d->standby = default_standby;
if (d->suspend == NULL) d->suspend = default_suspend;
if (d->resume == NULL) d->resume = default_resume;
if (d->end_request == NULL) d->end_request = default_end_request;
if (d->sense == NULL) d->sense = default_sense;
if (d->error == NULL) d->error = default_error;
- if (d->ioctl == NULL) d->ioctl = default_ioctl;
- if (d->open == NULL) d->open = default_open;
- if (d->release == NULL) d->release = default_release;
- if (d->media_change == NULL) d->media_change = default_check_media_change;
if (d->pre_reset == NULL) d->pre_reset = default_pre_reset;
if (d->capacity == NULL) d->capacity = default_capacity;
if (d->special == NULL) d->special = default_special;
struct block_device_operations ide_fops[] = {{
.owner = THIS_MODULE,
.open = ide_open,
- .release = ide_release,
- .ioctl = ide_ioctl,
- .media_changed = ide_check_media_change,
- .revalidate_disk= ide_revalidate_disk
}};
EXPORT_SYMBOL(ide_fops);
* Problem: This can schedule. I moved the block device
* wakeup almost late by priority because of that.
*/
- if (DRIVER(drive) && DRIVER(drive)->media_change)
- DRIVER(drive)->media_change(drive);
-
- /* We kick the VFS too (see fix in ide.c revalidate) */
if (DRIVER(drive))
check_disk_change(MKDEV(drive->disk->major, drive->disk->first_minor));
return ide_stopped;
}
-static int idescsi_do_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- /* need to figure out how to parse scsi-atapi media type */
- return -ENOTTY;
-}
-
-static int idescsi_ide_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static void idescsi_ide_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
-{
- MOD_DEC_USE_COUNT;
-}
-
static ide_drive_t *idescsi_drives[MAX_HWIFS * MAX_DRIVES];
static void idescsi_add_settings(ide_drive_t *drive)
if (ide_unregister_subdriver(drive))
return 1;
drive->driver_data = NULL;
+ drive->disk->fops = ide_fops;
kfree(scsi);
return 0;
}
* IDE subdriver functions, registered with ide.c
*/
static ide_driver_t idescsi_driver = {
- owner: THIS_MODULE,
- name: "ide-scsi",
- version: IDESCSI_VERSION,
- media: ide_scsi,
- busy: 0,
- supports_dma: 1,
- supports_dsc_overlap: 0,
- attach: idescsi_attach,
- cleanup: idescsi_cleanup,
- standby: NULL,
- flushcache: NULL,
- do_request: idescsi_do_request,
- end_request: idescsi_end_request,
- ioctl: idescsi_do_ioctl,
- open: idescsi_ide_open,
- release: idescsi_ide_release,
- media_change: NULL,
- revalidate: NULL,
- pre_reset: NULL,
- capacity: NULL,
- special: NULL,
- proc: NULL,
- drives: LIST_HEAD_INIT(idescsi_driver.drives),
+ .owner = THIS_MODULE,
+ .name = "ide-scsi",
+ .version = IDESCSI_VERSION,
+ .media = ide_scsi,
+ .busy = 0,
+ .supports_dma = 1,
+ .supports_dsc_overlap = 0,
+ .attach = idescsi_attach,
+ .cleanup = idescsi_cleanup,
+ .do_request = idescsi_do_request,
+ .end_request = idescsi_end_request,
+ .drives = LIST_HEAD_INIT(idescsi_driver.drives),
+};
+
+static int idescsi_ide_open(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ drive->usage++;
+ return 0;
+}
+
+static int idescsi_ide_release(struct inode *inode, struct file *filp)
+{
+ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data;
+ drive->usage--;
+ return 0;
+}
+
+static int idescsi_ide_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ return generic_ide_ioctl(bdev, cmd, arg);
+}
+
+static struct block_device_operations idescsi_ops = {
+ .owner = THIS_MODULE,
+ .open = idescsi_ide_open,
+ .release = idescsi_ide_release,
+ .ioctl = idescsi_ide_ioctl,
};
static int idescsi_attach(ide_drive_t *drive)
for (id = 0; id < MAX_HWIFS * MAX_DRIVES && idescsi_drives[id]; id++)
;
idescsi_setup (drive, scsi, id);
+ drive->disk->fops = &idescsi_ops;
return 0;
failed:
return 1;
u8 (*sense)(ide_drive_t *, const char *, u8);
ide_startstop_t (*error)(ide_drive_t *, const char *, u8);
int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
- int (*open)(struct inode *, struct file *, ide_drive_t *);
- void (*release)(struct inode *, struct file *, ide_drive_t *);
- int (*media_change)(ide_drive_t *);
- void (*revalidate)(ide_drive_t *);
void (*pre_reset)(ide_drive_t *);
unsigned long (*capacity)(ide_drive_t *);
ide_startstop_t (*special)(ide_drive_t *);
*/
extern unsigned long current_capacity (ide_drive_t *drive);
-extern void ide_revalidate_drive (ide_drive_t *drive);
-
/*
* Start a reset operation for an IDE interface.
* The caller should return immediately after invoking this.