diff --git a/repos/os/include/spec/exynos5/uart_defs.h b/repos/os/include/spec/exynos5/uart_defs.h deleted file mode 100644 index aca161f8da..0000000000 --- a/repos/os/include/spec/exynos5/uart_defs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * \brief EXYNOS5 UART definitions - * \author Stefan Kalkowski - * \date 2013-06-05 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__SPEC__EXYNOS5__UART_DEFS_H_ -#define _INCLUDE__SPEC__EXYNOS5__UART_DEFS_H_ - -#include - -enum { - /** Number of UARTs */ - UARTS_NUM = 2, - - BAUD_115200 = 115200, -}; - - -static struct Exynos_uart_cfg { - Genode::addr_t mmio_base; - Genode::size_t mmio_size; - int irq_number; -} exynos_uart_cfg[UARTS_NUM] = { - /* temporary workaround having first UART twice (most run-scripts have first UART reserved for the kernel ) */ - { Genode::Board_base::UART_2_MMIO_BASE, 4096, Genode::Board_base::UART_2_IRQ }, - { Genode::Board_base::UART_2_MMIO_BASE, 4096, Genode::Board_base::UART_2_IRQ }, -}; - -#endif /* _INCLUDE__SPEC__EXYNOS5__UART_DEFS_H_ */ diff --git a/repos/os/include/spec/panda/uart_defs.h b/repos/os/include/spec/panda/uart_defs.h deleted file mode 100644 index 663ccd675d..0000000000 --- a/repos/os/include/spec/panda/uart_defs.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * \brief OMAP4 UART definitions - * \author Ivan Loskutov - * \date 2012-11-08 - */ - -/* - * Copyright (C) 2012 Ksys Labs LLC - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__SPEC__PANDA__UART_DEFS_H_ -#define _INCLUDE__SPEC__PANDA__UART_DEFS_H_ - -#include - -enum { - /** Number of UARTs */ - UARTS_NUM = 4, - - BAUD_115200 = 26, -}; - - -static struct Omap_uart_cfg { - Genode::addr_t mmio_base; - Genode::size_t mmio_size; - int irq_number; -} omap_uart_cfg[UARTS_NUM] = { - { Genode::Board_base::TL16C750_1_MMIO_BASE, Genode::Board_base::TL16C750_MMIO_SIZE, Genode::Board_base::TL16C750_1_IRQ }, - { Genode::Board_base::TL16C750_2_MMIO_BASE, Genode::Board_base::TL16C750_MMIO_SIZE, Genode::Board_base::TL16C750_2_IRQ }, - { Genode::Board_base::TL16C750_3_MMIO_BASE, Genode::Board_base::TL16C750_MMIO_SIZE, Genode::Board_base::TL16C750_3_IRQ }, - { Genode::Board_base::TL16C750_4_MMIO_BASE, Genode::Board_base::TL16C750_MMIO_SIZE, Genode::Board_base::TL16C750_4_IRQ }, -}; - -#endif /* _INCLUDE__SPEC__PANDA__UART_DEFS_H_ */ diff --git a/repos/os/include/spec/pbxa9/pl011_defs.h b/repos/os/include/spec/pbxa9/pl011_defs.h deleted file mode 100644 index 72b79e3f57..0000000000 --- a/repos/os/include/spec/pbxa9/pl011_defs.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * \brief PL011 UART definitions for the RealView platform - * \author Christian Helmuth - * \date 2011-05-27 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INCLUDE__SPEC__PBXA9__PL011_DEFS_H_ -#define _INCLUDE__SPEC__PBXA9__PL011_DEFS_H_ - -#include -#include - -enum { - - /** Number of UARTs */ - PL011_NUM = 4, - - /** - * MMIO regions - */ - PL011_PHYS0 = 0x10009000, /* base for UART 0 */ - PL011_PHYS1 = 0x1000a000, /* base for UART 1 */ - PL011_PHYS2 = 0x1000b000, /* base for UART 2 */ - PL011_PHYS3 = 0x1000c000, /* base for UART 3 */ - PL011_SIZE = 0x1000, /* size of each MMIO region */ - - /** - * Interrupt lines - */ - PL011_IRQ0 = Genode::Board_base::PL011_0_IRQ, /* UART 0 */ - PL011_IRQ1 = Genode::Board_base::PL011_1_IRQ, /* UART 1 */ - PL011_IRQ2 = Genode::Board_base::PL011_2_IRQ, /* UART 2 */ - PL011_IRQ3 = Genode::Board_base::PL011_3_IRQ, /* UART 3 */ - - /** - * UART baud rate configuration (precalculated) - * - * div = 24000000 / 16 / baud rate - * IBRD = floor(div) - * FBRD = floor((div - IBRD) * 64 + 0.5) - */ - PL011_IBRD_115200 = 13, PL011_FBRD_115200 = 1, - PL011_IBRD_19200 = 78, PL011_FBRD_19200 = 8, - PL011_IBRD_9600 = 156, PL011_FBRD_9600 = 16, -}; - - -static struct Pl011_uart { - Genode::addr_t mmio_base; - Genode::size_t mmio_size; - int irq_number; -} pl011_uart[PL011_NUM] = { - { PL011_PHYS0, PL011_SIZE, PL011_IRQ0 }, - { PL011_PHYS1, PL011_SIZE, PL011_IRQ1 }, - { PL011_PHYS2, PL011_SIZE, PL011_IRQ2 }, - { PL011_PHYS3, PL011_SIZE, PL011_IRQ3 }, -}; - -#endif /* _INCLUDE__SPEC__PBXA9__PL011_DEFS_H_ */ diff --git a/repos/os/run/uart.run b/repos/os/run/uart.run index 673fbea4ea..7dc0a73eb4 100644 --- a/repos/os/run/uart.run +++ b/repos/os/run/uart.run @@ -46,9 +46,7 @@ set config { - - - + @@ -59,14 +57,6 @@ set config { - - - - - - - - } diff --git a/repos/os/src/drivers/uart/kdb/kdb_uart.h b/repos/os/src/drivers/uart/kdb/kdb_uart.h deleted file mode 100644 index 4a5e87ac10..0000000000 --- a/repos/os/src/drivers/uart/kdb/kdb_uart.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * \brief Fiasco(.OC) KDB UART driver - * \author Christian Prochaska - * \date 2013-03-07 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _KDB_UART_H_ -#define _KDB_UART_H_ - -/* Fiasco.OC includes */ -namespace Fiasco { -#include -} - -/* Genode includes */ -#include -#include - -/* local includes */ -#include "uart_driver.h" - -using namespace Genode; - - -class Kdb_uart : public Uart::Driver -{ - private: - - signed char _buffered_char; - Lock _kdb_read_lock; - - enum { STACK_SIZE = 2*1024*sizeof(addr_t) }; - - class Char_avail_checker_thread : public Thread_deprecated - { - private: - - Uart::Driver &_uart_driver; - Uart::Char_avail_callback &_char_avail_callback; - - public: - - Char_avail_checker_thread(Uart::Driver &uart_driver, - Uart::Char_avail_callback &char_avail_callback) - : - Thread_deprecated("char_avail_handler"), - _uart_driver(uart_driver), - _char_avail_callback(char_avail_callback) - { } - - void entry() - { - Timer::Connection timer; - - for(;;) { - if (_uart_driver.char_avail()) - _char_avail_callback(); - else - timer.msleep(20); - } - } - - } _char_avail_checker_thread; - - public: - - /** - * Constructor - */ - Kdb_uart(Uart::Char_avail_callback &callback) - : - _buffered_char(-1), - _char_avail_checker_thread(*this, callback) - { - _char_avail_checker_thread.start(); - } - - /*************************** - ** UART driver interface ** - ***************************/ - - void put_char(char c) - { - Fiasco::outchar(c); - } - - bool char_avail() - { - Lock_guard kdb_read_lock_guard(_kdb_read_lock); - - if (_buffered_char == -1) - _buffered_char = Fiasco::l4kd_inchar(); - - return (_buffered_char != -1); - } - - char get_char() - { - char result; - - if (_buffered_char != -1) { - result = _buffered_char; - _buffered_char = -1; - } else - result = 0; - - return result; - } - - void baud_rate(int bits_per_second) - { - } -}; - -#endif /* _KDB_UART_H_ */ diff --git a/repos/os/src/drivers/uart/kdb/main.cc b/repos/os/src/drivers/uart/kdb/main.cc deleted file mode 100644 index 05a48f70f6..0000000000 --- a/repos/os/src/drivers/uart/kdb/main.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * \brief Fiasco(.OC) KDB UART driver - * \author Christian Prochaska - * \date 2013-03-07 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include - -#include - -#include "uart_component.h" - -#include "kdb_uart.h" - - -int main(int argc, char **argv) -{ - using namespace Genode; - - printf("--- Fiasco(.OC) KDB UART driver started ---\n"); - - /** - * Factory used by 'Uart::Root' at session creation/destruction time - */ - struct Kdb_uart_driver_factory : Uart::Driver_factory - { - Kdb_uart *uart; - - /** - * Constructor - */ - Kdb_uart_driver_factory() : uart(0) { } - - Uart::Driver *create(unsigned index, unsigned baudrate, - Uart::Char_avail_callback &callback) - { - /* - * We assume the underlying kernel uses UART0 - */ - if (index > 0) - throw Uart::Driver_factory::Not_available(); - - if (!uart) - uart = new (env()->heap()) Kdb_uart(callback); - - return uart; - } - - void destroy(Uart::Driver *driver) { /* TODO */ } - - } driver_factory; - - enum { STACK_SIZE = 2*1024*sizeof(addr_t) }; - static Cap_connection cap; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); - - static Uart::Root uart_root(&ep, env()->heap(), driver_factory); - env()->parent()->announce(ep.manage(&uart_root)); - - sleep_forever(); - return 0; -} diff --git a/repos/os/src/drivers/uart/kdb/target.inc b/repos/os/src/drivers/uart/kdb/target.inc index f9af4b9fdb..0dd3fc1afe 100644 --- a/repos/os/src/drivers/uart/kdb/target.inc +++ b/repos/os/src/drivers/uart/kdb/target.inc @@ -1,7 +1,6 @@ TARGET = kdb_uart_drv SRC_CC = main.cc LIBS = base config +INC_DIR += $(REP_DIR)/src/drivers/uart $(REP_DIR)/src/drivers/uart/kdb -INC_DIR += $(PRG_DIR)/../.. $(PRG_DIR)/../../.. - -vpath main.cc $(PRG_DIR)/../.. +vpath main.cc $(REP_DIR)/src/drivers/uart diff --git a/repos/os/src/drivers/uart/kdb/uart_driver.h b/repos/os/src/drivers/uart/kdb/uart_driver.h new file mode 100644 index 0000000000..c8b9e6184e --- /dev/null +++ b/repos/os/src/drivers/uart/kdb/uart_driver.h @@ -0,0 +1,130 @@ +/* + * \brief Fiasco(.OC) KDB UART driver + * \author Christian Prochaska + * \date 2013-03-07 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _KDB_UART_H_ +#define _KDB_UART_H_ + +/* Fiasco.OC includes */ +namespace Fiasco { +#include +} + +/* Genode includes */ +#include +#include + +using namespace Genode; + +namespace Uart { + class Driver; + struct Driver_factory; + struct Char_avail_functor; +}; + + +/** + * Functor, called by 'Driver' when data is ready for reading + */ +struct Uart::Char_avail_functor +{ + Genode::Signal_context_capability sigh; + + void operator ()() { + if (sigh.valid()) Genode::Signal_transmitter(sigh).submit(); + else Genode::error("no sigh"); } + +}; + + + +class Uart::Driver +{ + private: + + signed char _buffered_char; + Char_avail_functor &_char_avail; + Timer::Connection _timer; + Signal_handler _timer_handler; + + void _timeout() { if (char_avail()) _char_avail(); } + + public: + + Driver(Genode::Env &env, unsigned, unsigned, + Uart::Char_avail_functor &func) + : _buffered_char(-1), + _char_avail(func), + _timer(env), + _timer_handler(env.ep(), *this, &Driver::_timeout) + { + _timer.sigh(_timer_handler); + _timer.trigger_periodic(20*1000); + } + + + /*************************** + ** UART driver interface ** + ***************************/ + + void put_char(char c) { Fiasco::outchar(c); } + + bool char_avail() + { + if (_buffered_char == -1) + _buffered_char = Fiasco::l4kd_inchar(); + + return (_buffered_char != -1); + } + + char get_char() + { + char result; + + if (_buffered_char != -1) { + result = _buffered_char; + _buffered_char = -1; + } else + result = 0; + + return result; + } + + void baud_rate(int bits_per_second) { } +}; + + +/** + * Factory used by 'Uart::Root' at session creation/destruction time + */ +struct Uart::Driver_factory +{ + struct Not_available {}; + + enum { UARTS_NUM = 1 }; + + Genode::Env &env; + Genode::Heap &heap; + Driver *drivers[UARTS_NUM] { nullptr }; + + Driver_factory(Genode::Env &env, Genode::Heap &heap) + : env(env), heap(heap) {} + + + Uart::Driver &create(unsigned index, unsigned baudrate, + Uart::Char_avail_functor &callback); + + void destroy(Uart::Driver *driver) { /* TODO */ } + +}; + +#endif /* _KDB_UART_H_ */ diff --git a/repos/os/src/drivers/uart/main.cc b/repos/os/src/drivers/uart/main.cc new file mode 100644 index 0000000000..dc97930f9c --- /dev/null +++ b/repos/os/src/drivers/uart/main.cc @@ -0,0 +1,52 @@ +/* + * \brief Driver for UART devices + * \author Stefan Kalkowski + * \date 2013-06-05 + */ + +/* + * Copyright (C) 2013-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include + +/* local includes */ +#include + + +struct Main +{ + Genode::Env &env; + Genode::Heap heap { env.ram(), env.rm() }; + Uart::Driver_factory factory { env, heap }; + Uart::Root uart_root { env, heap, factory }; + + Main(Genode::Env &env) : env(env) + { + Genode::log("--- UART driver started ---"); + env.parent().announce(env.ep().manage(uart_root)); + } +}; + + +namespace Component { + Genode::size_t stack_size() { return 2048*sizeof(Genode::addr_t); } + void construct(Genode::Env &env) { static Main uart_drv(env); } +} + + +Uart::Driver & Uart::Driver_factory::create(unsigned index, unsigned baudrate, + Uart::Char_avail_functor &functor) +{ + if (index >= UARTS_NUM) throw Not_available(); + + if (!drivers[index]) + drivers[index] = new (&heap) Driver(env, index, baudrate, functor); + return *drivers[index]; +} diff --git a/repos/os/src/drivers/uart/spec/exynos5/exynos5_uart.h b/repos/os/src/drivers/uart/spec/exynos5/exynos5_uart.h deleted file mode 100644 index 296d7ecae4..0000000000 --- a/repos/os/src/drivers/uart/spec/exynos5/exynos5_uart.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * \brief Driver for EXYNOS5 UARTs - * \author Stefan Kalkowski - * \author Ivan Loskutov - * \date 2013-06-05 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _EXYNOS_UART_H_ -#define _EXYNOS_UART_H_ - -/* Genode includes */ -#include -#include -#include -#include - -#include - -/* local includes */ -#include "uart_driver.h" - -class Exynos_uart : public Genode::Exynos_uart_base, - public Uart::Driver, - public Genode::Irq_handler -{ - private: - - Uart::Char_avail_callback &_char_avail_callback; - Genode::Irq_activation _irq_activation; - - public: - - /** - * Constructor - */ - Exynos_uart(Genode::Attached_io_mem_dataspace *uart_mmio, int irq_number, - unsigned baud_rate, Uart::Char_avail_callback &callback) - : Exynos_uart_base((Genode::addr_t)uart_mmio->local_addr(), - Genode::Board_base::UART_2_CLOCK, baud_rate), - _char_avail_callback(callback), - _irq_activation(irq_number, *this, sizeof(Genode::addr_t) * 1024) { - _rx_enable(); } - - - /*************************** - ** IRQ handler interface ** - ***************************/ - - void handle_irq(int irq_number) - { - /* inform client about the availability of data */ - _char_avail_callback(); - } - - - /*************************** - ** UART driver interface ** - ***************************/ - - void put_char(char c) { Exynos_uart_base::put_char(c); } - bool char_avail() { return _rx_avail(); } - char get_char() { return _rx_char(); } - void baud_rate(int bits_per_second) {} -}; - -#endif /* _EXYNOS_UART_H_ */ diff --git a/repos/os/src/drivers/uart/spec/exynos5/main.cc b/repos/os/src/drivers/uart/spec/exynos5/main.cc deleted file mode 100644 index 4e0a9267ba..0000000000 --- a/repos/os/src/drivers/uart/spec/exynos5/main.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* - * \brief Driver for Exynos5 UART - * \author Stefan Kalkowski - * \date 2013-06-05 - */ - -/* - * Copyright (C) 2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include - -#include - -/* local includes */ -#include "exynos5_uart.h" -#include "uart_component.h" - - -int main(int argc, char **argv) -{ - using namespace Genode; - - log("--- Exynos5 UART driver started ---"); - - /** - * Factory used by 'Terminal::Root' at session creation/destruction time - */ - struct Exynos_uart_driver_factory : Uart::Driver_factory - { - Exynos_uart *created[UARTS_NUM]; - - /** - * Constructor - */ - Exynos_uart_driver_factory() - { - for (unsigned i = 0; i < UARTS_NUM; i++) - created[i] = 0; - } - - Uart::Driver *create(unsigned index, unsigned baudrate, - Uart::Char_avail_callback &callback) - { - if (index >= UARTS_NUM) - throw Uart::Driver_factory::Not_available(); - - if (baudrate == 0) - { - warning("Baudrate is not defined. Use default 115200"); - baudrate = BAUD_115200; - } - - Exynos_uart_cfg *cfg = &exynos_uart_cfg[index]; - Exynos_uart *uart = created[index]; - - Genode::Attached_io_mem_dataspace *uart_mmio = new (env()->heap()) - Genode::Attached_io_mem_dataspace(cfg->mmio_base, cfg->mmio_size); - - if (!uart) { - uart = new (env()->heap()) - Exynos_uart(uart_mmio, cfg->irq_number, baudrate, callback); - - /* update 'created' table */ - created[index] = uart; - } - return uart; - } - - void destroy(Uart::Driver *driver) { /* TODO */ } - - } driver_factory; - - enum { STACK_SIZE = 0x2000 }; - static Cap_connection cap; - - static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); - - static Uart::Root uart_root(&ep, env()->heap(), driver_factory); - env()->parent()->announce(ep.manage(&uart_root)); - - sleep_forever(); - return 0; -} diff --git a/repos/os/src/drivers/uart/spec/exynos5/target.mk b/repos/os/src/drivers/uart/spec/exynos5/target.mk index 96a1629949..2d98a508bd 100644 --- a/repos/os/src/drivers/uart/spec/exynos5/target.mk +++ b/repos/os/src/drivers/uart/spec/exynos5/target.mk @@ -1,6 +1,3 @@ -TARGET = uart_drv REQUIRES = exynos5 -SRC_CC = main.cc -LIBS = base config -INC_DIR += $(PRG_DIR) $(REP_DIR)/src/drivers/uart +include $(REP_DIR)/src/drivers/uart/target.inc diff --git a/repos/os/src/drivers/uart/spec/exynos5/uart_driver.h b/repos/os/src/drivers/uart/spec/exynos5/uart_driver.h new file mode 100644 index 0000000000..8001a7f1ae --- /dev/null +++ b/repos/os/src/drivers/uart/spec/exynos5/uart_driver.h @@ -0,0 +1,89 @@ +/* + * \brief Driver for EXYNOS5 UARTs + * \author Stefan Kalkowski + * \author Ivan Loskutov + * \date 2013-06-05 + */ + +/* + * Copyright (C) 2013-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _UART_DRIVER_H_ +#define _UART_DRIVER_H_ + +/* Genode includes */ +#include +#include +#include +#include + +enum { UARTS_NUM = 2 }; /* needed by base class definitions */ + +/* local includes */ +#include + + +class Uart::Driver : public Genode::Attached_io_mem_dataspace, + public Genode::Exynos_uart_base, + public Uart::Driver_base +{ + private: + + enum { BAUD_115200 = 115200 }; + + struct Uart { + Genode::addr_t mmio_base; + Genode::size_t mmio_size; + int irq_number; + }; + + Uart & _config(unsigned index) + { + using namespace Genode; + + static Uart cfg[UARTS_NUM] = { + /* + * temporary workaround having first UART twice + * (most run-scripts have first UART reserved for the kernel) + */ + { Board_base::UART_2_MMIO_BASE, 4096, Board_base::UART_2_IRQ }, + { Board_base::UART_2_MMIO_BASE, 4096, Board_base::UART_2_IRQ }, + }; + return cfg[index]; + } + + unsigned _baud_rate(unsigned baud_rate) + { + if (baud_rate != BAUD_115200) + Genode::warning("baud_rate ", baud_rate, + " not supported, set to default"); + return BAUD_115200; + } + + public: + + Driver(Genode::Env &env, unsigned index, + unsigned baud_rate, Char_avail_functor &func) + : Genode::Attached_io_mem_dataspace(env, _config(index).mmio_base, + _config(index).mmio_size), + Exynos_uart_base((Genode::addr_t)local_addr(), + Genode::Board_base::UART_2_CLOCK, + _baud_rate(baud_rate)), + Driver_base(env, _config(index).irq_number, func) { + _rx_enable(); } + + + /*************************** + ** UART driver interface ** + ***************************/ + + void put_char(char c) override { Exynos_uart_base::put_char(c); } + bool char_avail() override { return _rx_avail(); } + char get_char() override { return _rx_char(); } +}; + +#endif /* _UART_DRIVER_H_ */ diff --git a/repos/os/src/drivers/uart/spec/i8250/main.cc b/repos/os/src/drivers/uart/spec/i8250/main.cc deleted file mode 100644 index e5064a3bac..0000000000 --- a/repos/os/src/drivers/uart/spec/i8250/main.cc +++ /dev/null @@ -1,109 +0,0 @@ -/* - * \brief Driver for PC UARTs - * \author Norman Feske - * \date 2011-09-12 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include - -#include - -#include "i8250.h" -#include "uart_component.h" - - -int main(int argc, char **argv) -{ - using namespace Genode; - - log("--- i8250 UART driver started ---"); - - /** - * Factory used by 'Uart::Root' at session creation/destruction time - */ - struct I8250_driver_factory : Uart::Driver_factory - { - enum { UART_NUM = 4 }; - I8250 *created[UART_NUM]; - - /** - * Return I/O port base for specified UART - */ - static unsigned io_port_base(int index) - { - unsigned port_base[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; - return port_base[index & 0x3]; - } - - /** - * Return irq number for specified UART - */ - static int irq_number(int index) - { - int irq[] = { 4, 3, 4, 3 }; - return irq[index & 0x3]; - } - - /** - * Constructor - */ - I8250_driver_factory() - { - for (unsigned i = 0; i < UART_NUM; i++) - created[i] = 0; - } - - Uart::Driver *create(unsigned index, unsigned baudrate, - Uart::Char_avail_callback &callback) - { - /* - * We assume the underlying kernel uses UART0 and, therefore, start at - * index 1 for the user-level driver. - */ - if (index < 1 || index >= UART_NUM) - throw Uart::Driver_factory::Not_available(); - - enum { BAUD = 115200 }; - if (baudrate == 0) - { - warning("Baudrate is not defined. Use default 115200"); - baudrate = BAUD; - } - - I8250 *uart = created[index]; - - if (!uart) { - uart = new (env()->heap()) - I8250(io_port_base(index), irq_number(index), - baudrate, callback); - - /* update 'created' table */ - created[index] = uart; - } - - return uart; - } - - void destroy(Uart::Driver *driver) { /* TODO */ } - - } driver_factory; - - enum { STACK_SIZE = 0x2000 }; - static Cap_connection cap; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); - - static Uart::Root uart_root(&ep, env()->heap(), driver_factory); - env()->parent()->announce(ep.manage(&uart_root)); - - sleep_forever(); - return 0; -} diff --git a/repos/os/src/drivers/uart/spec/omap4/main.cc b/repos/os/src/drivers/uart/spec/omap4/main.cc deleted file mode 100644 index 27829a33b3..0000000000 --- a/repos/os/src/drivers/uart/spec/omap4/main.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* - * \brief Driver for OMAP4 UARTs - * \author Ivan Loskutov - * \date 2012-11-08 - */ - -/* - * Copyright (C) 2012 Ksys Labs LLC - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include - -#include - -/* local includes */ -#include "omap_uart.h" -#include "uart_component.h" - - -int main(int argc, char **argv) -{ - using namespace Genode; - - log("--- OMAP4 UART driver started ---"); - - /** - * Factory used by 'Terminal::Root' at session creation/destruction time - */ - struct Omap_uart_driver_factory : Uart::Driver_factory - { - Omap_uart *created[UARTS_NUM]; - - /** - * Constructor - */ - Omap_uart_driver_factory() - { - for (unsigned i = 0; i < UARTS_NUM; i++) - created[i] = 0; - } - - Uart::Driver *create(unsigned index, unsigned baudrate, - Uart::Char_avail_callback &callback) - { - if (index > UARTS_NUM) - throw Uart::Driver_factory::Not_available(); - - if (baudrate == 0) - { - warning("Baudrate is not defined. Use default 115200"); - baudrate = BAUD_115200; - } - - Omap_uart_cfg *cfg = &omap_uart_cfg[index]; - Omap_uart *uart = created[index]; - - Genode::Attached_io_mem_dataspace *uart_mmio = new (env()->heap()) - Genode::Attached_io_mem_dataspace(cfg->mmio_base, cfg->mmio_size); - - if (!uart) { - uart = new (env()->heap()) - Omap_uart(uart_mmio, cfg->irq_number, baudrate, callback); - - /* update 'created' table */ - created[index] = uart; - } - - return uart; - } - - void destroy(Uart::Driver *driver) { /* TODO */ } - - } driver_factory; - - enum { STACK_SIZE = 0x2000 }; - static Cap_connection cap; - - static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); - - static Uart::Root uart_root(&ep, env()->heap(), driver_factory); - env()->parent()->announce(ep.manage(&uart_root)); - - sleep_forever(); - return 0; -} diff --git a/repos/os/src/drivers/uart/spec/omap4/omap_uart.h b/repos/os/src/drivers/uart/spec/omap4/omap_uart.h deleted file mode 100644 index edad8e996c..0000000000 --- a/repos/os/src/drivers/uart/spec/omap4/omap_uart.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * \brief Driver for OMAP4 UARTs - * \author Ivan Loskutov - * \date 2012-11-08 - */ - -/* - * Copyright (C) 2012 Ksys Labs LLC - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _DRIVERS__UART__SPEC__OMAP4__OMAP_UART_H_ -#define _DRIVERS__UART__SPEC__OMAP4__OMAP_UART_H_ - -/* Genode includes */ -#include -#include -#include -#include - -#include - -/* local includes */ -#include "uart_driver.h" - -class Omap_uart : public Genode::Tl16c750_base, public Uart::Driver, public Genode::Irq_handler -{ - private: - Genode::Attached_io_mem_dataspace &_uart_mmio; - - Uart::Char_avail_callback &_char_avail_callback; - - enum { IRQ_STACK_SIZE = 4096 }; - Genode::Irq_activation _irq_activation; - - void _enable_rx_interrupt() - { - /* enable access to 'Uart_fcr' and 'Uart_ier' */ - write(Uart_lcr::Reg_mode::OPERATIONAL); - - /* enable rx interrupt, disable other interrupts and sleep mode */ - write(Uart_ier::Rhr_it::bits(1) - | Uart_ier::Thr_it::bits(0) - | Uart_ier::Line_sts_it::bits(0) - | Uart_ier::Modem_sts_it::bits(0) - | Uart_ier::Sleep_mode::bits(0) - | Uart_ier::Xoff_it::bits(0) - | Uart_ier::Rts_it::bits(0) - | Uart_ier::Cts_it::bits(0)); - /* - * Configure protocol formatting and thereby return to - * operational mode. - */ - write(Uart_lcr::Char_length::bits(Uart_lcr::Char_length::_8_BIT) - | Uart_lcr::Nb_stop::bits(Uart_lcr::Nb_stop::_1_STOP_BIT) - | Uart_lcr::Parity_en::bits(0) - | Uart_lcr::Break_en::bits(0) - | Uart_lcr::Div_en::bits(0)); - } - - public: - - /** - * Constructor - */ - Omap_uart(Genode::Attached_io_mem_dataspace *uart_mmio, int irq_number, - unsigned baud_rate, Uart::Char_avail_callback &callback) - : - Tl16c750_base((Genode::addr_t)uart_mmio->local_addr(), Genode::Board_base::TL16C750_CLOCK, baud_rate), - _uart_mmio(*uart_mmio), - _char_avail_callback(callback), - _irq_activation(irq_number, *this, IRQ_STACK_SIZE) - { - _enable_rx_interrupt(); - } - - /** - * * IRQ handler interface ** - */ - void handle_irq(int irq_number) - { - /* inform client about the availability of data */ - unsigned int iir = read(); - if (iir) return; - _char_avail_callback(); - } - - /** - * * UART driver interface ** - */ - void put_char(char c) { Tl16c750_base::put_char(c); } - - bool char_avail() { return read(); } - - char get_char() { return read(); } - - void baud_rate(int bits_per_second) - { - _init(Genode::Board_base::TL16C750_CLOCK, bits_per_second); - _enable_rx_interrupt(); - } -}; - -#endif /* _DRIVERS__UART__SPEC__OMAP4__OMAP_UART_H_ */ diff --git a/repos/os/src/drivers/uart/spec/omap4/target.mk b/repos/os/src/drivers/uart/spec/omap4/target.mk deleted file mode 100644 index 76920bf525..0000000000 --- a/repos/os/src/drivers/uart/spec/omap4/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = uart_drv -REQUIRES = omap4 -SRC_CC = main.cc -LIBS = base config - -INC_DIR += $(PRG_DIR) $(REP_DIR)/src/drivers/uart diff --git a/repos/os/src/drivers/uart/spec/panda/target.mk b/repos/os/src/drivers/uart/spec/panda/target.mk new file mode 100644 index 0000000000..54a945a10d --- /dev/null +++ b/repos/os/src/drivers/uart/spec/panda/target.mk @@ -0,0 +1,3 @@ +REQUIRES = panda + +include $(REP_DIR)/src/drivers/uart/target.inc diff --git a/repos/os/src/drivers/uart/spec/panda/uart_driver.h b/repos/os/src/drivers/uart/spec/panda/uart_driver.h new file mode 100644 index 0000000000..137ce6a29d --- /dev/null +++ b/repos/os/src/drivers/uart/spec/panda/uart_driver.h @@ -0,0 +1,135 @@ +/* + * \brief Driver for OMAP4 UARTs + * \author Ivan Loskutov + * \author Stefan Kalkowski + * \date 2012-11-08 + */ + +/* + * Copyright (C) 2012 Ksys Labs LLC + * Copyright (C) 2011-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _UART_DRIVER_H_ +#define _UART_DRIVER_H_ + +/* Genode includes */ +#include +#include +#include +#include + +enum { UARTS_NUM = 4 }; /* needed by base class definitions */ + +/* local includes */ +#include + +class Uart::Driver : public Genode::Attached_io_mem_dataspace, + public Genode::Tl16c750_base, + public Uart::Driver_base +{ + private: + + void _enable_rx_interrupt() + { + /* enable access to 'Uart_fcr' and 'Uart_ier' */ + write(Uart_lcr::Reg_mode::OPERATIONAL); + + /* enable rx interrupt, disable other interrupts and sleep mode */ + write(Uart_ier::Rhr_it::bits(1) + | Uart_ier::Thr_it::bits(0) + | Uart_ier::Line_sts_it::bits(0) + | Uart_ier::Modem_sts_it::bits(0) + | Uart_ier::Sleep_mode::bits(0) + | Uart_ier::Xoff_it::bits(0) + | Uart_ier::Rts_it::bits(0) + | Uart_ier::Cts_it::bits(0)); + /* + * Configure protocol formatting and thereby return to + * operational mode. + */ + write(Uart_lcr::Char_length::bits(Uart_lcr::Char_length::_8_BIT) + | Uart_lcr::Nb_stop::bits(Uart_lcr::Nb_stop::_1_STOP_BIT) + | Uart_lcr::Parity_en::bits(0) + | Uart_lcr::Break_en::bits(0) + | Uart_lcr::Div_en::bits(0)); + } + + enum { BAUD_115200 = 115200 }; + + struct Uart { + Genode::addr_t mmio_base; + Genode::size_t mmio_size; + int irq_number; + }; + + Uart & _config(unsigned index) + { + using namespace Genode; + + static Uart cfg[UARTS_NUM] = { + { Board_base::TL16C750_1_MMIO_BASE, Board_base::TL16C750_MMIO_SIZE, + Board_base::TL16C750_1_IRQ }, + { Board_base::TL16C750_2_MMIO_BASE, Board_base::TL16C750_MMIO_SIZE, + Board_base::TL16C750_2_IRQ }, + { Board_base::TL16C750_3_MMIO_BASE, Board_base::TL16C750_MMIO_SIZE, + Board_base::TL16C750_3_IRQ }, + { Board_base::TL16C750_4_MMIO_BASE, Board_base::TL16C750_MMIO_SIZE, + Board_base::TL16C750_4_IRQ }, + }; + return cfg[index]; + } + + unsigned _baud_rate(unsigned baud_rate) + { + if (baud_rate != 0) return baud_rate; + + Genode::warning("baud_rate ", baud_rate, + " not supported, set to default"); + return BAUD_115200; + } + + public: + + Driver(Genode::Env &env, unsigned index, + unsigned baud_rate, Char_avail_functor &func) + : Genode::Attached_io_mem_dataspace(env, _config(index).mmio_base, + _config(index).mmio_size), + Tl16c750_base((Genode::addr_t)local_addr(), + Genode::Board_base::TL16C750_CLOCK, + _baud_rate(baud_rate)), + Driver_base(env, _config(index).irq_number, func) { + _enable_rx_interrupt(); } + + + /*************************** + ** UART driver interface ** + ***************************/ + + void handle_irq() override + { + /* check for interrupt */ + unsigned int iir = read(); + if (iir) return; + + /* inform client about the availability of data */ + Driver_base::handle_irq(); + } + + void put_char(char c) override { Tl16c750_base::put_char(c); } + + bool char_avail() override { return read(); } + + char get_char() override { return read(); } + + void baud_rate(int bits_per_second) override + { + _init(Genode::Board_base::TL16C750_CLOCK, bits_per_second); + _enable_rx_interrupt(); + } +}; + +#endif /* _UART_DRIVER_H_ */ diff --git a/repos/os/src/drivers/uart/spec/pbxa9/target.mk b/repos/os/src/drivers/uart/spec/pbxa9/target.mk new file mode 100644 index 0000000000..9e66e7833a --- /dev/null +++ b/repos/os/src/drivers/uart/spec/pbxa9/target.mk @@ -0,0 +1,3 @@ +REQUIRES = pbxa9 + +include $(REP_DIR)/src/drivers/uart/target.inc diff --git a/repos/os/src/drivers/uart/spec/pbxa9/uart_driver.h b/repos/os/src/drivers/uart/spec/pbxa9/uart_driver.h new file mode 100644 index 0000000000..c74cb1d108 --- /dev/null +++ b/repos/os/src/drivers/uart/spec/pbxa9/uart_driver.h @@ -0,0 +1,205 @@ +/* + * \brief Pbxa9 UART driver + * \author Christian Helmuth + * \author Stefan Kalkowski + * \date 2011-05-27 + */ + +/* + * Copyright (C) 2011-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _UART_DRIVER_H_ +#define _UART_DRIVER_H_ + +/* Genode includes */ +#include +#include +#include + +enum { UARTS_NUM = 4 }; /* needed by base class definitions */ + +/* local includes */ +#include + +class Uart::Driver : public Genode::Attached_io_mem_dataspace, + public Uart::Driver_base +{ + private: + + enum { + + /** + * MMIO regions + */ + PL011_PHYS0 = 0x10009000, /* base for UART 0 */ + PL011_PHYS1 = 0x1000a000, /* base for UART 1 */ + PL011_PHYS2 = 0x1000b000, /* base for UART 2 */ + PL011_PHYS3 = 0x1000c000, /* base for UART 3 */ + PL011_SIZE = 0x1000, /* size of each MMIO region */ + + /** + * Interrupt lines + */ + PL011_IRQ0 = Genode::Board_base::PL011_0_IRQ, /* UART 0 */ + PL011_IRQ1 = Genode::Board_base::PL011_1_IRQ, /* UART 1 */ + PL011_IRQ2 = Genode::Board_base::PL011_2_IRQ, /* UART 2 */ + PL011_IRQ3 = Genode::Board_base::PL011_3_IRQ, /* UART 3 */ + + /** + * UART baud rate configuration (precalculated) + * + * div = 24000000 / 16 / baud rate + * IBRD = floor(div) + * FBRD = floor((div - IBRD) * 64 + 0.5) + */ + PL011_IBRD_115200 = 13, PL011_FBRD_115200 = 1, + PL011_IBRD_19200 = 78, PL011_FBRD_19200 = 8, + PL011_IBRD_9600 = 156, PL011_FBRD_9600 = 16, + + BAUD_115200 = 115200 + }; + + struct Uart { + Genode::addr_t mmio_base; + Genode::size_t mmio_size; + int irq_number; + }; + + Uart & _config(unsigned index) + { + using namespace Genode; + + static Uart cfg[UARTS_NUM] = { + { PL011_PHYS0, PL011_SIZE, PL011_IRQ0 }, + { PL011_PHYS1, PL011_SIZE, PL011_IRQ1 }, + { PL011_PHYS2, PL011_SIZE, PL011_IRQ2 }, + { PL011_PHYS3, PL011_SIZE, PL011_IRQ3 }, + }; + return cfg[index]; + } + + + /* + * Constants for flags, registers, etc. only visible in this file are + * named as in the specification documents to relieve correlation + * between implementation and specification. + */ + + /** + * Register offsets + * + * Registers are read/writable unless explicitly stated. + */ + enum Register { + UARTDR = 0x000, /* data */ + UARTFR = 0x018, /* flags (read-only) */ + UARTIBRD = 0x024, /* integer baud rate divisor */ + UARTFBRD = 0x028, /* fractional baud rate divisor */ + UARTLCR_H = 0x02c, /* line control */ + UARTCR = 0x030, /* control */ + UARTIMSC = 0x038, /* interrupt mask register */ + UARTICR = 0x044, /* interrupt clear register */ + }; + + /** + * Flags + */ + enum Flag { + /* flag register */ + UARTFR_BUSY = 0x0008, /* busy on tx */ + UARTFR_TXFF = 0x0020, /* tx FIFO full */ + UARTFR_RXFE = 0x0010, /* rx FIFO empty */ + + /* line control register */ + UARTLCR_H_FEN = 0x0010, /* enable FIFOs */ + UARTLCR_H_WLEN_8 = 0x0060, /* 8 bit word length */ + + /* control register */ + UARTCR_UARTEN = 0x0001, /* enable uart */ + UARTCR_TXE = 0x0100, /* enable tx */ + UARTCR_RXE = 0x0200, /* enable rx */ + + /* interrupt mask register */ + UARTIMSC_RXIM = 0x10, /* rx interrupt mask */ + + /* interrupt clear register */ + UARTICR_RXIC = 0x10, /* rx interrupt clear */ + }; + + Genode::uint32_t volatile *_base; + + Genode::uint32_t _read_reg(Register reg) const { + return _base[reg >> 2]; } + + void _write_reg(Register reg, Genode::uint32_t v) { + _base[reg >> 2] = v; } + + public: + + Driver(Genode::Env &env, unsigned index, + unsigned baud_rate, Char_avail_functor &func) + : Genode::Attached_io_mem_dataspace(env, _config(index).mmio_base, + _config(index).mmio_size), + Driver_base(env, _config(index).irq_number, func), + _base(local_addr()) + { + if (baud_rate != BAUD_115200) + Genode::warning("baud_rate ", baud_rate, + " not supported, set to default"); + + /* disable and flush uart */ + _write_reg(UARTCR, 0); + while (_read_reg(UARTFR) & UARTFR_BUSY) ; + _write_reg(UARTLCR_H, 0); + + /* set baud-rate divisor */ + _write_reg(UARTIBRD, PL011_IBRD_115200); + _write_reg(UARTFBRD, PL011_FBRD_115200); + + /* enable FIFOs, 8-bit words */ + _write_reg(UARTLCR_H, UARTLCR_H_FEN | UARTLCR_H_WLEN_8); + + /* enable transmission */ + _write_reg(UARTCR, UARTCR_TXE); + + /* enable uart */ + _write_reg(UARTCR, _read_reg(UARTCR) | UARTCR_UARTEN); + + /* enable rx interrupt */ + _write_reg(UARTIMSC, UARTIMSC_RXIM); + } + + + /*************************** + ** UART driver interface ** + ***************************/ + + void handle_irq() override + { + /* inform client about the availability of data */ + Driver_base::handle_irq(); + + /* acknowledge irq */ + _write_reg(UARTICR, UARTICR_RXIC); + } + + void put_char(char c) override + { + /* spin while FIFO full */ + while (_read_reg(UARTFR) & UARTFR_TXFF) ; + + _write_reg(UARTDR, c); + } + + bool char_avail() override { + return !(_read_reg(UARTFR) & UARTFR_RXFE); } + + char get_char() override { + return _read_reg(UARTDR); } +}; + +#endif /* _UART_DRIVER_H_ */ diff --git a/repos/os/src/drivers/uart/spec/pl011/calc_brd_values.py b/repos/os/src/drivers/uart/spec/pl011/calc_brd_values.py deleted file mode 100755 index df54794b52..0000000000 --- a/repos/os/src/drivers/uart/spec/pl011/calc_brd_values.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/python - -from math import floor - -clock = 24000000 -bauds = [ 9600, 14400, 19200, 38400, 115200 ] - -print "Clock Desired IBRD FBRD Real" -print " MHz baud rate baud rate" -for baud in bauds: - div = clock / 16.0 / baud - ibrd = int(floor(div)) - fbrd = int(floor((div - ibrd) * 64 + 0.5)) - baud_ = clock / 16.0 / (ibrd + fbrd / 64.0) - - print "% 4d % 8d % 4d % 3d % 10.2f" % (clock / 1000000, baud, ibrd, fbrd, baud_) diff --git a/repos/os/src/drivers/uart/spec/pl011/main.cc b/repos/os/src/drivers/uart/spec/pl011/main.cc deleted file mode 100644 index e162f96726..0000000000 --- a/repos/os/src/drivers/uart/spec/pl011/main.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* - * \brief Driver for PL011 UARTs - * \author Christian Helmuth - * \date 2011-05-30 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* local includes */ -#include "pl011.h" -#include "uart_component.h" - - -int main(int argc, char **argv) -{ - using namespace Genode; - - log("--- PL011 UART driver started ---"); - - /** - * Factory used by 'Uart::Root' at session creation/destruction time - */ - struct Pl011_driver_factory : Uart::Driver_factory - { - Pl011 *created[PL011_NUM]; - - /** - * Constructor - */ - Pl011_driver_factory() - { - for (unsigned i = 0; i < PL011_NUM; i++) - created[i] = 0; - } - - Uart::Driver *create(unsigned index, unsigned /* baudrate */, - Uart::Char_avail_callback &callback) - { - warning("Setting baudrate is not supported yet. Use default 115200."); - - /* - * We assume the underlying kernel uses UART0 and, therefore, start at - * index 1 for the user-level driver. - */ - if (index < 1 || index >= PL011_NUM) - throw Uart::Driver_factory::Not_available(); - - Pl011_uart *cfg = &pl011_uart[index]; - Pl011 *uart = created[index]; - - if (!uart) { - uart = new (env()->heap()) - Pl011(cfg->mmio_base, cfg->mmio_size, - PL011_IBRD_115200, PL011_FBRD_115200, - cfg->irq_number, callback); - - /* update 'created' table */ - created[index] = uart; - } - - return uart; - } - - void destroy(Uart::Driver *driver) { /* TODO */ } - - } driver_factory; - - enum { STACK_SIZE = 0x2000 }; - static Cap_connection cap; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); - - static Uart::Root uart_root(&ep, env()->heap(), driver_factory); - env()->parent()->announce(ep.manage(&uart_root)); - - sleep_forever(); - return 0; -} diff --git a/repos/os/src/drivers/uart/spec/pl011/pl011.h b/repos/os/src/drivers/uart/spec/pl011/pl011.h deleted file mode 100644 index 6c42359515..0000000000 --- a/repos/os/src/drivers/uart/spec/pl011/pl011.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * \brief PL011 UART driver - * \author Christian Helmuth - * \date 2011-05-27 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _DRIVERS__UART__SPEC__PL011__PL011_H_ -#define _DRIVERS__UART__SPEC__PL011__PL011_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* local includes */ -#include "uart_driver.h" - -class Pl011 : public Uart::Driver, public Genode::Irq_handler -{ - private: - - /* - * Constants for flags, registers, etc. only visible in this file are - * named as in the specification documents to relieve correlation - * between implementation and specification. - */ - - /** - * Register offsets - * - * Registers are read/writable unless explicitly stated. - */ - enum Register { - UARTDR = 0x000, /* data */ - UARTFR = 0x018, /* flags (read-only) */ - UARTIBRD = 0x024, /* integer baud rate divisor */ - UARTFBRD = 0x028, /* fractional baud rate divisor */ - UARTLCR_H = 0x02c, /* line control */ - UARTCR = 0x030, /* control */ - UARTIMSC = 0x038, /* interrupt mask register */ - UARTICR = 0x044, /* interrupt clear register */ - }; - - /** - * Flags - */ - enum Flag { - /* flag register */ - UARTFR_BUSY = 0x0008, /* busy on tx */ - UARTFR_TXFF = 0x0020, /* tx FIFO full */ - UARTFR_RXFE = 0x0010, /* rx FIFO empty */ - - /* line control register */ - UARTLCR_H_FEN = 0x0010, /* enable FIFOs */ - UARTLCR_H_WLEN_8 = 0x0060, /* 8 bit word length */ - - /* control register */ - UARTCR_UARTEN = 0x0001, /* enable uart */ - UARTCR_TXE = 0x0100, /* enable tx */ - UARTCR_RXE = 0x0200, /* enable rx */ - - /* interrupt mask register */ - UARTIMSC_RXIM = 0x10, /* rx interrupt mask */ - - /* interrupt clear register */ - UARTICR_RXIC = 0x10, /* rx interrupt clear */ - }; - - Genode::Attached_io_mem_dataspace _io_mem; - Genode::uint32_t volatile *_base; - - Uart::Char_avail_callback &_char_avail_callback; - - enum { IRQ_STACK_SIZE = 4096 }; - Genode::Irq_activation _irq_activation; - - Genode::uint32_t _read_reg(Register reg) const - { - return _base[reg >> 2]; - } - - void _write_reg(Register reg, Genode::uint32_t v) - { - _base[reg >> 2] = v; - } - - public: - - /** - * Constructor - */ - Pl011(Genode::addr_t mmio_base, Genode::size_t mmio_size, - unsigned ibrd, unsigned fbrd, int irq_number, - Uart::Char_avail_callback &callback) - : - _io_mem(mmio_base, mmio_size), - _base(_io_mem.local_addr()), - _char_avail_callback(callback), - _irq_activation(irq_number, *this, IRQ_STACK_SIZE) - { - /* disable and flush uart */ - _write_reg(UARTCR, 0); - while (_read_reg(UARTFR) & UARTFR_BUSY) ; - _write_reg(UARTLCR_H, 0); - - /* set baud-rate divisor */ - _write_reg(UARTIBRD, ibrd); - _write_reg(UARTFBRD, fbrd); - - /* enable FIFOs, 8-bit words */ - _write_reg(UARTLCR_H, UARTLCR_H_FEN | UARTLCR_H_WLEN_8); - - /* enable transmission */ - _write_reg(UARTCR, UARTCR_TXE); - - /* enable uart */ - _write_reg(UARTCR, _read_reg(UARTCR) | UARTCR_UARTEN); - - /* enable rx interrupt */ - _write_reg(UARTIMSC, UARTIMSC_RXIM); - } - - /*************************** - ** IRQ handler interface ** - ***************************/ - - void handle_irq(int irq_number) - { - /* inform client about the availability of data */ - _char_avail_callback(); - - /* acknowledge irq */ - _write_reg(UARTICR, UARTICR_RXIC); - } - - /*************************** - ** UART driver interface ** - ***************************/ - - void put_char(char c) - { - /* spin while FIFO full */ - while (_read_reg(UARTFR) & UARTFR_TXFF) ; - - _write_reg(UARTDR, c); - } - - bool char_avail() - { - return !(_read_reg(UARTFR) & UARTFR_RXFE); - } - - char get_char() - { - return _read_reg(UARTDR); - } -}; - -#endif /* _DRIVERS__UART__SPEC__PL011__PL011_H_ */ diff --git a/repos/os/src/drivers/uart/spec/pl011/target.mk b/repos/os/src/drivers/uart/spec/pl011/target.mk deleted file mode 100644 index f17288bc60..0000000000 --- a/repos/os/src/drivers/uart/spec/pl011/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = uart_drv -REQUIRES = pl011 -SRC_CC = main.cc -LIBS = base config - -INC_DIR += $(PRG_DIR) $(REP_DIR)/src/drivers/uart diff --git a/repos/os/src/drivers/uart/spec/x86/target.mk b/repos/os/src/drivers/uart/spec/x86/target.mk new file mode 100644 index 0000000000..7cd5fb431e --- /dev/null +++ b/repos/os/src/drivers/uart/spec/x86/target.mk @@ -0,0 +1,3 @@ +REQUIRES = x86 + +include $(REP_DIR)/src/drivers/uart/target.inc diff --git a/repos/os/src/drivers/uart/spec/i8250/i8250.h b/repos/os/src/drivers/uart/spec/x86/uart_driver.h similarity index 58% rename from repos/os/src/drivers/uart/spec/i8250/i8250.h rename to repos/os/src/drivers/uart/spec/x86/uart_driver.h index 2faf56c745..6add7af050 100644 --- a/repos/os/src/drivers/uart/spec/i8250/i8250.h +++ b/repos/os/src/drivers/uart/spec/x86/uart_driver.h @@ -1,38 +1,55 @@ /* * \brief i8250 UART driver * \author Norman Feske + * \author Stefan Kalkowski * \date 2011-09-12 */ /* - * Copyright (C) 2011-2013 Genode Labs GmbH + * Copyright (C) 2011-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ -#ifndef _DRIVERS__UART__SPEC__I8250__I8250_H_ -#define _DRIVERS__UART__SPEC__I8250__I8250_H_ +#ifndef _UART_DRIVER_H_ +#define _UART_DRIVER_H_ /* Genode includes */ #include -#include -#include -#include #include +enum { UARTS_NUM = 4 }; /* needed by base class definitions */ + /* local includes */ -#include +#include - -class I8250 : public Uart::Driver, public Genode::Irq_handler +class Uart::Driver : public Uart::Driver_base { private: - unsigned _port_base; - + unsigned _port_base; Genode::Io_port_connection _io_port; + /** + * Return I/O port base for specified UART + */ + static unsigned _io_port_base(int index) + { + static unsigned port_base[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; + return port_base[index & 0x3]; + } + + /** + * Return irq number for specified UART + */ + static int _irq_number(int index) + { + static int irq[] = { 4, 3, 4, 3 }; + Genode::log("open IRQ ", irq[index & 0x3], "\n"); + return irq[index & 0x3]; + } + /** * Register offsets relative to '_port_base' */ @@ -48,6 +65,8 @@ class I8250 : public Uart::Driver, public Genode::Irq_handler DLHI = 1, }; + enum { BAUD_115200 = 115200 }; + /** * Read byte from i8250 register */ @@ -84,42 +103,29 @@ class I8250 : public Uart::Driver, public Genode::Irq_handler _inb(); } - Uart::Char_avail_callback &_char_avail_callback; - - enum { IRQ_STACK_SIZE = 4096 }; - Genode::Irq_activation _irq_activation; + unsigned _baud_rate(unsigned baud_rate) + { + if (baud_rate != BAUD_115200) + Genode::warning("baud_rate ", baud_rate, + " not supported, set to default\n"); + return BAUD_115200; + } public: - /** - * Constructor - */ - I8250(unsigned port_base, int irq_number, unsigned baud, - Uart::Char_avail_callback &callback) - : - _port_base(port_base), - _io_port(port_base, 0xf), - _char_avail_callback(callback), - _irq_activation(irq_number, *this, IRQ_STACK_SIZE) - { - _init_comport(baud); - } + Driver(Genode::Env &env, unsigned index, unsigned baud, + Uart::Char_avail_functor &func) + : Driver_base(env, _irq_number(index), func), + _port_base(_io_port_base(index)), + _io_port(_port_base, 0xf) { + _init_comport(_baud_rate(baud)); } - /*************************** - ** IRQ handler interface ** - ***************************/ - - void handle_irq(int irq_number) - { - /* inform client about the availability of data */ - _char_avail_callback(); - } /*************************** ** UART driver interface ** ***************************/ - void put_char(char c) + void put_char(char c) override { /* wait until serial port is ready */ while (!(_inb() & 0x60)); @@ -128,20 +134,20 @@ class I8250 : public Uart::Driver, public Genode::Irq_handler _outb(c); } - bool char_avail() + bool char_avail() override { return _inb() & 1; } - char get_char() + char get_char() override { return _inb(); } - void baud_rate(int bits_per_second) + void baud_rate(int bits_per_second) override { _init_comport(bits_per_second); } }; -#endif /* _DRIVERS__UART__SPEC__I8250__I8250_H_ */ +#endif /* _UART_DRIVER_H_ */ diff --git a/repos/os/src/drivers/uart/spec/i8250/target.mk b/repos/os/src/drivers/uart/target.inc similarity index 60% rename from repos/os/src/drivers/uart/spec/i8250/target.mk rename to repos/os/src/drivers/uart/target.inc index 9eb30f492a..25e71f6269 100644 --- a/repos/os/src/drivers/uart/spec/i8250/target.mk +++ b/repos/os/src/drivers/uart/target.inc @@ -1,6 +1,7 @@ TARGET = uart_drv -REQUIRES = x86 SRC_CC = main.cc -LIBS = base config +LIBS = base INC_DIR += $(PRG_DIR) $(REP_DIR)/src/drivers/uart + +vpath main.cc $(REP_DIR)/src/drivers/uart diff --git a/repos/os/src/drivers/uart/uart_component.h b/repos/os/src/drivers/uart/uart_component.h index 93f772841d..6b041946d3 100644 --- a/repos/os/src/drivers/uart/uart_component.h +++ b/repos/os/src/drivers/uart/uart_component.h @@ -1,11 +1,12 @@ /* * \brief UART LOG component * \author Christian Helmuth + * \author Stefan Kalkowski * \date 2011-05-30 */ /* - * Copyright (C) 2011-2013 Genode Labs GmbH + * Copyright (C) 2011-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -15,247 +16,236 @@ #define _UART_COMPONENT_H_ /* Genode includes */ +#include +#include #include #include #include -#include #include #include /* local includes */ -#include "uart_driver.h" +#include namespace Uart { using namespace Genode; - class Session_component : public Rpc_object - { - private: - - /* - * XXX Do not use hard-coded value, better make it dependent - * on the RAM quota donated by the client. - */ - enum { IO_BUFFER_SIZE = 4096 }; - - Genode::Attached_ram_dataspace _io_buffer; - - /** - * Functor informing the client about new data to read - */ - struct Char_avail_callback : Uart::Char_avail_callback - { - Genode::Signal_context_capability sigh; - - void operator ()() - { - if (sigh.valid()) - Genode::Signal_transmitter(sigh).submit(); - } - - } _char_avail_callback; - - Uart::Driver_factory &_driver_factory; - Uart::Driver &_driver; - - Size _size; - - unsigned char _poll_char() - { - while (!_driver.char_avail()); - return _driver.get_char(); - } - - void _put_string(char const *s) - { - for (; *s; s++) - _driver.put_char(*s); - } - - /** - * Read ASCII number from UART - * - * \return character that terminates the sequence of digits - */ - unsigned char _read_number(unsigned &result) - { - result = 0; - - for (;;) { - unsigned char c = _poll_char(); - - if (!is_digit(c)) - return c; - - result = result*10 + digit(c); - } - } - - /** - * Try to detect the size of the terminal - */ - Size _detect_size() - { - /* - * Set cursor position to (hopefully) exceed the terminal - * dimensions. - */ - _put_string("\033[1;199r\033[199;255H"); - - /* flush incoming characters */ - for (; _driver.char_avail(); _driver.get_char()); - - /* request cursor coordinates */ - _put_string("\033[6n"); - - unsigned width = 0, height = 0; - - if (_poll_char() == 27 - && _poll_char() == '[' - && _read_number(height) == ';' - && _read_number(width) == 'R') { - - Genode::log("detected terminal size ", width, "x", height); - return Size(width, height); - } - - return Size(0, 0); - } - - public: - - /** - * Constructor - */ - Session_component(Uart::Driver_factory &driver_factory, - unsigned index, unsigned baudrate, bool detect_size) - : - _io_buffer(Genode::env()->ram_session(), IO_BUFFER_SIZE), - _driver_factory(driver_factory), - _driver(*_driver_factory.create(index, baudrate, _char_avail_callback)), - _size(detect_size ? _detect_size() : Size(0, 0)) - { } - - - /**************************** - ** Uart session interface ** - ****************************/ - - void baud_rate(Genode::size_t bits_per_second) - { - _driver.baud_rate(bits_per_second); - } - - - /******************************** - ** Terminal session interface ** - ********************************/ - - Size size() { return _size; } - - bool avail() { return _driver.char_avail(); } - - Genode::size_t _read(Genode::size_t dst_len) - { - char *io_buf = _io_buffer.local_addr(); - Genode::size_t sz = Genode::min(dst_len, _io_buffer.size()); - - Genode::size_t n = 0; - while ((n < sz) && _driver.char_avail()) - io_buf[n++] = _driver.get_char(); - - return n; - } - - void _write(Genode::size_t num_bytes) - { - /* constain argument to I/O buffer size */ - num_bytes = Genode::min(num_bytes, _io_buffer.size()); - - char const *io_buf = _io_buffer.local_addr(); - for (Genode::size_t i = 0; i < num_bytes; i++) - _driver.put_char(io_buf[i]); - } - - Genode::Dataspace_capability _dataspace() - { - return _io_buffer.cap(); - } - - void connected_sigh(Genode::Signal_context_capability sigh) - { - /* - * Immediately reflect connection-established signal to the - * client because the session is ready to use immediately after - * creation. - */ - Genode::Signal_transmitter(sigh).submit(); - } - - void read_avail_sigh(Genode::Signal_context_capability sigh) - { - _char_avail_callback.sigh = sigh; - - if (_driver.char_avail()) - _char_avail_callback(); - } - - Genode::size_t read(void *, Genode::size_t) { return 0; } - Genode::size_t write(void const *, Genode::size_t) { return 0; } - }; - + class Session_component; + class Root; typedef Root_component Root_component; +}; - class Root : public Root_component - { - private: +class Uart::Session_component : public Rpc_object +{ + private: - Driver_factory &_driver_factory; + /* + * XXX Do not use hard-coded value, better make it dependent + * on the RAM quota donated by the client. + */ + enum { IO_BUFFER_SIZE = 4096 }; - protected: + Genode::Attached_ram_dataspace _io_buffer; - Session_component *_create_session(const char *args) - { - try { - Session_label label = label_from_args(args); - Session_policy policy(label); + /** + * Functor informing the client about new data to read + */ + Char_avail_functor _char_avail; + Uart::Driver_factory &_driver_factory; + Uart::Driver &_driver; - unsigned index = 0; - policy.attribute("uart").value(&index); + Size _size; - unsigned baudrate = 0; - try { - policy.attribute("baudrate").value(&baudrate); - } catch (Xml_node::Nonexistent_attribute) { } + unsigned char _poll_char() + { + while (!_driver.char_avail()); + return _driver.get_char(); + } - bool detect_size = policy.attribute_value("detect_size", false); + void _put_string(char const *s) + { + for (; *s; s++) + _driver.put_char(*s); + } - return new (md_alloc()) - Session_component(_driver_factory, index, baudrate, detect_size); + /** + * Read ASCII number from UART + * + * \return character that terminates the sequence of digits + */ + unsigned char _read_number(unsigned &result) + { + result = 0; - } catch (Xml_node::Nonexistent_attribute) { - Genode::error("Missing \"uart\" attribute in policy definition"); - throw Root::Unavailable(); - } catch (Session_policy::No_policy_defined) { - Genode::error("Invalid session request, no matching policy"); - throw Root::Unavailable(); - } + for (;;) { + unsigned char c = _poll_char(); + + if (!is_digit(c)) + return c; + + result = result*10 + digit(c); + } + } + + /** + * Try to detect the size of the terminal + */ + Size _detect_size() + { + /* + * Set cursor position to (hopefully) exceed the terminal + * dimensions. + */ + _put_string("\033[1;199r\033[199;255H"); + + /* flush incoming characters */ + for (; _driver.char_avail(); _driver.get_char()); + + /* request cursor coordinates */ + _put_string("\033[6n"); + + unsigned width = 0, height = 0; + + if (_poll_char() == 27 + && _poll_char() == '[' + && _read_number(height) == ';' + && _read_number(width) == 'R') { + + Genode::log("detected terminal size ", width, "x", height); + return Size(width, height); } - public: + return Size(0, 0); + } - /** - * Constructor + public: + + /** + * Constructor + */ + Session_component(Env &env, Uart::Driver_factory &driver_factory, + unsigned index, unsigned baudrate, bool detect_size) + : + _io_buffer(env.ram(), env.rm(), IO_BUFFER_SIZE), + _driver_factory(driver_factory), + _driver(_driver_factory.create(index, baudrate, _char_avail)), + _size(detect_size ? _detect_size() : Size(0, 0)) + { } + + + /**************************** + ** Uart session interface ** + ****************************/ + + void baud_rate(Genode::size_t bits_per_second) + { + _driver.baud_rate(bits_per_second); + } + + + /******************************** + ** Terminal session interface ** + ********************************/ + + Size size() { return _size; } + + bool avail() { return _driver.char_avail(); } + + Genode::size_t _read(Genode::size_t dst_len) + { + char *io_buf = _io_buffer.local_addr(); + Genode::size_t sz = Genode::min(dst_len, _io_buffer.size()); + + Genode::size_t n = 0; + while ((n < sz) && _driver.char_avail()) + io_buf[n++] = _driver.get_char(); + + return n; + } + + void _write(Genode::size_t num_bytes) + { + /* constain argument to I/O buffer size */ + num_bytes = Genode::min(num_bytes, _io_buffer.size()); + + char const *io_buf = _io_buffer.local_addr(); + for (Genode::size_t i = 0; i < num_bytes; i++) + _driver.put_char(io_buf[i]); + } + + Genode::Dataspace_capability _dataspace() { + return _io_buffer.cap(); } + + void connected_sigh(Genode::Signal_context_capability sigh) + { + /* + * Immediately reflect connection-established signal to the + * client because the session is ready to use immediately after + * creation. */ - Root(Rpc_entrypoint *ep, Allocator *md_alloc, Driver_factory &driver_factory) - : - Root_component(ep, md_alloc), _driver_factory(driver_factory) - { } - }; -} + Genode::Signal_transmitter(sigh).submit(); + } + + void read_avail_sigh(Genode::Signal_context_capability sigh) + { + _char_avail.sigh = sigh; + + if (_driver.char_avail()) _char_avail(); + } + + Genode::size_t read(void *, Genode::size_t) { return 0; } + Genode::size_t write(void const *, Genode::size_t) { return 0; } +}; + + +class Uart::Root : public Uart::Root_component +{ + private: + + Env &_env; + Driver_factory &_driver_factory; + Attached_rom_dataspace _config { _env, "config" }; + + protected: + + Session_component *_create_session(const char *args) + { + try { + Session_label label = label_from_args(args); + Session_policy policy(label, _config.xml()); + + unsigned index = 0; + policy.attribute("uart").value(&index); + + unsigned baudrate = 0; + try { + policy.attribute("baudrate").value(&baudrate); + } catch (Xml_node::Nonexistent_attribute) { } + + bool detect_size = policy.attribute_value("detect_size", false); + + return new (md_alloc()) + Session_component(_env, _driver_factory, index, + baudrate, detect_size); + + } catch (Xml_node::Nonexistent_attribute) { + Genode::error("Missing \"uart\" attribute in policy definition"); + throw Root::Unavailable(); + } catch (Session_policy::No_policy_defined) { + Genode::error("Invalid session request, no matching policy"); + throw Root::Unavailable(); + } + } + + public: + + Root(Env &env, Allocator &md_alloc, Driver_factory &driver_factory) + : Root_component(env.ep(), md_alloc), _env(env), + _driver_factory(driver_factory) { } +}; #endif /* _UART_COMPONENT_H_ */ diff --git a/repos/os/src/drivers/uart/uart_driver.h b/repos/os/src/drivers/uart/uart_driver.h deleted file mode 100644 index d194ea9798..0000000000 --- a/repos/os/src/drivers/uart/uart_driver.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * \brief UART driver interface - * \author Christian Helmuth - * \date 2011-05-30 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _UART_DRIVER_H_ -#define _UART_DRIVER_H_ - -namespace Uart { - - /** - * Functor, called by 'Driver' when data is ready for reading - */ - struct Char_avail_callback - { - virtual void operator()() { } - }; - - struct Driver - { - /** - * Write character to UART - */ - virtual void put_char(char c) = 0; - - /** - * Return true if character is available for reading - */ - virtual bool char_avail() = 0; - - /** - * Read character from UART - */ - virtual char get_char() = 0; - - /** - * Set baud rate for terminal - */ - virtual void baud_rate(int /*bits_per_second*/) - { - Genode::warning("Setting baudrate is not supported yet. Use default 115200."); - } - }; - - /** - * Interface for constructing the driver objects - */ - struct Driver_factory - { - struct Not_available { }; - - /** - * Construct new driver - * - * \param index index of UART to access - * \param baudrate baudrate of UART - * \param callback functor called when data becomes available for - * reading - * - * \throws Uart_not_available - * - * Note that the 'callback' is called in the context of the IRQ - * handler. Hence, the operations performed by the registered - * function must be properly synchronized. - */ - virtual Driver *create(unsigned index, unsigned baudrate, Char_avail_callback &callback) = 0; - - /** - * Destroy driver - */ - virtual void destroy(Driver *driver) = 0; - }; - -} - -#endif /* _UART_DRIVER_H_ */ diff --git a/repos/os/src/drivers/uart/uart_driver_base.h b/repos/os/src/drivers/uart/uart_driver_base.h new file mode 100644 index 0000000000..68d8c4a88d --- /dev/null +++ b/repos/os/src/drivers/uart/uart_driver_base.h @@ -0,0 +1,135 @@ +/* + * \brief UART driver interface + * \author Christian Helmuth + * \author Stefan Kalkowski + * \date 2011-05-30 + */ + +/* + * Copyright (C) 2011-2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _UART_DRIVER_BASE_H_ +#define _UART_DRIVER_BASE_H_ + +#include + +namespace Uart { + class Driver_base; + class Driver; + struct Driver_factory; + struct Char_avail_functor; +}; + + +/** + * Functor, called by 'Driver' when data is ready for reading + */ +struct Uart::Char_avail_functor +{ + Genode::Signal_context_capability sigh; + + void operator ()() { + if (sigh.valid()) Genode::Signal_transmitter(sigh).submit(); } + +}; + + +class Uart::Driver_base +{ + private: + + Char_avail_functor &_char_avail; + Genode::Irq_connection _irq; + Genode::Signal_handler _irq_handler; + + public: + + Driver_base(Genode::Env &env, int irq_number, Char_avail_functor &func) + : _char_avail(func), + _irq(env, irq_number), + _irq_handler(env.ep(), *this, &Driver_base::handle_irq) + { + _irq.sigh(_irq_handler); + _irq.ack_irq(); + } + + virtual ~Driver_base() {} + + /** + * Handle interrupt + */ + virtual void handle_irq() + { + _char_avail(); + _irq.ack_irq(); + } + + /** + * Write character to UART + */ + virtual void put_char(char c) = 0; + + /** + * Return true if character is available for reading + */ + virtual bool char_avail() = 0; + + /** + * Read character from UART + */ + virtual char get_char() = 0; + + /** + * Set baud rate for terminal + */ + virtual void baud_rate(int baud) + { + Genode::warning("Setting baudrate to ", baud, + " is not supported. Use default value."); + } +}; + + +/** + * Interface for constructing the driver objects + */ +struct Uart::Driver_factory +{ + struct Not_available { }; + + Genode::Env &env; + Genode::Heap &heap; + Driver *drivers[UARTS_NUM]; + + Driver_factory(Genode::Env &env, Genode::Heap &heap) + : env(env), heap(heap) { + for (unsigned i = 0; i < UARTS_NUM; i++) drivers[i] = 0; } + + /** + * Construct new driver + * + * \param index index of UART to access + * \param baudrate baudrate of UART + * \param functor functor called when data becomes available for + * reading + * + * \throws Uart_not_available + * + * Note that the 'callback' is called in the context of the IRQ + * handler. Hence, the operations performed by the registered + * function must be properly synchronized. + */ + Driver &create(unsigned index, unsigned baudrate, + Char_avail_functor &functor); + + /** + * Destroy driver + */ + void destroy(Driver &driver) { /* TODO */ } +}; + +#endif /* _UART_DRIVER_BASE_H_ */