# NOTE: This Makefile uses GNU gmake syntax and may not work with other makes
#
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. 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.
# 3. Neither the names of the above-listed copyright holders nor the
#    names of any contributors may be 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
# HOLDERS 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.
#

.KEEP_STATE:

include ../Makefile.com

CVTOBJS = $(CVTSRCS:%.c=%.o) ndislink.o
APIOBJS_CTF = $(APISRCS:%.c=%.o)
APIOBJS_NOCTF = winx64_wrap.o
APIOBJS = $(APIOBJS_CTF) $(APIOBJS_NOCTF)
NDISOBJS = driver.o ndis_prop.o ndis.o

CFLAGS_ARCH_AMD64 = -D__amd64__ -D__amd64 -m64 -mtune=opteron
CFLAGS_ARCH = $(CFLAGS_ARCH_AMD64)

$(NDIS) $(NDISAPI) $(NDISOBJS) :	CFLAGS = $(CFLAGS_ARCH) \
	-fident -finline -fno-inline-functions -fno-builtin \
	-fno-asm -nodefaultlibs -D__sun -O2 -gdwarf-2 \
	-fno-strict-aliasing -fno-unit-at-a-time \
	-fno-optimize-sibling-calls \
	-Wall -Wno-unknown-pragmas -Wno-missing-braces \
	-Wno-sign-compare -Wno-parentheses -Wno-uninitialized \
	-Wno-implicit-function-declaration -Wno-unused \
	-Wno-trigraphs -Wno-char-subscripts -Wno-switch \
	-ffreestanding -mcmodel=kernel -mno-red-zone \
	-D_KERNEL -DLINKEDIMAGE -I../include -I. -I/usr/include
#	-DKERNEL -D__KERNEL

ASMFLAGS = -O2 -fno-inline -Wall -ffreestanding -U_NO_LONGLONG \
	-D_KERNEL  -mcmodel=kernel -mno-red-zone -fno-strict-aliasing \
	$(CFLAGS_ARCH) -I../

$(NDISCVT) :	CFLAGS = -I../include -O $(CFLAGS_ARCH) -DLINKEDIMAGE -gdwarf-2

all: $(NDISAPI) $(NDIS)

inf-parse.o:
	$(YACC) -d -v ../inf-parse.y
	mv y.tab.c inf-parse.c
	$(CC) $(CFLAGS) -c inf-parse.c -o $@

inf-token.o: inf-parse.o
	rm -f inf-token.c
	$(LEX) -t ../inf-token.l > inf-token.c
	$(CC) $(CFLAGS) -c inf-token.c -o $@

%.o: ../%.c
	$(CC) $(CFLAGS) -c $< -o $@

$(NDISCVT): $(CVTOBJS)
	$(CC) $(CFLAGS) -o $@ $(CVTOBJS)
	rm -f $(CVTOBJS)

### Note: a component object of ndiscvt is later CTFCVT'ed which may require
### rebuild of ndiscvt on further invokations (i.e. "make all; make install",
### hence the "if" instead of make-dependency below to minimize the impact.
### Also, these objects are built differently (kernel and non-kernel).
ndis.h driver.s : ndis.inf ndis.sys
	if [ ! -x ./$(NDISCVT) ]; then \
	    make $(NDISCVT) || exit; \
	else true; fi
	./$(NDISCVT) -i ndis.inf -s ndis.sys -o ndis.h -a driver.s

ndis.o : ndis.h ../if_ndis.c
	$(CC) $(CFLAGS) -c ../if_ndis.c -o $@
	$(CTFCVT) $(CTFLAGS) $@

ndis_prop.o : ndis.h ../ndis_prop.c
	$(CC) $(CFLAGS) -c ../ndis_prop.c -o $@
	$(CTFCVT) $(CTFLAGS) $@

driver.o : driver.s
	$(CC) $(CFLAGS) -c ./driver.s -o $@

$(NDIS) : $(NDISOBJS)
	$(LD) -r -dy -N misc/`basename $(NDISAPI)` \
	    -N misc/mac -N misc/net80211 -N ip -o $@ $(NDISOBJS)
	$(CTFMERG) -l NDISWRAPPER -o $@ $(NDISOBJS)
	$(CTFMERG) -l NDISWRAPPER -o $@ $@
	chmod +x $@

winx64_wrap.o: ../winx64_wrap.S
	$(CC) -c $(ASMFLAGS) ../winx64_wrap.S -o $@

$(NDISAPI): $(APIOBJS)
	@ for F in $(APIOBJS_CTF); do \
	    echo "+ $(CTFCVT) $(CTFLAGS) '$$F' || exit"; \
	    $(CTFCVT) $(CTFLAGS) "$$F" || exit; \
	done
	$(LD) -r -o $@ $(APIOBJS)
	$(CTFMERG) -l NDISWRAPPER -o $@ $(APIOBJS)
	$(CTFMERG) -l NDISWRAPPER -o $@ $@
	chmod +x $@

