/*****************************************************************************
 * Copyright (c) 1988-95 Digi International Inc., All Rights Reserved
 * 
 * This  software  contains  proprietary  and  confidential   information   of
 * Digi International  Inc.   By  accepting  transfer  of this copy, Recipient
 * agrees to retain this software in  confidence,  to  prevent  disclosure  to
 * others,  and  to make no  use of this software other than that for which it
 * was delivered.  This is an unpublished copyright work  Digi   International
 * Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is
 * strictly prohibited.
 * 
 * Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc.
 * Confidential  when   combined   with   the   aggregated  modules  for  this
 * product) OBJECT CODE ONLY SOURCE MATERIALS
 * 
 * (C) COPYRIGHT Digi International Inc. 1995
 * 
 * All Rights Reserved
 * 
 * US   Government   Users   Restricted   Rights   -   Use,   duplication   or
 * disclosure  restricted by GSA ADP Schedule Contract with Digi International
 * Inc.
 * 
 *****************************************************************************/

/******************************************************************
 *
 *  Embedded STREAMS Package
 *
 *  Copyright 1990  Spider Systems Limited
 *
 *  STREAM.H
 *
 *    Main STREAMS definitions
 *
 ******************************************************************/

/*
 *	 /projects/common/PBRAIN/SCCS/pbrainF/dev/embed/common/71/s.stream.h
 *	@(#)stream.h	1.1
 *
 *	Last delta created	12:48:35 6/25/92
 *	This file extracted	12:55:11 10/29/92
 *
 *	Modifications:
 *
 *
 */

#ifndef _STREAM_D
#define	_STREAM_D


#define FAR
typedef unsigned char FAR *bufp_t;

/* Devices */
#define makedev(MAJ,MIN)    ((MAJ)<<8|(MIN))
#define major(DEV)          ((DEV)>>8)
#define minor(DEV)          ((DEV)&255)

/********************************************************/
/*          Streams message and queue types		*/
/********************************************************/

/*
 * Message block descriptor
 */
struct msgb {
    struct msgb  *b_next;    /* next message on queue */
    struct msgb  *b_prev;    /* previous message on queue */
    struct msgb  *b_cont;    /* next message block of message */
    bufp_t        b_rptr;    /* first unread data byte in buffer */
    bufp_t        b_wptr;    /* first unwritten data byte in buffer */
#ifdef SQUEEZE
    struct datab FAR *b_datap;   /* data block */
#else /* SQUEEZE */
    struct datab *b_datap;   /* data block */
#endif /* SQUEEZE */
#ifdef SOH
	BOOLEAN	bFreeMemory;    /* The memory is not part of the minimum allocation */	
#endif

};

typedef struct msgb   mblk_t;
typedef struct msgb MSGB, *PMSGB;

/*
 *  Data block descriptor
 */
struct datab {
#ifdef SQUEEZE
    struct datab FAR *db_freep;  /* used internally */
#else /* SQUEEZE */
    struct datab *db_freep;  /* used internally */
#endif /* SQUEEZE */
    bufp_t        db_base;   /* first byte of buffer */
    bufp_t        db_lim;    /* last byte + 1 of buffer */
    ushort        db_ref;    /* count of messages pointing to this block */
    unchar        db_type;   /* message type */
    unchar        db_class;  /* used internally */
    unchar        db_diag;   /* last-use field for diagnostics */
#ifdef SOH
	BOOLEAN	bFreeMemory;    /* The memory is not part of the minimum allocation */
#endif
};

#ifdef SQUEEZE
typedef struct datab FAR dblk_t;
#else /* SQUEEZE */
typedef struct datab  dblk_t;
#endif /* SQUEEZE */
typedef struct datab DATAB, *PDATAB;

/*
 * Queue information structure
 */
struct    qinit {
    int    (*qi_putp)();          /* put procedure */
    int    (*qi_srvp)();          /* service procedure */
    int    (*qi_qopen)();         /* called on startup */
    int    (*qi_qclose)();        /* called on finish */
    int    (*qi_qadmin)();        /* for 3bnet only */
    struct module_info *qi_minfo; /* module information structure */
    struct module_stat *qi_mstat; /* module statistics structure */
};

typedef struct qinit QINIT, *PQINIT;

/*
 * Module information structure
 */
