Re-add: ATA PIO driver (w/o paging)
This commit is contained in:
@@ -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)
|
||||
- [Bran's Kernel Development Tutorial](http://www.osdever.net/bkerndev/index.php)
|
||||
- Ralf Brown's Interrupt List
|
||||
- the [little book about OS development](https://littleosbook.github.io/) by Erik Helin and Adam Renberg
|
||||
|
||||
### ⚠️ 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 drivers (framebuffer, keyboard, serial, timer)
|
||||
- [X] Kernel-space utilities (shell, simple programs)
|
||||
- [ ] FAT32 filesystem
|
||||
- [ ] Paging/Page Frame Allocation
|
||||
- [ ] Filesystem (FAT32 or VFS ramdisk)
|
||||
- [ ] Changing the default VGA font
|
||||
- [X] Paging/Page Frame Allocation
|
||||
- [ ] TCP/IP Network stack
|
||||
- [ ] Getting to Ring-3 (userspace)
|
||||
- [ ] Multitasking (via round robin scheduling)
|
||||
|
||||
77
src/drivers/ata.c
Normal file
77
src/drivers/ata.c
Normal 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
7
src/drivers/ata.h
Normal 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
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "idt.h"
|
||||
#include "system.h"
|
||||
#include "paging.h"
|
||||
#include "../drivers/ata.h"
|
||||
|
||||
char* ascii_title =
|
||||
"\n"
|
||||
@@ -39,6 +40,8 @@ void kmain(unsigned int multiboot_info_address)
|
||||
init_paging();
|
||||
printf("Hello, paging world!\n");
|
||||
|
||||
//test_read_sector();
|
||||
|
||||
uint32_t *ptr = (uint32_t*)0xA0000000;
|
||||
uint32_t do_page_fault = *ptr;
|
||||
|
||||
|
||||
102
src/libc/stdio.c
102
src/libc/stdio.c
@@ -221,27 +221,44 @@ void dtostrf(double val, char *buffer, int precision)
|
||||
|
||||
void printf(const char* fmt, ...)
|
||||
{
|
||||
int* argp = (int*) &fmt;
|
||||
int* argp = (int*)&fmt;
|
||||
int state = PRINTF_STATE_START;
|
||||
int length = PRINTF_LENGTH_START;
|
||||
int radix = 10;
|
||||
bool sign = false;
|
||||
int width = 0;
|
||||
char pad_char = ' ';
|
||||
|
||||
argp++;
|
||||
while (*fmt)
|
||||
{
|
||||
switch(state) {
|
||||
switch (state)
|
||||
{
|
||||
case PRINTF_STATE_START:
|
||||
if (*fmt == '%')
|
||||
{
|
||||
state = PRINTF_STATE_LENGTH;
|
||||
width = 0;
|
||||
pad_char = ' ';
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
putc(*fmt);
|
||||
}
|
||||
break;
|
||||
|
||||
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;
|
||||
state = PRINTF_STATE_SHORT;
|
||||
@@ -251,40 +268,57 @@ void printf(const char* fmt, ...)
|
||||
length = PRINTF_LENGTH_LONG;
|
||||
state = PRINTF_STATE_LONG;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
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:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LONG:
|
||||
if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG_LONG;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_SPEC:
|
||||
PRINTF_STATE_SPEC_:
|
||||
switch(*fmt)
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
putc((char)*argp);
|
||||
argp++;
|
||||
break;
|
||||
case 's':
|
||||
puts(*(const char **)argp);
|
||||
puts(*(const char**)argp);
|
||||
argp++;
|
||||
break;
|
||||
case '%':
|
||||
@@ -294,33 +328,32 @@ void printf(const char* fmt, ...)
|
||||
case 'i':
|
||||
radix = 10;
|
||||
sign = true;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
break;
|
||||
case 'u':
|
||||
radix = 10;
|
||||
sign = false;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
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);
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
break;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
sign = false;
|
||||
argp = printf_number(argp, length, sign, radix);
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
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
|
||||
dtostrf(d, buffer, 6);
|
||||
puts(buffer);
|
||||
argp += 2; // Incrementing by 2 to move past the double argument
|
||||
argp += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -330,6 +363,8 @@ void printf(const char* fmt, ...)
|
||||
length = PRINTF_LENGTH_START;
|
||||
radix = 10;
|
||||
sign = false;
|
||||
width = 0;
|
||||
pad_char = ' ';
|
||||
break;
|
||||
}
|
||||
fmt++;
|
||||
@@ -338,14 +373,14 @@ void printf(const char* fmt, ...)
|
||||
|
||||
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];
|
||||
unsigned long long number;
|
||||
int number_sign = 1;
|
||||
int pos = 0;
|
||||
|
||||
switch(length)
|
||||
switch (length)
|
||||
{
|
||||
case PRINTF_LENGTH_SHORT_SHORT:
|
||||
case PRINTF_LENGTH_SHORT:
|
||||
@@ -358,10 +393,11 @@ int* printf_number(int* argp, int length, bool sign, int radix)
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long) n;
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned int*) argp;
|
||||
else
|
||||
{
|
||||
number = *(unsigned int*)argp;
|
||||
}
|
||||
argp++;
|
||||
break;
|
||||
@@ -374,10 +410,11 @@ int* printf_number(int* argp, int length, bool sign, int radix)
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long) n;
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned long int*) argp;
|
||||
else
|
||||
{
|
||||
number = *(unsigned long int*)argp;
|
||||
}
|
||||
argp += 2;
|
||||
break;
|
||||
@@ -390,16 +427,18 @@ int* printf_number(int* argp, int length, bool sign, int radix)
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long) n;
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else {
|
||||
number = *(unsigned long long int*) argp;
|
||||
else
|
||||
{
|
||||
number = *(unsigned long long int*)argp;
|
||||
}
|
||||
argp += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
uint32_t rem;
|
||||
x86_div64_32(number, radix, &number, &rem);
|
||||
buffer[pos++] = charset[rem];
|
||||
@@ -410,6 +449,13 @@ int* printf_number(int* argp, int length, bool sign, int radix)
|
||||
buffer[pos++] = '-';
|
||||
}
|
||||
|
||||
int padding = width - pos;
|
||||
|
||||
while (padding-- > 0)
|
||||
{
|
||||
putc(pad_char);
|
||||
}
|
||||
|
||||
while (--pos >= 0)
|
||||
{
|
||||
putc(buffer[pos]);
|
||||
|
||||
@@ -28,6 +28,7 @@ void colorputc(char c, unsigned int color);
|
||||
#define PRINTF_STATE_SHORT 2
|
||||
#define PRINTF_STATE_LONG 3
|
||||
#define PRINTF_STATE_SPEC 4
|
||||
#define PRINTF_STATE_WIDTH 5
|
||||
|
||||
#define PRINTF_LENGTH_START 0
|
||||
#define PRINTF_LENGTH_SHORT_SHORT 1
|
||||
@@ -36,7 +37,7 @@ void colorputc(char c, unsigned int color);
|
||||
#define PRINTF_LENGTH_LONG_LONG 4
|
||||
|
||||
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();
|
||||
void get_input(char *buffer, int size);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user