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)
12 #include <minix/type.h>
13 #include <minix/safecopies.h>
14 #include <minix/sys_config.h>
18 /*==========================================================================*
20 *==========================================================================*/
21 PUBLIC
int do_new_kmess(from
)
22 endpoint_t from
; /* who sent this message? */
24 /* Notification for a new kernel message. */
25 static struct kmessages kmess
; /* entire kmess structure */
26 static char print_buf
[_KMESS_BUF_SIZE
]; /* copy new message here */
31 static int kernel_prev_next
= 0;
32 static int tty_prev_next
= 0;
34 if (from
== TTY_PROC_NR
)
39 prev_nextp
= &tty_prev_next
;
40 gid
= cpf_grant_direct(TTY_PROC_NR
, (vir_bytes
)&kmess
, sizeof(kmess
),
45 report("LOG","cpf_grant_direct failed for TTY", errno
);
50 /* Ask TTY driver for log output */
51 mess
.GETKM_GRANT
= gid
;
52 mess
.m_type
= GET_KMESS_S
;
53 r
= sendrec(TTY_PROC_NR
, &mess
);
56 if (r
== OK
) r
= mess
.m_type
;
59 report("LOG","couldn't get copy of kmessages from TTY", r
);
65 /* Try to get a fresh copy of the buffer with kernel messages. */
66 if ((r
=sys_getkmessages(&kmess
)) != OK
) {
67 report("LOG","couldn't get copy of kmessages", r
);
70 prev_nextp
= &kernel_prev_next
;
73 /* Print only the new part. Determine how many new bytes there are with
74 * help of the current and previous 'next' index. Note that the kernel
75 * buffer is circular. This works fine if less then KMESS_BUF_SIZE bytes
76 * is new data; else we miss % KMESS_BUF_SIZE here.
77 * Check for size being positive, the buffer might as well be emptied!
79 if (kmess
.km_size
> 0) {
80 bytes
= ((kmess
.km_next
+ _KMESS_BUF_SIZE
) - (*prev_nextp
)) %
82 r
= *prev_nextp
; /* start at previous old */
85 print_buf
[i
] = kmess
.km_buf
[(r
%_KMESS_BUF_SIZE
)];
90 /* Now terminate the new message and save it in the log. */
92 log_append(print_buf
, i
);
95 /* Almost done, store 'next' so that we can determine what part of the
96 * kernel messages buffer to print next time a notification arrives.
98 *prev_nextp
= kmess
.km_next
;
102 /*===========================================================================*
104 *===========================================================================*/
105 PUBLIC
int do_diagnostics(message
*m
, int safe
)
107 /* The LOG server handles all diagnostic messages from servers and device
108 * drivers. It forwards the message to the TTY driver to display it to the
109 * user. It also saves a copy in a local buffer so that messages can be
110 * reviewed at a later time.
115 int i
= 0, offset
= 0;
116 static char diagbuf
[10240];
118 /* Also make a copy for the private buffer at the LOG server, so
119 * that the messages can be reviewed at a later time.
121 src
= (vir_bytes
) m
->DIAG_PRINT_BUF_G
;
122 count
= m
->DIAG_BUF_COUNT
;
123 while (count
> 0 && i
< sizeof(diagbuf
)-1) {
126 r
= sys_safecopyfrom(m
->m_source
, src
, offset
, (vir_bytes
) &c
, 1, D
);
128 r
= sys_datacopy(m
->m_source
, src
+offset
, SELF
, (vir_bytes
) &c
, 1);
135 log_append(diagbuf
, i
);
137 if(m
->m_type
== ASYN_DIAGNOSTICS_OLD
) return EDONTREPLY
;