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

📄 aic7xxx_core.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		if ((scb->flags & SCB_SENSE) != 0) {			/*			 * Clear the SCB_SENSE Flag and have			 * the sequencer do a normal command			 * complete.			 */			scb->flags &= ~SCB_SENSE;			ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);			break;		}		ahc_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);		/* Freeze the queue until the client sees the error. */		ahc_freeze_devq(ahc, scb);		ahc_freeze_scb(scb);		ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status);		switch (hscb->shared_data.status.scsi_status) {		case SCSI_STATUS_OK:			printf("%s: Interrupted for staus of 0???\n",			       ahc_name(ahc));			break;		case SCSI_STATUS_CMD_TERMINATED:		case SCSI_STATUS_CHECK_COND:		{			struct ahc_dma_seg *sg;			struct scsi_sense *sc;			struct ahc_initiator_tinfo *targ_info;			struct ahc_tmode_tstate *tstate;			struct ahc_transinfo *tinfo;#ifdef AHC_DEBUG			if (ahc_debug & AHC_SHOW_SENSE) {				ahc_print_path(ahc, scb);				printf("SCB %d: requests Check Status\n",				       scb->hscb->tag);			}#endif			if (ahc_perform_autosense(scb) == 0)				break;			targ_info = ahc_fetch_transinfo(ahc,							devinfo.channel,							devinfo.our_scsiid,							devinfo.target,							&tstate);			tinfo = &targ_info->curr;			sg = scb->sg_list;			sc = (struct scsi_sense *)(&hscb->shared_data.cdb); 			/*			 * Save off the residual if there is one.			 */			ahc_update_residual(ahc, scb);#ifdef AHC_DEBUG			if (ahc_debug & AHC_SHOW_SENSE) {				ahc_print_path(ahc, scb);				printf("Sending Sense\n");			}#endif			sg->addr = ahc_get_sense_bufaddr(ahc, scb);			sg->len = ahc_get_sense_bufsize(ahc, scb);			sg->len |= AHC_DMA_LAST_SEG;			/* Fixup byte order */			sg->addr = ahc_htole32(sg->addr);			sg->len = ahc_htole32(sg->len);			sc->opcode = REQUEST_SENSE;			sc->byte2 = 0;			if (tinfo->protocol_version <= SCSI_REV_2			 && SCB_GET_LUN(scb) < 8)				sc->byte2 = SCB_GET_LUN(scb) << 5;			sc->unused[0] = 0;			sc->unused[1] = 0;			sc->length = sg->len;			sc->control = 0;			/*			 * We can't allow the target to disconnect.			 * This will be an untagged transaction and			 * having the target disconnect will make this			 * transaction indestinguishable from outstanding			 * tagged transactions.			 */			hscb->control = 0;			/*			 * This request sense could be because the			 * the device lost power or in some other			 * way has lost our transfer negotiations.			 * Renegotiate if appropriate.  Unit attention			 * errors will be reported before any data			 * phases occur.			 */			if (ahc_get_residual(scb) 			 == ahc_get_transfer_length(scb)) {				ahc_update_neg_request(ahc, &devinfo,						       tstate, targ_info,						       AHC_NEG_IF_NON_ASYNC);			}			if (tstate->auto_negotiate & devinfo.target_mask) {				hscb->control |= MK_MESSAGE;				scb->flags &= ~SCB_NEGOTIATE;				scb->flags |= SCB_AUTO_NEGOTIATE;			}			hscb->cdb_len = sizeof(*sc);			hscb->dataptr = sg->addr; 			hscb->datacnt = sg->len;			hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;			hscb->sgptr = ahc_htole32(hscb->sgptr);			scb->sg_count = 1;			scb->flags |= SCB_SENSE;			ahc_qinfifo_requeue_tail(ahc, scb);			ahc_outb(ahc, RETURN_1, SEND_SENSE);			/*			 * Ensure we have enough time to actually			 * retrieve the sense.			 */			ahc_scb_timer_reset(scb, 5 * 1000000);			break;		}		default:			break;		}		break;	}	case NO_MATCH:	{		/* Ensure we don't leave the selection hardware on */		ahc_outb(ahc, SCSISEQ,			 ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));		printf("%s:%c:%d: no active SCB for reconnecting "		       "target - issuing BUS DEVICE RESET\n",		       ahc_name(ahc), devinfo.channel, devinfo.target);		printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "		       "ARG_1 == 0x%x ACCUM = 0x%x\n",		       ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN),		       ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM));		printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "		       "SINDEX == 0x%x\n",		       ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR),		       ahc_index_busy_tcl(ahc,			    BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID),				      ahc_inb(ahc, SAVED_LUN))),		       ahc_inb(ahc, SINDEX));		printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "		       "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n",		       ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID),		       ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG),		       ahc_inb(ahc, SCB_CONTROL));		printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n",		       ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI));		printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0));		printf("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL));		ahc_dump_card_state(ahc);		ahc->msgout_buf[0] = MSG_BUS_DEV_RESET;		ahc->msgout_len = 1;		ahc->msgout_index = 0;		ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;		ahc_outb(ahc, MSG_OUT, HOST_MSG);		ahc_assert_atn(ahc);		break;	}	case SEND_REJECT: 	{		u_int rejbyte = ahc_inb(ahc, ACCUM);		printf("%s:%c:%d: Warning - unknown message received from "		       "target (0x%x).  Rejecting\n", 		       ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte);		break; 	}	case PROTO_VIOLATION:	{		ahc_handle_proto_violation(ahc);		break;	}	case IGN_WIDE_RES:		ahc_handle_ign_wide_residue(ahc, &devinfo);		break;	case PDATA_REINIT:		ahc_reinitialize_dataptrs(ahc);		break;	case BAD_PHASE:	{		u_int lastphase;		lastphase = ahc_inb(ahc, LASTPHASE);		printf("%s:%c:%d: unknown scsi bus phase %x, "		       "lastphase = 0x%x.  Attempting to continue\n",		       ahc_name(ahc), devinfo.channel, devinfo.target,		       lastphase, ahc_inb(ahc, SCSISIGI));		break;	}	case MISSED_BUSFREE:	{		u_int lastphase;		lastphase = ahc_inb(ahc, LASTPHASE);		printf("%s:%c:%d: Missed busfree. "		       "Lastphase = 0x%x, Curphase = 0x%x\n",		       ahc_name(ahc), devinfo.channel, devinfo.target,		       lastphase, ahc_inb(ahc, SCSISIGI));		ahc_restart(ahc);		return;	}	case HOST_MSG_LOOP:	{		/*		 * 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.		 */		if (ahc->msg_type == MSG_TYPE_NONE) {			struct scb *scb;			u_int scb_index;			u_int bus_phase;			bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;			if (bus_phase != P_MESGIN			 && bus_phase != P_MESGOUT) {				printf("ahc_intr: HOST_MSG_LOOP bad "				       "phase 0x%x\n",				      bus_phase);				/*				 * Probably transitioned to bus free before				 * we got here.  Just punt the message.				 */				ahc_clear_intstat(ahc);				ahc_restart(ahc);				return;			}			scb_index = ahc_inb(ahc, SCB_TAG);			scb = ahc_lookup_scb(ahc, scb_index);			if (devinfo.role == ROLE_INITIATOR) {				if (scb == NULL)					panic("HOST_MSG_LOOP with "					      "invalid SCB %x\n", scb_index);				if (bus_phase == P_MESGOUT)					ahc_setup_initiator_msgout(ahc,								   &devinfo,								   scb);				else {					ahc->msg_type =					    MSG_TYPE_INITIATOR_MSGIN;					ahc->msgin_index = 0;				}			}#ifdef AHC_TARGET_MODE			else {				if (bus_phase == P_MESGOUT) {					ahc->msg_type =					    MSG_TYPE_TARGET_MSGOUT;					ahc->msgin_index = 0;				}				else 					ahc_setup_target_msgin(ahc,							       &devinfo,							       scb);			}#endif		}		ahc_handle_message_phase(ahc);		break;	}	case PERR_DETECTED:	{		/*		 * If we've cleared the parity error interrupt		 * but the sequencer still believes that SCSIPERR		 * is true, it must be that the parity error is		 * for the currently presented byte on the bus,		 * and we are not in a phase (data-in) where we will		 * eventually ack this byte.  Ack the byte and		 * throw it away in the hope that the target will		 * take us to message out to deliver the appropriate		 * error message.		 */		if ((intstat & SCSIINT) == 0		 && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) {			if ((ahc->features & AHC_DT) == 0) {				u_int curphase;				/*				 * The hardware will only let you ack bytes				 * if the expected phase in SCSISIGO matches				 * the current phase.  Make sure this is				 * currently the case.				 */				curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;				ahc_outb(ahc, LASTPHASE, curphase);				ahc_outb(ahc, SCSISIGO, curphase);			}			if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) == 0) {				int wait;				/*				 * In a data phase.  Faster to bitbucket				 * the data than to individually ack each				 * byte.  This is also the only strategy				 * that will work with AUTOACK enabled.				 */				ahc_outb(ahc, SXFRCTL1,					 ahc_inb(ahc, SXFRCTL1) | BITBUCKET);				wait = 5000;				while (--wait != 0) {					if ((ahc_inb(ahc, SCSISIGI)					  & (CDI|MSGI)) != 0)						break;					ahc_delay(100);				}				ahc_outb(ahc, SXFRCTL1,					 ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);				if (wait == 0) {					struct	scb *scb;					u_int	scb_index;					ahc_print_devinfo(ahc, &devinfo);					printf("Unable to clear parity error.  "					       "Resetting bus.\n");					scb_index = ahc_inb(ahc, SCB_TAG);					scb = ahc_lookup_scb(ahc, scb_index);					if (scb != NULL)						ahc_set_transaction_status(scb,						    CAM_UNCOR_PARITY);					ahc_reset_channel(ahc, devinfo.channel, 							  /*init reset*/TRUE);				}			} else {				ahc_inb(ahc, SCSIDATL);			}		}		break;	}	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.		 */		u_int scbindex = ahc_inb(ahc, SCB_TAG);		u_int lastphase = ahc_inb(ahc, LASTPHASE);		u_int i;		scb = ahc_lookup_scb(ahc, scbindex);		for (i = 0; i < num_phases; i++) {			if (lastphase == ahc_phase_table[i].phase)				break;		}		ahc_print_path(ahc, scb);		printf("data overrun detected %s."		       "  Tag == 0x%x.\n",		       ahc_phase_table[i].phasemsg,  		       scb->hscb->tag);		ahc_print_path(ahc, scb);		printf("%s seen Data Phase.  Length = %ld.  NumSGs = %d.\n",		       ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",		       ahc_get_transfer_length(scb), scb->sg_count);		if (scb->sg_count > 0) {			for (i = 0; i < scb->sg_count; i++) {				printf("sg[%d] - Addr 0x%x%x : Length %d\n",				       i,				       (ahc_le32toh(scb->sg_list[i].len) >> 24				        & SG_HIGH_ADDR_BITS),				       ahc_le32toh(scb->sg_list[i].addr),				       ahc_le32toh(scb->sg_list[i].len)				       & AHC_SG_LEN_MASK);			}		}		/*		 * Set this and it will take effect when the		 * target does a command complete.		 */		ahc_freeze_devq(ahc, scb);		if ((scb->flags & SCB_SENSE) == 0) {			ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);		} else {			scb->flags &= ~SCB_SENSE;			ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);		}		ahc_freeze_scb(scb);		if ((ahc->features & AHC_ULTRA2) != 0) {			/*			 * Clear the channel in case we return			 * to data phase later.			 */			ahc_outb(ahc, SXFRCTL0,				 ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN);			ahc_outb(ahc, SXFRCTL0,				 ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN);		}		if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {			u_int dscommand1;			/* Ensure HHADDR is 0 for future DMA operations. */			dscommand1 = ahc_inb(ahc, DSCOMMAND1);			ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0);			ahc_outb(ahc, HADDR, 0);			ahc_outb(ahc, DSCOMMAND1, dscommand1);		}		break;	}	case MKMSG_FAILED:	{		u_int scbindex;		printf("%s:%c:%d:%d: Attempt to issue message failed\n",		       ahc_name(ahc), devinfo.channel, devinfo.target,		       devinfo.lun);		scbindex = ahc_inb(ahc, SCB_TAG);		scb = ahc_lookup_scb(ahc, scbindex);		if (scb != NULL		 && (scb->flags & SCB_RECOVERY_SCB) != 0)			/*			 * Ensure that we didn't put a second instance of this			 * SCB into the QINFIFO.			 */			ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb),					   SCB_GET_CHANNEL(ahc, scb),					   SCB_GET_LUN(scb), scb->hscb->tag,					   ROLE_INITIATOR, /*status*/0,					   SEARCH_REMOVE);		break;	}	case NO_FREE_SCB:	{		printf("%s: No free or disconnected SCBs\n", ahc_name(ahc));		ahc_dump_card_state(ahc);		panic("for safety");		break;	}	case SCB_MISMATCH:	{		u_int scbptr;		scbptr = ahc_inb(ahc, SCBPTR);		printf("Bogus TAG after DMA.  SCBPTR %d, tag %d, our tag %d\n",		       scbptr, ahc_inb(ahc, ARG_1),		       ahc->scb_data->hscbs[scbptr].tag);

⌨️ 快捷键说明

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