Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Jun 2017 09:51:40 -0700
From:      Aaron Plattner <aplattner@nvidia.com>
To:        <freebsd-hackers@freebsd.org>
Subject:   efifb framebuffer info for NVIDIA driver console restore
Message-ID:  <c84970b6-6e70-2648-a711-57753696b2b0@nvidia.com>

next in thread | raw e-mail | index | archive | help
Hi FreeBSD hackers,

My name is Aaron Plattner. I'm a driver developer at NVIDIA working on
the FreeBSD driver, among other things. I was hoping you could help me
out regarding some changes I've been making to the driver.

Recently, we've revamped how our driver handles switching from
graphical modes to the console mode. For framebuffer consoles, the new
nvidia_modeset module tries to take care of it without having to fall
back to old-school VESA VBE modesets. However, in order for this to
work, the driver needs to know where the framebuffer console is in
physical memory, and its layout.

On Linux, we get this information from the global 'screen_info'
structure:

  void NV_API_CALL os_get_screen_info(
      NvU64 *pPhysicalAddress,
      NvU16 *pFbWidth,
      NvU16 *pFbHeight,
      NvU16 *pFbDepth,
      NvU16 *pFbPitch
  )
  {
      //
      // If there is not a framebuffer console, return 0 size.
      //
      // orig_video_isVGA is set to 1 during early Linux kernel
      // initialization, and then will be set to a value, such as
      // VIDEO_TYPE_VLFB or VIDEO_TYPE_EFI if an fbdev console is used.
      //
      if (screen_info.orig_video_isVGA <= 1)
      {
          *pPhysicalAddress = 0;
          *pFbWidth = *pFbHeight = *pFbDepth = *pFbPitch = 0;
          return;
      }

      *pPhysicalAddress = screen_info.lfb_base;
  #if defined(VIDEO_CAPABILITY_64BIT_BASE)
      *pPhysicalAddress |= (NvU64)screen_info.ext_lfb_base << 32;
  #endif
      *pFbWidth = screen_info.lfb_width;
      *pFbHeight = screen_info.lfb_height;
      *pFbDepth = screen_info.lfb_depth;
      *pFbPitch = screen_info.lfb_linelength;
  }

This works for both legacy boot systems with vesafb as well as UEFI
systems that use Linux's efifb.

On FreeBSD, I was able to find this information on my legacy system:

  void NV_API_CALL os_get_screen_info(
      NvU64 *pPhysicalAddress,
      NvU16 *pFbWidth,
      NvU16 *pFbHeight,
      NvU16 *pFbDepth,
      NvU16 *pFbPitch
  )
  {
      const sc_softc_t *sc = sc_get_softc(0, SC_KERNEL_CONSOLE);

      if (sc)
      {
          const video_adapter_t *adp = sc->adp;

          if (adp)
          {
              const struct video_info *vi = &adp->va_info;

              if (vi && (vi->vi_flags & V_INFO_LINEAR))
              {
                  *pPhysicalAddress = vi->vi_buffer;
                  *pFbWidth = vi->vi_width;
                  *pFbHeight = vi->vi_height;
                  *pFbDepth = vi->vi_depth;
                  *pFbPitch = adp->va_line_width;
                  return;
              }
          }
      }

      *pPhysicalAddress = 0;
      *pFbWidth = *pFbHeight = *pFbDepth = *pFbPitch = 0;
  }

However, this doesn't work on UEFI systems because efifb doesn't go
through the video_adapter_t stuff. Does anyone know how I can get that
information from efifb, or who to talk to about adding an interface
the driver can use to find it?

Sincerely,
Aaron



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?c84970b6-6e70-2648-a711-57753696b2b0>