/*
 * @author  xamidev <xamidev@riseup.net>
 * @brief   Kernel global macros
 * @license GPL-3.0-only
 */

#ifndef KERNEL_H
#define KERNEL_H

#include "limine.h"

// Not in POSIX order.
enum ErrorCodes {
	ENOMEM, // No memory
	EIO,    // Input/output error
	ENOENT, // No entry
	EBADFD,  // Bad file descriptor
	EMFILE,  // Too many open files
	EINVAL  // Invalid argument
};

#define CLEAR_INTERRUPTS __asm__ volatile("cli")
#define SET_INTERRUPTS __asm__ volatile("sti")

#include <io/serial/serial.h>
#include <io/term/term.h>
#include <arch/x86.h>
#include <stdbool.h>

extern volatile uint64_t ticks;
#define DEBUG(log, ...) kprintf("[%8u] debug: <%s>: " log "\r\n", ticks, __func__, ##__VA_ARGS__)

/* #define DEBUG(log, ...) \
	printf("debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__); \
	fctprintf((void*)&skputc, 0, "debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__)
 */

#define DIE_DEBUG(str) printf(str)

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);

void panic(struct cpu_status* ctx, const char* str);
void hcf(void);
void idle(void);

void pedicel_main(void* arg);

/* debug */
void debug_stack_trace(unsigned int max_frames);
const char* debug_find_symbol(uintptr_t rip, uintptr_t* offset);
void boot_mem_display(void);

int loader_load_raw();

#define assert(check) do { if(!(check)) hcf(); } while(0)

struct boot_context {
	struct limine_framebuffer* fb;
	struct limine_memmap_response* mmap;
	struct limine_hhdm_response* hhdm;
	struct limine_kernel_address_response* kaddr;
	struct limine_boot_time_response* bootdate;
	struct limine_module_response* module;
};

// Are these modules initialized yet?
struct init_status {
	bool terminal;
	bool serial;
	bool keyboard;
	bool timer;
	bool all;
};

#endif
