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

gnot/devhifi.c (diff list | history)

1992/0609/sys/src/9/gnot/devhifi.c:155,1621992/0611/sys/src/9/gnot/devhifi.c:155,160 (short | long)
remove unused variables
rsc Fri Mar 4 12:44:25 2005
1992/0609    
Chan* 
hifiopen(Chan *c, int omode) 
{ 
	Hifichan *hp = &hifichan[c->dev]; 
                 
	if(c->qid.path == CHDIR){ 
		if(omode != OREAD) 
			error(Eperm); 
1992/0609/sys/src/9/gnot/devhifi.c:183,1901992/0611/sys/src/9/gnot/devhifi.c:181,186
1992/0609    
void	  
hificlose(Chan *c) 
{ 
	Hifichan *hp = &hifichan[c->dev]; 
                 
	if(c->qid.path != CHDIR) 
		streamclose(c); 
} 
1992/0609/sys/src/9/gnot/devhifi.c:235,2411992/0611/sys/src/9/gnot/devhifi.c:231,236
1992/0609    
hifiwrite(Chan *c, void *buf, long n, ulong offset) 
{ 
	Hifichan *hp = &hifichan[c->dev]; 
	Hifi *hifi = hp->hdev; 
	char nbuf[32], *p; 
 
	if(n < 0) 
1992/0611/sys/src/9/gnot/devhifi.c:99,1051992/0627/sys/src/9/gnot/devhifi.c:99,105 (short | long)
change ialloc to xalloc (XXX)
rsc Fri Mar 4 12:44:25 2005
1992/0609    
void 
hifireset(void) 
{ 
	hifichan = ialloc(2*conf.nisdn*sizeof(Hifichan), 0); 
1992/0627    
	hifichan = xalloc(2*conf.nisdn*sizeof(Hifichan)); 
1992/0609    
	hifichanN = &hifichan[2*conf.nisdn]; 
} 
 
1992/0627/sys/src/9/gnot/devhifi.c:15,211992/0701/sys/src/9/gnot/devhifi.c:15,21 (short | long)
change BSIZE to 4000 instead of 4096 (better headers?). in hifikproc, change PUTNEXT to FLOWCTL (BUG XXX?) in hifirecv, set bp->rptr (BUG XXX?)
rsc Fri Mar 4 12:44:25 2005
1992/0609    
 
#define DPRINT 	if(hifidebug)kprint 
 
#define	BSIZE	4096 
1992/0701    
#define	BSIZE	4000 
1992/0609    
 
typedef struct Hifichan 
{ 
1992/0627/sys/src/9/gnot/devhifi.c:433,4411992/0701/sys/src/9/gnot/devhifi.c:433,441
1992/0609    
	for(;;){ 
		qlock(hp); 
		while(hp->ri != hp->wi){ 
			if(hp->rq) 
				PUTNEXT(hp->rq, hp->inb[hp->ri]); 
			else 
1992/0701    
			if(hp->rq){ 
				FLOWCTL(hp->rq, hp->inb[hp->ri]); 
			}else 
1992/0609    
				freeb(hp->inb[hp->ri]); 
			if(hp->renable) 
				hp->inb[hp->ri] = allocb(BSIZE); 
1992/0627/sys/src/9/gnot/devhifi.c:583,5881992/0701/sys/src/9/gnot/devhifi.c:583,589
1992/0609    
		if(n > m){ 
			hp->toolong++; 
			bp->wptr = bp->base; 
1992/0701    
			bp->rptr = bp->base; 
1992/0609    
			SET(hifi->opreg, hp->opreg | Rres); 
			return wake; 
		} 
1992/0627/sys/src/9/gnot/devhifi.c:613,6181992/0701/sys/src/9/gnot/devhifi.c:614,620
1992/0609    
					hp->badcount++; 
			} 
			bp->wptr = bp->base; 
1992/0701    
			bp->rptr = bp->base; 
1992/0609    
		}else 
			bp->wptr = p; 
	}else{ 
1992/0627/sys/src/9/gnot/devhifi.c:627,6321992/0701/sys/src/9/gnot/devhifi.c:629,635
1992/0609    
			i = NEXT(hp->wi); 
			if(i == hp->ri){ 
				bp->wptr = bp->base; 
1992/0701    
				bp->rptr = bp->base; 
1992/0609    
				return wake; 
			}else{ 
				bp->flags |= S_DELIM; 
1992/0701/sys/src/9/gnot/devhifi.c:175,1801992/0711/sys/src/9/gnot/devhifi.c:175,181 (short | long)
add USED annotations; remove unused variables
rsc Fri Mar 4 12:44:25 2005
1992/0609    
void	  
hificreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1992/0711    
	USED(c, name, omode, perm); 
1992/0609    
	error(Eperm); 
} 
 
1992/0701/sys/src/9/gnot/devhifi.c:233,2381992/0711/sys/src/9/gnot/devhifi.c:234,240
1992/0609    
	Hifichan *hp = &hifichan[c->dev]; 
	char nbuf[32], *p; 
 
1992/0711    
	USED(offset); 
1992/0609    
	if(n < 0) 
		return 0; 
	switch(STREAMTYPE(c->qid.path)){ 
1992/0701/sys/src/9/gnot/devhifi.c:252,2571992/0711/sys/src/9/gnot/devhifi.c:254,260
1992/0609    
void	  
hifiremove(Chan *c) 
{ 
1992/0711    
	USED(c); 
1992/0609    
	error(Eperm); 
} 
 
1992/0701/sys/src/9/gnot/devhifi.c:258,2631992/0711/sys/src/9/gnot/devhifi.c:261,267
1992/0609    
void	  
hifiwstat(Chan *c, char *dp) 
{ 
1992/0711    
	USED(c, dp); 
1992/0609    
	error(Eperm); 
} 
 
1992/0701/sys/src/9/gnot/devhifi.c:517,5241992/0711/sys/src/9/gnot/devhifi.c:521,527
1992/0609    
	Isdn *ip; 
	Hifichan *hp; 
	Hifi *hifi; 
	int intr = 0, status, n, c, wake = 0, w = 0; 
	uchar *p; 
1992/0711    
	int intr = 0, status, wake = 0, w = 0; 
1992/0609    
 
	for(hp=hifichan; hp<hifichanN; hp++){ 
		if(!(ip = hp->udev))	/* assign = */ 
1992/0711/sys/src/9/gnot/devhifi.c:31,361992/1204/sys/src/9/gnot/devhifi.c:31,37 (short | long)
add Hifichan.nohup, debug file, nohup message; use readstr
rsc Fri Mar 4 12:44:25 2005
1992/0609    
	QLock;			/* access to struct */ 
	int	hdlc;		/* hdlc mode enabled */ 
	int	hangup;		/* hangup pending */ 
1992/1204    
	int	nohup;		/* hangups ignored */ 
1992/0609    
 
	int	renable;	/* reading enabled */ 
	Block *	inb[NB];	/* input buffer */ 
1992/0711/sys/src/9/gnot/devhifi.c:76,871992/1204/sys/src/9/gnot/devhifi.c:77,89
1992/0609    
static void	hifixmiten(Hifichan*, int); 
 
enum { 
	Qdir, Qdev, Qstats 
1992/1204    
	Qdir, Qdev, Qstats, Qdebug 
1992/0609    
}; 
 
Dirtab hifidir[]={ 
	"dev",		{Qdev},		0,	0666, 
	"stats",	{Qstats},	0,	0444, 
1992/1204    
	"debug",	{Qdebug},	0,	0666, 
1992/0609    
}; 
#define	NHIFI	(sizeof hifidir/sizeof(Dirtab)) 
 
1992/0711/sys/src/9/gnot/devhifi.c:94,1001992/1204/sys/src/9/gnot/devhifi.c:96,102
1992/0609    
static void hifistclose(Queue*); 
Qinfo hifiinfo = { hifiiput, hifioput, hifistopen, hifistclose, "hifi" }; 
 
int	hifidebug = 1; 
1992/1204    
int	hifidebug; 
1992/0609    
 
void 
hifireset(void) 
1992/0711/sys/src/9/gnot/devhifi.c:161,1661992/1204/sys/src/9/gnot/devhifi.c:163,169
1992/0609    
	}else switch(STREAMTYPE(c->qid.path)){ 
	case Qdev: 
	case Qstats: 
1992/1204    
	case Qdebug: 
1992/0609    
		break; 
	default: 
		DPRINT("hifiopen dev=%d\n", c->dev); 
1992/0711/sys/src/9/gnot/devhifi.c:190,1961992/1204/sys/src/9/gnot/devhifi.c:193,199
1992/0609    
hifiread(Chan *c, void *buf, long n, ulong offset) 
{ 
	Hifichan *hp = &hifichan[c->dev]; 
	char nbuf[512], *p; int k; 
1992/1204    
	char nbuf[512], *p; 
1992/0609    
 
	if(n <= 0) 
		return 0; 
1992/0711/sys/src/9/gnot/devhifi.c:198,2071992/1204/sys/src/9/gnot/devhifi.c:201,209
1992/0609    
		return devdirread(c, buf, n, hifidir, NHIFI, streamgen); 
	}else switch(STREAMTYPE(c->qid.path)){ 
	case Qdev: 
		p = nbuf; 
		p += sprint(p, "0x%2.2ux = 0x%2.2ux\n", 
1992/1204    
		sprint(nbuf, "0x%2.2ux = 0x%2.2ux\n", 
1992/0609    
			hp->devaddr, isdnpeek(hp->udev, (void *)hp->devaddr)); 
		goto Readnbuf; 
1992/1204    
		return readstr(offset, buf, n, nbuf); 
1992/0609    
 
	case Qstats: 
		p = nbuf; 
1992/0711/sys/src/9/gnot/devhifi.c:214,2271992/1204/sys/src/9/gnot/devhifi.c:216,227
1992/0609    
		p += sprint(p, "toolong  %10lud\n", hp->toolong); 
		p += sprint(p, "underrun %10lud\n", hp->underrun); 
		p += sprint(p, "outchars %10lud\n", hp->outchars); 
	Readnbuf: 
		k = p - nbuf; 
		if (offset >= k) 
			return 0; 
		if (offset+n > k) 
			n = k - offset; 
		memmove(buf, &nbuf[offset], n); 
		return n; 
1992/1204    
		USED(p); 
		return readstr(offset, buf, n, nbuf); 
 
	case Qdebug: 
		sprint(nbuf, "%d\n", hifidebug); 
		return readstr(offset, buf, n, nbuf); 
1992/0609    
	} 
	if(!hp->renable) 
		hifirecven(hp, 1); 
1992/0711/sys/src/9/gnot/devhifi.c:247,2521992/1204/sys/src/9/gnot/devhifi.c:247,259
1992/0609    
		if(p = strchr(nbuf, '='))	/* assign = */ 
			isdnpoke(hp->udev, (void *)hp->devaddr, strtoul(++p,0,0)); 
		return n; 
1992/1204    
	case Qdebug: 
		if (n>sizeof nbuf) 
			n = sizeof nbuf; 
		memmove(nbuf, buf, n); 
		nbuf[n-1] = 0; 
		hifidebug = strtoul(nbuf,0,0); 
		return n; 
1992/0609    
	} 
	return streamwrite(c, buf, n, 0); 
} 
1992/0711/sys/src/9/gnot/devhifi.c:309,3141992/1204/sys/src/9/gnot/devhifi.c:316,322
1992/0609    
	qlock(hp); 
	hp->rq = 0; 
	hp->hangup = 0; 
1992/1204    
	hp->nohup = 0; 
1992/0609    
	if(tActive(hp)){ 
		if(!hp->wactive || waserror()){ 
			hifixmitdis(hp, 1); 
1992/0711/sys/src/9/gnot/devhifi.c:331,3381992/1204/sys/src/9/gnot/devhifi.c:339,347
1992/0609    
	Hifichan *hp = (Hifichan *)q->ptr; 
 
	if(bp->type == M_HANGUP){ 
		DPRINT("hifiiput %d M_HANGUP\n", hp-hifichan); 
		hifirecven(hp, 0); 
1992/1204    
		DPRINT("hifiiput %d M_HANGUP (%d)\n", hp-hifichan, hp->nohup); 
		if(!hp->nohup) 
			hifirecven(hp, 0); 
1992/0609    
	} 
	freeb(bp); 
} 
1992/0711/sys/src/9/gnot/devhifi.c:366,3711992/1204/sys/src/9/gnot/devhifi.c:375,382
1992/0609    
			hifirecven(hp, 0); 
		}else if(streamparse("recven", bp)){ 
			hifirecven(hp, 1); 
1992/1204    
		}else if(streamparse("nohup", bp)){ 
			hp->nohup = 1; 
1992/0609    
		} 
		freeb(bp); 
		return; 
1992/0711/sys/src/9/gnot/devhifi.c:661,6671992/1204/sys/src/9/gnot/devhifi.c:672,678
1992/0609    
	if(!(bp = hp->out)){	/* assign = */ 
		if(hp->ro == hp->wo){ 
			DPRINT("hifixmit %d: [%d] empty\n", 
				TK2MS(MACHP(0)->ticks), hp-hifichan); 
1992/1204    
				hp-hifichan, TK2MS(MACHP(0)->ticks)); 
1992/0609    
			return wake; 
		} 
		hp->out = bp = hp->outb[hp->ro]; 
1992/1204/sys/src/9/gnot/devhifi.c:1,7651993/0501/sys/src/9/gnot/devhifi.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:21:39 2005
1992/0609    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"../port/error.h" 
#include	"devtab.h" 
                 
#include	"io.h" 
#ifdef	SET 
#undef	SET 
#endif 
#include	"isdn.h" 
#include	"hifi.h" 
                 
#define DPRINT 	if(hifidebug)kprint 
                 
1992/0701    
#define	BSIZE	4000 
1992/0609    
                 
typedef struct Hifichan 
{ 
	Isdn *	udev;		/* unite interface */ 
	Hifi *	hdev;		/* pointer to device */ 
	uchar	imask;		/* interrupt bit */ 
	uchar	opreg;		/* sticky bits */ 
	uchar	tctl;		/* more sticky bits */ 
	uchar	devaddr;	/* debug access */ 
                 
	Lock	kctl;		/* kproc start */ 
	Rendez	kr;		/* kernel process sleep/wakeup */ 
	QLock;			/* access to struct */ 
	int	hdlc;		/* hdlc mode enabled */ 
	int	hangup;		/* hangup pending */ 
1992/1204    
	int	nohup;		/* hangups ignored */ 
1992/0609    
                 
	int	renable;	/* reading enabled */ 
	Block *	inb[NB];	/* input buffer */ 
	int	ri;		/* input read pointer */ 
	int	wi;		/* input write pointer */ 
	Queue *	rq;		/* read queue */ 
                 
	int	wenable;	/* writing enabled */ 
	int	wactive;	/* writing in progress */ 
	QLock	wlock;		/* write's are atomic */ 
	Block *	outb[NB];	/* output buffer */ 
	int	so;		/* output scavenge pointer */ 
	int	ro;		/* output read pointer */ 
	int	wo;		/* output write pointer */ 
	Block *	out;		/* current output block */ 
	Rendez	tr;		/* if transmitter must wait */ 
	Rendez	cr;		/* waiting to close */ 
                 
	/* statistics */ 
                 
	ulong	inchars; 
	ulong	badcrc; 
	ulong	abort; 
	ulong	overrun; 
	ulong	badcount; 
	ulong	overflow; 
	ulong	toolong; 
	ulong	underrun; 
	ulong	outchars; 
} Hifichan; 
                 
Hifichan *	hifichan; 
Hifichan *	hifichanN; 
                 
static void	devinit(int); 
static int	hifiintr(void); 
static void	hifikproc(void*); 
static void	hifiloopctl(Hifichan*, int); 
static int	hifirecv(Hifichan*); 
static void	hifirecven(Hifichan*, int); 
static int	hifixmit(Hifichan*); 
static void	hifixmitdis(Hifichan*, int); 
static void	hifixmiten(Hifichan*, int); 
                 
enum { 
1992/1204    
	Qdir, Qdev, Qstats, Qdebug 
1992/0609    
}; 
                 
Dirtab hifidir[]={ 
	"dev",		{Qdev},		0,	0666, 
	"stats",	{Qstats},	0,	0444, 
1992/1204    
	"debug",	{Qdebug},	0,	0666, 
1992/0609    
}; 
#define	NHIFI	(sizeof hifidir/sizeof(Dirtab)) 
                 
/* 
 *  stream module definition 
 */ 
static void hifiiput(Queue*, Block*); 
static void hifioput(Queue*, Block*); 
static void hifistopen(Queue*, Stream*); 
static void hifistclose(Queue*); 
Qinfo hifiinfo = { hifiiput, hifioput, hifistopen, hifistclose, "hifi" }; 
                 
1992/1204    
int	hifidebug; 
1992/0609    
                 
void 
hifireset(void) 
{ 
1992/0627    
	hifichan = xalloc(2*conf.nisdn*sizeof(Hifichan)); 
1992/0609    
	hifichanN = &hifichan[2*conf.nisdn]; 
} 
                 
void 
hifiinit(void) 
{} 
                 
Chan* 
hifiattach(char *spec) 
{ 
	int dev; 
	Chan *c; 
	Hifichan *hp; 
	static int intrinited; 
                 
	dev = strtoul(spec, 0, 0); 
	if(dev >= 2*conf.nisdn) 
		error(Enonexist); 
		                 
	c = devattach('H', spec); 
	c->dev = dev; 
	hp = &hifichan[dev]; 
	if(!hp->udev){ 
		DPRINT("hifiattach: init dev=%d\n", c->dev); 
		if(!intrinited){ 
			intrinited = 1; 
			DPRINT("addportintr(hifiintr)\n"); 
			addportintr(hifiintr); 
		} 
		devinit(c->dev); 
	} 
	return c; 
} 
                 
Chan* 
hificlone(Chan *c, Chan *nc) 
{ 
	return devclone(c, nc); 
} 
                 
int	  
hifiwalk(Chan *c, char *name) 
{ 
	return devwalk(c, name, hifidir, NHIFI, streamgen); 
} 
                 
void	  
hifistat(Chan *c, char *dp) 
{ 
	devstat(c, dp, hifidir, NHIFI, streamgen); 
} 
                 
Chan* 
hifiopen(Chan *c, int omode) 
{ 
	if(c->qid.path == CHDIR){ 
		if(omode != OREAD) 
			error(Eperm); 
	}else switch(STREAMTYPE(c->qid.path)){ 
	case Qdev: 
	case Qstats: 
1992/1204    
	case Qdebug: 
1992/0609    
		break; 
	default: 
		DPRINT("hifiopen dev=%d\n", c->dev); 
		streamopen(c, &hifiinfo); 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
                 
void	  
hificreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1992/0711    
	USED(c, name, omode, perm); 
1992/0609    
	error(Eperm); 
} 
                 
void	  
hificlose(Chan *c) 
{ 
	if(c->qid.path != CHDIR) 
		streamclose(c); 
} 
                 
long	  
hifiread(Chan *c, void *buf, long n, ulong offset) 
{ 
	Hifichan *hp = &hifichan[c->dev]; 
1992/1204    
	char nbuf[512], *p; 
1992/0609    
                 
	if(n <= 0) 
		return 0; 
	if(c->qid.path == CHDIR){ 
		return devdirread(c, buf, n, hifidir, NHIFI, streamgen); 
	}else switch(STREAMTYPE(c->qid.path)){ 
	case Qdev: 
1992/1204    
		sprint(nbuf, "0x%2.2ux = 0x%2.2ux\n", 
1992/0609    
			hp->devaddr, isdnpeek(hp->udev, (void *)hp->devaddr)); 
1992/1204    
		return readstr(offset, buf, n, nbuf); 
1992/0609    
                 
	case Qstats: 
		p = nbuf; 
		p += sprint(p, "inchars  %10lud\n", hp->inchars); 
		p += sprint(p, "badcrc   %10lud\n", hp->badcrc); 
		p += sprint(p, "abort    %10lud\n", hp->abort); 
		p += sprint(p, "overrun  %10lud\n", hp->overrun); 
		p += sprint(p, "badcount %10lud\n", hp->badcount); 
		p += sprint(p, "overflow %10lud\n", hp->overflow); 
		p += sprint(p, "toolong  %10lud\n", hp->toolong); 
		p += sprint(p, "underrun %10lud\n", hp->underrun); 
		p += sprint(p, "outchars %10lud\n", hp->outchars); 
1992/1204    
		USED(p); 
		return readstr(offset, buf, n, nbuf); 
                 
	case Qdebug: 
		sprint(nbuf, "%d\n", hifidebug); 
		return readstr(offset, buf, n, nbuf); 
1992/0609    
	} 
	if(!hp->renable) 
		hifirecven(hp, 1); 
	return streamread(c, buf, n); 
} 
                 
long	  
hifiwrite(Chan *c, void *buf, long n, ulong offset) 
{ 
	Hifichan *hp = &hifichan[c->dev]; 
	char nbuf[32], *p; 
                 
1992/0711    
	USED(offset); 
1992/0609    
	if(n < 0) 
		return 0; 
	switch(STREAMTYPE(c->qid.path)){ 
	case Qdev: 
		if(n>sizeof nbuf-1) 
			n = sizeof nbuf-1; 
		memmove(nbuf, buf, n); 
		nbuf[n-1] = 0; 
		hp->devaddr = (int)hp->hdev + strtoul(nbuf,0,0); 
		if(p = strchr(nbuf, '='))	/* assign = */ 
			isdnpoke(hp->udev, (void *)hp->devaddr, strtoul(++p,0,0)); 
		return n; 
1992/1204    
	case Qdebug: 
		if (n>sizeof nbuf) 
			n = sizeof nbuf; 
		memmove(nbuf, buf, n); 
		nbuf[n-1] = 0; 
		hifidebug = strtoul(nbuf,0,0); 
		return n; 
1992/0609    
	} 
	return streamwrite(c, buf, n, 0); 
} 
                 
void	  
hifiremove(Chan *c) 
{ 
1992/0711    
	USED(c); 
1992/0609    
	error(Eperm); 
} 
                 
void	  
hifiwstat(Chan *c, char *dp) 
{ 
1992/0711    
	USED(c, dp); 
1992/0609    
	error(Eperm); 
} 
                 
/* 
 *	the stream routines 
 */ 
                 
#define	Predicate(name, expr)	static int name(void *arg) { return expr; } 
#define	hp	((Hifichan *)arg) 
                 
Predicate(kRun, hp->ri != hp->wi || hp->so != hp->ro) 
                 
Predicate(tActive, hp->wenable) 
Predicate(tDead, hp->wenable == 0) 
Predicate(tEmpty, hp->ro == hp->wo) 
Predicate(tFull, NEXT(hp->wo) == hp->so) 
Predicate(tNotFull, NEXT(hp->wo) != hp->so) 
                 
#undef	hp 
                 
static void 
hifistopen(Queue *q, Stream *s) 
{ 
	Hifichan *hp = &hifichan[s->dev]; 
	char name[32]; 
                 
	DPRINT("hifistopen %d\n", s->dev); 
	qlock(hp); 
	q->ptr = q->other->ptr = hp; 
	hp->rq = q; 
	if(canlock(&hp->kctl)){ 
		sprint(name, "hifi%d", s->dev); 
		kproc(name, hifikproc, hp); 
	} 
	qunlock(hp); 
} 
                 
static void 
hifistclose(Queue * q) 
{ 
	Hifichan *hp = (Hifichan *)q->ptr; 
                 
	DPRINT("hifistclose %d...\n", hp-hifichan); 
	hifirecven(hp, -1); 
	qlock(hp); 
	hp->rq = 0; 
	hp->hangup = 0; 
1992/1204    
	hp->nohup = 0; 
1992/0609    
	if(tActive(hp)){ 
		if(!hp->wactive || waserror()){ 
			hifixmitdis(hp, 1); 
			wakeup(&hp->kr); 
		}else{ 
			sleep(&hp->cr, tDead, hp); 
			poperror(); 
		} 
	} 
	qunlock(hp); 
	DPRINT("hifistclose %d OK\n", hp-hifichan); 
} 
                 
/* 
 *  this is only called by hangup 
 */ 
static void 
hifiiput(Queue *q, Block *bp) 
{ 
	Hifichan *hp = (Hifichan *)q->ptr; 
                 
	if(bp->type == M_HANGUP){ 
1992/1204    
		DPRINT("hifiiput %d M_HANGUP (%d)\n", hp-hifichan, hp->nohup); 
		if(!hp->nohup) 
			hifirecven(hp, 0); 
1992/0609    
	} 
	freeb(bp); 
} 
                 
void 
hifioput(Queue *q, Block *bp) 
{ 
	Hifichan *hp = (Hifichan *)q->ptr; 
                 
	if(bp->type != M_DATA){ 
		if(hifidebug){ 
			char fmt[32]; 
			sprint(fmt, "hifioput %%d: %%.%ds\n", bp->wptr-bp->rptr); 
			kprint(fmt, hp-hifichan, bp->rptr); 
		} 
		if(streamparse("hdlc", bp)){ 
			if(streamparse("on", bp)){ 
				hp->hdlc = 1; 
				hifixmiten(hp, 1); 
			}else{ 
				hp->hdlc = 0; 
				if(hp->wenable) 
					hifixmiten(hp, 1); 
			} 
		}else if(streamparse("loop", bp)){ 
			if(streamparse("on", bp)) 
				hifiloopctl(hp, 1); 
			else 
				hifiloopctl(hp, 0); 
		}else if(streamparse("click!", bp)){ 
			hifirecven(hp, 0); 
		}else if(streamparse("recven", bp)){ 
			hifirecven(hp, 1); 
1992/1204    
		}else if(streamparse("nohup", bp)){ 
			hp->nohup = 1; 
1992/0609    
		} 
		freeb(bp); 
		return; 
	} 
	qlock(&hp->wlock); 
	if(!putq(q, bp)){	/* send only whole messages */ 
		qunlock(&hp->wlock); 
		return; 
	} 
	DPRINT("hifioput %d: [%d] len=%d\n", 
		hp-hifichan, TK2MS(MACHP(0)->ticks), q->len); 
	if(tFull(hp)) 
		sleep(&hp->tr, tNotFull, hp); 
	hp->outb[hp->wo] = grabq(q); 
	hp->wo = NEXT(hp->wo); 
	qunlock(&hp->wlock); 
                 
	isdnlock(hp->udev); 
	if(hifixmit(hp)) 
		wakeup(&hp->kr); 
	isdnunlock(hp->udev); 
} 
                 
static void 
hifirecven(Hifichan *hp, int r) 
{ 
	Hifi *hifi = hp->hdev; 
	int i; 
                 
	qlock(hp); 
	if(!hp->renable && r > 0){ 
		hp->ri = hp->wi; 
		for (i=0; i<NB; i++) 
			if(!hp->inb[i]) 
				hp->inb[i] = allocb(BSIZE); 
		hp->renable = 1; 
		isdnpoke(hp->udev, &hifi->opreg, hp->opreg |= Enr); 
		DPRINT("hifirecven %d: enabled\n", hp-hifichan); 
	}else if(hp->renable && r <= 0){ 
		isdnpoke(hp->udev, &hifi->opreg, hp->opreg &= ~Enr); 
		hp->renable = 0; 
		hp->hangup = 1; 
		wakeup(&hp->kr); 
		DPRINT("hifirecven %d: disabled\n", hp-hifichan); 
	} 
	if(r < 0){ 
		hp->ri = hp->wi; 
		for (i=0; i<NB; i++) 
			if(hp->inb[i]){ 
				freeb(hp->inb[i]); 
				hp->inb[i] = 0; 
			} 
		DPRINT("hifirecven %d: flushed\n", hp-hifichan); 
	} 
	qunlock(hp); 
} 
                 
static void 
hifikproc(void *arg) 
{ 
	Hifichan *hp = arg; 
	Block *bp; 
	int i; 
Top: 
	if(waserror()){ 
		print("hifikproc: error\n"); 
		goto Top; 
	} 
	for(;;){ 
		qlock(hp); 
		while(hp->ri != hp->wi){ 
1992/0701    
			if(hp->rq){ 
				FLOWCTL(hp->rq, hp->inb[hp->ri]); 
			}else 
1992/0609    
				freeb(hp->inb[hp->ri]); 
			if(hp->renable) 
				hp->inb[hp->ri] = allocb(BSIZE); 
			else 
				hp->inb[hp->ri] = 0; 
			hp->ri = NEXT(hp->ri); 
		} 
		if(hp->hangup){ 
			hp->hangup = 0; 
			if(hp->rq){ 
				bp = allocb(0); 
				bp->type = M_HANGUP; 
				PUTNEXT(hp->rq, bp); 
			} 
		} 
		i = 0; 
		while(hp->so != hp->ro){ 
			freeb(hp->outb[hp->so]); 
			hp->so = NEXT(hp->so); 
			i++; 
		} 
		qunlock(hp); 
		if(i) 
			wakeup(&hp->tr); 
		sleep(&hp->kr, kRun, hp); 
	} 
} 
                 
static void 
devinit(int h) 
{ 
	Hifichan *hp = &hifichan[h]; 
	Hifi *hifi = (h&1) ? hifi1 : hifi0; 
	Isdn *ip = &isdndev[h>>1]; 
                 
	isdnlock(ip); 
                 
	hp->udev = ip; 
	hp->hdev = hifi; 
	hp->imask = (h&1) ? Hint1 : Hint0; 
                 
	hp->opreg = 0; 
	SET(hifi->opreg, Rres|Tres);	/* master reset */ 
	SET(hifi->config, Fsen);	/* frame sync enable */ 
	hp->tctl = 30; 
	SET(hifi->tctl, hp->tctl);	/* transmitter interrupt level */ 
	SET(hifi->rctl, 20);		/* receiver interrupt level */ 
	SET(hifi->bofctl, Clkxi);	/* transmit in rising edge of CLKX */ 
	/* SET(hifi->tofctl, Dxi);	/* transmit inverted data */ 
	SET(hifi->tofctl, 0);		/* transmit normal data */ 
	SET(hifi->rof_tm, Dri);		/* receive inverted data */ 
	SET(hifi->config, Fsen|Alt);	/* alternate reg's... */ 
	SET(hifi->rof_tm, Trans);	/* transparent mode */ 
	SET(hifi->config, Fsen);	/* normal reg's... */ 
	SET(hifi->tmask, 0xff);		/* transmit all bits */ 
	SET(hifi->imask, Undie|Tdie|Teie|Rfie|Reofie); /* interrupt enables */ 
                 
	isdnunlock(ip); 
} 
                 
static void 
hifiloopctl(Hifichan *hp, int loop) 
{ 
	Isdn *ip = hp->udev; 
	Hifi *hifi = hp->hdev; 
                 
	DPRINT("hifiloopctl %d: %d\n", hp-hifichan, loop); 
	isdnlock(ip); 
	if(loop) 
		SET(hifi->opreg, hp->opreg |= Lloop); 
	else 
		SET(hifi->opreg, hp->opreg &= ~Lloop); 
	isdnunlock(ip); 
} 
                 
static int 
hifiintr(void) 
{ 
	Isdn *ip; 
	Hifichan *hp; 
	Hifi *hifi; 
1992/0711    
	int intr = 0, status, wake = 0, w = 0; 
1992/0609    
                 
	for(hp=hifichan; hp<hifichanN; hp++){ 
		if(!(ip = hp->udev))	/* assign = */ 
			continue; 
		if (!(*(ip->asr)&hp->imask)) 
			continue; 
		++intr; 
		hifi = hp->hdev; 
		status = GET(hifi->istat); 
		if(status&(Rf|Reof)){ 
			status &= ~(Rf|Reof); 
			wake += hifirecv(hp); 
		} 
		if(status&Te){ 
			status &= ~Te; 
			wake += w = hifixmit(hp); 
		} 
		if(status&Undabt){ 
			status &= ~Undabt; 
			DPRINT("hifiintr: hdlc %d under run\n", hp-hifichan); 
			++hp->underrun; 
		} 
		if(status&Tdone){ 
			status &= ~Tdone; 
			hp->wactive = 0; 
			if(!hp->hdlc && (w || hp->out || hp->ro != hp->wo)){ 
				DPRINT("hifiintr: trans %d under run\n", 
					hp-hifichan); 
				++hp->underrun; 
			}else if(!hp->hdlc || !hp->rq){ 
				DPRINT("hifiintr: xmtr %d done\n", hp-hifichan); 
				hifixmitdis(hp, 0); 
				++wake; 
				wakeup(&hp->cr); 
			} 
		} 
		if(wake) 
			wakeup(&hp->kr); 
		if(status) 
			DPRINT("hifiintr: status %d 0x%2.2x\n", 
				status, hp-hifichan); 
	} 
	return intr; 
} 
                 
static int 
hifirecv(Hifichan *hp) 
{ 
	Isdn *ip = hp->udev; 
	Hifi *hifi = hp->hdev; 
	Block *bp = hp->inb[hp->wi]; 
	uchar *p; 
	int status, i, n, m, wake = 0; 
Loop: 
	status = GET(hifi->rstat); 
	if(status == 0) 
		return wake; 
	n = status&0x7f; 
	p = bp->wptr; 
	m = bp->lim - p; 
	if(hp->hdlc){ 
		if(n > m){ 
			hp->toolong++; 
			bp->wptr = bp->base; 
1992/0701    
			bp->rptr = bp->base; 
1992/0609    
			SET(hifi->opreg, hp->opreg | Rres); 
			return wake; 
		} 
		hp->inchars += n; 
		SETADDR(&hifi->data); 
		while(--n >= 0) 
			*p++ = *(ip->data); 
		if(status&Eof){ 
			if(*--p == 0){ 
				i = NEXT(hp->wi); 
				if(i == hp->ri) 
					hp->overflow++; 
				else{ 
					bp->wptr = p; 
					bp->flags |= S_DELIM; 
					hp->wi = i; 
					bp = hp->inb[i]; 
					++wake; 
				} 
			}else{ 
				if(*p & 0x80) 
					hp->badcrc++; 
				if(*p & 0x40) 
					hp->abort++; 
				if(*p & 0x20) 
					hp->overrun++; 
				if(*p & 0x10) 
					hp->badcount++; 
			} 
			bp->wptr = bp->base; 
1992/0701    
			bp->rptr = bp->base; 
1992/0609    
		}else 
			bp->wptr = p; 
	}else{ 
		if(n > m) 
			n = m; 
		hp->inchars += n; 
		SETADDR(&hifi->data); 
		while(--n >= 0) 
			*p++ = *(ip->data); 
		bp->wptr = p; 
		if(p >= bp->lim){ 
			i = NEXT(hp->wi); 
			if(i == hp->ri){ 
				bp->wptr = bp->base; 
1992/0701    
				bp->rptr = bp->base; 
1992/0609    
				return wake; 
			}else{ 
				bp->flags |= S_DELIM; 
				hp->wi = i; 
				bp = hp->inb[i]; 
				++wake; 
			} 
		} 
	} 
	goto Loop; 
} 
                 
static int 
hifixmit(Hifichan *hp) 
{ 
	Isdn *ip = hp->udev; 
	Hifi *hifi = hp->hdev; 
	Block *bp; 
	uchar *p; 
	int n, k, wake = 0; 
                 
Loop: 
	n = GET(hifi->tstat)&0x7f; 
	if(n == 0) 
		return wake; 
	if(!(bp = hp->out)){	/* assign = */ 
		if(hp->ro == hp->wo){ 
			DPRINT("hifixmit %d: [%d] empty\n", 
1992/1204    
				hp-hifichan, TK2MS(MACHP(0)->ticks)); 
1992/0609    
			return wake; 
		} 
		hp->out = bp = hp->outb[hp->ro]; 
	} 
	p = bp->rptr; 
	k = bp->wptr - p; 
	if (n > k) 
		n = k; 
	hp->outchars += n; 
	SETADDR(&hifi->data); 
	if(hp->hdlc){ 
		while(--n >= 0) 
			*(ip->data) = *p++; 
	}else{ 
		while(--n >= 0) 
			*(ip->data) = ~*p++; 
	} 
	bp->rptr = p; 
	hp->wactive = 1; 
	if(!hp->wenable) 
		hifixmiten(hp, 0); 
	if(bp->rptr == bp->wptr){ 
		if(hp->hdlc && (bp->flags & S_DELIM)) 
			SET(hifi->tctl, hp->tctl|Tfc); 
		if(!(hp->out = bp = bp->next)){	/* assign = */ 
			hp->ro = NEXT(hp->ro); 
			++wake; 
		} 
	} 
	goto Loop; 
} 
                 
static void 
hifixmiten(Hifichan *hp, int dolock) 
{ 
	Isdn *ip = hp->udev; 
	Hifi *hifi = hp->hdev; 
                 
	DPRINT("hifixmiten %d: %s\n", hp-hifichan, hp->hdlc?"hdlc":"trans"); 
	if(dolock) 
		isdnlock(ip); 
	if(hp->hdlc){ 
		SET(hifi->tofctl, Dxi|Tlbit);	/* xmit ~data, lsb first */ 
		SET(hifi->rof_tm, Dri|Rlbit);	/* rcv ~data, lsb first */ 
		SET(hifi->config, Fsen|Alt);	/* alternate reg's... */ 
		SET(hifi->rof_tm, 0);		/* hdlc mode */ 
		SET(hifi->config, Fsen|Flags);	/* normal reg's, send flags */ 
	}else{ 
		SET(hifi->tofctl, 0);		/* xmit data, msb first */ 
		SET(hifi->rof_tm, Dri);		/* rcv ~data, msb first */ 
		SET(hifi->config, Fsen|Alt);	/* alternate reg's... */ 
		SET(hifi->rof_tm, Trans);	/* transparent mode */ 
		SET(hifi->config, Fsen);	/* normal reg's, send ones */ 
	} 
	hp->wenable = 1; 
	if(hp->hdev == hifi0){ 
		ip->venval &= ~DXCODEC; 
		if(hp->hdlc) 
			ip->venval &= ~DRCODEC; 
	}else if(hp->hdlc) 
		SET(hifi->config, Flags);	/* no fs on chan. 2 */ 
	SET(hifi->ttsctl, Dxac); 
	SET(hifi->opreg, hp->opreg |= Ent); 
	if(dolock) 
		isdnunlock(ip); 
} 
                 
static void 
hifixmitdis(Hifichan *hp, int dolock) 
{ 
	Isdn *ip = hp->udev; 
	Hifi *hifi = hp->hdev; 
                 
	DPRINT("hifixmitdis %d\n", hp-hifichan); 
	if(dolock) 
		isdnlock(ip); 
	SET(hifi->ttsctl, 0); 
	if(hp->hdev == hifi0){ 
		ip->venval |= DXCODEC; 
		if(hp->hdlc) 
			ip->venval |= DRCODEC; 
	} 
	SET(hifi->opreg, hp->opreg &= ~Ent); 
	hp->out = 0; 
	hp->ro = hp->wo; 
	hp->wenable = 0; 
	/*SET(hifi->opreg, hp->opreg | Tres);*/ 
	if(dolock) 
		isdnunlock(ip); 
} 


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