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

📄 scsi_obsolete.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* We do not know how to abort.  Try waiting another		 * time increment and see if this helps. Set the		 * WAS_TIMEDOUT flag set so we do not try this twice		 */	    case SCSI_ABORT_BUSY: /* Tough call - returning 1 from				   * this is too severe				   */	    case SCSI_ABORT_SNOOZE:		if(why == DID_TIME_OUT) {		    SCpnt->internal_timeout &= ~IN_ABORT;		    if(SCpnt->flags & WAS_TIMEDOUT) {			return 1; /* Indicate we cannot handle this.				   * We drop down into the reset handler				   * and try again				   */		    } else {			SCpnt->flags |= WAS_TIMEDOUT;			oldto = SCpnt->timeout_per_command;			update_timeout(SCpnt, oldto);		    }		}		return 0;	    case SCSI_ABORT_PENDING:		if(why != DID_TIME_OUT) {		    update_timeout(SCpnt, oldto);		}		return 0;	    case SCSI_ABORT_SUCCESS:		/* We should have already aborted this one.  No		 * need to adjust timeout		 */                 SCpnt->internal_timeout &= ~IN_ABORT;                 return 0;	    case SCSI_ABORT_NOT_RUNNING:		SCpnt->internal_timeout &= ~IN_ABORT;		update_timeout(SCpnt, 0);		return 0;	    case SCSI_ABORT_ERROR:	    default:		SCpnt->internal_timeout &= ~IN_ABORT;		return 1;	    }	}    }}/* Mark a single SCSI Device as having been reset. */static inline void scsi_mark_device_reset(Scsi_Device *Device){  Device->was_reset = 1;  Device->expecting_cc_ua = 1;}/* Mark all SCSI Devices on a specific Host as having been reset. */void scsi_mark_host_reset(struct Scsi_Host *Host){  Scsi_Cmnd   * SCpnt;  Scsi_Device * SDpnt;  for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next)    {      for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)        scsi_mark_device_reset(SCpnt->device);    }}/* Mark all SCSI Devices on a specific Host Bus as having been reset. */static void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel){  Scsi_Cmnd *SCpnt;  Scsi_Device * SDpnt;  for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next)    {      for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)        if (SCpnt->channel == channel)	  scsi_mark_device_reset(SCpnt->device);    }}static int scsi_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags){    int temp;    Scsi_Cmnd * SCpnt1;    Scsi_Device * SDpnt;    struct Scsi_Host * host = SCpnt->host;    printk("SCSI bus is being reset for host %d channel %d.\n",	   host->host_no, SCpnt->channel);#if 0    /*     * First of all, we need to make a recommendation to the low-level     * driver as to whether a BUS_DEVICE_RESET should be performed,     * or whether we should do a full BUS_RESET.  There is no simple     * algorithm here - we basically use a series of heuristics     * to determine what we should do.     */    SCpnt->host->suggest_bus_reset = FALSE;    /*     * First see if all of the active devices on the bus have     * been jammed up so that we are attempting resets.  If so,     * then suggest a bus reset.  Forcing a bus reset could     * result in some race conditions, but no more than     * you would usually get with timeouts.  We will cross     * that bridge when we come to it.     *     * This is actually a pretty bad idea, since a sequence of     * commands will often timeout together and this will cause a     * Bus Device Reset followed immediately by a SCSI Bus Reset.     * If all of the active devices really are jammed up, the     * Bus Device Reset will quickly timeout and scsi_times_out     * will follow up with a SCSI Bus Reset anyway.     */    SCpnt1 = host->host_queue;    while(SCpnt1) {	if( SCpnt1->request.rq_status != RQ_INACTIVE	    && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )            	break;        SCpnt1 = SCpnt1->next; 	}    if( SCpnt1 == NULL ) {        reset_flags |= SCSI_RESET_SUGGEST_BUS_RESET;    }    /*     * If the code that called us is suggesting a hard reset, then     * definitely request it.  This usually occurs because a     * BUS_DEVICE_RESET times out.     *     * Passing reset_flags along takes care of this automatically.     */    if( reset_flags & SCSI_RESET_SUGGEST_BUS_RESET ) {        SCpnt->host->suggest_bus_reset = TRUE;    }#endif    while (1) {	/*	 * Protect against races here.  If the command is done, or we are	 * on a different command forget it.	 */	if (reset_flags & SCSI_RESET_ASYNCHRONOUS)	  if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {	    return 0;	  }	if (SCpnt->internal_timeout & IN_RESET)	{	    spin_unlock_irq(&io_request_lock);	    while (SCpnt->internal_timeout & IN_RESET)		barrier();	    spin_lock_irq(&io_request_lock);	}	else	{	    SCpnt->internal_timeout |= IN_RESET;	    update_timeout(SCpnt, RESET_TIMEOUT);	    if (reset_flags & SCSI_RESET_SYNCHRONOUS)	      SCpnt->flags |= SYNC_RESET;	    if (host->host_busy)	    {                for(SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)                {                    SCpnt1 = SDpnt->device_queue;                    while(SCpnt1) {                        if (SCpnt1->request.rq_status != RQ_INACTIVE) {#if 0                            if (!(SCpnt1->flags & IS_RESETTING) &&                                !(SCpnt1->internal_timeout & IN_ABORT))                                scsi_abort(SCpnt1, DID_RESET);#endif                            SCpnt1->flags |= (WAS_RESET | IS_RESETTING);                        }                        SCpnt1 = SCpnt1->next;                    }                }		host->last_reset = jiffies;		host->resetting = 1;		/*		 * I suppose that the host reset callback will not play		 * with the resetting field. We have just set the resetting		 * flag here. -arca		 */		temp = host->hostt->reset(SCpnt, reset_flags);		/*		  This test allows the driver to introduce an additional bus		  settle time delay by setting last_reset up to 20 seconds in		  the future.  In the normal case where the driver does not		  modify last_reset, it must be assumed that the actual bus		  reset occurred immediately prior to the return to this code,		  and so last_reset must be updated to the current time, so		  that the delay in internal_cmnd will guarantee at least a		  MIN_RESET_DELAY bus settle time.		*/		if (host->last_reset - jiffies > 20UL * HZ)		  host->last_reset = jiffies;	    }	    else	    {		if (!host->block) host->host_busy++;		host->last_reset = jiffies;		host->resetting = 1;		SCpnt->flags |= (WAS_RESET | IS_RESETTING);		/*		 * I suppose that the host reset callback will not play		 * with the resetting field. We have just set the resetting		 * flag here. -arca		 */		temp = host->hostt->reset(SCpnt, reset_flags);		if (time_before(host->last_reset, jiffies) ||		    (time_after(host->last_reset, jiffies + 20 * HZ)))		  host->last_reset = jiffies;		if (!host->block) host->host_busy--;	    }	    if (reset_flags & SCSI_RESET_SYNCHRONOUS)	      SCpnt->flags &= ~SYNC_RESET;#ifdef DEBUG	    printk("scsi reset function returned %d\n", temp);#endif            /*             * Now figure out what we need to do, based upon             * what the low level driver said that it did.	     * If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING,	     * or SCSI_RESET_WAKEUP, then the low level driver did a	     * bus device reset or bus reset, so we should go through	     * and mark one or all of the devices on that bus	     * as having been reset.             */            switch(temp & SCSI_RESET_ACTION) {	    case SCSI_RESET_SUCCESS:	        if (temp & SCSI_RESET_HOST_RESET)		  scsi_mark_host_reset(host);	        else if (temp & SCSI_RESET_BUS_RESET)		  scsi_mark_bus_reset(host, SCpnt->channel);		else scsi_mark_device_reset(SCpnt->device);		SCpnt->internal_timeout &= ~(IN_RESET|IN_RESET2|IN_RESET3);		return 0;	    case SCSI_RESET_PENDING:	        if (temp & SCSI_RESET_HOST_RESET)		  scsi_mark_host_reset(host);	        else if (temp & SCSI_RESET_BUS_RESET)		  scsi_mark_bus_reset(host, SCpnt->channel);		else scsi_mark_device_reset(SCpnt->device);	    case SCSI_RESET_NOT_RUNNING:		return 0;	    case SCSI_RESET_PUNT:		SCpnt->internal_timeout &= ~(IN_RESET|IN_RESET2|IN_RESET3);                scsi_request_sense (SCpnt);                return 0;	    case SCSI_RESET_WAKEUP:	        if (temp & SCSI_RESET_HOST_RESET)		  scsi_mark_host_reset(host);	        else if (temp & SCSI_RESET_BUS_RESET)		  scsi_mark_bus_reset(host, SCpnt->channel);		else scsi_mark_device_reset(SCpnt->device);		SCpnt->internal_timeout &= ~(IN_RESET|IN_RESET2|IN_RESET3);		scsi_request_sense (SCpnt);                /*                 * If a bus reset was performed, we                 * need to wake up each and every command                 * that was active on the bus or if it was a HBA                 * reset all active commands on all channels                 */                if( temp & SCSI_RESET_HOST_RESET )                {                    for(SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)                    {                        SCpnt1 = SDpnt->device_queue;                        while(SCpnt1) {                            if (SCpnt1->request.rq_status != RQ_INACTIVE                                && SCpnt1 != SCpnt)                                scsi_request_sense (SCpnt1);                            SCpnt1 = SCpnt1->next;                        }                    }                } else if( temp & SCSI_RESET_BUS_RESET ) {                    for(SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)                    {                        SCpnt1 = SDpnt->device_queue;                        while(SCpnt1) {                            if(SCpnt1->request.rq_status != RQ_INACTIVE                               && SCpnt1 != SCpnt                               && SCpnt1->channel == SCpnt->channel)                                scsi_request_sense (SCpnt);                            SCpnt1 = SCpnt1->next;                        }                    }                }		return 0;	    case SCSI_RESET_SNOOZE:		/* In this case, we set the timeout field to 0		 * so that this command does not time out any more,		 * and we return 1 so that we get a message on the		 * screen.		 */		SCpnt->internal_timeout &= ~(IN_RESET|IN_RESET2|IN_RESET3);		update_timeout(SCpnt, 0);		/* If you snooze, you lose... */	    case SCSI_RESET_ERROR:	    default:		return 1;	    }	    return temp;	}    }}/* * The strategy is to cause the timer code to call scsi_times_out() * when the soonest timeout is pending. * The arguments are used when we are queueing a new command, because * we do not want to subtract the time used from this time, but when we * set the timer, we want to take this value into account. */int update_timeout(Scsi_Cmnd * SCset, int timeout){  int	rtn;  /*   * We are using the new error handling code to actually register/deregister   * timers for timeout.   */  if( !timer_pending(&SCset->eh_timeout) )    {      rtn = 0;    }  else    {      rtn = SCset->eh_timeout.expires - jiffies;    }  if( timeout == 0 )    {      scsi_delete_timer(SCset);    }  else    {      scsi_add_timer(SCset, timeout, scsi_old_times_out);    }  return rtn;}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */

⌨️ 快捷键说明

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