xref: /csrg-svn/sys/vax/stand/up.c (revision 10023)
1*10023Ssam /*	up.c	4.2	82/12/30	*/
29974Ssam 
3*10023Ssam /*
4*10023Ssam  * UNIBUS peripheral standalone driver
5*10023Ssam  * with ECC correction and bad block forwarding.
6*10023Ssam  * Also supports header operation and write
7*10023Ssam  * check for data and/or header.
8*10023Ssam  */
99974Ssam #include "../h/param.h"
109974Ssam #include "../h/inode.h"
119974Ssam #include "../h/fs.h"
129974Ssam #include "../h/dkbad.h"
139974Ssam #include "../h/vmmac.h"
149974Ssam 
159974Ssam #include "../vax/pte.h"
169974Ssam #include "../vaxuba/upreg.h"
179974Ssam #include "../vaxuba/ubareg.h"
189974Ssam 
19*10023Ssam #include "saio.h"
209974Ssam #include "savax.h"
219974Ssam 
22*10023Ssam u_short	ubastd[] = { 0776700 };
239974Ssam 
249974Ssam char	up_gottype[MAXNUBA*8] = { 0 };
259974Ssam char	up_type[MAXNUBA*8] = { 0 };
269974Ssam short	up_off[] = { 0, 27, 68, -1, -1, -1, -1, 82 };
279974Ssam short	fj_off[] = { 0, 50, 0, -1, -1, -1, -1, 155 };
289974Ssam /* this is called upam instead of am because hp.c has a similar array */
299974Ssam short	upam_off[] = { 0, 32, 0, 668, 723, 778, 668, 98 };
30*10023Ssam 
31*10023Ssam #define	NUPTYPES	3
32*10023Ssam 
339974Ssam struct upst {
349974Ssam 	short nsect;
359974Ssam 	short ntrak;
369974Ssam 	short nspc;
379974Ssam 	short ncyl;
389974Ssam 	short *off;
39*10023Ssam } upst[NUPTYPES] = {
40*10023Ssam 	32,	19,	32*19,	823,	up_off,		/* 9300/equiv */
41*10023Ssam 	32,	10,	32*10,	823,	fj_off,		/* Fuji 160 */
42*10023Ssam 	32,	16,	32*16,	1024,	upam_off,	/* Capricorn */
439974Ssam };
44*10023Ssam 
459974Ssam u_char	up_offset[16] = {
469974Ssam 	UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
479974Ssam 	UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800,
489974Ssam 	UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
499974Ssam 	0, 0, 0, 0
509974Ssam };
519974Ssam 
52*10023Ssam struct  dkbad upbad[MAXNUBA*8];		/* bad sector table */
53*10023Ssam 
549974Ssam upopen(io)
559974Ssam 	register struct iob *io;
569974Ssam {
57*10023Ssam 	register struct updevice *upaddr;
589974Ssam 	register struct upst *st;
599974Ssam 
60*10023Ssam 	if (io->i_boff < 0 || io->i_boff > 7 || st->off[io->i_boff] == -1)
61*10023Ssam 		_stop("up bad unit");
62*10023Ssam 	upaddr = (struct updevice *)ubamem(io->i_unit, ubastd[0]);
639974Ssam 	while ((upaddr->upcs1 & UP_DVA) == 0) /* infinite wait */
649974Ssam 		;
659974Ssam 	st = &upst[up_type[io->i_unit]];
669974Ssam 	if (up_gottype[io->i_unit] == 0) {
67*10023Ssam 		register int i;
68*10023Ssam 		struct iob tio;
69*10023Ssam 
709974Ssam 		upaddr->uphr = UPHR_MAXTRAK;
71*10023Ssam 		for (st = upst; st < &upst[NUPTYPES]; st++)
72*10023Ssam 			if (upaddr->uphr == st->ntrak - 1) {
73*10023Ssam 				up_type[io->i_unit] = st - upst;
74*10023Ssam 				break;
75*10023Ssam 			}
76*10023Ssam 		if (st == &upst[NUPTYPES]) {
77*10023Ssam 			printf("up%d: uphr=%x\n", upaddr->uphr);
78*10023Ssam 			_stop("unknown drive type");
79*10023Ssam 		}
809974Ssam 		upaddr->upcs2 = UPCS2_CLR;
819974Ssam #ifdef DEBUG
829974Ssam 		printf("Unittype=%d\n",up_type[io->i_unit]);
839974Ssam #endif
849974Ssam 
85*10023Ssam 		/*
86*10023Ssam 		 * Read in the bad sector table:
87*10023Ssam 		 *	copy the contents of the io structure
88*10023Ssam 		 *	to tio for use during the bb pointer
89*10023Ssam 		 *	read operation.
90*10023Ssam 		 */
91*10023Ssam 		tio = *io;
92*10023Ssam 		tio.i_bn = st->nspc * st->ncyl - st->nsect;
939974Ssam 		tio.i_ma = (char *)&upbad[tio.i_unit];
94*10023Ssam 		tio.i_cc = sizeof (upbad);
95*10023Ssam 		tio.i_flgs |= F_RDDATA;
96*10023Ssam 		for (i = 0; i < 5; i++) {
97*10023Ssam 			if (upstrategy(&tio, READ) == sizeof (upbad))
98*10023Ssam 				break;
999974Ssam 			tio.i_bn += 2;
1009974Ssam 		}
1019974Ssam 		if (i == 5) {
102*10023Ssam 			printf("Unable to read bad sector table\n");
103*10023Ssam 			for (i = 0; i < 126; i++) {
1049974Ssam 				upbad[io->i_unit].bt_bad[i].bt_cyl = -1;
1059974Ssam 				upbad[io->i_unit].bt_bad[i].bt_trksec = -1;
1069974Ssam 			}
1079974Ssam 		}
1089974Ssam 		up_gottype[io->i_unit] = 1;
1099974Ssam 	}
1109974Ssam 	io->i_boff = st->off[io->i_boff] * st->nspc;
111*10023Ssam 	io->i_flgs &= ~F_TYPEMASK;
1129974Ssam }
1139974Ssam 
1149974Ssam upstrategy(io, func)
1159974Ssam 	register struct iob *io;
1169974Ssam {
1179974Ssam 	int unit, cn, tn, sn;
1189974Ssam 	daddr_t bn;
1199974Ssam 	int recal, info, waitdry;
1209974Ssam 	register struct updevice *upaddr =
1219974Ssam 	    (struct updevice *)ubamem(io->i_unit, ubastd[0]);
1229974Ssam 	register struct upst *st = &upst[up_type[io->i_unit]];
1239974Ssam 
124*10023Ssam 	if (func != READ && func != WRITE) {
125*10023Ssam 		io->i_error = ECMD;
126*10023Ssam 		return (-1);
127*10023Ssam 	}
1289974Ssam 	unit = io->i_unit;
1299974Ssam 	io->i_errcnt = 0;
1309974Ssam 	recal = 3;
1319974Ssam 	upaddr->upcs2 = unit;
1329974Ssam 	if ((upaddr->upds & UPDS_VV) == 0) {
1339974Ssam 		upaddr->upcs1 = UP_DCLR|UP_GO;
1349974Ssam 		upaddr->upcs1 = UP_PRESET|UP_GO;
1359974Ssam 		upaddr->upof = UPOF_FMT22;
1369974Ssam 	}
1379974Ssam 	if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY)
1389974Ssam 		_stop("up not ready");
1399974Ssam 	info = ubasetup(io, 1);
1409974Ssam 	upaddr->upwc = -io->i_cc / sizeof (short);
1419974Ssam 	upaddr->upba = info;
1429974Ssam readmore:
1439974Ssam 	bn = io->i_bn + btop(io->i_cc + upaddr->upwc*sizeof(short));
144*10023Ssam 	while((upaddr->upds & UPDS_DRY) == 0)
145*10023Ssam 		;
1469974Ssam 	if (upstart(io, bn) != 0)
1479974Ssam 		return (-1);
1489974Ssam 	do {
1499974Ssam 		DELAY(25);
1509974Ssam 	} while ((upaddr->upcs1 & UP_RDY) == 0);
1519974Ssam 
1529974Ssam 	if (((upaddr->upds&UPDS_ERR) | (upaddr->upcs1&UP_TRE)) == 0 )
1539974Ssam 		return(io->i_cc);
1549974Ssam 
1559974Ssam #ifdef LOGALLERRS
1569974Ssam 	printf("uper: (c,t,s)=(%d,%d,%d) cs2=%b er1=%b er2=%b wc=%x\n",
1579974Ssam 			upaddr->updc, upaddr->upda>>8, (upaddr->upda&0x1f-1),
1589974Ssam 		    	upaddr->upcs2, UPCS2_BITS, upaddr->uper1,
1599974Ssam 			UPER1_BITS, upaddr->uper2, UPER2_BITS,-upaddr->upwc);
1609974Ssam #endif
1619974Ssam 	waitdry = 0;
162*10023Ssam 	while ((upaddr->upds & UPDS_DRY) == 0 && ++waitdry < 512)
163*10023Ssam 		DELAY(5);
1649974Ssam 	if (++io->i_errcnt > 27) {
1659974Ssam 		/*
1669974Ssam 		 * After 28 retries (16 without offset, and
1679974Ssam 		 * 12 with offset positioning) give up.
1689974Ssam 		 */
169*10023Ssam 		io->i_error = EHER;
1709974Ssam hard:
171*10023Ssam 		if (upaddr->upcs2 & UPCS2_WCE)
172*10023Ssam 			io->i_error = EWCK;
1739974Ssam 		bn = io->i_bn + btop(io->i_cc + upaddr->upwc*sizeof(short));
1749974Ssam 		cn = bn/st->nspc;
1759974Ssam 		sn = bn%st->nspc;
1769974Ssam 		tn = sn/st->nsect;
1779974Ssam 		sn = sn%st->nsect;
1789974Ssam 		printf("up error: (cyl,trk,sec)=(%d,%d,%d) cs2=%b er1=%b er2=%b\n",
1799974Ssam 		    	cn, tn, sn,
1809974Ssam 		    	upaddr->upcs2, UPCS2_BITS, upaddr->uper1,
1819974Ssam 			UPER1_BITS, upaddr->uper2, UPER2_BITS);
1829974Ssam 		upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO;
1839974Ssam 		return (io->i_cc + upaddr->upwc*sizeof(short));
1849974Ssam 	} else
1859974Ssam 		if (upaddr->uper1&UPER1_WLE) {
186*10023Ssam 			/*
187*10023Ssam 			 * Give up on write locked devices
188*10023Ssam 			 * immediately.
189*10023Ssam 			 */
190*10023Ssam 			printf("up%d: write locked\n", unit);
191*10023Ssam 			return(-1);
1929974Ssam 		}
1939974Ssam #ifndef NOBADSECT
1949974Ssam 	else if (upaddr->uper2 & UPER2_BSE) {
1959974Ssam 		if (upecc( io, BSE))
1969974Ssam 			goto success;
1979974Ssam 		else {
198*10023Ssam 			io->i_error = EBSE;
1999974Ssam 			goto hard;
2009974Ssam 		}
2019974Ssam 	}
2029974Ssam #endif
2039974Ssam 	else {
2049974Ssam 		/*
2059974Ssam 		 * Retriable error.
2069974Ssam 		 * If a soft ecc, correct it
2079974Ssam 		 * Otherwise fall through and retry the transfer
2089974Ssam 		 */
2099974Ssam 		if ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK) {
210*10023Ssam 			upecc(io, ECC);
2119974Ssam 			goto success;
212*10023Ssam 		} else
2139974Ssam 			io->i_active = 0; /* force retry */
2149974Ssam 	}
2159974Ssam 	/*
2169974Ssam 	 * Clear drive error and, every eight attempts,
2179974Ssam 	 * (starting with the fourth)
2189974Ssam 	 * recalibrate to clear the slate.
2199974Ssam 	 */
2209974Ssam 	upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO;
2219974Ssam 	if ((io->i_errcnt&07) == 4 && io->i_active == 0) {
2229974Ssam 		upaddr->upcs1 = UP_RECAL|UP_GO;
2239974Ssam 		recal = 0;
2249974Ssam 		goto nextrecal;
2259974Ssam 	}
2269974Ssam 	/*
2279974Ssam 	 * Advance recalibration finite state machine
2289974Ssam 	 * if recalibrate in progress, through
2299974Ssam 	 *	RECAL
2309974Ssam 	 *	SEEK
2319974Ssam 	 *	OFFSET (optional)
2329974Ssam 	 *	RETRY
2339974Ssam 	 */
2349974Ssam 	switch (recal) {
2359974Ssam 
2369974Ssam 	case 1:
2379974Ssam 		upaddr->updc = cn;
2389974Ssam 		upaddr->upcs1 = UP_SEEK|UP_GO;
2399974Ssam 		goto nextrecal;
240*10023Ssam 
2419974Ssam 	case 2:
2429974Ssam 		if (io->i_errcnt < 16 || (func & READ) == 0)
2439974Ssam 			goto donerecal;
2449974Ssam 		upaddr->upof = up_offset[io->i_errcnt & 017] | UPOF_FMT22;
2459974Ssam 		upaddr->upcs1 = UP_OFFSET|UP_GO;
2469974Ssam 	nextrecal:
2479974Ssam 		recal++;
2489974Ssam 		io->i_active = 1;
2499974Ssam 		goto readmore;
250*10023Ssam 
2519974Ssam 	donerecal:
2529974Ssam 	case 3:
2539974Ssam 		recal = 0;
2549974Ssam 		io->i_active = 0;
2559974Ssam 		break;
2569974Ssam 	}
2579974Ssam 	/*
2589974Ssam 	 * If still ``active'', then don't need any more retries.
2599974Ssam 	 */
2609974Ssam 	if (io->i_active) {
2619974Ssam 		/*
2629974Ssam 		 * If we were offset positioning,
2639974Ssam 		 * return to centerline.
2649974Ssam 		 */
2659974Ssam 		if (io->i_errcnt >= 16) {
2669974Ssam 			upaddr->upof = UPOF_FMT22;
2679974Ssam 			upaddr->upcs1 = UP_RTC|UP_GO;
268*10023Ssam 			while ((upaddr->upds&UPDS_DRY) == 0)
2699974Ssam 				DELAY(25);
2709974Ssam 		}
2719974Ssam 		goto readmore;
2729974Ssam 	}
2739974Ssam success:
2749974Ssam 	io->i_active = 1;
275*10023Ssam 	if (upaddr->upwc != 0)
2769974Ssam 		goto readmore;
2779974Ssam 	/*
2789974Ssam 	 * Release unibus
2799974Ssam 	 */
2809974Ssam 	ubafree(io, info);
2819974Ssam 	return (io->i_cc);
2829974Ssam }
2839974Ssam 
2849974Ssam /*
2859974Ssam  * Correct an ECC error, and restart the i/o to complete
2869974Ssam  * the transfer if necessary.  This is quite complicated because
2879974Ssam  * the transfer may be going to an odd memory address base and/or
2889974Ssam  * across a page boundary.
2899974Ssam  */
290*10023Ssam upecc(io, flag)
2919974Ssam 	register struct iob *io;
2929974Ssam 	int flag;
2939974Ssam {
2949974Ssam 	register struct updevice *up =
2959974Ssam 		(struct updevice *)ubamem(io->i_unit, ubastd[0]);
2969974Ssam 	register struct upst *st;
2979974Ssam 	register int i;
2989974Ssam 	caddr_t addr;
2999974Ssam 	int bit, byte, npf, mask;
3009974Ssam 	int bn, twc, bbn;
3019974Ssam 
3029974Ssam 	/*
3039974Ssam 	 * Npf is the number of sectors transferred before the sector
3049974Ssam 	 * containing the ECC error, bn is the current block number
3059974Ssam 	 */
3069974Ssam 	npf = btop((up->upwc * sizeof(short)) + io->i_cc);
3079974Ssam 	mask = up->upec2;
3089974Ssam #ifdef UPECCDEBUG
3099974Ssam 	printf("npf %d mask 0x%x pos %d wc 0x%x\n",npf,mask,up->upec1,-up->upwc);
3109974Ssam #endif
3119974Ssam 	bn = io->i_bn + npf + 1 ;
3129974Ssam 	st = &upst[up_type[io->i_unit]];
3139974Ssam 	twc = up->upwc;
3149974Ssam 	io->i_active = 2;
3159974Ssam 	/*
3169974Ssam 	 * action taken depends on the flag
3179974Ssam 	 */
3189974Ssam 	if (flag == ECC) {
3199974Ssam 		mask = up->upec2;
3209974Ssam 		printf("up%d: soft ecc sn%d\n", io->i_unit, io->i_bn + npf +1);
3219974Ssam 		/*
3229974Ssam 		 * Compute the
3239974Ssam 		 * byte and bit position of the error.  The variable i
3249974Ssam 		 * is the byte offset in the transfer.
3259974Ssam 		 */
3269974Ssam 		i = up->upec1 - 1;		/* -1 makes 0 origin */
3279974Ssam 		bit = i&07;
3289974Ssam 		i = (i&~07)>>3;
3299974Ssam 		byte = i;
3309974Ssam 		up->upcs1 = UP_TRE|UP_DCLR|UP_GO;
3319974Ssam 		/*
3329974Ssam 		 * Correct while possible bits remain of mask.  Since mask
3339974Ssam 		 * contains 11 bits, we continue while the bit offset is > -11.
3349974Ssam 		 * Also watch out for end of this block and the end of the whole
3359974Ssam 		 * transfer.
3369974Ssam 		 */
3379974Ssam 		while (i < 512 && (int)ptob(npf)+i < io->i_cc && bit > -11) {
3389974Ssam 			/*
339*10023Ssam 			 * addr = vax base addr + (number of sectors transferred
3409974Ssam 			 *	  before the error sector times the sector size)
3419974Ssam 			 *	  + byte number
3429974Ssam 			 */
3439974Ssam 			addr = io->i_ma + (npf*512) + byte;
3449974Ssam #ifdef UPECCDEBUG
3459974Ssam 			printf("addr %x old: %x ",addr, *addr);
3469974Ssam #endif
3479974Ssam 			*addr ^= (mask << bit);
3489974Ssam #ifdef UPECCDEBUG
3499974Ssam 			printf("new: %x\n", *addr);
3509974Ssam #endif
3519974Ssam 			byte++;
3529974Ssam 			i++;
3539974Ssam 			bit -= 8;
3549974Ssam 		}
3559974Ssam #ifndef NOBADSECT
3569974Ssam 	} else if (flag == BSE) {
3579974Ssam 		/*
3589974Ssam 		 * if not in bad sector table, return 0
3599974Ssam 		 */
3609974Ssam 		if ((bbn = isbad(&upbad[io->i_unit], st, bn)) < 0)
3619974Ssam 			return(0);
3629974Ssam 		up->upcs1 = UP_TRE|UP_DCLR|UP_GO;
3639974Ssam 		bbn = st->ncyl * st->nspc -st->nsect - 1 - bbn;
3649974Ssam 		twc = up->upwc + 512;
3659974Ssam 		up->upwc = -(512 / sizeof (short));
3669974Ssam #ifdef UPECCDEBUG
3679974Ssam 		printf("revector to block %d\n", bbn);
3689974Ssam #endif
3699974Ssam 		/*
3709974Ssam 	 	* Clear the drive & read the replacement sector.
3719974Ssam 	 	* If this is in the middle of a transfer, then set up the
3729974Ssam 	 	* controller registers in a normal fashion.
3739974Ssam 	 	* The ub-address need not be changed.
3749974Ssam 	 	*/
375*10023Ssam 		while (up->upcs1 & UP_RDY == 0)
3769974Ssam 			;
3779974Ssam 		up->upcs1 = UP_TRE|UP_DCLR|UP_GO;
378*10023Ssam 		if (upstart(io, bbn) != 0)
379*10023Ssam 			return (0);
3809974Ssam 		io->i_errcnt = 0;
3819974Ssam 		do {
3829974Ssam 			DELAY(25);
3839974Ssam 		} while ( up->upcs1 & UP_RDY == 0) ;
3849974Ssam 		if (up->upds & UPDS_ERR || up->upcs1 & UP_TRE) {
3859974Ssam 			up->upwc = twc -512;
3869974Ssam 			return (0);
3879974Ssam 		}
3889974Ssam 	}
389*10023Ssam 	if (twc != 0)
3909974Ssam 		up->upwc = twc;
3919974Ssam 	return (1);
3929974Ssam }
3939974Ssam 
3949974Ssam #ifndef NOBADSECT
3959974Ssam /*
3969974Ssam  * Search the bad sector table looking for
3979974Ssam  * the specified sector.  Return index if found.
3989974Ssam  * Return -1 if not found.
3999974Ssam  */
4009974Ssam isbad(bt, st, blno)
4019974Ssam 	register struct dkbad *bt;
4029974Ssam 	register struct upst *st;
4039974Ssam {
4049974Ssam 	register int i;
4059974Ssam 	register long blk, bblk;
4069974Ssam 	int trk, sec;
4079974Ssam 
4089974Ssam 	sec = blno % st->nspc;
4099974Ssam 	trk = sec / st->nsect;
4109974Ssam 	sec %= st->nsect;
4119974Ssam 	blk = ((long)(blno/st->nspc) << 16) + (trk << 8) + sec;
4129974Ssam 	for (i = 0; i < 126; i++) {
413*10023Ssam 		bblk = ((long)bt->bt_bad[i].bt_cyl << 16) +
414*10023Ssam 			bt->bt_bad[i].bt_trksec;
4159974Ssam 		if (blk == bblk)
4169974Ssam 			return (i);
4179974Ssam 		if (blk < bblk || bblk < 0)
4189974Ssam 			break;
4199974Ssam 	}
4209974Ssam 	return (-1);
4219974Ssam }
4229974Ssam #endif
4239974Ssam 
4249974Ssam upstart(io, bn)
425*10023Ssam 	register struct iob *io;
426*10023Ssam 	daddr_t bn;
4279974Ssam {
4289974Ssam 	register struct updevice *upaddr =
429*10023Ssam 		(struct updevice *)ubamem(io->i_unit, ubastd[0]);
4309974Ssam 	register struct upst *st = &upst[up_type[io->i_unit]];
4319974Ssam 	int sn, tn;
4329974Ssam 
4339974Ssam 	sn = bn%st->nspc;
4349974Ssam 	tn = sn/st->nsect;
4359974Ssam 	sn %= st->nsect;
4369974Ssam 	upaddr->updc = bn/st->nspc;
4379974Ssam 	upaddr->upda = (tn << 8) + sn;
438*10023Ssam 	switch (io->i_flgs&F_TYPEMASK) {
439*10023Ssam 
440*10023Ssam 	case F_RDDATA:
441*10023Ssam 		upaddr->upcs1 = UP_RCOM|UP_GO;
4429974Ssam 		break;
443*10023Ssam 
444*10023Ssam 	case F_WRDATA:
445*10023Ssam 		upaddr->upcs1 = UP_WCOM|UP_GO;
4469974Ssam 		break;
447*10023Ssam 
448*10023Ssam 	case F_HDR|F_RDDATA:
449*10023Ssam 		upaddr->upcs1 = UP_RHDR|UP_GO;
450*10023Ssam 		break;
451*10023Ssam 
452*10023Ssam 	case F_HDR|F_WRDATA:
453*10023Ssam 		upaddr->upcs1 = UP_WHDR|UP_GO;
454*10023Ssam 		break;
455*10023Ssam 
456*10023Ssam 	case F_CHECK|F_WRDATA:
457*10023Ssam 	case F_CHECK|F_RDDATA:
4589974Ssam 		upaddr->upcs1 = UP_WCDATA|UP_GO;
4599974Ssam 		break;
460*10023Ssam 
461*10023Ssam 	case F_HCHECK|F_WRDATA:
462*10023Ssam 	case F_HCHECK|F_RDDATA:
4639974Ssam 		upaddr->upcs1 = UP_WCHDR|UP_GO;
4649974Ssam 		break;
465*10023Ssam 
4669974Ssam 	default:
467*10023Ssam 		io->i_error = ECMD;
468*10023Ssam 		io->i_flgs &= ~F_TYPEMASK;
469*10023Ssam 		return (1);
4709974Ssam 	}
471*10023Ssam 	return (0);
4729974Ssam }
4739974Ssam 
474*10023Ssam /*ARGSUSED*/
475*10023Ssam upioctl(io, cmd, arg)
476*10023Ssam 	struct iob *io;
477*10023Ssam 	int cmd;
478*10023Ssam 	caddr_t arg;
479*10023Ssam {
480*10023Ssam 
481*10023Ssam 	return (ECMD);
482*10023Ssam }
483