forked from mirrors/linux
		
	ide: add generic ATA/ATAPI disk driver
* Add struct ide_disk_ops containing protocol specific methods.
* Add 'struct ide_disk_ops *' to ide_drive_t.
* Convert ide-{disk,floppy} drivers to use struct ide_disk_ops.
* Merge ide-{disk,floppy} drivers into generic ide-gd driver.
While at it:
- ide_disk_init_capacity() -> ide_disk_get_capacity()
Acked-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
			
			
This commit is contained in:
		
							parent
							
								
									79cb380397
								
							
						
					
					
						commit
						806f80a6fc
					
				
					 13 changed files with 304 additions and 456 deletions
				
			
		| 
						 | 
					@ -84,21 +84,40 @@ config BLK_DEV_IDE_SATA
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  If unsure, say N.
 | 
						  If unsure, say N.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config BLK_DEV_IDEDISK
 | 
					config IDE_GD
 | 
				
			||||||
	tristate "Include IDE/ATA-2 DISK support"
 | 
						tristate "generic ATA/ATAPI disk support"
 | 
				
			||||||
	---help---
 | 
						default y
 | 
				
			||||||
	  This will include enhanced support for MFM/RLL/IDE hard disks.  If
 | 
						help
 | 
				
			||||||
	  you have a MFM/RLL/IDE disk, and there is no special reason to use
 | 
						  Support for ATA/ATAPI disks (including ATAPI floppy drives).
 | 
				
			||||||
	  the old hard disk driver instead, say Y.  If you have an SCSI-only
 | 
					 | 
				
			||||||
	  system, you can say N here.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  To compile this driver as a module, choose M here: the
 | 
						  To compile this driver as a module, choose M here.
 | 
				
			||||||
	  module will be called ide-disk.
 | 
						  The module will be called ide-gd_mod.
 | 
				
			||||||
	  Do not compile this driver as a module if your root file system
 | 
					 | 
				
			||||||
	  (the one containing the directory /) is located on the IDE disk.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  If unsure, say Y.
 | 
						  If unsure, say Y.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config IDE_GD_ATA
 | 
				
			||||||
 | 
						bool "ATA disk support"
 | 
				
			||||||
 | 
						depends on IDE_GD
 | 
				
			||||||
 | 
						default y
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  This will include support for ATA hard disks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  If unsure, say Y.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config IDE_GD_ATAPI
 | 
				
			||||||
 | 
						bool "ATAPI floppy support"
 | 
				
			||||||
 | 
						depends on IDE_GD
 | 
				
			||||||
 | 
						select IDE_ATAPI
 | 
				
			||||||
 | 
						help
 | 
				
			||||||
 | 
						  This will include support for ATAPI floppy drives
 | 
				
			||||||
 | 
						  (i.e. Iomega ZIP or MKE LS-120).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  For information about jumper settings and the question
 | 
				
			||||||
 | 
						  of when a ZIP drive uses a partition table, see
 | 
				
			||||||
 | 
						  <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  If unsure, say N.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config BLK_DEV_IDECS
 | 
					config BLK_DEV_IDECS
 | 
				
			||||||
	tristate "PCMCIA IDE support"
 | 
						tristate "PCMCIA IDE support"
 | 
				
			||||||
	depends on PCMCIA
 | 
						depends on PCMCIA
 | 
				
			||||||
| 
						 | 
					@ -163,29 +182,6 @@ config BLK_DEV_IDETAPE
 | 
				
			||||||
	  To compile this driver as a module, choose M here: the
 | 
						  To compile this driver as a module, choose M here: the
 | 
				
			||||||
	  module will be called ide-tape.
 | 
						  module will be called ide-tape.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config BLK_DEV_IDEFLOPPY
 | 
					 | 
				
			||||||
	tristate "Include IDE/ATAPI FLOPPY support"
 | 
					 | 
				
			||||||
	select IDE_ATAPI
 | 
					 | 
				
			||||||
	---help---
 | 
					 | 
				
			||||||
	  If you have an IDE floppy drive which uses the ATAPI protocol,
 | 
					 | 
				
			||||||
	  answer Y.  ATAPI is a newer protocol used by IDE CD-ROM/tape/floppy
 | 
					 | 
				
			||||||
	  drives, similar to the SCSI protocol.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	  The LS-120 and the IDE/ATAPI Iomega ZIP drive are also supported by
 | 
					 | 
				
			||||||
	  this driver. For information about jumper settings and the question
 | 
					 | 
				
			||||||
	  of when a ZIP drive uses a partition table, see
 | 
					 | 
				
			||||||
	  <http://www.win.tue.nl/~aeb/linux/zip/zip-1.html>.
 | 
					 | 
				
			||||||
	  (ATAPI PD-CD/CDR drives are not supported by this driver; support
 | 
					 | 
				
			||||||
	  for PD-CD/CDR drives is available if you answer Y to
 | 
					 | 
				
			||||||
	  "SCSI emulation support", below).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	  If you say Y here, the FLOPPY drive will be identified along with
 | 
					 | 
				
			||||||
	  other IDE devices, as "hdb" or "hdc", or something similar (check
 | 
					 | 
				
			||||||
	  the boot messages with dmesg).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	  To compile this driver as a module, choose M here: the
 | 
					 | 
				
			||||||
	  module will be called ide-floppy.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config BLK_DEV_IDESCSI
 | 
					config BLK_DEV_IDESCSI
 | 
				
			||||||
	tristate "SCSI emulation support (DEPRECATED)"
 | 
						tristate "SCSI emulation support (DEPRECATED)"
 | 
				
			||||||
	depends on SCSI
 | 
						depends on SCSI
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,18 +37,25 @@ obj-$(CONFIG_IDE_H8300)			+= h8300/
 | 
				
			||||||
obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
 | 
					obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
 | 
				
			||||||
obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
 | 
					obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ide-disk_mod-y += ide-gd.o ide-disk.o ide-disk_ioctl.o
 | 
					ide-gd_mod-y += ide-gd.o
 | 
				
			||||||
ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
 | 
					ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
 | 
				
			||||||
ide-floppy_mod-y += ide-gd-floppy.o ide-floppy.o ide-floppy_ioctl.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(CONFIG_IDE_GD_ATA), y)
 | 
				
			||||||
 | 
						ide-gd_mod-y += ide-disk.o ide-disk_ioctl.o
 | 
				
			||||||
ifeq ($(CONFIG_IDE_PROC_FS), y)
 | 
					ifeq ($(CONFIG_IDE_PROC_FS), y)
 | 
				
			||||||
	ide-disk_mod-y += ide-disk_proc.o
 | 
						ide-gd_mod-y += ide-disk_proc.o
 | 
				
			||||||
	ide-floppy_mod-y += ide-floppy_proc.o
 | 
					endif
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk_mod.o
 | 
					ifeq ($(CONFIG_IDE_GD_ATAPI), y)
 | 
				
			||||||
 | 
						ide-gd_mod-y += ide-floppy.o ide-floppy_ioctl.o
 | 
				
			||||||
 | 
					ifeq ($(CONFIG_IDE_PROC_FS), y)
 | 
				
			||||||
 | 
						ide-gd_mod-y += ide-floppy_proc.o
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					obj-$(CONFIG_IDE_GD)			+= ide-gd_mod.o
 | 
				
			||||||
obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd_mod.o
 | 
					obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd_mod.o
 | 
				
			||||||
