FreeBSD/sys/dev/esp/ncr53c9x.c
/*
 * Send a command to a target, set the driver state to NCR_SELECTING
 * and let the caller take care of the rest.
 *
 * Keeping this as a function allows me to say that this may be done
 * by DMA instead of programmed I/O soon.
 */
Send a command to a target, set the driver state to NCR_SELECTING
and let the caller take care of the rest.

Keeping this as a function allows me to say that this may be done
by DMA instead of programmed I/O soon.
Send a command to a target set the driver state to NCR_SELECTING and let the caller take care of the rest . Keeping this as a function allows me to say that this may be done by DMA instead of programmed I / O soon .
static void
ncr53c9x_select(struct ncr53c9x_softc *sc, struct ncr53c9x_ecb *ecb)
{
	struct ncr53c9x_tinfo *ti;
	uint8_t *cmd;
	size_t dmasize;
	int clen, error, selatn3, selatns;
	int lun = ecb->ccb->ccb_h.target_lun;
	int target = ecb->ccb->ccb_h.target_id;
	NCR_LOCK_ASSERT(sc, MA_OWNED);
	NCR_TRACE(("[%s(t%d,l%d,cmd:%x,tag:%x,%x)] ", __func__, target, lun,
	    ecb->cmd.cmd.opcode, ecb->tag[0], ecb->tag[1]));
	ti = &sc->sc_tinfo[target];
	sc->sc_state = NCR_SELECTING;
	callout_reset(&ecb->ch, mstohz(ecb->timeout), ncr53c9x_callout, ecb);
	if (sc->sc_rev == NCR_VARIANT_FAS366) {
		NCRCMD(sc, NCRCMD_FLUSH);
		NCR_WRITE_REG(sc, NCR_SELID, target | NCR_BUSID_HMEXC32 |
		    NCR_BUSID_HMEENCID);
	} else
		NCR_WRITE_REG(sc, NCR_SELID, target);
	if ((ecb->flags & ECB_SENSE) != 0 && (ti->curr.offset != 0 ||
	    ti->curr.width != MSG_EXT_WDTR_BUS_8_BIT)) {
		ti->curr.period = 0;
		ti->curr.offset = 0;
		ti->curr.width = MSG_EXT_WDTR_BUS_8_BIT;
	}
	ncr53c9x_setsync(sc, ti);
	selatn3 = selatns = 0;
	if (ecb->tag[0] != 0) {
		if (sc->sc_features & NCR_F_SELATN3)
			selatn3 = 1;
		else
			selatns = 1;
	}
	if (ti->curr.period != ti->goal.period ||
	    ti->curr.offset != ti->goal.offset ||
	    ti->curr.width != ti->goal.width) {
		selatn3 = 0;
		selatns = 1;
	}
	cmd = (uint8_t *)&ecb->cmd.cmd;
	if (selatn3) {
		clen = ecb->clen + 3;
		cmd -= 3;
		cmd[0] = MSG_IDENTIFY(lun, 1);	
		cmd[1] = ecb->tag[0];		
		cmd[2] = ecb->tag[1];		
	} else {
		clen = ecb->clen + 1;
		cmd -= 1;
		cmd[0] = MSG_IDENTIFY(lun, (ti->flags & T_RSELECTOFF) == 0);
	}
	if ((sc->sc_features & NCR_F_DMASELECT) && !selatns) {
		dmasize = clen;
		sc->sc_cmdlen = clen;
		sc->sc_cmdp = cmd;
		error = NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0,
		    &dmasize);
		if (error != 0)
			goto cmd;
		NCR_SET_COUNT(sc, dmasize);
		NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
		if (selatn3) {
			sc->sc_msgout = SEND_TAG;
			sc->sc_flags |= NCR_ATN;
			NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA);
		} else
			NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
		NCRDMA_GO(sc);
		return;
	}
