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

📄 fas216.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);#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 int fas216_wait_cmd(FAS216_Info *info, int cmd){	int tout;	int stat;	outb(cmd, REG_CMD(info));	for (tout = 1000; tout; tout -= 1) {		stat = inb(REG_STAT(info));		if (stat & STAT_INT)			break;		udelay(1);	}	return stat;}static int fas216_get_msg_byte(FAS216_Info *info){	int stat;	stat = fas216_wait_cmd(info, CMD_MSGACCEPTED);	if ((stat & STAT_INT) == 0)		goto timedout;	if ((stat & STAT_BUSMASK) != STAT_MESGIN)		goto unexpected_phase_change;	inb(REG_INST(info));	stat = fas216_wait_cmd(info, CMD_TRANSFERINFO);	if ((stat & STAT_INT) == 0)		goto timedout;	if ((stat & STAT_BUSMASK) != STAT_MESGIN)		goto unexpected_phase_change;	inb(REG_INST(info));	return inb(REG_FF(info));timedout:	printk("scsi%d.%c: timed out waiting for message byte\n",		info->host->host_no, fas216_target(info));	return -1;unexpected_phase_change:	printk("scsi%d.%c: unexpected phase change: status = %02X\n",		info->host->host_no, fas216_target(info), stat);	return -2;}/* 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 = info->scsi.message;	unsigned int msglen = 1, i;	int msgbyte = 0;	fas216_checkmagic(info);	message[0] = inb(REG_FF(info));	if (message[0] == EXTENDED_MESSAGE) {		msgbyte = fas216_get_msg_byte(info);		if (msgbyte >= 0) {			message[1] = msgbyte;			for (msglen = 2; msglen < message[1] + 2; msglen++) {				msgbyte = fas216_get_msg_byte(info);				if (msgbyte >= 0)					message[msglen] = msgbyte;				else					break;			}		}	}	info->scsi.msglen = msglen;#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:		if (msglen != 1)			goto unrecognised;		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:		if (msglen != 1)			goto unrecognised;		/*		 * 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:		if (msglen != 1)			goto unrecognised;		/*		 * 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:		if (msglen != 1)			goto unrecognised;		info->scsi.phase = PHASE_MSGIN_DISCONNECT;		break;	case MESSAGE_REJECT:		if (msglen != 1)			goto unrecognised;		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:		if (msglen < 2)			goto unrecognised;		/* handled above - print a warning since this is untested */		printk("scsi%d.%c: reconnect queue tag %02X\n",			info->host->host_no, fas216_target(info),			message[1]);		break;	case EXTENDED_MESSAGE:		if (msglen < 3)			goto unrecognised;		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:			goto unrecognised;		}		break;	default:		goto unrecognised;	}	outb(CMD_MSGACCEPTED, REG_CMD(info));	return;unrecognised:	printk("scsi%d.%c: unrecognised message, rejecting\n",		info->host->host_no, fas216_target(info));	printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info));	for (i = 0; i < msglen; i++)		printk("%s%02X", i & 31 ? " " : "\n  ", message[i]);	printk("\n");	/*	 * Something strange seems to be happening here -	 * I can't use SETATN since the chip gives me an	 * invalid command interrupt when I do.  Weird.	 */outb(CMD_NOP, REG_CMD(info));fas216_dumpstate(info);	outb(CMD_SETATN, REG_CMD(info));	msgqueue_flush(&info->scsi.msgs);	msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);	info->scsi.phase = PHASE_MSGOUT_EXPECT;fas216_dumpstate(info);	outb(CMD_MSGACCEPTED, REG_CMD(info));}/* 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);	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, int start) * 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);	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);#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 (info->scsi.phase) {	case PHASE_SELECTION:		if ((ssr & IS_BITS) != 1)			goto bad_is;		break;	case PHASE_SELSTEPS:		switch (ssr & IS_BITS) {		case IS_SELARB:		case IS_MSGBYTESENT:			goto bad_is;		case IS_NOTCOMMAND:		case IS_EARLYPHASE:			if ((stat & STAT_BUSMASK) == STAT_MESGIN)				break;			goto bad_is;		case IS_COMPLETE:			break;		}	default:		break;	}	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);

⌨️ 快捷键说明

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