|
|
1.1 root 1: static char *sccsid = "@(#)hk.c 1.1 (Berkeley) 10/10/80";
2:
3: /*
4: * RK07 disk driver with bad-sector forwarding
5: *
6: * This driver, revised from a UCSB RK07 driver, is modeled
7: * after the Stanford SI 9500 driver with bad-sector forwarding.
8: * The bad-sector information on the last track of each pack is
9: * used to patch up transfers by forwarding accesses to bad sectors
10: * to spares on the last cylinder. The last cylinder is otherwise
11: * write-protected.
12: * The bad-sector table is read when a minor device is first
13: * opened after a close. No Volume-Valid checking is done;
14: * hamfists beware. To be correct, the open routine needs a
15: * mechanism for reading drive status and for doing a PACKACK.
16: * A pack is 1 minor device; there is no pack mapping.
17: * No attempt at ECC logic is included. Be my guest.
18: *
19: * BUGS: The same bomb is planted here as in most UBA DMA drivers,
20: * to wit, ubasetup is called from the interrupt level. Ubasetup
21: * will sleep if it cannot allocate; ka-boom!
22: *
23: * Author: Rob Mathews, EE Information Systems Lab, Stanford 4/80
24: */
25:
26: /*
27: * Debug control
28: *
29: * 1 - open/close
30: * 2 - strategy
31: * 4 - intr entry/exit
32: * 8 - intr detail
33: * 16 - intr sector mapping
34: * 32 - strat errors/lock-opens
35: * 64 - bst reading
36: *1024 - loop after errors
37: */
38:
39: #define debug(bit) if (rk7debug & (bit)) printf
40: int rk7debug = (0);
41:
42: #include "../h/param.h"
43: #include "../h/systm.h"
44: #include "../h/buf.h"
45: #include "../h/conf.h"
46: #include "../h/dir.h"
47: #include "../h/user.h"
48: #include "../h/map.h"
49: #include "../h/pte.h"
50: #include "../h/uba.h"
51:
52: /*
53: * Disk parameters
54: */
55:
56: #define NRK7 8
57: #define NCYLS 815
58: #define NTRKS 3
59: #define NSECTS 22
60: #define NBYTES 512
61: #define NBLKS (NCYLS*NTRKS*NSECTS)
62: #define BSCYL (NCYLS-1) /* bad-sector repair cylinder */
63: #define BSBASE (BSCYL*NTRKS*NSECTS) /* track 0,1 - repair pool */
64: #define BSTBLK (BSBASE + 2*NSECTS) /* track 2 - bad-sector table */
65: #define MAXBB 10 /* max tolerable bad sectors */
66:
67: /*
68: * Register definitions
69: */
70:
71: #define RK7ADDR ((struct rk7_regs *)(UBA0_DEV + 0177440))
72:
73: struct rk7_regs
74: {
75: short rkcs1, rkwc;
76: unsigned short rkba;
77: short rkda, rkcs2, rkds, rker, rkasof, rkdc, rknull, rkdb, rkmr1;
78: short rkecps, rkecpt, rkmr2, rkmr3;
79: };
80:
81: /*
82: * Register bits, per RK07 manual
83: */
84:
85: #define GO 01 /* cs1 */
86: #define DRCLR 04
87: #define READ 020
88: #define WRITE 022
89: #define PACKACK 02
90: #define IE 0100
91: #define RDY 0200
92: #define BA1617 01400
93: #define CDT 02000
94: #define CERR 0100000
95: #define CCLR 0100000
96: #define SCLR 040 /* cs2 */
97: #define SVAL 0100000 /* ds */
98: #define DRDY 0200
99: #define VV 0100
100: #define DRA 01
101: #define DCK 0100000 /* er */
102: #define BSE 0200
103: #define NXF 04
104:
105: #define Error ((RK7ADDR->rkcs1 & CERR) != 0)
106:
107: /*
108: * Driver parameters, data, and definitions
109: */
110:
111: #define RETRIES 10
112:
113: #define IDLE 0
114: #define NORMAL 1
115: #define MAPPED 2
116: #define RESTART 3
117:
118: struct buf rk7tab, rk7bsbuf, rrk7buf;
119:
120: struct rk7
121: {
122: long access;
123: short retries, errors, mapped, spurious;
124: int ubinfo, rwcommand;
125: short unsigned errer, errcs2, errds;
126: short cylnow, trksecnow;
127: unsigned short wcnow;
128: long manow;
129: }
130: rk7;
131:
132: struct bb
133: {
134: short serial, zeros[2], alignpack;
135: struct bbtbl
136: {
137: short bbtcyl, bbtts;
138: }
139: bbt[MAXBB];
140: }
141: rk7bb[NRK7];
142: #define OPENF bbt[MAXBB-1].bbtcyl
143: #define LOCKF zeros[0]
144:
145: #define b_trksec av_back
146: #define b_cylin b_resid
147: #define nsects(x) x/NBYTES
148:
149: /*
150: */
151:
152: rk7open (dev, flag)
153: {
154: register struct bb *bbp;
155: register m;
156:
157: if ((m = minor (dev)) >= NRK7)
158: {
159: u.u_error = ENXIO;
160: return;
161: }
162: bbp = &rk7bb[m];
163: debug (1) ("open\n");
164: if (bbp->OPENF != -1)
165: {
166: bbp->OPENF = 1;
167: debug (1|64) ("bs read\n");
168:
169: rk7bsbuf.b_flags = B_BUSY | B_READ;
170: rk7bsbuf.b_dev = minor (dev); /* major better not matter ! */
171: rk7bsbuf.b_bcount = sizeof (struct bb);
172: rk7bsbuf.b_un.b_addr = (caddr_t) bbp;
173: rk7bsbuf.b_blkno = BSTBLK;
174: rk7bsbuf.b_error = 0;
175: rk7strategy (&rk7bsbuf);
176: iowait (&rk7bsbuf);
177:
178: if (rk7bsbuf.b_flags & B_ERROR)
179: {
180: printf ("rk7: error reading bad sector table!\n");
181: }
182: else if (bbp->OPENF != -1)
183: {
184: printf ("rk7: too many bad sectors, drive %d\n", m);
185: bbp->OPENF = -1;
186: }
187: wakeup (&bbp->OPENF);
188: debug (1|64) ("bs read done\n");
189: }
190: else
191: while (bbp->OPENF != -1)
192: sleep (&bbp->OPENF, PSWP);
193: }
194:
195: rk7close (dev, flag)
196: {
197: debug (1) ("close\n");
198: if (!rk7bb[minor (dev)].LOCKF)
199: rk7bb[minor (dev)].OPENF = 0;
200: }
201:
202: rk7strategy (bp)
203: register struct buf *bp;
204: {
205: debug (2) ("strat %s ", bp->b_flags & B_READ ? "r" : "w");
206: if (rk7bb[minor (bp->b_dev)].OPENF == 0)
207: {
208: rk7open (bp->b_dev, 0); /* in case root or swap is here */
209: rk7bb[minor (bp->b_dev)].LOCKF++;
210: debug (32) ("lock-open\n");
211: }
212:
213: if (bp->b_blkno + nsects (bp->b_bcount)
214: > (bp->b_flags & B_READ ? NBLKS : BSBASE))
215: {
216: debug (2|32) ("error, blk %d, dev %d\n",
217: bp->b_blkno, minor (bp->b_dev));
218: bp->b_flags |= B_ERROR;
219: iodone(bp);
220: return;
221: }
222:
223: debug (2) ("queue ");
224: bp->b_cylin = bp->b_blkno / (NTRKS*NSECTS);
225: bp->b_trksec = (struct buf *) ((((bp->b_blkno / NSECTS) % NTRKS) << 8)
226: + (bp->b_blkno % NSECTS));
227:
228: spl5();
229: disksort (&rk7tab, bp);
230:
231: if(rk7tab.b_active == IDLE)
232: rk7intr();
233: spl0();
234: debug (2) ("end\n");
235: }
236:
237: /*
238: disksort (tabp, bp)
239: register struct buf *tabp, bp;
240: {
241: bp->av_forw = (struct buf *)NULL;
242: if(tabp->b_actf == NULL)
243: tabp->b_actf = bp;
244: else
245: tabp->b_actl->av_forw = bp;
246: tabp->b_actl = bp;
247: }
248: */
249:
250: /*
251: * Interrupt (co)routine
252: */
253:
254: #define iwait(x) rk7tab.b_active = x; return; case x:
255: rk7intr()
256: {
257: register struct buf *bp;
258:
259: bp = rk7tab.b_actf;
260: switch (rk7tab.b_active)
261: {
262: case IDLE:
263: debug (4) ("intr ");
264: if (bp == NULL)
265: {
266: rk7.spurious++;
267: return;
268: }
269:
270: do { /* empty the queue */
271:
272: rk7.access++;
273: rk7tab.b_errcnt = 0;
274:
275: do { /* transfer */
276: register short s;
277: short rk7map (), ms;
278:
279: rk7.rwcommand = bp->b_flags & B_READ
280: ? (READ|IE|CDT|GO)
281: : (WRITE|IE|CDT|GO);
282: if (Error)
283: {
284: debug (8) ("clear ");
285: rk7clear ();
286: }
287:
288: RK7ADDR->rkcs2 = minor (bp->b_dev);
289: RK7ADDR->rkcs1 = PACKACK|CDT|GO;
290: while (RK7ADDR->rkcs1 & GO);
291:
292: debug (8) ("setup ");
293: rk7.ubinfo = ubasetup (bp, 1);
294: rk7start ( rk7.rwcommand,
295: (short) bp->b_cylin, (short)(long) bp->b_trksec,
296: (long) rk7.ubinfo,
297: (short) (-(bp->b_bcount>>1)));
298: debug (8) ("started ");
299: iwait (NORMAL);
300:
301: debug (8) ("NORMAL ");
302: while (RK7ADDR->rker == BSE && (ms = rk7map ()) != -1)
303: { /* forwarding */
304: rk7.mapped++;
305: debug (8|16) ("mapping ");
306:
307: rk7clear ();
308:
309: rk7start (rk7.rwcommand,
310: (short) BSCYL, (short) ms, (long) rk7.manow,
311: (short) (-(rk7.wcnow > NBYTES/2
312: ? NBYTES/2 : rk7.wcnow)));
313: iwait (MAPPED);
314:
315: debug (8|16) ("mapped\n");
316: if (!Error && rk7.wcnow > NBYTES/2)
317: {
318: debug (8|16) ("restarting ");
319: rk7restart ();
320: iwait (RESTART);
321: debug (8|16) ("restarted\n");
322: }
323: } /* forwarding */
324:
325: if (Error)
326: {
327: rk7.errer = RK7ADDR->rker;
328: rk7.errcs2 = RK7ADDR->rkcs2;
329: rk7.errds = RK7ADDR->rkds;
330: }
331: debug (8) (Error ? "error\n" : "free ");
332: ubafree (rk7.ubinfo);
333: } /* transfer */
334: while (Error && ++rk7tab.b_errcnt != RETRIES);
335:
336: if (rk7tab.b_errcnt != 0)
337: rk7errs (bp);
338:
339: debug (8) ("next\n");
340: bp->b_resid = 0;
341: rk7tab.b_actf = bp->av_forw;
342: iodone (bp);
343:
344: } /* empty the queue */
345: while ((bp = rk7tab.b_actf) != NULL);
346:
347: rk7tab.b_active = IDLE;
348: debug (4) ("exit\n");
349: return;
350: }
351: }
352:
353: rk7clear ()
354: {
355: register drive;
356:
357: drive = RK7ADDR->rkcs2 & 07;
358: RK7ADDR->rkcs1 = CCLR;
359: RK7ADDR->rkcs2 = drive;
360: RK7ADDR->rkcs1 = DRCLR|CDT|GO;
361: while ((RK7ADDR->rkcs1 & RDY) == 0);
362: }
363:
364: rk7start (rwcommand, cyl, tsect, mem, wc)
365: short cyl, tsect, wc;
366: long mem;
367: {
368: RK7ADDR->rkdc = cyl;
369: RK7ADDR->rkda = tsect;
370: RK7ADDR->rkba = mem;
371: RK7ADDR->rkwc = wc;
372: RK7ADDR->rkcs1 = ((mem >> 8) & BA1617) | rwcommand;
373: }
374:
375: short rk7map ()
376: {
377: register struct bbtbl *bbp;
378: register i;
379:
380: rk7.wcnow = -RK7ADDR->rkwc;
381: rk7.cylnow = RK7ADDR->rkdc;
382: rk7.trksecnow = RK7ADDR->rkda;
383: rk7.manow = (((long)(RK7ADDR->rkcs1 & BA1617)) << 8) + RK7ADDR->rkba;
384:
385: for (bbp = rk7bb[RK7ADDR->rkcs2 & 07].bbt, i = 0;
386: bbp->bbtcyl != -1 &&
387: (bbp->bbtcyl != rk7.cylnow || bbp->bbtts != rk7.trksecnow);
388: bbp++, i++);
389: return (bbp->bbtcyl == -1 ? -1 : i /* trk & sec */);
390: }
391:
392: rk7restart ()
393: {
394: register short ts;
395:
396: ts = rk7.trksecnow;
397: if ((++ts & 0377) == NSECTS)
398: if (((ts += (1<<8) - NSECTS) >> 8) == NTRKS)
399: {
400: ts = 0;
401: rk7.cylnow++;
402: }
403: rk7start (rk7.rwcommand, (short) rk7.cylnow, (short) ts,
404: (long) rk7.manow + NBYTES, (short) (-(rk7.wcnow - NBYTES/2)));
405: }
406:
407: rk7errs (bp)
408: register struct buf *bp;
409: {
410: register nerr;
411:
412: nerr = rk7tab.b_errcnt;
413: rk7.retries += nerr;
414: if (nerr == RETRIES)
415: {
416: bp->b_flags |= B_ERROR;
417: rk7.errors++;
418: printf ("Hard rk7 ");
419: }
420: else
421: printf ("%d * rk7 ", nerr);
422: deverror (bp, rk7.errer, rk7.errcs2);
423: printf ("ds %X\n", rk7.errds);
424: while (nerr == RETRIES && (rk7debug & 1024));
425: }
426:
427: rk7read(dev)
428: dev_t dev;
429: {
430:
431: physio(rk7strategy, &rrk7buf, dev, B_READ, minphys);
432: }
433:
434: rk7write(dev)
435: dev_t dev;
436: {
437:
438: physio(rk7strategy, &rrk7buf, dev, B_WRITE, minphys);
439: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.