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

📄 fas216.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		/*		 * Something went wrong - send an initiator error to		 * the target.		 */		outb(CMD_SETATN, REG_CMD(info));		outb(CMD_MSGACCEPTED, REG_CMD(info));		msgqueue_flush(&info->scsi.msgs);		msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);		info->scsi.phase = PHASE_MSGOUT_EXPECT;		return;	}	target &= ~(1 << info->host->this_id);	switch (target) {	case   1:  target = 0; break;	case   2:  target = 1; break;	case   4:  target = 2; break;	case   8:  target = 3; break;	case  16:  target = 4; break;	case  32:  target = 5; break;	case  64:  target = 6; break;	case 128:  target = 7; break;	default:   target = info->host->this_id; break;	}	identify_msg &= 7;	info->scsi.reconnected.target = target;	info->scsi.reconnected.lun    = identify_msg;	info->scsi.reconnected.tag    = 0;	ok = 0;	if (info->scsi.disconnectable && info->SCpnt &&	    info->SCpnt->target == target && info->SCpnt->lun == identify_msg)		ok = 1;	if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg))		ok = 1;	msgqueue_flush(&info->scsi.msgs);	if (ok) {		info->scsi.phase = PHASE_RECONNECTED;		outb(target, REG_SDID(info));	} else {		/*		 * Our command structure not found - abort the		 * command on the target.  Since we have no		 * record of this command, we can't send		 * an INITIATOR DETECTED ERROR message.		 */		outb(CMD_SETATN, REG_CMD(info));		msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);		info->scsi.phase = PHASE_MSGOUT_EXPECT;	}	outb(CMD_MSGACCEPTED, REG_CMD(info));}/* Function: void fas216_finish_reconnect(FAS216_Info *info) * Purpose : finish reconnection sequence for device * Params  : info - interface which caused function done interrupt */static voidfas216_finish_reconnect(FAS216_Info *info){	fas216_checkmagic(info, "fas216_reconnect");#ifdef DEBUG_CONNECT	printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n",		info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag,		info->scsi.reconnected.target, info->scsi.reconnected.lun,		info->scsi.reconnected.tag);#endif	if (info->scsi.disconnectable && info->SCpnt) {		info->scsi.disconnectable = 0;		if (info->SCpnt->target == info->scsi.reconnected.target &&		    info->SCpnt->lun    == info->scsi.reconnected.lun &&		    info->SCpnt->tag    == info->scsi.reconnected.tag) {#ifdef DEBUG_CONNECT			printk("scsi%d.%c: reconnected",				info->host->host_no, fas216_target(info));#endif		} else {			queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);#ifdef DEBUG_CONNECT			printk("scsi%d.%c: had to move command to disconnected queue\n",				info->host->host_no, fas216_target(info));#endif			info->SCpnt = NULL;		}	}	if (!info->SCpnt) {		info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,					info->scsi.reconnected.target,					info->scsi.reconnected.lun,					info->scsi.reconnected.tag);#ifdef DEBUG_CONNECT		printk("scsi%d.%c: had to get command",			info->host->host_no, fas216_target(info));#endif	}	if (!info->SCpnt) {		outb(CMD_SETATN, REG_CMD(info));		msgqueue_flush(&info->scsi.msgs);#if 0		if (info->scsi.reconnected.tag)			msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag);		else#endif			msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);		info->scsi.phase = PHASE_MSGOUT_EXPECT;		info->scsi.aborting = 1;	} else {		/*		 * Restore data pointer from SAVED data pointer		 */		info->scsi.SCp = info->SCpnt->SCp;#ifdef DEBUG_CONNECT		printk(", data pointers: [%p, %X]",			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);#endif	}#ifdef DEBUG_CONNECT	printk("\n");#endif}static unsigned char fas216_get_msg_byte(FAS216_Info *info){	int tout;	outb(CMD_MSGACCEPTED, REG_CMD(info));	for (tout = 1000000; tout; tout --)		if (inb(REG_STAT(info)) & STAT_INT)			break;	inb(REG_INST(info));	outb(CMD_TRANSFERINFO, REG_CMD(info));	for (tout = 1000000; tout; tout --)		if (inb(REG_STAT(info)) & STAT_INT)			break;	inb(REG_INST(info));	return inb(REG_FF(info));}/* Function: void fas216_message(FAS216_Info *info) * Purpose : handle a function done interrupt from FAS216 chip * Params  : info - interface which caused function done interrupt */static void fas216_message(FAS216_Info *info){	unsigned char message[16];	unsigned int msglen = 1;	fas216_checkmagic(info, "fas216_message");	message[0] = inb(REG_FF(info));	if (message[0] == EXTENDED_MESSAGE) {		message[1] = fas216_get_msg_byte(info);		for (msglen = 2; msglen < message[1] + 2; msglen++)			message[msglen] = fas216_get_msg_byte(info);	}#ifdef DEBUG_MESSAGES	{		int i;		printk("scsi%d.%c: message in: ",			info->host->host_no, fas216_target(info));		for (i = 0; i < msglen; i++)			printk("%02X ", message[i]);		printk("\n");	}#endif	if (info->scsi.phase == PHASE_RECONNECTED) {		if (message[0] == SIMPLE_QUEUE_TAG)			info->scsi.reconnected.tag = message[1];		fas216_finish_reconnect(info);		info->scsi.phase = PHASE_MSGIN;	}	switch (message[0]) {	case COMMAND_COMPLETE:		printk(KERN_ERR "scsi%d.%c: command complete with no "			"status in MESSAGE_IN?\n",			info->host->host_no, fas216_target(info));		break;	case SAVE_POINTERS:		/*		 * Save current data pointer to SAVED data pointer		 * SCSI II standard says that we must not acknowledge		 * this until we have really saved pointers.		 * NOTE: we DO NOT save the command nor status pointers		 * as required by the SCSI II standard.  These always		 * point to the start of their respective areas.		 */		info->SCpnt->SCp = info->scsi.SCp;		info->SCpnt->SCp.sent_command = 0;#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)		printk("scsi%d.%c: save data pointers: [%p, %X]\n",			info->host->host_no, fas216_target(info),			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);#endif		break;	case RESTORE_POINTERS:		/*		 * Restore current data pointer from SAVED data pointer		 */		info->scsi.SCp = info->SCpnt->SCp;#if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)		printk("scsi%d.%c: restore data pointers: [%p, %X]\n",			info->host->host_no, fas216_target(info),			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);#endif		break;	case DISCONNECT:		info->scsi.phase = PHASE_MSGIN_DISCONNECT;		break;	case MESSAGE_REJECT:printk("scsi%d.%c: message reject at %02X (%X)\n", info->host->host_no, fas216_target(info), info->scsi.msgin_fifo,	fas216_get_last_msg(info, info->scsi.msgin_fifo));		switch(fas216_get_last_msg(info, info->scsi.msgin_fifo)) {		case EXTENDED_MESSAGE | EXTENDED_SDTR << 8:			fas216_handlesync(info, message);			break;		case EXTENDED_MESSAGE | EXTENDED_WDTR << 8:			fas216_handlewide(info, message);			break;		default:			printk("scsi%d.%c: reject, last message %04X\n",				info->host->host_no, fas216_target(info),				fas216_get_last_msg(info, info->scsi.msgin_fifo));		}		break;	case NOP:		break;	case SIMPLE_QUEUE_TAG:		/* handled above */		printk("scsi%d.%c: reconnect queue tag %02X\n",			info->host->host_no, fas216_target(info),			message[1]);		break;	case EXTENDED_MESSAGE:		switch (message[2]) {		case EXTENDED_SDTR:	/* Sync transfer negociation request/reply */			fas216_handlesync(info, message);			break;		case EXTENDED_WDTR:	/* Wide transfer negociation request/reply */			fas216_handlewide(info, message);			break;		default:			printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n",				info->host->host_no, fas216_target(info),				message[2]);			goto reject_message;		}		break;	default:		printk("scsi%d.%c: unrecognised message %02X, rejecting\n",			info->host->host_no, fas216_target(info),			message[0]);		goto reject_message;	}	outb(CMD_MSGACCEPTED, REG_CMD(info));	return;reject_message:	outb(CMD_SETATN, REG_CMD(info));	outb(CMD_MSGACCEPTED, REG_CMD(info));	msgqueue_flush(&info->scsi.msgs);	msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);	info->scsi.phase = PHASE_MSGOUT_EXPECT;}/* Function: void fas216_send_command(FAS216_Info *info) * Purpose : send a command to a target after all message bytes have been sent * Params  : info - interface which caused bus service */static void fas216_send_command(FAS216_Info *info){	int i;	fas216_checkmagic(info, "fas216_send_command");	outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info));	outb(CMD_FLUSHFIFO, REG_CMD(info));	/* load command */	for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++)		outb(info->SCpnt->cmnd[i], REG_FF(info));	outb(CMD_TRANSFERINFO, REG_CMD(info));	info->scsi.phase = PHASE_COMMAND;}/* Function: void fas216_send_messageout(FAS216_Info *info) * Purpose : handle bus service to send a message * Params  : info - interface which caused bus service * Note    : We do not allow the device to change the data direction! */static void fas216_send_messageout(FAS216_Info *info, int start){	unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs);	fas216_checkmagic(info, "fas216_send_messageout");	outb(CMD_FLUSHFIFO, REG_CMD(info));	if (tot_msglen) {		struct message *msg;		int msgnr = 0;		while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {			int i;			for (i = start; i < msg->length; i++)				outb(msg->msg[i], REG_FF(info));			msg->fifo = tot_msglen - (inb(REG_CFIS(info)) & CFIS_CF);			start = 0;		}	} else		outb(NOP, REG_FF(info));	outb(CMD_TRANSFERINFO, REG_CMD(info));	info->scsi.phase = PHASE_MSGOUT;}/* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) * Purpose : handle a bus service interrupt from FAS216 chip * Params  : info - interface which caused bus service interrupt *           stat - Status register contents *           ssr  - SCSI Status register contents */static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr){	fas216_checkmagic(info, "fas216_busservice_intr");#ifdef DEBUG_BUSSERVICE	printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n",		info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);#endif	switch (ssr & IS_BITS) {	case IS_MSGBYTESENT:		/* select with ATN and stop steps completed	*/	case IS_COMPLETE:			/* last action completed		*/		outb(CMD_NOP, REG_CMD(info));#define STATE(st,ph) ((ph) << 3 | (st))		/* This table describes the legal SCSI state transitions,		 * as described by the SCSI II spec.		 */		switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) {							/* Reselmsgin	-> Data In	*/		case STATE(STAT_DATAIN, PHASE_RECONNECTED):			fas216_finish_reconnect(info);		case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps	-> Data In	*/		case STATE(STAT_DATAIN, PHASE_DATAIN):	/* Data In	-> Data In	*/		case STATE(STAT_DATAIN, PHASE_MSGOUT):	/* Message Out	-> Data In	*/		case STATE(STAT_DATAIN, PHASE_COMMAND):	/* Command	-> Data In	*/		case STATE(STAT_DATAIN, PHASE_MSGIN):	/* Message In	-> Data In	*/			fas216_starttransfer(info, DMA_IN, 0);			return;		case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out	-> Data Out	*/			fas216_starttransfer(info, DMA_OUT, 0);			return;							/* Reselmsgin	-> Data Out	*/		case STATE(STAT_DATAOUT, PHASE_RECONNECTED):			fas216_finish_reconnect(info);		case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out	*/		case STATE(STAT_DATAOUT, PHASE_MSGOUT):	/* Message Out	-> Data Out	*/		case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command	-> Data Out	*/		case STATE(STAT_DATAOUT, PHASE_MSGIN):	/* Message In	-> Data Out	*/			fas216_starttransfer(info, DMA_OUT, 1);			return;							/* Reselmsgin	-> Status	*/		case STATE(STAT_STATUS, PHASE_RECONNECTED):			fas216_finish_reconnect(info);			goto status;		case STATE(STAT_STATUS, PHASE_DATAOUT):	/* Data Out	-> Status	*/		case STATE(STAT_STATUS, PHASE_DATAIN):	/* Data In	-> Status	*/			fas216_stoptransfer(info);		case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps	-> Status	*/		case STATE(STAT_STATUS, PHASE_MSGOUT):	/* Message Out	-> Status	*/		case STATE(STAT_STATUS, PHASE_COMMAND):	/* Command	-> Status	*/		case STATE(STAT_STATUS, PHASE_MSGIN):	/* Message In	-> Status	*/		status:			outb(CMD_INITCMDCOMPLETE, REG_CMD(info));			info->scsi.phase = PHASE_STATUS;			return;		case STATE(STAT_MESGIN, PHASE_DATAOUT):	/* Data Out	-> Message In	*/		case STATE(STAT_MESGIN, PHASE_DATAIN):	/* Data In	-> Message In	*/			fas216_stoptransfer(info);		case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps	-> Message In	*/		case STATE(STAT_MESGIN, PHASE_MSGOUT):	/* Message Out	-> Message In	*/			info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;			outb(CMD_TRANSFERINFO, REG_CMD(info));			info->scsi.phase = PHASE_MSGIN;			return;							/* Reselmsgin	-> Message In	*/		case STATE(STAT_MESGIN, PHASE_RECONNECTED):		case STATE(STAT_MESGIN, PHASE_MSGIN):			info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;			outb(CMD_TRANSFERINFO, REG_CMD(info));			return;							/* Reselmsgin	-> Command	*/		case STATE(STAT_COMMAND, PHASE_RECONNECTED):			fas216_finish_reconnect(info);		case STATE(STAT_COMMAND, PHASE_MSGOUT):	/* Message Out	-> Command	*/		case STATE(STAT_COMMAND, PHASE_MSGIN):	/* Message In	-> Command	*/			fas216_send_command(info);			info->scsi.phase = PHASE_COMMAND;			return;							/* Selection	-> Message Out	*/		case STATE(STAT_MESGOUT, PHASE_SELECTION):			fas216_send_messageout(info, 1);			return;							/* Any		-> Message Out	*/		case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT):			fas216_send_messageout(info, 0); 			return;		/* Error recovery rules.		 *   These either attempt to abort or retry the operation.		 * TODO: we need more of these		 */		case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command	-> Command	*/			/* error - we've sent out all the command bytes			 * we have.			 * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS			 * to include the command bytes sent for this to work			 * correctly.			 */			printk(KERN_ERR "scsi%d.%c: "

⌨️ 快捷键说明

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