plan 9 kernel history: overview | file list | diff list

2001/0314/alphapc/sd53c8xx.c (diff list | history)

2000/1129/sys/src/9/alphapc/sd53c8xx.c:1,542001/0314/sys/src/9/alphapc/sd53c8xx.c:1,16 (short | long | prev | next)
2000/0515    
/* 
 * NCR 53c8xx driver for Plan 9 
 * Nigel Roles (ngr@cotswold.demon.co.uk) 
2001/0314    
 * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9 
 * Nigel Roles (nigel@9fs.org) 
2000/0515    
 * 
 * 08/07/99	Ultra2 fixed. Brazil #ifdefs added. Fixed script error 6 diagnostics. 
2001/0314    
 * 13/3/01	Fixed microcode to support targets > 7 
2000/0515    
 * 
 * 09/06/99	Enhancements to support 895 and 896 correctly. Attempt at Ultra 2 negotiation, 
 *		though no device to test with yet. 
 *		Variant now contains the number of valid chip registers to assist 
 *		dumpncrregs()  
2001/0314    
 * 01/12/00	Removed previous comments. Fixed a small problem in 
 *			mismatch recovery for targets with synchronous offsets of >=16 
 *			connected to >=875s. Thanks, Jean. 
2000/0515    
 * 
 * 06/10/98	Various bug fixes and Brazil compiler inspired changes from jmk 
 * 
 * 05/10/98	Small fix to handle command length being greater than expected by device 
 * 
 * 04/08/98     Added missing locks to interrupt handler. Marked places where  
 *		multiple controller extensions could go 
 * 
 * 18/05/97	Fixed overestimate in size of local SCRIPT RAM 
 * 
 * 17/05/97	Bug fix to return status 
 * 
 * 06/10/96	Enhanced list of chip IDs. 875 revision 1 has no clock doubler, so assume it 
 *		is shipped with 80MHz crystal. Use bit 3 of the GPREG to recognise differential 
 *		boards. This is Symbios specific, but since they are about the only suppliers of 
 *		differential cards. 
 * 
 * 23/9/96	Wide and Ultra supported. 825A and 860 added to variants. Dual compiling 
 *		version for fileserver and cpu. 80MHz default clock for 860 
 *		 
 * 5/8/96	Waits for an Inquiry message before initiating synchronous negotiation 
 *		in case capabilities byte [7] indicates device does not support it. Devices 
 *		which do target initiated negotiation will typically get in first; a few 
 *		bugs in handling this have been fixed 
 * 
 * 3/8/96	Added differential support (put scsi0=diff in plan9.ini) 
 *		Split exec() into exec() and io(). Exec() is small, and Io() does not 
 *		use any Plan 9 specific data structures, so alternate exec() functions 
 *		may be done for other environments, such as the fileserver 
 * 
 * GENERAL 
 * 
 * Works on 810 and 875 
 * Should work on 815, 825, 810A, 825A, 860A 
 * Uses local RAM, large FIFO, prefetch, burst opcode fetch, and 16 byte synch. offset 
 * where applicable 
 * Supports multi-target, wide, Ultra 
 * Differential mode can be enabled by putting scsi0=diff in plan9.ini 
 * NO SUPPORT FOR tagged queuing (yet) 
 * 
 * Known problems 
2001/0314    
 * 
 * Read/write mismatch recovery may fail on 53c1010s. Really need to get a manual. 
2000/0515    
 */ 
 
#define MAXTARGET	16		/* can be 8 or 16 */ 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:77,822001/0314/sys/src/9/alphapc/sd53c8xx.c:39,46
2000/0515    
/* CPU specific macros            */ 
/**********************************/ 
 
2001/0314    
#define PRINTPREFIX "sd53c8xx: " 
 
2000/0515    
#ifdef BOOTDEBUG 
 
#define KPRINT oprint 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:315,3202001/0314/sys/src/9/alphapc/sd53c8xx.c:279,288
2000/0515    
 
typedef struct Controller { 
	Lock; 
2001/0314    
	struct { 
		uchar scntl3; 
		uchar stest2; 
	} bios; 
2000/0515    
	uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */ 
	NegoState s[MAXTARGET]; 
	uchar scntl3[MAXTARGET]; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:340,3522001/0314/sys/src/9/alphapc/sd53c8xx.c:308,321
2000/0515    
		Lock; 
		uchar head[4];		/* head of free list (NCR byte order) */ 
		Dsa	*tail; 
		Dsa	*free; 
2001/0314    
		Dsa	*freechain; 
2000/0515    
	} dsalist; 
 
	QLock q[MAXTARGET];		/* queues for each target */ 
} Controller; 
 
static Controller controller; 
2001/0314    
#define SYNCOFFMASK(c)		(((c)->v->maxsyncoff * 2) - 1) 
#define SSIDMASK(c)		(((c)->v->feature & Wide) ? 15 : 7) 
2000/0515    
 
/* ISTAT */ 
enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 }; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:359,3642001/0314/sys/src/9/alphapc/sd53c8xx.c:328,334
2000/0515    
 
static void setmovedata(Movedata*, ulong, ulong); 
static void advancedata(Movedata*, long); 
2001/0314    
static int bios_set_differential(Controller *c); 
2000/0515    
 
