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

@@ -226,22 +226,39 @@ void printf(const char* fmt, ...)
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: case PRINTF_STATE_START:
if (*fmt == '%') if (*fmt == '%')
{ {
state = PRINTF_STATE_LENGTH; state = PRINTF_STATE_LENGTH;
width = 0;
pad_char = ' ';
} }
else { else
{
putc(*fmt); putc(*fmt);
} }
break; break;
case PRINTF_STATE_LENGTH: case PRINTF_STATE_LENGTH:
if (*fmt == 'h') if (*fmt == '0')
{
pad_char = '0';
state = PRINTF_STATE_WIDTH;
}
else if (*fmt >= '1' && *fmt <= '9')
{
width = *fmt - '0';
state = PRINTF_STATE_WIDTH;
}
else if (*fmt == 'h')
{ {
length = PRINTF_LENGTH_SHORT; length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_SHORT; state = PRINTF_STATE_SHORT;
@@ -251,30 +268,47 @@ void printf(const char* fmt, ...)
length = PRINTF_LENGTH_LONG; length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LONG; state = PRINTF_STATE_LONG;
} }
else { else
{
goto PRINTF_STATE_SPEC_; goto PRINTF_STATE_SPEC_;
} }
break; break;
case PRINTF_STATE_WIDTH:
if (*fmt >= '0' && *fmt <= '9')
{
width = width * 10 + (*fmt - '0');
}
else
{
goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_SHORT: case PRINTF_STATE_SHORT:
if (*fmt == 'h') if (*fmt == 'h')
{ {
length = PRINTF_LENGTH_SHORT_SHORT; length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC; state = PRINTF_STATE_SPEC;
} }
else { else
{
goto PRINTF_STATE_SPEC_; goto PRINTF_STATE_SPEC_;
} }
break; break;
case PRINTF_STATE_LONG: case PRINTF_STATE_LONG:
if (*fmt == 'l') if (*fmt == 'l')
{ {
length = PRINTF_LENGTH_LONG_LONG; length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC; state = PRINTF_STATE_SPEC;
} }
else { else
{
goto PRINTF_STATE_SPEC_; goto PRINTF_STATE_SPEC_;
} }
break; break;
case PRINTF_STATE_SPEC: case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_: PRINTF_STATE_SPEC_:
switch (*fmt) switch (*fmt)
@@ -294,33 +328,32 @@ void printf(const char* fmt, ...)
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; radix = 10;
sign = false; sign = false;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix, width, pad_char);
break; break;
case 'X': case 'X':
case 'x': case 'x':
case 'p': case 'p':
radix = 16; radix = 16;
sign = false; sign = false;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix, width, pad_char);
break; break;
case 'o': case 'o':
radix = 8; radix = 8;
sign = false; sign = false;
argp = printf_number(argp, length, sign, radix); argp = printf_number(argp, length, sign, radix, width, pad_char);
break; break;
case 'f': { case 'f': {
// Handle floating-point numbers
double* dargp = (double*)argp; double* dargp = (double*)argp;
double d = *(double*)dargp; double d = *(double*)dargp;
char buffer[64]; char buffer[64];
dtostrf(d, buffer, 6); // Default precision: 6 dtostrf(d, buffer, 6);
puts(buffer); puts(buffer);
argp += 2; // Incrementing by 2 to move past the double argument argp += 2;
break; break;
} }
default: default:
@@ -330,6 +363,8 @@ void printf(const char* fmt, ...)
length = PRINTF_LENGTH_START; length = PRINTF_LENGTH_START;
radix = 10; radix = 10;
sign = false; sign = false;
width = 0;
pad_char = ' ';
break; break;
} }
fmt++; fmt++;
@@ -338,7 +373,7 @@ void printf(const char* 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;
@@ -360,7 +395,8 @@ int* printf_number(int* argp, int length, bool sign, int radix)
} }
number = (unsigned long long)n; number = (unsigned long long)n;
} }
else { else
{
number = *(unsigned int*)argp; number = *(unsigned int*)argp;
} }
argp++; argp++;
@@ -376,7 +412,8 @@ int* printf_number(int* argp, int length, bool sign, int radix)
} }
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;
@@ -392,14 +429,16 @@ int* printf_number(int* argp, int length, bool sign, int radix)
} }
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; uint32_t rem;
x86_div64_32(number, radix, &number, &rem); x86_div64_32(number, radix, &number, &rem);
buffer[pos++] = charset[rem]; buffer[pos++] = charset[rem];
@@ -410,6 +449,13 @@ int* printf_number(int* argp, int length, bool sign, int radix)
buffer[pos++] = '-'; buffer[pos++] = '-';
} }
int padding = width - pos;
while (padding-- > 0)
{
putc(pad_char);
}
while (--pos >= 0) while (--pos >= 0)
{ {
putc(buffer[pos]); putc(buffer[pos]);

View File

@@ -28,6 +28,7 @@ void colorputc(char c, unsigned int color);
#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
@@ -36,7 +37,7 @@ void colorputc(char c, unsigned int color);
#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);