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

📄 sym_glue.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct sym_tcb *tp;	int t, l;	switch (uc->cmd) {	case 0: return;#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT	case UC_SETDEBUG:		sym_debug_flags = uc->data;		break;#endif	case UC_SETVERBOSE:		np->verbose = uc->data;		break;	default:		/*		 * We assume that other commands apply to targets.		 * This should always be the case and avoid the below 		 * 4 lines to be repeated 6 times.		 */		for (t = 0; t < SYM_CONF_MAX_TARGET; t++) {			if (!((uc->target >> t) & 1))				continue;			tp = &np->target[t];			switch (uc->cmd) {			case UC_SETSYNC:				if (!uc->data || uc->data >= 255) {					tp->tgoal.iu = tp->tgoal.dt =						tp->tgoal.qas = 0;					tp->tgoal.offset = 0;				} else if (uc->data <= 9 && np->minsync_dt) {					if (uc->data < np->minsync_dt)						uc->data = np->minsync_dt;					tp->tgoal.iu = tp->tgoal.dt =						tp->tgoal.qas = 1;					tp->tgoal.width = 1;					tp->tgoal.period = uc->data;					tp->tgoal.offset = np->maxoffs_dt;				} else {					if (uc->data < np->minsync)						uc->data = np->minsync;					tp->tgoal.iu = tp->tgoal.dt =						tp->tgoal.qas = 0;					tp->tgoal.period = uc->data;					tp->tgoal.offset = np->maxoffs;				}				tp->tgoal.check_nego = 1;				break;			case UC_SETWIDE:				tp->tgoal.width = uc->data ? 1 : 0;				tp->tgoal.check_nego = 1;				break;			case UC_SETTAGS:				for (l = 0; l < SYM_CONF_MAX_LUN; l++)					sym_tune_dev_queuing(tp, l, uc->data);				break;			case UC_RESETDEV:				tp->to_reset = 1;				np->istat_sem = SEM;				OUTB(np, nc_istat, SIGP|SEM);				break;			case UC_CLEARDEV:				for (l = 0; l < SYM_CONF_MAX_LUN; l++) {					struct sym_lcb *lp = sym_lp(tp, l);					if (lp) lp->to_clear = 1;				}				np->istat_sem = SEM;				OUTB(np, nc_istat, SIGP|SEM);				break;			case UC_SETFLAG:				tp->usrflags = uc->data;				break;			}		}		break;	}}static int skip_spaces(char *ptr, int len){	int cnt, c;	for (cnt = len; cnt > 0 && (c = *ptr++) && isspace(c); cnt--);	return (len - cnt);}static int get_int_arg(char *ptr, int len, u_long *pv){	char *end;	*pv = simple_strtoul(ptr, &end, 10);	return (end - ptr);}static int is_keyword(char *ptr, int len, char *verb){	int verb_len = strlen(verb);	if (len >= verb_len && !memcmp(verb, ptr, verb_len))		return verb_len;	else		return 0;}#define SKIP_SPACES(ptr, len)						\	if ((arg_len = skip_spaces(ptr, len)) < 1)			\		return -EINVAL;						\	ptr += arg_len; len -= arg_len;#define GET_INT_ARG(ptr, len, v)					\	if (!(arg_len = get_int_arg(ptr, len, &(v))))			\		return -EINVAL;						\	ptr += arg_len; len -= arg_len;/* * Parse a control command */static int sym_user_command(struct sym_hcb *np, char *buffer, int length){	char *ptr	= buffer;	int len		= length;	struct sym_usrcmd cmd, *uc = &cmd;	int		arg_len;	u_long 		target;	memset(uc, 0, sizeof(*uc));	if (len > 0 && ptr[len-1] == '\n')		--len;	if	((arg_len = is_keyword(ptr, len, "setsync")) != 0)		uc->cmd = UC_SETSYNC;	else if	((arg_len = is_keyword(ptr, len, "settags")) != 0)		uc->cmd = UC_SETTAGS;	else if	((arg_len = is_keyword(ptr, len, "setverbose")) != 0)		uc->cmd = UC_SETVERBOSE;	else if	((arg_len = is_keyword(ptr, len, "setwide")) != 0)		uc->cmd = UC_SETWIDE;#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT	else if	((arg_len = is_keyword(ptr, len, "setdebug")) != 0)		uc->cmd = UC_SETDEBUG;#endif	else if	((arg_len = is_keyword(ptr, len, "setflag")) != 0)		uc->cmd = UC_SETFLAG;	else if	((arg_len = is_keyword(ptr, len, "resetdev")) != 0)		uc->cmd = UC_RESETDEV;	else if	((arg_len = is_keyword(ptr, len, "cleardev")) != 0)		uc->cmd = UC_CLEARDEV;	else		arg_len = 0;#ifdef DEBUG_PROC_INFOprintk("sym_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd);#endif	if (!arg_len)		return -EINVAL;	ptr += arg_len; len -= arg_len;	switch(uc->cmd) {	case UC_SETSYNC:	case UC_SETTAGS:	case UC_SETWIDE:	case UC_SETFLAG:	case UC_RESETDEV:	case UC_CLEARDEV:		SKIP_SPACES(ptr, len);		if ((arg_len = is_keyword(ptr, len, "all")) != 0) {			ptr += arg_len; len -= arg_len;			uc->target = ~0;		} else {			GET_INT_ARG(ptr, len, target);			uc->target = (1<<target);#ifdef DEBUG_PROC_INFOprintk("sym_user_command: target=%ld\n", target);#endif		}		break;	}	switch(uc->cmd) {	case UC_SETVERBOSE:	case UC_SETSYNC:	case UC_SETTAGS:	case UC_SETWIDE:		SKIP_SPACES(ptr, len);		GET_INT_ARG(ptr, len, uc->data);#ifdef DEBUG_PROC_INFOprintk("sym_user_command: data=%ld\n", uc->data);#endif		break;#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT	case UC_SETDEBUG:		while (len > 0) {			SKIP_SPACES(ptr, len);			if	((arg_len = is_keyword(ptr, len, "alloc")))				uc->data |= DEBUG_ALLOC;			else if	((arg_len = is_keyword(ptr, len, "phase")))				uc->data |= DEBUG_PHASE;			else if	((arg_len = is_keyword(ptr, len, "queue")))				uc->data |= DEBUG_QUEUE;			else if	((arg_len = is_keyword(ptr, len, "result")))				uc->data |= DEBUG_RESULT;			else if	((arg_len = is_keyword(ptr, len, "scatter")))				uc->data |= DEBUG_SCATTER;			else if	((arg_len = is_keyword(ptr, len, "script")))				uc->data |= DEBUG_SCRIPT;			else if	((arg_len = is_keyword(ptr, len, "tiny")))				uc->data |= DEBUG_TINY;			else if	((arg_len = is_keyword(ptr, len, "timing")))				uc->data |= DEBUG_TIMING;			else if	((arg_len = is_keyword(ptr, len, "nego")))				uc->data |= DEBUG_NEGO;			else if	((arg_len = is_keyword(ptr, len, "tags")))				uc->data |= DEBUG_TAGS;			else if	((arg_len = is_keyword(ptr, len, "pointer")))				uc->data |= DEBUG_POINTER;			else				return -EINVAL;			ptr += arg_len; len -= arg_len;		}#ifdef DEBUG_PROC_INFOprintk("sym_user_command: data=%ld\n", uc->data);#endif		break;#endif /* SYM_LINUX_DEBUG_CONTROL_SUPPORT */	case UC_SETFLAG:		while (len > 0) {			SKIP_SPACES(ptr, len);			if	((arg_len = is_keyword(ptr, len, "no_disc")))				uc->data &= ~SYM_DISC_ENABLED;			else				return -EINVAL;			ptr += arg_len; len -= arg_len;		}		break;	default:		break;	}	if (len)		return -EINVAL;	else {		unsigned long flags;		spin_lock_irqsave(np->s.host->host_lock, flags);		sym_exec_user_command (np, uc);		spin_unlock_irqrestore(np->s.host->host_lock, flags);	}	return length;}#endif	/* SYM_LINUX_USER_COMMAND_SUPPORT */#ifdef SYM_LINUX_USER_INFO_SUPPORT/* *  Informations through the proc file system. */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;}/* *  Copy formatted information into the input buffer. */static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len){	struct info_str info;	info.buffer	= ptr;	info.length	= len;	info.offset	= offset;	info.pos	= 0;	copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "			 "revision id 0x%x\n",			 np->s.chip_name, np->device_id, np->revision_id);	copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",		pci_name(np->s.device), IRQ_PRM(np->s.irq));	copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",			 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),			 np->maxwide ? "Wide" : "Narrow",			 np->minsync_dt ? ", DT capable" : "");	copy_info(&info, "Max. started commands %d, "			 "max. commands per LUN %d\n",			 SYM_CONF_MAX_START, SYM_CONF_MAX_TAG);	return info.pos > info.offset? info.pos - info.offset : 0;}#endif /* SYM_LINUX_USER_INFO_SUPPORT *//* *  Entry point of the scsi proc fs of the driver. *  - func = 0 means read  (returns adapter infos) *  - func = 1 means write (not yet merget from sym53c8xx) */static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,			char **start, off_t offset, int length, int func){	struct sym_hcb *np = sym_get_hcb(host);	int retv;	if (func) {#ifdef	SYM_LINUX_USER_COMMAND_SUPPORT		retv = sym_user_command(np, buffer, length);#else		retv = -EINVAL;#endif	} else {		if (start)			*start = buffer;#ifdef SYM_LINUX_USER_INFO_SUPPORT		retv = sym_host_info(np, buffer, offset, length);#else		retv = -EINVAL;#endif	}	return retv;}#endif /* SYM_LINUX_PROC_INFO_SUPPORT *//* *	Free controller resources. */static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev){	/*	 *  Free O/S specific resources.	 */	if (np->s.irq)		free_irq(np->s.irq, np);	if (np->s.ioaddr)		pci_iounmap(pdev, np->s.ioaddr);	if (np->s.ramaddr)		pci_iounmap(pdev, np->s.ramaddr);	/*	 *  Free O/S independent resources.	 */	sym_hcb_free(np);	sym_mfree_dma(np, sizeof(*np), "HCB");}/* *  Ask/tell the system about DMA addressing. */static int sym_setup_bus_dma_mask(struct sym_hcb *np){#if SYM_CONF_DMA_ADDRESSING_MODE > 0#if   SYM_CONF_DMA_ADDRESSING_MODE == 1#define	DMA_DAC_MASK	0x000000ffffffffffULL /* 40-bit */#elif SYM_CONF_DMA_ADDRESSING_MODE == 2#define	DMA_DAC_MASK	DMA_64BIT_MASK#endif	if ((np->features & FE_DAC) &&			!pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {		np->use_dac = 1;		return 0;	}#endif	if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))		return 0;	printf_warning("%s: No suitable DMA available\n", sym_name(np));	return -1;}/* *  Host attach and initialisations. * *  Allocate host data and ncb structure. *  Remap MMIO region. *  Do chip initialization. *  If all is OK, install interrupt handling and *  start the timer daemon. */static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,		int unit, struct sym_device *dev){	struct host_data *host_data;	struct sym_hcb *np = NULL;	struct Scsi_Host *instance = NULL;	struct pci_dev *pdev = dev->pdev;	unsigned long flags;	struct sym_fw *fw;	printk(KERN_INFO		"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",		unit, dev->chip.name, dev->chip.revision_id,		pci_name(pdev), IRQ_PRM(pdev->irq));	/*	 *  Get the firmware for this chip.	 */	fw = sym_find_firmware(&dev->chip);	if (!fw)		goto attach_failed;	/*	 *	Allocate host_data structure	 */	instance = scsi_host_alloc(tpnt, sizeof(*host_data));	if (!instance)		goto attach_failed;	host_data = (struct host_data *) instance->hostdata;	/*	 *  Allocate immediately the host control block, 	 *  since we are only expecting to succeed. :)	 *  We keep track in the HCB of all the resources that 	 *  are to be released on error.	 */	np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB");	if (!np)		goto attach_failed;	np->s.device = pdev;	np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */	host_data->ncb = np;	np->s.host = instance;	pci_set_drvdata(pdev, np);	/*	 *  Copy some useful infos to the HCB.	 */	np->hcb_ba	= vtobus(np);	np->verbose	= sym_driver_setup.verbose;	np->s.device	= pdev;	np->s.unit	= unit;	np->device_id	= dev->chip.device_id;	np->revision_id	= dev->chip.revision_id;	np->features	= dev->chip.features;	np->clock_divn	= dev->chip.nr_divisor;	np->maxoffs	= dev->chip.offset_max;	np->maxburst	= dev->chip.burst_max;	np->myaddr	= dev->host_id;	/*	 *  Edit its name.	 */	strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));	sprintf(np->s.inst_name, "sym%d", np->s.unit);	if (sym_setup_bus_dma_mask(np))		goto attach_failed;	/*	 *  Try to map the controller chip to	 *  virtual and physical memory.	 */	np->mmio_ba = (u32)dev->mmio_base;	np->s.ioaddr	= dev->s.ioaddr;	np->s.ramaddr	= dev->s.ramaddr;	np->s.io_ws = (np->features & FE_IO256) ? 256 : 128;	/*	 *  Map on-chip RAM if present and supported.	 */	if (!(np->features & FE_RAM))		dev->ram_base = 0;	if (dev->ram_base) {		np->ram_ba = (u32)dev->ram_base;		np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096;	}	if (sym_hcb_attach(instance, fw, dev->nvram))		goto attach_failed;	/*	 *  Install the interrupt handler.	 *  If we synchonize the C code with SCRIPTS on interrupt, 	 *  we do not want to share the INTR line at all.	 */	if (request_irq(pdev->irq, sym53c8xx_intr, SA_SHIRQ, NAME53C8XX, np)) {		printf_err("%s: request irq %d failure\n",			sym_name(np), pdev->irq);		goto attach_failed;	}	np->s.irq = pdev->irq;	/*	 *  After SCSI devices have been opened, we cannot	 *  reset the bus safely, so we do it here.	 */	spin_lock_irqsave(instance->host_lock, flags);	if (sym_reset_scsi_bus(np, 0))		goto reset_failed;	/*	 *  Start the SCRIPTS.	 */	sym_start_up (np, 1);	/*	 *  Start the timer daemon	 */	init_timer(&np->s.timer);	np->s.timer.data     = (unsigned long) np;	np->s.timer.function = sym53c8xx_timer;	np->s.lasttime=0;	sym_timer (np);	/*	 *  Fill Linux host instance structure	 *  and return success.	 */

⌨️ 快捷键说明

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