Merge into main the new state of the operating system/kernel #1
							
								
								
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							@ -1,3 +1,4 @@
 | 
			
		||||
*.pdf filter=lfs diff=lfs merge=lfs -text
 | 
			
		||||
*.png filter=lfs diff=lfs merge=lfs -text
 | 
			
		||||
*.svg filter=lfs diff=lfs merge=lfs -text
 | 
			
		||||
demodisk.img filter=lfs diff=lfs merge=lfs -text
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1 +1,3 @@
 | 
			
		||||
build
 | 
			
		||||
build
 | 
			
		||||
CON
 | 
			
		||||
.vscode
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
								
							@ -1,16 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "configurations": [
 | 
			
		||||
        {
 | 
			
		||||
            "name": "Linux",
 | 
			
		||||
            "includePath": [
 | 
			
		||||
                "${workspaceFolder}/**"
 | 
			
		||||
            ],
 | 
			
		||||
            "defines": [],
 | 
			
		||||
            "compilerPath": "/usr/bin/gcc",
 | 
			
		||||
            "cStandard": "gnu17",
 | 
			
		||||
            "cppStandard": "gnu++14",
 | 
			
		||||
            "intelliSenseMode": "linux-gcc-x64"
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "version": 4
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@ -24,7 +24,7 @@ all: clean build
 | 
			
		||||
build: build_kernel run 
 | 
			
		||||
 | 
			
		||||
run:
 | 
			
		||||
	$(EMULATOR)  -kernel $(BUILD_DIR)/myos.bin -serial stdio -vga std
 | 
			
		||||
	$(EMULATOR)  -kernel $(BUILD_DIR)/myos.bin -serial file:CON -vga std -monitor stdio -display gtk -m 2G -cpu core2duo -drive file=demodisk.img
 | 
			
		||||
 | 
			
		||||
build_kernel: $(OBJ_LINK_LIST)
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
@ -10,18 +10,17 @@ ________________________
 | 
			
		||||
The first scrolling boot screen. 😲
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<img src="screenshots/WIP_interruptHandling.png"></img>
 | 
			
		||||
   \
 | 
			
		||||
W.I.P - Working on interrupt handling
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 \
 | 
			
		||||
Multiboot information can be read by the kernel.
 | 
			
		||||
________________________
 | 
			
		||||
 | 
			
		||||
### The goal
 | 
			
		||||
Writing a hobby operating system to better understand the basic building blocks of any operating system.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
________________________
 | 
			
		||||
### Operating System Technical specs/details
 | 
			
		||||
The operating system can print strings to the 
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								screenshots/multiboot.png
									 (Stored with Git LFS)
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								screenshots/multiboot.png
									 (Stored with Git LFS)
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@ -23,6 +23,9 @@ void irs_handler (registers regs) {
 | 
			
		||||
            printf(" Error code: %d \n", regs.err_code);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
  
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,48 @@ void kterm_putat (char c, uint8_t color, size_t x, size_t y ) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor ){
 | 
			
		||||
    outb(0x3D4, 0x0A);
 | 
			
		||||
    outb(0x3D5, (inb(0x3D5) & 0xC0) | start_cursor);
 | 
			
		||||
 | 
			
		||||
    outb(0x3D4, 0x0B);
 | 
			
		||||
    outb(0x3D5, (inb(0x3D5) & 0xE0) | end_cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void disable_cursor() 
 | 
			
		||||
{
 | 
			
		||||
        outb(0x3D4, 0x0A);
 | 
			
		||||
        outb(0x3D5, 0x20);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void update_cursor(int x, int y){
 | 
			
		||||
    uint16_t pos = y * VGA_WIDTH + x;
 | 
			
		||||
 | 
			
		||||
    outb(0x3D4, 0x0F);
 | 
			
		||||
    outb(0x3D5, (uint8_t) (pos & 0xFF));
 | 
			
		||||
    outb(0x3D4, 0x0E);
 | 
			
		||||
    outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t get_cursor_position(){
 | 
			
		||||
    uint16_t pos = 0;
 | 
			
		||||
    outb(0x3D4, 0x0F);
 | 
			
		||||
    pos |= inb(0x3D5);
 | 
			
		||||
    outb(0x3D4, 0x0E);
 | 
			
		||||
    pos |= ((uint16_t) inb(0x3D5)) << 8;
 | 
			
		||||
    return pos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_cursor_x (uint16_t cursor_pos) {
 | 
			
		||||
    return cursor_pos % VGA_WIDTH;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int get_cursor_y (uint16_t cursor_pos ) {
 | 
			
		||||
    return cursor_pos / VGA_WIDTH;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  With the help from:
 | 
			
		||||
@ -63,6 +105,7 @@ void kterm_scrollup(){
 | 
			
		||||
 | 
			
		||||
void kterm_put (char c) {
 | 
			
		||||
    if(++kterm_column == VGA_WIDTH || c == '\n' ) {
 | 
			
		||||
        update_cursor(kterm_column , kterm_row);
 | 
			
		||||
        kterm_column = 0;
 | 
			
		||||
        if(kterm_row == VGA_HEIGHT-1 ) {       
 | 
			
		||||
            kterm_scrollup();
 | 
			
		||||
 | 
			
		||||
@ -5,12 +5,14 @@
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#include "../vga/colors.h"
 | 
			
		||||
 | 
			
		||||
#include "../../../io.h"
 | 
			
		||||
void kterm_init();
 | 
			
		||||
 | 
			
		||||
/* Kernel terminal - Colour functions*/
 | 
			
		||||
void kterm_resetcolor();
 | 
			
		||||
void kterm_setcolor(uint8_t);
 | 
			
		||||
 | 
			
		||||
/* Kernel terminal - Printing function */
 | 
			
		||||
void kterm_putat(char, uint8_t, size_t, size_t);
 | 
			
		||||
void kterm_put(char);
 | 
			
		||||
void kterm_write(const char*, size_t);
 | 
			
		||||
@ -18,6 +20,15 @@ void kterm_writestring(const char*);
 | 
			
		||||
void kterm_scrollup();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Kernel terminal - Cursor functions */
 | 
			
		||||
void enable_cursor (uint8_t start_cursor , uint8_t end_cursor );
 | 
			
		||||
void disable_cursor();
 | 
			
		||||
void update_cursor(int x, int y);
 | 
			
		||||
uint16_t get_cursor_position();
 | 
			
		||||
int get_cursor_x (uint16_t cursor_pos);
 | 
			
		||||
int get_cursor_y (uint16_t cursor_pos);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void printf ( const char *format, ...);
 | 
			
		||||
 | 
			
		||||
static void itoa (char *buf, int base, int d);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										41
									
								
								src/kernel/arch/i386/vga/VBE.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/kernel/arch/i386/vga/VBE.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
 | 
			
		||||
#define VBE_DISPI_IOPORT_INDEX 0x01CE
 | 
			
		||||
#define VBE_DISPI_IOPORT_DATA 0x01CF
 | 
			
		||||
 | 
			
		||||
/* VBE index values*/
 | 
			
		||||
#define VBE_DISPI_INDEX_ID              0x0
 | 
			
		||||
#define VBE_DISPI_INDEX_XRES            0x1
 | 
			
		||||
#define VBE_DISPI_INDEX_YRES            0x2
 | 
			
		||||
#define VBE_DISPI_INDEX_BPP             0x3
 | 
			
		||||
#define VBE_DISPI_INDEX_ENABLE          0x4
 | 
			
		||||
#define VBE_DISPI_INDEX_BANK            0x5
 | 
			
		||||
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
 | 
			
		||||
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
 | 
			
		||||
#define VBE_DISPI_INDEX_X_OFFSET        0x8
 | 
			
		||||
#define VBE_DISPI_INDEX_Y_OFFSET        0x9
 | 
			
		||||
 | 
			
		||||
/* BGA Version */
 | 
			
		||||
#define VBE_DISPI_ID5   0xB0C5
 | 
			
		||||
#define VBE_DISPI_ID4   0xB0C3 
 | 
			
		||||
#define VBE_DISPI_ID3   0xB0C2
 | 
			
		||||
#define VBE_DISPI_ID2   0xB0C1
 | 
			
		||||
#define VBE_DISPI_ID1   0xB0C0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* BGA BIT DEPTH */
 | 
			
		||||
#define VBE_DISPI_BPP_4 0x04
 | 
			
		||||
#define VBE_DISPI_BPP_8 0x08
 | 
			
		||||
#define VBE_DISPI_BPP_15 0x0F
 | 
			
		||||
#define VBE_DISPI_BPP_16 0x10
 | 
			
		||||
#define VBE_DISPI_BPP_24 0x18
 | 
			
		||||
#define VBE_DISPI_BPP_32 0x20
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /*unsigned short BGAReadRegister(unsigned short IndexValue){
 | 
			
		||||
        // outpw(VBE_DISPI_IOPORT_INDEX, IndexValue);
 | 
			
		||||
       // return inpw (VBE_DISPI_IOPORT_DATA);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int BGAIsAvailable (){
 | 
			
		||||
        return (BGAReadRegister(VBE_DISPI_INDEX_ID) == VBE_DISPI_ID5);
 | 
			
		||||
    }*/
 | 
			
		||||
							
								
								
									
										16
									
								
								src/kernel/cpu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/kernel/cpu.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
#include <cpuid.h> // NOTE: Only available in GCC 
 | 
			
		||||
 | 
			
		||||
    static int get_model(){
 | 
			
		||||
        int ebx, unused;
 | 
			
		||||
        __cpuid(0, unused, ebx, unused, unused);
 | 
			
		||||
        return ebx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    enum {
 | 
			
		||||
        CPUID_FEAT_EDX_APIC = 1 << 9
 | 
			
		||||
    };
 | 
			
		||||
    static int check_apic (){
 | 
			
		||||
        unsigned int eax, unused, edx;
 | 
			
		||||
        __get_cpuid(1, &eax, &unused, &unused, &edx);
 | 
			
		||||
        return  edx & CPUID_FEAT_EDX_APIC;
 | 
			
		||||
    }
 | 
			
		||||
@ -1,108 +1,14 @@
 | 
			
		||||
#include "kernel.h"
 | 
			
		||||
/**
 | 
			
		||||
 *      simple delay function 
 | 
			
		||||
 **/
 | 
			
		||||
void delay(int t){
 | 
			
		||||
    volatile int i,j;
 | 
			
		||||
    for(i=0;i<t;i++)
 | 
			
		||||
        for(j=0;j<25000;j++)
 | 
			
		||||
            asm("NOP");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Test {
 | 
			
		||||
    public:
 | 
			
		||||
         Test();
 | 
			
		||||
        void printMe();
 | 
			
		||||
         ~Test();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Test::Test(){
 | 
			
		||||
    kterm_writestring("Create a test object\n");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Test::printMe(){
 | 
			
		||||
    kterm_writestring("testObject.printMe()\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Test::~Test(){
 | 
			
		||||
    kterm_writestring("Destroy testObject! Bye bye\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PORT 0x3f8 
 | 
			
		||||
static int init_serial() {
 | 
			
		||||
   outb(PORT + 1, 0x00);    // Disable all interrupts
 | 
			
		||||
   outb(PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
 | 
			
		||||
   outb(PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
 | 
			
		||||
   outb(PORT + 1, 0x00);    //                  (hi byte)
 | 
			
		||||
   outb(PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
 | 
			
		||||
   outb(PORT + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
 | 
			
		||||
   outb(PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
 | 
			
		||||
   outb(PORT + 4, 0x1E);    // Set in loopback mode, test the serial chip
 | 
			
		||||
   outb(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(inb(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)
 | 
			
		||||
   outb(PORT + 4, 0x0F);
 | 
			
		||||
   return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_transmit_empty() {
 | 
			
		||||
   return inb(PORT + 5) & 0x20;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
void write_serial(char a) {
 | 
			
		||||
   while (is_transmit_empty() == 0);
 | 
			
		||||
 
 | 
			
		||||
   outb(PORT,a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int serial_received() {
 | 
			
		||||
   return inb(PORT + 5) & 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
char read_serial() {
 | 
			
		||||
   while (serial_received() == 0);
 | 
			
		||||
 
 | 
			
		||||
   return inb(PORT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_serial(const char* string ){
 | 
			
		||||
    for(size_t i = 0; i < strlen(string); i ++){
 | 
			
		||||
        write_serial(string[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_serial(){
 | 
			
		||||
        /** Serial test **/
 | 
			
		||||
        kterm_writestring("Writing to COM1 serial port:");
 | 
			
		||||
        init_serial();
 | 
			
		||||
        write_serial('A');
 | 
			
		||||
        write_serial('B');
 | 
			
		||||
        write_serial('C');
 | 
			
		||||
        write_serial('D');
 | 
			
		||||
        write_serial('E');
 | 
			
		||||
 | 
			
		||||
        char Character_received = read_serial();
 | 
			
		||||
        kterm_writestring("\n");
 | 
			
		||||
        kterm_writestring("received from COM 1: \n");
 | 
			
		||||
        kterm_put(Character_received);
 | 
			
		||||
 | 
			
		||||
        kterm_writestring("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
 | 
			
		||||
     multiboot_info_t *mbi;
 | 
			
		||||
    void early_main(unsigned long magic, unsigned long addr){
 | 
			
		||||
 | 
			
		||||
        /** initialize terminal interface */ 
 | 
			
		||||
        kterm_init();
 | 
			
		||||
      
 | 
			
		||||
        multiboot_info_t *mbi;
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
        if (magic != MULTIBOOT_BOOTLOADER_MAGIC){
 | 
			
		||||
            printf("Invalid magic number: 0x%x\n", (unsigned) magic);
 | 
			
		||||
@ -199,31 +105,20 @@ extern "C" {
 | 
			
		||||
        if (CHECK_FLAG (mbi->flags, 12)){
 | 
			
		||||
            printf("Can draw!");
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        int cpu_model = get_model();
 | 
			
		||||
        int local_apic = check_apic();
 | 
			
		||||
        printf( "CPU Model: %x, Local APIC: %D\n", cpu_model, local_apic);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void kernel_main (void) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        init_serial();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /** Setup the MMU **/
 | 
			
		||||
        //kterm_writestring("Starting MMU...\n");
 | 
			
		||||
        //auto mmu = MMU();
 | 
			
		||||
        //mmu.enable();
 | 
			
		||||
        //kterm_writestring("MMU enabled!\n");
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
       
 | 
			
		||||
       
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
        /** test interrupt handlers **/
 | 
			
		||||
        //asm volatile ("int $0x03");
 | 
			
		||||
 | 
			
		||||
        //asm volatile ("int $0x04");
 | 
			
		||||
 | 
			
		||||
        while (true){
 | 
			
		||||
            //Read time indefinetely 
 | 
			
		||||
@ -232,14 +127,8 @@ extern "C" {
 | 
			
		||||
            delay(1000);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        /** Lets start using the serial port for debugging .. **/
 | 
			
		||||
        // Hopefully once we go into realmode or do something that
 | 
			
		||||
        // cause the screen to go black.. this serial comms part will give
 | 
			
		||||
        // some situational awareness
 | 
			
		||||
        //Serial serialbus = Serial::init();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
       
 | 
			
		||||
       
 | 
			
		||||
    }   
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,105 @@ extern "C" {
 | 
			
		||||
#include "MMU.h"
 | 
			
		||||
#include "io.h"
 | 
			
		||||
#include "time.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "arch/i386/vga/VBE.h"
 | 
			
		||||
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
 | 
			
		||||
 | 
			
		||||
/* This needs to be moved! */
 | 
			
		||||
/**
 | 
			
		||||
 *      simple delay function 
 | 
			
		||||
 **/
 | 
			
		||||
void delay(int t){
 | 
			
		||||
    volatile int i,j;
 | 
			
		||||
    for(i=0;i<t;i++)
 | 
			
		||||
        for(j=0;j<25000;j++)
 | 
			
		||||
            asm("NOP");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Test {
 | 
			
		||||
    public:
 | 
			
		||||
         Test();
 | 
			
		||||
        void printMe();
 | 
			
		||||
         ~Test();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Test::Test(){
 | 
			
		||||
    kterm_writestring("Create a test object\n");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void Test::printMe(){
 | 
			
		||||
    kterm_writestring("testObject.printMe()\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Test::~Test(){
 | 
			
		||||
    kterm_writestring("Destroy testObject! Bye bye\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PORT 0x3f8 
 | 
			
		||||
static int init_serial() {
 | 
			
		||||
   outb(PORT + 1, 0x00);    // Disable all interrupts
 | 
			
		||||
   outb(PORT + 3, 0x80);    // Enable DLAB (set baud rate divisor)
 | 
			
		||||
   outb(PORT + 0, 0x03);    // Set divisor to 3 (lo byte) 38400 baud
 | 
			
		||||
   outb(PORT + 1, 0x00);    //                  (hi byte)
 | 
			
		||||
   outb(PORT + 3, 0x03);    // 8 bits, no parity, one stop bit
 | 
			
		||||
   outb(PORT + 2, 0xC7);    // Enable FIFO, clear them, with 14-byte threshold
 | 
			
		||||
   outb(PORT + 4, 0x0B);    // IRQs enabled, RTS/DSR set
 | 
			
		||||
   outb(PORT + 4, 0x1E);    // Set in loopback mode, test the serial chip
 | 
			
		||||
   outb(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(inb(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)
 | 
			
		||||
   outb(PORT + 4, 0x0F);
 | 
			
		||||
   return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int is_transmit_empty() {
 | 
			
		||||
   return inb(PORT + 5) & 0x20;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
void write_serial(char a) {
 | 
			
		||||
   while (is_transmit_empty() == 0);
 | 
			
		||||
 
 | 
			
		||||
   outb(PORT,a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int serial_received() {
 | 
			
		||||
   return inb(PORT + 5) & 1;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
char read_serial() {
 | 
			
		||||
   while (serial_received() == 0);
 | 
			
		||||
 
 | 
			
		||||
   return inb(PORT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void print_serial(const char* string ){
 | 
			
		||||
    for(size_t i = 0; i < strlen(string); i ++){
 | 
			
		||||
        write_serial(string[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void test_serial(){
 | 
			
		||||
        /** Serial test **/
 | 
			
		||||
        kterm_writestring("Writing to COM1 serial port:");
 | 
			
		||||
        init_serial();
 | 
			
		||||
        write_serial('A');
 | 
			
		||||
        write_serial('B');
 | 
			
		||||
        write_serial('C');
 | 
			
		||||
        write_serial('D');
 | 
			
		||||
        write_serial('E');
 | 
			
		||||
 | 
			
		||||
        char Character_received = read_serial();
 | 
			
		||||
        kterm_writestring("\n");
 | 
			
		||||
        kterm_writestring("received from COM 1: \n");
 | 
			
		||||
        kterm_put(Character_received);
 | 
			
		||||
 | 
			
		||||
        kterm_writestring("\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user