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