réplica de
https://github.com/Arnau478/quark.git
synced 2024-11-23 12:58:07 +01:00
Implemented UART and created its printf-like function
This commit is contained in:
pare
707a87828b
commit
0e0d79811e
S'han modificat 7 arxius amb 120 adicions i 81 eliminacions
|
@ -1,42 +0,0 @@
|
|||
#include "serial.h"
|
||||
#include "../arch/i686/io.h"
|
||||
|
||||
int serial_initialize(uint8_t port){
|
||||
i686_outb(port + 1, 0x00); // Disable all interrupts
|
||||
i686_outb(port + 3, 0x80); // Enable DLAB
|
||||
i686_outb(port + 0, 0x03); // Divisor high byte (38400 baud)
|
||||
i686_outb(port + 1, 0x00); // Divisor low byte
|
||||
i686_outb(port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||
i686_outb(port + 2, 0xC7); // Enable FIFO
|
||||
i686_outb(port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||
|
||||
i686_outb(port + 4, 0x1E); // Loopback mode, test serial chip
|
||||
i686_outb(port + 0, 0xAE); // Test serial chip sending 0xAE
|
||||
|
||||
if(i686_inb(port + 0) != 0xAE){ // Not working
|
||||
return 1;
|
||||
}
|
||||
|
||||
i686_outb(port + 4, 0x0F); // Normal operation mode
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial_received(uint8_t port){
|
||||
return i686_inb(port + 5) & 0x01;
|
||||
}
|
||||
|
||||
char serial_read(uint8_t port){
|
||||
while(!serial_received(port));
|
||||
|
||||
return i686_inb(port);
|
||||
}
|
||||
|
||||
static int serial_tx_empty(uint8_t port){
|
||||
return i686_inb(port + 5) & 0x20;
|
||||
}
|
||||
|
||||
void serial_write(uint8_t port, char c){
|
||||
while(!serial_tx_empty(port));
|
||||
|
||||
return i686_outb(port, c);
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define COM1 (uint8_t)0x3F8
|
||||
#define COM2 (uint8_t)0x2F8
|
||||
#define COM3 (uint8_t)0x3E8
|
||||
#define COM4 (uint8_t)0x2E8
|
||||
#define COM5 (uint8_t)0x5F8
|
||||
#define COM6 (uint8_t)0x4F8
|
||||
#define COM7 (uint8_t)0x5E8
|
||||
#define COM8 (uint8_t)0x4E8
|
||||
|
||||
int serial_initialize(uint8_t port);
|
||||
char serial_read(uint8_t port);
|
||||
void serial_write(uint8_t port, char c);
|
41
src/kernel/drivers/uart.c
Normal file
41
src/kernel/drivers/uart.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#include "uart.h"
|
||||
#include "../arch/i686/io.h"
|
||||
|
||||
void uart_set_baudrate(uint16_t port, uint16_t divisor){
|
||||
i686_outb(port + 3, 0x80); // Enable DLAB
|
||||
i686_outb(port, (divisor >> 8) & 0x00FF); // High part
|
||||
i686_outb(port, divisor & 0x00FF); // Low part
|
||||
}
|
||||
|
||||
void uart_initialize(uint16_t port, uint16_t baudrate_div){
|
||||
uart_set_baudrate(port, baudrate_div);
|
||||
|
||||
// Configure line
|
||||
i686_outb(port + 3, 0x03); // 8 bit, no parity, 1 stop bit, no break control
|
||||
|
||||
// Configure buffering
|
||||
i686_outb(port + 2, 0xC7); // FIFO enabled, clear both FIFO queues, 14 bytes queue(s)
|
||||
|
||||
// Configure modem
|
||||
i686_outb(port + 4, 0x03); // RTS=1 DTS=1
|
||||
}
|
||||
|
||||
static int uart_received(uint16_t port){
|
||||
return i686_inb(port + 5) & 0x01;
|
||||
}
|
||||
|
||||
char uart_read(uint16_t port){
|
||||
while(!uart_received(port));
|
||||
|
||||
return i686_inb(port);
|
||||
}
|
||||
|
||||
static int uart_tx_empty(uint16_t port){
|
||||
return i686_inb(port + 5) & 0x20;
|
||||
}
|
||||
|
||||
void uart_write(uint16_t port, char c){
|
||||
while(!uart_tx_empty(port));
|
||||
|
||||
return i686_outb(port, c);
|
||||
}
|
17
src/kernel/drivers/uart.h
Normal file
17
src/kernel/drivers/uart.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define COM1 (uint16_t)0x3F8
|
||||
#define COM2 (uint16_t)0x2F8
|
||||
#define COM3 (uint16_t)0x3E8
|
||||
#define COM4 (uint16_t)0x2E8
|
||||
#define COM5 (uint16_t)0x5F8
|
||||
#define COM6 (uint16_t)0x4F8
|
||||
#define COM7 (uint16_t)0x5E8
|
||||
#define COM8 (uint16_t)0x4E8
|
||||
|
||||
void uart_set_baudrate(uint16_t port, uint16_t divisor);
|
||||
void uart_initialize(uint16_t port, uint16_t baudrate_div);
|
||||
char uart_read(uint16_t port);
|
||||
void uart_write(uint16_t port, char c);
|
|
@ -2,6 +2,9 @@
|
|||
#include <stdbool.h>
|
||||
#include "stdio.h"
|
||||
#include "../drivers/vga.h"
|
||||
#include "../drivers/uart.h"
|
||||
|
||||
typedef void (*print_callable_fn_t)(char);
|
||||
|
||||
static char g_HexChars[] = "0123456789abcdef";
|
||||
|
||||
|
@ -16,7 +19,11 @@ void putc(char c){
|
|||
vga_print_string(str);
|
||||
}
|
||||
|
||||
static void printf_unsigned(unsigned long long num, int radix){
|
||||
void serial_putc(char c){
|
||||
uart_write(COM1, c); // TODO: Add an option to decide what COM to use
|
||||
}
|
||||
|
||||
static void printf_unsigned(print_callable_fn_t out_fn, unsigned long long num, int radix){
|
||||
char buffer[32];
|
||||
int pos = 0;
|
||||
|
||||
|
@ -27,21 +34,20 @@ static void printf_unsigned(unsigned long long num, int radix){
|
|||
buffer[pos++] = g_HexChars[rem];
|
||||
} while(num > 0);
|
||||
|
||||
while(--pos >= 0) putc(buffer[pos]); // Note reverse order
|
||||
while(--pos >= 0) out_fn(buffer[pos]); // Note reverse order
|
||||
}
|
||||
|
||||
static void printf_signed(unsigned long long num, int radix){
|
||||
static void printf_signed(print_callable_fn_t out_fn, unsigned long long num, int radix){
|
||||
if(num < 0){
|
||||
putc('-');
|
||||
printf_unsigned(-num, radix);
|
||||
out_fn('-');
|
||||
printf_unsigned(out_fn, -num, radix);
|
||||
}
|
||||
else printf_unsigned(num, radix);
|
||||
else printf_unsigned(out_fn, num, radix);
|
||||
}
|
||||
|
||||
void printf(char *fmt, ...){
|
||||
// printf() template
|
||||
static void _vprintf(print_callable_fn_t out_fn, char *fmt, va_list args){
|
||||
// Variadic function arguments
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
while(*fmt){
|
||||
if(*fmt == '%'){
|
||||
|
@ -52,10 +58,10 @@ void printf(char *fmt, ...){
|
|||
fmt++;
|
||||
switch(*fmt){
|
||||
case '%':
|
||||
putc('%');
|
||||
out_fn('%');
|
||||
break;
|
||||
case 'c':
|
||||
putc((char)va_arg(args, int));
|
||||
out_fn((char)va_arg(args, int));
|
||||
break;
|
||||
case 's':
|
||||
puts(va_arg(args, char *));
|
||||
|
@ -89,19 +95,39 @@ void printf(char *fmt, ...){
|
|||
// TODO: Implement length modifiers
|
||||
if(number){
|
||||
if(sign){
|
||||
printf_signed(va_arg(args, int), radix);
|
||||
printf_signed(out_fn, va_arg(args, int), radix);
|
||||
}
|
||||
else{
|
||||
printf_unsigned(va_arg(args, unsigned int), radix);
|
||||
printf_unsigned(out_fn, va_arg(args, unsigned int), radix);
|
||||
}
|
||||
}
|
||||
|
||||
fmt++;
|
||||
}
|
||||
else putc(*(fmt++));
|
||||
else out_fn(*(fmt++));
|
||||
}
|
||||
}
|
||||
|
||||
void vprintf(char *fmt, va_list args){
|
||||
_vprintf(putc, fmt, args);
|
||||
}
|
||||
|
||||
void printf(char *fmt, ...){
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
_vprintf(putc, fmt, args);
|
||||
}
|
||||
|
||||
void serial_vprintf(char *fmt, va_list args){
|
||||
_vprintf(putc, fmt, args);
|
||||
}
|
||||
|
||||
void serial_printf(char *fmt, ...){
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
_vprintf(serial_putc, fmt, args);
|
||||
}
|
||||
|
||||
void clear_screen(){
|
||||
vga_fill_screen(' ', VGA_COLOR_BG_BLACK | VGA_COLOR_FG_WHITE);
|
||||
vga_set_cursor(0);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "hal/hal.h"
|
||||
#include "drivers/timer.h"
|
||||
#include "drivers/keyboard.h"
|
||||
#include "drivers/serial.h"
|
||||
#include "drivers/uart.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "arch/i686/mm/pmm.h"
|
||||
#include "arch/i686/mm/vmm.h"
|
||||
|
@ -18,6 +18,9 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
|||
// Initialize chip-specific hardware
|
||||
hal_initialize();
|
||||
|
||||
// Initialize serial
|
||||
uart_initialize(COM1, 2);
|
||||
|
||||
// Initialize physical memory manager
|
||||
uint32_t mem_size = 1024 + multiboot_info->mem_lower + multiboot_info->mem_upper*64;
|
||||
|
||||
|
@ -25,7 +28,7 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
|||
|
||||
for(int i = 0; i < multiboot_info->mmap_length; i += sizeof(multiboot_memory_map_t)){
|
||||
multiboot_memory_map_t *memory_map = (multiboot_memory_map_t *)(multiboot_info->mmap_addr + i);
|
||||
printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type);
|
||||
serial_printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type);
|
||||
|
||||
if(memory_map->type == 1){
|
||||
i686_pmm_init_region(memory_map->addr_l, memory_map->len_l);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "lib/stdio.h"
|
||||
#include "lib/string.h"
|
||||
#include "lib/memory.h"
|
||||
#include "drivers/serial.h"
|
||||
#include "drivers/uart.h"
|
||||
|
||||
int shell_run(char *cmd){
|
||||
int ret = 0;
|
||||
|
@ -17,12 +17,22 @@ int shell_run(char *cmd){
|
|||
else if(!strcmp(cmd, "clear")){
|
||||
clear_screen();
|
||||
}
|
||||
else if(!strcmp(cmd, "serial")){
|
||||
serial_write(COM1, 'H');
|
||||
serial_write(COM1, 'E');
|
||||
serial_write(COM1, 'L');
|
||||
serial_write(COM1, 'L');
|
||||
serial_write(COM1, 'O');
|
||||
else if(!strcmp(cmd, "uart")){
|
||||
uart_write(COM1, '\x1b');
|
||||
uart_write(COM1, '[');
|
||||
uart_write(COM1, '3');
|
||||
uart_write(COM1, '2');
|
||||
uart_write(COM1, 'm');
|
||||
uart_write(COM1, 'H');
|
||||
uart_write(COM1, 'E');
|
||||
uart_write(COM1, 'L');
|
||||
uart_write(COM1, 'L');
|
||||
uart_write(COM1, 'O');
|
||||
uart_write(COM1, '\n');
|
||||
uart_write(COM1, '\x1b');
|
||||
uart_write(COM1, '[');
|
||||
uart_write(COM1, '0');
|
||||
uart_write(COM1, 'm');
|
||||
}
|
||||
else{
|
||||
printf("SHELL: Unknown command \"%s\"\n", cmd);
|
||||
|
|
Loading…
Referencia en una nova incidència