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

📄 scsi.c

📁 linux0.99源代码用于研究linux操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
					break;			        }			}			else				{				status = FINISHED;				break;				}			/* fall through to REDO */		case REDO:			if (SCpnt->flags & WAS_SENSE)							scsi_request_sense(SCpnt); 				else				  {			    memcpy ((void *) SCpnt->cmnd,				    (void*) SCpnt->data_cmnd, 				    sizeof(SCpnt->data_cmnd));			    SCpnt->request_buffer = SCpnt->buffer;			    SCpnt->request_bufflen = SCpnt->bufflen;			    internal_cmnd (SCpnt);			  };			break;			default: 			INTERNAL_ERROR;		}	if (status == FINISHED) 		{		#ifdef DEBUG			printk("Calling done function - at address %08x\n", SCpnt->done);		#endif		host_busy[host]--; /* Indicate that we are free */		wake_up(&host_wait[host]);		SCpnt->result = result | ((exit & 0xff) << 24);		SCpnt->done (SCpnt);		}#undef FINISHED#undef REDO#undef MAYREDO#undef PENDING	}/*	The scsi_abort function interfaces with the abort() function of the host	we are aborting, and causes the current command to not complete.  The 	caller should deal with any error messages or status returned on the 	next call.		This will not be called rentrantly for a given host.*/	/*	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;	int 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_busy[host] || !scsi_hosts[host].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;	int host = SCpnt->host;	#ifdef DEBUG	printk("Danger Will Robinson! - SCSI bus for host %d is being reset.\n",host);#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_busy[host])				{					sti();				SCpnt1 = host_queue[host];				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 = scsi_hosts[host].reset();							}							else				{				host_busy[host]++;					sti();				temp = scsi_hosts[host].reset();				last_reset[host] = jiffies;				host_busy[host]--;				}				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, 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 = 0; host < max_scsi_hosts; host++) {		  SCpnt = host_queue[host];		  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();      }/*	These are used to keep track of things. */static int time_start, time_elapsed;/*	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, host;	unsigned int oldto;	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 = 0; host < max_scsi_hosts; host++) {	  SCpnt = host_queue[host];	  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;char *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(char *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;	int host;	Scsi_Cmnd * SCpnt;#ifdef FOO_ON_YOU	return;#endif		timer_table[SCSI_TIMER].fn = scsi_main_timeout;	timer_table[SCSI_TIMER].expires = 0;	scsi_init();            /* initialize all hosts */	for (i = 0; i < max_scsi_hosts; ++i)		last_reset[i] = 0;					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);	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;	    };	  if(scsi_devices[i].type != -1){	    for(j=0;j<scsi_hosts[scsi_devices[i].host_no].cmd_per_lun;j++){	      SCpnt->host = scsi_devices[i].host_no;	      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;	      host = scsi_devices[i].host_no;	      if(host_queue[host])		host_queue[host]->prev = SCpnt;	      SCpnt->next = host_queue[host];	      SCpnt->prev = NULL;	      host_queue[host] = 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) {	  int host;	  host = scsi_devices[i].host_no;	  	  if(scsi_devices[i].type != TYPE_TAPE)	    dma_sectors += ((scsi_hosts[host].sg_tablesize * 			     sizeof(struct scatterlist) + 511) >> 9) * 			       scsi_hosts[host].cmd_per_lun;	  	  if(scsi_hosts[host].unchecked_isa_dma &&	     memory_end > ISA_DMA_THRESHOLD &&	     scsi_devices[i].type != TYPE_TAPE) {	    dma_sectors += 32 * scsi_hosts[host].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 = (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);	return memory_start;	}static void print_inquiry(unsigned char *data){        int i;	printk("  Vendor: ");	for (i = 8; i < 16; i++)	        {	        if (data[i] >= 20 && i < data[4] + 5)		        printk("%c", data[i]);	        else		        printk(" ");	        }	printk("  Model: ");	for (i = 16; i < 32; i++)	        {	        if (data[i] >= 20 && i < data[4] + 5)		        printk("%c", data[i]);	        else		        printk(" ");	        }	printk("  Rev: ");	for (i = 32; i < 36; i++)	        {	        if (data[i] >= 20 && i < data[4] + 5)		        printk("%c", data[i]);	        else		        printk(" ");	        }	printk("\n");	i = data[0] & 0x1f;	printk("  Type:   %s ", i == 0x00 ? "Direct-Access    " :				i == 0x01 ? "Sequential-Access" :				i == 0x02 ? "Printer          " :				i == 0x03 ? "Processor        " :				i == 0x04 ? "WORM             " :				i == 0x05 ? "CD-ROM           " :				i == 0x06 ? "Scanner          " :				i == 0x07 ? "Optical Device   " :				i == 0x08 ? "Medium Changer   " :				i == 0x09 ? "Communications   " :				            "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 + -