This commit is contained in:
2021-09-14 18:34:14 +03:00
parent 7cb940e485
commit 4e5c38d0ff
152 changed files with 5042 additions and 2585 deletions

92
SysCore/hal/cmos/cmos.c Normal file
View File

@ -0,0 +1,92 @@
#include <system.h>
#include <time.h>
#include "cmos.h"
volatile byte i86_cmos_data[128];
void i86_cmos_write ()
{
byte i;
for (i = 0; i < 128; i++) {
//asm volatile ("cli");
outportb(0x70, i);
iowait();
outportb(0x71, i86_cmos_data[i]);
//asm volatile ("sti");
}
}
void i86_cmos_read ()
{
byte i;
for (i = 0; i < 128; i++) {
//asm volatile ("cli");
outportb(0x70, i);
iowait();
i86_cmos_data[i] = inportb(0x71);
//asm volatile ("sti");
}
}
void i86_cmos_read_clock(TIME* tim)
{
i86_cmos_read();
if ((i86_cmos_data[0x0b]&4)==0) // BCD = true;
{
tim->seconds = (i86_cmos_data[0x00]%16) + 10*(i86_cmos_data[0x00]/16);
tim->minutes = (i86_cmos_data[0x02]%16) + 10*(i86_cmos_data[0x02]/16);
if ((i86_cmos_data[0x0b]&2)==0) { // AM/PM
if (i86_cmos_data[0x04]&80) { // pm
tim->hours = ((i86_cmos_data[0x04]-0x80)%16) + 10*((i86_cmos_data[0x04]-0x80)/16);
tim->am_pm = 1;
}
else { // am
tim->hours = (i86_cmos_data[0x04]%16) + 10*(i86_cmos_data[0x04]/16);
tim->am_pm = 0;
}
}
else { // 24 hours
tim->hours = (i86_cmos_data[0x04]%16) + 10*(i86_cmos_data[0x04]/16);
if (tim->hours > 12) {
tim->am_pm = 1;
tim->hours -= 12;
}
else tim->am_pm = 0;
}
tim->weekday = (i86_cmos_data[0x06]%16) + 10*(i86_cmos_data[0x06]/16);
tim->day = (i86_cmos_data[0x07]%16) + 10*(i86_cmos_data[0x07]/16);
tim->month = (i86_cmos_data[0x08]%16) + 10*(i86_cmos_data[0x08]/16);
tim->year = (i86_cmos_data[0x09]%16) + 10*(i86_cmos_data[0x09]/16);
tim->century = (i86_cmos_data[0x32]%16) + 10*(i86_cmos_data[0x32]/16);
}
else {//BCD = false;
tim->seconds = i86_cmos_data[0x00];
tim->minutes = i86_cmos_data[0x02];
if ((i86_cmos_data[0x0b]&2)==0) { // AM/PM
if (i86_cmos_data[0x04]&80) { // pm
tim->hours = i86_cmos_data[0x04]-0x80;
tim->am_pm = 1;
}
else { // am
tim->hours = i86_cmos_data[0x04];
tim->am_pm = 0;
}
}
else { // 24 hours
tim->hours = i86_cmos_data[0x02];
if (tim->hours > 12) {
tim->am_pm = 1;
tim->hours -= 12;
}
else tim->am_pm = 0;
}
tim->weekday = i86_cmos_data[0x06];
tim->day = i86_cmos_data[0x07];
tim->month = i86_cmos_data[0x08];
tim->year = i86_cmos_data[0x09];
tim->century = i86_cmos_data[0x32];
}
}

10
SysCore/hal/cmos/cmos.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __CMOS_H
#define __CMOS_H
extern volatile byte i86_cmos_data[128];
extern void i86_cmos_write ();
extern void i86_cmos_read ();
extern void i86_cmos_read_clock (TIME *tim);
#endif

View File

@ -0,0 +1,18 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/cmos.o cmos.c
@echo off
@echo .
@echo Done!
@pause

43
SysCore/hal/compile.bat Normal file
View File

@ -0,0 +1,43 @@
@echo off
set loader_name=loader
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
@echo ***************** CTA KERNEL *****************
:KernelEntry
@echo.
@echo Building Kernel entry...
@echo * Compiling kernel loader...
%nasm_path%\nasm.exe -f aout -o ./objects/%loader_name%.o %loader_name%.asm
@echo * Compiling kernel main...
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I./include -c -o ./objects/main.o main.c
:KernelSTDLIB
cd lib
call compile.bat
cd..
:KernelMemoryManager
cd memory
call compile.bat
cd..
rem here go other sources:
rem here go other sources ^
:Finish
cd objects
@echo Linking...
%djgpp_path%\ld -T link.ld
@echo.
echo Copying to floppy drive...
copy KERNEL.BIN A:\KERNEL.CTA
cd..

View File

@ -0,0 +1,18 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/cpu.o cpu.c
@echo off
@echo .
@echo Done!
@pause

35
SysCore/hal/cpu/cpu.c Normal file
View File

@ -0,0 +1,35 @@
#include <system.h>
#include "cpu.h"
#include "../gdt/gdt.h"
#include "../idt/idt.h"
#define cpuid(in, a, b, c, d) __asm__("cpuid": "=a" (a), "=b" (b), "=c" (c), "=d" (d) : "a" (in));
// initializes cpu resources
void i86_cpu_initialize()
{
// initialize processor tables
i86_gdt_install();
i86_idt_install();
}
void i86_cpu_shutdown()
{
}
char* i86_cpu_get_vender()
{
static char vender[13];
dword unused, arr[3];
int i;
cpuid(0, unused, arr[0], arr[2], arr[1]);
for (i=0; i<12; i++)
vender[i] = (arr[i/4]>>(i%4*8)) && 0xFF;
vender[12] = 0;
return vender;
}

29
SysCore/hal/cpu/cpu.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef _CPU_H_INCLUDED
#define _CPU_H_INCLUDED
//****************************************************************************
//**
//** cpu.h
//**
//** This is the processor interface. Everything outside of this module
//** must use this interface when working on processor data.
//**
//** A processor is a module that manages the very basic data structures
//** and data within the system. The processor interface provides the interface
//** for managing processors, processor cores, accessing processor structures,
//** and more
//**
//****************************************************************************
#include <stdint.h>
#include <regs.h>
//! initialize the processors
extern void i86_cpu_initialize ();
//! shutdown the processors
extern void i86_cpu_shutdown ();
//! get cpu vender
extern char* i86_cpu_get_vender ();
#endif

View File

@ -0,0 +1,19 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%nasm_path%\nasm.exe -f aout -o %objpath%/gdt_asm.o gdt.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/gdt.o gdt.c
@echo off
@echo .
@echo Done!
@pause

20
SysCore/hal/gdt/gdt.asm Normal file
View File

@ -0,0 +1,20 @@
bits 32
; !!! GDT !!!
; This will set up our new segment registers. We need to do
; something special in order to set CS. We do what is called a
; far jump. A jump that includes a segment as well as an offset.
; This is declared in C as 'extern void gdt_flush();'
global _i86_gdt_flush ; Allows the C code to link to this
extern _gp ; Says that '_gp' is in another file
_i86_gdt_flush:
lgdt [_gp] ; Load the GDT with our '_gp' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
flush2:
ret ; Returns back to the C code!

65
SysCore/hal/gdt/gdt.c Normal file
View File

@ -0,0 +1,65 @@
/******************************************************************
* gdt.c - GLOBAL DESCRIPTOR TABLE *
* Contains function prototypes for setting up the GDT *
******************************************************************/
#define MAX_DESCRIPTORS 3
#include "gdt.h"
/* Our GDT, with 3 entries, and finally our special GDT pointer */
struct gdt_entry gdt[3];
struct gdt_ptr gp;
/* Setup a descriptor in the Global Descriptor Table */
void i86_gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{
/* Setup the descriptor base address */
gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;
/* Setup the descriptor limits */
gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);
/* Finally, set up the granularity and access flags */
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}
struct gdt_entry* i86_gdt_get_gate(int num)
{
if (num>MAX_DESCRIPTORS) return 0;
return &gdt[num];
}
/* Should be called by main. This will setup the special GDT
* pointer, set up the first 3 entries in our GDT, and then
* finally call gdt_flush() in our assembler file in order
* to tell the processor where the new GDT is and update the
* new segment registers */
void i86_gdt_install()
{
/* Setup the GDT pointer and limit */
gp.limit = (sizeof(struct gdt_entry) * 3) - 1;
gp.base = (unsigned int)&gdt;
/* Our NULL descriptor */
i86_gdt_set_gate(0, 0, 0, 0, 0);
/* The second entry is our Code Segment. The base address
* is 0, the limit is 4GBytes, it uses 4KByte granularity,
* uses 32-bit opcodes, and is a Code Segment descriptor.
* Please check the table above in the tutorial in order
* to see exactly what each value means */
i86_gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
/* The third entry is our Data Segment. It's EXACTLY the
* same as our code segment, but the descriptor type in
* this entry's access byte says it's a Data Segment */
i86_gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
/* Flush out the old GDT and install the new changes! */
i86_gdt_flush();
}

39
SysCore/hal/gdt/gdt.h Normal file
View File

@ -0,0 +1,39 @@
/******************************************************************
* gdt.h - GLOBAL DESCRIPTOR TABLE *
* Contains structures and function declarations for GDT *
******************************************************************/
#ifndef __GDT_H
#define __GDT_H
/* Defines a GDT entry. We say packed, because it prevents the
* compiler from doing things that it thinks is best: Prevent
* compiler "optimization" by packing */
struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));
/* Special pointer which includes the limit: The max bytes
* taken up by the GDT, minus 1. Again, this NEEDS to be packed */
struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/* This will be a function in start.asm. We use this to properly
* reload the new segment registers */
extern void i86_gdt_flush();
extern void i86_gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran);
extern struct gdt_entry* i86_gdt_get_gate(int num);
extern void i86_gdt_install();
#endif

184
SysCore/hal/hal.c Normal file
View File

@ -0,0 +1,184 @@
#include <system.h>
#include <time.h>
#include <hal.h>
#include "cpu/cpu.h"
#include "gdt/gdt.h"
#include "idt/idt.h"
#include "pic/pic.h"
#include "pit/pit.h"
#include "cmos/cmos.h"
#include "irq/irq.h"
#include "isrs/isrs.h"
#include "keyboard/keyus.h"
// initialize hardware devices
void i86_hal_initialize () {
// initialize motherboard controllers and system timer
i86_cpu_initialize (); // (install GDT, IDT)
i86_isrs_install(); // (install ISR handler)
i86_irq_install(); // (install IRQ handler)
// install PIT and system clock; pit at 100 Hz
i86_kb_install_partone();
i86_cmos_read_clock((TIME*)&_internal_clock);
i86_pit_install (100);
i86_kb_install_parttwo();
// enable interrupts
i86_start_interrupts();
}
// shutdown hardware devices
int i86_hal_shutdown () {
i86_cpu_shutdown ();
return 0;
}
void reboot()
{
unsigned char good = 0x02;
while ((good & 0x02) != 0)
good = inportb(0x64);
outportb(0x64, 0xFE);
__asm__ __volatile__ ("hlt");
}
//! notifies hal interrupt is done
/*inline void interruptdone (unsigned int intno) {
//! insure its a valid hardware irq
if (intno > 16)
return;
//! test if we need to send end-of-interrupt to second pic
if (intno >= 8)
i86_pic_send_command (0x20, 0xA1);
//! always send end-of-interrupt to primary pic
i86_pic_send_command (0x20, 0x21);
}
*/
//! output sound to speaker
void sound (unsigned frequency) {
//! sets frequency for speaker. frequency of 0 disables speaker
outportb (0x61, 3 | (byte)(frequency<<2) );
}
//! sets new interrupt vector
/*void _cdecl setvect (int intno, void (_cdecl far &vect) ( ) ) {
//! install interrupt handler! This overwrites prev interrupt descriptor
i86_install_ir (intno, I86_IDT_DESC_PRESENT | I86_IDT_DESC_BIT32,
0x8, vect);
}
//! returns current interrupt vector
void (_cdecl far * _cdecl getvect (int intno)) ( ) {
//! get the descriptor from the idt
idt_descriptor* desc = i86_get_ir (intno);
if (!desc)
return 0;
//! get address of interrupt handler
uint32_t addr = desc->baseLo | (desc->baseHi << 16);
//! return interrupt handler
I86_IRQ_HANDLER irq = (I86_IRQ_HANDLER)addr;
return irq;
}
*/
//! returns cpu vender
const char* get_cpu_vender () {
return i86_cpu_get_vender();
}
/***************************************************************************************
* Keyboard Routines *
***************************************************************************************/
char getch()
{
kb_key alpha = getkey();
return alpha.character;
}
char scancode_to_ascii(byte scancode, byte status)
{
if ((status&1) || (status&2)) return kbdus_map_shift[scancode];
else return kbdus_map[scancode];
}
byte get_key_status (byte scancode)
{
if (scancode&0xF0) return kb_lights_status&0x0F;
else if (scancode&0x80) return kb_modifier_status&0x7F;
return i86_kb_get_key(scancode);
}
/***************************************
* Set repeat rate/delay *
***************************************
Values for inter-character delay (bits 4-0)
(characters per second; default is 10.9)
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
----+----+----+----+----+----+----+----+----
0 |30.0|26.7|24.0|21.8|20.0|18.5|17.1|16.0
8 |15.0|13.3|12.0|10.9|10.0|9.2 |8.6 |8.0
16 |7.5 |6.7 |6.0 |5.5 |5.0 |4.6 |4.3 |4.0
24 |3.7 |3.3 |3.0 |2.7 |2.5 |2.3 |2.1 |2.0
Values for delay:
(miliseconds; default is 500)
0 | 1 | 2 | 3
-----+-----+-----+-----
250 | 500 | 750 | 1000
***************************************/
void kb_set_repeat(float rate, int delay){
float rates[] = {30.0, 26.7, 24.0, 21.8, 20.0, 18.5, 17.1, 16.0, 15.0, 13.3, 12.0,
10.9, 10.0, 9.2, 8.6, 8.0, 7.5, 6.7, 6.0, 5.5, 5.0, 4.6, 4.3, 4.0,
3.7, 3.3, 3.0, 2.7, 2.5, 2.3, 2.1, 2.0} ;
byte r,d;
for (r = 0; rate != rates[r] && r < 32; r++)
if (rate==32) return;
switch(delay) {
case 250: d = 0; break;
case 500: d = 1; break;
case 750: d = 2; break;
case 1000: d = 3; break;
default: return;
}
i86_kb_set_repeat(r,d);
}
/***************************************
* Set keyboard LEDs *
***************************************
+-----------+-------+-------+--------+
| Bits 7-3 | Bit 2 | Bit 1 | Bit 0 |
| 0 | Caps | Num | Scroll |
|(reserved) | lock | lock | lock |
+-----------+-------+-------+--------+
***************************************/
void kb_set_LEDs(byte status) {
i86_kb_set_LEDs(status);
}

View File

@ -0,0 +1,19 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%nasm_path%\nasm.exe -f aout -o %objpath%/idt_asm.o idt.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/idt.o idt.c
@echo off
@echo .
@echo Done!
@pause

9
SysCore/hal/idt/idt.asm Normal file
View File

@ -0,0 +1,9 @@
bits 32
; !!! IDT !!!
; Loads the IDT defined in '_idtp'
global _i86_idt_load
extern _idtp
_i86_idt_load:
lidt [_idtp]
ret

49
SysCore/hal/idt/idt.c Normal file
View File

