print: Allow for more than one output for console messages
This commit is contained in:
		| @@ -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, ...); | ||||
|  | ||||
|   | ||||
| @@ -18,20 +18,72 @@ | ||||
|     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; | ||||
| 	} | ||||
| int (*print_putc)(char) = &putc_initial; | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| void print_init(int (*putcfn)(char)) { | ||||
| 	if (putcfn) | ||||
| 		print_putc = putcfn; | ||||
| 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_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) | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user