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

📄 st.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
			STps->drv_block++;		else			STps->drv_block += STbuffer->writing / STp->block_size;	}	STbuffer->writing = 0;	return;}/* Step over EOF if it has been inadvertently crossed (ioctl not used because   it messes up the block number). */static int cross_eof(Scsi_Tape * STp, int forward){	Scsi_Request *SRpnt;	unsigned char cmd[MAX_COMMAND_SIZE];	cmd[0] = SPACE;	cmd[1] = 0x01;		/* Space FileMarks */	if (forward) {		cmd[2] = cmd[3] = 0;		cmd[4] = 1;	} else		cmd[2] = cmd[3] = cmd[4] = 0xff;	/* -1 filemarks */	cmd[5] = 0;        DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n",		   tape_name(STp), forward ? "forward" : "backward"));	SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE,			   STp->device->timeout, MAX_RETRIES, TRUE);	if (!SRpnt)		return (STp->buffer)->syscall_result;	scsi_release_request(SRpnt);	SRpnt = NULL;	if ((STp->buffer)->midlevel_result != 0)		printk(KERN_ERR "%s: Stepping over filemark %s failed.\n",		   tape_name(STp), forward ? "forward" : "backward");	return (STp->buffer)->syscall_result;}/* Flush the write buffer (never need to write if variable blocksize). */static int flush_write_buffer(Scsi_Tape * STp){	int offset, transfer, blks;	int result;	unsigned char cmd[MAX_COMMAND_SIZE];	Scsi_Request *SRpnt;	ST_partstat *STps;	if ((STp->buffer)->writing) {		write_behind_check(STp);		if ((STp->buffer)->syscall_result) {                        DEBC(printk(ST_DEB_MSG                                       "%s: Async write error (flush) %x.\n",				       tape_name(STp), (STp->buffer)->midlevel_result))			if ((STp->buffer)->midlevel_result == INT_MAX)				return (-ENOSPC);			return (-EIO);		}	}	if (STp->block_size == 0)		return 0;	result = 0;	if (STp->dirty == 1) {		offset = (STp->buffer)->buffer_bytes;		transfer = ((offset + STp->block_size - 1) /			    STp->block_size) * STp->block_size;                DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n",                               tape_name(STp), transfer));		memset((STp->buffer)->b_data + offset, 0, transfer - offset);		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = WRITE_6;		cmd[1] = 1;		blks = transfer / STp->block_size;		cmd[2] = blks >> 16;		cmd[3] = blks >> 8;		cmd[4] = blks;		SRpnt = st_do_scsi(NULL, STp, cmd, transfer, SCSI_DATA_WRITE,				   STp->device->timeout, MAX_WRITE_RETRIES, TRUE);		if (!SRpnt)			return (STp->buffer)->syscall_result;		STps = &(STp->ps[STp->partition]);		if ((STp->buffer)->syscall_result != 0) {			if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&			    (SRpnt->sr_sense_buffer[2] & 0x40) &&			    (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {				STp->dirty = 0;				(STp->buffer)->buffer_bytes = 0;				result = (-ENOSPC);			} else {				printk(KERN_ERR "%s: Error on flush.\n",                                       tape_name(STp));				result = (-EIO);			}			STps->drv_block = (-1);		} else {			if (STps->drv_block >= 0)				STps->drv_block += blks;			STp->dirty = 0;			(STp->buffer)->buffer_bytes = 0;		}		scsi_release_request(SRpnt);		SRpnt = NULL;	}	return result;}/* Flush the tape buffer. The tape will be positioned correctly unless   seek_next is true. */static int flush_buffer(Scsi_Tape *STp, int seek_next){	int backspace, result;	ST_buffer *STbuffer;	ST_partstat *STps;	STbuffer = STp->buffer;	/*	 * If there was a bus reset, block further access	 * to this device.	 */	if (STp->pos_unknown)		return (-EIO);	if (STp->ready != ST_READY)		return 0;	STps = &(STp->ps[STp->partition]);	if (STps->rw == ST_WRITING)	/* Writing */		return flush_write_buffer(STp);	if (STp->block_size == 0)		return 0;	backspace = ((STp->buffer)->buffer_bytes +		     (STp->buffer)->read_pointer) / STp->block_size -	    ((STp->buffer)->read_pointer + STp->block_size - 1) /	    STp->block_size;	(STp->buffer)->buffer_bytes = 0;	(STp->buffer)->read_pointer = 0;	result = 0;	if (!seek_next) {		if (STps->eof == ST_FM_HIT) {			result = cross_eof(STp, FALSE);	/* Back over the EOF hit */			if (!result)				STps->eof = ST_NOEOF;			else {				if (STps->drv_file >= 0)					STps->drv_file++;				STps->drv_block = 0;			}		}		if (!result && backspace > 0)			result = st_int_ioctl(STp, MTBSR, backspace);	} else if (STps->eof == ST_FM_HIT) {		if (STps->drv_file >= 0)			STps->drv_file++;		STps->drv_block = 0;		STps->eof = ST_NOEOF;	}	return result;}/* Set the mode parameters */static int set_mode_densblk(Scsi_Tape * STp, ST_mode * STm){	int set_it = FALSE;	unsigned long arg;	char *name = tape_name(STp);	if (!STp->density_changed &&	    STm->default_density >= 0 &&	    STm->default_density != STp->density) {		arg = STm->default_density;		set_it = TRUE;	} else		arg = STp->density;	arg <<= MT_ST_DENSITY_SHIFT;	if (!STp->blksize_changed &&	    STm->default_blksize >= 0 &&	    STm->default_blksize != STp->block_size) {		arg |= STm->default_blksize;		set_it = TRUE;	} else		arg |= STp->block_size;	if (set_it &&	    st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) {		printk(KERN_WARNING		       "%s: Can't set default block size to %d bytes and density %x.\n",		       name, STm->default_blksize, STm->default_density);		if (modes_defined)			return (-EINVAL);	}	return 0;}/* Lock or unlock the drive door. Don't use when Scsi_Request allocated. */static int do_door_lock(Scsi_Tape * STp, int do_lock){	int retval, cmd;	DEB(char *name = tape_name(STp);)	cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;	DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name,		    do_lock ? "L" : "Unl"));	retval = scsi_ioctl(STp->device, cmd, NULL);	if (!retval) {		STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;	}	else {		STp->door_locked = ST_LOCK_FAILS;	}	return retval;}/* Set the internal state after reset */static void reset_state(Scsi_Tape *STp){	int i;	ST_partstat *STps;	STp->pos_unknown = 0;	for (i = 0; i < ST_NBR_PARTITIONS; i++) {		STps = &(STp->ps[i]);		STps->rw = ST_IDLE;		STps->eof = ST_NOEOF;		STps->at_sm = 0;		STps->last_block_valid = FALSE;		STps->drv_block = -1;		STps->drv_file = -1;	}	if (STp->can_partitions) {		STp->partition = find_partition(STp);		if (STp->partition < 0)			STp->partition = 0;		STp->new_partition = STp->partition;	}}/* Test if the drive is ready. Returns either one of the codes below or a negative system   error code. */#define CHKRES_READY       0#define CHKRES_NEW_SESSION 1#define CHKRES_NOT_READY   2#define CHKRES_NO_TAPE     3#define MAX_ATTENTIONS    10static int test_ready(Scsi_Tape *STp, int do_wait){	int attentions, waits, max_wait, scode;	int retval = CHKRES_READY, new_session = FALSE;	unsigned char cmd[MAX_COMMAND_SIZE];	Scsi_Request *SRpnt = NULL;	max_wait = do_wait ? ST_BLOCK_SECONDS : 0;	for (attentions=waits=0; ; ) {		memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);		cmd[0] = TEST_UNIT_READY;		SRpnt = st_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,				   STp->long_timeout, MAX_READY_RETRIES, TRUE);		if (!SRpnt) {			retval = (STp->buffer)->syscall_result;			break;		}		if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70) {			scode = (SRpnt->sr_sense_buffer[2] & 0x0f);			if (scode == UNIT_ATTENTION) { /* New media? */				new_session = TRUE;				if (attentions < MAX_ATTENTIONS) {					attentions++;					continue;				}				else {					retval = (-EIO);					break;				}			}			if (scode == NOT_READY) {				if (waits < max_wait) {					set_current_state(TASK_INTERRUPTIBLE);					schedule_timeout(HZ);					if (signal_pending(current)) {						retval = (-EINTR);						break;					}					waits++;					continue;				}				else {					if ((STp->device)->scsi_level >= SCSI_2 &&					    SRpnt->sr_sense_buffer[12] == 0x3a)	/* Check ASC */						retval = CHKRES_NO_TAPE;					else						retval = CHKRES_NOT_READY;					break;				}			}		}		retval = (STp->buffer)->syscall_result;		if (!retval)			retval = new_session ? CHKRES_NEW_SESSION : CHKRES_READY;		break;	}	if (SRpnt != NULL)		scsi_release_request(SRpnt);	return retval;}/* See if the drive is ready and gather information about the tape. Return values:   < 0   negative error code from errno.h   0     drive ready   1     drive not ready (possibly no tape)*/static int check_tape(Scsi_Tape *STp, struct file *filp){	int i, retval, new_session = FALSE, do_wait;	unsigned char cmd[MAX_COMMAND_SIZE], saved_cleaning;	unsigned short st_flags = filp->f_flags;	Scsi_Request *SRpnt = NULL;	ST_mode *STm;	ST_partstat *STps;	char *name = tape_name(STp);	struct inode *inode = filp->f_dentry->d_inode;	int mode = TAPE_MODE(inode);	STp->ready = ST_READY;	if (mode != STp->current_mode) {                DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n",			       name, STp->current_mode, mode));		new_session = TRUE;		STp->current_mode = mode;	}	STm = &(STp->modes[STp->current_mode]);	saved_cleaning = STp->cleaning_req;	STp->cleaning_req = 0;	do_wait = ((filp->f_flags & O_NONBLOCK) == 0);	retval = test_ready(STp, do_wait);	if (retval < 0)	    goto err_out;	if (retval == CHKRES_NEW_SESSION) {		STp->pos_unknown = 0;		STp->partition = STp->new_partition = 0;		if (STp->can_partitions)			STp->nbr_partitions = 1; /* This guess will be updated later                                                    if necessary */		for (i = 0; i < ST_NBR_PARTITIONS; i++) {			STps = &(STp->ps[i]);			STps->rw = ST_IDLE;			STps->eof = ST_NOEOF;			STps->at_sm = 0;			STps->last_block_valid = FALSE;			STps->drv_block = 0;			STps->drv_file = 0;		}		new_session = TRUE;	}	else {		STp->cleaning_req |= saved_cleaning;		if (retval == CHKRES_NOT_READY || retval == CHKRES_NO_TAPE) {			if (retval == CHKRES_NO_TAPE)				STp->ready = ST_NO_TAPE;			else				STp->ready = ST_NOT_READY;			STp->density = 0;	/* Clear the erroneous "residue" */			STp->write_prot = 0;			STp->block_size = 0;			STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);			STp->partition = STp->new_partition = 0;			STp->door_locked = ST_UNLOCKED;			return CHKRES_NOT_READY;		}	}	if (STp->omit_blklims)		STp->min_block = STp->max_block = (-1);	else {		memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);		cmd[0] = READ_BLOCK_LIMITS;		SRpnt = st_do_scsi(SRpnt, STp, cmd, 6, SCSI_DATA_READ, STp->device->timeout,				   MAX_READY_RETRIES, TRUE);		if (!SRpnt) {			retval = (STp->buffer)->syscall_result;			goto err_out;		}		if (!SRpnt->sr_result && !SRpnt->sr_sense_buffer[0]) {			STp->max_block = ((STp->buffer)->b_data[1] << 16) |			    ((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];			STp->min_block = ((STp->buffer)->b_data[4] << 8) |			    (STp->buffer)->b_data[5];			if ( DEB( debugging || ) !STp->inited)				printk(KERN_WARNING                                       "%s: Block limits %d - %d bytes.\n", name,                                       STp->min_block, STp->max_block);		} else {			STp->min_block = STp->max_block = (-1);                        DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n",                                       name));		}	}	memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);	cmd[0] = MODE_SENSE;	cmd[4] = 12;	SRpnt = st_do_scsi(SRpnt, STp, cmd, 12, SCSI_DATA_READ, STp->device->timeout,			   MAX_READY_RETRIES, TRUE);	if (!SRpnt) {		retval = (STp->buffer)->syscall_result;		goto err_out;	}	if ((STp->buffer)->syscall_result != 0) {                DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name));		STp->block_size = ST_DEFAULT_BLOCK;	/* Educated guess (?) */		(STp->buffer)->syscall_result = 0;	/* Prevent error propagation */		STp->drv_write_prot = 0;	} else {                DEBC(printk(ST_DEB_MSG                            "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",                            name,                            (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],                            (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]));		if ((STp->buffer)->b_data[3] >= 8) {

⌨️ 快捷键说明

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