# ATTO Linux Driver Makefile

# Figure out what sort of driver we are building

ifeq ($(DRIVER_NAME),)
DRIVER_NAME := $(shell ls *core_x86.o | cut -d_ -f1 | head -1)
endif

ifeq ($(DRIVER_NAME),)
blankdrivername:
	@echo 
	@echo Error: Unable to detect driver name
	@echo 
	@false
else
ifeq ($(DRIVER_NAME), celerityfc)
PRETTY_NAME := "Celerity FC"
FAMILY_COMPILE_FLAG := "CELERITYFC"
INSTALL_API := "yes"
USE_TRANSPORT := "yes"
USE_RPORTS := "yes"
DEFINE_FLAGS += -DTARGET_MODE
else
ifeq ($(DRIVER_NAME), express2)
PRETTY_NAME := "EPCI U320"
FAMILY_COMPILE_FLAG := "EXPRESS2"
else
ifeq ($(DRIVER_NAME), esasraid)
PRETTY_NAME := "ESAS RAID"
FAMILY_COMPILE_FLAG := "ESASRAID"
else
ifeq ($(DRIVER_NAME), esas2raid)
PRETTY_NAME := "ESAS 6GB RAID"
FAMILY_COMPILE_FLAG := "ESASRAID2"
USE_ATTO_LOG := "yes"
else
ifeq ($(DRIVER_NAME), esashba)
PRETTY_NAME := "ExpressSAS 3GB HBA"
FAMILY_COMPILE_FLAG := "ESASHBA"
NEED_SCSIREQUEST_H := 1
USE_TRANSPORT := "yes"
USE_SAS_PORTS := "yes"
USE_ATA_IOCTLS := "yes"
else
ifeq ($(DRIVER_NAME), celerity8fc)
PRETTY_NAME := "Celerity FC 8GB"
FAMILY_COMPILE_FLAG := "CELERITY8FC"
INSTALL_API := "yes"
USE_TRANSPORT := "yes"
USE_RPORTS := "yes"
DEFINE_FLAGS += -DTARGET_MODE
else
ifeq ($(DRIVER_NAME), esas2hba)
PRETTY_NAME := "ExpressSAS 6GB HBA"
FAMILY_COMPILE_FLAG := "ESAS2HBA"
NEED_SCSIREQUEST_H := 1
USE_TRANSPORT := "yes"
USE_SAS_PORTS := "yes"
USE_ATA_IOCTLS := "yes"
DEFINE_FLAGS += -DTARGET_MODE
else
ifeq ($(DRIVER_NAME), celerityfcmp)
PRETTY_NAME := "Celerity FC Multipathing"
FAMILY_COMPILE_FLAG := "CELERITYFC"
INSTALL_API := "yes"
# Turn off transport and rport for mp driver.
USE_TRANSPORT := "no"
USE_RPORTS := "no"
USE_ATTO_LOG := "yes"
DEFINE_FLAGS += -DTARGET_MODE -D_MP_
else
ifeq ($(DRIVER_NAME), celerity8fcmp)
PRETTY_NAME := "Celerity FC 8GB Multipathing"
FAMILY_COMPILE_FLAG := "CELERITY8FC"
# Turn off transport and rports for mp driver.
INSTALL_API := "yes"
USE_TRANSPORT := "no"
USE_RPORTS := "no"
USE_ATTO_LOG := "yes"
DEFINE_FLAGS += -DTARGET_MODE -D_MP_
else
ifeq ($(DRIVER_NAME), fastframe)
PRETTY_NAME := "FastFrame FCoE HBA"
FAMILY_COMPILE_FLAG := "FASTFRAME"
INSTALL_API := "yes"
USE_TRANSPORT := "yes"
USE_RPORTS := "yes"
DEFINE_FLAGS += -DTARGET_MODE -DATTO_NAPI
VNIC_DRIVER_NAME := ffxgbe
else
ifeq ($(DRIVER_NAME), esas3hba)
PRETTY_NAME := "ExpressSAS 6GB HBA"
FAMILY_COMPILE_FLAG := "ESAS3HBA"
NEED_SCSIREQUEST_H := 1
USE_TRANSPORT := "yes"
USE_SAS_PORTS := "yes"
USE_ATA_IOCTLS := "yes"
else
ifeq ($(DRIVER_NAME), celerity16fc)
PRETTY_NAME := "Celerity FC 16GB"
FAMILY_COMPILE_FLAG := "CELERITY16FC"
INSTALL_API := "yes"
USE_TRANSPORT := "yes"
USE_RPORTS := "yes"
DEFINE_FLAGS += -DTARGET_MODE
else
ifeq ($(DRIVER_NAME), celerity16fcmp)
PRETTY_NAME := "Celerity FC 16GB Multipathing"
FAMILY_COMPILE_FLAG := "CELERITY16FC"
# Turn off transport and rports for mp driver.
INSTALL_API := "yes"
USE_TRANSPORT := "no"
USE_RPORTS := "no"
USE_ATTO_LOG := "yes"
DEFINE_FLAGS += -DTARGET_MODE -D_MP_
else
errordrivername:
	@echo 
	@echo Error: Unknown driver name [$(DRIVER_NAME)]
	@echo 
	@false
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif
endif

# 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)
FULL_KERNEL_VERSION := $(shell grep UTS_RELEASE $(KDIR)/include/linux/utsrelease.h | cut -d" " -f3,3)
else
ifneq ($(shell test -f $(KDIR)/include/linux/version.h || echo 1),1)
FULL_KERNEL_VERSION := $(shell grep UTS_RELEASE $(KDIR)/include/linux/version.h | cut -d" " -f3,3)
else
FULL_KERNEL_VERSION := "2.6.1-invalid"
endif
endif
endif
endif

# Extract the major & minor version number so we know
# how to proceed in the build (2.4 or 2.6/3.x series kernels)

KERNEL_VERSION          := $(shell echo $(FULL_KERNEL_VERSION) | cut -d. -f1,2)
KERNEL_SUBMINOR_VERSION := $(shell echo $(FULL_KERNEL_VERSION) | cut -d. -f3,3 | cut -d- -f1,1)
KERNEL_SUBMAJOR_VERSION := $(shell echo $(FULL_KERNEL_VERSION) | cut -d. -f2,2 | cut -d- -f1,1)
KERNEL_MAJOR_VERSION    := $(shell echo $(FULL_KERNEL_VERSION) | cut -d. -f1,1 | cut -d- -f1,1)

ifeq ($(KERNEL_VERSION),2.6)
KERNEL_IS_26_OR_3="yes"
endif

ifeq ($(KERNEL_MAJOR_VERSION),3)
KERNEL_IS_26_OR_3="yes"
endif


# Figure out if config.h exists and should be included

ifneq ($(shell test -f $(KDIR)/include/linux/config.h || echo 1),1)
DEPRCHK := $(shell grep "warning Including config.h is deprecated." $(KDIR)/include/linux/config.h)
ifeq ($(strip $(DEPRCHK)),)
DEFINE_FLAGS += -DATTO_USE_CONFIG_H
endif
endif

ifeq ($(NEED_SCSIREQUEST_H), 1)
# Some versions of SUSE do not have the "scsi" include directory
# in the kernel build tree.  Figure out if this is the case and
# use the include in the kernel source tree if it exists
ifeq ($(shell test -d $(KDIR)/include/scsi || echo 1),1)
ifeq ($(shell test -d /usr/src/linux/include/scsi || echo 1),1)
noscsiincludes:
	@echo 
	@echo Error: You must install the kernel source code for this driver to build.
	@echo 
	@false
endif
ifneq ($(shell test -f /usr/src/linux/include/scsi/scsi_request.h || echo 1),1)
DEFINE_FLAGS += -DATTO_USE_SCSIREQUEST_H_IN_SRC_TREE
endif
else
# Figure out if scsi_request.h exists

ifneq ($(shell test -f $(KDIR)/include/scsi/scsi_request.h || echo 1),1)
DEFINE_FLAGS += -DATTO_USE_SCSIREQUEST_H
endif
endif
endif

# Figure out if smp_lock.h exists

ifneq ($(shell test -f $(KDIR)/include/linux/smp_lock.h || echo 1),1)
DEFINE_FLAGS += -DATTO_USE_SMP_LOCK_H
endif

# Figure out if asm/system.h exists

ifneq ($(shell test -f $(KDIR)/include/linux/asm/system.h || echo 1),1)
DEFINE_FLAGS += -DATTO_USE_ASM_SYSTEM_H
endif

# Check for a Red Hat 6.x kernel - they claim to use a
# 2.6.32 kernel but some of the APIs are from 2.6.33 or later

KERNEL_IS_REDHAT6 := $(shell echo $(FULL_KERNEL_VERSION) | grep el6)

ifneq ($(KERNEL_IS_REDHAT6),)
DEFINE_FLAGS += -DATTO_RHEL6
endif

# SLES 11 SP 1 pulls some funny business too

KERNEL_IS_SLES11SP1 := $(shell cat /etc/issue | grep SUSE | grep "11 SP1")

ifneq ($(KERNEL_IS_SLES11SP1),)
DEFINE_FLAGS += -DATTO_SLES11SP1
endif

# So does SLES 10 SP 3 & 4

KERNEL_IS_SLES10SP34 := $(shell cat /etc/issue | grep SUSE | grep "10 SP3")$(shell cat /etc/issue | grep SUSE | grep "10 SP4")

ifneq ($(KERNEL_IS_SLES10SP34),)
DEFINE_FLAGS += -DATTO_SLES10SP34
endif

# Check for a Fedora 13 kernel

KERNEL_IS_FC13 := $(shell echo $(FULL_KERNEL_VERSION) | grep fc13)

ifneq ($(KERNEL_IS_FC13),)
DEFINE_FLAGS += -DATTO_FC13
endif

# Check for a Fedora 15 kernel

KERNEL_IS_FC15 := $(shell echo $(FULL_KERNEL_VERSION) | grep fc15)

ifneq ($(KERNEL_IS_FC15),)
DEFINE_FLAGS += -DATTO_FC15
endif

# Save the current directory

ifeq ($(PWD),)
PWD := $(shell pwd)
endif

# Figure out which architecture we are on
# This determines which core file to link to,
# and which attofc*.so library to install.

ifeq ($(ARCH),)
ARCH := $(shell uname -m | sed -e s/i.86/i386/)
endif

# i386 section (ia32)
ifeq ($(ARCH), i386)
    CORE_TYPE    := x86
    ATTOFC_TYPE  := x86
    ARCH_CFLAG   := -DOS_32BIT -march=i486
    ARCH_LD      := -m elf_i386

ifeq ($(KERNEL_IS_26_OR_3),"yes")

# Extract the subminor version & force CONFIG_REGPARM if necessary
# (2.6.20 and greater always use -mregparm=3)

KERNEL_SUBMINOR_VERSION := $(shell echo $(FULL_KERNEL_VERSION) | cut -d. -f3,3 | cut -d- -f1,1)

ifeq ($(shell test $(KERNEL_SUBMINOR_VERSION) -lt 20 || echo 1),1)
CONFIG_REGPARM=1
endif
ifeq ($(KERNEL_MAJOR_VERSION),3)
CONFIG_REGPARM=1
endif
endif

# Kernel was built with -mregparm=3

    ifdef CONFIG_REGPARM
	CORE_TYPE    := x86_regparm
    endif
endif

# ia64 section (Itanium)
ifeq ($(ARCH),ia64)
    CORE_TYPE    := ia64
    ATTOFC_TYPE  := ia64
    ARCH_CFLAG   := -DOS_64BIT
    ifeq ($(KERNEL_VERSION),2.4)
	ARCH_CFLAG   += -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \
			-falign-functions=32 -frename-registers    \
			--param max-inline-insns=5000
	ARCH_LD      := -m elf64_ia64
    endif
endif

# x86_64 section (AMD64/EM64T)
ifeq ($(ARCH),x86_64)
    CORE_TYPE    := x86_64
    ATTOFC_TYPE  := x86_64
    ARCH_CFLAG   := -DOS_64BIT
    ifeq ($(KERNEL_VERSION),2.4)
	ARCH_CFLAG   += -mcmodel=kernel -mno-red-zone -DATTO_USE_KERNEL24_SCSI_TAPE_WORKAROUND
	ARCH_LD      := -m elf_x86_64
    endif
