📄 ide-floppy.c
字号:
unsigned reserved3 :1; /* Reserved */ unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ unsigned one5 :1; /* Should be set to 1 */ unsigned reserved6 :1; /* Reserved */ unsigned one7 :1; /* Should be set to 1 */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned one7 :1; /* Should be set to 1 */ unsigned reserved6 :1; /* Reserved */ unsigned one5 :1; /* Should be set to 1 */ unsigned drv :1; /* The responding drive will be drive 0 (0) or drive 1 (1) */ unsigned reserved3 :1; /* Reserved */ unsigned sam_lun :3; /* Logical unit number */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif } b;} idefloppy_drivesel_reg_t;/* * ATAPI Device Control Register */typedef union { unsigned all :8; struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned zero0 :1; /* Should be set to zero */ unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ unsigned one3 :1; /* Should be set to 1 */ unsigned reserved4567 :4; /* Reserved */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned reserved4567 :4; /* Reserved */ unsigned one3 :1; /* Should be set to 1 */ unsigned srst :1; /* ATA software reset. ATAPI devices should use the new ATAPI srst. */ unsigned nien :1; /* Device interrupt is disabled (1) or enabled (0) */ unsigned zero0 :1; /* Should be set to zero */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif } b;} idefloppy_control_reg_t;/* * The following is used to format the general configuration word of * the ATAPI IDENTIFY DEVICE command. */struct idefloppy_id_gcw { #if defined(__LITTLE_ENDIAN_BITFIELD) unsigned packet_size :2; /* Packet Size */ unsigned reserved234 :3; /* Reserved */ unsigned drq_type :2; /* Command packet DRQ type */ unsigned removable :1; /* Removable media */ unsigned device_type :5; /* Device type */ unsigned reserved13 :1; /* Reserved */ unsigned protocol :2; /* Protocol type */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned protocol :2; /* Protocol type */ unsigned reserved13 :1; /* Reserved */ unsigned device_type :5; /* Device type */ unsigned removable :1; /* Removable media */ unsigned drq_type :2; /* Command packet DRQ type */ unsigned reserved234 :3; /* Reserved */ unsigned packet_size :2; /* Packet Size */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif};/* * INQUIRY packet command - Data Format */typedef struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned device_type :5; /* Peripheral Device Type */ unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ unsigned reserved1_6t0 :7; /* Reserved */ unsigned rmb :1; /* Removable Medium Bit */ unsigned ansi_version :3; /* ANSI Version */ unsigned ecma_version :3; /* ECMA Version */ unsigned iso_version :2; /* ISO Version */ unsigned response_format :4; /* Response Data Format */ unsigned reserved3_45 :2; /* Reserved */ unsigned reserved3_6 :1; /* TrmIOP - Reserved */ unsigned reserved3_7 :1; /* AENC - Reserved */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned reserved0_765 :3; /* Peripheral Qualifier - Reserved */ unsigned device_type :5; /* Peripheral Device Type */ unsigned rmb :1; /* Removable Medium Bit */ unsigned reserved1_6t0 :7; /* Reserved */ unsigned iso_version :2; /* ISO Version */ unsigned ecma_version :3; /* ECMA Version */ unsigned ansi_version :3; /* ANSI Version */ unsigned reserved3_7 :1; /* AENC - Reserved */ unsigned reserved3_6 :1; /* TrmIOP - Reserved */ unsigned reserved3_45 :2; /* Reserved */ unsigned response_format :4; /* Response Data Format */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u8 additional_length; /* Additional Length (total_length-4) */ u8 rsv5, rsv6, rsv7; /* Reserved */ u8 vendor_id[8]; /* Vendor Identification */ u8 product_id[16]; /* Product Identification */ u8 revision_level[4]; /* Revision Level */ u8 vendor_specific[20]; /* Vendor Specific - Optional */ u8 reserved56t95[40]; /* Reserved - Optional */ /* Additional information may be returned */} idefloppy_inquiry_result_t;/* * REQUEST SENSE packet command result - Data Format. */typedef struct {#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned error_code :7; /* Current error (0x70) */ unsigned valid :1; /* The information field conforms to SFF-8070i */ u8 reserved1 :8; /* Reserved */ unsigned sense_key :4; /* Sense Key */ unsigned reserved2_4 :1; /* Reserved */ unsigned ili :1; /* Incorrect Length Indicator */ unsigned reserved2_67 :2;#elif defined(__BIG_ENDIAN_BITFIELD) unsigned valid :1; /* The information field conforms to SFF-8070i */ unsigned error_code :7; /* Current error (0x70) */ u8 reserved1 :8; /* Reserved */ unsigned reserved2_67 :2; unsigned ili :1; /* Incorrect Length Indicator */ unsigned reserved2_4 :1; /* Reserved */ unsigned sense_key :4; /* Sense Key */#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u32 information __attribute__ ((packed)); u8 asl; /* Additional sense length (n-7) */ u32 command_specific; /* Additional command specific information */ u8 asc; /* Additional Sense Code */ u8 ascq; /* Additional Sense Code Qualifier */ u8 replaceable_unit_code; /* Field Replaceable Unit Code */ u8 reserved[3]; u8 pad[2]; /* Padding to 20 bytes */} idefloppy_request_sense_result_t;/* * Pages of the SELECT SENSE / MODE SENSE packet commands. */#define IDEFLOPPY_CAPABILITIES_PAGE 0x1b#define IDEFLOPPY_FLEXIBLE_DISK_PAGE 0x05/* * Mode Parameter Header for the MODE SENSE packet command */typedef struct { u16 mode_data_length; /* Length of the following data transfer */ u8 medium_type; /* Medium Type */#if defined(__LITTLE_ENDIAN_BITFIELD) unsigned reserved3 :7; unsigned wp :1; /* Write protect */#elif defined(__BIG_ENDIAN_BITFIELD) unsigned wp :1; /* Write protect */ unsigned reserved3 :7;#else#error "Bitfield endianness not defined! Check your byteorder.h"#endif u8 reserved[4];} idefloppy_mode_parameter_header_t;#define IDEFLOPPY_MIN(a,b) ((a)<(b) ? (a):(b))#define IDEFLOPPY_MAX(a,b) ((a)>(b) ? (a):(b))/* * Too bad. The drive wants to send us data which we are not ready to accept. * Just throw it away. */static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount){ while (bcount--) IN_BYTE (IDE_DATA_REG);}#if IDEFLOPPY_DEBUG_BUGSstatic void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount){ while (bcount--) OUT_BYTE (0, IDE_DATA_REG);}#endif /* IDEFLOPPY_DEBUG_BUGS *//* * idefloppy_end_request is used to finish servicing a request. * * For read/write requests, we will call ide_end_request to pass to the * next buffer. */static void idefloppy_end_request (byte uptodate, ide_hwgroup_t *hwgroup){ ide_drive_t *drive = hwgroup->drive; idefloppy_floppy_t *floppy = drive->driver_data; struct request *rq = hwgroup->rq; int error;#if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Reached idefloppy_end_request\n");#endif /* IDEFLOPPY_DEBUG_LOG */ switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; case 1: error = 0; break; default: error = uptodate; } if (error) floppy->failed_pc = NULL; /* Why does this happen? */ if (!rq) return; if (!IDEFLOPPY_RQ_CMD (rq->cmd)) { ide_end_request (uptodate, hwgroup); return; } rq->errors = error; ide_end_drive_cmd (drive, 0, 0);}static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount){ struct request *rq = pc->rq; struct buffer_head *bh = rq->bh; int count; while (bcount) { if (pc->b_count == bh->b_size) { rq->sector += rq->current_nr_sectors; rq->nr_sectors -= rq->current_nr_sectors; idefloppy_end_request (1, HWGROUP(drive)); if ((bh = rq->bh) != NULL) pc->b_count = 0; } if (bh == NULL) { printk (KERN_ERR "%s: bh == NULL in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount); idefloppy_discard_data (drive, bcount); return; } count = IDEFLOPPY_MIN (bh->b_size - pc->b_count, bcount); atapi_input_bytes (drive, bh->b_data + pc->b_count, count); bcount -= count; pc->b_count += count; }}static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount){ struct request *rq = pc->rq; struct buffer_head *bh = rq->bh; int count; while (bcount) { if (!pc->b_count) { rq->sector += rq->current_nr_sectors; rq->nr_sectors -= rq->current_nr_sectors; idefloppy_end_request (1, HWGROUP(drive)); if ((bh = rq->bh) != NULL) { pc->b_data = bh->b_data; pc->b_count = bh->b_size; } } if (bh == NULL) { printk (KERN_ERR "%s: bh == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); idefloppy_write_zeros (drive, bcount); return; } count = IDEFLOPPY_MIN (pc->b_count, bcount); atapi_output_bytes (drive, pc->b_data, count); bcount -= count; pc->b_data += count; pc->b_count -= count; }}#ifdef CONFIG_BLK_DEV_IDEDMAstatic void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc){ struct request *rq = pc->rq; struct buffer_head *bh = rq->bh; while ((bh = rq->bh) != NULL) idefloppy_end_request (1, HWGROUP(drive));}#endif /* CONFIG_BLK_DEV_IDEDMA *//* * idefloppy_queue_pc_head generates a new packet command request in front * of the request queue, before the current request, so that it will be * processed immediately, on the next pass through the driver. */static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq){ ide_init_drive_cmd (rq); rq->buffer = (char *) pc; rq->cmd = IDEFLOPPY_PC_RQ; (void) ide_do_drive_cmd (drive, rq, ide_preempt);}static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; if (floppy->pc_stack_index==IDEFLOPPY_PC_STACK) floppy->pc_stack_index=0; return (&floppy->pc_stack[floppy->pc_stack_index++]);}static struct request *idefloppy_next_rq_storage (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; if (floppy->rq_stack_index==IDEFLOPPY_PC_STACK) floppy->rq_stack_index=0; return (&floppy->rq_stack[floppy->rq_stack_index++]);}/* * idefloppy_analyze_error is called on each failed packet command retry * to analyze the request sense. */static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result){ idefloppy_floppy_t *floppy = drive->driver_data; floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq;#if IDEFLOPPY_DEBUG_LOG if (floppy->failed_pc) printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); else printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq);#endif /* IDEFLOPPY_DEBUG_LOG */}static void idefloppy_request_sense_callback (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data;#if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n");#endif /* IDEFLOPPY_DEBUG_LOG */ if (!floppy->pc->error) { idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); idefloppy_end_request (1,HWGROUP (drive)); } else { printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); idefloppy_end_request (0,HWGROUP (drive)); }}/* * General packet command callback function. */static void idefloppy_pc_callback (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n");#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive));}/* * idefloppy_init_pc initializes a packet command. */static void idefloppy_init_pc (idefloppy_pc_t *pc){ memset (pc->c, 0, 12); pc->retries = 0; pc->flags = 0; pc->request_transfer = 0; pc->buffer = pc->pc_buffer; pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE; pc->b_data = NULL; pc->callback = &idefloppy_pc_callback;}static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc){ idefloppy_init_pc (pc); pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD; pc->c[4] = 255; pc->request_transfer = 18; pc->callback = &idefloppy_request_sense_callback;}/* * idefloppy_retry_pc is called when an error was detected during the * last packet command. We queue a request sense packet command in * the head of the request list. */static void idefloppy_retry_pc (ide_drive_t *drive){ idefloppy_pc_t *pc; struct request *rq; idefloppy_error_reg_t error; error.all = IN_BYTE (IDE_ERROR_REG); pc = idefloppy_next_pc_storage (drive); rq = idefloppy_next_rq_storage (drive); idefloppy_create_request_sense_cmd (pc); idefloppy_queue_pc_head (drive, pc, rq);}/* * idefloppy_pc_intr is the usual interrupt handler which will be called * during a packet command. */static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive){ idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_status_reg_t status; idefloppy_bcount_reg_t bcount; idefloppy_ireason_reg_t ireason; idefloppy_pc_t *pc=floppy->pc; struct request *rq = pc->rq; unsigned int temp;#if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n");#endif /* IDEFLOPPY_DEBUG_LOG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -