📄 st.c
字号:
dev, debugging);)}static int st_set_options(Scsi_Tape *STp, long options){ int value; long code; ST_mode *STm; int dev = TAPE_NR(STp->devt); STm = &(STp->modes[STp->current_mode]); if (!STm->defined) { memcpy(STm, &(STp->modes[0]), sizeof(ST_mode)); modes_defined = TRUE; DEBC(printk(ST_DEB_MSG "st%d: Initialized mode %d definition from mode 0\n", dev, STp->current_mode)); } code = options & MT_ST_OPTIONS; if (code == MT_ST_BOOLEANS) { STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0; STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0; STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0; STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0; STp->two_fm = (options & MT_ST_TWO_FM) != 0; STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0; STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0; STp->can_bsr = (options & MT_ST_CAN_BSR) != 0; STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0; if ((STp->device)->scsi_level >= SCSI_2) STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0; STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0; STm->sysv = (options & MT_ST_SYSV) != 0; DEB( debugging = (options & MT_ST_DEBUGGING) != 0; ) st_log_options(STp, STm, dev); } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { value = (code == MT_ST_SETBOOLEANS); if ((options & MT_ST_BUFFER_WRITES) != 0) STm->do_buffer_writes = value; if ((options & MT_ST_ASYNC_WRITES) != 0) STm->do_async_writes = value; if ((options & MT_ST_DEF_WRITES) != 0) STm->defaults_for_writes = value; if ((options & MT_ST_READ_AHEAD) != 0) STm->do_read_ahead = value; if ((options & MT_ST_TWO_FM) != 0) STp->two_fm = value; if ((options & MT_ST_FAST_MTEOM) != 0) STp->fast_mteom = value; if ((options & MT_ST_AUTO_LOCK) != 0) STp->do_auto_lock = value; if ((options & MT_ST_CAN_BSR) != 0) STp->can_bsr = value; if ((options & MT_ST_NO_BLKLIMS) != 0) STp->omit_blklims = value; if ((STp->device)->scsi_level >= SCSI_2 && (options & MT_ST_CAN_PARTITIONS) != 0) STp->can_partitions = value; if ((options & MT_ST_SCSI2LOGICAL) != 0) STp->scsi2_logical = value; if ((options & MT_ST_SYSV) != 0) STm->sysv = value; DEB( if ((options & MT_ST_DEBUGGING) != 0) debugging = value; ) st_log_options(STp, STm, dev); } else if (code == MT_ST_WRITE_THRESHOLD) { value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE; if (value < 1 || value > st_buffer_size) { printk(KERN_WARNING "st%d: Write threshold %d too small or too large.\n", dev, value); return (-EIO); } STp->write_threshold = value; printk(KERN_INFO "st%d: Write threshold set to %d bytes.\n", dev, value); } else if (code == MT_ST_DEF_BLKSIZE) { value = (options & ~MT_ST_OPTIONS); if (value == ~MT_ST_OPTIONS) { STm->default_blksize = (-1); printk(KERN_INFO "st%d: Default block size disabled.\n", dev); } else { STm->default_blksize = value; printk(KERN_INFO "st%d: Default block size set to %d bytes.\n", dev, STm->default_blksize); } } else if (code == MT_ST_TIMEOUTS) { value = (options & ~MT_ST_OPTIONS); if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) { STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ; printk(KERN_INFO "st%d: Long timeout set to %d seconds.\n", dev, (value & ~MT_ST_SET_LONG_TIMEOUT)); } else { STp->timeout = value * HZ; printk(KERN_INFO "st%d: Normal timeout set to %d seconds.\n", dev, value); } } else if (code == MT_ST_DEF_OPTIONS) { code = (options & ~MT_ST_CLEAR_DEFAULT); value = (options & MT_ST_CLEAR_DEFAULT); if (code == MT_ST_DEF_DENSITY) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_density = (-1); printk(KERN_INFO "st%d: Density default disabled.\n", dev); } else { STm->default_density = value & 0xff; printk(KERN_INFO "st%d: Density default set to %x\n", dev, STm->default_density); } } else if (code == MT_ST_DEF_DRVBUFFER) { if (value == MT_ST_CLEAR_DEFAULT) { STp->default_drvbuffer = 0xff; printk(KERN_INFO "st%d: Drive buffer default disabled.\n", dev); } else { STp->default_drvbuffer = value & 7; printk(KERN_INFO "st%d: Drive buffer default set to %x\n", dev, STp->default_drvbuffer); } } else if (code == MT_ST_DEF_COMPRESSION) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_compression = ST_DONT_TOUCH; printk(KERN_INFO "st%d: Compression default disabled.\n", dev); } else { STm->default_compression = (value & 1 ? ST_YES : ST_NO); printk(KERN_INFO "st%d: Compression default set to %x\n", dev, (value & 1)); } } } else return (-EIO); return 0;}#define MODE_HEADER_LENGTH 4/* Mode header and page byte offsets */#define MH_OFF_DATA_LENGTH 0#define MH_OFF_MEDIUM_TYPE 1#define MH_OFF_DEV_SPECIFIC 2#define MH_OFF_BDESCS_LENGTH 3#define MP_OFF_PAGE_NBR 0#define MP_OFF_PAGE_LENGTH 1/* Mode header and page bit masks */#define MH_BIT_WP 0x80#define MP_MSK_PAGE_NBR 0x3f/* Don't return block descriptors */#define MODE_SENSE_OMIT_BDESCS 0x08#define MODE_SELECT_PAGE_FORMAT 0x10/* Read a mode page into the tape buffer. The block descriptors are included if incl_block_descs is true. */static int read_mode_page(Scsi_Tape *STp, int page, int omit_block_descs){ unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request *SRpnt = NULL; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SENSE; if (omit_block_descs) cmd[1] = MODE_SENSE_OMIT_BDESCS; cmd[2] = page; cmd[4] = 255; SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE); if (SRpnt == NULL) return (STp->buffer)->syscall_result; scsi_release_request(SRpnt); return (STp->buffer)->syscall_result;}/* Send the mode page in the tape buffer to the drive. Assumes that the mode data in the buffer is correctly formatted. */static int write_mode_page(Scsi_Tape *STp, int page){ int pgo; unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request *SRpnt = NULL; memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = MODE_SELECT; cmd[1] = MODE_SELECT_PAGE_FORMAT; pgo = MODE_HEADER_LENGTH + (STp->buffer)->b_data[MH_OFF_BDESCS_LENGTH]; cmd[4] = pgo + (STp->buffer)->b_data[pgo + MP_OFF_PAGE_LENGTH] + 2; /* Clear reserved fields */ (STp->buffer)->b_data[MH_OFF_DATA_LENGTH] = 0; (STp->buffer)->b_data[MH_OFF_MEDIUM_TYPE] = 0; (STp->buffer)->b_data[MH_OFF_DEV_SPECIFIC] &= ~MH_BIT_WP; (STp->buffer)->b_data[pgo + MP_OFF_PAGE_NBR] &= MP_MSK_PAGE_NBR; SRpnt = st_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE); if (SRpnt == NULL) return (STp->buffer)->syscall_result; scsi_release_request(SRpnt); return (STp->buffer)->syscall_result;}#define COMPRESSION_PAGE 0x0f#define COMPRESSION_PAGE_LENGTH 16#define CP_OFF_DCE_DCC 2#define DCE_MASK 0x80#define DCC_MASK 0x40#define RED_MASK 0x60/* Control the compression with mode page 15. Algorithm not changed if zero. The block descriptors are read and written because Sony SDT-7000 does not work without this (suggestion from Michael Schaefer <Michael.Schaefer@dlr.de>). Including block descriptors should not cause any harm to other drives. */static int st_compression(Scsi_Tape * STp, int state){ int retval; int mpoffs; /* Offset to mode page start */ unsigned char *b_data = (STp->buffer)->b_data; DEB( int dev = TAPE_NR(STp->devt); ) if (STp->ready != ST_READY) return (-EIO); /* Read the current page contents */ retval = read_mode_page(STp, COMPRESSION_PAGE, FALSE); if (retval) { DEBC(printk(ST_DEB_MSG "st%d: Compression mode page not supported.\n", dev)); return (-EIO); } mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH]; DEBC(printk(ST_DEB_MSG "st%d: Compression state is %d.\n", dev, (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0))); /* Check if compression can be changed */ if ((b_data[mpoffs + 2] & DCC_MASK) == 0) { DEBC(printk(ST_DEB_MSG "st%d: Compression not supported.\n", dev)); return (-EIO); } /* Do the change */ if (state) b_data[mpoffs + CP_OFF_DCE_DCC] |= DCE_MASK; else b_data[mpoffs + CP_OFF_DCE_DCC] &= ~DCE_MASK; retval = write_mode_page(STp, COMPRESSION_PAGE); if (retval) { DEBC(printk(ST_DEB_MSG "st%d: Compression change failed.\n", dev)); return (-EIO); } DEBC(printk(ST_DEB_MSG "st%d: Compression state changed to %d.\n", dev, state)); STp->compression_changed = TRUE; return 0;}/* Internal ioctl function */static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg){ int timeout; long ltmp; int i, ioctl_result; int chg_eof = TRUE; unsigned char cmd[MAX_COMMAND_SIZE]; Scsi_Request *SRpnt; ST_partstat *STps; int fileno, blkno, at_sm, undone; int datalen = 0, direction = SCSI_DATA_NONE; int dev = TAPE_NR(STp->devt); if (STp->ready != ST_READY && cmd_in != MTLOAD) { if (STp->ready == ST_NO_TAPE) return (-ENOMEDIUM); else return (-EIO); } timeout = STp->long_timeout; STps = &(STp->ps[STp->partition]); fileno = STps->drv_file; blkno = STps->drv_block; at_sm = STps->at_sm; memset(cmd, 0, MAX_COMMAND_SIZE); switch (cmd_in) { case MTFSFM: chg_eof = FALSE; /* Changed from the FSF after this */ case MTFSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; DEBC(printk(ST_DEB_MSG "st%d: Spacing tape forward over %d filemarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4])); if (fileno >= 0) fileno += arg; blkno = 0; at_sm &= (arg == 0); break; case MTBSFM: chg_eof = FALSE; /* Changed from the FSF after this */ case MTBSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ ltmp = (-arg); cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; DEBC( if (cmd[2] & 0x80) ltmp = 0xff000000; ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; printk(ST_DEB_MSG "st%d: Spacing tape backward over %ld filemarks.\n", dev, (-ltmp)); ) if (fileno >= 0) fileno -= arg; blkno = (-1); /* We can't know the block number */ at_sm &= (arg == 0); break; case MTFSR: cmd[0] = SPACE; cmd[1] = 0x00; /* Space Blocks */ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; DEBC(printk(ST_DEB_MSG "st%d: Spacing tape forward %d blocks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4])); if (blkno >= 0) blkno += arg; at_sm &= (arg == 0); break; case MTBSR: cmd[0] = SPACE; cmd[1] = 0x00; /* Space Blocks */ ltmp = (-arg); cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; DEBC( if (cmd[2] & 0x80) ltmp = 0xff000000; ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; printk(ST_DEB_MSG "st%d: Spacing tape backward %ld blocks.\n", dev, (-ltmp)); ) if (blkno >= 0) blkno -= arg; at_sm &= (arg == 0); break; case MTFSS: cmd[0] = SPACE; cmd[1] = 0x04; /* Space Setmarks */ cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; DEBC(printk(ST_DEB_MSG "st%d: Spacing tape forward %d setmarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4])); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; } break; case MTBSS: cmd[0] = SPACE; cmd[1] = 0x04; /* Space Setmarks */ ltmp = (-arg); cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; DEBC( if (cmd[2] & 0x80) ltmp = 0xff000000; ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; printk(ST_DEB_MSG "st%d: Spacing tape backward %ld setmarks.\n", dev, (-ltmp)); ) if (arg != 0) { blkno = fileno = (-1); at_sm = 1; } break; case MTWEOF: case MTWSM: if (STp->write_prot) return (-EACCES); cmd[0] = WRITE_FILEMARKS; if (cmd_in == MTWSM) cmd[1] = 2; cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; timeout = STp->timeout; DEBC( if (cmd_in == MTWEOF) printk(ST_DEB_MSG "st%d: Writing %d filemarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); else printk(ST_DEB_MSG "st%d: Writing %d setmarks.\n", dev, cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); ) if (fileno >= 0) fileno += arg; blkno = 0; at_sm = (cmd_in == MTWSM); break; case MTREW: cmd[0] = REZERO_UNIT;#if ST_NOWAIT cmd[1] = 1; /* Don't wait for completion */ timeout = STp->timeout;#endif DEBC(printk(ST_DEB_MSG "st%d: Rewinding tape.\n", dev)); fileno = blkno = at_sm = 0; break; case MTOFFL: case MTLOAD: case MTUNLOAD: cmd[0] = START_STOP; if (cmd_in == MTLOAD) cmd[4] |= 1; /* * If arg >= 1 && arg <= 6 Enhanced load/unload in HP C1553A */ if (cmd_in != MTOFFL && arg >= 1 + MT_ST_HPLOADER_OFFSET && arg <= 6 + MT_ST_HPLOADER_OFFSET) { DEBC(printk(ST_DEB_MSG "st%d: Enhanced %sload slot %2ld.\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -