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

📄 aic79xx_core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		struct	scb *scb;		u_int	scbid;		int	cmds_pending;		scbid = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbid);		if (scb != NULL) {			ahd_complete_scb(ahd, scb);		} else {			printf("%s: WARNING no command for scb %d "			       "(bad status)\n", ahd_name(ahd), scbid);			ahd_dump_card_state(ahd);		}		cmds_pending = ahd_inw(ahd, CMDS_PENDING);		if (cmds_pending > 0)			ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);		break;	}	case ENTERING_NONPACK:	{		struct	scb *scb;		u_int	scbid;		AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),				 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));		scbid = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbid);		if (scb == NULL) {			/*			 * Somehow need to know if this			 * is from a selection or reselection.			 * From that, we can determine target			 * ID so we at least have an I_T nexus.			 */		} else {			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);			ahd_outb(ahd, SAVED_LUN, scb->hscb->lun);			ahd_outb(ahd, SEQ_FLAGS, 0x0);		}		if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0		 && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {			/*			 * Phase change after read stream with			 * CRC error with P0 asserted on last			 * packet.			 */#ifdef AHD_DEBUG			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)				printf("%s: Assuming LQIPHASE_NLQ with "				       "P0 assertion\n", ahd_name(ahd));#endif		}#ifdef AHD_DEBUG		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)			printf("%s: Entering NONPACK\n", ahd_name(ahd));#endif		break;	}	case INVALID_SEQINT:		printf("%s: Invalid Sequencer interrupt occurred.\n",		       ahd_name(ahd));		ahd_dump_card_state(ahd);		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);		break;	case STATUS_OVERRUN:	{		struct	scb *scb;		u_int	scbid;		scbid = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbid);		if (scb != NULL)			ahd_print_path(ahd, scb);		else			printf("%s: ", ahd_name(ahd));		printf("SCB %d Packetized Status Overrun", scbid);		ahd_dump_card_state(ahd);		ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);		break;	}	case CFG4ISTAT_INTR:	{		struct	scb *scb;		u_int	scbid;		scbid = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbid);		if (scb == NULL) {			ahd_dump_card_state(ahd);			printf("CFG4ISTAT: Free SCB %d referenced", scbid);			panic("For safety");		}		ahd_outq(ahd, HADDR, scb->sense_busaddr);		ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE);		ahd_outb(ahd, HCNT + 2, 0);		ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG);		ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);		break;	}	case ILLEGAL_PHASE:	{		u_int bus_phase;		bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;		printf("%s: ILLEGAL_PHASE 0x%x\n",		       ahd_name(ahd), bus_phase);		switch (bus_phase) {		case P_DATAOUT:		case P_DATAIN:		case P_DATAOUT_DT:		case P_DATAIN_DT:		case P_MESGOUT:		case P_STATUS:		case P_MESGIN:			ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);			printf("%s: Issued Bus Reset.\n", ahd_name(ahd));			break;		case P_COMMAND:		{			struct	ahd_devinfo devinfo;			struct	scb *scb;			struct	ahd_initiator_tinfo *targ_info;			struct	ahd_tmode_tstate *tstate;			struct	ahd_transinfo *tinfo;			u_int	scbid;			/*			 * If a target takes us into the command phase			 * assume that it has been externally reset and			 * has thus lost our previous packetized negotiation			 * agreement.  Since we have not sent an identify			 * message and may not have fully qualified the			 * connection, we change our command to TUR, assert			 * ATN and ABORT the task when we go to message in			 * phase.  The OSM will see the REQUEUE_REQUEST			 * status and retry the command.			 */			scbid = ahd_get_scbptr(ahd);			scb = ahd_lookup_scb(ahd, scbid);			if (scb == NULL) {				printf("Invalid phase with no valid SCB.  "				       "Resetting bus.\n");				ahd_reset_channel(ahd, 'A',						  /*Initiate Reset*/TRUE);				break;			}			ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),					    SCB_GET_TARGET(ahd, scb),					    SCB_GET_LUN(scb),					    SCB_GET_CHANNEL(ahd, scb),					    ROLE_INITIATOR);			targ_info = ahd_fetch_transinfo(ahd,							devinfo.channel,							devinfo.our_scsiid,							devinfo.target,							&tstate);			tinfo = &targ_info->curr;			ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,				      AHD_TRANS_ACTIVE, /*paused*/TRUE);			ahd_set_syncrate(ahd, &devinfo, /*period*/0,					 /*offset*/0, /*ppr_options*/0,					 AHD_TRANS_ACTIVE, /*paused*/TRUE);			ahd_outb(ahd, SCB_CDB_STORE, 0);			ahd_outb(ahd, SCB_CDB_STORE+1, 0);			ahd_outb(ahd, SCB_CDB_STORE+2, 0);			ahd_outb(ahd, SCB_CDB_STORE+3, 0);			ahd_outb(ahd, SCB_CDB_STORE+4, 0);			ahd_outb(ahd, SCB_CDB_STORE+5, 0);			ahd_outb(ahd, SCB_CDB_LEN, 6);			scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);			scb->hscb->control |= MK_MESSAGE;			ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);			ahd_outb(ahd, MSG_OUT, HOST_MSG);			ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);			/*			 * The lun is 0, regardless of the SCB's lun			 * as we have not sent an identify message.			 */			ahd_outb(ahd, SAVED_LUN, 0);			ahd_outb(ahd, SEQ_FLAGS, 0);			ahd_assert_atn(ahd);			scb->flags &= ~(SCB_PACKETIZED);			scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;			ahd_freeze_devq(ahd, scb);			ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);			ahd_freeze_scb(scb);			/*			 * Allow the sequencer to continue with			 * non-pack processing.			 */			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);			ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT);			if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {				ahd_outb(ahd, CLRLQOINT1, 0);			}#ifdef AHD_DEBUG			if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {				ahd_print_path(ahd, scb);				printf("Unexpected command phase from "				       "packetized target\n");			}#endif			break;		}		}		break;	}	case CFG4OVERRUN:	{		struct	scb *scb;		u_int	scb_index;		#ifdef AHD_DEBUG		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {			printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd),			       ahd_inb(ahd, MODE_PTR));		}#endif		scb_index = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scb_index);		if (scb == NULL) {			/*			 * Attempt to transfer to an SCB that is			 * not outstanding.			 */			ahd_assert_atn(ahd);			ahd_outb(ahd, MSG_OUT, HOST_MSG);			ahd->msgout_buf[0] = MSG_ABORT_TASK;			ahd->msgout_len = 1;			ahd->msgout_index = 0;			ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;			/*			 * Clear status received flag to prevent any			 * attempt to complete this bogus SCB.			 */			ahd_outb(ahd, SCB_CONTROL,				 ahd_inb_scbram(ahd, SCB_CONTROL)				 & ~STATUS_RCVD);		}		break;	}	case DUMP_CARD_STATE:	{		ahd_dump_card_state(ahd);		break;	}	case PDATA_REINIT:	{#ifdef AHD_DEBUG		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {			printf("%s: PDATA_REINIT - DFCNTRL = 0x%x "			       "SG_CACHE_SHADOW = 0x%x\n",			       ahd_name(ahd), ahd_inb(ahd, DFCNTRL),			       ahd_inb(ahd, SG_CACHE_SHADOW));		}#endif		ahd_reinitialize_dataptrs(ahd);		break;	}	case HOST_MSG_LOOP:	{		struct ahd_devinfo devinfo;		/*		 * The sequencer has encountered a message phase		 * that requires host assistance for completion.		 * While handling the message phase(s), we will be		 * notified by the sequencer after each byte is		 * transfered so we can track bus phase changes.		 *		 * If this is the first time we've seen a HOST_MSG_LOOP		 * interrupt, initialize the state of the host message		 * loop.		 */		ahd_fetch_devinfo(ahd, &devinfo);		if (ahd->msg_type == MSG_TYPE_NONE) {			struct scb *scb;			u_int scb_index;			u_int bus_phase;			bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;			if (bus_phase != P_MESGIN			 && bus_phase != P_MESGOUT) {				printf("ahd_intr: HOST_MSG_LOOP bad "				       "phase 0x%x\n", bus_phase);				/*				 * Probably transitioned to bus free before				 * we got here.  Just punt the message.				 */				ahd_dump_card_state(ahd);				ahd_clear_intstat(ahd);				ahd_restart(ahd);				return;			}			scb_index = ahd_get_scbptr(ahd);			scb = ahd_lookup_scb(ahd, scb_index);			if (devinfo.role == ROLE_INITIATOR) {				if (bus_phase == P_MESGOUT)					ahd_setup_initiator_msgout(ahd,								   &devinfo,								   scb);				else {					ahd->msg_type =					    MSG_TYPE_INITIATOR_MSGIN;					ahd->msgin_index = 0;				}			}#ifdef AHD_TARGET_MODE			else {				if (bus_phase == P_MESGOUT) {					ahd->msg_type =					    MSG_TYPE_TARGET_MSGOUT;					ahd->msgin_index = 0;				}				else 					ahd_setup_target_msgin(ahd,							       &devinfo,							       scb);			}#endif		}		ahd_handle_message_phase(ahd);		break;	}	case NO_MATCH:	{		/* Ensure we don't leave the selection hardware on */		AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);		ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);		printf("%s:%c:%d: no active SCB for reconnecting "		       "target - issuing BUS DEVICE RESET\n",		       ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4);		printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "		       "REG0 == 0x%x ACCUM = 0x%x\n",		       ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN),		       ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM));		printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "		       "SINDEX == 0x%x\n",		       ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd),		       ahd_find_busy_tcl(ahd,					 BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),						   ahd_inb(ahd, SAVED_LUN))),		       ahd_inw(ahd, SINDEX));		printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "		       "SCB_CONTROL == 0x%x\n",		       ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID),		       ahd_inb_scbram(ahd, SCB_LUN),		       ahd_inb_scbram(ahd, SCB_CONTROL));		printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n",		       ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI));		printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0));		printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0));		ahd_dump_card_state(ahd);		ahd->msgout_buf[0] = MSG_BUS_DEV_RESET;		ahd->msgout_len = 1;		ahd->msgout_index = 0;		ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;		ahd_outb(ahd, MSG_OUT, HOST_MSG);		ahd_assert_atn(ahd);		break;	}	case PROTO_VIOLATION:	{		ahd_handle_proto_violation(ahd);		break;	}	case IGN_WIDE_RES:	{		struct ahd_devinfo devinfo;		ahd_fetch_devinfo(ahd, &devinfo);		ahd_handle_ign_wide_residue(ahd, &devinfo);		break;	}	case BAD_PHASE:	{		u_int lastphase;		lastphase = ahd_inb(ahd, LASTPHASE);		printf("%s:%c:%d: unknown scsi bus phase %x, "		       "lastphase = 0x%x.  Attempting to continue\n",		       ahd_name(ahd), 'A',		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),		       lastphase, ahd_inb(ahd, SCSISIGI));		break;	}	case MISSED_BUSFREE:	{		u_int lastphase;		lastphase = ahd_inb(ahd, LASTPHASE);		printf("%s:%c:%d: Missed busfree. "		       "Lastphase = 0x%x, Curphase = 0x%x\n",		       ahd_name(ahd), 'A',		       SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),		       lastphase, ahd_inb(ahd, SCSISIGI));		ahd_restart(ahd);		return;	}	case DATA_OVERRUN:	{		/*		 * When the sequencer detects an overrun, it		 * places the controller in "BITBUCKET" mode		 * and allows the target to complete its transfer.		 * Unfortunately, none of the counters get updated		 * when the controller is in this mode, so we have		 * no way of knowing how large the overrun was.		 */		struct	scb *scb;		u_int	scbindex;#ifdef AHD_DEBUG		u_int	lastphase;#endif		scbindex = ahd_get_scbptr(ahd);		scb = ahd_lookup_scb(ahd, scbindex);#ifdef AHD_DEBUG		lastphase = ahd_inb(ahd, LASTPHASE);		if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {			ahd_print_path(ahd, scb);			printf("data overrun detected %s.  Tag == 0x%x.\n",			       ahd_lookup_phase_entry(lastphase)->phasemsg,			       SCB_GET_TAG(scb));			ahd_print_path(ahd, scb);			printf("%s seen Data Phase.  Length = %ld.  "			       "NumSGs = %d.\n",			       ahd_inb(ahd, SEQ_FLAGS) & DPHASE			       ? "Have" : "Haven't",			       ahd_get_transfer_length(scb), scb->sg_count);			ahd_dump_sglist(scb);		}#endif		/*

⌨️ 快捷键说明

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