📄 logterm.c
字号:
/* -*-C-*-
*
* $Revision: 1.1.2.4 $
* $Author: rivimey $
* $Date: 1998/01/12 21:22:34 $
*
* Copyright (c) 1997 Advanced RISC Machines Limited.
* All Rights Reserved.
*
* Project: ANGEL
*
* Title: Debug interface via Serial writes to 16c552 serial port B.
*/
#if DEBUG == 1 && (!defined(MINIMAL_ANGEL) || MINIMAL_ANGEL == 0)
#include <string.h>
#include "channels.h"
#include "pid.h"
#include "st16c552.h"
#include "logging.h"
#include "logging/logterm.h"
#include "debug.h"
#include "support.h"
#define SAVEBUFSIZE 2048 /* max #words in save buffer -- min 6 words/message */
#define MAXARGS 32 /* max number of distinct args on cmd line */
#define CMDBUFSIZE 128 /* max number of characters on command line */
#define OUTPUTBUFSIZE 64 /* number of buffered characters from message before flush */
#ifndef UNUSED
#define UNUSED(x) (0 ? (x) = (x) : 0)
#endif
static unsigned long msgsavebuf[SAVEBUFSIZE];
static struct LogSaveBuffer savebuf;
static char log_commandbuf[CMDBUFSIZE];
static int log_cursor = 0;
static WarnLevel logterm_level;
static char logterm_buf[OUTPUTBUFSIZE];
static char *logterm_pos;
static char *logterm_end;
static int log_tracing = TRUE;
static int log_deferredprompt = FALSE;
static int log_buflock = FALSE;
static int log_cmdlock = FALSE;
/* static void setupsave(void); */
void log_emitch(char ch);
void log_emitstr(char *str);
static void log_output(int enable);
static void log_processchar(char ch, unsigned int empty_stack);
static int log_dump(int argc, char **argv);
static int log_echo(int argc, char **argv);
static int log_ver(int argc, char **argv);
static int log_help(int argc, char **argv);
static int log_trace(int argc, char **argv);
static int log_go(int argc, char **argv);
static int log_pause(int argc, char **argv);
static int log_stat(int argc, char **argv);
static int log_level(int argc, char **argv);
static int log_format(int argc, char **argv);
static struct
{
char *str;
int (*pfn)(int argc, char **argv);
char *desc, *helpstr;
} log_cmds[] =
{ /* These must be kept in sorted order by name */
{ "dump", log_dump, "Dump\n",
"syntax: dump <start addr> [ <end addr> | +<len> ]\n"
},
{ "echo", log_echo, "Echo\n",
"syntax: echo <words>\n"
},
{ "format",log_format,"Show / set the per-line format string\n",
"syntax: format [<new string>]\n"
},
{ "go", log_go, "Undo pause; reenable ints\n",
"syntax: go\n"
},
{ "help", log_help, "Command help\n",
"syntax: help [command]\n"
},
{ "pause", log_pause, "Pause Angel; disable ints\n",
"syntax: pause\n"
},
{ "stat", log_stat, "Display internal statistics info\n",
"syntax: stat\n"
},
{ "level", log_level, "Set the minimum log level displayed.\n",
"syntax: level [info|warn|err]\n"
},
{ "trace", log_trace, "Enable/disable tracing or display trace buffer\n",
"syntax: trace -- display current settings\n"
" trace <n> -- show <n> lines of buffer\n"
" trace <n> -- show <n> lines of buffer\n"
" trace on | off -- enable/disable run-time trace\n"
},
{ "ver", log_ver, "Display Angel version info\n",
"syntax: ver\n"
},
};
static const int log_ncmds = sizeof(log_cmds)/sizeof(log_cmds[0]);
/*
* NT's HyperTerminal needs CRLF, not just LF!
*/
#define LOGTERM_ADD_CR_TO_LF
#pragma no_check_stack
#if DEFBAUD == 9600
# define BAUDVALUE Baud9600
#elif DEFBAUD == 19200
# define BAUDVALUE Baud19200
#elif DEFBAUD == 38400
# define BAUDVALUE Baud38400
#elif DEFBAUD == 57600
# define BAUDVALUE Baud57600
#elif DEFBAUD == 115200
# define BAUDVALUE Baud115200
#else
# error invalid baud rate
#endif
#include "banner.h"
#define LOGONMESSAGE "\n\n" ANGEL_BANNER "Type 'help' for more info.\n\n"
#define PROMPT "% "
/*
* the Interrupt Enable register is write-only, so we use the
* scratch register to keep track of currently enabled Ints
*/
#define IER_set(u, f) ((u)->ier = ((u)->spr |= (f)))
#define IER_clr(u, f) ((u)->ier = ((u)->spr &= (~(f))))
#define IER_reset(u) ((u)->ier = ((u)->spr = 0));
/*
* macros to control Interrupt Enable Register in various sensible ways
*/
#define st16c552_EnableTxInterrupt(u) (IER_set((u), TxReadyInt))
#define st16c552_DisableTxInterrupt(u) (IER_clr((u), TxReadyInt))
#define st16c552_EnableRxInterrupt(u) (IER_set((u), RxReadyInt))
#define st16c552_DisableRxInterrupt(u) (IER_clr((u), RxReadyInt))
/*
* macros to get and put serial characters
*/
#define st16c552_GetChar(u) ((u)->rhr)
#define st16c552_PutChar(u, c) ((u)->thr = (c))
/*
* macro to test "fullness" of transmit buffer
*/
#define st16c552_TxBuffFull(u) (((u)->lsr & (1 << 5)) == 0)
#define st16c552_TxBuffEmpty(u) (((u)->lsr & (1 << 6)) != 0)
#define st16c552_RxBuffEmpty(u) (((u)->lsr & (1 << 0)) == 0)
/*
* prefix for lines not at start of message -- see stuff in putchar too
*/
#define PREFIXLEN 6
/*
* prototypes
*/
/*
* Function: stoi
* Purpose: string to integer conversion; like atoi but doesn't pull in
* the rest of the c library!
*
* Pre-conditions: none.
*
* Params:
* Input: s - pointer to (base-10) number in ASCII
*
* Output: e - pointer to last character converted
*
* Returns: number converted
*/
static int stoi(char *s, char **e)
{
int i, sign = 0, base = 10;
while(*s == ' ')
s++;
switch(*s)
{
case '-':
sign = -1;
s++;
break;
case '0':
if (s[1] == 'x')
{
base = 16;
s+=2;
}
break;
case '+':
s++;
sign = 1;
break;
default:
sign = 1;
break;
}
i = 0;
if (base == 10)
{
while(*s >= '0' && *s <= '9')
{
i = (i * 10) + (*s - '0');
s++;
}
}
else
{
while((*s >= '0' && *s <= '9') || (*s >= 'a' && *s <= 'f'))
{
if (*s >= 'a')
i = (i * 16) + (*s - 'a' + 10);
else
i = (i * 16) + (*s - '0');
s++;
}
}
i *= sign;
*e = s;
return i;
}
void logterm_flushbuf(void);
/*
* Function: logterm_Initialise
* Purpose:
*
* Pre-conditions: none.
*
* Params:
* Input:
*
* Returns: 0.
*/
/* REMEMBER: This routine gets called VERY EARLY!! */
bool logterm_Initialise(void)
{
ST16C552Reg *const serchip = (LOGTERM_PORT == ST16C552_IDENT_A) ?
(ST16C552Reg *)NISA_SER_A : (ST16C552Reg *)NISA_SER_B;
/*
* Interrupt Enable Register - all interrupts off
*/
IER_reset(serchip);
/*
* wait for current transmits to finish
*/
while (!st16c552_TxBuffEmpty(serchip))
continue;
/*
* Modem Control Register - DTR* and RTS* outputs high; INT
* pin tri-stated; Rx and Tx "disabled" by setting chip in
* loopback mode.
*/
serchip->mcr = 0x10;
/*
* FIFO Control Register - FIFO enabled, but Rx and Tx
* FIFOs empty; RxRDY and TxRDY mode 1; FIFO interrupt
* trigger level = 1.
*/
serchip->fcr = 0x0f;
/*
* Enable divisor latch via the Line Control Register, and
* set the baud rates
*/
serchip->lcr = 0x80;
serchip->dll = (unsigned char)(BAUDVALUE & 0xff);
serchip->dlm = (unsigned char)((BAUDVALUE >> 8) & 0xff);
/*
* OK, set the operational values for the LCR: 8-bit words,
* 1 stop bit, no parity
*/
serchip->lcr = 0x03;
/*
* take the chip out of loopback, and enable interrupts; DTR* and
* RTS* outputs are forced low.
*/
serchip->mcr = 0x0b;
/*
* output is polled, but input is interrupt-driven.
*/
st16c552_DisableTxInterrupt(serchip);
st16c552_EnableRxInterrupt(serchip);
/*
* print a logon banner to say we're here!
*/
log_emitstr(LOGONMESSAGE);
log_emitstr(PROMPT);
log_deferredprompt = FALSE;
log_tracing = TRUE;
log_setupsave(&savebuf, msgsavebuf, SAVEBUFSIZE);
log_set_logging_options(WL_SAVEMSG|WL_PRINTMSG);
log_set_log_id(LOG_ALWAYS, 1);
/* this works because it's polled input... interrupts
* are disabled in this code
*/
log_pause(0,0);
return 0;
}
struct LogSaveBuffer *log_getlogtermbuf(void)
{
return &savebuf;
}
bool logterm_PreWarn(WarnLevel level)
{
/*
* set up the buffer pointers... reset in flushbuf
*/
logterm_pos = logterm_buf;
logterm_end = (logterm_buf + sizeof(logterm_buf) - 1);
logterm_level = level;
return TRUE;
}
void logterm_flushbuf(void)
{
char *p;
p = logterm_buf;
while(p < logterm_pos)
{
log_emitch(*p++);
}
logterm_pos = logterm_buf;
logterm_end = logterm_buf + sizeof(logterm_buf) - 1;
}
int logterm_PutChar(char c)
{
if (logterm_pos >= logterm_end)
logterm_flushbuf();
*logterm_pos++ = c;
return 0;
}
void logterm_PostWarn(unsigned int len)
{
if (len > 0)
logterm_flushbuf();
}
/*
* Show a number nlines of messages from the trace buffer, working
* back from the current insert position.
*
* This is done by starting at the insert position and using the
* count value (which is at 'insert' - 1) to skip backwards through
* the buffer until either the oldest data is reached or the required
* number of lines is found.
*
* Then work forward, calling log_logprint() to print the text.
*
*/
static void log_showitems(struct LogSaveBuffer *sb, int nlines)
{
int count, message_start = sb->message;
unsigned long *ptr = sb->current;
if (ptr == 0 || *ptr == 0) /* nothing to do */
return;
ptr--; /* normally, savebufinsert points at next free slot */
/*
* while we haven't got to the start point -- either the start of
* data, or the item we want to start with, or the oldest item in
* the buffer is reached, skip back from the insert point.
*
* Note: 'start of data' and 'oldest' are differently encoded -- start
* of data is indicated by a zero count, written when the buffer is
* set up. 'oldest' is reached when the current pointer is larger
* than the insert pointer, and (ptr - count) is less.
*/
count = nlines;
while(count > 0 && *ptr != 0)
{
/*
* got to oldest; no more (complete) messages available.
*/
if (ptr >= sb->current && (ptr - (*ptr & 0xff)) < sb->current)
break;
/*
* if this message marks the end of a line (flagged by the top
* bits of the word being set), decrement the message number too.
*/
if (*ptr & ~0xff)
{
message_start--;
count--;
}
/* skip one more back, wrapping around the beginning. */
ptr -= (*ptr & 0xff);
if (ptr < sb->start)
ptr += sb->size;
}
/*
* now run forward, printing each line from the data in the buffer. Of
* course, pointer values are printed from memory, and so may be incorrect
* if the program changed that memory in the meantime....
*/
count = nlines;
while(count > 0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -