BigOS/kernel/bga.c
2023-01-15 16:10:09 +08:00

136 lines
4.3 KiB
C

#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;
}