sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task); 
sym_clear_tasks(np, DID_ABORT, target, lun, task); 
static void sym_sir_task_recovery(struct sym_hcb *np, int num){	SYM_QUEHEAD *qp;	struct sym_ccb *cp;	struct sym_tcb *tp = NULL; /* gcc isn't quite smart enough yet */	struct scsi_target *starget;	int target=-1, lun=-1, task;	int i, k;	switch(num) {	/*	 *  The SCRIPTS processor stopped before starting	 *  the next command in order to allow us to perform 	 *  some task recovery.	 */	case SIR_SCRIPT_STOPPED:		/*		 *  Do we have any target to reset or unit to clear ?		 */		for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) {			tp = &np->target[i];			if (tp->to_reset || 			    (tp->lun0p && tp->lun0p->to_clear)) {				target = i;				break;			}			if (!tp->lunmp)				continue;			for (k = 1 ; k < SYM_CONF_MAX_LUN ; k++) {				if (tp->lunmp[k] && tp->lunmp[k]->to_clear) {					target	= i;					break;				}			}			if (target != -1)				break;		}		/*		 *  If not, walk the busy queue for any 		 *  disconnected CCB to be aborted.		 */		if (target == -1) {			FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {				cp = sym_que_entry(qp,struct sym_ccb,link_ccbq);				if (cp->host_status != HS_DISCONNECT)					continue;				if (cp->to_abort) {					target = cp->target;					break;				}			}		}		/*		 *  If some target is to be selected, 		 *  prepare and start the selection.		 */		if (target != -1) {			tp = &np->target[target];			np->abrt_sel.sel_id	= target;			np->abrt_sel.sel_scntl3 = tp->head.wval;			np->abrt_sel.sel_sxfer  = tp->head.sval;			OUTL(np, nc_dsa, np->hcb_ba);			OUTL_DSP(np, SCRIPTB_BA(np, sel_for_abort));			return;		}		/*		 *  Now look for a CCB to abort that haven't started yet.		 *  Btw, the SCRIPTS processor is still stopped, so 		 *  we are not in race.		 */		i = 0;		cp = NULL;		FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {			cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);			if (cp->host_status != HS_BUSY &&			    cp->host_status != HS_NEGOTIATE)				continue;			if (!cp->to_abort)				continue;#ifdef SYM_CONF_IARB_SUPPORT			/*			 *    If we are using IMMEDIATE ARBITRATION, we donnot 			 *    want to cancel the last queued CCB, since the 			 *    SCRIPTS may have anticipated the selection.			 */			if (cp == np->last_cp) {				cp->to_abort = 0;				continue;			}#endif			i = 1;	/* Means we have found some */			break;		}		if (!i) {			/*			 *  We are done, so we donnot need 			 *  to synchronize with the SCRIPTS anylonger.			 *  Remove the SEM flag from the ISTAT.			 */			np->istat_sem = 0;			OUTB(np, nc_istat, SIGP);			break;		}		/*		 *  Compute index of next position in the start 		 *  queue the SCRIPTS intends to start and dequeue 		 *  all CCBs for that device that haven't been started.		 */		i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;		i = sym_dequeue_from_squeue(np, i, cp->target, cp->lun, -1);		/*		 *  Make sure at least our IO to abort has been dequeued.		 */#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING		assert(i && sym_get_cam_status(cp->cmd) == CAM_REQUEUE_REQ);#else		sym_remque(&cp->link_ccbq);		sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);#endif		/*		 *  Keep track in cam status of the reason of the abort.		 */		if (cp->to_abort == 2)			sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);		else			sym_set_cam_status(cp->cmd, CAM_REQ_ABORTED);		/*		 *  Complete with error everything that we have dequeued.	 	 */		sym_flush_comp_queue(np, 0);		break;	/*	 *  The SCRIPTS processor has selected a target 	 *  we may have some manual recovery to perform for.	 */	case SIR_TARGET_SELECTED:		target = INB(np, nc_sdid) & 0xf;		tp = &np->target[target];		np->abrt_tbl.addr = cpu_to_scr(vtobus(np->abrt_msg));		/*		 *  If the target is to be reset, prepare a 		 *  M_RESET message and clear the to_reset flag 		 *  since we donnot expect this operation to fail.		 */		if (tp->to_reset) {			np->abrt_msg[0] = M_RESET;			np->abrt_tbl.size = 1;			tp->to_reset = 0;			break;		}		/*		 *  Otherwise, look for some logical unit to be cleared.		 */		if (tp->lun0p && tp->lun0p->to_clear)			lun = 0;		else if (tp->lunmp) {			for (k = 1 ; k < SYM_CONF_MAX_LUN ; k++) {				if (tp->lunmp[k] && tp->lunmp[k]->to_clear) {					lun = k;					break;				}			}		}		/*		 *  If a logical unit is to be cleared, prepare 		 *  an IDENTIFY(lun) + ABORT MESSAGE.		 */		if (lun != -1) {			struct sym_lcb *lp = sym_lp(tp, lun);			lp->to_clear = 0; /* We don't expect to fail here */			np->abrt_msg[0] = IDENTIFY(0, lun);			np->abrt_msg[1] = M_ABORT;			np->abrt_tbl.size = 2;			break;		}		/*		 *  Otherwise, look for some disconnected job to 		 *  abort for this target.		 */		i = 0;		cp = NULL;		FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {			cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);			if (cp->host_status != HS_DISCONNECT)				continue;			if (cp->target != target)				continue;			if (!cp->to_abort)				continue;			i = 1;	/* Means we have some */			break;		}		/*		 *  If we have none, probably since the device has 		 *  completed the command before we won abitration,		 *  send a M_ABORT message without IDENTIFY.		 *  According to the specs, the device must just 		 *  disconnect the BUS and not abort any task.		 */		if (!i) {			np->abrt_msg[0] = M_ABORT;			np->abrt_tbl.size = 1;			break;		}		/*		 *  We have some task to abort.		 *  Set the IDENTIFY(lun)		 */		np->abrt_msg[0] = IDENTIFY(0, cp->lun);		/*		 *  If we want to abort an untagged command, we 		 *  will send a IDENTIFY + M_ABORT.		 *  Otherwise (tagged command), we will send 		 *  a IDENTITFY + task attributes + ABORT TAG.		 */		if (cp->tag == NO_TAG) {			np->abrt_msg[1] = M_ABORT;			np->abrt_tbl.size = 2;		} else {			np->abrt_msg[1] = cp->scsi_smsg[1];			np->abrt_msg[2] = cp->scsi_smsg[2];			np->abrt_msg[3] = M_ABORT_TAG;			np->abrt_tbl.size = 4;		}		/*		 *  Keep track of software timeout condition, since the 		 *  peripheral driver may not count retries on abort 		 *  conditions not due to timeout.		 */		if (cp->to_abort == 2)			sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);		cp->to_abort = 0; /* We donnot expect to fail here */		break;	/*	 *  The target has accepted our message and switched 	 *  to BUS FREE phase as we expected.	 */	case SIR_ABORT_SENT:		target = INB(np, nc_sdid) & 0xf;		tp = &np->target[target];		starget = tp->sdev->sdev_target;				/*		**  If we didn't abort anything, leave here.		*/		if (np->abrt_msg[0] == M_ABORT)			break;		/*		 *  If we sent a M_RESET, then a hardware reset has 		 *  been performed by the target.		 *  - Reset everything to async 8 bit		 *  - Tell ourself to negotiate next time :-)		 *  - Prepare to clear all disconnected CCBs for 		 *    this target from our task list (lun=task=-1)		 */		lun = -1;		task = -1;		if (np->abrt_msg[0] == M_RESET) {			tp->head.sval = 0;			tp->head.wval = np->rv_scntl3;			tp->head.uval = 0;			spi_period(starget) = 0;			spi_offset(starget) = 0;			spi_width(starget) = 0;			spi_iu(starget) = 0;			spi_dt(starget) = 0;			spi_qas(starget) = 0;			tp->tgoal.check_nego = 1;		}		/*		 *  Otherwise, check for the LUN and TASK(s) 		 *  concerned by the cancelation.		 *  If it is not ABORT_TAG then it is CLEAR_QUEUE 		 *  or an ABORT message :-)		 */		else {			lun = np->abrt_msg[0] & 0x3f;			if (np->abrt_msg[1] == M_ABORT_TAG)				task = np->abrt_msg[2];		}		/*		 *  Complete all the CCBs the device should have 		 *  aborted due to our 'kiss of death' message.		 */		i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;		sym_dequeue_from_squeue(np, i, target, lun, -1);		sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task);		sym_flush_comp_queue(np, 0); 		/*		 *  If we sent a BDR, make upper layer aware of that. 		 */		if (np->abrt_msg[0] == M_RESET)			sym_xpt_async_sent_bdr(np, target);		break;	}	/*	 *  Print to the log the message we intend to send.	 */	if (num == SIR_TARGET_SELECTED) {		dev_info(&tp->sdev->sdev_target->dev, "control msgout:");		sym_printl_hex(np->abrt_msg, np->abrt_tbl.size);		np->abrt_tbl.size = cpu_to_scr(np->abrt_tbl.size);	}	/*	 *  Let the SCRIPTS processor continue.	 */	OUTONB_STD();}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/53222b906903fd861dc24ebccfa07ee125941313/sym_hipd.c/clean/drivers/scsi/sym53c8xx_2/sym_hipd.c