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

📄 st.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
				STps->drv_block += blks;		}		(STp->buffer)->buffer_bytes = 0;		STp->dirty = 0;	}	if (count != 0) {		STp->dirty = 1;		i = append_to_buffer(b_point, STp->buffer, count);		if (i) {			retval = i;			goto out;		}		filp->f_pos += count;		count = 0;	}	if (doing_write && (STp->buffer)->syscall_result != 0) {		retval = (STp->buffer)->syscall_result;		goto out;	}	if (STm->do_async_writes &&	    (((STp->buffer)->buffer_bytes >= STp->write_threshold &&	      (STp->buffer)->buffer_bytes >= STp->block_size) ||	     STp->block_size == 0)) {		/* Schedule an asynchronous write */		if (STp->block_size == 0)			(STp->buffer)->writing = (STp->buffer)->buffer_bytes;		else			(STp->buffer)->writing = ((STp->buffer)->buffer_bytes /				      STp->block_size) * STp->block_size;		STp->dirty = !((STp->buffer)->writing ==			       (STp->buffer)->buffer_bytes);		if (STp->block_size == 0)			blks = (STp->buffer)->writing;		else			blks = (STp->buffer)->writing / STp->block_size;		cmd[2] = blks >> 16;		cmd[3] = blks >> 8;		cmd[4] = blks;		DEB( STp->write_pending = 1; )		SRpnt = st_do_scsi(SRpnt, STp, cmd, (STp->buffer)->writing,				   SCSI_DATA_WRITE, STp->timeout,				   MAX_WRITE_RETRIES, FALSE);		if (SRpnt == NULL) {			retval = (STp->buffer)->syscall_result;			goto out;		}		SRpnt = NULL;  /* Prevent releasing this request! */	}	STps->at_sm &= (total == 0);	if (total > 0)		STps->eof = ST_NOEOF;	retval = total; out:	if (SRpnt != NULL)		scsi_release_request(SRpnt);	up(&STp->lock);	return retval;}/* Read data from the tape. Returns zero in the normal case, one if the   eof status has changed, and the negative error code in case of a   fatal error. Otherwise updates the buffer and the eof state. */static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt){	int transfer, blks, bytes;	unsigned char cmd[MAX_COMMAND_SIZE];	Scsi_Request *SRpnt;	ST_mode *STm;	ST_partstat *STps;	int dev = TAPE_NR(STp->devt);	int retval = 0;	if (count == 0)		return 0;	STm = &(STp->modes[STp->current_mode]);	STps = &(STp->ps[STp->partition]);	if (STps->eof == ST_FM_HIT)		return 1;	memset(cmd, 0, MAX_COMMAND_SIZE);	cmd[0] = READ_6;	cmd[1] = (STp->block_size != 0);	if (STp->block_size == 0)		blks = bytes = count;	else {		if (STm->do_read_ahead) {			blks = (STp->buffer)->buffer_blocks;			bytes = blks * STp->block_size;		} else {			bytes = count;			if (bytes > (STp->buffer)->buffer_size)				bytes = (STp->buffer)->buffer_size;			blks = bytes / STp->block_size;			bytes = blks * STp->block_size;		}	}	cmd[2] = blks >> 16;	cmd[3] = blks >> 8;	cmd[4] = blks;	SRpnt = *aSRpnt;	SRpnt = st_do_scsi(SRpnt, STp, cmd, bytes, SCSI_DATA_READ,			   STp->timeout, MAX_RETRIES, TRUE);	*aSRpnt = SRpnt;	if (!SRpnt)		return (STp->buffer)->syscall_result;	(STp->buffer)->read_pointer = 0;	STps->at_sm = 0;	/* Something to check */	if ((STp->buffer)->syscall_result) {		retval = 1;		DEBC(printk(ST_DEB_MSG "st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",                            dev,                            SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],                            SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],                            SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],                            SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]));		if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {	/* extended sense */			if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)				SRpnt->sr_sense_buffer[2] &= 0xcf;	/* No need for EOM in this case */			if ((SRpnt->sr_sense_buffer[2] & 0xe0) != 0) { /* EOF, EOM, or ILI */				/* Compute the residual count */				if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)					transfer = (SRpnt->sr_sense_buffer[3] << 24) |					    (SRpnt->sr_sense_buffer[4] << 16) |					    (SRpnt->sr_sense_buffer[5] << 8) |					    SRpnt->sr_sense_buffer[6];				else					transfer = 0;				if (STp->block_size == 0 &&				    (SRpnt->sr_sense_buffer[2] & 0x0f) == MEDIUM_ERROR)					transfer = bytes;				if (SRpnt->sr_sense_buffer[2] & 0x20) {	/* ILI */					if (STp->block_size == 0) {						if (transfer < 0) {							if (STps->drv_block >= 0)								STps->drv_block += 1;							return (-ENOMEM);						}						(STp->buffer)->buffer_bytes = bytes - transfer;					} else {						scsi_release_request(SRpnt);						SRpnt = *aSRpnt = NULL;						if (transfer == blks) {	/* We did not get anything, error */							printk(KERN_NOTICE "st%d: Incorrect block size.\n", dev);							if (STps->drv_block >= 0)								STps->drv_block += blks - transfer + 1;							st_int_ioctl(STp, MTBSR, 1);							return (-EIO);						}						/* We have some data, deliver it */						(STp->buffer)->buffer_bytes = (blks - transfer) *						    STp->block_size;                                                DEBC(printk(ST_DEB_MSG                                                            "st%d: ILI but enough data received %ld %d.\n",                                                            dev, count, (STp->buffer)->buffer_bytes));						if (STps->drv_block >= 0)							STps->drv_block += 1;						if (st_int_ioctl(STp, MTBSR, 1))							return (-EIO);					}				} else if (SRpnt->sr_sense_buffer[2] & 0x80) {	/* FM overrides EOM */					if (STps->eof != ST_FM_HIT)						STps->eof = ST_FM_HIT;					else						STps->eof = ST_EOD_2;					if (STp->block_size == 0)						(STp->buffer)->buffer_bytes = 0;					else						(STp->buffer)->buffer_bytes =						    bytes - transfer * STp->block_size;                                        DEBC(printk(ST_DEB_MSG                                                    "st%d: EOF detected (%d bytes read).\n",                                                    dev, (STp->buffer)->buffer_bytes));				} else if (SRpnt->sr_sense_buffer[2] & 0x40) {					if (STps->eof == ST_FM)						STps->eof = ST_EOD_1;					else						STps->eof = ST_EOM_OK;					if (STp->block_size == 0)						(STp->buffer)->buffer_bytes = bytes - transfer;					else						(STp->buffer)->buffer_bytes =						    bytes - transfer * STp->block_size;                                        DEBC(printk(ST_DEB_MSG "st%d: EOM detected (%d bytes read).\n",                                                    dev, (STp->buffer)->buffer_bytes));				}			}			/* end of EOF, EOM, ILI test */ 			else {	/* nonzero sense key */                                DEBC(printk(ST_DEB_MSG                                            "st%d: Tape error while reading.\n", dev));				STps->drv_block = (-1);				if (STps->eof == ST_FM &&				    (SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK) {                                        DEBC(printk(ST_DEB_MSG                                                    "st%d: Zero returned for first BLANK CHECK after EOF.\n",                                                    dev));					STps->eof = ST_EOD_2;	/* First BLANK_CHECK after FM */				} else	/* Some other extended sense code */					retval = (-EIO);			}		}		/* End of extended sense test */ 		else {		/* Non-extended sense */			retval = (STp->buffer)->syscall_result;		}	}	/* End of error handling */ 	else			/* Read successful */		(STp->buffer)->buffer_bytes = bytes;	if (STps->drv_block >= 0) {		if (STp->block_size == 0)			STps->drv_block++;		else			STps->drv_block += (STp->buffer)->buffer_bytes / STp->block_size;	}	return retval;}/* Read command */static ssize_t st_read(struct file *filp, char *buf, size_t count, loff_t * ppos){	struct inode *inode = filp->f_dentry->d_inode;	ssize_t total;	ssize_t retval = 0;	ssize_t i, transfer;	int special;	Scsi_Request *SRpnt = NULL;	Scsi_Tape *STp;	ST_mode *STm;	ST_partstat *STps;	int dev = TAPE_NR(inode->i_rdev);	read_lock(&st_dev_arr_lock);	STp = scsi_tapes[dev];	read_unlock(&st_dev_arr_lock);	if (down_interruptible(&STp->lock))		return -ERESTARTSYS;	/*	 * If we are in the middle of error recovery, don't let anyone	 * else try and use this device.  Also, if error recovery fails, it	 * may try and take the device offline, in which case all further	 * access to the device is prohibited.	 */	if (!scsi_block_when_processing_errors(STp->device)) {		retval = (-ENXIO);		goto out;	}	if (ppos != &filp->f_pos) {		/* "A request was outside the capabilities of the device." */		retval = (-ENXIO);		goto out;	}	if (STp->ready != ST_READY) {		if (STp->ready == ST_NO_TAPE)			retval = (-ENOMEDIUM);		else			retval = (-EIO);		goto out;	}	STm = &(STp->modes[STp->current_mode]);	if (!STm->defined) {		retval = (-ENXIO);		goto out;	}        DEB(	if (!STp->in_use) {		printk(ST_DEB_MSG "st%d: Incorrect device.\n", dev);		retval = (-EIO);		goto out;	} ) /* end DEB */	if (STp->can_partitions &&	    (retval = update_partition(STp)) < 0)		goto out;	if (STp->block_size == 0) {		if (STp->max_block > 0 &&		    (count < STp->min_block || count > STp->max_block)) {			retval = (-EINVAL);			goto out;		}		if (count > (STp->buffer)->buffer_size &&		    !enlarge_buffer(STp->buffer, count, STp->restr_dma)) {			retval = (-EOVERFLOW);			goto out;		}	}	if ((STp->buffer)->buffer_blocks < 1) {		/* Fixed block mode with too small buffer */		if (!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {			retval = (-EOVERFLOW);			goto out;		}		(STp->buffer)->buffer_blocks = 1;	}	if (!(STm->do_read_ahead) && STp->block_size != 0 &&	    (count % STp->block_size) != 0) {		retval = (-EINVAL);	/* Read must be integral number of blocks */		goto out;	}	if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&	    !st_int_ioctl(STp, MTLOCK, 0))		STp->door_locked = ST_LOCKED_AUTO;	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 "st%d: EOF/EOM flag up (%d). Bytes %d\n", dev,		       STps->eof, (STp->buffer)->buffer_bytes);        ) /* end DEB */	if ((STp->buffer)->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;	}	/* 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 ((STp->buffer)->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 ((STp->buffer)->buffer_bytes > 0) {                        DEB(			if (debugging && STps->eof != ST_NOEOF)				printk(ST_DEB_MSG                                       "st%d: EOF up (%d). Left %d, needed %d.\n", dev,				       STps->eof, (STp->buffer)->buffer_bytes,                                       count - total);                        ) /* end DEB */			transfer = (STp->buffer)->buffer_bytes < count - total ?			    (STp->buffer)->buffer_bytes : count - total;			i = from_buffer(STp->buffer, buf, transfer);			if (i) {				retval = i;				goto out;			}			filp->f_pos += transfer;			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) {		scsi_release_request(SRpnt);		SRpnt = NULL;	}	up(&STp->lock);	return retval;}/* Set the driver options */static void st_log_options(Scsi_Tape * STp, ST_mode * STm, int dev){	printk(KERN_INFO	       "st%d: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",	       dev, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,	       STm->do_read_ahead);	printk(KERN_INFO	       "st%d:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",	       dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);	printk(KERN_INFO	       "st%d:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",	       dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,	       STp->scsi2_logical);	printk(KERN_INFO	       "st%d:    sysv: %d\n", dev, STm->sysv);        DEB(printk(KERN_INFO                   "st%d:    debugging: %d\n",

⌨️ 快捷键说明

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