From ec4c75872c0c637bdadc8efe270580c9fbe152cc Mon Sep 17 00:00:00 2001 From: Yaloalo Date: Sat, 15 Mar 2025 18:51:45 +0100 Subject: [PATCH] Frist Sata push --- Makefile | 1 + include/x86_64/sata.h | 83 +++++++ src/kernel.c | 168 ++++++++------- src/std.c | 490 +++++++++++++++++++++--------------------- src/x86_64/sata.c | 158 +------------- 5 files changed, 422 insertions(+), 478 deletions(-) diff --git a/Makefile b/Makefile index 265c6fe..bf0f76c 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ KERNEL_SOURCES_x86_64 := \ src/x86_64/uart.c \ src/x86_64/mem.c \ src/x86_64/asm.c \ + src/x86_64/sata.c \ # end of x86_64 specific kernel sources list # Architecture-agnostic kernel sources. diff --git a/include/x86_64/sata.h b/include/x86_64/sata.h index e69de29..f158a8f 100644 --- a/include/x86_64/sata.h +++ b/include/x86_64/sata.h @@ -0,0 +1,83 @@ +#ifndef SATA_H +#define SATA_H + +#include +#include +#include + +#define HBA_GHC_RESET (1 << 0) +#define HBA_GHC_AE (1 << 31) + +typedef volatile struct __attribute__((packed)) SATA_DEVICE { + uint16_t vendor_id; + uint16_t device_id; + uint16_t command; + uint16_t status; + uint8_t revision_id; + uint8_t class_code[3]; + uint8_t cache_line_size; + uint8_t master_latency_timer; + uint8_t header_type; + uint8_t bist; + uint32_t bars[5]; + uint32_t abar; + uint32_t reserved0; + uint16_t subsystem_vendor_id; + uint16_t subsystem_id; + uint32_t expansion_rom_base; + uint8_t cap_ptr; + uint8_t reserved1[7]; + uint8_t interrupt_line; + uint8_t interrupt_pin; + uint8_t min_grant; + uint8_t max_latency; +} SATA_DEVICE; + +typedef volatile struct __attribute__((packed)) HBA_PORT { + uint32_t clb; + uint32_t clbu; + uint32_t fb; + uint32_t fbu; + uint32_t is; + uint32_t ie; + uint32_t cmd; + uint32_t reserved0; + uint32_t tfd; + uint32_t sig; + uint32_t ssts; + uint32_t sctl; + uint32_t serr; + uint32_t sact; + uint32_t ci; + uint32_t sntf; + uint32_t fbs; + uint8_t reserved1[0x80 - 0x44]; +} HBA_PORT; + +typedef volatile struct __attribute__((packed)) HBA_MEM { + uint32_t cap; + uint32_t ghc; + uint32_t is; + uint32_t pi; + uint32_t vs; + uint32_t ccc_ctl; + uint32_t ccc_ports; + uint32_t em_loc; + uint32_t em_ctl; + uint32_t cap2; + uint32_t bohc; + uint8_t reserved0[0x60 - 0x2C]; + uint8_t reserved1[0xA0 - 0x60]; + uint8_t vendor[0x100 - 0xA0]; + HBA_PORT ports[32]; +} HBA_MEM; + +/* Function prototypes */ +uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, + uint8_t offset); +int check_PCI_devices(SATA_DEVICE *list_of_devices, int range); +void *map_physical_region(uintptr_t phys_addr, size_t size); +int reset_hba(volatile HBA_MEM *hba); +void check_number_off_active_ports(volatile HBA_MEM *hba); + +#endif // SATA_//H diff --git a/src/kernel.c b/src/kernel.c index 7748d6d..f5b0b8a 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -29,120 +29,124 @@ #include #include -#include "x86_64/mem.h" -#include "x86_64/asm.h" #include "bootboot.h" #include "pci.h" #include "std.h" #include "tar.h" +#include "x86_64/asm.h" +#include "x86_64/mem.h" +#include "x86_64/sata.h" /* imported virtual addresses, see linker script */ extern BOOTBOOT bootboot; // see bootboot.h -extern unsigned char environment[4096]; // configuration, UTF-8 text key=value pairs -extern uint8_t fb; // linear framebuffer mapped +extern unsigned char + environment[4096]; // configuration, UTF-8 text key=value pairs +extern uint8_t fb; // linear framebuffer mapped void print_virtio_blk_bars() { - uint16_t bdf; - if (pci_search(0x1AF4, 0x1001, &bdf) && pci_search(0x1AF4, 0x1042, &bdf)) { - PANIC("couldn't find virtio_blk device!"); - } - puts("found virtio_blk device at bdf "); - putu16x(bdf); - printf(".\n"); - // read BARs - for (int i = 0; i < 6; i++) { - struct pci_bar_desc desc = pci_bar_desc_read(bdf, i); - pci_bar_desc_print(&desc); - } + uint16_t bdf; + if (pci_search(0x1AF4, 0x1001, &bdf) && pci_search(0x1AF4, 0x1042, &bdf)) { + PANIC("couldn't find virtio_blk device!"); + } + puts("found virtio_blk device at bdf "); + putu16x(bdf); + printf(".\n"); + // read BARs + for (int i = 0; i < 6; i++) { + struct pci_bar_desc desc = pci_bar_desc_read(bdf, i); + pci_bar_desc_print(&desc); + } } void check_initrd() { - putln(); - uint64_t printed_in_line = 0; - for (uint64_t off = 0; off < bootboot.initrd_size; off++) { - uint8_t byte = ((uint8_t*)bootboot.initrd_ptr)[off]; + putln(); + uint64_t printed_in_line = 0; + for (uint64_t off = 0; off < bootboot.initrd_size; off++) { + uint8_t byte = ((uint8_t *)bootboot.initrd_ptr)[off]; - putu8x(byte); - putc(' '); + putu8x(byte); + putc(' '); - if (++printed_in_line % 32 == 0) { - printed_in_line = 0; - putln(); - } + if (++printed_in_line % 32 == 0) { + printed_in_line = 0; + putln(); } - putln(); + } + putln(); } -/****************************************** +SATA_DEVICE list_of_devices[100]; + +/*:***************************************** * Entry point, called by BOOTBOOT Loader * ******************************************/ void _start() { - /*** NOTE: this code runs on all cores in parallel ***/ - int x, y, s = bootboot.fb_scanline, w = bootboot.fb_width, h = bootboot.fb_height; - if (s) { - // cross-hair to see screen dimension detected correctly - for (y = 0; y < h; y++) { - *((uint32_t *)(&fb + s * y + (w * 2))) = 0x000FFFFF; - } - for (x = 0; x < w; x++) { - *((uint32_t *)(&fb + s * (h / 2) + x * 4)) = 0x00FFFFFF; - } + /*** NOTE: this code runs on all cores in parallel ***/ + int x, y, s = bootboot.fb_scanline, w = bootboot.fb_width, + h = bootboot.fb_height; - // red, green, blue boxes in order - for (y = 0; y < 20; y++) { - for (x = 0; x < 20; x++) { - *((uint32_t *)(&fb + s * (y + 20) + (x + 20) * 4)) = 0x00FF0000; - } - } - for (y = 0; y < 20; y++) { - for (x = 0; x < 20; x++) { - *((uint32_t *)(&fb + s * (y + 20) + (x + 50) * 4)) = 0x0000FF00; - } - } - for (y = 0; y < 20; y++) { - for (x = 0; x < 20; x++) { - *((uint32_t *)(&fb + s * (y + 20) + (x + 80) * 4)) = 0x000000FF; - } - } + if (s) { + // cross-hair to see screen dimension detected correctly + for (y = 0; y < h; y++) { + *((uint32_t *)(&fb + s * y + (w * 2))) = 0x000FFFFF; + } + for (x = 0; x < w; x++) { + *((uint32_t *)(&fb + s * (h / 2) + x * 4)) = 0x00FFFFFF; } - // memory stuff - init_gdt(); - init_idt(); - - printf("Test after init\n"); - - // __asm__("int $0x80" :: ); - - struct tar_header hd; - int res = tar_get_file("hello.txt", &hd); - ASSERT(res == 1); - puts(hd.name); - putu32x(hd.size); - putln(); - for (uint64_t i = 0; i < hd.size; i++) { - putc(((char *)hd.data)[i]); + // red, green, blue boxes in order + for (y = 0; y < 20; y++) { + for (x = 0; x < 20; x++) { + *((uint32_t *)(&fb + s * (y + 20) + (x + 20) * 4)) = 0x00FF0000; + } } - putln(); + for (y = 0; y < 20; y++) { + for (x = 0; x < 20; x++) { + *((uint32_t *)(&fb + s * (y + 20) + (x + 50) * 4)) = 0x0000FF00; + } + } + for (y = 0; y < 20; y++) { + for (x = 0; x < 20; x++) { + *((uint32_t *)(&fb + s * (y + 20) + (x + 80) * 4)) = 0x000000FF; + } + } + } - // hang for now - PANIC("end of kernel"); + init_gdt(); + init_idt(); + + __asm__("int $0x80" ::); + + struct tar_header hd; + */ int res = tar_get_file("hello.txt", &hd); + */ ASSERT(res == 1); + */ puts(hd.name); + */ putu32x(hd.size); + */ putln(); + */ for (uint64_t i = 0; i < hd.size; i++) { + */ putc(((char *)hd.data)[i]); + */ + } + putln(); + + // hang for now + PANIC("end of kernel"); } /************************** * Display text on screen * **************************/ typedef struct { - uint32_t magic; - uint32_t version; - uint32_t headersize; - uint32_t flags; - uint32_t numglyph; - uint32_t bytesperglyph; - uint32_t height; - uint32_t width; - uint8_t glyphs; + uint32_t magic; + uint32_t version; + uint32_t headersize; + uint32_t flags; + uint32_t numglyph; + uint32_t bytesperglyph; + uint32_t height; + uint32_t width; + uint8_t glyphs; } __attribute__((packed)) psf2_t; extern volatile unsigned char _binary_font_psf_start; diff --git a/src/std.c b/src/std.c index 9df9dfa..84d94aa 100644 --- a/src/std.c +++ b/src/std.c @@ -8,77 +8,77 @@ /* --- Memory Functions --- */ void *memset(void *ptr, int value, size_t num) { - unsigned char *byte_ptr = (unsigned char *)ptr; - for (size_t i = 0; i < num; i++) { - byte_ptr[i] = (unsigned char)value; - } - return ptr; + unsigned char *byte_ptr = (unsigned char *)ptr; + for (size_t i = 0; i < num; i++) { + byte_ptr[i] = (unsigned char)value; + } + return ptr; } void *memcpy(void *dest, const void *src, size_t n) { - unsigned char *d = (unsigned char *)dest; - const unsigned char *s = (const unsigned char *)src; - for (size_t i = 0; i < n; i++) { - d[i] = s[i]; - } - return dest; + unsigned char *d = (unsigned char *)dest; + const unsigned char *s = (const unsigned char *)src; + for (size_t i = 0; i < n; i++) { + d[i] = s[i]; + } + return dest; } int memcmp(const void *ptr, const void *ptr2, size_t num) { - unsigned char *d = (unsigned char *)ptr; - unsigned char *b = (unsigned char *)ptr2; - for (size_t i = 0; i < num; i++) { - if (d[i] != b[i]) { - return (d[i] - b[i]); - } + unsigned char *d = (unsigned char *)ptr; + unsigned char *b = (unsigned char *)ptr2; + for (size_t i = 0; i < num; i++) { + if (d[i] != b[i]) { + return (d[i] - b[i]); } - return 0; + } + return 0; } void *memmove(void *dest, const void *src, size_t num) { - unsigned char *d = (unsigned char *)dest; - const unsigned char *s = (const unsigned char *)src; - if (d < s || d >= (s + num)) { - for (size_t i = 0; i < num; i++) { - d[i] = s[i]; - } - } else { - for (size_t i = num; i > 0; i--) { - d[i - 1] = s[i - 1]; - } + unsigned char *d = (unsigned char *)dest; + const unsigned char *s = (const unsigned char *)src; + if (d < s || d >= (s + num)) { + for (size_t i = 0; i < num; i++) { + d[i] = s[i]; } - return dest; + } else { + for (size_t i = num; i > 0; i--) { + d[i - 1] = s[i - 1]; + } + } + return dest; } /* --- String functions --- */ unsigned int strlen(const char *s) { - unsigned int len = 0; - while (*s != '\0') { - s++; - len++; - } - return len; + unsigned int len = 0; + while (*s != '\0') { + s++; + len++; + } + return len; } bool streq(const char *a, const char *b) { - while (*a != '\0' && *b != '\0') { - if (*a != *b) { - return false; - } - a++; - b++; + while (*a != '\0' && *b != '\0') { + if (*a != *b) { + return false; } - // must have same length - return *a == '\0' && *b == '\0'; + a++; + b++; + } + // must have same length + return *a == '\0' && *b == '\0'; } bool strcontains(const char *s, char c) { - while (*s != '\0') { - if (*s++ == c) { - return true; - } + while (*s != '\0') { + if (*s++ == c) { + return true; } - return false; + } + return false; } /* --- Line buffering --- */ @@ -87,77 +87,67 @@ static char linebuf[BUFFER_SIZE]; static unsigned int current_buffer_position = 0; static void linebuf_flush(void) { - for (unsigned int i = 0; i < current_buffer_position; i++) { - uart_write_char(linebuf[i]); - } - current_buffer_position = 0; + for (unsigned int i = 0; i < current_buffer_position; i++) { + uart_write_char(linebuf[i]); + } + current_buffer_position = 0; } static void linebuf_putc(char c) { - if (current_buffer_position == BUFFER_SIZE) { - linebuf_flush(); - } - linebuf[current_buffer_position++] = c; + if (current_buffer_position == BUFFER_SIZE) { + linebuf_flush(); + } + linebuf[current_buffer_position++] = c; } /* --- Low-level output functions --- */ void putc(char c) { - if (c == '\n') { - linebuf_putc('\r'); - linebuf_putc('\n'); - linebuf_flush(); - } else { - linebuf_putc(c); - } + if (c == '\n') { + linebuf_putc('\r'); + linebuf_putc('\n'); + linebuf_flush(); + } else { + linebuf_putc(c); + } } -void putln(void) { - putc('\n'); -} +void putln(void) { putc('\n'); } void puts(const char *s) { - while (*s != '\0') { - putc(*s++); - } + while (*s != '\0') { + putc(*s++); + } } void putsln(const char *s) { - puts(s); - putln(); + puts(s); + putln(); } void put_charbuf(const char *buf, unsigned int len) { - for (unsigned int i = 0; i < len; i++) { - putc(buf[i]); - } + for (unsigned int i = 0; i < len; i++) { + putc(buf[i]); + } } #define TO_HEX(n) ((n) < 10 ? (n) + '0' : (n) - 10 + 'a') -#define PUTUXX(nd) \ - do { \ - putc('0'); \ - putc('x'); \ - for (int i = 0; i < nd; i++) { \ - uint8_t hexval = (value >> ((((nd) - 1) - i) << 2)) & 0xf; \ - putc(TO_HEX(hexval)); \ - } \ - } while (0) +#define PUTUXX(nd) \ + do { \ + putc('0'); \ + putc('x'); \ + for (int i = 0; i < nd; i++) { \ + uint8_t hexval = (value >> ((((nd) - 1) - i) << 2)) & 0xf; \ + putc(TO_HEX(hexval)); \ + } \ + } while (0) -void putu8x(uint8_t value) { - PUTUXX(2); -} +void putu8x(uint8_t value) { PUTUXX(2); } -void putu16x(uint16_t value) { - PUTUXX(4); -} +void putu16x(uint16_t value) { PUTUXX(4); } -void putu32x(uint32_t value) { - PUTUXX(8); -} +void putu32x(uint32_t value) { PUTUXX(8); } -void putu64x(uint64_t value) { - PUTUXX(16); -} +void putu64x(uint64_t value) { PUTUXX(16); } /* --- Number Conversion Functions --- */ @@ -166,190 +156,192 @@ void putu64x(uint64_t value) { /* Converts an int value to a string in a given base */ void itoa(int value, unsigned int base, char *buffer) { - itoa_ll(value, base, buffer); + itoa_ll(value, base, buffer); } /* Converts an unsigned int value to a string in a given base */ void utoa(unsigned int value, unsigned int base, char *buffer) { - utoa_ll(value, base, buffer); + utoa_ll(value, base, buffer); } /* Converts a long long value to a string in a given base */ void itoa_ll(long long value, unsigned int base, char *buffer) { - bool is_negative = false; - unsigned long long uvalue; - if (base == 10 && value < 0) { - is_negative = true; - uvalue = -value; - } else { - uvalue = value; - } + bool is_negative = false; + unsigned long long uvalue; + if (base == 10 && value < 0) { + is_negative = true; + uvalue = -value; + } else { + uvalue = value; + } - if (is_negative) { - buffer[0] = '-'; - utoa_ll(uvalue, base, buffer + 1); - } else { - utoa_ll(uvalue, base, buffer); - } + if (is_negative) { + buffer[0] = '-'; + utoa_ll(uvalue, base, buffer + 1); + } else { + utoa_ll(uvalue, base, buffer); + } } /* Converts an unsigned long long value to a string in a given base */ void utoa_ll(unsigned long long value, unsigned int base, char *buffer) { - char temp[TOA_MAX_BUF_SIZE]; - int index = 0; - if (value == 0) { - temp[index++] = '0'; - } else { - while (value > 0) { - unsigned int digit = value % base; - temp[index++] = "0123456789ABCDEF"[digit]; - value /= base; - } + char temp[TOA_MAX_BUF_SIZE]; + int index = 0; + if (value == 0) { + temp[index++] = '0'; + } else { + while (value > 0) { + unsigned int digit = value % base; + temp[index++] = "0123456789ABCDEF"[digit]; + value /= base; } - int out_index = 0; - for (int i = index - 1; i >= 0; i--) { - buffer[out_index++] = temp[i]; - } - buffer[out_index] = '\0'; + } + int out_index = 0; + for (int i = index - 1; i >= 0; i--) { + buffer[out_index++] = temp[i]; + } + buffer[out_index] = '\0'; } /* --- Helper Functions --- */ unsigned int toa_buf_size(unsigned int bits, unsigned int base) { - unsigned int sz; - if (base == 2) { - sz = bits; // Binary: 1 symbol per bit - } else if (base == 8) { - sz = (bits + 2) / 3; // Octal: 3 bits per digit - } else if (base == 16) { - sz = (bits + 3) / 4; // Hex: 4 bits per digit - } else if (base == 10) { - sz = (bits * 30103) / 100000 + 1; // Approximate log10(2) ≈ 0.30103 - } else { - UNREACHABLE(); - } - return sz + 1; // null byte inclusive + unsigned int sz; + if (base == 2) { + sz = bits; // Binary: 1 symbol per bit + } else if (base == 8) { + sz = (bits + 2) / 3; // Octal: 3 bits per digit + } else if (base == 16) { + sz = (bits + 3) / 4; // Hex: 4 bits per digit + } else if (base == 10) { + sz = (bits * 30103) / 100000 + 1; // Approximate log10(2) ≈ 0.30103 + } else { + UNREACHABLE(); + } + return sz + 1; // null byte inclusive } /* --- Custom printf Implementation --- */ #define IS_PRINTABLE(c) ((c) >= ' ' && (c) <= '~') void printf(const char *format, ...) { - va_list args; - va_start(args, format); - while (*format) { - if (*format == '%') { - format++; - bool do_number = false; - int number_size_bits = 32; - char number_buffer[TOA_MAX_BUF_SIZE + 1]; - char base; - bool sign; - // Check for length modifiers: - switch (*format) { - case 'h': - do_number = true; - number_size_bits = 16; // 16-bit (promoted to int in varargs) - format++; - break; - case 'l': - do_number = true; - number_size_bits = 64; // 64-bit - format++; - break; - default: - break; - } - if (do_number && !strcontains("duxob", *format)) { - PANIC("printf: expected number format specifier after %h or %l"); - } + va_list args; + va_start(args, format); - switch (*format) { - case 'd': - do_number = true; - base = 10; - sign = true; - break; - case 'u': - do_number = true; - base = 10; - sign = false; - break; - case 'x': - do_number = true; - base = 16; - sign = false; - break; - case 'o': - do_number = true; - base = 8; - sign = false; - case 'b': - do_number = true; - base = 2; - sign = false; - break; - case 'c': { - char ch = (char)va_arg(args, int); - putc(ch); - break; - } - case 's': { - char *str = va_arg(args, char *); - puts(str); - break; - } - case 'p': { - void *ptr = va_arg(args, void *); - putu64x((uint64_t)(intptr_t)ptr); - break; - } - case '%': { - putc('%'); - break; - } - default: { - PANIC("printf: unsupported format specifier"); - break; - } - } - if (do_number) { - if (number_size_bits == 64) { - long long value = va_arg(args, long long); - if (sign) { - itoa_ll(value, base, number_buffer); - } else { - utoa_ll((unsigned long long)value, base, number_buffer); - } - } else { - int value = va_arg(args, int); - if (sign) { - itoa(value, base, number_buffer); - } else { - utoa((unsigned int)value, base, number_buffer); - } - } - puts(number_buffer); - } - format++; - } else if (IS_PRINTABLE(*format) || *format == '\n') { - putc(*format); - format++; + while (*format) { + if (*format == '%') { + format++; + bool do_number = false; + int number_size_bits = 32; + char number_buffer[TOA_MAX_BUF_SIZE + 1]; + char base; + bool sign; + // Check for length modifiers: + switch (*format) { + case 'h': + do_number = true; + number_size_bits = 16; // 16-bit (promoted to int in varargs) + format++; + break; + case 'l': + do_number = true; + number_size_bits = 64; // 64-bit + format++; + break; + default: + break; + } + if (do_number && !strcontains("duxob", *format)) { + PANIC("printf: expected number format specifier after %h or %l"); + } + + switch (*format) { + case 'd': + do_number = true; + base = 10; + sign = true; + break; + case 'u': + do_number = true; + base = 10; + sign = false; + break; + case 'x': + do_number = true; + base = 16; + sign = false; + break; + case 'o': + do_number = true; + base = 8; + sign = false; + case 'b': + do_number = true; + base = 2; + sign = false; + break; + case 'c': { + char ch = (char)va_arg(args, int); + putc(ch); + break; + } + case 's': { + char *str = va_arg(args, char *); + puts(str); + break; + } + case 'p': { + void *ptr = va_arg(args, void *); + putu64x((uint64_t)(intptr_t)ptr); + break; + } + case '%': { + putc('%'); + break; + } + default: { + PANIC("printf: unsupported format specifier"); + break; + } + } + if (do_number) { + if (number_size_bits == 64) { + long long value = va_arg(args, long long); + if (sign) { + itoa_ll(value, base, number_buffer); + } else { + utoa_ll((unsigned long long)value, base, number_buffer); + } } else { - // we disallow everything else for now (including \r, \t) - putc('['); - putu8x(*format); - putc(']'); - format++; + int value = va_arg(args, int); + if (sign) { + itoa(value, base, number_buffer); + } else { + utoa((unsigned int)value, base, number_buffer); + } } + puts(number_buffer); + } + format++; + } else if (IS_PRINTABLE(*format) || *format == '\n') { + putc(*format); + format++; + } else { + // we disallow everything else for now (including \r, \t) + putc('['); + putu8x(*format); + putc(']'); + format++; } - va_end(args); + } + va_end(args); } /* --- Debug helpers --- */ -__attribute__((noreturn)) void panic(const char *file, unsigned int line, const char *msg) { - printf("PANIC@%s:%d: %s\n", file, line, msg); - while (1) { - // loop forever - } +__attribute__((noreturn)) void panic(const char *file, unsigned int line, + const char *msg) { + printf("PANIC@%s:%d: %s\n", file, line, msg); + while (1) { + // loop forever + } } diff --git a/src/x86_64/sata.c b/src/x86_64/sata.c index 0299b4e..f022fa1 100644 --- a/src/x86_64/sata.c +++ b/src/x86_64/sata.c @@ -1,125 +1,7 @@ - #include #include #include - -typedef volatile struct __attribute__((packed)) SATA_DEVICE { - // 0x00 - 0x03: ID Identifiers (Vendor ID and Device ID) - uint16_t vendor_id; // 0x00-0x01: Vendor ID - uint16_t device_id; // 0x02-0x03: Device ID - - // 0x04 - 0x05: Command Register - uint16_t command; // 0x04-0x05 - - // 0x06 - 0x07: Status Register - uint16_t status; // 0x06-0x07 - - // 0x08: Revision ID - uint8_t revision_id; // 0x08 - - // 0x09 - 0x0B: Class Codes (3 bytes) - uint8_t class_code[3]; // 0x09-0x0B - - // 0x0C: Cache Line Size - uint8_t cache_line_size; // 0x0C - - // 0x0D: Master Latency Timer - uint8_t master_latency_timer; // 0x0D - - // 0x0E: Header Type - uint8_t header_type; // 0x0E - - // 0x0F: Built-in Self Test (BIST) - uint8_t bist; // 0x0F - - // 0x10 - 0x23: Base Address Registers (BAR0 - BAR4) - uint32_t bars[5]; // 5 * 4 bytes = 20 bytes - - // 0x24 - 0x27: AHCI Base Address Register (BAR5) - uint32_t abar; // 0x24-0x27 - - // 0x28 - 0x2B: Reserved (typically unused) - uint32_t reserved0; // 0x28-0x2B - - // 0x2C - 0x2F: Subsystem Identifiers - // Standard PCI header splits these into Subsystem Vendor ID and Subsystem ID. - uint16_t subsystem_vendor_id; // 0x2C-0x2D: Subsystem Vendor ID - uint16_t subsystem_id; // 0x2E-0x2F: Subsystem ID - - // 0x30 - 0x33: Expansion ROM Base Address (Optional) - uint32_t expansion_rom_base; // 0x30-0x33 - - // 0x34: Capabilities Pointer - uint8_t cap_ptr; // 0x34 - - // 0x35 - 0x3B: Reserved - uint8_t reserved1[7]; // 0x35-0x3B - - // 0x3C - 0x3D: Interrupt Information - // Typically split into Interrupt Line and Interrupt Pin. - uint8_t interrupt_line; // 0x3C - uint8_t interrupt_pin; // 0x3D - - // 0x3E: Min Grant (Optional) - uint8_t min_grant; // 0x3E - - // 0x3F: Max Latency (Optional) - uint8_t max_latency; // 0x3F -} SATA_DEVICE; - -typedef struct { - volatile HBA_MEM *hbaMem; // Pointer to the complete HBA memory block. - volatile HBA_PORT *ports; // Pointer to the port control registers block. -} HBA_MMAP; - -// Port for each device connected to the HBA device -typedef volatile struct __attribute__((packed)) HBA_PORT { - uint32_t clb; // 0x00: Command List Base Address - uint32_t clbu; // 0x04: Command List Base Address Upper 32 bits (if needed) - uint32_t fb; // 0x08: FIS Base Address - uint32_t fbu; // 0x0C: FIS Base Address Upper 32 bits (if needed) - uint32_t is; // 0x10: Interrupt Status - uint32_t ie; // 0x14: Interrupt Enable - uint32_t cmd; // 0x18: Command and Status - uint32_t reserved0; // 0x1C: Reserved - uint32_t tfd; // 0x20: Task File Data - uint32_t sig; // 0x24: Signature (to identify the type of device connected) - uint32_t ssts; // 0x28: SATA Status (SSTS) - uint32_t sctl; // 0x2C: SATA Control (SCTL) - uint32_t serr; // 0x30: SATA Error (SERR) - uint32_t sact; // 0x34: SATA Active (SACT) - uint32_t ci; // 0x38: Command Issue (CI) - uint32_t sntf; // 0x3C: SATA Notification (SNTF) - uint32_t fbs; // 0x40: FIS-Based Switching control (if supported) - // Padding to ensure the entire port register block is 0x80 bytes in size: - uint8_t reserved1[0x80 - 0x44]; // 0x44 to 0x7F reserved -} HBA_PORT; - -// Global registers vor the HBA controller -typedef volatile struct __attribute__((packed)) HBA_MEM { - uint32_t cap; // 0x00: Host Capabilities - uint32_t ghc; // 0x04: Global Host Control - uint32_t is; // 0x08: Interrupt Status - uint32_t pi; // 0x0C: Ports Implemented (bitmask indicating active ports) - uint32_t vs; // 0x10: Version - uint32_t ccc_ctl; // 0x14: Command Completion Coalescing Control - uint32_t ccc_ports; // 0x18: Command Completion Coalescing Ports - uint32_t em_loc; // 0x1C: Enclosure Management Location - uint32_t em_ctl; // 0x20: Enclosure Management Control - uint32_t cap2; // 0x24: Host Capabilities Extended - uint32_t bohc; // 0x28: BIOS/OS Handoff Control and Status - - // Reserved regions - uint8_t reserved0[0x60 - 0x2C]; // 0x2C - 0x5F: Reserved - uint8_t reserved1[0xA0 - 0x60]; // 0x60 - 0x9F: Reserved for NVMHCI - uint8_t vendor[0x100 - 0xA0]; // 0xA0 - 0xFF: Vendor Specific Registers - - // Port Control Registers - // Starting at 0x100, each port has a control register block (typically 0x80 - // bytes per port) - HBA_PORT ports[32]; // Maximum of 32 ports; the 'pi' field in the global - // registers indicates which are active -} HBA_MEM; +#include uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { @@ -129,11 +11,10 @@ uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, address); // Write the address to the PCI configuration address port return inl(0xCFC); // Read the configuration data from the data port } -// HBA_GHC_RESET: Bit 0 – when set, the HBA begins a global reset. -// HBA_GHC_AE: Bit 31 – when set, AHCI mode is enabled. -#define HBA_GHC_RESET (1 << 0) -#define HBA_GHC_AE (1 << 31) - +void debug() {}; +void debug1() {}; +void debug2() {}; +void debug3() {}; int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) { int array_index = 0; for (int bus = 0; bus < 256; bus++) { @@ -149,11 +30,13 @@ int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) { continue; } uint16_t device_id = (id_val >> 16) & 0xFFFF; + debug1(); // Offset 0x04: Command (lower 16 bits) and Status (upper 16 bits). uint32_t cmd_status = pci_read(bus, device, function, 0x04); uint16_t command = cmd_status & 0xFFFF; uint16_t status = (cmd_status >> 16) & 0xFFFF; + debug2(); // Offset 0x08: Revision ID and Class Codes. // The 32-bit value at 0x08 has: @@ -186,6 +69,7 @@ int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) { uint8_t master_latency_timer = (misc >> 8) & 0xFF; uint8_t header_type = (misc >> 16) & 0xFF; uint8_t bist = (misc >> 24) & 0xFF; + debug3(); // Offsets 0x10 - 0x23: BAR0 - BAR4. uint32_t bars[5]; @@ -263,6 +147,7 @@ int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) { list_of_devices[array_index++] = dev; } + debug(); } } } @@ -306,31 +191,10 @@ void check_number_off_active_ports(volatile HBA_MEM *hba) { uint32_t ports_implemented = hba->pi; uint32_t number_of_ports = 0; - while (ports_implemented = !0) { + while (ports_implemented != 0) { if (ports_implemented & 1) { number_of_ports++; } - ports_implemented >> 1; + // ports_implemented << 1; } } - -int main() { - if (ioperm(0xCF8, 8, 1)) { - perror("ioperm"); - return 1; - } - - SATA_DEVICE list_of_devices[100]; - int device_count = check_PCI_devices(list_of_devices, 100); - printf("\nFound %d SATA device(s).\n\n", device_count); - - // Map Registers from the active ports into memorz - // CommandList - // CommandTable - // FIS receive area - // Configure Ports - // Issue commands via CommndList and Table - // Use DMA and via PRDT to send and recieve data - - return 0; -}