Serial port driver.

This commit is contained in:
Felix Queißner 2016-06-26 15:48:43 +02:00
parent f147ee1901
commit 88982f25cd
4 changed files with 115 additions and 11 deletions

View file

@ -0,0 +1,37 @@
#pragma once
#include <stdint.h>
#define SERIAL_COM1 0x3F8
#define SERIAL_COM2 0x2F8
#define SERIAL_COM3 0x3E8
#define SERIAL_COM4 0x2E8
enum class Partiy
{
None = 0x0,
Even = 0x4,
Odd = 0x6,
High = 0x5,
Low = 0x7,
};
class SerialPort
{
private:
uint16_t mBase;
public:
SerialPort(
uint32_t portBase,
uint32_t baud = 9600,
Partiy parity = Partiy::None,
uint8_t dataBits = 8);
bool isTransmitEmpty() const;
bool isReceiveEmpty() const;
void write(uint8_t c);
uint8_t read();
};

View file

@ -0,0 +1,12 @@
##
# Build serial port library.
##
include ../config.mk
LIBRARY = libserial.a
all: builddir $(LIBRARY)
include ../common.mk
include ../library.mk

View file

@ -0,0 +1,66 @@
#include <driver/serial.hpp>
#include <io.hpp>
// Code adapted from:
// http://www.lowlevel.eu/wiki/Serielle_Schnittstelle
#define IER 1
#define IIR 2
#define FCR 2
#define LCR 3
#define MCR 4
#define LSR 5
#define MSR 6
SerialPort::SerialPort(uint32_t portBase, uint32_t baud, Partiy parity, uint8_t dataBits) :
mBase(portBase)
{
union {
uint8_t b[2];
uint16_t w;
} divisor;
divisor.w = 115200 / baud;
// Interrupt ausschalten
outb(this->mBase + IER, 0x00);
// DLAB-Bit setzen
outb(this->mBase + LCR, 0x80);
// Teiler (low) setzen
outb(this->mBase + 0, divisor.b[0]);
// Teiler (high) setzen
outb(this->mBase + 1, divisor.b[1]);
int iparity = (int)parity;
// Anzahl Bits, Parität, usw setzen (DLAB zurücksetzen)
outb(this->mBase + LCR, ((iparity&0x7)<<3)|((dataBits-5)&0x3));
// Initialisierung abschließen
outb(this->mBase + FCR, 0xC7);
outb(this->mBase + MCR, 0x0B);
}
bool SerialPort::isTransmitEmpty() const
{
return inb(this->mBase + LSR) & 0x20;
}
bool SerialPort::isReceiveEmpty() const
{
return (inb(this->mBase + LSR) & 1) == 0;
}
void SerialPort::write(uint8_t c)
{
while (this->isTransmitEmpty() == false);
outb(this->mBase, c);
}
uint8_t SerialPort::read()
{
while (this->isReceiveEmpty());
return inb(this->mBase);
}

View file

@ -5,17 +5,6 @@
#include <driver/video.hpp>
// Prüft, ob man bereits schreiben kann
static uint8_t is_transmit_empty(uint16_t base) {
return inb(base+5) & 0x20;
}
// Byte senden
static void write_com(uint16_t base, uint8_t chr) {
while (is_transmit_empty(base)==0);
outb(base,chr);
}
extern "C" void init(multiboot::Structure const & data)
{
write_com(0x3F8, 'H');