static char *phase[] = { 
	"data out", "data in", "command", "status", 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:416,4682001/0314/sys/src/9/alphapc/sd53c8xx.c:386,391
2000/0515    
 
#include "sd53c8xx.i" 
 
static void 
dumpdsa(Dsa* d) 
{ 
	int i; 
                 
	print("stateb %2.2uX result %2.2uX dmablks %2.2uX flag %2.2uX\n", 
		d->stateb, d->result, d->dmablks, d->flag); 
	print("dmaaddr %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->dmaaddr[3], d->dmaaddr[2], d->dmaaddr[1], d->dmaaddr[0]); 
	print("target %d lun %d\n", d->target, d->lun); 
	print("scntl3 %2.2uX sxfer %2.2uX\n", d->scntl3, d->sxfer); 
	print("next %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->next[3], d->next[2], d->next[1], d->next[0]); 
	print("scsi_id_buf %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->scsi_id_buf[3], d->scsi_id_buf[2], 
		d->scsi_id_buf[1], d->scsi_id_buf[0]); 
	print("msg_out_buf dbc %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->msg_out_buf.dbc[3], d->msg_out_buf.dbc[2], 
		d->msg_out_buf.dbc[1], d->msg_out_buf.dbc[0]); 
	print("msg_out_buf pa %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->msg_out_buf.pa[3], d->msg_out_buf.pa[2], 
		d->msg_out_buf.pa[1], d->msg_out_buf.pa[0]); 
	print("cmd_buf dbc %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->cmd_buf.dbc[3], d->cmd_buf.dbc[2], 
		d->cmd_buf.dbc[1], d->cmd_buf.dbc[0]); 
	print("cmd_buf pa %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->cmd_buf.pa[3], d->cmd_buf.pa[2], 
		d->cmd_buf.pa[1], d->cmd_buf.pa[0]); 
	print("data_buf dbc %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->data_buf.dbc[3], d->data_buf.dbc[2], 
		d->data_buf.dbc[1], d->data_buf.dbc[0]); 
	print("data_buf pa %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->data_buf.pa[3], d->data_buf.pa[2], 
		d->data_buf.pa[1], d->data_buf.pa[0]); 
	print("status_buf dbc %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->status_buf.dbc[3], d->status_buf.dbc[2], 
		d->status_buf.dbc[1], d->status_buf.dbc[0]); 
	print("status_buf pa %2.2uX %2.2uX %2.2uX %2.2uX\n", 
		d->status_buf.pa[3], d->status_buf.pa[2], 
		d->status_buf.pa[1], d->status_buf.pa[0]); 
	print("msg_out"); 
	for(i = 0; i < 10; i++) 
		print(" %2.2uX", d->msg_out[i]); 
	print("\nstatus %2.2uX p9status %d parityerror %2.2uX\n", 
		d->status, d->p9status, d->parityerror); 
} 
                 
static Dsa * 
dsaalloc(Controller *c, int target, int lun) 
{ 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:469,4782001/0314/sys/src/9/alphapc/sd53c8xx.c:392,401
2000/0515    
	Dsa *d; 
 
	ilock(&c->dsalist); 
	if ((d = c->dsalist.free) == 0) { 
2001/0314    
	if ((d = c->dsalist.freechain) == 0) { 
2000/0515    
		d = xalloc(sizeof(*d)); 
		if (DEBUG(1)) 
			KPRINT("sd53c8xx: %d/%d: allocated new dsa %lux\n", target, lun, d); 
2001/0314    
			KPRINT(PRINTPREFIX "%d/%d: allocated new dsa %lux\n", target, lun, (ulong)d); 
2000/0515    
		lesetl(d->next, 0); 
		lesetl(d->state, A_STATE_ALLOCATED); 
		if (legetl(c->dsalist.head) == 0) 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:483,4902001/0314/sys/src/9/alphapc/sd53c8xx.c:406,413
2000/0515    
	} 
	else { 
		if (DEBUG(1)) 
			KPRINT("sd53c8xx: %d/%d: reused dsa %lux\n", target, lun, d); 
		c->dsalist.free = d->freechain; 
2001/0314    
			KPRINT(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d); 
		c->dsalist.freechain = d->freechain; 
2000/0515    
		lesetl(d->state, A_STATE_ALLOCATED); 
	} 
	iunlock(&c->dsalist); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:497,5042001/0314/sys/src/9/alphapc/sd53c8xx.c:420,427
2000/0515    
dsafree(Controller *c, Dsa *d) 
{ 
	ilock(&c->dsalist); 
	d->freechain = c->dsalist.free; 
	c->dsalist.free = d; 
2001/0314    
	d->freechain = c->dsalist.freechain; 
	c->dsalist.freechain = d; 
2000/0515    
	lesetl(d->state, A_STATE_FREE); 
	iunlock(&c->dsalist); 
} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:753,7592001/0314/sys/src/9/alphapc/sd53c8xx.c:676,682
2000/0515    
		if (chooserate(c, tpf, &scf, &xferp) == tpf) { 
			unsigned tp = tpf == 10 ? 25 : (tpf == 12 ? 50 : tpf * 4); 
			unsigned long khz = (MEGA + tp - 1) / (tp); 
			KPRINT("sd53c8xx: tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n", 
2001/0314    
			KPRINT(PRINTPREFIX "tpf=%d scf=%d.%.1d xferp=%d mhz=%ld.%.3ld\n", 
2000/0515    
			    tpf, cf2[scf] / 2, (cf2[scf] & 1) ? 5 : 0, 
			    xferp + 4, khz / 1000, khz % 1000); 
			USED(khz); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:829,8382001/0314/sys/src/9/alphapc/sd53c8xx.c:752,760
2000/0515    
	ulong p; 
 
	if (c->running) 
		panic("sd53c8xx: start called while running"); 
2001/0314    
		panic(PRINTPREFIX "start called while running"); 
2000/0515    
	c->running = 1; 
	p = c->scriptpa + entry; 
mb(); 
	lesetl(c->n->dsp, p); 
	if (c->ssm) 
		c->n->dcntl |= 0x4;		/* start DMA in SSI mode */ 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:842,8482001/0314/sys/src/9/alphapc/sd53c8xx.c:764,770
2000/0515    
ncrcontinue(Controller *c) 
{ 
	if (c->running) 
		panic("sd53c8xx: ncrcontinue called while running"); 
2001/0314    
		panic(PRINTPREFIX "ncrcontinue called while running"); 
2000/0515    
	/* set the start DMA bit to continue execution */ 
	c->running = 1; 
	c->n->dcntl |= 0x4; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:886,8982001/0314/sys/src/9/alphapc/sd53c8xx.c:808,820
2000/0515    
		n->dmode |= (1 << 1);	/* burst opcode fetch */ 
	if (c->v->feature & Differential) { 
		/* chip capable */ 
		if ((c->feature & Differential) || (n->gpreg & 0x8) == 0) { 
			/* user enabled, or bit 3 of GPREG clear (Symbios cards) */ 
2001/0314    
		if ((c->feature & Differential) || bios_set_differential(c)) { 
			/* user enabled, or some evidence bios set differential */ 
2000/0515    
			if (n->sstat2 & (1 << 2)) 
				print("sd53c8xx: can't go differential; wrong cable\n"); 
2001/0314    
				print(PRINTPREFIX "can't go differential; wrong cable\n"); 
2000/0515    
			else { 
				n->stest2 = (1 << 5); 
				print("sd53c8xx: differential mode set\n"); 
2001/0314    
				print(PRINTPREFIX "differential mode set\n"); 
2000/0515    
			} 
		} 
	} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:923,9292001/0314/sys/src/9/alphapc/sd53c8xx.c:845,851
2000/0515    
			/* reply to my SDTR */ 
			histpf = n->scratcha[2]; 
			hisreqack = n->scratcha[3]; 
			KPRINT("sd53c8xx: %d: SDTN response %d %d\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN response %d %d\n", 
2000/0515    
			    dsa->target, histpf, hisreqack); 
 
			if (hisreqack == 0) 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:931,9372001/0314/sys/src/9/alphapc/sd53c8xx.c:853,859
2000/0515    
			else { 
				/* hisreqack should be <= c->v->maxsyncoff */ 
				tpf = chooserate(c, histpf, &scf, &xferp); 
				KPRINT("sd53c8xx: %d: SDTN: using %d %d\n", 
2001/0314    
				KPRINT(PRINTPREFIX "%d: SDTN: using %d %d\n", 
2000/0515    
				    dsa->target, tpf, hisreqack); 
				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack); 
			} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:939,9542001/0314/sys/src/9/alphapc/sd53c8xx.c:861,876
2000/0515    
			return; 
		case A_SIR_EV_PHASE_SWITCH_AFTER_ID: 
			/* target ignored ATN for message after IDENTIFY - not SCSI-II */ 
			KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); 
			KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); 
			KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target); 
2000/0515    
			setasync(dsa, c, dsa->target); 
			*cont = E_to_decisions; 
			return; 
		case A_SIR_MSG_REJECT: 
			/* rejection of my SDTR */ 
			KPRINT("sd53c8xx: %d: SDTN: rejected SDTR\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN: rejected SDTR\n", dsa->target); 
2000/0515    
		//async: 
			KPRINT("sd53c8xx: %d: SDTN: async\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN: async\n", dsa->target); 
2000/0515    
			setasync(dsa, c, dsa->target); 
			*cont = -2; 
			return; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:958,9642001/0314/sys/src/9/alphapc/sd53c8xx.c:880,886
2000/0515    
		switch (msg) { 
		case A_SIR_MSG_WDTR: 
			/* reply to my WDTR */ 
			KPRINT("sd53c8xx: %d: WDTN: response %d\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: response %d\n", 
2000/0515    
			    dsa->target, n->scratcha[2]); 
			setwide(dsa, c, dsa->target, n->scratcha[2]); 
			*cont = -2; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:965,9772001/0314/sys/src/9/alphapc/sd53c8xx.c:887,899
2000/0515    
			return; 
		case A_SIR_EV_PHASE_SWITCH_AFTER_ID: 
			/* target ignored ATN for message after IDENTIFY - not SCSI-II */ 
			KPRINT("sd53c8xx: %d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: illegal phase switch after ID message - SCSI-1 device?\n", dsa->target); 
2000/0515    
			setwide(dsa, c, dsa->target, 0); 
			*cont = E_to_decisions; 
			return; 
		case A_SIR_MSG_REJECT: 
			/* rejection of my SDTR */ 
			KPRINT("sd53c8xx: %d: WDTN: rejected WDTR\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: rejected WDTR\n", dsa->target); 
2000/0515    
			setwide(dsa, c, dsa->target, 0); 
			*cont = -2; 
			return; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:986,9962001/0314/sys/src/9/alphapc/sd53c8xx.c:908,918
2000/0515    
			uchar hiswide, mywide; 
			hiswide = n->scratcha[2]; 
			mywide = (c->v->feature & Wide) != 0; 
			KPRINT("sd53c8xx: %d: WDTN: target init %d\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: target init %d\n", 
2000/0515    
			    dsa->target, hiswide); 
			if (hiswide < mywide) 
				mywide = hiswide; 
			KPRINT("sd53c8xx: %d: WDTN: responding %d\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: responding %d\n", 
2000/0515    
			    dsa->target, mywide); 
			setwide(dsa, c, dsa->target, mywide); 
			len = buildwdtrmsg(dsa->msg_out, mywide); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1007,10132001/0314/sys/src/9/alphapc/sd53c8xx.c:929,935
2000/0515    
			/* target decides to renegotiate */ 
			histpf = n->scratcha[2]; 
			hisreqack = n->scratcha[3]; 
			KPRINT("sd53c8xx: %d: SDTN: target init %d %d\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN: target init %d %d\n", 
2000/0515    
			    dsa->target, histpf, hisreqack); 
			if (hisreqack == 0) { 
				/* he wants asynchronous */ 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1019,10252001/0314/sys/src/9/alphapc/sd53c8xx.c:941,947
2000/0515    
				tpf = chooserate(c, histpf, &scf, &xferp); 
				if (hisreqack > c->v->maxsyncoff) 
					hisreqack = c->v->maxsyncoff; 
				KPRINT("sd53c8xx: %d: using %d %d\n", 
2001/0314    
				KPRINT(PRINTPREFIX "%d: using %d %d\n", 
2000/0515    
				    dsa->target, tpf, hisreqack); 
				setsync(dsa, c, dsa->target, tpf < 25, scf, xferp, hisreqack); 
			} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1036,10472001/0314/sys/src/9/alphapc/sd53c8xx.c:958,969
2000/0515    
		switch (msg) { 
		case A_SIR_EV_RESPONSE_OK: 
			c->s[dsa->target] = WideDone; 
			KPRINT("sd53c8xx: %d: WDTN: response accepted\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: response accepted\n", dsa->target); 
2000/0515    
			*cont = -2; 
			return; 
		case A_SIR_MSG_REJECT: 
			setwide(dsa, c, dsa->target, 0); 
			KPRINT("sd53c8xx: %d: WDTN: response REJECTed\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: response REJECTed\n", dsa->target); 
2000/0515    
			*cont = -2; 
			return; 
		} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1050,10682001/0314/sys/src/9/alphapc/sd53c8xx.c:972,990
2000/0515    
		switch (msg) { 
		case A_SIR_EV_RESPONSE_OK: 
			c->s[dsa->target] = BothDone; 
			KPRINT("sd53c8xx: %d: SDTN: response accepted (%s)\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN: response accepted (%s)\n", 
2000/0515    
			    dsa->target, phase[n->sstat1 & 7]); 
			*cont = -2; 
			return;	/* chf */ 
		case A_SIR_MSG_REJECT: 
			setasync(dsa, c, dsa->target); 
			KPRINT("sd53c8xx: %d: SDTN: response REJECTed\n", dsa->target); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN: response REJECTed\n", dsa->target); 
2000/0515    
			*cont = -2; 
			return; 
		} 
		break; 
	} 
	KPRINT("sd53c8xx: %d: msgsm: state %d msg %d\n", 
2001/0314    
	KPRINT(PRINTPREFIX "%d: msgsm: state %d msg %d\n", 
2000/0515    
	    dsa->target, c->s[dsa->target], msg); 
	*wakeme = 1; 
	return; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1102,11112001/0314/sys/src/9/alphapc/sd53c8xx.c:1024,1033
2000/0515    
	else 
		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f; 
	if (inchip) { 
		IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: DMA FIFO = %d\n", 
2001/0314    
		IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: DMA FIFO = %d\n", 
2000/0515    
		    dsa->target, dsa->lun, inchip); 
	} 
	if (n->sxfer & 0xf) { 
2001/0314    
	if (n->sxfer & SYNCOFFMASK(c)) { 
2000/0515    
		/* SCSI FIFO */ 
		uchar fifo = n->sstat1 >> 4; 
		if (c->v->maxsyncoff > 8) 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1112,11182001/0314/sys/src/9/alphapc/sd53c8xx.c:1034,1040
2000/0515    
			fifo |= (n->sstat2 & (1 << 4)); 
		if (fifo) { 
			inchip += fifo; 
			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SCSI FIFO = %d\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SCSI FIFO = %d\n", 
2000/0515    
			    dsa->target, dsa->lun, fifo); 
		} 
	} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1119,11302001/0314/sys/src/9/alphapc/sd53c8xx.c:1041,1052
2000/0515    
	else { 
		if (n->sstat0 & (1 << 7)) { 
			inchip++; 
			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL full\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL full\n", 
2000/0515    
			    dsa->target, dsa->lun); 
		} 
		if (n->sstat2 & (1 << 7)) { 
			inchip++; 
			IPRINT("sd53c8xx: %d/%d: read_mismatch_recover: SIDL msb full\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: read_mismatch_recover: SIDL msb full\n", 
2000/0515    
			    dsa->target, dsa->lun); 
		} 
	} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1133,11392001/0314/sys/src/9/alphapc/sd53c8xx.c:1055,1061
2000/0515    
} 
 
static ulong 
write_mismatch_recover(Ncr *n, Dsa *dsa) 
2001/0314    
write_mismatch_recover(Controller *c, Ncr *n, Dsa *dsa) 
2000/0515    
{ 
	ulong dbc; 
	uchar dfifo = n->dfifo; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1147,11532001/0314/sys/src/9/alphapc/sd53c8xx.c:1069,1075
2000/0515    
		inchip = ((dfifo & 0x7f) - (dbc & 0x7f)) & 0x7f; 
#ifdef WMR_DEBUG 
	if (inchip) { 
		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: DMA FIFO = %d\n", 
2001/0314    
		IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: DMA FIFO = %d\n", 
2000/0515    
		    dsa->target, dsa->lun, inchip); 
	} 
#endif 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1154,11742001/0314/sys/src/9/alphapc/sd53c8xx.c:1076,1096
2000/0515    
	if (n->sstat0 & (1 << 5)) { 
		inchip++; 
#ifdef WMR_DEBUG 
		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun); 
2001/0314    
		IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL full\n", dsa->target, dsa->lun); 
2000/0515    
#endif 
	} 
	if (n->sstat2 & (1 << 5)) { 
		inchip++; 
#ifdef WMR_DEBUG 
		IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun); 
2001/0314    
		IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODL msb full\n", dsa->target, dsa->lun); 
2000/0515    
#endif 
	} 
	if (n->sxfer & 0xf) { 
2001/0314    
	if (n->sxfer & SYNCOFFMASK(c)) { 
2000/0515    
		/* synchronous SODR */ 
		if (n->sstat0 & (1 << 6)) { 
			inchip++; 
#ifdef WMR_DEBUG 
			IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR full\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR full\n", 
2000/0515    
			    dsa->target, dsa->lun); 
#endif 
		} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1175,11812001/0314/sys/src/9/alphapc/sd53c8xx.c:1097,1103
2000/0515    
		if (n->sstat2 & (1 << 6)) { 
			inchip++; 
#ifdef WMR_DEBUG 
			IPRINT("sd53c8xx: %d/%d: write_mismatch_recover: SODR msb full\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: write_mismatch_recover: SODR msb full\n", 
2000/0515    
			    dsa->target, dsa->lun); 
#endif 
		} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1202,12082001/0314/sys/src/9/alphapc/sd53c8xx.c:1124,1130
2000/0515    
 
	USED(ur); 
	if (DEBUG(1)) 
		IPRINT("sd53c8xx: int\n"); 
2001/0314    
		IPRINT(PRINTPREFIX "int\n"); 
2000/0515    
	ilock(c); 
	istat = n->istat; 
	if (istat & Intf) { 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1209,12152001/0314/sys/src/9/alphapc/sd53c8xx.c:1131,1137
2000/0515    
		Dsa *d; 
		int wokesomething = 0; 
		if (DEBUG(1)) 
			IPRINT("sd53c8xx: Intfly\n"); 
2001/0314    
			IPRINT(PRINTPREFIX "Intfly\n"); 
2000/0515    
		n->istat = Intf; 
		/* search for structures in A_STATE_DONE */ 
		for (d = KPTR(legetl(c->dsalist.head)); d; d = KPTR(legetl(d->next))) { 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1216,12332001/0314/sys/src/9/alphapc/sd53c8xx.c:1138,1155
2000/0515    
			if (d->stateb == A_STATE_DONE) { 
				d->p9status = d->status; 
				if (DEBUG(1)) 
					IPRINT("sd53c8xx: waking up dsa %lux\n", d); 
2001/0314    
					IPRINT(PRINTPREFIX "waking up dsa %lux\n", (ulong)d); 
2000/0515    
				wakeup(d); 
				wokesomething = 1; 
			} 
		} 
		if (!wokesomething) 
			IPRINT("sd53c8xx: nothing to wake up\n"); 
2001/0314    
			IPRINT(PRINTPREFIX "nothing to wake up\n"); 
2000/0515    
	} 
 
	if ((istat & (Sip | Dip)) == 0) { 
		if (DEBUG(1)) 
			IPRINT("sd53c8xx: int end %x\n", istat); 
2001/0314    
			IPRINT(PRINTPREFIX "int end %x\n", istat); 
2000/0515    
		iunlock(c); 
		return; 
	} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1250,12562001/0314/sys/src/9/alphapc/sd53c8xx.c:1172,1178
2000/0515    
			addr = legetl(n->dsp); 
			sa = addr - c->scriptpa; 
			if (DEBUG(1) || DEBUG(2)) 
				IPRINT("sd53c8xx: %d/%d: Phase Mismatch sa=%.8lux\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: Phase Mismatch sa=%.8lux\n", 
2000/0515    
				    dsa->target, dsa->lun, sa); 
			/* 
			 * now recover 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1260,12662001/0314/sys/src/9/alphapc/sd53c8xx.c:1182,1188
2000/0515    
				tbc = legetl(dsa->data_buf.dbc) - dbc; 
				advancedata(&dsa->data_buf, tbc); 
				if (DEBUG(1) || DEBUG(2)) 
					IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n", 
2001/0314    
					IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", 
2000/0515    
					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); 
				cont = E_to_decisions; 
			} 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1286,13012001/0314/sys/src/9/alphapc/sd53c8xx.c:1208,1223
2000/0515    
				cont = E_data_block_mismatch_recover; 
			} 
			else if (sa == E_data_out_mismatch) { 
				dbc = write_mismatch_recover(n, dsa); 
2001/0314    
				dbc = write_mismatch_recover(c, n, dsa); 
2000/0515    
				tbc = legetl(dsa->data_buf.dbc) - dbc; 
				advancedata(&dsa->data_buf, tbc); 
				if (DEBUG(1) || DEBUG(2)) 
					IPRINT("sd53c8xx: %d/%d: transferred = %ld residue = %ld\n", 
2001/0314    
					IPRINT(PRINTPREFIX "%d/%d: transferred = %ld residue = %ld\n", 
2000/0515    
					    dsa->target, dsa->lun, tbc, legetl(dsa->data_buf.dbc)); 
				cont = E_to_decisions; 
			} 
			else if (sa == E_data_out_block_mismatch) { 
				dbc = write_mismatch_recover(n, dsa); 
2001/0314    
				dbc = write_mismatch_recover(c, n, dsa); 
2000/0515    
				tbc = legetl(dsa->data_buf.dbc) - dbc; 
				/* recover current state from registers */ 
				dmablks = n->scratcha[2]; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1329,13372001/0314/sys/src/9/alphapc/sd53c8xx.c:1251,1259
2000/0515    
				 */ 
				ulong lim = legetl(dsa->msg_out_buf.dbc); 
				uchar p = n->sstat1 & 7; 
				dbc = write_mismatch_recover(n, dsa); 
2001/0314    
				dbc = write_mismatch_recover(c, n, dsa); 
2000/0515    
				tbc = lim - dbc; 
				IPRINT("sd53c8xx: %d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: msg_out_mismatch: %lud/%lud sent, phase %s\n", 
2000/0515    
				    dsa->target, dsa->lun, tbc, lim, phase[p]); 
				if (p != MessageIn && tbc == 1) { 
					msgsm(dsa, c, A_SIR_EV_PHASE_SWITCH_AFTER_ID, &cont, &wakeme); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1345,13592001/0314/sys/src/9/alphapc/sd53c8xx.c:1267,1281
2000/0515    
				 */ 
				ulong lim = legetl(dsa->cmd_buf.dbc); 
				uchar p = n->sstat1 & 7; 
				dbc = write_mismatch_recover(n, dsa); 
2001/0314    
				dbc = write_mismatch_recover(c, n, dsa); 
2000/0515    
				tbc = lim - dbc; 
				IPRINT("sd53c8xx: %d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: cmd_out_mismatch: %lud/%lud sent, phase %s\n", 
2000/0515    
				    dsa->target, dsa->lun, tbc, lim, phase[p]); 
				USED(p, tbc); 
				cont = E_to_decisions; 
			} 
			else { 
				IPRINT("sd53c8xx: %d/%d: ma sa=%.8lux wanted=%s got=%s\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: ma sa=%.8lux wanted=%s got=%s\n", 
2000/0515    
				    dsa->target, dsa->lun, sa, 
				    phase[n->dcmd & 7], 
				    phase[n->sstat1 & 7]); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1364,13702001/0314/sys/src/9/alphapc/sd53c8xx.c:1286,1292
2000/0515    
		} 
		/*else*/ if (sist & 0x400) { 
			if (DEBUG(0)) 
				IPRINT("sd53c8xx: %d/%d Sto\n", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d Sto\n", dsa->target, dsa->lun); 
2000/0515    
			dsa->p9status = SDtimeout; 
			dsa->stateb = A_STATE_DONE; 
			softreset(c); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1372,13822001/0314/sys/src/9/alphapc/sd53c8xx.c:1294,1304
2000/0515    
			wakeme = 1; 
		} 
		if (sist & 0x1) { 
			IPRINT("sd53c8xx: %d/%d: parity error\n", dsa->target, dsa->lun); 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: parity error\n", dsa->target, dsa->lun); 
2000/0515    
			dsa->parityerror = 1; 
		} 
		if (sist & 0x4) { 
			IPRINT("sd53c8xx: %d/%d: unexpected disconnect\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: unexpected disconnect\n", 
2000/0515    
			    dsa->target, dsa->lun); 
			dumpncrregs(c, 1); 
			//wakeme = 1; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1407,14162001/0314/sys/src/9/alphapc/sd53c8xx.c:1329,1338
2000/0515    
				break; 
			case A_SIR_MSG_IGNORE_WIDE_RESIDUE: 
				/* back up one in the data transfer */ 
				IPRINT("sd53c8xx: %d/%d: ignore wide residue %d, WSR = %d\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: ignore wide residue %d, WSR = %d\n", 
2000/0515    
				    dsa->target, dsa->lun, n->scratcha[1], n->scntl2 & 1); 
				if (dsa->dmablks == 0 && dsa->flag) 
					IPRINT("sd53c8xx: %d/%d: transfer over; residue ignored\n", 
2001/0314    
					IPRINT(PRINTPREFIX "%d/%d: transfer over; residue ignored\n", 
2000/0515    
					    dsa->target, dsa->lun); 
				else 
					calcblockdma(dsa, legetl(dsa->dmaaddr) - 1, 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1418,14702001/0314/sys/src/9/alphapc/sd53c8xx.c:1340,1392
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT: 
				IPRINT("sd53c8xx: %d: not msg_in after reselect (%s)", 
				    n->ssid & 7, phase[n->sstat1 & 7]); 
				dsa = dsafind(c, n->ssid & 7, -1, A_STATE_DISCONNECTED); 
2001/0314    
				IPRINT(PRINTPREFIX "%d: not msg_in after reselect (%s)", 
				    n->ssid & SSIDMASK(c), phase[n->sstat1 & 7]); 
				dsa = dsafind(c, n->ssid & SSIDMASK(c), -1, A_STATE_DISCONNECTED); 
2000/0515    
				dumpncrregs(c, 1); 
				wakeme = 1; 
				break; 
			case A_SIR_NOTIFY_MSG_IN: 
				IPRINT("sd53c8xx: %d/%d: msg_in %d\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: msg_in %d\n", 
2000/0515    
				    dsa->target, dsa->lun, n->sfbr); 
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_DISC: 
				IPRINT("sd53c8xx: %d/%d: disconnect:", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: disconnect:", dsa->target, dsa->lun); 
2000/0515    
				goto dsadump; 
			case A_SIR_NOTIFY_STATUS: 
				IPRINT("sd53c8xx: %d/%d: status\n", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: status\n", dsa->target, dsa->lun); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_COMMAND: 
				IPRINT("sd53c8xx: %d/%d: commands\n", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: commands\n", dsa->target, dsa->lun); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_DATA_IN: 
				IPRINT("sd53c8xx: %d/%d: data in a %lx b %lx\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: data in a %lx b %lx\n", 
2000/0515    
				    dsa->target, dsa->lun, legetl(n->scratcha), legetl(n->scratchb)); 
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_BLOCK_DATA_IN: 
				IPRINT("sd53c8xx: %d/%d: block data in: a2 %x b %lx\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: block data in: a2 %x b %lx\n", 
2000/0515    
				    dsa->target, dsa->lun, n->scratcha[2], legetl(n->scratchb)); 
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_DATA_OUT: 
				IPRINT("sd53c8xx: %d/%d: data out\n", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: data out\n", dsa->target, dsa->lun); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_DUMP: 
				IPRINT("sd53c8xx: %d/%d: dump\n", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: dump\n", dsa->target, dsa->lun); 
2000/0515    
				dumpncrregs(c, 1); 
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_DUMP2: 
				IPRINT("sd53c8xx: %d/%d: dump2:", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: dump2:", dsa->target, dsa->lun); 
2000/0515    
				IPRINT(" sa %lux", legetl(n->dsp) - c->scriptpa); 
				IPRINT(" dsa %lux", legetl(n->dsa)); 
				IPRINT(" sfbr %ux", n->sfbr); 
				IPRINT(" a %lux", n->scratcha); 
2001/0314    
				IPRINT(" a %lux", legetl(n->scratcha)); 
2000/0515    
				IPRINT(" b %lux", legetl(n->scratchb)); 
				IPRINT(" ssid %ux", n->ssid); 
				IPRINT("\n"); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1471,14862001/0314/sys/src/9/alphapc/sd53c8xx.c:1393,1408
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_WAIT_RESELECT: 
				IPRINT("sd53c8xx: wait reselect\n"); 
2001/0314    
				IPRINT(PRINTPREFIX "wait reselect\n"); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_RESELECT: 
				IPRINT("sd53c8xx: reselect: ssid %.2x sfbr %.2x at %ld\n", 
2001/0314    
				IPRINT(PRINTPREFIX "reselect: ssid %.2x sfbr %.2x at %ld\n", 
2000/0515    
				    n->ssid, n->sfbr, TK2MS(m->ticks)); 
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_ISSUE: 
				IPRINT("sd53c8xx: %d/%d: issue:", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: issue:", dsa->target, dsa->lun); 
2000/0515    
			dsadump: 
				IPRINT(" tgt=%d", dsa->target); 
				IPRINT(" time=%ld", TK2MS(m->ticks)); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1488,15042001/0314/sys/src/9/alphapc/sd53c8xx.c:1410,1426
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_ISSUE_CHECK: 
				IPRINT("sd53c8xx: issue check\n"); 
2001/0314    
				IPRINT(PRINTPREFIX "issue check\n"); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_SIGP: 
				IPRINT("sd53c8xx: responded to SIGP\n"); 
2001/0314    
				IPRINT(PRINTPREFIX "responded to SIGP\n"); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_DUMP_NEXT_CODE: { 
				ulong *dsp = DMASEG_TO_KADDR(legetl(n->dsp)); 
				int x; 
				IPRINT("sd53c8xx: code at %lux", dsp - c->script); 
2001/0314    
				IPRINT(PRINTPREFIX "code at %lux", dsp - c->script); 
2000/0515    
				for (x = 0; x < 6; x++) 
					IPRINT(" %.8lux", dsp[x]); 
				IPRINT("\n"); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1507,15272001/0314/sys/src/9/alphapc/sd53c8xx.c:1429,1449
2000/0515    
				break; 
			} 
			case A_SIR_NOTIFY_WSR: 
				IPRINT("sd53c8xx: %d/%d: WSR set\n", dsa->target, dsa->lun); 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: WSR set\n", dsa->target, dsa->lun); 
2000/0515    
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_LOAD_SYNC: 
				IPRINT("sd53c8xx: %d/%d: scntl=%.2x sxfer=%.2x\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: scntl=%.2x sxfer=%.2x\n", 
2000/0515    
				    dsa->target, dsa->lun, n->scntl3, n->sxfer); 
				cont = -2; 
				break; 
			case A_SIR_NOTIFY_RESELECTED_ON_SELECT: 
				IPRINT("sd53c8xx: %d/%d: reselected during select\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: reselected during select\n", 
2000/0515    
				    dsa->target, dsa->lun); 
				cont = -2; 
				break; 
			default: 
				IPRINT("sd53c8xx: %d/%d: script error %ld\n", 
2001/0314    
				IPRINT(PRINTPREFIX "%d/%d: script error %ld\n", 
2000/0515    
					dsa->target, dsa->lun, legetl(n->dsps)); 
				dumpncrregs(c, 1); 
				wakeme = 1; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1530,15362001/0314/sys/src/9/alphapc/sd53c8xx.c:1452,1458
2000/0515    
		/*else*/ if (dstat & Iid) { 
			ulong addr = legetl(n->dsp); 
			ulong dbc = (n->dbc[2]<<16)|(n->dbc[1]<<8)|n->dbc[0]; 
			IPRINT("sd53c8xx: %d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n", 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: Iid pa=%.8lux sa=%.8lux dbc=%lux\n", 
2000/0515    
			    dsa->target, dsa->lun, 
			    addr, addr - c->scriptpa, dbc); 
			addr = (ulong)DMASEG_TO_KADDR(addr); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1541,15472001/0314/sys/src/9/alphapc/sd53c8xx.c:1463,1469
2000/0515    
			wakeme = 1; 
		} 
		/*else*/ if (dstat & Bf) { 
			IPRINT("sd53c8xx: %d/%d: Bus Fault\n", dsa->target, dsa->lun); 
2001/0314    
			IPRINT(PRINTPREFIX "%d/%d: Bus Fault\n", dsa->target, dsa->lun); 
2000/0515    
			dumpncrregs(c, 1); 
			dsa->p9status = SDeio; 
			wakeme = 1; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1558,15642001/0314/sys/src/9/alphapc/sd53c8xx.c:1480,1486
2000/0515    
	} 
	iunlock(c); 
	if (DEBUG(1)) { 
		IPRINT("sd53c8xx: int end 1\n"); 
2001/0314    
		IPRINT(PRINTPREFIX "int end 1\n"); 
2000/0515    
	} 
} 
 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1599,16052001/0314/sys/src/9/alphapc/sd53c8xx.c:1521,1527
2000/0515    
	} 
 
	if (datalen) { 
		KPRINT("sd53c8xx:write:"); 
2001/0314    
		KPRINT(PRINTPREFIX "write:"); 
2000/0515    
		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) 
			KPRINT("%.2ux", *bp); 
		if (i < datalen) { 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1620,16262001/0314/sys/src/9/alphapc/sd53c8xx.c:1542,1548
2000/0515    
	} 
 
	if (datalen) { 
		KPRINT("sd53c8xx:read:"); 
2001/0314    
		KPRINT(PRINTPREFIX "read:"); 
2000/0515    
		for (i = 0, bp = data; i < 50 && i < datalen; i++, bp++) 
			KPRINT("%.2ux", *bp); 
		if (i < datalen) { 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1697,17032001/0314/sys/src/9/alphapc/sd53c8xx.c:1619,1625
2000/0515    
	/* work out what to do about negotiation */ 
	switch (c->s[target]) { 
	default: 
		KPRINT("sd53c8xx: %d: strange nego state %d\n", target, c->s[target]); 
2001/0314    
		KPRINT(PRINTPREFIX "%d: strange nego state %d\n", target, c->s[target]); 
2000/0515    
		c->s[target] = NeitherDone; 
		/* fall through */ 
	case NeitherDone: 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1709,17352001/0314/sys/src/9/alphapc/sd53c8xx.c:1631,1657
2000/0515    
			my_expo = target_expo; 
#ifdef ALWAYS_DO_WDTR 
		bc += buildwdtrmsg(d->msg_out + bc, my_expo); 
		KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo); 
2001/0314    
		KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); 
2000/0515    
		c->s[target] = WideInit; 
		break; 
#else 
		if (my_expo) { 
			bc += buildwdtrmsg(d->msg_out + bc, (c->v->feature & Wide) ? 1 : 0); 
			KPRINT("sd53c8xx: %d: WDTN: initiating expo %d\n", target, my_expo); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: WDTN: initiating expo %d\n", target, my_expo); 
2000/0515    
			c->s[target] = WideInit; 
			break; 
		} 
		KPRINT("sd53c8xx: %d: WDTN: narrow\n", target); 
2001/0314    
		KPRINT(PRINTPREFIX "%d: WDTN: narrow\n", target); 
2000/0515    
		/* fall through */ 
#endif 
	case WideDone: 
		if (c->cap[target] & (1 << 4)) { 
			KPRINT("sd53c8xx: %d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff); 
2001/0314    
			KPRINT(PRINTPREFIX "%d: SDTN: initiating %d %d\n", target, c->tpf, c->v->maxsyncoff); 
2000/0515    
			bc += buildsdtrmsg(d->msg_out + bc, c->tpf, c->v->maxsyncoff); 
			c->s[target] = SyncInit; 
			break; 
		} 
		KPRINT("sd53c8xx: %d: SDTN: async only\n", target); 
2001/0314    
		KPRINT(PRINTPREFIX "%d: SDTN: async only\n", target); 
2000/0515    
		c->s[target] = BothDone; 
		break; 
 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1742,17532001/0314/sys/src/9/alphapc/sd53c8xx.c:1664,1675
2000/0515    
	calcblockdma(d, DMASEG(r->data), r->dlen); 
 
	if (DEBUG(0)) { 
		KPRINT("sd53c8xx: %d/%d: exec: ", target, r->lun); 
2001/0314    
		KPRINT(PRINTPREFIX "%d/%d: exec: ", target, r->lun); 
2000/0515    
		for (bp = r->cmd; bp < &r->cmd[r->clen]; bp++) 
			KPRINT("%.2ux", *bp); 
		KPRINT("\n"); 
		if (!r->write) 
			KPRINT("sd53c8xx: %d/%d: exec: limit=(%d)%ld\n", 
2001/0314    
			KPRINT(PRINTPREFIX "%d/%d: exec: limit=(%d)%ld\n", 
2000/0515    
			  target, r->lun, d->dmablks, legetl(d->data_buf.dbc)); 
		else 
			dumpwritedata(r->data, r->dlen); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1759,17712001/0314/sys/src/9/alphapc/sd53c8xx.c:1681,1691
2000/0515    
	d->parityerror = 0; 
 
	d->stateb = A_STATE_ISSUE;		/* start operation */ 
mb(); 
 
	ilock(c); 
	if (c->ssm) 
		c->n->dcntl |= 0x10;		/* SSI */ 
	if (c->running) { 
mb(); 
		c->n->istat |= Sigp; 
	} 
	else { 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1775,17872001/0314/sys/src/9/alphapc/sd53c8xx.c:1695,1706
2000/0515    
 
	while(waserror()) 
		; 
	tsleep(d, done, d, 30 * 1000); 
2001/0314    
	tsleep(d, done, d, 600 * 1000); 
2000/0515    
	poperror(); 
 
	if (!done(d)) { 
		KPRINT("sd53c8xx: %d/%d: exec: Timed out\n", target, r->lun); 
2001/0314    
		KPRINT(PRINTPREFIX "%d/%d: exec: Timed out\n", target, r->lun); 
2000/0515    
		dumpncrregs(c, 0); 
		dumpdsa(d); 
		dsafree(c, d); 
		reset(c); 
		qunlock(&c->q[target]); 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1806,18122001/0314/sys/src/9/alphapc/sd53c8xx.c:1725,1731
2000/0515    
	if(!r->write) 
		dumpreaddata(r->data, r->rlen); 
	if (DEBUG(0)) 
		KPRINT("53c8xx: %d/%d: exec: p9status=%d status %d rlen %ld\n", 
2001/0314    
		KPRINT(PRINTPREFIX "%d/%d: exec: p9status=%d status %d rlen %ld\n", 
2000/0515    
		    target, r->lun, d->p9status, status, r->rlen); 
	/* 
	 * spot the identify 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1817,18232001/0314/sys/src/9/alphapc/sd53c8xx.c:1736,1742
2000/0515    
		c->capvalid |= 1 << target; 
		bp = r->data; 
		c->cap[target] = bp[7]; 
		KPRINT("sd53c8xx: %d: capabilities %.2x\n", target, bp[7]); 
2001/0314    
		KPRINT(PRINTPREFIX "%d: capabilities %.2x\n", target, bp[7]); 
2000/0515    
	} 
	if(!check && status == SDcheck && !(r->flags & SDnosense)){ 
		check = 1; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1843,18532001/0314/sys/src/9/alphapc/sd53c8xx.c:1762,1791
2000/0515    
		status = SDcheck; 
		r->flags |= SDvalidsense; 
	} 
2000/0608    
	KPRINT("sd53c8xx: %d: r flags %8.8uX status %d rlen %ld\n", 
2001/0314    
	KPRINT(PRINTPREFIX "%d: r flags %8.8uX status %d rlen %ld\n", 
2000/0608    
		target, r->flags, status, r->rlen); 
	return r->status = status; 
2000/0515    
} 
 
2001/0314    
static void 
cribbios(Controller *c) 
{ 
	c->bios.scntl3 = c->n->scntl3; 
	c->bios.stest2 = c->n->stest2; 
	print(PRINTPREFIX "bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2); 
} 
 
static int 
bios_set_differential(Controller *c) 
{ 
	/* Concept lifted from FreeBSD - thanks Gerard */ 
	/* basically, if clock conversion factors are set, then there is 
 	 * evidence the bios had a go at the chip, and if so, it would 
	 * have set the differential enable bit in stest2 
	 */ 
	return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0; 
} 
 
2000/0515    
#define NCR_VID 	0x1000 
#define NCR_810_DID 	0x0001 
#define NCR_820_DID	0x0002	/* don't know enough about this one to support it */ 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1859,18642001/0314/sys/src/9/alphapc/sd53c8xx.c:1797,1803
2000/0515    
#define SYM_895_DID	0x000c 
#define SYM_885_DID	0x000d	/* ditto */ 
#define SYM_875_DID	0x000f	/* ditto */ 
2001/0314    
#define SYM_1010_DID	0x0020 
2000/0515    
#define SYM_875J_DID	0x008f 
 
static Variant variant[] = { 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1877,18822001/0314/sys/src/9/alphapc/sd53c8xx.c:1816,1822
2000/0515    
{ SYM_885_DID,   0xff, "SYM53C885",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble }, 
{ SYM_895_DID,   0xff, "SYM53C895",	Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, 
{ SYM_896_DID,   0xff, "SYM53C896",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, 
2001/0314    
{ SYM_1010_DID,  0xff, "SYM53C1010",	Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, 
2000/0515    
}; 
 
#define offsetof(s, t) ((ulong)&((s *)0)->t) 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1898,19032001/0314/sys/src/9/alphapc/sd53c8xx.c:1838,1845
2000/0515    
		*v = offsetof(Dsa, status_buf); return 1; 
	case X_dsa_head: 
		*v = DMASEG(&c->dsalist.head[0]); return 1; 
2001/0314    
	case X_ssid_mask: 
		*v = SSIDMASK(c); return 1; 
2000/0515    
	default: 
		print("xfunc: can't find external %d\n", x); 
		return 0; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:1958,19812001/0314/sys/src/9/alphapc/sd53c8xx.c:1900,1931
2000/0515    
static SDev* 
sympnp(void) 
{ 
2001/0314    
	char *cp; 
2000/0515    
	Pcidev *p; 
	Variant *v; 
	int ba; 
2001/0314    
	int ba, nctlr; 
2000/0515    
	void *scriptma; 
	Controller *ctlr; 
	SDev *sdev, *head, *tail; 
	ulong regpa, *script, scriptpa; 
 
2001/0314    
	if(cp = getconf("*maxsd53c8xx")) 
		nctlr = strtoul(cp, 0, 0); 
	else 
		nctlr = 32; 
 
2000/0515    
	p = nil; 
	head = tail = nil; 
	while(p = pcimatch(p, NCR_VID, 0)){ 
2001/0314    
	while((p = pcimatch(p, NCR_VID, 0)) != nil && nctlr > 0){ 
2000/0515    
		for(v = variant; v < &variant[nelem(variant)]; v++){ 
			if(p->did == v->did && p->rid <= v->maxrid) 
				break; 
		} 
		if(v >= &variant[nelem(variant)]) 
2001/0314    
		if(v >= &variant[nelem(variant)]) { 
			print("no match\n"); 
2000/0515    
			continue; 
		print("sd53c8xx: %s rev. 0x%2.2x intr=%d command=%4.4luX\n", 
2001/0314    
		} 
		print(PRINTPREFIX "%s rev. 0x%2.2x intr=%d command=%4.4luX\n", 
2000/0515    
			v->name, p->rid, p->intl, p->pcr); 
 
		regpa = p->mem[1].bar; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:2044,20502001/0314/sys/src/9/alphapc/sd53c8xx.c:1994,2000
2000/0515    
		} 
		swabl(ctlr->script, ctlr->script, sizeof(na_script)); 
 
		ctlr->dsalist.free = 0; 
2001/0314    
		ctlr->dsalist.freechain = 0; 
2000/0515    
		lesetl(ctlr->dsalist.head, 0); 
 
		ctlr->pcidev = p; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:2062,20672001/0314/sys/src/9/alphapc/sd53c8xx.c:2012,2019
2000/0515    
		else 
			head = sdev; 
		tail = sdev; 
2001/0314    
 
		nctlr--; 
2000/0515    
	} 
 
	return head; 
2000/1129/sys/src/9/alphapc/sd53c8xx.c:2089,20942001/0314/sys/src/9/alphapc/sd53c8xx.c:2041,2047
2000/0515    
 
	ilock(ctlr); 
	synctabinit(ctlr); 
2001/0314    
	cribbios(ctlr); 
2000/0515    
	reset(ctlr); 
	iunlock(ctlr); 
 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)