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

📄 st.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!SRpnt)		return (STp->buffer)->syscall_result;	scsi_release_request(SRpnt);	SRpnt = NULL;	if ((STp->buffer)->midlevel_result != 0)		printk(KERN_ERR "st%d: Stepping over filemark %s failed.\n",		   TAPE_NR(STp->devt), 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                                       "st%d: Async write error (flush) %x.\n",				       TAPE_NR(STp->devt), (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 "st%d: Flushing %d bytes.\n",                               TAPE_NR(STp->devt), 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->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 "st%d: Error on flush.\n",                                       TAPE_NR(STp->devt));				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->device->was_reset)		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;	int dev = TAPE_NR(STp->devt);	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		       "st%d: Can't set default block size to %d bytes and density %x.\n",		       dev, STm->default_blksize, STm->default_density);		if (modes_defined)			return (-EINVAL);	}	return 0;}/* Open the device. Needs to be called with BKL only because of incrementing the SCSI host   module count. */static int st_open(struct inode *inode, struct file *filp){	unsigned short st_flags;	int i, need_dma_buffer, new_session = FALSE;	int retval;	unsigned char cmd[MAX_COMMAND_SIZE];	Scsi_Request *SRpnt;	Scsi_Tape *STp;	ST_mode *STm;	ST_partstat *STps;	int dev = TAPE_NR(inode->i_rdev);	int mode = TAPE_MODE(inode->i_rdev);	unsigned long flags;	write_lock_irqsave(&st_dev_arr_lock, flags);	STp = scsi_tapes[dev];	if (dev >= st_template.dev_max || STp == NULL) {		write_unlock_irqrestore(&st_dev_arr_lock, flags);		return (-ENXIO);	}	if (STp->in_use) {		write_unlock_irqrestore(&st_dev_arr_lock, flags);		DEB( printk(ST_DEB_MSG "st%d: Device already in use.\n", dev); )		return (-EBUSY);	}	STp->in_use = 1;	write_unlock_irqrestore(&st_dev_arr_lock, flags);	STp->rew_at_close = STp->autorew_dev = (MINOR(inode->i_rdev) & 0x80) == 0;	if (STp->device->host->hostt->module)		__MOD_INC_USE_COUNT(STp->device->host->hostt->module);	if (!scsi_block_when_processing_errors(STp->device)) {		retval = (-ENXIO);		goto err_out;	}	if (mode != STp->current_mode) {                DEBC(printk(ST_DEB_MSG "st%d: Mode change from %d to %d.\n",			       dev, STp->current_mode, mode));		new_session = TRUE;		STp->current_mode = mode;	}	STm = &(STp->modes[STp->current_mode]);	/* Allocate a buffer for this user */	need_dma_buffer = STp->restr_dma;	write_lock_irqsave(&st_dev_arr_lock, flags);	for (i = 0; i < st_nbr_buffers; i++)		if (!st_buffers[i]->in_use &&		    (!need_dma_buffer || st_buffers[i]->dma)) {			STp->buffer = st_buffers[i];			(STp->buffer)->in_use = 1;			break;		}	write_unlock_irqrestore(&st_dev_arr_lock, flags);	if (i >= st_nbr_buffers) {		STp->buffer = new_tape_buffer(FALSE, need_dma_buffer, TRUE);		if (STp->buffer == NULL) {			printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);			retval = (-EBUSY);			goto err_out;		}	}	(STp->buffer)->writing = 0;	(STp->buffer)->syscall_result = 0;	(STp->buffer)->use_sg = STp->device->host->sg_tablesize;	/* Compute the usable buffer size for this SCSI adapter */	if (!(STp->buffer)->use_sg)		(STp->buffer)->buffer_size = (STp->buffer)->sg[0].length;	else {		for (i = 0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg &&		     i < (STp->buffer)->sg_segs; i++)			(STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;	}	st_flags = filp->f_flags;	STp->write_prot = ((st_flags & O_ACCMODE) == O_RDONLY);	STp->dirty = 0;	for (i = 0; i < ST_NBR_PARTITIONS; i++) {		STps = &(STp->ps[i]);		STps->rw = ST_IDLE;	}	STp->ready = ST_READY;	STp->recover_count = 0;	DEB( STp->nbr_waits = STp->nbr_finished = 0; )	memset((void *) &cmd[0], 0, MAX_COMMAND_SIZE);	cmd[0] = TEST_UNIT_READY;	SRpnt = st_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->long_timeout,			   MAX_READY_RETRIES, TRUE);	if (!SRpnt) {		retval = (STp->buffer)->syscall_result;		goto err_out;	}	if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&	    (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {	/* New media? */		/* Flush the queued UNIT ATTENTION sense data */		for (i=0; i < 10; i++) {                        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->sr_sense_buffer[0] & 0x70) != 0x70 ||                            (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)                                break;		}		(STp->device)->was_reset = 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;	}	if ((STp->buffer)->syscall_result != 0) {		if ((STp->device)->scsi_level >= SCSI_2 &&		    (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&		    (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&		    SRpnt->sr_sense_buffer[12] == 0x3a) {	/* Check ASC */			STp->ready = ST_NO_TAPE;		} else			STp->ready = ST_NOT_READY;		scsi_release_request(SRpnt);		SRpnt = NULL;		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 0;	}	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->timeout,				   MAX_READY_RETRIES, TRUE);		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                                       "st%d: Block limits %d - %d bytes.\n", dev,                                       STp->min_block, STp->max_block);		} else {			STp->min_block = STp->max_block = (-1);                        DEBC(printk(ST_DEB_MSG "st%d: Can't read block limits.\n",                                       dev));		}	}	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->timeout,			   MAX_READY_RETRIES, TRUE);	if ((STp->buffer)->syscall_result != 0) {                DEBC(printk(ST_DEB_MSG "st%d: No Mode Sense.\n", dev));		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                            "st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n",                            dev,                            (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) {			STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;			STp->density = (STp->buffer)->b_data[4];			STp->block_size = (STp->buffer)->b_data[9] * 65536 +			    (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];                        DEBC(printk(ST_DEB_MSG                                    "st%d: Density %x, tape length: %x, drv buffer: %d\n",                                    dev, STp->density, (STp->buffer)->b_data[5] * 65536 +                                    (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],                                    STp->drv_buffer));		}		STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;	}	scsi_release_request(SRpnt);	SRpnt = NULL;        STp->inited = TRUE;	if (STp->block_size > 0)		(STp->buffer)->buffer_blocks =                        (STp->buffer)->buffer_size / STp->block_size;	else		(STp->buffer)->buffer_blocks = 1;	(STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;        DEBC(printk(ST_DEB_MSG                       "st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,		       STp->block_size, (STp->buffer)->buffer_size,		       (STp->buffer)->buffer_blocks));	if (STp->drv_write_prot) {		STp->write_prot = 1;                DEBC(printk(ST_DEB_MSG "st%d: Write protected\n", dev));		if ((st_flags & O_ACCMODE) == O_WRONLY || (st_flags & O_ACCMODE) == O_RDWR) {			retval = (-EROFS);			goto err_out;		}	}	if (STp->can_partitions && STp->nbr_partitions < 1) {		/* This code is reached when the device is opened for the first time		   after the driver has been initialized with tape in the drive and the		   partition support has been enabled. */                DEBC(printk(ST_DEB_MSG                            "st%d: Updating partition number in status.\n", dev));		if ((STp->partition = find_partition(STp)) < 0) {			retval = STp->partition;			goto err_out;		}		STp->new_partition = STp->partition;		STp->nbr_partitions = 1; /* This guess will be updated when necessary */	}	if (new_session) {	/* Change the drive parameters for the new mode */		STp->density_changed = STp->blksize_changed = FALSE;		STp->compression_changed = FALSE;		if (!(STm->defaults_for_writes) &&		    (retval = set_mode_densblk(STp, STm)) < 0)		    goto err_out;		if (STp->default_drvbuffer != 0xff) {			if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer))				printk(KERN_WARNING                                       "st%d: Can't set default drive buffering to %d.\n",				       dev, STp->default_drvbuffer);		}	}	return 0; err_out:	if (STp->buffer != NULL) {		(STp->buffer)->in_use = 0;		STp->buffer = NULL;	}	STp->in_use = 0;	if (STp->device->host->hostt->module)

⌨️ 快捷键说明

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