#
# Version: 1.0
#
#  This file is provided under a dual BSD/GPLv2 license.  When using or
#  redistributing this file, you may do so under either license.
#
#  GPL LICENSE SUMMARY
#
#  Copyright (C) 2008-2021 Intel Corporation. All rights reserved.
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of version 2 of the GNU General Public License as
#  published by the Free Software Foundation.
#
#  This program is distributed in the hope that it will be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#  General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
#  The full GNU General Public License is included in this distribution
#  in the file called LICENSE.GPL.
#
#  BSD LICENSE
#
#  Copyright (C) 2008-2021 Intel Corporation. All rights reserved.
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in
#      the documentation and/or other materials provided with the
#      distribution.
#    * Neither the name of Intel Corporation nor the names of its
#      contributors may be used to endorse or promote products derived
#      from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# -------------------- user configurable options ------------------------

# base name of socperf driver
DRIVER_NAME = socperf3

# location to install driver
INSTALL = .

# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
# Example flags are "-Werror", "-Wno-error", etc.
#EXTRA_CFLAGS += -I$(LDDINCDIR) -I$(LDDINCDIR1)
EXTRA_CFLAGS += -I$(M)/../include -I$(M)/inc

ifeq ($(UDEV_AVAILABLE),NO)
    EXTRA_CFLAGS += -DDRV_UDEV_UNAVAILABLE
    $(info ********************************************************************************)
    $(info WARNING: The device manager is NOT available. It create device files separately.)
    $(info ********************************************************************************)
endif

# if ARCH variable is set, unset it to avoid conflicts with kbuild
unexport ARCH

# platform details
MACH ?= $(shell uname -m)
export MACH
ifeq ($(MACH),x86_64)
PLATFORM=x32_64
endif
ifeq ($(PLATFORM),)
PLATFORM=x32
endif

KERNEL_VERSION ?= $(shell uname -r)
SMP := $(shell uname -v | grep SMP)
ARITY=up
ifneq ($(SMP),)
ARITY=smp
endif

ifneq ($(KERNEL_HEADER_DIR),)
    PATH_PREFIX = $(KERNEL_HEADER_DIR)
else
    PATH_PREFIX = /lib/modules/$(shell uname -r)/build
endif
# Path to the header file
class_create_header_file := $(PATH_PREFIX)/include/linux/device/class.h

# Define the logic to check the number of parameters in class_create
define check_class_create_signature
  grep -Eo "class_create\([^)]*\)" $(class_create_header_file) | head -n 1 | awk -F'[()]' '{print $$2}' | awk -F',' '{print NF}'
endef

# Check the number of parameters and set the flag if needed
PARAM_COUNT := $(shell $(call check_class_create_signature))

ifeq ($(PARAM_COUNT),1)
  EXTRA_CFLAGS += -DDRV_CLASS_CREATE_UPDATED
endif

MAKE_CMD = $(MAKE) -C $(KERNEL_SRC_DIR) M=$(PWD) KBUILD_EXTRA_SYMBOLS= LDDINCDIR=$(PWD)/../include LDDINCDIR1=$(PWD)/inc modules PWD=$(PWD) -j4

# eventual filename of socperf driver
DRIVER_MODE=$(DRIVER_NAME)
DRIVER_TYPE=$(PLATFORM)-$(KERNEL_VERSION)$(ARITY)
DRIVER_FILENAME=$(DRIVER_MODE)-$(DRIVER_TYPE).ko

# build options ...
ifneq ($(KERNELRELEASE),)
	obj-m := $(DRIVER_NAME).o

ifeq ($(PLATFORM),x32)
	arch-objs :=    pci.o                 \
			soc_uncore.o                  \
			haswellunc_sa.o               \
			npk_uncore.o
endif
ifeq ($(PLATFORM),x32_64)
	arch-objs :=    pci.o     \
			soc_uncore.o      \
			haswellunc_sa.o   \
			npk_uncore.o
endif

	$(DRIVER_NAME)-objs :=    \
			socperfdrv.o      \
			control.o         \
			utility.o         \
			pmu_list.o        \
			$(arch-objs)

# targets ...

# Otherwise, we were called directly from the command
# line, so the kernel build system will be used.
else
	KERNEL_SRC_DIR ?= /lib/modules/$(shell uname -r)/build
	PWD := $(shell pwd)

all: default

default:
ifeq ($(VERBOSE),1)
	$(MAKE_CMD)
	cp $(DRIVER_NAME).ko $(DRIVER_FILENAME)
else
	@$(MAKE_CMD) > /dev/null
	@cp $(DRIVER_NAME).ko $(DRIVER_FILENAME)
endif
endif

install:
	@cp $(DRIVER_NAME).ko $(INSTALL)/$(DRIVER_FILENAME)
	@cp insmod-socperf $(INSTALL)/insmod-socperf
	@cp rmmod-socperf $(INSTALL)/rmmod-socperf
	@cp boot-script $(INSTALL)/boot-script
	@echo "Installed $(DRIVER_NAME) driver to $(INSTALL)/$(DRIVER_FILENAME) ."

clean:
	rm -f *.o .*.o.cmd .*.o.d .*.ko.cmd .*.ko.unsigned.cmd *.gcno .cache.mk *.o.ur-safe .*.o.tmp *.mod .*.mod.cmd
	rm -f $(DRIVER_NAME).ko $(DRIVER_NAME).ko.unsigned
	rm -f $(DRIVER_MODE)*$(DRIVER_TYPE).ko
	rm -f Module.symvers Modules.symvers *.mod.c modules.order Module.markers .modules.order.cmd .Module.symvers.cmd
	rm -rf .tmp_versions

distclean: clean
	rm -f $(DRIVER_NAME)*.ko
