diff options
Diffstat (limited to 'sys/dev/isp/isp.c')
| -rw-r--r-- | sys/dev/isp/isp.c | 813 | 
1 files changed, 198 insertions, 615 deletions
| diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 1b8b9d893a7ee..b93775007e833 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -1,5 +1,4 @@ -/* $Id: isp.c,v 1.10 1999/01/10 02:55:10 mjacob Exp $ */ -/* release_12_28_98_A+ */ +/* $FreeBSD$ */  /*   * Machine and OS Independent (well, as best as possible)   * code for the Qlogic ISP SCSI adapters. @@ -52,7 +51,7 @@  #include <dev/isp/isp_freebsd.h>  #endif  #ifdef	__linux__ -#include "isp_linux.h" +#include <isp_linux.h>  #endif  /* @@ -64,7 +63,7 @@  /*   * Local static data   */ -#ifdef	ISP_TARGET_MODE +#if	defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)  static const char tgtiqd[36] = {  	0x03, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,  	0x51, 0x4C, 0x4F, 0x47, 0x49, 0x43, 0x20, 0x20, @@ -89,16 +88,11 @@ static const char tgtiqd[36] = {  /*   * Local function prototypes.   */ -static int isp_parse_async __P((struct ispsoftc *, int)); +static int isp_parse_async __P((struct ispsoftc *, u_int16_t));  static int isp_handle_other_response  __P((struct ispsoftc *, ispstatusreq_t *, u_int8_t *)); -#ifdef	ISP_TARGET_MODE +#if	defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)  static int isp_modify_lun __P((struct ispsoftc *, int, int, int)); -static void isp_notify_ack __P((struct ispsoftc *, void *)); -static void isp_handle_atio __P((struct ispsoftc *, void *)); -static void isp_handle_atio2 __P((struct ispsoftc *, void *)); -static void isp_handle_ctio __P((struct ispsoftc *, void *)); -static void isp_handle_ctio2 __P((struct ispsoftc *, void *));  #endif  static void isp_parse_status  __P((struct ispsoftc *, ispstatusreq_t *, ISP_SCSI_XFER_T *)); @@ -107,7 +101,7 @@ static void isp_fw_state __P((struct ispsoftc *));  static void isp_dumpregs __P((struct ispsoftc *, const char *));  static void isp_dumpxflist __P((struct ispsoftc *));  static void isp_prtstst __P((ispstatusreq_t *)); -static char *isp2100_fw_statename __P((int)); +static char *isp2100_fw_statename __P((u_int8_t));  static void isp_mboxcmd __P((struct ispsoftc *, mbreg_t *));  static void isp_update  __P((struct ispsoftc *)); @@ -128,7 +122,7 @@ isp_reset(isp)  {  	static char once = 1;  	mbreg_t mbs; -	int loops, i, dodnld = 1, deadchip; +	int loops, i, dodnld = 1;  	char *revname;  	isp->isp_state = ISP_NILSTATE; @@ -139,26 +133,16 @@ isp_reset(isp)  	 * here.  	 */  	isp->isp_dblev = DFLT_DBLEVEL; -	deadchip = ISP_READ(isp, HCCR) & HCCR_RESET; -	if (deadchip) { -		ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); -		if (ISP_READ(isp, HCCR) & HCCR_RESET) { -			isp_dumpregs(isp, "still reset after release"); -			SYS_DELAY(1000); -		} else { -			deadchip = 1; -		} -	} -  	if (isp->isp_type & ISP_HA_FC) {  		revname = "2100";  	} else {  		sdparam *sdp = isp->isp_param; -		i = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK; -		switch (i) { + +		int rev = ISP_READ(isp, BIU_CONF0) & BIU_CONF0_HW_MASK; +		switch (rev) {  		default:  			PRINTF("%s: unknown chip rev. 0x%x- assuming a 1020\n", -			    isp->isp_name, i); +			    isp->isp_name, rev);  			/* FALLTHROUGH */  		case 1:  			revname = "1020";	 @@ -195,20 +179,16 @@ isp_reset(isp)  		 * Try and figure out if we're connected to a differential bus.  		 * You have to pause the RISC processor to read SXP registers.  		 */ -		if (deadchip == 0) { -			ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); -			i = 100; -			while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) { -				SYS_DELAY(20); -				if (--i == 0) { -					isp_dumpregs(isp, -					    "cannot stop RISC processor"); -					i = -1; -					break; -				} +		ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); +		i = 100; +		while ((ISP_READ(isp, HCCR) & HCCR_PAUSE) == 0) { +			SYS_DELAY(20); +			if (--i == 0) { +				PRINTF("%s: unable to pause RISC processor\n", +				    isp->isp_name); +				i = -1; +				break;  			} -		} else { -			i = 0;  		}  		if (i > 0) {  			if (isp->isp_bustype != ISP_BT_SBUS) { @@ -243,10 +223,9 @@ isp_reset(isp)  				sdp->isp_clock = 40;  			}  			/* -			 * Restart processor, if necessary. +			 * Restart processor  			 */ -			if (deadchip == 0) -				ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); +			ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE);  		}  		/*  		 * Machine dependent clock (if set) overrides @@ -264,7 +243,7 @@ isp_reset(isp)  	 */  	ISP_RESET0(isp); -	if (once == 1 && deadchip == 0) { +	if (once == 1) {  		once = 0;  		/*  		 * Get the current running firmware revision out of the @@ -285,7 +264,6 @@ isp_reset(isp)  		}  	} -  	/*  	 * Hit the chip over the head with hammer,  	 * and give the ISP a chance to recover. @@ -353,21 +331,9 @@ isp_reset(isp)  	ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);  	SYS_DELAY(100); -	/* -	 * Establish some initial burst rate thingies -	 * (only for the 1XX0 boards). This really should -	 * be done later after fetching from NVRAM. -	 */  	if (isp->isp_type & ISP_HA_SCSI) { -		u_int16_t conf1 = isp->isp_mdvec->dv_conf1; -		/* -		 * Busted FIFO. Turn off all but burst enables. -		 */ -		if (isp->isp_type == ISP_HA_SCSI_1040A) { -			conf1 &= BIU_BURST_ENABLE; -		} -		ISP_SETBITS(isp, BIU_CONF1, conf1); -		if (conf1 & BIU_BURST_ENABLE) { +		ISP_SETBITS(isp, BIU_CONF1, isp->isp_mdvec->dv_conf1); +		if (isp->isp_mdvec->dv_conf1 & BIU_BURST_ENABLE) {  			ISP_SETBITS(isp, CDMA_CONF, DMA_ENABLE_BURST);  			ISP_SETBITS(isp, DDMA_CONF, DMA_ENABLE_BURST);  		} @@ -740,7 +706,7 @@ isp_fibre_init(isp)  	fcparam *fcp;  	isp_icb_t *icbp;  	mbreg_t mbs; -	int count, loopid; +	int count;  	u_int8_t lwfs;  	fcp = isp->isp_param; @@ -749,41 +715,16 @@ isp_fibre_init(isp)  		PRINTF("%s: can't setup DMA for mailboxes\n", isp->isp_name);  		return;  	} -	/* -	 * For systems that don't have BIOS methods for which -	 * we can easily change the NVRAM based loopid, we'll -	 * override that here. Note that when we initialize -	 * the firmware we may get back a different loopid than -	 * we asked for anyway. XXX This is probably not the -	 * best way to figure this out XXX -	 */ -#ifndef	__i386__ -	loopid = DEFAULT_LOOPID; -#else -	loopid = fcp->isp_loopid; -#endif -  	icbp = (isp_icb_t *) fcp->isp_scratch; -	MEMZERO(icbp, sizeof (*icbp)); +	bzero(icbp, sizeof (*icbp));  	icbp->icb_version = ICB_VERSION1; -#ifdef	ISP_TARGET_MODE -	fcp->isp_fwoptions = ICBOPT_TGT_ENABLE|ICBOPT_INI_TGTTYPE; -#else +  	fcp->isp_fwoptions = 0; -#endif -	fcp->isp_fwoptions |= ICBOPT_INI_ADISC|ICBOPT_FAIRNESS; -	fcp->isp_fwoptions |= ICBOPT_PDBCHANGE_AE; -	fcp->isp_fwoptions |= ICBOPT_HARD_ADDRESS; -#ifdef	CHECKME -	fcp->isp_fwoptions |= ICBOPT_USE_PORTNAME; -#endif -#ifdef	THIS_WORKED -	/* -	 * This has unhappiness in target mode -	 */ -	fcp->isp_fwoptions |= ICBOPT_FULL_LOGIN; +#ifdef	ISP2100_TARGET_MODE +	fcp->isp_fwoptions |= ICBOPT_TGT_ENABLE	| ICBOPT_INI_TGTTYPE; +	icbp->icb_iqdevtype = 0x23;	/* DPQ_SUPPORTED/PROCESSOR */  #endif  	icbp->icb_fwoptions = fcp->isp_fwoptions;  	icbp->icb_maxfrmlen = fcp->isp_maxfrmlen; @@ -796,13 +737,9 @@ isp_fibre_init(isp)  	icbp->icb_execthrottle = fcp->isp_execthrottle;  	icbp->icb_retry_delay = fcp->isp_retry_delay;  	icbp->icb_retry_count = fcp->isp_retry_count; -	icbp->icb_hardaddr = loopid;  	MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, fcp->isp_wwn); -	if (icbp->icb_fwoptions & ICBOPT_USE_PORTNAME) { -		u_int64_t portname = fcp->isp_wwn | (2LL << 56); -		MAKE_NODE_NAME_FROM_WWN(icbp->icb_nodename, portname); -	} +  	icbp->icb_rqstqlen = RQUEST_QUEUE_LEN;  	icbp->icb_rsltqlen = RESULT_QUEUE_LEN;  	icbp->icb_rqstaddr[RQRSP_ADDR0015] = @@ -851,15 +788,24 @@ isp_fibre_init(isp)  	isp->isp_residx = 0;  	/* -	 * Wait up to 5 seconds for FW to go to READY state. +	 * Wait up to 12 seconds for FW to go to READY state. +	 * This used to be 3 seconds, but that lost. +	 * +	 * This is all very much not right. The problem here +	 * is that the cable may not be plugged in, or there +	 * may be many many members of the loop that haven't +	 * been logged into. +	 * +	 * This model of doing things doesn't support dynamic +	 * attachment, so we just plain lose (for now).  	 */  	lwfs = FW_CONFIG_WAIT;  	for (count = 0; count < 12000; count++) {  		isp_fw_state(isp);  		if (lwfs != fcp->isp_fwstate) {  			PRINTF("%s: Firmware State %s -> %s\n", -			    isp->isp_name, isp2100_fw_statename((int)lwfs), -			    isp2100_fw_statename((int)fcp->isp_fwstate)); +			    isp->isp_name, isp2100_fw_statename(lwfs), +			    isp2100_fw_statename(fcp->isp_fwstate));  			lwfs = fcp->isp_fwstate;  		}  		if (fcp->isp_fwstate == FW_READY) { @@ -882,14 +828,16 @@ isp_fibre_init(isp)  		}  		fcp->isp_loopid = mbs.param[1];  		fcp->isp_alpa = mbs.param[2]; -		PRINTF("%s: Loop ID %d, ALPA 0x%x\n", isp->isp_name, +		PRINTF("%s: Loop ID 0x%x, ALPA 0x%x\n", isp->isp_name,  		    fcp->isp_loopid, fcp->isp_alpa);  		isp->isp_state = ISP_INITSTATE; -#ifdef	ISP_TARGET_MODE +#if	defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)  		DISABLE_INTS(isp); -		if (isp_modify_lun(isp, 0, 1, 1)) { -			PRINTF("%s: failed to enable target mode\n", -			    isp->isp_name); +		if (isp->isp_fwrev >= ISP_FW_REV(1, 13)) { +			if (isp_modify_lun(isp, 0, 1, 1)) { +				PRINTF("%s: failed to establish target mode\n", +				    isp->isp_name); +			}  		}  		ENABLE_INTS(isp);  #endif @@ -900,6 +848,29 @@ isp_fibre_init(isp)  }  /* + * Free any associated resources prior to decommissioning and + * set the card to a known state (so it doesn't wake up and kick + * us when we aren't expecting it to). + * + * Locks are held before coming here. + */ +void +isp_uninit(isp) +	struct ispsoftc *isp; +{ +	/* +	 * Leave with interrupts disabled. +	 */ +	DISABLE_INTS(isp); + +	/* +	 * Stop the watchdog timer (if started). +	 */ +	STOP_WATCHDOG(isp_watch, isp); +} + + +/*   * Start a command. Locking is assumed done in the caller.   */ @@ -964,7 +935,7 @@ ispscsicmd(xs)  		u_int8_t niptr;  		ispmarkreq_t *marker = (ispmarkreq_t *) reqp; -		MEMZERO((void *) marker, sizeof (*marker)); +		bzero((void *) marker, sizeof (*marker));  		marker->req_header.rqs_entry_count = 1;  		marker->req_header.rqs_entry_type = RQSTYPE_MARKER;  		marker->req_modifier = SYNC_ALL; @@ -991,7 +962,7 @@ ispscsicmd(xs)  		iptr = niptr;  	} -	MEMZERO((void *) reqp, UZSIZE); +	bzero((void *) reqp, UZSIZE);  	reqp->req_header.rqs_entry_count = 1;  	if (isp->isp_type & ISP_HA_FC) {  		reqp->req_header.rqs_entry_type = RQSTYPE_T2RQS; @@ -1046,19 +1017,12 @@ ispscsicmd(xs)  			reqp->req_flags = 0;  		}  	} +	reqp->req_lun_trn = XS_LUN(xs);  	reqp->req_target = XS_TGT(xs);  	if (isp->isp_type & ISP_HA_SCSI) { -		reqp->req_lun_trn = XS_LUN(xs);  		reqp->req_cdblen = XS_CDBLEN(xs); -	} else { -#ifdef	SCCLUN -		reqp->req_scclun = XS_LUN(xs); -#else -		reqp->req_lun_trn = XS_LUN(xs); -#endif -  	} -	MEMCPY(reqp->req_cdb, XS_CDBP(xs), XS_CDBLEN(xs)); +	bcopy((void *)XS_CDBP(xs), reqp->req_cdb, XS_CDBLEN(xs));  	IDPRINTF(5, ("%s(%d.%d): START%d cmd 0x%x datalen %d\n", isp->isp_name,  	    XS_TGT(xs), XS_LUN(xs), reqp->req_header.rqs_seqno, @@ -1158,18 +1122,7 @@ isp_control(isp, ctl, arg)  			break;  		}  		mbs.param[0] = MBOX_ABORT; -#ifdef	SCCLUN -		if (isp->isp_type & ISP_HA_FC) { -			mbs.param[1] = XS_TGT(xs) << 8; -			mbs.param[4] = 0; -			mbs.param[5] = 0; -			mbs.param[6] = XS_LUN(xs); -		} else { -			mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs); -		} -#else -		mbs.param[1] = XS_TGT(xs) << 8 | XS_LUN(xs); -#endif +		mbs.param[1] = XS_TGT(xs) | XS_LUN(xs);  		mbs.param[2] = (i+1) >> 16;  		mbs.param[3] = (i+1) & 0xffff;  		isp_mboxcmd(isp, &mbs); @@ -1227,7 +1180,7 @@ isp_intr(arg)  	if (ISP_READ(isp, BIU_SEMA) & 1) {  		u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); -		if (isp_parse_async(isp, (int) mbox)) +		if (isp_parse_async(isp, mbox))  			return (1);  		ISP_WRITE(isp, BIU_SEMA, 0);  	} @@ -1319,14 +1272,14 @@ isp_intr(arg)  		XS_STS(xs) = sp->req_scsi_status & 0xff;  		if (isp->isp_type & ISP_HA_SCSI) {  			if (sp->req_state_flags & RQSF_GOT_SENSE) { -				MEMCPY(XS_SNSP(xs), sp->req_sense_data, +				bcopy(sp->req_sense_data, XS_SNSP(xs),  					XS_SNSLEN(xs));  				XS_SNS_IS_VALID(xs);  			}  		} else {  			if (XS_STS(xs) == SCSI_CHECK) {  				XS_SNS_IS_VALID(xs); -				MEMCPY(XS_SNSP(xs), sp->req_sense_data, +				bcopy(sp->req_sense_data, XS_SNSP(xs),  					XS_SNSLEN(xs));  				sp->req_state_flags |= RQSF_GOT_SENSE;  			} @@ -1346,9 +1299,8 @@ isp_intr(arg)  		} else {  			PRINTF("%s: unknown return %x\n", isp->isp_name,  				sp->req_header.rqs_entry_type); -			if (XS_NOERR(xs)) { +			if (XS_NOERR(xs))  				XS_SETERR(xs, HBA_BOTCH); -			}  		}  		if (isp->isp_type & ISP_HA_SCSI) {  			XS_RESID(xs) = sp->req_resid; @@ -1368,8 +1320,7 @@ isp_intr(arg)  		 */  		if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) {  			if (XS_NOERR(xs)) { -				PRINTF("%s: ARQ failure for target %d lun %d\n", -				    isp->isp_name, XS_TGT(xs), XS_LUN(xs)); +				PRINTF("%s: ARQ Failure\n", isp->isp_name);  				XS_SETERR(xs, HBA_ARQFAIL);  			}  		} @@ -1389,8 +1340,9 @@ isp_intr(arg)  		}  		ISP_WRITE(isp, INMAILBOX5, optr); -		if (isp->isp_nactive > 0) -		    isp->isp_nactive--; +		isp->isp_nactive--; +		if (isp->isp_nactive < 0) +			isp->isp_nactive = 0;  		complist[ndone++] = xs;	/* defer completion call until later */  	}  	/* @@ -1417,15 +1369,12 @@ isp_intr(arg)  static int  isp_parse_async(isp, mbox)  	struct ispsoftc *isp; -	int mbox; +	u_int16_t mbox;  {  	switch (mbox) {  	case ASYNC_BUS_RESET:  		PRINTF("%s: SCSI bus reset detected\n", isp->isp_name);  		isp->isp_sendmarker = 1; -#ifdef	ISP_TARGET_MODE -		isp_notify_ack(isp, NULL); -#endif  		break;  	case ASYNC_SYSTEM_ERROR: @@ -1452,16 +1401,10 @@ isp_parse_async(isp, mbox)  	case ASYNC_TIMEOUT_RESET:  		PRINTF("%s: timeout initiated SCSI bus reset\n", isp->isp_name);  		isp->isp_sendmarker = 1; -#ifdef	ISP_TARGET_MODE -		isp_notify_ack(isp, NULL); -#endif  		break; -	case ASYNC_DEVICE_RESET: -		PRINTF("%s: device reset\n", isp->isp_name); -#ifdef	ISP_TARGET_MODE -		isp_notify_ack(isp, NULL); -#endif +	case ASYNC_UNSPEC_TMODE: +		PRINTF("%s: mystery async target completion\n", isp->isp_name);  		break;  	case ASYNC_EXTMSG_UNDERRUN: @@ -1497,7 +1440,6 @@ isp_parse_async(isp, mbox)  		break;  	case ASYNC_CTIO_DONE: -		/* Should only occur when Fast Posting Set for 2100s */  		PRINTF("%s: CTIO done\n", isp->isp_name);  		break; @@ -1515,9 +1457,6 @@ isp_parse_async(isp, mbox)  	case ASYNC_LOOP_RESET:  		PRINTF("%s: Loop RESET\n", isp->isp_name); -#ifdef	ISP_TARGET_MODE -		isp_notify_ack(isp, NULL); -#endif  		break;  	case ASYNC_PDB_CHANGED: @@ -1544,122 +1483,62 @@ isp_handle_other_response(isp, sp, optrp)  	u_int8_t iptr, optr;  	int reqsize = 0;  	void *ireqp = NULL; -#ifdef	ISP_TARGET_MODE -	union { -		at_entry_t	*atio; -		at2_entry_t	*at2io; -		ct_entry_t	*ctio; -		ct2_entry_t	*ct2io; -		lun_entry_t	*lunen; -		in_entry_t	*inot; -		in_fcentry_t	*inot_fc; -		na_entry_t	*nack; -		na_fcentry_t	*nack_fc; -		void            *voidp; -#define	atio	un.atio -#define	at2io	un.at2io -#define	ctio	un.ctio -#define	ct2io	un.ct2io -#define	lunen	un.lunen -#define	inot	un.inot -#define	inot_fc	un.inot_fc -#define	nack	un.nack -#define	nack_fc	un.nack_fc -	} un; - -	un.voidp = sp; -#endif -  	switch (sp->req_header.rqs_entry_type) {  	case RQSTYPE_REQUEST:  		return (-1); -#ifdef	ISP_TARGET_MODE +#if	defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)  	case RQSTYPE_NOTIFY_ACK:  	{ -		static const char *f = -			"%s: Notify Ack Status 0x%x Sequence Id 0x%x\n" -		/* -		 * The ISP is acknowleding our ack of an Immediate Notify. -		 */ -		if (isp->isp_type & ISP_HA_FC) { -			PRINTF(f, isp->isp_name, -			    nack_fc->na-status, nack_fc->na_seqid); -		} else { -			PRINTF(f, isp->isp_name, -			    nack->na_status, nack->na_seqid); -		} +		ispnotify_t *spx = (ispnotify_t *) sp; +		PRINTF("%s: Immediate Notify Ack %d.%d Status 0x%x Sequence " +		    "0x%x\n", isp->isp_name, spx->req_initiator, spx->req_lun, +		    spx->req_status, spx->req_sequence);  		break;  	}  	case RQSTYPE_NOTIFY:  	{ -		u_int16_t seqid, status; - -		/* -		 * Either the ISP received a SCSI message it cannot handle -		 * or some other out of band condition (e.g., Port Logout) -		 * or it is returning an Immediate Notify entry we sent. -		 */ -		if (isp->isp_type & ISP_HA_FC) { -			status = inot_fc->status; -			seqid = inot_fc->in_seqid; -		} else { -			status = inot->status; -			seqid = inot->seqid & 0xff; -		} -		PRINTF("%s: Immediate Notify Status 0x%x Sequence Id 0x%x\n", -		    isp->isp_name, status, seqid); - -		switch (status) { -		case IN_MSG_RECEIVED: -		case IN_IDE_RECEIVED: -			ptisp_got_msg(ptp, &inot); -			break; -		case IN_RSRC_UNAVAIL: -                        PRINTF("%s: Firmware out of ATIOs\n", isp->isp_name); -                        break; -                case IN_ABORT_TASK: -			PRINTF("%s: Abort Task iid %d rx_id 0x%x\n", -			    inot_fc->in_iid, seqid); -                        break; -                case IN_PORT_LOGOUT: -			PRINTF("%s: Port Logout for Initiator %d\n", -			    isp->isp_name, inot_fc->in_iid); -                        break; -                default: -			PRINTF("%s: bad status (0x%x) in Immediate Notify\n", -                            isp->isp_name, status); -                        break; - -		} -		isp_notify_ack(isp, un.voidp); -		reqsize = 0; +		ispnotify_t *spx = (ispnotify_t *) sp; + +		PRINTF("%s: Notify loopid %d to lun %d req_status 0x%x " +		    "req_task_flags 0x%x seq 0x%x\n", isp->isp_name, 				    spx->req_initiator, spx->req_lun, spx->req_status,  +		    spx->req_task_flags, spx->req_sequence); +		reqsize = sizeof (*spx); +		spx->req_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; +		spx->req_header.rqs_entry_count = 1; +		spx->req_header.rqs_flags = 0; +		spx->req_header.rqs_seqno = isp->isp_seqno++; +		spx->req_handle = (spx->req_initiator<<16) | RQSTYPE_NOTIFY_ACK; +		if (spx->req_status == IN_RSRC_UNAVAIL) +			spx->req_flags = LUN_INCR_CMD; +		else if (spx->req_status == IN_NOCAP) +			spx->req_flags = LUN_INCR_IMMED; +		else { +			reqsize = 0; +		} +		ireqp = spx;  		break;  	}  	case RQSTYPE_ENABLE_LUN: -	case RQSTYPE_MODIFY_LUN: -		if (lunen->req_status != 1) { -		    PRINTF("%s: ENABLE/MODIFY LUN returned status 0x%x\n", -			isp->isp_name, lunen->req_status); +	{ +		isplun_t *ip = (isplun_t *) sp; +		if (ip->req_status != 1) { +		    PRINTF("%s: ENABLE LUN returned status 0x%x\n", +			isp->isp_name, ip->req_status);  		}  		break; +	}  	case RQSTYPE_ATIO2:  	{  		fcparam *fcp = isp->isp_param;  		ispctiot2_t local, *ct2 = NULL;  		ispatiot2_t *at2 = (ispatiot2_t *) sp; -		int s, lun; +		int s; -#ifdef	SCCLUN -		lun = at2->req_scclun; -#else -		lun = at2->req_lun; -#endif -		PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags0x%x " -		    "tflags0x%x ecodes0x%x rqstatus0x%x\n", isp->isp_name, -		    at2->req_initiator, lun, at2->req_rxid, -		    at2->req_flags, at2->req_taskflags, at2->req_execodes, -		    at2->req_status); +		PRINTF("%s: atio2 loopid %d for lun %d rxid 0x%x flags 0x%x " +		    "task flags 0x%x exec codes 0x%x\n", isp->isp_name, +		    at2->req_initiator, at2->req_lun, at2->req_rxid, +		    at2->req_flags, at2->req_taskflags, at2->req_execodes);  		switch (at2->req_status & ~ATIO_SENSEVALID) {  		case ATIO_PATH_INVALID: @@ -1692,15 +1571,13 @@ isp_handle_other_response(isp, sp, optrp)  		}  		PRINTF("%s: datalen %d cdb0=0x%x\n", isp->isp_name,  		    at2->req_datalen, at2->req_cdb[0]); -		MEMZERO((void *) ct2, sizeof (*ct2)); +		bzero ((void *) ct2, sizeof (*ct2));  		ct2->req_header.rqs_entry_type = RQSTYPE_CTIO2;  		ct2->req_header.rqs_entry_count = 1;  		ct2->req_header.rqs_flags = 0;  		ct2->req_header.rqs_seqno = isp->isp_seqno++; -		ct2->req_handle = (at2->req_initiator << 16) | lun; -#ifndef	SCCLUN -		ct2->req_lun = lun; -#endif +		ct2->req_handle = (at2->req_initiator << 16) | at2->req_lun; +		ct2->req_lun = at2->req_lun;  		ct2->req_initiator = at2->req_initiator;  		ct2->req_rxid = at2->req_rxid; @@ -1718,16 +1595,16 @@ isp_handle_other_response(isp, sp, optrp)  			ct2->req_seg_count = 1;  			if (at2->req_cdb[0] == 0x12) {  				s = sizeof(tgtiqd); -				MEMCPY(fcp->isp_scratch, tgtiqd, s); +				bcopy((void *)tgtiqd, fcp->isp_scratch, s);  			} else {  				s = at2->req_datalen; -				MEMZERO(fcp->isp_scratch, s); +				bzero(fcp->isp_scratch, s);  			}  			ct2->req_m.mode0.req_dataseg[0].ds_base =  			    fcp->isp_scdma;  			ct2->req_m.mode0.req_dataseg[0].ds_count = s;  			ct2->req_m.mode0.req_datalen = s; -#if	1 +#if	0  			if (at2->req_datalen < s) {  				ct2->req_m.mode1.req_scsi_status |=  				    CTIO2_RESP_VALID|CTIO2_RSPOVERUN; @@ -1741,7 +1618,7 @@ isp_handle_other_response(isp, sp, optrp)  		default:		/* ALL OTHERS */  			ct2->req_flags |= CTIO_NODATA | CTIO2_SMODE1;  			ct2->req_m.mode1.req_scsi_status = 0; -#if	1 +#if	0  			if (at2->req_datalen) {  				ct2->req_m.mode1.req_scsi_status |=  				    CTIO2_RSPUNDERUN; @@ -1773,8 +1650,9 @@ isp_handle_other_response(isp, sp, optrp)  				ct2->req_m.mode1.req_sense_len = 18;  				ct2->req_m.mode1.req_scsi_status |=  				    at2->req_scsi_status; -				MEMCPY(ct2->req_m.mode1.req_response, -				    at2->req_sense, sizeof (at2->req_sense)); +				bcopy((void *)at2->req_sense, +				    (void *)ct2->req_m.mode1.req_response, +				    sizeof (at2->req_sense));  			}  			break;  		} @@ -1801,15 +1679,6 @@ isp_handle_other_response(isp, sp, optrp)  		ireqp = at2;  		break;  	} -#undef	atio -#undef	at2io -#undef	ctio -#undef	ct2io -#undef	lunen -#undef	inot -#undef	inot_fc -#undef	nack -#undef	nack_fc  #endif  	default:  		PRINTF("%s: other response type %x\n", isp->isp_name, @@ -1826,7 +1695,7 @@ isp_handle_other_response(isp, sp, optrp)  			PRINTF("%s: Request Queue Overflow other response\n",  			    isp->isp_name);  		} else { -			MEMCPY(reqp, ireqp, reqsize); +			bcopy(ireqp, reqp, reqsize);  			ISP_WRITE(isp, INMAILBOX4, iptr);  			isp->isp_reqidx = iptr;  		} @@ -1834,37 +1703,7 @@ isp_handle_other_response(isp, sp, optrp)  	return (0);  } -#ifdef	ISP_TARGET_MODE - -static void isp_tmd_newcmd_dflt __P((void *, tmd_cmd_t *)); -static void isp_tmd_event_dflt __P((void *, int)); -static void isp_tmd_notify_dflt __P((void *, tmd_notify_t *)); - -static void isp_tgt_data_xfer __P ((tmd_cmd_t *)); -static void isp_tgt_endcmd __P ((tmd_cmd_t *, u_int8_t)); -static void isp_tgt_done __P ((tmd_cmd_t *)); - -static void -isp_tmd_newcmd_dflt(arg0, cmdp) -	void *arg0; -	tmd_cmd_t *cmdp; -{ -} - -static void -isp_tmd_event_dflt(arg0, event) -	void *arg0; -	int event; -{ -} - -static void -isp_tmd_notify_dflt(arg0, npt) -	void *arg0; -	tmd_notify_t *npt; -{ -} - +#if	defined(ISP2100_TARGET_MODE) || defined(ISP_TARGET_MODE)  /*   * Locks held, and ints disabled (if FC).   * @@ -1890,14 +1729,13 @@ isp_modify_lun(isp, lun, icnt, ccnt)  		return (-1);  	} -	MEMZERO((void *) ip, sizeof (*ip)); +	bzero((void *) ip, sizeof (*ip));  	ip->req_header.rqs_entry_type = RQSTYPE_ENABLE_LUN;  	ip->req_header.rqs_entry_count = 1; +	ip->req_header.rqs_flags = 0;  	ip->req_header.rqs_seqno = isp->isp_seqno++;  	ip->req_handle = RQSTYPE_ENABLE_LUN; -	if (isp->isp_type & ISP_HA_SCSI) { -		ip->req_lun = lun; -	} +	ip->req_lun = lun;  	ip->req_cmdcount = ccnt;  	ip->req_imcount = icnt;  	ip->req_timeout = 0;	/* default 30 seconds */ @@ -1905,263 +1743,6 @@ isp_modify_lun(isp, lun, icnt, ccnt)  	isp->isp_reqidx = iptr;  	return (0);  } - -static void -isp_notify_ack(isp, ptrp) -	struct ispsoftc *isp; -	void *ptrp; -{ -	void *reqp; -	u_int8_t iptr, optr; -	union { -		na_fcentry_t _naf; -		na_entry_t _nas; -	} un; - -	MEMZERO((caddr_t)&un, sizeof (un)); -	un._nas.na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; -	un._nas.na_header.rqs_entry_count = 1; - -	if (isp->isp_type & ISP_HA_FC) { -		na_fcentry_t *na = &un._nas; -		if (ptrp) { -			in_fcentry_t *inp = ptrp; -			na->na_iid = inp->in_iid; -			na->na_lun = inp->in_lun; -			na->na_task_flags = inp->in_task_flags; -			na->na_seqid = inp->in_seqid; -			na->na_status = inp->in_status; -		} else { -			na->na_flags = NAFC_RST_CLRD; -		} -	} else { -		na_entry_t *na = &un._nas; -		if (ptrp) { -			in_entry_t *inp = ptrp; -			na->na_iid = inp->in_iid; -			na->na_lun = inp->in_lun; -			na->na_tgt = inp->in_tgt; -			na->na_seqid = inp->in_seqid; -		} else { -			na->na_flags = NA_RST_CLRD; -		} -	} -	optr = isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); -	iptr = isp->isp_reqidx; -	reqp = (void *) ISP_QUEUE_ENTRY(isp->isp_rquest, iptr); -	iptr = ISP_NXT_QENTRY(iptr, RQUEST_QUEUE_LEN); -	if (iptr == optr) { -		PRINTF("%s: Request Queue Overflow For isp_notify_ack\n", -		    isp->isp_name); -	} else { -		MEMCPY(reqp, ireqp, sizeof (un)); -		ISP_WRITE(isp, INMAILBOX4, iptr); -		isp->isp_reqidx = iptr; -	} -} - -/* - * These are dummy stubs for now until the outside framework is plugged in. - */ - -static void -isp_handle_atio (isp, aep) -	struct ispsoftc *isp; -	at_entry_t *aep; -{ -	int status, connected; -	tmd_cmd_t local, *cdp = &local; - -	/* -	 * Get the ATIO status and see if we're still connected. -	 */ -	status = aep->at_status; -	connected = ((aep->at_flags & AT_NODISC) != 0); - -	PRINTF("%s: ATIO status=0x%x, connected=%d\n", isp->isp_name, -	    status, connected); - -	/* -	 * The firmware status (except for the SenseValid bit) indicates -	 * why this ATIO was sent to us. -	 * If SenseValid is set, the firware has recommended Sense Data. -	 * If the Disconnects Disabled bit is set in the flags field, -	 * we're still connected on the SCSI bus - i.e. the initiator -	 * did not set DiscPriv in the identify message. We don't care -	 * about this so it's ignored. -	 */ -	switch(status & ~TGTSVALID) { -	case AT_PATH_INVALID: -		/* -		 * ATIO rejected by the firmware due to disabled lun. -		 */ -		PRINTF("%s: Firmware rejected ATIO for disabled lun %d\n", -		    isp->isp_name, aep->at_lun); -		break; - -	case AT_PHASE_ERROR: -		/* -		 * Bus Pase Sequence error. -		 * -		 * The firmware should have filled in the correct -		 * sense data. -		 */ - - -		if (status & TGTSVALID) { -			MEMCPY(&cdp->cd_sensedata, aep->at_sense, -			    sizeof (cdp->cd_sensedata)); -			PRINTF("%s: Bus Phase Sequence error key 0x%x\n", -			    isp->isp_name, cdp->cd_sensedata[2] & 0xf); -		} else { -			PRINTF("%s: Bus Phase Sequence With No Sense\n", -			    isp->isp_name); -		} -		(*isp->isp_tmd_newcmd)(isp, cdp); -		break; - -	case AT_NOCAP: -		/* -		 * Requested Capability not available -		 * We sent an ATIO that overflowed the firmware's -		 * command resource count. -		 */ -		PRINTF("%s: Firmware rejected ATIO, command count overflow\n", -		    isp->isp_name); -		break; - -	case AT_BDR_MSG: -		/* -		 * If we send an ATIO to the firmware to increment -		 * its command resource count, and the firmware is -		 * recovering from a Bus Device Reset, it returns -		 * the ATIO with this status. -		 */ -		PRINTF("%s: ATIO returned with BDR received\n", isp->isp_name); -		break; - -	case AT_CDB: -		/* -		 * New CDB -		 */ -		cdp->cd_hba = isp; -		cdp->cd_iid = aep->at_iid; -		cdp->cd_tgt = aep->at_tgt; -		cdp->cd_lun = aep->at_lun; -		cdp->cd_tagtype = aep->at_tag_type; -		cdp->cd_tagval = aep->at_tag_val; -		MEMCPY(cdp->cd_cdb, aep->at_cdb, 16); -		PRINTF("%s: CDB 0x%x itl %d/%d/%d\n", isp->isp_name, -		    cdp->cd_cdb[0], cdp->cd_iid, cdp->cd_tgt, cdp->cd_lun); -		(*isp->isp_tmd_newcmd)(isp, cdp); -		break; - -	default: -		PRINTF("%s: Unknown status (0x%x) in ATIO\n", -		    isp->isp_name, status); -		cdp->cd_hba = isp; -		cdp->cd_iid = aep->at_iid; -		cdp->cd_tgt = aep->at_tgt; -		cdp->cd_lun = aep->at_lun; -		cdp->cd_tagtype = aep->at_tag_type; -		cdp->cd_tagval = aep->at_tag_val; -		isp_tgtcmd_done(cdp); -		break; -	} -} - -static void -isp_handle_atio2(isp, aep) -	struct ispsoftc *isp; -	at2_entry_t *aep; -{ -	int status; -	tmd_cmd_t local, *cdp = &local; - -	/* -	 * Get the ATIO2 status. -	 */ -	status = aep->at_status; -	PRINTD("%s: ATIO2 status=0x%x\n", status); - -	/* -	 * The firmware status (except for the SenseValid bit) indicates -	 * why this ATIO was sent to us. -	 * If SenseValid is set, the firware has recommended Sense Data. -	 */ -	switch(status & ~TGTSVALID) { -	case AT_PATH_INVALID: -		/* -		 * ATIO rejected by the firmware due to disabled lun. -		 */ -		PRINTF("%s: Firmware rejected ATIO2 for disabled lun %d\n", -		    isp->isp_name, aep->at_lun); -		break; - -	case AT_NOCAP: -		/* -		 * Requested Capability not available -		 * We sent an ATIO that overflowed the firmware's -		 * command resource count. -		 */ -		PRINTF("%s: Firmware rejected ATIO2, command count overflow\n", -		    isp->isp_name); -		break; - -	case AT_BDR_MSG: -		/* -		 * If we send an ATIO to the firmware to increment -		 * its command resource count, and the firmware is -		 * recovering from a Bus Device Reset, it returns -		 * the ATIO with this status. -		 */ -		PRINTF("%s: ATIO2 returned with BDR rcvd\n", isp->isp_name); -		break; - -	case AT_CDB: -		/* -		 * New CDB -		 */ -		cdp->cd_hba = isp; -		cdp->cd_iid = aep->at_iid; -		cdp->cd_tgt = 0; -		cdp->cd_lun = aep->at_lun; -		MEMCPY(cdp->cd_cdb, aep->at_cdb, 16); -		cdp->cd_rxid = aep->at_rxid; -		cdp->cp_origdlen = aep->at_datalen; -		cdp->cp_totbytes = 0; -		PRINTF("%s: CDB 0x%x rx_id 0x%x itl %d/%d/%d dlen %d\n", -		    isp->isp_name, cdp->cd_cdb[0], cdp->cd_tagval, cdp->cd_iid, -		    cdp->cd_tgt, cdp->cd_lun, aep->at_datalen); -		(*isp->isp_tmd_newcmd)(isp, cdp); -		break; - -	default: -		PRINTF("%s: Unknown status (0x%x) in ATIO2\n", -		    isp->isp_name, status); -		cdp->cd_hba = isp; -		cdp->cd_iid = aep->at_iid; -		cdp->cd_tgt = aep->at_tgt; -		cdp->cd_lun = aep->at_lun; -		cdp->cp_rxid = aep->at_rxid; -		isp_tgtcmd_done(cdp); -		break; -	} -} - -static void -isp_handle_ctio(isp, cep) -	struct ispsoftc *isp; -	ct_entry_t *aep; -{ -} - -static void -isp_handle_ctio2(isp, cep) -	struct ispsoftc *isp; -	at2_entry_t *aep; -{ -}  #endif  static void @@ -2288,7 +1869,7 @@ isp_parse_status(isp, sp, xs)  		break;  	case RQCS_UNEXP_BUS_FREE: -		PRINTF("%s: target %d lun %d had an unexpected bus free\n", +		PRINTF("%s: target %d lun %d had unexeptected bus free\n",  		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));  		break; @@ -2323,17 +1904,8 @@ isp_parse_status(isp, sp, xs)  		break;  	case RQCS_QUEUE_FULL: -		PRINTF("%s: internal queues full for target %d lun %d " -		    "status 0x%x\n", isp->isp_name, XS_TGT(xs), XS_LUN(xs), -		    XS_STS(xs)); -		/* -		 * If QFULL or some other status byte is set, then this -		 * isn't an error, per se. -		 */ -		if (XS_STS(xs) != 0) { -			XS_SETERR(xs, HBA_NOERROR); -			return; -		} +		PRINTF("%s: internal queues full for target %d lun %d\n", +		    isp->isp_name, XS_TGT(xs), XS_LUN(xs));  		break;  	case RQCS_PHASE_SKIPPED: @@ -2556,29 +2128,6 @@ isp_mboxcmd(isp, mbp)  	} -	/* -	 * Check for variants -	 */ -#ifdef	SCCLUN -	if (isp->isp_type & ISP_HA_FC) { -		switch (mbp->param[0]) { -		case MBOX_ABORT: -			inparam = 7; -			break; -		case MBOX_ABORT_DEVICE: -		case MBOX_START_QUEUE: -		case MBOX_STOP_QUEUE: -		case MBOX_SINGLE_STEP_QUEUE: -		case MBOX_ABORT_QUEUE: -		case MBOX_GET_DEV_QUEUE_STATUS: -			inparam = 3; -			break; -		default: -			break; -		} -	} -#endif -  command_known:  	/* @@ -2597,7 +2146,7 @@ command_known:  			    isp->isp_name, ISP_READ(isp, BIU_ISR));  			if (ISP_READ(isp, BIU_SEMA) & 1) {  				u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); -				if (isp_parse_async(isp, (int) mbox)) +				if (isp_parse_async(isp, mbox))  					return;  				ISP_WRITE(isp, BIU_SEMA, 0);  			} @@ -2726,13 +2275,8 @@ command_known:  		    isp->isp_name, opcode);  		break; -	/* -	 * Be silent about these... -	 */ -  	case ASYNC_LOOP_UP:  	case ASYNC_LIP_OCCURRED: -	case ASYNC_PDB_CHANGED:  		break;  	default: @@ -2850,7 +2394,6 @@ again:  		isp_mboxcmd(isp, &mbs);  		if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {  			if (mbs.param[0] == ASYNC_LIP_OCCURRED || -			    mbs.param[0] == ASYNC_PDB_CHANGED ||  			    mbs.param[0] == ASYNC_LOOP_UP) {  				if (once++ < 2) {  					goto again; @@ -3106,14 +2649,59 @@ isp_restart(isp)  		if (XS_NULL(xs)) {  			continue;  		} -		if (isp->isp_nactive > 0) -		    isp->isp_nactive--; +		isp->isp_nactive--; +		if (isp->isp_nactive < 0) { +			isp->isp_nactive = 0; +		}  		XS_RESID(xs) = XS_XFRLEN(xs);  		XS_SETERR(xs, HBA_BUSRESET);  		XS_CMD_DONE(xs);  	}  } +void +isp_watch(arg) +	void *arg; +{ +	int i; +	struct ispsoftc *isp = arg; +	ISP_SCSI_XFER_T *xs; +	ISP_LOCKVAL_DECL; + +	/* +	 * Look for completely dead commands (but not polled ones). +	 */ +	ISP_ILOCK(isp); +	for (i = 0; i < RQUEST_QUEUE_LEN; i++) { +		if ((xs = (ISP_SCSI_XFER_T *) isp->isp_xflist[i]) == NULL) { +			continue; +		} +		if (XS_TIME(xs) == 0) { +			continue; +		} +		XS_TIME(xs) -= (WATCH_INTERVAL * 1000); +		/* +		 * Avoid later thinking that this +		 * transaction is not being timed. +		 * Then give ourselves to watchdog +		 * periods of grace. +		 */ +		if (XS_TIME(xs) == 0) +			XS_TIME(xs) = 1; +		else if (XS_TIME(xs) > -(2 * WATCH_INTERVAL * 1000)) { +			continue; +		} +		if (isp_control(isp, ISPCTL_ABORT_CMD, xs)) { +			PRINTF("%s: isp_watch failed to abort command\n", +			    isp->isp_name); +			isp_restart(isp); +			break; +		} +	} +	ISP_IUNLOCK(isp); +	RESTART_WATCHDOG(isp_watch, isp); +} +  /*   * Miscellaneous debug statements.   */ @@ -3159,7 +2747,7 @@ isp_prtstst(sp)  static char *  isp2100_fw_statename(state) -	int state; +	u_int8_t state;  {  	switch(state) {  	case FW_CONFIG_WAIT:	return "Config Wait"; @@ -3232,9 +2820,9 @@ isp_read_nvram(isp)  	if (isp->isp_type & ISP_HA_SCSI) {  		sdparam *sdp = (sdparam *) isp->isp_param; +		/* XXX CHECK THIS FOR SANITY XXX */  		sdp->isp_fifo_threshold = -			ISP_NVRAM_FIFO_THRESHOLD(nvram_data) | -			(ISP_NVRAM_FIFO_THRESHOLD_128(nvram_data) << 2); +			ISP_NVRAM_FIFO_THRESHOLD(nvram_data);  		sdp->isp_initiator_id =  			ISP_NVRAM_INITIATOR_ID(nvram_data); @@ -3276,6 +2864,8 @@ isp_read_nvram(isp)  		sdp->isp_tag_aging =  			ISP_NVRAM_TAG_AGE_LIMIT(nvram_data); +		/* XXX ISP_NVRAM_FIFO_THRESHOLD_128 XXX */ +  		sdp->isp_selection_timeout =  			ISP_NVRAM_SELECTION_TIMEOUT(nvram_data); @@ -3284,12 +2874,6 @@ isp_read_nvram(isp)  		sdp->isp_fast_mttr = ISP_NVRAM_FAST_MTTR_ENABLE(nvram_data); -#if	0 -		PRINTF("%s: fifo_threshold = 0x%x cbena%d dbena%d\n", -		    isp->isp_name, sdp->isp_fifo_threshold, -		    sdp->isp_cmd_dma_burst_enable, -		    sdp->isp_data_dma_burst_enabl); -#endif  		for (i = 0; i < 16; i++) {  			sdp->isp_devparam[i].dev_enable =  				ISP_NVRAM_TGT_DEVICE_ENABLE(nvram_data, i); @@ -3364,9 +2948,8 @@ isp_read_nvram(isp)  		fcp->isp_wwn = wwnstore.full64;  		wwnstore.full64 = ISP2100_NVRAM_BOOT_NODE_NAME(nvram_data);  		if (wwnstore.full64 != 0) { -			PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", -			    isp->isp_name, wwnstore.wds.hi32, -			    wwnstore.wds.lo32); +			PRINTF("%s: BOOT DEVICE WWN 0x%08x%08x\n", isp->isp_name, +			    wwnstore.wds.hi32, wwnstore.wds.lo32);  		}  		fcp->isp_maxalloc =  			ISP2100_NVRAM_MAXIOCBALLOCATION(nvram_data); | 
