ableos/sysdata/programs/svga_driver/src/device.hb

131 lines
3.3 KiB
Plaintext

stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, log} := stn
pci := @use("../../../libraries/pci/src/lib.hb");
.{PCIAddress, get_ids, config_read32} := pci;
.{dt_get} := @use("../../../libraries/dt_api/src/lib.hb")
reg := @use("./reg.hb")
PCI_VENDOR_ID_VMWARE := 0x15AD
PCI_DEVICE_ID_VMWARE_SVGA2 := 0x405
read_reg := fn(svga_dev: ^SVGADevice, index: u32): u32 {
memory.outl(svga_dev.ioBase, index)
return memory.inl(svga_dev.ioBase + 4)
}
write_reg := fn(svga_dev: ^SVGADevice, index: u32, value: u32): void {
memory.outl(svga_dev.ioBase, index)
memory.outl(svga_dev.ioBase + 4, value)
return
}
FIFO := struct {
reserved_size: u32,
using_bounce_buffer: u8,
//bounce_buffer: [u8; 1024 * 1024],
next_fence: u32,
}
new_fifo := fn(): FIFO {
//bounce_buffer := @as([u8; 1024 * 1024], idk)
/*bounce_buffer,*/
return FIFO.(0, 0, 0)
}
IRQ := struct {
pending: u32,
switchContext: u32,
//IntrContext oldContext;
//IntrContext newContext;
count: u32,
}
new_irq := fn(): IRQ {
return IRQ.(0, 0, 0)
}
SVGADevice := struct {
pciAddr: PCIAddress,
ioBase: u32,
fifoMem: ^u32,
fbMem: ^u8,
fifoSize: int,
fbSize: int,
vramSize: int,
deviceVersionId: int,
capabilities: int,
width: int,
height: int,
bpp: int,
pitch: int,
fifo: FIFO,
irq: IRQ,
}
svga_device := fn(): SVGADevice {
pci_addr := PCIAddress.(0, 0, 0)
fifo := new_fifo()
irq := new_irq()
return SVGADevice.(pci_addr, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, fifo, irq)
}
setup_device := fn(svga_dev: ^SVGADevice): void {
svga_dev.pciAddr = PCIAddress.(0, 2, 0)
pci_id := get_ids(svga_dev.pciAddr.bus, svga_dev.pciAddr.device, svga_dev.pciAddr.function)
if pci_id.vendor != PCI_VENDOR_ID_VMWARE | pci_id.device != PCI_DEVICE_ID_VMWARE_SVGA2 {
log.error("SVGA device not found\0")
return
}
svga_dev.ioBase = config_read32(svga_dev.pciAddr.bus, svga_dev.pciAddr.device, svga_dev.pciAddr.function, 0x10) & 0xFFFFFFF0
write_reg(&svga_dev, reg.SVGA_REG_ENABLE, reg.SVGA_REG_ENABLE_ENABLE)
svga_dev.capabilities = read_reg(&svga_dev, 0x1)
svga_dev.deviceVersionId = read_reg(&svga_dev, 0x2)
// hardcode values for now
svga_dev.width = 1024
svga_dev.height = 768
svga_dev.bpp = 32
svga_dev.pitch = svga_dev.width * 4
svga_dev.fbSize = svga_dev.width * svga_dev.height * svga_dev.bpp / 8
svga_dev.vramSize = read_reg(&svga_dev, 0x10)
log.info("SVGA device initialized successfully\0")
return
}
setup_framebuffer := fn(svga_dev: ^SVGADevice): void {
write_reg(svga_dev, SVGA_REG_WIDTH, svga_dev.width)
write_reg(svga_dev, SVGA_REG_HEIGHT, svga_dev.height)
write_reg(svga_dev, SVGA_REG_BITS_PER_PIXEL, svga_dev.bpp)
// 0x23 is probably framebuffer address idk
svga_dev.fbMem = @as(^u8, read_reg(svga_dev, 0x23))
log.info("Framebuffer setup complete\0")
return
}
draw_pixel := fn(svga_dev: ^SVGADevice, x: int, y: int, color: u32): void {
if x >= svga_dev.width || y >= svga_dev.height {
return // what happens if we write outside here : )
}
offset := y * svga_dev.pitch + x * svga_dev.bpp / 8
mem_addr := svga_dev.fbMem + offset
memory.outl(mem_addr, color)
return
}
clear_screen := fn(svga_dev: ^SVGADevice, color: u32): void {
y := 0
loop if y == svga_dev.height break else {
x := 0
loop if x == svga_dev.width break else {
draw_pixel(svga_dev, x, y, color)
x += 1
}
y += 1
}
return
}