libdrm: Add NVIDIA Tegra support

Add the libdrm_tegra helper library to encapsulate Tegra-specific
interfaces to the DRM.

Furthermore, Tegra is added to the list of supported chips in the
modetest and vbltest programs.

Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
main
Thierry Reding 2012-12-01 10:30:38 +01:00 committed by Thierry Reding
parent fb4177046d
commit d6a4c2cbd1
12 changed files with 556 additions and 3 deletions

View File

@ -53,7 +53,11 @@ if HAVE_FREEDRENO
FREEDRENO_SUBDIR = freedreno FREEDRENO_SUBDIR = freedreno
endif endif
SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) tests man if HAVE_TEGRA
TEGRA_SUBDIR = tegra
endif
SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(FREEDRENO_SUBDIR) $(TEGRA_SUBDIR) tests man
libdrm_la_LTLIBRARIES = libdrm.la libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir) libdrm_ladir = $(libdir)

View File

@ -26,6 +26,7 @@ LIBDRM_INCLUDE_H_FILES := \
include/drm/radeon_drm.h \ include/drm/radeon_drm.h \
include/drm/savage_drm.h \ include/drm/savage_drm.h \
include/drm/sis_drm.h \ include/drm/sis_drm.h \
include/drm/tegra_drm.h \
include/drm/via_drm.h include/drm/via_drm.h
LIBDRM_INCLUDE_VMWGFX_H_FILES := \ LIBDRM_INCLUDE_VMWGFX_H_FILES := \

View File

