// SPDX-License-Identifier: MPL-2.0
#ifndef SH_LIB_PEZ_H
#define SH_LIB_PEZ_H
#include "std/type.h"
#include "std/status.h"
#include "memory/slabs/slab_reg_phys.h"
#include "memory/slabs/slab_reg_virt.h"
#include "memory/pez/radix.h"
#define SH_PEZ_REGION_OBJECT_INDEX_SIZE_BYTES 3
// Physical region object
#pragma pack(1)
typedef struct {
  sh_uint32 start_page_index;
  sh_uint32 region_size_pages;
  sh_uint8 next_region_index[3];
  sh_uint8 flags;
} sh_pez_REGION_PHYSICAL_OBJECT;
#pragma pack()
// Virtual region object
#pragma pack(1)
typedef struct {
  sh_uint32 start_page_index;
  sh_uint32 region_size_pages;
  sh_uint32 next_region_index;
} sh_pez_REGION_VIRTUAL_OBJECT;
#pragma pack()
// Physical plane structure
typedef struct {
  sh_uint32 free_pages;
  sh_uint32 used_pages;
  sh_radix_TREE region_radix_tree;
  sh_radix_TREE boundary_radix_tree;
  sh_slab_reg_phys_SLAB_ALLOCATOR *slab_reg_phys;
  struct sh_slab_radix_node_SLAB_ALLOCATOR *slab_radix_node;
  sh_page_PAGE_TABLE_POOL *kernel_ptp;
  sh_uint8 *physical_bitmap;
  sh_uint64 physical_page_count;
} sh_pez_PHYSICAL_PLANE;
// Virtual plane structure
typedef struct {
  sh_uint32 free_pages;
  sh_uint32 used_pages;
  sh_radix_TREE region_radix_tree;
  sh_radix_TREE boundary_radix_tree;
  sh_slab_reg_virt_SLAB_ALLOCATOR *slab_reg_virt;
  struct sh_slab_radix_node_SLAB_ALLOCATOR *slab_radix_node;
  sh_page_PAGE_TABLE_POOL *kernel_ptp;
  sh_page_PAGE_TABLE_POOL *reference_ptp;
  sh_page_VIRTUAL_ADDRESS plane_offset;
} sh_pez_VIRTUAL_PLANE;
// Set Pez state to true
void sh_pez_set_available();
// Return current state of Pez
sh_bool sh_pez_is_available();
// Return reference Pez physical plane
sh_pez_PHYSICAL_PLANE* sh_pez_get_reference_phys_plane();
// Initialize a physical plane
SH_STATUS sh_pez_init_physical_plane(sh_uint8 *physical_bitmap,sh_uint64 physical_page_count,sh_slab_reg_phys_SLAB_ALLOCATOR *slab_reg_phys,struct sh_slab_radix_node_SLAB_ALLOCATOR *slab_radix_node,sh_page_PAGE_TABLE_POOL *kernel_ptp,sh_pez_PHYSICAL_PLANE *phys_plane);
// Allocate physical pages from the physical plane
SH_STATUS sh_pez_alloc_physical_pages(sh_pez_PHYSICAL_PLANE *phys_plane,sh_uint32 pages_count,sh_page_PHYSICAL_ADDRESS *address);
// Free physical pages from the physical plane
SH_STATUS sh_pez_free_physical_pages(sh_pez_PHYSICAL_PLANE *phys_plane,sh_page_PHYSICAL_ADDRESS *address,sh_uint32 pages_count);
// Debug Pez Physical
SH_STATUS sh_pez_debug_physical(sh_pez_PHYSICAL_PLANE *phys_plane);
// Initialize a virtual plane
SH_STATUS sh_pez_init_virtual_plane(sh_page_VIRTUAL_ADDRESS plane_offset,sh_slab_reg_virt_SLAB_ALLOCATOR *slab_reg_virt,struct sh_slab_radix_node_SLAB_ALLOCATOR *slab_radix_node,sh_page_PAGE_TABLE_POOL *kernel_ptp,sh_page_PAGE_TABLE_POOL *reference_ptp,sh_pez_VIRTUAL_PLANE *virt_plane);
// Allocate virtual space from the virtual plane
SH_STATUS sh_pez_alloc_virtual_pages(sh_pez_VIRTUAL_PLANE *virt_plane,sh_uint32 pages_count,sh_page_VIRTUAL_ADDRESS *address);
// Free virtual space from the virtual plane
SH_STATUS sh_pez_free_virtual_pages(sh_pez_VIRTUAL_PLANE *virt_plane,sh_page_VIRTUAL_ADDRESS *address,sh_uint32 pages_count);
#endif
