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