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 := 1029 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) } // TODO : this function is broken GetBARAddr := fn(addr: PCIAddress, index: int): u32 { //bar := config_read32(addr, offsetof(PCIConfigSpace, BAR[index])); bar := config_read32(0, 3, 0, 0) PCI_CONF_BAR_IO := 0 mask := 0xF /* if bar & PCI_CONF_BAR_IO { 0x3 } else { }*/ return bar & (mask ^ 0xFFFFFFFF) } setup_device := fn(svga_dev: ^SVGADevice): void { // TODO: Fix this // refer to https://git.ablecorp.us/able/vmware-svga/src/commit/eea7ddcd0d34702f8f0a33c1933718706c6318c5/lib/refdriver/svga.c#L55 svga_dev.pciAddr = PCIAddress.(0, 3, 0) pci_dev := pci.check_device(0, 3) if pci_dev.device_id.vendor != PCI_VENDOR_ID_VMWARE { log.error("SVGA device not found\0") return } //| pci_dev.device_id.device != PCI_DEVICE_ID_VMWARE_SVGA2 { 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) svga_dev.fbMem = GetBARAddr(svga_dev.pciAddr, 1) // 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, reg.SVGA_REG_WIDTH, svga_dev.width) write_reg(svga_dev, reg.SVGA_REG_HEIGHT, svga_dev.height) write_reg(svga_dev, reg.SVGA_REG_BITS_PER_PIXEL, svga_dev.bpp) 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 }