Allowed printing diagnostic messages (either from system processes or the
kernel) to the log driver. The log driver forwards such output to the TTY. Changed driver_task() not to send a reply if the return value is EDONTREPLY.
This commit is contained in:
parent
da9b8e45f9
commit
09830fc33e
|
@ -128,11 +128,13 @@ struct driver *dp; /* Device dependent entry points. */
|
||||||
(*dp->dr_cleanup)();
|
(*dp->dr_cleanup)();
|
||||||
|
|
||||||
/* Finally, prepare and send the reply message. */
|
/* Finally, prepare and send the reply message. */
|
||||||
|
if (r != EDONTREPLY) {
|
||||||
mess.m_type = TASK_REPLY;
|
mess.m_type = TASK_REPLY;
|
||||||
mess.REP_PROC_NR = proc_nr;
|
mess.REP_PROC_NR = proc_nr;
|
||||||
|
/* Status is # of bytes transferred or error code. */
|
||||||
mess.REP_STATUS = r; /* # of bytes transferred or error code */
|
mess.REP_STATUS = r;
|
||||||
send(device_caller, &mess); /* send reply to caller */
|
send(device_caller, &mess);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ CFLAGS = -I$i
|
||||||
LDFLAGS = -i
|
LDFLAGS = -i
|
||||||
LIBS = -lsys -lsysutil
|
LIBS = -lsys -lsysutil
|
||||||
|
|
||||||
OBJ = log.o
|
OBJ = log.o diag.o kputc.o
|
||||||
LIBDRIVER = $d/libdriver/driver.o
|
LIBDRIVER = $d/libdriver/driver.o
|
||||||
|
|
||||||
|
|
||||||
|
|
122
drivers/log/diag.c
Normal file
122
drivers/log/diag.c
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/* This file handle diagnostic output that is directly sent to the LOG driver.
|
||||||
|
* This output can either be a kernel message (announced through a SYS_EVENT
|
||||||
|
* with a SIGKMESS in the signal set) or output from another system process
|
||||||
|
* (announced through a DIAGNOSTICS message).
|
||||||
|
*
|
||||||
|
* Changes:
|
||||||
|
* 21 July 2005: Created (Jorrit N. Herder)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
#include "../../kernel/const.h"
|
||||||
|
#include "../../kernel/config.h"
|
||||||
|
#include "../../kernel/type.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*==========================================================================*
|
||||||
|
* do_new_kmess *
|
||||||
|
*==========================================================================*/
|
||||||
|
PUBLIC int do_new_kmess(m)
|
||||||
|
message *m; /* notification message */
|
||||||
|
{
|
||||||
|
/* Notification for a new kernel message. */
|
||||||
|
struct kmessages kmess; /* entire kmess structure */
|
||||||
|
char print_buf[KMESS_BUF_SIZE]; /* copy new message here */
|
||||||
|
static int prev_next = 0;
|
||||||
|
int size, next;
|
||||||
|
int bytes;
|
||||||
|
int i, r;
|
||||||
|
|
||||||
|
/* Try to get a fresh copy of the buffer with kernel messages. */
|
||||||
|
if ((r=sys_getkmessages(&kmess)) != OK) {
|
||||||
|
report("LOG","couldn't get copy of kmessages", r);
|
||||||
|
return EDONTREPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print only the new part. Determine how many new bytes there are with
|
||||||
|
* help of the current and previous 'next' index. Note that the kernel
|
||||||
|
* buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
|
||||||
|
* is new data; else we miss % KMESS_BUF_SIZE here.
|
||||||
|
* Check for size being positive, the buffer might as well be emptied!
|
||||||
|
*/
|
||||||
|
if (kmess.km_size > 0) {
|
||||||
|
bytes = ((kmess.km_next + KMESS_BUF_SIZE) - prev_next) % KMESS_BUF_SIZE;
|
||||||
|
r=prev_next; /* start at previous old */
|
||||||
|
i=0;
|
||||||
|
while (bytes > 0) {
|
||||||
|
print_buf[i] = kmess.km_buf[(r%KMESS_BUF_SIZE)];
|
||||||
|
log_putc( kmess.km_buf[(r%KMESS_BUF_SIZE)] );
|
||||||
|
bytes --;
|
||||||
|
r ++;
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
/* Now terminate the new message and print it. */
|
||||||
|
print_buf[i] = 0;
|
||||||
|
printf(print_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Almost done, store 'next' so that we can determine what part of the
|
||||||
|
* kernel messages buffer to print next time a notification arrives.
|
||||||
|
*/
|
||||||
|
prev_next = kmess.km_next;
|
||||||
|
return EDONTREPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* do_diagnostics *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC int do_diagnostics(message *m)
|
||||||
|
{
|
||||||
|
/* The LOG server handles all diagnostic messages from servers and device
|
||||||
|
* drivers. It forwards the message to the TTY driver to display it to the
|
||||||
|
* user. It also saves a copy in a local buffer so that messages can be
|
||||||
|
* reviewed at a later time.
|
||||||
|
*/
|
||||||
|
int result;
|
||||||
|
int proc_nr;
|
||||||
|
vir_bytes src;
|
||||||
|
int count;
|
||||||
|
char c;
|
||||||
|
int i = 0;
|
||||||
|
static char diagbuf[1024];
|
||||||
|
|
||||||
|
/* Forward the message to the TTY driver. Inform the TTY driver about the
|
||||||
|
* original sender, so that it knows where the buffer to be printed is.
|
||||||
|
* The message type, DIAGNOSTICS, remains the same.
|
||||||
|
*/
|
||||||
|
if ((proc_nr = m->DIAG_PROC_NR) == SELF)
|
||||||
|
m->DIAG_PROC_NR = proc_nr = m->m_source;
|
||||||
|
result = _sendrec(TTY, m);
|
||||||
|
|
||||||
|
/* Now also make a copy for the private buffer at the LOG server, so
|
||||||
|
* that the messages can be reviewed at a later time.
|
||||||
|
*/
|
||||||
|
src = (vir_bytes) m->DIAG_PRINT_BUF;
|
||||||
|
count = m->DIAG_BUF_COUNT;
|
||||||
|
while (count > 0) {
|
||||||
|
if (sys_datacopy(proc_nr, src, SELF, (vir_bytes) &c, 1) != OK)
|
||||||
|
break; /* stop copying on error */
|
||||||
|
log_putc(c); /* accumulate character */
|
||||||
|
src ++;
|
||||||
|
count --;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* log_putc *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void log_putc(c)
|
||||||
|
int c; /* char to be added to diag buffer */
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
36
drivers/log/kputc.c
Normal file
36
drivers/log/kputc.c
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* A server must occasionally print some message. It uses a simple version of
|
||||||
|
* printf() found in the system library that calls putk() to output characters.
|
||||||
|
* The LOG driver cannot use the regular putk(). Hence, it uses a special
|
||||||
|
* version of putk() that directly sends to the TTY task.
|
||||||
|
*
|
||||||
|
* Changes:
|
||||||
|
* 21 July 2005: Created (Jorrit N. Herder)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* kputc *
|
||||||
|
*===========================================================================*/
|
||||||
|
void kputc(c)
|
||||||
|
int c;
|
||||||
|
{
|
||||||
|
/* Accumulate another character. If 0 or buffer full, print it. */
|
||||||
|
static int buf_count; /* # characters in the buffer */
|
||||||
|
static char print_buf[80]; /* output is buffered here */
|
||||||
|
message m;
|
||||||
|
|
||||||
|
if ((c == 0 && buf_count > 0) || buf_count == sizeof(print_buf)) {
|
||||||
|
m.DIAG_BUF_COUNT = buf_count;
|
||||||
|
m.DIAG_PRINT_BUF = print_buf;
|
||||||
|
m.DIAG_PROC_NR = SELF;
|
||||||
|
m.m_type = DIAGNOSTICS; /* request TTY to output this buffer */
|
||||||
|
_sendrec(TTY, &m); /* if it fails, we cannot do better */
|
||||||
|
buf_count = 0; /* clear buffer for next batch */
|
||||||
|
}
|
||||||
|
if (c != 0) {
|
||||||
|
print_buf[buf_count++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,44 +2,25 @@
|
||||||
* /dev/klog - system log device
|
* /dev/klog - system log device
|
||||||
*
|
*
|
||||||
* Changes:
|
* Changes:
|
||||||
* 7 july 2005 - Created (Ben Gras)
|
* 21 July 2005 - Support for diagnostic messages (Jorrit N. Herder)
|
||||||
|
* 7 July 2005 - Created (Ben Gras)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "../drivers.h"
|
#include "log.h"
|
||||||
#include "../libdriver/driver.h"
|
#include <sys/time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
#include "../../kernel/const.h"
|
#include "../../kernel/const.h"
|
||||||
#include "../../kernel/type.h"
|
#include "../../kernel/type.h"
|
||||||
|
|
||||||
#include <sys/time.h>
|
#define LOG_DEBUG 0 /* enable/ disable debugging */
|
||||||
#include <sys/select.h>
|
|
||||||
|
|
||||||
#define NR_DEVS 1 /* number of minor devices */
|
#define NR_DEVS 1 /* number of minor devices */
|
||||||
#define KRANDOM_PERIOD 10 /* ticks between krandom calls */
|
|
||||||
|
|
||||||
#define LOG_DEBUG 0
|
|
||||||
|
|
||||||
#define MINOR_KLOG 0 /* /dev/klog */
|
#define MINOR_KLOG 0 /* /dev/klog */
|
||||||
|
|
||||||
#define LOG_SIZE (5*1024)
|
|
||||||
#define LOGINC(n, i) do { (n) = (((n) + (i)) % LOG_SIZE); } while(0)
|
#define LOGINC(n, i) do { (n) = (((n) + (i)) % LOG_SIZE); } while(0)
|
||||||
|
|
||||||
#define SUSPENDABLE 1
|
PUBLIC struct logdevice logdevices[NR_DEVS];
|
||||||
|
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of devices */
|
||||||
PRIVATE struct logdevice {
|
|
||||||
char log_buffer[LOG_SIZE];
|
|
||||||
int log_size, /* no. of bytes in log buffer */
|
|
||||||
log_read, /* read mark */
|
|
||||||
log_write; /* write mark */
|
|
||||||
#if SUSPENDABLE
|
|
||||||
int log_proc_nr,
|
|
||||||
log_source,
|
|
||||||
log_iosize; /* proc that is blocking on read */
|
|
||||||
vir_bytes log_user_vir;
|
|
||||||
#endif
|
|
||||||
int log_selected, log_select_proc;
|
|
||||||
} logdevices[NR_DEVS];
|
|
||||||
|
|
||||||
PRIVATE struct device log_geom[NR_DEVS]; /* base and size of each device */
|
|
||||||
PRIVATE int log_device = -1; /* current device */
|
PRIVATE int log_device = -1; /* current device */
|
||||||
|
|
||||||
FORWARD _PROTOTYPE( char *log_name, (void) );
|
FORWARD _PROTOTYPE( char *log_name, (void) );
|
||||||
|
@ -376,15 +357,22 @@ message *m_ptr;
|
||||||
* understand.
|
* understand.
|
||||||
*/
|
*/
|
||||||
switch(m_ptr->m_type) {
|
switch(m_ptr->m_type) {
|
||||||
case DIAGNOSTICS:
|
case DIAGNOSTICS: {
|
||||||
r = subwrite(&logdevices[0], m_ptr->DIAG_BUF_COUNT,
|
r = do_diagnostics(m_ptr);
|
||||||
m_ptr->m_source, (vir_bytes) m_ptr->DIAG_PRINT_BUF);
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case SYS_EVENT: {
|
||||||
|
sigset_t sigset = m_ptr->NOTIFY_ARG;
|
||||||
|
if (sigismember(&sigset, SIGKMESS)) {
|
||||||
|
do_new_kmess(m_ptr);
|
||||||
|
}
|
||||||
|
r = EDONTREPLY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
r = EINVAL;
|
r = EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
36
drivers/log/log.h
Normal file
36
drivers/log/log.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/* Includes. */
|
||||||
|
#include "../drivers.h"
|
||||||
|
#include "../libdriver/driver.h"
|
||||||
|
#include <minix/type.h>
|
||||||
|
#include <minix/const.h>
|
||||||
|
#include <minix/com.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <minix/ipc.h>
|
||||||
|
|
||||||
|
/* Constants and types. */
|
||||||
|
|
||||||
|
#define LOG_SIZE (5*1024)
|
||||||
|
#define SUSPENDABLE 1
|
||||||
|
|
||||||
|
struct logdevice {
|
||||||
|
char log_buffer[LOG_SIZE];
|
||||||
|
int log_size, /* no. of bytes in log buffer */
|
||||||
|
log_read, /* read mark */
|
||||||
|
log_write; /* write mark */
|
||||||
|
#if SUSPENDABLE
|
||||||
|
int log_proc_nr,
|
||||||
|
log_source,
|
||||||
|
log_iosize; /* proc that is blocking on read */
|
||||||
|
vir_bytes log_user_vir;
|
||||||
|
#endif
|
||||||
|
int log_selected, log_select_proc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Function prototypes. */
|
||||||
|
_PROTOTYPE( void kputc, (int c) );
|
||||||
|
_PROTOTYPE( int do_new_kmess, (message *m) );
|
||||||
|
_PROTOTYPE( int do_diagnostics, (message *m) );
|
||||||
|
_PROTOTYPE( void log_putc, (int c) );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue