Commit adf283f2 authored by Alexander Viro's avatar Alexander Viro Committed by James Bottomley

[PATCH] ide-{disk,cd,...} got separate block_device_operations

	* first application of the fact that block device methods are
per-disk and not per-major - IDE subdrivers got block_device_operations
of their own, redirects in ide.c are gone, so is a bunch of methods of
IDE subdrivers.
parent f3da61af
......@@ -3205,56 +3205,6 @@ int ide_cdrom_setup (ide_drive_t *drive)
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)
{
......@@ -3289,6 +3239,7 @@ int ide_cdrom_cleanup(ide_drive_t *drive)
kfree(info);
drive->driver_data = NULL;
del_gendisk(g);
g->fops = ide_fops;
return 0;
}
......@@ -3307,29 +3258,75 @@ static ide_driver_t ide_cdrom_driver = {
#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;
......@@ -3397,6 +3394,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
DRIVER(drive)->busy--;
cdrom_read_toc(drive, &sense);
g->fops = &idecd_ops;
add_disk(g);
return 0;
failed:
......
......@@ -788,57 +788,8 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u
#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);
......@@ -1610,28 +1561,6 @@ static void idedisk_add_settings(ide_drive_t *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;
......@@ -1749,6 +1678,7 @@ static int idedisk_cleanup (ide_drive_t *drive)
if (ide_unregister_subdriver(drive))
return 1;
del_gendisk(g);
g->fops = ide_fops;
return 0;
}
......@@ -1771,24 +1701,87 @@ static ide_driver_t idedisk_driver = {
.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)
......@@ -1828,6 +1821,7 @@ 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:
......
......@@ -1511,10 +1511,7 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
**
*/
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;
......@@ -1590,10 +1587,7 @@ static int idefloppy_get_format_capacities (ide_drive_t *drive,
** 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;
......@@ -1626,10 +1620,7 @@ static int idefloppy_begin_format(ide_drive_t *drive,
** 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;
......@@ -1664,181 +1655,6 @@ static int idefloppy_get_format_progress(ide_drive_t *drive,
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.
*/
......@@ -2042,6 +1858,7 @@ static int idefloppy_cleanup (ide_drive_t *drive)
drive->driver_data = NULL;
kfree(floppy);
del_gendisk(g);
g->fops = ide_fops;
return 0;
}
......@@ -2076,29 +1893,179 @@ static ide_driver_t idefloppy_driver = {
#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;
......@@ -2135,6 +2102,7 @@ static int idefloppy_attach (ide_drive_t *drive)
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:
......
......@@ -4221,7 +4221,7 @@ static int idetape_rewind_tape (ide_drive_t *drive)
* 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;
......@@ -4249,28 +4249,6 @@ static int idetape_blkdev_ioctl (ide_drive_t *drive, struct inode *inode, struct
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.
*/
......@@ -5337,7 +5315,7 @@ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigne
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);
}
}
......@@ -5461,7 +5439,6 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
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))
......@@ -5479,15 +5456,12 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
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)
......@@ -5562,7 +5536,6 @@ static int idetape_chrdev_release (struct inode *inode, struct file *filp)
if (!idetape_queue_pc_tail(drive, &pc))
tape->door_locked = DOOR_UNLOCKED;
}
MOD_DEC_USE_COUNT;
}
clear_bit(IDETAPE_BUSY, &tape->flags);
unlock_kernel();
......@@ -6150,6 +6123,7 @@ static int idetape_cleanup (ide_drive_t *drive)
devfs_unregister(tape->de_r);
devfs_unregister(tape->de_n);
kfree (tape);
drive->disk->fops = ide_fops;
return 0;
}
......@@ -6196,26 +6170,11 @@ static ide_driver_t idetape_driver = {
#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),
};
......@@ -6231,6 +6190,38 @@ static struct file_operations idetape_fops = {
.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;
......@@ -6279,6 +6270,7 @@ static int idetape_attach (ide_drive_t *drive)
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;
......
......@@ -1565,29 +1565,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
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) {
......@@ -1603,21 +1580,7 @@ EXPORT_SYMBOL(ide_probe_module);
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);
......@@ -2575,26 +2538,6 @@ int generic_ide_ioctl(struct block_device *bdev, unsigned int cmd,
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.
......@@ -3168,11 +3111,6 @@ void __init ide_init_builtin_drivers (void)
#endif
}
static int default_cleanup (ide_drive_t *drive)
{
return ide_unregister_subdriver(drive);
}
static int default_standby (ide_drive_t *drive)
{
return 0;
......@@ -3214,27 +3152,6 @@ static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, u8 st
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)
{
}
......@@ -3265,7 +3182,6 @@ static void setup_driver_defaults (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;
......@@ -3274,10 +3190,6 @@ static void setup_driver_defaults (ide_drive_t *drive)
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;
......@@ -3415,10 +3327,6 @@ EXPORT_SYMBOL(ide_unregister_driver);
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);
......
......@@ -1579,10 +1579,6 @@ idepmac_wake_device(ide_drive_t *drive, int used_dma)
* 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));
......
......@@ -501,23 +501,6 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
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)
......@@ -563,6 +546,7 @@ static int idescsi_cleanup (ide_drive_t *drive)
if (ide_unregister_subdriver(drive))
return 1;
drive->driver_data = NULL;
drive->disk->fops = ide_fops;
kfree(scsi);
return 0;
}
......@@ -573,29 +557,46 @@ static int idescsi_attach(ide_drive_t *drive);
* 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)
......@@ -622,6 +623,7 @@ 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;
......
......@@ -1189,10 +1189,6 @@ typedef struct ide_driver_s {
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 *);
......@@ -1324,8 +1320,6 @@ extern int ide_xlate_1024(struct block_device *, int, int, const char *);
*/
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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment