Blame ndmp-src/ndml_chan.c

Packit 23ab03
/*
Packit 23ab03
 * Copyright (c) 1998,1999,2000
Packit 23ab03
 *	Traakan, Inc., Los Altos, CA
Packit 23ab03
 *	All rights reserved.
Packit 23ab03
 *
Packit 23ab03
 * Redistribution and use in source and binary forms, with or without
Packit 23ab03
 * modification, are permitted provided that the following conditions
Packit 23ab03
 * are met:
Packit 23ab03
 * 1. Redistributions of source code must retain the above copyright
Packit 23ab03
 *    notice unmodified, this list of conditions, and the following
Packit 23ab03
 *    disclaimer.
Packit 23ab03
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 23ab03
 *    notice, this list of conditions and the following disclaimer in the
Packit 23ab03
 *    documentation and/or other materials provided with the distribution.
Packit 23ab03
 *
Packit 23ab03
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
Packit 23ab03
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 23ab03
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 23ab03
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
Packit 23ab03
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 23ab03
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 23ab03
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 23ab03
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 23ab03
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 23ab03
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 23ab03
 * SUCH DAMAGE.
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Project:  NDMJOB
Packit 23ab03
 * Ident:    $Id: $
Packit 23ab03
 *
Packit 23ab03
 * Description:
Packit 23ab03
 *
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
Packit 23ab03
#include "ndmlib.h"
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Initialize a channel. Make sure it won't be confused for active.
Packit 23ab03
 */
Packit 23ab03
void
Packit 23ab03
ndmchan_initialize (struct ndmchan *ch, char *name)
Packit 23ab03
{
Packit 23ab03
	NDMOS_MACRO_ZEROFILL(ch);
Packit 23ab03
	ch->name = name ? name : "???";
Packit 23ab03
	ch->fd = -1;
Packit 23ab03
	ch->mode = NDMCHAN_MODE_IDLE;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Set the data buffer
Packit 23ab03
 */
Packit 23ab03
int
Packit 23ab03
ndmchan_setbuf (struct ndmchan *ch, char *data, unsigned data_size)
Packit 23ab03
{
Packit 23ab03
	ch->data = data;
Packit 23ab03
	ch->data_size = data_size;
Packit 23ab03
Packit 23ab03
	ch->beg_ix = 0;
Packit 23ab03
	ch->end_ix = 0;
Packit 23ab03
Packit 23ab03
	return 0;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Interfaces for starting a channel in various modes.
Packit 23ab03
 */
Packit 23ab03
int
Packit 23ab03
ndmchan_start_mode (struct ndmchan *ch, int fd, int chan_mode)
Packit 23ab03
{
Packit 23ab03
	ch->fd = fd;
Packit 23ab03
	ch->mode = chan_mode;
Packit 23ab03
	return 0;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_start_read (struct ndmchan *ch, int fd)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_READ);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_start_write (struct ndmchan *ch, int fd)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_WRITE);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_start_readchk (struct ndmchan *ch, int fd)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_READCHK);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_start_listen (struct ndmchan *ch, int fd)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_LISTEN);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_start_resident (struct ndmchan *ch)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_start_mode (ch, -1, NDMCHAN_MODE_RESIDENT);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_start_pending (struct ndmchan *ch, int fd)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_PENDING);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Change a PENDING channel to an active (READ/WRITE) channel
Packit 23ab03
 */
Packit 23ab03
int
Packit 23ab03
ndmchan_pending_to_mode (struct ndmchan *ch, int chan_mode)
Packit 23ab03
{
Packit 23ab03
	ch->mode = chan_mode;
Packit 23ab03
	return 0;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_pending_to_read (struct ndmchan *ch)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_pending_to_mode (ch, NDMCHAN_MODE_READ);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_pending_to_write (struct ndmchan *ch)
Packit 23ab03
{
Packit 23ab03
	return ndmchan_pending_to_mode (ch, NDMCHAN_MODE_WRITE);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Interfaces for stopping (close()ing) a channel.
Packit 23ab03
 * This is a bit of a hodge-podge. Could probably be cleaner.
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_set_eof (struct ndmchan *ch)
Packit 23ab03
{
Packit 23ab03
	ch->eof = 1;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_close_set_errno (struct ndmchan *ch, int err_no)
Packit 23ab03
{
Packit 23ab03
	ch->eof = 1;
Packit 23ab03
	if (ch->fd >= 0) {
Packit 23ab03
		close (ch->fd);
Packit 23ab03
		ch->fd = -1;
Packit 23ab03
	}
Packit 23ab03
	ch->mode = NDMCHAN_MODE_CLOSED;
Packit 23ab03
	ch->saved_errno = err_no;
Packit 23ab03
	ch->beg_ix = ch->end_ix = 0;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_close (struct ndmchan *ch) {
Packit 23ab03
	ndmchan_close_set_errno (ch, 0);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_abort (struct ndmchan *ch) {
Packit 23ab03
	ndmchan_close_set_errno (ch,
Packit 23ab03
		ch->saved_errno == 0 ? EINTR : ch->saved_errno);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_close_as_is (struct ndmchan *ch) {
Packit 23ab03
	ndmchan_close_set_errno (ch, ch->saved_errno);
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_cleanup (struct ndmchan *ch) {
Packit 23ab03
	if (ch->mode != NDMCHAN_MODE_IDLE) {
Packit 23ab03
		ndmchan_close_as_is (ch);
Packit 23ab03
	}
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * CPU Quantum for a set of channels. There are three
Packit 23ab03
 * phases:
Packit 23ab03
 * 1) Identify the channels to check for ready to do I/O.
Packit 23ab03
 *    For example, a READ channel with no buffer space
Packit 23ab03
 *    need not be checked.
Packit 23ab03
 * 2) Call the OS dependent function that performs the
Packit 23ab03
 *    actual select()/poll()/whatever.
Packit 23ab03
 * 3) Based on the results, perform actual read()/write().
Packit 23ab03
 *    EOF and errors are detected.
Packit 23ab03
 *
Packit 23ab03
 * This is constructed so that applications which can not use
Packit 23ab03
 * ndmchan_quantum() directly have access to the helper functions
Packit 23ab03
 * ndmchan_pre_poll() and ndmchan_post_poll().
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_quantum (struct ndmchan *chtab[], unsigned n_chtab, int milli_timo)
Packit 23ab03
{
Packit 23ab03
	int			rc;
Packit 23ab03
Packit 23ab03
	ndmchan_pre_poll (chtab, n_chtab);
Packit 23ab03
Packit 23ab03
	rc = ndmos_chan_poll (chtab, n_chtab, milli_timo);
Packit 23ab03
	if (rc <= 0)
Packit 23ab03
		return rc;
Packit 23ab03
Packit 23ab03
	rc = ndmchan_post_poll (chtab, n_chtab);
Packit 23ab03
Packit 23ab03
	return rc;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_pre_poll (struct ndmchan *chtab[], unsigned n_chtab)
Packit 23ab03
{
Packit 23ab03
	struct ndmchan *	ch;
Packit 23ab03
	unsigned int		i, n_check;
Packit 23ab03
Packit 23ab03
	n_check = 0;
Packit 23ab03
	for (i = 0; i < n_chtab; i++) {
Packit 23ab03
		ch = chtab[i];
Packit 23ab03
		ch->ready = 0;
Packit 23ab03
		ch->check = 0;
Packit 23ab03
Packit 23ab03
		if (ch->error)
Packit 23ab03
			continue;
Packit 23ab03
Packit 23ab03
		switch (ch->mode) {
Packit 23ab03
		default:
Packit 23ab03
		case NDMCHAN_MODE_IDLE:
Packit 23ab03
		case NDMCHAN_MODE_PENDING:
Packit 23ab03
		case NDMCHAN_MODE_RESIDENT:
Packit 23ab03
		case NDMCHAN_MODE_CLOSED:
Packit 23ab03
			continue;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_LISTEN:
Packit 23ab03
		case NDMCHAN_MODE_READCHK:
Packit 23ab03
			break;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_READ:
Packit 23ab03
			if (ch->eof)
Packit 23ab03
				continue;
Packit 23ab03
			if (ndmchan_n_avail (ch) == 0)
Packit 23ab03
				continue;
Packit 23ab03
			break;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_WRITE:
Packit 23ab03
			if (ndmchan_n_ready (ch) == 0)
Packit 23ab03
				continue;
Packit 23ab03
			break;
Packit 23ab03
		}
Packit 23ab03
Packit 23ab03
		ch->check = 1;
Packit 23ab03
		n_check++;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	return n_check;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_post_poll (struct ndmchan *chtab[], unsigned n_chtab)
Packit 23ab03
{
Packit 23ab03
	struct ndmchan *	ch;
Packit 23ab03
	unsigned int		i;
Packit 23ab03
	int			rc, len, n_ready;
Packit 23ab03
Packit 23ab03
	n_ready = 0;
Packit 23ab03
Packit 23ab03
	for (i = 0; i < n_chtab; i++) {
Packit 23ab03
		ch = chtab[i];
Packit 23ab03
Packit 23ab03
		if (!ch->ready)
Packit 23ab03
			continue;
Packit 23ab03
Packit 23ab03
		switch (ch->mode) {
Packit 23ab03
		case NDMCHAN_MODE_READ:
Packit 23ab03
			len = ndmchan_n_avail (ch);
Packit 23ab03
			if (len <= 0) continue;
Packit 23ab03
Packit 23ab03
			n_ready++;
Packit 23ab03
			rc = read (ch->fd, &ch->data[ch->end_ix], len);
Packit 23ab03
			if (rc < 0) {
Packit 23ab03
				if (errno != NDMOS_CONST_EWOULDBLOCK) {
Packit 23ab03
					ch->error = ch->eof = 1;
Packit 23ab03
					ch->saved_errno = errno;
Packit 23ab03
					if (!ch->saved_errno)
Packit 23ab03
						ch->saved_errno = -1;
Packit 23ab03
				} else {
Packit 23ab03
					/* no bytes read */
Packit 23ab03
				}
Packit 23ab03
			} else if (rc == 0) {
Packit 23ab03
				ch->eof = 1;
Packit 23ab03
				ch->error = 0;
Packit 23ab03
				ch->saved_errno = 0;
Packit 23ab03
			} else {
Packit 23ab03
				ch->end_ix += rc;
Packit 23ab03
			}
Packit 23ab03
			break;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_WRITE:
Packit 23ab03
			len = ndmchan_n_ready (ch);
Packit 23ab03
			if (len <= 0) continue;
Packit 23ab03
Packit 23ab03
			n_ready++;
Packit 23ab03
			rc = write (ch->fd, &ch->data[ch->beg_ix], len);
Packit 23ab03
			if (rc < 0) {
Packit 23ab03
				if (errno != NDMOS_CONST_EWOULDBLOCK) {
Packit 23ab03
					ch->eof = 1;
Packit 23ab03
					ch->error = 1;
Packit 23ab03
					ch->saved_errno = errno;
Packit 23ab03
					if (!ch->saved_errno)
Packit 23ab03
						ch->saved_errno = -1;
Packit 23ab03
				} else {
Packit 23ab03
					/* no bytes written */
Packit 23ab03
					/* EWOULDBLOCK but ready? */
Packit 23ab03
				}
Packit 23ab03
			} else if (rc == 0) {
Packit 23ab03
				/* NDMOS_CONST_EWOULDBLOCK? */
Packit 23ab03
				ch->eof = 1;
Packit 23ab03
				ch->error = 1;
Packit 23ab03
				ch->saved_errno = 0;
Packit 23ab03
			} else {
Packit 23ab03
				ch->beg_ix += rc;
Packit 23ab03
			}
Packit 23ab03
			break;
Packit 23ab03
		}
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	return n_ready;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Channel data buffer space manipulation.
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
void
Packit 23ab03
ndmchan_compress (struct ndmchan *ch) {
Packit 23ab03
	unsigned	len = ch->end_ix - ch->beg_ix;
Packit 23ab03
Packit 23ab03
	if (ch->beg_ix > 0 && len > 0) {
Packit 23ab03
		bcopy (&ch->data[ch->beg_ix], ch->data, len);
Packit 23ab03
	} else {
Packit 23ab03
		if (len > ch->data_size)
Packit 23ab03
			len = 0;
Packit 23ab03
	}
Packit 23ab03
	ch->beg_ix = 0;
Packit 23ab03
	ch->end_ix = len;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_n_avail (struct ndmchan *ch) {
Packit 23ab03
	if (ch->end_ix == ch->beg_ix)
Packit 23ab03
		ch->end_ix = ch->beg_ix = 0;
Packit 23ab03
Packit 23ab03
	if (ch->end_ix >= ch->data_size) {
Packit 23ab03
		ndmchan_compress (ch);
Packit 23ab03
	}
Packit 23ab03
	return ch->data_size - ch->end_ix;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_n_avail_record (struct ndmchan *ch, unsigned long size) {
Packit 23ab03
	if (ch->end_ix == ch->beg_ix)
Packit 23ab03
		ch->end_ix = ch->beg_ix = 0;
Packit 23ab03
Packit 23ab03
	if (ch->end_ix >= ch->data_size - size) {
Packit 23ab03
		ndmchan_compress (ch);
Packit 23ab03
	}
Packit 23ab03
	return ch->data_size - ch->end_ix;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_n_avail_total (struct ndmchan *ch) {
Packit 23ab03
	if (ch->end_ix == ch->beg_ix)
Packit 23ab03
		ch->end_ix = ch->beg_ix = 0;
Packit 23ab03
Packit 23ab03
	if (ch->end_ix >= ch->data_size) {
Packit 23ab03
		ndmchan_compress (ch);
Packit 23ab03
	}
Packit 23ab03
	return ch->data_size - ch->end_ix + ch->beg_ix;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmchan_n_ready (struct ndmchan *ch) {
Packit 23ab03
	return ch->end_ix - ch->beg_ix;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Interfaces for interpreting channel state, obtaining pointers, lengths
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
enum ndmchan_read_interpretation
Packit 23ab03
ndmchan_read_interpret (struct ndmchan *ch, char **data_p,
Packit 23ab03
  unsigned *n_ready_p)
Packit 23ab03
{
Packit 23ab03
	unsigned	n_ready;
Packit 23ab03
Packit 23ab03
	n_ready = *n_ready_p = ndmchan_n_ready (ch);
Packit 23ab03
	*data_p = &ch->data[ch->beg_ix];
Packit 23ab03
Packit 23ab03
	if (ch->error) {
Packit 23ab03
		if (n_ready == 0) {
Packit 23ab03
			return NDMCHAN_RI_DONE_ERROR;
Packit 23ab03
		} else {
Packit 23ab03
			return NDMCHAN_RI_DRAIN_ERROR;
Packit 23ab03
		}
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (ch->eof) {
Packit 23ab03
		if (n_ready == 0) {
Packit 23ab03
			return NDMCHAN_RI_DONE_EOF;
Packit 23ab03
		} else {
Packit 23ab03
			return NDMCHAN_RI_DRAIN_EOF;
Packit 23ab03
		}
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (n_ready == 0) {
Packit 23ab03
		return NDMCHAN_RI_EMPTY;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (n_ready == ch->data_size) {
Packit 23ab03
		return NDMCHAN_RI_READY_FULL;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	return NDMCHAN_RI_READY;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
enum ndmchan_write_interpretation
Packit 23ab03
ndmchan_write_interpret (struct ndmchan *ch, char **data_p,
Packit 23ab03
  unsigned *n_avail_p)
Packit 23ab03
{
Packit 23ab03
	unsigned	n_avail;
Packit 23ab03
Packit 23ab03
	n_avail = *n_avail_p = ndmchan_n_avail (ch);
Packit 23ab03
	*data_p = &ch->data[ch->end_ix];
Packit 23ab03
Packit 23ab03
	if (ch->error) {
Packit 23ab03
		/* We don't use WI_DRAIN_ERROR. If it's kaput, it's kaput */
Packit 23ab03
		return NDMCHAN_WI_DONE_ERROR;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (ch->eof) {
Packit 23ab03
		if (n_avail == ch->data_size) {
Packit 23ab03
			return NDMCHAN_WI_DONE_EOF;
Packit 23ab03
		} else {
Packit 23ab03
			return NDMCHAN_WI_DRAIN_EOF;
Packit 23ab03
		}
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (n_avail == 0) {
Packit 23ab03
		return NDMCHAN_WI_FULL;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (n_avail == ch->data_size) {
Packit 23ab03
		return NDMCHAN_WI_AVAIL_EMPTY;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	return NDMCHAN_WI_AVAIL;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
/*
Packit 23ab03
 * Pretty printer
Packit 23ab03
 */
Packit 23ab03
void
Packit 23ab03
ndmchan_pp (struct ndmchan *ch, char *buf)
Packit 23ab03
{
Packit 23ab03
	int		show_ra = 0;
Packit 23ab03
	char *		bp = buf;
Packit 23ab03
	char *		p;
Packit 23ab03
Packit 23ab03
	sprintf (bp, "name=%s", ch->name); while (*bp) bp++;
Packit 23ab03
Packit 23ab03
	switch (ch->mode) {
Packit 23ab03
	case NDMCHAN_MODE_IDLE:		p = "idle"; break;
Packit 23ab03
	case NDMCHAN_MODE_RESIDENT:	p = "resident"; show_ra = 1; break;
Packit 23ab03
	case NDMCHAN_MODE_READ:		p = "read"; show_ra = 1; break;
Packit 23ab03
	case NDMCHAN_MODE_WRITE:	p = "write"; show_ra = 1; break;
Packit 23ab03
	case NDMCHAN_MODE_READCHK:	p = "readchk"; break;
Packit 23ab03
	case NDMCHAN_MODE_LISTEN:	p = "listen"; break;
Packit 23ab03
	case NDMCHAN_MODE_PENDING:	p = "pending"; break;
Packit 23ab03
	case NDMCHAN_MODE_CLOSED:	p = "closed"; break;
Packit 23ab03
	default:			p = "mode=???"; break;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	sprintf (bp, " %s ", p);
Packit 23ab03
	while (*bp) bp++;
Packit 23ab03
Packit 23ab03
	if (show_ra) {
Packit 23ab03
		sprintf (bp, "ready=%d avail=%d ",
Packit 23ab03
			ndmchan_n_ready(ch), ndmchan_n_avail(ch));
Packit 23ab03
		while (*bp) bp++;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	if (ch->ready)	strcat (bp, "-rdy");
Packit 23ab03
	if (ch->check)	strcat (bp, "-chk");
Packit 23ab03
	if (ch->eof)	strcat (bp, "-eof");
Packit 23ab03
	if (ch->error)	strcat (bp, "-err");
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
Packit 23ab03
#ifdef NDMOS_OPTION_USE_SELECT_FOR_CHAN_POLL
Packit 23ab03
/*
Packit 23ab03
 * Here because it is almost always used
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmos_chan_poll (struct ndmchan *chtab[], unsigned n_chtab, int milli_timo)
Packit 23ab03
{
Packit 23ab03
	struct ndmchan *	ch;
Packit 23ab03
	fd_set			rfds, wfds;
Packit 23ab03
	int			nfd = 0, rc;
Packit 23ab03
	unsigned		i;
Packit 23ab03
	struct timeval		timo;
Packit 23ab03
Packit 23ab03
	FD_ZERO(&rfds);
Packit 23ab03
	FD_ZERO(&wfds);
Packit 23ab03
Packit 23ab03
	timo.tv_sec = milli_timo / 1000;
Packit 23ab03
	timo.tv_usec = (milli_timo%1000) * 1000;
Packit 23ab03
Packit 23ab03
	for (i = 0; i < n_chtab; i++) {
Packit 23ab03
		ch = chtab[i];
Packit 23ab03
		if (!ch->check)
Packit 23ab03
			continue;
Packit 23ab03
Packit 23ab03
		switch (ch->mode) {
Packit 23ab03
		case NDMCHAN_MODE_LISTEN:
Packit 23ab03
		case NDMCHAN_MODE_READCHK:
Packit 23ab03
		case NDMCHAN_MODE_READ:
Packit 23ab03
			FD_SET (ch->fd, &rfds);
Packit 23ab03
			break;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_WRITE:
Packit 23ab03
			FD_SET (ch->fd, &wfds);
Packit 23ab03
			break;
Packit 23ab03
		}
Packit 23ab03
		if (nfd < ch->fd+1)
Packit 23ab03
			nfd = ch->fd+1;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	rc = select (nfd, &rfds, &wfds, (void*)0, &timo;;
Packit 23ab03
	if (rc <= 0)
Packit 23ab03
		return rc;
Packit 23ab03
Packit 23ab03
	for (i = 0; i < n_chtab; i++) {
Packit 23ab03
		ch = chtab[i];
Packit 23ab03
		if (!ch->check)
Packit 23ab03
			continue;
Packit 23ab03
Packit 23ab03
		switch (ch->mode) {
Packit 23ab03
		case NDMCHAN_MODE_LISTEN:
Packit 23ab03
		case NDMCHAN_MODE_READCHK:
Packit 23ab03
		case NDMCHAN_MODE_READ:
Packit 23ab03
			if (FD_ISSET (ch->fd, &rfds))
Packit 23ab03
				ch->ready = 1;
Packit 23ab03
			break;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_WRITE:
Packit 23ab03
			if (FD_ISSET (ch->fd, &wfds))
Packit 23ab03
				ch->ready = 1;
Packit 23ab03
			break;
Packit 23ab03
		}
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	return rc;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
#endif /* NDMOS_OPTION_USE_SELECT_FOR_CHAN_POLL */
Packit 23ab03
Packit 23ab03
#ifdef NDMOS_OPTION_USE_POLL_FOR_CHAN_POLL
Packit 23ab03
/*
Packit 23ab03
 * Here because it is common, and because poll(2) is
Packit 23ab03
 * INFINITELY SUPERIOR to select(2).
Packit 23ab03
 */
Packit 23ab03
Packit 23ab03
int
Packit 23ab03
ndmos_chan_poll (struct ndmchan *chtab[], unsigned n_chtab, int milli_timo)
Packit 23ab03
{
Packit 23ab03
	struct ndmchan *	ch;
Packit 23ab03
	struct pollfd		pfdtab[20];
Packit 23ab03
	int			n_pfdtab = 0;
Packit 23ab03
	int			rc, i;
Packit 23ab03
Packit 23ab03
	NDMOS_MACRO_ZEROFILL (pfdtab);
Packit 23ab03
Packit 23ab03
	for (i = 0; i < n_chtab; i++) {
Packit 23ab03
		ch = chtab[i];
Packit 23ab03
		if (!ch->check)
Packit 23ab03
			continue;
Packit 23ab03
Packit 23ab03
		switch (ch->mode) {
Packit 23ab03
		case NDMCHAN_MODE_LISTEN:
Packit 23ab03
		case NDMCHAN_MODE_READCHK:
Packit 23ab03
		case NDMCHAN_MODE_READ:
Packit 23ab03
			pfdtab[n_pfdtab].fd = ch->fd;
Packit 23ab03
			pfdtab[n_pfdtab].events = POLLIN;
Packit 23ab03
			break;
Packit 23ab03
Packit 23ab03
		case NDMCHAN_MODE_WRITE:
Packit 23ab03
			pfdtab[n_pfdtab].fd = ch->fd;
Packit 23ab03
			pfdtab[n_pfdtab].events = POLLOUT;
Packit 23ab03
			break;
Packit 23ab03
		}
Packit 23ab03
		n_pfdtab++;
Packit 23ab03
	}
Packit 23ab03
Packit 23ab03
	rc = poll (pfdtab, n_pfdtab, milli_timo);
Packit 23ab03
Packit 23ab03
	@@@ TODO: post them back. Not easy @@@
Packit 23ab03
Packit 23ab03
	return rc;
Packit 23ab03
}
Packit 23ab03
Packit 23ab03
#endif /* NDMOS_OPTION_USE_POLL_FOR_CHAN_POLL */
Packit 23ab03