Frist Sata push

This commit is contained in:
Yaloalo 2025-03-15 18:51:45 +01:00
parent 5c90823d61
commit ec4c75872c
5 changed files with 422 additions and 478 deletions

View file

@ -11,6 +11,7 @@ KERNEL_SOURCES_x86_64 := \
src/x86_64/uart.c \ src/x86_64/uart.c \
src/x86_64/mem.c \ src/x86_64/mem.c \
src/x86_64/asm.c \ src/x86_64/asm.c \
src/x86_64/sata.c \
# end of x86_64 specific kernel sources list # end of x86_64 specific kernel sources list
# Architecture-agnostic kernel sources. # Architecture-agnostic kernel sources.

View file

@ -0,0 +1,83 @@
#ifndef SATA_H
#define SATA_H
#include <stddef.h>
#include <stdint.h>
#include <sys/io.h>
#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

View file

@ -29,16 +29,18 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "x86_64/mem.h"
#include "x86_64/asm.h"
#include "bootboot.h" #include "bootboot.h"
#include "pci.h" #include "pci.h"
#include "std.h" #include "std.h"
#include "tar.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 */ /* imported virtual addresses, see linker script */
extern BOOTBOOT bootboot; // see bootboot.h extern BOOTBOOT bootboot; // see bootboot.h
extern unsigned char environment[4096]; // configuration, UTF-8 text key=value pairs extern unsigned char
environment[4096]; // configuration, UTF-8 text key=value pairs
extern uint8_t fb; // linear framebuffer mapped extern uint8_t fb; // linear framebuffer mapped
void print_virtio_blk_bars() { void print_virtio_blk_bars() {
@ -60,7 +62,7 @@ void check_initrd() {
putln(); putln();
uint64_t printed_in_line = 0; uint64_t printed_in_line = 0;
for (uint64_t off = 0; off < bootboot.initrd_size; off++) { for (uint64_t off = 0; off < bootboot.initrd_size; off++) {
uint8_t byte = ((uint8_t*)bootboot.initrd_ptr)[off]; uint8_t byte = ((uint8_t *)bootboot.initrd_ptr)[off];
putu8x(byte); putu8x(byte);
putc(' '); putc(' ');
@ -73,12 +75,16 @@ void check_initrd() {
putln(); putln();
} }
/****************************************** SATA_DEVICE list_of_devices[100];
/*:*****************************************
* Entry point, called by BOOTBOOT Loader * * Entry point, called by BOOTBOOT Loader *
******************************************/ ******************************************/
void _start() { void _start() {
/*** NOTE: this code runs on all cores in parallel ***/ /*** NOTE: this code runs on all cores in parallel ***/
int x, y, s = bootboot.fb_scanline, w = bootboot.fb_width, h = bootboot.fb_height; int x, y, s = bootboot.fb_scanline, w = bootboot.fb_width,
h = bootboot.fb_height;
if (s) { if (s) {
// cross-hair to see screen dimension detected correctly // cross-hair to see screen dimension detected correctly
@ -107,22 +113,20 @@ void _start() {
} }
} }
// memory stuff
init_gdt(); init_gdt();
init_idt(); init_idt();
printf("Test after init\n"); __asm__("int $0x80" ::);
// __asm__("int $0x80" :: );
struct tar_header hd; struct tar_header hd;
int res = tar_get_file("hello.txt", &hd); */ int res = tar_get_file("hello.txt", &hd);
ASSERT(res == 1); */ ASSERT(res == 1);
puts(hd.name); */ puts(hd.name);
putu32x(hd.size); */ putu32x(hd.size);
putln(); */ putln();
for (uint64_t i = 0; i < hd.size; i++) { */ for (uint64_t i = 0; i < hd.size; i++) {
putc(((char *)hd.data)[i]); */ putc(((char *)hd.data)[i]);
*/
} }
putln(); putln();

View file

@ -111,9 +111,7 @@ void putc(char c) {
} }
} }
void putln(void) { void putln(void) { putc('\n'); }
putc('\n');
}
void puts(const char *s) { void puts(const char *s) {
while (*s != '\0') { while (*s != '\0') {
@ -143,21 +141,13 @@ void put_charbuf(const char *buf, unsigned int len) {
} \ } \
} while (0) } while (0)
void putu8x(uint8_t value) { void putu8x(uint8_t value) { PUTUXX(2); }
PUTUXX(2);
}
void putu16x(uint16_t value) { void putu16x(uint16_t value) { PUTUXX(4); }
PUTUXX(4);
}
void putu32x(uint32_t value) { void putu32x(uint32_t value) { PUTUXX(8); }
PUTUXX(8);
}
void putu64x(uint64_t value) { void putu64x(uint64_t value) { PUTUXX(16); }
PUTUXX(16);
}
/* --- Number Conversion Functions --- */ /* --- Number Conversion Functions --- */
@ -234,6 +224,7 @@ unsigned int toa_buf_size(unsigned int bits, unsigned int base) {
#define IS_PRINTABLE(c) ((c) >= ' ' && (c) <= '~') #define IS_PRINTABLE(c) ((c) >= ' ' && (c) <= '~')
void printf(const char *format, ...) { void printf(const char *format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
@ -347,7 +338,8 @@ void printf(const char *format, ...) {
} }
/* --- Debug helpers --- */ /* --- Debug helpers --- */
__attribute__((noreturn)) void panic(const char *file, unsigned int line, const char *msg) { __attribute__((noreturn)) void panic(const char *file, unsigned int line,
const char *msg) {
printf("PANIC@%s:%d: %s\n", file, line, msg); printf("PANIC@%s:%d: %s\n", file, line, msg);
while (1) { while (1) {
// loop forever // loop forever

View file

@ -1,125 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <sys/io.h> #include <sys/io.h>
#include <x86_64/sata.h>
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;
uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function,
uint8_t offset) { 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 address); // Write the address to the PCI configuration address port
return inl(0xCFC); // Read the configuration data from the data 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. void debug() {};
// HBA_GHC_AE: Bit 31 when set, AHCI mode is enabled. void debug1() {};
#define HBA_GHC_RESET (1 << 0) void debug2() {};
#define HBA_GHC_AE (1 << 31) void debug3() {};
int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) { int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) {
int array_index = 0; int array_index = 0;
for (int bus = 0; bus < 256; bus++) { for (int bus = 0; bus < 256; bus++) {
@ -149,11 +30,13 @@ int check_PCI_devices(SATA_DEVICE *list_of_devices, int range) {
continue; continue;
} }
uint16_t device_id = (id_val >> 16) & 0xFFFF; uint16_t device_id = (id_val >> 16) & 0xFFFF;
debug1();
// Offset 0x04: Command (lower 16 bits) and Status (upper 16 bits). // Offset 0x04: Command (lower 16 bits) and Status (upper 16 bits).
uint32_t cmd_status = pci_read(bus, device, function, 0x04); uint32_t cmd_status = pci_read(bus, device, function, 0x04);
uint16_t command = cmd_status & 0xFFFF; uint16_t command = cmd_status & 0xFFFF;
uint16_t status = (cmd_status >> 16) & 0xFFFF; uint16_t status = (cmd_status >> 16) & 0xFFFF;
debug2();
// Offset 0x08: Revision ID and Class Codes. // Offset 0x08: Revision ID and Class Codes.
// The 32-bit value at 0x08 has: // 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 master_latency_timer = (misc >> 8) & 0xFF;
uint8_t header_type = (misc >> 16) & 0xFF; uint8_t header_type = (misc >> 16) & 0xFF;
uint8_t bist = (misc >> 24) & 0xFF; uint8_t bist = (misc >> 24) & 0xFF;
debug3();
// Offsets 0x10 - 0x23: BAR0 - BAR4. // Offsets 0x10 - 0x23: BAR0 - BAR4.
uint32_t bars[5]; 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; 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 ports_implemented = hba->pi;
uint32_t number_of_ports = 0; uint32_t number_of_ports = 0;
while (ports_implemented = !0) { while (ports_implemented != 0) {
if (ports_implemented & 1) { if (ports_implemented & 1) {
number_of_ports++; 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;
}