📄 ide-floppy.c
字号:
/* * linux/drivers/ide/ide-floppy.c Version 0.97.sv Jan 14 2001 * * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il> * Copyright (C) 2000 - 2001 Paul Bristow <paul@paulbristow.net> *//* * IDE ATAPI floppy driver. * * The driver currently doesn't have any fancy features, just the bare * minimum read/write support. * * This driver supports the following IDE floppy drives: * * LS-120 SuperDisk * Iomega Zip 100/250 * Iomega PC Card Clik!/PocketZip * * Many thanks to Lode Leroy <Lode.Leroy@www.ibase.be>, who tested so many * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive. * * Ver 0.1 Oct 17 96 Initial test version, mostly based on ide-tape.c. * Ver 0.2 Oct 31 96 Minor changes. * Ver 0.3 Dec 2 96 Fixed error recovery bug. * Ver 0.4 Jan 26 97 Add support for the HDIO_GETGEO ioctl. * Ver 0.5 Feb 21 97 Add partitions support. * Use the minimum of the LBA and CHS capacities. * Avoid hwgroup->rq == NULL on the last irq. * Fix potential null dereferencing with DEBUG_LOG. * Ver 0.8 Dec 7 97 Increase irq timeout from 10 to 50 seconds. * Add media write-protect detection. * Issue START command only if TEST UNIT READY fails. * Add work-around for IOMEGA ZIP revision 21.D. * Remove idefloppy_get_capabilities(). * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of * bytes requested on each interrupt to be zero. * Thanks to <shanos@es.co.nz> for pointing this out. * Ver 0.9.sv Jan 6 01 Sam Varshavchik <mrsam@courier-mta.com> * Implement low level formatting. Reimplemented * IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp * bit. My LS-120 drive barfs on * IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me. * Compromise by not reporting a failure to get this * mode page. Implemented four IOCTLs in order to * implement formatting. IOCTls begin with 0x4600, * 0x46 is 'F' as in Format. * Jan 9 01 Userland option to select format verify. * Added PC_SUPPRESS_ERROR flag - some idefloppy drives * do not implement IDEFLOPPY_CAPABILITIES_PAGE, and * return a sense error. Suppress error reporting in * this particular case in order to avoid spurious * errors in syslog. The culprit is * idefloppy_get_capability_page(), so move it to * idefloppy_begin_format() so that it's not used * unless absolutely necessary. * If drive does not support format progress indication * monitor the dsc bit in the status register. * Also, O_NDELAY on open will allow the device to be * opened without a disk available. This can be used to * open an unformatted disk, or get the device capacity. * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by * <paul@paulbristow.net> * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this * driver. Included Powerbook internal zip kludge. * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive * no disk on insert and disk change now works * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere * Ver 0.95 Nov 7 00 Brought across to kernel 2.4 * Ver 0.96 Jan 7 01 Actually in line with release version of 2.4.0 * including set_bit patch from Rusty Russel * Ver 0.97 Jul 22 01 Merge 0.91-0.96 onto 0.9.sv for ac series * Ver 0.97.sv Aug 3 01 Backported from 2.4.7-ac3 */#define IDEFLOPPY_VERSION "0.97.sv"#include <linux/config.h>#include <linux/module.h>#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>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/unaligned.h>#include <asm/bitops.h>/* * The following are used to debug the driver. */#define IDEFLOPPY_DEBUG_LOG 0#define IDEFLOPPY_DEBUG_INFO 0#define IDEFLOPPY_DEBUG_BUGS 1/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */#define IDEFLOPPY_DEBUG( fmt, args... )/* * Some drives require a longer irq timeout. */#define IDEFLOPPY_WAIT_CMD (5 * WAIT_CMD)/* * After each failed packet command we issue a request sense command * and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times. */#define IDEFLOPPY_MAX_PC_RETRIES 3/* * With each packet command, we allocate a buffer of * IDEFLOPPY_PC_BUFFER_SIZE bytes. */#define IDEFLOPPY_PC_BUFFER_SIZE 256/* * In various places in the driver, we need to allocate storage * for packet commands and requests, which will remain valid while * we leave the driver to wait for an interrupt or a timeout event. */#define IDEFLOPPY_PC_STACK (10 + IDEFLOPPY_MAX_PC_RETRIES)/* * Our view of a packet command. */typedef struct idefloppy_packet_command_s { u8 c[12]; /* Actual packet bytes */ int retries; /* On each retry, we increment retries */ int error; /* Error code */ int request_transfer; /* Bytes to transfer */ int actually_transferred; /* Bytes actually transferred */ int buffer_size; /* Size of our data buffer */ char *b_data; /* Pointer which runs on the buffers */ int b_count; /* Missing/Available data on the current buffer */ struct request *rq; /* The corresponding request */ byte *buffer; /* Data buffer */ byte *current_position; /* Pointer into the above buffer */ void (*callback) (ide_drive_t *); /* Called when this packet command is completed */ byte pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE]; /* Temporary buffer */ unsigned long flags; /* Status/Action bit flags: long for set_bit */} idefloppy_pc_t;/* * Packet command flag bits. */#define PC_ABORT 0 /* Set when an error is considered normal - We won't retry */#define PC_DMA_RECOMMENDED 2 /* 1 when we prefer to use DMA if possible */#define PC_DMA_IN_PROGRESS 3 /* 1 while DMA in progress */#define PC_DMA_ERROR 4 /* 1 when encountered problem during DMA */#define PC_WRITING 5 /* Data direction */#define PC_SUPPRESS_ERROR 6 /* Suppress error reporting *//* * Removable Block Access Capabilities Page */typedef struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned page_code :6; /* Page code - Should be 0x1b */ unsigned reserved1_6 :1; /* Reserved */ unsigned ps :1; /* Should be 0 */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned ps :1; /* Should be 0 */ unsigned reserved1_6 :1; /* Reserved */ unsigned page_code :6; /* Page code - Should be 0x1b */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u8 page_length; /* Page Length - Should be 0xa */#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned reserved2 :6; unsigned srfp :1; /* Supports reporting progress of format */ unsigned sflp :1; /* System floppy type device */ unsigned tlun :3; /* Total logical units supported by the device */ unsigned reserved3 :3; unsigned sml :1; /* Single / Multiple lun supported */ unsigned ncd :1; /* Non cd optical device */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned sflp :1; /* System floppy type device */ unsigned srfp :1; /* Supports reporting progress of format */ unsigned reserved2 :6; unsigned ncd :1; /* Non cd optical device */ unsigned sml :1; /* Single / Multiple lun supported */ unsigned reserved3 :3; unsigned tlun :3; /* Total logical units supported by the device */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u8 reserved[8];} idefloppy_capabilities_page_t;/* * Flexible disk page. */typedef struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned page_code :6; /* Page code - Should be 0x5 */ unsigned reserved1_6 :1; /* Reserved */ unsigned ps :1; /* The device is capable of saving the page */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned ps :1; /* The device is capable of saving the page */ unsigned reserved1_6 :1; /* Reserved */ unsigned page_code :6; /* Page code - Should be 0x5 */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u8 page_length; /* Page Length - Should be 0x1e */ u16 transfer_rate; /* In kilobits per second */ u8 heads, sectors; /* Number of heads, Number of sectors per track */ u16 sector_size; /* Byes per sector */ u16 cyls; /* Number of cylinders */ u8 reserved10[10]; u8 motor_delay; /* Motor off delay */ u8 reserved21[7]; u16 rpm; /* Rotations per minute */ u8 reserved30[2];} idefloppy_flexible_disk_page_t; /* * Format capacity */typedef struct { u8 reserved[3]; u8 length; /* Length of the following descriptors in bytes */} idefloppy_capacity_header_t;typedef struct { u32 blocks; /* Number of blocks */#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned dc :2; /* Descriptor Code */ unsigned reserved :6;#elif defined(__BIG_ENDIAN_BITFIELD) unsigned reserved :6; unsigned dc :2; /* Descriptor Code */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u8 length_msb; /* Block Length (MSB)*/ u16 length; /* Block Length */} idefloppy_capacity_descriptor_t;#define CAPACITY_INVALID 0x00#define CAPACITY_UNFORMATTED 0x01#define CAPACITY_CURRENT 0x02#define CAPACITY_NO_CARTRIDGE 0x03/* * 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_drive_t *drive; idefloppy_pc_t *pc; /* Current packet command */ idefloppy_pc_t *failed_pc; /* Last failed packet command */ idefloppy_pc_t pc_stack[IDEFLOPPY_PC_STACK];/* Packet command stack */ int pc_stack_index; /* Next free packet command storage space */ struct request rq_stack[IDEFLOPPY_PC_STACK]; int rq_stack_index; /* We implement a circular array */ /* * Last error information */ byte sense_key, asc, ascq; int progress_indication; /* * Device information */ int blocks, block_size, bs_factor; /* Current format */ idefloppy_capacity_descriptor_t capacity; /* Last format capacity */ idefloppy_flexible_disk_page_t flexible_disk_page; /* Copy of the flexible disk page */ int wp; /* Write protect */ int srfp; /* Supports format progress report */ unsigned long flags; /* Status/Action flags */} idefloppy_floppy_t;/* * Floppy flag bits values. */#define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */#define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */#define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */#define IDEFLOPPY_FORMAT_IN_PROGRESS 3 /* Format in progress */#define IDEFLOPPY_CLIK_DRIVE 4 /* Avoid commands not supported in Clik drive *//* * ATAPI floppy drive packet commands */#define IDEFLOPPY_FORMAT_UNIT_CMD 0x04#define IDEFLOPPY_INQUIRY_CMD 0x12#define IDEFLOPPY_MODE_SELECT_CMD 0x55#define IDEFLOPPY_MODE_SENSE_CMD 0x5a#define IDEFLOPPY_READ10_CMD 0x28#define IDEFLOPPY_READ12_CMD 0xa8#define IDEFLOPPY_READ_CAPACITY_CMD 0x23#define IDEFLOPPY_REQUEST_SENSE_CMD 0x03#define IDEFLOPPY_PREVENT_REMOVAL_CMD 0x1e#define IDEFLOPPY_SEEK_CMD 0x2b#define IDEFLOPPY_START_STOP_CMD 0x1b#define IDEFLOPPY_TEST_UNIT_READY_CMD 0x00#define IDEFLOPPY_VERIFY_CMD 0x2f#define IDEFLOPPY_WRITE10_CMD 0x2a#define IDEFLOPPY_WRITE12_CMD 0xaa#define IDEFLOPPY_WRITE_VERIFY_CMD 0x2e/* * Defines for the mode sense command */#define MODE_SENSE_CURRENT 0x00#define MODE_SENSE_CHANGEABLE 0x01#define MODE_SENSE_DEFAULT 0x02 #define MODE_SENSE_SAVED 0x03/* * IOCTLs used in low-level formatting. */#define IDEFLOPPY_IOCTL_FORMAT_SUPPORTED 0x4600#define IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY 0x4601#define IDEFLOPPY_IOCTL_FORMAT_START 0x4602#define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS 0x4603/* * Special requests for our block device strategy routine. */#define IDEFLOPPY_FIRST_RQ 90/* * IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue. */#define IDEFLOPPY_PC_RQ 90#define IDEFLOPPY_LAST_RQ 90/* * A macro which can be used to check if a given request command * originated in the driver or in the buffer cache layer. */#define IDEFLOPPY_RQ_CMD(cmd) ((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ))/* * Error codes which are returned in rq->errors to the higher part * of the driver. */#define IDEFLOPPY_ERROR_GENERAL 101/* * The ATAPI Status Register. */typedef union { unsigned all :8; struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned check :1; /* Error occurred */ unsigned idx :1; /* Reserved */ unsigned corr :1; /* Correctable error occurred */ unsigned drq :1; /* Data is request by the device */ unsigned dsc :1; /* Media access command finished */ unsigned reserved5 :1; /* Reserved */ unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ unsigned bsy :1; /* The device has access to the command block */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned bsy :1; /* The device has access to the command block */ unsigned drdy :1; /* Ignored for ATAPI commands (ready to accept ATA command) */ unsigned reserved5 :1; /* Reserved */ unsigned dsc :1; /* Media access command finished */ unsigned drq :1; /* Data is request by the device */ unsigned corr :1; /* Correctable error occurred */ unsigned idx :1; /* Reserved */ unsigned check :1; /* Error occurred */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif } b;} idefloppy_status_reg_t;/* * The ATAPI error register. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -