xref: /csrg-svn/sys/vax/stand/up.c (revision 32196)
123248Smckusick /*
2*32196Skarels  * Copyright (c) 1982 Regents of the University of California.
323248Smckusick  * All rights reserved.  The Berkeley software License Agreement
423248Smckusick  * specifies the terms and conditions for redistribution.
523248Smckusick  *
6*32196Skarels  *	@(#)up.c	7.2 (Berkeley) 09/16/87
723248Smckusick  */
89974Ssam 
910023Ssam /*
1010023Ssam  * UNIBUS peripheral standalone driver
1110023Ssam  * with ECC correction and bad block forwarding.
1210023Ssam  * Also supports header operation and write
1310023Ssam  * check for data and/or header.
1410023Ssam  */
15*32196Skarels #include "param.h"
16*32196Skarels #include "inode.h"
17*32196Skarels #include "fs.h"
18*32196Skarels #include "dkbad.h"
19*32196Skarels #include "vmmac.h"
209974Ssam 
21*32196Skarels #include "vax/pte.h"
22*32196Skarels #include "vaxuba/upreg.h"
23*32196Skarels #include "vaxuba/ubareg.h"
249974Ssam 
2510023Ssam #include "saio.h"
269974Ssam #include "savax.h"
279974Ssam 
2825443Skarels #define RETRIES		27
2925443Skarels 
3010352Shelge #define MAXBADDESC	126	/* max number of bad sectors recorded */
3110352Shelge #define SECTSIZ		512	/* sector size in bytes */
3210352Shelge #define HDRSIZ		4	/* number of bytes in sector header */
3311365Ssam 
3410023Ssam u_short	ubastd[] = { 0776700 };
359974Ssam 
3611143Ssam extern	struct st upst[];
3710023Ssam 
38*32196Skarels #ifndef SMALL
3911365Ssam struct  dkbad upbad[MAXNUBA*8];		/* bad sector table */
40*32196Skarels #endif
4111365Ssam int 	sectsiz;			/* real sector size */
4211365Ssam 
4325443Skarels struct	up_softc {
4425443Skarels 	char	gottype;
4525443Skarels 	char	type;
4625443Skarels 	char	debug;
4725443Skarels #	define	UPF_BSEDEBUG	01	/* debugging bad sector forwarding */
4825443Skarels #	define	UPF_ECCDEBUG	02	/* debugging ecc correction */
4925443Skarels 	int	retries;
5025443Skarels 	int	ecclim;
5125443Skarels } up_softc[MAXNUBA * 8];
5225443Skarels 
539974Ssam u_char	up_offset[16] = {
549974Ssam 	UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
559974Ssam 	UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800,
569974Ssam 	UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
579974Ssam 	0, 0, 0, 0
589974Ssam };
599974Ssam 
609974Ssam upopen(io)
619974Ssam 	register struct iob *io;
629974Ssam {
6310352Shelge 	register unit = io->i_unit;
6410023Ssam 	register struct updevice *upaddr;
6525443Skarels 	register struct up_softc *sc = &up_softc[unit];
6611118Ssam 	register struct st *st;
679974Ssam 
6811143Ssam 	if (io->i_boff < 0 || io->i_boff > 7)
6910023Ssam 		_stop("up bad unit");
7010352Shelge 	upaddr = (struct updevice *)ubamem(unit, ubastd[0]);
7115067Skarels 	upaddr->upcs2 = unit % 8;
7211085Ssam 	while ((upaddr->upcs1 & UP_DVA) == 0)
739974Ssam 		;
7425443Skarels 	if (sc->gottype == 0) {
7510023Ssam 		register int i;
7610023Ssam 		struct iob tio;
7710023Ssam 
7825443Skarels 		sc->retries = RETRIES;
7925443Skarels 		sc->ecclim = 11;
8025443Skarels 		sc->debug = 0;
8125443Skarels 		sc->type = upmaptype(unit, upaddr);
8225443Skarels 		if (sc->type < 0)
8310023Ssam 			_stop("unknown drive type");
8425443Skarels 		st = &upst[sc->type];
8511143Ssam 		if (st->off[io->i_boff] == -1)
8611143Ssam 			_stop("up bad unit");
87*32196Skarels #ifndef SMALL
8810023Ssam 		/*
8911365Ssam 		 * Read in the bad sector table.
9010023Ssam 		 */
9110023Ssam 		tio = *io;
9210023Ssam 		tio.i_bn = st->nspc * st->ncyl - st->nsect;
939974Ssam 		tio.i_ma = (char *)&upbad[tio.i_unit];
9410638Shelge 		tio.i_cc = sizeof (struct dkbad);
9510023Ssam 		tio.i_flgs |= F_RDDATA;
9610023Ssam 		for (i = 0; i < 5; i++) {
9710638Shelge 			if (upstrategy(&tio, READ) == sizeof (struct dkbad))
9810023Ssam 				break;
999974Ssam 			tio.i_bn += 2;
1009974Ssam 		}
1019974Ssam 		if (i == 5) {
10210023Ssam 			printf("Unable to read bad sector table\n");
10310352Shelge 			for (i = 0; i < MAXBADDESC; i++) {
10410352Shelge 				upbad[unit].bt_bad[i].bt_cyl = -1;
10510352Shelge 				upbad[unit].bt_bad[i].bt_trksec = -1;
1069974Ssam 			}
1079974Ssam 		}
108*32196Skarels #endif
10925443Skarels 		sc->gottype = 1;
1109974Ssam 	}
11125443Skarels 	st = &upst[sc->type];
1129974Ssam 	io->i_boff = st->off[io->i_boff] * st->nspc;
11310023Ssam 	io->i_flgs &= ~F_TYPEMASK;
1149974Ssam }
1159974Ssam 
1169974Ssam upstrategy(io, func)
1179974Ssam 	register struct iob *io;
1189974Ssam {
11911317Ssam 	int cn, tn, sn, o;
12010352Shelge 	register unit = io->i_unit;
1219974Ssam 	daddr_t bn;
1229974Ssam 	int recal, info, waitdry;
1239974Ssam 	register struct updevice *upaddr =
12410352Shelge 	    (struct updevice *)ubamem(unit, ubastd[0]);
12525443Skarels 	struct up_softc *sc = &up_softc[unit];
12625443Skarels 	register struct st *st = &upst[sc->type];
12725443Skarels 	int doprintf = 0, error, rv = io->i_cc;
1289974Ssam 
12910352Shelge 	sectsiz = SECTSIZ;
13011085Ssam 	if (io->i_flgs & (F_HDR|F_HCHECK))
13110352Shelge 		sectsiz += HDRSIZ;
13211365Ssam 	upaddr->upcs2 = unit % 8;
1339974Ssam 	if ((upaddr->upds & UPDS_VV) == 0) {
1349974Ssam 		upaddr->upcs1 = UP_DCLR|UP_GO;
1359974Ssam 		upaddr->upcs1 = UP_PRESET|UP_GO;
1369974Ssam 		upaddr->upof = UPOF_FMT22;
1379974Ssam 	}
13825443Skarels 	if ((upaddr->upds & UPDS_DREADY) == 0) {
13925443Skarels 		printf("up%d not ready", unit);
14025443Skarels 		return (-1);
14125443Skarels 	}
1429974Ssam 	info = ubasetup(io, 1);
1439974Ssam 	upaddr->upwc = -io->i_cc / sizeof (short);
14411085Ssam 	recal = 0;
14511085Ssam 	io->i_errcnt = 0;
14611085Ssam 
14710638Shelge restart:
14825443Skarels 	error = 0;
14911317Ssam 	o = io->i_cc + (upaddr->upwc * sizeof (short));
15011317Ssam 	upaddr->upba = info + o;
15111317Ssam 	bn = io->i_bn + o / sectsiz;
15225443Skarels 	if (doprintf && sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG))
15311386Ssam 		printf("wc=%d o=%d i_bn=%d bn=%d\n",
15411365Ssam 			upaddr->upwc, o, io->i_bn, bn);
15510023Ssam 	while((upaddr->upds & UPDS_DRY) == 0)
15610023Ssam 		;
15710352Shelge 	if (upstart(io, bn) != 0) {
15825443Skarels 		rv = -1;
15925443Skarels 		goto done;
16010352Shelge 	}
1619974Ssam 	do {
1629974Ssam 		DELAY(25);
1639974Ssam 	} while ((upaddr->upcs1 & UP_RDY) == 0);
16411085Ssam 	/*
16511085Ssam 	 * If transfer has completed, free UNIBUS
16611085Ssam 	 * resources and return transfer size.
16711085Ssam 	 */
16815067Skarels 	if ((upaddr->upds&UPDS_ERR) == 0 && (upaddr->upcs1&UP_TRE) == 0)
16915067Skarels 		goto done;
17025443Skarels 	bn = io->i_bn +
17125443Skarels 		(io->i_cc + upaddr->upwc * sizeof (short)) / sectsiz;
17225443Skarels 	if (upaddr->uper1 & (UPER1_DCK|UPER1_ECH))
17325443Skarels 		bn--;
17425443Skarels 	cn = bn/st->nspc;
17525443Skarels 	sn = bn%st->nspc;
17625443Skarels 	tn = sn/st->nsect;
17725443Skarels 	sn = sn%st->nsect;
178*32196Skarels #ifndef SMALL
17925443Skarels 	if (sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) {
18025443Skarels 		printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ",
18125443Skarels 		   bn, cn, tn, sn);
18211386Ssam 		printf("cs2=%b er1=%b er2=%b wc=%d\n",
18311365Ssam 	    	  upaddr->upcs2, UPCS2_BITS, upaddr->uper1,
18411386Ssam 		  UPER1_BITS, upaddr->uper2, UPER2_BITS, upaddr->upwc);
18511365Ssam 	}
186*32196Skarels #endif
1879974Ssam 	waitdry = 0;
18811386Ssam 	while ((upaddr->upds&UPDS_DRY) == 0 && ++waitdry < sectsiz)
18910023Ssam 		DELAY(5);
190*32196Skarels #ifndef SMALL
19111085Ssam 	if (upaddr->uper1&UPER1_WLE) {
19211085Ssam 		/*
19311085Ssam 		 * Give up on write locked devices immediately.
19411085Ssam 		 */
19511085Ssam 		printf("up%d: write locked\n", unit);
19625443Skarels 		rv = -1;
19725443Skarels 		goto done;
19811085Ssam 	}
19925443Skarels 	if (upaddr->uper2 & UPER2_BSE) {
20025443Skarels 		if ((io->i_flgs&F_NBSF) == 0 && upecc(io, BSE) == 0)
20125443Skarels 			goto success;
20225443Skarels 		error = EBSE;
20325443Skarels 		goto hard;
20425443Skarels 	}
20525443Skarels 	/*
20625443Skarels 	 * ECC error. If a soft error, correct it;
20725443Skarels 	 * if correction is too large, no more retries.
20825443Skarels 	 */
20925443Skarels 	if ((upaddr->uper1 & (UPER1_DCK|UPER1_ECH|UPER1_HCRC)) == UPER1_DCK) {
21025443Skarels 		if (upecc(io, ECC) == 0)
21125443Skarels 			goto success;
21225443Skarels 		error = EECC;
21325443Skarels 		goto hard;
21425443Skarels 	}
21525443Skarels 	/*
21625443Skarels 	 * If the error is a header CRC,
21725443Skarels 	 * check if a replacement sector exists in
21825443Skarels 	 * the bad sector table.
21925443Skarels 	 */
22025443Skarels 	if ((upaddr->uper1&UPER1_HCRC) && (io->i_flgs&F_NBSF) == 0 &&
22125443Skarels 	     upecc(io, BSE) == 0)
22225443Skarels 		goto success;
223*32196Skarels #endif
22425443Skarels 	if (++io->i_errcnt > sc->retries) {
2259974Ssam 		/*
2269974Ssam 		 * After 28 retries (16 without offset, and
2279974Ssam 		 * 12 with offset positioning) give up.
2289974Ssam 		 */
22910352Shelge hard:
23025443Skarels 		if (error == 0) {
23125443Skarels 			error = EHER;
23225443Skarels 			if (upaddr->upcs2 & UPCS2_WCE)
23325443Skarels 				error = EWCK;
23425443Skarels 		}
23525443Skarels 		printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ",
23625443Skarels 		   bn, cn, tn, sn);
23725443Skarels 		printf("cs2=%b er1=%b er2=%b\n",
23811085Ssam 		   upaddr->upcs2, UPCS2_BITS, upaddr->uper1,
23911085Ssam 		   UPER1_BITS, upaddr->uper2, UPER2_BITS);
2409974Ssam 		upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO;
24110352Shelge 		io->i_errblk = bn;
24215067Skarels 		if (io->i_errcnt >= 16) {
24315067Skarels 			upaddr->upof = UPOF_FMT22;
24415067Skarels 			upaddr->upcs1 = UP_RTC|UP_GO;
24515067Skarels 			while ((upaddr->upds&UPDS_DRY) == 0)
24615067Skarels 				DELAY(25);
24715067Skarels 		}
24825443Skarels 		rv = -1;
24925443Skarels 		goto done;
25011085Ssam 	}
25111085Ssam 	/*
2529974Ssam 	 * Clear drive error and, every eight attempts,
2539974Ssam 	 * (starting with the fourth)
2549974Ssam 	 * recalibrate to clear the slate.
2559974Ssam 	 */
2569974Ssam 	upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO;
25710638Shelge 	if ((io->i_errcnt&07) == 4 ) {
2589974Ssam 		upaddr->upcs1 = UP_RECAL|UP_GO;
25915067Skarels 		while ((upaddr->upds&UPDS_DRY) == 0)
26015067Skarels 			DELAY(25);
2619974Ssam 		upaddr->updc = cn;
2629974Ssam 		upaddr->upcs1 = UP_SEEK|UP_GO;
26315067Skarels 		while ((upaddr->upds&UPDS_DRY) == 0)
26415067Skarels 			DELAY(25);
26515067Skarels 	}
26615067Skarels 	if (io->i_errcnt >= 16 && (func & READ)) {
2679974Ssam 		upaddr->upof = up_offset[io->i_errcnt & 017] | UPOF_FMT22;
2689974Ssam 		upaddr->upcs1 = UP_OFFSET|UP_GO;
26910638Shelge 		while ((upaddr->upds&UPDS_DRY) == 0)
27010638Shelge 			DELAY(25);
2719974Ssam 	}
27210638Shelge 	goto restart;
27311085Ssam 
2749974Ssam success:
27511386Ssam #define	rounddown(x, y)	(((x) / (y)) * (y))
27611386Ssam 	upaddr->upwc = rounddown(upaddr->upwc, sectsiz / sizeof (short));
27711386Ssam 	if (upaddr->upwc) {
27811317Ssam 		doprintf++;
27910638Shelge 		goto restart;
28011317Ssam 	}
28115067Skarels done:
2829974Ssam 	/*
28311365Ssam 	 * Release UNIBUS
2849974Ssam 	 */
2859974Ssam 	ubafree(io, info);
28615067Skarels 	/*
28715067Skarels 	 * If we were offset positioning,
28815067Skarels 	 * return to centerline.
28915067Skarels 	 */
29015067Skarels 	if (io->i_errcnt >= 16) {
29115067Skarels 		upaddr->upof = UPOF_FMT22;
29215067Skarels 		upaddr->upcs1 = UP_RTC|UP_GO;
29315067Skarels 		while ((upaddr->upds&UPDS_DRY) == 0)
29415067Skarels 			DELAY(25);
29515067Skarels 	}
29625443Skarels 	return (rv);
2979974Ssam }
2989974Ssam 
299*32196Skarels #ifndef SMALL
3009974Ssam /*
30111143Ssam  * Correct an ECC error, and restart the
30211143Ssam  * i/o to complete the transfer (if necessary).
30311143Ssam  * This is quite complicated because the transfer
30411143Ssam  * may be going to an odd memory address base and/or
3059974Ssam  * across a page boundary.
3069974Ssam  */
30710023Ssam upecc(io, flag)
3089974Ssam 	register struct iob *io;
3099974Ssam 	int flag;
3109974Ssam {
31111365Ssam 	register i, unit = io->i_unit;
31225443Skarels 	register struct up_softc *sc = &up_softc[unit];
3139974Ssam 	register struct updevice *up =
31411365Ssam 		(struct updevice *)ubamem(unit, ubastd[0]);
31510352Shelge 	register struct st *st;
3169974Ssam 	caddr_t addr;
31710410Shelge 	int bn, twc, npf, mask, cn, tn, sn;
31810352Shelge 	daddr_t bbn;
3199974Ssam 
3209974Ssam 	/*
32111143Ssam 	 * Npf is the number of sectors transferred
32211143Ssam 	 * before the sector containing the ECC error;
32311143Ssam 	 * bn is the current block number.
3249974Ssam 	 */
32510352Shelge 	twc = up->upwc;
32611143Ssam 	npf = ((twc * sizeof(short)) + io->i_cc) / sectsiz;
32715067Skarels 	if (flag == ECC)
32815067Skarels 		npf--;
32925443Skarels 	if (sc->debug & UPF_ECCDEBUG)
33011386Ssam 		printf("npf=%d mask=0x%x ec1=%d wc=%d\n",
33111386Ssam 			npf, up->upec2, up->upec1, twc);
33211317Ssam 	bn = io->i_bn + npf;
33325443Skarels 	st = &upst[sc->type];
33410410Shelge 	cn = bn/st->nspc;
33510410Shelge 	sn = bn%st->nspc;
33610410Shelge 	tn = sn/st->nsect;
33710410Shelge 	sn = sn%st->nsect;
33811143Ssam 
3399974Ssam 	/*
34011143Ssam 	 * ECC correction.
3419974Ssam 	 */
3429974Ssam 	if (flag == ECC) {
34325443Skarels 		int bit, o;
34411085Ssam 
3459974Ssam 		mask = up->upec2;
34611365Ssam 		printf("up%d: soft ecc sn%d\n", unit, bn);
34725443Skarels 		for (i = mask, bit = 0; i; i >>= 1)
34825443Skarels 			if (i & 1)
34925443Skarels 				bit++;
35025443Skarels 		if (bit > sc->ecclim) {
35125443Skarels 			printf("%d-bit error\n", bit);
35225443Skarels 			return (1);
35325443Skarels 		}
3549974Ssam 		/*
35511317Ssam 		 * Compute the byte and bit position of
35611317Ssam 		 * the error.  o is the byte offset in
35711317Ssam 		 * the transfer at which the correction
35811317Ssam 		 * applied.
3599974Ssam 		 */
3609974Ssam 		i = up->upec1 - 1;		/* -1 makes 0 origin */
36111386Ssam 		bit = i & 07;
36211386Ssam 		o = (i & ~07) >> 3;
3639974Ssam 		up->upcs1 = UP_TRE|UP_DCLR|UP_GO;
3649974Ssam 		/*
36511143Ssam 		 * Correct while possible bits remain of mask.
36611143Ssam 		 * Since mask contains 11 bits, we continue while
36711143Ssam 		 * the bit offset is > -11.  Also watch out for
36811143Ssam 		 * end of this block and the end of the transfer.
3699974Ssam 		 */
37011317Ssam 		while (o < sectsiz && (npf*sectsiz)+o < io->i_cc && bit > -11) {
3719974Ssam 			/*
37211143Ssam 			 * addr =
37311317Ssam 			 *  (base address of transfer) +
37411143Ssam 			 *  (# sectors transferred before the error) *
37511143Ssam 			 *    (sector size) +
37611317Ssam 			 *  (byte offset to incorrect data)
3779974Ssam 			 */
37811317Ssam 			addr = io->i_ma + (npf * sectsiz) + o;
37911317Ssam 			/*
38011317Ssam 			 * No data transfer occurs with a write check,
38111317Ssam 			 * so don't correct the resident copy of data.
38211317Ssam 			 */
38311365Ssam 			if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) {
38425443Skarels 				if (sc->debug & UPF_ECCDEBUG)
38511365Ssam 					printf("addr=0x%x old=0x%x ", addr,
38611365Ssam 						(*addr&0xff));
38710352Shelge 				*addr ^= (mask << bit);
38825443Skarels 				if (sc->debug & UPF_ECCDEBUG)
38911365Ssam 					printf("new=0x%x\n", (*addr&0xff));
39011365Ssam 			}
39111317Ssam 			o++, bit -= 8;
3929974Ssam 		}
39311085Ssam 		return (0);
39411085Ssam 	}
39511143Ssam 
39611143Ssam 	/*
39711143Ssam 	 * Bad sector forwarding.
39811143Ssam 	 */
39911085Ssam 	if (flag == BSE) {
4009974Ssam 		/*
40111143Ssam 		 * If not in bad sector table,
40211143Ssam 		 * indicate a hard error to caller.
4039974Ssam 		 */
40410352Shelge 		up->upcs1 = UP_TRE|UP_DCLR|UP_GO;
40511365Ssam 		if ((bbn = isbad(&upbad[unit], cn, tn, sn)) < 0)
40611085Ssam 			return (1);
40711386Ssam 		bbn = (st->ncyl * st->nspc) - st->nsect - 1 - bbn;
40810352Shelge 		twc = up->upwc + sectsiz;
40911085Ssam 		up->upwc = - (sectsiz / sizeof (short));
41025443Skarels 		if (sc->debug & UPF_BSEDEBUG)
41111365Ssam 			printf("revector sn %d to %d\n", sn, bbn);
4129974Ssam 		/*
41311143Ssam 	 	 * Clear the drive & read the replacement
41411143Ssam 		 * sector.  If this is in the middle of a
41511143Ssam 		 * transfer, then set up the controller
41611143Ssam 		 * registers in a normal fashion.
41711143Ssam 	 	 * The UNIBUS address need not be changed.
41811143Ssam 	 	 */
41911386Ssam 		while ((up->upcs1 & UP_RDY) == 0)
4209974Ssam 			;
42111386Ssam 		if (upstart(io, bbn))
42210352Shelge 			return (1);		/* error */
42310352Shelge 		io->i_errcnt = 0;		/* success */
4249974Ssam 		do {
4259974Ssam 			DELAY(25);
42611386Ssam 		} while ((up->upcs1 & UP_RDY) == 0) ;
42711386Ssam 		if ((up->upds & UPDS_ERR) || (up->upcs1 & UP_TRE)) {
42811386Ssam 			up->upwc = twc - sectsiz;
42910352Shelge 			return (1);
4309974Ssam 		}
4319974Ssam 	}
43210638Shelge 	if (twc)
4339974Ssam 		up->upwc = twc;
43410352Shelge 	return (0);
4359974Ssam }
436*32196Skarels #endif
4379974Ssam 
4389974Ssam upstart(io, bn)
43910023Ssam 	register struct iob *io;
44010023Ssam 	daddr_t bn;
4419974Ssam {
4429974Ssam 	register struct updevice *upaddr =
44310023Ssam 		(struct updevice *)ubamem(io->i_unit, ubastd[0]);
44425443Skarels 	register struct up_softc *sc = &up_softc[io->i_unit];
44525443Skarels 	register struct st *st = &upst[sc->type];
4469974Ssam 	int sn, tn;
4479974Ssam 
4489974Ssam 	sn = bn%st->nspc;
4499974Ssam 	tn = sn/st->nsect;
4509974Ssam 	sn %= st->nsect;
4519974Ssam 	upaddr->updc = bn/st->nspc;
4529974Ssam 	upaddr->upda = (tn << 8) + sn;
45310352Shelge 	switch (io->i_flgs & F_TYPEMASK) {
45410023Ssam 
45510023Ssam 	case F_RDDATA:
45610023Ssam 		upaddr->upcs1 = UP_RCOM|UP_GO;
4579974Ssam 		break;
45810023Ssam 
45910023Ssam 	case F_WRDATA:
46010023Ssam 		upaddr->upcs1 = UP_WCOM|UP_GO;
4619974Ssam 		break;
46210023Ssam 
463*32196Skarels #ifndef SMALL
46410023Ssam 	case F_HDR|F_RDDATA:
46510023Ssam 		upaddr->upcs1 = UP_RHDR|UP_GO;
46610023Ssam 		break;
46710023Ssam 
46810023Ssam 	case F_HDR|F_WRDATA:
46910023Ssam 		upaddr->upcs1 = UP_WHDR|UP_GO;
47010023Ssam 		break;
47110023Ssam 
47210023Ssam 	case F_CHECK|F_WRDATA:
47310023Ssam 	case F_CHECK|F_RDDATA:
4749974Ssam 		upaddr->upcs1 = UP_WCDATA|UP_GO;
4759974Ssam 		break;
47610023Ssam 
47710023Ssam 	case F_HCHECK|F_WRDATA:
47810023Ssam 	case F_HCHECK|F_RDDATA:
4799974Ssam 		upaddr->upcs1 = UP_WCHDR|UP_GO;
4809974Ssam 		break;
481*32196Skarels #endif
48210023Ssam 
4839974Ssam 	default:
48410023Ssam 		io->i_error = ECMD;
48510023Ssam 		io->i_flgs &= ~F_TYPEMASK;
48610023Ssam 		return (1);
4879974Ssam 	}
48810023Ssam 	return (0);
4899974Ssam }
4909974Ssam 
49110023Ssam /*ARGSUSED*/
49210023Ssam upioctl(io, cmd, arg)
49310023Ssam 	struct iob *io;
49410023Ssam 	int cmd;
49510023Ssam 	caddr_t arg;
49610023Ssam {
497*32196Skarels #ifndef SMALL
49825443Skarels 	int unit = io->i_unit;
49925443Skarels 	register struct up_softc *sc = &up_softc[unit];
50025443Skarels 	struct st *st = &upst[sc->type];
50110352Shelge 
50210352Shelge 	switch(cmd) {
50310352Shelge 
50411365Ssam 	case SAIODEBUG:
50525443Skarels 		sc->debug = (int)arg;
50625443Skarels 		break;
50711365Ssam 
50810352Shelge 	case SAIODEVDATA:
50925443Skarels 		*(struct st *)arg = *st;
51025443Skarels 		break;
51125443Skarels 
51225443Skarels 	case SAIOGBADINFO:
51325443Skarels 		*(struct dkbad *)arg = upbad[unit];
51425443Skarels 		break;
51525443Skarels 
51625443Skarels 	case SAIOECCLIM:
51725443Skarels 		sc->ecclim = (int)arg;
51825443Skarels 		break;
51925443Skarels 
52025443Skarels 	case SAIORETRIES:
52125443Skarels 		sc->retries = (int)arg;
52225443Skarels 		break;
52325443Skarels 
52425443Skarels 	default:
52525443Skarels 		return (ECMD);
52610352Shelge 	}
52725443Skarels 	return (0);
528*32196Skarels #else SMALL
529*32196Skarels 	return (ECMD);
530*32196Skarels #endif
53110023Ssam }
532