initcalls: Add initial implementation
Create simple serial subsystem which makes use of initcalls, and convert existing serial drivers to its use.
This commit is contained in:
		@@ -3,6 +3,9 @@ SUBDIRS :=
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
include $(BASEDIR)/header.mk
 | 
					include $(BASEDIR)/header.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OBJS_$(d) := \
 | 
				
			||||||
 | 
						$(d)/serial.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OBJS_$(d)_$(CONFIG_VEXPRESS_A9) := \
 | 
					OBJS_$(d)_$(CONFIG_VEXPRESS_A9) := \
 | 
				
			||||||
	$(d)/pl011.o \
 | 
						$(d)/pl011.o \
 | 
				
			||||||
	$(d)/pl111.o
 | 
						$(d)/pl111.o
 | 
				
			||||||
@@ -15,6 +18,6 @@ OBJS_$(d)_$(CONFIG_RPI) := \
 | 
				
			|||||||
	$(d)/bcm2835_mailbox.o \
 | 
						$(d)/bcm2835_mailbox.o \
 | 
				
			||||||
	$(d)/bcm2835_videocore.o
 | 
						$(d)/bcm2835_videocore.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
KOBJS += $(OBJS_$(d)_y)
 | 
					KOBJS += $(OBJS_$(d)) $(OBJS_$(d)_y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include $(BASEDIR)/footer.mk
 | 
					include $(BASEDIR)/footer.mk
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,8 +18,11 @@
 | 
				
			|||||||
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <init.h>
 | 
				
			||||||
#include <types.h>
 | 
					#include <types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <drivers/serial.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000)
 | 
					#define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Auxiliary IO registers (includes both mini-UART and SPI) */
 | 
					/* Auxiliary IO registers (includes both mini-UART and SPI) */
 | 
				
			||||||
@@ -57,7 +60,7 @@
 | 
				
			|||||||
#define GPPUD VC_MMU_IO_OFFSET(0x7E200094)
 | 
					#define GPPUD VC_MMU_IO_OFFSET(0x7E200094)
 | 
				
			||||||
#define GPPUDCLK0 VC_MMU_IO_OFFSET(0x7E200098)
 | 
					#define GPPUDCLK0 VC_MMU_IO_OFFSET(0x7E200098)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mini_uart_init() {
 | 
					void mini_uart_device_init() {
 | 
				
			||||||
	uint32 aux_enables;
 | 
						uint32 aux_enables;
 | 
				
			||||||
	uint32 gpfsel1;
 | 
						uint32 gpfsel1;
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
@@ -96,10 +99,23 @@ void mini_uart_init() {
 | 
				
			|||||||
	*(uint32 *)AUX_MU_CNTL_REG = 2; //enable TX
 | 
						*(uint32 *)AUX_MU_CNTL_REG = 2; //enable TX
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void mini_uart_putc(char c) {
 | 
					int mini_uart_putc(char c) {
 | 
				
			||||||
	/* Wait until the serial buffer is empty */
 | 
						/* Wait until the serial buffer is empty */
 | 
				
			||||||
	while (!(*(volatile uint32*)AUX_MU_LSR_REG & MINI_UART_TX_EMPTY));
 | 
						while (!(*(volatile uint32*)AUX_MU_LSR_REG & MINI_UART_TX_EMPTY));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* When it's empty, write our character */
 | 
						/* When it's empty, write our character */
 | 
				
			||||||
	*(volatile uint32*)AUX_MU_IO_REG = c;
 | 
						*(volatile uint32*)AUX_MU_IO_REG = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct serial_dev mini_uart_dev = {
 | 
				
			||||||
 | 
						.putc = &mini_uart_putc
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void mini_uart_init() {
 | 
				
			||||||
 | 
						mini_uart_device_init();
 | 
				
			||||||
 | 
						serial_register_device(&mini_uart_dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					early_initcall(mini_uart_init);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,17 +18,31 @@
 | 
				
			|||||||
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <init.h>
 | 
				
			||||||
 | 
					#include <drivers/serial.h>
 | 
				
			||||||
#include <types.h>
 | 
					#include <types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PL011_SERIAL_BASE 0x10009000
 | 
					#define PL011_SERIAL_BASE 0x10009000
 | 
				
			||||||
#define PL011_SERIAL_FLAG_REGISTER 0x18
 | 
					#define PL011_SERIAL_FLAG_REGISTER 0x18
 | 
				
			||||||
#define PL011_SERIAL_BUFFER_FULL (1 << 5)
 | 
					#define PL011_SERIAL_BUFFER_FULL (1 << 5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pl011_putc(char c)
 | 
					int pl011_putc(char c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* Wait until the serial buffer is empty */
 | 
						/* Wait until the serial buffer is empty */
 | 
				
			||||||
	while (*(volatile uint32*)(PL011_SERIAL_BASE + PL011_SERIAL_FLAG_REGISTER) & (PL011_SERIAL_BUFFER_FULL));
 | 
						while (*(volatile uint32*)(PL011_SERIAL_BASE + PL011_SERIAL_FLAG_REGISTER) & (PL011_SERIAL_BUFFER_FULL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* When it's empty, put our character at the base */
 | 
						/* When it's empty, put our character at the base */
 | 
				
			||||||
	*(volatile uint32*)PL011_SERIAL_BASE = c;
 | 
						*(volatile uint32*)PL011_SERIAL_BASE = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct serial_dev pl011_dev = {
 | 
				
			||||||
 | 
						.putc = &pl011_putc
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pl011_init() {
 | 
				
			||||||
 | 
						serial_register_device(&pl011_dev);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					early_initcall(pl011_init);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								drivers/serial.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								drivers/serial.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					    Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This file is part of Aedrix.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <init.h>
 | 
				
			||||||
 | 
					#include <drivers/serial.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct serial_dev *first_serial_dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int serial_register_device(struct serial_dev *sdev) {
 | 
				
			||||||
 | 
						if (!first_serial_dev)
 | 
				
			||||||
 | 
							first_serial_dev = sdev;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct serial_dev *serial_first_device() {
 | 
				
			||||||
 | 
						return first_serial_dev;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void serial_init() {
 | 
				
			||||||
 | 
						first_serial_dev = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					driversubsys_initcall(serial_init);
 | 
				
			||||||
@@ -22,6 +22,6 @@
 | 
				
			|||||||
#define CONSOLE_H
 | 
					#define CONSOLE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void console_init(struct fb *f);
 | 
					void console_init(struct fb *f);
 | 
				
			||||||
void console_putc(char c);
 | 
					int console_putc(char c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CONSOLE_H */
 | 
					#endif /* CONSOLE_H */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								include/drivers/serial.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/drivers/serial.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					    Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This file is part of Aedrix.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct serial_dev {
 | 
				
			||||||
 | 
						//TODO add more functions and attributes here
 | 
				
			||||||
 | 
						int (*putc)(char);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int serial_register_device(struct serial_dev *sdev);
 | 
				
			||||||
 | 
					struct serial_dev *serial_first_device();
 | 
				
			||||||
							
								
								
									
										34
									
								
								include/init.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/init.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					    Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This file is part of Aedrix.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_earlyinitcalls();
 | 
				
			||||||
 | 
					void init_initcalls();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct initcall_func {
 | 
				
			||||||
 | 
						void (*fptr)();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _initcall(level_name, level, func) struct initcall_func func##_##level##_initcall \
 | 
				
			||||||
 | 
						__attribute__ ((section ("." level_name "initcalls"))) = { func }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The actual calls to be used externally */
 | 
				
			||||||
 | 
					#define early_initcall(func) _initcall("early", 0, func)
 | 
				
			||||||
 | 
					#define driversubsys_initcall(func) _initcall("driversubsys", 1, func)
 | 
				
			||||||
 | 
					#define device_initcall(func) _initcall("device", 2, func)
 | 
				
			||||||
@@ -21,8 +21,8 @@
 | 
				
			|||||||
#ifndef PRINT_H
 | 
					#ifndef PRINT_H
 | 
				
			||||||
#define PRINT_H
 | 
					#define PRINT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void print_init(void (*putc)(char));
 | 
					void print_init(int (*putc)(char));
 | 
				
			||||||
int print(char *fmt, ...);
 | 
					int print(char *fmt, ...);
 | 
				
			||||||
int print_func(void (putcf)(char), char *fmt, ...);
 | 
					int print_func(int (putcf)(char), char *fmt, ...);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* PRINT_H */
 | 
					#endif /* PRINT_H */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -123,17 +123,17 @@ void console_newline() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void console_putc(char c) {
 | 
					int console_putc(char c) {
 | 
				
			||||||
	char *console_buffer_end = console_buffer + chars_per_line * lines;
 | 
						char *console_buffer_end = console_buffer + chars_per_line * lines;
 | 
				
			||||||
	char *write_char_at;
 | 
						char *write_char_at;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (c) {
 | 
						switch (c) {
 | 
				
			||||||
		case '\n':
 | 
							case '\n':
 | 
				
			||||||
			console_newline();
 | 
								console_newline();
 | 
				
			||||||
			return;
 | 
								return 0;
 | 
				
			||||||
		case '\r':
 | 
							case '\r':
 | 
				
			||||||
			curr_char = 0;
 | 
								curr_char = 0;
 | 
				
			||||||
			return;
 | 
								return 0;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -148,4 +148,6 @@ void console_putc(char c) {
 | 
				
			|||||||
	*write_char_at = c;
 | 
						*write_char_at = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	console_char_to_fb(c, curr_char++, curr_line);
 | 
						console_char_to_fb(c, curr_char++, curr_line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								kernel/init.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								kernel/init.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					    Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This file is part of Aedrix.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					    the Free Software Foundation; either version 2 of the License, or
 | 
				
			||||||
 | 
					    (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					    GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You should have received a copy of the GNU General Public License along
 | 
				
			||||||
 | 
					    with this program; if not, write to the Free Software Foundation, Inc.,
 | 
				
			||||||
 | 
					    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <types.h>
 | 
				
			||||||
 | 
					#include <print.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern uint32 early_initcalls_start, early_initcalls_end;
 | 
				
			||||||
 | 
					extern uint32 initcalls_start, initcalls_end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_earlyinitcalls() {
 | 
				
			||||||
 | 
						void (**initcall)();
 | 
				
			||||||
 | 
						for (initcall = (void (**)()) &early_initcalls_start; initcall < (void (**)())&early_initcalls_end; initcall++)
 | 
				
			||||||
 | 
							(*initcall)();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void init_initcalls() {
 | 
				
			||||||
 | 
						void (**initcall)();
 | 
				
			||||||
 | 
						for (initcall = (void (**)()) &initcalls_start; initcall < (void (**)())&initcalls_end; initcall++)
 | 
				
			||||||
 | 
							(*initcall)();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,6 +7,7 @@ OBJS_$(d) := $(d)/atags.o \
 | 
				
			|||||||
	$(d)/console.o \
 | 
						$(d)/console.o \
 | 
				
			||||||
	$(d)/font.o \
 | 
						$(d)/font.o \
 | 
				
			||||||
	$(d)/framebuffer.o \
 | 
						$(d)/framebuffer.o \
 | 
				
			||||||
 | 
						$(d)/init.o \
 | 
				
			||||||
	$(d)/kmalloc.o \
 | 
						$(d)/kmalloc.o \
 | 
				
			||||||
	$(d)/list.o \
 | 
						$(d)/list.o \
 | 
				
			||||||
	$(d)/math.o \
 | 
						$(d)/math.o \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,22 +23,23 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* This function exists solely so crashes don't happen if putc() gets
 | 
					/* This function exists solely so crashes don't happen if putc() gets
 | 
				
			||||||
 * called before it is initialized. */
 | 
					 * called before it is initialized. */
 | 
				
			||||||
void putc_initial(char c) {
 | 
					int putc_initial(char c) {
 | 
				
			||||||
	(void)c;
 | 
						(void)c;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void (*print_putc)(char) = &putc_initial;
 | 
					int (*print_putc)(char) = &putc_initial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void print_init(void (*putcfn)(char)) {
 | 
					void print_init(int (*putcfn)(char)) {
 | 
				
			||||||
	if (putcfn)
 | 
						if (putcfn)
 | 
				
			||||||
		print_putc = putcfn;
 | 
							print_putc = putcfn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
void puts(void (*putc)(char), const char *s)
 | 
					void puts(int (*putc)(char), const char *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    while (*s) putc (*s++);
 | 
					    while (*s) putc (*s++);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void puti(void (*putc)(char), int i)
 | 
					void puti(int (*putc)(char), int i)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int left;
 | 
						unsigned int left;
 | 
				
			||||||
	char buf[1 << (sizeof(int)*8) / 10];
 | 
						char buf[1 << (sizeof(int)*8) / 10];
 | 
				
			||||||
@@ -64,7 +65,7 @@ void puti(void (*putc)(char), int i)
 | 
				
			|||||||
		putc(*p);
 | 
							putc(*p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void putx(void (*putc)(char), unsigned int i) {
 | 
					void putx(int (*putc)(char), unsigned int i) {
 | 
				
			||||||
	int j;
 | 
						int j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	puts(putc, "0x");
 | 
						puts(putc, "0x");
 | 
				
			||||||
@@ -78,7 +79,7 @@ void putx(void (*putc)(char), unsigned int i) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void putb(void (*putc)(char), unsigned int i) {
 | 
					void putb(int (*putc)(char), unsigned int i) {
 | 
				
			||||||
	int j;
 | 
						int j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	puts(putc, "0b");
 | 
						puts(putc, "0b");
 | 
				
			||||||
@@ -88,7 +89,7 @@ void putb(void (*putc)(char), unsigned int i) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int _print(void (*putc)(char), char *fmt, va_list arg) {
 | 
					int _print(int (*putc)(char), char *fmt, va_list arg) {
 | 
				
			||||||
	char *c;
 | 
						char *c;
 | 
				
			||||||
	for (c = fmt; *c; c++) {
 | 
						for (c = fmt; *c; c++) {
 | 
				
			||||||
		if (*c == '%') {
 | 
							if (*c == '%') {
 | 
				
			||||||
@@ -138,7 +139,7 @@ int print(char *fmt, ...) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int print_func(void (*putc)(char), char *fmt, ...) {
 | 
					int print_func(int (*putc)(char), char *fmt, ...) {
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
	va_list arg;
 | 
						va_list arg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <atags.h>
 | 
					#include <atags.h>
 | 
				
			||||||
 | 
					#include <init.h>
 | 
				
			||||||
#include <kmalloc.h>
 | 
					#include <kmalloc.h>
 | 
				
			||||||
#include <mmu.h>
 | 
					#include <mmu.h>
 | 
				
			||||||
#include <mm.h>
 | 
					#include <mm.h>
 | 
				
			||||||
@@ -26,13 +27,13 @@
 | 
				
			|||||||
#include <framebuffer.h>
 | 
					#include <framebuffer.h>
 | 
				
			||||||
#include <console.h>
 | 
					#include <console.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <drivers/serial.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_VEXPRESS_A9
 | 
					#ifdef CONFIG_VEXPRESS_A9
 | 
				
			||||||
#include <drivers/pl011.h>
 | 
					 | 
				
			||||||
#include <drivers/pl111.h>
 | 
					#include <drivers/pl111.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_RPI
 | 
					#ifdef CONFIG_RPI
 | 
				
			||||||
#include <drivers/pi_mini_uart.h>
 | 
					 | 
				
			||||||
#include <drivers/bcm2835_videocore.h>
 | 
					#include <drivers/bcm2835_videocore.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -56,74 +57,11 @@ void video_init(void) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void test_mm() {
 | 
					void serial_console_init() {
 | 
				
			||||||
	struct page *p, *q;
 | 
						struct serial_dev *sdev = serial_first_device();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	print("\ntest_mm():\n");
 | 
						if (sdev)
 | 
				
			||||||
 | 
							print_init(sdev->putc);
 | 
				
			||||||
	p = mm_get_free_pages(0);
 | 
					 | 
				
			||||||
	if (p)
 | 
					 | 
				
			||||||
		print("%x, %x\n", p, p->address);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		print("Error: failed to allocate memory for p\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	q = mm_get_free_pages(4);
 | 
					 | 
				
			||||||
	if (q)
 | 
					 | 
				
			||||||
		print("%x, %x\n", q, q->address);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		print("Error: failed to allocate memory for q\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	mm_put_free_pages(p);
 | 
					 | 
				
			||||||
	mm_put_free_pages(q);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	q = mm_get_free_pages(1);
 | 
					 | 
				
			||||||
	if (q)
 | 
					 | 
				
			||||||
		print("%x, %x\n", q, q->address);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		print("Error: failed to allocate memory for q\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	p = mm_get_free_pages(0);
 | 
					 | 
				
			||||||
	if (p)
 | 
					 | 
				
			||||||
		print("%x, %x\n", p, p->address);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		print("Error: failed to allocate memory for p\n");
 | 
					 | 
				
			||||||
	mm_put_free_pages(p);
 | 
					 | 
				
			||||||
	mm_put_free_pages(q);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void test_kmalloc() {
 | 
					 | 
				
			||||||
	void *a, *b, *c, *d;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	print("\ntest_kmalloc():\n");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	a = kmalloc(4);
 | 
					 | 
				
			||||||
	print("a: %x\n", a);
 | 
					 | 
				
			||||||
	b = kmalloc(13);
 | 
					 | 
				
			||||||
	print("b: %x\n", b);
 | 
					 | 
				
			||||||
	c = kmalloc(4);
 | 
					 | 
				
			||||||
	print("c: %x\n", c);
 | 
					 | 
				
			||||||
	d = kmalloc(25);
 | 
					 | 
				
			||||||
	print("d: %x\n", d);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	kfree(c);
 | 
					 | 
				
			||||||
	kfree(b);
 | 
					 | 
				
			||||||
	kfree(a);
 | 
					 | 
				
			||||||
	kfree(d);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	a = kmalloc(13);
 | 
					 | 
				
			||||||
	print("a: %x\n", a);
 | 
					 | 
				
			||||||
	b = kmalloc(4);
 | 
					 | 
				
			||||||
	print("b: %x\n", b);
 | 
					 | 
				
			||||||
	c = kmalloc(25);
 | 
					 | 
				
			||||||
	print("c: %x\n", c);
 | 
					 | 
				
			||||||
	d = kmalloc(7);
 | 
					 | 
				
			||||||
	print("d: %x\n", d);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void test_memory() {
 | 
					 | 
				
			||||||
	test_mm();
 | 
					 | 
				
			||||||
	test_kmalloc();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void kmalloc_init();
 | 
					void kmalloc_init();
 | 
				
			||||||
@@ -135,14 +73,9 @@ int main(void) {
 | 
				
			|||||||
	//setup MMU
 | 
						//setup MMU
 | 
				
			||||||
	mmu_reinit();
 | 
						mmu_reinit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//initialize the serial console
 | 
						init_earlyinitcalls();
 | 
				
			||||||
#ifdef CONFIG_VEXPRESS_A9
 | 
					
 | 
				
			||||||
	print_init(&pl011_putc);
 | 
						serial_console_init();
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef CONFIG_RPI
 | 
					 | 
				
			||||||
	mini_uart_init();
 | 
					 | 
				
			||||||
	print_init(&mini_uart_putc);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//setup memory
 | 
						//setup memory
 | 
				
			||||||
	mm_init();
 | 
						mm_init();
 | 
				
			||||||
@@ -159,7 +92,7 @@ int main(void) {
 | 
				
			|||||||
		declare_memory_region(lower, upper);
 | 
							declare_memory_region(lower, upper);
 | 
				
			||||||
	} while (!atags_next_mem_region(&atags));
 | 
						} while (!atags_next_mem_region(&atags));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	test_memory();
 | 
						init_initcalls();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	video_init();
 | 
						video_init();
 | 
				
			||||||
	console_init(&myfb);
 | 
						console_init(&myfb);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								link.ld
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								link.ld
									
									
									
									
									
								
							@@ -4,6 +4,15 @@ SECTIONS
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	. = 0x80100000;
 | 
						. = 0x80100000;
 | 
				
			||||||
	.text : { *(.text*) *(.rodata*) }
 | 
						.text : { *(.text*) *(.rodata*) }
 | 
				
			||||||
 | 
						.init : {
 | 
				
			||||||
 | 
							early_initcalls_start = .;
 | 
				
			||||||
 | 
							*(.earlyinitcalls*)
 | 
				
			||||||
 | 
							early_initcalls_end = .;
 | 
				
			||||||
 | 
							initcalls_start = .;
 | 
				
			||||||
 | 
							*(.driversubsysinitcalls*)
 | 
				
			||||||
 | 
							*(.deviceinitcalls*)
 | 
				
			||||||
 | 
							initcalls_end = .;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	.data : { *(.data*) }
 | 
						.data : { *(.data*) }
 | 
				
			||||||
	.bss : { *(.bss*) *(COMMON*) }
 | 
						.bss : { *(.bss*) *(COMMON*) }
 | 
				
			||||||
	kernel_end = .;
 | 
						kernel_end = .;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user