Files
KirkOS/src/drivers/fb/fbdev.c
T
2026-05-18 04:02:59 -04:00

129 lines
4.4 KiB
C

#include "libk/debug.h"
#include "libk/errno.h"
#include "fb.h"
#include "fs/vfs.h"
#include "mm/memory.h"
#include "mm/mmap.h"
#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/
#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */
#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */
#define FB_ACTIVATE_MASK 15
#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
#define FB_VMODE_INTERLACED 1 /* interlaced */
#define FB_VMODE_DOUBLE 2 /* double scan */
#define FB_VMODE_ODD_FLD_FIRST 4 /* interlaced: top line first */
#define FB_VMODE_MASK 255
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_TYPE_PLANES 1 /* Non interleaved planes */
#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
#define FB_TYPE_TEXT 3 /* Text/attributes */
#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
#define FB_TYPE_FOURCC 5 /* Type identified by a V4L2 FOURCC */
#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
#define FB_VISUAL_TRUECOLOR 2 /* True color */
#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
#define FB_VISUAL_FOURCC 6 /* Visual identified by a V4L2 FOURCC */
#define FBIOGET_VSCREENINFO 0x4600
#define FBIOPUT_VSCREENINFO 0x4601
#define FBIOGET_FSCREENINFO 0x4602
#define FBIOBLANK 0x4611
static struct fb_var_screeninfo framebuffer_var_info = {0};
static struct fb_fix_screeninfo framebuffer_fix_info = {0};
static struct resource *framebuff_res;
static ssize_t fbdev_write(struct resource *this,
struct f_description *description, const void *buf,
off_t offset, size_t count) {
(void)description;
spinlock_acquire_or_wait(&this->lock);
memcpy((void *)(framebuff.address + offset), buf, count);
spinlock_drop(&this->lock);
return 0;
}
static void *fbdev_mmap(struct resource *this, size_t file_page, int flags) {
(void)flags;
spinlock_acquire_or_wait(&this->lock);
size_t offset = file_page * PAGE_SIZE;
if (offset >= (framebuff.height * framebuff.pitch)) {
return NULL;
}
spinlock_drop(&this->lock);
return (void *)(((uint64_t)(framebuff.address) - MEM_PHYS_OFFSET) + offset);
}
static int fbdev_ioctl(struct resource *this, struct f_description *description,
uint64_t request, uint64_t arg) {
switch (request) {
case FBIOGET_VSCREENINFO:
*(struct fb_var_screeninfo *)arg = framebuffer_var_info;
return 0;
case FBIOGET_FSCREENINFO:
*(struct fb_fix_screeninfo *)arg = framebuffer_fix_info;
return 0;
case FBIOPUT_VSCREENINFO:
spinlock_acquire_or_wait(&this->lock);
framebuffer_var_info = *(struct fb_var_screeninfo *)arg;
spinlock_drop(&this->lock);
return 0;
case FBIOBLANK:
return 0;
}
return resource_default_ioctl(this, description, request, arg);
}
void fbdev_init(void) {
extern uint8_t framebuffer_initialised;
if (!framebuffer_initialised)
return;
framebuffer_fix_info.smem_len = framebuff.pitch * framebuff.height;
framebuffer_fix_info.mmio_len = framebuff.pitch * framebuff.height;
framebuffer_fix_info.line_length = framebuff.pitch;
framebuffer_fix_info.type = FB_TYPE_PACKED_PIXELS;
framebuffer_fix_info.visual = FB_VISUAL_TRUECOLOR;
framebuffer_var_info.xres = framebuff.width;
framebuffer_var_info.yres = framebuff.height;
framebuffer_var_info.xres_virtual = framebuff.width;
framebuffer_var_info.yres_virtual = framebuff.height;
framebuffer_var_info.bits_per_pixel = framebuff.bpp;
framebuffer_var_info.red = framebuff.color_masks[0];
framebuffer_var_info.green = framebuff.color_masks[1];
framebuffer_var_info.blue = framebuff.color_masks[2];
framebuffer_var_info.activate = FB_ACTIVATE_NOW;
framebuffer_var_info.vmode = FB_VMODE_NONINTERLACED;
framebuffer_var_info.width = -1;
framebuffer_var_info.height = -1;
framebuff_res = resource_create(sizeof(struct resource));
framebuff_res->ioctl = fbdev_ioctl;
framebuff_res->write = fbdev_write;
framebuff_res->mmap = fbdev_mmap;
framebuff_res->can_mmap = true;
framebuff_res->stat.st_size = 0;
framebuff_res->stat.st_blocks = 0;
framebuff_res->stat.st_blksize = 4096;
framebuff_res->stat.st_rdev = resource_create_dev_id();
framebuff_res->stat.st_mode = 0666 | S_IFCHR;
devtmpfs_add_device(framebuff_res, "fbdev");
vfs_symlink(vfs_root, "/dev/fbdev", "/dev/fb0");
}