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

📄 esp.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
		bursts = (DMA_BURST32 - 1);	esp->bursts = bursts;}static void __init esp_get_revision(struct esp *esp){	u8 tmp;	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);	sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);	tmp = sbus_readb(esp->eregs + ESP_CFG2);	tmp &= ~ESP_CONFIG2_MAGIC;	if (tmp != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {		/* If what we write to cfg2 does not come back, cfg2		 * is not implemented, therefore this must be a plain		 * esp100.		 */		esp->erev = esp100;		printk("NCR53C90(esp100)\n");	} else {		esp->config2 = 0;		esp->prev_cfg3 = esp->config3[0] = 5;		sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);		sbus_writeb(0, esp->eregs + ESP_CFG3);		sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);		tmp = sbus_readb(esp->eregs + ESP_CFG3);		if (tmp != 5) {			/* The cfg2 register is implemented, however			 * cfg3 is not, must be esp100a.			 */			esp->erev = esp100a;			printk("NCR53C90A(esp100a)\n");		} else {			int target;			for (target = 0; target < 16; target++)				esp->config3[target] = 0;			esp->prev_cfg3 = 0;			sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);			/* All of cfg{1,2,3} implemented, must be one of			 * the fas variants, figure out which one.			 */			if (esp->raw_cfact > ESP_CCF_F5) {				esp->erev = fast;				esp->sync_defp = SYNC_DEFP_FAST;				printk("NCR53C9XF(espfast)\n");			} else {				esp->erev = esp236;				printk("NCR53C9x(esp236)\n");			}			esp->config2 = 0;			sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);		}	}}static void __init esp_init_swstate(struct esp *esp){	int i;	/* Driver spinlock... */	spin_lock_init(&esp->lock);	/* Command queues... */	esp->current_SC = NULL;	esp->disconnected_SC = NULL;	esp->issue_SC = NULL;	/* Target and current command state... */	esp->targets_present = 0;	esp->resetting_bus = 0;	esp->snip = 0;	/* Debugging... */	for(i = 0; i < 32; i++)		esp->espcmdlog[i] = 0;	esp->espcmdent = 0;	/* MSG phase state... */	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;	esp->prev_hme_dmacsr = 0xffffffff;}static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_dev,				 struct sbus_dev *espdma, struct sbus_bus *sbus,				 int id, int hme){	struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp));	struct esp *esp;		if (!esp_host) {		printk("ESP: Cannot register SCSI host\n");		return -1;	}	if (hme)		esp_host->max_id = 16;	esp = (struct esp *) esp_host->hostdata;	esp->ehost = esp_host;	esp->sdev = esp_dev;	esp->esp_id = id;	esp->prom_node = esp_dev->prom_node;	prom_getstring(esp->prom_node, "name", esp->prom_name,		       sizeof(esp->prom_name));	esp_chain_add(esp);	if (esp_find_dvma(esp, espdma) < 0)		goto fail_unlink;	if (esp_map_regs(esp, hme) < 0) {		printk("ESP registers unmappable");		goto fail_dvma_release;	}	if (esp_map_cmdarea(esp) < 0) {		printk("ESP DVMA transport area unmappable");		goto fail_unmap_regs;	}	if (esp_register_irq(esp) < 0)		goto fail_unmap_cmdarea;	esp_get_scsi_id(esp);	esp->diff = prom_getbool(esp->prom_node, "differential");	if (esp->diff)		printk("Differential ");	esp_get_clock_params(esp);	esp_get_bursts(esp, espdma);	esp_get_revision(esp);	esp_init_swstate(esp);	esp_bootup_reset(esp);	return 0;fail_unmap_cmdarea:	sbus_free_consistent(esp->sdev, 16,			     (void *) esp->esp_command,			     esp->esp_command_dvma);fail_unmap_regs:	sbus_iounmap(esp->eregs, ESP_REG_SIZE);fail_dvma_release:	esp->dma->allocated = 0;fail_unlink:	esp_chain_del(esp);	scsi_unregister(esp_host);	return -1;}/* Detecting ESP chips on the machine.  This is the simple and easy * version. */#ifdef CONFIG_SUN4#include <asm/sun4paddr.h>int __init esp_detect(Scsi_Host_Template *tpnt){	static struct sbus_dev esp_dev;	int esps_in_use = 0;	espchain = 0;	if (sun4_esp_physaddr) {		memset (&esp_dev, 0, sizeof(esp_dev));		esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;		esp_dev.irqs[0] = 4;		esp_dev.resource[0].start = sun4_esp_physaddr;		esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1;		esp_dev.resource[0].flags = IORESOURCE_IO;		if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0))			esps_in_use++;		printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use);		esps_running =  esps_in_use;	}	return esps_in_use;}#else /* !CONFIG_SUN4 */int __init esp_detect(Scsi_Host_Template *tpnt){	struct sbus_bus *sbus;	struct sbus_dev *esp_dev, *sbdev_iter;	int nesps = 0, esps_in_use = 0;	espchain = 0;	if (!sbus_root) {#ifdef CONFIG_PCI		return 0;#else		panic("No SBUS in esp_detect()");#endif	}	for_each_sbus(sbus) {		for_each_sbusdev(sbdev_iter, sbus) {			struct sbus_dev *espdma = NULL;			int hme = 0;			/* Is it an esp sbus device? */			esp_dev = sbdev_iter;			if (strcmp(esp_dev->prom_name, "esp") &&			    strcmp(esp_dev->prom_name, "SUNW,esp")) {				if (!strcmp(esp_dev->prom_name, "SUNW,fas")) {					hme = 1;					espdma = esp_dev;				} else {					if (!esp_dev->child ||					    (strcmp(esp_dev->prom_name, "espdma") &&					     strcmp(esp_dev->prom_name, "dma")))						continue; /* nope... */					espdma = esp_dev;					esp_dev = esp_dev->child;					if (strcmp(esp_dev->prom_name, "esp") &&					    strcmp(esp_dev->prom_name, "SUNW,esp"))						continue; /* how can this happen? */				}			}						if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0)				continue;							esps_in_use++;		} /* for each sbusdev */	} /* for each sbus */	printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,	       esps_in_use);	esps_running = esps_in_use;	return esps_in_use;}#endif /* !CONFIG_SUN4 *//* 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 esp *esp;	esp = (struct esp *) host->hostdata;	switch (esp->erev) {	case esp100:		return "Sparc ESP100 (NCR53C90)";	case esp100a:		return "Sparc ESP100A (NCR53C90A)";	case esp236:		return "Sparc ESP236";	case fas236:		return "Sparc ESP236-FAST";	case fashme:		return "Sparc ESP366-HME";	case fas100a:		return "Sparc ESP100A-FAST";	default:		return "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 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, "Sparc ESP Host Adapter:\n");	copy_info(&info, "\tPROM node\t\t%08x\n", (unsigned int) esp->prom_node);	copy_info(&info, "\tPROM name\t\t%s\n", esp->prom_name);	copy_info(&info, "\tESP Model\t\t");	switch (esp->erev) {	case esp100:		copy_info(&info, "ESP100\n");		break;	case esp100a:		copy_info(&info, "ESP100A\n");		break;	case esp236:		copy_info(&info, "ESP236\n");		break;	case fas236:		copy_info(&info, "FAS236\n");		break;	case fas100a:		copy_info(&info, "FAS100A\n");		break;	case fast:		copy_info(&info, "FAST\n");		break;	case fashme:		copy_info(&info, "Happy Meal FAS\n");		break;	case espunknown:	default:		copy_info(&info, "Unknown!\n");		break;	};	copy_info(&info, "\tDMA Revision\t\t");	switch (esp->dma->revision) {	case dvmarev0:		copy_info(&info, "Rev 0\n");		break;	case dvmaesc1:		copy_info(&info, "ESC Rev 1\n");		break;	case dvmarev1:		copy_info(&info, "Rev 1\n");		break;	case dvmarev2:		copy_info(&info, "Rev 2\n");		break;	case dvmarev3:		copy_info(&info, "Rev 3\n");		break;	case dvmarevplus:		copy_info(&info, "Rev 1+\n");		break;	case dvmahme:		copy_info(&info, "Rev HME/FAS\n");		break;	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\tWide\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\t\t", SDptr->disconnect ? "yes" : "no");			copy_info(&info, "%s\n",				  (esp->config3[i] & ESP_CONFIG3_EWIDE) ? "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 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 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 (sp->request_bufflen) {			sp->SCp.have_data_in = sbus_map_single(esp->sdev, sp->SCp.buffer,							       sp->SCp.this_residual,							       scsi_to_sbus_dma_dir(sp->sc_data_direction));			sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in);		} else {			sp->SCp.ptr = NULL;		}	} else {		sp->SCp.buffer = (struct scatterlist *) sp->buffer;		sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,						       sp->SCp.buffer,						       sp->use_sg,						       scsi_to_sbus_dma_dir(sp->sc_data_direction));		sp->SCp.this_residual = sg_dma_len(sp->SCp.buffer);		sp->SCp.ptr = (char *) ((unsigned long)sg_dma_address(sp->SCp.buffer));	}}static void esp_release_dmabufs(struct esp *esp, Scsi_Cmnd *sp){	if (sp->use_sg) {		sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg,			      scsi_to_sbus_dma_dir(sp->sc_data_direction));	} else if (sp->request_bufflen) {		sbus_unmap_single(esp->sdev,				  sp->SCp.have_data_in,				  sp->request_bufflen,				  scsi_to_sbus_dma_dir(sp->sc_data_direction));	}}static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp){	struct esp_pointers *ep = &esp->data_pointers[sp->target];	sp->SCp.ptr = ep->saved_ptr;	sp->SCp.buffer = ep->saved_buffer;	sp->SCp.this_residual = ep->saved_this_residual;	sp->SCp.buffers_residual = ep->saved_buffers_residual;}

⌨️ 快捷键说明

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