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
2008-02-02 21:56:38 +03:00
/* Error code returned in rq->errors to the higher part of the driver. */
2005-04-17 02:20:36 +04:00
# define IDEFLOPPY_ERROR_GENERAL 101
/*
2008-02-02 21:56:38 +03:00
* Used to finish servicing a request . For read / write requests , we will call
* ide_end_request to pass to the next buffer .
2005-04-17 02:20:36 +04:00
*/
2008-10-17 20:09:14 +04:00
static int ide_floppy_end_request ( ide_drive_t * drive , int uptodate , int nsecs )
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
struct request * rq = HWGROUP ( drive ) - > rq ;
int error ;
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_FUNC , " Call %s \n " , __func__ ) ;
2005-04-17 02:20:36 +04:00
switch ( uptodate ) {
2008-10-13 23:39:35 +04:00
case 0 :
error = IDEFLOPPY_ERROR_GENERAL ;
break ;
case 1 :
error = 0 ;
break ;
default :
error = uptodate ;
2005-04-17 02:20:36 +04:00
}
2008-10-13 23:39:35 +04:00
2005-04-17 02:20:36 +04:00
if ( error )
floppy - > failed_pc = NULL ;
/* Why does this happen? */
if ( ! rq )
return 0 ;
2006-08-10 10:44:47 +04:00
if ( ! blk_special_request ( rq ) ) {
2005-04-17 02:20:36 +04:00
/* our real local end request function */
ide_end_request ( drive , uptodate , nsecs ) ;
return 0 ;
}
rq - > errors = error ;
/* fixme: need to move this local also */
ide_end_drive_cmd ( drive , 0 , 0 ) ;
return 0 ;
}
2008-04-18 02:46:27 +04:00
static void idefloppy_update_buffers ( ide_drive_t * drive ,
struct ide_atapi_pc * pc )
2005-04-17 02:20:36 +04:00
{
struct request * rq = pc - > rq ;
struct bio * bio = rq - > bio ;
while ( ( bio = rq - > bio ) ! = NULL )
2008-10-17 20:09:13 +04:00
ide_floppy_end_request ( drive , 1 , 0 ) ;
2005-04-17 02:20:36 +04:00
}
2008-10-13 23:39:30 +04:00
static void 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 ;
2008-07-15 23:21:56 +04:00
int uptodate = pc - > error ? 0 : 1 ;
2005-04-17 02:20:36 +04:00
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_FUNC , " Call %s \n " , __func__ ) ;
2008-02-02 21:56:34 +03:00
2008-07-15 23:22:01 +04:00
if ( floppy - > failed_pc = = pc )
floppy - > failed_pc = NULL ;
2008-07-15 23:21:56 +04:00
if ( pc - > c [ 0 ] = = GPCMD_READ_10 | | pc - > c [ 0 ] = = GPCMD_WRITE_10 | |
( pc - > rq & & blk_pc_request ( pc - > rq ) ) )
uptodate = 1 ; /* FIXME */
else if ( pc - > c [ 0 ] = = GPCMD_REQUEST_SENSE ) {
2008-10-13 23:39:31 +04:00
u8 * buf = pc - > buf ;
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
2008-07-15 23:21:56 +04:00
if ( floppy - > failed_pc )
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_PC , " pc = %x, " ,
floppy - > 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, "
" ascq = %x \n " , floppy - > sense_key ,
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
2008-10-17 20:09:13 +04:00
ide_floppy_end_request ( drive , uptodate , 0 ) ;
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
}
2008-02-02 21:56:38 +03:00
static ide_startstop_t idefloppy_issue_pc ( ide_drive_t * drive ,
2008-04-18 02:46:27 +04:00
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
if ( floppy - > failed_pc = = NULL & &
2008-02-02 21:56:33 +03:00
pc - > c [ 0 ] ! = GPCMD_REQUEST_SENSE )
2005-04-17 02:20:36 +04:00
floppy - > 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 ) {
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 ) ;
/* Giving up */
pc - > error = IDEFLOPPY_ERROR_GENERAL ;
2005-04-17 02:20:36 +04:00
floppy - > failed_pc = NULL ;
2008-10-13 23:39:30 +04:00
drive - > pc_callback ( drive , 0 ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_FUNC , " %s: Retry #%d \n " , __func__ , pc - > retries ) ;
2005-04-17 02:20:36 +04:00
pc - > retries + + ;
2008-10-13 23:39:32 +04:00
return ide_issue_pc ( drive , WAIT_FLOPPY_CMD , NULL ) ;
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 ;
int blocks = rq - > nr_sectors / floppy - > bs_factor ;
int cmd = rq_data_dir ( rq ) ;
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_FUNC , " %s: block: %d, blocks: %d \n " , __func__ ,
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 ;
2008-10-11 00:39:35 +04:00
pc - > b_count = 0 ;
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 ;
2008-04-18 02:46:27 +04:00
pc - > buf = NULL ;
pc - > req_xfer = pc - > buf_size = blocks * floppy - > block_size ;
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 ;
2008-10-11 00:39:35 +04:00
pc - > b_count = 0 ;
2007-07-09 14:38:05 +04:00
if ( rq - > data_len & & rq_data_dir ( rq ) = = WRITE )
2008-02-02 21:56:37 +03:00
pc - > flags | = PC_FLAG_WRITING ;
2008-04-18 02:46:27 +04:00
pc - > buf = rq - > data ;
2007-07-09 14:38:05 +04:00
if ( rq - > bio )
2008-07-15 23:21:56 +04:00
pc - > flags | = PC_FLAG_DMA_OK ;
2007-07-09 14:38:05 +04:00
/*
* possibly problematic , doesn ' t look like ide - floppy correctly
* handled scattered requests if dma fails . . .
*/
2008-04-18 02:46:27 +04:00
pc - > req_xfer = pc - > buf_size = rq - > data_len ;
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 ;
2008-10-11 00:39:35 +04:00
ide_hwif_t * hwif = drive - > hwif ;
2008-04-18 02:46:27 +04:00
struct ide_atapi_pc * pc ;
2005-04-17 02:20:36 +04:00
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_FUNC , " %s: dev: %s, cmd: 0x%x, cmd_type: %x, "
" errors: %d \n " ,
__func__ , rq - > rq_disk ? rq - > rq_disk - > disk_name : " ? " ,
rq - > cmd [ 0 ] , rq - > cmd_type , rq - > errors ) ;
2008-10-11 00:39:35 +04:00
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_FUNC , " %s: sector: %ld, nr_sectors: %ld, "
" current_nr_sectors: %d \n " ,
__func__ , ( long ) rq - > sector , rq - > nr_sectors ,
rq - > current_nr_sectors ) ;
2005-04-17 02:20:36 +04:00
if ( rq - > errors > = ERROR_MAX ) {
2008-02-02 21:56:35 +03:00
if ( floppy - > failed_pc )
ide_floppy_report_error ( floppy , floppy - > failed_pc ) ;
2005-04-17 02:20:36 +04:00
else
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: I/O error \n " , drive - > name ) ;
2008-10-17 20:09:13 +04:00
ide_floppy_end_request ( drive , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
2006-08-10 10:44:47 +04:00
if ( blk_fs_request ( rq ) ) {
2005-04-17 02:20:36 +04:00
if ( ( ( long ) rq - > sector % floppy - > bs_factor ) | |
( rq - > nr_sectors % floppy - > bs_factor ) ) {
2008-10-13 23:39:35 +04:00
printk ( KERN_ERR PFX " %s: unsupported r/w rq size \n " ,
drive - > name ) ;
2008-10-17 20:09:13 +04:00
ide_floppy_end_request ( drive , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
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 ) ;
2006-08-10 10:44:47 +04:00
} else if ( blk_special_request ( rq ) ) {
2008-04-18 02:46:27 +04:00
pc = ( struct ide_atapi_pc * ) rq - > buffer ;
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 ) ;
2005-04-17 02:20:36 +04:00
} else {
2008-10-13 23:39:35 +04:00
blk_dump_rq_flags ( rq , PFX " unsupported command in queue " ) ;
2008-10-17 20:09:13 +04:00
ide_floppy_end_request ( drive , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
return ide_stopped ;
}
2008-10-11 00:39:35 +04:00
ide_init_sg_cmd ( drive , rq ) ;
ide_map_sg ( drive , rq ) ;
pc - > sg = hwif - > sg_table ;
pc - > sg_cnt = hwif - > sg_nents ;
2005-04-17 02:20:36 +04:00
pc - > rq = rq ;
2008-07-15 23:21:57 +04:00
2005-04-17 02:20:36 +04:00
return idefloppy_issue_pc ( drive , pc ) ;
}
/*
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
*/
2008-02-02 21:56:35 +03:00
static int ide_floppy_get_flexible_disk_page ( 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 * page ;
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
2008-10-11 00:39:38 +04:00
ide_floppy_create_mode_sense_cmd ( & pc , IDEFLOPPY_FLEXIBLE_DISK_PAGE ) ;
2008-02-02 21:56:35 +03:00
2008-10-11 00:39:38 +04:00
if ( ide_queue_pc_tail ( drive , disk , & pc ) ) {
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
if ( pc . 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
2008-04-18 02:46:27 +04:00
page = & pc . buf [ 8 ] ;
2008-02-02 21:56:35 +03:00
2008-07-16 22:33:47 +04:00
transfer_rate = be16_to_cpup ( ( __be16 * ) & pc . buf [ 8 + 2 ] ) ;
sector_size = be16_to_cpup ( ( __be16 * ) & pc . buf [ 8 + 6 ] ) ;
cyls = be16_to_cpup ( ( __be16 * ) & pc . buf [ 8 + 8 ] ) ;
rpm = be16_to_cpup ( ( __be16 * ) & pc . buf [ 8 + 28 ] ) ;
2008-04-18 02:46:27 +04:00
heads = pc . buf [ 8 + 4 ] ;
sectors = pc . 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 ;
u8 header_len , desc_cnt ;
int i , rc = 1 , blocks , length ;
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 ) ;
2008-10-11 00:39:38 +04:00
if ( ide_queue_pc_tail ( drive , disk , & pc ) ) {
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 ;
}
2008-04-18 02:46:27 +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 ;
2008-07-16 22:33:47 +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, "
" %d sector size \n " ,
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
2008-04-18 02:46:27 +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 ;
}
2008-10-13 23:39:35 +04:00
ide_debug_log ( IDE_DBG_PROBE , " Descriptor 0 Code: %d \n " ,
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 ) )
2008-02-02 21:56:35 +03:00
( void ) ide_floppy_get_flexible_disk_page ( drive ) ;
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 ;
drive - > pc_update_buffers = idefloppy_update_buffers ;
drive - > pc_io_buffers = ide_io_buffers ;
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 ,
. end_request = ide_floppy_end_request ,
. ioctl = ide_floppy_ioctl ,
} ;