Coherent4.2.10/conf/tr/src/trace.c
/*
* conf/trace.c
*
* trace device
* Used for buffering the output of cmn_err ().
*/
/*
* -----------------------------------------------------------------
* Includes.
*/
#define __KERNEL__ 1
#include <sys/coherent.h>
#include <sys/cmn_err.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <sys/errno.h>
#include <sys/io.h>
#include <sys/mmu.h>
#include <sys/poll.h>
#include <sys/seg.h>
#include <kernel/trace.h>
/* Tunable parameters. */
extern int TRACE_BUF_LEN;
unsigned char * traceBuf;
struct Trace {
/* Booleans. */
unsigned char tr_open;
/* Queue pointers and count. */
unsigned int tr_head;
unsigned int tr_tail;
unsigned int tr_count;
};
static struct Trace tr;
static event_t tr_ev;
/************************************************************************
* trAlloc ()
*
* Attempt to acquire storage for the trace buffer.
* In case of failure, leave traceBuf at its initial value of 0.
***********************************************************************/
#if __USE_PROTO__
void trAlloc (void)
#else
void
trAlloc ()
#endif
{
__caddr_t devVaddr;
int devSeg;
int s;
int pagesNeeded;
int pte;
int i;
__paddr_t pageTablePaddr;
__caddr_t pageTableVaddr;
int * ptable;
_chirp ('U', 154);
/* Expand paging services to allow for this buffer area. */
pagesNeeded = btocru(TRACE_BUF_LEN);
/*
* See if there are enough pages to do the allocation.
* Allow about 64 extra since the system will need some room to run.
*/
if (allocno () < pagesNeeded + 64) {
return;
}
_chirp ('V', 154);
/* Compute the virtual address where device buffer memory starts. */
devVaddr = DEVICE_SEG_VADDR(TRACE_MAJOR);
/* Compute the segment number of the 4 MByte-aligned virtual segment. */
devSeg = btosrd ((int)devVaddr);
s = sphi ();
/* Grab a page to map the buffer area for this device. */
pageTablePaddr = (__paddr_t)(ctob (* -- sysmem.pfree));
pageTableVaddr = __PTOV(pageTablePaddr);
pte = (int)(pageTablePaddr) | SEG_RW;
ptable0_v [devSeg] = pte;
_chirp ('W', 154);
/* Grab and map the specified number of pages for the device buffer. */
ptable = (int *)pageTableVaddr;
for (i = 0; i < pagesNeeded; i++) {
pte = ctob (* -- sysmem.pfree) | SEG_RW;
* ptable ++ = pte;
}
spl (s);
mmuupd ();
_chirp ('X', 154);
traceBuf = (unsigned char *)devVaddr;
cmn_err (CE_NOTE, "!trAlloc () - using %d pages at virt address %x",
pagesNeeded, (int)devVaddr);
_chirp ('Y', 154);
return;
}
/************************************************************************
* _put_putbuf ()
*
***********************************************************************/
#if __USE_PROTO__
void (_put_putbuf) (unsigned char outch)
#else
void
_put_putbuf __ARGS ((outch))
unsigned char outch;
#endif
{
int s;
/* If buffer didn't get allocated, do nothing. */
if (traceBuf == NULL)
return;
s = sphi ();
/* If queue is full, discard oldest contents. */
while (tr.tr_count >= TRACE_BUF_LEN) {
tr.tr_count --;
tr.tr_tail ++;
if (tr.tr_tail >= TRACE_BUF_LEN)
tr.tr_tail = 0;
}
/* Assertion: (tr.tr_count < TRACE_BUF_LEN). */
traceBuf [tr.tr_head] = outch;
tr.tr_count ++;
tr.tr_head ++;
if (tr.tr_head >= TRACE_BUF_LEN)
tr.tr_head = 0;
if (tr_ev.e_procp)
pollwake (& tr_ev);
spl (s);
}
/************************************************************************
* tropen
*
***********************************************************************/
#if __USE_PROTO__
static void tropen(o_dev_t __NOTUSED(dev), int __NOTUSED(mode),
int __NOTUSED(_flags), __cred_t * __NOTUSED(_credp))
#else
static void
tropen (dev, mode)
o_dev_t dev;
int mode;
#endif
{
/* Only one open at a time. */
if (tr.tr_open) {
cmn_err (CE_WARN, "TR : Only one open at a time.");
set_user_error (EBUSY);
return;
}
if (traceBuf == NULL) {
cmn_err (CE_WARN, "TR : Buffer not allocated.");
set_user_error (EIO);
return;
}
tr.tr_open = 1;
return;
}
/************************************************************************
* trclose
*
***********************************************************************/
#if __USE_PROTO__
static void trclose(o_dev_t __NOTUSED(dev),
int __NOTUSED(_mode), int __NOTUSED(_flags), __cred_t * __NOTUSED(_credp))
#else
static void
trclose (dev)
o_dev_t dev;
#endif
{
tr.tr_open = 0;
}
/************************************************************************
* trread
*
***********************************************************************/
#if __USE_PROTO__
static void trread(o_dev_t __NOTUSED(dev), IO * iop,
__cred_t * __NOTUSED(_credp))
#else
static void
trread(dev, iop)
o_dev_t dev;
IO * iop;
#endif
{
int s;
while (iop->io_ioc && tr.tr_count) {
ioputc(traceBuf [tr.tr_tail], iop);
s = sphi ();
tr.tr_count --;
spl (s);
tr.tr_tail ++;
if (tr.tr_tail >= TRACE_BUF_LEN)
tr.tr_tail = 0;
}
}
/************************************************************************
* trpoll
*
***********************************************************************/
#if __USE_PROTO__
static int trpoll(o_dev_t __NOTUSED(dev), int ev, int msec)
#else
static int
trpoll(dev, ev, msec)
o_dev_t dev;
int ev;
int msec;
#endif
{
/*
* Only POLLIN is supported.
*/
ev &= POLLIN;
/*
* Input poll with no data present.
*/
if ((ev & POLLIN) != 0 && tr.tr_count == 0) {
/*
* Blocking input poll.
*/
if (msec != 0)
pollopen (& tr_ev);
}
return ev;
}
/*
* Configuration table.
*/
CON trcon ={
DFCHR | DFPOL, /* Flags */
TRACE_MAJOR, /* Major index */
tropen, /* Open */
trclose, /* Close */
NULL, /* Block */
trread, /* Read */
NULL, /* Write */
NULL, /* Ioctl */
NULL, /* Powerfail */
NULL, /* Timeout */
NULL, /* Load */
NULL, /* Unload */
trpoll /* Poll */
};