#ident "$Header: stream.c 1.19 89/08/07 $"

/*
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*
 * $Log:	stream.c,v $
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

/*
 * This file contains code for the crash functions:  stream, queue, mblock,
 * mbfree, dblock, dbfree, strstat, linkblk, dballoc, qrun.
 */


#include "crash.h"

#include <sys/types.h>
#include <sys/param.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <sys/map.h>
#include <sys/dir.h>
#include <sys/resource.h>
#include <signal.h>
#include <sys/user.h>
#include <sys/timer.h>
#include <sys/proc.h>

#define	INKERNEL
#include <sys/var.h>
#include <sys/sysmacros.h>
#include <sys/poll.h>
#include <sys/session.h>
#include <sys/stream.h>
#include <sys/strstat.h>
#include <sys/stropts.h>
#include <setjmp.h>

#include "a.out.h"
#include "stdio.h"
#include <sys/conf.h>
#define NARGS 25		/* number of arguments to one function */


static struct sym *Queue, *Streams, *Mblock, *Dblock, *Qhead,
	*Mbfree, *Dbfree, *Nmblock, *Ndblock, *Linkblk, 
	*Nmuxlink, *Dballoc, *Strst, *Svcqs, *Svcruns;
static int _ndblock;	
static int _nmblock;	
static long _queue;
static long _streams;
static long _mblock;
static long _dblock;
static long _linkblk;
struct var vbuf;	/* contains v.v_* structure */
char *args[NARGS];	/* argument array */
int argcnt;		/* argument count */

extern jmp_buf jmp;	/* syntax error label */
extern int optind;	/* argument index */
extern char *optarg;	/* getopt argument */
extern struct sym *symsrch();
extern long getargs1();



/* initialization for namelist symbols */
stream_init()
{
	if(!(Queue = symsrch("queue")))
		error("queue not found in symbol table\n");
	readv(Queue->sym_value, &_queue, sizeof _queue);
	if(!(Streams = symsrch("streams")))
		error("streams not found in symbol table\n");
	readv(Streams->sym_value, &_streams, sizeof _streams);
	if(!(Mblock = symsrch("mblock")))
		error("mblock not found in symbol table\n");
	readv(Mblock->sym_value, &_mblock, sizeof _mblock);
	if(!(Dblock = symsrch("dblock")))
		error("dblock not found in symbol table\n");
	readv(Dblock->sym_value, &_dblock, sizeof _dblock);
	if(!(Qhead = symsrch("qhead")))
		error("qhead not found in symbol table\n");
	if(!(Mbfree = symsrch("mbfreelist")))
		error("mbfreelist not found in symbol table\n");
	if(!(Dbfree = symsrch("dbfreelist")))
		error("dbfreelist not found in symbol table\n");
	if(!(Nmblock = symsrch("nmblock")))
		error("nmblock not found in symbol table\n");
	readv(Nmblock->sym_value, &_nmblock, sizeof _nmblock);
	if(!(Ndblock = symsrch("ndblock")))
		error("ndblock not found in symbol table\n");
	readv(Ndblock->sym_value, &_ndblock, sizeof _ndblock);
	if(!(Linkblk = symsrch("linkblk")))
		error("linkblk not found in symbol table\n");
	readv(Linkblk->sym_value, &_linkblk, sizeof _linkblk);
	if(!(Nmuxlink = symsrch("nmuxlink")))
		error("nmuxlink not found in symbol table\n");
	if(!(Dballoc = symsrch("dballoc")))
		error("dballoc not found in symbol table\n");
	if(!(Strst = symsrch("strst")))
		error("strst not found in symbol table\n");
	if(!(Svcqs = symsrch("svcqs")))
		error("svcqs not found in symbol table\n");
	if(!(Svcruns = symsrch("svcruns")))
		error("svcruns not found in symbol table\n");
	readv(search("v"), &vbuf, sizeof vbuf);
}

/* get arguments for stream function */
int
getstream()
{
	int slot = -1;
	int full = 0;
	int all = 0;
	int phys = 0;
	long addr = -1;
	long arg1 = -1;
	long arg2 = -1;
	int c;
	char *heading = "SLOT  WRQ IOCB  PGRP    IOCID   IOCWT WOFF ERR FLAG\n";

	fixup_args();
	while((c = getopt(argcnt,args,"ef")) !=EOF) {
		switch(c) {
			case 'e' :	all = 1;
					break;
			case 'f' :	full = 1;
					break;
			default  :	longjmp(jmp,0);
		}
	}
	printf("STREAM TABLE SIZE = %d\n",vbuf.v_nstream);
	if(!full)
		printf("%s",heading);
	if(args[optind]) {
		all = 1;
		do {
			getargs1(vbuf.v_nstream,&arg1,&arg2);
			if(arg1 == -1) 
				continue;
			if(arg2 != -1)
				for(slot = arg1; slot <= arg2; slot++)
					prstream(all,full,slot,phys,addr,
						heading);
			else {
				if(arg1 < vbuf.v_nstream)
					slot = arg1;
				else addr = arg1;
				prstream(all,full,slot,phys,addr,heading);
			}
			slot = addr = arg1 = arg2 = -1;
		} while(args[++optind]);
	} else {
		for (slot = 0; slot < vbuf.v_nstream; slot++) {
			prstream(all,full,slot,phys,addr,heading);
		}
	}
}


/* print streams table */
int
prstream(all,full,slot,phys,addr,heading)
int all,full,slot,phys;
long addr;
char *heading;
{
	struct stdata strm;
	struct strevent evbuf;
	struct strevent *next;
	queue_t que;
	int ioc_slot; 

	if (addr > -1) {
		readv(addr, (char *)&strm, sizeof strm);
		slot = getslot(addr,_streams,sizeof strm,phys, vbuf.v_nstream);
	} else {
		readv((_streams+slot*sizeof strm), (char *)&strm, sizeof strm);
	}
	if (!(strm.sd_flag & STRINUSE) && !all) 
		return;
	if(full)
		printf("%s",heading);
	if(slot == -1)
		printf("  -  ");
	else 
		printf("%4d ",slot);
	printf("%4d ",((long)strm.sd_wrq - _queue)/sizeof(struct queue));
	ioc_slot = ((long)strm.sd_iocblk - _mblock)/(sizeof(struct msgb));
	if ((ioc_slot>=0) && (ioc_slot<_nmblock))
		printf("%4d ",ioc_slot);
	else
		printf("   - ");

	printf("%5d %10d %5d %4d %3o ", strm.sd_ctty.c_pgrp, strm.sd_iocid,
		strm.sd_iocwait, strm.sd_wroff, strm.sd_error);
	printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
		((strm.sd_flag & STRINUSE) ? "strinuse " : ""),
		((strm.sd_flag & IOCWAIT) ? "iocwait " : ""),
		((strm.sd_flag & RSLEEP) ? "rsleep " : ""),
		((strm.sd_flag & WSLEEP) ? "wsleep " : ""),
		((strm.sd_flag & STRPRI) ? "strpri " : ""),
		((strm.sd_flag & STRHUP) ? "strhup " : ""),
		((strm.sd_flag & STWOPEN) ? "stwopen " : ""),
		((strm.sd_flag & STPLEX) ? "stplex " : ""),
		((strm.sd_flag & CTTYFLG) ? "cttyflg " : ""),
		((strm.sd_flag & RMSGDIS) ? "rmsgdis " : ""),
		((strm.sd_flag & RMSGNODIS) ? "rmsgnodis " : ""),
		((strm.sd_flag & STRERR) ? "strerr " : ""),
		((strm.sd_flag & STRTIME) ? "strtime " : ""),
		((strm.sd_flag & STR2TIME) ? "str2time " : ""),
		((strm.sd_flag & STR3TIME) ? "str3time " : ""),
		((strm.sd_flag & STRVTIME) ? "strvtime " : ""),
		((strm.sd_flag & TTYVMODE) ? "ttyvmode " : ""),
		((strm.sd_flag & FLUSHWAIT) ? "flushwait " : ""));

	if(full) {
		printf("\t ADDR= %x LOCK= %x DEVNO= %x REFCNT= %x STRTAB= %x PUSHCNT= %x\n", 
		       (long)(_streams+slot*sizeof strm), strm.sd_mutex, 
		       strm.sd_rdev, strm.sd_refcnt, strm.sd_strtab, strm.sd_pushcnt);
		if (strm.sd_flag & TTYVMODE) {
			printf("\t VMIN= %x VTIME= %x\n", (int)strm.sd_vmin, (int)strm.sd_vtime);
		}
		printf("\tSIGFLAGS:  %s%s%s%s\n",
			((strm.sd_sigflags & S_INPUT) ? " input" : ""),
			((strm.sd_sigflags & S_HIPRI) ? " hipri" : ""),
			((strm.sd_sigflags & S_OUTPUT) ? " output" : ""),
			((strm.sd_sigflags & S_MSG) ? " msg" : ""));
		printf("\tSIGLIST:\n");
		next = strm.sd_siglist;
		while(next) {
			readv(next,(char *)&evbuf, sizeof evbuf);
			printf("\t\tPROC:  %3x   %s%s%s%s\n",
				((long)evbuf.se_procp),
				((evbuf.se_events & S_INPUT) ? " input" : ""),
				((evbuf.se_events & S_HIPRI) ? " hipri" : ""),
				((evbuf.se_events & S_OUTPUT) ? " output" : ""),
				((evbuf.se_events & S_MSG) ? " msg" : ""));
			next = evbuf.se_next;	
		}
		printf("\tPOLLFLAGS:  %s%s%s\n",
			((strm.sd_pollflags & POLLIN) ? " in" : ""),
			((strm.sd_pollflags & POLLPRI) ? " pri" : ""),
			((strm.sd_pollflags & POLLOUT) ? " out" : ""));
		printf("\tPOLLIST:\n");
		next = strm.sd_pollist;
		while(next) {
			readv(next,(char *)&evbuf, sizeof evbuf);
			printf("\t\tPROC:  %3x   %s%s%s\n",
				((long)evbuf.se_procp),
				((evbuf.se_events & POLLIN) ? " in" : ""),
				((evbuf.se_events & POLLPRI) ? " pri" : ""),
				((evbuf.se_events & POLLOUT) ? " out" : ""));
			next = evbuf.se_next;	
		}
		printf("\n");
		/* print all the attached queues also */
		printf("SLOT   QADDR  NEXT LINK   QPTR    CNT  HEAD TAIL MINP MAXP  HWM  LWM  PUTCNT\n");
		addr = (long)strm.sd_wrq;
		while (addr) {
			slot = (addr - _queue)/sizeof(struct queue);
			prqueue(all,slot-1,-1,-1);	/* read q */
			prqueue(all,slot,-1,-1);	/* write q */
			readv(addr, (char *)&que, sizeof que);
			addr = (long)que.q_next;
		}
	}
}

/* get arguments for queue function */
int
getqueue()
{
	int slot = -1;
	int all = 0;
	int phys = 0;
	long addr = -1;
	long arg1 = -1;
	long arg2 = -1;
	int c;

	fixup_args();
	while((c = getopt(argcnt,args,"e")) !=EOF) {
		switch(c) {
			case 'e' :	all = 1;
					break;
			default  :	longjmp(jmp,0);
		}
	}
	printf("QUEUE TABLE SIZE = %d\n",vbuf.v_nqueue);
	printf("SLOT   QADDR  NEXT LINK   QPTR    CNT  HEAD TAIL MINP MAXP  HWM  LWM  PUTCNT\n");
	if(args[optind]) {
		all = 1;
		do {
			getargs1(vbuf.v_nqueue,&arg1,&arg2);
			if(arg1 == -1) 
				continue;
			if(arg2 != -1)
				for(slot = arg1; slot <= arg2; slot++)
					prqueue(all,slot,phys,addr);
			else {
				if(arg1 < vbuf.v_nqueue)
					slot = arg1;
				else addr = arg1;
				prqueue(all,slot,phys,addr);
			}
			slot = addr = arg1 = arg2 = -1;
		}while(args[++optind]);
	}
	else for(slot = 0; slot < vbuf.v_nqueue; slot++)
		prqueue(all,slot,phys,addr);
}

