FreeBSD/sys/dev/esp/ncr53c9x.c
/*
 * Send the highest priority, scheduled message.
 */
Send the highest priority, scheduled message.
Send the highest priority scheduled message .
static void
ncr53c9x_msgout(struct ncr53c9x_softc *sc)
{
	struct ncr53c9x_tinfo *ti;
	struct ncr53c9x_ecb *ecb;
	size_t size;
	int error;
#ifdef NCR53C9X_DEBUG
	int i;
#endif
	NCR_LOCK_ASSERT(sc, MA_OWNED);
	NCR_TRACE(("[%s(priq:%x, prevphase:%x)]", __func__, sc->sc_msgpriq,
	    sc->sc_prevphase));
	if (sc->sc_flags & NCR_ATN) {
		if (sc->sc_prevphase != MESSAGE_OUT_PHASE) {
		new:
			NCRCMD(sc, NCRCMD_FLUSH);
#if 0
			DELAY(1);
#endif
			sc->sc_msgoutq = 0;
			sc->sc_omlen = 0;
		}
	} else {
		if (sc->sc_prevphase == MESSAGE_OUT_PHASE) {
			ncr53c9x_sched_msgout(sc->sc_msgoutq);
			goto new;
		} else
			device_printf(sc->sc_dev, "at line %d: unexpected "
			    "MESSAGE OUT phase\n", __LINE__);
	}
	if (sc->sc_omlen == 0) {
		sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
		sc->sc_msgoutq |= sc->sc_msgout;
		sc->sc_msgpriq &= ~sc->sc_msgout;
		sc->sc_omlen = 1;		
		switch (sc->sc_msgout) {
		case SEND_SDTR:
			ecb = sc->sc_nexus;
			ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
			sc->sc_omess[0] = MSG_EXTENDED;
			sc->sc_omess[1] = MSG_EXT_SDTR_LEN;
			sc->sc_omess[2] = MSG_EXT_SDTR;
			sc->sc_omess[3] = ti->goal.period;
			sc->sc_omess[4] = ti->goal.offset;
			sc->sc_omlen = 5;
			break;
		case SEND_WDTR:
			ecb = sc->sc_nexus;
			ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
			sc->sc_omess[0] = MSG_EXTENDED;
			sc->sc_omess[1] = MSG_EXT_WDTR_LEN;
			sc->sc_omess[2] = MSG_EXT_WDTR;
			sc->sc_omess[3] = ti->goal.width;
			sc->sc_omlen = 4;
			break;
		case SEND_IDENTIFY:
			if (sc->sc_state != NCR_CONNECTED)
				device_printf(sc->sc_dev, "at line %d: no "
				    "nexus\n", __LINE__);
			ecb = sc->sc_nexus;
			sc->sc_omess[0] =
			    MSG_IDENTIFY(ecb->ccb->ccb_h.target_lun, 0);
			break;
		case SEND_TAG:
			if (sc->sc_state != NCR_CONNECTED)
				device_printf(sc->sc_dev, "at line %d: no "
				    "nexus\n", __LINE__);
			ecb = sc->sc_nexus;
			sc->sc_omess[0] = ecb->tag[0];
			sc->sc_omess[1] = ecb->tag[1];
			sc->sc_omlen = 2;
			break;
		case SEND_DEV_RESET:
			sc->sc_flags |= NCR_ABORTING;
			sc->sc_omess[0] = MSG_BUS_DEV_RESET;
			ecb = sc->sc_nexus;
			ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
			ti->curr.period = 0;
			ti->curr.offset = 0;
			ti->curr.width = MSG_EXT_WDTR_BUS_8_BIT;
			break;
		case SEND_PARITY_ERROR:
			sc->sc_omess[0] = MSG_PARITY_ERROR;
			break;
		case SEND_ABORT:
			sc->sc_flags |= NCR_ABORTING;
			sc->sc_omess[0] = MSG_ABORT;
			break;
		case SEND_INIT_DET_ERR:
			sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
			break;
		case SEND_REJECT:
			sc->sc_omess[0] = MSG_MESSAGE_REJECT;
			break;
		default:
			sc->sc_flags &= ~NCR_ATN;
			sc->sc_omess[0] = MSG_NOOP;
		}
		sc->sc_omp = sc->sc_omess;
	}
#ifdef NCR53C9X_DEBUG
	if ((ncr53c9x_debug & NCR_SHOWMSGS) != 0) {
		NCR_MSGS(("<msgout:"));
		for (i = 0; i < sc->sc_omlen; i++)
			NCR_MSGS((" %02x", sc->sc_omess[i]));
		NCR_MSGS(("> "));
	}
#endif
	if (sc->sc_rev != NCR_VARIANT_FAS366) {
		size = ulmin(sc->sc_omlen, sc->sc_maxxfer);
		error = NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
		if (error != 0)
			goto cmd;
		NCR_SET_COUNT(sc, size);
		NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
		NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
		NCRDMA_GO(sc);
		return;
	}
cmd:
	sc->sc_cmdlen = 0;
	ncr53c9x_flushfifo(sc);
	ncr53c9x_wrfifo(sc, sc->sc_omp, sc->sc_omlen);
	NCRCMD(sc, NCRCMD_TRANS);
}
static void ncr53c9x_msgout ( struct ncr53c9x_softc * sc ) { struct ncr53c9x_tinfo * ti ; struct ncr53c9x_ecb * ecb ; size_t size ; int error ; #ifdef NCR53C9X_DEBUG int i ; #endif NCR_LOCK_ASSERT ( sc , MA_OWNED ) ; NCR_TRACE ( ( " " , __func__ , sc -> sc_msgpriq , sc -> sc_prevphase ) ) ; if ( sc -> sc_flags & NCR_ATN ) { if ( sc -> sc_prevphase != MESSAGE_OUT_PHASE ) { new : NCRCMD ( sc , NCRCMD_FLUSH ) ; #if 0 DELAY ( 1 ) ; #endif sc -> sc_msgoutq = 0 ; sc -> sc_omlen = 0 ; } } else { if ( sc -> sc_prevphase == MESSAGE_OUT_PHASE ) { ncr53c9x_sched_msgout ( sc -> sc_msgoutq ) ; goto new ; } else device_printf ( sc -> sc_dev , " " " \n " , __LINE__ ) ; } if ( sc -> sc_omlen == 0 ) { sc -> sc_msgout = sc -> sc_msgpriq & - sc -> sc_msgpriq ; sc -> sc_msgoutq |= sc -> sc_msgout ; sc -> sc_msgpriq &= ~ sc -> sc_msgout ; sc -> sc_omlen = 1 ; switch ( sc -> sc_msgout ) { case SEND_SDTR : ecb = sc -> sc_nexus ; ti = & sc -> sc_tinfo [ ecb -> ccb -> ccb_h . target_id ] ; sc -> sc_omess [ 0 ] = MSG_EXTENDED ; sc -> sc_omess [ 1 ] = MSG_EXT_SDTR_LEN ; sc -> sc_omess [ 2 ] = MSG_EXT_SDTR ; sc -> sc_omess [ 3 ] = ti -> goal . period ; sc -> sc_omess [ 4 ] = ti -> goal . offset ; sc -> sc_omlen = 5 ; break ; case SEND_WDTR : ecb = sc -> sc_nexus ; ti = & sc -> sc_tinfo [ ecb -> ccb -> ccb_h . target_id ] ; sc -> sc_omess [ 0 ] = MSG_EXTENDED ; sc -> sc_omess [ 1 ] = MSG_EXT_WDTR_LEN ; sc -> sc_omess [ 2 ] = MSG_EXT_WDTR ; sc -> sc_omess [ 3 ] = ti -> goal . width ; sc -> sc_omlen = 4 ; break ; case SEND_IDENTIFY : if ( sc -> sc_state != NCR_CONNECTED ) device_printf ( sc -> sc_dev , " " " \n " , __LINE__ ) ; ecb = sc -> sc_nexus ; sc -> sc_omess [ 0 ] = MSG_IDENTIFY ( ecb -> ccb -> ccb_h . target_lun , 0 ) ; break ; case SEND_TAG : if ( sc -> sc_state != NCR_CONNECTED ) device_printf ( sc -> sc_dev , " " " \n " , __LINE__ ) ; ecb = sc -> sc_nexus ; sc -> sc_omess [ 0 ] = ecb -> tag [ 0 ] ; sc -> sc_omess [ 1 ] = ecb -> tag [ 1 ] ; sc -> sc_omlen = 2 ; break ; case SEND_DEV_RESET : sc -> sc_flags |= NCR_ABORTING ; sc -> sc_omess [ 0 ] = MSG_BUS_DEV_RESET ; ecb = sc -> sc_nexus ; ti = & sc -> sc_tinfo [ ecb -> ccb -> ccb_h . target_id ] ; ti -> curr . period = 0 ; ti -> curr . offset = 0 ; ti -> curr . width = MSG_EXT_WDTR_BUS_8_BIT ; break ; case SEND_PARITY_ERROR : sc -> sc_omess [ 0 ] = MSG_PARITY_ERROR ; break ; case SEND_ABORT : sc -> sc_flags |= NCR_ABORTING ; sc -> sc_omess [ 0 ] = MSG_ABORT ; break ; case SEND_INIT_DET_ERR : sc -> sc_omess [ 0 ] = MSG_INITIATOR_DET_ERR ; break ; case SEND_REJECT : sc -> sc_omess [ 0 ] = MSG_MESSAGE_REJECT ; break ; default : sc -> sc_flags &= ~ NCR_ATN ; sc -> sc_omess [ 0 ] = MSG_NOOP ; } sc -> sc_omp = sc -> sc_omess ; } #ifdef NCR53C9X_DEBUG if ( ( ncr53c9x_debug & NCR_SHOWMSGS ) != 0 ) { NCR_MSGS ( ( " " ) ) ; for ( i = 0 ; i < sc -> sc_omlen ; i ++ ) NCR_MSGS ( ( " " , sc -> sc_omess [ i ] ) ) ; NCR_MSGS ( ( " " ) ) ; } #endif if ( sc -> sc_rev != NCR_VARIANT_FAS366 ) { size = ulmin ( sc -> sc_omlen , sc -> sc_maxxfer ) ; error = NCRDMA_SETUP ( sc , & sc -> sc_omp , & sc -> sc_omlen , 0 , & size ) ; if ( error != 0 ) goto cmd ; NCR_SET_COUNT ( sc , size ) ; NCRCMD ( sc , NCRCMD_NOP | NCRCMD_DMA ) ; NCRCMD ( sc , NCRCMD_TRANS | NCRCMD_DMA ) ; NCRDMA_GO ( sc ) ; return ; } cmd : sc -> sc_cmdlen = 0 ; ncr53c9x_flushfifo ( sc ) ; ncr53c9x_wrfifo ( sc , sc -> sc_omp , sc -> sc_omlen ) ; NCRCMD ( sc , NCRCMD_TRANS ) ; }
Send the highest priority, scheduled message.
Send the highest priority scheduled message .
/*
	 * XXX - the NCR_ATN flag is not in sync with the actual ATN
	 *	 condition on the SCSI bus.  The 53c9x chip
	 *	 automatically turns off ATN before sending the
	 *	 message byte.  (See also the comment below in the
	 *	 default case when picking out a message to send.)
	 */ /* Pick up highest priority message. */ /* "Default" message len */ /*
			 * We normally do not get here, since the chip
			 * automatically turns off ATN before the last
			 * byte of a message is sent to the target.
			 * However, if the target rejects our (multi-byte)
			 * message early by switching to MSG IN phase
			 * ATN remains on, so the target may return to
			 * MSG OUT phase.  If there are no scheduled messages
			 * left we send a NO-OP.
			 *
			 * XXX - Note that this leaves no useful purpose for
			 * the NCR_ATN flag.
			 */ /* (Re)send the message. */ /* Program the SCSI counter. */ /* Load the count in and start the message-out transfer. */ /*
	 * XXX FIFO size
	 */