Read BIOS data area (BDA) to get serial I/O ports
If the I/O ports are non default (3f8), we had to specify manually the correct I/O ports. With this commit the BDA is read and the I/O port of the first serial interface (COM) is taken. If no serial interface is available no device configuration will be undertaken.
This commit is contained in:
parent
5e66b6d5ed
commit
4d12464cee
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* \brief Console backend for NOVA
|
* \brief Console backend for NOVA
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Alexander Boettcher
|
||||||
* \date 2009-12-28
|
* \date 2009-12-28
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -18,15 +19,13 @@
|
||||||
/* NOVA includes */
|
/* NOVA includes */
|
||||||
#include <nova/syscalls.h>
|
#include <nova/syscalls.h>
|
||||||
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read byte from I/O port
|
* Read byte from I/O port
|
||||||
*/
|
*/
|
||||||
inline uint8_t inb(unsigned short port)
|
inline Genode::uint8_t inb(Genode::uint16_t port)
|
||||||
{
|
{
|
||||||
uint8_t res;
|
Genode::uint8_t res;
|
||||||
asm volatile ("inb %%dx, %0" :"=a"(res) :"Nd"(port));
|
asm volatile ("inb %%dx, %0" :"=a"(res) :"Nd"(port));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +34,7 @@ inline uint8_t inb(unsigned short port)
|
||||||
/**
|
/**
|
||||||
* Write byte to I/O port
|
* Write byte to I/O port
|
||||||
*/
|
*/
|
||||||
inline void outb(unsigned short port, uint8_t val)
|
inline void outb(Genode::uint16_t port, Genode::uint8_t val)
|
||||||
{
|
{
|
||||||
asm volatile ("outb %b0, %w1" : : "a" (val), "Nd" (port));
|
asm volatile ("outb %b0, %w1" : : "a" (val), "Nd" (port));
|
||||||
}
|
}
|
||||||
|
@ -44,14 +43,14 @@ inline void outb(unsigned short port, uint8_t val)
|
||||||
/**
|
/**
|
||||||
* Definitions of PC serial ports
|
* Definitions of PC serial ports
|
||||||
*/
|
*/
|
||||||
enum Comport { COMPORT_0, COMPORT_1, COMPORT_2, COMPORT_3 };
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// COMPORT_0_BASE = 0x1010, /* comport of serial PCI card */
|
MAP_ADDR_BDA = 0x1000,
|
||||||
COMPORT_0_BASE = 0x3f8, /* default comport 0, used wiht Qemu */
|
|
||||||
COMPORT_1_BASE = 0x2f8,
|
BDA_SERIAL_BASE_COM1 = 0x400,
|
||||||
COMPORT_2_BASE = 0x3e8,
|
BDA_EQUIPMENT_WORD = 0x410,
|
||||||
COMPORT_3_BASE = 0x2e8,
|
BDA_EQUIPMENT_SERIAL_COUNT_MASK = 0x7,
|
||||||
|
BDA_EQUIPMENT_SERIAL_COUNT_SHIFT = 9,
|
||||||
|
|
||||||
COMPORT_DATA_OFFSET = 0,
|
COMPORT_DATA_OFFSET = 0,
|
||||||
COMPORT_STATUS_OFFSET = 5,
|
COMPORT_STATUS_OFFSET = 5,
|
||||||
|
|
||||||
|
@ -65,8 +64,11 @@ enum {
|
||||||
*
|
*
|
||||||
* Based on 'init_serial' of L4ka::Pistachio's 'kdb/platform/pc99/io.cc'
|
* Based on 'init_serial' of L4ka::Pistachio's 'kdb/platform/pc99/io.cc'
|
||||||
*/
|
*/
|
||||||
static void init_comport(unsigned short port, unsigned baud)
|
static void init_comport(Genode::uint16_t port, unsigned baud)
|
||||||
{
|
{
|
||||||
|
if (!port)
|
||||||
|
return;
|
||||||
|
|
||||||
const unsigned
|
const unsigned
|
||||||
IER = port + 1,
|
IER = port + 1,
|
||||||
EIR = port + 2,
|
EIR = port + 2,
|
||||||
|
@ -98,17 +100,15 @@ static void init_comport(unsigned short port, unsigned baud)
|
||||||
/**
|
/**
|
||||||
* Output character to serial port
|
* Output character to serial port
|
||||||
*/
|
*/
|
||||||
inline void serial_out_char(Comport comport, uint8_t c)
|
inline void serial_out_char(Genode::uint16_t comport, Genode::uint8_t c)
|
||||||
{
|
{
|
||||||
static int io_port[] = { COMPORT_0_BASE, COMPORT_1_BASE,
|
|
||||||
COMPORT_2_BASE, COMPORT_3_BASE };
|
|
||||||
|
|
||||||
/* wait until serial port is ready */
|
/* wait until serial port is ready */
|
||||||
uint8_t ready = STATUS_THR_EMPTY;
|
Genode::uint8_t ready = STATUS_THR_EMPTY;
|
||||||
while ((inb(io_port[comport] + COMPORT_STATUS_OFFSET) & ready) != ready);
|
while ((inb(comport + COMPORT_STATUS_OFFSET) & ready) != ready);
|
||||||
|
|
||||||
/* output character */
|
/* output character */
|
||||||
outb(io_port[comport] + COMPORT_DATA_OFFSET, c);
|
outb(comport + COMPORT_DATA_OFFSET, c);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,18 +116,42 @@ namespace Genode {
|
||||||
|
|
||||||
class Core_console : public Console
|
class Core_console : public Console
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint16_t _comport;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void _out_char(char c)
|
void _out_char(char c)
|
||||||
{
|
{
|
||||||
|
if (!_comport)
|
||||||
|
return;
|
||||||
|
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
serial_out_char(COMPORT_0, '\r');
|
serial_out_char(_comport, '\r');
|
||||||
serial_out_char(COMPORT_0, c);
|
serial_out_char(_comport, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Core_console() { init_comport(COMPORT_0_BASE, 115200); }
|
Core_console() : _comport(0)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read BDA (Bios Data Area) to obtain I/O ports of COM
|
||||||
|
* interfaces. The page must be mapped by the platform code !
|
||||||
|
*/
|
||||||
|
char * map_bda = reinterpret_cast<char *>(MAP_ADDR_BDA);
|
||||||
|
uint16_t serial_count = *reinterpret_cast<uint16_t *>(map_bda + BDA_EQUIPMENT_WORD);
|
||||||
|
serial_count >>= BDA_EQUIPMENT_SERIAL_COUNT_SHIFT;
|
||||||
|
serial_count &= BDA_EQUIPMENT_SERIAL_COUNT_MASK;
|
||||||
|
|
||||||
|
if (serial_count > 0)
|
||||||
|
_comport = *reinterpret_cast<uint16_t *>(
|
||||||
|
map_bda + BDA_SERIAL_BASE_COM1);
|
||||||
|
|
||||||
|
init_comport(_comport, 115200);
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,8 +74,12 @@ static int map_local(Nova::Utcb *utcb, Nova::Crd src_crd, Nova::Crd dst_crd,
|
||||||
static inline int unmap_local(Nova::Crd crd, bool self = true) {
|
static inline int unmap_local(Nova::Crd crd, bool self = true) {
|
||||||
return Nova::revoke(crd, self); }
|
return Nova::revoke(crd, self); }
|
||||||
|
|
||||||
|
inline int
|
||||||
|
map_local_phys_to_virt(Nova::Utcb *utcb, Nova::Crd src, Nova::Crd dst) {
|
||||||
|
return map_local(utcb, src, dst, true); }
|
||||||
|
|
||||||
inline int map_local_one_to_one(Nova::Utcb *utcb, Nova::Crd crd) {
|
inline int
|
||||||
|
map_local_one_to_one(Nova::Utcb *utcb, Nova::Crd crd) {
|
||||||
return map_local(utcb, crd, crd, true); }
|
return map_local(utcb, crd, crd, true); }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Genode {
|
||||||
/**
|
/**
|
||||||
* Virtual address range usable by non-core processes
|
* Virtual address range usable by non-core processes
|
||||||
*/
|
*/
|
||||||
addr_t _vm_base;
|
const addr_t _vm_base;
|
||||||
size_t _vm_size;
|
size_t _vm_size;
|
||||||
|
|
||||||
void _preserve_page(addr_t phys_page);
|
void _preserve_page(addr_t phys_page);
|
||||||
|
|
|
@ -194,7 +194,7 @@ static void init_core_page_fault_handler()
|
||||||
Platform::Platform() :
|
Platform::Platform() :
|
||||||
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
|
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
|
||||||
_irq_alloc(core_mem_alloc()),
|
_irq_alloc(core_mem_alloc()),
|
||||||
_vm_base(0), _vm_size(0)
|
_vm_base(0x2000), _vm_size(0)
|
||||||
{
|
{
|
||||||
Hip *hip = (Hip *)__initial_sp;
|
Hip *hip = (Hip *)__initial_sp;
|
||||||
|
|
||||||
|
@ -211,6 +211,11 @@ Platform::Platform() :
|
||||||
/* locally map the whole I/O port range */
|
/* locally map the whole I/O port range */
|
||||||
enum { ORDER_64K = 16 };
|
enum { ORDER_64K = 16 };
|
||||||
map_local_one_to_one(__main_thread_utcb, Io_crd(0, ORDER_64K));
|
map_local_one_to_one(__main_thread_utcb, Io_crd(0, ORDER_64K));
|
||||||
|
/* map BDA region, core_console reads out serial i/o ports at 0x400 */
|
||||||
|
map_local_phys_to_virt(__main_thread_utcb,
|
||||||
|
Mem_crd(0x0, 0, Rights(true, false, false)),
|
||||||
|
Mem_crd(0x1, 0, Rights(true, false, false)));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we can access the I/O ports for comport 0, printf works...
|
* Now that we can access the I/O ports for comport 0, printf works...
|
||||||
|
@ -223,7 +228,6 @@ Platform::Platform() :
|
||||||
}
|
}
|
||||||
|
|
||||||
/* configure virtual address spaces */
|
/* configure virtual address spaces */
|
||||||
_vm_base = get_page_size();
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
_vm_size = 0x800000000000UL - _vm_base;
|
_vm_size = 0x800000000000UL - _vm_base;
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in New Issue
Block a user