#include "bga.h" #include "assert.h" #include "console.h" #include "const.h" #include "global.h" #include "keyboard.h" #include "memman.h" #include "pci.h" #include "proc.h" #include "protect.h" #include "proto.h" #include "stdio.h" #include "string.h" #include "tty.h" #include "type.h" #include "x86.h" #define VBE_DISPI_IOPORT_INDEX 0x01CE #define VBE_DISPI_IOPORT_DATA 0x01CF #define VBE_DISPI_INDEX_ID 0x0 #define VBE_DISPI_INDEX_XRES 0x1 #define VBE_DISPI_INDEX_YRES 0x2 #define VBE_DISPI_INDEX_BPP 0x3 #define VBE_DISPI_INDEX_ENABLE 0x4 #define VBE_DISPI_INDEX_BANK 0x5 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 #define VBE_DISPI_INDEX_X_OFFSET 0x8 #define VBE_DISPI_INDEX_Y_OFFSET 0x9 #define VBE_DISPI_DISABLED 0x00 #define VBE_DISPI_ENABLED 0x01 #define VBE_DISPI_LFB_ENABLED 0x40 static uint16_t bga_screen_width, bga_screen_height; static uint32_t bga_screen_line_size, bga_screen_buffer_size; static uint32_t bga_buf_paddr; static inline void _bga_write_reg(uint16_t cmd, uint16_t data) { outw(VBE_DISPI_IOPORT_INDEX, cmd); outw(VBE_DISPI_IOPORT_DATA, data); } static inline uint16_t _bga_read_reg(uint16_t cmd) { outw(VBE_DISPI_IOPORT_INDEX, cmd); return inw(VBE_DISPI_IOPORT_DATA); } static void _bga_set_resolution(uint16_t width, uint16_t height) { _bga_write_reg(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); _bga_write_reg(VBE_DISPI_INDEX_XRES, width); _bga_write_reg(VBE_DISPI_INDEX_YRES, height); _bga_write_reg(VBE_DISPI_INDEX_VIRT_WIDTH, width); _bga_write_reg(VBE_DISPI_INDEX_VIRT_HEIGHT, (uint16_t)height * 2); _bga_write_reg(VBE_DISPI_INDEX_BPP, 32); _bga_write_reg(VBE_DISPI_INDEX_X_OFFSET, 0); _bga_write_reg(VBE_DISPI_INDEX_Y_OFFSET, 0); _bga_write_reg(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); _bga_write_reg(VBE_DISPI_INDEX_BANK, 0); bga_screen_line_size = (uint32_t)width * 4; } static void bga_set_resolution(uint32_t width, uint32_t height) { _bga_set_resolution(width, height); bga_screen_width = width; bga_screen_height = height; bga_screen_buffer_size = bga_screen_line_size * height * 2; } int bga_ioctl(uintptr_t cmd, uintptr_t arg) { uint32_t y_offset = 0; switch (cmd) { case BGA_GET_HEIGHT: return bga_screen_height; case BGA_GET_WIDTH: return bga_screen_width; case BGA_GET_SCALE: return 1; case BGA_GET_BUFFER: if (arg == 0) return bga_buf_paddr; else return bga_buf_paddr + bga_screen_buffer_size / 2; case BGA_SWAP_BUFFERS: y_offset = bga_screen_height * (arg & 1); _bga_write_reg(VBE_DISPI_INDEX_Y_OFFSET, (uint16_t)y_offset); return 0; case BGA_DISABLE: _bga_write_reg(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED); return 0; case BGA_SET_WIDTH: bga_screen_width = arg; return 0; case BGA_SET_HEIGHT: bga_screen_height = arg; return 0; case BGA_SET_UPDATE: bga_set_resolution(bga_screen_width, bga_screen_height); return 0; default: return -1; } } int init_bga(pci_dev_t *dev) { if (dev->type != DEVICE_DISPLAY) { return -1; } bga_buf_paddr = pci_read_bar(dev, 0) & 0xfffffff0; bga_set_resolution(1024, 768); kprintf("bga buf paddr=%p; buf size= %d KB\n", bga_buf_paddr, bga_screen_buffer_size / 1024); kprintf("bga mapped in kernel cr3=%p\n", read_cr3()); // for (int k = 0; k < bga_screen_buffer_size; k += 4096) { // klin_mapping_phy(bga_buf_paddr + k, bga_buf_paddr + k, // PG_P | PG_USU | PG_RWW, PG_P | PG_USU | PG_RWW); // } // uint32_t *test = (uint32_t *)bga_buf_paddr; // uint32_t *test2 = (uint32_t *)(bga_buf_paddr + bga_screen_buffer_size / 2); // for (int i = 0; i <= 1024 * 20; ++i) test[i] = 0x00ff12; // for (int i = 1024 * 20; i <= 1024 * 40; ++i) test2[i] = 0x0000ff; // while (1) { // bga_ioctl(BGA_SWAP_BUFFERS, 1); // for (volatile int i = 0; i < 0x03ffffff; ++i) // ; // bga_ioctl(BGA_SWAP_BUFFERS, 0); // for (volatile int i = 0; i < 0x03ffffff; ++i) // ; // } return 0; }