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

📄 st.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	STm = &(STp->modes[STp->current_mode]);	STps = &(STp->ps[STp->partition]);	if (STp->write_prot) {		retval = (-EACCES);		goto out;	}	if (STps->rw == ST_READING) {		retval = flush_buffer(STp, 0);		if (retval)			goto out;		STps->rw = ST_WRITING;	} else if (STps->rw != ST_WRITING &&		   STps->drv_file == 0 && STps->drv_block == 0) {		if ((retval = set_mode_densblk(STp, STm)) < 0)			goto out;		if (STm->default_compression != ST_DONT_TOUCH &&		    !(STp->compression_changed)) {			if (st_compression(STp, (STm->default_compression == ST_YES))) {				printk(KERN_WARNING "%s: Can't set default compression.\n",				       name);				if (modes_defined) {					retval = (-EINVAL);					goto out;				}			}		}	}	STbp = STp->buffer;	if (STbp->writing) {		write_behind_check(STp);		if (STbp->syscall_result) {                        DEBC(printk(ST_DEB_MSG "%s: Async write error (write) %x.\n",                                    name, STbp->midlevel_result));			if (STbp->midlevel_result == INT_MAX)				STps->eof = ST_EOM_OK;			else				STps->eof = ST_EOM_ERROR;		}	}	if (STps->eof == ST_EOM_OK) {		STps->eof = ST_EOD_1;  /* allow next write */		retval = (-ENOSPC);		goto out;	}	else if (STps->eof == ST_EOM_ERROR) {		retval = (-EIO);		goto out;	}	/* Check the buffer readability in cases where copy_user might catch	   the problems after some tape movement. */	if (STp->block_size != 0 &&	    !STbp->do_dio &&	    (copy_from_user(&i, buf, 1) != 0 ||	     copy_from_user(&i, buf + count - 1, 1) != 0)) {		retval = (-EFAULT);		goto out;	}	retval = setup_buffering(STp, buf, count, FALSE);	if (retval)		goto out;	total = count;	memset(cmd, 0, MAX_COMMAND_SIZE);	cmd[0] = WRITE_6;	cmd[1] = (STp->block_size != 0);	STps->rw = ST_WRITING;	b_point = buf;	while (count > 0 && !retry_eot) {		if (STbp->do_dio) {			do_count = count;		}		else {			if (STp->block_size == 0)				do_count = count;			else {				do_count = STbp->buffer_blocks * STp->block_size -					STbp->buffer_bytes;				if (do_count > count)					do_count = count;			}			i = append_to_buffer(b_point, STbp, do_count);			if (i) {				retval = i;				goto out;			}		}		count -= do_count;		filp->f_pos += do_count;		b_point += do_count;		async_write = STp->block_size == 0 && !STbp->do_dio &&			STm->do_async_writes && STps->eof < ST_EOM_OK;		if (STp->block_size != 0 && STm->do_buffer_writes &&		    !(STp->try_dio && try_wdio) && STps->eof < ST_EOM_OK &&		    STbp->buffer_bytes < STbp->buffer_size) {			STp->dirty = TRUE;			/* Don't write a buffer that is not full enough. */			if (!async_write && count == 0)				break;		}	retry_write:		if (STp->block_size == 0)			blks = transfer = do_count;		else {			if (!STbp->do_dio)				blks = STbp->buffer_bytes;			else				blks = do_count;			blks /= STp->block_size;			transfer = blks * STp->block_size;		}		cmd[2] = blks >> 16;		cmd[3] = blks >> 8;		cmd[4] = blks;		SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,				   STp->device->timeout, MAX_WRITE_RETRIES, !async_write);		if (!SRpnt) {			retval = STbp->syscall_result;			goto out;		}		if (async_write) {			STbp->writing = transfer;			STp->dirty = !(STbp->writing ==				       STbp->buffer_bytes);			SRpnt = NULL;  /* Prevent releasing this request! */			DEB( STp->write_pending = 1; )			break;		}		if (STbp->syscall_result != 0) {                        DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name));			if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&			    (SRpnt->sr_sense_buffer[2] & 0x40)) {				scode = SRpnt->sr_sense_buffer[2] & 0x0f;				if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)					undone = (SRpnt->sr_sense_buffer[3] << 24) |					    (SRpnt->sr_sense_buffer[4] << 16) |					    (SRpnt->sr_sense_buffer[5] << 8) |                                                SRpnt->sr_sense_buffer[6];				else if (STp->block_size == 0 &&					 scode == VOLUME_OVERFLOW)					undone = transfer;				else					undone = 0;				if (STp->block_size != 0)					undone *= STp->block_size;				filp->f_pos -= undone;				if (undone <= do_count) {					/* Only data from this write is not written */					count += undone;					do_count -= undone;					if (STp->block_size)						blks = (transfer - undone) / STp->block_size;					STps->eof = ST_EOM_OK;					/* Continue in fixed block mode if all written					   in this request but still something left to write					   (retval left to zero)					*/					if (STp->block_size == 0 ||					    undone > 0 || count == 0)						retval = (-ENOSPC); /* EOM within current request */                                        DEBC(printk(ST_DEB_MSG                                                       "%s: EOM with %d bytes unwritten.\n",						       name, count));				} else {					/* EOT within data buffered earlier (possible only					   in fixed block mode without direct i/o) */					if (!retry_eot && (SRpnt->sr_sense_buffer[0] & 1) == 0 &&					    (scode == NO_SENSE || scode == RECOVERED_ERROR)) {						move_buffer_data(STp->buffer, transfer - undone);						retry_eot = TRUE;						if (STps->drv_block >= 0) {							STps->drv_block += (transfer - undone) /								STp->block_size;						}						STps->eof = ST_EOM_OK;						DEBC(printk(ST_DEB_MSG							    "%s: Retry write of %d bytes at EOM.\n",							    name, STp->buffer->buffer_bytes));						goto retry_write;					}					else {						/* Either error within data buffered by driver or						   failed retry */						count -= do_count;						blks = do_count = 0;						STps->eof = ST_EOM_ERROR;						STps->drv_block = (-1); /* Too cautious? */						retval = (-EIO);	/* EOM for old data */						DEBC(printk(ST_DEB_MSG							    "%s: EOM with lost data.\n",							    name));					}				}			} else {				filp->f_pos -= do_count;				count += do_count;				STps->drv_block = (-1);		/* Too cautious? */				retval = (-EIO);			}		}		if (STps->drv_block >= 0) {			if (STp->block_size == 0)				STps->drv_block += (do_count > 0);			else				STps->drv_block += blks;		}		STbp->buffer_bytes = 0;		STp->dirty = 0;		if (retval || retry_eot) {			if (count < total)				retval = total - count;			goto out;		}	}	if (STps->eof == ST_EOD_1)		STps->eof = ST_EOM_OK;	else if (STps->eof != ST_EOM_OK)		STps->eof = ST_NOEOF;	retval = total - count; out:	if (SRpnt != NULL)		scsi_release_request(SRpnt);	release_buffering(STp);	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.   Does release user buffer mapping if it is set.*/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;	ST_buffer *STbp;	int retval = 0;	char *name = tape_name(STp);	if (count == 0)		return 0;	STm = &(STp->modes[STp->current_mode]);	STps = &(STp->ps[STp->partition]);	if (STps->eof == ST_FM_HIT)		return 1;	STbp = STp->buffer;	if (STp->block_size == 0)		blks = bytes = count;	else {		if (!(STp->try_dio && try_rdio) && STm->do_read_ahead) {			blks = (STp->buffer)->buffer_blocks;			bytes = blks * STp->block_size;		} else {			bytes = count;			if (!STbp->do_dio && bytes > (STp->buffer)->buffer_size)				bytes = (STp->buffer)->buffer_size;			blks = bytes / STp->block_size;			bytes = blks * STp->block_size;		}	}	memset(cmd, 0, MAX_COMMAND_SIZE);	cmd[0] = READ_6;	cmd[1] = (STp->block_size != 0);	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->device->timeout, MAX_RETRIES, TRUE);	release_buffering(STp);	*aSRpnt = SRpnt;	if (!SRpnt)		return STbp->syscall_result;	STbp->read_pointer = 0;	STps->at_sm = 0;	/* Something to check */	if (STbp->syscall_result) {		retval = 1;		DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",                            name,                            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 (transfer < 0)								printk(KERN_NOTICE								       "%s: Failed to read %d byte block with %d byte transfer.\n",								       name, bytes - transfer, bytes);							if (STps->drv_block >= 0)								STps->drv_block += 1;							STbp->buffer_bytes = 0;							return (-ENOMEM);						}						STbp->buffer_bytes = bytes - transfer;					} else {						scsi_release_request(SRpnt);						SRpnt = *aSRpnt = NULL;						if (transfer == blks) {	/* We did not get anything, error */							printk(KERN_NOTICE "%s: Incorrect block size.\n", name);							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 */						STbp->buffer_bytes = (blks - transfer) *						    STp->block_size;                                                DEBC(printk(ST_DEB_MSG                                                            "%s: ILI but enough data received %ld %d.\n",                                                            name, count, STbp->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)						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 (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)						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 &&				    (SRpnt->sr_sense_buffer[2] & 0x0f) == 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;	Scsi_Request *SRpnt = NULL;	Scsi_Tape *STp = filp->private_data;	ST_mode *STm;	ST_partstat *STps;	ST_buffer *STbp = STp->buffer;	DEB( char *name = tape_name(STp); )	if (down_interruptible(&STp->lock))		return -ERESTARTSYS;	retval = rw_checks(STp, filp, count);	if (retval || count == 0)

⌨️ 快捷键说明

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