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