
# ATTO ExpressSAS 12Gb HBA Makefile

BLD_TYPE := rf
MP := 0
GPU := 0


DRIVER_NAME := esas4hba
DISPLAY_NAME := ExpressSAS H12xx

FAMILY_CFLAGS := -DHW_LOGGING -DESASHBA4 -DHW_SCSI_TGT

PROTO_SAS := 1

FEAT_ATTOCFG := 1
FEAT_TRANSPORT := 1

# Default to release build

BLD_TYPE ?= rf

ENABLE_ATTO_SYMBOLS := 0
ENABLE_ATTO_DEBUG := 0
ENABLE_ATTO_TRACING := 0
EXTRA_CHECKS := 0


ifeq "$(BLD_TYPE)" "rft"
ENABLE_ATTO_TRACING := 1
endif

ifeq "$(BLD_TYPE)" "rc"
ENABLE_ATTO_SYMBOLS := 1
endif

ifeq "$(BLD_TYPE)" "rct"
ENABLE_ATTO_TRACING := 1
ENABLE_ATTO_SYMBOLS := 1
endif

ifeq "$(BLD_TYPE)" "dc"
ENABLE_ATTO_TRACING := 1
ENABLE_ATTO_SYMBOLS := 1
ENABLE_ATTO_DEBUG := 1
endif

ifeq "$(BLD_TYPE)" "df"
ENABLE_ATTO_TRACING := 1
ENABLE_ATTO_DEBUG := 1
endif

ifeq "$(BLD_TYPE)" "xc"
ENABLE_ATTO_TRACING := 1
ENABLE_ATTO_SYMBOLS := 1
ENABLE_ATTO_DEBUG := 1
EXTRA_CHECKS := 1
endif

ifeq "$(BLD_TYPE)" "xf"
ENABLE_ATTO_TRACING := 1
EXTRA_CHECKS := 1
endif


# Default to system architecture

ARCH ?= $(shell uname -m | sed -e s/i.86/i386/)

ifeq ($(ARCH), i386)
    ARCH_TYPE    := x86
    ARCH_CFLAG   := -DOS_32BIT -D_IA32_ -march=i486
endif

ifeq ($(ARCH), x86_64)
    ARCH_TYPE    := x86_64
    ARCH_CFLAG   := -DOS_64BIT -D_EM64_
endif


# Define the core filenames

CORE_NAME := $(DRIVER_NAME)_core_$(ARCH_TYPE)
CORE_SHIP := $(CORE_NAME).o_shipped
CORE_OBJ  := $(CORE_NAME).o


# Disable compiler cache (overridable)

ifndef KERNELRELEASE

CCACHE_DISABLE ?= 1

ifneq ($(CCACHE_DISABLE),0)
export CCACHE_DISABLE := 1
else
unexport CCACHE_DISABLE
endif

endif


# cflags derived from build and driver family configuration

FAMILY_CFLAGS += -DOS_LINUX -DNO_WIDE_CHARACTERS


ifeq ($(MP),1)

ifeq ($(ENABLE_ATTO_DEBUG),1)
FAMILY_CFLAGS += -DSF_DEBUG
endif
FAMILY_CFLAGS += -D_MP_ -DSF_MP -DSF_LOGGING

else # MP

# Only non-MP drivers can include NVMe/transport layer support

ifdef FEAT_NVME
FAMILY_CFLAGS += -DHW_NVME_INI -DHW_NVME_TGT
endif

ifdef FEAT_TRANSPORT
FAMILY_CFLAGS += -DATTO_USE_TRANSPORT
endif

endif # MP


ifeq ($(GPU),1)
FAMILY_CFLAGS += -DDIRECT2GPU
endif

ifeq ($(EXTRA_CHECKS),1)
FAMILY_CFLAGS += -DHW_EDI
endif

ifeq ($(ENABLE_ATTO_TRACING),1)
FAMILY_CFLAGS += -DHW_TRACING
endif

ifeq ($(ENABLE_ATTO_DEBUG),1)
  FAMILY_CFLAGS += -DATTO_DEBUG -DATTO_OS_ASSERTS -DUSE_ATTO_LOG

  ifneq ($(PRINTF_DEBUG),0)
    FAMILY_CFLAGS += -DPRINTF_DEBUG
  else
    FAMILY_CFLAGS += -DSER_DEBUG -DCOM1_DEBUG
  endif

  ifdef ATTO_DEBUG_DEFERABLE
    FAMILY_CFLAGS += -DSER_DEBUG_DEFERABLE
  endif
