# Build NVIDIA DRM components using FreeBSD's linuxkpi
#
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: MIT
#
# 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 AUTHORS OR COPYRIGHT HOLDERS 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.

# get our conftest and sources lists from here
.include "nvidia-drm-sources.mk"

GENERATED_KMOD_SRCS += device_if.h \
        vnode_if.h \
        bus_if.h \
        pci_if.h \
        pci_iov_if.h \
        device_if.h \
        iicbus_if.h \
        opt_teken.h \
        opt_splash.h \
        opt_syscons.h \
        opt_compat.h \
        opt_drm.h \
        opt_vm.h \
        opt_syscons.h

SRCS += ${GENERATED_KMOD_SRCS}

# drop the "nvidia-drm/" prefix that Linux uses
NVIDIA_DRM_SRCS = ${NVIDIA_DRM_SOURCES:S/nvidia-drm\///g}
NVIDIA_DRM_SRCS += nvidia-drm-freebsd-lkpi.c

SRCS += ${NVIDIA_DRM_SRCS}

KMOD = nvidia-drm

# So that the build can include machine/stdarg.h
CFLAGS += -Imachine

# So that the build can include sys/stddef.h
CFLAGS += -I${SYSDIR}/sys

CFLAGS += -g -I../common/inc -Wno-visibility -Wno-error=unused-but-set-variable -Wno-error=missing-prototypes

# to workaround dma-buf-map.h
CFLAGS += -Wno-error=pointer-arith

# FreeBSD's uint64_t on amd64 is not unsigned long long like NvU64 is, use this to have
# us use the real uint64_t so it matches
CFLAGS += -DNVTYPES_USE_STDINT=1

CFLAGS += -DNV_VERSION_STRING=\"580.105.08\"

include ../common/optional-cflags.mk

# we need to get the linux kpi headers for compilation. BSDSRCTOP
# is the top of a FreeBSD src tree (or empty to use /sys)
BSDSRCTOP ?= /usr/src
# FreeBSD linuxkpi specific headers
# This is the path at which https://github.com/freebsd/drm-kmod is installed
DRMKMODDIR ?= ${HOME}/git/drm-kmod

NV_CONFTEST_CFLAGS = \
        -I${DRMKMODDIR}/linuxkpi/bsd/include \
        -I${DRMKMODDIR}/linuxkpi/gplv2/include/ \
        -I${BSDSRCTOP}/sys/compat/linuxkpi/common/include/ \
        -I${DRMKMODDIR}/linuxkpi/dummy/include/ \
        -I${BSDSRCTOP}/sys/compat/linuxkpi/dummy/include/ \
        -I${DRMKMODDIR}/include/ \
        -I${DRMKMODDIR}/include/uapi/ \
        -I${DRMKMODDIR}/drivers/gpu/ \
        -I${BSDSRCTOP}/sys/contrib/ck/include

CFLAGS += ${NV_CONFTEST_CFLAGS}

# add src/nvidia as we need headers from there for nvidia_softc
# we use the softc to get the device_t during probing
CFLAGS += -I../nvidia/

CFLAGS += -Wno-cast-qual -Wno-incompatible-pointer-types-discards-qualifiers

# Include from BSDSRCTOP here since kmod.mk adds -nostdinc. We want to get headers from
# the source tree not the current install in case they don't match
NV_CONFTEST_CFLAGS+=-I. -I${BSDSRCTOP}/sys -I${BSDSRCTOP}/include -I${BSDSRCTOP}/sys/contrib/ck/include
NV_CONFTEST_CFLAGS+=-D_KERNEL -DKLD_MODULE -DKBUILD_MODNAME='"nvidia-drm"' -DLINUXKPI_PARAM_PREFIX=nvidia_drm_
# For fb_mode_option and drm_ioctl_kernel on FreeBSD 12.2
NV_CONFTEST_CFLAGS += -Wno-error=redundant-decls

# For drm_connector_helper_funcs_mode_valid_has_const_mode_arg and other
# conftests that rely on -Werror=incompatible-pointer-types
NV_CONFTEST_CFLAGS += -Werror=incompatible-pointer-types

# Mark the linux version we support.
# This solves issues with things like ww_mutex_trylock, we will have
# to bump this manually over time unfortunately
.include "${DRMKMODDIR}/linuxkpi_version.mk"
NV_CONFTEST_CFLAGS += -DLINUXKPI_VERSION=${LINUXKPI_VERSION_NUMBER}

# Include drm-kmod's kconfig declarations. This lets us define things
# such as CONFIG_COMPAT so that 32-bit linux emulation works. On < 13
# this is not present and things are handled in drm_os_config.h
.if exists(${DRMKMODDIR}/kconfig.mk)
# Disable the fbdev code since it's unsupported in drm-kmod
NO_FBDEV=1
.include "${DRMKMODDIR}/kconfig.mk"
NV_CONFTEST_CFLAGS += ${KCONFIG:C/(.*)/-DCONFIG_\1/}
.endif

.include "header-presence-tests.mk"

.for HEADER in ${NV_HEADER_PRESENCE_TESTS}
# Define a rule to check the header $(1).
#
# Depend on the headers generated by bsd.kmod.mk, without this the linuxkpi
# files will fail to import and fail the presence test
conftest/header_presence/${HEADER}.part: ${GENERATED_KMOD_SRCS} ${PWD}/conftest.sh ${DRMKMODDIR}
	mkdir -p conftest/header_presence/${HEADER:H}
	OS=FreeBSD ${PWD}/conftest.sh '${CC}' x86_64 ${DRMKMODDIR} this_arg_not_used_on_bsd test_kernel_header '${NV_CONFTEST_CFLAGS}' ${HEADER} > conftest/header_presence/${HEADER}.part

CONFTEST_HEADER_PARTS += conftest/header_presence/${HEADER}.part

.endfor

# Concatenate all of the parts into headers.h.
conftest/headers.h: ${CONFTEST_HEADER_PARTS}
	cat ${CONFTEST_HEADER_PARTS} > conftest/headers.h

conftest/generic.h: ${PWD}/conftest.sh ${DRMKMODDIR}
	mkdir -p conftest
	OS=FreeBSD ${PWD}/conftest.sh '${CC}' x86_64 ${DRMKMODDIR} this_arg_not_used_on_bsd compile_tests '${NV_CONFTEST_CFLAGS}' ${NV_CONFTEST_GENERIC_COMPILE_TESTS} > conftest/generic.h

conftest/functions.h: ${PWD}/conftest.sh ${DRMKMODDIR}
	mkdir -p conftest
	OS=FreeBSD ${PWD}/conftest.sh '${CC}' x86_64 ${DRMKMODDIR} this_arg_not_used_on_bsd compile_tests '${NV_CONFTEST_CFLAGS}' ${NV_CONFTEST_FUNCTION_COMPILE_TESTS} > conftest/functions.h

conftest/types.h: ${PWD}/conftest.sh ${DRMKMODDIR}
	mkdir -p conftest
	OS=FreeBSD ${PWD}/conftest.sh '${CC}' x86_64 ${DRMKMODDIR} this_arg_not_used_on_bsd compile_tests '${NV_CONFTEST_CFLAGS}' ${NV_CONFTEST_TYPE_COMPILE_TESTS} > conftest/types.h

conftest/macros.h:
	mkdir -p conftest
	touch conftest/macros.h

conftest/symbols.h:
	mkdir -p conftest
	touch conftest/symbols.h

CONFTEST_FILES = conftest/generic.h conftest/functions.h conftest/types.h conftest/macros.h conftest/symbols.h

${CONFTEST_FILES}: conftest/headers.h

${NVIDIA_DRM_SRCS}: ${CONFTEST_FILES}

clean:
	rm -rf conftest

.include <bsd.kmod.mk>

