add basic support of an UART device
This commit is contained in:
parent
8648ca0dfe
commit
df0b192e21
10 changed files with 494 additions and 7 deletions
|
@ -29,8 +29,7 @@ GDBFLAGS = -x debug.gdb
|
|||
QEMU = qemu-system-i386
|
||||
QEMUFLAGS = -smp 2 -monitor stdio \
|
||||
-net nic,model=rtl8139 \
|
||||
-net user,hostfwd=tcp::12345-:7 \
|
||||
-serial tcp::12346,server,nowait
|
||||
-net user,hostfwd=tcp::12345-:7
|
||||
|
||||
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include
|
||||
# Compiler options for final code
|
||||
|
@ -73,6 +72,9 @@ veryclean: clean
|
|||
qemu: $(NAME).elf
|
||||
$(QEMU) $(QEMUFLAGS) -kernel $(NAME).elf
|
||||
|
||||
uart: $(NAME).elf
|
||||
$(QEMU) -chardev null,id=tS0 -device pci-serial,chardev=tS0 -serial tcp::4555,server $(QEMUFLAGS) -kernel $(NAME).elf
|
||||
|
||||
debug: $(NAME).elf
|
||||
$(TERM) -e $(GDB) $(GDBFLAGS) &
|
||||
$(QEMU) $(QEMUFLAGS) -s -S -kernel $(NAME).elf
|
||||
|
|
|
@ -88,6 +88,9 @@ Overview of all branches
|
|||
Add support of paging. See http://www.noteblok.net/2014/06/14/bachelor
|
||||
for a detailed description.
|
||||
|
||||
6. stage6 - Add UART support
|
||||
Add basic support of a serial device
|
||||
|
||||
Usefull Links
|
||||
-------------
|
||||
0. http://www.gnu.org/software/grub/manual/multiboot/
|
||||
|
|
49
arch/x86/include/asm/pci.h
Normal file
49
arch/x86/include/asm/pci.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/pci.h
|
||||
* @brief functions related to PCI initialization and information
|
||||
*
|
||||
* This file contains a procedure to initialize the PCI environment
|
||||
* and functions to access information about specific PCI devices.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_PCI_H__
|
||||
#define __ARCH_PCI_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t base[6];
|
||||
uint32_t size[6];
|
||||
uint32_t irq;
|
||||
} pci_info_t;
|
||||
|
||||
/** @brief Initialize the PCI environment
|
||||
*/
|
||||
int pci_init(void);
|
||||
|
||||
/** @brief Determine the IObase address and the interrupt number of a specific device
|
||||
*
|
||||
* @param vendor_id The device's vendor ID
|
||||
* @param device_id the device's ID
|
||||
* @param info Pointer to the record pci_info_t where among other the IObase address will be stored
|
||||
*
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL (-22) on failure
|
||||
*/
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, pci_info_t* info);
|
||||
|
||||
/** @brief Print information of existing pci adapters
|
||||
*
|
||||
* @return 0 in any case
|
||||
*/
|
||||
int print_pci_adapters(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -38,6 +38,9 @@
|
|||
|
||||
#include <eduos/stddef.h>
|
||||
#include <asm/gdt.h>
|
||||
#ifdef CONFIG_PCI
|
||||
#include <asm/pci.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -206,6 +209,9 @@ static inline size_t lsb(size_t i)
|
|||
inline static int system_init(void)
|
||||
{
|
||||
gdt_install();
|
||||
#ifdef CONFIG_PCI
|
||||
pci_init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
67
arch/x86/include/asm/uart.h
Normal file
67
arch/x86/include/asm/uart.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Stefan Lankes
|
||||
* @file arch/x86/include/asm/uart.h
|
||||
* @brief UART related code
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_UART_H__
|
||||
#define __ARCH_UART_H__
|
||||
|
||||
#include <eduos/stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Initialize UART output
|
||||
*
|
||||
* @return Returns 0 on success
|
||||
*/
|
||||
int uart_init(void);
|
||||
|
||||
/** @brief Simple string output on a serial device.
|
||||
*
|
||||
* If you want a new line you will have to "\\n".
|
||||
*
|
||||
* @return Length of output in bytes
|
||||
*/
|
||||
int uart_puts(const char *text);
|
||||
|
||||
/** @brief Simple character output on a serial device.
|
||||
*
|
||||
* @return The original input character casted to int
|
||||
*/
|
||||
int uart_putchar(unsigned char c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
C_source := tasks.c vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c
|
||||
C_source := tasks.c vga.c gdt.c irq.c idt.c isrs.c timer.c processor.c uart.c pci.c
|
||||
ASM_source := entry.asm string32.asm
|
||||
MODULE := arch_x86_kernel
|
||||
|
||||
|
|
187
arch/x86/kernel/pci.c
Normal file
187
arch/x86/kernel/pci.c
Normal file
|
@ -0,0 +1,187 @@
|
|||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <eduos/errno.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
#include <asm/pci.h>
|
||||
#include "pcihdr.h"
|
||||
|
||||
/*
|
||||
* PCI configuration registers
|
||||
*/
|
||||
#define PCI_CFID 0x00 /* Configuration ID */
|
||||
#define PCI_CFCS 0x04 /* Configurtion Command/Status */
|
||||
#define PCI_CFRV 0x08 /* Configuration Revision */
|
||||
#define PCI_CFLT 0x0c /* Configuration Latency Timer */
|
||||
#define PCI_CBIO 0x10 /* Configuration Base IO Address */
|
||||
#define PCI_CFIT 0x3c /* Configuration Interrupt */
|
||||
#define PCI_CFDA 0x40 /* Configuration Driver Area */
|
||||
|
||||
#define PHYS_IO_MEM_START 0
|
||||
#define PCI_MEM 0
|
||||
#define PCI_INTA 0
|
||||
#define PCI_NSLOTS 22
|
||||
#define PCI_NBUS 0
|
||||
|
||||
#define PCI_CONF_ADDR_REG 0xcf8
|
||||
#define PCI_CONF_FRWD_REG 0xcf8
|
||||
#define PCI_CONF_DATA_REG 0xcfc
|
||||
|
||||
#define PCI_IO_CONF_START 0xc000
|
||||
|
||||
#define MAX_BUS 16
|
||||
#define MAX_SLOTS 32
|
||||
|
||||
static uint32_t mechanism = 0;
|
||||
static uint32_t adapters[MAX_BUS][MAX_SLOTS] = {[0 ... MAX_BUS-1][0 ... MAX_SLOTS-1] = -1};
|
||||
|
||||
static void pci_conf_write(uint32_t bus, uint32_t slot, uint32_t off, uint32_t val)
|
||||
{
|
||||
if (mechanism == 1) {
|
||||
outportl(PCI_CONF_FRWD_REG, bus);
|
||||
outportl(PCI_CONF_ADDR_REG, 0xf0);
|
||||
outportl(PCI_IO_CONF_START | (slot << 8) | off, val);
|
||||
} else {
|
||||
outportl(PCI_CONF_ADDR_REG,
|
||||
(0x80000000 | (bus << 16) | (slot << 11) | off));
|
||||
outportl(PCI_CONF_DATA_REG, val);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t pci_conf_read(uint32_t bus, uint32_t slot, uint32_t off)
|
||||
{
|
||||
uint32_t data = -1;
|
||||
|
||||
outportl(PCI_CONF_ADDR_REG,
|
||||
(0x80000000 | (bus << 16) | (slot << 11) | off));
|
||||
data = inportl(PCI_CONF_DATA_REG);
|
||||
|
||||
if ((data == 0xffffffff) && (slot < 0x10)) {
|
||||
outportl(PCI_CONF_FRWD_REG, bus);
|
||||
outportl(PCI_CONF_ADDR_REG, 0xf0);
|
||||
data = inportl(PCI_IO_CONF_START | (slot << 8) | off);
|
||||
if (data == 0xffffffff)
|
||||
return data;
|
||||
if (!mechanism)
|
||||
mechanism = 1;
|
||||
} else if (!mechanism)
|
||||
mechanism = 2;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_irq(uint32_t bus, uint32_t slot)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CFIT) & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_iobase(uint32_t bus, uint32_t slot, uint32_t nr)
|
||||
{
|
||||
return pci_conf_read(bus, slot, PCI_CBIO + nr*4) & 0xFFFFFFFC;
|
||||
}
|
||||
|
||||
static inline uint32_t pci_what_size(uint32_t bus, uint32_t slot, uint32_t nr)
|
||||
{
|
||||
uint32_t tmp, ret;
|
||||
|
||||
// backup the original value
|
||||
tmp = pci_conf_read(bus, slot, PCI_CBIO + nr*4);
|
||||
|
||||
// determine size
|
||||
pci_conf_write(bus, slot, PCI_CBIO + nr*4, 0xFFFFFFFF);
|
||||
ret = ~pci_conf_read(bus, slot, PCI_CBIO + nr*4) + 1;
|
||||
|
||||
// restore original value
|
||||
pci_conf_write(bus, slot, PCI_CBIO + nr*4, tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_init(void)
|
||||
{
|
||||
uint32_t slot, bus;
|
||||
|
||||
for (bus = 0; bus < MAX_BUS; bus++)
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++)
|
||||
adapters[bus][slot] = pci_conf_read(bus, slot, PCI_CFID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pci_get_device_info(uint32_t vendor_id, uint32_t device_id, pci_info_t* info)
|
||||
{
|
||||
uint32_t slot, bus, i;
|
||||
|
||||
if (!info)
|
||||
return -EINVAL;
|
||||
|
||||
if (!mechanism)
|
||||
pci_init();
|
||||
|
||||
for (bus = 0; bus < MAX_BUS; bus++) {
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
||||
if (adapters[bus][slot] != -1) {
|
||||
if (((adapters[bus][slot] & 0xffff) == vendor_id) &&
|
||||
(((adapters[bus][slot] & 0xffff0000) >> 16) == device_id)) {
|
||||
for(i=0; i<6; i++) {
|
||||
info->base[i] = pci_what_iobase(bus, slot, i);
|
||||
info->size[i] = (info->base[i]) ? pci_what_size(bus, slot, i) : 0;
|
||||
}
|
||||
info->irq = pci_what_irq(bus, slot);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int print_pci_adapters(void)
|
||||
{
|
||||
uint32_t slot, bus;
|
||||
uint32_t i, counter = 0;
|
||||
|
||||
if (!mechanism)
|
||||
pci_init();
|
||||
|
||||
for (bus = 0; bus < MAX_BUS; bus++) {
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++) {
|
||||
|
||||
if (adapters[bus][slot] != -1) {
|
||||
counter++;
|
||||
|
||||
kprintf("%d) Vendor ID: 0x%x Device Id: 0x%x\n",
|
||||
counter, adapters[bus][slot] & 0xffff,
|
||||
(adapters[bus][slot] & 0xffff0000) >> 16);
|
||||
|
||||
for (i=0; i<PCI_VENTABLE_LEN; i++) {
|
||||
if ((adapters[bus][slot] & 0xffff) ==
|
||||
(uint32_t)PciVenTable[i].VenId)
|
||||
kprintf("\tVendor is %s\n",
|
||||
PciVenTable[i].VenShort);
|
||||
}
|
||||
|
||||
for (i=0; i<PCI_DEVTABLE_LEN; i++) {
|
||||
if ((adapters[bus][slot] & 0xffff) ==
|
||||
(uint32_t)PciDevTable[i].VenId) {
|
||||
if (((adapters[bus][slot] & 0xffff0000) >> 16) ==
|
||||
PciDevTable[i].DevId) {
|
||||
kprintf
|
||||
("\tChip: %s ChipDesc: %s\n",
|
||||
PciDevTable[i].Chip,
|
||||
PciDevTable[i].ChipDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
166
arch/x86/kernel/uart.c
Normal file
166
arch/x86/kernel/uart.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Stefan Lankes, RWTH Aachen University
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <eduos/stdio.h>
|
||||
#include <eduos/string.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uart.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/irqflags.h>
|
||||
#include <asm/vga.h>
|
||||
#ifdef CONFIG_PCI
|
||||
#include <asm/pci.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UART
|
||||
|
||||
#define UART_RX 0 /* In: Receive buffer */
|
||||
#define UART_TX 0 /* Out: Transmit buffer */
|
||||
|
||||
#define UART_IER 1 /* Out: Interrupt Enable Register */
|
||||
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
|
||||
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
|
||||
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
|
||||
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
|
||||
|
||||
#define UART_FCR 2 /* Out: FIFO Control Register */
|
||||
#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */
|
||||
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
|
||||
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
|
||||
#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
|
||||
#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
|
||||
|
||||
#define UART_DLL 0 /* Out: Divisor Latch Low */
|
||||
#define UART_DLM 1 /* Out: Divisor Latch High */
|
||||
|
||||
#define UART_LCR 3 /* Out: Line Control Register */
|
||||
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
|
||||
#define UART_LCR_SBC 0x40 /* Set break control */
|
||||
#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
|
||||
#define UART_LCR_EPAR 0x10 /* Even parity select */
|
||||
#define UART_LCR_PARITY 0x08 /* Parity Enable */
|
||||
#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 bit, 1=2 bits */
|
||||
#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
|
||||
|
||||
static uint32_t iobase = 0;
|
||||
|
||||
unsigned char uart_getchar(void)
|
||||
{
|
||||
return inportb(iobase + UART_RX);
|
||||
}
|
||||
|
||||
/* Handles all UART's interrupt */
|
||||
static void uart_handler(struct state *s)
|
||||
{
|
||||
vga_puts("UART interrupt\n");
|
||||
}
|
||||
|
||||
/* Puts a single character on a serial device */
|
||||
int uart_putchar(unsigned char c)
|
||||
{
|
||||
if (!iobase)
|
||||
return 0;
|
||||
|
||||
outportb(iobase + UART_TX, c);
|
||||
|
||||
return (int) c;
|
||||
}
|
||||
|
||||
/* Uses the routine above to output a string... */
|
||||
int uart_puts(const char *text)
|
||||
{
|
||||
size_t i, len = strlen(text);
|
||||
|
||||
if (!iobase)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
uart_putchar(text[i]);
|
||||
|
||||
return i-1;
|
||||
}
|
||||
|
||||
static void uart_config(void)
|
||||
{
|
||||
/*
|
||||
* enable FIFOs
|
||||
* clear RX and TX FIFO
|
||||
* set irq trigger to 8 bytes
|
||||
*/
|
||||
outportb(iobase + UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_1);
|
||||
|
||||
/*
|
||||
* 8bit word length
|
||||
* 1 stop bit
|
||||
* no partity
|
||||
* set DLAB=1
|
||||
*/
|
||||
char lcr = UART_LCR_WLEN8 | UART_LCR_DLAB;
|
||||
outportb(iobase + UART_LCR, lcr);
|
||||
|
||||
/*
|
||||
* set baudrate to 115200 (on qemu)
|
||||
*/
|
||||
outportb(iobase + UART_DLL, 0x01);
|
||||
outportb(iobase + UART_DLM, 0x00);
|
||||
|
||||
/* set DLAB=0 */
|
||||
outportb(iobase + UART_LCR, lcr & (~UART_LCR_DLAB));
|
||||
|
||||
/* enable interrupt */
|
||||
outportb(iobase + UART_IER, UART_IER_RDI | UART_IER_RLSI | UART_IER_THRI);
|
||||
}
|
||||
|
||||
int uart_init(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
pci_info_t pci_info;
|
||||
|
||||
// Searching for Intel's UART device
|
||||
if (pci_get_device_info(0x8086, 0x0936, &pci_info) == 0) {
|
||||
iobase = pci_info.base[0];
|
||||
goto Lsuccess;
|
||||
}
|
||||
// Searching for Qemu's UART device
|
||||
if (pci_get_device_info(0x1b36, 0x0002, &pci_info) == 0) {
|
||||
iobase = 0x03f8;
|
||||
goto Lsuccess;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
Lsuccess:
|
||||
irq_install_handler(32+pci_info.irq, uart_handler);
|
||||
|
||||
// configure uart
|
||||
uart_config();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -45,6 +45,8 @@ extern "C" {
|
|||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
#define CONFIG_VGA
|
||||
#define CONFIG_PCI
|
||||
#define CONFIG_UART
|
||||
|
||||
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||
|
|
|
@ -29,12 +29,16 @@
|
|||
#include <eduos/string.h>
|
||||
#include <eduos/stdarg.h>
|
||||
#include <eduos/spinlock.h>
|
||||
#include <asm/uart.h>
|
||||
#include <asm/vga.h>
|
||||
|
||||
static spinlock_irqsave_t olock = SPINLOCK_IRQSAVE_INIT;
|
||||
|
||||
int koutput_init(void)
|
||||
{
|
||||
#ifdef CONFIG_UART
|
||||
uart_init();
|
||||
#endif
|
||||
#ifdef CONFIG_VGA
|
||||
vga_init();
|
||||
#endif
|
||||
|
@ -45,6 +49,9 @@ int koutput_init(void)
|
|||
int kputchar(int c)
|
||||
{
|
||||
spinlock_irqsave_lock(&olock);
|
||||
#ifdef CONFIG_UART
|
||||
uart_putchar(c);
|
||||
#endif
|
||||
#ifdef CONFIG_VGA
|
||||
vga_putchar(c);
|
||||
#endif
|
||||
|
@ -55,12 +62,10 @@ int kputchar(int c)
|
|||
|
||||
int kputs(const char *str)
|
||||
{
|
||||
#ifdef CONFIG_VGA
|
||||
int i;
|
||||
|
||||
for(i=0; str[i] != '\0'; i++)
|
||||
vga_putchar((int) str[i]);
|
||||
kputchar((int) str[i]);
|
||||
|
||||
return i;
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue