File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / sys / bsc / bscm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
Power 6/32 Unix version 1.2b

/*	D.L.Buck and Associates, Inc. - 9/4/84
 *
 *	COPYRIGHT NOTICE:
 *		Copyright c 9/4/84 - An unpublished work by
 *		D.L.Buck and Associates, Inc.
 *
 *	PROPRIETARY RIGHTS NOTICE:
 *		All rights reserved. This document and program contains
 *		proprietary information of D.L.Buck and Associates,Inc.
 *		of San Jose, California, U.S.A., embodying confidential
 *		information,  ideas, and expressions,  no part of which
 *		may be reproduced, or transmitted in any form or by any
 *		means,  electronic,  mechanical,  or otherwise, without
 *		the written permission of D.L.Buck and Associates, Inc.
 *
 * NAME
 *	bsm - multi-station bisync device driver
 *
 * DESCRIPTION
 *	This file contains the Unix system interface routines, prepared for
 *	UNIX Version 7, System III, System V, or BSD 4.2.
 *	The entry points are bsmopen, bsmclose, bsmread, bsmwrite, and
 *	bsmioctl.  These routines are meant to be hardware-independent.
 */

#ifndef lint
static char bsm_c[] = "@(#)bscm.c	1.17 REL";
#endif

#include "../bsc/local.h"
#include "../bsc/bscio.h"
#include "../bsc/bsc.h"

#if defined v7 || defined BSD42
#define	delay(x)	sleep((caddr_t)&lbolt, BSCPRI)
extern int lbolt;
#endif

#if defined BSD42
#define ERRRET(x)	return x
#define	UCOUNT	uio->uio_resid
#else
#define	ERRRET(x)	u.u_error = x; return
#define	UCOUNT	u.u_count
#endif


/***
#define DEV(dev)  (minor(dev) >> 5) & 0x7
#define SUBDEV(dev)  minor(dev) & 0x1f
***/

#define DEV(dev)  (minor(dev) >> 4) & 0xf
#define SUBDEV(dev)  minor(dev) & 0xf

extern struct state states[];		/* state table in bscpsm.c */
#ifdef NBSM
extern struct bsc bsc[];		/* device-specific information */
struct bscsub bscsubs[NVBSC*NBSM][NBSSUB];

/*
 *	DEVICE ADDRESSING TABLES
 *		For device numbers 0 - 31, the tables hold the corresponding
 *		EBCDIC (ebcdev) or ASCII (ascdev) address
 */


char ascdev[] = {0x20,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
		 0x48,0x49,0x5b,0x2e,0x3c,0x28,0x2b,0x21,
		 0x26,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,
		0x51,0x52,0x5d,0x24,0x2a,0x29,0x3b,0x5e};

char ebcdev[] = {0x40,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
		 0xc8,0xc9,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
		 0x50,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,
		0xd8,0xd9,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f};
/*
 * NAME
 *	bsmopen -- Prepare for BISYNC communications, multistation mode
 * SYNOPSIS
 *	bsmopen (dev, flag)
 *	dev_t dev;		minor device number:
 *				bits 7-5: modem port number
 *				bits 4-0: station number, 0-31
 *	int flag;		unused
 * ALGORITHM
 *	1. Check and lock device.
 *	2. If first station to open on this line, do line initialization
 *		2.1 Set up defaults for ioctl-provided params
 *		2.2 Set up counters and fields returned via ioctl
 *		2.3 Set up miscellaneous fields for driver
 *		2.4 Initialize I/O port
 *	3. Wait till DSR shows
 *	4. If tracing activated, awaken bstopen
 */

/* VARARGS1 */
bsmopen (dev)				/* prepare for BISYNC communication */
dev_t dev;
{
	register dev_t bscdev;		/* modem port number */
	register struct bsc *bp;	/* ptr to port's bsc entry */
	register int subdev;		/* station number */
	register struct bscsub *bpsub;  /* ptr to station's bscsubs entry */
	int errcode;

	/* 1. Check and lock device. */
	bscdev = DEV(dev);
	subdev = SUBDEV(dev);

	if (bscdev >= MX_NBSM || subdev >= NBSSUB){
		ERRRET(ENXIO);	/* no such device */
	}
	bp = &bsc[bscdev];
	bpsub = &bscsubs[bscdev][subdev];
	if ((bp->b_lock == SSLOCK) || 	/* line opened for point to point */
	    (bpsub->bs_mode != BS_FREE)) {	/* subdevice busy */
		ERRRET(EBUSY);
	}
	bpsub->bs_mode = BS_IDLE;
	bpsub->bs_sema = BSC_DDONE | BSC_PDONE;

	/* 2. If first station to open on this line, do line initialization */
	if (++bp->b_lock == 1) {	/* First one initializes */

		/* 2.1 Set up defaults for ioctl-provided params */
		bp->b_iocin.b_blks = BSCMBLK;	/* max block size */
		bp->b_hlflgs = BSCMPT;		/* flags: we are multipoint */
		bp->b_iocin.b_termid[0]	= '\0';	/* no terminal id */
		bp->b_iocin.b_hostid[0] = '\0';	/* no host id */
		bp->b_iocin.b_nbid = 		/* max # bids */
		bp->b_iocin.b_nnak = 		/* max # naks we will give */
		bp->b_iocin.b_nretry = 15;	/* max # rcv t/o's and naks */
						/*       we will accept */
		bp->b_iocin.b_nttd = 		/* max # ttds we will accept */
		bp->b_iocin.b_nwack = 100;	/* max # wacks we will accept */
		bp->b_iocin.b_nor = 30;		/* max time to wait on */
						/* initial rd */

		/* 2.2 Set up counters and fields returned via ioctl */
		bp->b_iocout.b_blks = 0;	/* # blocks sent/received */
		bp->b_iocout.b_flags = 0;	/* flags: see definition */
		bp->b_iocout.b_termid[0] = '\0';/* no terminal id */
		bp->b_iocout.b_hostid[0] = '\0';/* no host id */
		bp->b_iocout.b_nbid = 0;	/* no bids so far */
		bp->b_iocout.b_nnak = 0;	/* no naks so far */
		bp->b_iocout.b_nretry = 0;	/* no retry so far */
		bp->b_iocout.b_nttd = 0;	/* no ttds so far */
		bp->b_iocout.b_nwack = 0;	/* no wacks so far */
		bp->b_iocout.b_nor = 0;		/* no overruns so far */

		/* 2.3 Set up miscellaneous fields for driver */
		bp->b_state = 0;		/* set initial psm state*/
		bp->b_mode = BSC_INIT;		/* initial mode indicates */
						/* haven't done any i/o yet */
		bp->b_psmbsy = -1;		/* no device selected */
		bp->b_rxst0 = 0;		/* reset l/l driver state */
		bp->b_tmperr = 0;		/* no temp. errors yet */
		bp->b_sema = BSC_DDONE;		/* driver not busy */

		/* 2.4 Initialize I/O port */
		errcode = bsclopn(bscdev,bp);	/* device-specific init. */
		if (errcode) {
			bp->b_lock = 0;		/* Unlock device	*/
			ERRRET(errcode);
		}
	}

	/* 3. Wait till DSR shows */
	while (bsckdsr(bscdev,bp), !(bp->b_hlflgs & BSC_DSR) && !u.u_error)
		delay(PSMTICK);

	/* 4. If tracing activated, awaken bstopen */
	if (bp->b_trace)
		wakeup(&bp->b_trace);
	if (u.u_error)
		bsmclose(dev);
#if defined BSD42
	return 0;
#endif
}

/*
 * NAME
 *	bsmclose -- Terminate station processing
 * SYNOPSIS
 *	bsmclose(dev)
 *	dev_t dev;		minor device number:
 *				bits 7-5: modem port number
 *				bits 4-0: station number, 0-31
 * ALGORITHM
 *	1. Mark station done, free; decrement multistation lock
 *	   If not last station using line, return.
 *	2. Terminate PSM processing, kill receive and tracing
 *	3. Turn off DTR
 */
bsmclose(dev)
dev_t dev;
{
	register dev_t bscdev;		/* modem port number */
	register struct bsc *bp;	/* ptr to port's bsc entry */
	register int subdev;		/* station number */
	register struct bscsub *bpsub;  /* ptr to station's bscsubs entry */
	register long s;

	bscdev = DEV(dev);
	subdev = SUBDEV(dev);
	bp = &bsc[bscdev];
	bpsub = &bscsubs[bscdev][subdev];

	/* 1. Mark station done, free; decrement multistation lock.	*/
	/*    If not last station using line, return.			*/
	bpsub->bs_sema &= ~BSC_DBUSY;
	bpsub->bs_sema |= BSC_DDONE;
	bpsub->bs_mode = BS_FREE;
	bpsub->bs_flags = 0;
	if (--bp->b_lock) return;	/* others still using the line */
        s = spl8(); 

	/* 2. Terminate PSM processing, kill receive and tracing */
	bp->b_mode = BSC_CLOSED;		/* mode is CLOSED */
	bp->b_rclptr = (char *)0;		/* terminate receive */
	bstclose(bscdev);			/* close trace device, too */

	/* 3. Turn off DTR */
	bsclcls (bscdev, bp);
        splx(s);

#if defined BSD42
	return 0;
#endif
}

/*
 * NAME
 *	bsmread -- read next data block.
 * SYNOPSIS
 *	bsmread(dev)
 *	dev_t dev;		minor device number:
 *				bits 7-5: modem port number
 *				bits 4-0: station number, 0-31
 * ALGORITHM
 *	1. Check for error latch or lack of DSR.
 *	   If either set, return EIO error.
 *	2. If first activity on line, set up psm.
 *	3. Based on present mode:
 *	3.1 Write: error (EINVAL)
 *	3.2 Idle: Synch up with psm, then go to Read mode
 *	3.3 Read: If delay mode in effect, wait for err, eof, or data
 *	3.3.1 Check for NO DELAY mode
 *	3.3.2 Wait for full buffer, eof, or error
 *	3.3.3 If EOF, chg mode to Idle, return 0 bytes read
 *	3.3.4 If ERR, leave mode at Read, return -1(EIO)
 *	3.3.5 Buffer full. Copy data out, set length.
 *	4. Mark buffer empty, awaken psm if its sleeping
 */
