xref: /csrg-svn/sys/vax/stand/hp.c (revision 10334)
1*10334Shelge /*	hp.c	4.1	83/01/16	*/
2*10334Shelge 
3*10334Shelge /*
4*10334Shelge  * RP??/RM?? disk driver
5*10334Shelge  * with ECC handling and bad block forwarding.
6*10334Shelge  * Also supports header io operations and
7*10334Shelge  * commands to write check header and data.
8*10334Shelge  */
9*10334Shelge 
10*10334Shelge #include "../h/param.h"
11*10334Shelge #include "../h/inode.h"
12*10334Shelge #include "../h/fs.h"
13*10334Shelge #include "../h/dkbad.h"
14*10334Shelge 
15*10334Shelge #include "../vax/pte.h"
16*10334Shelge #include "../vaxmba/hpreg.h"
17*10334Shelge #include "../vaxmba/mbareg.h"
18*10334Shelge 
19*10334Shelge #include "saio.h"
20*10334Shelge #include "savax.h"
21*10334Shelge 
22*10334Shelge #define	MASKREG(reg)	((reg)&0xffff)
23*10334Shelge 
24*10334Shelge #define MAXBADDESC	126
25*10334Shelge #define SECTSIZ 	512	/* sector size in bytes */
26*10334Shelge #define HDRSIZ		4	/* number of bytes in sector header */
27*10334Shelge #define MAXECC		5	/* the maximum number of bad bits accepted in
28*10334Shelge 				 * an ecc error when F_ECCLM is set */
29*10334Shelge 
30*10334Shelge char	hp_type[MAXNMBA*8] = { 0 };
31*10334Shelge 
32*10334Shelge /* THIS SHOULD BE READ IN OFF THE PACK, PER DRIVE */
33*10334Shelge short	hp6_off[8] =	{ 0, 38, 0, -1, -1, -1, 118, -1 };
34*10334Shelge short	rm3_off[8] =	{ 0, 100, 0, -1, -1, -1, 310, -1 };
35*10334Shelge short	rm5_off[8] =	{ 0, 27, 0, 562, 589, 681, 562, 82 };
36*10334Shelge short	rm80_off[8] =	{ 0, 37, 0, -1, -1, -1, 115, 305 };
37*10334Shelge short	hp7_off[8] = 	{ 0, 10, 0, 330, 340, 500, 330, 50 };
38*10334Shelge short	ml_off[8] =	{ 0, -1, -1, -1, -1, -1, -1, -1 };
39*10334Shelge short	si9775_off[8] =	{ 0, 13, 0, -1, -1, -1, 40, 441 };
40*10334Shelge short	si9730_off[8] = { 0, 50, 0, -1, -1, -1, -1, 155 };
41*10334Shelge short	hpam_off[8] =	{ 0, 32, 0, 668, 723, 778, 668, 98 };
42*10334Shelge /* END SHOULD BE READ IN */
43*10334Shelge 
44*10334Shelge short	hptypes[] =
45*10334Shelge     { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, MBDT_RP05, MBDT_RP07,
46*10334Shelge       MBDT_ML11A, MBDT_ML11B, -1/*9755*/, -1/*9730*/, -1/*Capr*/, MBDT_RM02, 0};
47*10334Shelge 
48*10334Shelge #define RP06 (hptypes[UNITTODRIVE(unit)] <= MBDT_RP06)
49*10334Shelge #define ML11 (hptypes[UNITTODRIVE(unit)] <= MBDT_ML11A)
50*10334Shelge #define RM80 (hptypes[UNITTODRIVE(unit)] <= MBDT_RM80)
51*10334Shelge 
52*10334Shelge u_char	hp_offset[16] = {
53*10334Shelge     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
54*10334Shelge     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
55*10334Shelge     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
56*10334Shelge     0, 0, 0, 0,
57*10334Shelge };
58*10334Shelge 
59*10334Shelge struct hpst {
60*10334Shelge 	short	nsect;
61*10334Shelge 	short	ntrak;
62*10334Shelge 	short	nspc;
63*10334Shelge 	short	ncyl;
64*10334Shelge 	short	*off;
65*10334Shelge } hpst[] = {
66*10334Shelge 	32,	5,	32*5,	823,	rm3_off,	/* RM03 */
67*10334Shelge 	32,	19,	32*19,	823,	rm5_off,	/* RM05 */
68*10334Shelge 	22,	19,	22*19,	815,	hp6_off,	/* RP06 */
69*10334Shelge 	31,	14, 	31*14,	559,	rm80_off,	/* RM80 */
70*10334Shelge 	22,	19,	22*19,	411,	hp6_off,	/* RP06 */
71*10334Shelge 	50,	32,	50*32,	630,	hp7_off,	/* RP07 */
72*10334Shelge 	1,	1,	1,	1,	ml_off,		/* ML11A */
73*10334Shelge 	1,	1,	1,	1,	ml_off,		/* ML11B */
74*10334Shelge 	32,	40,	32*40,	843,	si9775_off,	/* 9775 */
75*10334Shelge 	32,	10,	32*10,	823,	si9730_off,	/* 9730 */
76*10334Shelge 	32,	16,	32*16,	1024,	hpam_off,	/* AMPEX capricorn */
77*10334Shelge 	1,	1,	1,	1,	0,		/* rm02 - not used */
78*10334Shelge };
79*10334Shelge struct dkbad hpbad[MAXNMBA*8];
80*10334Shelge int sectsiz;
81*10334Shelge 
82*10334Shelge hpopen(io)
83*10334Shelge 	register struct iob *io;
84*10334Shelge {
85*10334Shelge 	register unit = io->i_unit;
86*10334Shelge 	struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
87*10334Shelge 	register struct hpst *st;
88*10334Shelge 
89*10334Shelge 	mbainit(UNITTOMBA(unit));
90*10334Shelge 	if (hp_type[unit] == 0) {
91*10334Shelge 		register type = hpaddr->hpdt & MBDT_TYPE;
92*10334Shelge 		register int i;
93*10334Shelge 		struct iob tio;
94*10334Shelge 
95*10334Shelge 		for (i = 0; hptypes[i]; i++)
96*10334Shelge 			if (hptypes[i] == type)
97*10334Shelge 				goto found;
98*10334Shelge 		_stop("unknown drive type");
99*10334Shelge found:
100*10334Shelge 		switch (i) {
101*10334Shelge 		case 0: case 1:	{	/* rm03 or rm05 */
102*10334Shelge 			register hpsn = hpaddr->hpsn;
103*10334Shelge 
104*10334Shelge 			if ((hpsn & SIMB_LU) != unit)
105*10334Shelge 				break;
106*10334Shelge 			switch ((hpsn & SIMB_MB) &~ (SIMB_S6|SIRM03|SIRM05)) {
107*10334Shelge 			case SI9775D:
108*10334Shelge 				i = 8;	/* si9775 */
109*10334Shelge 				break;
110*10334Shelge 			case SI9730D:
111*10334Shelge 				i = 9;	/* si9730 */
112*10334Shelge 				break;
113*10334Shelge 			case SI9766:
114*10334Shelge 				i = 1;	/* rm05 */
115*10334Shelge 				hpaddr->hpcs1 = HP_RECAL|HP_GO;
116*10334Shelge 				DELAY(100000);
117*10334Shelge 				break;
118*10334Shelge 			case SI9762:
119*10334Shelge 				i = 0;	/* rm03 */
120*10334Shelge 				break;
121*10334Shelge 			}
122*10334Shelge 			break;
123*10334Shelge 		}
124*10334Shelge 
125*10334Shelge 		case 11:		/* rm02 */
126*10334Shelge 			hpaddr->hpcs1 = HP_NOP;
127*10334Shelge 			hpaddr->hphr = HPHR_MAXTRAK;
128*10334Shelge 			if (MASKREG(hpaddr->hphr) == 15)
129*10334Shelge 				i = 10;		/* ampex capricorn */
130*10334Shelge 			else
131*10334Shelge 				i = 0;		/* rm03 */
132*10334Shelge 			break;
133*10334Shelge 
134*10334Shelge 		case 6: case 7:		/* ml11a ml11b */
135*10334Shelge 			i = 6;			/* ml11a */
136*10334Shelge 			break;
137*10334Shelge 		}
138*10334Shelge 		hp_type[unit] = i;
139*10334Shelge 		/*
140*10334Shelge 		 * Read in the bad sector table:
141*10334Shelge 		 *	copy the contents of the io structure
142*10334Shelge 		 *	to tio for use during the bb pointer
143*10334Shelge 		 *	read operation.
144*10334Shelge 		 */
145*10334Shelge 		st = &hpst[hp_type[unit]];
146*10334Shelge 		tio = *io;
147*10334Shelge 		tio.i_bn = st->nspc * st->ncyl - st->nsect;
148*10334Shelge 		tio.i_ma = (char *)&hpbad[tio.i_unit];
149*10334Shelge 		tio.i_cc = sizeof (hpbad);
150*10334Shelge 		tio.i_flgs |= F_RDDATA;
151*10334Shelge 		for (i = 0; i < 5; i++) {
152*10334Shelge 			if (hpstrategy(&tio, READ) == sizeof (hpbad))
153*10334Shelge 				break;
154*10334Shelge 			tio.i_bn += 2;
155*10334Shelge 		}
156*10334Shelge 		if (i == 5) {
157*10334Shelge 			printf("Unable to read bad sector table\n");
158*10334Shelge 			for (i = 0; i < MAXBADDESC; i++) {
159*10334Shelge 				hpbad[unit].bt_bad[i].bt_cyl = -1;
160*10334Shelge 				hpbad[unit].bt_bad[i].bt_trksec = -1;
161*10334Shelge 			}
162*10334Shelge 		}
163*10334Shelge 	}
164*10334Shelge 	if (io->i_boff < 0 || io->i_boff > 7 ||
165*10334Shelge 	    st->off[io->i_boff]== -1)
166*10334Shelge 		_stop("hp bad minor");
167*10334Shelge 	io->i_boff = st->off[io->i_boff] * st->nspc;
168*10334Shelge }
169*10334Shelge 
170*10334Shelge hpstrategy(io, func)
171*10334Shelge 	register struct iob *io;
172*10334Shelge {
173*10334Shelge 	register unit = io->i_unit;
174*10334Shelge 	struct mba_regs *mba = mbamba(unit);
175*10334Shelge 	daddr_t bn;
176*10334Shelge 	struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
177*10334Shelge 	struct hpst *st = &hpst[hp_type[unit]];
178*10334Shelge 	int cn, tn, sn, bytecnt, bytesleft;
179*10334Shelge 	daddr_t startblock;
180*10334Shelge 	char *membase;
181*10334Shelge 	int er1, er2, hprecal;
182*10334Shelge 
183*10334Shelge 	sectsiz = SECTSIZ;
184*10334Shelge 	if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0)
185*10334Shelge 		sectsiz += HDRSIZ;
186*10334Shelge 	if ((hpaddr->hpds & HPDS_VV) == 0) {
187*10334Shelge 		hpaddr->hpcs1 = HP_DCLR|HP_GO;
188*10334Shelge 		hpaddr->hpcs1 = HP_PRESET|HP_GO;
189*10334Shelge 		if (hp_type[unit] != 6)		/* any but ml11 */
190*10334Shelge 			hpaddr->hpof = HPOF_FMT22;
191*10334Shelge 	}
192*10334Shelge 	io->i_errcnt = 0;
193*10334Shelge 	bytecnt = io->i_cc;
194*10334Shelge 	membase = io->i_ma;
195*10334Shelge 	startblock = io->i_bn;
196*10334Shelge 	hprecal = 1;
197*10334Shelge readmore:
198*10334Shelge 	bn = io->i_bn;
199*10334Shelge 	cn = bn/st->nspc;
200*10334Shelge 	sn = bn%st->nspc;
201*10334Shelge 	tn = sn/st->nsect;
202*10334Shelge 	sn = sn%st->nsect;
203*10334Shelge 
204*10334Shelge 	while ((hpaddr->hpds & HPDS_DRY) == 0)
205*10334Shelge 		;
206*10334Shelge 	if (hp_type[unit] == 6)		/* ml11 */
207*10334Shelge 		hpaddr->hpda = bn;
208*10334Shelge 	else {
209*10334Shelge 		hpaddr->hpdc = cn;
210*10334Shelge 		hpaddr->hpda = (tn << 8) + sn;
211*10334Shelge 	}
212*10334Shelge 	if (mbastart(io, func) != 0)		/* start transfer */
213*10334Shelge 		return (-1);
214*10334Shelge 
215*10334Shelge 	while ((hpaddr->hpds & HPDS_DRY) == 0)
216*10334Shelge 		;
217*10334Shelge 	if (((hpaddr->hpds&HPDS_ERR) | (mba->mba_sr&MBSR_EBITS)) == 0 )
218*10334Shelge 		return(bytecnt);
219*10334Shelge 
220*10334Shelge 	/* ------- error handling ------- */
221*10334Shelge 
222*10334Shelge 	if (bytesleft = MASKREG(mba->mba_bcr>>16))
223*10334Shelge 		bytesleft |= 0xffff0000;	/* sign ext */
224*10334Shelge 	bn = io->i_bn + (io->i_cc + bytesleft)/sectsiz;
225*10334Shelge 	cn = bn/st->nspc;
226*10334Shelge 	sn = bn%st->nspc;
227*10334Shelge 	tn = sn/st->nsect;
228*10334Shelge 	sn = sn%st->nsect;
229*10334Shelge 	er1 = MASKREG(hpaddr->hper1);
230*10334Shelge 	er2 = MASKREG(hpaddr->hper2);
231*10334Shelge #ifdef HPDEBUG
232*10334Shelge 	printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n",
233*10334Shelge 		cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
234*10334Shelge 	printf("er1=%b er2=%b",
235*10334Shelge 		er1, HPER1_BITS,
236*10334Shelge 		er2, HPER2_BITS);
237*10334Shelge 	printf("\n");
238*10334Shelge #endif
239*10334Shelge 	if (er1 & HPER1_HCRC) {
240*10334Shelge 		er1 &= ~(HPER1_HCE|HPER1_FER);
241*10334Shelge 		er2 &= ~HPER2_BSE;
242*10334Shelge 	}
243*10334Shelge 	if (er1&HPER1_WLE) {
244*10334Shelge 		printf("hp%d: write locked\n", unit);
245*10334Shelge 		return(-1);
246*10334Shelge 	} else if ((er1&0xffff) == HPER1_FER && RP06) {
247*10334Shelge 		goto badsect;
248*10334Shelge 
249*10334Shelge 	} else if (++io->i_errcnt > 27 ||
250*10334Shelge 		   er1 & HPER1_HARD ||
251*10334Shelge 		   (!ML11 && (er2 & HPER2_HARD))) {
252*10334Shelge 		io->i_error = EHER;
253*10334Shelge 		if ((mba->mba_sr & (MBSR_WCKUP | MBSR_WCKLWR)) != 0)
254*10334Shelge 			io->i_error = EWCK;
255*10334Shelge hard:
256*10334Shelge 		io->i_errblk = bn;
257*10334Shelge 		printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n",
258*10334Shelge 			   cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
259*10334Shelge 		printf("er1=%b er2=%b",
260*10334Shelge 			   er1, HPER1_BITS,
261*10334Shelge 			   er2, HPER2_BITS);
262*10334Shelge 		if (hpaddr->hpmr)
263*10334Shelge 			printf(" mr=%o", hpaddr->hpmr&0xffff);
264*10334Shelge 		if (hpaddr->hpmr2)
265*10334Shelge 			printf(" mr2=%o", hpaddr->hpmr2&0xffff);
266*10334Shelge 		printf("\n");
267*10334Shelge 		return(-1);
268*10334Shelge 
269*10334Shelge 	} else if ((er2 & HPER2_BSE) && !ML11) {
270*10334Shelge badsect:
271*10334Shelge 		if ((io->i_flgs & F_NBSF) != 0) {
272*10334Shelge 			io->i_error = EBSE;
273*10334Shelge 			goto hard;
274*10334Shelge 		}
275*10334Shelge 		if (hpecc(io, BSE) == 0)
276*10334Shelge 			goto success;
277*10334Shelge 		else {
278*10334Shelge 			io->i_error = EBSE;
279*10334Shelge 			goto hard;
280*10334Shelge 		}
281*10334Shelge 	} else if (RM80 && er2&HPER2_SSE) {
282*10334Shelge 	/* skip sector error */
283*10334Shelge 		(void) hpecc(io, SSE);
284*10334Shelge 		goto success;
285*10334Shelge 	} else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
286*10334Shelge 		if ( hpecc(io, ECC) == 0)
287*10334Shelge 			goto success;
288*10334Shelge 		else {
289*10334Shelge 			io->i_error = EECC;
290*10334Shelge 			return(1);
291*10334Shelge 		}
292*10334Shelge 	} else
293*10334Shelge 		io->i_active = 0;		/* force retry */
294*10334Shelge 
295*10334Shelge 	hpaddr->hpcs1 = HP_DCLR|HP_GO;
296*10334Shelge 	while ((hpaddr->hpds & HPDS_DRY) == 0)
297*10334Shelge 		;
298*10334Shelge 	if (ML11) {
299*10334Shelge 		if (io->i_errcnt >= 16)
300*10334Shelge 			goto hard;
301*10334Shelge 	} else if (((io->i_errcnt&07) == 4) && (io->i_active == 0)) {
302*10334Shelge 		hpaddr->hpcs1 = HP_RECAL|HP_GO;
303*10334Shelge 		hprecal = 0;
304*10334Shelge 		goto nextrecal;
305*10334Shelge 	}
306*10334Shelge 	switch (hprecal) {
307*10334Shelge 
308*10334Shelge 	case 1:
309*10334Shelge 		hpaddr->hpdc = cn;
310*10334Shelge 		hpaddr->hpcs1 = HP_SEEK|HP_GO;
311*10334Shelge 		goto nextrecal;
312*10334Shelge 	case 2:
313*10334Shelge 		if (io->i_errcnt < 16 || (func & READ) == 0)
314*10334Shelge 			goto donerecal;
315*10334Shelge 		hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22;
316*10334Shelge 		hpaddr->hpcs1 = HP_OFFSET|HP_GO;
317*10334Shelge nextrecal:
318*10334Shelge 		hprecal++;
319*10334Shelge 		io->i_active = 1;
320*10334Shelge 		goto try_again;
321*10334Shelge 	donerecal:
322*10334Shelge 	case 3:
323*10334Shelge 		hprecal = 0;
324*10334Shelge 		io->i_active = 0;
325*10334Shelge 		goto try_again;
326*10334Shelge 	}
327*10334Shelge 	if (io->i_active) {
328*10334Shelge 		if (io->i_errcnt >= 16) {
329*10334Shelge 			hpaddr->hpcs1 = HP_RTC|HP_GO;
330*10334Shelge 			while (hpaddr->hpds & HPDS_PIP)
331*10334Shelge 				;
332*10334Shelge 		}
333*10334Shelge 	}
334*10334Shelge success:		 /* continue with the next block */
335*10334Shelge 	bn++;
336*10334Shelge 	if ((bn-startblock) * sectsiz < bytecnt) {
337*10334Shelge 
338*10334Shelge try_again:		/* re-read same block */
339*10334Shelge 		io->i_bn = bn;
340*10334Shelge 		mba->mba_sr = -1;
341*10334Shelge 		io->i_ma = membase + (io->i_bn - startblock)*sectsiz;
342*10334Shelge 		io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz;
343*10334Shelge #ifdef HPDEBUG
344*10334Shelge 		printf("restart: bl %d, byte %d, mem 0x%x %d\n",
345*10334Shelge 			io->i_bn, io->i_cc, io->i_ma, io->i_ma);
346*10334Shelge #endif
347*10334Shelge 		goto readmore;
348*10334Shelge 	}
349*10334Shelge 	return (bytecnt);
350*10334Shelge }
351*10334Shelge hpecc(io, flag)
352*10334Shelge 	register struct iob *io;
353*10334Shelge 	int flag;
354*10334Shelge {
355*10334Shelge 	register unit = io->i_unit;
356*10334Shelge 	register struct mba_regs *mbp = mbamba(unit);
357*10334Shelge 	register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit);
358*10334Shelge 	register struct hpst *st = &hpst[hp_type[unit]];
359*10334Shelge 	int npf;
360*10334Shelge 	int bn, cn, tn, sn;
361*10334Shelge 	int bcr, tad;
362*10334Shelge 
363*10334Shelge 	if (bcr = MASKREG(mbp->mba_bcr>>16))
364*10334Shelge 		bcr |= 0xffff0000;		/* sxt */
365*10334Shelge 	npf = (bcr + io->i_cc)/sectsiz;		/* number of sectors read */
366*10334Shelge 	switch (flag) {
367*10334Shelge 	case ECC:
368*10334Shelge 		{
369*10334Shelge 		register int i;
370*10334Shelge 		caddr_t addr;
371*10334Shelge 		int bit, byte, mask, ecccnt = 0;
372*10334Shelge 
373*10334Shelge 		printf("hp%d: soft ecc sn%d\n", unit, io->i_bn + npf);
374*10334Shelge 		mask = MASKREG(rp->hpec2);
375*10334Shelge 		i = MASKREG(rp->hpec1) - 1;		/* -1 makes 0 origin */
376*10334Shelge 		bit = i&07;
377*10334Shelge 		i = (i&~07)>>3;
378*10334Shelge 		byte = i;
379*10334Shelge 		rp->hpcs1 = HP_DCLR | HP_GO;
380*10334Shelge 		while (i <sectsiz && npf*sectsiz + i < io->i_cc && bit > -11) {
381*10334Shelge 			addr = io->i_ma + (npf*sectsiz) + byte;
382*10334Shelge #ifdef HPECCDEBUG
383*10334Shelge 			printf("addr %x old:%x ",addr, (*addr&0xff));
384*10334Shelge #endif
385*10334Shelge 			if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0)
386*10334Shelge 				*addr ^= (mask << bit);	/* don't 'correct' mem-
387*10334Shelge 							 * ory during Wcheck */
388*10334Shelge #ifdef HPECCDEBUG
389*10334Shelge 			printf("new:%x\n",(*addr&0xff));
390*10334Shelge #endif
391*10334Shelge 			byte++;
392*10334Shelge 			i++;
393*10334Shelge 			bit -= 8;
394*10334Shelge 			if ((ecccnt++>=MAXECC) && ((io->i_flgs&F_ECCLM) != 0))
395*10334Shelge 				return(1);
396*10334Shelge 		}
397*10334Shelge 		return(0);
398*10334Shelge 		}
399*10334Shelge 
400*10334Shelge 	case SSE:		/* skip sector error */
401*10334Shelge 				/* -----this section must be fixed------*/
402*10334Shelge 		rp->hpcs1 = HP_DCLR | HP_GO;
403*10334Shelge 		rp->hpof |= HPOF_SSEI;
404*10334Shelge 		mbp->mba_bcr = -(io->i_cc - npf*sectsiz);
405*10334Shelge 		/* presumably the disk address has already
406*10334Shelge 		 * been incremented to point to the next sector	*/
407*10334Shelge 		return(0);
408*10334Shelge 
409*10334Shelge #ifndef NOBADSECT
410*10334Shelge 	case BSE:
411*10334Shelge #ifdef HPDEBUG
412*10334Shelge 		printf("hpecc: BSE @ bn %d\n", bn);
413*10334Shelge #endif
414*10334Shelge 		rp->hpcs1 = HP_DCLR | HP_GO;
415*10334Shelge 		bcr += SECTSIZ;
416*10334Shelge 		tad = rp->hpda;
417*10334Shelge 		if ((bn = isbad(&hpbad[unit], bcr, tad>>8, tad&0x7f)) < 0)
418*10334Shelge 			return(1);
419*10334Shelge 		bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
420*10334Shelge 		cn = bn/st->nspc;
421*10334Shelge 		sn = bn%st->nspc;
422*10334Shelge 		tn = sn/st->nsect;
423*10334Shelge 		sn %= st->nsect;
424*10334Shelge 		io->i_cc = -SECTSIZ;
425*10334Shelge 		io->i_ma = (char *)((io->i_bn + npf -1)*SECTSIZ);
426*10334Shelge #ifdef HPDEBUG
427*10334Shelge 		printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
428*10334Shelge #endif
429*10334Shelge 		rp->hpdc = cn;
430*10334Shelge 		rp->hpda = (tn<<8) + sn;
431*10334Shelge 		mbp->mba_sr = -1;
432*10334Shelge 		mbastart(io,io->i_flgs);
433*10334Shelge 		io->i_errcnt = 0;	/* error has been corrected */
434*10334Shelge 		while(rp->hpds & HPDS_DRY == 0)
435*10334Shelge 			;
436*10334Shelge 		if (rp->hpds&HPDS_ERR)
437*10334Shelge 			return(1);
438*10334Shelge 		else
439*10334Shelge 			return(0);
440*10334Shelge 	}
441*10334Shelge }
442*10334Shelge /*ARGSUSED*/
443*10334Shelge hpioctl(io, cmd, arg)
444*10334Shelge 	struct iob *io;
445*10334Shelge 	int cmd;
446*10334Shelge 	caddr_t arg;
447*10334Shelge {
448*10334Shelge 
449*10334Shelge 	struct hpst *st = &hpst[hp_type[io->i_unit]];
450*10334Shelge 	struct mba_drv *drv = mbadrv(io->i_unit);
451*10334Shelge 	struct devdata *devd;
452*10334Shelge 
453*10334Shelge 	switch(cmd) {
454*10334Shelge 
455*10334Shelge 	case SAIODEVDATA:
456*10334Shelge 		if ((drv->mbd_dt&MBDT_TAP) == 0) {
457*10334Shelge 			devd = (struct devdata *)arg;
458*10334Shelge 			devd->ncyl = st->ncyl;
459*10334Shelge 			devd->ntrak = st->ntrak;
460*10334Shelge 			devd->nspc = st->nspc;
461*10334Shelge 			devd->nsect = st->nsect;
462*10334Shelge 			return(0);
463*10334Shelge 		}
464*10334Shelge 		else
465*10334Shelge 			return(ECMD);
466*10334Shelge 
467*10334Shelge 	default:
468*10334Shelge 		return (ECMD);
469*10334Shelge 	}
470*10334Shelge }
471*10334Shelge 
472*10334Shelge /* this routine is common to up & hp, move to a separate file */
473*10334Shelge 
474*10334Shelge /*
475*10334Shelge  * Search the bad sector table looking for
476*10334Shelge  * the specified sector.  Return index if found.
477*10334Shelge  * Return -1 if not found.
478*10334Shelge  */
479*10334Shelge 
480*10334Shelge isbad(bt, st, blno)
481*10334Shelge 	register struct dkbad *bt;
482*10334Shelge 	register struct devdata *st;	/* dirty, must be fixed */
483*10334Shelge {
484*10334Shelge 	register int i;
485*10334Shelge 	register long blk, bblk;
486*10334Shelge 	int trk, sec;
487*10334Shelge 
488*10334Shelge 	sec = blno % st->nspc;
489*10334Shelge 	trk = sec / st->nsect;
490*10334Shelge 	sec %= st->nsect;
491*10334Shelge 	blk = ((long)(blno/st->nspc) << 16) + (trk << 8) + sec;
492*10334Shelge 	for (i = 0; i < MAXBADDESC; i++) {
493*10334Shelge 		bblk = ((long)bt->bt_bad[i].bt_cyl << 16) +
494*10334Shelge 			bt->bt_bad[i].bt_trksec;
495*10334Shelge 		if (blk == bblk)
496*10334Shelge 			return (i);
497*10334Shelge 		if (blk < bblk || bblk < 0)
498*10334Shelge 			break;
499*10334Shelge 	}
500*10334Shelge 	return (-1);
501*10334Shelge }
502