wd33c93.c

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

C
2,078
字号
/* * Case 3: If the command is currently disconnected from the bus, * we're not going to expend much effort here: Let's just return * an ABORT_SNOOZE and hope for the best... */	tmp = (struct scsi_cmnd *) hostdata->disconnected_Q;	while (tmp) {		if (tmp == cmd) {			printk			    ("scsi%d: Abort - command %ld found on disconnected_Q - ",			     instance->host_no, cmd->pid);			printk("Abort SNOOZE. ");			enable_irq(cmd->device->host->irq);			return FAILED;		}		tmp = (struct scsi_cmnd *) tmp->host_scribble;	}/* * Case 4 : If we reached this point, the command was not found in any of *     the queues. * * We probably reached this point because of an unlikely race condition * between the command completing successfully and the abortion code, * so we won't panic, but we will notify the user in case something really * broke. *//*   sti();*/	wd33c93_execute(instance);	enable_irq(cmd->device->host->irq);	printk("scsi%d: warning : SCSI command probably completed successfully"	       "         before abortion. ", instance->host_no);	return FAILED;}#define MAX_WD33C93_HOSTS 4#define MAX_SETUP_ARGS ((int)(sizeof(setup_args) / sizeof(char *)))#define SETUP_BUFFER_SIZE 200static char setup_buffer[SETUP_BUFFER_SIZE];static char setup_used[MAX_SETUP_ARGS];static int done_setup = 0;intwd33c93_setup(char *str){	int i;	char *p1, *p2;	/* The kernel does some processing of the command-line before calling	 * this function: If it begins with any decimal or hex number arguments,	 * ints[0] = how many numbers found and ints[1] through [n] are the values	 * themselves. str points to where the non-numeric arguments (if any)	 * start: We do our own parsing of those. We construct synthetic 'nosync'	 * keywords out of numeric args (to maintain compatibility with older	 * versions) and then add the rest of the arguments.	 */	p1 = setup_buffer;	*p1 = '\0';	if (str)		strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));	setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';	p1 = setup_buffer;	i = 0;	while (*p1 && (i < MAX_SETUP_ARGS)) {		p2 = strchr(p1, ',');		if (p2) {			*p2 = '\0';			if (p1 != p2)				setup_args[i] = p1;			p1 = p2 + 1;			i++;		} else {			setup_args[i] = p1;			break;		}	}	for (i = 0; i < MAX_SETUP_ARGS; i++)		setup_used[i] = 0;	done_setup = 1;	return 1;}__setup("wd33c93=", wd33c93_setup);/* check_setup_args() returns index if key found, 0 if not */static intcheck_setup_args(char *key, int *flags, int *val, char *buf){	int x;	char *cp;	for (x = 0; x < MAX_SETUP_ARGS; x++) {		if (setup_used[x])			continue;		if (!strncmp(setup_args[x], key, strlen(key)))			break;		if (!strncmp(setup_args[x], "next", strlen("next")))			return 0;	}	if (x == MAX_SETUP_ARGS)		return 0;	setup_used[x] = 1;	cp = setup_args[x] + strlen(key);	*val = -1;	if (*cp != ':')		return ++x;	cp++;	if ((*cp >= '0') && (*cp <= '9')) {		*val = simple_strtoul(cp, NULL, 0);	}	return ++x;}voidwd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,	     dma_setup_t setup, dma_stop_t stop, int clock_freq){	struct WD33C93_hostdata *hostdata;	int i;	int flags;	int val;	char buf[32];	if (!done_setup && setup_strings)		wd33c93_setup(setup_strings);	hostdata = (struct WD33C93_hostdata *) instance->hostdata;	hostdata->regs = regs;	hostdata->clock_freq = clock_freq;	hostdata->dma_setup = setup;	hostdata->dma_stop = stop;	hostdata->dma_bounce_buffer = NULL;	hostdata->dma_bounce_len = 0;	for (i = 0; i < 8; i++) {		hostdata->busy[i] = 0;		hostdata->sync_xfer[i] =		    calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);		hostdata->sync_stat[i] = SS_UNSET;	/* using default sync values */#ifdef PROC_STATISTICS		hostdata->cmd_cnt[i] = 0;		hostdata->disc_allowed_cnt[i] = 0;		hostdata->disc_done_cnt[i] = 0;#endif	}	hostdata->input_Q = NULL;	hostdata->selecting = NULL;	hostdata->connected = NULL;	hostdata->disconnected_Q = NULL;	hostdata->state = S_UNCONNECTED;	hostdata->dma = D_DMA_OFF;	hostdata->level2 = L2_BASIC;	hostdata->disconnect = DIS_ADAPTIVE;	hostdata->args = DEBUG_DEFAULTS;	hostdata->incoming_ptr = 0;	hostdata->outgoing_len = 0;	hostdata->default_sx_per = DEFAULT_SX_PER;	hostdata->no_sync = 0xff;	/* sync defaults to off */	hostdata->no_dma = 0;	/* default is DMA enabled */#ifdef PROC_INTERFACE	hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |	    PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;#ifdef PROC_STATISTICS	hostdata->dma_cnt = 0;	hostdata->pio_cnt = 0;	hostdata->int_cnt = 0;#endif#endif	if (check_setup_args("nosync", &flags, &val, buf))		hostdata->no_sync = val;	if (check_setup_args("nodma", &flags, &val, buf))		hostdata->no_dma = (val == -1) ? 1 : val;	if (check_setup_args("period", &flags, &val, buf))		hostdata->default_sx_per =		    sx_table[round_period((unsigned int) val)].period_ns;	if (check_setup_args("disconnect", &flags, &val, buf)) {		if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))			hostdata->disconnect = val;		else			hostdata->disconnect = DIS_ADAPTIVE;	}	if (check_setup_args("level2", &flags, &val, buf))		hostdata->level2 = val;	if (check_setup_args("debug", &flags, &val, buf))		hostdata->args = val & DB_MASK;	if (check_setup_args("clock", &flags, &val, buf)) {		if (val > 7 && val < 11)			val = WD33C93_FS_8_10;		else if (val > 11 && val < 16)			val = WD33C93_FS_12_15;		else if (val > 15 && val < 21)			val = WD33C93_FS_16_20;		else			val = WD33C93_FS_8_10;		hostdata->clock_freq = val;	}	if ((i = check_setup_args("next", &flags, &val, buf))) {		while (i)			setup_used[--i] = 1;	}#ifdef PROC_INTERFACE	if (check_setup_args("proc", &flags, &val, buf))		hostdata->proc = val;#endif	spin_lock_irq(&hostdata->lock);	reset_wd33c93(instance);	spin_unlock_irq(&hostdata->lock);	printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",	       instance->host_no,	       (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip ==							    C_WD33C93A) ?	       "WD33c93A" : (hostdata->chip ==			     C_WD33C93B) ? "WD33c93B" : "unknown",	       hostdata->microcode, hostdata->no_sync, hostdata->no_dma);#ifdef DEBUGGING_ON	printk(" debug_flags=0x%02x\n", hostdata->args);#else	printk(" debugging=OFF\n");#endif	printk("           setup_args=");	for (i = 0; i < MAX_SETUP_ARGS; i++)		printk("%s,", setup_args[i]);	printk("\n");	printk("           Version %s - %s, Compiled %s at %s\n",	       WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);}intwd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in){#ifdef PROC_INTERFACE	char *bp;	char tbuf[128];	struct WD33C93_hostdata *hd;	struct scsi_cmnd *cmd;	int x, i;	static int stop = 0;	hd = (struct WD33C93_hostdata *) instance->hostdata;/* If 'in' is TRUE we need to _read_ the proc file. We accept the following * keywords (same format as command-line, but only ONE per read): *    debug *    disconnect *    period *    resync *    proc *    nodma */	if (in) {		buf[len] = '\0';		bp = buf;		if (!strncmp(bp, "debug:", 6)) {			bp += 6;			hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;		} else if (!strncmp(bp, "disconnect:", 11)) {			bp += 11;			x = simple_strtoul(bp, NULL, 0);			if (x < DIS_NEVER || x > DIS_ALWAYS)				x = DIS_ADAPTIVE;			hd->disconnect = x;		} else if (!strncmp(bp, "period:", 7)) {			bp += 7;			x = simple_strtoul(bp, NULL, 0);			hd->default_sx_per =			    sx_table[round_period((unsigned int) x)].period_ns;		} else if (!strncmp(bp, "resync:", 7)) {			bp += 7;			x = simple_strtoul(bp, NULL, 0);			for (i = 0; i < 7; i++)				if (x & (1 << i))					hd->sync_stat[i] = SS_UNSET;		} else if (!strncmp(bp, "proc:", 5)) {			bp += 5;			hd->proc = simple_strtoul(bp, NULL, 0);		} else if (!strncmp(bp, "nodma:", 6)) {			bp += 6;			hd->no_dma = simple_strtoul(bp, NULL, 0);		} else if (!strncmp(bp, "level2:", 7)) {			bp += 7;			hd->level2 = simple_strtoul(bp, NULL, 0);		}		return len;	}	spin_lock_irq(&hd->lock);	bp = buf;	*bp = '\0';	if (hd->proc & PR_VERSION) {		sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s",			WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);		strcat(bp, tbuf);	}	if (hd->proc & PR_INFO) {		sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d",			hd->clock_freq, hd->no_sync, hd->no_dma);		strcat(bp, tbuf);		strcat(bp, "\nsync_xfer[] =       ");		for (x = 0; x < 7; x++) {			sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);			strcat(bp, tbuf);		}		strcat(bp, "\nsync_stat[] =       ");		for (x = 0; x < 7; x++) {			sprintf(tbuf, "\t%02x", hd->sync_stat[x]);			strcat(bp, tbuf);		}	}#ifdef PROC_STATISTICS	if (hd->proc & PR_STATISTICS) {		strcat(bp, "\ncommands issued:    ");		for (x = 0; x < 7; x++) {			sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);			strcat(bp, tbuf);		}		strcat(bp, "\ndisconnects allowed:");		for (x = 0; x < 7; x++) {			sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);			strcat(bp, tbuf);		}		strcat(bp, "\ndisconnects done:   ");		for (x = 0; x < 7; x++) {			sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);			strcat(bp, tbuf);		}		sprintf(tbuf,			"\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",			hd->int_cnt, hd->dma_cnt, hd->pio_cnt);		strcat(bp, tbuf);	}#endif	if (hd->proc & PR_CONNECTED) {		strcat(bp, "\nconnected:     ");		if (hd->connected) {			cmd = (struct scsi_cmnd *) hd->connected;			sprintf(tbuf, " %ld-%d:%d(%02x)",				cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);			strcat(bp, tbuf);		}	}	if (hd->proc & PR_INPUTQ) {		strcat(bp, "\ninput_Q:       ");		cmd = (struct scsi_cmnd *) hd->input_Q;		while (cmd) {			sprintf(tbuf, " %ld-%d:%d(%02x)",				cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);			strcat(bp, tbuf);			cmd = (struct scsi_cmnd *) cmd->host_scribble;		}	}	if (hd->proc & PR_DISCQ) {		strcat(bp, "\ndisconnected_Q:");		cmd = (struct scsi_cmnd *) hd->disconnected_Q;		while (cmd) {			sprintf(tbuf, " %ld-%d:%d(%02x)",				cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);			strcat(bp, tbuf);			cmd = (struct scsi_cmnd *) cmd->host_scribble;		}	}	strcat(bp, "\n");	spin_unlock_irq(&hd->lock);	*start = buf;	if (stop) {		stop = 0;		return 0;	}	if (off > 0x40000)	/* ALWAYS stop after 256k bytes have been read */		stop = 1;	if (hd->proc & PR_STOP)	/* stop every other time */		stop = 1;	return strlen(bp);#else				/* PROC_INTERFACE */	return 0;#endif				/* PROC_INTERFACE */}voidwd33c93_release(void){}EXPORT_SYMBOL(wd33c93_host_reset);EXPORT_SYMBOL(wd33c93_init);EXPORT_SYMBOL(wd33c93_release);EXPORT_SYMBOL(wd33c93_abort);EXPORT_SYMBOL(wd33c93_queuecommand);EXPORT_SYMBOL(wd33c93_intr);EXPORT_SYMBOL(wd33c93_proc_info);

⌨️ 快捷键说明

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