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