xref: /csrg-svn/sys/vax/uba/up.c (revision 2395)
1 /*	up.c	4.13	81/02/10	*/
2 
3 #include "up.h"
4 #if NSC21 > 0
5 /*
6  * UNIBUS disk driver with overlapped seeks and ECC recovery.
7  */
8 #define	DELAY(N)		{ register int d; d = N; while (--d > 0); }
9 
10 #include "../h/param.h"
11 #include "../h/systm.h"
12 #include "../h/cpu.h"
13 #include "../h/nexus.h"
14 #include "../h/dk.h"
15 #include "../h/buf.h"
16 #include "../h/conf.h"
17 #include "../h/dir.h"
18 #include "../h/user.h"
19 #include "../h/map.h"
20 #include "../h/pte.h"
21 #include "../h/mba.h"
22 #include "../h/mtpr.h"
23 #include "../h/uba.h"
24 #include "../h/vm.h"
25 #include "../h/cmap.h"
26 
27 #include "../h/upreg.h"
28 
29 struct	up_softc {
30 	int	sc_softas;
31 	int	sc_seek;
32 	int	sc_info;
33 	int	sc_wticks;
34 } up_softc[NSC21];
35 
36 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
37 struct	size
38 {
39 	daddr_t	nblocks;
40 	int	cyloff;
41 } up_sizes[8] = {
42 	15884,	0,		/* A=cyl 0 thru 26 */
43 	33440,	27,		/* B=cyl 27 thru 81 */
44 	495520,	0,		/* C=cyl 0 thru 814 */
45 	15884,	562,		/* D=cyl 562 thru 588 */
46 	55936,	589,		/* E=cyl 589 thru 680 */
47 	81472,	681,		/* F=cyl 681 thru 814 */
48 	153824,	562,		/* G=cyl 562 thru 814 */
49 	291346,	82,		/* H=cyl 82 thru 561 */
50 }, fj_sizes[8] = {
51 	15884,	0,		/* A=cyl 0 thru 49 */
52 	33440,	50,		/* B=cyl 50 thru 154 */
53 	263360,	0,		/* C=cyl 0 thru 822 */
54 	0,	0,
55 	0,	0,
56 	0,	0,
57 	0,	0,
58 	213760,	155,		/* H=cyl 155 thru 822 */
59 };
60 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
61 
62 #define	_upSDIST	2		/* 1.0 msec */
63 #define	_upRDIST	4		/* 2.0 msec */
64 
65 int	upSDIST = _upSDIST;
66 int	upRDIST = _upRDIST;
67 
68 int	upcntrlr(), upslave(), updgo(), upintr();
69 struct	uba_minfo *upminfo[NSC21];
70 struct	uba_dinfo *updinfo[NUP];
71 struct	uba_minfo up_minfo[NSC21];
72 	/* there is no reason for this to be a global structure, it
73 	   is only known/used locally, it would be better combined
74 	   with up_softc - but that would mean I would have to alter
75 	   more than I want to just now. Similarly, there is no longer
76 	   any real need for upminfo, but the code still uses it so ...
77 	*/
78 
79 u_short	upstd[] = { 0 };
80 int	(*upivec[])() = { upintr, 0 };
81 struct	uba_driver updriver =
82 	{ upcntrlr, upslave, updgo, 4, 0, upstd, updinfo, upivec };
83 struct	buf	uputab[NUP];
84 
85 struct	upst {
86 	short	nsect;
87 	short	ntrak;
88 	short	nspc;
89 	short	ncyl;
90 	struct	size *sizes;
91 } upst[] = {
92 	32,	19,	32*19,	815,	up_sizes,	/* 9300 */
93 	32,	19,	32*19,	823,	up_sizes,	/* so cdc will boot */
94 	32,	10,	32*10,	823,	fj_sizes,	/* fujitsu 160m */
95 };
96 
97 int	up_offset[16] =
98 {
99 	P400, M400, P400, M400,
100 	P800, M800, P800, M800,
101 	P1200, M1200, P1200, M1200,
102 	0, 0, 0, 0,
103 };
104 
105 struct	buf	rupbuf;			/* GROT */
106 
107 #define	b_cylin b_resid
108 
109 #ifdef INTRLVE
110 daddr_t dkblock();
111 #endif
112 
113 int	upwstart, upwatch();		/* Have started guardian */
114 
115 /*ARGSUSED*/
116 upcntrlr(um, reg)
117 	struct uba_minfo *um;
118 	caddr_t reg;
119 {
120 	((struct device *)reg)->upcs1 |= (IE|RDY);
121 	return(1);			/* just assume it is us (for now) */
122 }
123 
124 upslave(ui, reg, slaveno, uban)
125 	struct uba_dinfo *ui;
126 	caddr_t reg;
127 {
128 	register struct device *upaddr = (struct device *)reg;
129 	register struct uba_minfo *um;
130 	register int sc21;
131 
132 	upaddr->upcs1 = 0;		/* conservative */
133 	upaddr->upcs2 = slaveno;
134 	if (upaddr->upcs2&NED) {
135 		upaddr->upcs1 = DCLR|GO;
136 		return (0);
137 	}
138 	/*** we should check device type (return 0 if we don't like it) ***/
139 	/*** and set type index in ui->ui_type, but we KNOW all we are  ***/
140 	/*** going to see at the minute is a 9300, and the index for a  ***/
141 	/*** 9300 is 0, which is the value already in ui->ui_type, so ..***/
142 
143 	um = &up_minfo[0];
144 	for (sc21 = 0; sc21 < NSC21; sc21++) {
145 		if (um->um_alive == 0) {	/* this is a new ctrlr */
146 			um->um_addr = reg;
147 			um->um_ubanum = uban;
148 			um->um_num = sc21;	/* not needed after up_softc
149 						   combined with um ???  */
150 			um->um_alive = 1;
151 			upminfo[sc21] = um;	/* just till upminfo vanishes */
152 			goto found;
153 		}
154 		if (um->um_addr == reg && um->um_ubanum == uban)
155 			goto found;
156 		um++;
157 	}
158 	return(0);				/* too many sc21's */
159 
160     found:
161 	ui->ui_mi = um;
162 
163 	if (upwstart == 0) {
164 		timeout(upwatch, (caddr_t)0, HZ);
165 		upwstart++;
166 	}
167 	return (1);
168 }
169 
170 /*
171 	dk_mspw[UPDK_N+unit] = .0000020345;
172 */
173 
174 upstrategy(bp)
175 	register struct buf *bp;
176 {
177 	register struct uba_dinfo *ui;
178 	register struct uba_minfo *um;
179 	register struct upst *st;
180 	register int unit;
181 	int xunit = minor(bp->b_dev) & 07;
182 	long sz, bn;
183 
184 	sz = bp->b_bcount;
185 	sz = (sz+511) >> 9;		/* transfer size in 512 byte sectors */
186 	unit = dkunit(bp);
187 	if (unit >= NUP)
188 		goto bad;
189 	ui = updinfo[unit];
190 	if (ui == 0 || ui->ui_alive == 0)
191 		goto bad;
192 	st = &upst[ui->ui_type];
193 	if (bp->b_blkno < 0 ||
194 	    (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
195 		goto bad;
196 	bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
197 	(void) spl5();
198 	disksort(&uputab[ui->ui_unit], bp);
199 	if (uputab[ui->ui_unit].b_active == 0) {
200 		(void) upustart(ui);
201 		bp = &ui->ui_mi->um_tab;
202 		if (bp->b_actf && bp->b_active == 0)
203 			(void) upstart(ui->ui_mi);
204 	}
205 	(void) spl0();
206 	return;
207 
208 bad:
209 	bp->b_flags |= B_ERROR;
210 	iodone(bp);
211 	return;
212 }
213 
214 upustart(ui)
215 	register struct uba_dinfo *ui;
216 {
217 	register struct buf *bp, *dp;
218 	register struct uba_minfo *um;
219 	register struct device *upaddr;
220 	register struct upst *st;
221 	daddr_t bn;
222 	int sn, cn, csn;
223 	int didie = 0;
224 
225 	/* SC21 cancels commands if you say cs1 = IE, so dont */
226 	/* being ultra-cautious, we clear as bits only in upintr() */
227 	dk_busy &= ~(1<<ui->ui_dk);
228 	dp = &uputab[ui->ui_unit];
229 	if ((bp = dp->b_actf) == NULL)
230 		goto out;
231 	/* dont confuse controller by giving SEARCH while dt in progress */
232 	um = ui->ui_mi;
233 	if (um->um_tab.b_active) {
234 		up_softc[um->um_num].sc_softas |= 1<<ui->ui_slave;
235 		return (0);
236 	}
237 	if (dp->b_active)
238 		goto done;
239 	dp->b_active = 1;
240 	upaddr = (struct device *)um->um_addr;
241 	upaddr->upcs2 = ui->ui_slave;
242 	if ((upaddr->upds & VV) == 0) {
243 		upaddr->upcs1 = IE|DCLR|GO;
244 		upaddr->upcs1 = IE|PRESET|GO;
245 		upaddr->upof = FMT22;
246 		didie = 1;
247 	}
248 	if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL))
249 		goto done;
250 	st = &upst[ui->ui_type];
251 	bn = dkblock(bp);
252 	cn = bp->b_cylin;
253 	sn = bn%st->nspc;
254 	sn = (sn + st->nsect - upSDIST) % st->nsect;
255 	if (cn - upaddr->updc)
256 		goto search;		/* Not on-cylinder */
257 /****				WHAT SHOULD THIS BE NOW ???
258 	else if (upseek)
259 		goto done;		/* Ok just to be on-cylinder */
260 	csn = (upaddr->upla>>6) - sn - 1;
261 	if (csn < 0)
262 		csn += st->nsect;
263 	if (csn > st->nsect - upRDIST)
264 		goto done;
265 search:
266 	upaddr->updc = cn;
267 /***				ANOTHER OCCURRENCE
268 	if (upseek)
269 		upaddr->upcs1 = IE|SEEK|GO;
270 	else  ****/   {
271 		upaddr->upda = sn;
272 		upaddr->upcs1 = IE|SEARCH|GO;
273 	}
274 	didie = 1;
275 	if (ui->ui_dk >= 0) {
276 		dk_busy |= 1<<ui->ui_dk;
277 		dk_seek[ui->ui_dk]++;
278 	}
279 	goto out;
280 done:
281 	dp->b_forw = NULL;
282 	if (um->um_tab.b_actf == NULL)
283 		um->um_tab.b_actf = dp;
284 	else
285 		um->um_tab.b_actl->b_forw = dp;
286 	um->um_tab.b_actl = dp;
287 out:
288 	return (didie);
289 }
290 
291 upstart(um)
292 	register struct uba_minfo *um;
293 {
294 	register struct buf *bp, *dp;
295 	register struct uba_dinfo *ui;
296 	register unit;
297 	register struct device *upaddr;
298 	register struct upst *st;
299 	daddr_t bn;
300 	int dn, sn, tn, cn, cmd;
301 
302 loop:
303 	if ((dp = um->um_tab.b_actf) == NULL)
304 		return (0);
305 	if ((bp = dp->b_actf) == NULL) {
306 		um->um_tab.b_actf = dp->b_forw;
307 		goto loop;
308 	}
309 	/*
310 	 * Mark the controller busy, and multi-part disk address.
311 	 * Select the unit on which the i/o is to take place.
312 	 */
313 	um->um_tab.b_active++;
314 	ui = updinfo[dkunit(bp)];
315 	bn = dkblock(bp);
316 	dn = ui->ui_slave;
317 	st = &upst[ui->ui_type];
318 	sn = bn%st->nspc;
319 	tn = sn/st->nsect;
320 	sn %= st->nsect;
321 	upaddr = (struct device *)ui->ui_addr;
322 	if ((upaddr->upcs2 & 07) != dn)
323 		upaddr->upcs2 = dn;
324 	up_softc[um->um_num].sc_info =
325 	    ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP|UBA_CANTWAIT);
326 	/*
327 	 * If drive is not present and on-line, then
328 	 * get rid of this with an error and loop to get
329 	 * rid of the rest of its queued requests.
330 	 * (Then on to any other ready drives.)
331 	 */
332 	if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
333 		printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds);
334 		if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
335 			printf("-- hard\n");
336 			um->um_tab.b_active = 0;
337 			um->um_tab.b_errcnt = 0;
338 			dp->b_actf = bp->av_forw;
339 			dp->b_active = 0;
340 			bp->b_flags |= B_ERROR;
341 			iodone(bp);
342 			/* A funny place to do this ... */
343 			ubarelse(&up_softc[um->um_num].sc_info);
344 			goto loop;
345 		}
346 		printf("-- came back\n");
347 	}
348 	/*
349 	 * If this is a retry, then with the 16'th retry we
350 	 * begin to try offsetting the heads to recover the data.
351 	 */
352 	if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) {
353 		upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | FMT22;
354 		upaddr->upcs1 = IE|OFFSET|GO;
355 		while (upaddr->upds & PIP)
356 			DELAY(25);
357 	}
358 	/*
359 	 * Now set up the transfer, retrieving the high
360 	 * 2 bits of the UNIBUS address from the information
361 	 * returned by ubasetup() for the cs1 register bits 8 and 9.
362 	 */
363 	upaddr->updc = cn;
364 	upaddr->upda = (tn << 8) + sn;
365 	upaddr->upba = up_softc[um->um_num].sc_info;
366 	upaddr->upwc = -bp->b_bcount / sizeof (short);
367 	cmd = (up_softc[um->um_num].sc_info >> 8) & 0x300;
368 	if (bp->b_flags & B_READ)
369 		cmd |= IE|RCOM|GO;
370 	else
371 		cmd |= IE|WCOM|GO;
372 	upaddr->upcs1 = cmd;
373 	/*
374 	 * This is a controller busy situation.
375 	 * Record in dk slot NUP+UPDK_N (after last drive)
376 	 * unless there aren't that many slots reserved for
377 	 * us in which case we record this as a drive busy
378 	 * (if there is room for that).
379 	 */
380 	unit = ui->ui_dk;
381 	dk_busy |= 1<<unit;
382 	dk_xfer[unit]++;
383 	dk_wds[unit] += bp->b_bcount>>6;
384 	return (1);
385 }
386 
387 updgo()
388 {
389 }
390 
391 /*
392  * Handle a device interrupt.
393  *
394  * If the transferring drive needs attention, service it
395  * retrying on error or beginning next transfer.
396  * Service all other ready drives, calling ustart to transfer
397  * their blocks to the ready queue in um->um_tab, and then restart
398  * the controller if there is anything to do.
399  */
400 upintr(sc21)
401 	register sc21;
402 {
403 	register struct buf *bp, *dp;
404 	register struct uba_minfo *um = upminfo[sc21];
405 	register struct uba_dinfo *ui;
406 	register struct device *upaddr = (struct device *)um->um_addr;
407 	register unit;
408 	int as = upaddr->upas & 0377;
409 	int needie = 1;
410 
411 	(void) spl6();
412 	up_softc[um->um_num].sc_wticks = 0;
413 	if (um->um_tab.b_active) {
414 		if ((upaddr->upcs1 & RDY) == 0) {
415 			printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1,
416 			    upaddr->upds, upaddr->upwc);
417 			printf("as=%d act %d %d %d\n", as, um->um_tab.b_active,
418 			    uputab[0].b_active, uputab[1].b_active);
419 		}
420 		dp = um->um_tab.b_actf;
421 		bp = dp->b_actf;
422 		ui = updinfo[dkunit(bp)];
423 		dk_busy &= ~(1 << ui->ui_dk);
424 		upaddr->upcs2 = ui->ui_slave;
425 		if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) {
426 			int cs2;
427 			while ((upaddr->upds & DRY) == 0)
428 				DELAY(25);
429 			if (++um->um_tab.b_errcnt > 28 || upaddr->uper1&WLE)
430 				bp->b_flags |= B_ERROR;
431 			else
432 				um->um_tab.b_active = 0; /* force retry */
433 			if (um->um_tab.b_errcnt > 27) {
434 				cs2 = (int)upaddr->upcs2;
435 				deverror(bp, cs2, (int)upaddr->uper1);
436 			}
437 			if ((upaddr->uper1&(DCK|ECH))==DCK && upecc(ui))
438 				return;
439 			upaddr->upcs1 = TRE|IE|DCLR|GO;
440 			needie = 0;
441 			if ((um->um_tab.b_errcnt&07) == 4) {
442 				upaddr->upcs1 = RECAL|GO|IE;
443 				while(upaddr->upds & PIP)
444 					DELAY(25);
445 			}
446 			if (um->um_tab.b_errcnt == 28 && cs2&(NEM|MXF)) {
447 				printf("FLAKEY UP ");
448 				ubareset(um->um_ubanum);
449 				return;
450 			}
451 		}
452 		if (um->um_tab.b_active) {
453 			if (um->um_tab.b_errcnt >= 16) {
454 				upaddr->upcs1 = RTC|GO|IE;
455 				while (upaddr->upds & PIP)
456 					DELAY(25);
457 				needie = 0;
458 			}
459 			um->um_tab.b_active = 0;
460 			um->um_tab.b_errcnt = 0;
461 			um->um_tab.b_actf = dp->b_forw;
462 			dp->b_active = 0;
463 			dp->b_errcnt = 0;
464 			dp->b_actf = bp->av_forw;
465 			bp->b_resid = (-upaddr->upwc * sizeof(short));
466 			if (bp->b_resid)
467 				printf("resid %d ds %o er? %o %o %o\n",
468 				    bp->b_resid, upaddr->upds,
469 				    upaddr->uper1, upaddr->uper2, upaddr->uper3);
470 			iodone(bp);
471 			if (dp->b_actf)
472 				if (upustart(ui))
473 					needie = 0;
474 		}
475 		up_softc[um->um_num].sc_softas &= ~(1<<ui->ui_slave);
476 		ubarelse(&up_softc[um->um_num].sc_info);
477 	} else {
478 		if (upaddr->upcs1 & TRE)
479 			upaddr->upcs1 = TRE;
480 	}
481 	as |= up_softc[um->um_num].sc_softas;
482 	for (unit = 0; unit < NUP; unit++) {
483 		if ((ui = updinfo[unit]) == 0 || ui->ui_mi != um)
484 			continue;
485 		if (as & (1<<unit)) {
486 			if (as & (1<<unit))
487 				upaddr->upas = 1<<unit;
488 			if (upustart(ui))
489 				needie = 0;
490 		}
491 	}
492 	if (um->um_tab.b_actf && um->um_tab.b_active == 0)
493 		if (upstart(um))
494 			needie = 0;
495 	if (needie)
496 		upaddr->upcs1 = IE;
497 }
498 
499 upread(dev)
500 {
501 	physio(upstrategy, &rupbuf, dev, B_READ, minphys);
502 }
503 
504 upwrite(dev)
505 {
506 	physio(upstrategy, &rupbuf, dev, B_WRITE, minphys);
507 }
508 
509 /*
510  * Correct an ECC error, and restart the i/o to complete
511  * the transfer if necessary.  This is quite complicated because
512  * the transfer may be going to an odd memory address base and/or
513  * across a page boundary.
514  */
515 upecc(ui)
516 	register struct uba_dinfo *ui;
517 {
518 	register struct device *up = (struct device *)ui->ui_addr;
519 	register struct buf *bp = uputab[ui->ui_unit].b_actf;
520 	register struct uba_minfo *um = ui->ui_mi;
521 	register struct upst *st;
522 	struct uba_regs *ubp = ui->ui_hd->uh_uba;
523 	register int i;
524 	caddr_t addr;
525 	int reg, bit, byte, npf, mask, o, cmd, ubaddr;
526 	int bn, cn, tn, sn;
527 
528 	/*
529 	 * Npf is the number of sectors transferred before the sector
530 	 * containing the ECC error, and reg is the UBA register
531 	 * mapping (the first part of) the transfer.
532 	 * O is offset within a memory page of the first byte transferred.
533 	 */
534 	npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
535 	reg = btop(up_softc[um->um_num].sc_info&0x3ffff) + npf;
536 	o = (int)bp->b_un.b_addr & PGOFSET;
537 	printf("%D ", bp->b_blkno+npf);
538 	prdev("ECC", bp->b_dev);
539 	mask = up->upec2;
540 	if (mask == 0) {
541 		up->upof = FMT22;		/* == RTC ???? */
542 		return (0);
543 	}
544 	/*
545 	 * Flush the buffered data path, and compute the
546 	 * byte and bit position of the error.  The variable i
547 	 * is the byte offset in the transfer, the variable byte
548 	 * is the offset from a page boundary in main memory.
549 	 */
550 	ubp->uba_dpr[(up_softc[um->um_num].sc_info>>28)&0x0f] |= UBA_BNE;
551 	i = up->upec1 - 1;		/* -1 makes 0 origin */
552 	bit = i&07;
553 	i = (i&~07)>>3;
554 	byte = i + o;
555 	/*
556 	 * Correct while possible bits remain of mask.  Since mask
557 	 * contains 11 bits, we continue while the bit offset is > -11.
558 	 * Also watch out for end of this block and the end of the whole
559 	 * transfer.
560 	 */
561 	while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
562 		addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
563 		    (byte & PGOFSET);
564 		putmemc(addr, getmemc(addr)^(mask<<bit));
565 		byte++;
566 		i++;
567 		bit -= 8;
568 	}
569 	um->um_tab.b_active++;	/* Either complete or continuing... */
570 	if (up->upwc == 0)
571 		return (0);
572 	/*
573 	 * Have to continue the transfer... clear the drive,
574 	 * and compute the position where the transfer is to continue.
575 	 * We have completed npf+1 sectors of the transfer already;
576 	 * restart at offset o of next sector (i.e. in UBA register reg+1).
577 	 */
578 	up->upcs1 = TRE|IE|DCLR|GO;
579 	bn = dkblock(bp);
580 	st = &upst[ui->ui_type];
581 	cn = bp->b_cylin;
582 	sn = bn%st->nspc + npf + 1;
583 	tn = sn/st->nsect;
584 	sn %= st->nsect;
585 	cn += tn/st->ntrak;
586 	tn %= st->ntrak;
587 	up->updc = cn;
588 	up->upda = (tn << 8) | sn;
589 	ubaddr = (int)ptob(reg+1) + o;
590 	up->upba = ubaddr;
591 	cmd = (ubaddr >> 8) & 0x300;
592 	cmd |= IE|GO|RCOM;
593 	up->upcs1 = cmd;
594 	return (1);
595 }
596 
597 /*
598  * Reset driver after UBA init.
599  * Cancel software state of all pending transfers
600  * and restart all units and the controller.
601  */
602 upreset(uban)
603 {
604 	register struct uba_minfo *um;
605 	register struct uba_dinfo *ui;
606 	register sc21, unit;
607 
608 	/* we should really delay the printf & DELAY till we know
609 	 * that there is at least one sc21 on this UBA, but then
610 	 * we would have to remember we had done it before, or the
611 	 * msg would come twice(or whatever) - but perhaps that
612 	 * wouldn't be such a bad thing - too many delays would
613 	 * be annoying however
614 	 */
615 	printf(" up");
616 	DELAY(15000000);		/* give it time to self-test */
617 	for (sc21 = 0; sc21 < NSC21; sc21++) {
618 		if ((um = upminfo[sc21]) == 0)
619 			continue;
620 		if (um->um_ubanum != uban)
621 			continue;
622 		if (!um->um_alive)
623 			continue;
624 		um->um_tab.b_active = 0;
625 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
626 		if (up_softc[um->um_num].sc_info) {
627 			printf("<%d>", (up_softc[um->um_num].sc_info>>28)&0xf);
628 			ubarelse(&up_softc[um->um_num].sc_info);
629 		}
630 		((struct device *)(um->um_addr))->upcs2 = CLR;
631 		for (unit = 0; unit < NUP; unit++) {
632 			if ((ui = updinfo[unit]) == 0)
633 				continue;
634 			if (ui->ui_alive == 0)
635 				continue;
636 			uputab[unit].b_active = 0;
637 			(void) upustart(ui);
638 		}
639 		(void) upstart(um);
640 	}
641 }
642 
643 /*
644  * Wake up every second and if an interrupt is pending
645  * but nothing has happened increment a counter.
646  * If nothing happens for 20 seconds, reset the controller
647  * and begin anew.
648  */
649 upwatch()
650 {
651 	register struct uba_minfo *um;
652 	register sc21, unit;
653 
654 	timeout(upwatch, (caddr_t)0, HZ);
655 	for (sc21 = 0; sc21 < NSC21; sc21++) {
656 		um = upminfo[sc21];
657 		if (um->um_tab.b_active == 0) {
658 			for (unit = 0; unit < NUP; unit++)
659 				if (updinfo[unit]->ui_mi == um &&
660 				    uputab[unit].b_active)
661 					goto active;
662 			up_softc[sc21].sc_wticks = 0;
663 			continue;
664 		}
665     active:
666 		up_softc[sc21].sc_wticks++;
667 		if (up_softc[sc21].sc_wticks >= 20) {
668 			up_softc[sc21].sc_wticks = 0;
669 			printf("LOST INTERRUPT RESET");
670 			upreset(um->um_ubanum);
671 			printf("\n");
672 		}
673 	}
674 }
675 
676 #define	DBSIZE	20
677 
678 updump(dev)
679 	dev_t dev;
680 {
681 	struct device *upaddr;
682 	char *start;
683 	int num, blk, unit, nsect, ntrak, nspc;
684 	struct size *sizes;
685 	register struct uba_regs *uba;
686 	register struct uba_dinfo *ui;
687 	register short *rp;
688 	struct upst *st;
689 	int bdp;
690 
691 	unit = minor(dev) >> 3;
692 	if (unit >= NUP) {
693 		printf("bad unit\n");
694 		return (-1);
695 	}
696 #define	phys1(cast, addr) ((cast)((int)addr & 0x7fffffff))
697 #define	phys(cast, addr) phys1(cast, phys1(cast *, &addr))
698 	ui = phys(struct uba_dinfo *, updinfo[unit]);
699 	if (ui->ui_alive == 0) {
700 		printf("dna\n");
701 		return(-1);
702 	}
703 	uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
704 #if VAX780
705 	if (cpu == VAX_780) {
706 		uba->uba_cr = UBA_ADINIT;
707 		uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE;
708 		while ((uba->uba_cnfgr & UBA_UBIC) == 0)
709 			;
710 	}
711 #endif
712 	DELAY(1000000);
713 	upaddr = (struct device *)ui->ui_physaddr;
714 	while ((upaddr->upcs1&DVA) == 0)
715 		;
716 	num = maxfree;
717 	start = 0;
718 	upaddr->upcs2 = unit;
719 	if ((upaddr->upds & VV) == 0) {
720 		upaddr->upcs1 = DCLR|GO;
721 		upaddr->upcs1 = PRESET|GO;
722 		upaddr->upof = FMT22;
723 	}
724 	if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
725 		printf("up !DPR || !MOL\n");
726 		return (-1);
727 	}
728 	st = phys1(struct upst *, &upst[ui->ui_type]);
729 	nsect = st->nsect;
730 	ntrak = st->ntrak;
731 	sizes = phys(struct size *, st->sizes);
732 	if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) {
733 		printf("oor\n");
734 		return (-1);
735 	}
736 	nspc = st->nspc;
737 	while (num > 0) {
738 		register struct pte *io;
739 		register int i;
740 		int cn, sn, tn;
741 		daddr_t bn;
742 
743 		blk = num > DBSIZE ? DBSIZE : num;
744 		bdp = 1;		/* trick pcc */
745 		uba->uba_dpr[bdp] |= UBA_BNE;
746 		io = uba->uba_map;
747 		for (i = 0; i < blk; i++)
748 			*(int *)io++ = (btop(start)+i) | (1<<21) | UBA_MRV;
749 		*(int *)io = 0;
750 		bn = dumplo + btop(start);
751 		cn = bn/nspc + sizes[minor(dev)&07].cyloff;
752 		sn = bn%nspc;
753 		tn = sn/nsect;
754 		sn = sn%nsect;
755 		upaddr->updc = cn;
756 		rp = (short *) &upaddr->upda;
757 		*rp = (tn << 8) + sn;
758 		*--rp = 0;
759 		*--rp = -blk*NBPG / sizeof (short);
760 		*--rp = GO|WCOM;
761 		do {
762 			DELAY(25);
763 		} while ((upaddr->upcs1 & RDY) == 0);
764 		if (upaddr->upcs1&ERR) {
765 			printf("up dump dsk err: (%d,%d,%d) cs1=%x, er1=%x\n",
766 			    cn, tn, sn, upaddr->upcs1, upaddr->uper1);
767 			return (-1);
768 		}
769 		start += blk*NBPG;
770 		num -= blk;
771 	}
772 	bdp = 1;		/* crud to fool c compiler */
773 	uba->uba_dpr[bdp] |= UBA_BNE;
774 	return (0);
775 }
776 #endif
777