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

📄 aic79xx_core.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * Flush the good status FIFO for compelted packetized commands.	 */	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {		scbid = (ahd_inb(ahd, GSFIFO+1) << 8)		      | ahd_inb(ahd, GSFIFO);		scb = ahd_lookup_scb(ahd, scbid);		if (scb == NULL) {			printf("%s: Warning - GSFIFO SCB %d invalid\n",			       ahd_name(ahd), scbid);			continue;		}		ahd_complete_scb(ahd, scb);	}	/*	 * Restore state.	 */	ahd_restore_modes(ahd, saved_modes);	ahd->flags |= AHD_UPDATE_PEND_CMDS;}voidahd_run_qoutfifo(struct ahd_softc *ahd){	struct scb *scb;	u_int  scb_index;	if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0)		panic("ahd_run_qoutfifo recursion");	ahd->flags |= AHD_RUNNING_QOUTFIFO;	ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);	while ((ahd->qoutfifo[ahd->qoutfifonext]	     & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {		scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]				      & ~QOUTFIFO_ENTRY_VALID_LE);		scb = ahd_lookup_scb(ahd, scb_index);		if (scb == NULL) {			printf("%s: WARNING no command for scb %d "			       "(cmdcmplt)\nQOUTPOS = %d\n",			       ahd_name(ahd), scb_index,			       ahd->qoutfifonext);			ahd_dump_card_state(ahd);		} else			ahd_complete_scb(ahd, scb);		ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);		if (ahd->qoutfifonext == 0)			ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE;	}	ahd->flags &= ~AHD_RUNNING_QOUTFIFO;}/************************* Interrupt Handling *********************************/voidahd_handle_hwerrint(struct ahd_softc *ahd){	/*	 * Some catastrophic hardware error has occurred.	 * Print it for the user and disable the controller.	 */	int i;	int error;	error = ahd_inb(ahd, ERROR);	for (i = 0; i < num_errors; i++) {		if ((error & ahd_hard_errors[i].errno) != 0)			printf("%s: hwerrint, %s\n",			       ahd_name(ahd), ahd_hard_errors[i].errmesg);	}	ahd_dump_card_state(ahd);	panic("BRKADRINT");	/* Tell everyone that this HBA is no longer available */	ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,		       CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,		       CAM_NO_HBA);	/* Tell the system that this controller has gone away. */	ahd_free(ahd);}voidahd_handle_seqint(struct ahd_softc *ahd, u_int intstat){	u_int seqintcode;	/*	 * Save the sequencer interrupt code and clear the SEQINT	 * bit. We will unpause the sequencer, if appropriate,	 * after servicing the request.	 */	seqintcode = ahd_inb(ahd, SEQINTCODE);	ahd_outb(ahd, CLRINT, CLRSEQINT);	if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {		/*		 * Unpause the sequencer and let it clear		 * SEQINT by writing NO_SEQINT to it.  This		 * will cause the sequencer to be paused again,		 * which is the expected state of this routine.		 */		ahd_unpause(ahd);		while (!ahd_is_paused(ahd))			;		ahd_outb(ahd, CLRINT, CLRSEQINT);	}	ahd_update_modes(ahd);#ifdef AHD_DEBUG	if ((ahd_debug & AHD_SHOW_MISC) != 0)		printf("%s: Handle Seqint Called for code %d\n",		       ahd_name(ahd), seqintcode);#endif	switch (seqintcode) {	case BAD_SCB_STATUS:	{		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 termine 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(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;				}			}#if 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

⌨️ 快捷键说明

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