clean:
	rm -rf *.o $(NDISCVT) inf-parse.c y.tab.h y.output inf-token.c \
	    $(NDIS) $(NDISAPI) ndis.h driver.s $(NDISOBJS) $(APIOBJS)

distclean: clean
	rm -f ndis.inf ndis.sys

install64: $(NDIS) $(NDISAPI)
	cp -pf $(NDIS) /kernel/drv/amd64
	cp -pf $(NDISAPI) /kernel/misc/amd64

install32: $(NDIS) $(NDISAPI)
	cp -pf $(NDIS) /kernel/drv
	cp -pf $(NDISAPI) /kernel/misc

install: install64

ndis.sys: bcmwl564.sys
	cp -f bcmwl564.sys ndis.sys

ndis.inf: bcmwl?.inf
	iconv -f utf-16 -t utf-8 bcmwl5.inf > ndis.inf

testunload:
	if modinfo | grep "$(NDIS)"; then \
	    modunload -i `modinfo | grep "$(NDIS)" | awk '{print $$1}'`; \
	else true; fi
	if modinfo | grep "$(NDISAPI)"; then \
	    modunload -i `modinfo | grep "$(NDISAPI)" | awk '{print $$1}'`; \
	else true; fi
	if modinfo | egrep "$(NDISAPI)|$(NDIS)"; then false; else true; fi

testpresence:
	@ echo "====="
	@ echo "=== Info about currently built NDIS modules:"
	file $(NDIS) $(NDISAPI)
	ls -la $(NDIS) $(NDISAPI)
	@ echo "=== Info about currently loaded NDIS modules (may be not same as built, may be not loaded):"
	modinfo | egrep "$(NDISAPI)|$(NDIS)" || true
	@ echo "====="
	sleep 3

### Note that modload will skip modules of the same name loaded already,
### so this test makes sense on a virgin system with no previously running
### bcmndis+ndisapi modules, or they should be modunload'ed between runs.

### Note that this installs the binaries into system and tests that
testload64: testunload testpresence install64
	# if ! modload /kernel/misc/amd64/$(NDISAPI) ; then \
	#     date; sleep 2; dmesg | tail; date; exit 1; \
	# else true; fi
	if ! modload /kernel/drv/amd64/$(NDIS) ; then \
	    date; sleep 2; dmesg | tail; date; exit 1; \
	else true; fi
	modinfo | egrep "$(NDIS)|$(NDISAPI)"

### Note that this loads the current build, not the installed binaries
testload: $(NDIS) $(NDISAPI) testunload testpresence
	if ! modload $(NDISAPI) ; then \
	    date; sleep 2; dmesg | grep $(NDISAPI) | tail; date; exit 1; \
	else true; fi
	if ! modload $(NDIS) ; then \
	    date; sleep 2; dmesg | grep $(NDIS) | tail; date; exit 1; \
	else true; fi
	modinfo | egrep "$(NDIS)|$(NDISAPI)"

### This is not part of common modload test, but rather automation to unload
### a working driver, if any, to test the new one
unplumb:
	@ echo "=== Trying to UNPLUMB Wifi interface $(WIFI_INTERFACE)"
	@ echo "=== This would allow to unload the NDIS modules for further tests"
	@ echo "=== Current interface IP config (if any):"
	ifconfig $(WIFI_INTERFACE) || true
	sleep 3
	wificonfig -i $(WIFI_INTERFACE) disconnect || true
	ifconfig $(WIFI_INTERFACE) down unplumb || true
	sleep 3
	ifconfig $(WIFI_INTERFACE) || true
	sleep 3

### This is not part of common modload test, but rather automation to set up
### networking on a wifi driver that's already loaded
plumb: testpresence
	@ echo "=== Trying to PLUMB Wifi interface $(WIFI_INTERFACE) and connect with DHCP"
	@ echo "=== The NDIS modules which you test should already be loaded (see above)"
	ifconfig $(WIFI_INTERFACE) plumb up
	if [ x"$(WIFI_PROFILE)" != x ]; then \
	    wificonfig -i $(WIFI_INTERFACE) connect $(WIFI_PROFILE); \
	else \
	    [ -s /etc/inet/wifi ] && wificonfig -i $(WIFI_INTERFACE) connect \
	      "`cat /etc/inet/wifi | ggrep -A1 'preference' | tail -1`"; \
	fi
	ifconfig $(WIFI_INTERFACE) dhcp
	@ echo "=== Current interface IP config:"
	ifconfig $(WIFI_INTERFACE)

test: testload

