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