/* *  Remember all informations needed to free this CCB. */ 
struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order){	u_char tn = cmd->device->id;	u_char ln = cmd->device->lun;	struct sym_tcb *tp = &np->target[tn];	struct sym_lcb *lp = sym_lp(tp, ln);	u_short tag = NO_TAG;	SYM_QUEHEAD *qp;	struct sym_ccb *cp = NULL;	/*	 *  Look for a free CCB	 */	if (sym_que_empty(&np->free_ccbq))		sym_alloc_ccb(np);	qp = sym_remque_head(&np->free_ccbq);	if (!qp)		goto out;	cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING	/*	 *  If the LCB is not yet available and the LUN	 *  has been probed ok, try to allocate the LCB.	 */	if (!lp && sym_is_bit(tp->lun_map, ln)) {		lp = sym_alloc_lcb(np, tn, ln);		if (!lp)			goto out_free;	}#endif	/*	 *  If the LCB is not available here, then the 	 *  logical unit is not yet discovered. For those 	 *  ones only accept 1 SCSI IO per logical unit, 	 *  since we cannot allow disconnections.	 */	if (!lp) {		if (!sym_is_bit(tp->busy0_map, ln))			sym_set_bit(tp->busy0_map, ln);		else			goto out_free;	} else {		/*		 *  If we have been asked for a tagged command.		 */		if (tag_order) {			/*			 *  Debugging purpose.			 */#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING			assert(lp->busy_itl == 0);#endif			/*			 *  Allocate resources for tags if not yet.			 */			if (!lp->cb_tags) {				sym_alloc_lcb_tags(np, tn, ln);				if (!lp->cb_tags)					goto out_free;			}			/*			 *  Get a tag for this SCSI IO and set up			 *  the CCB bus address for reselection, 			 *  and count it for this LUN.			 *  Toggle reselect path to tagged.			 */			if (lp->busy_itlq < SYM_CONF_MAX_TASK) {				tag = lp->cb_tags[lp->ia_tag];				if (++lp->ia_tag == SYM_CONF_MAX_TASK)					lp->ia_tag = 0;				++lp->busy_itlq;#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING				lp->itlq_tbl[tag] = cpu_to_scr(cp->ccb_ba);				lp->head.resel_sa =					cpu_to_scr(SCRIPTA_BA(np, resel_tag));#endif#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING				cp->tags_si = lp->tags_si;				++lp->tags_sum[cp->tags_si];				++lp->tags_since;#endif			}			else				goto out_free;		}		/*		 *  This command will not be tagged.		 *  If we already have either a tagged or untagged 		 *  one, refuse to overlap this untagged one.		 */		else {			/*			 *  Debugging purpose.			 */#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING			assert(lp->busy_itl == 0 && lp->busy_itlq == 0);#endif			/*			 *  Count this nexus for this LUN.			 *  Set up the CCB bus address for reselection.			 *  Toggle reselect path to untagged.			 */			++lp->busy_itl;#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING			if (lp->busy_itl == 1) {				lp->head.itl_task_sa = cpu_to_scr(cp->ccb_ba);				lp->head.resel_sa =				      cpu_to_scr(SCRIPTA_BA(np, resel_no_tag));			}			else				goto out_free;#endif		}	}	/*	 *  Put the CCB into the busy queue.	 */	sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING	if (lp) {		sym_remque(&cp->link2_ccbq);		sym_insque_tail(&cp->link2_ccbq, &lp->waiting_ccbq);	}#endif	/*	 *  Remember all informations needed to free this CCB.	 */	cp->to_abort = 0;	cp->tag	   = tag;	cp->order  = tag_order;	cp->target = tn;	cp->lun    = ln;	if (DEBUG_FLAGS & DEBUG_TAGS) {		sym_print_addr(cmd, "ccb @%p using tag %d.\n", cp, tag);	}out:	return cp;out_free:	sym_insque_head(&cp->link_ccbq, &np->free_ccbq);	return NULL;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/53222b906903fd861dc24ebccfa07ee125941313/sym_hipd.c/buggy/drivers/scsi/sym53c8xx_2/sym_hipd.c