#if defined BSD42
bsmread(dev,uio)
register dev_t dev;
struct uio *uio;
#else
bsmread(dev)
register dev_t dev;
#endif
{
	register dev_t bscdev;		/* modem port number */
	register struct bsc *bp;	/* ptr to port's bsc entry */
	register int subdev;		/* station number */
	register struct bscsub *bpsub;  /* ptr to station's bscsubs entry */
	register int l;			/* length info. */
	int x;				/* prty save area */
	int errcode = 0;		/* Error code upon return	*/

	bscdev = DEV(dev);
	subdev = SUBDEV(dev);
	bp = &bsc[bscdev];
	bpsub = &bscsubs[bscdev][subdev];

	/* 1. Check for error latch or lack of DSR.	*/
	/*    If either set, return EIO error.		*/
	if (!(bp->b_hlflgs & BSC_DSR) || (bpsub->bs_flags & BS_ERR)) {
		if (!(bpsub->bs_flags & BS_ERR)) {
			bpsub->bs_flags |= BS_ERR;
			bpsub->bs_err = BSCNDSR;
		}
		bpsub->bs_mode = BS_IDLE;
		ERRRET(EIO);
	}

	/* 2. If first activity on line, set up psm */
	if (bp->b_mode == BSC_INIT) {
		bscsetup(bscdev);
		bp->b_mode = BSC_IDLE;
	}

	/* 3. Based on present mode:				*/
	switch (bpsub->bs_mode)
	{
	/* 3.1 Write: error (EINVAL)				*/
	case BS_WRITE:
		ERRRET(EINVAL);

	/* 3.2 Idle: Synch up with psm, then go to Read mode	*/
	case BS_IDLE:			/* First read call */
		while (!u.u_error &&
		       !(bpsub->bs_sema & BSC_PDONE) &&
			(bpsub->bs_mode == BS_IDLE) &&
		       !(bpsub->bs_flags&BS_ERR))
			delay(PSMTICK);	/* Synchronize */
		/* Set read timeout counter */
		bpsub->bs_rdflg = bp->b_iocin.b_nor*PSMTPS;
		bpsub->bs_mode = BS_READ;
		bpsub->bs_sema |= BSC_DBUSY;
		bpsub->bs_sema &= ~BSC_DDONE;	/* driver now busy */

	/* 3.3 Read: If delay mode in effect, wait for err, eof, or data */
	case BS_READ:			/* not first read */
forceread:
		x = spl8();
		/* 3.3.1 Check for NO DELAY mode */
		if (bpsub->bs_sema & BSC_SEENBUF) {
			bpsub->bs_flags &= ~BS_FULL;
			bpsub->bs_sema &= ~BSC_SEENBUF;
			if (states[bp->b_state].s_type == 'd' &&
			    bp->b_alenb) {
				bp->b_alenb = 0;	/* disable alarm */
				splx(x);
				bscpsm(bscdev);		/* awaken psm */
			}
		}
		if ((bpsub->bs_sema & BSC_NDLY) && 
		    !(bpsub->bs_flags & (BS_FULL|BS_ERR|BS_LAST))) {
			splx(x);
			ERRRET(EAGAIN);	/* Call again later */
		}

		/* 3.3.2 Wait for full buffer, eof, or error */
		while (!(bpsub->bs_flags & (BS_FULL|BS_ERR|BS_LAST)))
			sleep ((caddr_t)&bpsub->bs_flags,BSCPRI);
		splx(x);

		bpsub->bs_rdflg = 0;		/* cancel read timeout */

		/* 3.3.3 If EOF, chg mode to Idle, return 0 bytes read */
		if (bpsub->bs_flags & BS_LAST) {
			bpsub->bs_mode = BS_IDLE;
			bp->b_hlflgs &= ~(BSC_XLAST|BSC_XTRN);
			bpsub->bs_flags &= ~(BS_LAST|BSC_XTRN);
			bpsub->bs_sema |= BSC_DDONE;
			bpsub->bs_sema &= ~BSC_DBUSY;
			goto readexit;
		}

		/* 3.3.4 If ERR, leave mode at Read, return -1(EIO) */
		if (bpsub->bs_flags & BS_ERR) {	/* error way out */
			bp->b_hlflgs &= ~(BSC_XLAST|BSC_FULL|BSC_XTRN);
			bpsub->bs_flags &= ~BS_FULL;
			bpsub->bs_sema &= ~BSC_SEENBUF;
			errcode = EIO;
			goto readexit;
		}

		/* 3.3.5 Buffer full. Copy data out, set length.	*/
		l = bp->b_bsize;	/* buffer space occupied */
		if (l > UCOUNT)
			l = UCOUNT;
		if (l)
#if defined BSD42
			errcode = uiomove(bp->b_buffer,l,UIO_READ,uio);
#else
			if (iomove (bp->b_buffer, l, B_READ))
				errcode = EFAULT;
#endif

		if (bpsub->bs_sema & BSC_FACK) {
			bpsub->bs_sema |= BSC_SEENBUF;
			goto readret;
		}

	/* 4. Mark buffer empty, awaken psm if its sleeping */
readexit:
		bpsub->bs_flags &= ~BS_FULL;
		bp->b_hlflgs &= ~BSC_FULL;	/* mark buffer empty */
		x = spl8();
		if (states[bp->b_state].s_type == 'd' &&
		    bp->b_alenb) {
			bp->b_alenb = 0;	/* disable alarm */
			splx(x);
			bscpsm(bscdev);		/* awaken psm */
		} else	splx(x);
	}
readret:
#if defined BSD42
	return errcode;
#else
	if (errcode)
		u.u_error = errcode;
#endif
}

/*
 *	bsmwrite -- 1) if user's length = 0 or > max block, error
 *		    2) if mode = read, or if error latch set, error!
 *		    3) if mode = init, prime the driver
 *		    4) if mode = idle, init, or write,
 *			  a) set mode to write,
 *			  b) wait till buffer empty,
 *			  c) fill the buffer, 
 *			  d) set flag to show buffer full.
 *		    ** The psm will reset the mode to idle after sending EOT.
 */
#if defined BSD42
bsmwrite(dev,uio)
register dev_t dev;
struct uio *uio;
#else
bsmwrite(dev)
register dev_t dev;
#endif
{
	register int l;			/* length given us */
	register struct bsc *bp;	/* ptr to bsc dev info */
	register struct bscsub *bpsub;  /* ptr to bsc prot dev */
	register int subdev;
	register dev_t bscdev;
	int x;				/* prty save area */
	int errcode = 0;		/* Error code to be returned	*/

	subdev = SUBDEV(dev);
	bscdev = DEV(dev);
	bp = &bsc[bscdev];
	bpsub = &bscsubs[bscdev][subdev];

	/* 0. Check error latch and DSR */
	if ((bpsub->bs_flags & BS_ERR) || !(bp->b_hlflgs & BSC_DSR)) {
		if (!(bpsub->bs_flags & BS_ERR)) {
			bpsub->bs_flags |= BS_ERR;
			bpsub->bs_err = BSCNDSR;
		}
		ERRRET(EIO);
	}

	/* 1. Check length and other errors */
	if ( (l = UCOUNT) == 0 || l > bp->b_iocin.b_blks) {
		ERRRET(EINVAL);
	}

	if (bp->b_mode == BSC_INIT) {
		bscsetup(bscdev);
		bp->b_mode = BSC_IDLE;
	}

	/* 2. process according to mode */
	switch (bpsub->bs_mode)
	{
	case BS_READ:
		if ((bpsub->bs_sema & BSC_FACK) &&
		    (bpsub->bs_sema & BSC_SEENBUF)) {
			bpsub->bs_flags &= ~BS_FULL;
			bpsub->bs_sema &= ~BSC_SEENBUF;
			bpsub->bs_mode = BS_WRITE;
			goto casewrite;
		}
		if (bpsub->bs_rdflg == 0) {
			ERRRET(EINVAL);	/* oops - can't read now! */
		} else {
			bpsub->bs_sema &= ~BSC_DBUSY;
			bpsub->bs_sema |= BSC_DDONE;
			bpsub->bs_rdflg = 1;
			while (bpsub->bs_mode == BS_READ &&
			       !(bpsub->bs_flags & BS_ERR))
				delay(PSMTICK);
		}
		bpsub->bs_mode = BS_IDLE;

	case BS_IDLE:
		if (bpsub->bs_flags & BS_FULL) {
			ERRRET(EINVAL);	/* Caller needs to read */
		}
		while (!(bpsub->bs_sema & BSC_PDONE) &&
		       !(bpsub->bs_flags & BS_ERR))
			delay(PSMTICK);	/* Synchronize */
		bpsub->bs_mode = BS_WRITE;
		bpsub->bs_flags &= ~BS_ERR;	/* reset possible err */
		bpsub->bs_sema |= BSC_DBUSY;
		bpsub->bs_sema &= ~BSC_DDONE;	/* driver now busy */

casewrite:
	case BS_WRITE:
		x = spl8();
		while ((bpsub->bs_flags & BS_FULL) &&   /*wait til empty */
			(!(bpsub->bs_flags & BS_ERR)))
			sleep ((caddr_t)&bpsub->bs_flags,BSCPRI);
		splx(x);

		if (bpsub->bs_flags & BS_ERR){
			bp->b_hlflgs &= ~(BSC_FULL|BSC_XLAST|BSC_XTRN);
			bpsub->bs_flags &= ~(BS_FULL|BS_LAST|BSC_XTRN);
			bpsub->bs_mode = BS_IDLE;
			ERRRET(EIO);
		}

		/* copy data to buffer */
#if defined BSD42
		errcode = uiomove(bpsub->bs_buf,l,UIO_WRITE,uio);
#else
		if (iomove (bpsub->bs_buf, l, B_WRITE))
			errcode = EFAULT;
#endif

		bpsub->bs_size = l;			/*save size */

		x = spl8();
		bpsub->bs_flags |= BS_FULL;		/* bufr now full */
		if (states[bp->b_state].s_type == 'd' &&
		    bp->b_alenb) {		/* decision wait? */
			bp->b_alenb = 0;	/* disable pto */
			splx(x);
			bscpsm(bscdev);		/* wake 'em up */
		} else	splx(x);

		if (bpsub->bs_flags & BS_LAST) { /* if last block, wait */
			x = spl8();
			while ((bpsub->bs_flags & BS_FULL) && /*wait til empty*/
				(!(bpsub->bs_flags & BS_ERR))) /*no error*/
				sleep ((caddr_t)&bpsub->bs_flags, BSCPRI);
			splx(x);
			if (bpsub->bs_flags & BS_ERR){
				errcode = EIO;
			} else	{
				bpsub->bs_sema |= BSC_DDONE;
				bpsub->bs_sema &= ~BSC_DBUSY;
				bpsub->bs_mode = BS_IDLE;
			}
			bp->b_hlflgs &= ~(BSC_XLAST|BSC_FULL|BSC_XTRN);
			bpsub->bs_flags &= ~(BS_LAST|BS_FULL|BSC_XTRN);
		}
	}
#if defined BSD42
	return errcode;
#else
	if (errcode)
		u.u_error = errcode;
#endif
}

