Orion
Barry Keyboard/Mouse drivers + POSIX names for structs 1628fcf (2 years, 4 months ago)/* * This file implements the driver for the Bochs Graphics Adapter video card. * It is a simple card available in virtual machines. It creates a framebuffer * device node, and handles the reading/writing to it, and also mapping the * framebuffer into memory. */ #include <stdint.h> #include <string.h> #include <sys/fb.h> #include "../drivers.h" #include "../pci.h" #include "../../mem/paging.h" #include "../../vfs/vfs.h" #include "../../io.h" size_t bga_write(File *file, char *buf, size_t size, off_t offset); int bga_ioctl(File *file, unsigned long request, uintptr_t argp); void bga_mmap(File *file, void *addr, size_t len, off_t offset); FileOps bgaFileOps = { .write = bga_write, .ioctl = bga_ioctl, .mmap = bga_mmap, }; Driver bgaDriver = { .major = 3, .ops = &bgaFileOps, .next = NULL, }; static uint32_t bgaWidth, bgaHeight, bgaBpp; static uintptr_t lfb; enum BGAIndex { BGA_INDEX_ID, BGA_INDEX_XRES, BGA_INDEX_YRES, BGA_INDEX_BPP, BGA_INDEX_ENABLE, BGA_INDEX_BANK, BGA_INDEX_VIRT_WIDTH, BGA_INDEX_VIRT_HEIGHT, BGA_INDEX_XOFF, BGA_INDEX_YOFF, }; /* Write a BGA register */ void bga_write_register(uint16_t index, uint16_t data) { outw(0x1CE, index); outw(0x1CF, data); } /* Set the video mode */ void bga_set_mode(uint32_t width, uint32_t height, uint32_t bpp) { bgaWidth = width; bgaHeight = height; bgaBpp = bpp; bga_write_register(BGA_INDEX_ENABLE, 0); bga_write_register(BGA_INDEX_XRES, width); bga_write_register(BGA_INDEX_YRES, height); bga_write_register(BGA_INDEX_BPP, bpp); bga_write_register(BGA_INDEX_ENABLE, 1 | 0x40); /* 0x40 for framebuffer */ } /* Initialise the BGA card */ void bga_init(uint8_t bus, uint8_t slot, uint8_t func) { register_driver(&bgaDriver); const int width = 1280; const int height = 720; const int bpp = 32; bga_set_mode(width, height, bpp); lfb = pci_read_dword(bus, slot, func, 0x10) & 0xFFFFFFF0; for (uintptr_t i = 0; i < width*height*(bpp/8); i += 0x1000) *get_page((void *) lfb + i) = (0xFD000000 + i) | PTE_PRESENT | PTE_WRITE | PTE_GLOBAL; /* use the MMAP method to map pages of it into a page dir */ mknod("/dev/fb", S_IFCHR | 0600, MKDEV(bgaDriver.major, 0)); } /* Write to the BGA framebuffer */ size_t bga_write(File *file, char *buf, size_t size, off_t offset) { size_t max, count = 0; page_t oldpg; while (size) { max = (size < 0x1000) ? size : 0x1000; acquire(&quickPageLock); oldpg = quick_page(lfb + PG_ADDR(offset) + count); memcpy(QUICK_PAGE, buf + count, max); quick_page(oldpg); release(&quickPageLock); count += max; size -= max; } return count; } /* Control the BGA framebuffer/device */ int bga_ioctl(File *file, unsigned long request, uintptr_t argp) { FBVarInfo *vinfo; FBFixInfo *finfo; switch (request) { case FBIOGET_VSCREENINFO: vinfo = (void *) argp; vinfo->xres = bgaWidth; vinfo->yres = bgaHeight; vinfo->bpp = bgaBpp; return 0; case FBIOPUT_VSCREENINFO: vinfo = (void *) argp; bga_set_mode(vinfo->xres, vinfo->yres, vinfo->bpp); return 0; case FBIOGET_FSCREENINFO: finfo = (void *) argp; finfo->fbmem = 0xFD000000; // lfb; finfo->fbmemLen = bgaWidth*bgaHeight*(bgaBpp/8); return 0; } } /* Map the linear frame buffer into memory */ void bga_mmap(File *file, void *addr, size_t len, off_t offset) { if (offset >= bgaWidth*bgaHeight*(bgaBpp/8)) return; if (len + offset > bgaWidth*bgaHeight*(bgaBpp/8)) len = (bgaWidth*bgaHeight*(bgaBpp/8)) - offset; page_t *pg, new; size_t max, count = 0; while (len) { max = (len < 0x1000) ? len : 0x1000; pg = get_page(addr + count); new = PG_ATTR(*pg); free_page(pg); alloc_page(pg, PG_ATTR(new), 0xFD000000 + offset + count); count += max; len -= max; } }