endif


# Finished product names

CORE_NAME    := $(DRIVER_NAME)_core_$(CORE_TYPE).o
ATTOFC_NAME  := attofc_$(ATTOFC_TYPE).so

all: checkkernel
	@echo
	@echo "ATTO $(PRETTY_NAME) Driver Makefile"
	@echo
ifeq ($(DRIVER_NAME), celerityfc)
	@echo "Celerity FC HBA driver & SNIA HBA API library"
	@echo
else
ifeq ($(DRIVER_NAME), celerity8fc)
	@echo "Celerity FC 8GB HBA driver & SNIA HBA API library"
	@echo
endif
endif
	@echo "Detected kernel version:  $(FULL_KERNEL_VERSION)"
	@echo "Kernel build directory:   $(KDIR)"
ifdef CONFIG_REGPARM
	@echo "Architecture:             $(ARCH) (regparm)"
else
	@echo "Architecture:             $(ARCH)"
endif
	@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

checkkernel:
ifneq ($(KERNEL_MAJOR_VERSION),3)
ifneq ($(KERNEL_VERSION),2.6)
ifneq ($(KERNEL_VERSION),2.4)
	@echo "This driver only works with Linux kernel version 2.4, 2.6, or 3.x"
	@echo "You appear to be running kernel version $(KERNEL_VERSION)"
	@false
endif
endif
endif
	@true

KERNEL_HEADERS := -I$(KDIR)/include
MODULE_ROOT    := /lib/modules/$(FULL_KERNEL_VERSION)/kernel/drivers
DEFINE_FLAGS   += -D$(FAMILY_COMPILE_FLAG)

# Print debugging info to syslog; see attolog.h for atto_log_mask settings
ifeq ($(USE_ATTO_LOG), "yes")
DEFINE_FLAGS += -DUSE_ATTO_LOG
endif

# if you want to print debugging info from the
# datapath to the syslog, uncomment this line:
#DEFINE_FLAGS += -DATTO_LOG_DATA_PATH

# -DATTO_DEBUG and -DATTO_DEBUG_LOUD control legacy debugging output
#DEFINE_FLAGS += -DATTO_DEBUG

# ...and if you want even more, uncomment this one too:
#DEFINE_FLAGS += -DATTO_DEBUG_LOUD

#DEFINE_FLAGS += -DATTO_USE_LINUX_COMPLETION -DATTO_USE_TM_COMPLETIONS

ifeq ($(KERNEL_IS_26_OR_3),"yes")
# start of stuff for 2.6/3.x kernels

ifeq ($(USE_TRANSPORT), "yes")
DEFINE_FLAGS += -DATTO_USE_TRANSPORT
ifeq ($(USE_RPORTS), "yes")
DEFINE_FLAGS += -DATTO_USE_RPORTS
endif
ifeq ($(USE_SAS_PORTS), "yes")
DEFINE_FLAGS += -DATTO_USE_SAS_PORTS
endif
endif

$(DRIVER_NAME)-objs := $(CORE_NAME) oswrap.o osutil.o
ifeq ($(USE_TRANSPORT), "yes")
$(DRIVER_NAME)-objs += ostransport.o
endif
ifeq ($(USE_ATA_IOCTLS), "yes")
$(DRIVER_NAME)-objs += osata.o
endif
attocfg-objs        := atto_cfg.o
obj-m               := $(DRIVER_NAME).o attocfg.o
EXTRA_CFLAGS        += -I$(KDIR)/drivers/scsi -I$(obj) -DLINUX $(ARCH_CFLAG) $(DEFINE_FLAGS)
EXTRA_LDFLAGS       := -d

ifneq ($(VNIC_DRIVER_NAME),)
$(VNIC_DRIVER_NAME)-objs := $(VNIC_DRIVER_NAME)_main.o $(VNIC_DRIVER_NAME)_ethtool.o
obj-m                    += $(VNIC_DRIVER_NAME).o
endif

src ?= .
obj ?= .

# 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

$(obj)/$(CORE_NAME):
	@echo
	@echo
	@echo "ERROR: Core file $(CORE_NAME) is missing!"
	@echo
	@echo
	@false

modules:
	@echo "Architecture is $(ARCH) ($(CORE_TYPE))"
	@$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) ARCH=$(ARCH) DRIVER_NAME=$(DRIVER_NAME) modules
ifeq ($(VNIC_DRIVER_NAME),)
	@echo "$(DRIVER_NAME) and attocfg modules built"
else
	@echo "$(DRIVER_NAME), $(VNIC_DRIVER_NAME), and attocfg modules built"
endif

ifeq ($(INSTALL_API), "yes")
install: modules api_install
else
install: modules
endif
	@mkdir -p $(MODULE_ROOT)
	@mkdir -p $(MODULE_ROOT)/scsi
	@install -m 0744 -o root -g root $(DRIVER_NAME).ko $(MODULE_ROOT)/scsi
	@install -m 0744 -o root -g root attocfg.ko	   $(MODULE_ROOT)
ifneq ($(VNIC_DRIVER_NAME),)
	@install -m 0744 -o root -g root $(VNIC_DRIVER_NAME).ko $(MODULE_ROOT)/net
endif
	@depmod -a $(FULL_KERNEL_VERSION)
ifeq ($(INSTALL_API), "yes")
	@echo "Modules and library installed"
else
	@echo "Modules installed"
endif
endif


ifeq ($(KERNEL_VERSION),2.4)
# start of stuff for 2.4.x kernels

DEFINE_FLAGS += -DLINUX -D__KERNEL__ -DMODULE -DMODVERSIONS

CFLAGS := -Wall $(DEFINE_FLAGS) \
	  -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce \
	  -pipe -falign-loops=2 -falign-jumps=2 -falign-functions=2 \
	  -DCONFIG_X86_LOCAL_APIC $(ARCH_CFLAG) \
	  -I$(KDIR)/include -I$(PWD) \
	  -I$(KDIR)/drivers/scsi -O2

ATTO_INCLUDES := oswrap.h
ATTO_OBJS := $(CORE_NAME) oswrap.o osutil.o

$(DRIVER_NAME): $(ATTO_OBJS)
	@ld $(ARCH_LD) -r -o $(DRIVER_NAME).o $(ATTO_OBJS)
	@echo "$(DRIVER_NAME) module built"

oswrap.o: oswrap.c $(ATTO_INCLUDES)
	@$(CC) $(CFLAGS) -c oswrap.c

osutil.o: osutil.c $(ATTO_INCLUDES)
	@$(CC) $(CFLAGS) -c osutil.c

modules: $(DRIVER_NAME)

ifeq ($(INSTALL_API), "yes")
install: modules api_install
else
install: modules
endif
	@mkdir -p $(MODULE_ROOT)
	@mkdir -p $(MODULE_ROOT)/scsi
	@cp $(DRIVER_NAME).o $(MODULE_ROOT)/scsi
	@/sbin/depmod -a $(FULL_KERNEL_VERSION)
ifeq ($(INSTALL_API), "yes")
	@echo "Module and library installed"
else
	@echo "Module installed"
endif
endif

clean:
	@rm -f osata.o oswrap.o $(DRIVER_NAME).o osutil.o ostransport.o attocfg.o atto_cfg.o *.ko
	@rm -f \.*o.cmd *.mod.*

ifeq ($(INSTALL_API), "yes")
api_install:    $(ATTOFC_NAME) checkkernel
		@rm -f /usr/lib/attofc.so
		@cp $(ATTOFC_NAME) /usr/lib
		@if [ -f /etc/hba.conf ]; then \
		    mv /etc/hba.conf /etc/hba.conf.orig; \
		    grep -v attofc /etc/hba.conf.orig > /etc/hba.conf; \
		    true; \
		fi;
		@echo "com.attotech.$(DRIVER_NAME)   /usr/lib/$(ATTOFC_NAME)" >> /etc/hba.conf
		@echo "ATTO SNIA HBA API library installation completed"
endif
