static void FPT_ssel()

in FlashPoint.c [2275:2564]


static void FPT_ssel(u32 port, unsigned char p_card)
{

	unsigned char auto_loaded, i, target, *theCCB;

	u32 cdb_reg;
	struct sccb_card *CurrCard;
	struct sccb *currSCCB;
	struct sccb_mgr_tar_info *currTar_Info;
	unsigned char lastTag, lun;

	CurrCard = &FPT_BL_Card[p_card];
	currSCCB = CurrCard->currentSCCB;
	target = currSCCB->TargID;
	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
	lastTag = CurrCard->tagQ_Lst;

	ARAM_ACCESS(port);

	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
		currSCCB->ControlByte &= ~F_USE_CMD_Q;

	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))

		lun = currSCCB->Lun;
	else
		lun = 0;

	if (CurrCard->globalFlags & F_TAG_STARTED) {
		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
			if ((currTar_Info->TarLUN_CA == 0)
			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
				== TAG_Q_TRYING)) {

				if (currTar_Info->TarTagQ_Cnt != 0) {
					currTar_Info->TarLUNBusy[lun] = 1;
					FPT_queueSelectFail(CurrCard, p_card);
					SGRAM_ACCESS(port);
					return;
				}

				else {
					currTar_Info->TarLUNBusy[lun] = 1;
				}

			}
			/*End non-tagged */
			else {
				currTar_Info->TarLUNBusy[lun] = 1;
			}

		}
		/*!Use cmd Q Tagged */
		else {
			if (currTar_Info->TarLUN_CA == 1) {
				FPT_queueSelectFail(CurrCard, p_card);
				SGRAM_ACCESS(port);
				return;
			}

			currTar_Info->TarLUNBusy[lun] = 1;

		}		/*else use cmd Q tagged */

	}
	/*if glob tagged started */
	else {
		currTar_Info->TarLUNBusy[lun] = 1;
	}

	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
		if (CurrCard->discQCount >= QUEUE_DEPTH) {
			currTar_Info->TarLUNBusy[lun] = 1;
			FPT_queueSelectFail(CurrCard, p_card);
			SGRAM_ACCESS(port);
			return;
		}
		for (i = 1; i < QUEUE_DEPTH; i++) {
			if (++lastTag >= QUEUE_DEPTH)
				lastTag = 1;
			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
				CurrCard->tagQ_Lst = lastTag;
				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
				CurrCard->discQ_Tbl[lastTag] = currSCCB;
				CurrCard->discQCount++;
				break;
			}
		}
		if (i == QUEUE_DEPTH) {
			currTar_Info->TarLUNBusy[lun] = 1;
			FPT_queueSelectFail(CurrCard, p_card);
			SGRAM_ACCESS(port);
			return;
		}
	}

	auto_loaded = 0;

	WR_HARPOON(port + hp_select_id, target);
	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */

	if (currSCCB->OperationCode == RESET_COMMAND) {
		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
						   (currSCCB->
						    Sccb_idmsg & ~DISC_PRIV)));

		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);

		currSCCB->Sccb_scsimsg = TARGET_RESET;

		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
		auto_loaded = 1;
		currSCCB->Sccb_scsistat = SELECT_BDR_ST;

		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
			currTar_Info->TarSyncCtrl = 0;
			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
		}

		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
		}

		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
		FPT_SccbMgrTableInitTarget(p_card, target);

	}

	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
						   (currSCCB->
						    Sccb_idmsg & ~DISC_PRIV)));

		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);

		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
						     (((unsigned
							char)(currSCCB->
							      ControlByte &
							      TAG_TYPE_MASK)
						       >> 6) | (unsigned char)
						      0x20)));
		WRW_HARPOON((port + SYNC_MSGS + 2),
			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));

		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
		auto_loaded = 1;

	}

	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
		auto_loaded = FPT_siwidn(port, p_card);
		currSCCB->Sccb_scsistat = SELECT_WN_ST;
	}

	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
		   == SYNC_SUPPORTED)) {
		auto_loaded = FPT_sisyncn(port, p_card, 0);
		currSCCB->Sccb_scsistat = SELECT_SN_ST;
	}

	if (!auto_loaded) {

		if (currSCCB->ControlByte & F_USE_CMD_Q) {

			CurrCard->globalFlags |= F_TAG_STARTED;

			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
			    == TAG_Q_REJECT) {
				currSCCB->ControlByte &= ~F_USE_CMD_Q;

				/* Fix up the start instruction with a jump to
				   Non-Tag-CMD handling */
				WRW_HARPOON((port + ID_MSG_STRT),
					    BRH_OP + ALWAYS + NTCMD);

				WRW_HARPOON((port + NON_TAG_ID_MSG),
					    (MPM_OP + AMSG_OUT +
					     currSCCB->Sccb_idmsg));

				WR_HARPOON(port + hp_autostart_3,
					   (SELECT + SELCHK_STRT));

				/* Setup our STATE so we know what happened when
				   the wheels fall off. */
				currSCCB->Sccb_scsistat = SELECT_ST;

				currTar_Info->TarLUNBusy[lun] = 1;
			}

			else {
				WRW_HARPOON((port + ID_MSG_STRT),
					    (MPM_OP + AMSG_OUT +
					     currSCCB->Sccb_idmsg));

				WRW_HARPOON((port + ID_MSG_STRT + 2),
					    (MPM_OP + AMSG_OUT +
					     (((unsigned char)(currSCCB->
							       ControlByte &
							       TAG_TYPE_MASK)
					       >> 6) | (unsigned char)0x20)));

				for (i = 1; i < QUEUE_DEPTH; i++) {
					if (++lastTag >= QUEUE_DEPTH)
						lastTag = 1;
					if (CurrCard->discQ_Tbl[lastTag] ==
					    NULL) {
						WRW_HARPOON((port +
							     ID_MSG_STRT + 6),
							    (MPM_OP + AMSG_OUT +
							     lastTag));
						CurrCard->tagQ_Lst = lastTag;
						currSCCB->Sccb_tag = lastTag;
						CurrCard->discQ_Tbl[lastTag] =
						    currSCCB;
						CurrCard->discQCount++;
						break;
					}
				}

				if (i == QUEUE_DEPTH) {
					currTar_Info->TarLUNBusy[lun] = 1;
					FPT_queueSelectFail(CurrCard, p_card);
					SGRAM_ACCESS(port);
					return;
				}

				currSCCB->Sccb_scsistat = SELECT_Q_ST;

				WR_HARPOON(port + hp_autostart_3,
					   (SELECT + SELCHK_STRT));
			}
		}

		else {

			WRW_HARPOON((port + ID_MSG_STRT),
				    BRH_OP + ALWAYS + NTCMD);

			WRW_HARPOON((port + NON_TAG_ID_MSG),
				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));

			currSCCB->Sccb_scsistat = SELECT_ST;

			WR_HARPOON(port + hp_autostart_3,
				   (SELECT + SELCHK_STRT));
		}

		theCCB = (unsigned char *)&currSCCB->Cdb[0];

		cdb_reg = port + CMD_STRT;

		for (i = 0; i < currSCCB->CdbLength; i++) {
			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
			cdb_reg += 2;
			theCCB++;
		}

		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));

	}
	/* auto_loaded */
	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
	WR_HARPOON(port + hp_xferstat, 0x00);

	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));

	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));

	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
		WR_HARPOON(port + hp_scsictrl_0,
			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
	} else {

/*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
      auto_loaded |= AUTO_IMMED; */
		auto_loaded = AUTO_IMMED;

		DISABLE_AUTO(port);

		WR_HARPOON(port + hp_autostart_3, auto_loaded);
	}

	SGRAM_ACCESS(port);
}