struct module_info {
    ushort  mi_idnum;     /* module id number */
    char   *mi_idname;    /* module name */
    short   mi_minpsz;    /* min packet size accepted */
    short   mi_maxpsz;    /* max packet size accepted */
    ushort  mi_hiwat;     /* hi-water mark */
    ushort  mi_lowat;     /* lo-water mark */
};

typedef struct module_info  module_info_t;
typedef struct module_info MODINFO, *PMODINFO;

/*
 * Module statistics structure (not used in current implementation)
 */
struct module_stat {
    long    ms_pcnt;      /* count of calls to put proc */
    long    ms_scnt;      /* count of calls to service proc */
    long    ms_ocnt;      /* count of calls to open proc */
    long    ms_ccnt;      /* count of calls to close proc */
    long    ms_acnt;      /* count of calls to admin proc */
    char   *ms_xptr;      /* pointer to private statistics */
    short   ms_xsize;     /* length of private statistics buffer */
};

typedef struct module_stat  module_stat_t;
typedef struct module_stat MODSTAT, *PMODSTAT;

/*
 * Streamtab (used in cdevsw and fmodsw to point to module or driver)
 */
struct streamtab {
    struct qinit *st_rdinit;   /* defines read QUEUE */
    struct qinit *st_wrinit;   /* defines write QUEUE */
    struct qinit *st_muxrinit; /* for multiplexing drivers only */
    struct qinit *st_muxwinit; /* for multiplexing drivers only */
};

typedef struct streamtab  streamtab_t;
typedef struct streamtab STREAMTAB, *PSTREAMTAB;

/*
 * data queue
 */
struct queue {
    struct qinit *q_qinfo;   /* procs and limits for queue */
    struct msgb  *q_first;   /* first data block */
    struct msgb  *q_last;    /* last data block */
    struct queue *q_next;    /* Q of next stream */
    struct queue *q_link;    /* to next Q for scheduling */
#ifdef SQUEEZE
    union
    {
	caddr_t	q_ptr_c;	/* to private data structure */
	ulong	q_ptr_m;
    }	q_ptr_b;
#else /* SQUEEZE */
    caddr_t       q_ptr;     /* to private data structure */
#endif /* SQUEEZE */
    ushort        q_count;   /* number of blocks on Q */
    ushort        q_flag;    /* queue state */
    short         q_minpsz;  /* min packet size accepted by this module */
    short         q_maxpsz;  /* max packet size accepted by this module */
    ushort        q_hiwat;   /* queue high water mark */
    ushort        q_lowat;   /* queue low water mark */
    struct queue *q_other;   /* other queue of pair */
    struct queue *q_can;     /* queue 'canput' looks at */
    struct queue *q_back;    /* queue to back-enable */
#ifdef SOH
	BOOLEAN	bFreeMemory;    /* The memory is not part of the minimum allocation */
#endif
};

#ifdef SQUEEZE
#define q_ptr	q_ptr_b.q_ptr_c
#endif /* SQUEEZE */

typedef struct queue  queue_t;
typedef struct queue QUEUE, *PQUEUE;

/*
 * Structure attached to every (write) side head queue
 */
struct stream {
	struct stream FAR	*str_cnext;	/* next controlled stream */
	struct stream FAR	*str_cprev;	/* prev controlled stream */
	struct stream FAR	*str_cstrm;	/* controlling stream */
	struct stream FAR	*str_clast;	/* last controlled stream */
	struct queue	*str_sq;	/* stream head (write) queue */
	struct queue	*str_dq;	/* driver (write) queue */
	struct streamtab *str_stab;	/* driver streamtab */
	int		 str_dev;	/* stream device */
	int		 str_lindex;	/* link index */
#ifdef SOH
	BOOLEAN	bFreeMemory;    /* The memory is not part of the minimum allocation */
#endif
};
#ifdef	OLDSTR
struct stream {
    struct queue     *str_sq;     /* stream head (write) queue */
    struct queue     *str_dq;     /* driver (write) queue */
    struct streamtab *str_stab;   /* driver streamtab */
#ifdef SQUEEZE
    struct stream    FAR *str_cstrm;  /* controlling stream */
    struct stream    FAR *str_cnext;  /* next controlled stream */
    struct stream    FAR *str_cprev;  /* prev controlled stream */
    struct stream    FAR *str_clast;  /* last controlled stream */
#else /* SQUEEZE */
    struct stream    *str_cstrm;  /* controlling stream */
    struct stream    *str_cnext;  /* next controlled stream */
    struct stream    *str_cprev;  /* prev controlled stream */
    struct stream    *str_clast;  /* last controlled stream */
#endif /* SQUEEZE */
    int		      str_dev;    /* stream device */
    int		      str_lindex; /* link index */
};
#endif	/* OLDSTR */