obj-$(CONFIG_BLK_DEV_IDEFLOPPY)		+= ide-floppy_mod.o
 | 
					 | 
				
			||||||
obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
 | 
					obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(CONFIG_BLK_DEV_IDECS), y)
 | 
					ifeq ($(CONFIG_BLK_DEV_IDECS), y)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
 | 
				
			||||||
 * 1073741822 == 549756 MB or 48bit addressing fake drive
 | 
					 * 1073741822 == 549756 MB or 48bit addressing fake drive
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
 | 
					static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
 | 
				
			||||||
				      sector_t block)
 | 
									      sector_t block)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ide_hwif_t *hwif = HWIF(drive);
 | 
						ide_hwif_t *hwif = HWIF(drive);
 | 
				
			||||||
| 
						 | 
					@ -333,7 +333,7 @@ static void idedisk_check_hpa(ide_drive_t *drive)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_disk_init_capacity(ide_drive_t *drive)
 | 
					static int ide_disk_get_capacity(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u16 *id = drive->id;
 | 
						u16 *id = drive->id;
 | 
				
			||||||
	int lba;
 | 
						int lba;
 | 
				
			||||||
| 
						 | 
					@ -382,6 +382,8 @@ void ide_disk_init_capacity(ide_drive_t *drive)
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
			drive->dev_flags &= ~IDE_DFLAG_LBA48;
 | 
								drive->dev_flags &= ~IDE_DFLAG_LBA48;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 | 
					static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
 | 
				
			||||||
| 
						 | 
					@ -590,7 +592,12 @@ ide_ext_devset_rw(wcache, wcache);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ide_ext_devset_rw_sync(nowerr, nowerr);
 | 
					ide_ext_devset_rw_sync(nowerr, nowerr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_disk_setup(ide_drive_t *drive)
 | 
					static int ide_disk_check(ide_drive_t *drive, const char *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ide_disk_setup(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ide_disk_obj *idkp = drive->driver_data;
 | 
						struct ide_disk_obj *idkp = drive->driver_data;
 | 
				
			||||||
	ide_hwif_t *hwif = drive->hwif;
 | 
						ide_hwif_t *hwif = drive->hwif;
 | 
				
			||||||
| 
						 | 
					@ -626,7 +633,7 @@ void ide_disk_setup(ide_drive_t *drive)
 | 
				
			||||||
			 drive->queue->max_sectors / 2);
 | 
								 drive->queue->max_sectors / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* calculate drive capacity, and select LBA if possible */
 | 
						/* calculate drive capacity, and select LBA if possible */
 | 
				
			||||||
	ide_disk_init_capacity(drive);
 | 
						ide_disk_get_capacity(drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * if possible, give fdisk access to more of the drive,
 | 
						 * if possible, give fdisk access to more of the drive,
 | 
				
			||||||
| 
						 | 
					@ -682,7 +689,7 @@ void ide_disk_setup(ide_drive_t *drive)
 | 
				
			||||||
		drive->dev_flags |= IDE_DFLAG_ATTACH;
 | 
							drive->dev_flags |= IDE_DFLAG_ATTACH;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_disk_flush(ide_drive_t *drive)
 | 
					static void ide_disk_flush(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (ata_id_flush_enabled(drive->id) == 0 ||
 | 
						if (ata_id_flush_enabled(drive->id) == 0 ||
 | 
				
			||||||
	    (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
 | 
						    (drive->dev_flags & IDE_DFLAG_WCACHE) == 0)
 | 
				
			||||||
| 
						 | 
					@ -692,7 +699,13 @@ void ide_disk_flush(ide_drive_t *drive)
 | 
				
			||||||
		printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
 | 
							printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ide_disk_set_doorlock(ide_drive_t *drive, int on)
 | 
					static int ide_disk_init_media(ide_drive_t *drive, struct gendisk *disk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk,
 | 
				
			||||||
 | 
									 int on)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	ide_task_t task;
 | 
						ide_task_t task;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -711,3 +724,15 @@ int ide_disk_set_doorlock(ide_drive_t *drive, int on)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct ide_disk_ops ide_ata_disk_ops = {
 | 
				
			||||||
 | 
						.check		= ide_disk_check,
 | 
				
			||||||
 | 
						.get_capacity	= ide_disk_get_capacity,
 | 
				
			||||||
 | 
						.setup		= ide_disk_setup,
 | 
				
			||||||
 | 
						.flush		= ide_disk_flush,
 | 
				
			||||||
 | 
						.init_media	= ide_disk_init_media,
 | 
				
			||||||
 | 
						.set_doorlock	= ide_disk_set_doorlock,
 | 
				
			||||||
 | 
						.do_request	= ide_do_rw_disk,
 | 
				
			||||||
 | 
						.end_request	= ide_end_request,
 | 
				
			||||||
 | 
						.ioctl		= ide_disk_ioctl,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,22 +1,11 @@
 | 
				
			||||||
#ifndef __IDE_DISK_H
 | 
					#ifndef __IDE_DISK_H
 | 
				
			||||||
#define __IDE_DISK_H
 | 
					#define __IDE_DISK_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ide_disk_obj {
 | 
					#include "ide-gd.h"
 | 
				
			||||||
	ide_drive_t	*drive;
 | 
					 | 
				
			||||||
	ide_driver_t	*driver;
 | 
					 | 
				
			||||||
	struct gendisk	*disk;
 | 
					 | 
				
			||||||
	struct kref	kref;
 | 
					 | 
				
			||||||
	unsigned int	openers;	/* protected by BKL for now */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
sector_t ide_gd_capacity(ide_drive_t *);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_IDE_GD_ATA
 | 
				
			||||||
/* ide-disk.c */
 | 
					/* ide-disk.c */
 | 
				
			||||||
void ide_disk_init_capacity(ide_drive_t *);
 | 
					extern const struct ide_disk_ops ide_ata_disk_ops;
 | 
				
			||||||
void ide_disk_setup(ide_drive_t *);
 | 
					 | 
				
			||||||
void ide_disk_flush(ide_drive_t *);
 | 
					 | 
				
			||||||
int ide_disk_set_doorlock(ide_drive_t *, int);
 | 
					 | 
				
			||||||
ide_startstop_t ide_do_rw_disk(ide_drive_t *, struct request *, sector_t);
 | 
					 | 
				
			||||||
ide_decl_devset(address);
 | 
					ide_decl_devset(address);
 | 
				
			||||||
ide_decl_devset(multcount);
 | 
					ide_decl_devset(multcount);
 | 
				
			||||||
ide_decl_devset(nowerr);
 | 
					ide_decl_devset(nowerr);
 | 
				
			||||||
| 
						 | 
					@ -24,12 +13,17 @@ ide_decl_devset(wcache);
 | 
				
			||||||
ide_decl_devset(acoustic);
 | 
					ide_decl_devset(acoustic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ide-disk_ioctl.c */
 | 
					/* ide-disk_ioctl.c */
 | 
				
			||||||
int ide_disk_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 | 
					int ide_disk_ioctl(ide_drive_t *, struct inode *, struct file *, unsigned int,
 | 
				
			||||||
 | 
							   unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_IDE_PROC_FS
 | 
					#ifdef CONFIG_IDE_PROC_FS
 | 
				
			||||||
/* ide-disk_proc.c */
 | 
					/* ide-disk_proc.c */
 | 
				
			||||||
extern ide_proc_entry_t ide_disk_proc[];
 | 
					extern ide_proc_entry_t ide_disk_proc[];
 | 
				
			||||||
extern const struct ide_proc_devset ide_disk_settings[];
 | 
					extern const struct ide_proc_devset ide_disk_settings[];
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define ide_disk_proc		NULL
 | 
				
			||||||
 | 
					#define ide_disk_settings	NULL
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __IDE_DISK_H */
 | 
					#endif /* __IDE_DISK_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,12 +13,10 @@ static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
 | 
				
			||||||
{ 0 }
 | 
					{ 0 }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ide_disk_ioctl(struct inode *inode, struct file *file,
 | 
					int ide_disk_ioctl(ide_drive_t *drive, struct inode *inode, struct file *file,
 | 
				
			||||||
		   unsigned int cmd, unsigned long arg)
 | 
							   unsigned int cmd, unsigned long arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct block_device *bdev = inode->i_bdev;
 | 
						struct block_device *bdev = inode->i_bdev;
 | 
				
			||||||
	struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
 | 
					 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
					 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
 | 
						err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@
 | 
				
			||||||
 * Used to finish servicing a request. For read/write requests, we will call
 | 
					 * Used to finish servicing a request. For read/write requests, we will call
 | 
				
			||||||
 * ide_end_request to pass to the next buffer.
 | 
					 * ide_end_request to pass to the next buffer.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
 | 
					static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	idefloppy_floppy_t *floppy = drive->driver_data;
 | 
						idefloppy_floppy_t *floppy = drive->driver_data;
 | 
				
			||||||
	struct request *rq = HWGROUP(drive)->rq;
 | 
						struct request *rq = HWGROUP(drive)->rq;
 | 
				
			||||||
| 
						 | 
					@ -280,13 +280,12 @@ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
 | 
				
			||||||
	pc->req_xfer = pc->buf_size = rq->data_len;
 | 
						pc->req_xfer = pc->buf_size = rq->data_len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, struct request *rq,
 | 
					static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
 | 
				
			||||||
				      sector_t block_s)
 | 
										     struct request *rq, sector_t block)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	idefloppy_floppy_t *floppy = drive->driver_data;
 | 
						idefloppy_floppy_t *floppy = drive->driver_data;
 | 
				
			||||||
	ide_hwif_t *hwif = drive->hwif;
 | 
						ide_hwif_t *hwif = drive->hwif;
 | 
				
			||||||
	struct ide_atapi_pc *pc;
 | 
						struct ide_atapi_pc *pc;
 | 
				
			||||||
	unsigned long block = (unsigned long)block_s;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
 | 
						ide_debug_log(IDE_DBG_FUNC, "%s: dev: %s, cmd: 0x%x, cmd_type: %x, "
 | 
				
			||||||
		      "errors: %d\n",
 | 
							      "errors: %d\n",
 | 
				
			||||||
| 
						 | 
					@ -316,7 +315,7 @@ ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, struct request *rq,
 | 
				
			||||||
			return ide_stopped;
 | 
								return ide_stopped;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pc = &floppy->queued_pc;
 | 
							pc = &floppy->queued_pc;
 | 
				
			||||||
		idefloppy_create_rw_cmd(drive, pc, rq, block);
 | 
							idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
 | 
				
			||||||
	} else if (blk_special_request(rq)) {
 | 
						} else if (blk_special_request(rq)) {
 | 
				
			||||||
		pc = (struct ide_atapi_pc *) rq->buffer;
 | 
							pc = (struct ide_atapi_pc *) rq->buffer;
 | 
				
			||||||
	} else if (blk_pc_request(rq)) {
 | 
						} else if (blk_pc_request(rq)) {
 | 
				
			||||||
| 
						 | 
					@ -406,7 +405,7 @@ static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
 | 
				
			||||||
 * Determine if a media is present in the floppy drive, and if so, its LBA
 | 
					 * Determine if a media is present in the floppy drive, and if so, its LBA
 | 
				
			||||||
 * capacity.
 | 
					 * capacity.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int ide_floppy_get_capacity(ide_drive_t *drive)
 | 
					static int ide_floppy_get_capacity(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	idefloppy_floppy_t *floppy = drive->driver_data;
 | 
						idefloppy_floppy_t *floppy = drive->driver_data;
 | 
				
			||||||
	struct gendisk *disk = floppy->disk;
 | 
						struct gendisk *disk = floppy->disk;
 | 
				
			||||||
| 
						 | 
					@ -505,9 +504,9 @@ int ide_floppy_get_capacity(ide_drive_t *drive)
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ide_floppy_setup(ide_drive_t *drive)
 | 
					static void ide_floppy_setup(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ide_floppy_obj *floppy = drive->driver_data;
 | 
						struct ide_disk_obj *floppy = drive->driver_data;
 | 
				
			||||||
	u16 *id = drive->id;
 | 
						u16 *id = drive->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drive->pc_callback	 = ide_floppy_callback;
 | 
						drive->pc_callback	 = ide_floppy_callback;
 | 
				
			||||||
| 
						 | 
					@ -547,3 +546,33 @@ void ide_floppy_setup(ide_drive_t *drive)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drive->dev_flags |= IDE_DFLAG_ATTACH;
 | 
						drive->dev_flags |= IDE_DFLAG_ATTACH;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void ide_floppy_flush(ide_drive_t *drive)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ide_floppy_init_media(ide_drive_t *drive, struct gendisk *disk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ide_do_test_unit_ready(drive, disk))
 | 
				
			||||||
 | 
							ide_do_start_stop(drive, disk, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = ide_floppy_get_capacity(drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						set_capacity(disk, ide_gd_capacity(drive));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct ide_disk_ops ide_atapi_disk_ops = {
 | 
				
			||||||
 | 
						.check		= ide_check_atapi_device,
 | 
				
			||||||
 | 
						.get_capacity	= ide_floppy_get_capacity,
 | 
				
			||||||
 | 
						.setup		= ide_floppy_setup,
 | 
				
			||||||
 | 
						.flush		= ide_floppy_flush,
 | 
				
			||||||
 | 
						.init_media	= ide_floppy_init_media,
 | 
				
			||||||
 | 
						.set_doorlock	= ide_set_media_lock,
 | 
				
			||||||
 | 
						.do_request	= ide_floppy_do_request,
 | 
				
			||||||
 | 
						.end_request	= ide_floppy_end_request,
 | 
				
			||||||
 | 
						.ioctl		= ide_floppy_ioctl,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,48 +1,10 @@
 | 
				
			||||||
#ifndef __IDE_FLOPPY_H
 | 
					#ifndef __IDE_FLOPPY_H
 | 
				
			||||||
#define __IDE_FLOPPY_H
 | 
					#define __IDE_FLOPPY_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DRV_NAME "ide-floppy"
 | 
					#include "ide-gd.h"
 | 
				
			||||||
#define PFX DRV_NAME ": "
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* define to see debug info */
 | 
					#ifdef CONFIG_IDE_GD_ATAPI
 | 
				
			||||||
#define IDEFLOPPY_DEBUG_LOG	0
 | 
					typedef struct ide_disk_obj idefloppy_floppy_t;
 | 
				
			||||||
 | 
					 | 
				
			||||||
#if IDEFLOPPY_DEBUG_LOG
 | 
					 | 
				
			||||||
#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define ide_debug_log(lvl, fmt, args...) do {} while (0)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Most of our global data which we need to save even as we leave the driver
 | 
					 | 
				
			||||||
 * due to an interrupt or a timer event is stored in a variable of type
 | 
					 | 
				
			||||||
 * idefloppy_floppy_t, defined below.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
typedef struct ide_floppy_obj {
 | 
					 | 
				
			||||||
	ide_drive_t	*drive;
 | 
					 | 
				
			||||||
	ide_driver_t	*driver;
 | 
					 | 
				
			||||||
	struct gendisk	*disk;
 | 
					 | 
				
			||||||
	struct kref	kref;
 | 
					 | 
				
			||||||
	unsigned int	openers;	/* protected by BKL for now */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Last failed packet command */
 | 
					 | 
				
			||||||
	struct ide_atapi_pc *failed_pc;
 | 
					 | 
				
			||||||
	/* used for blk_{fs,pc}_request() requests */
 | 
					 | 
				
			||||||
	struct ide_atapi_pc queued_pc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Last error information */
 | 
					 | 
				
			||||||
	u8 sense_key, asc, ascq;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int progress_indication;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Device information */
 | 
					 | 
				
			||||||
	/* Current format */
 | 
					 | 
				
			||||||
	int blocks, block_size, bs_factor;
 | 
					 | 
				
			||||||
	/* Last format capacity descriptor */
 | 
					 | 
				
			||||||
	u8 cap_desc[8];
 | 
					 | 
				
			||||||
	/* Copy of the flexible disk page */
 | 
					 | 
				
			||||||
	u8 flexible_disk_page[32];
 | 
					 | 
				
			||||||
} idefloppy_floppy_t;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Pages of the SELECT SENSE / MODE SENSE packet commands.
 | 
					 * Pages of the SELECT SENSE / MODE SENSE packet commands.
 | 
				
			||||||
| 
						 | 
					@ -57,23 +19,23 @@ typedef struct ide_floppy_obj {
 | 
				
			||||||
#define	IDEFLOPPY_IOCTL_FORMAT_START		0x4602
 | 
					#define	IDEFLOPPY_IOCTL_FORMAT_START		0x4602
 | 
				
			||||||
#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS	0x4603
 | 
					#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS	0x4603
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sector_t ide_gd_capacity(ide_drive_t *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* ide-floppy.c */
 | 
					/* ide-floppy.c */
 | 
				
			||||||
 | 
					extern const struct ide_disk_ops ide_atapi_disk_ops;
 | 
				
			||||||
void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
 | 
					void ide_floppy_create_mode_sense_cmd(struct ide_atapi_pc *, u8);
 | 
				
			||||||
void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
 | 
					void ide_floppy_create_read_capacity_cmd(struct ide_atapi_pc *);
 | 
				
			||||||
int ide_floppy_get_capacity(ide_drive_t *);
 | 
					 | 
				
			||||||
void ide_floppy_setup(ide_drive_t *);
 | 
					 | 
				
			||||||
ide_startstop_t ide_floppy_do_request(ide_drive_t *, struct request *, sector_t);
 | 
					 | 
				
			||||||
int ide_floppy_end_request(ide_drive_t *, int, int);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ide-floppy_ioctl.c */
 | 
					/* ide-floppy_ioctl.c */
 | 
				
			||||||
int ide_floppy_ioctl(struct inode *, struct file *, unsigned, unsigned long);
 | 
					int ide_floppy_ioctl(ide_drive_t *, struct inode *, struct file *, unsigned int,
 | 
				
			||||||
 | 
							     unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_IDE_PROC_FS
 | 
					#ifdef CONFIG_IDE_PROC_FS
 | 
				
			||||||
/* ide-floppy_proc.c */
 | 
					/* ide-floppy_proc.c */
 | 
				
			||||||
extern ide_proc_entry_t ide_floppy_proc[];
 | 
					extern ide_proc_entry_t ide_floppy_proc[];
 | 
				
			||||||
extern const struct ide_proc_devset ide_floppy_settings[];
 | 
					extern const struct ide_proc_devset ide_floppy_settings[];
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define ide_floppy_proc		NULL
 | 
				
			||||||
 | 
					#define ide_floppy_settings	NULL
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /*__IDE_FLOPPY_H */
 | 
					#endif /*__IDE_FLOPPY_H */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
 | 
					static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ide_floppy_obj *floppy = drive->driver_data;
 | 
						struct ide_disk_obj *floppy = drive->driver_data;
 | 
				
			||||||
	struct ide_atapi_pc pc;
 | 
						struct ide_atapi_pc pc;
 | 
				
			||||||
	u8 header_len, desc_cnt;
 | 
						u8 header_len, desc_cnt;
 | 
				
			||||||
	int i, blocks, length, u_array_size, u_index;
 | 
						int i, blocks, length, u_array_size, u_index;
 | 
				
			||||||
| 
						 | 
					@ -260,13 +260,10 @@ static int ide_floppy_format_ioctl(ide_drive_t *drive, struct file *file,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ide_floppy_ioctl(struct inode *inode, struct file *file,
 | 
					int ide_floppy_ioctl(ide_drive_t *drive, struct inode *inode,
 | 
				
			||||||
		    unsigned int cmd, unsigned long arg)
 | 
							     struct file *file, unsigned int cmd, unsigned long arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct block_device *bdev = inode->i_bdev;
 | 
						struct block_device *bdev = inode->i_bdev;
 | 
				
			||||||
	struct ide_floppy_obj *floppy = ide_drv_g(bdev->bd_disk,
 | 
					 | 
				
			||||||
						     ide_floppy_obj);
 | 
					 | 
				
			||||||
	ide_drive_t *drive = floppy->drive;
 | 
					 | 
				
			||||||
	struct ide_atapi_pc pc;
 | 
						struct ide_atapi_pc pc;
 | 
				
			||||||
	void __user *argp = (void __user *)arg;
 | 
						void __user *argp = (void __user *)arg;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,309 +0,0 @@
 | 
				
			||||||
#include <linux/module.h>
 | 
					 | 
				
			||||||
#include <linux/types.h>
 | 
					 | 
				
			||||||
#include <linux/string.h>
 | 
					 | 
				
			||||||
#include <linux/kernel.h>
 | 
					 | 
				
			||||||
#include <linux/errno.h>
 | 
					 | 
				
			||||||
#include <linux/genhd.h>
 | 
					 | 
				
			||||||
#include <linux/mutex.h>
 | 
					 | 
				
			||||||
#include <linux/ide.h>
 | 
					 | 
				
			||||||
#include <linux/hdreg.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "ide-floppy.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define IDEFLOPPY_VERSION "1.00"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* module parameters */
 | 
					 | 
				
			||||||
static unsigned long debug_mask;
 | 
					 | 
				
			||||||
module_param(debug_mask, ulong, 0644);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static DEFINE_MUTEX(ide_disk_ref_mutex);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void ide_disk_release(struct kref *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct ide_floppy_obj *ide_disk_get(struct gendisk *disk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&ide_disk_ref_mutex);
 | 
					 | 
				
			||||||
	idkp = ide_drv_g(disk, ide_floppy_obj);
 | 
					 | 
				
			||||||
	if (idkp) {
 | 
					 | 
				
			||||||
		if (ide_device_get(idkp->drive))
 | 
					 | 
				
			||||||
			idkp = NULL;
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			kref_get(&idkp->kref);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	mutex_unlock(&ide_disk_ref_mutex);
 | 
					 | 
				
			||||||
	return idkp;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void ide_disk_put(struct ide_floppy_obj *idkp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mutex_lock(&ide_disk_ref_mutex);
 | 
					 | 
				
			||||||
	kref_put(&idkp->kref, ide_disk_release);
 | 
					 | 
				
			||||||
	ide_device_put(drive);
 | 
					 | 
				
			||||||
	mutex_unlock(&ide_disk_ref_mutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
sector_t ide_gd_capacity(ide_drive_t *drive)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return drive->capacity64;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_probe(ide_drive_t *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void ide_gd_remove(ide_drive_t *drive)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = drive->driver_data;
 | 
					 | 
				
			||||||
	struct gendisk *g = idkp->disk;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_proc_unregister_driver(drive, idkp->driver);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	del_gendisk(g);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_disk_put(idkp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void ide_disk_release(struct kref *kref)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = to_ide_drv(kref, ide_floppy_obj);
 | 
					 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
					 | 
				
			||||||
	struct gendisk *g = idkp->disk;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	drive->driver_data = NULL;
 | 
					 | 
				
			||||||
	g->private_data = NULL;
 | 
					 | 
				
			||||||
	put_disk(g);
 | 
					 | 
				
			||||||
	kfree(idkp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_IDE_PROC_FS
 | 
					 | 
				
			||||||
static ide_proc_entry_t *ide_floppy_proc_entries(ide_drive_t *drive)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return ide_floppy_proc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct ide_proc_devset *ide_floppy_proc_devsets(ide_drive_t *drive)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return ide_floppy_settings;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static ide_driver_t ide_gd_driver = {
 | 
					 | 
				
			||||||
	.gen_driver = {
 | 
					 | 
				
			||||||
		.owner		= THIS_MODULE,
 | 
					 | 
				
			||||||
		.name		= "ide-floppy",
 | 
					 | 
				
			||||||
		.bus		= &ide_bus_type,
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	.probe			= ide_gd_probe,
 | 
					 | 
				
			||||||
	.remove			= ide_gd_remove,
 | 
					 | 
				
			||||||
	.version		= IDEFLOPPY_VERSION,
 | 
					 | 
				
			||||||
	.do_request		= ide_floppy_do_request,
 | 
					 | 
				
			||||||
	.end_request		= ide_floppy_end_request,
 | 
					 | 
				
			||||||
	.error			= __ide_error,
 | 
					 | 
				
			||||||
#ifdef CONFIG_IDE_PROC_FS
 | 
					 | 
				
			||||||
	.proc_entries		= ide_floppy_proc_entries,
 | 
					 | 
				
			||||||
	.proc_devsets		= ide_floppy_proc_devsets,
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_open(struct inode *inode, struct file *filp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct gendisk *disk = inode->i_bdev->bd_disk;
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp;
 | 
					 | 
				
			||||||
	ide_drive_t *drive;
 | 
					 | 
				
			||||||
	int ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	idkp = ide_disk_get(disk);
 | 
					 | 
				
			||||||
	if (idkp == NULL)
 | 
					 | 
				
			||||||
		return -ENXIO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	drive = idkp->drive;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	idkp->openers++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (idkp->openers == 1) {
 | 
					 | 
				
			||||||
		drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
 | 
					 | 
				
			||||||
		/* Just in case */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (ide_do_test_unit_ready(drive, disk))
 | 
					 | 
				
			||||||
			ide_do_start_stop(drive, disk, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret = ide_floppy_get_capacity(drive);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		set_capacity(disk, ide_gd_capacity(drive));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (ret && (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
 | 
					 | 
				
			||||||
		     */
 | 
					 | 
				
			||||||
			ret = -EIO;
 | 
					 | 
				
			||||||
			goto out_put_idkp;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) {
 | 
					 | 
				
			||||||
			ret = -EROFS;
 | 
					 | 
				
			||||||
			goto out_put_idkp;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ide_set_media_lock(drive, disk, 1);
 | 
					 | 
				
			||||||
		drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
 | 
					 | 
				
			||||||
		check_disk_change(inode->i_bdev);
 | 
					 | 
				
			||||||
	} else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
 | 
					 | 
				
			||||||
		ret = -EBUSY;
 | 
					 | 
				
			||||||
		goto out_put_idkp;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out_put_idkp:
 | 
					 | 
				
			||||||
	idkp->openers--;
 | 
					 | 
				
			||||||
	ide_disk_put(idkp);
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_release(struct inode *inode, struct file *filp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct gendisk *disk = inode->i_bdev->bd_disk;
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj);
 | 
					 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (idkp->openers == 1) {
 | 
					 | 
				
			||||||
		ide_set_media_lock(drive, disk, 0);
 | 
					 | 
				
			||||||
		drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	idkp->openers--;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_disk_put(idkp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = ide_drv_g(bdev->bd_disk, ide_floppy_obj);
 | 
					 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	geo->heads = drive->bios_head;
 | 
					 | 
				
			||||||
	geo->sectors = drive->bios_sect;
 | 
					 | 
				
			||||||
	geo->cylinders = (u16)drive->bios_cyl; /* truncate */
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_media_changed(struct gendisk *disk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj);
 | 
					 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* do not scan partitions twice if this is a removable device */
 | 
					 | 
				
			||||||
	if (drive->dev_flags & IDE_DFLAG_ATTACH) {
 | 
					 | 
				
			||||||
		drive->dev_flags &= ~IDE_DFLAG_ATTACH;
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
 | 
					 | 
				
			||||||
	drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_revalidate_disk(struct gendisk *disk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp = ide_drv_g(disk, ide_floppy_obj);
 | 
					 | 
				
			||||||
	set_capacity(disk, ide_gd_capacity(idkp->drive));
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct block_device_operations ide_gd_ops = {
 | 
					 | 
				
			||||||
	.owner			= THIS_MODULE,
 | 
					 | 
				
			||||||
	.open			= ide_gd_open,
 | 
					 | 
				
			||||||
	.release		= ide_gd_release,
 | 
					 | 
				
			||||||
	.ioctl			= ide_floppy_ioctl,
 | 
					 | 
				
			||||||
	.getgeo			= ide_gd_getgeo,
 | 
					 | 
				
			||||||
	.media_changed		= ide_gd_media_changed,
 | 
					 | 
				
			||||||
	.revalidate_disk	= ide_gd_revalidate_disk
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int ide_gd_probe(ide_drive_t *drive)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct ide_floppy_obj *idkp;
 | 
					 | 
				
			||||||
	struct gendisk *g;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!strstr("ide-floppy", drive->driver_req))
 | 
					 | 
				
			||||||
		goto failed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (drive->media != ide_floppy)
 | 
					 | 
				
			||||||
		goto failed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!ide_check_atapi_device(drive, DRV_NAME)) {
 | 
					 | 
				
			||||||
		printk(KERN_ERR PFX "%s: not supported by this version of "
 | 
					 | 
				
			||||||
		       DRV_NAME "\n", drive->name);
 | 
					 | 
				
			||||||
		goto failed;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
 | 
					 | 
				
			||||||
	if (!idkp) {
 | 
					 | 
				
			||||||
		printk(KERN_ERR PFX "%s: Can't allocate a floppy structure\n",
 | 
					 | 
				
			||||||
		       drive->name);
 | 
					 | 
				
			||||||
		goto failed;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	g = alloc_disk_node(1 << PARTN_BITS, hwif_to_node(drive->hwif));
 | 
					 | 
				
			||||||
	if (!g)
 | 
					 | 
				
			||||||
		goto out_free_idkp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_init_disk(g, drive);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	kref_init(&idkp->kref);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	idkp->drive = drive;
 | 
					 | 
				
			||||||
	idkp->driver = &ide_gd_driver;
 | 
					 | 
				
			||||||
	idkp->disk = g;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	g->private_data = &idkp->driver;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	drive->driver_data = idkp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	drive->debug_mask = debug_mask;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ide_floppy_setup(drive);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	set_capacity(g, ide_gd_capacity(drive));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	g->minors = 1 << PARTN_BITS;
 | 
					 | 
				
			||||||
	g->driverfs_dev = &drive->gendev;
 | 
					 | 
				
			||||||
	if (drive->dev_flags & IDE_DFLAG_REMOVABLE)
 | 
					 | 
				
			||||||
		g->flags = GENHD_FL_REMOVABLE;
 | 
					 | 
				
			||||||
	g->fops = &ide_gd_ops;
 | 
					 | 
				
			||||||
	add_disk(g);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out_free_idkp:
 | 
					 | 
				
			||||||
	kfree(idkp);
 | 
					 | 
				
			||||||
failed:
 | 
					 | 
				
			||||||
	return -ENODEV;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init ide_gd_init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printk(KERN_INFO DRV_NAME " driver " IDEFLOPPY_VERSION "\n");
 | 
					 | 
				
			||||||
	return driver_register(&ide_gd_driver.gen_driver);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void __exit ide_gd_exit(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	driver_unregister(&ide_gd_driver.gen_driver);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MODULE_ALIAS("ide:*m-floppy*");
 | 
					 | 
				
			||||||
MODULE_ALIAS("ide-floppy");
 | 
					 | 
				
			||||||
module_init(ide_gd_init);
 | 
					 | 
				
			||||||
module_exit(ide_gd_exit);
 | 
					 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					 | 
				
			||||||
MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
 | 
					 | 
				
			||||||
| 
						 | 
					@ -15,9 +15,14 @@
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ide-disk.h"
 | 
					#include "ide-disk.h"
 | 
				
			||||||
 | 
					#include "ide-floppy.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IDE_GD_VERSION	"1.18"
 | 
					#define IDE_GD_VERSION	"1.18"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* module parameters */
 | 
				
			||||||
 | 
					static unsigned long debug_mask;
 | 
				
			||||||
 | 
					module_param(debug_mask, ulong, 0644);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static DEFINE_MUTEX(ide_disk_ref_mutex);
 | 
					static DEFINE_MUTEX(ide_disk_ref_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ide_disk_release(struct kref *);
 | 
					static void ide_disk_release(struct kref *);
 | 
				
			||||||
| 
						 | 
					@ -64,7 +69,7 @@ static void ide_gd_remove(ide_drive_t *drive)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	del_gendisk(g);
 | 
						del_gendisk(g);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ide_disk_flush(drive);
 | 
						drive->disk_ops->flush(drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ide_disk_put(idkp);
 | 
						ide_disk_put(idkp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -75,6 +80,7 @@ static void ide_disk_release(struct kref *kref)
 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
						ide_drive_t *drive = idkp->drive;
 | 
				
			||||||
	struct gendisk *g = idkp->disk;
 | 
						struct gendisk *g = idkp->disk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drive->disk_ops = NULL;
 | 
				
			||||||
	drive->driver_data = NULL;
 | 
						drive->driver_data = NULL;
 | 
				
			||||||
	g->private_data = NULL;
 | 
						g->private_data = NULL;
 | 
				
			||||||
	put_disk(g);
 | 
						put_disk(g);
 | 
				
			||||||
| 
						 | 
					@ -89,7 +95,7 @@ static void ide_disk_release(struct kref *kref)
 | 
				
			||||||
static void ide_gd_resume(ide_drive_t *drive)
 | 
					static void ide_gd_resume(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (ata_id_hpa_enabled(drive->id))
 | 
						if (ata_id_hpa_enabled(drive->id))
 | 
				
			||||||
		ide_disk_init_capacity(drive);
 | 
							(void)drive->disk_ops->get_capacity(drive);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ide_gd_shutdown(ide_drive_t *drive)
 | 
					static void ide_gd_shutdown(ide_drive_t *drive)
 | 
				
			||||||
| 
						 | 
					@ -110,7 +116,7 @@ static void ide_gd_shutdown(ide_drive_t *drive)
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	if (system_state == SYSTEM_RESTART) {
 | 
						if (system_state == SYSTEM_RESTART) {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		ide_disk_flush(drive);
 | 
							drive->disk_ops->flush(drive);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -122,19 +128,31 @@ static void ide_gd_shutdown(ide_drive_t *drive)
 | 
				
			||||||
#ifdef CONFIG_IDE_PROC_FS
 | 
					#ifdef CONFIG_IDE_PROC_FS
 | 
				
			||||||
static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
 | 
					static ide_proc_entry_t *ide_disk_proc_entries(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return ide_disk_proc;
 | 
						return (drive->media == ide_disk) ? ide_disk_proc : ide_floppy_proc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
 | 
					static const struct ide_proc_devset *ide_disk_proc_devsets(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return ide_disk_settings;
 | 
						return (drive->media == ide_disk) ? ide_disk_settings
 | 
				
			||||||
 | 
										  : ide_floppy_settings;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ide_startstop_t ide_gd_do_request(ide_drive_t *drive,
 | 
				
			||||||
 | 
										 struct request *rq, sector_t sector)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return drive->disk_ops->do_request(drive, rq, sector);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ide_gd_end_request(ide_drive_t *drive, int uptodate, int nrsecs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return drive->disk_ops->end_request(drive, uptodate, nrsecs);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ide_driver_t ide_gd_driver = {
 | 
					static ide_driver_t ide_gd_driver = {
 | 
				
			||||||
	.gen_driver = {
 | 
						.gen_driver = {
 | 
				
			||||||
		.owner		= THIS_MODULE,
 | 
							.owner		= THIS_MODULE,
 | 
				
			||||||
		.name		= "ide-disk",
 | 
							.name		= "ide-gd",
 | 
				
			||||||
		.bus		= &ide_bus_type,
 | 
							.bus		= &ide_bus_type,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	.probe			= ide_gd_probe,
 | 
						.probe			= ide_gd_probe,
 | 
				
			||||||
| 
						 | 
					@ -142,8 +160,8 @@ static ide_driver_t ide_gd_driver = {
 | 
				
			||||||
	.resume			= ide_gd_resume,
 | 
						.resume			= ide_gd_resume,
 | 
				
			||||||
	.shutdown		= ide_gd_shutdown,
 | 
						.shutdown		= ide_gd_shutdown,
 | 
				
			||||||
	.version		= IDE_GD_VERSION,
 | 
						.version		= IDE_GD_VERSION,
 | 
				
			||||||
	.do_request		= ide_do_rw_disk,
 | 
						.do_request		= ide_gd_do_request,
 | 
				
			||||||
	.end_request		= ide_end_request,
 | 
						.end_request		= ide_gd_end_request,
 | 
				
			||||||
	.error			= __ide_error,
 | 
						.error			= __ide_error,
 | 
				
			||||||
#ifdef CONFIG_IDE_PROC_FS
 | 
					#ifdef CONFIG_IDE_PROC_FS
 | 
				
			||||||
	.proc_entries		= ide_disk_proc_entries,
 | 
						.proc_entries		= ide_disk_proc_entries,
 | 
				
			||||||
| 
						 | 
					@ -156,6 +174,7 @@ static int ide_gd_open(struct inode *inode, struct file *filp)
 | 
				
			||||||
	struct gendisk *disk = inode->i_bdev->bd_disk;
 | 
						struct gendisk *disk = inode->i_bdev->bd_disk;
 | 
				
			||||||
	struct ide_disk_obj *idkp;
 | 
						struct ide_disk_obj *idkp;
 | 
				
			||||||
	ide_drive_t *drive;
 | 
						ide_drive_t *drive;
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idkp = ide_disk_get(disk);
 | 
						idkp = ide_disk_get(disk);
 | 
				
			||||||
	if (idkp == NULL)
 | 
						if (idkp == NULL)
 | 
				
			||||||
| 
						 | 
					@ -163,19 +182,49 @@ static int ide_gd_open(struct inode *inode, struct file *filp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drive = idkp->drive;
 | 
						drive = idkp->drive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idkp->openers++;
 | 
						idkp->openers++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
 | 
						if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
 | 
				
			||||||
 | 
							drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
 | 
				
			||||||
 | 
							/* Just in case */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ret = drive->disk_ops->init_media(drive, disk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * 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
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (ret && (filp->f_flags & O_NDELAY) == 0) {
 | 
				
			||||||
 | 
								ret = -EIO;
 | 
				
			||||||
 | 
								goto out_put_idkp;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((drive->dev_flags & IDE_DFLAG_WP) && (filp->f_mode & 2)) {
 | 
				
			||||||
 | 
								ret = -EROFS;
 | 
				
			||||||
 | 
								goto out_put_idkp;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Ignore the return code from door_lock,
 | 
							 * Ignore the return code from door_lock,
 | 
				
			||||||
		 * since the open() has already succeeded,
 | 
							 * since the open() has already succeeded,
 | 
				
			||||||
		 * and the door_lock is irrelevant at this point.
 | 
							 * and the door_lock is irrelevant at this point.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		ide_disk_set_doorlock(drive, 1);
 | 
							drive->disk_ops->set_doorlock(drive, disk, 1);
 | 
				
			||||||
		drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
 | 
							drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
 | 
				
			||||||
		check_disk_change(inode->i_bdev);
 | 
							check_disk_change(inode->i_bdev);
 | 
				
			||||||
 | 
						} else if (drive->dev_flags & IDE_DFLAG_FORMAT_IN_PROGRESS) {
 | 
				
			||||||
 | 
							ret = -EBUSY;
 | 
				
			||||||
 | 
							goto out_put_idkp;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_put_idkp:
 | 
				
			||||||
 | 
						idkp->openers--;
 | 
				
			||||||
 | 
						ide_disk_put(idkp);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ide_gd_release(struct inode *inode, struct file *filp)
 | 
					static int ide_gd_release(struct inode *inode, struct file *filp)
 | 
				
			||||||
| 
						 | 
					@ -184,11 +233,15 @@ static int ide_gd_release(struct inode *inode, struct file *filp)
 | 
				
			||||||
	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 | 
						struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 | 
				
			||||||
	ide_drive_t *drive = idkp->drive;
 | 
						ide_drive_t *drive = idkp->drive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (idkp->openers == 1)
 | 
						ide_debug_log(IDE_DBG_FUNC, "Call %s\n", __func__);
 | 
				
			||||||
		ide_disk_flush(drive);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1)
 | 
						if (idkp->openers == 1)
 | 
				
			||||||
		ide_disk_set_doorlock(drive, 0);
 | 
							drive->disk_ops->flush(drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((drive->dev_flags & IDE_DFLAG_REMOVABLE) && idkp->openers == 1) {
 | 
				
			||||||
 | 
							drive->disk_ops->set_doorlock(drive, disk, 0);
 | 
				
			||||||
 | 
							drive->dev_flags &= ~IDE_DFLAG_FORMAT_IN_PROGRESS;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idkp->openers--;
 | 
						idkp->openers--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,11 +286,21 @@ static int ide_gd_revalidate_disk(struct gendisk *disk)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int ide_gd_ioctl(struct inode *inode, struct file *file,
 | 
				
			||||||
 | 
								     unsigned int cmd, unsigned long arg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct block_device *bdev = inode->i_bdev;
 | 
				
			||||||
 | 
						struct ide_disk_obj *idkp = ide_drv_g(bdev->bd_disk, ide_disk_obj);
 | 
				
			||||||
 | 
						ide_drive_t *drive = idkp->drive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return drive->disk_ops->ioctl(drive, inode, file, cmd, arg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct block_device_operations ide_gd_ops = {
 | 
					static struct block_device_operations ide_gd_ops = {
 | 
				
			||||||
	.owner			= THIS_MODULE,
 | 
						.owner			= THIS_MODULE,
 | 
				
			||||||
	.open			= ide_gd_open,
 | 
						.open			= ide_gd_open,
 | 
				
			||||||
	.release		= ide_gd_release,
 | 
						.release		= ide_gd_release,
 | 
				
			||||||
	.ioctl			= ide_disk_ioctl,
 | 
						.ioctl			= ide_gd_ioctl,
 | 
				
			||||||
	.getgeo			= ide_gd_getgeo,
 | 
						.getgeo			= ide_gd_getgeo,
 | 
				
			||||||
	.media_changed		= ide_gd_media_changed,
 | 
						.media_changed		= ide_gd_media_changed,
 | 
				
			||||||
	.revalidate_disk	= ide_gd_revalidate_disk
 | 
						.revalidate_disk	= ide_gd_revalidate_disk
 | 
				
			||||||
| 
						 | 
					@ -245,19 +308,37 @@ static struct block_device_operations ide_gd_ops = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ide_gd_probe(ide_drive_t *drive)
 | 
					static int ide_gd_probe(ide_drive_t *drive)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						const struct ide_disk_ops *disk_ops = NULL;
 | 
				
			||||||
	struct ide_disk_obj *idkp;
 | 
						struct ide_disk_obj *idkp;
 | 
				
			||||||
	struct gendisk *g;
 | 
						struct gendisk *g;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* strstr("foo", "") is non-NULL */
 | 
						/* strstr("foo", "") is non-NULL */
 | 
				
			||||||
	if (!strstr("ide-disk", drive->driver_req))
 | 
						if (!strstr("ide-gd", drive->driver_req))
 | 
				
			||||||
		goto failed;
 | 
							goto failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (drive->media != ide_disk)
 | 
					#ifdef CONFIG_IDE_GD_ATA
 | 
				
			||||||
 | 
						if (drive->media == ide_disk)
 | 
				
			||||||
 | 
							disk_ops = &ide_ata_disk_ops;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef CONFIG_IDE_GD_ATAPI
 | 
				
			||||||
 | 
						if (drive->media == ide_floppy)
 | 
				
			||||||
 | 
							disk_ops = &ide_atapi_disk_ops;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						if (disk_ops == NULL)
 | 
				
			||||||
		goto failed;
 | 
							goto failed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (disk_ops->check(drive, DRV_NAME) == 0) {
 | 
				
			||||||
 | 
							printk(KERN_ERR PFX "%s: not supported by this driver\n",
 | 
				
			||||||
 | 
								drive->name);
 | 
				
			||||||
 | 
							goto failed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
 | 
						idkp = kzalloc(sizeof(*idkp), GFP_KERNEL);
 | 
				
			||||||
	if (!idkp)
 | 
						if (!idkp) {
 | 
				
			||||||
 | 
							printk(KERN_ERR PFX "%s: can't allocate a disk structure\n",
 | 
				
			||||||
 | 
								drive->name);
 | 
				
			||||||
		goto failed;
 | 
							goto failed;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
 | 
						g = alloc_disk_node(IDE_DISK_MINORS, hwif_to_node(drive->hwif));
 | 
				
			||||||
	if (!g)
 | 
						if (!g)
 | 
				
			||||||
| 
						 | 
					@ -274,8 +355,10 @@ static int ide_gd_probe(ide_drive_t *drive)
 | 
				
			||||||
	g->private_data = &idkp->driver;
 | 
						g->private_data = &idkp->driver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drive->driver_data = idkp;
 | 
						drive->driver_data = idkp;
 | 
				
			||||||
 | 
						drive->debug_mask = debug_mask;
 | 
				
			||||||
 | 
						drive->disk_ops = disk_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ide_disk_setup(drive);
 | 
						disk_ops->setup(drive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	set_capacity(g, ide_gd_capacity(drive));
 | 
						set_capacity(g, ide_gd_capacity(drive));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -296,6 +379,7 @@ static int ide_gd_probe(ide_drive_t *drive)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __init ide_gd_init(void)
 | 
					static int __init ide_gd_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						printk(KERN_INFO DRV_NAME " driver " IDE_GD_VERSION "\n");
 | 
				
			||||||
	return driver_register(&ide_gd_driver.gen_driver);
 | 
						return driver_register(&ide_gd_driver.gen_driver);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -306,7 +390,9 @@ static void __exit ide_gd_exit(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODULE_ALIAS("ide:*m-disk*");
 | 
					MODULE_ALIAS("ide:*m-disk*");
 | 
				
			||||||
MODULE_ALIAS("ide-disk");
 | 
					MODULE_ALIAS("ide-disk");
 | 
				
			||||||
 | 
					MODULE_ALIAS("ide:*m-floppy*");
 | 
				
			||||||
 | 
					MODULE_ALIAS("ide-floppy");
 | 
				
			||||||
module_init(ide_gd_init);
 | 
					module_init(ide_gd_init);
 | 
				
			||||||
module_exit(ide_gd_exit);
 | 
					module_exit(ide_gd_exit);
 | 
				
			||||||
MODULE_LICENSE("GPL");
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
MODULE_DESCRIPTION("ATA DISK Driver");
 | 
					MODULE_DESCRIPTION("generic ATA/ATAPI disk driver");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										44
									
								
								drivers/ide/ide-gd.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								drivers/ide/ide-gd.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					#ifndef __IDE_GD_H
 | 
				
			||||||
 | 
					#define __IDE_GD_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define DRV_NAME "ide-gd"
 | 
				
			||||||
 | 
					#define PFX DRV_NAME ": "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* define to see debug info */
 | 
				
			||||||
 | 
					#define IDE_GD_DEBUG_LOG	0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if IDE_GD_DEBUG_LOG
 | 
				
			||||||
 | 
					#define ide_debug_log(lvl, fmt, args...) __ide_debug_log(lvl, fmt, args)
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define ide_debug_log(lvl, fmt, args...) do {} while (0)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ide_disk_obj {
 | 
				
			||||||
 | 
						ide_drive_t	*drive;
 | 
				
			||||||
 | 
						ide_driver_t	*driver;
 | 
				
			||||||
 | 
						struct gendisk	*disk;
 | 
				
			||||||
 | 
						struct kref	kref;
 | 
				
			||||||
 | 
						unsigned int	openers;	/* protected by BKL for now */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Last failed packet command */
 | 
				
			||||||
 | 
						struct ide_atapi_pc *failed_pc;
 | 
				
			||||||
 | 
						/* used for blk_{fs,pc}_request() requests */
 | 
				
			||||||
 | 
						struct ide_atapi_pc queued_pc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Last error information */
 | 
				
			||||||
 | 
						u8 sense_key, asc, ascq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int progress_indication;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Device information */
 | 
				
			||||||
 | 
						/* Current format */
 | 
				
			||||||
 | 
						int blocks, block_size, bs_factor;
 | 
				
			||||||
 | 
						/* Last format capacity descriptor */
 | 
				
			||||||
 | 
						u8 cap_desc[8];
 | 
				
			||||||
 | 
						/* Copy of the flexible disk page */
 | 
				
			||||||
 | 
						u8 flexible_disk_page[32];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sector_t ide_gd_capacity(ide_drive_t *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __IDE_GD_H */
 | 
				
			||||||
| 
						 | 
					@ -179,7 +179,7 @@ config LEDS_TRIGGER_TIMER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config LEDS_TRIGGER_IDE_DISK
 | 
					config LEDS_TRIGGER_IDE_DISK
 | 
				
			||||||
	bool "LED IDE Disk Trigger"
 | 
						bool "LED IDE Disk Trigger"
 | 
				
			||||||
	depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK
 | 
						depends on LEDS_TRIGGERS && IDE_GD_ATA
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	  This allows LEDs to be controlled by IDE disk activity.
 | 
						  This allows LEDs to be controlled by IDE disk activity.
 | 
				
			||||||
	  If unsure, say Y.
 | 
						  If unsure, say Y.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -461,6 +461,23 @@ struct ide_acpi_drive_link;
 | 
				
			||||||
struct ide_acpi_hwif_link;
 | 
					struct ide_acpi_hwif_link;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ide_drive_s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ide_disk_ops {
 | 
				
			||||||
 | 
						int		(*check)(struct ide_drive_s *, const char *);
 | 
				
			||||||
 | 
						int		(*get_capacity)(struct ide_drive_s *);
 | 
				
			||||||
 | 
						void		(*setup)(struct ide_drive_s *);
 | 
				
			||||||
 | 
						void		(*flush)(struct ide_drive_s *);
 | 
				
			||||||
 | 
						int		(*init_media)(struct ide_drive_s *, struct gendisk *);
 | 
				
			||||||
 | 
						int		(*set_doorlock)(struct ide_drive_s *, struct gendisk *,
 | 
				
			||||||
 | 
										int);
 | 
				
			||||||
 | 
						ide_startstop_t	(*do_request)(struct ide_drive_s *, struct request *,
 | 
				
			||||||
 | 
									      sector_t);
 | 
				
			||||||
 | 
						int		(*end_request)(struct ide_drive_s *, int, int);
 | 
				
			||||||
 | 
						int		(*ioctl)(struct ide_drive_s *, struct inode *,
 | 
				
			||||||
 | 
									 struct file *, unsigned int, unsigned long);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ATAPI device flags */
 | 
					/* ATAPI device flags */
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	IDE_AFLAG_DRQ_INTERRUPT		= (1 << 0),
 | 
						IDE_AFLAG_DRQ_INTERRUPT		= (1 << 0),
 | 
				
			||||||
| 
						 | 
					@ -594,6 +611,8 @@ struct ide_drive_s {
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	struct hwif_s		*hwif;	/* actually (ide_hwif_t *) */
 | 
						struct hwif_s		*hwif;	/* actually (ide_hwif_t *) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const struct ide_disk_ops *disk_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned long dev_flags;
 | 
						unsigned long dev_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned long sleep;		/* sleep until this time */
 | 
						unsigned long sleep;		/* sleep until this time */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue