📄 ide-tape.c
字号:
* In pipelined write mode, ide-tape can not return accurate error codes * to the user program since we usually just add the request to the * pipeline without waiting for it to be serviced. In case an error * occurs, I will report it on the next user request. * * In the pipelined read mode, subsequent read requests or forward * filemark spacing will perform correctly, as we preserve all blocks * and filemarks which we encountered during our excess read-ahead. * * For accurate tape positioning and error reporting, disabling * pipelined mode might be the best option. * * You can enable/disable/tune the pipelined operation mode by adjusting * the compile time parameters below. *//* * Possible improvements. * * 1. Support for the ATAPI overlap protocol. * * In order to maximize bus throughput, we currently use the DSC * overlap method which enables ide.c to service requests from the * other device while the tape is busy executing a command. The * DSC overlap method involves polling the tape's status register * for the DSC bit, and servicing the other device while the tape * isn't ready. * * In the current QIC development standard (December 1995), * it is recommended that new tape drives will *in addition* * implement the ATAPI overlap protocol, which is used for the * same purpose - efficient use of the IDE bus, but is interrupt * driven and thus has much less CPU overhead. * * ATAPI overlap is likely to be supported in most new ATAPI * devices, including new ATAPI cdroms, and thus provides us * a method by which we can achieve higher throughput when * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */#define IDETAPE_VERSION "1.17a"#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/devfs_fs_kernel.h>#include <linux/errno.h>#include <linux/genhd.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/ide.h>#include <linux/smp_lock.h>#include <linux/completion.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>#define NO_LONGER_REQUIRED (1)/* * OnStream support */#define ONSTREAM_DEBUG (0)#define OS_CONFIG_PARTITION (0xff)#define OS_DATA_PARTITION (0)#define OS_PARTITION_VERSION (1)#define OS_EW 300#define OS_ADR_MINREV 2#define OS_DATA_STARTFRAME1 20#define OS_DATA_ENDFRAME1 2980/* * partition */typedef struct os_partition_s { __u8 partition_num; __u8 par_desc_ver; __u16 wrt_pass_cntr; __u32 first_frame_addr; __u32 last_frame_addr; __u32 eod_frame_addr;} os_partition_t;/* * DAT entry */typedef struct os_dat_entry_s { __u32 blk_sz; __u16 blk_cnt; __u8 flags; __u8 reserved;} os_dat_entry_t;/* * DAT */#define OS_DAT_FLAGS_DATA (0xc)#define OS_DAT_FLAGS_MARK (0x1)typedef struct os_dat_s { __u8 dat_sz; __u8 reserved1; __u8 entry_cnt; __u8 reserved3; os_dat_entry_t dat_list[16];} os_dat_t;/* * Frame types */#define OS_FRAME_TYPE_FILL (0)#define OS_FRAME_TYPE_EOD (1 << 0)#define OS_FRAME_TYPE_MARKER (1 << 1)#define OS_FRAME_TYPE_HEADER (1 << 3)#define OS_FRAME_TYPE_DATA (1 << 7)/* * AUX */typedef struct os_aux_s { __u32 format_id; /* hardware compability AUX is based on */ char application_sig[4]; /* driver used to write this media */ __u32 hdwr; /* reserved */ __u32 update_frame_cntr; /* for configuration frame */ __u8 frame_type; __u8 frame_type_reserved; __u8 reserved_18_19[2]; os_partition_t partition; __u8 reserved_36_43[8]; __u32 frame_seq_num; __u32 logical_blk_num_high; __u32 logical_blk_num; os_dat_t dat; __u8 reserved188_191[4]; __u32 filemark_cnt; __u32 phys_fm; __u32 last_mark_addr; __u8 reserved204_223[20]; /* * __u8 app_specific[32]; * * Linux specific fields: */ __u32 next_mark_addr; /* when known, points to next marker */ __u8 linux_specific[28]; __u8 reserved_256_511[256];} os_aux_t;typedef struct os_header_s { char ident_str[8]; __u8 major_rev; __u8 minor_rev; __u8 reserved10_15[6]; __u8 par_num; __u8 reserved1_3[3]; os_partition_t partition;} os_header_t;/* * OnStream Tape Parameters Page */typedef struct { unsigned page_code :6; /* Page code - Should be 0x2b */ unsigned reserved1_6 :1; unsigned ps :1; __u8 reserved2; __u8 density; /* kbpi */ __u8 reserved3,reserved4; __u16 segtrk; /* segment of per track */ __u16 trks; /* tracks per tape */ __u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10;} onstream_tape_paramtr_page_t;/* * OnStream ADRL frame */#define OS_FRAME_SIZE (32 * 1024 + 512)#define OS_DATA_SIZE (32 * 1024)#define OS_AUX_SIZE (512)/* * internal error codes for onstream */#define OS_PART_ERROR 2#define OS_WRITE_ERROR 1#include <linux/mtio.h>/**************************** Tunable parameters *****************************//* * Pipelined mode parameters. * * We try to use the minimum number of stages which is enough to * keep the tape constantly streaming. To accomplish that, we implement * a feedback loop around the maximum number of stages: * * We start from MIN maximum stages (we will not even use MIN stages * if we don't need them), increment it by RATE*(MAX-MIN) * whenever we sense that the pipeline is empty, until we reach * the optimum value or until we reach MAX. * * Setting the following parameter to 0 will disable the pipelined mode. */#define IDETAPE_MIN_PIPELINE_STAGES 200#define IDETAPE_MAX_PIPELINE_STAGES 400#define IDETAPE_INCREASE_STAGES_RATE 20/* * The following are used to debug the driver: * * Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities. * Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control. * Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in * some places. * * Setting them to 0 will restore normal operation mode: * * 1. Disable logging normal successful operations. * 2. Disable self-sanity checks. * 3. Errors will still be logged, of course. * * All the #if DEBUG code will be removed some day, when the driver * is verified to be stable enough. This will make it much more * esthetic. */#define IDETAPE_DEBUG_INFO 1#define IDETAPE_DEBUG_LOG 1#define IDETAPE_DEBUG_LOG_VERBOSE 0#define IDETAPE_DEBUG_BUGS 1/* * After each failed packet command we issue a request sense command * and retry the packet command IDETAPE_MAX_PC_RETRIES times. * * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries. */#define IDETAPE_MAX_PC_RETRIES 3/* * With each packet command, we allocate a buffer of * IDETAPE_PC_BUFFER_SIZE bytes. This is used for several packet * commands (Not for READ/WRITE commands). */#define IDETAPE_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 IDETAPE_PC_STACK (10 + IDETAPE_MAX_PC_RETRIES)/* * Some tape drives require a long irq timeout */#define IDETAPE_WAIT_CMD (60*HZ)/* * The following parameter is used to select the point in the internal * tape fifo in which we will start to refill the buffer. Decreasing * the following parameter will improve the system's latency and * interactive response, while using a high value might improve sytem * throughput. */#define IDETAPE_FIFO_THRESHOLD 2/* * DSC polling parameters. * * Polling for DSC (a single bit in the status register) is a very * important function in ide-tape. There are two cases in which we * poll for DSC: * * 1. Before a read/write packet command, to ensure that we * can transfer data from/to the tape's data buffers, without * causing an actual media access. In case the tape is not * ready yet, we take out our request from the device * request queue, so that ide.c will service requests from * the other device on the same interface meanwhile. * * 2. After the successful initialization of a "media access * packet command", which is a command which can take a long * time to complete (it can be several seconds or even an hour). * * Again, we postpone our request in the middle to free the bus * for the other device. The polling frequency here should be * lower than the read/write frequency since those media access * commands are slow. We start from a "fast" frequency - * IDETAPE_DSC_MA_FAST (one second), and if we don't receive DSC * after IDETAPE_DSC_MA_THRESHOLD (5 minutes), we switch it to a * lower frequency - IDETAPE_DSC_MA_SLOW (1 minute). * * We also set a timeout for the timer, in case something goes wrong. * The timeout should be longer then the maximum execution time of a * tape operation. */ /* * DSC timings. */#define IDETAPE_DSC_RW_MIN 5*HZ/100 /* 50 msec */#define IDETAPE_DSC_RW_MAX 40*HZ/100 /* 400 msec */#define IDETAPE_DSC_RW_TIMEOUT 2*60*HZ /* 2 minutes */#define IDETAPE_DSC_MA_FAST 2*HZ /* 2 seconds */#define IDETAPE_DSC_MA_THRESHOLD 5*60*HZ /* 5 minutes */#define IDETAPE_DSC_MA_SLOW 30*HZ /* 30 seconds */#define IDETAPE_DSC_MA_TIMEOUT 2*60*60*HZ /* 2 hours *//*************************** End of tunable parameters ***********************//* * Debugging/Performance analysis * * I/O trace support */#define USE_IOTRACE 0#if USE_IOTRACE#include <linux/io_trace.h>#define IO_IDETAPE_FIFO 500#endif/* * Read/Write error simulation */#define SIMULATE_ERRORS 0/* * For general magnetic tape device compatibility. */typedef enum { idetape_direction_none, idetape_direction_read, idetape_direction_write} idetape_chrdev_direction_t;/* * Our view of a packet command. */typedef struct idetape_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 */ struct buffer_head *bh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -