printf ("Phase mismatch: REQ not asserted! %02x dsp %x\n",
printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n",
ssh_checkintr(sc, istat, dstat, sstat0, status)	struct   ssh_softc *sc;	u_char   istat;	u_char   dstat;	u_char   sstat0;	int   *status;{	ssh_regmap_p rp = sc->sc_sshp;	struct ssh_acb *acb = sc->sc_nexus;	int   target;	int   dfifo, dbc, sstat1;	dfifo = rp->ssh_dfifo;	dbc = rp->ssh_dbc0;	sstat1 = rp->ssh_sstat1;	rp->ssh_ctest8 |= SSH_CTEST8_CLF;	while ((rp->ssh_ctest1 & SSH_CTEST1_FMT) != SSH_CTEST1_FMT)		;	rp->ssh_ctest8 &= ~SSH_CTEST8_CLF;#ifdef DEBUG	++sshints;#if 0	if (ssh_debug & 0x100) {		DCIAS(&acb->stat[0]);	/* XXX */		printf ("sshchkintr: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",				  istat, dstat, sstat0, rp->ssh_dsps, rp->ssh_sbcl, acb->stat[0], acb->msg[0]);		printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",				  acb->msg[0], acb->msg[1], acb->msg[2],				  acb->msg[3], acb->msg[4], acb->msg[5]);	}#endif	if (rp->ssh_dsp && (rp->ssh_dsp < sc->sc_scriptspa ||								rp->ssh_dsp >= sc->sc_scriptspa + sizeof(scripts))) {		printf ("%s: dsp not within script dsp %x scripts %x:%x",				  sc->sc_dev.dv_xname, rp->ssh_dsp, sc->sc_scriptspa,				  sc->sc_scriptspa + sizeof(scripts));		printf(" istat %x dstat %x sstat0 %x\n",				 istat, dstat, sstat0);		Debugger();	}#endif	SSH_TRACE('i',dstat,istat,(istat&SSH_ISTAT_DIP)?rp->ssh_dsps&0xff:sstat0);	if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff00) {		/* Normal completion status, or check condition */#ifdef DEBUG		if (rp->ssh_dsa != kvtop(&acb->ds)) {			printf ("ssh: invalid dsa: %x %x\n", rp->ssh_dsa,					  kvtop(&acb->ds));			panic("*** ssh DSA invalid ***");		}#endif		target = acb->xs->sc_link->target;		if (sc->sc_sync[target].state == SYNC_SENT) {#ifdef DEBUG			if (sshsync_debug)				printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",						  acb->msg[0], acb->msg[1], acb->msg[2],						  acb->msg[3], acb->msg[4], acb->msg[5]);#endif			if (acb->msg[1] == 0xff)				printf ("%s: target %d ignored sync request\n",						  sc->sc_dev.dv_xname, target);			else if (acb->msg[1] == MSG_REJECT)				printf ("%s: target %d rejected sync request\n",						  sc->sc_dev.dv_xname, target);			sc->sc_sync[target].state = SYNC_DONE;			sc->sc_sync[target].sxfer = 0;			sc->sc_sync[target].sbcl = 0;			if (acb->msg[2] == 3 &&				 acb->msg[3] == MSG_SYNC_REQ &&				 acb->msg[5] != 0) {#ifdef MAXTOR_KLUDGE				/*				 * Kludge for my Maxtor XT8580S				 * It accepts whatever we request, even				 * though it won't work.  So we ask for				 * a short period than we can handle.  If				 * the device says it can do it, use 208ns.				 * If the device says it can do less than				 * 100ns, then we limit it to 100ns.				 */				if (acb->msg[4] && acb->msg[4] < 100 / 4) {#ifdef DEBUG					printf ("%d: target %d wanted %dns period\n",							  sc->sc_dev.dv_xname, target,							  acb->msg[4] * 4);#endif					if (acb->msg[4] == 50 / 4)						acb->msg[4] = 208 / 4;					else						acb->msg[4]	= 100 / 4;				}#endif /* MAXTOR_KLUDGE */				printf ("%s: target %d now synchronous, period=%dns, offset=%d\n",						  sc->sc_dev.dv_xname, target,						  acb->msg[4] * 4, acb->msg[5]);				scsi_period_to_ssh (sc, target);			}		}		dma_cachectl(&acb->stat[0], 1);		*status = acb->stat[0];#ifdef DEBUG		if (rp->ssh_sbcl & SSH_BSY) {			/*printf ("ACK! ssh was busy at end: rp %x script %x dsa %x\n",				 rp, &scripts, &acb->ds);*/#ifdef DDB			/*Debugger();*/#endif		}		if (acb->msg[0] != 0x00)			printf("%s: message was not COMMAND COMPLETE: %x\n",					 sc->sc_dev.dv_xname, acb->msg[0]);#endif		if (sc->nexus_list.tqh_first)			rp->ssh_dcntl |= SSH_DCNTL_STD;		return 1;	}	if (sstat0 & SSH_SSTAT0_M_A) {		/* Phase mismatch */#ifdef DEBUG		++sshphmm;		if (acb == NULL)			printf("%s: Phase mismatch with no active command?\n",					 sc->sc_dev.dv_xname);#endif		if (acb->iob_len) {			int adjust;			adjust = ((dfifo - (dbc & 0x7f)) & 0x7f);			if (sstat1 & SSH_SSTAT1_ORF)				++adjust;			if (sstat1 & SSH_SSTAT1_OLF)				++adjust;			acb->iob_curlen = *((long *)&rp->ssh_dcmd) & 0xffffff;			acb->iob_curlen += adjust;			acb->iob_curbuf = *((long *)&rp->ssh_dnad) - adjust;#ifdef DEBUG			if (ssh_debug & 0x100) {				int i;				printf ("Phase mismatch: curbuf %x curlen %x dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %x\n",						  acb->iob_curbuf, acb->iob_curlen, dfifo,						  dbc, sstat1, adjust, rp->ssh_sbcl, sshstarts, acb);				if (acb->ds.chain[1].datalen) {					for (i = 0; acb->ds.chain[i].datalen; ++i)						printf("chain[%d] addr %x len %x\n",								 i, acb->ds.chain[i].databuf,								 acb->ds.chain[i].datalen);				}			}#endif			dma_cachectl ((caddr_t)acb, sizeof(*acb));		}#ifdef DEBUG		SSH_TRACE('m',rp->ssh_sbcl,(rp->ssh_dsp>>8),rp->ssh_dsp);		if (ssh_debug & 9)			printf ("Phase mismatch: %x dsp +%x dcmd %x\n",					  rp->ssh_sbcl,					  rp->ssh_dsp - sc->sc_scriptspa,					  *((long *)&rp->ssh_dcmd));#endif		if ((rp->ssh_sbcl & SSH_REQ) == 0) {			printf ("Phase mismatch: REQ not asserted! %02x dsp %x\n",					  rp->ssh_sbcl, rp->ssh_dsp);#ifdef DEBUG			Debugger();#endif		}		switch (rp->ssh_sbcl & 7) {			case 0:		/* data out */			case 1:		/* data in */			case 2:		/* status */			case 3:		/* command */			case 6:		/* message in */			case 7:		/* message out */				rp->ssh_dsp = sc->sc_scriptspa + Ent_switch;				break;			default:				goto bad_phase;		}		return 0;	}	if (sstat0 & SSH_SSTAT0_STO) {		/* Select timed out */#ifdef DEBUG		if (acb == NULL)			printf("%s: Select timeout with no active command?\n",					 sc->sc_dev.dv_xname);		if (rp->ssh_sbcl & SSH_BSY) {			printf ("ACK! ssh was busy at timeout: rp %x script %x dsa %x\n",					  rp, &scripts, &acb->ds);			printf(" sbcl %x sdid %x istat %x dstat %x sstat0 %x\n",					 rp->ssh_sbcl, rp->ssh_sdid, istat, dstat, sstat0);			if (!(rp->ssh_sbcl & SSH_BSY)) {				printf ("Yikes, it's not busy now!\n");#if 0				*status = -1;				if (sc->nexus_list.tqh_first)					rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;				return 1;#endif			}/*			rp->ssh_dcntl |= SSH_DCNTL_STD;*/			return (0);#ifdef DDB			Debugger();#endif		}#endif		*status = -1;		acb->xs->error = XS_SELTIMEOUT;		if (sc->nexus_list.tqh_first)			rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;		return 1;	}	if (acb)		target = acb->xs->sc_link->target;	else		target = 7;	if (sstat0 & SSH_SSTAT0_UDC) {#ifdef DEBUG		if (acb == NULL)			printf("%s: Unexpected disconnect with no active command?\n",					 sc->sc_dev.dv_xname);		printf ("%s: target %d disconnected unexpectedly\n",				  sc->sc_dev.dv_xname, target);#endif#if 0		sshabort (sc, rp, "sshchkintr");#endif		*status = STS_BUSY;		if (sc->nexus_list.tqh_first)			rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;		return 1;	}	if (dstat & SSH_DSTAT_SIR && (rp->ssh_dsps == 0xff01 ||											 rp->ssh_dsps == 0xff02)) {#ifdef DEBUG		if (ssh_debug & 0x100)			printf ("%s: ID %02x disconnected TEMP %x (+%x) curbuf %x curlen %x buf %x len %x dfifo %x dbc %x sstat1 %x starts %d acb %x\n",					  sc->sc_dev.dv_xname, 1 << target, rp->ssh_temp,					  rp->ssh_temp ? rp->ssh_temp - sc->sc_scriptspa : 0,					  acb->iob_curbuf, acb->iob_curlen,					  acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, sshstarts, acb);#endif		if (acb == NULL) {			printf("%s: Disconnect with no active command?\n",					 sc->sc_dev.dv_xname);			return (0);		}		/*		 * XXXX need to update iob_curbuf/iob_curlen to reflect		 * current data transferred.  If device disconnected in		 * the middle of a DMA block, they should already be set		 * by the phase change interrupt.  If the disconnect		 * occurs on a DMA block boundary, we have to figure out		 * which DMA block it was.		 */		if (acb->iob_len && rp->ssh_temp) {			int n = rp->ssh_temp - sc->sc_scriptspa;			if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen)				printf("%s: iob_curbuf/len already set? n %x iob %x/%x chain[0] %x/%x\n",						 sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen,						 acb->ds.chain[0].databuf, acb->ds.chain[0].datalen);			if (n < Ent_datain)				n = (n - Ent_dataout) / 16;			else				n = (n - Ent_datain) / 16;			if (n <= 0 || n >= DMAMAXIO)				printf("TEMP invalid %d\n", n);			else {				acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf;				acb->iob_curlen = acb->ds.chain[n].datalen;			}#ifdef DEBUG			if (ssh_debug & 0x100) {				printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n);				printf(" curbuf %x curlen %x\n", acb->iob_curbuf,						 acb->iob_curlen);			}#endif		}		/*		 * If data transfer was interrupted by disconnect, iob_curbuf		 * and iob_curlen should reflect the point of interruption.		 * Adjust the DMA chain so that the data transfer begins		 * at the appropriate place upon reselection.		 * XXX This should only be done on save data pointer message?		 */		if (acb->iob_curlen) {			int i, j;#ifdef DEBUG			if (ssh_debug & 0x100)				printf ("%s: adjusting DMA chain\n",						  sc->sc_dev.dv_xname);			if (rp->ssh_dsps == 0xff02)				printf ("%s: ID %02x disconnected without Save Data Pointers\n",						  sc->sc_dev.dv_xname, 1 << target);#endif			for (i = 0; i < DMAMAXIO; ++i) {				if (acb->ds.chain[i].datalen == 0)					break;				if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf &&					 acb->iob_curbuf < (long)(acb->ds.chain[i].databuf +													  acb->ds.chain[i].datalen))					break;			}			if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0)				printf("couldn't find saved data pointer\n");#ifdef DEBUG			if (ssh_debug & 0x100)				printf("  chain[0]: %x/%x -> %x/%x\n",						 acb->ds.chain[0].databuf,						 acb->ds.chain[0].datalen,						 acb->iob_curbuf,						 acb->iob_curlen);#endif			acb->ds.chain[0].databuf = (char *)acb->iob_curbuf;			acb->ds.chain[0].datalen = acb->iob_curlen;			for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) {#ifdef DEBUG				if (ssh_debug & 0x100)					printf("  chain[%d]: %x/%x -> %x/%x\n", j,							 acb->ds.chain[j].databuf,							 acb->ds.chain[j].datalen,							 acb->ds.chain[i].databuf,							 acb->ds.chain[i].datalen);#endif				acb->ds.chain[j].databuf = acb->ds.chain[i].databuf;				acb->ds.chain[j].datalen = acb->ds.chain[i].datalen;			}			if (j < DMAMAXIO)				acb->ds.chain[j].datalen = 0;			DCIAS(kvtop((vaddr_t)&acb->ds.chain));		}		++sc->sc_tinfo[target].dconns;		/*		 * add nexus to waiting list		 * clear nexus		 * try to start another command for another target/lun		 */		acb->status = sc->sc_flags & SSH_INTSOFF;		TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);		sc->sc_nexus = NULL;		/* no current device */		/* start script to wait for reselect */		if (sc->sc_nexus == NULL)			rp->ssh_dsp = sc->sc_scriptspa + Ent_wait_reselect;/* XXXX start another command ? */		if (sc->ready_list.tqh_first)			ssh_sched(sc);		return (0);	}	if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff03) {		int reselid = rp->ssh_scratch & 0x7f;		int reselun = rp->ssh_sfbr & 0x07;		sc->sc_sstat1 = rp->ssh_sbcl;	/* XXXX save current SBCL */#ifdef DEBUG		if (ssh_debug & 0x100)			printf ("%s: target ID %02x reselected dsps %x\n",					  sc->sc_dev.dv_xname, reselid,					  rp->ssh_dsps);		if ((rp->ssh_sfbr & 0x80) == 0)			printf("%s: Reselect message in was not identify: %x\n",					 sc->sc_dev.dv_xname, rp->ssh_sfbr);#endif		if (sc->sc_nexus) {#ifdef DEBUG			if (ssh_debug & 0x100)				printf ("%s: reselect ID %02x w/active\n",						  sc->sc_dev.dv_xname, reselid);#endif			TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain);			sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target].lubusy			&= ~(1 << sc->sc_nexus->xs->sc_link->lun);			--sc->sc_active;		}		/*		 * locate acb of reselecting device		 * set sc->sc_nexus to acb		 */		for (acb = sc->nexus_list.tqh_first; acb;			 acb = acb->chain.tqe_next) {			if (reselid != (acb->ds.scsi_addr >> 16) ||				 reselun != (acb->msgout[0] & 0x07))				continue;			TAILQ_REMOVE(&sc->nexus_list, acb, chain);			sc->sc_nexus = acb;			sc->sc_flags |= acb->status;			acb->status = 0;			DCIAS(kvtop((vaddr_t)&acb->stat[0]));			rp->ssh_dsa = kvtop((vaddr_t)&acb->ds);			rp->ssh_sxfer = sc->sc_sync[acb->xs->sc_link->target].sxfer;			rp->ssh_sbcl = sc->sc_sync[acb->xs->sc_link->target].sbcl;			break;		}		if (acb == NULL) {			printf("%s: target ID %02x reselect nexus_list %x\n",					 sc->sc_dev.dv_xname, reselid,					 sc->nexus_list.tqh_first);			panic("unable to find reselecting device");		}		dma_cachectl ((caddr_t)acb, sizeof(*acb));		rp->ssh_temp = 0;		rp->ssh_dcntl |= SSH_DCNTL_STD;		return (0);	}	if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff04) {#ifdef DEBUG		u_short ctest2 = rp->ssh_ctest2;		/* reselect was interrupted (by Sig_P or select) */		if (ssh_debug & 0x100 ||			 (ctest2 & SSH_CTEST2_SIGP) == 0)			printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x 					  sfbr %x istat %x/%x\n", sc->sc_dev.dv_xname, rp->ssh_scntl1,					  ctest2, rp->ssh_sfbr, istat, rp->ssh_istat);#endif		/* XXX assumes it was not select */		if (sc->sc_nexus == NULL) {			printf("%s: reselect interrupted, sc_nexus == NULL\n",					 sc->sc_dev.dv_xname);#if 0			ssh_dump(sc);#ifdef DDB			Debugger();#endif#endif			rp->ssh_dcntl |= SSH_DCNTL_STD;			return (0);		}		target = sc->sc_nexus->xs->sc_link->target;		rp->ssh_temp = 0;		rp->ssh_dsa = kvtop((vaddr_t)&sc->sc_nexus->ds);		rp->ssh_sxfer = sc->sc_sync[target].sxfer;		rp->ssh_sbcl = sc->sc_sync[target].sbcl;		rp->ssh_dsp = sc->sc_scriptspa;		return (0);	}	if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff06) {		if (acb == NULL)			printf("%s: Bad message-in with no active command?\n",					 sc->sc_dev.dv_xname);		/* Unrecognized message in byte */		dma_cachectl (&acb->msg[1],1);		printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n",				  sc->sc_dev.dv_xname, rp->ssh_sfbr, acb->msg[1], rp->ssh_sbcl);		/* what should be done here? */		DCIAS(kvtop((vaddr_t)&acb->msg[1]));		rp->ssh_dsp = sc->sc_scriptspa + Ent_switch;		return (0);	}	if (dstat & SSH_DSTAT_SIR && rp->ssh_dsps == 0xff0a) {		/* Status phase wasn't followed by message in phase? */		printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n",				  sc->sc_dev.dv_xname, rp->ssh_sbcl, rp->ssh_sbdl);		if (rp->ssh_sbcl == 0xa7) {			/* It is now, just continue the script? */			rp->ssh_dcntl |= SSH_DCNTL_STD;			return (0);		}	}	if (sstat0 == 0 && dstat & SSH_DSTAT_SIR) {		dma_cachectl (&acb->stat[0], 1);		dma_cachectl (&acb->msg[0], 1);		printf ("SSH interrupt: %x sts %x msg %x %x sbcl %x\n",				  rp->ssh_dsps, acb->stat[0], acb->msg[0], acb->msg[1],				  rp->ssh_sbcl);		sshreset (sc);		*status = -1;		return 0;	/* sshreset has cleaned up */	}	if (sstat0 & SSH_SSTAT0_SGE)		printf ("SSH: SCSI Gross Error\n");	if (sstat0 & SSH_SSTAT0_PAR)		printf ("SSH: Parity Error\n");	if (dstat & SSH_DSTAT_IID)		printf ("SSH: Invalid instruction detected\n");	bad_phase:	/*	 * temporary panic for unhandled conditions	 * displays various things about the 53C710 status and registers	 * then panics.	 * XXXX need to clean this up to print out the info, reset, and continue	 */	printf ("sshchkintr: target %x ds %x\n", target, &acb->ds);	printf ("scripts %x ds %x rp %x dsp %x dcmd %x\n", sc->sc_scriptspa,	  kvtop((vaddr_t)&acb->ds), kvtop((vaddr_t)rp), rp->ssh_dsp,	  *((long *)&rp->ssh_dcmd));	printf ("sshchkintr: istat %x dstat %x sstat0 %x dsps %x "			  "dsa %x sbcl %x sts %x msg %x %x sfbr %x\n",			  istat, dstat, sstat0, rp->ssh_dsps, rp->ssh_dsa,			  rp->ssh_sbcl, acb->stat[0], acb->msg[0], acb->msg[1],			  rp->ssh_sfbr);#ifdef DEBUG	if (ssh_debug & 0x20)		panic("sshchkintr: **** temp ****");#ifdef DDB	/* Debugger(); */#endif#endif	sshreset (sc);		/* hard reset */	*status = -1;	return 0;		/* sshreset cleaned up */}