#define STRM_T

#ifdef SQUEEZE
typedef struct stream FAR strm_t;
#else /* SQUEEZE */
typedef struct stream strm_t;
#endif /* SQUEEZE */
typedef struct stream STREAM, *PSTREAM;

/*
 * Priority definitions for block allocation.
 */
#define NPRI        3   /* Number of priority values */

#define BPRI_LO     0
#define BPRI_MED    1
#define BPRI_HI     2
#define BPRI_INT    3 /* Interrupt level Priority */ 

#define ALLOC_NOWRAP	0x80	/* Don't wrap to next block size */
#define ALLOC_PRI_MASK	7

/*
 * Queue flags
 */
#define QENAB      01   /* Queue is already enabled to run */
#define QSCHED     02   /* Service wants to run Q */
#define QBACK      04   /* Back-enable primed */
#define QFULL     010   /* Q is considered full */
#define QREADR    020   /* This is the reader (first) Q */
#define QUSE      040   /* This queue in use (allocation) */
#define QNOENB   0100   /* Don't enable Q via putq */
#define QSERV    0200   /* This queue has a service proc */
#define QEND     0400   /* This queue is this stream side end */


/*
 * Finding related queues
 */
#define OTHERQ(Q)    ((Q)->q_other)
#define WR(Q)        ((Q)->q_other)
#define RD(Q)        ((Q)->q_other)


#define CLONEDEV   255
#define NSTREAMS    20

#define DUMMYCLASS 255  /* Dummy in-buffer data-block class */

/*
 *  IOCTL structure - this structure is the format of the M_IOCTL message type.
 */
struct iocblk {
    int     ioc_cmd;	/* ioctl command type */
    ushort  ioc_uid;	/* effective uid of user */
    ushort  ioc_gid;	/* effective gid of user */
    uint    ioc_id;	/* ioctl id */
    uint    ioc_count;  /* count of bytes in data field */
    int     ioc_error;  /* error code */
    int     ioc_rval;   /* return value  */
};

typedef struct iocblk iocblk_t;
typedef struct iocblk IOCBLK, *PIOCBLK;

/*
 * Link structure for I_LINK and I_UNLINK ioctl's
 */
struct linkblk {
    queue_t *l_qtop;   /* lowest level write queue of upper stream */
    queue_t *l_qbot;   /* highest level write queue of lower stream */
    int      l_index;  /* file[] index for lower stream. */
};

typedef struct linkblk linkblk_t;
typedef struct linkblk LINKBLK, *PLINKBLK;

/*
 * Options structure for M_SETOPTS message.  This is sent upstream
 * by driver to set stream head options.
 */
struct stroptions {
    short  so_flags;	            /* options to set */
    short  so_readopt;              /* read option */
    ushort so_wroff;	            /* write offset */
    short  so_minpsz;               /* minimum read packet size */
    short  so_maxpsz;               /* maximum read packet size */
    ushort so_hiwat;	            /* read queue high water mark */
    ushort so_lowat;	            /* read queue low water mark */
    unsigned char   so_band;        /* update water marks for this band */
                                    /* note: banding not supported */
};

typedef struct stroptions stroptions_t;
typedef struct stroptions STROPTIONS, *PSTROPTIONS;

/*
 * Flags for stream options set message
 */
#define SO_ALL      077  /* set all options */
#define SO_READOPT   01  /* set read opttion */
#define SO_WROFF     02  /* set write offset */
#define SO_MINPSZ    04  /* set min packet size */
#define SO_MAXPSZ   010  /* set max packet size */
#define SO_HIWAT    020  /* set high water mark */
#define SO_LOWAT    040  /* set low water mark */

/*
 * Data and protocol messages (regular priority)
 */
#define M_DATA       00  /* regular data */
#define M_PROTO      01  /* protocol control */

