1
0

print: Allow for more than one output for console messages

This commit is contained in:
Aaron Lindsay 2012-10-09 23:13:37 -04:00
parent a64668b239
commit 5f59e07432
3 changed files with 74 additions and 13 deletions

View File

@ -21,7 +21,9 @@
#ifndef PRINT_H
#define PRINT_H
void print_init(int (*putc)(char));
int print_register_func_early(int (*putc)(char));
int print_register_func(int (*putc)(char));
int print_unregister_func(int (*putc)(char));
int print(char *fmt, ...);
int print_func(int (putcf)(char), char *fmt, ...);

View File

@ -18,25 +18,77 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <init.h>
#include <list.h>
#include <kmalloc.h>
#include <print.h>
#include <vargs.h>
/* This function exists solely so crashes don't happen if putc() gets
* called before it is initialized. */
int putc_initial(char c) {
(void)c;
struct dlist_node print_funcs_list;
struct print_func {
int (*putc)(char);
struct dlist_node list;
};
/*
* On startup, we'd like to have print capabilities before kmalloc is
* initialized, so statically allocate one struct print_func to allow for the
* registration of one print 'sink' before kmalloc is initialized.
*/
struct print_func print_func_early;
int print_register_func_early(int (*putc)(char)) {
if (list_empty(&print_funcs_list)) {
print_func_early.putc = putc;
insert_before(&print_funcs_list, &print_func_early.list);
return 0;
}
return -1;
}
int print_register_func(int (*putc)(char)) {
struct print_func *pf;
if (!(pf = kmalloc(sizeof(struct print_func))))
return -1;
pf->putc = putc;
insert_before(&print_funcs_list, &pf->list);
return 0;
}
int (*print_putc)(char) = &putc_initial;
void print_init(int (*putcfn)(char)) {
if (putcfn)
print_putc = putcfn;
int print_unregister_func(int (*putc)(char)) {
struct print_func *it;
if (list_empty(&print_funcs_list))
return -1;
for_each_list(it, &print_funcs_list, struct print_func, list) {
if (it->putc == putc) {
remove(&it->list);
//only kfree if it was kmalloced
if (it != &print_func_early)
kfree(it);
return 0;
}
}
return -1;
}
int print_putc(char c) {
struct print_func *it;
if (list_empty(&print_funcs_list))
return -1;
for_each_list(it, &print_funcs_list, struct print_func, list)
it->putc(c);
return 0;
}
void puts(int (*putc)(char), const char *s)
{
while (*s) putc (*s++);
while (*s) putc(*s++);
}
void puti(int (*putc)(char), int i)
@ -132,7 +184,7 @@ int print(char *fmt, ...) {
va_list arg;
va_start(arg, fmt);
ret = _print(print_putc, fmt, arg);
ret = _print(&print_putc, fmt, arg);
va_end(arg);
return ret;
@ -149,3 +201,9 @@ int print_func(int (*putc)(char), char *fmt, ...) {
return ret;
}
void print_init() {
init_list(&print_funcs_list);
}
early_initcall(print_init);

View File

@ -59,6 +59,7 @@ void video_console_init(void) {
if ((console_init(&console_fb)))
return;
print_register_func(&console_putc);
print_console_logo();
print_func(&console_putc, "Successfully initialized video console on %s.\n", fbdev->name);
@ -70,7 +71,7 @@ void serial_console_init() {
if (!sdev)
return;
print_init(sdev->putc);
print_register_func_early(sdev->putc);
print("Successfully initialized serial console on %s\n", sdev->name);
}