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 #ifndef PRINT_H
#define 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(char *fmt, ...);
int print_func(int (putcf)(char), 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. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <init.h>
#include <list.h>
#include <kmalloc.h>
#include <print.h> #include <print.h>
#include <vargs.h> #include <vargs.h>
/* This function exists solely so crashes don't happen if putc() gets struct dlist_node print_funcs_list;
* called before it is initialized. */
int putc_initial(char c) { struct print_func {
(void)c; 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; return 0;
} }
int (*print_putc)(char) = &putc_initial;
void print_init(int (*putcfn)(char)) { int print_unregister_func(int (*putc)(char)) {
if (putcfn) struct print_func *it;
print_putc = putcfn;
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) void puts(int (*putc)(char), const char *s)
{ {
while (*s) putc (*s++); while (*s) putc(*s++);
} }
void puti(int (*putc)(char), int i) void puti(int (*putc)(char), int i)
@ -132,7 +184,7 @@ int print(char *fmt, ...) {
va_list arg; va_list arg;
va_start(arg, fmt); va_start(arg, fmt);
ret = _print(print_putc, fmt, arg); ret = _print(&print_putc, fmt, arg);
va_end(arg); va_end(arg);
return ret; return ret;
@ -149,3 +201,9 @@ int print_func(int (*putc)(char), char *fmt, ...) {
return ret; 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))) if ((console_init(&console_fb)))
return; return;
print_register_func(&console_putc);
print_console_logo(); print_console_logo();
print_func(&console_putc, "Successfully initialized video console on %s.\n", fbdev->name); print_func(&console_putc, "Successfully initialized video console on %s.\n", fbdev->name);
@ -70,7 +71,7 @@ void serial_console_init() {
if (!sdev) if (!sdev)
return; return;
print_init(sdev->putc); print_register_func_early(sdev->putc);
print("Successfully initialized serial console on %s\n", sdev->name); print("Successfully initialized serial console on %s\n", sdev->name);
} }