Coherent4.2.10/include/sys/stream.h
/* (-lgl
* Coherent 386 release 4.2
* Copyright (c) 1982, 1993 by Mark Williams Company.
* All rights reserved. May not be copied without permission.
* For copying permission and licensing info, write licensing@mwc.com
-lgl) */
#ifndef __SYS_STREAM_H__
#define __SYS_STREAM_H__
/*
* This ^^^^^^^^^^^^^^^^ symbol is used in the DDI/DKI header <sys/ddi.h> to
* determine which #undef directives it is required to perform, on the basis
* that it should avoid touching namespaces unless they have been reserved
* by the inclusion of a header which reserves such classes of names.
*/
#include <common/ccompat.h>
#include <common/__cred.h>
#include <common/__caddr.h>
#include <common/__types.h>
#include <kernel/__pl.h>
#include <kernel/_toid.h>
#include <kernel/x86lock.h>
#include <common/_stream.h>
/*
* Public section of the <sys/stream.h> file, for consumption by user
* application code using access to the STREAMS messaging system, and
* by STREAMS drivers.
*
* The information in this header is directly related to the information
* published in the System V, Release 4 STREAMS Programmer's Guide,
* Appendices A and B.
*/
/*
* Message types. The particular values here may have some significance
* to some macros defined later, particularly datamsg ().
*/
#define M_PRI 0x80
#define QPCTL M_PRI
/* regular messages */
#define M_DATA 0
#define M_PROTO 1
#define M_DELAY 2
#define M_IOCTL 3
#define M_SETOPTS 4
#define M_SIG 5
#define M_CTL 6
#define M_BREAK 7
#define M_PASSFP 8
#define M_RSE 9
/* priority messages */
#define M_PCPROTO (1 + M_PRI)
#define M_IOCACK (3 + M_PRI)
#define M_IOCNAK (4 + M_PRI)
#define M_PCSIG (5 + M_PRI)
#define M_ERROR (6 + M_PRI)
#define M_FLUSH (7 + M_PRI)
#define M_HANGUP (8 + M_PRI)
#define M_START (9 + M_PRI)
#define M_STOP (10 + M_PRI)
#define M_COPYIN (11 + M_PRI)
#define M_COPYOUT (12 + M_PRI)
#define M_IOCDATA (13 + M_PRI)
#define M_PCRSE (14 + M_PRI)
#define M_READ (15 + M_PRI)
#define M_STARTI (16 + M_PRI)
#define M_STOPI (17 + M_PRI)
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 */
};
/*
* Private type definitions.
*/
typedef atomic_uchar_t __str_lock_t;
/*
* QUEUE structures - these structures are used to build streams.
*
* Note that "queue_t" structures occur in pairs, first the write queue, then
* the read queue. The QREADR flag distinguishes them for the RD (q), WR (q)
* and OTHERQ (q) macros.
*
* The System V DDI/DKI adds multiprocessor support to STREAMS via the notion
* of "freezing" a stream, something mostly analagous to a basic lock. We can
* implement this facility either in terms of the primitive machine-specific
* atomic operations, or in terms of the DDI/DKI high-level lock operations.
*
* For now, we choose the latter.
*/
struct queue {
struct qinit * q_qinfo; /* procedures and limits for queue */
mblk_t * q_first; /* head of message queue for QUEUE */
mblk_t * q_last; /* tail of message queue for QUEUE */
queue_t * q_next; /* next QUEUE in stream */
queue_t * q_link; /* next on STEAMS scheduling list */
__VOID__ * q_ptr; /* to private data structure */
unsigned long q_count; /* number of characters in queue */
unsigned long q_flag; /* QUEUE state */
long q_minpsz; /* minimum packet size accepted */
long q_maxpsz; /* maximum packet size accepted */
unsigned long q_hiwat; /* message queue high water mark */
unsigned long q_lowat; /* message queue low water mark */
qband_t * q_bandp; /* separate flow information */
unsigned char q_nband; /* number of priority bands */
unsigned char q_pad1 [3]; /* reserved for future use */
long q_pad2 [2]; /* reserved for future use */
/*
* Data from this point are MWC extensions for multiprocessing. The
* DDI/DKI revokes user's right to know about the size of the
* structure, among other things.
*/
unsigned char q_active; /* count of active put/srv routines */
unsigned char q_lastband; /* band of last retrieved message */
__str_lock_t q_locked; /* hack implementation of freezing */
};
/*
* Hack around the union above. This field should only be referred to by some
* layering macros in <sys/strmlib.h> anyway, but we try and keep it clean.
*/
#define q_lock x.q_lock
/*
* Queue flag definitions : these are internal to the system, and the values
* bear no relation to any definitions in System V. Drivers use these flags at
* their own risk...
*/
#define QENAB 0x0001 /* queue is on qenable () schedule */
#define QWANTR 0x0002 /* someone wants to read from the queue */
#define QWANTW 0x0004 /* someone wants to write to the queue */
#define QFULL 0x0008 /* queue is full */
#define QREADR 0x0010 /* set for read queues */
#define QNOENB 0x0020 /* prevent queue from being enabled */
#define QBACK 0x0040 /* queue has been back-enabled */
#define QOLD 0x0080 /* pre-SVR4 open/close interface */
#define QPROCSOFF 0x0100 /* put/service routines disabled */
#define QDRAIN 0x0200 /* waiting for queue to drain */
#define QSRVACTIVE 0x0400 /* service routine is active */
/* #define QUSE ????? queue has been allocated */
/* #define QHLIST ????? SVR4, not used by this implementation */
/*
* queue priority-band information.
*/
struct qband {
struct qband * qb_next; /* next band's info */
unsigned long qb_count; /* count of bytes in band */
struct msgb * qb_first; /* beginning of band's data */
struct msgb * qb_last; /* end of band's data */
unsigned long qb_hiwat; /* high water mark for band */
unsigned long qb_lowat; /* low water mark for band */
unsigned long qb_flag; /* flags, see below */
unsigned long qb_pad1; /* reserved for future use */
};
/* Flags used in band structure */
#define QB_FULL 0x0001 /* band is considered full */
#define QB_WANTW 0x0002 /* someone wants to write to band */
#define QB_BACK 0x0004 /* queue has been back-enabled */
/* non-SVR4 flag */
#define QB_FIRST 0x0100 /* first entry in allocation unit */
/*
* Message structures - the format of STREAMS messages and message data
* blocks.
*/
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 */
unsigned char * b_rptr; /* first unread data byte in buffer */
unsigned char * b_wptr; /* first unwritten data byte in buffer */
struct datab * b_datap; /* data block */
unsigned char b_band; /* message priority */
unsigned char b_pad1;
unsigned short b_flag; /* message flags */
long b_pad2;
};
/* Flag definitions for message blocks */
#define MSGMARK 0x0001 /* last byte of message is "marked" */
#define MSGNOLOOP 0x0002 /* don't loop message to write-side of stream */
#define MSGDELIM 0x0004 /* message is delimited */
/* Extra flag definitions, for STREAMS private use only */
#define MSGTRIPLE 0x0100 /* message block is part of triple */
#define MSGFREE 0x0200 /* message block is free */
#define MSGMASK_SYSTEM 0x0300 /* system-private flags */
/*
* Data structure used to control freeing of user-defined STREAMS buffer
* memory (such as user memory that is temporarily mapped to kernel space
* to avoid copying, or driver-dependent shared memory from an I/O space).
*/
struct free_rtn {
void (* free_func) /* driver-dependent free routine */
__PROTO ((__VOID__ * _arg));
__VOID__ * free_arg; /* argument for free_rtn */
};
typedef struct free_rtn frtn_t;
/*
* Data block descriptors - several mblk_t's may refer to the same section
* of STREAMS buffer memory to avoid copying.
*
* Note that this data structure is NOT identical to its System V counterpart.
*/
struct datab {
frtn_t * db_frtnp; /* internal use */
unsigned char * db_base; /* first byte of buffer */
unsigned char * db_lim; /* last+1 byte of buffer */
unsigned char db_ref; /* count of messages pointing here */
unsigned char db_type; /* message type */
short db_pad1; /* reserved for future use */
long db_pad2; /* reserved for future use */
};
/*
* Define one of these structures with external visibility to publish the
* entry points to your STREAMS driver.
*/
typedef void (* __putp_t) /* put procedure */
__PROTO ((queue_t * _q, mblk_t * _mp));
typedef void (* __srvp_t) /* service procedure */
__PROTO ((queue_t * _q));
typedef int (* __qopen_t) /* open procedure */
__PROTO ((queue_t * _q, n_dev_t * _devp, int _flag,
int _sflag, __cred_t * _credp));
typedef int (* __qclose_t) /* called on last close/pop */
__PROTO ((queue_t * _q, int _flag, __cred_t * _credp));
typedef int (* __qadmin_t) /* reserved for future use */
__PROTO ((void));
struct qinit {
__putp_t qi_putp; /* put procedure */
__srvp_t qi_srvp; /* service procedure */
__qopen_t qi_qopen; /* called on each open */
__qclose_t qi_qclose; /* called on last close/pop */
__qadmin_t qu_qadmin; /* reserved for future use */
struct module_info
* qi_minfo; /* information structure */
struct module_stat
* qi_mstat; /* statistics - optional */
};
/*
* General STREAMS "module information", mainly used by SysV configuration
* utilities, although it also provides defaults for the queues at open time.
*/
struct module_info {
unsigned short mi_idnum; /* module ID number */
char * mi_idname; /* module name */
long mi_minpsz; /* min packet size accepted */
long mi_maxpsz; /* max packet size accepted */
unsigned long mi_hiwat; /* hi-water mark, for flow control */
unsigned long mi_lowat; /* lo-water mark, for flow control */
};
/* Infinite message size, for use in module_info mi_minpsz/mi_maxpsz */
#define INFPSZ 0x7FFFFFFF
/*
* General statistics structure, useful for profiling module/driver
* activity.
*/
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 stats buffer */
};
/*
* link block for multiplexed streams... this structure appears in the data
* portion of I_LINK and I_UNLINK M_IOCTL messages.
*
* Note that the STREAMS manual documents the type of "l_index" as an "int",
* but for our purposes an "n_dev_t" (which is a long) is more appropriate.
*/
typedef n_dev_t __muxid_t;
struct linkblk {
queue_t * l_qtop; /* lowest write queue of upper stream */
queue_t * l_qbot; /* highest write queue of lower stream */
__muxid_t l_index; /* unique index for lower stream */
long l_pad [5]; /* reserved for future use */
};
/*
* Stream head options control message format, used as the data part of an
* M_SETOPTS message set from a driver or module to the stream head. The
* values for the "so_readopt" member can be found in <stropts.h> as well
* as below.
*/
struct stroptions {
unsigned long so_flags; /* options to set */
short so_readopt; /* read option */
unsigned short so_wroff; /* write offset */
long so_minpsz; /* min packet size */
long so_maxpsz; /* max packet size */
unsigned long so_hiwat; /* read queue high-water mark */
unsigned long so_lowat; /* read queue low-water mark */
unsigned char so_band; /* band for water marks */
};
/*
* Flag values for the "so_flags" member,
*/
#define SO_ALL 0x3F /* set all options */
#define SO_READOPT 0x0001 /* set read option */
#define SO_WROFF 0x0002 /* set write offset */
#define SO_MINPSZ 0x0004 /* set min packet size */
#define SO_MAXPSZ 0x0008 /* set max packet size */
#define SO_HIWAT 0x0010 /* set read queue high-water mark */
#define SO_LOWAT 0x0020 /* set read queue low-water mark */
/* Flags above control which members to look at, below are R4 extensions */
#define SO_MREADON 0x0040 /* set read notification on */
#define SO_MREADOFF 0x0080 /* set read notification off */
#define SO_NDELON 0x0100 /* old TTY semantics for NDELAY */
#define SO_NDELOFF 0x0200 /* STREAMS semantics for NDELAY */
#define SO_ISTTY 0x0400 /* stream is acting as a terminal */
#define SO_ISNTTY 0x0800 /* stream is not acting as a terminal */
#define SO_TOSTOP 0x1000 /* stop on background writes to stream */
#define SO_TONSTOP 0x2000 /* don't stop on background writes */
#define SO_BAND 0x4000 /* water marks that affect band */
/*
* Other flags relevant to the above structure are defined in <sys/stropts.h>.
*/
/*
* Structure of data block found at head of M_IOCTL message, usually reused
* for replying to M_IOCTL with an M_IOCACK or M_IOCNAK message.
*/
struct iocblk {
int ioc_cmd; /* ioctl () command type */
__cred_t * ioc_cr; /* user's full credentials */
unsigned int ioc_id; /* M_IOCTL sequence number */
unsigned int ioc_count; /* bytes in data field */
int ioc_error; /* error code */
int ioc_rval; /* return value */
long ioc_filler [4]; /* reserved for future use */
};
/*
* For compatibility with SVR3 sources
*/
#define ioc_uid ioc_cr->cr_uid
#define ioc_gid ioc_cr->cr_gid
/*
* This special value of "ioc_count" is used to indicate that the stream
* head has passed us a "transparent" ioctl rather than an I_STR ioctl.
*/
#define TRANSPARENT ((unsigned int) -1)
/*
* This structure defines the data format used in an M_COPYIN/M_COPYOUT
* message (used to request data copying from user process space during
* an ioctl ()). Note that the first three members of the "copyreq" structure
* match the first three fields of the "iocblk" structure. It is intended
* that drivers be able to use this property to simply use the intial message
* block from M_IOCTL for all the transparent IOCTL messages.
*/
struct copyreq {
int cq_cmd; /* ioctl command (from ioc_cmd) */
__cred_t * cq_cr; /* full credentials (from ioc_cr) */
unsigned int cq_id; /* ioctl id (from ioc_id) */
__caddr_t cq_addr; /* user address to copy data to/from */
unsigned int cq_size; /* number of bytes to copy */
int cq_flag; /* flags, see below */
mblk_t * cq_private; /* private state information */
long cq_filler [4]; /* reserved for future use */
};
/* For compatibility with old sources. */
#define cq_uid cq_cr->cr_uid
#define cq_gid cq_cr->cr_gid
/* cq_flag values */
#define STRCANON 0x0001 /* b_cont data block contains canonical format specifier */
#define RECOPY 0x0002 /* perform I_STR copyin again using canonical format specifier */
/*
* This structure is used in the M_IOCDATA response to an M_COPYIN/M_COPYOUT,
* and is laid out so that equivalent fields from the "struct copyreq"
* structure remain at the same offset, ie we expect the stream head to
* simply turn around our request, although it is not required to do so.
*/
struct copyresp {
int cp_cmd; /* ioctl command (from cq_cmd) */
__cred_t * cp_cr; /* full credentials (from cq_cr) */
unsigned int cp_id; /* ioctl id (from cq_id) */
__caddr_t cp_rval; /* request status: 0 success, non-zero failure */
unsigned int cp_pad1; /* reserved */
unsigned int cp_pad2; /* reserved */
mblk_t * cp_private; /* private state information */
long cp_filler [4]; /* reserved for future use */
};
/* for compatibility with old sources */
#define cp_uid cp_cr->cr_uid
#define cp_gid cp_cr->cr_gid
/*
* LOCAL EXTENSIONS : The methods used in the multiplexing examples in the
* STREAMS V.2 manual are slightly inefficient. The following general STREAMS
* queue schedling routines were defined for multiplexing drivers and device
* drivers (such as Ethernet drivers) that must consume data from several
* queues.
*
* In the STREAMS code supplied, these routines are also used for the main
* streams queue scheduling, so we define them here. A consequence of this is
* that a given queue may not be queued for both STREAMS execution and
* multiplexing at the same time.
*
* The basic idea is to use qschedule () and qunschedule () to add and remove
* a queue from the scheduling list. Lower queues may then getq () from the
* "s_head" of the scheduling list to consume the data. Since by default this
* will simply attempt to drain each scheduled queue of data before moving to
* the next, the muxrobin () call adjusts the head/tail pointers to effect
* a round-robin of the queues that have data.
*/
struct strsched {
queue_t * s_head; /* next queue to read data from */
queue_t * s_tail; /* last queue to read data from */
};
/*
* Message allocation priorities, used with allocb () and bufcall ()
*/
enum {
BPRI_LO,
BPRI_MED,
BPRI_HI
};
/*
* Flag values used with flushq () and flushband ().
*/
enum {
FLUSHDATA, /* flush M_DATA, M_PROTO, M_PCPROTO, M_DELAY */
FLUSHALL /* flush all messages from queue */
};
/*
* queue field numbers to be used with strqget ()/strqset ().
*/
typedef enum qfields {
QHIWAT = 0, /* q_hiwat or qb_hiwat */
QLOWAT = 1, /* q_lowat or qb_lowat */
QMAXPSZ = 2, /* q_maxpsz */
QMINPSZ = 3, /* q_minpsz */
QCOUNT = 4, /* q_count or qb_count */
QFIRST = 5, /* q_first or qb_first */
QLAST = 6, /* q_last or qb_last */
QFLAG = 7, /* q_flag or qb_flag */
QBAD = 8
} qfields_t;
#if _DDI_DKI
/*
* External function definitions for the STREAMS library.
*
* Note that prototypes are also provided for those STREAMS functions that
* are available as macros. This is since this header is a more appropriate
* place to encode this knowledge than the DDI/DKI required header
* <sys/ddi.h>.
*
* The System V Release 4 Multi-Processor DDI/DKI defines some extra versions
* of some common STREAMS library functions so that STREAMS driver code does
* not reference the q->q_next member, since this may not be safe in a multi-
* processor environment. These functions are included in this implementation
* and are prototyped below to help device drivers anticipate the multi-
* processor environment.
*/
__EXTERN_C_BEGIN__
int adjmsg __PROTO ((mblk_t * _mp, int _len));
mblk_t * allocb __PROTO ((int _size, unsigned int _pri));
queue_t * backq __PROTO ((queue_t * _q));
int bcanput __PROTO ((queue_t * _q, unsigned char _pri));
int bcanputnext __PROTO ((queue_t * _q, unsigned char _pri));
/* see <sys/bufcall.h> for a discussion of this declaration for bufcall () */
#define __STDARG_BUFCALL__
toid_t bufcall __PROTO ((unsigned int _size, int _pri, ...));
int canput __PROTO ((queue_t * _q));
int canputnext __PROTO ((queue_t * _q));
mblk_t * copyb __PROTO ((mblk_t * _bp));
mblk_t * copymsg __PROTO ((mblk_t * _mp));
int datamsg __PROTO ((unsigned char _type));
mblk_t * dupb __PROTO ((mblk_t * _bp));
mblk_t * dupmsg __PROTO ((mblk_t * _mp));
void enableok __PROTO ((queue_t * _q));
mblk_t * esballoc __PROTO ((unsigned char * _mbase, int _size,
int _pri, frtn_t * _fr_rtn));
/* The following assumes __STDARG_BUFCALL__ as above */
toid_t esbbcall __PROTO ((int _pri, ...));
void flushband __PROTO ((queue_t * _q, unsigned char _pri,
int _flag));
void flushq __PROTO ((queue_t * _q, int _flag));
__pl_t freezestr __PROTO ((queue_t * _q));
void freeb __PROTO ((mblk_t * _bp));
void freemsg __PROTO ((mblk_t * _mp));
int (* getadmin __PROTO ((unsigned short _mid)))
__PROTO ((void));
unsigned short getmid __PROTO ((char * _name));
mblk_t * getq __PROTO ((queue_t * _q));
int insq __PROTO ((queue_t * _q, mblk_t * _emp,
mblk_t * _nmp));
void linkb __PROTO ((mblk_t * _mp, mblk_t * _bp));
int msgdsize __PROTO ((mblk_t * _mp));
mblk_t * msgpullup __PROTO ((mblk_t * _mp, int _len));
void noenable __PROTO ((queue_t * _q));
queue_t * OTHERQ __PROTO ((queue_t * _q));
int pcmsg __PROTO ((__uchar_t _type));
int pullupmsg __PROTO ((mblk_t * _mp, int _len));
void put __PROTO ((queue_t * _q, mblk_t * _mp));
int putbq __PROTO ((queue_t * _q, mblk_t * _mp));
int putctl __PROTO ((queue_t * _q, int _type));
int putctl1 __PROTO ((queue_t * _q, int _type,
int _param));
int putnext __PROTO ((queue_t * _q, mblk_t * _mp));
int putnextctl __PROTO ((queue_t * _q, int _type));
int putnextctl1 __PROTO ((queue_t * _q, int _type,
int _param));
int putq __PROTO ((queue_t * _q, mblk_t * _mp));
void qenable __PROTO ((queue_t * _q));
void qprocsoff __PROTO ((queue_t * _rq));
void qprocson __PROTO ((queue_t * _rq));
void qreply __PROTO ((queue_t * _q, mblk_t * _mp));
int qsize __PROTO ((queue_t * _q));
queue_t * RD __PROTO ((queue_t * _q));
mblk_t * rmvb __PROTO ((mblk_t * _mp, mblk_t * _bp));
void rmvq __PROTO ((queue_t * _q, mblk_t * _mp));
int strlog __PROTO ((short _mid, short _sid, char _level,
unsigned short _flags, char * _fmt,
...));
int strqget __PROTO ((queue_t * _q, qfields_t _what,
unsigned char _pri, long * _valp));
int strqset __PROTO ((queue_t * _q, qfields_t _what,
unsigned char _pri, long _val));
int testb __PROTO ((int _size, int _pri));
void unbufcall __PROTO ((toid_t _id));
void unfreezestr __PROTO ((queue_t * _q, __pl_t _pl));
mblk_t * unlinkb __PROTO ((mblk_t * _mp));
queue_t * WR __PROTO ((queue_t * _q));
__EXTERN_C_END__
/*
* Possible values for the stream open flag "sflag" in a module or driver
* open (0 implies a normal driver open)
*/
enum {
MODOPEN = 1, /* normal module open */
CLONEOPEN /* clone device open */
};
/*
* Special value for the two-byte form of the M_ERROR message.
*/
enum {
NOERROR = 0xFF
};
/*
* Functions that are normally implemented as macros (although the function
* versions which are prototyped above are available by including the
* <sys/ddi.h> header.
*/
/*
* NB: Borland C++ 3.1 in 'C' mode insists that if a pointer is derived from
* a ternary where the arms are calculated from lvalues then dereferencing
* that pointer does not yield a valid lvalue, e.g.
* WR (q)->q_ptr = NULL;
* it thinks is invalid, which is untrue. To fix this, the pointer value from
* the ternary seems to need massaging to turn it into a proper rvalue... the
* easiest way to do this is add 0 to the *result* of the ternary. This is
* optimized away by basic constant-folding in even simple compilers.
*/
#define __HACK(exp) ((exp) + 0)
#define datamsg(type) ((unsigned char) ((type) & (M_PRI - 1)) <= M_DELAY)
/* There is no multiprocessor macro implementation of enableok () */
/* There is no multiprocessor macro implementation of noenable () */
#define OTHERQ(q) __HACK (((q)->q_flag & QREADR) != 0 ? (q) + 1 : (q) - 1)
#define pcmsg(type) ((type) >= QPCTL)
#define RD(q) __HACK (((q)->q_flag & QREADR) != 0 ? (q) : (q) - 1)
#define WR(q) __HACK (((q)->q_flag & QREADR) != 0 ? (q) + 1 : (q))
#endif /* _DDI_DKI */
#endif /* ! defined (__SYS_STREAM_H__) */