⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
					if (STps->eof != ST_FM_HIT)						STps->eof = ST_FM_HIT;					else						STps->eof = ST_EOD_2;					if (STp->block_size == 0)						STbp->buffer_bytes = 0;					else						STbp->buffer_bytes =						    bytes - transfer * STp->block_size;                                        DEBC(printk(ST_DEB_MSG                                                    "%s: EOF detected (%d bytes read).\n",                                                    name, STbp->buffer_bytes));				} else if (cmdstatp->flags & SENSE_EOM) {					if (STps->eof == ST_FM)						STps->eof = ST_EOD_1;					else						STps->eof = ST_EOM_OK;					if (STp->block_size == 0)						STbp->buffer_bytes = bytes - transfer;					else						STbp->buffer_bytes =						    bytes - transfer * STp->block_size;                                        DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n",                                                    name, STbp->buffer_bytes));				}			}			/* end of EOF, EOM, ILI test */ 			else {	/* nonzero sense key */                                DEBC(printk(ST_DEB_MSG                                            "%s: Tape error while reading.\n", name));				STps->drv_block = (-1);				if (STps->eof == ST_FM &&				    cmdstatp->sense_hdr.sense_key == BLANK_CHECK) {                                        DEBC(printk(ST_DEB_MSG                                                    "%s: Zero returned for first BLANK CHECK after EOF.\n",                                                    name));					STps->eof = ST_EOD_2;	/* First BLANK_CHECK after FM */				} else	/* Some other extended sense code */					retval = (-EIO);			}			if (STbp->buffer_bytes < 0)  /* Caused by bogus sense data */				STbp->buffer_bytes = 0;		}		/* End of extended sense test */ 		else {		/* Non-extended sense */			retval = STbp->syscall_result;		}	}	/* End of error handling */ 	else			/* Read successful */		STbp->buffer_bytes = bytes;	if (STps->drv_block >= 0) {		if (STp->block_size == 0)			STps->drv_block++;		else			STps->drv_block += STbp->buffer_bytes / STp->block_size;	}	return retval;}/* Read command */static ssize_tst_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos){	ssize_t total;	ssize_t retval = 0;	ssize_t i, transfer;	int special, do_dio = 0;	struct st_request *SRpnt = NULL;	struct scsi_tape *STp = filp->private_data;	struct st_modedef *STm;	struct st_partstat *STps;	struct st_buffer *STbp = STp->buffer;	DEB( char *name = tape_name(STp); )	if (mutex_lock_interruptible(&STp->lock))		return -ERESTARTSYS;	retval = rw_checks(STp, filp, count);	if (retval || count == 0)		goto out;	STm = &(STp->modes[STp->current_mode]);	if (STp->block_size != 0 && (count % STp->block_size) != 0) {		if (!STm->do_read_ahead) {			retval = (-EINVAL);	/* Read must be integral number of blocks */			goto out;		}		STp->try_dio_now = 0;  /* Direct i/o can't handle split blocks */	}	STps = &(STp->ps[STp->partition]);	if (STps->rw == ST_WRITING) {		retval = flush_buffer(STp, 0);		if (retval)			goto out;		STps->rw = ST_READING;	}        DEB(	if (debugging && STps->eof != ST_NOEOF)		printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name,		       STps->eof, STbp->buffer_bytes);        ) /* end DEB */	retval = setup_buffering(STp, buf, count, 1);	if (retval)		goto out;	do_dio = STbp->do_dio;	if (STbp->buffer_bytes == 0 &&	    STps->eof >= ST_EOD_1) {		if (STps->eof < ST_EOD) {			STps->eof += 1;			retval = 0;			goto out;		}		retval = (-EIO);	/* EOM or Blank Check */		goto out;	}	if (do_dio) {		/* Check the buffer writability before any tape movement. Don't alter		   buffer data. */		if (copy_from_user(&i, buf, 1) != 0 ||		    copy_to_user(buf, &i, 1) != 0 ||		    copy_from_user(&i, buf + count - 1, 1) != 0 ||		    copy_to_user(buf + count - 1, &i, 1) != 0) {			retval = (-EFAULT);			goto out;		}	}	STps->rw = ST_READING;	/* Loop until enough data in buffer or a special condition found */	for (total = 0, special = 0; total < count && !special;) {		/* Get new data if the buffer is empty */		if (STbp->buffer_bytes == 0) {			special = read_tape(STp, count - total, &SRpnt);			if (special < 0) {	/* No need to continue read */				retval = special;				goto out;			}		}		/* Move the data from driver buffer to user buffer */		if (STbp->buffer_bytes > 0) {                        DEB(			if (debugging && STps->eof != ST_NOEOF)				printk(ST_DEB_MSG                                       "%s: EOF up (%d). Left %d, needed %d.\n", name,				       STps->eof, STbp->buffer_bytes,                                       (int)(count - total));                        ) /* end DEB */			transfer = STbp->buffer_bytes < count - total ?			    STbp->buffer_bytes : count - total;			if (!do_dio) {				i = from_buffer(STbp, buf, transfer);				if (i) {					retval = i;					goto out;				}			}			buf += transfer;			total += transfer;		}		if (STp->block_size == 0)			break;	/* Read only one variable length block */	}			/* for (total = 0, special = 0;                                   total < count && !special; ) */	/* Change the eof state if no data from tape or buffer */	if (total == 0) {		if (STps->eof == ST_FM_HIT) {			STps->eof = ST_FM;			STps->drv_block = 0;			if (STps->drv_file >= 0)				STps->drv_file++;		} else if (STps->eof == ST_EOD_1) {			STps->eof = ST_EOD_2;			STps->drv_block = 0;			if (STps->drv_file >= 0)				STps->drv_file++;		} else if (STps->eof == ST_EOD_2)			STps->eof = ST_EOD;	} else if (STps->eof == ST_FM)		STps->eof = ST_NOEOF;	retval = total; out:	if (SRpnt != NULL) {		st_release_request(SRpnt);		SRpnt = NULL;	}	if (do_dio) {		release_buffering(STp, 1);		STbp->buffer_bytes = 0;	}	mutex_unlock(&STp->lock);	return retval;}DEB(/* Set the driver options */static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name){	if (debugging) {		printk(KERN_INFO		       "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",		       name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,		       STm->do_read_ahead);		printk(KERN_INFO		       "%s:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",		       name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);		printk(KERN_INFO		       "%s:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",		       name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,		       STp->scsi2_logical);		printk(KERN_INFO		       "%s:    sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate);		printk(KERN_INFO "%s:    debugging: %d\n",		       name, debugging);	}}	)static int st_set_options(struct scsi_tape *STp, long options){	int value;	long code;	struct st_modedef *STm;	char *name = tape_name(STp);	struct cdev *cd0, *cd1;	STm = &(STp->modes[STp->current_mode]);	if (!STm->defined) {		cd0 = STm->cdevs[0]; cd1 = STm->cdevs[1];		memcpy(STm, &(STp->modes[0]), sizeof(struct st_modedef));		STm->cdevs[0] = cd0; STm->cdevs[1] = cd1;		modes_defined = 1;                DEBC(printk(ST_DEB_MSG                            "%s: Initialized mode %d definition from mode 0\n",                            name, 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;		STp->immediate = (options & MT_ST_NOWAIT) != 0;		STm->sysv = (options & MT_ST_SYSV) != 0;		DEB( debugging = (options & MT_ST_DEBUGGING) != 0;		     st_log_options(STp, STm, name); )	} 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_NOWAIT) != 0)			STp->immediate = value;		if ((options & MT_ST_SYSV) != 0)			STm->sysv = value;                DEB(		if ((options & MT_ST_DEBUGGING) != 0)			debugging = value;			st_log_options(STp, STm, name); )	} else if (code == MT_ST_WRITE_THRESHOLD) {		/* Retained for compatibility */	} else if (code == MT_ST_DEF_BLKSIZE) {		value = (options & ~MT_ST_OPTIONS);		if (value == ~MT_ST_OPTIONS) {			STm->default_blksize = (-1);			DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name));		} else {			STm->default_blksize = value;			DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n",			       name, STm->default_blksize));			if (STp->ready == ST_READY) {				STp->blksize_changed = 0;				set_mode_densblk(STp, STm);			}		}	} 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;			DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name,			       (value & ~MT_ST_SET_LONG_TIMEOUT)));		} else {			STp->device->timeout = value * HZ;			DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n",				name, value) );		}	} else if (code == MT_ST_SET_CLN) {		value = (options & ~MT_ST_OPTIONS) & 0xff;		if (value != 0 &&		    value < EXTENDED_SENSE_START && value >= SCSI_SENSE_BUFFERSIZE)			return (-EINVAL);		STp->cln_mode = value;		STp->cln_sense_mask = (options >> 8) & 0xff;		STp->cln_sense_value = (options >> 16) & 0xff;		printk(KERN_INFO		       "%s: Cleaning request mode %d, mask %02x, value %02x\n",		       name, value, STp->cln_sense_mask, STp->cln_sense_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);				DEBC( printk(KERN_INFO "%s: Density default disabled.\n",                                       name));			} else {				STm->default_density = value & 0xff;				DEBC( printk(KERN_INFO "%s: Density default set to %x\n",				       name, STm->default_density));				if (STp->ready == ST_READY) {					STp->density_changed = 0;					set_mode_densblk(STp, STm);				}			}		} else if (code == MT_ST_DEF_DRVBUFFER) {			if (value == MT_ST_CLEAR_DEFAULT) {				STp->default_drvbuffer = 0xff;				DEBC( printk(KERN_INFO                                       "%s: Drive buffer default disabled.\n", name));			} else {				STp->default_drvbuffer = value & 7;				DEBC( printk(KERN_INFO                                       "%s: Drive buffer default set to %x\n",				       name, STp->default_drvbuffer));				if (STp->ready == ST_READY)					st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer);			}		} else if (code == MT_ST_DEF_COMPRESSION) {			if (value == MT_ST_CLEAR_DEFAULT) {				STm->default_compression = ST_DONT_TOUCH;				DEBC( printk(KERN_INFO                                       "%s: Compression default disabled.\n", name));			} else {				if ((value & 0xff00) != 0) {					STp->c_algo = (value & 0xff00) >> 8;					DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n",					       name, STp->c_algo));				}				if ((value & 0xff) != 0xff) {					STm->default_compression = (value & 1 ? ST_YES : ST_NO);					DEBC( printk(KERN_INFO "%s: Compression default set to %x\n",					       name, (value & 1)));					if (STp->ready == ST_READY) {						STp->compression_changed = 0;						st_compression(STp, (STm->default_compression == ST_YES));					}				}			}		}	} 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. The page control is ored to the page number   parameter, if necessary. */static int read_mode_page(struct scsi_tape *STp, int page, int omit_block_descs){	unsigned char cmd[MAX_COMMAND_SIZE];	struct st_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], DMA_FROM_DEVICE,			   STp->device->timeout, 0, 1);	if (SRpnt == NULL)		return (STp->buffer)->syscall_result;	st_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. The long timeout is used if slow is non-zero. */static int write_mode_page(struct scsi_tape *STp, int page, int slow){	int pgo;	unsigned char cmd[MAX_COMMAND_SIZE];	struct st_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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -