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

📄 fas216.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			SCpnt->result = DID_ERROR << 16;			done(SCpnt);		}		save_flags_cli(flags);		if (!info->SCpnt || info->scsi.disconnectable)			fas216_kick(info);		restore_flags(flags);	} else {		/* no interrupts to rely on - we'll have to handle the		 * command ourselves.  For now, we give up.		 */		SCpnt->result = DID_ERROR << 16;		done(SCpnt);	}	return 0;}/* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt) * Purpose : trigger restart of a waiting thread in fas216_command * Params  : SCpnt - Command to wake */static void fas216_internal_done(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	fas216_checkmagic(info, "fas216_internal_done");	info->internal_done = 1;}/* Function: int fas216_command(Scsi_Cmnd *SCpnt) * Purpose : queue a command for adapter to process. * Params  : SCpnt - Command to queue * Returns : scsi result code */int fas216_command(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	unsigned long flags;	fas216_checkmagic(info, "fas216_command");	info->internal_done = 0;	fas216_queue_command(SCpnt, fas216_internal_done);	/*	 * This wastes time, since we can't return until the command is	 * complete. We can't seep either since we may get re-entered!	 * However, we must re-enable interrupts, or else we'll be	 * waiting forever.	 */	save_flags(flags);	sti();	while (!info->internal_done)		barrier();	restore_flags(flags);	return SCpnt->result;}/* Prototype: void fas216_reportstatus(Scsi_Cmnd **SCpntp1, *				       Scsi_Cmnd **SCpntp2, int result) * Purpose  : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 * Params   : SCpntp1 - pointer to command to return *	      SCpntp2 - pointer to command to check *	      result  - result to pass back to mid-level done function * Returns  : *SCpntp2 = NULL if *SCpntp1 is the same command *	      structure as *SCpntp2. */static void fas216_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2,				int result){	Scsi_Cmnd *SCpnt = *SCpntp1;	if (SCpnt) {		*SCpntp1 = NULL;		SCpnt->result = result;		SCpnt->scsi_done(SCpnt);	}	if (SCpnt == *SCpntp2)		*SCpntp2 = NULL;}/* Function: int fas216_abort(Scsi_Cmnd *SCpnt) * Purpose : abort a command if something horrible happens. * Params  : SCpnt - Command that is believed to be causing a problem. * Returns : one of SCSI_ABORT_ macros. */int fas216_abort(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	int result = SCSI_ABORT_SNOOZE;	fas216_checkmagic(info, "fas216_abort");	info->stats.aborts += 1;	print_debug_list();	fas216_dumpstate(info);	fas216_dumpinfo(info);	printk(KERN_WARNING "scsi%d: fas216_abort: ", info->host->host_no);	do {		/* If command is waiting in the issue queue, then we can		 * simply remove the command and return abort status		 */		if (queue_removecmd(&info->queues.issue, SCpnt)) {			SCpnt->result = DID_ABORT << 16;			SCpnt->scsi_done(SCpnt);			printk("command on issue queue");			result = SCSI_ABORT_SUCCESS;			break;		}		/* If the command is on the disconencted queue, we need to		 * reconnect to the device		 */		if (queue_cmdonqueue(&info->queues.disconnected, SCpnt))			printk("command on disconnected queue");		/* If the command is connected, we need to flag that the		 * command needs to be aborted		 */		if (info->SCpnt == SCpnt)			printk("command executing");		/* If the command is pending for execution, then again		 * this is simple - we remove it and report abort status		 */		if (info->origSCpnt == SCpnt) {			info->origSCpnt = NULL;			SCpnt->result = DID_ABORT << 16;			SCpnt->scsi_done(SCpnt);			printk("command waiting for execution");			result = SCSI_ABORT_SUCCESS;			break;		}	} while (0);	printk("\n");	return result;}/* Function: void fas216_reset_state(FAS216_Info *info) * Purpose : Initialise driver internal state * Params  : info - state to initialise */static void fas216_reset_state(FAS216_Info *info){	neg_t sync_state, wide_state;	int i;	fas216_checkmagic(info, "fas216_reset_state");	/*	 * Clear out all stale info in our state structure	 */	memset(info->busyluns, 0, sizeof(info->busyluns));	msgqueue_flush(&info->scsi.msgs);	info->scsi.reconnected.target = 0;	info->scsi.reconnected.lun = 0;	info->scsi.reconnected.tag = 0;	info->scsi.disconnectable = 0;	info->scsi.aborting = 0;	info->scsi.phase = PHASE_IDLE;	info->scsi.async_stp =			fas216_syncperiod(info, info->ifcfg.asyncperiod);	if (info->ifcfg.wide_max_size == 0)		wide_state = neg_invalid;	else#ifdef SCSI2_WIDE		wide_state = neg_wait;#else		wide_state = neg_invalid;#endif	if (info->host->dma_channel == NO_DMA || !info->dma.setup)		sync_state = neg_invalid;	else#ifdef SCSI2_SYNC		sync_state = neg_wait;#else		sync_state = neg_invalid;#endif	for (i = 0; i < 8; i++) {		info->device[i].disconnect_ok	= info->ifcfg.disconnect_ok;		info->device[i].sync_state	= sync_state;		info->device[i].wide_state	= wide_state;		info->device[i].period		= info->ifcfg.asyncperiod / 4;		info->device[i].stp		= info->scsi.async_stp;		info->device[i].sof		= 0;		info->device[i].wide_xfer	= 0;	}}/* Function: void fas216_init_chip(FAS216_Info *info) * Purpose : Initialise FAS216 state after reset * Params  : info - state structure for interface */static void fas216_init_chip(FAS216_Info *info){	fas216_checkmagic(info, "fas216_init_chip");	outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info));	outb(info->scsi.cfg[0], REG_CNTL1(info));	outb(info->scsi.cfg[1], REG_CNTL2(info));	outb(info->scsi.cfg[2], REG_CNTL3(info));	outb(info->ifcfg.select_timeout, REG_STIM(info));	outb(0, REG_SOF(info));	outb(info->scsi.async_stp, REG_STP(info));	outb(info->scsi.cfg[0], REG_CNTL1(info));}/* Function: int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) * Purpose : resets the adapter if something horrible happens. * Params  : SCpnt - Command that is believed to be causing a problem. *	     reset_flags - flags indicating reset type that is believed *           to be required. * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET *           macros. */int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	Scsi_Cmnd *SCptr;	int result = 0;	fas216_checkmagic(info, "fas216_reset");	/*	 * Validate that command is actually on one of our queues if we're doing	 * an asynchronous reset	 */	if (reset_flags & SCSI_RESET_ASYNCHRONOUS &&	    SCpnt &&	    info->SCpnt != SCpnt &&	    info->origSCpnt != SCpnt &&	    !queue_cmdonqueue(&info->queues.disconnected, SCpnt) &&	    !queue_cmdonqueue(&info->queues.issue, SCpnt)) {		printk("scsi%d: fas216_reset: asynchronous reset for unknown command\n",		       info->host->host_no);		return SCSI_RESET_NOT_RUNNING;	}	info->stats.resets += 1;	print_debug_list();	printk(KERN_WARNING "scsi%d: fas216_reset: ", info->host->host_no);	if (SCpnt)		printk(" for target %d ", SCpnt->target);	outb(info->scsi.cfg[3], REG_CNTL3(info));	fas216_stoptransfer(info);	switch (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) {	case SCSI_RESET_SUGGEST_BUS_RESET:		outb(CMD_RESETSCSI, REG_CMD(info));		outb(CMD_NOP, REG_CMD(info));		result |= SCSI_RESET_BUS_RESET;		break;	case SCSI_RESET_SUGGEST_HOST_RESET:		outb(CMD_RESETCHIP, REG_CMD(info));		outb(CMD_NOP, REG_CMD(info));		result |= SCSI_RESET_HOST_RESET;		break;	default:		outb(CMD_RESETCHIP, REG_CMD(info));		outb(CMD_NOP, REG_CMD(info));		outb(CMD_RESETSCSI, REG_CMD(info));		result |= SCSI_RESET_HOST_RESET | SCSI_RESET_BUS_RESET;		break;	}	udelay(300);	fas216_reset_state(info);	fas216_init_chip(info);	/*	 * Signal all commands in progress have been reset	 */	fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16);	while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL)		fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16);	if (SCpnt) {		/*		 * Command not found on disconnected queue, nor currently		 * executing command - check pending commands		 */		if (info->origSCpnt == SCpnt)			info->origSCpnt = NULL;		queue_removecmd(&info->queues.issue, SCpnt);		SCpnt->result = DID_RESET << 16;		SCpnt->scsi_done(SCpnt);	}	printk("\n");	return result | SCSI_RESET_SUCCESS;}/* Function: int fas216_init(struct Scsi_Host *instance) * Purpose : initialise FAS/NCR/AMD SCSI ic. * Params  : instance - a driver-specific filled-out structure * Returns : 0 on success */int fas216_init(struct Scsi_Host *instance){	FAS216_Info *info = (FAS216_Info *)instance->hostdata;	unsigned long flags;	int target_jiffies;	info->magic_start = MAGIC;	info->magic_end = MAGIC;	info->host = instance;	info->scsi.cfg[0] = instance->this_id;	info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;	info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB;	info->scsi.type = "unknown";	info->SCpnt = NULL;	fas216_reset_state(info);	memset(&info->stats, 0, sizeof(info->stats));	msgqueue_initialise(&info->scsi.msgs);	if (!queue_initialise(&info->queues.issue))		return 1;	if (!queue_initialise(&info->queues.disconnected)) {		queue_free(&info->queues.issue);		return 1;	}	outb(0, REG_CNTL3(info));	outb(CNTL2_S2FE, REG_CNTL2(info));	if ((inb(REG_CNTL2(info)) & (~0xe0)) != CNTL2_S2FE) {		info->scsi.type = "NCR53C90";	} else {		outb(0, REG_CNTL2(info));		outb(0, REG_CNTL3(info));		outb(5, REG_CNTL3(info));		if (inb(REG_CNTL3(info)) != 5) {			info->scsi.type = "NCR53C90A";		} else {			outb(0, REG_CNTL3(info));			info->scsi.type = "NCR53C9x";		}	}	outb(CNTL3_ADIDCHK, REG_CNTL3(info));	outb(0, REG_CNTL3(info));	outb(CMD_RESETCHIP, REG_CMD(info));	outb(CMD_WITHDMA | CMD_NOP, REG_CMD(info));	outb(CNTL2_ENF, REG_CNTL2(info));	outb(CMD_RESETCHIP, REG_CMD(info));	switch (inb(REG1_ID(info))) {	case 12:		info->scsi.type = "Am53CF94";		break;	default:		break;	}	udelay(300);	/* now for the real initialisation */	fas216_init_chip(info);	outb(info->scsi.cfg[0] | CNTL1_DISR, REG_CNTL1(info));	outb(CMD_RESETSCSI, REG_CMD(info));	/* scsi standard says 250ms */	target_jiffies = jiffies + (25 * HZ) / 100;	save_flags(flags);	sti();	while (jiffies < target_jiffies) barrier();	restore_flags(flags);	outb(info->scsi.cfg[0], REG_CNTL1(info));	inb(REG_INST(info));	/* now for the real initialisation */	fas216_init_chip(info);	fas216_checkmagic(info, "fas216_init");	return 0;}/* Function: int fas216_release(struct Scsi_Host *instance) * Purpose : release all resources and put everything to bed for *           FAS/NCR/AMD SCSI ic. * Params  : instance - a driver-specific filled-out structure * Returns : 0 on success */int fas216_release(struct Scsi_Host *instance){	FAS216_Info *info = (FAS216_Info *)instance->hostdata;	fas216_checkmagic(info, "fas216_release");	outb(CMD_RESETCHIP, REG_CMD(info));	queue_free(&info->queues.disconnected);	queue_free(&info->queues.issue);	return 0;}int fas216_print_stats(FAS216_Info *info, char *buffer){	return sprintf(buffer,			"Queued commands: %-10u   Issued commands: %-10u\n"			"Done commands  : %-10u   Reads          : %-10u\n"			"Writes         : %-10u   Others         : %-10u\n"			"Disconnects    : %-10u   Aborts         : %-10u\n"			"Resets         : %-10u\n",			info->stats.queues,      info->stats.removes,			info->stats.fins,        info->stats.reads,			info->stats.writes,      info->stats.miscs,			info->stats.disconnects, info->stats.aborts,			info->stats.resets);}int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer){	struct fas216_device *dev = &info->device[scd->id];	int len = 0;	char *p;	proc_print_scsidevice(scd, buffer, &len, 0);	p = buffer + len;	p += sprintf(p, "  Extensions: ");	if (scd->tagged_supported)		p += sprintf(p, "TAG %sabled [%d

⌨️ 快捷键说明

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