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

📄 scsi.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      scsi_bh_queue_head = NULL;            if( SCpnt == NULL ) {          spin_unlock_irqrestore(&io_request_lock, flags);          return;          }            SCnext = SCpnt->bh_next;            for(; SCpnt; SCpnt = SCnext)      {          SCnext = SCpnt->bh_next;                    switch( scsi_decide_disposition(SCpnt) )          {          case SUCCESS:              /*               * Add to BH queue.               */              SCSI_LOG_MLCOMPLETE(3,printk("Command finished %d %d 0x%x\n", SCpnt->host->host_busy,                     SCpnt->host->host_failed,                     SCpnt->result));                            scsi_finish_command(SCpnt);              break;          case NEEDS_RETRY:              /*               * We only come in here if we want to retry a command.  The               * test to see whether the command should be retried should be               * keeping track of the number of tries, so we don't end up looping,               * of course.               */              SCSI_LOG_MLCOMPLETE(3,printk("Command needs retry %d %d 0x%x\n", SCpnt->host->host_busy,                     SCpnt->host->host_failed, SCpnt->result));                            scsi_retry_command(SCpnt);              break;          case ADD_TO_MLQUEUE:              /*                * This typically happens for a QUEUE_FULL message -               * typically only when the queue depth is only               * approximate for a given device.  Adding a command               * to the queue for the device will prevent further commands               * from being sent to the device, so we shouldn't end up               * with tons of things being sent down that shouldn't be.               */              scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);              break;          default:              /*               * Here we have a fatal error of some sort.  Turn it over to               * the error handler.               */              SCSI_LOG_MLCOMPLETE(3,printk("Command failed %p %x active=%d busy=%d failed=%d\n",                                            SCpnt, SCpnt->result,                                           atomic_read(&SCpnt->host->host_active),                                           SCpnt->host->host_busy,                                           SCpnt->host->host_failed));                            /*               * Dump the sense information too.               */              if ((status_byte (SCpnt->result) & CHECK_CONDITION) != 0)              {                  SCSI_LOG_MLCOMPLETE(3,print_sense("bh",SCpnt));              }              if( SCpnt->host->eh_wait != NULL )              {                  SCpnt->host->host_failed++;                  SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;                  SCpnt->state = SCSI_STATE_FAILED;                  SCpnt->host->in_recovery = 1;                  /*                   * If the host is having troubles, then look to see if this was the last                   * command that might have failed.  If so, wake up the error handler.                   */                  if( SCpnt->host->host_busy == SCpnt->host->host_failed )                  {                    SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",                                                      atomic_read(&SCpnt->host->eh_wait->count)));                      up(SCpnt->host->eh_wait);                  }              }              else              {                  /*                   * We only get here if the error recovery thread has died.                   */                  scsi_finish_command(SCpnt);              }          }      } /* for(; SCpnt...) */  } /* while(1==1) */  spin_unlock_irqrestore(&io_request_lock, flags);}/* * Function:    scsi_retry_command * * Purpose:     Send a command back to the low level to be retried. * * Notes:       This command is always executed in the context of the *              bottom half handler, or the error handler thread. Low *              level drivers should not become re-entrant as a result of *              this. */intscsi_retry_command(Scsi_Cmnd * SCpnt){  memcpy ((void *) SCpnt->cmnd,  (void*) SCpnt->data_cmnd,          sizeof(SCpnt->data_cmnd));  SCpnt->request_buffer = SCpnt->buffer;  SCpnt->request_bufflen = SCpnt->bufflen;  SCpnt->use_sg = SCpnt->old_use_sg;  SCpnt->cmd_len = SCpnt->old_cmd_len;  SCpnt->result = 0;  memset ((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer);  return internal_cmnd (SCpnt);}/* * Function:    scsi_finish_command * * Purpose:     Pass command off to upper layer for finishing of I/O *              request, waking processes that are waiting on results, *              etc. */voidscsi_finish_command(Scsi_Cmnd * SCpnt){    struct Scsi_Host * host;    Scsi_Device * device;    host = SCpnt->host;    device = SCpnt->device;    host->host_busy--; /* Indicate that we are free */    device->device_busy--; /* Decrement device usage counter. */      if (host->block && host->host_busy == 0)     {        host_active = NULL;                /* For block devices "wake_up" is done in end_scsi_request */        if (!SCSI_BLK_MAJOR(MAJOR(SCpnt->request.rq_dev))) {            struct Scsi_Host * next;                        for (next = host->block; next != host; next = next->block)                wake_up(&next->host_wait);        }            }      /*     * Now try and drain the mid-level queue if any commands have been     * inserted.  Check to see whether the queue even has anything in     * it first, as otherwise this is useless overhead.     */    if( SCpnt->host->pending_commands != NULL )    {        scsi_mlqueue_finish(SCpnt->host, SCpnt->device);    }    wake_up(&host->host_wait);        /*     * If we have valid sense information, then some kind of recovery     * must have taken place.  Make a note of this.     */    if( scsi_sense_valid(SCpnt) )    {        SCpnt->result |= (DRIVER_SENSE << 24);    }        SCSI_LOG_MLCOMPLETE(3,printk("Notifying upper driver of completion for device %d %x\n",                                     SCpnt->device->id, SCpnt->result));        SCpnt->owner = SCSI_OWNER_HIGHLEVEL;    SCpnt->state = SCSI_STATE_FINISHED;    /* We can get here with use_sg=0, causing a panic in the upper level (DB) */    SCpnt->use_sg = SCpnt->old_use_sg;    SCpnt->done (SCpnt);}#ifdef CONFIG_MODULESstatic int scsi_register_host(Scsi_Host_Template *);static void scsi_unregister_host(Scsi_Host_Template *);#endifvoid *scsi_malloc(unsigned int len){    unsigned int nbits, mask;    int i, j;    if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE)	return NULL;    nbits = len >> 9;    mask = (1 << nbits) - 1;    for(i=0;i < dma_sectors / SECTORS_PER_PAGE; i++)	for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){	    if ((dma_malloc_freelist[i] & (mask << j)) == 0){		dma_malloc_freelist[i] |= (mask << j);		scsi_dma_free_sectors -= nbits;#ifdef DEBUG                SCSI_LOG_MLQUEUE(3,printk("SMalloc: %d %p [From:%p]\n",len, dma_malloc_pages[i] + (j << 9)));		printk("SMalloc: %d %p [From:%p]\n",len, dma_malloc_pages[i] + (j << 9));#endif		return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));	    }	}    return NULL;  /* Nope.  No more */}int scsi_free(void *obj, unsigned int len){    unsigned int page, sector, nbits, mask;#ifdef DEBUG    unsigned long ret = 0;#ifdef __mips__    __asm__ __volatile__ ("move\t%0,$31":"=r"(ret));#else   ret = __builtin_return_address(0);#endif    printk("scsi_free %p %d\n",obj, len);    SCSI_LOG_MLQUEUE(3,printk("SFree: %p %d\n",obj, len));#endif    for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {        unsigned long page_addr = (unsigned long) dma_malloc_pages[page];        if ((unsigned long) obj >= page_addr &&	    (unsigned long) obj <  page_addr + PAGE_SIZE)	{	    sector = (((unsigned long) obj) - page_addr) >> 9;            nbits = len >> 9;            mask = (1 << nbits) - 1;            if ((mask << sector) >= (1 << SECTORS_PER_PAGE))                panic ("scsi_free:Bad memory alignment");            if((dma_malloc_freelist[page] &                (mask << sector)) != (mask<<sector)){#ifdef DEBUG		printk("scsi_free(obj=%p, len=%d) called from %08lx\n",                       obj, len, ret);#endif                panic("scsi_free:Trying to free unused memory");            }            scsi_dma_free_sectors += nbits;            dma_malloc_freelist[page] &= ~(mask << sector);            return 0;	}    }    panic("scsi_free:Bad offset");}int scsi_loadable_module_flag; /* Set after we scan builtin drivers */void * scsi_init_malloc(unsigned int size, int gfp_mask){    void * retval;    /*     * For buffers used by the DMA pool, we assume page aligned      * structures.     */    if ((size % PAGE_SIZE) == 0) {	int order, a_size;	for (order = 0, a_size = PAGE_SIZE;             a_size < size; order++, a_size <<= 1)            ;	retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order);    } else	retval = kmalloc(size, gfp_mask);    if (retval)	memset(retval, 0, size);    return retval;}void scsi_init_free(char * ptr, unsigned int size){    /*     * We need this special code here because the DMA pool assumes     * page aligned data.  Besides, it is wasteful to allocate     * page sized chunks with kmalloc.     */    if ((size % PAGE_SIZE) == 0) {    	int order, a_size;	for (order = 0, a_size = PAGE_SIZE;	     a_size < size; order++, a_size <<= 1)	    ;	free_pages((unsigned long)ptr, order);    } else	kfree(ptr);}void scsi_build_commandblocks(Scsi_Device * SDpnt){    struct Scsi_Host *host = SDpnt->host;    int j;    Scsi_Cmnd * SCpnt;    if (SDpnt->queue_depth == 0)        SDpnt->queue_depth = host->cmd_per_lun;    SDpnt->device_queue = NULL;    for(j=0;j<SDpnt->queue_depth;j++){        SCpnt = (Scsi_Cmnd *)              scsi_init_malloc(sizeof(Scsi_Cmnd),                               GFP_ATOMIC |                               (host->unchecked_isa_dma ? GFP_DMA : 0));	if (NULL == SCpnt)	    break; /* If not, the next line will oops ... */        memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));	SCpnt->host                      = host;	SCpnt->device                    = SDpnt;	SCpnt->target                    = SDpnt->id;	SCpnt->lun                       = SDpnt->lun;	SCpnt->channel                   = SDpnt->channel;	SCpnt->request.rq_status         = RQ_INACTIVE;        SCpnt->host_wait                 = FALSE;        SCpnt->device_wait               = FALSE;	SCpnt->use_sg                    = 0;	SCpnt->old_use_sg                = 0;	SCpnt->old_cmd_len               = 0;	SCpnt->underflow                 = 0;	SCpnt->transfersize              = 0;	SCpnt->serial_number             = 0;	SCpnt->serial_number_at_timeout  = 0;	SCpnt->host_scribble             = NULL;	SCpnt->next                      = SDpnt->device_queue;	SDpnt->device_queue              = SCpnt;        SCpnt->state                     = SCSI_STATE_UNUSED;        SCpnt->owner                     = SCSI_OWNER_NOBODY;    }    if (j < SDpnt->queue_depth) { /* low on space (D.Gilbert 990424) */	printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n",	       SDpnt->queue_depth, j);	SDpnt->queue_depth = j;	SDpnt->has_cmdblocks = (0 != j);    }    else	SDpnt->has_cmdblocks = 1;}#ifndef MODULE /* { *//* * scsi_dev_init() is our initialization routine, which in turn calls host * initialization, bus scanning, and sd/st initialization routines. * This is only used at boot time. */__initfunc(int scsi_dev_init(void)){    Scsi_Device * SDpnt;    struct Scsi_Host * shpnt;    struct Scsi_Device_Template * sdtpnt;#ifdef FOO_ON_YOU    return;#endif    /* Yes we're here... */#if CONFIG_PROC_FS    dispatch_scsi_info_ptr = dispatch_scsi_info;#endif    /* Init a few things so we can "malloc" memory. */    scsi_loadable_module_flag = 0;    /* Register the /proc/scsi/scsi entry */#if CONFIG_PROC_FS    proc_scsi_register(0, &proc_scsi_scsi);#endif    /* initialize all hosts */    scsi_init();    /*     * This is where the processing takes place for most everything     * when commands are completed.  Until we do this, we will not be able     * to queue any commands.     */    init_bh(SCSI_BH, scsi_bottom_half_handler);    for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {	scan_scsis(shpnt,0,0,0,0);           /* scan for scsi devices */	if (shpnt->select_queue_depths != NULL)	    (shpnt->select_queue_depths)(shpnt, shpnt->host_queue);    }    printk("scsi : detected ");    for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)	if (sdtpnt->dev_noticed && sdtpnt->name)	    printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name,		   (sdtpnt->dev_noticed != 1) ? "s" : "");    printk("total.\n");    for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)	if(sdtpnt->init && s

⌨️ 快捷键说明

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