From d8d17375291f89d37cad43df36c11d9c132e23be Mon Sep 17 00:00:00 2001 From: Marvin Borner Date: Thu, 20 May 2021 22:18:35 +0200 Subject: Added BGA driver and generic FB wrapper --- kernel/Makefile | 2 + kernel/drivers/bga.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++ kernel/drivers/ide.c | 6 +-- kernel/drivers/rtl8139.c | 9 ++-- kernel/drivers/vbe.c | 34 ++++++------- kernel/features/fb.c | 32 ++++++++++++ kernel/features/io.c | 11 ++-- kernel/features/mm.c | 4 +- kernel/inc/drivers/bga.h | 11 ++++ kernel/inc/fb.h | 14 ++++++ 10 files changed, 212 insertions(+), 38 deletions(-) create mode 100644 kernel/drivers/bga.c create mode 100644 kernel/features/fb.c create mode 100644 kernel/inc/drivers/bga.h create mode 100644 kernel/inc/fb.h (limited to 'kernel') diff --git a/kernel/Makefile b/kernel/Makefile index 853f03f..263f08b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -13,6 +13,7 @@ COBJS = entry_asm.o \ drivers/mbr.o \ drivers/ide.o \ drivers/vbe.o \ + drivers/bga.o \ drivers/timer.o \ drivers/vmware.o \ drivers/ps2/ps2.o \ @@ -22,6 +23,7 @@ COBJS = entry_asm.o \ features/fs.o \ features/io.o \ features/bus.o \ + features/fb.o \ features/logger.o \ features/load.o \ features/proc.o \ diff --git a/kernel/drivers/bga.c b/kernel/drivers/bga.c new file mode 100644 index 0000000..2f3b1fa --- /dev/null +++ b/kernel/drivers/bga.c @@ -0,0 +1,127 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BGA_ADDRESS 0x01ce +#define BGA_DATA 0x01cf + +#define BGA_VERSION 0 +#define BGA_XRES 1 +#define BGA_YRES 2 +#define BGA_BPP 3 +#define BGA_ENABLE 4 +#define BGA_BANK 5 +#define BGA_VWIDTH 6 +#define BGA_VHEIGHT 7 +#define BGA_XOFF 8 +#define BGA_YOFF 9 + +#define BGA_LINEAR_FB 0x40 + +#define BGA_V0 0xb0c0 +#define BGA_V1 0xb0c1 +#define BGA_V2 0xb0c2 +#define BGA_V3 0xb0c3 +#define BGA_V4 0xb0c4 +#define BGA_V5 0xb0c5 + +PROTECTED static u32 bga_device_pci = 0; +PROTECTED static struct fb_generic generic = { 0 }; + +CLEAR static void bga_find(u32 device, u16 vendor_id, u16 device_id, void *extra) +{ + if ((vendor_id == 0x1234) && (device_id == 0x1111)) + *((u32 *)extra) = device; +} + +static void bga_write_reg(u16 address, u16 data) +{ + outw(BGA_ADDRESS, address); + outw(BGA_DATA, data); +} + +static u16 bga_read_reg(u16 index) +{ + outw(BGA_ADDRESS, index); + return inw(BGA_DATA); +} + +CLEAR u8 bga_available(void) +{ + pci_scan(&bga_find, -1, &bga_device_pci); + u16 status = bga_read_reg(BGA_VERSION); + return bga_device_pci != 0 && status >= BGA_V0 && status <= BGA_V5; +} + +CLEAR static u32 bga_fb_base(void) +{ + u32 bar0 = pci_read_field(bga_device_pci, PCI_BAR0, 4); + assert(!(bar0 & 7)); // MMIO32 + return bar0 & 0xfffffff0; +} + +// TODO: BGA resolution using control calls +static u32 fb_owner = 0; +static res bga_control(u32 request, void *arg1, void *arg2, void *arg3) +{ + UNUSED(arg3); + + switch (request) { + case IOCTL_FB_GET: { + if (!generic.fb) + return -ENOENT; + + u32 size = MIN(sizeof(generic), (u32)arg2); + if (!memory_writable_range(memory_range(arg1, size))) + return -EFAULT; + + if (fb_owner != 0 && proc_from_pid(fb_owner)) + return -EBUSY; + fb_owner = proc_current()->pid; + + u32 fb = fb_map_buffer(proc_current()->page_dir, &generic); + + stac(); + memcpy(arg1, &generic, size); + ((struct fb_generic *)arg1)->fb = (u8 *)fb; + clac(); + + return EOK; + } + default: + return -EINVAL; + } +} + +CLEAR static void bga_enable(u16 width, u16 height, u16 depth) +{ + bga_write_reg(BGA_ENABLE, 0); + bga_write_reg(BGA_XRES, width); + bga_write_reg(BGA_YRES, height); + bga_write_reg(BGA_BPP, depth); + bga_write_reg(BGA_ENABLE, 1 | BGA_LINEAR_FB); + + generic.pitch = width * (depth >> 3); + generic.bpp = depth; + generic.width = width; + generic.height = height; + generic.fb = (u8 *)bga_fb_base(); + fb_protect(&generic); +} + +CLEAR void bga_install(void) +{ + bga_enable(1920, 1200, 32); + + struct io_dev *dev = zalloc(sizeof(*dev)); + dev->control = bga_control; + io_add(IO_FRAMEBUFFER, dev); +} diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c index 9e09860..324b453 100644 --- a/kernel/drivers/ide.c +++ b/kernel/drivers/ide.c @@ -1,13 +1,13 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include -#include #include -#include +#include #include #include -#include #include +#include +#include #include #include diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c index fdbc0c8..8e7bc88 100644 --- a/kernel/drivers/rtl8139.c +++ b/kernel/drivers/rtl8139.c @@ -2,14 +2,14 @@ // Uses parts of the ToAruOS Project, released under the terms of the NCSA // Copyright (C) 2011-2018 K. Lange -#include #include +#include #include +#include +#include #include #include -#include #include -#include static int rtl_irq = 0; static u8 mac[6] = { 0 }; @@ -77,9 +77,8 @@ void rtl8139_send_packet(void *data, u32 len) static void rtl8139_find(u32 device, u16 vendor_id, u16 device_id, void *extra) { - if ((vendor_id == 0x10ec) && (device_id == 0x8139)) { + if ((vendor_id == 0x10ec) && (device_id == 0x8139)) *((u32 *)extra) = device; - } } static void rtl8139_irq_handler(struct regs *r) diff --git a/kernel/drivers/vbe.c b/kernel/drivers/vbe.c index b384936..fd91062 100644 --- a/kernel/drivers/vbe.c +++ b/kernel/drivers/vbe.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -12,8 +13,6 @@ #include #include -#define FB_SIZE (vbe->height * vbe->pitch) - struct vbe_basic { u8 stuff1[16]; u16 pitch; @@ -24,15 +23,7 @@ struct vbe_basic { u8 stuff3[212]; }; -PROTECTED static struct vbe_basic *vbe = NULL; - -static u32 vbe_map_buffer(struct page_dir *dir) -{ - assert(vbe); - struct memory_range r = - virtual_alloc(dir, memory_range_around((u32)vbe->fb, FB_SIZE), MEMORY_USER); - return r.base; -} +PROTECTED static struct fb_generic generic = { 0 }; static u32 fb_owner = 0; static res vbe_control(u32 request, void *arg1, void *arg2, void *arg3) @@ -41,10 +32,10 @@ static res vbe_control(u32 request, void *arg1, void *arg2, void *arg3) switch (request) { case IOCTL_FB_GET: { - if (!vbe) + if (!generic.fb) return -ENOENT; - u32 size = MIN(sizeof(*vbe), (u32)arg2); + u32 size = MIN(sizeof(generic), (u32)arg2); if (!memory_writable_range(memory_range(arg1, size))) return -EFAULT; @@ -52,11 +43,11 @@ static res vbe_control(u32 request, void *arg1, void *arg2, void *arg3) return -EBUSY; fb_owner = proc_current()->pid; - u32 fb = vbe_map_buffer(proc_current()->page_dir); + u32 fb = fb_map_buffer(proc_current()->page_dir, &generic); stac(); - memcpy(arg1, vbe, size); - ((struct vbe_basic *)arg1)->fb = (u8 *)fb; + memcpy(arg1, &generic, size); + ((struct fb_generic *)arg1)->fb = (u8 *)fb; clac(); return EOK; @@ -68,12 +59,15 @@ static res vbe_control(u32 request, void *arg1, void *arg2, void *arg3) CLEAR void vbe_install(u32 data) { - vbe = (void *)data; + struct vbe_basic *vbe = (void *)data; + generic.bpp = (vbe->pitch / vbe->width) << 3; + generic.pitch = vbe->pitch; + generic.width = vbe->width; + generic.height = vbe->height; + generic.fb = vbe->fb; + fb_protect(&generic); struct io_dev *dev = zalloc(sizeof(*dev)); dev->control = vbe_control; io_add(IO_FRAMEBUFFER, dev); - - // Set framebuffer range used to prevent unwanted writing - physical_set_used(memory_range_around((u32)vbe->fb, FB_SIZE)); } diff --git a/kernel/features/fb.c b/kernel/features/fb.c new file mode 100644 index 0000000..08d99df --- /dev/null +++ b/kernel/features/fb.c @@ -0,0 +1,32 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include +#include +#include +#include +#include +#include + +#define FB_SIZE (generic->height * generic->pitch) + +u32 fb_map_buffer(struct page_dir *dir, struct fb_generic *generic) +{ + struct memory_range r = + virtual_alloc(dir, memory_range_around((u32)generic->fb, FB_SIZE), MEMORY_USER); + return r.base; +} + +CLEAR void fb_protect(struct fb_generic *generic) +{ + physical_set_used(memory_range_around((u32)generic->fb, FB_SIZE)); +} + +CLEAR void fb_install(void) +{ + if (bga_available()) + bga_install(); + else if (multiboot_vbe()) + vbe_install(multiboot_vbe()); + else + panic("No framebuffer driver found!\n"); +} diff --git a/kernel/features/io.c b/kernel/features/io.c index 4bbc4e0..28388ae 100644 --- a/kernel/features/io.c +++ b/kernel/features/io.c @@ -3,12 +3,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -231,18 +233,11 @@ CLEAR void io_install(void) ps2_mouse_install(ps2_mouse); } - /** - * Framebuffer detection - */ - - u32 vbe = multiboot_vbe(); - if (vbe) - vbe_install(vbe); - /** * Other devices */ + fb_install(); timer_install(); logger_install(); bus_install(); diff --git a/kernel/features/mm.c b/kernel/features/mm.c index 81645af..227ba0a 100644 --- a/kernel/features/mm.c +++ b/kernel/features/mm.c @@ -2,10 +2,10 @@ // MIT License, Copyright (c) 2021 Marvin Borner #include -#include #include -#include +#include #include +#include #include #include #include diff --git a/kernel/inc/drivers/bga.h b/kernel/inc/drivers/bga.h new file mode 100644 index 0000000..53c153c --- /dev/null +++ b/kernel/inc/drivers/bga.h @@ -0,0 +1,11 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef BGA_H +#define BGA_H + +#include + +u8 bga_available(void); +void bga_install(void); + +#endif diff --git a/kernel/inc/fb.h b/kernel/inc/fb.h new file mode 100644 index 0000000..0f94b28 --- /dev/null +++ b/kernel/inc/fb.h @@ -0,0 +1,14 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef FB_H +#define FB_H + +#include +#include +#include + +u32 fb_map_buffer(struct page_dir *dir, struct fb_generic *generic); +void fb_protect(struct fb_generic *generic); +void fb_install(void); + +#endif -- cgit v1.2.3