/*	bsmioctl -- set options or get counter values
 *		    Depending on cmd:
 *		    BSCGET   - copy b_iocout to user's area
 *		    BSCSET   - copy user's values to b_iocin (set stuff)
 *		    BSCTRNSP - set transparent mode flag
 *		    BSCNTRNS - reset transparent mode flag
 *		    BSCSOH   - set send SOH flag
 *		    BSCNSOH  - turn off SOH flag
 *		    BSCLAST  - set send last flag
 *		    BSCID    - determine port id number 
 */

/*VARARGS3*/
bsmioctl(dev, cmd, arg)
dev_t dev;
struct bscio *arg; 
{
	register struct bsc *bp;	/* ptr to dev info */
	register struct bscsub *bpsub;	/* ptr to port info */
	struct bscio tmp;		/* temp struct for chk'g user params*/
	register int x;
	register int subdev;
	register dev_t bscdev;
	int y,errcode = 0;

	dev = minor(dev);
	subdev = SUBDEV(dev);
	bscdev = DEV(dev);
	bp = &bsc[bscdev];
	bpsub = &bscsubs[bscdev][subdev];
	if (cmd != BSCGET && cmd != BSCSET) {	/* if write op, wait on buf */
		x = spl8();
		while (bpsub->bs_mode == BS_WRITE && bpsub->bs_flags & BS_FULL)
			sleep ((caddr_t)&bpsub->bs_flags, BSCPRI);
		splx(x);
	}

