plan 9 kernel history: overview | file list | diff list

1992/0111/port/stfcall.c (diff list | history)

port/stfcall.c on 1991/0521
1991/0521    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1991/0521    
 
#include	"fcall.h" 
 
1991/1003    
#define DPRINT 	if(fcalldebug)kprint 
1991/0521    
 
int fcalldebug = 0; 
 
typedef struct Fcalld	Fcalld; 
 
struct Fcalld{ 
	int	dev;		/* ref. for debug output */ 
	int	state; 
	int	type;		/* of current message */ 
	int	need;		/* bytes remaining in current message */ 
	int	nhdr;		/* bytes of header treasured up in hdr */ 
	uchar	hdr[16]; 
}; 
 
enum { 
	Startup, Startup1, Begin, Header, Data 
}; 
 
/* 
 *  fcall stream module definition 
 */ 
static void fcalliput(Queue*, Block*); 
static void fcalloput(Queue*, Block*); 
static void fcallopen(Queue*, Stream*); 
static void fcallclose(Queue*); 
static void fcallreset(void); 
Qinfo fcallinfo = 
{ 
	fcalliput, 
	fcalloput, 
	fcallopen, 
	fcallclose, 
	"fcall", 
	fcallreset 
}; 
 
static Block *	putmsg(Queue*, Block*, int); 
 
static uchar msglen[] = { 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  3,  3,  3,  3,  0, 67,  5,  3, 89, 13,  7,  5, 33, 13, 
	  6, 13, 38, 13, 15,  8, 16,  7,  5,  5,  5,  5,  5,121,121,  5, 
1991/1003    
	 35, 13, 69, 35,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
1991/0521    
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 
}; 
static void 
fcallreset(void) 
{} 
 
static void 
fcallopen(Queue *q, Stream *s) 
{ 
	Fcalld *f; 
 
	DPRINT("fcallopen %d\n", s->dev); 
 
	q->ptr = allocb(sizeof(Fcalld)); 
	f = (Fcalld *)((Block *)q->ptr)->base; 
	f->dev = s->dev; 
	f->state = Startup; 
	f->type = 0; 
	f->need = 0; 
	f->nhdr = 0; 
} 
 
static void 
fcallclose(Queue * q) 
{ 
	Fcalld *f = (Fcalld *)((Block *)q->ptr)->base; 
 
	DPRINT("fcallstclose %d\n", f->dev); 
	freeb(q->ptr); 
	q->ptr = 0; 
} 
 
void 
fcalloput(Queue *q, Block *bp) 
{ 
	PUTNEXT(q, bp); 
} 
 
 
static void 
fcalliput(Queue *q, Block *bp) 
{ 
	Fcalld *f = (Fcalld *)((Block *)q->ptr)->base; 
	int len, n; 
 
	len = BLEN(bp); 
	DPRINT("fcalliput %d: blen=%d\n", f->dev, len); 
	if(bp->type != M_DATA){ 
		DPRINT("fcalliput %d: type=%d\n", f->dev, bp->type); 
		PUTNEXT(q, bp); 
		return; 
	} 
	bp->flags &= ~S_DELIM; 
	if(len == 0){ 
		freeb(bp); 
		return; 
	} 
	while(len > 0)switch(f->state){ 
	case Startup: 
		if (len == 1 && bp->rptr[0] == 'O'){ 
			DPRINT("fcalliput %d: O\n", f->dev); 
			PUTNEXT(q, bp); 
			f->state = Startup1; 
			return; 
		} 
		if(bp->rptr[0] == 'O' && bp->rptr[1] == 'K'){ 
			DPRINT("fcalliput %d: OK\n", f->dev); 
			bp = putmsg(q, bp, 2); 
			len -= 2; 
		} 
		f->state = Begin; 
		break; 
 
	case Startup1: 
		if(bp->rptr[0] == 'K'){ 
			DPRINT("fcalliput %d: K\n", f->dev); 
			bp = putmsg(q, bp, 1); 
			len -= 1; 
			f->state = Begin; 
			break; 
		} 
		f->type = 'O'; 
		f->need = msglen['O']-1; 
		f->state = Data; 
		DPRINT("fcalliput %d: type=%d, need=%d\n", 
			f->dev, f->type, f->need); 
		break; 
 
	case Begin: 
		f->type = bp->rptr[0]; 
		f->need = msglen[f->type]; 
		f->nhdr = 0; 
		if(f->type == Twrite || f->type == Rread) 
			f->state = Header; 
		else 
			f->state = Data; 
		DPRINT("fcalliput %d: type=%d, need=%d\n", 
			f->dev, f->type, f->need); 
		break; 
 
	case Header: 
		n = f->need; 
		if(n > len) 
			n = len; 
		memmove(&f->hdr[f->nhdr], bp->rptr, n); 
		f->nhdr += n; 
		DPRINT("fcalliput %d: nhdr=%d\n", 
			f->dev, f->nhdr); 
		if(n == f->need){ 
			f->need += f->hdr[f->nhdr-3]; 
			f->need += f->hdr[f->nhdr-2] << 8; 
			f->state = Data; 
			DPRINT("fcalliput %d: need=%d\n", 
				f->dev, f->need); 
		} 
		/* fall through */ 
 
	case Data: 
		if(f->need > len){ 
			f->need -= len; 
			PUTNEXT(q, bp); 
			return; 
		} 
		bp = putmsg(q, bp, f->need); 
		len -= f->need; 
		f->state = Begin; 
		break; 
	} 
} 
 
static Block * 
putmsg(Queue *q, Block *bp, int n) 
{ 
	Block *xbp; 
	int k; 
 
	DPRINT("putmsg: n=%d\n\n", n); 
	k = BLEN(bp) - n; 
	if(k == 0){ 
		bp->flags |= S_DELIM; 
		PUTNEXT(q, bp); 
		return 0; 
	} 
	if(n <= k){ 
		xbp = allocb(n); 
		memmove(xbp->wptr, bp->rptr, n); 
		xbp->wptr += n; 
		bp->rptr += n; 
		xbp->flags |= S_DELIM; 
		PUTNEXT(q, xbp); 
		return bp; 
	} 
	xbp = allocb(k); 
	memmove(xbp->wptr, bp->rptr+n, k); 
	xbp->wptr += k; 
	bp->wptr -= k; 
	bp->flags |= S_DELIM; 
	PUTNEXT(q, bp); 
	return xbp; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)