/*
 * Control messages (regular priority)
 */
#define M_BREAK         010  /* line break */
#define M_PASSFP        011  /* pass file pointer */
#define M_SIG           013  /* generate process signal */
#define M_DELAY         014  /* real-time xmit delay (1 param) */
#define M_CTL           015  /* device-specific control message */
#define M_IOCTL         016  /* ioctl; set/get params */
#define M_SETOPTS       020  /* set various stream head options */
#define	M_POSITION_RPT  030  /* Position Report message */

/*
 * Control messages (high priority; go to head of queue)
 */
#define M_IOCACK   0201  /* acknowledge ioctl */
#define M_IOCNAK   0202  /* negative ioctl acknowledge */
#define M_PCPROTO  0203  /* priority proto message */
#define M_PCSIG    0204  /* generate process signal */
#define M_FLUSH    0206  /* flush your queues */
#define M_STOP     0207  /* stop transmission immediately */
#define M_START    0210  /* restart transmission after stop */
#define M_HANGUP   0211  /* line disconnect */
#define M_ERROR    0212  /* fatal error used to set u.u_error */

/*
 * Ioctl command codes
 */
#define I_LINK     9901  /* lower stream linked */
#define I_UNLINK   9902  /* lower stream unlinked */

/*
 * Queue message class definitions.
 */
#define QNORM         0  /* normal messages */
#define QPCTL      0200  /* priority cntrl messages */


/************************************************************/
/*        Miscellaneous parameters and flags		    */
/************************************************************/

/*
 * Stream head default high/low water marks
 */
#define STRHIGH    5120
#define STRLOW     1024

/*
 * Block allocation parameters
 */
#define QBSIZE       65  /* min size for block allocation retries */
#define MAXBSIZE   4096  /* max block size */
#define MAXIOCBSZ  1024  /* max ioctl data block size */

/*
 * Values for stream flag in open to indicate module open, clone open;
 * return value for failure.
 */
#define MODOPEN       1  /* open as a module */
#define CLONEOPEN     2  /* open for clone, pick own minor device */
#define OPENFAIL     -1  /* returned for open failure */

/*
 * Value for packet size that denotes infinity
 */
#define INFPSZ       -1

/*
 * Flags for MFLUSH messages
 */
#define FLUSHW       02  /* flush downstream */
#define FLUSHR       01  /* flush upstream */



/*
 * Flags for flushq()
 */
#define FLUSHALL      1  /* flush all messages */
#define FLUSHDATA     0  /* don't flush control messages */

/* User area */
struct user {
    struct proc	*u_procp;	/* process structure pointer */
    short	*u_ttyp;	/* tty group ID pointer */
    int		u_error;	/* system call error number */
    ushort	u_uid;		/* effective user ID */
    ushort	u_gid;		/* effective group ID */
    ushort	u_ruid;		/* real user ID */
    ushort	u_rgid;		/* real group ID */
};

typedef struct user user_t;
typedef struct user USER, *PUSER;


/************************************************************************/
/*    Defintions of Streams macros and function interfaces.        */
/************************************************************************/

/*
 * determine block allocation cutoff for given class and priority.
 */
#define bcmax(class, pri) ( (pri) == BPRI_LO ? dballoc[class].dba_lo : \
	       ((pri) == BPRI_HI ? nmblock : dballoc[class].dba_med))

/*
 * noenable - set queue so that putq() will not enable it.
 * enableok - set queue so that putq() can enable it.
 * canenable - check if queue can be enabled by putq().
 */
#define noenable(q)  (q)->q_flag |= QNOENB
#define enableok(q)  (q)->q_flag &= ~QNOENB
#define canenable(q) !((q)->q_flag & QNOENB)
/*
 * put a message of the next queue of the given queue
 */
#define putnext(q, mp)  (*q->q_next->q_qinfo->qi_putp)(q->q_next, mp)

/*
 * Test if data block type is one of the data messages (i.e. not a control
 * message).
 */
#define datamsg(type) (type == M_DATA || type == M_PROTO || type == M_PCPROTO)

/*
 * extract queue class of message block
 */
#define queclass(bp) (bp->b_datap->db_type & QPCTL)

/*
 * Align address on next lower word boundary
 */
#define straln(a)    (caddr_t)((long)(a) & ~(sizeof(int)-1))

#endif