Re-add: ATA PIO driver (w/o paging)

This commit is contained in:
xamidev
2024-08-18 12:45:24 +02:00
parent cd705589de
commit 2f562758ad
6 changed files with 315 additions and 179 deletions

View File

@@ -79,6 +79,7 @@ Two other documents are available to help you understand the project better. One
- the Intel [64 and IA-32 Architectures Software Developer Manuals](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html) - the Intel [64 and IA-32 Architectures Software Developer Manuals](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html)
- [Bran's Kernel Development Tutorial](http://www.osdever.net/bkerndev/index.php) - [Bran's Kernel Development Tutorial](http://www.osdever.net/bkerndev/index.php)
- Ralf Brown's Interrupt List - Ralf Brown's Interrupt List
- the [little book about OS development](https://littleosbook.github.io/) by Erik Helin and Adam Renberg
### ⚠️ Disclaimer ### ⚠️ Disclaimer
@@ -90,8 +91,9 @@ This is a hobbyist operating system kernel and it comes without any warranty wha
- [X] Common basic structures (IDT, GDT, ISRs, IRQs) - [X] Common basic structures (IDT, GDT, ISRs, IRQs)
- [X] Common drivers (framebuffer, keyboard, serial, timer) - [X] Common drivers (framebuffer, keyboard, serial, timer)
- [X] Kernel-space utilities (shell, simple programs) - [X] Kernel-space utilities (shell, simple programs)
- [ ] FAT32 filesystem - [ ] Filesystem (FAT32 or VFS ramdisk)
- [ ] Paging/Page Frame Allocation - [ ] Changing the default VGA font
- [X] Paging/Page Frame Allocation
- [ ] TCP/IP Network stack - [ ] TCP/IP Network stack
- [ ] Getting to Ring-3 (userspace) - [ ] Getting to Ring-3 (userspace)
- [ ] Multitasking (via round robin scheduling) - [ ] Multitasking (via round robin scheduling)

77
src/drivers/ata.c Normal file
View File

@@ -0,0 +1,77 @@
#include "../libc/stdint.h"
#include "../kernel/io.h"
#include "../libc/stdio.h"
#define ATA_PRIMARY_IO 0x1F0
#define ATA_PRIMARY_CTRL 0x3F6
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_IDENTIFY 0xEC
#define ATA_REG_DATA 0x00
#define ATA_REG_ERROR 0x01
#define ATA_REG_SECCOUNT0 0x02
#define ATA_REG_LBA0 0x03
#define ATA_REG_LBA1 0x04
#define ATA_REG_LBA2 0x05
#define ATA_REG_HDDEVSEL 0x06
#define ATA_REG_COMMAND 0x07
#define ATA_REG_STATUS 0x07
#define ATA_SR_BSY 0x80
#define ATA_SR_DRDY 0x40
#define ATA_SR_DRQ 0x08
#define ATA_SR_ERR 0x01
static inline uint16_t inw(uint16_t port) {
uint16_t result;
asm volatile("inw %1, %0" : "=a"(result) : "dN"(port));
return result;
}
static inline void outw(uint16_t port, uint16_t data) {
asm volatile("outw %1, %0" : : "dN"(port), "a"(data));
}
void ata_wait_bsy() {
while (inb(ATA_PRIMARY_IO + ATA_REG_STATUS) & ATA_SR_BSY);
}
void ata_wait_drq() {
while (!(inb(ATA_PRIMARY_IO + ATA_REG_STATUS) & ATA_SR_DRQ));
}
void ata_select_drive(uint8_t drive) {
outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | (drive << 4));
}
void ata_read_sector(uint32_t lba, uint8_t* buffer) {
ata_wait_bsy();
ata_select_drive(0);
outb(ATA_PRIMARY_IO + ATA_REG_SECCOUNT0, 1);
outb(ATA_PRIMARY_IO + ATA_REG_LBA0, (uint8_t)lba);
outb(ATA_PRIMARY_IO + ATA_REG_LBA1, (uint8_t)(lba >> 8));
outb(ATA_PRIMARY_IO + ATA_REG_LBA2, (uint8_t)(lba >> 16));
outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | ((lba >> 24) & 0x0F));
outb(ATA_PRIMARY_IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
ata_wait_bsy();
ata_wait_drq();
for (int i = 0; i < 256; i++) {
((uint16_t*)buffer)[i] = inw(ATA_PRIMARY_IO + ATA_REG_DATA);
}
}
// Works only w/o paging
void test_read_sector() {
uint8_t buffer[512];
ata_read_sector(0, buffer);
for (int i = 0; i < 512; i++) {
if (i%25==0) puts("\n");
printf("%02x ", buffer[i]);
}
}

7
src/drivers/ata.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef ATA_H
#define ATA_H
void ata_read_sector(uint32_t lba, uint8_t* buffer);
void test_read_sector();
#endif

View File

@@ -4,6 +4,7 @@
#include "idt.h" #include "idt.h"
#include "system.h" #include "system.h"
#include "paging.h" #include "paging.h"
#include "../drivers/ata.h"
char* ascii_title = char* ascii_title =
"\n" "\n"
@@ -39,6 +40,8 @@ void kmain(unsigned int multiboot_info_address)
init_paging(); init_paging();
printf("Hello, paging world!\n"); printf("Hello, paging world!\n");
//test_read_sector();
uint32_t *ptr = (uint32_t*)0xA0000000; uint32_t *ptr = (uint32_t*)0xA0000000;
uint32_t do_page_fault = *ptr; uint32_t do_page_fault = *ptr;

View File

@@ -221,201 +221,247 @@ void dtostrf(double val, char *buffer, int precision)
void printf(const char* fmt, ...) void printf(const char* fmt, ...)
{ {
int* argp = (int*) &fmt; int* argp = (int*)&fmt;
int state = PRINTF_STATE_START; int state = PRINTF_STATE_START;
int length = PRINTF_LENGTH_START; int length = PRINTF_LENGTH_START;
int radix = 10; int radix = 10;
bool sign = false; bool sign = false;
int width = 0;
char pad_char = ' ';
argp++; argp++;
while (*fmt) while (*fmt)
{ {
switch(state) { switch (state)
case PRINTF_STATE_START:
if (*fmt == '%')
{ {
state = PRINTF_STATE_LENGTH; case PRINTF_STATE_START:
} if (*fmt == '%')
else { {
putc(*fmt); state = PRINTF_STATE_LENGTH;
} width = 0;
break; pad_char = ' ';
case PRINTF_STATE_LENGTH: }
if (*fmt == 'h') else
{ {
length = PRINTF_LENGTH_SHORT; putc(*fmt);
state = PRINTF_STATE_SHORT; }
} break;
else if (*fmt == 'l')
{ case PRINTF_STATE_LENGTH:
length = PRINTF_LENGTH_LONG; if (*fmt == '0')
state = PRINTF_STATE_LONG; {
} pad_char = '0';
else { state = PRINTF_STATE_WIDTH;
goto PRINTF_STATE_SPEC_; }
} else if (*fmt >= '1' && *fmt <= '9')
break; {
case PRINTF_STATE_SHORT: width = *fmt - '0';
if (*fmt == 'h') state = PRINTF_STATE_WIDTH;
{ }
length = PRINTF_LENGTH_SHORT_SHORT; else if (*fmt == 'h')
state = PRINTF_STATE_SPEC; {
} length = PRINTF_LENGTH_SHORT;
else { state = PRINTF_STATE_SHORT;
goto PRINTF_STATE_SPEC_; }
} else if (*fmt == 'l')
break; {
case PRINTF_STATE_LONG: length = PRINTF_LENGTH_LONG;
if (*fmt == 'l') state = PRINTF_STATE_LONG;
{ }
length = PRINTF_LENGTH_LONG_LONG; else
state = PRINTF_STATE_SPEC; {
} goto PRINTF_STATE_SPEC_;
else { }
goto PRINTF_STATE_SPEC_; break;
}
break; case PRINTF_STATE_WIDTH:
case PRINTF_STATE_SPEC: if (*fmt >= '0' && *fmt <= '9')
{
width = width * 10 + (*fmt - '0');
}
else
{
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_SHORT:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC;
}
else
{
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_LONG:
if (*fmt == 'l')
{
length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC;
}
else
{
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_: PRINTF_STATE_SPEC_:
switch(*fmt) switch (*fmt)
{ {
case 'c': case 'c':
putc((char)*argp); putc((char)*argp);
argp++; argp++;
break; break;
case 's': case 's':
puts(*(const char **)argp); puts(*(const char**)argp);
argp++; argp++;
break; break;
case '%': case '%':
putc('%'); putc('%');
break; break;
case 'd': case 'd':
case 'i': case 'i':
radix = 10; radix = 10;
sign = true; sign = true;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix, width, pad_char);
break; break;
case 'u': case 'u':
radix = 10;
sign = false;
argp = printf_number(argp, length, sign, radix, width, pad_char);
break;
case 'X':
case 'x':
case 'p':
radix = 16;
sign = false;
argp = printf_number(argp, length, sign, radix, width, pad_char);
break;
case 'o':
radix = 8;
sign = false;
argp = printf_number(argp, length, sign, radix, width, pad_char);
break;
case 'f': {
double* dargp = (double*)argp;
double d = *(double*)dargp;
char buffer[64];
dtostrf(d, buffer, 6);
puts(buffer);
argp += 2;
break;
}
default:
break;
}
state = PRINTF_STATE_START;
length = PRINTF_LENGTH_START;
radix = 10; radix = 10;
sign = false; sign = false;
argp = printf_number(argp, length, sign, radix); width = 0;
break; pad_char = ' ';
case 'X':
case 'x':
case 'p':
radix = 16;
sign = false;
argp = printf_number(argp, length, sign, radix);
break;
case 'o':
radix = 8;
sign = false;
argp = printf_number(argp, length, sign, radix);
break;
case 'f': {
// Handle floating-point numbers
double* dargp = (double*)argp;
double d = *(double*)dargp;
char buffer[64];
dtostrf(d, buffer, 6); // Default precision: 6
puts(buffer);
argp += 2; // Incrementing by 2 to move past the double argument
break;
}
default:
break; break;
} }
state = PRINTF_STATE_START; fmt++;
length = PRINTF_LENGTH_START;
radix = 10;
sign = false;
break;
} }
fmt++;
}
} }
const char charset[] = "0123456789abcdef"; const char charset[] = "0123456789abcdef";
int* printf_number(int* argp, int length, bool sign, int radix) int* printf_number(int* argp, int length, bool sign, int radix, int width, char pad_char)
{ {
char buffer[32]; char buffer[32];
unsigned long long number; unsigned long long number;
int number_sign = 1; int number_sign = 1;
int pos = 0; int pos = 0;
switch(length) switch (length)
{ {
case PRINTF_LENGTH_SHORT_SHORT: case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT: case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_START: case PRINTF_LENGTH_START:
if (sign) if (sign)
{
int n = *argp;
if (n < 0)
{ {
n = -n; int n = *argp;
number_sign = -1; if (n < 0)
{
n = -n;
number_sign = -1;
}
number = (unsigned long long)n;
} }
number = (unsigned long long) n; else
} {
else { number = *(unsigned int*)argp;
number = *(unsigned int*) argp; }
} argp++;
argp++; break;
break;
case PRINTF_LENGTH_LONG: case PRINTF_LENGTH_LONG:
if (sign) if (sign)
{
long int n = *(long int*)argp;
if (n < 0)
{ {
n = -n; long int n = *(long int*)argp;
number_sign = -1; if (n < 0)
{
n = -n;
number_sign = -1;
}
number = (unsigned long long)n;
} }
number = (unsigned long long) n; else
} {
else { number = *(unsigned long int*)argp;
number = *(unsigned long int*) argp; }
} argp += 2;
argp += 2; break;
break;
case PRINTF_LENGTH_LONG_LONG: case PRINTF_LENGTH_LONG_LONG:
if (sign) if (sign)
{
long long int n = *(long long int*)argp;
if (n < 0)
{ {
n = -n; long long int n = *(long long int*)argp;
number_sign = -1; if (n < 0)
{
n = -n;
number_sign = -1;
}
number = (unsigned long long)n;
} }
number = (unsigned long long) n; else
} {
else { number = *(unsigned long long int*)argp;
number = *(unsigned long long int*) argp; }
} argp += 4;
argp += 4; break;
break; }
}
do { do
uint32_t rem; {
x86_div64_32(number, radix, &number, &rem); uint32_t rem;
buffer[pos++] = charset[rem]; x86_div64_32(number, radix, &number, &rem);
} while (number > 0); buffer[pos++] = charset[rem];
} while (number > 0);
if (sign && number_sign < 0) if (sign && number_sign < 0)
{ {
buffer[pos++] = '-'; buffer[pos++] = '-';
} }
while (--pos >= 0) int padding = width - pos;
{
putc(buffer[pos]);
}
return argp; while (padding-- > 0)
{
putc(pad_char);
}
while (--pos >= 0)
{
putc(buffer[pos]);
}
return argp;
} }
int getch() int getch()

View File

@@ -23,20 +23,21 @@ void scroll(int lines);
void putc(char c); void putc(char c);
void colorputc(char c, unsigned int color); void colorputc(char c, unsigned int color);
#define PRINTF_STATE_START 0 #define PRINTF_STATE_START 0
#define PRINTF_STATE_LENGTH 1 #define PRINTF_STATE_LENGTH 1
#define PRINTF_STATE_SHORT 2 #define PRINTF_STATE_SHORT 2
#define PRINTF_STATE_LONG 3 #define PRINTF_STATE_LONG 3
#define PRINTF_STATE_SPEC 4 #define PRINTF_STATE_SPEC 4
#define PRINTF_STATE_WIDTH 5
#define PRINTF_LENGTH_START 0 #define PRINTF_LENGTH_START 0
#define PRINTF_LENGTH_SHORT_SHORT 1 #define PRINTF_LENGTH_SHORT_SHORT 1
#define PRINTF_LENGTH_SHORT 2 #define PRINTF_LENGTH_SHORT 2
#define PRINTF_LENGTH_LONG 3 #define PRINTF_LENGTH_LONG 3
#define PRINTF_LENGTH_LONG_LONG 4 #define PRINTF_LENGTH_LONG_LONG 4
void printf(const char* fmt, ...); void printf(const char* fmt, ...);
int* printf_number(int* argp, int length, bool sign, int radix); int* printf_number(int* argp, int length, bool sign, int radix, int width, char pad_char);
int getch(); int getch();
void get_input(char *buffer, int size); void get_input(char *buffer, int size);