/* * \brief i8250 UART driver * \author Norman Feske * \date 2011-09-12 */ /* * Copyright (C) 2011-2012 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 _I8250_H_ #define _I8250_H_ /* Genode includes */ #include #include #include #include #include /* local includes */ #include "uart_driver.h" class I8250 : public Uart::Driver, public Genode::Irq_handler { private: unsigned _port_base; Genode::Io_port_connection _io_port; /** * Register offsets relative to '_port_base' */ enum Reg { TRB = 0, /* transmit/receive buffer */ IER = 1, EIR = 2, LCR = 3, MCR = 4, LSR = 5, /* line status register */ MSR = 6, DLLO = 0, DLHI = 1, }; /** * Read byte from i8250 register */ template char _inb() { return _io_port.inb(_port_base + REG); } /** * Write byte to i8250 register */ template void _outb(char value) { _io_port.outb(_port_base + REG, value); } /** * Initialize UART * * Based on 'init_serial' of L4ka::Pistachio's 'kdb/platform/pc99/io.cc' */ void _init_comport(unsigned baud) { _outb(0x80); /* select bank 1 */ for (volatile int i = 10000000; i--; ); _outb((115200/baud) >> 0); _outb((115200/baud) >> 8); _outb(0x03); /* set 8,N,1 */ _outb(0x00); /* disable interrupts */ _outb(0x07); /* enable FIFOs */ _outb(0x0b); /* force data terminal ready */ _outb(0x01); /* enable RX interrupts */ _inb(); _inb(); _inb(); _inb(); _inb(); _inb(); } Uart::Char_avail_callback &_char_avail_callback; enum { IRQ_STACK_SIZE = 4096 }; Genode::Irq_activation _irq_activation; 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); } /*************************** ** 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) { /* wait until serial port is ready */ while (!(_inb() & 0x60)); /* output character */ _outb(c); } bool char_avail() { return _inb() & 1; } char get_char() { return _inb(); } void baud_rate(int bits_per_second) { _init_comport(bits_per_second); } }; #endif /* _I8250_H_ */