xref: /csrg-svn/sys/vax/uba/up.c (revision 420)
1 /*	up.c	3.20	07/29/80	*/
2 
3 /*
4  * Emulex UNIBUS disk driver with overlapped seeks and ECC recovery.
5  *
6  * NB: This driver works reliably only on an SC-11B controller with
7  *     rev. level at least J (in particular rev. level H will not work well).
8  *     If you have an newer controller you should change olducode below to:
9  *		int	olducode = 0;
10  *     which saves time by stalling less in the system.
11  *
12  * Controller switch settings:
13  *	SW1-1	5/19 surfaces	(off, 19 surfaces on Ampex 9300)
14  *	SW1-2	chksum enable	(off, checksum disabled)
15  *	SW1-3	volume select	(off, 815 cylinders)
16  *	SW1-4	sector select	(on, 32 sectors)
17  *	SW1-5	unused		(off)
18  *	SW1-6	port select	(on, single port)
19  *	SW1-7	npr delay	(off, disable)
20  *	SW1-8	ecc test mode	(off, disable)
21  * and top mounted switches:
22  *	SW2-1	extend opcodes	(off=open, disable)
23  *	SW2-2	extend diag	(off=open, disable)
24  *	SW2-3	4 wd dma burst	(on=closed, enable)
25  *	SW2-4	unused		(off=open)
26  */
27 
28 #include "../h/param.h"
29 #include "../h/systm.h"
30 #include "../h/dk.h"
31 #include "../h/buf.h"
32 #include "../h/conf.h"
33 #include "../h/dir.h"
34 #include "../h/user.h"
35 #include "../h/map.h"
36 #include "../h/pte.h"
37 #include "../h/mba.h"
38 #include "../h/mtpr.h"
39 #include "../h/uba.h"
40 #include "../h/vm.h"
41 
42 /*
43  * Define number of drives, and range of sampling information to be used.
44  *
45  * Normally, DK_N .. DK_N+NUP-1 gather individual drive stats,
46  * and DK_N+NUP gathers controller transferring stats.
47  *
48  * If DK_N+NUP > DK_NMAX, then transfer stats are divided per drive.
49  * If DK_NMAX is yet smaller, some drives are not monitored.
50  */
51 #define	DK_N	2
52 #define	DK_NMAX	3
53 
54 #define	ushort	unsigned short
55 
56 struct	device
57 {
58 	ushort	upcs1;		/* control and status register 1 */
59 	short	upwc;		/* word count register */
60 	ushort	upba;		/* UNIBUS address register */
61 	ushort	upda;		/* desired address register */
62 	ushort	upcs2;		/* control and status register 2 */
63 	ushort	upds;		/* drive Status */
64 	ushort	uper1;		/* error register 1 */
65 	ushort	upas;		/* attention summary */
66 	ushort	upla;		/* look ahead */
67 	ushort	updb;		/* data buffer */
68 	ushort	upmr;		/* maintenance */
69 	ushort	updt;		/* drive type */
70 	ushort	upsn;		/* serial number */
71 	ushort	upof;		/* offset register */
72 	ushort	updc;		/* desired cylinder address register */
73 	ushort	upcc;		/* current cylinder */
74 	ushort	uper2;		/* error register 2 */
75 	ushort	uper3;		/* error register 3 */
76 	ushort	upec1;		/* burst error bit position */
77 	ushort	upec2;		/* burst error bit pattern */
78 };
79 
80 /*
81  * Software extension to the upas register, so we can
82  * postpone starting SEARCH commands until the controller
83  * is not transferring.
84  */
85 int	upsoftas;
86 
87 /*
88  * If upseek then we don't issue SEARCH commands but rather just
89  * settle for a SEEK to the correct cylinder.
90  */
91 int	upseek;
92 
93 #define	UPADDR	((struct device *)(UBA0_DEV + 0176700))
94 
95 #define	NUP	2		/* Number of drives this installation */
96 
97 #define	NSECT	32
98 #define	NTRAC	19
99 
100 /*
101  * Constants controlling on-cylinder SEARCH usage.
102  *
103  * 	upSDIST/2 msec		time needed to start transfer
104  * 	upRDIST/2 msec		tolerable rotational latency when on-cylinder
105  *
106  * If we are no closer than upSDIST sectors and no further than upSDIST+upRDIST
107  * and in the driver then we take it as it is.  Otherwise we do a SEARCH
108  * requesting an interrupt upSDIST sectors in advance.
109  */
110 #define	_upSDIST	6		/* 3.0 msec */
111 #define	_upRDIST	6		/* 3.0 msec */
112 
113 int	upSDIST = _upSDIST;
114 int	upRDIST = _upRDIST;
115 
116 /*
117  * To fill a 300M drive:
118  *	A is designed to be used as a root.
119  *	B is suitable for a swap area.
120  *	H is the primary storage area.
121  * On systems with RP06'es, we normally use only 291346 blocks of the H
122  * area, and use DEF or G to cover the rest of the drive.  The C system
123  * covers the whole drive and can be used for pack-pack copying.
124  */
125 struct	size
126 {
127 	daddr_t	nblocks;
128 	int	cyloff;
129 } up_sizes[8] = {
130 	15884,	0,		/* A=cyl 0 thru 26 */
131 	33440,	27,		/* B=cyl 27 thru 81 */
132 	495520,	0,		/* C=cyl 0 thru 814 */
133 	15884,	562,		/* D=cyl 562 thru 588 */
134 	55936,	589,		/* E=cyl 589 thru 680 */
135 	81472,	681,		/* F=cyl 681 thru 814 */
136 	153824,	562,		/* G=cyl 562 thru 814 */
137 	445664,	82,		/* H=cyl 82 thru 814 */
138 /* Later, and more safely for H area...
139 	291346,	82,		/* H=cyl 82 thru 561 */
140 };
141 
142 /*
143  * The following defines are used in offset positioning
144  * when trying to recover disk errors, with the constants being
145  * +/- microinches.  Note that header compare inhibit (HCI) is not
146  * tried (this makes sense only during read, in any case.)
147  *
148  * NOT ALL OF THESE ARE IMPLEMENTED ON 9300!?!
149  */
150 #define	P400	020
151 #define	M400	0220
152 #define	P800	040
153 #define	M800	0240
154 #define	P1200	060
155 #define	M1200	0260
156 #define	HCI	020000
157 
158 int	up_offset[16] =
159 {
160 	P400, M400, P400, M400,
161 	P800, M800, P800, M800,
162 	P1200, M1200, P1200, M1200,
163 	0, 0, 0, 0,
164 };
165 
166 /*
167  * Each drive has a table uputab[i].  On this table are sorted the
168  * pending requests implementing an elevator algorithm (see dsort.c.)
169  * In the upustart() routine, each drive is independently advanced
170  * until it is on the desired cylinder for the next transfer and near
171  * the desired sector.  The drive is then chained onto the uptab
172  * table, and the transfer is initiated by the upstart() routine.
173  * When the transfer is completed the driver reinvokes the upustart()
174  * routine to set up the next transfer.
175  */
176 struct	buf	uptab;
177 struct	buf	uputab[NUP];
178 
179 struct	buf	rupbuf;			/* Buffer for raw i/o */
180 
181 /* Drive commands, placed in upcs1 */
182 #define	GO	01		/* Go bit, set in all commands */
183 #define	PRESET	020		/* Preset drive at init or after errors */
184 #define	OFFSET	014		/* Offset heads to try to recover error */
185 #define	RTC	016		/* Return to center-line after OFFSET */
186 #define	SEARCH	030		/* Search for cylinder+sector */
187 #define	SEEK	04		/* Seek to cylinder */
188 #define	RECAL	06		/* Recalibrate, needed after seek error */
189 #define	DCLR	010		/* Drive clear, after error */
190 #define	WCOM	060		/* Write */
191 #define	RCOM	070		/* Read */
192 
193 /* Other bits of upcs1 */
194 #define	IE	0100		/* Controller wide interrupt enable */
195 #define	TRE	040000		/* Transfer error */
196 #define	RDY	0200		/* Transfer terminated */
197 
198 /* Drive status bits of upds */
199 #define	PIP	020000		/* Positioning in progress */
200 #define	ERR	040000		/* Error has occurred, DCLR necessary */
201 #define	VV	0100		/* Volume is valid, set by PRESET */
202 #define	DPR	0400		/* Drive has been preset */
203 #define	MOL	010000		/* Drive is online, heads loaded, etc */
204 #define	DRY	0200		/* Drive ready */
205 
206 /* Bits of upcs2 */
207 #define	CLR	040		/* Controller clear */
208 /* Bits of uper1 */
209 #define	DCK	0100000		/* Ecc error occurred */
210 #define	ECH	0100		/* Ecc error was unrecoverable */
211 #define	WLE	04000		/* Attempt to write read-only drive */
212 
213 /* Bits of upof; the offset bits above are also in this register */
214 #define	FMT22	010000		/* 16 bits/word, must be always set */
215 
216 #define	b_cylin b_resid
217 
218 int	up_ubinfo;		/* Information about UBA usage saved here */
219 /*
220  * The EMULEX controller balks if accessed quickly after
221  * certain operations.  With rev J delays seem to be needed only
222  * when selecting a new unit, and in drive initialization type
223  * like PRESET and DCLR.  The following variables control the delay
224  * DELAY(n) is approximately n usec.
225  */
226 int	olducode = 1;
227 int	idelay = 500;		/* Delay after PRESET or DCLR */
228 int	osdelay = 150;		/* Old delay after selecting drive in upcs2 */
229 int	ordelay = 100;		/* Old delay after SEARCH */
230 int	oasdel = 100;		/* Old delay after clearing bit in upas */
231 int	nsdelay = 25;
232 
233 #define	DELAY(N)		{ register int d; d = N; while (--d > 0); }
234 
235 int	nwaitcs2;		/* How many sdelay loops ? */
236 int	neasycs2;		/* How many sdelay loops not needed ? */
237 
238 int	up_wticks;		/* Ticks waiting for interrupt */
239 int	upwstart;		/* Have started guardian */
240 int	upwatch();
241 
242 #ifdef INTRLVE
243 daddr_t dkblock();
244 #endif
245 
246 /*
247  * Queue an i/o request for a drive, checking first that it is in range.
248  *
249  * A unit start is issued if the drive is inactive, causing
250  * a SEARCH for the correct cylinder/sector.  If the drive is
251  * already nearly on the money and the controller is not transferring
252  * we kick it to start the transfer.
253  */
254 upstrategy(bp)
255 register struct buf *bp;
256 {
257 	register struct buf *dp;
258 	register unit, xunit;
259 	long sz, bn;
260 
261 	if (upwstart == 0) {
262 		timeout((caddr_t)upwatch, 0, HZ);
263 		upwstart++;
264 	}
265 	xunit = minor(bp->b_dev) & 077;
266 	sz = bp->b_bcount;
267 	sz = (sz+511) >> 9;		/* transfer size in 512 byte sectors */
268 	unit = dkunit(bp);
269 	if (unit >= NUP ||
270 	    bp->b_blkno < 0 ||
271 	    (bn = dkblock(bp))+sz > up_sizes[xunit&07].nblocks) {
272 		bp->b_flags |= B_ERROR;
273 		iodone(bp);
274 		return;
275 	}
276 	bp->b_cylin = bn/(NSECT*NTRAC) + up_sizes[xunit&07].cyloff;
277 	dp = &uputab[unit];
278 	(void) spl5();
279 	disksort(dp, bp);
280 	if (dp->b_active == 0) {
281 		(void) upustart(unit);
282 		if (uptab.b_actf && uptab.b_active == 0)
283 			(void) upstart();
284 	}
285 	(void) spl0();
286 }
287 
288 /*
289  * Start activity on specified drive; called when drive is inactive
290  * and new transfer request arrives and also when upas indicates that
291  * a SEARCH command is complete.
292  */
293 upustart(unit)
294 register unit;
295 {
296 	register struct buf *bp, *dp;
297 	register struct device *upaddr = UPADDR;
298 	daddr_t bn;
299 	int sn, cn, csn;
300 	int didie = 0;
301 
302 	/*
303 	 * Other drivers tend to say something like
304 	 *	upaddr->upcs1 = IE;
305 	 *	upaddr->upas = 1<<unit;
306 	 * here, but the SC-11B will cancel a command which
307 	 * happens to be sitting in the cs1 if you clear the go
308 	 * bit by storing there (so the first is not safe),
309 	 * and it also does not like being bothered with operations
310 	 * such as clearing upas when a transfer is active (as
311 	 * it may well be.)
312 	 *
313 	 * Thus we keep careful track of when we re-enable IE
314 	 * after an interrupt and do it only if we didn't issue
315 	 * a command which re-enabled it as a matter of course.
316 	 * We clear bits in upas in the interrupt routine, when
317 	 * no transfers are active.
318 	 */
319 	if (unit >= NUP)
320 		goto out;
321 	if (unit+DK_N <= DK_NMAX)
322 		dk_busy &= ~(1<<(unit+DK_N));
323 	dp = &uputab[unit];
324 	if ((bp = dp->b_actf) == NULL)
325 		goto out;
326 	/*
327 	 * The SC-11B doesn't start SEARCH commands when transfers are
328 	 * in progress.  In fact, it tends to get confused when given
329 	 * SEARCH'es during transfers, generating interrupts with neither
330 	 * RDY nor a bit in the upas register.  Thus we defer
331 	 * until an interrupt when a transfer is pending.
332 	 */
333 	if (uptab.b_active) {
334 		upsoftas |= 1<<unit;
335 		return (0);
336 	}
337 	if (dp->b_active)
338 		goto done;
339 	dp->b_active = 1;
340 	if ((upaddr->upcs2 & 07) != unit) {
341 		upaddr->upcs2 = unit;
342 		DELAY(olducode ? osdelay : nsdelay);
343 		nwaitcs2++;
344 	} else
345 		neasycs2++;
346 	/*
347 	 * If we have changed packs or just initialized,
348 	 * then the volume will not be valid; if so, clear
349 	 * the drive, preset it and put in 16bit/word mode.
350 	 */
351 	if ((upaddr->upds & VV) == 0) {
352 		upaddr->upcs1 = IE|DCLR|GO;
353 		DELAY(idelay);
354 		upaddr->upcs1 = IE|PRESET|GO;
355 		DELAY(idelay);
356 		upaddr->upof = FMT22;
357 		didie = 1;
358 	}
359 	if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL))
360 		goto done;
361 	/*
362 	 * Do enough of the disk address decoding to determine
363 	 * which cylinder and sector the request is on.
364 	 * If we are on the correct cylinder and the desired sector
365 	 * lies between upSDIST and upSDIST+upRDIST sectors ahead of us, then
366 	 * we don't bother to SEARCH but just begin the transfer asap.
367 	 * Otherwise ask for a interrupt upSDIST sectors ahead.
368 	 */
369 	bn = dkblock(bp);
370 	cn = bp->b_cylin;
371 	sn = bn%(NSECT*NTRAC);
372 	sn = (sn+NSECT-upSDIST)%NSECT;
373 
374 	if (cn - upaddr->updc)
375 		goto search;		/* Not on-cylinder */
376 	else if (upseek)
377 		goto done;		/* Ok just to be on-cylinder */
378 	csn = (upaddr->upla>>6) - sn - 1;
379 	if (csn < 0)
380 		csn += NSECT;
381 	if (csn > NSECT-upRDIST)
382 		goto done;
383 
384 search:
385 	upaddr->updc = cn;
386 	if (upseek)
387 		upaddr->upcs1 = IE|SEEK|GO;
388 	else {
389 		upaddr->upda = sn;
390 		upaddr->upcs1 = IE|SEARCH|GO;
391 	}
392 	didie = 1;
393 	/*
394 	 * Mark this unit busy.
395 	 */
396 	unit += DK_N;
397 	if (unit <= DK_NMAX && DK_N+NUP <= DK_NMAX) {
398 		dk_busy |= 1<<unit;
399 		dk_numb[unit]++;
400 	}
401 	if (olducode)
402 		DELAY(ordelay);
403 	goto out;
404 
405 done:
406 	/*
407 	 * This unit is ready to go so
408 	 * link it onto the chain of ready disks.
409 	 */
410 	dp->b_forw = NULL;
411 	if (uptab.b_actf == NULL)
412 		uptab.b_actf = dp;
413 	else
414 		uptab.b_actl->b_forw = dp;
415 	uptab.b_actl = dp;
416 
417 out:
418 	return (didie);
419 }
420 
421 /*
422  * Start a transfer; call from top level at spl5() or on interrupt.
423  */
424 upstart()
425 {
426 	register struct buf *bp, *dp;
427 	register unit;
428 	register struct device *upaddr;
429 	daddr_t bn;
430 	int dn, sn, tn, cn, cmd;
431 
432 loop:
433 	/*
434 	 * Pick a drive off the queue of ready drives, and
435 	 * perform the first transfer on its queue.
436 	 *
437 	 * Looping here is completely for the sake of drives which
438 	 * are not present and on-line, for which we completely clear the
439 	 * request queue.
440 	 */
441 	if ((dp = uptab.b_actf) == NULL)
442 		return (0);
443 	if ((bp = dp->b_actf) == NULL) {
444 		uptab.b_actf = dp->b_forw;
445 		goto loop;
446 	}
447 	/*
448 	 * Mark the controller busy, and multi-part disk address.
449 	 * Select the unit on which the i/o is to take place.
450 	 */
451 	uptab.b_active++;
452 	unit = minor(bp->b_dev) & 077;
453 	dn = dkunit(bp);
454 	bn = dkblock(bp);
455 	cn = up_sizes[unit&07].cyloff;
456 	cn += bn/(NSECT*NTRAC);
457 	sn = bn%(NSECT*NTRAC);
458 	tn = sn/NSECT;
459 	sn %= NSECT;
460 	upaddr = UPADDR;
461 	if ((upaddr->upcs2 & 07) != dn) {
462 		upaddr->upcs2 = dn;
463 		/* DELAY(sdelay);		Provided by ubasetup() */
464 		nwaitcs2++;
465 	} else
466 		neasycs2++;
467 	up_ubinfo = ubasetup(bp, 1);	/* Providing delay */
468 	/*
469 	 * If drive is not present and on-line, then
470 	 * get rid of this with an error and loop to get
471 	 * rid of the rest of its queued requests.
472 	 * (Then on to any other ready drives.)
473 	 */
474 	if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
475 		printf("!DPR || !MOL, unit %d, ds %o\n", dn, upaddr->upds);
476 		uptab.b_active = 0;
477 		uptab.b_errcnt = 0;
478 		dp->b_actf = bp->av_forw;
479 		dp->b_active = 0;
480 		bp->b_flags |= B_ERROR;
481 		iodone(bp);
482 		ubafree(up_ubinfo), up_ubinfo = 0;	/* A funny place ... */
483 		goto loop;
484 	}
485 	/*
486 	 * If this is a retry, then with the 16'th retry we
487 	 * begin to try offsetting the heads to recover the data.
488 	 */
489 	if (uptab.b_errcnt >= 16) {
490 		upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22;
491 		upaddr->upcs1 = IE|OFFSET|GO;
492 		DELAY(idelay);
493 		while (upaddr->upds & PIP)
494 			DELAY(25);
495 	}
496 	/*
497 	 * Now set up the transfer, retrieving the high
498 	 * 2 bits of the UNIBUS address from the information
499 	 * returned by ubasetup() for the cs1 register bits 8 and 9.
500 	 */
501 	upaddr->updc = cn;
502 	upaddr->upda = (tn << 8) + sn;
503 	upaddr->upba = up_ubinfo;
504 	upaddr->upwc = -bp->b_bcount / sizeof (short);
505 	cmd = (up_ubinfo >> 8) & 0x300;
506 	if (bp->b_flags & B_READ)
507 		cmd |= IE|RCOM|GO;
508 	else
509 		cmd |= IE|WCOM|GO;
510 	upaddr->upcs1 = cmd;
511 	/*
512 	 * This is a controller busy situation.
513 	 * Record in dk slot NUP+DK_N (after last drive)
514 	 * unless there aren't that many slots reserved for
515 	 * us in which case we record this as a drive busy
516 	 * (if there is room for that).
517 	 */
518 	unit = dn+DK_N;
519 	if (NUP+DK_N == DK_NMAX)
520 		unit = NUP+DK_N;
521 	if (unit <= DK_NMAX) {
522 		dk_busy |= 1<<unit;
523 		dk_numb[unit]++;
524 		dk_wds[unit] += bp->b_bcount>>6;
525 	}
526 	return (1);
527 }
528 
529 /*
530  * Handle a device interrupt.
531  *
532  * If the transferring drive needs attention, service it
533  * retrying on error or beginning next transfer.
534  * Service all other ready drives, calling ustart to transfer
535  * their blocks to the ready queue in uptab, and then restart
536  * the controller if there is anything to do.
537  */
538 upintr()
539 {
540 	register struct buf *bp, *dp;
541 	register unit;
542 	register struct device *upaddr = UPADDR;
543 	int as = upaddr->upas & 0377;
544 	int oupsoftas;
545 	int needie = 1;
546 
547 	(void) spl6();
548 	up_wticks = 0;
549 	if (uptab.b_active) {
550 		/*
551 		 * The drive is transferring, thus the hardware
552 		 * (say the designers) will only interrupt when the transfer
553 		 * completes; check for it anyways.
554 		 */
555 		if ((upaddr->upcs1 & RDY) == 0) {
556 			printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1,
557 			    upaddr->upds, upaddr->upwc);
558 			printf("as=%d act %d %d %d\n", as, uptab.b_active,
559 			    uputab[0].b_active, uputab[1].b_active);
560 		}
561 		/*
562 		 * Mark controller or drive not busy, and check for an
563 		 * error condition which may have resulted from the transfer.
564 		 */
565 		dp = uptab.b_actf;
566 		bp = dp->b_actf;
567 		unit = dkunit(bp);
568 		if (DK_N+NUP == DK_NMAX)
569 			dk_busy &= ~(1<<(DK_N+NUP));
570 		else if (DK_N+unit <= DK_NMAX)
571 			dk_busy &= ~(1<<(DK_N+unit));
572 		if ((upaddr->upcs2 & 07) != unit) {
573 			upaddr->upcs2 = unit;
574 			DELAY(olducode ? osdelay : nsdelay);
575 			nwaitcs2++;
576 		} else
577 			neasycs2++;
578 		if (upaddr->upds & ERR) {
579 			/*
580 			 * An error occurred, indeed.  Select this unit
581 			 * to get at the drive status (a SEARCH may have
582 			 * intervened to change the selected unit), and
583 			 * wait for the command which caused the interrupt
584 			 * to complete (DRY).
585 			 */
586 			while ((upaddr->upds & DRY) == 0)
587 				DELAY(25);
588 			/*
589 			 * After 28 retries (16 w/o servo offsets, and then
590 			 * 12 with servo offsets), or if we encountered
591 			 * an error because the drive is write-protected,
592 			 * give up.  Print an error message on the last 2
593 			 * retries before a hard failure.
594 			 */
595 			if (++uptab.b_errcnt > 28 || upaddr->uper1&WLE)
596 				bp->b_flags |= B_ERROR;
597 			else
598 				uptab.b_active = 0;	/* To force retry */
599 			if (uptab.b_errcnt > 27)
600 				deverror(bp, upaddr->upcs2, upaddr->uper1);
601 			/*
602 			 * If this was a correctible ECC error, let upecc
603 			 * do the dirty work to correct it.  If upecc
604 			 * starts another READ for the rest of the data
605 			 * then it returns 1 (having set uptab.b_active).
606 			 * Otherwise we are done and fall through to
607 			 * finish up.
608 			 */
609 			if ((upaddr->uper1&(DCK|ECH))==DCK && upecc(upaddr, bp))
610 				return;
611 			/*
612 			 * Clear the drive and, every 4 retries, recalibrate
613 			 * to hopefully help clear up seek positioning problems.
614 			 */
615 			upaddr->upcs1 = TRE|IE|DCLR|GO;
616 			DELAY(idelay);
617 			needie = 0;
618 			if ((uptab.b_errcnt&07) == 4) {
619 				upaddr->upcs1 = RECAL|GO|IE;
620 				DELAY(idelay);
621 				while(upaddr->upds & PIP)
622 					DELAY(25);
623 			}
624 		}
625 		/*
626 		 * If we are still noted as active, then no
627 		 * (further) retries are necessary.
628 		 *
629 		 * Make sure the correct unit is selected,
630 		 * return it to centerline if necessary, and mark
631 		 * this i/o complete, starting the next transfer
632 		 * on this drive with the upustart routine (if any).
633 		 */
634 		if (uptab.b_active) {
635 			if (uptab.b_errcnt >= 16) {
636 				upaddr->upcs1 = RTC|GO|IE;
637 				DELAY(idelay);
638 				while (upaddr->upds & PIP)
639 					DELAY(25);
640 				needie = 0;
641 			}
642 			uptab.b_active = 0;
643 			uptab.b_errcnt = 0;
644 			uptab.b_actf = dp->b_forw;
645 			dp->b_active = 0;
646 			dp->b_errcnt = 0;
647 			dp->b_actf = bp->av_forw;
648 			bp->b_resid = (-upaddr->upwc * sizeof(short));
649 			if (bp->b_resid)
650 				printf("resid %d ds %o er? %o %o %o\n",
651 				    bp->b_resid, upaddr->upds,
652 				    upaddr->uper1, upaddr->uper2, upaddr->uper3);
653 			iodone(bp);
654 			if(dp->b_actf)
655 				if (upustart(unit))
656 					needie = 0;
657 		}
658 		as &= ~(1<<unit);
659 		upsoftas &= ~(1<<unit);
660 		ubafree(up_ubinfo), up_ubinfo = 0;
661 	} else {
662 		if (upaddr->upcs1 & TRE) {
663 			upaddr->upcs1 = TRE;
664 			DELAY(idelay);
665 		}
666 	}
667 	/*
668 	 * If we have a unit with an outstanding SEARCH,
669 	 * and the hardware indicates the unit requires attention,
670 	 * the bring the drive to the ready queue.
671 	 * Finally, if the controller is not transferring
672 	 * start it if any drives are now ready to transfer.
673 	 */
674 	as |= upsoftas;
675 	oupsoftas = upsoftas;
676 	upsoftas = 0;
677 	for (unit = 0; unit < NUP; unit++)
678 		if ((as|oupsoftas) & (1<<unit)) {
679 			if (as & (1<<unit)) {
680 				upaddr->upas = 1<<unit;
681 				if (olducode)
682 					DELAY(oasdel);
683 			}
684 			if (upustart(unit))
685 				needie = 0;
686 		}
687 	if (uptab.b_actf && uptab.b_active == 0)
688 		if (upstart())
689 			needie = 0;
690 out:
691 	if (needie)
692 		upaddr->upcs1 = IE;
693 }
694 
695 upread(dev)
696 {
697 
698 	physio(upstrategy, &rupbuf, dev, B_READ, minphys);
699 }
700 
701 upwrite(dev)
702 {
703 
704 	physio(upstrategy, &rupbuf, dev, B_WRITE, minphys);
705 }
706 
707 /*
708  * Correct an ECC error, and restart the i/o to complete
709  * the transfer if necessary.  This is quite complicated because
710  * the transfer may be going to an odd memory address base and/or
711  * across a page boundary.
712  */
713 upecc(up, bp)
714 register struct device *up;
715 register struct buf *bp;
716 {
717 	struct uba_regs *ubp = (struct uba_regs *)UBA0;
718 	register int i;
719 	caddr_t addr;
720 	int reg, bit, byte, npf, mask, o, cmd, ubaddr;
721 	int bn, cn, tn, sn;
722 
723 	/*
724 	 * Npf is the number of sectors transferred before the sector
725 	 * containing the ECC error, and reg is the UBA register
726 	 * mapping (the first part of) the transfer.
727 	 * O is offset within a memory page of the first byte transferred.
728 	 */
729 	npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
730 	reg = btop(up_ubinfo&0x3ffff) + npf;
731 	o = (int)bp->b_un.b_addr & PGOFSET;
732 	printf("%D ", bp->b_blkno+npf);
733 	prdev("ECC", bp->b_dev);
734 	mask = up->upec2;
735 	if (mask == 0) {
736 		up->upof = FMT22;		/* == RTC ???? */
737 		DELAY(idelay);
738 		return (0);
739 	}
740 	/*
741 	 * Flush the buffered data path, and compute the
742 	 * byte and bit position of the error.  The variable i
743 	 * is the byte offset in the transfer, the variable byte
744 	 * is the offset from a page boundary in main memory.
745 	 */
746 	ubp->uba_dpr[(up_ubinfo>>28)&0x0f] |= BNE;
747 	i = up->upec1 - 1;		/* -1 makes 0 origin */
748 	bit = i&07;
749 	i = (i&~07)>>3;
750 	byte = i + o;
751 	/*
752 	 * Correct while possible bits remain of mask.  Since mask
753 	 * contains 11 bits, we continue while the bit offset is > -11.
754 	 * Also watch out for end of this block and the end of the whole
755 	 * transfer.
756 	 */
757 	while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
758 		addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
759 		    (byte & PGOFSET);
760 		putmemc(addr, getmemc(addr)^(mask<<bit));
761 		byte++;
762 		i++;
763 		bit -= 8;
764 	}
765 	uptab.b_active++;	/* Either complete or continuing... */
766 	if (up->upwc == 0)
767 		return (0);
768 	/*
769 	 * Have to continue the transfer... clear the drive,
770 	 * and compute the position where the transfer is to continue.
771 	 * We have completed npf+1 sectors of the transfer already;
772 	 * restart at offset o of next sector (i.e. in UBA register reg+1).
773 	 */
774 	up->upcs1 = TRE|IE|DCLR|GO;
775 	DELAY(idelay);
776 	bn = dkblock(bp);
777 	cn = bp->b_cylin;
778 	sn = bn%(NSECT*NTRAC) + npf + 1;
779 	tn = sn/NSECT;
780 	sn %= NSECT;
781 	cn += tn/NTRAC;
782 	tn %= NTRAC;
783 	up->updc = cn;
784 	up->upda = (tn << 8) | sn;
785 	ubaddr = (int)ptob(reg+1) + o;
786 	up->upba = ubaddr;
787 	cmd = (ubaddr >> 8) & 0x300;
788 	cmd |= IE|GO|RCOM;
789 	up->upcs1 = cmd;
790 	return (1);
791 }
792 
793 /*
794  * Reset driver after UBA init.
795  * Cancel software state of all pending transfers
796  * and restart all units and the controller.
797  */
798 upreset()
799 {
800 	int unit;
801 
802 	printf(" up");
803 	uptab.b_active = 0;
804 	uptab.b_actf = uptab.b_actl = 0;
805 	if (DK_N+NUP == DK_NMAX)
806 		dk_busy &= ~(1<<(DK_N+NUP));
807 	if (up_ubinfo) {
808 		printf("<%d>", (up_ubinfo>>28)&0xf);
809 		ubafree(up_ubinfo), up_ubinfo = 0;
810 	}
811 	UPADDR->upcs2 = CLR;		/* clear controller */
812 	DELAY(idelay);
813 	for (unit = 0; unit < NUP; unit++) {
814 		uputab[unit].b_active = 0;
815 		(void) upustart(unit);
816 	}
817 	(void) upstart();
818 }
819 
820 /*
821  * Wake up every second and if an interrupt is pending
822  * but nothing has happened increment a counter.
823  * If nothing happens for 20 seconds, reset the controller
824  * and begin anew.
825  */
826 upwatch()
827 {
828 	int i;
829 
830 	timeout((caddr_t)upwatch, 0, HZ);
831 	if (uptab.b_active == 0) {
832 		for (i = 0; i < NUP; i++)
833 			if (uputab[i].b_active)
834 				goto active;
835 		up_wticks = 0;		/* idling */
836 		return;
837 	}
838 active:
839 	up_wticks++;
840 	if (up_wticks >= 20) {
841 		up_wticks = 0;
842 		printf("LOST INTERRUPT RESET");
843 		upreset();
844 		printf("\n");
845 	}
846 }
847