|
|
1.1 root 1: /* hp.c 6.3 83/09/23 */
2:
3: /*
4: * RP??/RM?? disk driver
5: * with ECC handling and bad block forwarding.
6: * Also supports header io operations and
7: * commands to write check header and data.
8: */
9: #include "../h/param.h"
10: #include "../h/inode.h"
11: #include "../h/fs.h"
12: #include "../h/dkbad.h"
13:
14: #include "../vax/pte.h"
15: #include "../vaxmba/hpreg.h"
16: #include "../vaxmba/mbareg.h"
17:
18: #include "saio.h"
19: #include "savax.h"
20:
21: #define MASKREG(reg) ((reg)&0xffff)
22:
23: #define MAXBADDESC 126
24: #define SECTSIZ 512 /* sector size in bytes */
25: #define HDRSIZ 4 /* number of bytes in sector header */
26: #define MAXECC 5 /* max # bits allow in ecc error w/ F_ECCLM */
27:
28: char hp_type[MAXNMBA*8] = { 0 };
29: extern struct st hpst[];
30:
31: short hptypes[] = {
32: MBDT_RM03,
33: MBDT_RM05,
34: MBDT_RP06,
35: MBDT_RM80,
36: MBDT_RP05,
37: MBDT_RP07,
38: MBDT_ML11A,
39: MBDT_ML11B,
40: -1, /* 9755 */
41: -1, /* 9730 */
42: -1, /* Capricorn */
43: -1, /* Eagle */
44: MBDT_RM02, /* actually something else */
45: -1, /* 9300 */
46: 0
47: };
48:
49: #define RP06 (hptypes[hp_type[unit]] <= MBDT_RP06)
50: #define ML11 (hptypes[hp_type[unit]] == MBDT_ML11A)
51: #define RM80 (hptypes[hp_type[unit]] == MBDT_RM80)
52:
53: u_char hp_offset[16] = {
54: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
55: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
56: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
57: 0, 0, 0, 0,
58: };
59:
60: struct dkbad hpbad[MAXNMBA*8];
61: int ssect[MAXNMBA*8]; /* 1 when on track w/skip sector */
62:
63: int hpdebug[MAXNMBA*8];
64: #define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */
65: #define HPF_ECCDEBUG 02 /* debugging ecc correction */
66:
67: int sectsiz;
68:
69: /*
70: * When awaiting command completion, don't
71: * hang on to the status register since
72: * this ties up some controllers.
73: */
74: #define HPWAIT(addr) \
75: while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500);
76:
77: hpopen(io)
78: register struct iob *io;
79: {
80: register unit = io->i_unit;
81: struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
82: register struct st *st;
83:
84: mbainit(UNITTOMBA(unit));
85: if (hp_type[unit] == 0) {
86: register i, type = hpaddr->hpdt & MBDT_TYPE;
87: struct iob tio;
88:
89: for (i = 0; hptypes[i]; i++)
90: if (hptypes[i] == type)
91: goto found;
92: _stop("unknown drive type");
93: found:
94: hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */
95: hpaddr->hpcs1 = HP_PRESET|HP_GO;
96: if (!ML11)
97: hpaddr->hpof = HPOF_FMT22;
98: hp_type[unit] = hpmaptype(hpaddr, i, unit);
99: /*
100: * Read in the bad sector table.
101: */
102: st = &hpst[hp_type[unit]];
103: tio = *io;
104: tio.i_bn = st->nspc * st->ncyl - st->nsect;
105: tio.i_ma = (char *)&hpbad[unit];
106: tio.i_cc = sizeof (struct dkbad);
107: tio.i_flgs |= F_RDDATA;
108: for (i = 0; i < 5; i++) {
109: if (hpstrategy(&tio, READ) == sizeof (struct dkbad))
110: break;
111: tio.i_bn += 2;
112: }
113: if (i == 5) {
114: printf("Unable to read bad sector table\n");
115: for (i = 0; i < MAXBADDESC; i++) {
116: hpbad[unit].bt_bad[i].bt_cyl = -1;
117: hpbad[unit].bt_bad[i].bt_trksec = -1;
118: }
119: }
120: }
121: if (io->i_boff < 0 || io->i_boff > 7 ||
122: st->off[io->i_boff]== -1)
123: _stop("hp bad minor");
124: io->i_boff = st->off[io->i_boff] * st->nspc;
125: }
126:
127: hpstrategy(io, func)
128: register struct iob *io;
129: {
130: register unit = io->i_unit;
131: struct mba_regs *mba = mbamba(unit);
132: daddr_t bn, startblock;
133: struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
134: struct st *st = &hpst[hp_type[unit]];
135: int cn, tn, sn, bytecnt, bytesleft;
136: char *membase;
137: int er1, er2, hprecal;
138:
139: sectsiz = SECTSIZ;
140: if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0)
141: sectsiz += HDRSIZ;
142: if ((hpaddr->hpds & HPDS_VV) == 0) {
143: hpaddr->hpcs1 = HP_DCLR|HP_GO;
144: hpaddr->hpcs1 = HP_PRESET|HP_GO;
145: if (!ML11)
146: hpaddr->hpof = HPOF_FMT22;
147: }
148: io->i_errcnt = 0;
149: ssect[unit] = 0;
150: bytecnt = io->i_cc;
151: membase = io->i_ma;
152: startblock = io->i_bn;
153: hprecal = 0;
154:
155: restart:
156: bn = io->i_bn;
157: cn = bn/st->nspc;
158: sn = bn%st->nspc;
159: tn = sn/st->nsect;
160: sn = sn%st->nsect + ssect[unit];
161:
162: HPWAIT(hpaddr);
163: mba->mba_sr = -1;
164: if (ML11)
165: hpaddr->hpda = bn;
166: else {
167: hpaddr->hpdc = cn;
168: hpaddr->hpda = (tn << 8) + sn;
169: }
170: if (mbastart(io, func) != 0) /* start transfer */
171: return (-1);
172: HPWAIT(hpaddr);
173: /*
174: * Successful data transfer, return.
175: */
176: if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0)
177: goto done;
178:
179: /*
180: * Error handling. Calculate location of error.
181: */
182: bytesleft = MASKREG(mba->mba_bcr);
183: if (bytesleft)
184: bytesleft |= 0xffff0000; /* sxt */
185: bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz;
186: er1 = MASKREG(hpaddr->hper1);
187: er2 = MASKREG(hpaddr->hper2);
188: if (er1 & (HPER1_DCK|HPER1_ECH))
189: bn--; /* Error is in Prev block */
190: cn = bn/st->nspc;
191: sn = bn%st->nspc;
192: tn = sn/st->nsect;
193: sn = sn%st->nsect;
194: if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) {
195: printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b\n",
196: cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
197: printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS);
198: printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft,
199: hpaddr->hpof, hpaddr->hpda);
200: }
201: if (er1 & HPER1_HCRC) {
202: er1 &= ~(HPER1_HCE|HPER1_FER);
203: er2 &= ~HPER2_BSE;
204: }
205: /*
206: * Give up early if drive write locked.
207: */
208: if (er1&HPER1_WLE) {
209: printf("hp%d: write locked\n", unit);
210: return (-1);
211: }
212: /*
213: * Interpret format error bit as a bad block on RP06's.
214: */
215: if (MASKREG(er1) == HPER1_FER && RP06)
216: goto badsect;
217:
218: /*
219: * If a hard error, or maximum retry count
220: * exceeded, clear controller state and
221: * pass back error to caller.
222: */
223: if (++io->i_errcnt > 27 || (er1 & HPER1_HARD) ||
224: (!ML11 && (er2 & HPER2_HARD))) {
225: /*
226: * The last ditch effort to bad sector forward
227: * below will probably fail since mba byte ctr
228: * (bcr) is different for BSE and ECC errors and
229: * the wrong block will be revectored to if one
230: * has 2 contiguous bad blocks and reads the second.
231: * For now, we can probably just let a header CRC
232: * error be handled like a BSE since no data will
233: * have been transferred and the bcr should the same
234: * as it would with a BSE error.
235: * --ghg.
236: */
237: if (er1 & HPER1_HCRC)
238: if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0)
239: goto success;
240: hard0:
241: io->i_error = EHER;
242: if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR))
243: io->i_error = EWCK;
244: hard:
245: io->i_errblk = bn + ssect[unit];
246: printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n",
247: cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
248: printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS);
249: if (hpaddr->hpmr)
250: printf(" mr1=%o", MASKREG(hpaddr->hpmr));
251: if (hpaddr->hpmr2)
252: printf(" mr2=%o", MASKREG(hpaddr->hpmr2));
253: if (hpdebug[unit] & (HPF_BSEDEBUG|HPF_ECCDEBUG))
254: printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc),
255: MASKREG(hpaddr->hpda));
256: hpaddr->hpcs1 = HP_DCLR|HP_GO;
257: printf("\n");
258: bytecnt = -1;
259: goto done;
260:
261: }
262: /*
263: * Attempt to forward bad sectors on
264: * anything but an ML11. If drive
265: * supports skip sector handling, try to
266: * use it first; otherwise try the
267: * bad sector table.
268: */
269: if ((er2 & HPER2_BSE) && !ML11) {
270: badsect:
271: if (!ssect[unit] && (er2&HPER2_SSE))
272: goto skipsect;
273: if (io->i_flgs & F_NBSF) {
274: io->i_error = EBSE;
275: goto hard;
276: }
277: if (hpecc(io, BSE) == 0)
278: goto success;
279: io->i_error = EBSE;
280: goto hard;
281: }
282:
283: /*
284: * Skip sector handling.
285: */
286: if (RM80 && (er2 & HPER2_SSE)) {
287: skipsect:
288: (void) hpecc(io, SSE);
289: ssect[unit] = 1;
290: goto success;
291: }
292: /*
293: * ECC correction?
294: */
295: if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) {
296: if (hpecc(io, ECC) == 0)
297: goto success;
298: io->i_error = EECC;
299: io->i_errblk = bn + ssect[unit];
300: return (-1);
301: }
302: #ifdef F_SEVRE
303: if (io->i_flgs & F_SEVRE)
304: goto hard;
305: #endif
306: if (ML11 && (io->i_errcnt >= 16))
307: goto hard0;
308: /* fall thru to retry */
309: hpaddr->hpcs1 = HP_DCLR|HP_GO;
310: HPWAIT(hpaddr);
311:
312: /*
313: * Every fourth retry recalibrate.
314: */
315: if (((io->i_errcnt & 07) == 4) ) {
316: hpaddr->hpcs1 = HP_RECAL|HP_GO;
317: HPWAIT(hpaddr);
318: hpaddr->hpdc = cn;
319: hpaddr->hpcs1 = HP_SEEK|HP_GO;
320: HPWAIT(hpaddr);
321: }
322:
323: if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) {
324: hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22;
325: hpaddr->hpcs1 = HP_OFFSET|HP_GO;
326: HPWAIT(hpaddr);
327: }
328: if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG))
329: printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
330: io->i_bn, io->i_cc, io->i_ma, hprecal);
331: goto restart; /* retry whole transfer --ghg */
332:
333: success:
334: /*
335: * On successful error recovery, bump
336: * block number to advance to next portion
337: * of i/o transfer.
338: */
339: bn++;
340: if ((bn-startblock) * sectsiz < bytecnt) {
341: io->i_bn = bn;
342: io->i_ma = membase + (io->i_bn - startblock)*sectsiz;
343: io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz;
344: if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG))
345: printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
346: io->i_bn, io->i_cc, io->i_ma, hprecal);
347: goto restart;
348: }
349: done:
350: if (io->i_errcnt >= 16) {
351: hpaddr->hpcs1 = HP_RTC|HP_GO;
352: while (hpaddr->hpds & HPDS_PIP)
353: ;
354: }
355: return (bytecnt);
356: }
357:
358: hpecc(io, flag)
359: register struct iob *io;
360: int flag;
361: {
362: register unit = io->i_unit;
363: register struct mba_regs *mbp = mbamba(unit);
364: register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit);
365: register struct st *st = &hpst[hp_type[unit]];
366: int npf, bn, cn, tn, sn, bcr;
367:
368: bcr = MASKREG(mbp->mba_bcr);
369: if (bcr)
370: bcr |= 0xffff0000; /* sxt */
371: npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */
372: if (flag == ECC)
373: npf--; /* Error is in prev block --ghg */
374: bn = io->i_bn + npf + ssect[unit]; /* physical block #*/
375: if (hpdebug[unit]&HPF_ECCDEBUG)
376: printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n",
377: bcr, npf, ssect[unit], sectsiz, io->i_cc);
378: /*
379: * ECC correction logic.
380: */
381: if (flag == ECC) {
382: register int i;
383: caddr_t addr;
384: int bit, o, mask, ecccnt = 0;
385:
386: printf("hp%d: soft ecc sn%d\n", unit, bn);
387: mask = MASKREG(rp->hpec2);
388: i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */
389: bit = i&07;
390: o = (i & ~07) >> 3;
391: rp->hpcs1 = HP_DCLR | HP_GO;
392: while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) {
393: addr = io->i_ma + (npf*sectsiz) + o;
394: /*
395: * No data transfer occurs with a write check,
396: * so don't correct the resident copy of data.
397: */
398: if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) {
399: if (hpdebug[unit] & HPF_ECCDEBUG)
400: printf("addr=%x old=%x ", addr,
401: (*addr & 0xff));
402: *addr ^= (mask << bit);
403: if (hpdebug[unit] & HPF_ECCDEBUG)
404: printf("new=%x\n",(*addr & 0xff));
405: }
406: o++, bit -= 8;
407: if ((io->i_flgs & F_ECCLM) && ecccnt++ >= MAXECC)
408: return (1);
409: }
410: #ifdef F_SEVRE
411: if (io->i_flgs & F_SEVRE)
412: return(1);
413: #endif
414: return (0);
415: }
416:
417: /*
418: * Skip sector error.
419: * Set skip-sector-inhibit and
420: * read next sector
421: */
422: if (flag == SSE) {
423: rp->hpcs1 = HP_DCLR | HP_GO;
424: HPWAIT(rp);
425: rp->hpof |= HPOF_SSEI;
426: return (0);
427: }
428:
429: /*
430: * Bad block forwarding.
431: */
432: if (flag == BSE) {
433: int bbn;
434:
435: rp->hpcs1 = HP_DCLR | HP_GO;
436: if (hpdebug[unit] & HPF_BSEDEBUG)
437: printf("hpecc: BSE @ bn %d\n", bn);
438: cn = bn/st->nspc;
439: sn = bn%st->nspc;
440: tn = sn/st->nsect;
441: sn = sn%st->nsect;
442: bcr += sectsiz;
443: if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0)
444: return (1);
445: bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn;
446: cn = bbn/st->nspc;
447: sn = bbn%st->nspc;
448: tn = sn/st->nsect;
449: sn = sn%st->nsect;
450: io->i_cc = sectsiz;
451: io->i_ma += npf*sectsiz;
452: if (hpdebug[unit] & HPF_BSEDEBUG)
453: printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
454: rp->hpof &= ~HPOF_SSEI;
455: mbp->mba_sr = -1;
456: rp->hpdc = cn;
457: rp->hpda = (tn<<8) + sn;
458: mbastart(io,io->i_flgs);
459: io->i_errcnt = 0;
460: HPWAIT(rp);
461: return (rp->hpds&HPDS_ERR);
462: }
463: printf("hpecc: flag=%d\n", flag);
464: return (1);
465: }
466:
467: /*ARGSUSED*/
468: hpioctl(io, cmd, arg)
469: struct iob *io;
470: int cmd;
471: caddr_t arg;
472: {
473: register unit = io->i_unit;
474: struct st *st = &hpst[hp_type[unit]], *tmp;
475: struct mba_drv *drv = mbadrv(unit);
476: int flag;
477:
478: switch(cmd) {
479:
480: case SAIODEBUG:
481: flag = (int)arg;
482: if (flag > 0)
483: hpdebug[unit] |= flag;
484: else
485: hpdebug[unit] &= ~flag;
486: return (0);
487:
488: case SAIODEVDATA:
489: if ((drv->mbd_dt&MBDT_TAP) == 0) {
490: tmp = (struct st *)arg;
491: *tmp = *st;
492: return (0);
493: }
494: return (ECMD);
495:
496: case SAIOSSI: /* skip-sector-inhibit */
497: if (drv->mbd_dt&MBDT_TAP)
498: return (ECMD);
499: if ((io->i_flgs&F_SSI) == 0) {
500: /* make sure this is done once only */
501: io->i_flgs |= F_SSI;
502: st->nsect++;
503: st->nspc += st->ntrak;
504: }
505: return (0);
506:
507: case SAIONOSSI: /* remove skip-sector-inhibit */
508: if (io->i_flgs & F_SSI) {
509: io->i_flgs &= ~F_SSI;
510: drv->mbd_of &= ~HPOF_SSEI;
511: st->nsect--;
512: st->nspc -= st->ntrak;
513: }
514: return(0);
515:
516: case SAIOSSDEV: /* drive have skip sector? */
517: return (RM80 ? 0 : ECMD);
518: }
519: return (ECMD);
520: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.