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

📄 ncr53c9x.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	case fas216:	case fas236:	case fsc:		/* Fast ESP variants */		esp_write(eregs->esp_cfg2, esp->config2);		for(i=0; i<8; i++)			esp->config3[i] |= ESP_CONFIG3_FCLK;		esp->prev_cfg3 = esp->config3[0];		esp_write(eregs->esp_cfg3, esp->prev_cfg3);		if(esp->diff)			esp->radelay = 0;		else			esp->radelay = 16;		/* Different timeout constant for these chips */		esp->neg_defp =			FSC_NEG_DEFP(esp->cfreq,				     (esp->cfact == ESP_CCF_F0 ?				      ESP_CCF_F7 + 1 : esp->cfact));		esp_write(eregs->esp_timeo, esp->neg_defp);		/* Enable Active Negotiation if possible */		if((esp->erev == fsc) && !esp->diff)			esp_write(eregs->esp_cfg4, ESP_CONFIG4_EAN);		break;	case fas100a:		/* Fast 100a */		esp_write(eregs->esp_cfg2, esp->config2);		for(i=0; i<8; i++)			esp->config3[i] |= ESP_CONFIG3_FCLOCK;		esp->prev_cfg3 = esp->config3[0];		esp_write(eregs->esp_cfg3, esp->prev_cfg3);		esp->radelay = 32;		break;	default:		panic("esp: what could it be... I wonder...");		break;	};	/* Eat any bitrot in the chip */	trash = esp_read(eregs->esp_intrpt);	udelay(100);}/* This places the ESP into a known state at boot time. */void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs){	volatile unchar trash;	/* Reset the DMA */	if(esp->dma_reset)		esp->dma_reset(esp);	/* Reset the ESP */	esp_reset_esp(esp, eregs);	/* Reset the SCSI bus, but tell ESP not to generate an irq */	esp_write(eregs->esp_cfg1, (esp_read(eregs->esp_cfg1) | ESP_CONFIG1_SRRDISAB));	esp_cmd(esp, eregs, ESP_CMD_RS);	udelay(400);	esp_write(eregs->esp_cfg1, esp->config1);	/* Eat any bitrot in the chip and we are done... */	trash = esp_read(eregs->esp_intrpt);}/* Allocate structure and insert basic data such as SCSI chip frequency * data and a pointer to the device */struct NCR_ESP* esp_allocate(Scsi_Host_Template *tpnt, void *esp_dev){	struct NCR_ESP *esp, *elink;	struct Scsi_Host *esp_host;	esp_host = scsi_register(tpnt, sizeof(struct NCR_ESP));	if(!esp_host)		panic("Cannot register ESP SCSI host");	esp = (struct NCR_ESP *) esp_host->hostdata;	if(!esp)		panic("No esp in hostdata");	esp->ehost = esp_host;	esp->edev = esp_dev;	esp->esp_id = nesps++;	/* Set bitshift value (only used on Amiga with multiple ESPs) */	esp->shift = 2;	/* Put into the chain of esp chips detected */	if(espchain) {		elink = espchain;		while(elink->next) elink = elink->next;		elink->next = esp;	} else {		espchain = esp;	}	esp->next = 0;	return esp;}void esp_deallocate(struct NCR_ESP *esp){	struct NCR_ESP *elink;	if(espchain == esp) {		espchain = 0;	} else {		for(elink = espchain; elink && (elink->next != esp); elink = elink->next);		if(elink) 			elink->next = esp->next;	}	nesps--;}/* Complete initialization of ESP structure and device * Caller must have initialized appropriate parts of the ESP structure * between the call to esp_allocate and this function. */void esp_initialize(struct NCR_ESP *esp){	struct ESP_regs *eregs = esp->eregs;	unsigned int fmhz;	unchar ccf;	int i;		/* Check out the clock properties of the chip. */	/* This is getting messy but it has to be done	 * correctly or else you get weird behavior all	 * over the place.  We are trying to basically	 * figure out three pieces of information.	 *	 * a) Clock Conversion Factor	 *	 *    This is a representation of the input	 *    crystal clock frequency going into the	 *    ESP on this machine.  Any operation whose	 *    timing is longer than 400ns depends on this	 *    value being correct.  For example, you'll	 *    get blips for arbitration/selection during	 *    high load or with multiple targets if this	 *    is not set correctly.	 *	 * b) Selection Time-Out	 *	 *    The ESP isn't very bright and will arbitrate	 *    for the bus and try to select a target	 *    forever if you let it.  This value tells	 *    the ESP when it has taken too long to	 *    negotiate and that it should interrupt	 *    the CPU so we can see what happened.	 *    The value is computed as follows (from	 *    NCR/Symbios chip docs).	 *	 *          (Time Out Period) *  (Input Clock)	 *    STO = ----------------------------------	 *          (8192) * (Clock Conversion Factor)	 *	 *    You usually want the time out period to be	 *    around 250ms, I think we'll set it a little	 *    bit higher to account for fully loaded SCSI	 *    bus's and slow devices that don't respond so	 *    quickly to selection attempts. (yeah, I know	 *    this is out of spec. but there is a lot of	 *    buggy pieces of firmware out there so bite me)	 *	 * c) Imperical constants for synchronous offset	 *    and transfer period register values	 *	 *    This entails the smallest and largest sync	 *    period we could ever handle on this ESP.	 */		fmhz = esp->cfreq;	if(fmhz <= (5000000))		ccf = 0;	else		ccf = (((5000000 - 1) + (fmhz))/(5000000));	if(!ccf || ccf > 8) {		/* If we can't find anything reasonable,		 * just assume 20MHZ.  This is the clock		 * frequency of the older sun4c's where I've		 * been unable to find the clock-frequency		 * PROM property.  All other machines provide		 * useful values it seems.		 */		ccf = ESP_CCF_F4;		fmhz = (20000000);	}	if(ccf==(ESP_CCF_F7+1))		esp->cfact = ESP_CCF_F0;	else if(ccf == ESP_CCF_NEVER)		esp->cfact = ESP_CCF_F2;	else		esp->cfact = ccf;	esp->cfreq = fmhz;	esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);	esp->ctick = ESP_TICK(ccf, esp->ccycle);	esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);	esp->sync_defp = SYNC_DEFP_SLOW;	printk("SCSI ID %d Clk %dMHz CCF=%d TOut %d ",	       esp->scsi_id, (esp->cfreq / 1000000),	       ccf, (int) esp->neg_defp);	/* Fill in ehost data */	esp->ehost->base = (unsigned long)eregs;	esp->ehost->this_id = esp->scsi_id;	esp->ehost->irq = esp->irq;	/* SCSI id mask */	esp->scsi_id_mask = (1 << esp->scsi_id);	/* Probe the revision of this esp */	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);	esp_write(eregs->esp_cfg2, esp->config2);	if((esp_read(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=	   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {		printk("NCR53C90(esp100)\n");		esp->erev = esp100;	} else {		esp->config2 = 0;		esp_write(eregs->esp_cfg2, 0);		esp_write(eregs->esp_cfg3, 5);		if(esp_read(eregs->esp_cfg3) != 5) {			printk("NCR53C90A(esp100a)\n");			esp->erev = esp100a;		} else {			int target;			for(target=0; target<8; target++)				esp->config3[target] = 0;			esp->prev_cfg3 = 0;			esp_write(eregs->esp_cfg3, 0);			if(ccf > ESP_CCF_F5) {				printk("NCR53C9XF(espfast)\n");				esp->erev = fast;				esp->sync_defp = SYNC_DEFP_FAST;			} else {				printk("NCR53C9x(esp236)\n");				esp->erev = esp236;			}		}	}					/* Initialize the command queues */	esp->current_SC = 0;	esp->disconnected_SC = 0;	esp->issue_SC = 0;	/* Clear the state machines. */	esp->targets_present = 0;	esp->resetting_bus = 0;	esp->snip = 0;	esp->fas_premature_intr_workaround = 0;	for(i = 0; i < 32; i++)		esp->espcmdlog[i] = 0;	esp->espcmdent = 0;	for(i = 0; i < 16; i++) {		esp->cur_msgout[i] = 0;		esp->cur_msgin[i] = 0;	}	esp->prevmsgout = esp->prevmsgin = 0;	esp->msgout_len = esp->msgin_len = 0;	/* Clear the one behind caches to hold unmatchable values. */	esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff;	/* Reset the thing before we try anything... */	esp_bootup_reset(esp, eregs);#ifdef MODULE	MOD_INC_USE_COUNT;#endif	esps_in_use++;}/* The info function will return whatever useful * information the developer sees fit.  If not provided, then * the name field will be used instead. */const char *esp_info(struct Scsi_Host *host){	struct NCR_ESP *esp;	esp = (struct NCR_ESP *) host->hostdata;	switch(esp->erev) {	case esp100:		return "ESP100 (NCR53C90)";	case esp100a:		return "ESP100A (NCR53C90A)";	case esp236:		return "ESP236 (NCR53C9x)";	case fas216:		return "Emulex FAS216";	case fas236:		return "Emulex FAS236";	case fas366:		return "QLogic FAS366";	case fas100a:		return "FPESP100A";	case fsc:		return "Symbios Logic 53CF9x-2";	default:		panic("Bogon ESP revision");	};}/* From Wolfgang Stanglmeier's NCR scsi driver. */struct info_str{	char *buffer;	int length;	int offset;	int pos;};static void copy_mem_info(struct info_str *info, char *data, int len){	if (info->pos + len > info->length)		len = info->length - info->pos;	if (info->pos + len < info->offset) {		info->pos += len;		return;	}	if (info->pos < info->offset) {		data += (info->offset - info->pos);		len  -= (info->offset - info->pos);	}	if (len > 0) {		memcpy(info->buffer + info->pos, data, len);		info->pos += len;	}}static int copy_info(struct info_str *info, char *fmt, ...){	va_list args;	char buf[81];	int len;	va_start(args, fmt);	len = vsprintf(buf, fmt, args);	va_end(args);	copy_mem_info(info, buf, len);	return len;}static int esp_host_info(struct NCR_ESP *esp, char *ptr, off_t offset, int len){	struct info_str info;	int i;	info.buffer	= ptr;	info.length	= len;	info.offset	= offset;	info.pos	= 0;	copy_info(&info, "ESP Host Adapter:\n");	copy_info(&info, "\tESP Model\t\t");	switch(esp->erev) {	case esp100:		copy_info(&info, "ESP100 (NCR53C90)\n");		break;	case esp100a:		copy_info(&info, "ESP100A (NCR53C90A)\n");		break;	case esp236:		copy_info(&info, "ESP236 (NCR53C9x)\n");		break;	case fas216:		copy_info(&info, "Emulex FAS216\n");		break;	case fas236:		copy_info(&info, "Emulex FAS236\n");		break;	case fas100a:		copy_info(&info, "FPESP100A\n");		break;	case fast:		copy_info(&info, "Generic FAST\n");		break;	case fas366:		copy_info(&info, "QLogic FAS366\n");		break;	case fsc:		copy_info(&info, "Symbios Logic 53C9x-2\n");		break;	case espunknown:	default:		copy_info(&info, "Unknown!\n");		break;	};	copy_info(&info, "\tLive Targets\t\t[ ");	for(i = 0; i < 15; i++) {		if(esp->targets_present & (1 << i))			copy_info(&info, "%d ", i);	}	copy_info(&info, "]\n\n");		/* Now describe the state of each existing target. */	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\n");	for(i = 0; i < 15; i++) {		if(esp->targets_present & (1 << i)) {			Scsi_Device *SDptr = esp->ehost->host_queue;			while((SDptr->host != esp->ehost) &&			      (SDptr->id != i) &&			      (SDptr->next))				SDptr = SDptr->next;			copy_info(&info, "%d\t\t", i);			copy_info(&info, "%08lx\t", esp->config3[i]);			copy_info(&info, "[%02lx,%02lx]\t\t\t", SDptr->sync_max_offset,				  SDptr->sync_min_period);			copy_info(&info, "%s\n", SDptr->disconnect ? "yes" : "no");		}	}	return info.pos > info.offset? info.pos - info.offset : 0;}/* ESP proc filesystem code. */int esp_proc_info(char *buffer, char **start, off_t offset, int length,		  int hostno, int inout){	struct NCR_ESP *esp;	if(inout)		return -EINVAL; /* not yet */	for_each_esp(esp) {		if(esp->ehost->host_no == hostno)			break;	}	if(!esp)		return -EINVAL;	if(start)		*start = buffer;	return esp_host_info(esp, buffer, offset, length);}static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp){	if(sp->use_sg == 0) {		sp->SCp.this_residual = sp->request_bufflen;		sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;		sp->SCp.buffers_residual = 0;		if (esp->dma_mmu_get_scsi_one)			esp->dma_mmu_get_scsi_one(esp, sp);		else			sp->SCp.have_data_in = (int) sp->SCp.ptr =				(char *) virt_to_phys(sp->request_buffer);	} else {		sp->SCp.buffer = (struct scatterlist *) sp->buffer;		sp->SCp.buffers_residual = sp->use_sg - 1;		sp->SCp.this_residual = sp->SCp.buffer->length;		if (esp->dma_mmu_get_scsi_sgl)

⌨️ 快捷键说明

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