3333#include <kos/anno.h>
3434#include <kos/aref.h>
3535#include <kos/io.h>
36+ #include <kos/ioctl/file.h>
3637#include <kos/ioctl/svga.h>
3738#include <kos/sched/shared-lock.h>
3839#include <kos/types.h>
3940#include <sys/ioctl.h>
41+ #include <sys/mman.h>
4042#include <sys/perm.h>
4143#include <sys/syslog.h>
4244#include <sys/types.h>
6264#include <libvideo/driver/monitor.h>
6365#include <libvideo/gfx/api.h>
6466#include <libvideo/gfx/buffer.h>
65- #include <libvideo/gfx/buffer/rambuffer .h>
67+ #include <libvideo/gfx/buffer/ramfdbuffer .h>
6668#include <libvideo/gfx/codec/codec-extra.h>
6769#include <libvideo/gfx/codec/codec.h>
6870#include <libvideo/gfx/codec/palette.h>
@@ -85,6 +87,28 @@ DECL_BEGIN
8587 syslog(LOG_ERR, "[libvideo-driver,svga.c:%d] " format, __LINE__, ##__VA_ARGS__)
8688
8789
90+ /* Ask the kernel to create a sub-region of "fd" */
91+ PRIVATE WUNUSED fd_t CC
92+ file_newsubregion (fd_t fd ,
93+ /*page-aligned*/ uint64_t minaddr ,
94+ /*page-aligned*/ uint64_t num_bytes ) {
95+ struct file_subregion sr ;
96+ bzero (& sr , sizeof (sr ));
97+ sr .fsr_minaddr = minaddr ;
98+ if (OVERFLOW_UADD (minaddr , num_bytes - 1 , & sr .fsr_maxaddr ))
99+ goto err_range ;
100+ sr .fsr_resfd .of_mode = OPENFD_MODE_AUTO ;
101+ sr .fsr_resfd .of_flags = IO_CLOEXEC ;
102+ if unlikely (ioctl (fd , FILE_IOC_SUBREGION , & sr ) < 0 )
103+ goto err ;
104+ return sr .fsr_resfd .of_hint ;
105+ err_range :
106+ errno = ERANGE ;
107+ err :
108+ return -1 ;
109+ }
110+
111+
88112PRIVATE ATTR_IN (1 ) ATTR_OUT (2 ) void CC
89113modeinfo_to_codecspecs (struct svga_modeinfo const * __restrict modeinfo ,
90114 struct video_codec_specs * __restrict specs ) {
@@ -340,16 +364,6 @@ svga_noop_updaterects(struct video_display *__restrict self,
340364
341365
342366
343- PRIVATE NONNULL ((1 )) void LIBVIDEO_GFX_FCC
344- svga_buffer_destroy (struct video_buffer * __restrict self ) {
345- struct svga_buffer * me = video_buffer_assvga (self );
346- struct svga_adapter * svga = svga_buffer_getadapter (me );
347- (* svga -> sva_libphys_unmap )(me -> rb_data , me -> svb_rb_total );
348- __video_buffer_fini_common (me );
349- free (me );
350- }
351-
352-
353367PRIVATE WUNUSED NONNULL ((1 )) REF struct video_palette * CC
354368svga_palette_new (struct svga_adapter * __restrict self , shift_t colorbits ) {
355369 video_pixel_t i , palsize ;
@@ -388,43 +402,61 @@ svga_palette_new(struct svga_adapter *__restrict self, shift_t colorbits) {
388402PRIVATE WUNUSED ATTR_INOUT (1 ) REF struct svga_buffer * CC
389403svga_newbuffer (struct svga_adapter * __restrict self ) {
390404 REF struct svga_buffer * result ;
391- struct video_buffer_ops const * rambuffer_ops ;
392405 struct svga_modeinfo * modeinfo ;
393406 physaddr_t lfb_addr ;
407+ uintptr_t lfb_offset ;
408+ size_t lfb_size ;
409+ size_t ps = getpagesize (), pm = ps - 1 ;
394410 result = (REF struct svga_buffer * )malloc (sizeof (struct svga_buffer ));
395411 if unlikely (!result )
396412 goto err ;
397413
398- /* Inherit all operators from "rambuffer_ops" by default. */
399- rambuffer_ops = video_rambuffer_ops ();
400- memcpy (& result -> svb_ops , rambuffer_ops , sizeof (struct video_buffer_ops ));
414+ /* Inherit all operators from "rambuffer_ops" by default.
415+ * Note how we use the subregion-variant, since that one
416+ * also supports FD-revocation. Since the FD we're linking
417+ * is actually a sub-region of /dev/mem, it actually can
418+ * be consider a buffer sub-region, too. */
419+ result -> svb_ops = * video_ramfdbuffer_subregion_ops ();
401420
402421 /* Override certain operators */
403- result -> svb_ops .vi_destroy = & svga_buffer_destroy ;
404422 if (self -> sva_cs .sc_modeops .sco_hw_async_copyrect ||
405423 self -> sva_cs .sc_modeops .sco_hw_async_fillrect ) {
406424 /* TODO: Hook into GFX to provide hardware-accelerated fill/blit operators */
407425 }
408426
409427 /* Map LFB for "result" */
410428 modeinfo = self -> sva_modeinfo ;
411- result -> rb_stride = modeinfo -> smi_scanline ;
412- result -> svb_rb_total = modeinfo -> smi_scanline * modeinfo -> smi_resy ;
429+ result -> rb_stride = modeinfo -> smi_scanline ;
430+ result -> rfdb_total = modeinfo -> smi_scanline * modeinfo -> smi_resy ;
431+
432+ /* Determine address of linear frame buffer */
413433 lfb_addr = modeinfo -> smi_lfb ;
414434 if (!(modeinfo -> smi_flags & SVGA_MODEINFO_F_LFB ))
415435 lfb_addr = (physaddr_t )0xA0000 ;
416- result -> rb_data = (byte_t * )(* self -> sva_libphys_map )(lfb_addr , result -> svb_rb_total );
417- if unlikely (result -> rb_data == MAP_FAILED )
436+ lfb_offset = lfb_addr & pm ;
437+ lfb_addr &= ~pm ;
438+ lfb_size = (lfb_offset + result -> rfdb_total + pm ) & ~pm ;
439+
440+ /* Create sub-region of /dev/mem for linear frame buffer */
441+ result -> rfdb_fd = file_newsubregion (self -> sva_devmem , lfb_addr , lfb_size );
442+ if unlikely (result -> rfdb_fd < 0 )
418443 goto err_r ;
419444
445+ /* Map linear frame buffer into memory */
446+ result -> rb_data = (byte_t * )mmap (NULL , result -> rfdb_total , PROT_READ | PROT_WRITE ,
447+ MAP_SHARED | MAP_FILE , result -> rfdb_fd , lfb_offset );
448+ if unlikely (result -> rb_data == MAP_FAILED )
449+ goto err_r_fd ;
450+ assert (((uintptr_t )result -> rb_data & pm ) == lfb_offset );
451+
420452 /* Allocate palette (if necessary) */
421453 result -> vb_surf .vs_flags = VIDEO_GFX_F_NORMAL ;
422454 result -> vb_surf .vs_pal = NULL ;
423455 if (self -> sva_mode .vmm_codec -> vc_specs .vcs_flags & VIDEO_CODEC_FLAG_PAL ) {
424456 shift_t cbits = self -> sva_mode .vmm_codec -> vc_specs .vcs_cbits ;
425457 result -> vb_surf .vs_pal = svga_palette_new (self , cbits );
426458 if unlikely (!result -> vb_surf .vs_pal )
427- goto err_r_data ;
459+ goto err_r_fd_data ;
428460 result -> vb_surf .vs_flags |= VIDEO_GFX_F_PALOBJ ;
429461 }
430462
@@ -437,8 +469,10 @@ svga_newbuffer(struct svga_adapter *__restrict self) {
437469 result -> vb_surf .vs_buffer = result ;
438470 result -> vb_refcnt = 1 ;
439471 return result ;
440- err_r_data :
441- (* self -> sva_libphys_unmap )(result -> rb_data , result -> svb_rb_total );
472+ err_r_fd_data :
473+ (void )munmap (result -> rb_data , result -> rfdb_total );
474+ err_r_fd :
475+ (void )close (result -> rfdb_fd );
442476err_r :
443477 free (result );
444478err :
@@ -590,6 +624,8 @@ INTERN WUNUSED struct svga_adapter *CC
590624svga_tryopen (/*inherited(on_success)*/ fd_t fd ) {
591625 char csname [SVGA_CSNAMELEN ];
592626 struct svga_adapter * result ;
627+ PGETDEVMEM pdyn_getdevmem ;
628+
593629 {
594630 PSVGA_CHIPSET_GETDRIVERS svga_chipset_getdrivers ;
595631 struct svga_chipset_driver const * result__sva_drv ;
@@ -667,14 +703,14 @@ svga_tryopen(/*inherited(on_success)*/ fd_t fd) {
667703 LOGERR ("dlerror: %s\n" , dlerror ());
668704 goto err_r_vdlck_libsvgadrv ;
669705 }
670- * (void * * )& result -> sva_libphys_map = dlsym (result -> sva_libphys , "mmapphys " );
671- if unlikely (!result -> sva_libphys_map ) {
706+ * (void * * )& pdyn_getdevmem = dlsym (result -> sva_libphys , "getdevmem " );
707+ if unlikely (!pdyn_getdevmem ) {
672708 LOGERR ("dlerror: %s\n" , dlerror ());
673709 goto err_r_vdlck_libsvgadrv_libphys ;
674710 }
675- * ( void * * ) & result -> sva_libphys_unmap = dlsym ( result -> sva_libphys , "munmapphys" );
676- if unlikely (! result -> sva_libphys_unmap ) {
677- LOGERR ("dlerror: %s\n" , dlerror () );
711+ result -> sva_devmem = ( * pdyn_getdevmem )( );
712+ if unlikely (result -> sva_devmem < 0 ) {
713+ LOGERR ("Failed to obtain file descriptor for /dev/mem" );
678714 goto err_r_vdlck_libsvgadrv_libphys ;
679715 }
680716
0 commit comments