273 lines
4.6 KiB
C
273 lines
4.6 KiB
C
/**
|
|
** Streams BUF module
|
|
**/
|
|
|
|
#include "f_module.h"
|
|
#include "primitives.h"
|
|
#include "kernel.h"
|
|
#include "f_signal.h"
|
|
#include "f_malloc.h"
|
|
#include "streams.h"
|
|
#include "stropts.h"
|
|
#ifdef DONT_ADDERROR
|
|
#include "f_user.h"
|
|
#endif
|
|
#include "streamlib.h"
|
|
#include "buffer.h"
|
|
#include "isdn_proto.h"
|
|
|
|
|
|
/*
|
|
* Standard Streams stuff.
|
|
*/
|
|
static struct module_info buf_minfo =
|
|
{
|
|
0, "buffer", 0, INFPSZ, 4096, 2048
|
|
};
|
|
|
|
static qf_open buf_open;
|
|
static qf_close buf_close;
|
|
static qf_put buf_rput,buf_wput;
|
|
static qf_srv buf_rsrv,buf_wsrv;
|
|
|
|
static struct qinit buf_rinit =
|
|
{
|
|
buf_rput, buf_rsrv, buf_open, buf_close, NULL, &buf_minfo, NULL
|
|
};
|
|
|
|
static struct qinit buf_winit =
|
|
{
|
|
buf_wput, buf_wsrv, NULL, NULL, NULL, &buf_minfo, NULL
|
|
};
|
|
|
|
struct streamtab bufinfo =
|
|
{&buf_rinit, &buf_winit, NULL, NULL};
|
|
|
|
/* Streams code to open the driver. */
|
|
static int
|
|
buf_open (queue_t * q, dev_t dev, int flag, int sflag ERR_DECL)
|
|
{
|
|
if (q->q_ptr) {
|
|
return 0;
|
|
}
|
|
/* do nothing... */
|
|
return 0;
|
|
}
|
|
|
|
/* Streams code to close the driver. */
|
|
static void
|
|
buf_close (queue_t * q, int dummy)
|
|
{
|
|
flushq (q, FLUSHALL);
|
|
flushq (WR (q), FLUSHALL);
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
buf_proto (queue_t * q, mblk_t * mp, char down)
|
|
{
|
|
streamchar *origmp = mp->b_rptr;
|
|
ushort_t id;
|
|
int error = 0;
|
|
|
|
if (m_getid (mp, &id) != 0) {
|
|
mp->b_rptr = origmp;
|
|
putnext (q, mp);
|
|
return;
|
|
}
|
|
switch (id) {
|
|
default:
|
|
break;
|
|
case PROTO_MODULE:
|
|
if (strnamecmp (q, mp)) { /* Config information for me. */
|
|
long z;
|
|
|
|
while (mp != NULL && m_getsx (mp, &id) == 0) {
|
|
switch (id) {
|
|
default:
|
|
goto err;
|
|
case PROTO_MODULE:
|
|
break;
|
|
case BUF_UP:
|
|
if ((error = m_geti (mp, &z)) != 0)
|
|
goto err;
|
|
if ((z < 10) || (z > 32*1024))
|
|
goto err;
|
|
RDQ(q)->q_flag |= QWANTR;
|
|
RDQ(q)->q_hiwat = z;
|
|
RDQ(q)->q_lowat = z>>2;
|
|
qenable(RDQ(q));
|
|
break;
|
|
case BUF_DOWN:
|
|
if ((error = m_geti (mp, &z)) != 0)
|
|
goto err;
|
|
if ((z < 10) || (z > 32*1024))
|
|
goto err;
|
|
WRQ(q)->q_flag |= QWANTR;
|
|
WRQ(q)->q_hiwat = z;
|
|
WRQ(q)->q_lowat = z>>2;
|
|
qenable(WRQ(q));
|
|
break;
|
|
case BUF_BOTH:
|
|
if ((error = m_geti (mp, &z)) != 0)
|
|
goto err;
|
|
if ((z < 10) || (z > 32*1024))
|
|
goto err;
|
|
RDQ(q)->q_flag |= QWANTR;
|
|
WRQ(q)->q_flag |= QWANTR;
|
|
RDQ(q)->q_hiwat = z;
|
|
WRQ(q)->q_hiwat = z;
|
|
RDQ(q)->q_lowat = z>>2;
|
|
WRQ(q)->q_lowat = z>>2;
|
|
qenable(RDQ(q));
|
|
qenable(WRQ(q));
|
|
break;
|
|
}
|
|
}
|
|
if (mp != NULL) {
|
|
mp->b_rptr = origmp;
|
|
m_reply(q,mp,0);
|
|
mp = NULL;
|
|
}
|
|
}
|
|
}
|
|
if(mp != NULL) {
|
|
if (origmp != NULL)
|
|
mp->b_rptr = origmp;
|
|
putnext(q,mp);
|
|
}
|
|
return;
|
|
err:
|
|
mp->b_rptr = origmp;
|
|
m_reply (q, mp, error ? error : -EINVAL);
|
|
}
|
|
|
|
|
|
/* Streams code to write data. */
|
|
static void
|
|
buf_wput (queue_t * q, mblk_t * mp)
|
|
{
|
|
switch (DATA_TYPE(mp)) {
|
|
case MSG_PROTO:
|
|
case CASE_DATA:
|
|
putq (q, mp);
|
|
break;
|
|
case M_FLUSH:
|
|
if (*mp->b_rptr & FLUSHW)
|
|
flushq (q, FLUSHDATA);
|
|
putnext (q, mp);
|
|
break;
|
|
default:
|
|
putnext (q, mp);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Streams code to scan the write queue. */
|
|
static void
|
|
buf_wsrv (queue_t * q)
|
|
{
|
|
mblk_t *mp;
|
|
|
|
while ((mp = getq (q)) != NULL) {
|
|
switch (DATA_TYPE(mp)) {
|
|
case MSG_PROTO:
|
|
buf_proto (q, mp, 1);
|
|
break;
|
|
case CASE_DATA:
|
|
if (!canput (q->q_next)) {
|
|
putbq (q, mp);
|
|
return;
|
|
}
|
|
putnext (q, mp);
|
|
break;
|
|
case M_FLUSH:
|
|
if (*mp->b_rptr & FLUSHW)
|
|
flushq (q, FLUSHDATA);
|
|
/* FALL THRU */
|
|
default:
|
|
if (DATA_TYPE(mp) > QPCTL || canput (q->q_next)) {
|
|
putnext (q, mp);
|
|
continue;
|
|
} else {
|
|
putbq (q, mp);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Streams code to read data. */
|
|
static void
|
|
buf_rput (queue_t * q, mblk_t * mp)
|
|
{
|
|
switch (DATA_TYPE(mp)) {
|
|
|
|
case M_FLUSH:
|
|
if (*mp->b_rptr & FLUSHR) {
|
|
flushq (q, FLUSHDATA);
|
|
}
|
|
putnext (q, mp); /* send it along too */
|
|
break;
|
|
case MSG_PROTO:
|
|
case CASE_DATA:
|
|
putq (q, mp); /* queue it for my service routine */
|
|
break;
|
|
|
|
default:
|
|
putq (q, mp);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Streams code to scan the read queue. */
|
|
static void
|
|
buf_rsrv (queue_t * q)
|
|
{
|
|
mblk_t *mp;
|
|
|
|
while ((mp = getq (q)) != NULL) {
|
|
switch (DATA_TYPE(mp)) {
|
|
case MSG_PROTO:
|
|
buf_proto (q, mp, 0);
|
|
break;
|
|
case CASE_DATA:
|
|
if (!canput (q->q_next)) {
|
|
putbq (q, mp);
|
|
return;
|
|
}
|
|
putnext (q, mp);
|
|
break;
|
|
case M_HANGUP:
|
|
case M_ERROR:
|
|
/* FALL THRU */
|
|
default:
|
|
if (DATA_TYPE(mp) > QPCTL || canput (q->q_next)) {
|
|
putnext (q, mp);
|
|
continue;
|
|
} else {
|
|
putbq (q, mp);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
#ifdef MODULE
|
|
static int do_init_module(void)
|
|
{
|
|
return register_strmod(&bufinfo);
|
|
}
|
|
|
|
static int do_exit_module(void)
|
|
{
|
|
return unregister_strmod(&bufinfo);
|
|
}
|
|
#endif
|