target = siop_cmd->xs->sc_link->target; lun = siop_cmd->xs->sc_link->lun; siop_lun = sc->targets[target]->siop_lun[lun];
target = siop_cmd->cmd_c.xs->sc_link->target; lun = siop_cmd->cmd_c.xs->sc_link->lun; siop_lun = ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
siop_start(sc)	struct siop_softc *sc;{	struct siop_cmd *siop_cmd, *next_siop_cmd;	struct siop_lun *siop_lun;	u_int32_t dsa;	int timeout;	int target, lun, tag, slot;	int newcmd = 0; 	int doingready = 0;	/*	 * first make sure to read valid data	 */	siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);	/*	 * The queue management here is a bit tricky: the script always looks	 * at the slots from first to last, so if we always use the first 	 * free slot commands can stay at the tail of the queue ~forever.	 * The algorithm used here is to restart from the head when we know	 * that the queue is empty, and only add commands after the last one.	 * When we're at the end of the queue wait for the script to clear it.	 * The best thing to do here would be to implement a circular queue,	 * but using only 53c720 features this can be "interesting".	 * A mid-way solution could be to implement 2 queues and swap orders.	 */	slot = sc->sc_currschedslot;	/*	 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is	 * free. As this is the last used slot, all previous slots are free,	 * we can restart from 1.	 * slot 0 is reserved for request sense commands.	 */	if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==	    0x80000000) {		slot = sc->sc_currschedslot = 1;	} else {		slot++;	}	/* first handle commands from the urgent list */	siop_cmd = TAILQ_FIRST(&sc->urgent_list);again:	for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {		next_siop_cmd = TAILQ_NEXT(siop_cmd, next);#ifdef DIAGNOSTIC		if (siop_cmd->status != CMDST_READY &&		    siop_cmd->status != CMDST_SENSE)			panic("siop: non-ready cmd in ready list");#endif			target = siop_cmd->xs->sc_link->target;		lun = siop_cmd->xs->sc_link->lun;		siop_lun = sc->targets[target]->siop_lun[lun];		/* if non-tagged command active, wait */		if (siop_lun->siop_tag[0].active != NULL)			continue;		/*		 * if we're in a queue full condition don't start a new		 * command, unless it's a request sense		 */		if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&		    siop_cmd->status == CMDST_READY)			continue;		/* find a free tag if needed */		if (siop_cmd->flags & CMDFL_TAG) {			for (tag = 1; tag < SIOP_NTAG; tag++) {				if (siop_lun->siop_tag[tag].active == NULL)					break;			}			if (tag == SIOP_NTAG) /* no free tag */				continue;		} else {			tag = 0;		}		siop_cmd->tag = tag;		/*		 * find a free scheduler slot and load it. If it's a request		 * sense we need to use slot 0.		 */		if (siop_cmd->status != CMDST_SENSE) {			for (; slot < SIOP_NSLOTS; slot++) {				/*				 * If cmd if 0x80000000 the slot is free				 */				if (siop_script_read(sc,				    (Ent_script_sched_slot0 / 4) + slot * 2) ==				    0x80000000)					break;			}			/* no more free slots, no need to continue */			if (slot == SIOP_NSLOTS) {				goto end;			}		} else {			slot = 0;			if (siop_script_read(sc, Ent_script_sched_slot0 / 4)			    != 0x80000000) 				goto end;		}#ifdef SIOP_DEBUG_SCHED		printf("using slot %d for DSA 0x%lx\n", slot,		    (u_long)siop_cmd->dsa);#endif		/* Ok, we can add the tag message */		if (tag > 0) {#ifdef DIAGNOSTIC			int msgcount =			    letoh32(siop_cmd->siop_tables.t_msgout.count);			if (msgcount != 1)				printf("%s:%d:%d: tag %d with msgcount %d\n",				    sc->sc_dev.dv_xname, target, lun, tag,				    msgcount);#endif			if (siop_cmd->xs->bp != NULL &&			    (siop_cmd->xs->bp->b_flags & B_ASYNC))				siop_cmd->siop_tables.msg_out[1] =				    MSG_SIMPLE_Q_TAG;			else				siop_cmd->siop_tables.msg_out[1] =				    MSG_ORDERED_Q_TAG;			siop_cmd->siop_tables.msg_out[2] = tag;			siop_cmd->siop_tables.t_msgout.count = htole32(3);		}		/* note that we started a new command */		newcmd = 1;		/* mark command as active */		if (siop_cmd->status == CMDST_READY) {			siop_cmd->status = CMDST_ACTIVE;		} else if (siop_cmd->status == CMDST_SENSE) {			siop_cmd->status = CMDST_SENSE_ACTIVE;		} else			panic("siop_start: bad status");		if (doingready)			TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);		else			TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);		siop_lun->siop_tag[tag].active = siop_cmd;		/* patch scripts with DSA addr */		dsa = siop_cmd->dsa;		/* first reselect switch, if we have an entry */		if (siop_lun->siop_tag[tag].reseloff > 0)			siop_script_write(sc,			    siop_lun->siop_tag[tag].reseloff + 1,			    dsa + sizeof(struct siop_xfer_common) +			    Ent_ldsa_reload_dsa);		/* CMD script: MOVE MEMORY addr */		siop_cmd->siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = 		   htole32(sc->sc_scriptaddr + Ent_script_sched_slot0 +		   slot * 8);		siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);		/* scheduler slot: JUMP ldsa_select */		siop_script_write(sc,		    (Ent_script_sched_slot0 / 4) + slot * 2 + 1,		    dsa + sizeof(struct siop_xfer_common) + Ent_ldsa_select);		/* handle timeout */		if (siop_cmd->status == CMDST_ACTIVE) {			if ((siop_cmd->xs->flags & SCSI_POLL) == 0) {				/* start expire timer */				timeout = (u_int64_t) siop_cmd->xs->timeout *				    (u_int64_t)hz / 1000;				if (timeout == 0)					timeout = 1;				timeout_add(&siop_cmd->xs->stimeout, timeout);			}		}		/*		 * Change JUMP cmd so that this slot will be handled		 */		siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,		    0x80080000);		/* if we're using the request sense slot, stop here */		if (slot == 0)			goto end;		sc->sc_currschedslot = slot;		slot++;	}	if (doingready == 0) {		/* now process ready list */		doingready = 1;		siop_cmd = TAILQ_FIRST(&sc->ready_list);		goto again;	}end:	/* if nothing changed no need to flush cache and wakeup script */	if (newcmd == 0)		return;	/* make sure SCRIPT processor will read valid data */	siop_script_sync(sc,BUS_DMASYNC_PREREAD |  BUS_DMASYNC_PREWRITE);	/* Signal script it has some work to do */	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SIGP);	/* and wait for IRQ */	return;}