Pretty Much Finish Basic Serial Driver
This commit is contained in:
parent
b4388c9808
commit
16ab26257e
7
build.sh
7
build.sh
@ -38,7 +38,12 @@ case $yn in
|
|||||||
echo -------------
|
echo -------------
|
||||||
echo STARTING QEMU
|
echo STARTING QEMU
|
||||||
echo -------------
|
echo -------------
|
||||||
qemu-system-i386 -audiodev pa,id=speaker -machine pcspk-audiodev=speaker -fda build/main_floppy.img
|
qemu-system-i386 -chardev pty,id=serial1 \
|
||||||
|
-serial mon:stdio \
|
||||||
|
-serial chardev:serial1 \
|
||||||
|
-audiodev pa,id=speaker \
|
||||||
|
-machine pcspk-audiodev=speaker \
|
||||||
|
-fda build/main_floppy.img
|
||||||
echo --------
|
echo --------
|
||||||
echo Finshed!
|
echo Finshed!
|
||||||
echo --------
|
echo --------
|
||||||
|
|||||||
@ -4,3 +4,278 @@
|
|||||||
|Tyler McGurrin |
|
|Tyler McGurrin |
|
||||||
\*----------------*/
|
\*----------------*/
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <arch/i686/io.h>
|
||||||
|
|
||||||
|
char Serial_Read_Buffer;
|
||||||
|
char Serial_Write_Buffer;
|
||||||
|
|
||||||
|
/*
|
||||||
|
IO Port Offset Setting of DLAB I/O Access Register mapped to this port
|
||||||
|
+0 0 Read Receive buffer.
|
||||||
|
+0 0 Write Transmit buffer.
|
||||||
|
+1 0 Read/Write Interrupt Enable Register.
|
||||||
|
+0 1 Read/Write With DLAB set to 1, this is the least significant byte of the divisor value for setting the baud rate.
|
||||||
|
+1 1 Read/Write With DLAB set to 1, this is the most significant byte of the divisor value.
|
||||||
|
+2 - Read Interrupt Identification
|
||||||
|
+2 - Write FIFO control registers
|
||||||
|
+3 - Read/Write Line Control Register. The most significant bit of this register is the DLAB.
|
||||||
|
+4 - Read/Write Modem Control Register.
|
||||||
|
+5 - Read Line Status Register.
|
||||||
|
+6 - Read Modem Status Register.
|
||||||
|
+7 - Read/Write Scratch Register.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Cannot Figure out what part of spec triggers this,
|
||||||
|
// OSDEV wiki just says it exists thats about it...
|
||||||
|
void COM1_Serial_Handler()
|
||||||
|
{
|
||||||
|
// Serial_Read_Buffer = Read_Serial(COM1_PORT);
|
||||||
|
// printf("Serial Read Buffer: %s", Serial_Read_Buffer);
|
||||||
|
printf("IRQ 4 Triggered!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Init_Serial(uint16_t COM_Port, int Baud)
|
||||||
|
{
|
||||||
|
uint8_t Divisor = 115200 / Baud;
|
||||||
|
|
||||||
|
i686_outb(COM_Port + 1, 0x00); // Disable all interrupts
|
||||||
|
i686_outb(COM_Port + 3, Divisor); // Enable DLAB (set baud rate divisor)
|
||||||
|
i686_outb(COM_Port + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
|
||||||
|
i686_outb(COM_Port + 1, 0x00); // (hi byte)
|
||||||
|
i686_outb(COM_Port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||||
|
i686_outb(COM_Port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
|
i686_outb(COM_Port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||||
|
i686_outb(COM_Port + 4, 0x1E); // Set in loopback mode, test the serial chip
|
||||||
|
i686_outb(COM_Port + 0, 0xAE); // Test serial chip (send byte 0xAE and check if serial returns same byte)
|
||||||
|
|
||||||
|
// Check if serial is faulty (i.e: not same byte as sent)
|
||||||
|
if(i686_inb(COM_Port + 0) != 0xAE) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If serial is not faulty set it in normal operation mode
|
||||||
|
// (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
|
||||||
|
i686_outb(COM_Port + 4, 0x0F);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serial_Received(uint16_t COM_Port)
|
||||||
|
{
|
||||||
|
return i686_inb(COM_Port + 5) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char Read_Serial(uint16_t COM_Port)
|
||||||
|
{
|
||||||
|
while (Serial_Received(COM_Port) == 0);
|
||||||
|
|
||||||
|
return i686_inb(COM_Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Serial_Transmit_Empty(uint16_t COM_Port)
|
||||||
|
{
|
||||||
|
return i686_inb(COM_Port + 5) & 0x20;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write_Serial(uint16_t COM_Port, char a)
|
||||||
|
{
|
||||||
|
while (Serial_Transmit_Empty(COM_Port) == 0);
|
||||||
|
|
||||||
|
i686_outb(COM_Port,a);
|
||||||
|
}
|
||||||
|
// We do the funny...
|
||||||
|
extern const char g_HexChars[];
|
||||||
|
|
||||||
|
void Serial_Puts(uint16_t COM_Port, const char* str)
|
||||||
|
{
|
||||||
|
while(*str)
|
||||||
|
{
|
||||||
|
Write_Serial(COM_Port, *str);
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial_Printf_Unsigned(uint16_t COM_Port,unsigned long long number, int radix)
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
//number to ASCII conversion
|
||||||
|
do {
|
||||||
|
unsigned long long rem = number % radix;
|
||||||
|
number /= radix;
|
||||||
|
buffer[pos++] = g_HexChars[rem];
|
||||||
|
} while (number > 0);
|
||||||
|
|
||||||
|
//print number in reverse order
|
||||||
|
while (--pos >= 0)
|
||||||
|
Write_Serial(COM_Port, buffer[pos]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Serial_Printf_Signed(uint16_t COM_Port,long long number, int radix)
|
||||||
|
{
|
||||||
|
if (number < 0)
|
||||||
|
{
|
||||||
|
Write_Serial(COM_Port, '-');
|
||||||
|
Serial_Printf_Unsigned(COM_Port, -number, radix);
|
||||||
|
}
|
||||||
|
else Serial_Printf_Unsigned(COM_Port, number, radix);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define PRINTF_STATE_NORMAL 0
|
||||||
|
#define PRINTF_STATE_LENGTH 1
|
||||||
|
#define PRINTF_STATE_LENGTH_SHORT 2
|
||||||
|
#define PRINTF_STATE_LENGTH_LONG 3
|
||||||
|
#define PRINTF_STATE_SPEC 4
|
||||||
|
|
||||||
|
#define PRINTF_LENGTH_DEFAULT 0
|
||||||
|
#define PRINTF_LENGTH_SHORT_SHORT 1
|
||||||
|
#define PRINTF_LENGTH_SHORT 2
|
||||||
|
#define PRINTF_LENGTH_LONG 3
|
||||||
|
#define PRINTF_LENGTH_LONG_LONG 4
|
||||||
|
|
||||||
|
void Serial_Printf(uint16_t COM_Port, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
int state = PRINTF_STATE_NORMAL;
|
||||||
|
int length = PRINTF_LENGTH_DEFAULT;
|
||||||
|
int radix = 10;
|
||||||
|
bool sign = false;
|
||||||
|
bool number = false;
|
||||||
|
|
||||||
|
while (*fmt)
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case PRINTF_STATE_NORMAL:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case '%': state = PRINTF_STATE_LENGTH;
|
||||||
|
break;
|
||||||
|
default: Write_Serial(COM_Port, *fmt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case 'h': length = PRINTF_LENGTH_SHORT;
|
||||||
|
state = PRINTF_STATE_LENGTH_SHORT;
|
||||||
|
break;
|
||||||
|
case 'l': length = PRINTF_LENGTH_LONG;
|
||||||
|
state = PRINTF_STATE_LENGTH_LONG;
|
||||||
|
break;
|
||||||
|
default: goto PRINTF_STATE_SPEC_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH_SHORT:
|
||||||
|
if (*fmt == 'h')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||||
|
state = PRINTF_STATE_SPEC;
|
||||||
|
}
|
||||||
|
else goto PRINTF_STATE_SPEC_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_LENGTH_LONG:
|
||||||
|
if (*fmt == 'l')
|
||||||
|
{
|
||||||
|
length = PRINTF_LENGTH_LONG_LONG;
|
||||||
|
state = PRINTF_STATE_SPEC;
|
||||||
|
}
|
||||||
|
else goto PRINTF_STATE_SPEC_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_STATE_SPEC:
|
||||||
|
PRINTF_STATE_SPEC_:
|
||||||
|
switch (*fmt)
|
||||||
|
{
|
||||||
|
case 'c': Write_Serial(COM_Port, (char)va_arg(args, int));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
Serial_Puts(COM_Port, va_arg(args, const char*));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '%': Write_Serial(COM_Port, '%');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'i': radix = 10; sign = true; number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'u': radix = 10; sign = false; number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
case 'x':
|
||||||
|
case 'p': radix = 16; sign = false; number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o': radix = 8; sign = false; number = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ignore invalid spec
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (number)
|
||||||
|
{
|
||||||
|
if (sign)
|
||||||
|
{
|
||||||
|
switch (length)
|
||||||
|
{
|
||||||
|
case PRINTF_LENGTH_SHORT_SHORT:
|
||||||
|
case PRINTF_LENGTH_SHORT:
|
||||||
|
case PRINTF_LENGTH_DEFAULT: Serial_Printf_Signed(COM_Port, va_arg(args, int), radix);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_LENGTH_LONG: Serial_Printf_Signed(COM_Port, va_arg(args, long), radix);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_LENGTH_LONG_LONG: Serial_Printf_Signed(COM_Port, va_arg(args, long long), radix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (length)
|
||||||
|
{
|
||||||
|
case PRINTF_LENGTH_SHORT_SHORT:
|
||||||
|
case PRINTF_LENGTH_SHORT:
|
||||||
|
case PRINTF_LENGTH_DEFAULT: Serial_Printf_Unsigned(COM_Port, va_arg(args, unsigned int), radix);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_LENGTH_LONG: Serial_Printf_Unsigned(COM_Port, va_arg(args, unsigned long), radix);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINTF_LENGTH_LONG_LONG: Serial_Printf_Unsigned(COM_Port, va_arg(args, unsigned long long), radix);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset state
|
||||||
|
state = PRINTF_STATE_NORMAL;
|
||||||
|
length = PRINTF_LENGTH_DEFAULT;
|
||||||
|
radix = 10;
|
||||||
|
sign = false;
|
||||||
|
number = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
@ -4,3 +4,27 @@
|
|||||||
|Tyler McGurrin |
|
|Tyler McGurrin |
|
||||||
\*----------------*/
|
\*----------------*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// You can really only trust the first and 2nd COM port addresses...
|
||||||
|
// fun.
|
||||||
|
enum COMPorts
|
||||||
|
{
|
||||||
|
COM1_PORT = 0x3F8,
|
||||||
|
COM2_PORT = 0x2F8,
|
||||||
|
COM3_PORT = 0x3E8,
|
||||||
|
COM4_PORT = 0x2E8,
|
||||||
|
COM5_PORT = 0x5F8,
|
||||||
|
COM6_PORT = 0x4F8,
|
||||||
|
COM7_PORT = 0x5E8,
|
||||||
|
COM8_PORT = 0x4E8
|
||||||
|
};
|
||||||
|
|
||||||
|
void COM1_Serial_Handler();
|
||||||
|
int Serial_Received(uint16_t COM_Port);
|
||||||
|
char Read_Serial(uint16_t COM_Port);
|
||||||
|
int Serial_Transmit_Empty(uint16_t COM_Port);
|
||||||
|
void Write_Serial(uint16_t COM_Port, char a);
|
||||||
|
int Init_Serial(uint16_t COM_Port, int Baud);
|
||||||
|
void Serial_Printf(uint16_t COM_Port, const char* fmt, ...);
|
||||||
@ -12,6 +12,7 @@
|
|||||||
#include <arch/i686/basicfunc.h>
|
#include <arch/i686/basicfunc.h>
|
||||||
#include <dri/keyboard.h>
|
#include <dri/keyboard.h>
|
||||||
#include <dri/cmos.h>
|
#include <dri/cmos.h>
|
||||||
|
#include <dri/serial.h>
|
||||||
#include <dri/fat.h>
|
#include <dri/fat.h>
|
||||||
#include <dri/disk/floppy.h>
|
#include <dri/disk/floppy.h>
|
||||||
#include <dri/disk/ata.h>
|
#include <dri/disk/ata.h>
|
||||||
@ -57,8 +58,10 @@ void __attribute__((section(".entry"))) start(BootParams* bootParams) {
|
|||||||
HAL_Initialize();
|
HAL_Initialize();
|
||||||
movecursorpos(19, 8);
|
movecursorpos(19, 8);
|
||||||
printf("Done!\n\n\n\n\n");
|
printf("Done!\n\n\n\n\n");
|
||||||
|
Init_Serial(COM1_PORT, 9600);
|
||||||
i686_IRQ_RegisterHandler(0, timer);
|
i686_IRQ_RegisterHandler(0, timer);
|
||||||
i686_IRQ_RegisterHandler(8, CMOS_RTC_Handler);
|
i686_IRQ_RegisterHandler(8, CMOS_RTC_Handler);
|
||||||
|
i686_IRQ_RegisterHandler(4, COM1_Serial_Handler);
|
||||||
|
|
||||||
// Begin Loading Basic Drivers
|
// Begin Loading Basic Drivers
|
||||||
printf("Load Keyboard Driver...");
|
printf("Load Keyboard Driver...");
|
||||||
@ -72,7 +75,8 @@ void __attribute__((section(".entry"))) start(BootParams* bootParams) {
|
|||||||
slaveFDDType = Slave_FDD_Detect();
|
slaveFDDType = Slave_FDD_Detect();
|
||||||
Floppy_Drive_Start(1);
|
Floppy_Drive_Start(1);
|
||||||
Print_Storage_Types(masterFDDType, slaveFDDType);
|
Print_Storage_Types(masterFDDType, slaveFDDType);
|
||||||
printf("Kernel Params: %s\n", bootParams->KernelParams);
|
// printf("Kernel Params: %s\n", bootParams->KernelParams);
|
||||||
|
Serial_Printf(COM1_PORT, "Hello World!");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,5 +6,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n"
|
#define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n"
|
||||||
#define VERSION "RD-00020"
|
#define VERSION "RD-00023"
|
||||||
#define BOOTLOGO " _ ______ ____ ____ ______\n / | / / __ )/ __ \\/ __ /_ __/\n / |/ / __ / / / / / / // / \n / /| / /_/ / /_/ / /_/ // / \n/_/ |_/_____/\\____/\\____//_/ \n"
|
#define BOOTLOGO " _ ______ ____ ____ ______\n / | / / __ )/ __ \\/ __ /_ __/\n / |/ / __ / / / / / / // / \n / /| / /_/ / /_/ / /_/ // / \n/_/ |_/_____/\\____/\\____//_/ \n"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user