FreeBSD/sys/dev/esp/ncr53c9x.c
/*
 * Schedule a SCSI operation.  This has now been pulled out of the interrupt
 * handler so that we may call it from ncr53c9x_action and ncr53c9x_done.
 * This may save us an unnecessary interrupt just to get things going.
 * Should only be called when state == NCR_IDLE and with sc_lock held.
 */
Schedule a SCSI operation.  This has now been pulled out of the interrupt
handler so that we may call it from ncr53c9x_action and ncr53c9x_done.
This may save us an unnecessary interrupt just to get things going.
Should only be called when state == NCR_IDLE and with sc_lock held.
Schedule a SCSI operation . This has now been pulled out of the interrupt handler so that we may call it from ncr53c9x_action and ncr53c9x_done . This may save us an unnecessary interrupt just to get things going . Should only be called when state == NCR_IDLE and with sc_lock held .
static void
ncr53c9x_sched(struct ncr53c9x_softc *sc)
{
	struct ncr53c9x_ecb *ecb;
	struct ncr53c9x_linfo *li;
	struct ncr53c9x_tinfo *ti;
	int lun, tag;
	NCR_LOCK_ASSERT(sc, MA_OWNED);
	NCR_TRACE(("[%s] ", __func__));
	if (sc->sc_state != NCR_IDLE)
		panic("%s: not IDLE (state=%d)", __func__, sc->sc_state);
	TAILQ_FOREACH(ecb, &sc->ready_list, chain) {
		ti = &sc->sc_tinfo[ecb->ccb->ccb_h.target_id];
		lun = ecb->ccb->ccb_h.target_lun;
		if ((ti->flags & (T_RSELECTOFF | T_TAG)) != T_TAG)
			tag = 0;
		else if ((ecb->flags & ECB_SENSE) != 0)
			tag = 0;
		else if ((ecb->ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) == 0)
			tag = 0;
		else if (ecb->ccb->csio.tag_action == CAM_TAG_ACTION_NONE)
			tag = 0;
		else
			tag = ecb->ccb->csio.tag_action;
		li = TINFO_LUN(ti, lun);
		if (li == NULL) {
			li = malloc(sizeof(*li), M_DEVBUF, M_NOWAIT | M_ZERO);
			if (li == NULL)
				continue;
			li->lun = lun;
			LIST_INSERT_HEAD(&ti->luns, li, link);
			if (lun < NCR_NLUN)
				ti->lun[lun] = li;
		}
		li->last_used = time_second;
		if (tag == 0) {
			if (li->untagged == NULL)
				li->untagged = ecb;
		}
		if (li->untagged != NULL) {
			tag = 0;
			if ((li->busy != 1) && li->used == 0) {
				ecb = li->untagged;
			} else {
				continue;
			}
		}
		ecb->tag[0] = tag;
		if (tag != 0) {
			li->queued[ecb->tag_id] = ecb;
			ecb->tag[1] = ecb->tag_id;
			li->used++;
		}
		if (li->untagged != NULL && (li->busy != 1)) {
			li->busy = 1;
			TAILQ_REMOVE(&sc->ready_list, ecb, chain);
			ecb->flags &= ~ECB_READY;
			sc->sc_nexus = ecb;
			ncr53c9x_select(sc, ecb);
			break;
		}
		if (li->untagged == NULL && tag != 0) {
			TAILQ_REMOVE(&sc->ready_list, ecb, chain);
			ecb->flags &= ~ECB_READY;
			sc->sc_nexus = ecb;
			ncr53c9x_select(sc, ecb);
			break;
		} else
			NCR_TRACE(("[%s %d:%d busy] \n", __func__,
			    ecb->ccb->ccb_h.target_id,
			    ecb->ccb->ccb_h.target_lun));
	}
}
static void ncr53c9x_sched ( struct ncr53c9x_softc * sc ) { struct ncr53c9x_ecb * ecb ; struct ncr53c9x_linfo * li ; struct ncr53c9x_tinfo * ti ; int lun , tag ; NCR_LOCK_ASSERT ( sc , MA_OWNED ) ; NCR_TRACE ( ( " " , __func__ ) ) ; if ( sc -> sc_state != NCR_IDLE ) panic ( " " , __func__ , sc -> sc_state ) ; TAILQ_FOREACH ( ecb , & sc -> ready_list , chain ) { ti = & sc -> sc_tinfo [ ecb -> ccb -> ccb_h . target_id ] ; lun = ecb -> ccb -> ccb_h . target_lun ; if ( ( ti -> flags & ( T_RSELECTOFF | T_TAG ) ) != T_TAG ) tag = 0 ; else if ( ( ecb -> flags & ECB_SENSE ) != 0 ) tag = 0 ; else if ( ( ecb -> ccb -> ccb_h . flags & CAM_TAG_ACTION_VALID ) == 0 ) tag = 0 ; else if ( ecb -> ccb -> csio . tag_action == CAM_TAG_ACTION_NONE ) tag = 0 ; else tag = ecb -> ccb -> csio . tag_action ; li = TINFO_LUN ( ti , lun ) ; if ( li == NULL ) { li = malloc ( sizeof ( * li ) , M_DEVBUF , M_NOWAIT | M_ZERO ) ; if ( li == NULL ) continue ; li -> lun = lun ; LIST_INSERT_HEAD ( & ti -> luns , li , link ) ; if ( lun < NCR_NLUN ) ti -> lun [ lun ] = li ; } li -> last_used = time_second ; if ( tag == 0 ) { if ( li -> untagged == NULL ) li -> untagged = ecb ; } if ( li -> untagged != NULL ) { tag = 0 ; if ( ( li -> busy != 1 ) && li -> used == 0 ) { ecb = li -> untagged ; } else { continue ; } } ecb -> tag [ 0 ] = tag ; if ( tag != 0 ) { li -> queued [ ecb -> tag_id ] = ecb ; ecb -> tag [ 1 ] = ecb -> tag_id ; li -> used ++ ; } if ( li -> untagged != NULL && ( li -> busy != 1 ) ) { li -> busy = 1 ; TAILQ_REMOVE ( & sc -> ready_list , ecb , chain ) ; ecb -> flags &= ~ ECB_READY ; sc -> sc_nexus = ecb ; ncr53c9x_select ( sc , ecb ) ; break ; } if ( li -> untagged == NULL && tag != 0 ) { TAILQ_REMOVE ( & sc -> ready_list , ecb , chain ) ; ecb -> flags &= ~ ECB_READY ; sc -> sc_nexus = ecb ; ncr53c9x_select ( sc , ecb ) ; break ; } else NCR_TRACE ( ( " \n " , __func__ , ecb -> ccb -> ccb_h . target_id , ecb -> ccb -> ccb_h . target_lun ) ) ; } }
Schedule a SCSI operation.
Schedule a SCSI operation .
/*
	 * Find first ecb in ready queue that is for a target/lunit
	 * combinations that is not busy.
	 */ /* Select type of tag for this command */ /* Initialize LUN info and add to list. */ /* Try to issue this as an untagged command. */ /*
				 * We need to issue this untagged command
				 * now.
				 */ /* not ready, yet */