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

📄 scsi.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
*/
	
/*
	Since we're nice guys and specified that abort() and reset()
	can be non-reentrant.  The internal_timeout flags are used for
	this.
*/


int scsi_abort (Scsi_Cmnd * SCpnt, int why)
	{
	int temp, oldto;
	struct Scsi_Host * host = SCpnt->host;
	
	while(1)	
		{
		cli();
		if (SCpnt->internal_timeout & IN_ABORT) 
			{
			sti();
			while (SCpnt->internal_timeout & IN_ABORT);
			}
		else
			{	
			SCpnt->internal_timeout |= IN_ABORT;
			oldto = update_timeout(SCpnt, ABORT_TIMEOUT);

			
			sti();
			if (!host->host_busy || !host->hostt->abort(SCpnt, why))
				temp =  0;
			else
				temp = 1;
			
			cli();
			SCpnt->internal_timeout &= ~IN_ABORT;
			update_timeout(SCpnt, oldto);
			sti();
			return temp;
			}
		}	
	}

int scsi_reset (Scsi_Cmnd * SCpnt)
	{
	int temp, oldto;
	Scsi_Cmnd * SCpnt1;
	struct Scsi_Host * host = SCpnt->host;
	
#ifdef DEBUG
	printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",host->host_no);
#endif
	while (1) {
		cli();	
		if (SCpnt->internal_timeout & IN_RESET)
			{
			sti();
			while (SCpnt->internal_timeout & IN_RESET);
			}
		else
			{
			SCpnt->internal_timeout |= IN_RESET;
			oldto = update_timeout(SCpnt, RESET_TIMEOUT);	
					
			if (host->host_busy)
				{	
				sti();
				SCpnt1 = host->host_queue;
				while(SCpnt1) {
				  if ((SCpnt1->request.dev > 0) &&
				      !(SCpnt1->flags & IS_RESETTING) && 
				      !(SCpnt1->internal_timeout & IN_ABORT))
				    scsi_abort(SCpnt1, DID_RESET);
				  SCpnt1 = SCpnt1->next;
				};

				temp = host->hostt->reset(SCpnt);	
				}				
			else
				{
				host->host_busy++;
	
				sti();
				temp = host->hostt->reset(SCpnt);
				host->last_reset = jiffies;
				host->host_busy--;
				}
	
			cli();
			SCpnt->internal_timeout &= ~IN_RESET;
			update_timeout(SCpnt, oldto);
			sti();
			return temp;	
			}
		}
	}
			 

static void scsi_main_timeout(void)
	{
	/*
		We must not enter update_timeout with a timeout condition still pending.
	*/

	int timed_out;
	struct Scsi_Host * host;
	Scsi_Cmnd * SCpnt = NULL;

	do 	{	
		cli();

	/*
		Find all timers such that they have 0 or negative (shouldn't happen)
		time remaining on them.
	*/
			
		timed_out = 0;
		for(host = scsi_hostlist; host; host = host->next) {
		  SCpnt = host->host_queue;
		  while (SCpnt){
		    if (SCpnt->timeout > 0 && SCpnt->timeout <= time_elapsed)
		      {
			sti();
			SCpnt->timeout = 0;
			scsi_times_out(SCpnt);
			++timed_out; 
			cli();
		      }
		  SCpnt =  SCpnt->next;
		  };
		};
		update_timeout(NULL, 0);
	      } while (timed_out);	
	sti();
      }

/*
	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.
*/
	