@ -0,0 +1,49 @@
/******************************************************************
* idt.h - INTERRUPT DESCRIPTOR TABLE *
* Contains structures and function declarations for IDT *
******************************************************************/
#include <system.h>
#include "idt.h"
/* Declare an IDT of 256 entries. Although we will only use the
* first 32 entries in this tutorial, the rest exists as a bit
* of a trap. If any undefined IDT entry is hit, it normally
* will cause an "Unhandled Interrupt" exception. Any descriptor
* for which the 'presence' bit is cleared (0) will generate an
* "Unhandled Interrupt" exception */
struct idt_entry idt[256];
struct idt_ptr idtp;
/* Use this function to set an entry in the IDT. Alot simpler
* than twiddling with the GDT ;) */
void i86_idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags)
{
/* The interrupt routine's base address */
idt[num].base_lo = (base & 0xFFFF);
idt[num].base_hi = (base >> 16) & 0xFFFF;
/* The segment or 'selector' that this IDT entry will use
* is set here, along with any access flags */
idt[num].sel = sel;
idt[num].always0 = 0;
idt[num].flags = flags;
}
struct idt_entry* i86_idt_get_gate(unsigned char num)
{
return &idt[num];
}
/* Installs the IDT */
void i86_idt_install()
{
/* Sets the special IDT pointer up, just like in 'gdt.c' */
idtp.limit = (sizeof (struct idt_entry) * 256) - 1;
idtp.base = (unsigned int)&idt;
/* Clear out the entire IDT, initializing it to zeros */
memset (&idt, 0, sizeof(struct idt_entry) * 256);
/* Points the processor's internal register to the new IDT */
i86_idt_load();
}

32
SysCore/hal/idt/idt.h Normal file
View File

@ -0,0 +1,32 @@
/******************************************************************
* idt.h - INTERRUPT DESCRIPTOR TABLE *
* Contains structures and function declarations for IDT *
******************************************************************/
#ifndef __IDT_H
#define __IDT_H
/* Defines an IDT entry */
struct idt_entry
{
unsigned short base_lo;
unsigned short sel;
unsigned char always0;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));
struct idt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));
/* This exists in 'start.asm', and is used to load our IDT */
extern void i86_idt_load();
extern void i86_idt_set_gate(unsigned char num, unsigned long base, unsigned short sel, unsigned char flags);
extern struct idt_entry* i86_idt_get_gate(unsigned char num);
extern void i86_idt_install();
#endif

View File

@ -0,0 +1,19 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%nasm_path%\nasm.exe -f aout -o %objpath%/irq_asm.o irq.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/irq.o irq.c
@echo off
@echo .
@echo Done!
@pause

159
SysCore/hal/irq/irq.asm Normal file
View File

@ -0,0 +1,159 @@
bits 32
; !!! IRQ !!!
global _i86_irq0
global _i86_irq1
global _i86_irq2
global _i86_irq3
global _i86_irq4
global _i86_irq5
global _i86_irq6
global _i86_irq7
global _i86_irq8
global _i86_irq9
global _i86_irq10
global _i86_irq11
global _i86_irq12
global _i86_irq13
global _i86_irq14
global _i86_irq15
; 32: IRQ0
_i86_irq0:
cli
push byte 0
push byte 32; Note that these don't push an error code on the stack:
; We need to push a dummy error code
jmp irq_common_stub
; 33: IRQ1
_i86_irq1:
cli
push byte 0
push byte 33
jmp irq_common_stub
; 34: IRQ2
_i86_irq2:
cli
push byte 0
push byte 34
jmp irq_common_stub
; 35: IRQ3
_i86_irq3:
cli
push byte 0
push byte 35
jmp irq_common_stub
; 36: IRQ4
_i86_irq4:
cli
push byte 0
push byte 36
jmp irq_common_stub
; 37: IRQ5
_i86_irq5:
cli
push byte 0
push byte 37
jmp irq_common_stub
; 38: IRQ6
_i86_irq6:
cli
push byte 0
push byte 38
jmp irq_common_stub
; 39: IRQ7
_i86_irq7:
cli
push byte 0
push byte 39
jmp irq_common_stub
; 40: IRQ8
_i86_irq8:
cli
push byte 0
push byte 40
jmp irq_common_stub
; 41: IRQ9
_i86_irq9:
cli
push byte 0
push byte 41
jmp irq_common_stub
; 42: IRQ10
_i86_irq10:
cli
push byte 0
push byte 42
jmp irq_common_stub
; 43: IRQ11
_i86_irq11:
cli
push byte 0
push byte 43
jmp irq_common_stub
; 44: IRQ12
_i86_irq12:
cli
push byte 0
push byte 44
jmp irq_common_stub
; 45: IRQ13
_i86_irq13:
cli
push byte 0
push byte 45
jmp irq_common_stub
; 46: IRQ14
_i86_irq14:
cli
push byte 0
push byte 46
jmp irq_common_stub
; 47: IRQ15
_i86_irq15:
cli
push byte 0
push byte 47
jmp irq_common_stub
extern _i86_irq_handler
; This is a stub that we have created for IRQ based ISRs. This calls
; '_i86_irq_handler' in our C code. We need to create this in an 'irq.c'
irq_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, _i86_irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret

79
SysCore/hal/irq/irq.c Normal file
View File

@ -0,0 +1,79 @@
#include <system.h>
#include "../idt/idt.h"
#include "../pic/pic.h"
#include "irq.h"
/* This array is actually an array of function pointers. We use
* this to handle custom IRQ handlers for a given IRQ */
void *irq_routines[16] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
/* This installs a custom IRQ handler for the given IRQ */
void i86_irq_install_handler (int irq, void (*handler)(ISR_stack_regs *r))
{
irq_routines[irq] = handler;
}
void i86_irq_uninstall_handler (int irq)
{
irq_routines[irq] = 0;
}
/* We first remap the interrupt controllers, and then we install
* the appropriate ISRs to the correct entries in the IDT. This
* is just like installing the exception handlers */
void i86_irq_install()
{
i86_pic_remap(32,40);
i86_idt_set_gate(32, (unsigned)i86_irq0, 0x08, 0x8E);
i86_idt_set_gate(33, (unsigned)i86_irq1, 0x08, 0x8E);
i86_idt_set_gate(34, (unsigned)i86_irq2, 0x08, 0x8E);
i86_idt_set_gate(35, (unsigned)i86_irq3, 0x08, 0x8E);
i86_idt_set_gate(36, (unsigned)i86_irq4, 0x08, 0x8E);
i86_idt_set_gate(37, (unsigned)i86_irq5, 0x08, 0x8E);
i86_idt_set_gate(38, (unsigned)i86_irq6, 0x08, 0x8E);
i86_idt_set_gate(39, (unsigned)i86_irq7, 0x08, 0x8E);
i86_idt_set_gate(40, (unsigned)i86_irq8, 0x08, 0x8E);
i86_idt_set_gate(41, (unsigned)i86_irq9, 0x08, 0x8E);
i86_idt_set_gate(42, (unsigned)i86_irq10, 0x08, 0x8E);
i86_idt_set_gate(43, (unsigned)i86_irq11, 0x08, 0x8E);
i86_idt_set_gate(44, (unsigned)i86_irq12, 0x08, 0x8E);
i86_idt_set_gate(45, (unsigned)i86_irq13, 0x08, 0x8E);
i86_idt_set_gate(46, (unsigned)i86_irq14, 0x08, 0x8E);
i86_idt_set_gate(47, (unsigned)i86_irq15, 0x08, 0x8E);
}
/* Each of the IRQ ISRs point to this function, rather than
* the 'fault_handler' in 'isrs.c'. The IRQ Controllers need
* to be told when you are done servicing them, so you need
* to send them an "End of Interrupt" command (0x20). There
* are two 8259 chips: The first exists at 0x20, the second
* exists at 0xA0. If the second controller (an IRQ from 8 to
* 15) gets an interrupt, you need to acknowledge the
* interrupt at BOTH controllers, otherwise, you only send
* an EOI command to the first controller. If you don't send
* an EOI, you won't raise any more IRQs */
void i86_irq_handler (ISR_stack_regs *r)
{
/* This is a blank function pointer */
void (*handler)(ISR_stack_regs *r);
/* Find out if we have a custom handler to run for this
* IRQ, and then finally, run it */
handler = irq_routines[r->int_no - 32];
if (handler) handler(r);
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send an EOI to
* the slave controller */
if (r->int_no >=40) outportb(0x0A, 0x20);
/* In either case, we need to send an EOI to the master
* interrupt controller too */
outportb(0x20, 0x20);
}

29
SysCore/hal/irq/irq.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __IRQ_H
#define __IRQ_H
/* These are own ISRs that point to our special IRQ handler
* instead of the regular 'fault_handler' function */
extern void i86_irq0();
extern void i86_irq1();
extern void i86_irq2();
extern void i86_irq3();
extern void i86_irq4();
extern void i86_irq5();
extern void i86_irq6();
extern void i86_irq7();
extern void i86_irq8();
extern void i86_irq9();
extern void i86_irq10();
extern void i86_irq11();
extern void i86_irq12();
extern void i86_irq13();
extern void i86_irq14();
extern void i86_irq15();
extern void i86_irq_install_handler (int irq, void (*handler)(ISR_stack_regs *r));
extern void i86_irq_uninstall_handler (int irq);
extern void i86_irq_install();
extern void i86_irq_handler (ISR_stack_regs *r);
#endif

79
SysCore/hal/isrs/BSOD.c Normal file
View File

@ -0,0 +1,79 @@
#include <system.h>
#include <conio.h>
char *exception_messages[] = {
"Division By Zero Exception",
"Debug Exception",
"Non Maskable Interrupt Exception",
"Breakpoint Exception",
"Into Detected Overflow Exception",
"Out of Bounds Exception",
"Invalid Opcode Exception",
"No Coprocessor",
"Double Fault Exception",
"Coprocessor Segment Overrun Exception",
"Bad TSS Exception",
"Segment Not Present Exception",
"Stack Fault Exception",
"General Protection Fault Exception",
"Page Fault Exception",
"Unknown Interrupt Exception",
"Coprocessor Fault Exception",
"Alignment Check Exception",
"Machine Check Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception",
"Reserved Exception"
};
void _STOP_ERROR_SCREEN (ISR_stack_regs *r)
{
set_default_colors (0x01, 0x0F); clrscr();
puts (" Blue Screen Of Death\n");
int i; for (i = 79; i>=0; i--) putc('=');
puts_pos_font (15, 2, "A fatal error has occured, CTA OS has been halted.", 0x01, 0x0C);
puts_pos_font (10, 4, "gs", 0x01, 0x0B); put_hex_pos(15, 4, r->gs);
puts_pos_font (10, 5, "fs", 0x01, 0x0B); put_hex_pos(15, 5, r->fs);
puts_pos_font (10, 6, "es", 0x01, 0x0B); put_hex_pos(15, 6, r->es);
puts_pos_font (10, 7, "ds", 0x01, 0x0B); put_hex_pos(15, 7, r->ds);
puts_pos_font (40, 4, "edi", 0x01, 0x0B); put_hex_pos(45, 4, r->edi);
puts_pos_font (40, 5, "esi", 0x01, 0x0B); put_hex_pos(45, 5, r->esi);
puts_pos_font (40, 6, "ebp", 0x01, 0x0B); put_hex_pos(45, 6, r->ebp);
puts_pos_font (40, 7, "esp", 0x01, 0x0B); put_hex_pos(45, 7, r->esp);
puts_pos_font (10, 9, "eax", 0x01, 0x0B); put_hex_pos(15, 9, r->eax);
puts_pos_font (10, 10, "ebx", 0x01, 0x0B); put_hex_pos(15, 10, r->ebx);
puts_pos_font (40, 9, "ecx", 0x01, 0x0B); put_hex_pos(45, 9, r->ecx);
puts_pos_font (40, 10, "edx", 0x01, 0x0B); put_hex_pos(45, 10, r->edx);
puts_pos_font (10, 12, "int_no", 0x01, 0x0B); put_hex_pos(17, 12, r->int_no);
puts_pos_font (10, 14, "Error code:", 0x01, 0x0B); put_hex_pos(24, 14, r->err_code);
puts_pos_font (10, 15, "Error msg: ", 0x01, 0x0B); puts_pos(24, 15, exception_messages[r->int_no]);
puts_pos_font (10, 17, "eip", 0x01, 0x0B); put_hex_pos(17, 17, r->eip);
puts_pos_font (10, 18, "cs", 0x01, 0x0B); put_hex_pos(17, 18, r->cs);
puts_pos_font (10, 19, "eflags", 0x01, 0x0B); put_hex_pos(17, 19, r->eflags);
puts_pos_font (10, 20, "useresp", 0x01, 0x0B); put_hex_pos(17, 20, r->useresp);
puts_pos_font (10, 21, "ss", 0x01, 0x0B); put_hex_pos(17, 21, r->ss);
puts_pos_font (29, 24, "!!! System Halted !!!", 0x01, 0x0C);
}
/*void _STOP_ERROR_SCREEN (ISR_stack_regs *r)
{
puts_pos_font (30, 24, "Stop error 0x", 0x01, 0x0B); put_hex_pos(37, 24, r->int_no);
puts_pos(50, 24, exception_messages[r->int_no]);
puts_pos_font (5, 24, "!!! System Halted !!!", 0x01, 0x0C);
}*/

View File

@ -0,0 +1,20 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%nasm_path%\nasm.exe -f aout -o %objpath%/isrs_asm.o isrs.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/isrs.o isrs.c
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/BSOD.o BSOD.c
@echo off
@echo .
@echo Done!
@pause

217
SysCore/hal/isrs/isrs.asm Normal file
View File

@ -0,0 +1,217 @@
bits 32
; !!! ISRs !!!
global _i86_isr0
global _i86_isr1
global _i86_isr2
global _i86_isr3
global _i86_isr4
global _i86_isr5
global _i86_isr6
global _i86_isr7
global _i86_isr8
global _i86_isr9
global _i86_isr10
global _i86_isr11
global _i86_isr12
global _i86_isr13
global _i86_isr14
global _i86_isr15
global _i86_isr16
global _i86_isr17
global _i86_isr18
global _i86_isr19
global _i86_isr20
global _i86_isr21
global _i86_isr22
global _i86_isr23
global _i86_isr24
global _i86_isr25
global _i86_isr26
global _i86_isr27
global _i86_isr28
global _i86_isr29
global _i86_isr30
global _i86_isr31
_i86_isr0:
cli
push byte 0; A normal ISR stub that pops a dummy error code to keep a
; uniform stack frame
push byte 0
jmp isr_common_stub
_i86_isr1:
cli
push byte 0
push byte 1
jmp isr_common_stub
_i86_isr2:
cli
push byte 0
push byte 2
jmp isr_common_stub
_i86_isr3:
cli
push byte 0
push byte 3
jmp isr_common_stub
_i86_isr4:
cli
push byte 0
push byte 4
jmp isr_common_stub
_i86_isr5:
cli
push byte 0
push byte 5
jmp isr_common_stub
_i86_isr6:
cli
push byte 0
push byte 6
jmp isr_common_stub
_i86_isr7:
cli
push byte 0
push byte 7
jmp isr_common_stub
_i86_isr8:
cli
push byte 8
jmp isr_common_stub
_i86_isr9:
cli
push byte 0
push byte 9
jmp isr_common_stub
_i86_isr10:
cli
push byte 10
jmp isr_common_stub
_i86_isr11:
cli
push byte 11
jmp isr_common_stub
_i86_isr12:
cli
push byte 12
jmp isr_common_stub
_i86_isr13:
cli
push byte 13
jmp isr_common_stub
_i86_isr14:
cli
push byte 14
jmp isr_common_stub
_i86_isr15:
cli
push byte 0
push byte 15
jmp isr_common_stub
_i86_isr16:
cli
push byte 0
push byte 16
jmp isr_common_stub
_i86_isr17:
cli
push byte 0
push byte 17
jmp isr_common_stub
_i86_isr18:
cli
push byte 0
push byte 18
jmp isr_common_stub
_i86_isr19:
cli
push byte 0
push byte 19
jmp isr_common_stub
_i86_isr20:
cli
push byte 0
push byte 20
jmp isr_common_stub
_i86_isr21:
cli
push byte 0
push byte 21
jmp isr_common_stub
_i86_isr22:
cli
push byte 0
push byte 22
jmp isr_common_stub
_i86_isr23:
cli
push byte 0
push byte 23
jmp isr_common_stub
_i86_isr24:
cli
push byte 0
push byte 24
jmp isr_common_stub
_i86_isr25:
cli
push byte 0
push byte 25
jmp isr_common_stub
_i86_isr26:
cli
push byte 0
push byte 26
jmp isr_common_stub
_i86_isr27:
cli
push byte 0
push byte 27
jmp isr_common_stub
_i86_isr28:
cli
push byte 0
push byte 28
jmp isr_common_stub
_i86_isr29:
cli
push byte 0
push byte 29
jmp isr_common_stub
_i86_isr30:
cli
push byte 0
push byte 30
jmp isr_common_stub
_i86_isr31:
cli
push byte 0
push byte 31
jmp isr_common_stub
extern _i86_fault_handler
isr_common_stub:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10 ; Load the Kernel Data Segment descriptor!
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp ; Push us the stack
push eax
mov eax, _i86_fault_handler
call eax ; A special call, preserves the 'eip' register
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8 ; Cleans up the pushed error code and pushed ISR number
iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP!

70
SysCore/hal/isrs/isrs.c Normal file
View File

@ -0,0 +1,70 @@
#include <system.h>
#include "isrs.h"
#include "../idt/idt.h"
extern void _STOP_ERROR_SCREEN(ISR_stack_regs *);
/* This is a very repetitive function... it's not hard, it's
* just annoying. As you can see, we set the first 32 entries
* in the IDT to the first 32 ISRs. We can't use a for loop
* for this, because there is no way to get the function names
* that correspond to that given entry. We set the access
* flags to 0x8E. This means that the entry is present, is
* running in ring 0 (kernel level), and has the lower 5 bits
* set to the required '14', which is represented by 'E' in
* hex. */
void i86_isrs_install()
{
i86_idt_set_gate(0, (unsigned)i86_isr0, 0x08, 0x8E);
i86_idt_set_gate(1, (unsigned)i86_isr1, 0x08, 0x8E);
i86_idt_set_gate(2, (unsigned)i86_isr2, 0x08, 0x8E);
i86_idt_set_gate(3, (unsigned)i86_isr3, 0x08, 0x8E);
i86_idt_set_gate(4, (unsigned)i86_isr4, 0x08, 0x8E);
i86_idt_set_gate(5, (unsigned)i86_isr5, 0x08, 0x8E);
i86_idt_set_gate(6, (unsigned)i86_isr6, 0x08, 0x8E);
i86_idt_set_gate(7, (unsigned)i86_isr7, 0x08, 0x8E);
i86_idt_set_gate(8, (unsigned)i86_isr8, 0x08, 0x8E);
i86_idt_set_gate(9, (unsigned)i86_isr9, 0x08, 0x8E);
i86_idt_set_gate(10, (unsigned)i86_isr10, 0x08, 0x8E);
i86_idt_set_gate(11, (unsigned)i86_isr11, 0x08, 0x8E);
i86_idt_set_gate(12, (unsigned)i86_isr12, 0x08, 0x8E);
i86_idt_set_gate(13, (unsigned)i86_isr13, 0x08, 0x8E);
i86_idt_set_gate(14, (unsigned)i86_isr14, 0x08, 0x8E);
i86_idt_set_gate(15, (unsigned)i86_isr15, 0x08, 0x8E);
i86_idt_set_gate(16, (unsigned)i86_isr16, 0x08, 0x8E);
i86_idt_set_gate(17, (unsigned)i86_isr17, 0x08, 0x8E);
i86_idt_set_gate(18, (unsigned)i86_isr18, 0x08, 0x8E);
i86_idt_set_gate(19, (unsigned)i86_isr19, 0x08, 0x8E);
i86_idt_set_gate(20, (unsigned)i86_isr20, 0x08, 0x8E);
i86_idt_set_gate(21, (unsigned)i86_isr21, 0x08, 0x8E);
i86_idt_set_gate(22, (unsigned)i86_isr22, 0x08, 0x8E);
i86_idt_set_gate(23, (unsigned)i86_isr23, 0x08, 0x8E);
i86_idt_set_gate(24, (unsigned)i86_isr24, 0x08, 0x8E);
i86_idt_set_gate(25, (unsigned)i86_isr25, 0x08, 0x8E);
i86_idt_set_gate(26, (unsigned)i86_isr26, 0x08, 0x8E);
i86_idt_set_gate(27, (unsigned)i86_isr27, 0x08, 0x8E);
i86_idt_set_gate(28, (unsigned)i86_isr28, 0x08, 0x8E);
i86_idt_set_gate(29, (unsigned)i86_isr29, 0x08, 0x8E);
i86_idt_set_gate(30, (unsigned)i86_isr30, 0x08, 0x8E);
i86_idt_set_gate(31, (unsigned)i86_isr31, 0x08, 0x8E);
}
/* All of our Exception handling Interrupt Service Routines will
* point to this function. This will tell us what exception has
* happened! Right now, we simply halt the system by hitting an
* endless loop. All ISRs disable interrupts while they are being
* serviced as a 'locking' mechanism to prevent an IRQ from
* happening and messing up kernel data structures */
void i86_fault_handler(ISR_stack_regs *r)
{
/* Is this a fault whose number is from 0 to 31? */
if (r->int_no < 32)
{
_STOP_ERROR_SCREEN(r);
/* Display the description for the Exception that occurred.*/
/* Put on the BSOD screen*/
for (;;);
}
}

40
SysCore/hal/isrs/isrs.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef __ISRS_H
#define __ISRS_H
extern void i86_isr0();
extern void i86_isr1();
extern void i86_isr2();
extern void i86_isr3();
extern void i86_isr4();
extern void i86_isr5();
extern void i86_isr6();
extern void i86_isr7();
extern void i86_isr8();
extern void i86_isr9();
extern void i86_isr10();
extern void i86_isr11();
extern void i86_isr12();
extern void i86_isr13();
extern void i86_isr14();
extern void i86_isr15();
extern void i86_isr16();
extern void i86_isr17();
extern void i86_isr18();
extern void i86_isr19();
extern void i86_isr20();
extern void i86_isr21();
extern void i86_isr22();
extern void i86_isr23();
extern void i86_isr24();
extern void i86_isr25();
extern void i86_isr26();
extern void i86_isr27();
extern void i86_isr28();
extern void i86_isr29();
extern void i86_isr30();
extern void i86_isr31();
extern void i86_isrs_install();
extern void i86_fault_handler(ISR_stack_regs *r);
#endif

View File

@ -0,0 +1,18 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/keyus.o keyus.c
@echo off
@echo .
@echo Done!
@pause

View File

@ -0,0 +1,135 @@
*0x00 Pause/Break
0x01 F9
0x02 F7
0x03 F5
0x04 F3
0x05 F1
0x06 F2
0x07 F12
0x08 Print Screen
0x09 F10
0x0A F8
0x0B F6
0x0C F4
0x0D Tab
0x0E `~
0x0F
0x10
0x11
0x12
0x13
0x14
0x15 Q
0x16 1!
0x17
0x18
0x19
0x1A Z
0x1B S
0x1C A
0x1D W
0x1E 2@
0x1F LeftWin
0x20
0x21 C
0x22 X
0x23 D
0x24 E
0x25 4$
0x26 3#
0x27 RightWin
0x28
0x29 Space
0x2A V
0x2B F
0x2C T
0x2D R
0x2E 5%
0x2F Menu
0x30
0x31 N
0x32 B
0x33 H
0x34 G
0x35 Y
0x36 6^
0x37
0x38
0x39
0x3A M
0x3B J
0x3C U
0x3D 7&
0x3E 8*
0x3F
0x40
0x41 ,<
0x42 K
0x43 I
0x44 O
0x45 0)
0x46 9(
0x47
0x48
0x49 .>
0x4A /?
0x4B L
0x4C ;:
0x4D P
0x4E -_
0x4F
0x50
0x51
0x52 '"
0x53
0x54 [{
0x55 =+
0x56
0x57
0x58
0x59 Numpad Enter
0x5A Enter
0x5B ]}
0x5C
0x5D \|
0x5E End
0x5F Left
0x60 Home
0x61 Insert
0x62 Delete
0x63 Down
0x64 Right
0x65 Up
0x66 Backspace
0x67 PageDown
0x68 PageUp
0x69 Numpad 1 (end)
0x6A Numpad /
0x6B Numpad 4 (left)
0x6C Numpad 7 (Home)
0x6D
0x6E
0x6F
0x70 Numpad 0 (insert)
0x71 Numpad . (del)
0x72 Numpad 2 (down)
0x73 Numpad 5
0x74 Numpad 6 (right)
0x75 Numpad 8 (up)
0x76 Esc
0x77
0x78 F11
0x79 Numpad +
0x7A Numpad 3 (pgdwn)
0x7B Numpad -
0x7C Numpad *
0x7D Numpad 9 (pgup)
0x7E
0x7F

View File

@ -0,0 +1,133 @@
#define KB_KEY_LSHIFT 0x81 // 1000 0001
#define KB_KEY_RSHIFT 0X82 // 1000 0010
#define KB_KEY_LALT 0X84 // 1000 0100
#define KB_KEY_RALT 0x88 // 1000 1000
#define KB_KEY_LCTRL 0x90 // 1001 0000
#define KB_KEY_RCTRL 0xA0 // 1010 0000
#define KB_KEY_FSHIFT 0xC0 // 1100 0000
extern volatile byte kb_modifier_status;
#define KB_PREFIX_GRAY 0x01 // Gray
#define KB_PREFIX_BREAK 0x02 // Break code
#define KB_PREFIX_PAUSE 0x04 // Pause/break key
#define KB_PREFIX_PAUSE1 0x08 // Recieved first byte from pause/break
extern volatile byte kb_prefix;
#define KB_KEY_SCROLL 0xF1 // 1111 0001
#define KB_KEY_NUM 0xF2 // 1111 0010
#define KB_KEY_CAPS 0xF4 // 1111 0100
extern volatile byte kb_lights_status;
extern byte kb_scancode_set;
#define KB_KEY_PAUSE 0x00
#define KB_KEY_F9 0x01
#define KB_KEY_F7 0x02
#define KB_KEY_F5 0X03
#define KB_KEY_F3 0x04
#define KB_KEY_F1 0x05
#define KB_KEY_F2 0x06
#define KB_KEY_F12 0x07
#define KB_KEY_PRINTSCRN 0x08
#define KB_KEY_F10 0x09
#define KB_KEY_F8 0x0A
#define KB_KEY_F6 0x0B
#define KB_KEY_F4 0x0C
#define KB_KEY_TAB 0x0D
#define KB_KEY_TILDA 0x0E
#define KB_KEY_Q 0x15
#define KB_KEY_1 0x16
#define KB_KEY_Z 0x1A
#define KB_KEY_S 0x1B
#define KB_KEY_A 0x1C
#define KB_KEY_W 0x1D
#define KB_KEY_2 0x1E
#define KB_KEY_LWIN 0x1F
#define KB_KEY_C 0x21
#define KB_KEY_X 0x22
#define KB_KEY_D 0x23
#define KB_KEY_E 0x24
#define KB_KEY_4 0x25
#define KB_KEY_3 0x26
#define KB_KEY_RWIN 0x27
#define KB_KEY_SPACE 0x29
#define KB_KEY_V 0x2A
#define KB_KEY_F 0x2B
#define KB_KEY_T 0x2C
#define KB_KEY_R 0x2D
#define KB_KEY_5 0x2E
#define KB_KEY_MENU 0x2F
#define KB_KEY_N 0x31
#define KB_KEY_B 0x32
#define KB_KEY_H 0x33
#define KB_KEY_G 0x34
#define KB_KEY_Y 0x35
#define KB_KEY_6 0x36
#define KB_KEY_M 0x3A
#define KB_KEY_J 0x3B
#define KB_KEY_U 0x3C
#define KB_KEY_7 0x3D
#define KB_KEY_8 0x3E
#define KB_KEY_COMMA 0x41
#define KB_KEY_K 0x42
#define KB_KEY_I 0x43
#define KB_KEY_O 0x44
#define KB_KEY_0 0x45
#define KB_KEY_9 0x46
#define KB_KEY_PERIOD 0x49
#define KB_KEY_SLASH 0x4A
#define KB_KEY_L 0x4B
#define KB_KEY_SEMICOLON 0x4C
#define KB_KEY_P 0x4D
#define KB_KEY_DASH 0x4E
#define KB_KEY_APOSTROPHE 0x52
#define KB_KEY_LBRACKET 0x54
#define KB_KEY_EQUAL 0x55
#define KB_KEY_NUMPAD_ENTER 0x59
#define KB_KEY_ENTER 0x5A
#define KB_KEY_RBRACKET 0x5B
#define KB_KEY_BACKSLASH 0x5D
#define KB_KEY_END 0x5E
#define KB_KEY_LEFT 0x5F
#define KB_KEY_HOME 0x60
#define KB_KEY_INSERT 0x61
#define KB_KEY_DELETE 0x62
#define KB_KEY_DOWN 0x63
#define KB_KEY_RIGHT 0x64
#define KB_KEY_UP 0x65
#define KB_KEY_BACKSPACE 0x66
#define KB_KEY_PGDOWN 0x67
#define KB_KEY_PGUP 0x68
#define KB_KEY_NUMPAD_1 0x69
#define KB_KEY_NUMPAD_SLASH 0x6A
#define KB_KEY_NUMPAD_4 0x6B
#define KB_KEY_NUMPAD_7 0x6C
#define KB_KEY_NUMPAD_0 0x70
#define KB_KEY_NUMPAD_COLON 0x71
#define KB_KEY_NUMPAD_2 0x72
#define KB_KEY_NUMPAD_5 0x73
#define KB_KEY_NUMPAD_6 0x74
#define KB_KEY_NUMPAD_8 0x75
#define KB_KEY_ESC 0x76
#define KB_KEY_F11 0x78
#define KB_KEY_NUMPAD_PLUS 0x79
#define KB_KEY_NUMPAD_3 0x7A
#define KB_KEY_NUMPAD_MINUS 0x7B
#define KB_KEY_NUMPAD_ASTERISK 0x7C
#define KB_KEY_NUMPAD_9 0x7D
typedef struct {
byte status;
byte lights;
byte scancode;
byte character;
} kb_key;
extern char getch();
extern kb_key get_key();
extern scancode_to_ascii(byte scancode);
extern byte get_key_status(byte scancode);
extern void kb_set_repeat(float rate, int delay);
extern void kb_set_LEDs(byte status);

View File

@ -0,0 +1,326 @@
#include <system.h>
#include <hal.h>
#include "keyus.h"
#include "../irq/irq.h"
extern void reboot();
const char kbdus_map[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '`', 0,
0, 0, 0, 0, 0, 'q', '1', 0, 0, 0, 'z', 's', 'a', 'w', '2', 0,
0, 'c', 'x', 'd', 'e', '4', '3', 0, 0, ' ', 'v', 'f', 't', 'r', '5', 0,
0, 'n', 'b', 'h', 'g', 'y', '6', 0, 0, 0, 'm', 'j', 'u', '7', '8', 0,
0, ',', 'k', 'i', 'o', '0', '9', 0, 0, '.', '/', 'l', ';', 'p', '-', 0,
0, 0, '\'', 0, '[', '=', 0, 0, 0, '\n', '\n', ']', 0, '\\', 0, 0,
0, 0, 0x7F, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', 0, 0, 0,
'0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0
};
const char kbdus_map_shift[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '~', 0,
0, 0, 0, 0, 0, 'Q', '!', 0, 0, 0, 'Z', 'S', 'A', 'W', '@', 0,
0, 'C', 'X', 'D', 'E', '$', '#', 0, 0, ' ', 'V', 'F', 'T', 'R', '%', 0,
0, 'N', 'B', 'H', 'G', 'Y', '^', 0, 0, 0, 'M', 'J', 'U', '&', '*', 0,
0, '<', 'K', 'I', 'O', ')', '(', 0, 0, '>', '?', 'L', ':', 'P', '_', 0,
0, 0, '\"', 0, '{', '+', 0, 0, 0, '\n', '\n', '}', 0, '|', 0, 0,
0, 0, 0x7F, 0, 0, 0, '\b', 0, 0, '1', '/', '4', '7', 0, 0, 0,
'0', '.', '2', '5', '6', '8', 0, 0, 0, '+', '3', '-', '*', '9', 0, 0
};
volatile byte kb_array[16];
volatile byte kb_newdata;
volatile byte kb_modifier_status;
volatile byte kb_prefix;
volatile byte kb_lights_status;
byte kb_scancode_set;
void i86_kb_set_key(byte scancode, byte val)
{
byte pos = scancode/8;
byte offset = scancode%8;
if (val) {
kb_array[pos] |= 1<<offset;
kb_newdata = scancode;
}
else kb_array[pos] &= 0xFF - (1<<offset);
}
byte i86_kb_get_key(byte scancode)
{
byte pos = scancode/8;
byte offset = scancode%8;
return (kb_array[pos]&(1<<offset));
}
void i86_kb_handler(ISR_stack_regs *r) {
byte scancode = inportb(0x60);
switch (scancode) {
case 0x00: // Error 0x00
case 0xFC: // Diagnostics failed (MF kb)
case 0xFD: // Diagnostics failed (AT kb)
case 0xFF: i86_kb_waitin(); outportb(0x60, 0xF4); // Error 0xFF
break;
case 0xAA: // BAT test successful.
case 0xFA: // ACKnowledge
case 0xFE: // Last command invalid or parity error
case 0xEE: break; // Echo response
// Gray or break
case 0xE0: kb_prefix |= 1; break;
case 0xE1: kb_prefix |= 4; break;
case 0xF0: kb_prefix |= 2; break;
// Alt, ctrl...
case 0x11: if ((kb_prefix&1) == 0) { // Left alt
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<2;
else kb_modifier_status &= 0xFF - (1<<2);
}
else { // Right alt
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<3;
else kb_modifier_status &= 0xFF - (1<<3);
}
kb_prefix = 0; break;
case 0x12: if ((kb_prefix&1) == 0) { // Left shift
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<0;
else kb_modifier_status &= 0xFF - (1<<0);
}
else { // Fake shift
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<6;
else kb_modifier_status &= 0xFF - (1<<6);
}
kb_prefix = 0; break;
case 0x14: if (kb_prefix&4) {
if ((kb_prefix&2) == 0) i86_kb_set_key (0, 1);
else i86_kb_set_key (0, 0);
kb_prefix |= 8; break;
}
else if ((kb_prefix&1) == 0) { // Left ctrl
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<4;
else kb_modifier_status &= 0xFF - (1<<4);
}
else { // Right ctrl
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<5;
else kb_modifier_status &= 0xFF - (1<<5);
}
kb_prefix = 0; break;
case 0x59: // Right shift
if ((kb_prefix&2) == 0) kb_modifier_status |= 1<<1;
else kb_modifier_status &= 0xFF - (1<<1);
kb_prefix = 0; break;
// LEDs
case 0x58: if ((kb_prefix&2) == 0) {
kb_lights_status ^= 4; i86_kb_set_LEDs(kb_lights_status);
} kb_prefix = 0; break; // Caps
//TO ADD BELOW: pause/break byte2
case 0x77:
if ((kb_prefix&4) && (kb_prefix&8)) kb_prefix=0;
else if ((kb_prefix&2) == 0) {
kb_lights_status ^= 2; i86_kb_set_LEDs(kb_lights_status);
} kb_prefix = 0; break; // Num
case 0x7E: if ((kb_prefix&2) == 0) {
kb_lights_status ^= 1; i86_kb_set_LEDs(kb_lights_status);
} kb_prefix = 0; break; // Scroll
case 0x83: scancode = 0x02; // Put F7 under the 0x80 (128bit) barrier
default:
// Remap gray keys
if (kb_prefix&1) switch (scancode) {
case 0x7C: scancode=0x08; break; // PrintScreen
case 0x4A: scancode=0x6A; break; // Numpad /
case 0x5A: scancode=0x59; break; // Numpad Enter
case 0x69: scancode=0x5E; break; // End
case 0x6B: scancode=0x5F; break; // Left
case 0x6C: scancode=0x60; break; // Home
case 0x70: scancode=0x61; break; // Insert
case 0x71: scancode=0x62; break; // Delete
case 0x72: scancode=0x63; break; // Down
case 0x74: scancode=0x64; break; // Right
case 0x75: scancode=0x65; break; // Up
case 0x7A: scancode=0x67; break; // PageDown
case 0x7D: scancode=0x68; break; // PageUp
}
if ((kb_prefix&2) == 0) i86_kb_set_key(scancode, 1);
else i86_kb_set_key(scancode, 0);
kb_prefix = 0; break;
}
// Alt+ctrl+del = reset
if (scancode==0x62) {
int ok=0;
if ((kb_modifier_status&4) || (kb_modifier_status&8)) ok++;
if ((kb_modifier_status&16) || (kb_modifier_status&32)) ok++;
if (ok==2) reboot();
}
outportb(0x20, 0x20);
}
kb_key getkey()
{
kb_key ret;
kb_newdata = 0xFF;
while (kb_newdata==0xFF); // wait for keypress
ret.scancode = kb_newdata; // Send scancode for non-chars
ret.status = kb_modifier_status; // Shift, ctrl... state
ret.lights = kb_lights_status; // Num, caps.... state
if ((ret.status & 1) || (ret.status & 2)) // Shift is on
ret.character = kbdus_map_shift[ret.scancode];
else ret.character = kbdus_map[ret.scancode]; // Shift is off
return ret; // And send it.
}
/***************************************
* Set repeat rate/delay *
***************************************
Values for inter-character delay (bits 4-0)
(characters per second; default is 10.9)
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
----+----+----+----+----+----+----+----+----
0 |30.0|26.7|24.0|21.8|20.0|18.5|17.1|16.0
8 |15.0|13.3|12.0|10.9|10.0|9.2 |8.6 |8.0
16 |7.5 |6.7 |6.0 |5.5 |5.0 |4.6 |4.3 |4.0
24 |3.7 |3.3 |3.0 |2.7 |2.5 |2.3 |2.1 |2.0
Values for delay:
(miliseconds; default is 500)
0 | 1 | 2 | 3
-----+-----+-----+-----
250 | 500 | 750 | 1000
***************************************/
void i86_kb_set_repeat(byte rate, byte delay)
{
if (rate>3 || delay>31) return;
byte out = rate<<5 | delay;
while ((inportb(0x64)&2) != 0);
outportb(0x60, 0xF3);
while ((inportb(0x64)&2) != 0);
outportb(0x60, out);
}
/***************************************
* Set keyboard LEDs *
***************************************
+-----------+-------+-------+--------+
| Bits 7-3 | Bit 2 | Bit 1 | Bit 0 |
| 0 | Caps | Num | Scroll |
|(reserved) | lock | lock | lock |
+-----------+-------+-------+--------+
***************************************/
void i86_kb_set_LEDs(byte status)
{
while ((inportb (0x64)&2)!=0);
outportb (0x60, 0xED);
while ((inportb (0x64)&2)!=0);
outportb (0x60, status);
}
/***************************************
* Set scancode set *
***************************************
0 Get current scancode set
1 Set to scancode set 1
2 Set to scancode set 2
3 Set to scancode set 3
***************************************/
void i86_kb_set_scancodeset(byte set)
{
if (set>3) return;
while ((inportb (0x64)&2)!=0);
outportb (0x60, 0xF0);
while ((inportb (0x64)&2)!=0);
outportb (0x60, set);
kb_scancode_set = set;
}
byte i86_kb_get_scancodeset() {
return kb_scancode_set;
}
void i86_kb_waitin()
{
int fail_safe=200000;
while ((inportb(0x64)&2)!=0 && fail_safe>0) fail_safe--;
}
void i86_kb_waitout()
{
int fail_safe=200000;
while ((inportb(0x64)&1)==0 && fail_safe>0) fail_safe--;
}
void i86_kb_install_partone()
{
i86_irq_install_handler(1, i86_kb_handler);// instali handler
i86_kb_waitin(); outportb(0x60, 0xFF); // Reset kb
// Initialize variables
kb_newdata = 0;
kb_modifier_status = 0;
kb_prefix = 0;
kb_lights_status = 0;
kb_scancode_set = 0;
}
int i86_kb_install_parttwo()
{
int ret = 0;
// Wait for BAT test results
byte temp;
do temp = inportb(0x60);
while (temp!=0xAA && temp!=0xFC);
if (temp == 0xFC) ret = -1;
// Set new repeat rate
i86_kb_set_repeat(1, 11);
// Set scancode set 2
i86_kb_set_scancodeset(2); // Set new scancode set
i86_kb_waitin();
outportb(0x64, 0x20); // Get "Command byte"
do { temp = inportb(0x60);
} while (temp==0xFA || temp==0xAA);
temp &= 0xFF - (1<<6); // Set bit6 to 0: disable conversion
i86_kb_waitin(); outportb(0x64, 0x60); // Function to write cmd byte
i86_kb_waitin(); outportb(0x60, temp); // Send it
memset((void*)kb_array, 0, 16);
return ret;
}

View File

@ -0,0 +1,28 @@
#ifndef __KEYUS_H
#define __KEYUS_H
extern const char kbdus_map[0x80];
extern const char kbdus_map_shift[0x80];
extern volatile byte kb_modifier_status;
extern volatile byte kb_prefix;
extern volatile byte kb_lights_status;
extern byte kb_scancode_set;
extern void i86_kb_set_key(byte scancode, byte val);
extern void i86_kb_set_LEDs(byte status);
extern void i86_kb_set_repeat(byte rate, byte delay);
extern void i86_kb_set_scancodeset(byte set);
extern byte i86_kb_get_key(byte scancode);
extern void i86_kb_handler(ISR_stack_regs *r);
extern kb_key getkey();
extern void i86_kb_set_repeat(byte rate, byte delay);
extern void i86_kb_set_LEDs(byte status);
extern void i86_kb_set_scancodeset(byte set);
extern byte i86_kb_get_scancodeset();
extern void i86_kb_waitin();
extern void i86_kb_waitout();
extern void i86_kb_install_partone();
extern int i86_kb_install_parttwo();
#endif

109
SysCore/hal/makeall.bat Normal file
View File

@ -0,0 +1,109 @@
@echo off
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
@echo Building Hardware Abstraction Layer...
set objpath=..\objects
set incpath=../include
del %objpath%\hal.o
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/hal.o hal.c
if not exist %objpath%\hal.o goto error
set objpath=..\..\objects
set incpath=../../include
goto cmos
:error
@echo.
@echo There have been build errors. Building halted.
@pause
exit
:cmos
cd cmos
@echo * Compiling CMOS...
del %objpath%\cmos.o
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/cmos.o cmos.c
if not exist %objpath%\cmos.o goto error
cd..
:cpu
cd cpu
@echo * Compiling Central Processing Unit...
del %objpath%\cpu.o
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/cpu.o cpu.c
if not exist %objpath%\cpu.o goto error
cd..
:gdt
cd gdt
@echo * Compiling Global Descriptor Table...
del %objpath%\gdt.o
del %objpath%\gdt_asm.o
%nasm_path%\nasm.exe -f aout -o %objpath%/gdt_asm.o gdt.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/gdt.o gdt.c
if not exist %objpath%\gdt.o goto error
if not exist %objpath%\gdt_asm.o goto error
cd..
:idt
cd idt
@echo * Compiling Interrupt Descriptor Table...
del %objpath%\idt.o
del %objpath%\idt_asm.o
%nasm_path%\nasm.exe -f aout -o %objpath%/idt_asm.o idt.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/idt.o idt.c
if not exist %objpath%\idt.o goto error
if not exist %objpath%\idt_asm.o goto error
cd..
:irq
cd irq
@echo * Compiling Interrupt ReQuests...
del %objpath%\irq.o
del %objpath%\irq_asm.o
%nasm_path%\nasm.exe -f aout -o %objpath%/irq_asm.o irq.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/irq.o irq.c
if not exist %objpath%\irq.o goto error
if not exist %objpath%\irq_asm.o goto error
cd..
:isrs
cd isrs
@echo * Compiling Interrupt Service Routines...
del %objpath%\isrs_asm.o
del %objpath%\isrs.o
del %objpath%\BSOD.o
%nasm_path%\nasm.exe -f aout -o %objpath%/isrs_asm.o isrs.asm
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/isrs.o isrs.c
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/BSOD.o BSOD.c
if not exist %objpath%\isrs_asm.o goto error
if not exist %objpath%\isrs.o goto error
if not exist %objpath%\BSOD.o goto error
cd..
:keyboard
cd keyboard
@echo * Compiling KEYBOARD...
del %objpath%\keyus.o
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/keyus.o keyus.c
if not exist %objpath%\keyus.o goto error
cd..
:pic
cd pic
@echo * Compiling Programmable Interrupt Controller...
del %objpath%\pic.o
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/pic.o pic.c
if not exist %objpath%\pic.o goto error
cd..
:pit
cd pit
@echo * Compiling Programmable Interval Timer...
del %objpath%\pit.o
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/pit.o pit.c
if not exist %objpath%\pit.o goto error
cd..

View File

@ -0,0 +1,18 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/pic.o pic.c
@echo off
@echo .
@echo Done!
@pause

23
SysCore/hal/pic/pic.c Normal file
View File

@ -0,0 +1,23 @@
#include <system.h>
#include "pic.h"
void i86_pic_remap(int pic1, int pic2)
{
// Send ICW1
outportb(0x20, 0x11);
outportb(0xA0, 0x11);
// send ICW2
outportb(0x21, pic1); // remap pics
outportb(0xA1, pic2);
// send ICW3
outportb(0x21, 4);
outportb(0xA1, 2);
// Send ICW4
outportb(0x21, 0x01);
outportb(0xA1, 0x01);
outportb(0x21, 0x00);
}

6
SysCore/hal/pic/pic.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _PIC_H
#define _PIC_H
extern void i86_pic_remap(int pic1, int pic2);
#endif

View File

@ -0,0 +1,18 @@
@echo off
rem The name of the loader assembly file (without extension, must be .asm):
set loader_name=loader
rem NASM and DJGPP executable paths:
set nasm_path=C:\nasm
set djgpp_path=C:\DJGPP\bin
set objpath=../../objects
set incpath=../../include
@echo on
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/pit.o pit.c
@echo off
@echo .
@echo Done!
@pause

56
SysCore/hal/pit/pit.c Normal file
View File

@ -0,0 +1,56 @@
#include <system.h>
#include <time.h>
#include "../irq/irq.h"
#include "pit.h"
volatile unsigned int _pit_ticks = 0;
volatile unsigned int _pit_frequency = 0;
unsigned char _pit_init = 0;
volatile TIME _internal_clock;
void i86_pit_set_frequency(int frequency)
{
int divisor = 1193180/frequency; // Calculate the divisor
outportb(0x43, 0x36); // Set our command byte 0x36
outportb(0x40, divisor&0xFF); // Set low byte
outportb(0x40, divisor>>8); // Set high byte
_pit_frequency = frequency;
}
void i86_pit_handler(ISR_stack_regs *r)
{
_pit_ticks++; // count tick
if (_pit_ticks % _pit_frequency == 0)
_CLOCK_INC((TIME*)&_internal_clock); // update internal clock
}
unsigned int i86_pit_set_tick_count(unsigned int i)
{
unsigned int r = _pit_ticks;
_pit_ticks = i;
return r;
}
unsigned int i86_pit_get_tick_count()
{
return _pit_ticks;
}
unsigned int i86_pit_get_frequency()
{
return _pit_frequency;
}
void i86_pit_install(int freq)
{
i86_irq_install_handler(0, i86_pit_handler);
i86_pit_set_frequency(freq);
_pit_ticks = 0;
_pit_init = 1;
}
unsigned char i86_pit_is_initialized()
{
return _pit_init;
}

17
SysCore/hal/pit/pit.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef __PIT_H
#define __PIT_H
#include<regs.h>
extern volatile unsigned int _pit_ticks;
extern volatile unsigned int _pit_frequency;
extern volatile TIME _internal_clock;
extern void i86_pit_handler(ISR_stack_regs *r);
extern void i86_pit_set_frequency(int frequency);
extern unsigned int i86_pit_set_tick_count(unsigned int i);
extern unsigned int i86_pit_get_tick_count();
extern unsigned int i86_pit_get_frequency();
extern void i86_pit_install(int freq);
extern unsigned char i86_pit_is_initialized();
#endif