xref: /csrg-svn/sys/vax/mba/hp.c (revision 914)
1*914Sbill /*	hp.c	3.12	09/25/80	*/
221Sbill 
321Sbill /*
4886Sbill  * RP06/RM03/RM05 disk driver
521Sbill  */
621Sbill 
721Sbill #include "../h/param.h"
821Sbill #include "../h/systm.h"
9305Sbill #include "../h/dk.h"
1021Sbill #include "../h/buf.h"
1121Sbill #include "../h/conf.h"
1221Sbill #include "../h/dir.h"
1321Sbill #include "../h/user.h"
1421Sbill #include "../h/map.h"
15420Sbill #include "../h/pte.h"
1621Sbill #include "../h/mba.h"
1721Sbill #include "../h/mtpr.h"
18420Sbill #include "../h/vm.h"
1921Sbill 
2021Sbill #define	DK_N	0
21344Sbill #define	DK_NMAX	1
2221Sbill 
2321Sbill struct	device
2421Sbill {
2521Sbill 	int	hpcs1;		/* control and Status register 1 */
2621Sbill 	int	hpds;		/* Drive Status */
2721Sbill 	int	hper1;		/* Error register 1 */
2821Sbill 	int	hpmr;		/* Maintenance */
2921Sbill 	int	hpas;		/* Attention Summary */
3021Sbill 	int	hpda;		/* Desired address register */
3121Sbill 	int	hpdt;		/* Drive type */
3221Sbill 	int	hpla;		/* Look ahead */
3321Sbill 	int	hpsn;		/* serial number */
3421Sbill 	int	hpof;		/* Offset register */
3521Sbill 	int	hpdc;		/* Desired Cylinder address register */
3621Sbill 	int	hpcc;		/* Current Cylinder */
3721Sbill 	int	hper2;		/* Error register 2 */
3821Sbill 	int	hper3;		/* Error register 3 */
3921Sbill 	int	hpec1;		/* Burst error bit position */
4021Sbill 	int	hpec2;		/* Burst error bit pattern */
4121Sbill };
4221Sbill 
43420Sbill #define	HPMBA		MBA0
44420Sbill #define	HPMBANUM	0
45420Sbill 
46342Sbill #define	NHP	2
4721Sbill #define	RP	022
4821Sbill #define	RM	024
49886Sbill #define	RM5	027
5021Sbill #define	NSECT	22
5121Sbill #define	NTRAC	19
5221Sbill #define	NRMSECT	32
5321Sbill #define	NRMTRAC	5
5421Sbill 
55305Sbill #define	_hpSDIST	3
56305Sbill #define	_hpRDIST	6
57305Sbill 
58305Sbill int	hpSDIST = _hpSDIST;
59305Sbill int	hpRDIST = _hpRDIST;
60305Sbill int	hpseek;
61305Sbill 
6221Sbill struct	size
6321Sbill {
6421Sbill 	daddr_t	nblocks;
6521Sbill 	int	cyloff;
6621Sbill } hp_sizes[8] =
6721Sbill {
68886Sbill 	15884,	0,		/* A=cyl 0 thru 37 */
69886Sbill 	33440,	38,		/* B=cyl 38 thru 117 */
70886Sbill 	340670,	0,		/* C=cyl 0 thru 814 */
7121Sbill 	0,	0,
7221Sbill 	0,	0,
7321Sbill 	0,	0,
74886Sbill 	291346,	118,		/* G=cyl 118 thru 814 */
7521Sbill 	0,	0,
7621Sbill }, rm_sizes[8] = {
77886Sbill 	15884,	0,		/* A=cyl 0 thru 99 */
78886Sbill 	33440,	100,		/* B=cyl 100 thru 309 */
79886Sbill 	131680,	0,		/* C=cyl 0 thru 822 */
8021Sbill 	0,	0,
8121Sbill 	0,	0,
8221Sbill 	0,	0,
83886Sbill 	82080,	310,		/* G=cyl 310 thru 822 */
8421Sbill 	0,	0,
85886Sbill }, rm5_sizes[8] = {
86886Sbill 	15884,	0,		/* A=cyl 0 thru 26 */
87886Sbill 	33440,	27,		/* B=cyl 27 thru 81 */
88886Sbill 	500992,	0,		/* C=cyl 0 thru 823 */
89886Sbill 	15884,	562,		/* D=cyl 562 thru 588 */
90886Sbill 	55936,	589,		/* E=cyl 589 thru 680 */
91886Sbill 	86944,	681,		/* F=cyl 681 thru 823 */
92886Sbill 	159296,	562,		/* G=cyl 562 thru 823 */
93886Sbill 	291346,	82,		/* H=cyl 82 thru 561 */
9421Sbill };
9521Sbill 
9621Sbill #define	P400	020
9721Sbill #define	M400	0220
9821Sbill #define	P800	040
9921Sbill #define	M800	0240
10021Sbill #define	P1200	060
10121Sbill #define	M1200	0260
10221Sbill int	hp_offset[16] =
10321Sbill {
10421Sbill 	P400, M400, P400, M400,
10521Sbill 	P800, M800, P800, M800,
10621Sbill 	P1200, M1200, P1200, M1200,
10721Sbill 	0, 0, 0, 0,
10821Sbill };
10921Sbill 
11021Sbill struct	buf	hptab;
11121Sbill struct	buf	rhpbuf;
11221Sbill struct	buf	hputab[NHP];
11321Sbill char	hp_type[NHP];	/* drive type */
11421Sbill 
11521Sbill #define	GO	01
11621Sbill #define	PRESET	020
11721Sbill #define	RTC	016
11821Sbill #define	OFFSET	014
119305Sbill #define	SEEK	04
12021Sbill #define	SEARCH	030
12121Sbill #define	RECAL	06
12221Sbill #define	DCLR	010
12321Sbill #define	WCOM	060
12421Sbill #define	RCOM	070
12521Sbill 
12621Sbill #define	IE	0100
12721Sbill #define	PIP	020000
12821Sbill #define	DRY	0200
12921Sbill #define	ERR	040000
13021Sbill #define	TRE	040000
13121Sbill #define	DCK	0100000
13221Sbill #define	WLE	04000
13321Sbill #define	ECH	0100
13421Sbill #define	VV	0100
13521Sbill #define	DPR	0400
13621Sbill #define	MOL	010000
13721Sbill #define	FMT22	010000
13821Sbill 
13921Sbill #define	b_cylin b_resid
14021Sbill 
14121Sbill #ifdef INTRLVE
14221Sbill daddr_t dkblock();
14321Sbill #endif
14421Sbill 
14521Sbill hpstrategy(bp)
14621Sbill register struct buf *bp;
14721Sbill {
14821Sbill 	register struct buf *dp;
14921Sbill 	register unit, xunit, nspc;
15021Sbill 	long sz, bn;
15121Sbill 	struct size *sizes;
15221Sbill 
153420Sbill 	if ((mbaact&(1<<HPMBANUM)) == 0)
154420Sbill 		mbainit(HPMBANUM);
15521Sbill 	xunit = minor(bp->b_dev) & 077;
15621Sbill 	sz = bp->b_bcount;
15721Sbill 	sz = (sz+511) >> 9;
15821Sbill 	unit = dkunit(bp);
15921Sbill 	if (hp_type[unit] == 0) {
16021Sbill 		struct device *hpaddr;
16121Sbill 
16221Sbill 		/* determine device type */
163420Sbill 		hpaddr = mbadev(HPMBA, unit);
16421Sbill 		hp_type[unit] = hpaddr->hpdt;
16521Sbill 	}
166886Sbill 	switch (hp_type[unit]) {
167886Sbill 
168886Sbill 	case RM:
16921Sbill 		sizes = rm_sizes;
17021Sbill 		nspc = NRMSECT*NRMTRAC;
171886Sbill 		break;
172886Sbill 	case RM5:
173886Sbill 		sizes = rm5_sizes;
174886Sbill 		nspc = NRMSECT*NTRAC;
175886Sbill 		break;
176886Sbill 	case RP:
17721Sbill 		sizes = hp_sizes;
17821Sbill 		nspc = NSECT*NTRAC;
179886Sbill 		break;
180886Sbill 	default:
181886Sbill 		printf("hp: unknown device type 0%o\n", hp_type[unit]);
182886Sbill 		u.u_error = ENXIO;
183886Sbill 		unit = NHP+1;	/* force error */
18421Sbill 	}
18521Sbill 	if (unit >= NHP ||
18621Sbill 	    bp->b_blkno < 0 ||
18721Sbill 	    (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
18821Sbill 		bp->b_flags |= B_ERROR;
18921Sbill 		iodone(bp);
19021Sbill 		return;
19121Sbill 	}
19221Sbill 	bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
19321Sbill 	dp = &hputab[unit];
194127Sbill 	(void) spl5();
19521Sbill 	disksort(dp, bp);
19621Sbill 	if (dp->b_active == 0) {
19721Sbill 		hpustart(unit);
19821Sbill 		if(hptab.b_active == 0)
19921Sbill 			hpstart();
20021Sbill 	}
201127Sbill 	(void) spl0();
20221Sbill }
20321Sbill 
20421Sbill hpustart(unit)
20521Sbill register unit;
20621Sbill {
20721Sbill 	register struct buf *bp, *dp;
20821Sbill 	register struct device *hpaddr;
20921Sbill 	daddr_t bn;
21021Sbill 	int sn, cn, csn;
21121Sbill 
21221Sbill 	((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
213420Sbill 	hpaddr = mbadev(HPMBA, 0);
214420Sbill 	hpaddr->hpas = 1<<unit;
21521Sbill 
21621Sbill 	if(unit >= NHP)
21721Sbill 		return;
218344Sbill 	if (unit+DK_N <= DK_NMAX)
219344Sbill 		dk_busy &= ~(1<<(unit+DK_N));
22021Sbill 	dp = &hputab[unit];
22121Sbill 	if((bp=dp->b_actf) == NULL)
22221Sbill 		return;
223420Sbill 	hpaddr = mbadev(HPMBA, unit);
22421Sbill 	if((hpaddr->hpds & VV) == 0) {
22521Sbill 		hpaddr->hpcs1 = PRESET|GO;
22621Sbill 		hpaddr->hpof = FMT22;
22721Sbill 	}
22821Sbill 	if(dp->b_active)
22921Sbill 		goto done;
23021Sbill 	dp->b_active++;
23121Sbill 	if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
23221Sbill 		goto done;
23321Sbill 
23421Sbill 	bn = dkblock(bp);
23521Sbill 	cn = bp->b_cylin;
236886Sbill 	switch (hp_type[unit]) {
237886Sbill 
238886Sbill 	case RM:
23921Sbill 		sn = bn%(NRMSECT*NRMTRAC);
240305Sbill 		sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
241886Sbill 		break;
242886Sbill 	case RM5:
243886Sbill 		sn = bn%(NRMSECT*NTRAC);
244886Sbill 		sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
245886Sbill 		break;
246886Sbill 	case RP:
24721Sbill 		sn = bn%(NSECT*NTRAC);
248305Sbill 		sn = (sn+NSECT-hpSDIST)%NSECT;
249886Sbill 		break;
250886Sbill 	default:
251886Sbill 		panic("hpustart");
25221Sbill 	}
25321Sbill 
25421Sbill 	if(cn - (hpaddr->hpdc & 0xffff))
25521Sbill 		goto search;
256305Sbill 	else if (hpseek)
257305Sbill 		goto done;
258305Sbill 	csn = ((hpaddr->hpla & 0xffff)>>6) - sn + 1;
25921Sbill 	if(csn < 0)
26021Sbill 		csn += NSECT;
261305Sbill 	if(csn > NSECT-hpRDIST)
26221Sbill 		goto done;
26321Sbill 
26421Sbill search:
26521Sbill 	hpaddr->hpdc = cn;
266305Sbill 	if (hpseek)
267305Sbill 		hpaddr->hpcs1 = SEEK|GO;
268305Sbill 	else {
269305Sbill 		hpaddr->hpda = sn;
270305Sbill 		hpaddr->hpcs1 = SEARCH|GO;
271305Sbill 	}
27221Sbill 	unit += DK_N;
273344Sbill 	if (unit <= DK_NMAX && DK_N+NHP <= DK_NMAX) {
274344Sbill 		dk_busy |= 1<<unit;
275344Sbill 		dk_numb[unit]++;
276344Sbill 	}
27721Sbill 	return;
27821Sbill 
27921Sbill done:
28021Sbill 	dp->b_forw = NULL;
28121Sbill 	if(hptab.b_actf == NULL)
282344Sbill 		hptab.b_actf = dp;
283344Sbill 	else
28421Sbill 		hptab.b_actl->b_forw = dp;
28521Sbill 	hptab.b_actl = dp;
28621Sbill }
28721Sbill 
28821Sbill hpstart()
28921Sbill {
29021Sbill 	register struct buf *bp, *dp;
29121Sbill 	register unit;
29221Sbill 	register struct device *hpaddr;
29321Sbill 	daddr_t bn;
29421Sbill 	int dn, sn, tn, cn, nspc, ns;
29521Sbill 
29621Sbill loop:
29721Sbill 	if ((dp = hptab.b_actf) == NULL)
29821Sbill 		return;
29921Sbill 	if ((bp = dp->b_actf) == NULL) {
30021Sbill 		hptab.b_actf = dp->b_forw;
30121Sbill 		goto loop;
30221Sbill 	}
30321Sbill 	hptab.b_active++;
30421Sbill 	unit = minor(bp->b_dev) & 077;
30521Sbill 	dn = dkunit(bp);
30621Sbill 	bn = dkblock(bp);
307886Sbill 	switch (hp_type[dn]) {
308886Sbill 	case RM:
30921Sbill 		nspc = NRMSECT*NRMTRAC;
31021Sbill 		ns = NRMSECT;
31121Sbill 		cn = rm_sizes[unit&07].cyloff;
312886Sbill 		break;
313886Sbill 	case RM5:
314886Sbill 		nspc = NRMSECT*NTRAC;
315886Sbill 		ns = NRMSECT;
316886Sbill 		cn = rm5_sizes[unit&07].cyloff;
317886Sbill 		break;
318886Sbill 	case RP:
31921Sbill 		nspc = NSECT*NTRAC;
32021Sbill 		ns = NSECT;
32121Sbill 		cn = hp_sizes[unit&07].cyloff;
322886Sbill 		break;
323886Sbill 	default:
324886Sbill 		panic("hpstart");
32521Sbill 	}
32621Sbill 	cn += bn/nspc;
32721Sbill 	sn = bn%nspc;
32821Sbill 	tn = sn/ns;
32921Sbill 	sn = sn%ns;
33021Sbill 
331420Sbill 	hpaddr = mbadev(HPMBA, dn);
33221Sbill 	if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
33321Sbill 		hptab.b_active = 0;
33421Sbill 		hptab.b_errcnt = 0;
33521Sbill 		dp->b_actf = bp->av_forw;
33621Sbill 		bp->b_flags |= B_ERROR;
33721Sbill 		iodone(bp);
33821Sbill 		goto loop;
33921Sbill 	}
34021Sbill 	if(hptab.b_errcnt >= 16) {
34121Sbill 		hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
342420Sbill 		HPMBA->mba_cr &= ~MBAIE;
34321Sbill 		hpaddr->hpcs1 = OFFSET|GO;
34421Sbill 		while(hpaddr->hpds & PIP)
34521Sbill 			;
346420Sbill 		HPMBA->mba_cr |= MBAIE;
34721Sbill 	}
34821Sbill 	hpaddr->hpdc = cn;
34921Sbill 	hpaddr->hpda = (tn << 8) + sn;
35021Sbill 	mbastart(bp, (int *)hpaddr);
35121Sbill 
352344Sbill 	unit = dn+DK_N;
353344Sbill 	if (NHP+DK_N == DK_NMAX)
354344Sbill 		unit = NHP+DK_N;
355344Sbill 	if (unit <= DK_NMAX) {
356344Sbill 		dk_busy |= 1<<unit;
357344Sbill 		dk_numb[unit]++;
358344Sbill 		dk_wds[unit] += bp->b_bcount>>6;
359344Sbill 	}
36021Sbill }
36121Sbill 
36221Sbill hpintr(mbastat, as)
36321Sbill {
36421Sbill 	register struct buf *bp, *dp;
36521Sbill 	register unit;
36621Sbill 	register struct device *hpaddr;
36721Sbill 
36821Sbill 	if(hptab.b_active) {
36921Sbill 		dp = hptab.b_actf;
37021Sbill 		bp = dp->b_actf;
37121Sbill 		unit = dkunit(bp);
372344Sbill 		if (DK_N+NHP == DK_NMAX)
373344Sbill 			dk_busy &= ~(1<<(DK_N+NHP));
374344Sbill 		else if (DK_N+unit <= DK_NMAX)
375344Sbill 			dk_busy &= ~(1<<(DK_N+unit));
376420Sbill 		hpaddr = mbadev(HPMBA, unit);
377420Sbill 		if (hpaddr->hpds & ERR || mbastat & MBAEBITS) {
37821Sbill 			while((hpaddr->hpds & DRY) == 0)
37921Sbill 				;
38021Sbill 			if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
381420Sbill 				bp->b_flags |= B_ERROR;
382420Sbill 			else
38321Sbill 				hptab.b_active = 0;
38421Sbill 			if(hptab.b_errcnt > 27)
38521Sbill 				deverror(bp, mbastat, hpaddr->hper1);
38621Sbill 			if ((hpaddr->hper1&0xffff) == DCK) {
38721Sbill 				if (hpecc(hpaddr, bp))
38821Sbill 					return;
38921Sbill 			}
39021Sbill 			hpaddr->hpcs1 = DCLR|GO;
39121Sbill 			if((hptab.b_errcnt&07) == 4) {
392420Sbill 				HPMBA->mba_cr &= ~MBAIE;
39321Sbill 				hpaddr->hpcs1 = RECAL|GO;
39421Sbill 				while(hpaddr->hpds & PIP)
39521Sbill 					;
396420Sbill 				HPMBA->mba_cr |= MBAIE;
39721Sbill 			}
39821Sbill 		}
39921Sbill 		if(hptab.b_active) {
40021Sbill 			if(hptab.b_errcnt) {
401420Sbill 				HPMBA->mba_cr &= ~MBAIE;
40221Sbill 				hpaddr->hpcs1 = RTC|GO;
40321Sbill 				while(hpaddr->hpds & PIP)
40421Sbill 					;
405420Sbill 				HPMBA->mba_cr |= MBAIE;
40621Sbill 			}
40721Sbill 			hptab.b_active = 0;
40821Sbill 			hptab.b_errcnt = 0;
40921Sbill 			hptab.b_actf = dp->b_forw;
41021Sbill 			dp->b_active = 0;
41121Sbill 			dp->b_errcnt = 0;
41221Sbill 			dp->b_actf = bp->av_forw;
413420Sbill 			bp->b_resid = -HPMBA->mba_bcr & 0xffff;
41421Sbill 			iodone(bp);
41521Sbill 			if(dp->b_actf)
41621Sbill 				hpustart(unit);
41721Sbill 		}
41821Sbill 		as &= ~(1<<unit);
41921Sbill 	} else {
42021Sbill 		if(as == 0)
421420Sbill 			HPMBA->mba_cr |= MBAIE;
42221Sbill 	}
42321Sbill 	for(unit=0; unit<NHP; unit++)
42421Sbill 		if(as & (1<<unit))
42521Sbill 			hpustart(unit);
42621Sbill 	hpstart();
42721Sbill }
42821Sbill 
42921Sbill hpread(dev)
43021Sbill {
43121Sbill 
43221Sbill 	physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
43321Sbill }
43421Sbill 
43521Sbill hpwrite(dev)
43621Sbill {
43721Sbill 
43821Sbill 	physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
43921Sbill }
44021Sbill 
44121Sbill hpecc(rp, bp)
44221Sbill register struct device *rp;
44321Sbill register struct buf *bp;
44421Sbill {
445420Sbill 	struct mba_regs *mbp = HPMBA;
446420Sbill 	register int i;
447420Sbill 	caddr_t addr;
448420Sbill 	int reg, bit, byte, npf, mask, o;
449420Sbill 	int dn, bn, cn, tn, sn, ns, nt;
450106Sbill 	extern char buffers[NBUF][BSIZE];
451420Sbill 	struct pte mpte;
452*914Sbill 	int bcr;
45321Sbill 
454420Sbill 	/*
455420Sbill 	 * Npf is the number of sectors transferred before the sector
456420Sbill 	 * containing the ECC error, and reg is the MBA register
457420Sbill 	 * mapping (the first part of)the transfer.
458420Sbill 	 * O is offset within a memory page of the first byte transferred.
459420Sbill 	 */
460*914Sbill 	bcr = mbp->mba_bcr & 0xffff;
461*914Sbill 	if (bcr)
462*914Sbill 		bcr |= 0xffff0000;		/* sxt */
463719Sbill 	npf = btop(bcr + bp->b_bcount) - 1;
464719Sbill 	printf("bcr %d npf %d\n", bcr, npf);
465420Sbill 	if (bp->b_flags&B_PHYS)
466420Sbill 		reg = 128 + npf;
467420Sbill 	else
468420Sbill 		reg = btop(bp->b_un.b_addr - buffers[0]) + npf;
469420Sbill 	o = (int)bp->b_un.b_addr & PGOFSET;
470420Sbill 	printf("%D ", bp->b_blkno + npf);
47121Sbill 	prdev("ECC", bp->b_dev);
47221Sbill 	mask = rp->hpec2&0xffff;
47321Sbill 	if (mask == 0) {
47421Sbill 		rp->hpof = FMT22;
475420Sbill 		return (0);
47621Sbill 	}
477420Sbill 
478420Sbill 	/*
479420Sbill 	 * Compute the byte and bit position of the error.
480420Sbill 	 * The variable i is the byte offset in the transfer,
481420Sbill 	 * the variable byte is the offset from a page boundary
482420Sbill 	 * in main memory.
483420Sbill 	 */
484420Sbill 	i = (rp->hpec1&0xffff) - 1;		/* -1 makes 0 origin */
485719Sbill 	bit = i&07;
486420Sbill 	i = (i&~07)>>3;
487420Sbill 	byte = i + o;
488420Sbill 	/*
489420Sbill 	 * Correct while possible bits remain of mask.  Since mask
490420Sbill 	 * contains 11 bits, we continue while the bit offset is > -11.
491420Sbill 	 * Also watch out for end of this block and the end of the whole
492420Sbill 	 * transfer.
493420Sbill 	 */
494420Sbill 	while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
495420Sbill 		mpte = mbp->mba_map[reg+btop(byte)];
496420Sbill 		addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
497420Sbill 		putmemc(addr, getmemc(addr)^(mask<<bit));
498420Sbill 		byte++;
499420Sbill 		i++;
500420Sbill 		bit -= 8;
50121Sbill 	}
502420Sbill 	hptab.b_active++;		/* Either complete or continuing */
503719Sbill 	if (bcr == 0)
504420Sbill 		return (0);
505420Sbill 	/*
506420Sbill 	 * Have to continue the transfer... clear the drive,
507420Sbill 	 * and compute the position where the transfer is to continue.
508420Sbill 	 * We have completed npf+1 sectores of the transfer already;
509420Sbill 	 * restart at offset o of next sector (i.e. in MBA register reg+1).
510420Sbill 	 */
511420Sbill 	rp->hpcs1 = DCLR|GO;
512420Sbill 	dn = dkunit(bp);
513420Sbill 	bn = dkblock(bp);
514886Sbill 	switch (hp_type[dn]) {
515886Sbill 
516886Sbill 	case RM:
517886Sbill 		ns = NRMSECT; nt = NRMTRAC; break;
518886Sbill 	case RM5:
519886Sbill 		ns = NRMSECT; nt = NTRAC; break;
520886Sbill 	case RP:
521886Sbill 		ns = NSECT; nt = NTRAC; break;
522886Sbill 	default:
523886Sbill 		panic("hpecc");
52421Sbill 	}
525420Sbill 	cn = bp->b_cylin;
526420Sbill 	sn = bn%(ns*nt) + npf + 1;
527420Sbill 	tn = sn/ns;
528420Sbill 	sn %= ns;
529420Sbill 	cn += tn/nt;
530420Sbill 	tn %= nt;
531420Sbill 	rp->hpdc = cn;
532420Sbill 	rp->hpda = (tn<<8) + sn;
533420Sbill 	mbp->mba_sr = -1;
534420Sbill 	mbp->mba_var = (int)ptob(reg+1) + o;
535420Sbill 	rp->hpcs1 = RCOM|GO;
536420Sbill 	return (1);
53721Sbill }
538