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.
(*dp->dr_cleanup)();
/* Finally, prepare and send the reply message. */
- mess.m_type = TASK_REPLY;
- mess.REP_PROC_NR = proc_nr;
-
- mess.REP_STATUS = r; /* # of bytes transferred or error code */
- send(device_caller, &mess); /* send reply to caller */
+ if (r != EDONTREPLY) {
+ mess.m_type = TASK_REPLY;
+ mess.REP_PROC_NR = proc_nr;
+ /* Status is # of bytes transferred or error code. */
+ mess.REP_STATUS = r;
+ send(device_caller, &mess);
+ }
}
}
LDFLAGS = -i
LIBS = -lsys -lsysutil
-OBJ = log.o
+OBJ = log.o diag.o kputc.o
LIBDRIVER = $d/libdriver/driver.o
--- /dev/null
+/* 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 */
+{
+
+}
+
+
+
--- /dev/null
+/* 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;
+ }
+}
+
* /dev/klog - system log device
*
* 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 "../libdriver/driver.h"
-#include "../../kernel/const.h"
-#include "../../kernel/type.h"
-
+#include "log.h"
#include <sys/time.h>
#include <sys/select.h>
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
-#define NR_DEVS 1 /* number of minor devices */
-#define KRANDOM_PERIOD 10 /* ticks between krandom calls */
-
-#define LOG_DEBUG 0
+#define LOG_DEBUG 0 /* enable/ disable debugging */
+#define NR_DEVS 1 /* number of minor devices */
#define MINOR_KLOG 0 /* /dev/klog */
-#define LOG_SIZE (5*1024)
#define LOGINC(n, i) do { (n) = (((n) + (i)) % LOG_SIZE); } while(0)
-#define SUSPENDABLE 1
-
-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 */
+PUBLIC struct logdevice logdevices[NR_DEVS];
+PRIVATE struct device log_geom[NR_DEVS]; /* base and size of devices */
+PRIVATE int log_device = -1; /* current device */
FORWARD _PROTOTYPE( char *log_name, (void) );
FORWARD _PROTOTYPE( struct device *log_prepare, (int device) );
* understand.
*/
switch(m_ptr->m_type) {
- case DIAGNOSTICS:
- r = subwrite(&logdevices[0], m_ptr->DIAG_BUF_COUNT,
- m_ptr->m_source, (vir_bytes) m_ptr->DIAG_PRINT_BUF);
- break;
- default:
- r = EINVAL;
- break;
+ case DIAGNOSTICS: {
+ r = do_diagnostics(m_ptr);
+ break;
+ }
+ case SYS_EVENT: {
+ sigset_t sigset = m_ptr->NOTIFY_ARG;
+ if (sigismember(&sigset, SIGKMESS)) {
+ do_new_kmess(m_ptr);
+ }
+ r = EDONTREPLY;
+ break;
+ }
+ default:
+ r = EINVAL;
+ break;
}
-
return r;
}
--- /dev/null
+/* 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) );
+
+