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