cmd:
	sc->sc_cmdlen = 0;
	ncr53c9x_wrfifo(sc, cmd, clen);
	if (selatns) {
		NCR_MSGS(("SELATNS \n"));
		NCRCMD(sc, NCRCMD_SELATNS);
	} else if (selatn3) {
		sc->sc_msgout = SEND_TAG;
		sc->sc_flags |= NCR_ATN;
		NCRCMD(sc, NCRCMD_SELATN3);
	} else
		NCRCMD(sc, NCRCMD_SELATN);
}
static void ncr53c9x_select ( struct ncr53c9x_softc * sc , struct ncr53c9x_ecb * ecb ) { struct ncr53c9x_tinfo * ti ; uint8_t * cmd ; size_t dmasize ; int clen , error , selatn3 , selatns ; int lun = ecb -> ccb -> ccb_h . target_lun ; int target = ecb -> ccb -> ccb_h . target_id ; NCR_LOCK_ASSERT ( sc , MA_OWNED ) ; NCR_TRACE ( ( " " , __func__ , target , lun , ecb -> cmd . cmd . opcode , ecb -> tag [ 0 ] , ecb -> tag [ 1 ] ) ) ; ti = & sc -> sc_tinfo [ target ] ; sc -> sc_state = NCR_SELECTING ; callout_reset ( & ecb -> ch , mstohz ( ecb -> timeout ) , ncr53c9x_callout , ecb ) ; if ( sc -> sc_rev == NCR_VARIANT_FAS366 ) { NCRCMD ( sc , NCRCMD_FLUSH ) ; NCR_WRITE_REG ( sc , NCR_SELID , target | NCR_BUSID_HMEXC32 | NCR_BUSID_HMEENCID ) ; } else NCR_WRITE_REG ( sc , NCR_SELID , target ) ; if ( ( ecb -> flags & ECB_SENSE ) != 0 && ( ti -> curr . offset != 0 || ti -> curr . width != MSG_EXT_WDTR_BUS_8_BIT ) ) { ti -> curr . period = 0 ; ti -> curr . offset = 0 ; ti -> curr . width = MSG_EXT_WDTR_BUS_8_BIT ; } ncr53c9x_setsync ( sc , ti ) ; selatn3 = selatns = 0 ; if ( ecb -> tag [ 0 ] != 0 ) { if ( sc -> sc_features & NCR_F_SELATN3 ) selatn3 = 1 ; else selatns = 1 ; } if ( ti -> curr . period != ti -> goal . period || ti -> curr . offset != ti -> goal . offset || ti -> curr . width != ti -> goal . width ) { selatn3 = 0 ; selatns = 1 ; } cmd = ( uint8_t * ) & ecb -> cmd . cmd ; if ( selatn3 ) { clen = ecb -> clen + 3 ; cmd -= 3 ; cmd [ 0 ] = MSG_IDENTIFY ( lun , 1 ) ; cmd [ 1 ] = ecb -> tag [ 0 ] ; cmd [ 2 ] = ecb -> tag [ 1 ] ; } else { clen = ecb -> clen + 1 ; cmd -= 1 ; cmd [ 0 ] = MSG_IDENTIFY ( lun , ( ti -> flags & T_RSELECTOFF ) == 0 ) ; } if ( ( sc -> sc_features & NCR_F_DMASELECT ) && ! selatns ) { dmasize = clen ; sc -> sc_cmdlen = clen ; sc -> sc_cmdp = cmd ; error = NCRDMA_SETUP ( sc , & sc -> sc_cmdp , & sc -> sc_cmdlen , 0 , & dmasize ) ; if ( error != 0 ) goto cmd ; NCR_SET_COUNT ( sc , dmasize ) ; NCRCMD ( sc , NCRCMD_NOP | NCRCMD_DMA ) ; if ( selatn3 ) { sc -> sc_msgout = SEND_TAG ; sc -> sc_flags |= NCR_ATN ; NCRCMD ( sc , NCRCMD_SELATN3 | NCRCMD_DMA ) ; } else NCRCMD ( sc , NCRCMD_SELATN | NCRCMD_DMA ) ; NCRDMA_GO ( sc ) ; return ; } cmd : sc -> sc_cmdlen = 0 ; ncr53c9x_wrfifo ( sc , cmd , clen ) ; if ( selatns ) { NCR_MSGS ( ( " \n " ) ) ; NCRCMD ( sc , NCRCMD_SELATNS ) ; } else if ( selatn3 ) { sc -> sc_msgout = SEND_TAG ; sc -> sc_flags |= NCR_ATN ; NCRCMD ( sc , NCRCMD_SELATN3 ) ; } else NCRCMD ( sc , NCRCMD_SELATN ) ; }
Send a command to a target, set the driver state to NCR_SELECTING
 and let the caller take care of the rest.
Send a command to a target set the driver state to NCR_SELECTING and let the caller take care of the rest .
/*
	 * Schedule the callout now, the first time we will go away
	 * expecting to come back due to an interrupt, because it is
	 * always possible that the interrupt may never happen.
	 */ /*
	 * The docs say the target register is never reset, and I
	 * can't think of a better place to set it.
	 */ /*
	 * If we are requesting sense, force a renegotiation if we are
	 * currently using anything different from asynchronous at 8 bit
	 * as the target might have lost our transfer negotiations.
	 */ /* Use SELATN3 to send tag messages. */ /* We don't have SELATN3; use SELATNS to send tags. */ /* We have to use SELATNS to send sync/wide messages. */ /* We'll use tags with SELATN3. */ /* msg[0] */ /* msg[1] */ /* msg[2] */ /* We don't have tags, or will send messages with SELATNS. */ /* Setup DMA transfer for command. */ /* Program the SCSI counter. */ /* Load the count in. */ /* And get the target's attention. */ /*
	 * Who am I?  This is where we tell the target that we are
	 * happy for it to disconnect etc.
	 */ /* Now get the command into the FIFO. */ /* And get the target's attention. */ /* Arbitrate, select and stop after IDENTIFY message. */