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

📄 osst.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif	if (frame < 0 || frame >= STp->capacity) return (-ENXIO);	if (frame <= STp->first_data_ppos) {		STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;		return (osst_set_frame_position(STp, aSRpnt, frame, 0));	}	r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);	if (r < 0) return r;	r = osst_get_logical_frame(STp, aSRpnt, -1, 1);	if (r < 0) return r;	if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);	if (offset) {		STp->logical_blk_num      += offset / STp->block_size;		STp->buffer->read_pointer  = offset;		STp->buffer->buffer_bytes -= offset;	} else {		STp->frame_seq_number++;		STp->frame_in_buffer       = 0;		STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);		STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;	}	STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);	if (STps->eof == ST_FM_HIT) {		STps->drv_file++;		STps->drv_block = 0;	} else {		STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?				    STp->logical_blk_num -					(STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):				  -1;	}	STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;#if DEBUG	printk(OSST_DEB_MSG 		"osst%d:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",		dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,		STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);#endif	return 0;}/* * Read back the drive's internal buffer contents, as a part * of the write error recovery mechanism for old OnStream * firmware revisions. * Precondition for this function to work: all frames in the * drive's buffer must be of one type (DATA, MARK or EOD)! */static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,					unsigned int frame, unsigned int skip, int pending){	Scsi_Request  * SRpnt = * aSRpnt;	unsigned char * buffer, * p;	unsigned char	cmd[MAX_COMMAND_SIZE];	int             flag, new_frame, i;	int             nframes          = STp->cur_frames;	int             blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);	int             frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)						- (nframes + pending - 1);	int             logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 						- (nframes + pending - 1) * blks_per_frame;	int		dev              = TAPE_NR(STp->devt);	long		startwait        = jiffies;#if DEBUG	int		dbg              = debugging;#endif	if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)		return (-EIO);	printk(KERN_INFO "osst%d:I: Reading back %d frames from drive buffer%s\n",			 dev, nframes, pending?" and one that was pending":"");	osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));#if DEBUG	if (pending && debugging)		printk(OSST_DEB_MSG "osst%d:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",				dev, frame_seq_number + nframes,			       	logical_blk_num + nframes * blks_per_frame,			       	p[0], p[1], p[2], p[3]);#endif	for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = 0x3C;		/* Buffer Read           */		cmd[1] = 6;		/* Retrieve Faulty Block */		cmd[7] = 32768 >> 8;		cmd[8] = 32768 & 0xff;		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,					    STp->timeout, MAX_RETRIES, TRUE);			if ((STp->buffer)->syscall_result || !SRpnt) {			printk(KERN_ERR "osst%d:E: Failed to read frame back from OnStream buffer\n", dev);			vfree((void *)buffer);			*aSRpnt = SRpnt;			return (-EIO);		}		osst_copy_from_buffer(STp->buffer, p);#if DEBUG		if (debugging)			printk(OSST_DEB_MSG "osst%d:D: Read back logical frame %d, data %02x %02x %02x %02x\n",					  dev, frame_seq_number + i, p[0], p[1], p[2], p[3]);#endif	}	*aSRpnt = SRpnt;	osst_get_frame_position(STp, aSRpnt);#if DEBUG	printk(OSST_DEB_MSG "osst%d:D: Frames left in buffer: %d\n", dev, STp->cur_frames);#endif	/* Write synchronously so we can be sure we're OK again and don't have to recover recursively */	/* In the header we don't actually re-write the frames that fail, just the ones after them */	for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {		if (flag) {			if (STp->write_type == OS_WRITE_HEADER) {				i += skip;				p += skip * OS_DATA_SIZE;			}			else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)				new_frame = 3000-i;			else				new_frame += skip;#if DEBUG			printk(OSST_DEB_MSG "osst%d:D: Position to frame %d, write fseq %d\n",						dev, new_frame+i, frame_seq_number+i);#endif			osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);			osst_wait_ready(STp, aSRpnt, 60);			osst_get_frame_position(STp, aSRpnt);			SRpnt = * aSRpnt;			if (new_frame > frame + 1000) {				printk(KERN_ERR "osst%d:E: Failed to find writable tape media\n", dev);				vfree((void *)buffer);				return (-EIO);			}			flag = 0;			if ( i >= nframes + pending ) break;		}		osst_copy_to_buffer(STp->buffer, p);		/*		 * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!		 */		osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,			       	logical_blk_num + i*blks_per_frame,			       	ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);		memset(cmd, 0, MAX_COMMAND_SIZE);		cmd[0] = WRITE_6;		cmd[1] = 1;		cmd[4] = 1;#if DEBUG		if (debugging)			printk(OSST_DEB_MSG				"osst%d:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",				dev, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,				p[0], p[1], p[2], p[3]);#endif		SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,					    STp->timeout, MAX_WRITE_RETRIES, TRUE);		if (STp->buffer->syscall_result)			flag = 1;		else {			p += OS_DATA_SIZE; i++;			/* if we just sent the last frame, wait till all successfully written */			if ( i == nframes + pending ) {#if DEBUG				printk(OSST_DEB_MSG "osst%d:D: Check re-write successful\n", dev);#endif				memset(cmd, 0, MAX_COMMAND_SIZE);				cmd[0] = WRITE_FILEMARKS;				cmd[1] = 1;				SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,							    STp->timeout, MAX_WRITE_RETRIES, TRUE);#if DEBUG				if (debugging) {					printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);					printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);					debugging = 0;				}#endif				flag = STp->buffer->syscall_result;				while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {					memset(cmd, 0, MAX_COMMAND_SIZE);					cmd[0] = TEST_UNIT_READY;					SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,									 MAX_READY_RETRIES, TRUE);					if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&					    (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {						/* in the process of becoming ready */						schedule_timeout(HZ / 10);						continue;					}					if (STp->buffer->syscall_result)						flag = 1;					break;				}#if DEBUG				debugging = dbg;				printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);#endif			}		}		*aSRpnt = SRpnt;		if (flag) {			if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&			     SRpnt->sr_sense_buffer[12]         ==  0 &&			     SRpnt->sr_sense_buffer[13]         ==  2) {				printk(KERN_ERR "osst%d:E: Volume overflow in write error recovery\n", dev);				vfree((void *)buffer);				return (-EIO);			/* hit end of tape = fail */			}			i = ((SRpnt->sr_sense_buffer[3] << 24) |			     (SRpnt->sr_sense_buffer[4] << 16) |			     (SRpnt->sr_sense_buffer[5] <<  8) |			      SRpnt->sr_sense_buffer[6]        ) - new_frame;			p = &buffer[i * OS_DATA_SIZE];#if DEBUG			printk(OSST_DEB_MSG "osst%d:D: Additional write error at %d\n", dev, new_frame+i);#endif			osst_get_frame_position(STp, aSRpnt);#if DEBUG			printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",					  dev, STp->first_frame_position, STp->last_frame_position);#endif		}	}    	if (!pending)		osst_copy_to_buffer(STp->buffer, p);	/* so buffer content == at entry in all cases */	vfree((void *)buffer);	return 0;}static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,					unsigned int frame, unsigned int skip, int pending){	unsigned char	cmd[MAX_COMMAND_SIZE];	Scsi_Request  * SRpnt;	int		dev       = TAPE_NR(STp->devt);	int		expected  = 0;	int		attempts  = 1000 / skip;	int		flag      = 1;	long		startwait = jiffies;#if DEBUG	int		dbg       = debugging;#endif	while (attempts && time_before(jiffies, startwait + 60*HZ)) {		if (flag) {#if DEBUG			debugging = dbg;#endif			if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)				frame = 3000-skip;			expected = frame+skip+STp->cur_frames+pending;#if DEBUG			printk(OSST_DEB_MSG "osst%d:D: Position to fppos %d, re-write from fseq %d\n",					  dev, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);#endif			osst_set_frame_position(STp, aSRpnt, frame + skip, 1);			flag = 0;			attempts--;		}		if (osst_get_frame_position(STp, aSRpnt) < 0) {		/* additional write error */#if DEBUG			printk(OSST_DEB_MSG "osst%d:D: Addl error, host %d, tape %d, buffer %d\n",					  dev, STp->first_frame_position,					  STp->last_frame_position, STp->cur_frames);#endif			frame = STp->last_frame_position;			flag = 1;			continue;		}		if (pending && STp->cur_frames < 50) {			memset(cmd, 0, MAX_COMMAND_SIZE);			cmd[0] = WRITE_6;			cmd[1] = 1;			cmd[4] = 1;#if DEBUG			printk(OSST_DEB_MSG "osst%d:D: About to write pending fseq %d at fppos %d\n",					  dev, STp->frame_seq_number-1, STp->first_frame_position);#endif			SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,						      STp->timeout, MAX_WRITE_RETRIES, TRUE);			*aSRpnt = SRpnt;			if (STp->buffer->syscall_result) {		/* additional write error */				if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&				     SRpnt->sr_sense_buffer[12]         ==  0 &&				     SRpnt->sr_sense_buffer[13]         ==  2) {					printk(KERN_ERR					       "osst%d:E: Volume overflow in write error recovery\n",					       dev);					break;				/* hit end of tape = fail */				}				flag = 1;			}			else				pending = 0;			continue;		}		if (STp->cur_frames == 0) {#if DEBUG			debugging = dbg;			printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);#endif			if (STp->first_frame_position != expected) {				printk(KERN_ERR "osst%d:A: Actual position %d - expected %d\n", 						dev, STp->first_frame_position, expected);				return (-EIO);			}			return 0;		}#if DEBUG		if (debugging) {			printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);			printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);			debugging = 0;		}#endif		schedule_timeout(HZ / 10);	}	printk(KERN_ERR "osst%d:E: Failed to find valid tape media\n", dev);#if DEBUG	debugging = dbg;#endif	return (-EIO);}/* * Error recovery algorithm for the OnStream tape. */static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending){	Scsi_Request * SRpnt  = * aSRpnt;	ST_partstat  * STps   = & STp->ps[STp->partition];	int            dev    = TAPE_NR(STp->devt);	int            retval = 0;	int            rw_state;	unsigned int  frame, skip;	rw_state = STps->rw;	if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3	  || SRpnt->sr_sense_buffer[12]         != 12	  || SRpnt->sr_sense_buffer[13]         != 0) {#if DEBUG		printk(OSST_DEB_MSG "osst%d:D: Write error recovery cannot handle %02x:%02x:%02x\n", dev,			SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);#endif		return (-EIO);	}	frame =	(SRpnt->sr_sense_buffer[3] << 24) |		(SRpnt->sr_sense_buffer[4] << 16) |		(SRpnt->sr_sense_buffer[5] <<  8) |		 SRpnt->sr_sense_buffer[6];	skip  =  SRpnt->sr_sense_buffer[9]; #if DEBUG	printk(OSST_DEB_MSG "osst%d:D: Detected physical bad frame at %u, advised to skip %d\n", dev, frame, skip);#endif	osst_get_frame_position(STp, aSRpnt);#if DEBUG	printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",			dev, STp->first_frame_position, STp->last_frame_position);#endif	switch (STp->write_type) {	   case OS_WRITE_DATA:	   case OS_WRITE_EOD:	   case OS_WRITE_NEW_MARK:		printk(KERN_WARNING 			"osst%d:I: Relocating %d buffered logical frames from position %u to %u\n",			dev, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);		if (STp->os_fw_rev >= 10600)			retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);		else			retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);		printk(KERN_WARNING "osst%d:%s: %sWrite error%srecovered\n", dev,			       	retval?"E"    :"I",			       	retval?""     :"Don't worry, ",			       	retval?" not ":" ");		break;	   case OS_WRITE_LAST_MARK:		printk(KERN_ERR "osst%d:E: Bad frame in update last marker, fatal\n", dev);

⌨️ 快捷键说明

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