@ -98,6 +98,11 @@ AC_ARG_ENABLE(freedreno-experimental-api,
[Enable support for freedreno's experimental API (default: disabled)]), [Enable support for freedreno's experimental API (default: disabled)]),
[FREEDRENO=$enableval], [FREEDRENO=no]) [FREEDRENO=$enableval], [FREEDRENO=no])
AC_ARG_ENABLE(tegra-experimental-api,
AS_HELP_STRING([--enable-tegra-experimental-api],
[Enable support for Tegra's experimental API (default: disabled)]),
[TEGRA=$enableval], [TEGRA=no])
AC_ARG_ENABLE(install-test-programs, AC_ARG_ENABLE(install-test-programs,
AS_HELP_STRING([--enable-install-test-programs], AS_HELP_STRING([--enable-install-test-programs],
[Install test programs (default: no)]), [Install test programs (default: no)]),
@ -304,6 +309,11 @@ if test "x$RADEON" = xyes; then
AC_DEFINE(HAVE_RADEON, 1, [Have radeon support]) AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
fi fi
AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes])
if test "x$TEGRA" = xyes; then
AC_DEFINE(HAVE_TEGRA, 1, [Have Tegra support])
fi
AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes]) AM_CONDITIONAL(HAVE_INSTALL_TESTS, [test "x$INSTALL_TESTS" = xyes])
if test "x$INSTALL_TESTS" = xyes; then if test "x$INSTALL_TESTS" = xyes; then
AC_DEFINE(HAVE_INSTALL_TESTS, 1, [Install test programs]) AC_DEFINE(HAVE_INSTALL_TESTS, 1, [Install test programs])
@ -403,6 +413,8 @@ AC_CONFIG_FILES([
exynos/libdrm_exynos.pc exynos/libdrm_exynos.pc
freedreno/Makefile freedreno/Makefile
freedreno/libdrm_freedreno.pc freedreno/libdrm_freedreno.pc
tegra/Makefile
tegra/libdrm_tegra.pc
tests/Makefile tests/Makefile
tests/modeprint/Makefile tests/modeprint/Makefile
tests/modetest/Makefile tests/modetest/Makefile
@ -426,4 +438,5 @@ echo " Nouveau API $NOUVEAU"
echo " OMAP API $OMAP" echo " OMAP API $OMAP"
echo " EXYNOS API $EXYNOS" echo " EXYNOS API $EXYNOS"
echo " Freedreno API $FREEDRENO" echo " Freedreno API $FREEDRENO"
echo " Tegra API $TEGRA"
echo "" echo ""

154
include/drm/tegra_drm.h Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _UAPI_TEGRA_DRM_H_
#define _UAPI_TEGRA_DRM_H_
#include <drm.h>
#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0)
#define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1)
struct drm_tegra_gem_create {
__u64 size;
__u32 flags;
__u32 handle;
};
struct drm_tegra_gem_mmap {
__u32 handle;
__u32 offset;
};
struct drm_tegra_syncpt_read {
__u32 id;
__u32 value;
};
struct drm_tegra_syncpt_incr {
__u32 id;
__u32 pad;
};
struct drm_tegra_syncpt_wait {
__u32 id;
__u32 thresh;
__u32 timeout;
__u32 value;
};
#define DRM_TEGRA_NO_TIMEOUT (0xffffffff)
struct drm_tegra_open_channel {
__u32 client;
__u32 pad;
__u64 context;
};
struct drm_tegra_close_channel {
__u64 context;
};
struct drm_tegra_get_syncpt {
__u64 context;
__u32 index;
__u32 id;
};
struct drm_tegra_get_syncpt_base {
__u64 context;
__u32 syncpt;
__u32 id;
};
struct drm_tegra_syncpt {
__u32 id;
__u32 incrs;
};
struct drm_tegra_cmdbuf {
__u32 handle;
__u32 offset;
__u32 words;
__u32 pad;
};
struct drm_tegra_reloc {
struct {
__u32 handle;
__u32 offset;
} cmdbuf;
struct {
__u32 handle;
__u32 offset;
} target;
__u32 shift;
__u32 pad;
};
struct drm_tegra_waitchk {
__u32 handle;
__u32 offset;
__u32 syncpt;
__u32 thresh;
};
struct drm_tegra_submit {
__u64 context;
__u32 num_syncpts;
__u32 num_cmdbufs;
__u32 num_relocs;
__u32 num_waitchks;
__u32 waitchk_mask;
__u32 timeout;
__u64 syncpts;
__u64 cmdbufs;
__u64 relocs;
__u64 waitchks;
__u32 fence; /* Return value */
__u32 reserved[5]; /* future expansion */
};
#define DRM_TEGRA_GEM_CREATE 0x00
#define DRM_TEGRA_GEM_MMAP 0x01
#define DRM_TEGRA_SYNCPT_READ 0x02
#define DRM_TEGRA_SYNCPT_INCR 0x03
#define DRM_TEGRA_SYNCPT_WAIT 0x04
#define DRM_TEGRA_OPEN_CHANNEL 0x05
#define DRM_TEGRA_CLOSE_CHANNEL 0x06
#define DRM_TEGRA_GET_SYNCPT 0x07
#define DRM_TEGRA_SUBMIT 0x08
#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
#define DRM_IOCTL_TEGRA_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_READ, struct drm_tegra_syncpt_read)
#define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr)
#define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait)
#define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel)
#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel)
#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
#endif

1
tegra/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
libdrm_tegra.pc

23
tegra/Makefile.am Normal file
View File

@ -0,0 +1,23 @@
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/include/drm
AM_CFLAGS = \
@PTHREADSTUBS_CFLAGS@ \
$(VISIBILITY_CFLAGS) \
$(WARN_CFLAGS)
libdrm_tegra_ladir = $(libdir)
libdrm_tegra_la_LTLIBRARIES = libdrm_tegra.la
libdrm_tegra_la_LDFLAGS = -version-number 0:0:0 -no-undefined
libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
libdrm_tegra_la_SOURCES = \
private.h \
tegra.c
libdrm_tegraincludedir = ${includedir}/libdrm
libdrm_tegrainclude_HEADERS = tegra.h
pkgconfigdir = @pkgconfigdir@
pkgconfig_DATA = libdrm_tegra.pc

11
tegra/libdrm_tegra.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libdrm_tegra
Description: Userspace interface to Tegra kernel DRM services
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -ldrm_tegra
Cflags: -I${includedir} -I${includedir}/libdrm
Requires.private: libdrm

51
tegra/private.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright © 2012, 2013 Thierry Reding
* Copyright © 2013 Erik Faye-Lund
* Copyright © 2014 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DRM_TEGRA_PRIVATE_H__
#define __DRM_TEGRA_PRIVATE_H__ 1
#include <stdbool.h>
#include <stdint.h>
#include <libdrm.h>
#include <xf86atomic.h>
#include "tegra.h"
struct drm_tegra {
bool close;
int fd;
};
struct drm_tegra_bo {
struct drm_tegra *drm;
uint32_t handle;
uint32_t offset;
uint32_t flags;
uint32_t size;
atomic_t ref;
void *map;
};
#endif /* __DRM_TEGRA_PRIVATE_H__ */

248
tegra/tegra.c Normal file
View File

@ -0,0 +1,248 @@
/*
* Copyright © 2012, 2013 Thierry Reding
* Copyright © 2013 Erik Faye-Lund
* Copyright © 2014 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <xf86drm.h>
#include <tegra_drm.h>
#include "private.h"
static void drm_tegra_bo_free(struct drm_tegra_bo *bo)
{
struct drm_tegra *drm = bo->drm;
struct drm_gem_close args;
if (bo->map)
munmap(bo->map, bo->size);
memset(&args, 0, sizeof(args));
args.handle = bo->handle;
drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &args);
free(bo);
}
static int drm_tegra_wrap(struct drm_tegra **drmp, int fd, bool close)
{
struct drm_tegra *drm;
if (fd < 0 || !drmp)
return -EINVAL;
drm = calloc(1, sizeof(*drm));
if (!drm)
return -ENOMEM;
drm->close = close;
drm->fd = fd;
*drmp = drm;
return 0;
}
drm_public
int drm_tegra_new(struct drm_tegra **drmp, int fd)
{
bool supported = false;
drmVersionPtr version;
version = drmGetVersion(fd);
if (!version)
return -ENOMEM;
if (!strncmp(version->name, "tegra", version->name_len))
supported = true;
drmFreeVersion(version);
if (!supported)
return -ENOTSUP;
return drm_tegra_wrap(drmp, fd, false);
}
drm_public
void drm_tegra_close(struct drm_tegra *drm)
{
if (!drm)
return;
if (drm->close)
close(drm->fd);
free(drm);
}
drm_public
int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
uint32_t flags, uint32_t size)
{
struct drm_tegra_gem_create args;
struct drm_tegra_bo *bo;
int err;
if (!drm || size == 0 || !bop)
return -EINVAL;
bo = calloc(1, sizeof(*bo));
if (!bo)
return -ENOMEM;
atomic_set(&bo->ref, 1);
bo->flags = flags;
bo->size = size;
bo->drm = drm;
memset(&args, 0, sizeof(args));
args.flags = flags;
args.size = size;
err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args,
sizeof(args));
if (err < 0) {
err = -errno;
free(bo);
return err;
}
bo->handle = args.handle;
*bop = bo;
return 0;
}
drm_public
int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
uint32_t handle, uint32_t flags, uint32_t size)
{
struct drm_tegra_bo *bo;
if (!drm || !bop)
return -EINVAL;
bo = calloc(1, sizeof(*bo));
if (!bo)
return -ENOMEM;
atomic_set(&bo->ref, 1);
bo->handle = handle;
bo->flags = flags;
bo->size = size;
bo->drm = drm;
*bop = bo;
return 0;
}
drm_public
struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo)
{
if (bo)
atomic_inc(&bo->ref);
return bo;
}
drm_public
void drm_tegra_bo_unref(struct drm_tegra_bo *bo)
{
if (bo && atomic_dec_and_test(&bo->ref))
drm_tegra_bo_free(bo);
}
drm_public
int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle)
{
if (!bo || !handle)
return -EINVAL;
*handle = bo->handle;
return 0;
}
drm_public
int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr)
{
struct drm_tegra *drm = bo->drm;
if (!bo->map) {
struct drm_tegra_gem_mmap args;
int err;
memset(&args, 0, sizeof(args));
args.handle = bo->handle;
err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_MMAP, &args,
sizeof(args));
if (err < 0)
return -errno;
bo->offset = args.offset;
bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
drm->fd, bo->offset);
if (bo->map == MAP_FAILED) {
bo->map = NULL;
return -errno;
}
}
if (ptr)
*ptr = bo->map;
return 0;
}
drm_public
int drm_tegra_bo_unmap(struct drm_tegra_bo *bo)
{
if (!bo)
return -EINVAL;
if (!bo->map)
return 0;
if (munmap(bo->map, bo->size))
return -errno;
bo->map = NULL;
return 0;
}

47
tegra/tegra.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright © 2012, 2013 Thierry Reding
* Copyright © 2013 Erik Faye-Lund
* Copyright © 2014 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DRM_TEGRA_H__
#define __DRM_TEGRA_H__ 1
#include <stdint.h>
#include <stdlib.h>
struct drm_tegra_bo;
struct drm_tegra;
int drm_tegra_new(struct drm_tegra **drmp, int fd);
void drm_tegra_close(struct drm_tegra *drm);
int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm,
uint32_t flags, uint32_t size);
int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm,
uint32_t handle, uint32_t flags, uint32_t size);
struct drm_tegra_bo *drm_tegra_bo_ref(struct drm_tegra_bo *bo);
void drm_tegra_bo_unref(struct drm_tegra_bo *bo);
int drm_tegra_bo_get_handle(struct drm_tegra_bo *bo, uint32_t *handle);
int drm_tegra_bo_map(struct drm_tegra_bo *bo, void **ptr);
int drm_tegra_bo_unmap(struct drm_tegra_bo *bo);
#endif /* __DRM_TEGRA_H__ */

View File

@ -1456,7 +1456,7 @@ int main(int argc, char **argv)
int drop_master = 0; int drop_master = 0;
int test_vsync = 0; int test_vsync = 0;
int test_cursor = 0; int test_cursor = 0;
const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "sti" }; const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", "tilcdc", "msm", "sti", "tegra" };
char *device = NULL; char *device = NULL;
char *module = NULL; char *module = NULL;
unsigned int i; unsigned int i;

View File

@ -105,7 +105,7 @@ static void usage(char *name)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int i, c, fd, ret; int i, c, fd, ret;
char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm" }; char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos", "omapdrm", "tilcdc", "msm", "tegra" };
drmVBlank vbl; drmVBlank vbl;
drmEventContext evctx; drmEventContext evctx;
struct vbl_info handler_info; struct vbl_info handler_info;