📄 ide-tape.c
字号:
*/typedef struct { unsigned page_code :6; /* Page code - Should be 0x30 */ unsigned reserved1_6 :1; unsigned ps :1; __u8 page_length; /* Page Length - Should be 2 */ __u8 reserved2; unsigned play32 :1; unsigned play32_5 :1; unsigned reserved2_23 :2; unsigned record32 :1; unsigned record32_5 :1; unsigned reserved2_6 :1; unsigned one :1;} idetape_block_size_page_t;/* * A pipeline stage. */typedef struct idetape_stage_s { struct request rq; /* The corresponding request */ struct idetape_bh *bh; /* The data buffers */ struct idetape_stage_s *next; /* Pointer to the next stage */} idetape_stage_t;/* * REQUEST SENSE packet command result - Data Format. */typedef struct { unsigned error_code :7; /* Current of deferred errors */ unsigned valid :1; /* The information field conforms to QIC-157C */ __u8 reserved1 :8; /* Segment Number - Reserved */ unsigned sense_key :4; /* Sense Key */ unsigned reserved2_4 :1; /* Reserved */ unsigned ili :1; /* Incorrect Length Indicator */ unsigned eom :1; /* End Of Medium */ unsigned filemark :1; /* Filemark */ __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 */ unsigned sk_specific1 :7; /* Sense Key Specific */ unsigned sksv :1; /* Sense Key Specific information is valid */ __u8 sk_specific2; /* Sense Key Specific */ __u8 sk_specific3; /* Sense Key Specific */ __u8 pad[2]; /* Padding to 20 bytes */} idetape_request_sense_result_t;/* * 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 idetape_tape_t, defined below. */typedef struct ide_tape_obj { ide_drive_t *drive; ide_driver_t *driver; struct gendisk *disk; struct kref kref; /* * Since a typical character device operation requires more * than one packet command, we provide here enough memory * for the maximum of interconnected packet commands. * The packet commands are stored in the circular array pc_stack. * pc_stack_index points to the last used entry, and warps around * to the start when we get to the last array entry. * * pc points to the current processed packet command. * * failed_pc points to the last failed packet command, or contains * NULL if we do not need to retry any packet command. This is * required since an additional packet command is needed before the * retry, to get detailed information on what went wrong. */ /* Current packet command */ idetape_pc_t *pc; /* Last failed packet command */ idetape_pc_t *failed_pc; /* Packet command stack */ idetape_pc_t pc_stack[IDETAPE_PC_STACK]; /* Next free packet command storage space */ int pc_stack_index; struct request rq_stack[IDETAPE_PC_STACK]; /* We implement a circular array */ int rq_stack_index; /* * DSC polling variables. * * While polling for DSC we use postponed_rq to postpone the * current request so that ide.c will be able to service * pending requests on the other device. Note that at most * we will have only one DSC (usually data transfer) request * in the device request queue. Additional requests can be * queued in our internal pipeline, but they will be visible * to ide.c only one at a time. */ struct request *postponed_rq; /* The time in which we started polling for DSC */ unsigned long dsc_polling_start; /* Timer used to poll for dsc */ struct timer_list dsc_timer; /* Read/Write dsc polling frequency */ unsigned long best_dsc_rw_frequency; /* The current polling frequency */ unsigned long dsc_polling_frequency; /* Maximum waiting time */ unsigned long dsc_timeout; /* * Read position information */ u8 partition; /* Current block */ unsigned int first_frame_position; unsigned int last_frame_position; unsigned int blocks_in_buffer; /* * Last error information */ u8 sense_key, asc, ascq; /* * Character device operation */ unsigned int minor; /* device name */ char name[4]; /* Current character device data transfer direction */ idetape_chrdev_direction_t chrdev_direction; /* * Device information */ /* Usually 512 or 1024 bytes */ unsigned short tape_block_size; int user_bs_factor; /* Copy of the tape's Capabilities and Mechanical Page */ idetape_capabilities_page_t capabilities; /* * Active data transfer request parameters. * * At most, there is only one ide-tape originated data transfer * request in the device request queue. This allows ide.c to * easily service requests from the other device when we * postpone our active request. In the pipelined operation * mode, we use our internal pipeline structure to hold * more data requests. * * The data buffer size is chosen based on the tape's * recommendation. */ /* Pointer to the request which is waiting in the device request queue */ struct request *active_data_request; /* Data buffer size (chosen based on the tape's recommendation */ int stage_size; idetape_stage_t *merge_stage; int merge_stage_size; struct idetape_bh *bh; char *b_data; int b_count; /* * Pipeline parameters. * * To accomplish non-pipelined mode, we simply set the following * variables to zero (or NULL, where appropriate). */ /* Number of currently used stages */ int nr_stages; /* Number of pending stages */ int nr_pending_stages; /* We will not allocate more than this number of stages */ int max_stages, min_pipeline, max_pipeline; /* The first stage which will be removed from the pipeline */ idetape_stage_t *first_stage; /* The currently active stage */ idetape_stage_t *active_stage; /* Will be serviced after the currently active request */ idetape_stage_t *next_stage; /* New requests will be added to the pipeline here */ idetape_stage_t *last_stage; /* Optional free stage which we can use */ idetape_stage_t *cache_stage; int pages_per_stage; /* Wasted space in each stage */ int excess_bh_size; /* Status/Action flags: long for set_bit */ unsigned long flags; /* protects the ide-tape queue */ spinlock_t spinlock; /* * Measures average tape speed */ unsigned long avg_time; int avg_size; int avg_speed; /* last sense information */ idetape_request_sense_result_t sense; char vendor_id[10]; char product_id[18]; char firmware_revision[6]; int firmware_revision_num; /* the door is currently locked */ int door_locked; /* the tape hardware is write protected */ char drv_write_prot; /* the tape is write protected (hardware or opened as read-only) */ char write_prot; /* * Limit the number of times a request can * be postponed, to avoid an infinite postpone * deadlock. */ /* request postpone count limit */ int postpone_cnt; /* * Measures number of frames: * * 1. written/read to/from the driver pipeline (pipeline_head). * 2. written/read to/from the tape buffers (idetape_bh). * 3. written/read by the tape to/from the media (tape_head). */ int pipeline_head; int buffer_head; int tape_head; int last_tape_head; /* * Speed control at the tape buffers input/output */ unsigned long insert_time; int insert_size; int insert_speed; int max_insert_speed; int measure_insert_time; /* * Measure tape still time, in milliseconds */ unsigned long tape_still_time_begin; int tape_still_time; /* * Speed regulation negative feedback loop */ int speed_control; int pipeline_head_speed; int controlled_pipeline_head_speed; int uncontrolled_pipeline_head_speed; int controlled_last_pipeline_head; int uncontrolled_last_pipeline_head; unsigned long uncontrolled_pipeline_head_time; unsigned long controlled_pipeline_head_time; int controlled_previous_pipeline_head; int uncontrolled_previous_pipeline_head; unsigned long controlled_previous_head_time; unsigned long uncontrolled_previous_head_time; int restart_speed_control_req; /* * Debug_level determines amount of debugging output; * can be changed using /proc/ide/hdx/settings * 0 : almost no debugging output * 1 : 0+output errors only * 2 : 1+output all sensekey/asc * 3 : 2+follow all chrdev related procedures * 4 : 3+follow all procedures * 5 : 4+include pc_stack rq_stack info * 6 : 5+USE_COUNT updates */ int debug_level; } idetape_tape_t;static DEFINE_MUTEX(idetape_ref_mutex);static struct class *idetape_sysfs_class;#define to_ide_tape(obj) container_of(obj, struct ide_tape_obj, kref)#define ide_tape_g(disk) \ container_of((disk)->private_data, struct ide_tape_obj, driver)static struct ide_tape_obj *ide_tape_get(struct gendisk *disk){ struct ide_tape_obj *tape = NULL; mutex_lock(&idetape_ref_mutex); tape = ide_tape_g(disk); if (tape) kref_get(&tape->kref); mutex_unlock(&idetape_ref_mutex); return tape;}static void ide_tape_release(struct kref *);static void ide_tape_put(struct ide_tape_obj *tape){ mutex_lock(&idetape_ref_mutex); kref_put(&tape->kref, ide_tape_release); mutex_unlock(&idetape_ref_mutex);}/* * Tape door status */#define DOOR_UNLOCKED 0#define DOOR_LOCKED 1#define DOOR_EXPLICITLY_LOCKED 2/* * Tape flag bits values. */#define IDETAPE_IGNORE_DSC 0#define IDETAPE_ADDRESS_VALID 1 /* 0 When the tape position is unknown */#define IDETAPE_BUSY 2 /* Device already opened */#define IDETAPE_PIPELINE_ERROR 3 /* Error detected in a pipeline stage */#define IDETAPE_DETECT_BS 4 /* Attempt to auto-detect the current user block size */#define IDETAPE_FILEMARK 5 /* Currently on a filemark */#define IDETAPE_DRQ_INTERRUPT 6 /* DRQ interrupt device */#define IDETAPE_READ_ERROR 7#define IDETAPE_PIPELINE_ACTIVE 8 /* pipeline active *//* 0 = no tape is loaded, so we don't rewind after ejecting */#define IDETAPE_MEDIUM_PRESENT 9/* * Supported ATAPI tape drives packet commands */#define IDETAPE_TEST_UNIT_READY_CMD 0x00#define IDETAPE_REWIND_CMD 0x01#define IDETAPE_REQUEST_SENSE_CMD 0x03#define IDETAPE_READ_CMD 0x08#define IDETAPE_WRITE_CMD 0x0a#define IDETAPE_WRITE_FILEMARK_CMD 0x10#define IDETAPE_SPACE_CMD 0x11#define IDETAPE_INQUIRY_CMD 0x12#define IDETAPE_ERASE_CMD 0x19#define IDETAPE_MODE_SENSE_CMD 0x1a#define IDETAPE_MODE_SELECT_CMD 0x15#define IDETAPE_LOAD_UNLOAD_CMD 0x1b#define IDETAPE_PREVENT_CMD 0x1e#define IDETAPE_LOCATE_CMD 0x2b#define IDETAPE_READ_POSITION_CMD 0x34#define IDETAPE_READ_BUFFER_CMD 0x3c#define IDETAPE_SET_SPEED_CMD 0xbb/* * Some defines for the READ BUFFER command */#define IDETAPE_RETRIEVE_FAULTY_BLOCK 6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -