📄 ide-tape.c
字号:
/* * Some defines for the SPACE command */#define IDETAPE_SPACE_OVER_FILEMARK 1#define IDETAPE_SPACE_TO_EOD 3/* * Some defines for the LOAD UNLOAD command */#define IDETAPE_LU_LOAD_MASK 1#define IDETAPE_LU_RETENSION_MASK 2#define IDETAPE_LU_EOT_MASK 4/* * Special requests for our block device strategy routine. * * In order to service a character device command, we add special * requests to the tail of our block device request queue and wait * for their completion. */enum { REQ_IDETAPE_PC1 = (1 << 0), /* packet command (first stage) */ REQ_IDETAPE_PC2 = (1 << 1), /* packet command (second stage) */ REQ_IDETAPE_READ = (1 << 2), REQ_IDETAPE_WRITE = (1 << 3), REQ_IDETAPE_READ_BUFFER = (1 << 4),};/* * Error codes which are returned in rq->errors to the higher part * of the driver. */#define IDETAPE_ERROR_GENERAL 101#define IDETAPE_ERROR_FILEMARK 102#define IDETAPE_ERROR_EOD 103/* * The following is used to format the general configuration word of * the ATAPI IDENTIFY DEVICE command. */struct idetape_id_gcw { 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 */};/* * INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C) */typedef struct { 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 */ __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 */} idetape_inquiry_result_t;/* * READ POSITION packet command - Data Format (From Table 6-57) */typedef struct { unsigned reserved0_10 :2; /* Reserved */ unsigned bpu :1; /* Block Position Unknown */ unsigned reserved0_543 :3; /* Reserved */ unsigned eop :1; /* End Of Partition */ unsigned bop :1; /* Beginning Of Partition */ u8 partition; /* Partition Number */ u8 reserved2, reserved3; /* Reserved */ u32 first_block; /* First Block Location */ u32 last_block; /* Last Block Location (Optional) */ u8 reserved12; /* Reserved */ u8 blocks_in_buffer[3]; /* Blocks In Buffer - (Optional) */ u32 bytes_in_buffer; /* Bytes In Buffer (Optional) */} idetape_read_position_result_t;/* * Follows structures which are related to the SELECT SENSE / MODE SENSE * packet commands. Those packet commands are still not supported * by ide-tape. */#define IDETAPE_BLOCK_DESCRIPTOR 0#define IDETAPE_CAPABILITIES_PAGE 0x2a#define IDETAPE_PARAMTR_PAGE 0x2b /* Onstream DI-x0 only */#define IDETAPE_BLOCK_SIZE_PAGE 0x30#define IDETAPE_BUFFER_FILLING_PAGE 0x33/* * Mode Parameter Header for the MODE SENSE packet command */typedef struct { __u8 mode_data_length; /* Length of the following data transfer */ __u8 medium_type; /* Medium Type */ __u8 dsp; /* Device Specific Parameter */ __u8 bdl; /* Block Descriptor Length */#if 0 /* data transfer page */ __u8 page_code :6; __u8 reserved0_6 :1; __u8 ps :1; /* parameters saveable */ __u8 page_length; /* page Length == 0x02 */ __u8 reserved2; __u8 read32k :1; /* 32k blk size (data only) */ __u8 read32k5 :1; /* 32.5k blk size (data&AUX) */ __u8 reserved3_23 :2; __u8 write32k :1; /* 32k blk size (data only) */ __u8 write32k5 :1; /* 32.5k blk size (data&AUX) */ __u8 reserved3_6 :1; __u8 streaming :1; /* streaming mode enable */#endif} idetape_mode_parameter_header_t;/* * Mode Parameter Block Descriptor the MODE SENSE packet command * * Support for block descriptors is optional. */typedef struct { __u8 density_code; /* Medium density code */ __u8 blocks[3]; /* Number of blocks */ __u8 reserved4; /* Reserved */ __u8 length[3]; /* Block Length */} idetape_parameter_block_descriptor_t;/* * The Data Compression Page, as returned by the MODE SENSE packet command. */typedef struct { unsigned page_code :6; /* Page Code - Should be 0xf */ unsigned reserved0 :1; /* Reserved */ unsigned ps :1; __u8 page_length; /* Page Length - Should be 14 */ unsigned reserved2 :6; /* Reserved */ unsigned dcc :1; /* Data Compression Capable */ unsigned dce :1; /* Data Compression Enable */ unsigned reserved3 :5; /* Reserved */ unsigned red :2; /* Report Exception on Decompression */ unsigned dde :1; /* Data Decompression Enable */ __u32 ca; /* Compression Algorithm */ __u32 da; /* Decompression Algorithm */ __u8 reserved[4]; /* Reserved */} idetape_data_compression_page_t;/* * The Medium Partition Page, as returned by the MODE SENSE packet command. */typedef struct { unsigned page_code :6; /* Page Code - Should be 0x11 */ unsigned reserved1_6 :1; /* Reserved */ unsigned ps :1; __u8 page_length; /* Page Length - Should be 6 */ __u8 map; /* Maximum Additional Partitions - Should be 0 */ __u8 apd; /* Additional Partitions Defined - Should be 0 */ unsigned reserved4_012 :3; /* Reserved */ unsigned psum :2; /* Should be 0 */ unsigned idp :1; /* Should be 0 */ unsigned sdp :1; /* Should be 0 */ unsigned fdp :1; /* Fixed Data Partitions */ __u8 mfr; /* Medium Format Recognition */ __u8 reserved[2]; /* Reserved */} idetape_medium_partition_page_t;/* * Run time configurable parameters. */typedef struct { int dsc_rw_frequency; int dsc_media_access_frequency; int nr_stages;} idetape_config_t;/* * The variables below are used for the character device interface. * Additional state variables are defined in our ide_drive_t structure. */static struct ide_tape_obj * idetape_devs[MAX_HWIFS * MAX_DRIVES];#define ide_tape_f(file) ((file)->private_data)static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i){ struct ide_tape_obj *tape = NULL; mutex_lock(&idetape_ref_mutex); tape = idetape_devs[i]; if (tape) kref_get(&tape->kref); mutex_unlock(&idetape_ref_mutex); return tape;}/* * Function declarations * */static int idetape_chrdev_release (struct inode *inode, struct file *filp);static void idetape_write_release (ide_drive_t *drive, unsigned int minor);/* * Too bad. The drive wants to send us data which we are not ready to accept. * Just throw it away. */static void idetape_discard_data (ide_drive_t *drive, unsigned int bcount){ while (bcount--) (void) HWIF(drive)->INB(IDE_DATA_REG);}static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount){ struct idetape_bh *bh = pc->bh; int count; while (bcount) {#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_input_buffers\n"); idetape_discard_data(drive, bcount); return; }#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount); HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count); bcount -= count; atomic_add(count, &bh->b_count); if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) atomic_set(&bh->b_count, 0); } } pc->bh = bh;}static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount){ struct idetape_bh *bh = pc->bh; int count; while (bcount) {#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_output_buffers\n"); return; }#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)pc->b_count, (unsigned int)bcount); HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count); bcount -= count; pc->b_data += count; pc->b_count -= count; if (!pc->b_count) { pc->bh = bh = bh->b_reqnext; if (bh) { pc->b_data = bh->b_data; pc->b_count = atomic_read(&bh->b_count); } } }}static void idetape_update_buffers (idetape_pc_t *pc){ struct idetape_bh *bh = pc->bh; int count; unsigned int bcount = pc->actually_transferred; if (test_bit(PC_WRITING, &pc->flags)) return; while (bcount) {#if IDETAPE_DEBUG_BUGS if (bh == NULL) { printk(KERN_ERR "ide-tape: bh == NULL in " "idetape_update_buffers\n"); return; }#endif /* IDETAPE_DEBUG_BUGS */ count = min((unsigned int)bh->b_size, (unsigned int)bcount); atomic_set(&bh->b_count, count); if (atomic_read(&bh->b_count) == bh->b_size) bh = bh->b_reqnext; bcount -= count; } pc->bh = bh;}/* * idetape_next_pc_storage returns a pointer to a place in which we can * safely store a packet command, even though we intend to leave the * driver. A storage space for a maximum of IDETAPE_PC_STACK packet * commands is allocated at initialization time. */static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive){ idetape_tape_t *tape = drive->driver_data;#if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) printk(KERN_INFO "ide-tape: pc_stack_index=%d\n", tape->pc_stack_index);#endif /* IDETAPE_DEBUG_LOG */ if (tape->pc_stack_index == IDETAPE_PC_STACK) tape->pc_stack_index=0; return (&tape->pc_stack[tape->pc_stack_index++]);}/* * idetape_next_rq_storage is used along with idetape_next_pc_storage. * Since we queue packet commands in the request queue, we need to * allocate a request, along with the allocation of a packet command. */ /************************************************************** * * * This should get fixed to use kmalloc(.., GFP_ATOMIC) * * followed later on by kfree(). -ml * * * **************************************************************/ static struct request *idetape_next_rq_storage (ide_drive_t *drive){ idetape_tape_t *tape = drive->driver_data;#if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) printk(KERN_INFO "ide-tape: rq_stack_index=%d\n", tape->rq_stack_index);#endif /* IDETAPE_DEBUG_LOG */ if (tape->rq_stack_index == IDETAPE_PC_STACK) tape->rq_stack_index=0; return (&tape->rq_stack[tape->rq_stack_index++]);}/* * idetape_init_pc initializes a packet command. */static void idetape_init_pc (idetape_pc_t *pc){ memset(pc->c, 0, 12); pc->retries = 0; pc->flags = 0; pc->request_transfer = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -