|
|
Power 6/32 Unix version 1.2b
/* D.L.Buck and Associates, Inc. - 8/27/84
*
* COPYRIGHT NOTICE:
* Copyright c 8/27/84 - An unpublished work by
* D.L.Buck and Associates, Inc.
*
* PROPRIETARY RIGHTS NOTICE:
* All rights reserved. This document and program contains
* proprietary information of D.L.Buck and Associates,Inc.
* of San Jose, California, U.S.A., embodying confidential
* information, ideas, and expressions, no part of which
* may be reproduced, or transmitted in any form or by any
* means, electronic, mechanical, or otherwise, without
* the written permission of D.L.Buck and Associates, Inc.
*
* NAME
* bsctr - BISYNC TRACE Driver
*
* DESCRIPTION
* This trace module represents a pseudo-device to Unix. It has
* the usual open, close, read, and ioctl routines for a read-only
* device. As well, it has a trace event logging routine which is
* called from the other portions of the bisync driver to log state
* changes, received information, transmitted information, and errors.
* Trace events are stored in a trace buffer until read by a user-level
* routine.
*/
#ifndef lint
static char bsctr_c[] = "@(#)bsctr.c 1.7 REL";
#endif
#include "../bsc/local.h"
#include "../bsc/bscio.h"
#include "../bsc/bsc.h"
#include "../bsc/bsctr.h"
#if defined BSD42
#define ERRRET(x) return x
#define UCOUNT uio->uio_resid
#else
#define ERRRET(x) u.u_error = x; return
#define UCOUNT u.u_count
#endif
#define SIZEMASK 0x03ff
extern struct bsc bsc[]; /* device information */
char bsctbuf[TBUFSIZE]; /* circular trace buffer */
char *bsctbin, *bsctbout; /* ptrs to next write, read locations */
char *lastpkt; /* pts to len field of last pkt if 'y' */
char bscbw; /* someone's waiting on the trace buffer */
unsigned char bsclost; /* number of lost trace events */
int bsctlock = -1; /* Trace lock */
#if defined BSD42
extern struct timeval time;
#define TRTIME time.tv_sec
#else
extern long time;
#define TRTIME time
#endif
#define INSERT(x) {*bsctbin = (x);\
if (++bsctbin == &bsctbuf[TBUFSIZE]) bsctbin = bsctbuf;}
#define ZERO 0 /* dummy insert value for odd byte receive packets */
/*
* NAME
* bsctr - trace an event for Bisync Drivers
* SYNOPSIS
* bsctr (dev, state, type [, len, dptr])
* dev_t dev; Device number
* unsigned state; State number (bscpsm) or other info (bscll)
* char type; Trace Packet type
* short len; (Optional) Length of data section of packet
* char *dptr; (Optional) Pointer to data section (kernel space)
* ALGORITHM
* 1. Check for trace buffer overflow
* 2. If we can't insert next trace packet, count
* trace buffer overruns. Otherwise, insert
* packet into trace buffer.
* 3. If the last packet was of type 'y' and this packet is the
* same, combine the packets by merging the data from the
* second into the first.
* 4. If the last packet was type 'y' and the data length was
* odd, make it even by adding a dummy data byte.
* 5. Add the new data packet by inserting the time (a long),
* state, type, and if type 'x' or 'y', the length and
* data.
* MACHINE DEPENDENCIES
* This algorithm assumes a 'normal' byte ordering within a short.
* If the length needs to be increased ((3) above), the low-order
* byte address is computed and incremented, and any carry
* added to the computed high-order address.
* On Intel and PDP-11's, for example, this algorithm will need
* to be modified.
*/
bsctr(dev,state,type,len,dptr)
dev_t dev; /* bsc device minor number */
unsigned state; /* current state number, or other info */
char type; /* current state's type */
register short int len; /* length of data in dptr */
register char *dptr; /* data to be logged */
{
register int avail; /* number of trace buffer bytes available */
short int givenlen;
/* 1. check for trace buffer overflow */
avail = (bsctbin >= bsctbout) ? TBUFSIZE - (bsctbin - bsctbout):
bsctbout - bsctbin;
--avail; /* don't allow in to catch out */
/* 2. if we can't insert next trace packet, count
* trace buffer overruns. Otherwise, insert
* packet into trace buffer.
*/
givenlen = (type < 'x') ? 0 : (len & SIZEMASK);
if (avail < givenlen+8) { /* we will lose data */
++bsclost;
return;
}
/*
* 3. If it is a 'y' type (receive) then the characters will be
* sent here one at a time. In order to store them similarly to
* 'x' types (transmit), each character is added to the end of the
* list of received characters and the length is incremented by one
* instead of storing each of the characters as an individual packet.
* The first receive character is stored just as a transmit packet
* with a length of one. The next packet, if a 'y', is stored as
* noted above.
*/
if (type == 'y' && lastpkt) {
INSERT(*dptr);
lastpkt[0]++; /* Incr. length */
if (*lastpkt == 0) { /* Overflow? */
if (lastpkt == bsctbuf)
bsctbuf[TBUFSIZE-1]++;
else lastpkt[-1]++;
}
} else {
/*
* Check to see if the last character stored was a receive type
* and whether the length was odd. If it was, a
* dummy character must be added to force an even boundary
* as with transmit characters
*/
if (lastpkt && (*lastpkt & 1))
INSERT(ZERO);
lastpkt = (char *)0;
INSERT(TRTIME>>24);
INSERT(TRTIME>>16);
INSERT(TRTIME>>8);
INSERT(TRTIME);
INSERT(state);
INSERT(type);
if (type >= 'x') { /* we will log data */
INSERT(givenlen>>8);
if (type == 'y')
lastpkt = bsctbin;
INSERT(givenlen);
if (type == 'x' && (givenlen & 1)) ++givenlen;
while (--givenlen >= 0)
INSERT(*dptr++);
}
}
if (bscbw) { /* someone waiting */
bscbw = 0;
wakeup (bsctbuf);
}
}
#if defined BSD42
bstread(dev,uio) /* user request to read trace buffer */
register dev_t dev;
struct uio *uio;
#else
bstread(dev) /* user request to read trace buffer */
register dev_t dev;
#endif
{
register int x, diff;
int errcode = 0;
dev = minor(dev);
x = spl8();
while (bsctbin == bsctbout) { /* buffer empty */
if (bsc[dev].b_mode == BSC_CLOSED){
splx(x);
#if defined BSD42
return 0;
#else
return;
#endif
}
++bscbw; /* indicate we'll sleep for trace buf*/
sleep(bsctbuf, BSCPRI);/* sleep for it */
}
if (lastpkt && (*lastpkt & 1))
INSERT(ZERO);
lastpkt = (char *)0;
diff = (bsctbin > bsctbout) ? bsctbin - bsctbout :
TBUFSIZE - (bsctbout - bsctbin);
splx(x);
if (diff > UCOUNT) diff = UCOUNT;
if (&bsctbout[diff] >= &bsctbuf[TBUFSIZE]) {
x = &bsctbuf[TBUFSIZE] - bsctbout;
#if defined BSD42
errcode = uiomove(bsctbout, x, UIO_READ, uio);
if (!errcode)
errcode = uiomove (bsctbuf, diff - x, UIO_READ, uio);
#else
if (iomove (bsctbout, x, B_READ) ||
iomove (bsctbuf, diff - x, B_READ))
errcode = EFAULT;
#endif
bsctbout = &bsctbuf[diff - x];
} else {
#if defined BSD42
errcode = uiomove(bsctbout, diff, UIO_READ, uio);
#else
if (iomove(bsctbout, diff, B_READ))
errcode = EFAULT;
#endif
bsctbout += diff;
}
/* ?. If trace events were lost, add loss event to next buffer */
if (bsclost) { /* # trace events lost */
x = spl8();
bsctr(dev, bsclost, 'o'); /* overrun event */
bsclost = 0;
splx(x);
}
#ifdef BSD42
return errcode;
#else
if (errcode)
u.u_error = errcode;
#endif
}
bstopen(dev, flag)
dev_t dev;
{
if (bsctlock != -1) {
ERRRET(EBUSY);
}
bsctlock = dev = minor(dev);
bsc[dev].b_trace = 1; /* indicate tracing activated */
bsctbin = bsctbout = bsctbuf; /* initialize in, out pointers */
lastpkt = (char *)0;
while (bsc[dev].b_mode == BSC_CLOSED) /* wait till open */
sleep (&bsc[dev].b_trace, BSCPRI);
#ifdef BSD42
return 0;
#endif
}
bstclose(dev)
dev_t dev;
{
wakeup(bsctbuf);
bsc[minor(dev)].b_trace = 0;
bsctlock = -1;
#if defined BSD42
return 0;
#endif
}
bstioctl(dev,cmd,arg) /* ioctl entry */
dev_t dev;
{
bsc[minor(dev)].b_trace = (cmd&0xf) + 1;
#if defined BSD42
return 0;
#endif
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.