/* print queue table */
int
prqueue(all,slot,phys,addr)
int all,slot,phys;
long addr;
{
	queue_t que;
	mblk_t *m;
	mblk_t mblk;
	int qn, ql;
	struct qinit qinfo;
	struct module_info minfo;
	char mi_idname[8];

	if(addr > -1) {
		slot = getslot(addr,_queue,sizeof que,phys,
			       vbuf.v_nqueue);
		readv(addr, (char *)&que, sizeof que);
	} else {
		readv(_queue+slot*(sizeof que), (char *)&que, sizeof que);
	}
	if (!(que.q_flag & QUSE) && !all)
		return;
	readv(que.q_qinfo, (char *)&qinfo, sizeof qinfo);
	readv(qinfo.qi_minfo, (char *)&minfo, sizeof minfo);
	readv(minfo.mi_idname, mi_idname, 8);
	if(slot == -1)
		printf("  -  ");
        else printf("%4d ",slot);
	printf("%7x ", _queue+slot*(sizeof que));
	qn = ((long)que.q_next - _queue)/(sizeof(struct queue));
	ql = ((long)que.q_linkr - _queue)/(sizeof(struct queue));
	if ((qn >= 0) && (qn < vbuf.v_nqueue))
		printf("%4d ",qn);
	else printf("   - ");
	if ((ql >= 0) && (ql < vbuf.v_nqueue))
		printf("%4d ",ql);
	else printf("   - ");
	printf("%7x ",que.q_ptr);
	printf(" %4d ",que.q_count);
	m = que.q_first;
	if (m)
		printf("%4d ", getslot((long)m,_mblock,sizeof mblk,0,_nmblock));
	else 
		printf("   - ");
	m = que.q_last;
	if (m)
		printf("%4d ", getslot((long)m,_mblock,sizeof mblk,0,_nmblock));
	else
		printf("   - ");
	printf("%4d %4d %4d %4d %2d\n",
		que.q_minpsz,
		que.q_maxpsz,
		que.q_hiwat,
		que.q_lowat,
	        que.q_putcnt);
	printf("%s %s ", mi_idname, ((que.q_flag & QREADR) ? "RDq " : "WRq "));
	printf("flags= %s%s%s%s%s%s%s%s%s%s\n",
		((que.q_flag & QUSE) ? "quse " : "invalid "),
		((que.q_svcflag & QENAB) ? "qenab " : ""),
		((que.q_svcflag & QSVCBUSY) ? "qsvcbusy " : ""),
		((que.q_flag & QWANTR) ? "qwantr " : ""),
		((que.q_flag & QWANTW) ? "qwantw " : ""),
		((que.q_flag & QFULL) ? "qfull " : ""),
		((que.q_flag & QFREEZE) ? "qfreeze " : ""),
		((que.q_flag & QTOENAB) ? "qtoenab " : ""),
		((que.q_flag & QPROCENAB) ? "qprocenab " : ""),
		((que.q_flag & QNOENB) ? "qnoenab " : ""));
}

/* get arguments for mblock function */
int
getmess()
{
	int slot = -1;
	int all = 0;
	int phys = 0;
	long addr = -1;
	long arg1 = -1;
	long arg2 = -1;
	int c;

	fixup_args();
	while((c = getopt(argcnt,args,"e")) !=EOF) {
		switch(c) {
			case 'e' :	all = 1;
					break;
			default  :	longjmp(jmp,0);
		}
	}
	printf("MESSAGE BLOCK TABLE SIZE = %d\n",_nmblock);
	printf("SLOT NEXT CONT PREV   RPTR     WPTR   DATAB\n");
	if(args[optind]) {
		all = 1;
		do {
			getargs1(_nmblock,&arg1,&arg2);
			if(arg1 == -1) 
				continue;
			if(arg2 != -1)
				for(slot = arg1; slot <= arg2; slot++)
					prmess(all,slot,phys,addr);
			else {
				if(arg1 < _nmblock)
					slot = arg1;
				else addr = arg1;
				prmess(all,slot,phys,addr);
			}
			slot = addr = arg1 = arg2 = -1;
		}while(args[++optind]);
	}
	else for(slot = 0; slot < _nmblock; slot++)
		prmess(all,slot,phys,addr);
}

/* print mblock table */
int
prmess(all,slot,phys,addr)
int all,slot,phys;
long addr;
{
	mblk_t mblk;
	int mnext, mcont, datab, mprev;

	if(addr > -1) {
		slot = getslot(addr,_mblock,sizeof mblk,phys,_nmblock);
		readv(addr, (char *)&mblk, sizeof mblk);
	} else {
		readv(_mblock+slot*(sizeof mblk), (char *)&mblk, sizeof mblk);
	}
	if (!mblk.b_datap && !all) 
		return(-1);
	if(slot == -1)
		printf("  -  ");
	else printf("%4d ",slot);
	mnext = ((long)mblk.b_next - _mblock)/sizeof(struct msgb);
	mcont = ((long)mblk.b_cont - _mblock)/sizeof(struct msgb);
	mprev = ((long)mblk.b_prev - _mblock)/sizeof(struct msgb);
	datab = ((long)mblk.b_datap - _dblock)/sizeof(struct datab);
	if ((mnext >= 0) && (mnext < _nmblock))
		printf("%4d ",mnext);
	else printf("   - ");
	if ((mcont >= 0) && (mcont < _nmblock))
		printf("%4d ",mcont);
	else printf("   - ");
	if ((mprev >= 0) && (mprev < _nmblock))
		printf("%4d ",mprev);
	else printf("   - ");
	printf("%8x %8x ",
		mblk.b_rptr,
		mblk.b_wptr);
	if ((datab >= 0) && (datab < _ndblock))
		printf("%4d\n",datab);
	else printf("   -\n");
	return(mnext);
}

/* get arguments for mbfree function */
int
getmbfree()
{
	int c;

	printf("SLOT NEXT CONT PREV   RPTR     WPTR   DATAB\n");
	prmbfree();
}

/* print mblock free list */
int
prmbfree()
{
	mblk_t *m;
	int  mnext;

	readv(Mbfree->sym_value, (char *)&m, sizeof m);
	mnext = ((long)m - _mblock)/sizeof(struct msgb);
	while ((mnext >=0) && (mnext < _nmblock))
		mnext = prmess(1,mnext,0,-1);
}


/* get arguments for dblock function */
int
getdblk()
{
	int slot = -1;
	int all = 0;
	int phys = 0;
	int class = 0;
	long addr = -1;
	long arg2 = -1;
	long arg1 = -1;
	int c;
	int klass;

	fixup_args();
	while((c = getopt(argcnt,args,"ec")) !=EOF) {
		switch(c) {
			case 'e' :	all = 1;
					break;
			case 'c' :	class = 1;
					break;
			default  :	longjmp(jmp,0);
		}
	}
	printf("DATA BLOCK TABLE SIZE = %d\n",_ndblock);
	printf("SLOT CLASS SIZE  RCNT   TYPE     BASE     LIMIT  FREEP		FUNC(ARG)\n");
	if(args[optind]) {
		if(class) 
			do {
				if((klass = (int)strcon(args[optind++],'d'))
					== -1)
					continue;
				prclass(klass);
			}while(args[optind]);
		else {
			all = 1;
			do {
				getargs1(_ndblock,&arg1,&arg2);
				if(arg1 == -1) 
					continue;
				if(arg2 != -1)
					for(slot = arg1; slot <= arg2; slot++)
						prdblk(all,slot,phys,addr);
				else {
					if(arg1 < _ndblock)
						slot = arg1;
					else addr = arg1;
					prdblk(all,slot,phys,addr);
				}
				slot = addr = arg1 = arg2 = -1;
			}while(args[++optind]);
		}
	}
	else for(slot = 0; slot < _ndblock; slot++)
		prdblk(all,slot,phys,addr);
}