static int update_timeout(Scsi_Cmnd * SCset, int timeout)
	{
	unsigned int least, used;
	unsigned int oldto;
	struct Scsi_Host * host;
	Scsi_Cmnd * SCpnt = NULL;

	cli();

/* 
	Figure out how much time has passed since the last time the timeouts 
   	were updated 
*/
	used = (time_start) ? (jiffies - time_start) : 0;

/*
	Find out what is due to timeout soonest, and adjust all timeouts for
	the amount of time that has passed since the last time we called 
	update_timeout. 
*/
	
	oldto = 0;

	if(SCset){
	  oldto = SCset->timeout - used;
	  SCset->timeout = timeout + used;
	};

	least = 0xffffffff;

	for(host = scsi_hostlist; host; host = host->next) {
	  SCpnt = host->host_queue;
	  while (SCpnt){
	    if (SCpnt->timeout > 0 && (SCpnt->timeout -= used) < least)
	      least = SCpnt->timeout;
	    SCpnt =  SCpnt->next;
	  };
	};

/*
	If something is due to timeout again, then we will set the next timeout 
	interrupt to occur.  Otherwise, timeouts are disabled.
*/
	
	if (least != 0xffffffff)
		{
		time_start = jiffies;	
		timer_table[SCSI_TIMER].expires = (time_elapsed = least) + jiffies;	
		timer_active |= 1 << SCSI_TIMER;
		}
	else
		{
		timer_table[SCSI_TIMER].expires = time_start = time_elapsed = 0;
		timer_active &= ~(1 << SCSI_TIMER);
		}	
	sti();
	return oldto;
	}		


static unsigned short * dma_malloc_freelist = NULL;
static unsigned int dma_sectors = 0;
unsigned int dma_free_sectors = 0;
unsigned int need_isa_buffer = 0;
static unsigned char * dma_malloc_buffer = NULL;

void *scsi_malloc(unsigned int len)
{
  unsigned int nbits, mask;
  int i, j;
  if((len & 0x1ff) || len > 4096)
    panic("Inappropriate buffer size requested");
  
  cli();
  nbits = len >> 9;
  mask = (1 << nbits) - 1;
  
  for(i=0;i < (dma_sectors >> 4); i++)
    for(j=0; j<17-nbits; j++){
      if ((dma_malloc_freelist[i] & (mask << j)) == 0){
	dma_malloc_freelist[i] |= (mask << j);
	sti();
	dma_free_sectors -= nbits;
#ifdef DEBUG
	printk("SMalloc: %d %x ",len, dma_malloc_buffer + (i << 13) + (j << 9));
#endif
	return (void *) ((unsigned long) dma_malloc_buffer + (i << 13) + (j << 9));
      };
    };
  sti();
  return NULL;  /* Nope.  No more */
}

int scsi_free(void *obj, unsigned int len)
{
  int offset;
  int page, sector, nbits, mask;

#ifdef DEBUG
  printk("Sfree %x %d\n",obj, len);
#endif

  offset = ((int) obj) - ((int) dma_malloc_buffer);

  if (offset < 0) panic("Bad offset");
  page = offset >> 13;
  sector = offset >> 9;
  if(sector >= dma_sectors) panic ("Bad page");

  sector = (offset >> 9) & 15;
  nbits = len >> 9;
  mask = (1 << nbits) - 1;

  if ((mask << sector) > 0xffff) panic ("Bad memory alignment");

  cli();
  if(dma_malloc_freelist[page] & (mask << sector) != (mask<<sector))
    panic("Trying to free unused memory");

  dma_free_sectors += nbits;
  dma_malloc_freelist[page] &= ~(mask << sector);
  sti();
  return 0;
}

/*
	scsi_dev_init() is our initialization routine, which inturn calls host 
	initialization, bus scanning, and sd/st initialization routines.  It 
	should be called from main().
*/

unsigned long scsi_dev_init (unsigned long memory_start,unsigned long memory_end)
	{
	int i;
	struct Scsi_Host * host;
	Scsi_Cmnd * SCpnt;
#ifdef FOO_ON_YOU
	return;
#endif	
	timer_table[SCSI_TIMER].fn = scsi_main_timeout;
	timer_table[SCSI_TIMER].expires = 0;

	/* initialize all hosts */
	memory_start = scsi_init(memory_start, memory_end); 
				
	scsi_devices = (Scsi_Device *) memory_start;
        scan_scsis();           /* scan for scsi devices */
	memory_start += NR_SCSI_DEVICES * sizeof(Scsi_Device);

	memory_start = sd_init1(memory_start, memory_end);
        memory_start = st_init1(memory_start, memory_end);
	memory_start = sr_init1(memory_start, memory_end);
	memory_start = sg_init1(memory_start, memory_end);

	last_cmnd = (Scsi_Cmnd *) memory_start;

	SCpnt = last_cmnd;

	for (i=0; i< NR_SCSI_DEVICES; i++) {
	  int j;
	  switch (scsi_devices[i].type)
	    {
	    case TYPE_TAPE :
	      st_attach(&scsi_devices[i]);
	      break;
	    case TYPE_ROM:
	      sr_attach(&scsi_devices[i]);
	      break;
	    case TYPE_DISK:
	    case TYPE_MOD:
	      sd_attach(&scsi_devices[i]);
	    default:
	      break;
	    };
	  sg_attach(&scsi_devices[i]);
	  if(scsi_devices[i].type != -1){
	    for(j=0;j<scsi_devices[i].host->hostt->cmd_per_lun;j++){
	      SCpnt->host = scsi_devices[i].host;
	      SCpnt->target = scsi_devices[i].id;
	      SCpnt->lun = scsi_devices[i].lun;
	      SCpnt->index = i;
	      SCpnt->request.dev = -1; /* Mark not busy */
	      SCpnt->use_sg = 0;
	      SCpnt->old_use_sg = 0;
              SCpnt->underflow = 0;
              SCpnt->transfersize = 0;
	      SCpnt->host_scribble = NULL;
	      host = scsi_devices[i].host;
	      if(host->host_queue)
		host->host_queue->prev = SCpnt;
	      SCpnt->next = host->host_queue;
	      SCpnt->prev = NULL;
	      host->host_queue = SCpnt;
	      SCpnt++;
	    };
	  };
	};

	memory_start = (int) SCpnt;

	if (NR_SD > 0 || NR_SR > 0 || NR_ST > 0)
	  dma_sectors = 16;  /* Base value we use */

	for (i = 0; i < NR_SCSI_DEVICES; ++i) {
	  struct Scsi_Host * host;
	  host = scsi_devices[i].host;
	  
	  if(scsi_devices[i].type != TYPE_TAPE)
	    dma_sectors += ((host->sg_tablesize * 
			     sizeof(struct scatterlist) + 511) >> 9) * 
			       host->hostt->cmd_per_lun;
	  
	  if(host->unchecked_isa_dma &&
	     memory_end > ISA_DMA_THRESHOLD &&
	     scsi_devices[i].type != TYPE_TAPE) {
	    dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
	      host->hostt->cmd_per_lun;
	    need_isa_buffer++;
	  };
	};

	dma_sectors = (dma_sectors + 15) & 0xfff0;
	dma_free_sectors = dma_sectors;  /* This must be a multiple of 16 */

	memory_start = (memory_start + 3) & 0xfffffffc;
	dma_malloc_freelist = (unsigned short *) memory_start;
	memory_start += dma_sectors >> 3;
	memset(dma_malloc_freelist, 0, dma_sectors >> 3);

	if(memory_start & 1) memory_start++; /* Some host adapters require
						buffers to be word aligned */
	dma_malloc_buffer = (unsigned char *) memory_start;
	memory_start += dma_sectors << 9;

	memory_start = sd_init(memory_start, memory_end); /* init scsi disks */
        memory_start = st_init(memory_start, memory_end); /* init scsi tapes */
	memory_start = sr_init(memory_start, memory_end); /* init scsi CDROMs */
	memory_start = sg_init(memory_start, memory_end); /* init scsi generic */
	
	return memory_start;
	}

static void print_inquiry(unsigned char *data)
{
        int i;

	printk("  Vendor: ");
	for (i = 8; i < 16; i++)
	        {
	        if (data[i] >= 0x20 && i < data[4] + 5)
		        printk("%c", data[i]);
	        else
		        printk(" ");
	        }

	printk("  Model: ");
	for (i = 16; i < 32; i++)
	        {
	        if (data[i] >= 0x20 && i < data[4] + 5)
		        printk("%c", data[i]);
	        else
		        printk(" ");
	        }

	printk("  Rev: ");
	for (i = 32; i < 36; i++)
	        {
	        if (data[i] >= 0x20 && i < data[4] + 5)
		        printk("%c", data[i]);
	        else
		        printk(" ");
	        }

	printk("\n");

	i = data[0] & 0x1f;

	printk("  Type:   %s ",
	       i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : "Unknown          " );
	printk("                 ANSI SCSI revision: %02x", data[2] & 0x07);
	if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
	  printk(" CCS\n");
	else
	  printk("\n");
}

⌨️ 快捷键说明

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