mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +00:00
uart_drv: transition to new base API
* Unify uart drivers of different hardware drivers * Remove deprecated IRQ activations * Remove additional timer thread in Fiasco* KDB driver * Move more generic UART definitions to specific supported platforms (e.g.: pl011 -> pbxa9) * Move internal definitions from global to local headers Ref #1987 Fix #2071
This commit is contained in:
parent
a75684d217
commit
f1535b2481
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* \brief EXYNOS5 UART definitions
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \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 <drivers/board_base.h>
|
||||
|
||||
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_ */
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* \brief OMAP4 UART definitions
|
||||
* \author Ivan Loskutov <ivan.loskutov@ksyslabs.org>
|
||||
* \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 <spec/panda/drivers/board_base.h>
|
||||
|
||||
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_ */
|
@ -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 <base/stdint.h>
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
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_ */
|
@ -46,9 +46,7 @@ set config {
|
||||
</provides>
|
||||
<config>
|
||||
<policy label="test-uart1" uart="1"/>
|
||||
<policy label="test-uart2" uart="2"/>
|
||||
<policy label="test-uart3" uart="3"/>
|
||||
<policy label="test-uart4" uart="1"/>
|
||||
<policy label="test-uart2" uart="1"/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="test-uart1">
|
||||
@ -59,14 +57,6 @@ set config {
|
||||
<binary name="test-uart"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
<start name="test-uart3">
|
||||
<binary name="test-uart"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
<start name="test-uart4">
|
||||
<binary name="test-uart"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
|
@ -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 <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* 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<STACK_SIZE>
|
||||
{
|
||||
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<STACK_SIZE>("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<Lock> 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_ */
|
@ -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 <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
#include <cap_session/connection.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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
|
||||
|
130
repos/os/src/drivers/uart/kdb/uart_driver.h
Normal file
130
repos/os/src/drivers/uart/kdb/uart_driver.h
Normal file
@ -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 <l4/sys/kdebug.h>
|
||||
}
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/signal.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
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<Driver> _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_ */
|
52
repos/os/src/drivers/uart/main.cc
Normal file
52
repos/os/src/drivers/uart/main.cc
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* \brief Driver for UART devices
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \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 <base/heap.h>
|
||||
#include <base/log.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
|
||||
/* local includes */
|
||||
#include <uart_component.h>
|
||||
|
||||
|
||||
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];
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* \brief Driver for EXYNOS5 UARTs
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \author Ivan Loskutov <ivan.loskutov@ksyslabs.org>
|
||||
* \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 <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <os/irq_activation.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
|
||||
#include <drivers/uart_base.h>
|
||||
|
||||
/* 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<void>(),
|
||||
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_ */
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* \brief Driver for Exynos5 UART
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \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 <base/log.h>
|
||||
#include <base/sleep.h>
|
||||
#include <os/config.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
|
||||
#include <uart_defs.h>
|
||||
|
||||
/* 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;
|
||||
}
|
@ -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
|
||||
|
89
repos/os/src/drivers/uart/spec/exynos5/uart_driver.h
Normal file
89
repos/os/src/drivers/uart/spec/exynos5/uart_driver.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* \brief Driver for EXYNOS5 UARTs
|
||||
* \author Stefan Kalkowski <stefan.kalkowski@genode-labs.com>
|
||||
* \author Ivan Loskutov <ivan.loskutov@ksyslabs.org>
|
||||
* \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 <base/attached_io_mem_dataspace.h>
|
||||
#include <base/env.h>
|
||||
#include <drivers/uart_base.h>
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
enum { UARTS_NUM = 2 }; /* needed by base class definitions */
|
||||
|
||||
/* local includes */
|
||||
#include <uart_driver_base.h>
|
||||
|
||||
|
||||
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<void>(),
|
||||
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_ */
|
@ -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 <base/log.h>
|
||||
#include <base/sleep.h>
|
||||
#include <os/config.h>
|
||||
|
||||
#include <cap_session/connection.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* \brief Driver for OMAP4 UARTs
|
||||
* \author Ivan Loskutov <ivan.loskutov@ksyslabs.org>
|
||||
* \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 <base/log.h>
|
||||
#include <base/sleep.h>
|
||||
#include <os/config.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
|
||||
#include <uart_defs.h>
|
||||
|
||||
/* 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;
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* \brief Driver for OMAP4 UARTs
|
||||
* \author Ivan Loskutov <ivan.loskutov@ksyslabs.org>
|
||||
* \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 <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <os/irq_activation.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
|
||||
#include <drivers/uart_base.h>
|
||||
|
||||
/* 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>(Uart_lcr::Reg_mode::OPERATIONAL);
|
||||
|
||||
/* enable rx interrupt, disable other interrupts and sleep mode */
|
||||
write<Uart_ier>(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>(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<void>(), 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<Uart_iir::It_pending>();
|
||||
if (iir) return;
|
||||
_char_avail_callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* * UART driver interface **
|
||||
*/
|
||||
void put_char(char c) { Tl16c750_base::put_char(c); }
|
||||
|
||||
bool char_avail() { return read<Uart_lsr::Rx_fifo_empty>(); }
|
||||
|
||||
char get_char() { return read<Uart_rhr::Rhr>(); }
|
||||
|
||||
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_ */
|
@ -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
|
3
repos/os/src/drivers/uart/spec/panda/target.mk
Normal file
3
repos/os/src/drivers/uart/spec/panda/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
REQUIRES = panda
|
||||
|
||||
include $(REP_DIR)/src/drivers/uart/target.inc
|
135
repos/os/src/drivers/uart/spec/panda/uart_driver.h
Normal file
135
repos/os/src/drivers/uart/spec/panda/uart_driver.h
Normal file
@ -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 <base/attached_io_mem_dataspace.h>
|
||||
#include <base/env.h>
|
||||
#include <drivers/uart_base.h>
|
||||
#include <spec/panda/drivers/board_base.h>
|
||||
|
||||
enum { UARTS_NUM = 4 }; /* needed by base class definitions */
|
||||
|
||||
/* local includes */
|
||||
#include <uart_driver_base.h>
|
||||
|
||||
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>(Uart_lcr::Reg_mode::OPERATIONAL);
|
||||
|
||||
/* enable rx interrupt, disable other interrupts and sleep mode */
|
||||
write<Uart_ier>(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>(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<void>(),
|
||||
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<Uart_iir::It_pending>();
|
||||
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<Uart_lsr::Rx_fifo_empty>(); }
|
||||
|
||||
char get_char() override { return read<Uart_rhr::Rhr>(); }
|
||||
|
||||
void baud_rate(int bits_per_second) override
|
||||
{
|
||||
_init(Genode::Board_base::TL16C750_CLOCK, bits_per_second);
|
||||
_enable_rx_interrupt();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _UART_DRIVER_H_ */
|
3
repos/os/src/drivers/uart/spec/pbxa9/target.mk
Normal file
3
repos/os/src/drivers/uart/spec/pbxa9/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
REQUIRES = pbxa9
|
||||
|
||||
include $(REP_DIR)/src/drivers/uart/target.inc
|
205
repos/os/src/drivers/uart/spec/pbxa9/uart_driver.h
Normal file
205
repos/os/src/drivers/uart/spec/pbxa9/uart_driver.h
Normal file
@ -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 <base/attached_io_mem_dataspace.h>
|
||||
#include <base/env.h>
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
enum { UARTS_NUM = 4 }; /* needed by base class definitions */
|
||||
|
||||
/* local includes */
|
||||
#include <uart_driver_base.h>
|
||||
|
||||
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<unsigned volatile>())
|
||||
{
|
||||
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_ */
|
@ -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_)
|
@ -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 <base/log.h>
|
||||
#include <base/sleep.h>
|
||||
#include <pl011_defs.h>
|
||||
#include <os/config.h>
|
||||
#include <cap_session/connection.h>
|
||||
|
||||
/* 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;
|
||||
}
|
@ -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 <base/env.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/printf.h>
|
||||
#include <os/irq_activation.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
|
||||
/* 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<unsigned volatile>()),
|
||||
_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_ */
|
@ -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
|
3
repos/os/src/drivers/uart/spec/x86/target.mk
Normal file
3
repos/os/src/drivers/uart/spec/x86/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
REQUIRES = x86
|
||||
|
||||
include $(REP_DIR)/src/drivers/uart/target.inc
|
@ -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 <base/env.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/printf.h>
|
||||
#include <os/irq_activation.h>
|
||||
#include <io_port_session/connection.h>
|
||||
|
||||
enum { UARTS_NUM = 4 }; /* needed by base class definitions */
|
||||
|
||||
/* local includes */
|
||||
#include <uart_driver.h>
|
||||
#include <uart_driver_base.h>
|
||||
|
||||
|
||||
class I8250 : public Uart::Driver, public Genode::Irq_handler
|
||||
class Uart::Driver : public Uart::Driver_base
|
||||
{
|
||||
private:
|
||||
|
||||
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<MSR>();
|
||||
}
|
||||
|
||||
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<LSR>() & 0x60));
|
||||
@ -128,20 +134,20 @@ class I8250 : public Uart::Driver, public Genode::Irq_handler
|
||||
_outb<TRB>(c);
|
||||
}
|
||||
|
||||
bool char_avail()
|
||||
bool char_avail() override
|
||||
{
|
||||
return _inb<LSR>() & 1;
|
||||
}
|
||||
|
||||
char get_char()
|
||||
char get_char() override
|
||||
{
|
||||
return _inb<TRB>();
|
||||
}
|
||||
|
||||
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_ */
|
@ -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
|
@ -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,23 +16,31 @@
|
||||
#define _UART_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <os/attached_ram_dataspace.h>
|
||||
#include <root/component.h>
|
||||
#include <uart_session/uart_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include "uart_driver.h"
|
||||
#include <uart_driver.h>
|
||||
|
||||
namespace Uart {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
class Session_component : public Rpc_object<Uart::Session,
|
||||
Session_component>
|
||||
{
|
||||
class Session_component;
|
||||
class Root;
|
||||
|
||||
typedef Root_component<Session_component, Multiple_clients> Root_component;
|
||||
};
|
||||
|
||||
|
||||
class Uart::Session_component : public Rpc_object<Uart::Session,
|
||||
Uart::Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
@ -45,18 +54,7 @@ namespace Uart {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
Char_avail_functor _char_avail;
|
||||
Uart::Driver_factory &_driver_factory;
|
||||
Uart::Driver &_driver;
|
||||
|
||||
@ -129,12 +127,12 @@ namespace Uart {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Uart::Driver_factory &driver_factory,
|
||||
Session_component(Env &env, Uart::Driver_factory &driver_factory,
|
||||
unsigned index, unsigned baudrate, bool detect_size)
|
||||
:
|
||||
_io_buffer(Genode::env()->ram_session(), IO_BUFFER_SIZE),
|
||||
_io_buffer(env.ram(), env.rm(), IO_BUFFER_SIZE),
|
||||
_driver_factory(driver_factory),
|
||||
_driver(*_driver_factory.create(index, baudrate, _char_avail_callback)),
|
||||
_driver(_driver_factory.create(index, baudrate, _char_avail)),
|
||||
_size(detect_size ? _detect_size() : Size(0, 0))
|
||||
{ }
|
||||
|
||||
@ -179,10 +177,8 @@ namespace Uart {
|
||||
_driver.put_char(io_buf[i]);
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability _dataspace()
|
||||
{
|
||||
return _io_buffer.cap();
|
||||
}
|
||||
Genode::Dataspace_capability _dataspace() {
|
||||
return _io_buffer.cap(); }
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
@ -196,25 +192,23 @@ namespace Uart {
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
_char_avail_callback.sigh = sigh;
|
||||
_char_avail.sigh = sigh;
|
||||
|
||||
if (_driver.char_avail())
|
||||
_char_avail_callback();
|
||||
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; }
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
typedef Root_component<Session_component, Multiple_clients> Root_component;
|
||||
|
||||
|
||||
class Root : public Root_component
|
||||
{
|
||||
class Uart::Root : public Uart::Root_component
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Driver_factory &_driver_factory;
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
protected:
|
||||
|
||||
@ -222,7 +216,7 @@ namespace Uart {
|
||||
{
|
||||
try {
|
||||
Session_label label = label_from_args(args);
|
||||
Session_policy policy(label);
|
||||
Session_policy policy(label, _config.xml());
|
||||
|
||||
unsigned index = 0;
|
||||
policy.attribute("uart").value(&index);
|
||||
@ -235,7 +229,8 @@ namespace Uart {
|
||||
bool detect_size = policy.attribute_value("detect_size", false);
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_driver_factory, index, baudrate, detect_size);
|
||||
Session_component(_env, _driver_factory, index,
|
||||
baudrate, detect_size);
|
||||
|
||||
} catch (Xml_node::Nonexistent_attribute) {
|
||||
Genode::error("Missing \"uart\" attribute in policy definition");
|
||||
@ -248,14 +243,9 @@ namespace Uart {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Root(Rpc_entrypoint *ep, Allocator *md_alloc, Driver_factory &driver_factory)
|
||||
:
|
||||
Root_component(ep, md_alloc), _driver_factory(driver_factory)
|
||||
{ }
|
||||
};
|
||||
}
|
||||
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_ */
|
||||
|
@ -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_ */
|
135
repos/os/src/drivers/uart/uart_driver_base.h
Normal file
135
repos/os/src/drivers/uart/uart_driver_base.h
Normal file
@ -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 <irq_session/connection.h>
|
||||
|
||||
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<Driver_base> _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_ */
|
Loading…
x
Reference in New Issue
Block a user