endif

ifdef FEAT_NPIV
FAMILY_CFLAGS += -DHW_NPIV
endif
#############################################################################
# The kernel makefile includes this makefile again; don't mess with its     #
# settings after we have invoked it.                                        #
#############################################################################


# Variables needed for both the kernel and user invocation.
#############################################################################

ifndef DRIVER_NAME
$(error Error: Unable to detect driver name)
endif

ifndef GPU
$(error Error: Unable to detect driver type)
endif

ifndef MP
$(error Error: Unable to detect driver type)
endif

ifndef BLD_TYPE
$(error Error: Unable to detect build type)
endif

ifndef ARCH
$(error Error: Unable to detect system architecture)
endif


# If the user is calling the makefile
#############################################################################

ifndef KERNELRELEASE

MAKEFLAGS += --no-builtin-rules --warn-undefined-variables
SHELL := bash
.SUFFIXES:


# Figure out what name to display to the user

PRETTY_NAME := $(DISPLAY_NAME) Driver

ifeq ($(MP),1)
PRETTY_NAME := $(DISPLAY_NAME) Multipath Director
endif

ifeq ($(GPU),1)
PRETTY_NAME := $(DISPLAY_NAME) Direct2GPU Driver
endif


# Default values, may be overridden via the environment or make overrides,
KDIR ?=


# Get the current kernel version.  This makefile assumes
# that the user is compiling the driver for whatever
# kernel they are currently running;  if this is not
# the case, specify the correct kernel header path on
# the 'make' command line with 'KDIR=/correct/path'

ifeq ($(KDIR),)
FULL_KERNEL_VERSION := $(shell uname -r)

# Figure out where the kernel header files are located
KDIR := "/lib/modules/$(FULL_KERNEL_VERSION)/build"
else

# User has specified a different kernel header path,
# try to extract the full kernel version from it
ifneq ($(shell test -f $(KDIR)/include/generated/utsrelease.h || echo 1),1)
FULL_KERNEL_VERSION := $(shell grep UTS_RELEASE $(KDIR)/include/generated/utsrelease.h | cut -d" " -f3,3)
else
ifneq ($(shell test -f $(KDIR)/include/linux/utsrelease.h || echo 1),1)
# 2.6.32 and prior
FULL_KERNEL_VERSION := $(shell grep UTS_RELEASE $(KDIR)/include/linux/utsrelease.h | cut -d" " -f3,3)
endif
endif

FULL_KERNEL_VERSION ?=

ifeq ($(FULL_KERNEL_VERSION),)
$(error Unable to detect kernel version (2.6.32 or later is required))
endif
endif

# Save the current directory
ifeq ($(PWD),)
PWD := $(shell dirname "$(readlink -f "$0")")
endif


ifdef FEAT_SMHBA
SMHBA_NAME := $(DRIVER_NAME)sm
endif

# Install directory defaults to '/extra' on most systems
# For Ubuntu we want to use the default dkms install directory
ifneq ($(shell cat /etc/os-release | grep -i ubuntu),)
INSTALL_DIR := INSTALL_MOD_DIR=updates/dkms
else
INSTALL_DIR :=
endif

# Make Rules
###############################################################################

.PHONY: all
all:
	@echo
	@echo "ATTO $(PRETTY_NAME) Makefile"
	@echo
	@echo "Detected kernel version:  $(FULL_KERNEL_VERSION)"
	@echo "Kernel build directory:   $(KDIR)"
	@echo "Architecture:             $(ARCH)"
	@echo
	@echo "Options:"
	@echo "   make install     - build & install the drivers (recommended)"
	@echo "   make modules     - build the drivers (but do not install)"
	@echo "   make clean       - delete previously built drivers and objects"
	@echo


