printf and shitty paging
This commit is contained in:
parent
e5f54a0cfb
commit
e46c2dbf0a
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
.vscode/
|
||||
workspace.code-workspace
|
||||
*.o
|
||||
*.bin
|
||||
*.iso
|
||||
|
|
5
Makefile
5
Makefile
|
@ -16,7 +16,8 @@ ISO = build/HhhOS.iso
|
|||
DIRS = build build/boot build/std build/drivers build/drivers/terminal build/drivers/idt build/drivers/device build/drivers/keyboard build/drivers/pic build/drivers/ide
|
||||
|
||||
OBJS = build/boot/boot.o build/boot/kernel.o build/std/string.o build/drivers/terminal/terminal.o build/drivers/idt/idt.o \
|
||||
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o build/drivers/ide/ide.o
|
||||
build/drivers/idt/isr.o build/std/util.o build/drivers/device/device.o build/drivers/keyboard/keyboard.o build/drivers/pic/pic.o \
|
||||
build/drivers/ide/ide.o build/std/stdio.o
|
||||
|
||||
ARCHDIR = arch/$(ARCH)/
|
||||
|
||||
|
@ -34,7 +35,7 @@ $(ISO): dirs $(BIN)
|
|||
grub-mkrescue -o $(ISO) sysroot
|
||||
|
||||
$(BIN): $(OBJS)
|
||||
$(CC) -T linker.ld $(LDFLAGS) -o $@ $^
|
||||
$(CC) -T linker.ld -o $@ $^ $(LDFLAGS)
|
||||
|
||||
build/%.o: $(ARCHDIR)%.c
|
||||
$(CC) -c $(CFLAGS) -Iinclude -o $@ $<
|
||||
|
|
|
@ -63,7 +63,6 @@ data_segment equ gdt.data - gdt
|
|||
; Declare _start as a function symbol with the given symbol size.
|
||||
section .text
|
||||
global _start:function (_start.end - _start)
|
||||
global load_idt
|
||||
|
||||
gdt_load:
|
||||
push eax
|
||||
|
@ -79,6 +78,27 @@ gdt_load:
|
|||
pop eax
|
||||
ret
|
||||
|
||||
global load_page_directory
|
||||
load_page_directory:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, [esp + 8]
|
||||
mov cr3, eax
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
global enable_paging
|
||||
enable_paging:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, cr0
|
||||
or eax, 80000001h
|
||||
mov cr0, eax
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
_start:
|
||||
; The bootloader has loaded us into 32-bit protected mode on a x86
|
||||
; machine. Interrupts are disabled. Paging is disabled. The processor
|
||||
|
@ -95,6 +115,15 @@ _start:
|
|||
; in assembly as languages such as C cannot function without a stack.
|
||||
mov esp, stack_top
|
||||
|
||||
;now enable SSE and the like
|
||||
mov eax, cr0
|
||||
and ax, 0xFFFB ;clear coprocessor emulation CR0.EM
|
||||
or ax, 0x2 ;set coprocessor monitoring CR0.MP
|
||||
mov cr0, eax
|
||||
mov eax, cr4
|
||||
or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
|
||||
mov cr4, eax
|
||||
|
||||
; This is a good place to initialize crucial processor state before the
|
||||
; high-level kernel is entered. It's best to minimize the early
|
||||
; environment where crucial features are offline. Note that the
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <std/stdio.h>
|
||||
#include <drivers/idt/isr.h>
|
||||
#include <drivers/keyboard/keyboard.h>
|
||||
#include <drivers/pic/pic.h>
|
||||
|
@ -11,10 +12,10 @@ int keyboard_descriptor = 0;
|
|||
int terminal_descriptor = 0;
|
||||
|
||||
void shell() {
|
||||
terminal_writestring("hello yes");
|
||||
printf("hello yes");
|
||||
|
||||
while (is_running) {
|
||||
terminal_writestring("\n> ");
|
||||
printf("\n> ");
|
||||
|
||||
while (true) {
|
||||
unsigned char scancode = read(keyboard_descriptor, NULL);
|
||||
|
@ -44,40 +45,66 @@ void shell() {
|
|||
}
|
||||
|
||||
if (finished) break;
|
||||
if (!special) terminal_putchar(keyboard_get_key_from_scancode(scancode));
|
||||
if (!special) putchar(keyboard_get_key_from_scancode(scancode));
|
||||
terminal_updatecursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern void load_page_directory(uint32_t);
|
||||
extern void enable_paging();
|
||||
|
||||
uint32_t page_directory[1024] __attribute__((aligned(4096)));
|
||||
uint32_t first_page_table[1024] __attribute__((aligned(4096)));
|
||||
|
||||
void kmain() {
|
||||
terminal_descriptor = terminal_initialize();
|
||||
terminal_writestring("Initializing terminal... done, descriptor: ");
|
||||
terminal_writeline(itoa(terminal_descriptor));
|
||||
terminal_writestring("Preparing interrupts... ");
|
||||
pic_init();
|
||||
isr_install();
|
||||
terminal_writeline("done");
|
||||
|
||||
terminal_writestring("Preparing keyboard... ");
|
||||
keyboard_descriptor = keyboard_init();
|
||||
terminal_writestring("done, descriptor: ");
|
||||
terminal_writeline(itoa(keyboard_descriptor));
|
||||
|
||||
terminal_writeline("Preparing IDE driver... ");
|
||||
terminal_writeline("Searching for IDE devices... ");
|
||||
ide_init();
|
||||
|
||||
terminal_writestring("Are interrupts enabled? ");
|
||||
if (are_interrupts_enabled() == 1) {
|
||||
terminal_writeline("yes");
|
||||
} else {
|
||||
terminal_writeline("no");
|
||||
//set each entry to not present
|
||||
for (uint32_t i = 0; i < 1024; i++) {
|
||||
// This sets the following flags to the pages:
|
||||
// Supervisor: Only kernel-mode can access them
|
||||
// Write Enabled: It can be both read from and written to
|
||||
// Not Present: The page table is not present
|
||||
page_directory[i] = 0x00000002;
|
||||
}
|
||||
|
||||
terminal_writestring("kmain memory address: ");
|
||||
terminal_writeline(itoa(kmain));
|
||||
// i holds the physical address where we want to start mapping these pages to.
|
||||
// in this case, we want to map these pages to the very beginning of memory.
|
||||
// we will fill all 1024 entries in the table, mapping 4 megabytes
|
||||
for (uint32_t i = 0; i < 1024; i++) {
|
||||
// As the address is page aligned, it will always leave 12 bits zeroed.
|
||||
// Those bits are used by the attributes ;)
|
||||
first_page_table[i] = (i * 0x1000) | 3; // attributes: supervisor level, read/write, present.
|
||||
}
|
||||
|
||||
terminal_writeline("----------");
|
||||
// attributes: supervisor level, read/write, present
|
||||
page_directory[0] = ((uint32_t)first_page_table) | 3;
|
||||
|
||||
load_page_directory(page_directory);
|
||||
enable_paging();
|
||||
|
||||
terminal_descriptor = terminal_initialize();
|
||||
printf("Terminal initialized, descriptor: %d\n", terminal_descriptor);
|
||||
printf("Preparing interrupts... ");
|
||||
pic_init();
|
||||
isr_install();
|
||||
printf("done\n");
|
||||
|
||||
keyboard_descriptor = keyboard_init();
|
||||
printf("Keyboard ready, descriptor: %d\n", keyboard_descriptor);
|
||||
|
||||
printf("Preparing IDE driver... \n");
|
||||
printf("Searching for IDE devices... \n");
|
||||
ide_init();
|
||||
|
||||
printf("Are interrupts enabled? ");
|
||||
if (are_interrupts_enabled() == 1) {
|
||||
printf("yes\n");
|
||||
} else {
|
||||
printf("no\n");
|
||||
}
|
||||
|
||||
printf("kmain memory address: %p\n", kmain);
|
||||
|
||||
printf("----------\n");
|
||||
shell();
|
||||
}
|
|
@ -8,20 +8,20 @@
|
|||
// NOTE(hippoz): The function below is actually a joke. It's temporary. I'll
|
||||
// implement the timer soon.
|
||||
uint8_t sleep(int h) {
|
||||
if (h != 1)
|
||||
return 1;
|
||||
for (unsigned long long i = 0; i < 99999999999; i++)
|
||||
;
|
||||
return 0;
|
||||
if (h != 1)
|
||||
return 1;
|
||||
for (unsigned long long i = 0; i < 99999999999; i++)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---- IDE Channel Registers ----
|
||||
|
||||
struct IDEChannelRegisters {
|
||||
unsigned short base; // I/O Base.
|
||||
unsigned short ctrl; // Control Base
|
||||
unsigned short bmide; // Bus Master IDE
|
||||
unsigned char nIEN; // nIEN (No Interrupt);
|
||||
unsigned short base; // I/O Base.
|
||||
unsigned short ctrl; // Control Base
|
||||
unsigned short bmide; // Bus Master IDE
|
||||
unsigned char nIEN; // nIEN (No Interrupt);
|
||||
} channels[2];
|
||||
|
||||
// ---- Variables ----
|
||||
|
@ -32,264 +32,245 @@ unsigned static char ide_irq_invoked = 0;
|
|||
// ---- IDE Device ----
|
||||
|
||||
struct ide_device {
|
||||
unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists).
|
||||
unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
|
||||
unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive).
|
||||
unsigned short Type; // 0: ATA, 1:ATAPI.
|
||||
unsigned short Signature; // Drive Signature
|
||||
unsigned short Capabilities; // Features.
|
||||
unsigned int CommandSets; // Command Sets Supported.
|
||||
unsigned int Size; // Size in Sectors.
|
||||
unsigned char Model[41]; // Model in string.
|
||||
unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists).
|
||||
unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
|
||||
unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive).
|
||||
unsigned short Type; // 0: ATA, 1:ATAPI.
|
||||
unsigned short Signature; // Drive Signature
|
||||
unsigned short Capabilities; // Features.
|
||||
unsigned int CommandSets; // Command Sets Supported.
|
||||
unsigned int Size; // Size in Sectors.
|
||||
unsigned char Model[41]; // Model in string.
|
||||
} ide_devices[4];
|
||||
|
||||
// ---- Functions ----
|
||||
|
||||
void ide_write(unsigned char channel, unsigned char reg, unsigned char data) {
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
if (reg < 0x08)
|
||||
outportb(channels[channel].base + reg - 0x00, data);
|
||||
else if (reg < 0x0C)
|
||||
outportb(channels[channel].base + reg - 0x06, data);
|
||||
else if (reg < 0x0E)
|
||||
outportb(channels[channel].ctrl + reg - 0x0A, data);
|
||||
else if (reg < 0x16)
|
||||
outportb(channels[channel].bmide + reg - 0x0E, data);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
if (reg < 0x08)
|
||||
outportb(channels[channel].base + reg - 0x00, data);
|
||||
else if (reg < 0x0C)
|
||||
outportb(channels[channel].base + reg - 0x06, data);
|
||||
else if (reg < 0x0E)
|
||||
outportb(channels[channel].ctrl + reg - 0x0A, data);
|
||||
else if (reg < 0x16)
|
||||
outportb(channels[channel].bmide + reg - 0x0E, data);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
}
|
||||
|
||||
unsigned char ide_read(unsigned char channel, unsigned char reg) {
|
||||
unsigned char result;
|
||||
unsigned char result;
|
||||
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
if (reg < 0x08)
|
||||
result = inportb(channels[channel].base + reg - 0x00);
|
||||
else if (reg < 0x0C)
|
||||
result = inportb(channels[channel].base + reg - 0x06);
|
||||
else if (reg < 0x0E)
|
||||
result = inportb(channels[channel].ctrl + reg - 0x0A);
|
||||
else if (reg < 0x16)
|
||||
result = inportb(channels[channel].bmide + reg - 0x0E);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
if (reg < 0x08)
|
||||
result = inportb(channels[channel].base + reg - 0x00);
|
||||
else if (reg < 0x0C)
|
||||
result = inportb(channels[channel].base + reg - 0x06);
|
||||
else if (reg < 0x0E)
|
||||
result = inportb(channels[channel].ctrl + reg - 0x0A);
|
||||
else if (reg < 0x16)
|
||||
result = inportb(channels[channel].bmide + reg - 0x0E);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
void ide_read_buffer(unsigned char channel, unsigned char reg,
|
||||
unsigned int *buffer, unsigned int quads) {
|
||||
/* WARNING: This code contains a serious bug. The inline assembly trashes ES
|
||||
* and ESP for all of the code the compiler generates between the inline
|
||||
* assembly blocks.
|
||||
*/
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
/* WARNING: This code contains a serious bug. The inline assembly trashes ES
|
||||
* and ESP for all of the code the compiler generates between the inline
|
||||
* assembly blocks.
|
||||
*/
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
|
||||
|
||||
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
|
||||
asm("pushw %es; movw %ds, %ax; movw %ax, %es");
|
||||
|
||||
if (reg < 0x08)
|
||||
insl(channels[channel].base + reg - 0x00, buffer, quads);
|
||||
else if (reg < 0x0C)
|
||||
insl(channels[channel].base + reg - 0x06, buffer, quads);
|
||||
else if (reg < 0x0E)
|
||||
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
|
||||
else if (reg < 0x16)
|
||||
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
|
||||
if (reg < 0x08)
|
||||
insl(channels[channel].base + reg - 0x00, buffer, quads);
|
||||
else if (reg < 0x0C)
|
||||
insl(channels[channel].base + reg - 0x06, buffer, quads);
|
||||
else if (reg < 0x0E)
|
||||
insl(channels[channel].ctrl + reg - 0x0A, buffer, quads);
|
||||
else if (reg < 0x16)
|
||||
insl(channels[channel].bmide + reg - 0x0E, buffer, quads);
|
||||
|
||||
asm("popw %es;");
|
||||
asm("popw %es;");
|
||||
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
if (reg > 0x07 && reg < 0x0C)
|
||||
ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
|
||||
}
|
||||
|
||||
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
|
||||
// Delay 400 ns for BSY to be set:
|
||||
for (int i = 0; i < 4; i++)
|
||||
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port
|
||||
// wastes 100ns; loop four times.
|
||||
|
||||
// Delay 400 ns for BSY to be set:
|
||||
for (int i = 0; i < 4; i++)
|
||||
ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port
|
||||
// wastes 100ns; loop four times.
|
||||
// Wait for BSY to be 0:
|
||||
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY) {
|
||||
if (advanced_check) {
|
||||
unsigned char state = ide_read(channel, ATA_REG_STATUS); // Read Status Register.
|
||||
|
||||
// Wait for BSY to be 0:
|
||||
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
|
||||
// Check For Errors:
|
||||
if (state & ATA_SR_ERR)
|
||||
return 2; // Error
|
||||
|
||||
if (advanced_check) {
|
||||
unsigned char state =
|
||||
ide_read(channel, ATA_REG_STATUS); // Read Status Register.
|
||||
// Check If Device fault:
|
||||
if (state & ATA_SR_DF)
|
||||
return 1; // Device Fault.
|
||||
|
||||
// Check For Errors:
|
||||
if (state & ATA_SR_ERR)
|
||||
return 2; // Error
|
||||
|
||||
// Check If Device fault:
|
||||
if (state & ATA_SR_DF)
|
||||
return 1; // Device Fault.
|
||||
|
||||
// Check DRQ:
|
||||
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
|
||||
if ((state & ATA_SR_DRQ) == 0)
|
||||
return 3; // DRQ should be set
|
||||
// Check DRQ:
|
||||
// BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
|
||||
if ((state & ATA_SR_DRQ) == 0)
|
||||
return 3; // DRQ should be set
|
||||
}
|
||||
}
|
||||
return 0; // No Error.
|
||||
return 0; // No Error.
|
||||
}
|
||||
|
||||
unsigned char ide_print_error(unsigned int drive, unsigned char err) {
|
||||
if (err == 0)
|
||||
if (err == 0)
|
||||
return err;
|
||||
|
||||
printf("IDE - ");
|
||||
if (err == 1) {
|
||||
printf("Device Fault");
|
||||
err = 19;
|
||||
} else if (err == 2) {
|
||||
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
|
||||
if (st & ATA_ER_AMNF) {
|
||||
printf("No Address Mark Found");
|
||||
err = 7;
|
||||
}
|
||||
if (st & ATA_ER_TK0NF) {
|
||||
printf("No Media or Media Error");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_ABRT) {
|
||||
printf("Command Aborted");
|
||||
err = 20;
|
||||
}
|
||||
if (st & ATA_ER_MCR) {
|
||||
printf("No Media or Media Error");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_IDNF) {
|
||||
printf("ID mark not Found");
|
||||
err = 21;
|
||||
}
|
||||
if (st & ATA_ER_MC) {
|
||||
printf("No Media or Media Error");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_UNC) {
|
||||
printf("Uncorrectable Data Error");
|
||||
err = 22;
|
||||
}
|
||||
if (st & ATA_ER_BBK) {
|
||||
printf("Bad Sectors");
|
||||
err = 13;
|
||||
}
|
||||
} else if (err == 3) {
|
||||
printf("Reads Nothing");
|
||||
err = 23;
|
||||
} else if (err == 4) {
|
||||
printf("Write Protected");
|
||||
err = 8;
|
||||
}
|
||||
|
||||
printf(" - [%s %s %s\n", (const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel],
|
||||
(const char *[]){"Master", "Slave"}[ide_devices[drive].Drive], ide_devices[drive].Model);
|
||||
|
||||
return err;
|
||||
|
||||
terminal_writestring("IDE:");
|
||||
if (err == 1) {
|
||||
terminal_writestring("- Device Fault\n ");
|
||||
err = 19;
|
||||
} else if (err == 2) {
|
||||
unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
|
||||
if (st & ATA_ER_AMNF) {
|
||||
terminal_writestring("- No Address Mark Found\n");
|
||||
err = 7;
|
||||
}
|
||||
if (st & ATA_ER_TK0NF) {
|
||||
terminal_writestring("- No Media or Media Error\n");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_ABRT) {
|
||||
terminal_writestring("- Command Aborted\n");
|
||||
err = 20;
|
||||
}
|
||||
if (st & ATA_ER_MCR) {
|
||||
terminal_writestring("- No Media or Media Error\n");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_IDNF) {
|
||||
terminal_writestring("- ID mark not Found\n");
|
||||
err = 21;
|
||||
}
|
||||
if (st & ATA_ER_MC) {
|
||||
terminal_writestring("- No Media or Media Error\n");
|
||||
err = 3;
|
||||
}
|
||||
if (st & ATA_ER_UNC) {
|
||||
terminal_writestring("- Uncorrectable Data Error\n");
|
||||
err = 22;
|
||||
}
|
||||
if (st & ATA_ER_BBK) {
|
||||
terminal_writestring("- Bad Sectors\n");
|
||||
err = 13;
|
||||
}
|
||||
} else if (err == 3) {
|
||||
terminal_writestring("- Reads Nothing\n");
|
||||
err = 23;
|
||||
} else if (err == 4) {
|
||||
terminal_writestring("- Write Protected\n");
|
||||
err = 8;
|
||||
}
|
||||
|
||||
terminal_writestring("- [");
|
||||
terminal_writestring(
|
||||
(const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel]);
|
||||
terminal_writestring(" ");
|
||||
terminal_writestring(
|
||||
(const char *[]){"Master", "Slave"}[ide_devices[drive].Drive]);
|
||||
terminal_writestring(" ");
|
||||
terminal_writeline(ide_devices[drive].Model);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
||||
unsigned int BAR3, unsigned int BAR4) {
|
||||
int j, k, count = 0;
|
||||
|
||||
int j, k, count = 0;
|
||||
// Detect I/O Ports which interface IDE Controller:
|
||||
channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
|
||||
channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
|
||||
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
|
||||
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
|
||||
channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
|
||||
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
|
||||
|
||||
// Detect I/O Ports which interface IDE Controller:
|
||||
channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
|
||||
channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
|
||||
channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
|
||||
channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
|
||||
channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
|
||||
channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE
|
||||
// Disable IRQs:
|
||||
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
||||
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
|
||||
|
||||
// Disable IRQs:
|
||||
ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 2);
|
||||
ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
|
||||
// Detect ATA-ATAPI Devices:
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++) {
|
||||
unsigned char err = 0, type = IDE_ATA, status;
|
||||
ide_devices[count].Reserved = 0; // Assuming that no drive here.
|
||||
|
||||
// Detect ATA-ATAPI Devices:
|
||||
for (int i = 0; i < 2; i++)
|
||||
for (j = 0; j < 2; j++) {
|
||||
unsigned char err = 0, type = IDE_ATA, status;
|
||||
ide_devices[count].Reserved = 0; // Assuming that no drive here.
|
||||
// Select Drive:
|
||||
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
|
||||
sleep(1); // Wait 1ms for drive select to work.
|
||||
|
||||
// Select Drive:
|
||||
ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
|
||||
sleep(1); // Wait 1ms for drive select to work.
|
||||
// Send ATA Identify Command:
|
||||
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||
sleep(1); // This function should be implemented in your OS. which waits
|
||||
// for 1 ms. it is based on System Timer Device Driver.
|
||||
|
||||
// Send ATA Identify Command:
|
||||
ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
|
||||
sleep(1); // This function should be implemented in your OS. which waits
|
||||
// for 1 ms. it is based on System Timer Device Driver.
|
||||
// Polling:
|
||||
if (ide_read(i, ATA_REG_STATUS) == 0)
|
||||
continue; // If Status = 0, No Device.
|
||||
|
||||
// Polling:
|
||||
if (ide_read(i, ATA_REG_STATUS) == 0)
|
||||
continue; // If Status = 0, No Device.
|
||||
while (1) {
|
||||
status = ide_read(i, ATA_REG_STATUS);
|
||||
if ((status & ATA_SR_ERR)) {
|
||||
err = 1;
|
||||
break;
|
||||
} // If Err, Device is not ATA.
|
||||
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ))
|
||||
break; // Everything is right.
|
||||
}
|
||||
|
||||
while (1) {
|
||||
status = ide_read(i, ATA_REG_STATUS);
|
||||
if ((status & ATA_SR_ERR)) {
|
||||
err = 1;
|
||||
break;
|
||||
} // If Err, Device is not ATA.
|
||||
if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ))
|
||||
break; // Everything is right.
|
||||
}
|
||||
// Read Identification Space of the Device:
|
||||
ide_read_buffer(i, ATA_REG_DATA, (unsigned int)ide_buf, 128);
|
||||
|
||||
// Read Identification Space of the Device:
|
||||
ide_read_buffer(i, ATA_REG_DATA, (unsigned int)ide_buf, 128);
|
||||
// Read Device Parameters:
|
||||
ide_devices[count].Reserved = 1;
|
||||
ide_devices[count].Type = type;
|
||||
ide_devices[count].Channel = i;
|
||||
ide_devices[count].Drive = j;
|
||||
ide_devices[count].Signature = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
|
||||
ide_devices[count].Capabilities = *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
|
||||
ide_devices[count].CommandSets = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
|
||||
|
||||
// Read Device Parameters:
|
||||
ide_devices[count].Reserved = 1;
|
||||
ide_devices[count].Type = type;
|
||||
ide_devices[count].Channel = i;
|
||||
ide_devices[count].Drive = j;
|
||||
ide_devices[count].Signature =
|
||||
*((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
|
||||
ide_devices[count].Capabilities =
|
||||
*((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
|
||||
ide_devices[count].CommandSets =
|
||||
*((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
|
||||
// Get Size:
|
||||
if (ide_devices[count].CommandSets & (1 << 26))
|
||||
// Device uses 48-Bit Addressing:
|
||||
ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
|
||||
else
|
||||
// Device uses CHS or 28-bit Addressing:
|
||||
ide_devices[count].Size = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
|
||||
|
||||
// Get Size:
|
||||
if (ide_devices[count].CommandSets & (1 << 26))
|
||||
// Device uses 48-Bit Addressing:
|
||||
ide_devices[count].Size =
|
||||
*((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
|
||||
else
|
||||
// Device uses CHS or 28-bit Addressing:
|
||||
ide_devices[count].Size =
|
||||
*((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
|
||||
|
||||
// String indicates model of device (like Western Digital HDD and SONY
|
||||
// DVD-RW...):
|
||||
for (k = 0; k < 40; k += 2) {
|
||||
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
|
||||
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
|
||||
}
|
||||
ide_devices[count].Model[40] = 0; // Terminate String.
|
||||
count++;
|
||||
// String indicates model of device (like Western Digital HDD and SONY
|
||||
// DVD-RW...):
|
||||
for (k = 0; k < 40; k += 2) {
|
||||
ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
|
||||
ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];
|
||||
}
|
||||
ide_devices[count].Model[40] = 0; // Terminate String.
|
||||
count++;
|
||||
}
|
||||
|
||||
// Print Summary:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (ide_devices[i].Reserved == 1) {
|
||||
terminal_writestring("IDE FOUND DEVICE-> ");
|
||||
terminal_writestring(
|
||||
(const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type]);
|
||||
terminal_writestring(" Drive ");
|
||||
terminal_writestring(itoa(ide_devices[i].Size / 1024 / 2));
|
||||
terminal_writestring("MB - ");
|
||||
terminal_writeline(ide_devices[i].Model);
|
||||
// Print Summary:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (ide_devices[i].Reserved == 1) {
|
||||
printf("IDE FOUND DEVICE-> %s Drive %dMB - %s\n", (const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type],
|
||||
ide_devices[i].Size / 1024 / 2, ide_devices[i].Model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ATA/ATAPI Read/Write Modes:
|
||||
|
@ -321,198 +302,215 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2,
|
|||
void ide_irq() { ide_irq_invoked = 1; }
|
||||
|
||||
void ide_wait_irq() {
|
||||
while (!ide_irq_invoked)
|
||||
;
|
||||
ide_irq_invoked = 0;
|
||||
while (!ide_irq_invoked)
|
||||
;
|
||||
ide_irq_invoked = 0;
|
||||
}
|
||||
|
||||
unsigned char ide_ata_access(unsigned char direction, unsigned char drive,
|
||||
unsigned int lba, uint8_t *buf) {
|
||||
unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */,
|
||||
dma /* 0: No DMA, 1: DMA */, cmd;
|
||||
unsigned char lba_io[6];
|
||||
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
|
||||
unsigned int slavebit =
|
||||
ide_devices[drive].Drive; // Read the Drive [Master/Slave]
|
||||
unsigned int bus =
|
||||
channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
|
||||
unsigned int words =
|
||||
256; // Almost every ATA drive has a sector-size of 512-byte.
|
||||
unsigned short cyl, i;
|
||||
unsigned char head, sect, err;
|
||||
unsigned char lba_mode /* 0: CHS, 1:LBA28, 2: LBA48 */,
|
||||
dma /* 0: No DMA, 1: DMA */, cmd;
|
||||
unsigned char lba_io[6];
|
||||
unsigned int channel = ide_devices[drive].Channel; // Read the Channel.
|
||||
unsigned int slavebit = ide_devices[drive].Drive; // Read the Drive [Master/Slave]
|
||||
unsigned int bus = channels[channel].base; // Bus Base, like 0x1F0 which is also data port.
|
||||
unsigned int words = 256; // Almost every ATA drive has a sector-size of 512-byte.
|
||||
unsigned short cyl, i;
|
||||
unsigned char head, sect, err;
|
||||
|
||||
ide_write(channel, ATA_REG_CONTROL,
|
||||
channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
|
||||
ide_write(channel, ATA_REG_CONTROL,
|
||||
channels[channel].nIEN = (ide_irq_invoked = 0x0) + 0x02);
|
||||
|
||||
// Read parameters
|
||||
// Select one from LBA28, LBA48 or CHS;
|
||||
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or you
|
||||
// are giving a wrong LBA.
|
||||
// LBA48:
|
||||
lba_mode = 2;
|
||||
lba_io[0] = (lba & 0x000000FF) >> 0;
|
||||
lba_io[1] = (lba & 0x0000FF00) >> 8;
|
||||
lba_io[2] = (lba & 0x00FF0000) >> 16;
|
||||
lba_io[3] = (lba & 0xFF000000) >> 24;
|
||||
lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
||||
lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
||||
head = 0; // Lower 4-bits of HDDEVSEL are not used here.
|
||||
} else if (ide_devices[drive].Capabilities & 0x200) { // Drive supports LBA?
|
||||
// LBA28:
|
||||
lba_mode = 1;
|
||||
lba_io[0] = (lba & 0x00000FF) >> 0;
|
||||
lba_io[1] = (lba & 0x000FF00) >> 8;
|
||||
lba_io[2] = (lba & 0x0FF0000) >> 16;
|
||||
lba_io[3] = 0; // These Registers are not used here.
|
||||
lba_io[4] = 0; // These Registers are not used here.
|
||||
lba_io[5] = 0; // These Registers are not used here.
|
||||
head = (lba & 0xF000000) >> 24;
|
||||
} else {
|
||||
// CHS:
|
||||
lba_mode = 0;
|
||||
sect = (lba % 63) + 1;
|
||||
cyl = (lba + 1 - sect) / (16 * 63);
|
||||
lba_io[0] = sect;
|
||||
lba_io[1] = (cyl >> 0) & 0xFF;
|
||||
lba_io[2] = (cyl >> 8) & 0xFF;
|
||||
lba_io[3] = 0;
|
||||
lba_io[4] = 0;
|
||||
lba_io[5] = 0;
|
||||
head = (lba + 1 - sect) % (16 * 63) /
|
||||
(63); // Head number is written to HDDEVSEL lower 4-bits.
|
||||
}
|
||||
|
||||
dma = 0; // 0 = We don't support DMA
|
||||
|
||||
// Wait if the drive is busy...
|
||||
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
|
||||
; // Wait if busy.
|
||||
|
||||
// Select Drive from the controller...
|
||||
if (lba_mode == 0)
|
||||
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||
0xA0 | (slavebit << 4) | head); // Drive & CHS.
|
||||
else
|
||||
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||
0xE0 | (slavebit << 4) | head); // Drive & LBA
|
||||
|
||||
// Write Parameters;
|
||||
if (lba_mode == 2) {
|
||||
ide_write(channel, ATA_REG_SECCOUNT1, 0);
|
||||
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
|
||||
ide_write(channel, ATA_REG_LBA4, lba_io[4]);
|
||||
ide_write(channel, ATA_REG_LBA5, lba_io[5]);
|
||||
}
|
||||
ide_write(channel, ATA_REG_SECCOUNT0,
|
||||
1); // Number of sectors, always 1 in our case
|
||||
ide_write(channel, ATA_REG_LBA0, lba_io[0]);
|
||||
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
|
||||
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
|
||||
|
||||
// Select the command and send it;
|
||||
// Routine that is followed:
|
||||
// If ( DMA & LBA48) DO_DMA_EXT;
|
||||
// If ( DMA & LBA28) DO_DMA_LBA;
|
||||
// If ( DMA & LBA28) DO_DMA_CHS;
|
||||
// If (!DMA & LBA48) DO_PIO_EXT;
|
||||
// If (!DMA & LBA28) DO_PIO_LBA;
|
||||
// If (!DMA & !LBA#) DO_PIO_CHS;
|
||||
|
||||
if (lba_mode == 0 && dma == 0 && direction == 0)
|
||||
cmd = ATA_CMD_READ_PIO;
|
||||
if (lba_mode == 1 && dma == 0 && direction == 0)
|
||||
cmd = ATA_CMD_READ_PIO;
|
||||
if (lba_mode == 2 && dma == 0 && direction == 0)
|
||||
cmd = ATA_CMD_READ_PIO_EXT;
|
||||
if (lba_mode == 0 && dma == 1 && direction == 0)
|
||||
cmd = ATA_CMD_READ_DMA;
|
||||
if (lba_mode == 1 && dma == 1 && direction == 0)
|
||||
cmd = ATA_CMD_READ_DMA;
|
||||
if (lba_mode == 2 && dma == 1 && direction == 0)
|
||||
cmd = ATA_CMD_READ_DMA_EXT;
|
||||
if (lba_mode == 0 && dma == 0 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_PIO;
|
||||
if (lba_mode == 1 && dma == 0 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_PIO;
|
||||
if (lba_mode == 2 && dma == 0 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_PIO_EXT;
|
||||
if (lba_mode == 0 && dma == 1 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_DMA;
|
||||
if (lba_mode == 1 && dma == 1 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_DMA;
|
||||
if (lba_mode == 2 && dma == 1 && direction == 1)
|
||||
cmd = ATA_CMD_WRITE_DMA_EXT;
|
||||
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
|
||||
if (dma) {
|
||||
if (direction == 0) {
|
||||
// DMA read.
|
||||
// Read parameters
|
||||
// Select one from LBA28, LBA48 or CHS;
|
||||
if (lba >= 0x10000000) { // Sure Drive should support LBA in this case, or you
|
||||
// are giving a wrong LBA.
|
||||
// LBA48:
|
||||
lba_mode = 2;
|
||||
lba_io[0] = (lba & 0x000000FF) >> 0;
|
||||
lba_io[1] = (lba & 0x0000FF00) >> 8;
|
||||
lba_io[2] = (lba & 0x00FF0000) >> 16;
|
||||
lba_io[3] = (lba & 0xFF000000) >> 24;
|
||||
lba_io[4] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
||||
lba_io[5] = 0; // LBA28 is integer, so 32-bits are enough to access 2TB.
|
||||
head = 0; // Lower 4-bits of HDDEVSEL are not used here.
|
||||
} else if (ide_devices[drive].Capabilities & 0x200) { // Drive supports LBA?
|
||||
// LBA28:
|
||||
lba_mode = 1;
|
||||
lba_io[0] = (lba & 0x00000FF) >> 0;
|
||||
lba_io[1] = (lba & 0x000FF00) >> 8;
|
||||
lba_io[2] = (lba & 0x0FF0000) >> 16;
|
||||
lba_io[3] = 0; // These Registers are not used here.
|
||||
lba_io[4] = 0; // These Registers are not used here.
|
||||
lba_io[5] = 0; // These Registers are not used here.
|
||||
head = (lba & 0xF000000) >> 24;
|
||||
} else {
|
||||
// DMA write.
|
||||
// CHS:
|
||||
lba_mode = 0;
|
||||
sect = (lba % 63) + 1;
|
||||
cyl = (lba + 1 - sect) / (16 * 63);
|
||||
lba_io[0] = sect;
|
||||
lba_io[1] = (cyl >> 0) & 0xFF;
|
||||
lba_io[2] = (cyl >> 8) & 0xFF;
|
||||
lba_io[3] = 0;
|
||||
lba_io[4] = 0;
|
||||
lba_io[5] = 0;
|
||||
head = (lba + 1 - sect) % (16 * 63) /
|
||||
(63); // Head number is written to HDDEVSEL lower 4-bits.
|
||||
}
|
||||
} else {
|
||||
if (direction == 0) {
|
||||
// PIO Read.
|
||||
if (err = ide_polling(channel, 1))
|
||||
return err; // Polling, set error and exit if there is.
|
||||
inportsm(bus, buf, words);
|
||||
ide_write(channel, ATA_REG_COMMAND,
|
||||
|
||||
dma = 0; // 0 = We don't support DMA
|
||||
|
||||
// Wait if the drive is busy...
|
||||
while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
|
||||
; // Wait if busy.
|
||||
|
||||
// Select Drive from the controller...
|
||||
if (lba_mode == 0)
|
||||
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||
0xA0 | (slavebit << 4) | head); // Drive & CHS.
|
||||
else
|
||||
ide_write(channel, ATA_REG_HDDEVSEL,
|
||||
0xE0 | (slavebit << 4) | head); // Drive & LBA
|
||||
|
||||
// Write Parameters;
|
||||
if (lba_mode == 2) {
|
||||
ide_write(channel, ATA_REG_SECCOUNT1, 0);
|
||||
ide_write(channel, ATA_REG_LBA3, lba_io[3]);
|
||||
ide_write(channel, ATA_REG_LBA4, lba_io[4]);
|
||||
ide_write(channel, ATA_REG_LBA5, lba_io[5]);
|
||||
}
|
||||
ide_write(channel, ATA_REG_SECCOUNT0,
|
||||
1); // Number of sectors, always 1 in our case
|
||||
ide_write(channel, ATA_REG_LBA0, lba_io[0]);
|
||||
ide_write(channel, ATA_REG_LBA1, lba_io[1]);
|
||||
ide_write(channel, ATA_REG_LBA2, lba_io[2]);
|
||||
|
||||
// Select the command and send it;
|
||||
// Routine that is followed:
|
||||
// If ( DMA & LBA48) DO_DMA_EXT;
|
||||
// If ( DMA & LBA28) DO_DMA_LBA;
|
||||
// If ( DMA & LBA28) DO_DMA_CHS;
|
||||
// If (!DMA & LBA48) DO_PIO_EXT;
|
||||
// If (!DMA & LBA28) DO_PIO_LBA;
|
||||
// If (!DMA & !LBA#) DO_PIO_CHS;
|
||||
|
||||
if (lba_mode == 0 && dma == 0 && direction == ATA_READ)
|
||||
cmd = ATA_CMD_READ_PIO;
|
||||
if (lba_mode == 1 && dma == 0 && direction == ATA_READ)
|
||||
cmd = ATA_CMD_READ_PIO;
|
||||
if (lba_mode == 2 && dma == 0 && direction == ATA_READ)
|
||||
cmd = ATA_CMD_READ_PIO_EXT;
|
||||
if (lba_mode == 0 && dma == 1 && direction == ATA_READ)
|
||||
cmd = ATA_CMD_READ_DMA;
|
||||
if (lba_mode == 1 && dma == 1 && direction == ATA_READ)
|
||||
cmd = ATA_CMD_READ_DMA;
|
||||
if (lba_mode == 2 && dma == 1 && direction == ATA_READ)
|
||||
cmd = ATA_CMD_READ_DMA_EXT;
|
||||
if (lba_mode == 0 && dma == 0 && direction == ATA_WRITE)
|
||||
cmd = ATA_CMD_WRITE_PIO;
|
||||
if (lba_mode == 1 && dma == 0 && direction == ATA_WRITE)
|
||||
cmd = ATA_CMD_WRITE_PIO;
|
||||
if (lba_mode == 2 && dma == 0 && direction == ATA_WRITE)
|
||||
cmd = ATA_CMD_WRITE_PIO_EXT;
|
||||
if (lba_mode == 0 && dma == 1 && direction == ATA_WRITE)
|
||||
cmd = ATA_CMD_WRITE_DMA;
|
||||
if (lba_mode == 1 && dma == 1 && direction == ATA_WRITE)
|
||||
cmd = ATA_CMD_WRITE_DMA;
|
||||
if (lba_mode == 2 && dma == 1 && direction == ATA_WRITE)
|
||||
cmd = ATA_CMD_WRITE_DMA_EXT;
|
||||
ide_write(channel, ATA_REG_COMMAND, cmd); // Send the Command.
|
||||
if (dma) {
|
||||
if (direction == ATA_READ) {
|
||||
// DMA read.
|
||||
} else {
|
||||
// DMA write.
|
||||
}
|
||||
} else {
|
||||
if (direction == ATA_READ) {
|
||||
// PIO Read.
|
||||
if (err = ide_polling(channel, 1))
|
||||
return err; // Polling, set error and exit if there is.
|
||||
inportsm(bus, buf, words);
|
||||
ide_write(channel, ATA_REG_COMMAND,
|
||||
(char[]){(char)ATA_CMD_CACHE_FLUSH, (char)ATA_CMD_CACHE_FLUSH,
|
||||
(char)ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
|
||||
ide_polling(channel, 0); // Polling.
|
||||
} else {
|
||||
// PIO Write.
|
||||
ide_polling(channel, 0); // Polling.
|
||||
outportsm(bus, buf, words);
|
||||
ide_write(channel, ATA_REG_COMMAND,
|
||||
(char)ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
|
||||
ide_polling(channel, 0); // Polling.
|
||||
} else {
|
||||
// PIO Write.
|
||||
ide_polling(channel, 0); // Polling.
|
||||
outportsm(bus, buf, words);
|
||||
ide_write(channel, ATA_REG_COMMAND,
|
||||
(char[]){ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH,
|
||||
ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
|
||||
ide_polling(channel, 0);
|
||||
ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]);
|
||||
ide_polling(channel, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; // Easy, isn't it? no
|
||||
return 0; // Easy, isn't it? no
|
||||
}
|
||||
|
||||
uint8_t ide_read_sectors(unsigned char drive, unsigned int lba, uint8_t *buf) {
|
||||
// Check if the drive is present:
|
||||
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||
return 0x01; // Drive not present
|
||||
|
||||
// Check if the drive is present:
|
||||
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||
return 0x01; // Drive not present
|
||||
// Check if inputs are valid:
|
||||
if (((lba + 1) > ide_devices[drive].Size) && (ide_devices[drive].Type == IDE_ATA))
|
||||
return 0x02; // Seeking to invalid position.
|
||||
|
||||
// Check if inputs are valid:
|
||||
if (((lba + 1) > ide_devices[drive].Size) &&
|
||||
(ide_devices[drive].Type == IDE_ATA))
|
||||
return 0x02; // Seeking to invalid position.
|
||||
|
||||
// Read in PIO Mode through Polling & IRQs:
|
||||
unsigned char err;
|
||||
if (ide_devices[drive].Type == IDE_ATA) {
|
||||
err = ide_ata_access(ATA_READ, drive, lba, buf);
|
||||
} else {
|
||||
// err = ide_atapi_read(drive, lba + i, 1, es, edi + (i*2048));
|
||||
return 0x03; // We don't support this yet.
|
||||
}
|
||||
return ide_print_error(drive, err);
|
||||
// Read in PIO Mode through Polling & IRQs:
|
||||
unsigned char err;
|
||||
if (ide_devices[drive].Type == IDE_ATA) {
|
||||
err = ide_ata_access(ATA_READ, drive, lba, buf);
|
||||
} else {
|
||||
// err = a_read(drive, lba + i, 1, es, edi + (i*2048));
|
||||
return 0x03; // We don't support this yet.
|
||||
}
|
||||
return ide_print_error(drive, err);
|
||||
}
|
||||
|
||||
uint8_t ide_write_sectors(unsigned char drive, unsigned int lba, uint8_t *buf) {
|
||||
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||
return 0x01; // Drive not present
|
||||
if (((lba + 1) > ide_devices[drive].Size) &&
|
||||
(ide_devices[drive].Type == IDE_ATA))
|
||||
return 0x02; // Seeking to invalid position.
|
||||
if (drive > 3 || ide_devices[drive].Reserved == 0)
|
||||
return 0x01; // Drive not present
|
||||
if (((lba + 1) > ide_devices[drive].Size) &&
|
||||
(ide_devices[drive].Type == IDE_ATA))
|
||||
return 0x02; // Seeking to invalid position.
|
||||
|
||||
// Write in PIO Mode through Polling & IRQs:
|
||||
unsigned char err;
|
||||
if (ide_devices[drive].Type == IDE_ATA) {
|
||||
err = ide_ata_access(ATA_WRITE, drive, lba, buf);
|
||||
} else {
|
||||
err = 4; // Write-Protected.
|
||||
}
|
||||
return ide_print_error(drive, err);
|
||||
// Write in PIO Mode through Polling & IRQs:
|
||||
unsigned char err;
|
||||
if (ide_devices[drive].Type == IDE_ATA) {
|
||||
err = ide_ata_access(ATA_WRITE, drive, lba, buf);
|
||||
} else {
|
||||
err = 4; // Write-Protected.
|
||||
}
|
||||
return ide_print_error(drive, err);
|
||||
}
|
||||
|
||||
void ide_init() {
|
||||
ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000);
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
ide_initialize(0x1F0, 0x3F6, 0x170, 0x376, 0x000);
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
|
||||
printf("Testing IDE drive...\n");
|
||||
uint8_t buf[512] = {0};
|
||||
memcpy(buf, "Hello world", sizeof("Hello world"));
|
||||
ide_write_sectors(0, 1, buf);
|
||||
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
|
||||
uint8_t outbuf[512] = {0};
|
||||
ide_read_sectors(0, 1, outbuf);
|
||||
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
sleep(1);
|
||||
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
printf("%d: %c | ", i, outbuf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
478
arch/i386/std/stdio.c
Normal file
478
arch/i386/std/stdio.c
Normal file
|
@ -0,0 +1,478 @@
|
|||
#include <std/stdio.h>
|
||||
#include <std/string.h>
|
||||
#include <std/ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// shamelessly stolen from https://wiki.osdev.org/User:A22347/Printf
|
||||
|
||||
char* __int_str(intmax_t i, char b[], int base, bool plusSignIfNeeded, bool spaceSignIfNeeded,
|
||||
int paddingNo, bool justify, bool zeroPad) {
|
||||
|
||||
char digit[32] = {0};
|
||||
memset(digit, 0, 32);
|
||||
strcpy(digit, "0123456789");
|
||||
|
||||
if (base == 16) {
|
||||
strcat(digit, "ABCDEF");
|
||||
} else if (base == 17) {
|
||||
strcat(digit, "abcdef");
|
||||
base = 16;
|
||||
}
|
||||
|
||||
char* p = b;
|
||||
if (i < 0) {
|
||||
*p++ = '-';
|
||||
i *= -1;
|
||||
} else if (plusSignIfNeeded) {
|
||||
*p++ = '+';
|
||||
} else if (!plusSignIfNeeded && spaceSignIfNeeded) {
|
||||
*p++ = ' ';
|
||||
}
|
||||
|
||||
intmax_t shifter = i;
|
||||
do {
|
||||
++p;
|
||||
shifter = shifter / base;
|
||||
} while (shifter);
|
||||
|
||||
*p = '\0';
|
||||
do {
|
||||
*--p = digit[i % base];
|
||||
i = i / base;
|
||||
} while (i);
|
||||
|
||||
int padding = paddingNo - (int)strlen(b);
|
||||
if (padding < 0) padding = 0;
|
||||
|
||||
if (justify) {
|
||||
while (padding--) {
|
||||
if (zeroPad) {
|
||||
b[strlen(b)] = '0';
|
||||
} else {
|
||||
b[strlen(b)] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
char a[256] = {0};
|
||||
while (padding--) {
|
||||
if (zeroPad) {
|
||||
a[strlen(a)] = '0';
|
||||
} else {
|
||||
a[strlen(a)] = ' ';
|
||||
}
|
||||
}
|
||||
strcat(a, b);
|
||||
strcpy(b, a);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void displayCharacter(char c, int* a) {
|
||||
putchar(c);
|
||||
*a += 1;
|
||||
}
|
||||
|
||||
void displayString(char* c, int* a) {
|
||||
for (int i = 0; c[i]; ++i) {
|
||||
displayCharacter(c[i], a);
|
||||
}
|
||||
}
|
||||
|
||||
int vprintf (const char* format, va_list list)
|
||||
{
|
||||
int chars = 0;
|
||||
char intStrBuffer[256] = {0};
|
||||
|
||||
for (int i = 0; format[i]; ++i) {
|
||||
|
||||
char specifier = '\0';
|
||||
char length = '\0';
|
||||
|
||||
int lengthSpec = 0;
|
||||
int precSpec = 0;
|
||||
bool leftJustify = false;
|
||||
bool zeroPad = false;
|
||||
bool spaceNoSign = false;
|
||||
bool altForm = false;
|
||||
bool plusSign = false;
|
||||
bool emode = false;
|
||||
int expo = 0;
|
||||
|
||||
if (format[i] == '%') {
|
||||
++i;
|
||||
|
||||
bool extBreak = false;
|
||||
while (1) {
|
||||
|
||||
switch (format[i]) {
|
||||
case '-':
|
||||
leftJustify = true;
|
||||
++i;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
plusSign = true;
|
||||
++i;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
altForm = true;
|
||||
++i;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
spaceNoSign = true;
|
||||
++i;
|
||||
break;
|
||||
|
||||
case '0':
|
||||
zeroPad = true;
|
||||
++i;
|
||||
break;
|
||||
|
||||
default:
|
||||
extBreak = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (extBreak) break;
|
||||
}
|
||||
|
||||
while (isdigit(format[i])) {
|
||||
lengthSpec *= 10;
|
||||
lengthSpec += format[i] - 48;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (format[i] == '*') {
|
||||
lengthSpec = va_arg(list, int);
|
||||
++i;
|
||||
}
|
||||
|
||||
if (format[i] == '.') {
|
||||
++i;
|
||||
while (isdigit(format[i])) {
|
||||
precSpec *= 10;
|
||||
precSpec += format[i] - 48;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (format[i] == '*') {
|
||||
precSpec = va_arg(list, int);
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
precSpec = 6;
|
||||
}
|
||||
|
||||
if (format[i] == 'h' || format[i] == 'l' || format[i] == 'j' ||
|
||||
format[i] == 'z' || format[i] == 't' || format[i] == 'L') {
|
||||
length = format[i];
|
||||
++i;
|
||||
if (format[i] == 'h') {
|
||||
length = 'H';
|
||||
} else if (format[i] == 'l') {
|
||||
length = 'q';
|
||||
++i;
|
||||
}
|
||||
}
|
||||
specifier = format[i];
|
||||
|
||||
memset(intStrBuffer, 0, 256);
|
||||
|
||||
int base = 10;
|
||||
if (specifier == 'o') {
|
||||
base = 8;
|
||||
specifier = 'u';
|
||||
if (altForm) {
|
||||
displayString("0", &chars);
|
||||
}
|
||||
}
|
||||
if (specifier == 'p') {
|
||||
base = 16;
|
||||
length = 'z';
|
||||
specifier = 'u';
|
||||
}
|
||||
switch (specifier) {
|
||||
case 'X':
|
||||
base = 16;
|
||||
case 'x':
|
||||
base = base == 10 ? 17 : base;
|
||||
if (altForm) {
|
||||
displayString("0x", &chars);
|
||||
}
|
||||
|
||||
case 'u':
|
||||
{
|
||||
switch (length) {
|
||||
case 0:
|
||||
{
|
||||
unsigned int integer = va_arg(list, unsigned int);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'H':
|
||||
{
|
||||
unsigned char integer = (unsigned char) va_arg(list, unsigned int);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
{
|
||||
unsigned short int integer = va_arg(list, unsigned int);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
{
|
||||
unsigned long integer = va_arg(list, unsigned long);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'q':
|
||||
{
|
||||
unsigned long long integer = va_arg(list, unsigned long long);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'j':
|
||||
{
|
||||
uintmax_t integer = va_arg(list, uintmax_t);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'z':
|
||||
{
|
||||
size_t integer = va_arg(list, size_t);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
{
|
||||
ptrdiff_t integer = va_arg(list, ptrdiff_t);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
switch (length) {
|
||||
case 0:
|
||||
{
|
||||
int integer = va_arg(list, int);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'H':
|
||||
{
|
||||
signed char integer = (signed char) va_arg(list, int);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
{
|
||||
short int integer = va_arg(list, int);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
{
|
||||
long integer = va_arg(list, long);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'q':
|
||||
{
|
||||
long long integer = va_arg(list, long long);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'j':
|
||||
{
|
||||
intmax_t integer = va_arg(list, intmax_t);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 'z':
|
||||
{
|
||||
size_t integer = va_arg(list, size_t);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
{
|
||||
ptrdiff_t integer = va_arg(list, ptrdiff_t);
|
||||
__int_str(integer, intStrBuffer, base, plusSign, spaceNoSign, lengthSpec, leftJustify, zeroPad);
|
||||
displayString(intStrBuffer, &chars);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
{
|
||||
if (length == 'l') {
|
||||
//displayCharacter(va_arg(list, wint_t), &chars);
|
||||
} else {
|
||||
displayCharacter(va_arg(list, int), &chars);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 's':
|
||||
{
|
||||
displayString(va_arg(list, char*), &chars);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'n':
|
||||
{
|
||||
switch (length) {
|
||||
case 'H':
|
||||
*(va_arg(list, signed char*)) = chars;
|
||||
break;
|
||||
case 'h':
|
||||
*(va_arg(list, short int*)) = chars;
|
||||
break;
|
||||
|
||||
case 0: {
|
||||
int* a = va_arg(list, int*);
|
||||
*a = chars;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'l':
|
||||
*(va_arg(list, long*)) = chars;
|
||||
break;
|
||||
case 'q':
|
||||
*(va_arg(list, long long*)) = chars;
|
||||
break;
|
||||
case 'j':
|
||||
*(va_arg(list, intmax_t*)) = chars;
|
||||
break;
|
||||
case 'z':
|
||||
*(va_arg(list, size_t*)) = chars;
|
||||
break;
|
||||
case 't':
|
||||
*(va_arg(list, ptrdiff_t*)) = chars;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
emode = true;
|
||||
|
||||
/*
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'g':
|
||||
case 'G':
|
||||
{
|
||||
double floating = va_arg(list, double);
|
||||
|
||||
while (emode && floating >= 10) {
|
||||
floating /= 10;
|
||||
++expo;
|
||||
}
|
||||
|
||||
int form = lengthSpec - precSpec - expo - (precSpec || altForm ? 1 : 0);
|
||||
if (emode) {
|
||||
form -= 4; // 'e+00'
|
||||
}
|
||||
if (form < 0) {
|
||||
form = 0;
|
||||
}
|
||||
|
||||
__int_str(floating, intStrBuffer, base, plusSign, spaceNoSign, form, \
|
||||
leftJustify, zeroPad);
|
||||
|
||||
displayString(intStrBuffer, &chars);
|
||||
|
||||
floating -= (int) floating;
|
||||
|
||||
for (int i = 0; i < precSpec; ++i) {
|
||||
floating *= 10;
|
||||
}
|
||||
intmax_t decPlaces = (intmax_t) (floating + 0.5);
|
||||
|
||||
if (precSpec) {
|
||||
displayCharacter('.', &chars);
|
||||
__int_str(decPlaces, intStrBuffer, 10, false, false, 0, false, false);
|
||||
intStrBuffer[precSpec] = 0;
|
||||
displayString(intStrBuffer, &chars);
|
||||
} else if (altForm) {
|
||||
displayCharacter('.', &chars);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
*/
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
//ACK! Hexadecimal floating points...
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (specifier == 'e') {
|
||||
displayString("e+", &chars);
|
||||
} else if (specifier == 'E') {
|
||||
displayString("E+", &chars);
|
||||
}
|
||||
|
||||
if (specifier == 'e' || specifier == 'E') {
|
||||
__int_str(expo, intStrBuffer, 10, false, false, 2, false, true);
|
||||
displayString(intStrBuffer, &chars);
|
||||
}
|
||||
|
||||
} else {
|
||||
displayCharacter(format[i], &chars);
|
||||
}
|
||||
}
|
||||
|
||||
return chars;
|
||||
}
|
||||
|
||||
__attribute__ ((format (printf, 1, 2))) int printf (const char* format, ...) {
|
||||
va_list list;
|
||||
va_start (list, format);
|
||||
int i = vprintf (format, list);
|
||||
va_end (list);
|
||||
return i;
|
||||
}
|
|
@ -38,8 +38,7 @@ char* itoa(int res) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
unsigned int atoi(const char *in)
|
||||
{
|
||||
unsigned int atoi(const char *in) {
|
||||
unsigned int size = 0;
|
||||
unsigned int j;
|
||||
unsigned int count = 1;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _AHCI_H
|
||||
#define _AHCI_H 1
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -350,5 +349,3 @@ void ahci_init(void);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _AHCI_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _DEVICE_H
|
||||
#define _DEVICE_H 1
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -18,5 +17,3 @@ void* write(int descriptor, void* data);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DEVICE_H */
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef _IDE_H
|
||||
#define _IDE_H 1
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -103,9 +103,8 @@ extern "C" {
|
|||
// ---- Functions -----
|
||||
|
||||
void ide_init();
|
||||
uint8_t ide_write_sectors(unsigned char drive, unsigned int lba, uint8_t *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IDE_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _IDT_H
|
||||
#define _IDT_H 1
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <std/util.h>
|
||||
|
@ -19,8 +18,7 @@ struct idt_entry {
|
|||
unsigned short int offset_higherbits;
|
||||
};
|
||||
|
||||
struct interrupt_frame
|
||||
{
|
||||
struct interrupt_frame {
|
||||
uintptr_t ip;
|
||||
uintptr_t cs;
|
||||
uintptr_t flags;
|
||||
|
@ -34,5 +32,3 @@ void idt_register_handler(uint8_t interrupt, unsigned long address);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IDT_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _ISR_H
|
||||
#define _ISR_H 1
|
||||
#pragma once
|
||||
|
||||
#include <drivers/idt/idt.h>
|
||||
|
||||
|
@ -12,5 +11,3 @@ void isr_install(void);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ISR_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _KEYBOARD_H
|
||||
#define _KEYBOARD_H 1
|
||||
#pragma once
|
||||
|
||||
#include <drivers/idt/isr.h>
|
||||
#include <drivers/terminal/terminal.h>
|
||||
|
@ -18,5 +17,3 @@ uint8_t keyboard_enabled(void);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _KEYBOARD_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _PIC_H
|
||||
#define _PIC_H 1
|
||||
#pragma once
|
||||
|
||||
#include <std/inline.h>
|
||||
|
||||
|
@ -27,5 +26,3 @@ void pic_irq_disable(uint8_t no);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PIC_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _TAR_H
|
||||
#define _TAR_H 1
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -23,5 +22,3 @@ struct tar_header* tar_seek(int fd, char filename[100]);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TAR_H */
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _TERMINAL_H
|
||||
#define _TERMINAL_H 1
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
@ -70,5 +69,3 @@ static inline void terminal_writeline(const char* data) {
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TERMINAL_H */
|
||||
|
|
15
include/std/ctype.h
Normal file
15
include/std/ctype.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
inline int isdigit(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef INLINE_H_
|
||||
#define INLINE_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
@ -20,6 +19,10 @@ static inline void outportl(uint16_t const port, uint32_t const val) {
|
|||
asm volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) );
|
||||
}
|
||||
|
||||
static inline void outportsm(unsigned short port, unsigned char* data, unsigned long size) {
|
||||
asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port));
|
||||
}
|
||||
|
||||
static inline uint8_t inportb(uint16_t const port) {
|
||||
uint8_t ret;
|
||||
asm volatile ( "inb %1, %0" : "=a"(ret) : "Nd"(port) );
|
||||
|
@ -38,6 +41,10 @@ static inline uint32_t inportl(uint16_t const port) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static inline void inportsm(unsigned short port, unsigned char* data, unsigned long size) {
|
||||
asm volatile ("rep insw" : "+D" (data), "+c" (size) : "d" (port) : "memory");
|
||||
}
|
||||
|
||||
static inline void io_wait() {
|
||||
asm volatile("outb %%al, $0x80" : : "a"(0));
|
||||
}
|
||||
|
@ -50,20 +57,9 @@ static inline bool are_interrupts_enabled() {
|
|||
return flags & (1 << 9);
|
||||
}
|
||||
|
||||
inline static void inportsm(unsigned short port, unsigned char* data, unsigned long size)
|
||||
{
|
||||
asm volatile ("rep insw" : "+D" (data), "+c" (size) : "d" (port) : "memory");
|
||||
}
|
||||
|
||||
inline static void outportsm(unsigned short port, unsigned char* data, unsigned long size) {
|
||||
asm volatile ("rep outsw" : "+S" (data), "+c" (size) : "d" (port));
|
||||
}
|
||||
|
||||
static void insl(unsigned reg, unsigned int *buffer, int quads)
|
||||
{
|
||||
static inline void insl(unsigned reg, unsigned int *buffer, int quads) {
|
||||
int index;
|
||||
for(index = 0; index < quads; index++)
|
||||
{
|
||||
for (index = 0; index < quads; index++) {
|
||||
buffer[index] = inportl(reg);
|
||||
}
|
||||
}
|
||||
|
@ -71,5 +67,3 @@ static void insl(unsigned reg, unsigned int *buffer, int quads)
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INLINE_H_ */
|
||||
|
|
17
include/std/stdio.h
Normal file
17
include/std/stdio.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include <drivers/terminal/terminal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
inline void putchar(char c) {
|
||||
terminal_putchar(c);
|
||||
}
|
||||
|
||||
__attribute__ ((format (printf, 1, 2))) int printf (const char* format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _STRING_H
|
||||
#define _STRING_H 1
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
@ -18,5 +17,3 @@ char* strcat(char* dst, const char* src);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _STRING_H */
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _UTIL_H
|
||||
#define _UTIL_H 1
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
@ -20,5 +19,3 @@ unsigned int atoi(const char *in);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UTIL_H */
|
Loading…
Reference in a new issue