1 /* This file handle diagnostic output that is directly sent to the LOG driver.
2 * This output can either be a kernel message (announced through a SYS_EVENT
3 * with a SIGKMESS in the signal set) or output from another system process
4 * (announced through a DIAGNOSTICS message).
7 * 21 July 2005: Created (Jorrit N. Herder)
11 #include <minix/type.h>
12 #include <minix/safecopies.h>
13 #include <minix/sys_config.h>
17 /*==========================================================================*
19 *==========================================================================*/
20 PUBLIC
int do_new_kmess(from
)
21 endpoint_t from
; /* who sent this message? */
23 /* Notification for a new kernel message. */
24 static struct kmessages kmess
; /* entire kmess structure */
25 static char print_buf
[_KMESS_BUF_SIZE
]; /* copy new message here */
30 static int kernel_prev_next
= 0;
31 static int tty_prev_next
= 0;
33 if (from
== TTY_PROC_NR
)
38 prev_nextp
= &tty_prev_next
;
39 gid
= cpf_grant_direct(TTY_PROC_NR
, (vir_bytes
)&kmess
, sizeof(kmess
),
46 /* Ask TTY driver for log output */
47 mess
.GETKM_GRANT
= gid
;
48 mess
.m_type
= GET_KMESS_S
;
49 r
= sendrec(TTY_PROC_NR
, &mess
);
52 if (r
== OK
) r
= mess
.m_type
;
55 printf("log: couldn't get copy of kmessages from TTY: %d\n", r
);
61 /* Try to get a fresh copy of the buffer with kernel messages. */
62 if ((r
=sys_getkmessages(&kmess
)) != OK
) {
63 printf("log: couldn't get copy of kmessages: %d\n", r
);
66 prev_nextp
= &kernel_prev_next
;
69 /* Print only the new part. Determine how many new bytes there are with
70 * help of the current and previous 'next' index. Note that the kernel
71 * buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
72 * is new data; else we miss % KMESS_BUF_SIZE here.
73 * Check for size being positive, the buffer might as well be emptied!
75 if (kmess
.km_size
> 0) {
76 bytes
= ((kmess
.km_next
+ _KMESS_BUF_SIZE
) - (*prev_nextp
)) %
78 r
= *prev_nextp
; /* start at previous old */
81 print_buf
[i
] = kmess
.km_buf
[(r
%_KMESS_BUF_SIZE
)];
86 /* Now terminate the new message and save it in the log. */
88 log_append(print_buf
, i
);
91 /* Almost done, store 'next' so that we can determine what part of the
92 * kernel messages buffer to print next time a notification arrives.
94 *prev_nextp
= kmess
.km_next
;
98 /*===========================================================================*
100 *===========================================================================*/
101 PUBLIC
int do_diagnostics(message
*m
, int safe
)
103 /* The LOG server handles all diagnostic messages from servers and device
104 * drivers. It forwards the message to the TTY driver to display it to the
105 * user. It also saves a copy in a local buffer so that messages can be
106 * reviewed at a later time.
111 int i
= 0, offset
= 0;
112 static char diagbuf
[10240];
114 /* Also make a copy for the private buffer at the LOG server, so
115 * that the messages can be reviewed at a later time.
117 src
= (vir_bytes
) m
->DIAG_PRINT_BUF_G
;
118 count
= m
->DIAG_BUF_COUNT
;
119 while (count
> 0 && i
< sizeof(diagbuf
)-1) {
122 r
= sys_safecopyfrom(m
->m_source
, src
, offset
, (vir_bytes
) &c
, 1, D
);
124 r
= sys_datacopy(m
->m_source
, src
+offset
, SELF
, (vir_bytes
) &c
, 1);
131 log_append(diagbuf
, i
);
133 if(m
->m_type
== ASYN_DIAGNOSTICS_OLD
) return EDONTREPLY
;