~kernel/idt.cr
.cr
Crystal
(text/x-crystal)
require "./vga.cr"

# IDT module
module IDT
  # require "crystal/kernel"  # core types

  IDT_ENTRIES = 256

  # Storage for the IDT entries
  @idt = StaticArray(Entry, IDT_ENTRIES)

  @[Packed]
  struct Entry
    offset_low : UInt16
    selector : UInt16
    ist : UInt8
    type_attr : UInt8
    offset_mid : UInt16
    offset_high : UInt32
    zero : UInt32
  end

  @[Packed]
  struct Ptr
    limit : UInt16
    base : UInt64
  end

  # External functions from assembly
  extern "C" def lidt(ptr : Ptr*): Nil
    {% if flag?(:linux) %}
    {% else %}
    {% end %}
  end

  # IRQ handlers storage
  @irq_handlers = StaticArray(Void*, IDT_ENTRIES)

  extern "C" def isr_handler_common: Nil

  def self.register_irq(irq : Int32, handler : Void*) : Nil
    if irq >= 0 && irq < IDT_ENTRIES
      @irq_handlers[irq] = handler
    end
  end

  def self.init : Nil
    ptr = Ptr.new
    ptr.limit = (IDT_ENTRIES * Entry.size) - 1
    ptr.base = getaddr(&@idt).to_u64
    lidt(&ptr)

    VGA.putd("IDT initialized\n")
  end
end