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

📄 scsi_lib.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * If there are blocks left over at the end, set up the command	 * to queue the remainder of them.	 */	if (req->bh) {                request_queue_t *q;		if( !requeue )		{			return SCpnt;		}                q = &SCpnt->device->request_queue;		req->buffer = bh->b_data;		/*		 * Bleah.  Leftovers again.  Stick the leftovers in		 * the front of the queue, and goose the queue again.		 */		scsi_queue_next_request(q, SCpnt);		return SCpnt;	}	/*	 * This request is done.  If there is someone blocked waiting for this	 * request, wake them up.  Typically used to wake up processes trying	 * to swap a page into memory.	 */	if (req->waiting != NULL) {		complete(req->waiting);	}	add_blkdev_randomness(MAJOR(req->rq_dev));        SDpnt = SCpnt->device;	/*	 * This will goose the queue request function at the end, so we don't	 * need to worry about launching another command.	 */	__scsi_release_command(SCpnt);	if( frequeue ) {		request_queue_t *q;		q = &SDpnt->request_queue;		scsi_queue_next_request(q, NULL);                	}	return NULL;}/* * Function:    scsi_end_request() * * Purpose:     Post-processing of completed commands called from interrupt *              handler or a bottom-half handler. * * Arguments:   SCpnt    - command that is complete. *              uptodate - 1 if I/O indicates success, 0 for I/O error. *              sectors  - number of sectors we want to mark. * * Lock status: Assumed that lock is not held upon entry. * * Returns:     Nothing * * Notes:       This is called for block device requests in order to *              mark some number of sectors as complete. *  *		We are guaranteeing that the request queue will be goosed *		at some point during this call. */Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors){	return __scsi_end_request(SCpnt, uptodate, sectors, 1, 1);}/* * Function:    scsi_release_buffers() * * Purpose:     Completion processing for block device I/O requests. * * Arguments:   SCpnt   - command that we are bailing. * * Lock status: Assumed that no lock is held upon entry. * * Returns:     Nothing * * Notes:       In the event that an upper level driver rejects a *		command, we must release resources allocated during *		the __init_io() function.  Primarily this would involve *		the scatter-gather table, and potentially any bounce *		buffers. */static void scsi_release_buffers(Scsi_Cmnd * SCpnt){	ASSERT_LOCK(&io_request_lock, 0);	/*	 * Free up any indirection buffers we allocated for DMA purposes. 	 */	if (SCpnt->use_sg) {		struct scatterlist *sgpnt;		void **bbpnt;		int i;		sgpnt = (struct scatterlist *) SCpnt->request_buffer;		bbpnt = SCpnt->bounce_buffers;		if (bbpnt) {			for (i = 0; i < SCpnt->use_sg; i++) {				if (bbpnt[i])					scsi_free(sgpnt[i].address, sgpnt[i].length);			}		}		scsi_free(SCpnt->request_buffer, SCpnt->sglist_len);	} else {		if (SCpnt->request_buffer != SCpnt->request.buffer) {			scsi_free(SCpnt->request_buffer, SCpnt->request_bufflen);		}	}	/*	 * Zero these out.  They now point to freed memory, and it is	 * dangerous to hang onto the pointers.	 */	SCpnt->buffer  = NULL;	SCpnt->bufflen = 0;	SCpnt->request_buffer = NULL;	SCpnt->request_bufflen = 0;}/* * Function:    scsi_io_completion() * * Purpose:     Completion processing for block device I/O requests. * * Arguments:   SCpnt   - command that is finished. * * Lock status: Assumed that no lock is held upon entry. * * Returns:     Nothing * * Notes:       This function is matched in terms of capabilities to *              the function that created the scatter-gather list. *              In other words, if there are no bounce buffers *              (the normal case for most drivers), we don't need *              the logic to deal with cleaning up afterwards. */void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,			int block_sectors){	int result = SCpnt->result;	int this_count = SCpnt->bufflen >> 9;	request_queue_t *q = &SCpnt->device->request_queue;	/*	 * We must do one of several things here:	 *	 *	Call scsi_end_request.  This will finish off the specified	 *	number of sectors.  If we are done, the command block will	 *	be released, and the queue function will be goosed.  If we	 *	are not done, then scsi_end_request will directly goose	 *	the queue.	 *	 *	We can just use scsi_queue_next_request() here.  This	 *	would be used if we just wanted to retry, for example.	 *	 */	ASSERT_LOCK(&io_request_lock, 0);	/*	 * Free up any indirection buffers we allocated for DMA purposes. 	 * For the case of a READ, we need to copy the data out of the	 * bounce buffer and into the real buffer.	 */	if (SCpnt->use_sg) {		struct scatterlist *sgpnt;		void **bbpnt;		int i;		sgpnt = (struct scatterlist *) SCpnt->buffer;		bbpnt = SCpnt->bounce_buffers;		if (bbpnt) {			for (i = 0; i < SCpnt->use_sg; i++) {				if (bbpnt[i]) {					if (SCpnt->request.cmd == READ) {						memcpy(bbpnt[i],						       sgpnt[i].address,						       sgpnt[i].length);					}					scsi_free(sgpnt[i].address, sgpnt[i].length);				}			}		}		scsi_free(SCpnt->buffer, SCpnt->sglist_len);	} else {		if (SCpnt->buffer != SCpnt->request.buffer) {			if (SCpnt->request.cmd == READ) {				memcpy(SCpnt->request.buffer, SCpnt->buffer,				       SCpnt->bufflen);			}			scsi_free(SCpnt->buffer, SCpnt->bufflen);		}	}	/*	 * Zero these out.  They now point to freed memory, and it is	 * dangerous to hang onto the pointers.	 */	SCpnt->buffer  = NULL;	SCpnt->bufflen = 0;	SCpnt->request_buffer = NULL;	SCpnt->request_bufflen = 0;	/*	 * Next deal with any sectors which we were able to correctly	 * handle.	 */	if (good_sectors > 0) {		SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d sectors done.\n",					      SCpnt->request.nr_sectors,					      good_sectors));		SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg));		SCpnt->request.errors = 0;		/*		 * If multiple sectors are requested in one buffer, then		 * they will have been finished off by the first command.		 * If not, then we have a multi-buffer command.		 *		 * If block_sectors != 0, it means we had a medium error		 * of some sort, and that we want to mark some number of		 * sectors as not uptodate.  Thus we want to inhibit		 * requeueing right here - we will requeue down below		 * when we handle the bad sectors.		 */		SCpnt = __scsi_end_request(SCpnt, 					   1, 					   good_sectors,					   result == 0,					   1);		/*		 * If the command completed without error, then either finish off the		 * rest of the command, or start a new one.		 */		if (result == 0 || SCpnt == NULL ) {			return;		}	}	/*	 * Now, if we were good little boys and girls, Santa left us a request	 * sense buffer.  We can extract information from this, so we	 * can choose a block to remap, etc.	 */	if (driver_byte(result) != 0) {		if (suggestion(result) == SUGGEST_REMAP) {#ifdef REMAP			/*			 * Not yet implemented.  A read will fail after being remapped,			 * a write will call the strategy routine again.			 */			if (SCpnt->device->remap) {				result = 0;			}#endif		}		if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) {			/*			 * If the device is in the process of becoming ready,			 * retry.			 */			if (SCpnt->sense_buffer[12] == 0x04 &&			    SCpnt->sense_buffer[13] == 0x01) {				scsi_queue_next_request(q, SCpnt);				return;			}			if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) {				if (SCpnt->device->removable) {					/* detected disc change.  set a bit 					 * and quietly refuse further access.		 			 */					SCpnt->device->changed = 1;					SCpnt = scsi_end_request(SCpnt, 0, this_count);					return;				} else {					/*				 	* Must have been a power glitch, or a				 	* bus reset.  Could not have been a				 	* media change, so we just retry the				 	* request and see what happens.  				 	*/					scsi_queue_next_request(q, SCpnt);					return;				}			}		}		/* If we had an ILLEGAL REQUEST returned, then we may have		 * performed an unsupported command.  The only thing this should be		 * would be a ten byte read where only a six byte read was supported.		 * Also, on a system where READ CAPACITY failed, we have have read		 * past the end of the disk.		 */		switch (SCpnt->sense_buffer[2]) {		case ILLEGAL_REQUEST:			if (SCpnt->device->ten) {				SCpnt->device->ten = 0;				/*				 * This will cause a retry with a 6-byte				 * command.				 */				scsi_queue_next_request(q, SCpnt);				result = 0;			} else {				SCpnt = scsi_end_request(SCpnt, 0, this_count);				return;			}			break;		case NOT_READY:			printk(KERN_INFO "Device %s not ready.\n",			       kdevname(SCpnt->request.rq_dev));			SCpnt = scsi_end_request(SCpnt, 0, this_count);			return;			break;		case MEDIUM_ERROR:		case VOLUME_OVERFLOW:			printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ",			       SCpnt->host->host_no, (int) SCpnt->channel,			       (int) SCpnt->target, (int) SCpnt->lun);			print_command(SCpnt->cmnd);			print_sense("sd", SCpnt);			SCpnt = scsi_end_request(SCpnt, 0, block_sectors);			return;		default:			break;		}	}			/* driver byte != 0 */	if (host_byte(result) == DID_RESET) {		/*		 * Third party bus reset or reset for error		 * recovery reasons.  Just retry the request		 * and see what happens.  		 */		scsi_queue_next_request(q, SCpnt);		return;	}	if (result) {		struct Scsi_Device_Template *STpnt;		STpnt = scsi_get_request_dev(&SCpnt->request);		printk("SCSI %s error : host %d channel %d id %d lun %d return code = %x\n",		       (STpnt ? STpnt->name : "device"),		       SCpnt->device->host->host_no,		       SCpnt->device->channel,		       SCpnt->device->id,		       SCpnt->device->lun, result);		if (driver_byte(result) & DRIVER_SENSE)			print_sense("sd", SCpnt);		/*		 * Mark a single buffer as not uptodate.  Queue the remainder.		 * We sometimes get this cruft in the event that a medium error		 * isn't properly reported.		 */		SCpnt = scsi_end_request(SCpnt, 0, SCpnt->request.current_nr_sectors);		return;	}}/* * Function:    scsi_get_request_dev() * * Purpose:     Find the upper-level driver that is responsible for this *              request * * Arguments:   request   - I/O request we are preparing to queue. * * Lock status: No locks assumed to be held, but as it happens the *              io_request_lock is held when this is called. * * Returns:     Nothing * * Notes:       The requests in the request queue may have originated *              from any block device driver.  We need to find out which *              one so that we can later form the appropriate command. */struct Scsi_Device_Template *scsi_get_request_dev(struct request *req){	struct Scsi_Device_Template *spnt;	kdev_t dev = req->rq_dev;	int major = MAJOR(dev);	ASSERT_LOCK(&io_request_lock, 1);	for (spnt = scsi_devicelist; spnt; spnt = spnt->next) {		/*		 * Search for a block device driver that supports this		 * major.		 */		if (spnt->blk && spnt->major == major) {

⌨️ 快捷键说明

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