#
# Opnic Driver - A driver for the Opnic PCI card
# Copyright (c) 2025 Q.M Technologies LTD., All rights reserved.
#
# Use of this source code is governed by a GPL-style
# license that can be found in the LICENSE file in the root of the repo
#
# Author: Jonatan Nevo
#

# If KERNELRELEASE is defined, we're being called from the kernel build system
ifneq ($(KERNELRELEASE),)
    # Use KERNELRELEASE instead of shell uname -r
    KVER = $(KERNELRELEASE)
else
    # For direct calls to make, use the running kernel
    KVER = $(shell uname -r)
endif

MODULE_NAME := opnic
MODULE_FILE := $(MODULE_NAME).ko
CURRENT_DIR := $(shell pwd)

QM_NO_CUDA ?= 0

ifneq ($(QM_NO_CUDA), 1)
	# Try to get it based on available nvidia module version (just in case there are sources for couple of versions)
	nv_version=$(shell /sbin/modinfo -F version -k $(KVER) nvidia 2>/dev/null)
	nv_sources=$(shell /bin/ls -d /usr/src/nvidia-$(nv_version)/ 2>/dev/null)
	ifneq ($(shell test -d "$(nv_sources)" && echo "true" || echo "" ),)
		NVIDIA_SRC_DIR ?= $(shell find "$(nv_sources)" -name "nv-p2p.h"|head -1|xargs dirname || echo "NVIDIA_DRIVER_MISSING")
	else
		NVIDIA_SRC_DIR ?= $(shell find /usr/src/nvidia-* -name "nv-p2p.h"|head -1|xargs dirname || echo "NVIDIA_DRIVER_MISSING")
	endif
endif

KBUILD_MODPOST_WARN=1

obj-m += ${MODULE_NAME}.o

ccflags-y += -I$(src)/source -I$(src)/api-specs/drivers

ifeq ($(QM_NO_CUDA), 1)
	DMA_SRCS := source/dma/cpu_dma.o \
				source/dma/dummy_gpu_dma.o
	ccflags-y += -DQM_NO_CUDA
    INSTALL_ARG = QM_NO_CUDA=1
else
	DMA_SRCS := source/dma/cpu_dma.o \
				source/dma/gpu_dma.o
	ccflags-y += -I$(NVIDIA_SRC_DIR)
endif

$(MODULE_NAME)-y := source/main.o source/opnic_pci.o source/registers.o source/pin_context.o $(DMA_SRCS)
ccflags-y += -Wall

DEST_DIR = /usr/src/
MODULES_DIR := /lib/modules/$(KVER)
KDIR := $(MODULES_DIR)/build
MODULE_DESTDIR := $(MODULES_DIR)/extra/
DEPMOD := /sbin/depmod

all: module

#ifeq ($(QM_NO_CUDA), 1)
GIT_COMMIT_HASH=$(shell git rev-parse --short=7 HEAD)
ccflags-y += -DGIT_COMMIT_HASH=\"$(GIT_COMMIT_HASH)\"

QM_VERSION=$(shell $(CURRENT_DIR)/scripts/get_version.sh)
ccflags-y += -DQM_VERSION_STRING=\"$(QM_VERSION)\"

module:
	@ $(MAKE) -j4 -C $(KDIR) $(MAKE_PARAMS) M=$$PWD GIT_COMMIT_HASH=$(GIT_COMMIT_HASH) QM_VERSION=$(QM_VERSION) modules
	# Check build result
	if [ ! -f "${MODULE_NAME}.ko" ]; then exit 1; fi

# Sparse: address-space (__user/__kernel), lock-context (__acquires/__releases),
# and endianness checking. C=2 forces every file to be re-checked, not just
# the ones that would otherwise be rebuilt.
sparse:
	$(MAKE) -C $(KDIR) $(MAKE_PARAMS) M=$$PWD GIT_COMMIT_HASH=$(GIT_COMMIT_HASH) C=2 CF="-D__CHECK_ENDIAN__" modules

# Smatch: deeper static analysis (null derefs, unchecked returns, locking bugs)
# than sparse alone. Requires smatch installed and on $PATH; -p=kernel selects
# its kernel-specific checks. Override with `make smatch SMATCH=/path/to/smatch`.
SMATCH ?= smatch
smatch:
	$(MAKE) -C $(KDIR) $(MAKE_PARAMS) M=$$PWD GIT_COMMIT_HASH=$(GIT_COMMIT_HASH) C=2 CHECK=$(SMATCH) CF="-p=kernel" modules

#else
#nv_symbols:
#	@ echo "Picking NVIDIA driver sources from NVIDIA_SRC_DIR=$(NVIDIA_SRC_DIR). If that does not meet your expectation, you might have a stale driver still around and that might cause problems."
#	@ chmod +x create_nv.symvers.sh
#	@if [ -f "./nvidia.ko" ]; then \
#		rm -f ./nvidia.ko; \
#	fi
#	@ ./create_nv.symvers.sh
#
#module: nv_symbols
#	$(MAKE) -j4 -C $(KDIR) $(MAKE_PARAMS) M=$$PWD modules
#endif

install:
	@chmod +x scripts/install.sh
	@scripts/install.sh $(INSTALL_ARG)

uninstall:
	@chmod +x scripts/uninstall.sh
	@scripts/uninstall.sh

deb:
	@chmod +x scripts/build_deb.sh
	@scripts/build_deb.sh $(INSTALL_ARG)

help:
	$(MAKE) -C $(KDIR) M=$$PWD help

test_pin:
	$(CC) -O2 -o tests/test_pin tests/test_pin.c

clean:
	$(MAKE) -C $(KDIR) M=$$PWD clean
	rm -f tests/test_pin
#	rm -f nv.symvers

.PHONY: module sparse smatch install uninstall deb help clean all