	if ((cmd == BSCSET) && (bp->b_lock != 1)) {/* only 1st can set modes */
		ERRRET(EINVAL);
	}
	switch (cmd) {
	case BSCGET:
		x = spl8();
		bp->b_iocout.b_flags = bpsub->bs_err;
#if defined BSD42
		bcopy((caddr_t)&bp->b_iocout, arg, sizeof bp->b_iocout);
#else
		if (copyout(&bp->b_iocout, arg, sizeof bp->b_iocout))
			errcode = EFAULT;
#endif
		bpsub->bs_err = 0;
		bp->b_iocout.b_flags = 0;
		if (bpsub->bs_flags & BS_ERR) {
			bpsub->bs_flags &= ~(BS_ERR|BS_LAST|BS_FULL|BSC_XTRN);
			bpsub->bs_sema &= ~BSC_DBUSY;
			bpsub->bs_sema |= BSC_DDONE;
			bpsub->bs_mode = BS_IDLE;
		}
		splx(x);
		break;

	case BSCSET:
		if (bpsub->bs_mode == BS_READ || bpsub->bs_mode == BS_WRITE) {
			errcode = EINVAL;	/* can't set if active */
			break;
		}
#if defined BSD42
		bcopy(arg, (caddr_t)&tmp, sizeof tmp);
#else
		if (copyin (arg, &tmp, sizeof tmp)) {
			errcode = EFAULT;
			break;
		}
#endif
		if (tmp.b_blks > BSCMBLK ||	/* block size too big? */
		    tmp.b_blks > sizeof bpsub->bs_buf) {
			errcode = EINVAL;
			break;
		}
		bcopy (/*from*/&tmp, /*to*/&bp->b_iocin, sizeof tmp);
		x = spl8();		/* *** protect hlflgs */
		bp->b_hlflgs &= ~BSC_UFLAGS;	/* throw out old user flags */
		bp->b_hlflgs |= (BSCMPT|(tmp.b_flags & BSC_UFLAGS));
		splx(x);		/* *** end protection */
		bscparam(bscdev);	/* redo parameters */
		break;

	case BSCTRNSP:
		x = spl8();		/* *** protect bsflgs */
		bpsub->bs_flags |= BSC_XTRN;	/* set transparent mode */
		splx(x);		/* *** end protection */
		break;

	case BSCNTRNS:
		x = spl8();		/* *** protect bsflgs */
		bpsub->bs_flags &= ~BSC_XTRN;	/* reset transp. mode */
		splx(x);		/* *** end protection */
		break;

	case BSCSOH:
		x = spl8();		/* *** protect bsflags */
		bpsub->bs_flags |= BSC_XSOH;	/* set send SOH flag */
		splx(x);		/* *** end protection */
		break;

	case BSCNSOH:
		x = spl8();		/* *** protect bsflags */
		bpsub->bs_flags &= ~BSC_XSOH;	/* clear send SOH flag*/
		splx(x);		/* end protection */
		break;

	case BSCLAST:
		x = spl8();		/* *** protect bsflags */
		bpsub->bs_flags |= BS_LAST;   /* set send last blk flag */
		splx(x);		/* end protection */
		break;

	case BSCNDLY:
		x = spl8();		/* protect bs flags */
		bpsub->bs_sema |= BSC_NDLY;
		splx(x);
		break;

	case BSCID:
		y = ((bp->b_hlflgs & BSCASCII)?ascdev:ebcdev)[subdev];
#if defined BSD42
		bcopy((caddr_t)&y, (int *)arg, sizeof y);
#else
		copyout(&y,(int *)arg,sizeof y);
#endif
		break;

	case BSCFACK:
		x = spl8();
		bpsub->bs_sema |= BSC_FACK;
		splx(x);
		break;

	default:
		errcode = EINVAL;
		break;
	}
#if defined BSD42
	return errcode;
#else
	if (errcode)
		u.u_error = errcode;
#endif
}
#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.