# The kernel makefile spews with --warn-undefined-variables when building from
# the top level makefile.
.PHONY: modules
modules: MAKEFLAGS := $(filter-out --warn-undefined-variables,$(MAKEFLAGS))
modules:
	@echo "Architecture is $(ARCH) ($(ARCH_TYPE))"
	@touch $(PWD)/.$(DRIVER_NAME)_core_$(ARCH_TYPE).o.cmd
	@$(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(ARCH) modules
	@echo "$(DRIVER_NAME) modules built"


.PHONY: install
install: MAKEFLAGS := $(filter-out --warn-undefined-variables,$(MAKEFLAGS))
install: modules
	@$(MAKE) -C $(KDIR) M=$(PWD) $(INSTALL_DIR) modules_install
	@depmod -a $(FULL_KERNEL_VERSION)
	@echo "Modules installed"


.PHONY: clean
clean: MAKEFLAGS := $(filter-out --warn-undefined-variables,$(MAKEFLAGS))
clean:
	@$(MAKE) -C $(KDIR) M=$(PWD) clean


ifdef FEAT_SMHBA
.PHONY: api_install
api_install:
		@rm -f /usr/lib/$(SMHBA_NAME).so
		@cp $(SMHBA_NAME)_$(ARCH_TYPE).so /usr/lib/$(SMHBA_NAME).so
		@if [ -f /etc/hba.conf ]; then \
		    mv /etc/hba.conf /etc/hba.conf.orig; \
		    grep -v $(SMHBA_NAME) /etc/hba.conf.orig > /etc/hba.conf; \
		    true; \
		fi;
		@echo "com.attotech.$(SMHBA_NAME)   /usr/lib/$(SMHBA_NAME).so" >> /etc/hba.conf
		@echo "ATTO SM-HBA API library installation completed"
endif


# The kernel is calling the makefile
###############################################################################
else # KERNELRELEASE


MIN_VER := '2.6.32'
MAX_VER := $(shell printf '$(MIN_VER)\n$(KERNELRELEASE)' | sort -t. -k 1,1 -k 2,2 -k 3,3 | tail -n 1)

ifneq ($(MAX_VER),$(KERNELRELEASE))
    $(error Linux kernel $(MIN_VER) or later is required (detected $(KERNELRELEASE)))
endif

SRCDIR ?= .


# Base driver sources/flags

ccflags-y += $(FAMILY_CFLAGS) -DUSE_ATTO_LOG \
             $(ARCH_CFLAG) \
             -DATTO_HBA_MOD_RAWNAME=$(DRIVER_NAME)     \
             -DATTO_CFG_MOD_RAWNAME=$(DRIVER_NAME)_cfg \
             -I$(KDIR)/drivers/scsi \
             -I$(PWD)/../../../../hw \
             -I$(src) \
             -I$(PWD)/../../../../../../include/linux \
             -I$(PWD)/../../../../../shared/linux/driver


attocfg-objs            := $(SRCDIR)/atto_cfg.o
$(DRIVER_NAME)_cfg-objs := $(SRCDIR)/atto_cfg2.o
$(DRIVER_NAME)-objs     := $(SRCDIR)/oswrap.o $(SRCDIR)/osutil.o

obj-m := $(DRIVER_NAME).o $(DRIVER_NAME)_cfg.o
ifdef FEAT_ATTOCFG
obj-m += attocfg.o
endif

# FC HBA sources/flags

ifneq ($(MP),1)
ifdef PROTO_FC
$(DRIVER_NAME)-objs += $(SRCDIR)/ostransportfc.o
endif

ifdef FEAT_NVME
$(DRIVER_NAME)-objs += $(SRCDIR)/atto_nvme.o $(SRCDIR)/atto_nvmet.o

ccflags-y += -DSUPPORTS_NVME_FC -DSUPPORTS_NVME_TARGET_FC
endif
endif # !MP

# SAS HBA sources/flags

ifdef PROTO_SAS
$(DRIVER_NAME)-objs += $(SRCDIR)/ostransportsas.o $(SRCDIR)/osata.o
endif

# Direct2GPU sources/flags

ifeq ($(GPU),1)
$(DRIVER_NAME)-objs += $(SRCDIR)/direct2gpu.o

ccflags-y += -DDIRECT2GPU -I$(NVIDIA_INCDIR)

NVIDIA_SYMS ?=
KBUILD_EXTRA_SYMBOLS := $(NVIDIA_SYMS)
endif


# Work around for an Ubuntu 16.04 LTS backport of parts of the 4.4.168 kernel.
# As soon as Ubuntu 16.04 LTS is no longer supported, we should remove this!

ifneq (,$(wildcard /etc/lsb-release))
ifneq ($(shell grep "xenial" /etc/lsb-release),)
ifeq ($(shell test $(uname -r | cut -d - -f 2) -gt 142),0)
ccflags-y += -D_UBUNTU_XENIAL_BACKPORTS_
endif
endif
endif

$(DRIVER_NAME)-objs += $(CORE_OBJ)

ldflags-y := -d


# These here should never be used, as they're just a stub for
# kbuild, so that it doesn't try to build the core files

$(src)/$(CORE_SHIP):
	$(error ERROR: Core file $(CORE_SHIP) is missing!)


endif #KERNELRELEASE