/* print dblock table */
int
prdblk(all,slot,phys,addr)
int all,slot,phys;
long addr;
{
	dblk_t dblk;
	int dfree;
	static int lastcls;

	if(addr > -1) {
		slot = getslot(addr,_dblock,sizeof dblk,phys, _ndblock);
		readv(addr, (char *)&dblk, sizeof dblk);
	} else {
		readv(_dblock+slot*(sizeof dblk), (char *)&dblk, sizeof dblk);
	}
	if (!dblk.db_ref && !all)
		return(-1);
	if (dblk.db_class != lastcls) {
		printf("\n");
		lastcls=dblk.db_class;
	}
	if(slot == -1)
		printf("  - ");
	else printf("%4d",slot);
	printf(" %5d ",
		dblk.db_class);
	switch (dblk.db_class) {
		case 0: printf("   4 "); break;
		case 1: printf("  16 "); break;
		case 2: printf("  64 "); break;
		case 3: printf(" 128 "); break;
		case 4: printf(" 256 "); break;
		case 5: printf(" 512 "); break;
		case 6: printf("1024 "); break;
		case 7: printf("2048 "); break;
		case 8: printf("4096 "); break;
		case 9: printf("priv "); break;
		default: printf("   - ");
	}
	printf(" %4d ", dblk.db_ref); 
	switch (dblk.db_type) {
		case M_DATA: printf("data     "); break;
		case M_PROTO: printf("proto    "); break;
		case M_BREAK: printf("break    "); break;
		case M_PASSFP: printf("passfs   "); break;
		case M_SIG: printf("sig      "); break;
		case M_DELAY: printf("delay    "); break;
		case M_CTL: printf("ctl      "); break;
		case M_IOCTL: printf("ioctl    "); break;
		case M_SETOPTS: printf("setopts  "); break;
		case M_RSE: printf("rse  "); break;
		case M_IOCACK: printf("iocack   "); break;
		case M_IOCNAK: printf("iocnak   "); break;
		case M_PCPROTO: printf("pcproto  "); break;
		case M_PCSIG: printf("pcsig    "); break;
		case M_READ: printf("read    "); break;
		case M_FLUSH: printf("flush    "); break;
		case M_STOP: printf("stop     "); break;
		case M_START: printf("start    "); break;
		case M_HANGUP: printf("hangup   "); break;
		case M_ERROR: printf("error    "); break;
		case M_COPYIN: printf("copyin    "); break;
		case M_COPYOUT: printf("copyout    "); break;
		case M_IOCDATA: printf("iocdata    "); break;
		case M_PCRSE: printf("pcrse    "); break;
		case M_PCCTL: printf("pcctl    "); break;
		case M_PCIOCTL: printf("pcioctl  "); break;
		case M_PCSETOPTS: printf("pcsetopt "); break;
		default: printf("       - ");
	}
	printf("%8x %8x ",
		dblk.db_base,
		dblk.db_lim);
	dfree = ((long)dblk.db_freep - _dblock)/sizeof(struct datab);
	if ((dfree >= 0) && (dfree < _ndblock))
		printf(" %4d",dfree);
	else 
		printf("   -");
	if ((dblk.db_class == 9) || (dblk.db_arg > 0)) {
		/* private buffer type or debug colouring is on */
		printf("\t%s(0x%x)", addr_str((long)dblk.db_func), dblk.db_arg);
	}
	printf("\n");
	return(dfree);
}

/* get class for dblock */
int
prclass(class)
int class;
{
	int i,n, *p;
	int clasize[NCLASS+1];

	if ((class < 0) || (class > NCLASS))
		error("%d is out of range\n",class);
	p = &(vbuf.v_nblkpriv);
	for (i=NCLASS; i>=0; i--) clasize[i] = *p++;  /* load size of each block class */
	n=0;
	for (i=NCLASS; i>class; i--) n+=clasize[i];	/* compute slot of first block */
	for (i=0; i<clasize[class]; i++)
		prdblk(0,n++,0,-1);
}

/* get arguments for dbfree function */
int
getdbfree()
{
	int c;
	int class;
	int klass;

	fixup_args();
	printf("SLOT CLASS SIZE  RCNT   TYPE     BASE     LIMIT  FREEP\n");
	if(args[optind]) 
		do {
			if((klass = (int)strcon(args[optind++],'d')) == -1)
				continue;
			prdbfree(klass);
		} while(args[optind]);
	else for(class = 0; class <= NCLASS; class++)
		prdbfree(class);
}

/* print dblock free list */
int
prdbfree(class)
int class;
{
	dblk_t *d;
	int  dnext;

	if ((class < 0) || (class > NCLASS))
		error("%d is out of class range\n",class);
	readv(Dbfree->sym_value+class*(sizeof d), (char *)&d, sizeof d);
	dnext = ((long)d - _dblock)/sizeof(struct datab);
	while ((dnext >=0) && (dnext < _ndblock))
		dnext = prdblk(1,dnext,0,-1);
}

/* get arguments for qrun function */
int
getqrun()
{
	prqrun();
}

/* print qrun information */
int
prqrun()
{
	queue_t que, *q;
	int  ql;

	readv(Qhead->sym_value, (char *)&q, sizeof q);
	printf("Queue slots scheduled for service: ");
	while (q) {
		ql = ((long)q - _queue)/(sizeof(struct queue));
		printf("%4d ",ql);
		readv(q, (char *)&que, sizeof que);
		q = que.q_linkr;
	}
	printf("\n");
}


/* get arguments for strstat function */
int
getstrstat()
{
	optind = 1;
	prstrstat();
}

/* print stream statistics */
int
prstrstat()
{
	struct strstat strst;
	alcdat svcqs, svcruns;
	int dcc[NCLASS+1];
	int i, j, *p;

	p = &(vbuf.v_nblkpriv);
	for (i=NCLASS; i>=0; i--) dcc[i] = *p++;

	printf("ITEM                  CONFIG    ALLOC    FREE         TOTAL     MAX    FAIL\n");

	readv(Svcqs->sym_value, (char *)&svcqs, sizeof svcqs);
	readv(Svcruns->sym_value, (char *)&svcruns, sizeof svcruns);
	if (readv(Strst->sym_value, &strst, sizeof strst) != sizeof strst) 
		error("read error for strst\n");

	printf("streams                 %4d     %4d    %4d    %10d    %4d    %4d\n",
		vbuf.v_nstream, strst.stream.use, vbuf.v_nstream - strst.stream.use, strst.stream.total, strst.stream.max, strst.stream.fail);
	printf("queues                  %4d     %4d    %4d    %10d    %4d    %4d\n",
		vbuf.v_nqueue, strst.queue.use, vbuf.v_nqueue - strst.queue.use, strst.queue.total, strst.queue.max, strst.queue.fail);
	printf("message blocks          %4d     %4d    %4d    %10d    %4d    %4d\n",
		_nmblock, strst.mblock.use, _nmblock - strst.mblock.use, strst.mblock.total, strst.mblock.max, strst.mblock.fail);
	printf("data block totals       %4d     %4d    %4d    %10d    %4d    %4d\n",
		_ndblock, strst.dblock.use, _ndblock - strst.dblock.use, strst.dblock.total, strst.dblock.max, strst.dblock.fail);
	for (i=0; i<=NCLASS; i++) 
		{
		printf("data block size ");
		switch (i) {
			case 0: printf("   4  "); break;
			case 1: printf("  16  "); break;
			case 2: printf("  64  "); break;
			case 3: printf(" 128  "); break;
			case 4: printf(" 256  "); break;
			case 5: printf(" 512  "); break;
			case 6: printf("1024  "); break;
			case 7: printf("2048  "); break;
			case 8: printf("4096  "); break;
			case 9: printf("priv  "); break;
			default: printf("   -  ");
			}
		printf("  %4d     %4d    %4d    %10d    %4d    %4d\n",
			dcc[i], strst.dblk[i].use, dcc[i]-strst.dblk[i].use, strst.dblk[i].total, strst.dblk[i].max, strst.dblk[i].fail); 
		}
	printf("ITEM                  IN-USE        TOTAL        HWM\n");
	printf("scheduled queues      %d           %d          %d\n",
		svcqs.use, svcqs.total, svcqs.max); 
	printf("running queues        %d           %d          %d\n",
		svcruns.use, svcruns.total, svcruns.max); 
}


/* get arguments for linkblk function */
int
getlinkblk()
{
	int c;
	int slot = -1;
	int all = 0;
	int phys = 0;
	long addr = -1;
	long arg2 = -1;
	long arg1 = -1;
	int nmuxlink;

	fixup_args();
	while((c = getopt(argcnt,args,"e")) !=EOF) {
		switch(c) {
			case 'e' :	all = 1;
					break;
			default  :	longjmp(jmp,0);
		}
	}
	readv(Nmuxlink->sym_value,(char *)&nmuxlink, sizeof nmuxlink);
	printf("LINKBLK TABLE SIZE = %d\n",nmuxlink);
	printf("SLOT   QTOP     QBOT   INDEX\n");
	if(args[optind]) {
		all = 1;
		do {
			getargs1(nmuxlink,&arg1,&arg2);
			if(arg1 == -1) 
				continue;
			if(arg2 != -1)
				for(slot = arg1; slot <= arg2; slot++)
					prlinkblk(all,slot,phys,addr,nmuxlink);
			else {
				if(arg1 < nmuxlink)
					slot = arg1;
				else addr = arg1;
				prlinkblk(all,slot,phys,addr,nmuxlink);
			}
			slot = addr = arg1 = arg2 = -1;
		}while(args[++optind]);
	}
	else for(slot = 0; slot < nmuxlink; slot++)
		prlinkblk(all,slot,phys,addr,nmuxlink);	
}

/* print linkblk table */
int
prlinkblk(all,slot,phys,addr,max)
int all,slot,phys,max;
long addr;
{
	struct linkblk linkbuf;

	if(addr > -1) {
		slot = getslot(addr,_linkblk,sizeof linkbuf,phys, max);
		readv(addr, (char *)&linkbuf, sizeof linkbuf);
	} else {
		readv(_linkblk+slot*(sizeof linkbuf), (char *)&linkbuf,sizeof linkbuf);
	}
	if(!linkbuf.l_qtop && !all)
		return;
	if(slot == -1)
		printf("  - ");
	else printf("%4d", slot);
		slot = ((long)linkbuf.l_qtop-_queue)/ sizeof(struct queue);
		if((slot >= 0) && (slot < vbuf.v_nqueue))
			printf("    %5d",slot);
		else printf(" %8x",linkbuf.l_qtop);
		slot = ((long)linkbuf.l_qbot-_queue)/ sizeof(struct queue);
		if((slot >= 0) && (slot < vbuf.v_nqueue))
			printf("    %5d",slot);
		else printf(" %8x",linkbuf.l_qbot);
		printf("   %3d\n",linkbuf.l_index);
}


/* get arguments for dballoc function */
int
getdballoc()
{
	int c,class;

	fixup_args();
	if(args[optind]) {
		do {
			if((class = strcon(args[optind++],'d')) == -1)
				continue;
			if((class >= 0) && (class <= NCLASS))
				prdballoc(class);
			else {
				printf("%d is out of class range\n",
					class);
				continue;
			}
		} while(args[optind]);
	}
	else for(class = 0; class <= NCLASS; class++)
		prdballoc(class);
}

/* print dballoc table */
int
prdballoc(class)
int class;
{
	struct dbalcst dbalbuf;
	struct strevent *next;
	struct strevent *prfuncname();

	readv(Dballoc->sym_value+class*(sizeof dbalbuf), (char *)&dbalbuf, sizeof dbalbuf);
	printf("CLASS   RCNT    LO   MED\n");
	printf("  %d    %5d %5d %5d\n",
		class,
		dbalbuf.dba_cnt,
		dbalbuf.dba_lo,
		dbalbuf.dba_med);
	printf("\tLOP:\n");
	next = dbalbuf.dba_lop;
	while (next) {
		next = prfuncname(next);
	}
	printf("\tMEDP:\n");
	next = dbalbuf.dba_medp;
	while (next) {
		next = prfuncname(next);
	}
	printf("\tHIP:\n");
	next = dbalbuf.dba_hip;
	while (next) {
		next = prfuncname(next);
	}
}

/* print function name for dballoc and return next addr */

struct strevent *
prfuncname(addr)
long(addr);
{
	struct strevent evbuf;
	
	readv(addr, (char *)&evbuf, sizeof evbuf);
	printf("\t\t%s", addr_str(evbuf.se_func));
	printf("(0x%x)\n",evbuf.se_arg);
	return(evbuf.se_next);
}


