esp.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,423 行 · 第 1/5 页

C
2,423
字号
	    (bursts & DMA_BURST16) == 0 ||	    (bursts & DMA_BURST32) == 0)		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;	/* 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;	init_waitqueue_head(&esp->reset_queue);	/* 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(struct 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>static int __init esp_detect(struct 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 */static int __init esp_detect(struct 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 *//* */static int esp_release(struct Scsi_Host *host){	struct esp *esp = (struct esp *) host->hostdata;	ESP_INTSOFF(esp->dregs);#if 0	esp_reset_dma(esp);	esp_reset_esp(esp);#endif	free_irq(esp->ehost->irq, esp);	sbus_free_consistent(esp->sdev, 16,			     (void *) esp->esp_command, esp->esp_command_dvma);	sbus_iounmap(esp->eregs, ESP_REG_SIZE);	esp->dma->allocated = 0;	esp_chain_del(esp);        return 0;}/* The info function will return whatever useful * information the developer sees fit.  If not provided, then * the name field will be used instead. */static 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 scsi_device *sdev;	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");	shost_for_each_device(sdev, esp->ehost) {		struct esp_device *esp_dev = sdev->hostdata;		uint id = sdev->id;		if (!(esp->targets_present & (1 << id)))			continue;		copy_info(&info, "%d\t\t", id);		copy_info(&info, "%08lx\t", esp->config3[id]);		copy_info(&info, "[%02lx,%02lx]\t\t\t",			esp_dev->sync_max_offset,			esp_dev->sync_min_period);		copy_info(&info, "%s\t\t",			esp_dev->disconnect ? "yes" : "no");		copy_info(&info, "%s\n",			(esp->config3[id] & ESP_CONFIG3_EWIDE) ? "yes" : "no");	}	return info.pos > info.offset? info.pos - info.offset : 0;}/* ESP proc filesystem code. */static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,			 int length, int inout){	struct esp *esp;	if (inout)		return -EINVAL; /* not yet */	for_each_esp(esp) {		if (esp->ehost == host)			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, struct 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,							       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,						       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));

⌨️ 快捷键说明

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