2005-04-17 02:20:36 +04:00
/*
2008-02-02 01:09:33 +03:00
* IDE ATAPI floppy driver .
*
2008-02-02 01:09:33 +03:00
* Copyright ( C ) 1996 - 1999 Gadi Oxman < gadio @ netvision . net . il >
* Copyright ( C ) 2000 - 2002 Paul Bristow < paul @ paulbristow . net >
* Copyright ( C ) 2005 Bartlomiej Zolnierkiewicz
2008-02-02 21:56:38 +03:00
*
2005-04-17 02:20:36 +04:00
* This driver supports the following IDE floppy drives :
*
* LS - 120 / 240 SuperDisk
* Iomega Zip 100 / 250
* Iomega PC Card Clik ! / PocketZip
*
2008-02-02 01:09:33 +03:00
* For a historical changelog see
* Documentation / ide / ChangeLog . ide - floppy .1996 - 2002
2005-04-17 02:20:36 +04:00
*/
# include <linux/types.h>
# include <linux/string.h>
# include <linux/kernel.h>
# include <linux/delay.h>
# include <linux/timer.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
# include <linux/major.h>
# include <linux/errno.h>
# include <linux/genhd.h>
# include <linux/slab.h>
# include <linux/cdrom.h>
# include <linux/ide.h>
2008-10-11 00:39:27 +04:00
# include <linux/hdreg.h>
2005-04-17 02:20:36 +04:00
# include <linux/bitops.h>
2006-03-23 14:00:45 +03:00
# include <linux/mutex.h>
2008-10-11 00:39:35 +04:00
# include <linux/scatterlist.h>
2005-04-17 02:20:36 +04:00
2007-07-20 03:11:59 +04:00
# include <scsi/scsi_ioctl.h>
2005-04-17 02:20:36 +04:00
# include <asm/byteorder.h>
2008-02-02 21:56:34 +03:00
# include <linux/irq.h>
# include <linux/uaccess.h>
# include <linux/io.h>
2005-04-17 02:20:36 +04:00
# include <asm/unaligned.h>
2008-10-11 00:39:38 +04:00
# include "ide-floppy.h"
2005-04-17 02:20:36 +04:00
/*
2008-02-02 21:56:38 +03:00
* After each failed packet command we issue a request sense command and retry
* the packet command IDEFLOPPY_MAX_PC_RETRIES times .
2005-04-17 02:20:36 +04:00
*/
# define IDEFLOPPY_MAX_PC_RETRIES 3
2008-02-02 21:56:35 +03:00
/* format capacities descriptor codes */
2005-04-17 02:20:36 +04:00
# define CAPACITY_INVALID 0x00
# define CAPACITY_UNFORMATTED 0x01
# define CAPACITY_CURRENT 0x02
# define CAPACITY_NO_CARTRIDGE 0x03
2008-10-13 23:39:32 +04:00
/*
* The following delay solves a problem with ATAPI Zip 100 drive where BSY bit
* was apparently being deasserted before the unit was ready to receive data .
*/
# define IDEFLOPPY_PC_DELAY (HZ / 20) /* default delay for ZIP 100 (50ms) */
2005-04-17 02:20:36 +04:00
2009-03-27 14:46:36 +03:00
static int ide_floppy_callback ( ide_drive_t * drive , int dsc )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:16 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2008-10-13 23:39:31 +04:00
struct ide_atapi_pc * pc = drive - > pc ;
2009-03-27 14:46:34 +03:00
struct request * rq = pc - > rq ;
2008-07-15 23:21:56 +04:00
int uptodate = pc - > error ? 0 : 1 ;
2005-04-17 02:20:36 +04:00
2009-01-02 15:34:47 +03:00
ide_debug_log ( IDE_DBG_FUNC , " enter " ) ;
2008-02-02 21:56:34 +03:00
2009-03-27 14:46:34 +03:00
if ( drive - > failed_pc = = pc )
drive - > failed_pc = NULL ;
2008-07-15 23:22:01 +04:00
2008-07-15 23:21:56 +04:00
if ( pc - > c [ 0 ] = = GPCMD_READ_10 | | pc - > c [ 0 ] = = GPCMD_WRITE_10 | |
2009-03-27 14:46:34 +03:00
( rq & & blk_pc_request ( rq ) ) )
2008-07-15 23:21:56 +04:00
uptodate = 1 ; /* FIXME */
else if ( pc - > c [ 0 ] = = GPCMD_REQUEST_SENSE ) {
2009-05-02 12:58:17 +04:00
u8 * buf = bio_data ( rq - > bio ) ;
2008-02-02 21:56:34 +03:00
2008-07-15 23:21:56 +04:00
if ( ! pc - > error ) {
floppy - > sense_key = buf [ 2 ] & 0x0F ;
floppy - > asc = buf [ 12 ] ;
floppy - > ascq = buf [ 13 ] ;
floppy - > progress_indication = buf [ 15 ] & 0x80 ?
( u16 ) get_unaligned ( ( u16 * ) & buf [ 16 ] ) : 0x10000 ;
2008-02-02 21:56:34 +03:00
2009-03-27 14:46:34 +03:00
if ( drive - > failed_pc )
2009-01-02 15:34:47 +03:00
ide_debug_log ( IDE_DBG_PC , " pc = %x " ,
2009-03-27 14:46:34 +03:00
drive - > failed_pc - > c [ 0 ] ) ;
2008-02-02 21:56:34 +03:00
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_SENSE , " sense key = %x, asc = %x, "
2009-01-02 15:34:47 +03:00
" ascq = %x " , floppy - > sense_key ,
2008-10-13 23:39:35 +04:00
floppy - > asc , floppy - > ascq ) ;
2008-07-15 23:21:56 +04:00
} else
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " Error in REQUEST SENSE itself - "
" Aborting request! \n " ) ;
2008-07-15 23:21:56 +04:00
}
2005-04-17 02:20:36 +04:00
2009-03-27 14:46:36 +03:00
if ( blk_special_request ( rq ) )
2009-03-27 14:46:34 +03:00
rq - > errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL ;
2009-03-27 14:46:36 +03:00
return uptodate ;
2005-04-17 02:20:36 +04:00
}
2008-10-17 20:09:16 +04:00
static void ide_floppy_report_error ( struct ide_disk_obj * floppy ,
2008-04-18 02:46:27 +04:00
struct ide_atapi_pc * pc )
2005-04-17 02:20:36 +04:00
{
2008-02-02 21:56:35 +03:00
/* supress error messages resulting from Medium not present */
2005-04-17 02:20:36 +04:00
if ( floppy - > sense_key = = 0x02 & &
floppy - > asc = = 0x3a & &
floppy - > ascq = = 0x00 )
2008-02-02 21:56:35 +03:00
return ;
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: I/O error, pc = %2x, key = %2x, "
2008-02-02 21:56:35 +03:00
" asc = %2x, ascq = %2x \n " ,
floppy - > drive - > name , pc - > c [ 0 ] , floppy - > sense_key ,
floppy - > asc , floppy - > ascq ) ;
2005-04-17 02:20:36 +04:00
}
2009-03-27 14:46:46 +03:00
static ide_startstop_t ide_floppy_issue_pc ( ide_drive_t * drive ,
struct ide_cmd * cmd ,
struct ide_atapi_pc * pc )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:16 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2005-04-17 02:20:36 +04:00
2009-03-27 14:46:34 +03:00
if ( drive - > failed_pc = = NULL & &
2008-02-02 21:56:33 +03:00
pc - > c [ 0 ] ! = GPCMD_REQUEST_SENSE )
2009-03-27 14:46:34 +03:00
drive - > failed_pc = pc ;
2008-10-13 23:39:31 +04:00
2005-04-17 02:20:36 +04:00
/* Set the current packet command */
2008-10-13 23:39:31 +04:00
drive - > pc = pc ;
2005-04-17 02:20:36 +04:00
2008-02-02 21:56:37 +03:00
if ( pc - > retries > IDEFLOPPY_MAX_PC_RETRIES ) {
2009-04-19 03:46:02 +04:00
unsigned int done = blk_rq_bytes ( drive - > hwif - > rq ) ;
2008-02-02 21:56:37 +03:00
if ( ! ( pc - > flags & PC_FLAG_SUPPRESS_ERROR ) )
2008-02-02 21:56:37 +03:00
ide_floppy_report_error ( floppy , pc ) ;
2009-04-19 03:46:02 +04:00
2008-02-02 21:56:37 +03:00
/* Giving up */
2009-03-27 14:46:34 +03:00
pc - > error = IDE_DRV_ERROR_GENERAL ;
2008-02-02 21:56:37 +03:00
2009-03-27 14:46:34 +03:00
drive - > failed_pc = NULL ;
2008-10-13 23:39:30 +04:00
drive - > pc_callback ( drive , 0 ) ;
2009-04-19 03:46:02 +04:00
ide_complete_rq ( drive , - EIO , done ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
2009-01-02 15:34:47 +03:00
ide_debug_log ( IDE_DBG_FUNC , " retry #%d " , pc - > retries ) ;
2005-04-17 02:20:36 +04:00
pc - > retries + + ;
2009-03-27 14:46:46 +03:00
return ide_issue_pc ( drive , cmd ) ;
2005-04-17 02:20:36 +04:00
}
2008-10-11 00:39:38 +04:00
void ide_floppy_create_read_capacity_cmd ( struct ide_atapi_pc * pc )
2005-04-17 02:20:36 +04:00
{
2008-10-11 00:39:37 +04:00
ide_init_pc ( pc ) ;
2008-02-02 21:56:33 +03:00
pc - > c [ 0 ] = GPCMD_READ_FORMAT_CAPACITIES ;
2005-04-17 02:20:36 +04:00
pc - > c [ 7 ] = 255 ;
pc - > c [ 8 ] = 255 ;
2008-04-18 02:46:27 +04:00
pc - > req_xfer = 255 ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 21:56:38 +03:00
/* A mode sense command is used to "sense" floppy parameters. */
2008-10-11 00:39:38 +04:00
void ide_floppy_create_mode_sense_cmd ( struct ide_atapi_pc * pc , u8 page_code )
2005-04-17 02:20:36 +04:00
{
2008-02-02 21:56:34 +03:00
u16 length = 8 ; /* sizeof(Mode Parameter Header) = 8 Bytes */
2008-02-02 21:56:38 +03:00
2008-10-11 00:39:37 +04:00
ide_init_pc ( pc ) ;
2008-02-02 21:56:33 +03:00
pc - > c [ 0 ] = GPCMD_MODE_SENSE_10 ;
2005-04-17 02:20:36 +04:00
pc - > c [ 1 ] = 0 ;
2008-10-11 00:39:36 +04:00
pc - > c [ 2 ] = page_code ;
2005-04-17 02:20:36 +04:00
switch ( page_code ) {
2008-02-02 21:56:38 +03:00
case IDEFLOPPY_CAPABILITIES_PAGE :
length + = 12 ;
break ;
case IDEFLOPPY_FLEXIBLE_DISK_PAGE :
length + = 32 ;
break ;
default :
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " unsupported page code in %s \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 21:56:33 +03:00
put_unaligned ( cpu_to_be16 ( length ) , ( u16 * ) & pc - > c [ 7 ] ) ;
2008-04-18 02:46:27 +04:00
pc - > req_xfer = length ;
2005-04-17 02:20:36 +04:00
}
2008-10-13 23:39:35 +04:00
static void idefloppy_create_rw_cmd ( ide_drive_t * drive ,
2008-04-18 02:46:27 +04:00
struct ide_atapi_pc * pc , struct request * rq ,
2008-02-02 21:56:36 +03:00
unsigned long sector )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:16 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2005-04-17 02:20:36 +04:00
int block = sector / floppy - > bs_factor ;
2009-05-07 17:24:40 +04:00
int blocks = blk_rq_sectors ( rq ) / floppy - > bs_factor ;
2005-04-17 02:20:36 +04:00
int cmd = rq_data_dir ( rq ) ;
2009-01-02 15:34:47 +03:00
ide_debug_log ( IDE_DBG_FUNC , " block: %d, blocks: %d " , block , blocks ) ;
2005-04-17 02:20:36 +04:00
2008-10-11 00:39:37 +04:00
ide_init_pc ( pc ) ;
2008-02-02 21:56:36 +03:00
pc - > c [ 0 ] = cmd = = READ ? GPCMD_READ_10 : GPCMD_WRITE_10 ;
put_unaligned ( cpu_to_be16 ( blocks ) , ( unsigned short * ) & pc - > c [ 7 ] ) ;
2008-02-02 21:56:33 +03:00
put_unaligned ( cpu_to_be32 ( block ) , ( unsigned int * ) & pc - > c [ 2 ] ) ;
2008-02-02 21:56:36 +03:00
2008-07-23 21:56:00 +04:00
memcpy ( rq - > cmd , pc - > c , 12 ) ;
2005-04-17 02:20:36 +04:00
pc - > rq = rq ;
2006-08-10 10:44:47 +04:00
if ( rq - > cmd_flags & REQ_RW )
2008-02-02 21:56:37 +03:00
pc - > flags | = PC_FLAG_WRITING ;
2009-05-04 11:53:03 +04:00
2008-07-15 23:21:56 +04:00
pc - > flags | = PC_FLAG_DMA_OK ;
2005-04-17 02:20:36 +04:00
}
2008-10-17 20:09:16 +04:00
static void idefloppy_blockpc_cmd ( struct ide_disk_obj * floppy ,
2008-04-18 02:46:27 +04:00
struct ide_atapi_pc * pc , struct request * rq )
2005-04-17 02:20:36 +04:00
{
2008-10-11 00:39:37 +04:00
ide_init_pc ( pc ) ;
2005-04-17 02:20:36 +04:00
memcpy ( pc - > c , rq - > cmd , sizeof ( pc - > c ) ) ;
2007-07-09 14:38:05 +04:00
pc - > rq = rq ;
2009-05-07 17:24:43 +04:00
if ( blk_rq_bytes ( rq ) ) {
2008-07-15 23:21:56 +04:00
pc - > flags | = PC_FLAG_DMA_OK ;
2009-04-19 02:00:42 +04:00
if ( rq_data_dir ( rq ) = = WRITE )
pc - > flags | = PC_FLAG_WRITING ;
}
2005-04-17 02:20:36 +04:00
}
2008-10-17 20:09:14 +04:00
static ide_startstop_t ide_floppy_do_request ( ide_drive_t * drive ,
struct request * rq , sector_t block )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:16 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2009-03-27 14:46:46 +03:00
struct ide_cmd cmd ;
2008-04-18 02:46:27 +04:00
struct ide_atapi_pc * pc ;
2005-04-17 02:20:36 +04:00
2009-03-31 22:15:26 +04:00
ide_debug_log ( IDE_DBG_FUNC , " enter, cmd: 0x%x \n " , rq - > cmd [ 0 ] ) ;
2009-01-02 15:34:47 +03:00
if ( drive - > debug_mask & IDE_DBG_RQ )
blk_dump_rq_flags ( rq , ( rq - > rq_disk
? rq - > rq_disk - > disk_name
: " dev? " ) ) ;
2005-04-17 02:20:36 +04:00
if ( rq - > errors > = ERROR_MAX ) {
2009-03-27 14:46:34 +03:00
if ( drive - > failed_pc ) {
2009-03-27 14:46:34 +03:00
ide_floppy_report_error ( floppy , drive - > failed_pc ) ;
2009-03-27 14:46:34 +03:00
drive - > failed_pc = NULL ;
} else
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: I/O error \n " , drive - > name ) ;
2009-03-27 14:46:34 +03:00
if ( blk_special_request ( rq ) ) {
2009-03-27 14:46:43 +03:00
rq - > errors = 0 ;
2009-03-27 14:46:44 +03:00
ide_complete_rq ( drive , 0 , blk_rq_bytes ( rq ) ) ;
2009-03-27 14:46:34 +03:00
return ide_stopped ;
} else
goto out_end ;
2005-04-17 02:20:36 +04:00
}
2006-08-10 10:44:47 +04:00
if ( blk_fs_request ( rq ) ) {
2009-05-07 17:24:40 +04:00
if ( ( ( long ) blk_rq_pos ( rq ) % floppy - > bs_factor ) | |
( blk_rq_sectors ( rq ) % floppy - > bs_factor ) ) {
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: unsupported r/w rq size \n " ,
drive - > name ) ;
2009-03-27 14:46:34 +03:00
goto out_end ;
2005-04-17 02:20:36 +04:00
}
2008-10-11 00:39:36 +04:00
pc = & floppy - > queued_pc ;
2008-10-17 20:09:14 +04:00
idefloppy_create_rw_cmd ( drive , pc , rq , ( unsigned long ) block ) ;
2009-04-19 02:00:42 +04:00
} else if ( blk_special_request ( rq ) | | blk_sense_request ( rq ) ) {
2009-04-19 02:00:42 +04:00
pc = ( struct ide_atapi_pc * ) rq - > special ;
2006-08-10 10:44:47 +04:00
} else if ( blk_pc_request ( rq ) ) {
2008-10-11 00:39:36 +04:00
pc = & floppy - > queued_pc ;
2007-07-09 14:38:05 +04:00
idefloppy_blockpc_cmd ( floppy , pc , rq ) ;
2009-06-16 00:16:10 +04:00
} else
BUG ( ) ;
2005-04-17 02:20:36 +04:00
2009-04-19 02:00:42 +04:00
ide_prep_sense ( drive , rq ) ;
2009-03-27 14:46:46 +03:00
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2009-03-27 14:46:46 +03:00
if ( rq_data_dir ( rq ) )
2009-03-27 14:46:46 +03:00
cmd . tf_flags | = IDE_TFLAG_WRITE ;
cmd . rq = rq ;
2009-03-27 14:46:46 +03:00
2009-05-01 22:35:21 +04:00
if ( blk_fs_request ( rq ) | | blk_rq_bytes ( rq ) ) {
ide_init_sg_cmd ( & cmd , blk_rq_bytes ( rq ) ) ;
2009-03-27 14:46:46 +03:00
ide_map_sg ( drive , & cmd ) ;
2009-03-13 23:16:12 +03:00
}
2008-10-11 00:39:35 +04:00
2005-04-17 02:20:36 +04:00
pc - > rq = rq ;
2008-07-15 23:21:57 +04:00
2009-03-27 14:46:46 +03:00
return ide_floppy_issue_pc ( drive , & cmd , pc ) ;
2009-03-27 14:46:34 +03:00
out_end :
drive - > failed_pc = NULL ;
2009-03-27 14:46:43 +03:00
if ( blk_fs_request ( rq ) = = 0 & & rq - > errors = = 0 )
rq - > errors = - EIO ;
2009-03-27 14:46:45 +03:00
ide_complete_rq ( drive , - EIO , ide_rq_bytes ( rq ) ) ;
2009-03-27 14:46:34 +03:00
return ide_stopped ;
2005-04-17 02:20:36 +04:00
}
/*
2008-02-02 21:56:35 +03:00
* Look at the flexible disk page parameters . We ignore the CHS capacity
* parameters and use the LBA parameters instead .
2005-04-17 02:20:36 +04:00
*/
ide-floppy: allocate only toplevel packet commands
This makes the top-level function just allocate a single pc entry, and then
pass it down as a pointer to all the helper functions that also need one
of those "struct ide_atapi_pc" things. As far as I can tell, the use of
these things never overlaps each other, BUT I DID NOT CHECK VERY CLOSELY!
So I'm not guaranteeing this is correct, and I don't have the hardware. It
would be good for somebody who knows the code more, and has the hardware,
could please test this?
With this, ide-floppy still has fairly big stack usage, but instead of
idefloppy_ioctl [vmlinux]: 1208
ide_floppy_get_capacity [vmlinux]: 872
idefloppy_release [vmlinux]: 408
idefloppy_open [vmlinux]: 408
where those two first ones are at the very top of the list of stack users
for me, it's now
ide_floppy_get_capacity [vmlinux]: 404
ide_floppy_ioctl [vmlinux]: 364
ie they are still high, but they are no longer at the top.
Borislav: Since ide_floppy_get_capacity is passed as a function pointer to other
parts of the kernel (e.g., block layer) we need that ide_atapi_pc to be created
on stack. Also, redid stack users numbers above. The two functions missing from
Linus' original 'make stackusage' output are due to ide being
rewritten/reorganized atm.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2009-01-02 18:12:51 +03:00
static int ide_floppy_get_flexible_disk_page ( ide_drive_t * drive ,
struct ide_atapi_pc * pc )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:16 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2008-10-11 00:39:38 +04:00
struct gendisk * disk = floppy - > disk ;
2009-05-02 12:43:11 +04:00
u8 * page , buf [ 40 ] ;
2005-04-17 02:20:36 +04:00
int capacity , lba_capacity ;
2008-02-02 21:56:35 +03:00
u16 transfer_rate , sector_size , cyls , rpm ;
u8 heads , sectors ;
2005-04-17 02:20:36 +04:00
ide-floppy: allocate only toplevel packet commands
This makes the top-level function just allocate a single pc entry, and then
pass it down as a pointer to all the helper functions that also need one
of those "struct ide_atapi_pc" things. As far as I can tell, the use of
these things never overlaps each other, BUT I DID NOT CHECK VERY CLOSELY!
So I'm not guaranteeing this is correct, and I don't have the hardware. It
would be good for somebody who knows the code more, and has the hardware,
could please test this?
With this, ide-floppy still has fairly big stack usage, but instead of
idefloppy_ioctl [vmlinux]: 1208
ide_floppy_get_capacity [vmlinux]: 872
idefloppy_release [vmlinux]: 408
idefloppy_open [vmlinux]: 408
where those two first ones are at the very top of the list of stack users
for me, it's now
ide_floppy_get_capacity [vmlinux]: 404
ide_floppy_ioctl [vmlinux]: 364
ie they are still high, but they are no longer at the top.
Borislav: Since ide_floppy_get_capacity is passed as a function pointer to other
parts of the kernel (e.g., block layer) we need that ide_atapi_pc to be created
on stack. Also, redid stack users numbers above. The two functions missing from
Linus' original 'make stackusage' output are due to ide being
rewritten/reorganized atm.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2009-01-02 18:12:51 +03:00
ide_floppy_create_mode_sense_cmd ( pc , IDEFLOPPY_FLEXIBLE_DISK_PAGE ) ;
2008-02-02 21:56:35 +03:00
2009-05-02 12:43:11 +04:00
if ( ide_queue_pc_tail ( drive , disk , pc , buf , pc - > req_xfer ) ) {
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " Can't get flexible disk page params \n " ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2008-10-11 00:39:38 +04:00
2009-05-02 12:43:11 +04:00
if ( buf [ 3 ] & 0x80 )
2008-10-17 20:09:11 +04:00
drive - > dev_flags | = IDE_DFLAG_WP ;
2008-10-11 00:39:38 +04:00
else
2008-10-17 20:09:11 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_WP ;
2008-10-11 00:39:38 +04:00
2008-10-17 20:09:11 +04:00
set_disk_ro ( disk , ! ! ( drive - > dev_flags & IDE_DFLAG_WP ) ) ;
2008-10-11 00:39:38 +04:00
2009-05-02 12:43:11 +04:00
page = & buf [ 8 ] ;
2008-02-02 21:56:35 +03:00
2009-05-02 12:43:11 +04:00
transfer_rate = be16_to_cpup ( ( __be16 * ) & buf [ 8 + 2 ] ) ;
sector_size = be16_to_cpup ( ( __be16 * ) & buf [ 8 + 6 ] ) ;
cyls = be16_to_cpup ( ( __be16 * ) & buf [ 8 + 8 ] ) ;
rpm = be16_to_cpup ( ( __be16 * ) & buf [ 8 + 28 ] ) ;
heads = buf [ 8 + 4 ] ;
sectors = buf [ 8 + 5 ] ;
2008-02-02 21:56:35 +03:00
capacity = cyls * heads * sectors * sector_size ;
if ( memcmp ( page , & floppy - > flexible_disk_page , 32 ) )
2008-10-13 23:39:35 +04:00
printk ( KERN_INFO PFX " %s: %dkB, %d/%d/%d CHS, %d kBps, "
2005-04-17 02:20:36 +04:00
" %d sector size, %d rpm \n " ,
2008-02-02 21:56:35 +03:00
drive - > name , capacity / 1024 , cyls , heads ,
sectors , transfer_rate / 8 , sector_size , rpm ) ;
memcpy ( & floppy - > flexible_disk_page , page , 32 ) ;
drive - > bios_cyl = cyls ;
drive - > bios_head = heads ;
drive - > bios_sect = sectors ;
2005-04-17 02:20:36 +04:00
lba_capacity = floppy - > blocks * floppy - > block_size ;
2008-02-02 21:56:35 +03:00
2005-04-17 02:20:36 +04:00
if ( capacity < lba_capacity ) {
2008-10-13 23:39:35 +04:00
printk ( KERN_NOTICE PFX " %s: The disk reports a capacity of %d "
2005-04-17 02:20:36 +04:00
" bytes, but the drive only handles %d \n " ,
drive - > name , lba_capacity , capacity ) ;
2008-02-02 21:56:35 +03:00
floppy - > blocks = floppy - > block_size ?
capacity / floppy - > block_size : 0 ;
2008-10-17 20:09:10 +04:00
drive - > capacity64 = floppy - > blocks * floppy - > bs_factor ;
2005-04-17 02:20:36 +04:00
}
2008-10-17 20:09:10 +04:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
/*
2008-02-02 21:56:35 +03:00
* Determine if a media is present in the floppy drive , and if so , its LBA
* capacity .
2005-04-17 02:20:36 +04:00
*/
2008-10-17 20:09:14 +04:00
static int ide_floppy_get_capacity ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:16 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2008-10-11 00:39:38 +04:00
struct gendisk * disk = floppy - > disk ;
2008-04-18 02:46:27 +04:00
struct ide_atapi_pc pc ;
2008-02-02 21:56:35 +03:00
u8 * cap_desc ;
2009-03-31 22:15:25 +04:00
u8 pc_buf [ 256 ] , header_len , desc_cnt ;
2008-02-02 21:56:35 +03:00
int i , rc = 1 , blocks , length ;
2009-03-31 22:15:26 +04:00
ide_debug_log ( IDE_DBG_FUNC , " enter " ) ;
2005-04-17 02:20:36 +04:00
drive - > bios_cyl = 0 ;
drive - > bios_head = drive - > bios_sect = 0 ;
2007-02-17 04:40:20 +03:00
floppy - > blocks = 0 ;
floppy - > bs_factor = 1 ;
2008-10-17 20:09:10 +04:00
drive - > capacity64 = 0 ;
2005-04-17 02:20:36 +04:00
2008-10-11 00:39:38 +04:00
ide_floppy_create_read_capacity_cmd ( & pc ) ;
2009-05-02 12:26:12 +04:00
if ( ide_queue_pc_tail ( drive , disk , & pc , pc_buf , pc . req_xfer ) ) {
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " Can't get floppy parameters \n " ) ;
2005-04-17 02:20:36 +04:00
return 1 ;
}
2009-05-02 12:26:12 +04:00
header_len = pc_buf [ 3 ] ;
cap_desc = & pc_buf [ 4 ] ;
2008-02-02 21:56:35 +03:00
desc_cnt = header_len / 8 ; /* capacity descriptor of 8 bytes */
for ( i = 0 ; i < desc_cnt ; i + + ) {
unsigned int desc_start = 4 + i * 8 ;
2009-05-02 12:26:12 +04:00
blocks = be32_to_cpup ( ( __be32 * ) & pc_buf [ desc_start ] ) ;
length = be16_to_cpup ( ( __be16 * ) & pc_buf [ desc_start + 6 ] ) ;
2008-02-02 21:56:35 +03:00
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_PROBE , " Descriptor %d: %dkB, %d blocks, "
2009-01-02 15:34:47 +03:00
" %d sector size " ,
i , blocks * length / 1024 ,
blocks , length ) ;
2005-04-17 02:20:36 +04:00
2008-02-02 21:56:35 +03:00
if ( i )
continue ;
/*
* the code below is valid only for the 1 st descriptor , ie i = 0
*/
2005-04-17 02:20:36 +04:00
2009-05-02 12:26:12 +04:00
switch ( pc_buf [ desc_start + 4 ] & 0x03 ) {
2005-04-17 02:20:36 +04:00
/* Clik! drive returns this instead of CAPACITY_CURRENT */
case CAPACITY_UNFORMATTED :
2008-07-23 21:56:01 +04:00
if ( ! ( drive - > atapi_flags & IDE_AFLAG_CLIK_DRIVE ) )
2008-02-02 21:56:38 +03:00
/*
2005-04-17 02:20:36 +04:00
* If it is not a clik drive , break out
* ( maintains previous driver behaviour )
*/
break ;
case CAPACITY_CURRENT :
/* Normal Zip/LS-120 disks */
2008-02-02 21:56:35 +03:00
if ( memcmp ( cap_desc , & floppy - > cap_desc , 8 ) )
2008-10-13 23:39:35 +04:00
printk ( KERN_INFO PFX " %s: %dkB, %d blocks, %d "
" sector size \n " ,
drive - > name , blocks * length / 1024 ,
blocks , length ) ;
2008-02-02 21:56:35 +03:00
memcpy ( & floppy - > cap_desc , cap_desc , 8 ) ;
2005-04-17 02:20:36 +04:00
if ( ! length | | length % 512 ) {
2008-10-13 23:39:35 +04:00
printk ( KERN_NOTICE PFX " %s: %d bytes block size "
" not supported \n " , drive - > name , length ) ;
2005-04-17 02:20:36 +04:00
} else {
2008-02-02 21:56:35 +03:00
floppy - > blocks = blocks ;
floppy - > block_size = length ;
floppy - > bs_factor = length / 512 ;
if ( floppy - > bs_factor ! = 1 )
2008-10-13 23:39:35 +04:00
printk ( KERN_NOTICE PFX " %s: Warning: "
" non 512 bytes block size not "
" fully supported \n " ,
drive - > name ) ;
2008-10-17 20:09:10 +04:00
drive - > capacity64 =
floppy - > blocks * floppy - > bs_factor ;
2008-02-02 21:56:35 +03:00
rc = 0 ;
2005-04-17 02:20:36 +04:00
}
break ;
case CAPACITY_NO_CARTRIDGE :
/*
* This is a KERN_ERR so it appears on screen
* for the user to see
*/
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: No disk in drive \n " ,
drive - > name ) ;
2005-04-17 02:20:36 +04:00
break ;
case CAPACITY_INVALID :
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: Invalid capacity for disk "
2005-04-17 02:20:36 +04:00
" in drive \n " , drive - > name ) ;
break ;
}
2009-01-02 15:34:47 +03:00
ide_debug_log ( IDE_DBG_PROBE , " Descriptor 0 Code: %d " ,
2009-05-02 12:26:12 +04:00
pc_buf [ desc_start + 4 ] & 0x03 ) ;
2005-04-17 02:20:36 +04:00
}
/* Clik! disk does not support get_flexible_disk_page */
2008-07-23 21:56:01 +04:00
if ( ! ( drive - > atapi_flags & IDE_AFLAG_CLIK_DRIVE ) )
ide-floppy: allocate only toplevel packet commands
This makes the top-level function just allocate a single pc entry, and then
pass it down as a pointer to all the helper functions that also need one
of those "struct ide_atapi_pc" things. As far as I can tell, the use of
these things never overlaps each other, BUT I DID NOT CHECK VERY CLOSELY!
So I'm not guaranteeing this is correct, and I don't have the hardware. It
would be good for somebody who knows the code more, and has the hardware,
could please test this?
With this, ide-floppy still has fairly big stack usage, but instead of
idefloppy_ioctl [vmlinux]: 1208
ide_floppy_get_capacity [vmlinux]: 872
idefloppy_release [vmlinux]: 408
idefloppy_open [vmlinux]: 408
where those two first ones are at the very top of the list of stack users
for me, it's now
ide_floppy_get_capacity [vmlinux]: 404
ide_floppy_ioctl [vmlinux]: 364
ie they are still high, but they are no longer at the top.
Borislav: Since ide_floppy_get_capacity is passed as a function pointer to other
parts of the kernel (e.g., block layer) we need that ide_atapi_pc to be created
on stack. Also, redid stack users numbers above. The two functions missing from
Linus' original 'make stackusage' output are due to ide being
rewritten/reorganized atm.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2009-01-02 18:12:51 +03:00
( void ) ide_floppy_get_flexible_disk_page ( drive , & pc ) ;
2005-04-17 02:20:36 +04:00
return rc ;
}
2008-10-17 20:09:14 +04:00
static void ide_floppy_setup ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
2008-10-17 20:09:14 +04:00
struct ide_disk_obj * floppy = drive - > driver_data ;
2008-10-11 00:39:19 +04:00
u16 * id = drive - > id ;
2008-10-11 00:39:36 +04:00
2008-10-13 23:39:32 +04:00
drive - > pc_callback = ide_floppy_callback ;
2008-04-18 02:46:25 +04:00
2005-04-17 02:20:36 +04:00
/*
2008-02-02 21:56:38 +03:00
* We used to check revisions here . At this point however I ' m giving up .
* Just assume they are all broken , its easier .
2005-04-17 02:20:36 +04:00
*
2008-02-02 21:56:38 +03:00
* The actual reason for the workarounds was likely a driver bug after
* all rather than a firmware bug , and the workaround below used to hide
* it . It should be fixed as of version 1.9 , but to be on the safe side
* we ' ll leave the limitation below for the 2.2 . x tree .
2005-04-17 02:20:36 +04:00
*/
2008-10-11 00:39:19 +04:00
if ( ! strncmp ( ( char * ) & id [ ATA_ID_PROD ] , " IOMEGA ZIP 100 ATAPI " , 20 ) ) {
2008-07-23 21:56:01 +04:00
drive - > atapi_flags | = IDE_AFLAG_ZIP_DRIVE ;
2005-04-17 02:20:36 +04:00
/* This value will be visible in the /proc/ide/hdx/settings */
2008-10-13 23:39:32 +04:00
drive - > pc_delay = IDEFLOPPY_PC_DELAY ;
2005-04-17 02:20:36 +04:00
blk_queue_max_sectors ( drive - > queue , 64 ) ;
}
/*
2008-02-02 21:56:38 +03:00
* Guess what ? The IOMEGA Clik ! drive also needs the above fix . It makes
* nasty clicking noises without it , so please don ' t remove this .
*/
2008-10-11 00:39:19 +04:00
if ( strncmp ( ( char * ) & id [ ATA_ID_PROD ] , " IOMEGA Clik! " , 11 ) = = 0 ) {
2005-04-17 02:20:36 +04:00
blk_queue_max_sectors ( drive - > queue , 64 ) ;
2008-07-23 21:56:01 +04:00
drive - > atapi_flags | = IDE_AFLAG_CLIK_DRIVE ;
2008-10-11 00:39:38 +04:00
/* IOMEGA Clik! drives do not support lock/unlock commands */
2008-10-17 20:09:11 +04:00
drive - > dev_flags & = ~ IDE_DFLAG_DOORLOCKING ;
2005-04-17 02:20:36 +04:00
}
2008-02-02 21:56:35 +03:00
( void ) ide_floppy_get_capacity ( drive ) ;
2008-10-11 00:39:27 +04:00
ide_proc_register_driver ( drive , floppy - > driver ) ;
2008-10-17 20:09:10 +04:00
drive - > dev_flags | = IDE_DFLAG_ATTACH ;
2005-04-17 02:20:36 +04:00
}
2008-10-17 20:09:14 +04:00
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 ,
. ioctl = ide_floppy_ioctl ,
} ;