📄 ide-floppy.c
字号:
/* * linux/drivers/block/ide-floppy.c Version 0.9 Jul 4, 1999 * * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il> *//* * IDE ATAPI floppy driver. * * The driver currently doesn't have any fancy features, just the bare * minimum read/write support. * * 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. */#define IDEFLOPPY_VERSION "0.9"#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/malloc.h>#include <linux/cdrom.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>/* * Main Linux ide driver include file */#include "ide.h"/* * The following are used to debug the driver. */#define IDEFLOPPY_DEBUG_LOG 0#define IDEFLOPPY_DEBUG_INFO 0#define IDEFLOPPY_DEBUG_BUGS 1/* * 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 int flags; /* Status/Action bit flags */} 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 *//* * 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; /* * 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 */ unsigned int 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 *//* * 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/* * 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. */typedef union { unsigned all :8; struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned ili :1; /* Illegal Length Indication */ unsigned eom :1; /* End Of Media Detected */ unsigned abrt :1; /* Aborted command - As defined by ATA */ unsigned mcr :1; /* Media Change Requested - As defined by ATA */ unsigned sense_key :4; /* Sense key of the last failed packet command */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned sense_key :4; /* Sense key of the last failed packet command */ unsigned mcr :1; /* Media Change Requested - As defined by ATA */ unsigned abrt :1; /* Aborted command - As defined by ATA */ unsigned eom :1; /* End Of Media Detected */ unsigned ili :1; /* Illegal Length Indication */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif } b;} idefloppy_error_reg_t;/* * ATAPI Feature Register */typedef union { unsigned all :8; struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned dma :1; /* Using DMA or PIO */ unsigned reserved321 :3; /* Reserved */ unsigned reserved654 :3; /* Reserved (Tag Type) */ unsigned reserved7 :1; /* Reserved */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned reserved7 :1; /* Reserved */ unsigned reserved654 :3; /* Reserved (Tag Type) */ unsigned reserved321 :3; /* Reserved */ unsigned dma :1; /* Using DMA or PIO */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif } b;} idefloppy_feature_reg_t;/* * ATAPI Byte Count Register. */typedef union { unsigned all :16; struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned low :8; /* LSB */ unsigned high :8; /* MSB */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned high :8; /* MSB */ unsigned low :8; /* LSB */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif } b;} idefloppy_bcount_reg_t;/* * ATAPI Interrupt Reason Register. */typedef union { unsigned all :8; struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned cod :1; /* Information transferred is command (1) or data (0) */ unsigned io :1; /* The device requests us to read (1) or write (0) */ unsigned reserved :6; /* Reserved */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned reserved :6; /* Reserved */ unsigned io :1; /* The device requests us to read (1) or write (0) */ unsigned cod :1; /* Information transferred is command (1) or data (0) */#else#error "Bitfield endianness not defined! Check your byteorder.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -