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)
|
- 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
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 "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;
|
||||||
|
|
||||||
|
|||||||
378
src/libc/stdio.c
378
src/libc/stdio.c
@@ -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()
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user